diff options
Diffstat (limited to 'source/Core')
74 files changed, 35531 insertions, 46550 deletions
diff --git a/source/Core/Address.cpp b/source/Core/Address.cpp index f3ea1718d6f2..e2ccf9d72216 100644 --- a/source/Core/Address.cpp +++ b/source/Core/Address.cpp @@ -19,1108 +19,963 @@ #include "lldb/Core/Section.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/Variable.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" -#include "lldb/Symbol/SymbolVendor.h" using namespace lldb; using namespace lldb_private; -static size_t -ReadBytes (ExecutionContextScope *exe_scope, const Address &address, void *dst, size_t dst_len) -{ - if (exe_scope == nullptr) - return 0; - - TargetSP target_sp (exe_scope->CalculateTarget()); - if (target_sp) - { - Error error; - bool prefer_file_cache = false; - return target_sp->ReadMemory (address, prefer_file_cache, dst, dst_len, error); - } +static size_t ReadBytes(ExecutionContextScope *exe_scope, + const Address &address, void *dst, size_t dst_len) { + if (exe_scope == nullptr) return 0; -} -static bool -GetByteOrderAndAddressSize (ExecutionContextScope *exe_scope, const Address &address, ByteOrder& byte_order, uint32_t& addr_size) -{ - byte_order = eByteOrderInvalid; - addr_size = 0; - if (exe_scope == nullptr) - return false; - - TargetSP target_sp (exe_scope->CalculateTarget()); - if (target_sp) - { - byte_order = target_sp->GetArchitecture().GetByteOrder(); - addr_size = target_sp->GetArchitecture().GetAddressByteSize(); - } + TargetSP target_sp(exe_scope->CalculateTarget()); + if (target_sp) { + Error error; + bool prefer_file_cache = false; + return target_sp->ReadMemory(address, prefer_file_cache, dst, dst_len, + error); + } + return 0; +} + +static bool GetByteOrderAndAddressSize(ExecutionContextScope *exe_scope, + const Address &address, + ByteOrder &byte_order, + uint32_t &addr_size) { + byte_order = eByteOrderInvalid; + addr_size = 0; + if (exe_scope == nullptr) + return false; - if (byte_order == eByteOrderInvalid || addr_size == 0) - { - ModuleSP module_sp (address.GetModule()); - if (module_sp) - { - byte_order = module_sp->GetArchitecture().GetByteOrder(); - addr_size = module_sp->GetArchitecture().GetAddressByteSize(); - } - } - return byte_order != eByteOrderInvalid && addr_size != 0; -} + TargetSP target_sp(exe_scope->CalculateTarget()); + if (target_sp) { + byte_order = target_sp->GetArchitecture().GetByteOrder(); + addr_size = target_sp->GetArchitecture().GetAddressByteSize(); + } -static uint64_t -ReadUIntMax64 (ExecutionContextScope *exe_scope, const Address &address, uint32_t byte_size, bool &success) -{ - uint64_t uval64 = 0; - if (exe_scope == nullptr || byte_size > sizeof(uint64_t)) - { - success = false; - return 0; + if (byte_order == eByteOrderInvalid || addr_size == 0) { + ModuleSP module_sp(address.GetModule()); + if (module_sp) { + byte_order = module_sp->GetArchitecture().GetByteOrder(); + addr_size = module_sp->GetArchitecture().GetAddressByteSize(); } - uint64_t buf = 0; - - success = ReadBytes (exe_scope, address, &buf, byte_size) == byte_size; - if (success) - { - ByteOrder byte_order = eByteOrderInvalid; - uint32_t addr_size = 0; - if (GetByteOrderAndAddressSize (exe_scope, address, byte_order, addr_size)) - { - DataExtractor data (&buf, sizeof(buf), byte_order, addr_size); - lldb::offset_t offset = 0; - uval64 = data.GetU64(&offset); - } - else - success = false; - } - return uval64; + } + return byte_order != eByteOrderInvalid && addr_size != 0; } -static bool -ReadAddress (ExecutionContextScope *exe_scope, const Address &address, uint32_t pointer_size, Address &deref_so_addr) -{ - if (exe_scope == nullptr) - return false; - - bool success = false; - addr_t deref_addr = ReadUIntMax64 (exe_scope, address, pointer_size, success); - if (success) - { - ExecutionContext exe_ctx; - exe_scope->CalculateExecutionContext(exe_ctx); - // If we have any sections that are loaded, try and resolve using the - // section load list - Target *target = exe_ctx.GetTargetPtr(); - if (target && !target->GetSectionLoadList().IsEmpty()) - { - if (target->GetSectionLoadList().ResolveLoadAddress (deref_addr, deref_so_addr)) - return true; - } - else - { - // If we were not running, yet able to read an integer, we must - // have a module - ModuleSP module_sp (address.GetModule()); - - assert (module_sp); - if (module_sp->ResolveFileAddress(deref_addr, deref_so_addr)) - return true; - } +static uint64_t ReadUIntMax64(ExecutionContextScope *exe_scope, + const Address &address, uint32_t byte_size, + bool &success) { + uint64_t uval64 = 0; + if (exe_scope == nullptr || byte_size > sizeof(uint64_t)) { + success = false; + return 0; + } + uint64_t buf = 0; + + success = ReadBytes(exe_scope, address, &buf, byte_size) == byte_size; + if (success) { + ByteOrder byte_order = eByteOrderInvalid; + uint32_t addr_size = 0; + if (GetByteOrderAndAddressSize(exe_scope, address, byte_order, addr_size)) { + DataExtractor data(&buf, sizeof(buf), byte_order, addr_size); + lldb::offset_t offset = 0; + uval64 = data.GetU64(&offset); + } else + success = false; + } + return uval64; +} + +static bool ReadAddress(ExecutionContextScope *exe_scope, + const Address &address, uint32_t pointer_size, + Address &deref_so_addr) { + if (exe_scope == nullptr) + return false; - // We couldn't make "deref_addr" into a section offset value, but we were - // able to read the address, so we return a section offset address with - // no section and "deref_addr" as the offset (address). - deref_so_addr.SetRawAddress(deref_addr); + bool success = false; + addr_t deref_addr = ReadUIntMax64(exe_scope, address, pointer_size, success); + if (success) { + ExecutionContext exe_ctx; + exe_scope->CalculateExecutionContext(exe_ctx); + // If we have any sections that are loaded, try and resolve using the + // section load list + Target *target = exe_ctx.GetTargetPtr(); + if (target && !target->GetSectionLoadList().IsEmpty()) { + if (target->GetSectionLoadList().ResolveLoadAddress(deref_addr, + deref_so_addr)) return true; - } - return false; -} + } else { + // If we were not running, yet able to read an integer, we must + // have a module + ModuleSP module_sp(address.GetModule()); -static bool -DumpUInt (ExecutionContextScope *exe_scope, const Address &address, uint32_t byte_size, Stream* strm) -{ - if (exe_scope == nullptr || byte_size == 0) - return 0; - std::vector<uint8_t> buf(byte_size, 0); - - if (ReadBytes (exe_scope, address, &buf[0], buf.size()) == buf.size()) - { - ByteOrder byte_order = eByteOrderInvalid; - uint32_t addr_size = 0; - if (GetByteOrderAndAddressSize (exe_scope, address, byte_order, addr_size)) - { - DataExtractor data (&buf.front(), buf.size(), byte_order, addr_size); - - data.Dump (strm, - 0, // Start offset in "data" - eFormatHex, // Print as characters - buf.size(), // Size of item - 1, // Items count - UINT32_MAX, // num per line - LLDB_INVALID_ADDRESS,// base address - 0, // bitfield bit size - 0); // bitfield bit offset - - return true; - } + assert(module_sp); + if (module_sp->ResolveFileAddress(deref_addr, deref_so_addr)) + return true; } - return false; -} -static size_t -ReadCStringFromMemory (ExecutionContextScope *exe_scope, const Address &address, Stream *strm) -{ - if (exe_scope == nullptr) - return 0; - const size_t k_buf_len = 256; - char buf[k_buf_len+1]; - buf[k_buf_len] = '\0'; // NULL terminate - - // Byte order and address size don't matter for C string dumping.. - DataExtractor data (buf, sizeof(buf), endian::InlHostByteOrder(), 4); - size_t total_len = 0; - size_t bytes_read; - Address curr_address(address); - strm->PutChar ('"'); - while ((bytes_read = ReadBytes (exe_scope, curr_address, buf, k_buf_len)) > 0) - { - size_t len = strlen(buf); - if (len == 0) - break; - if (len > bytes_read) - len = bytes_read; - - data.Dump (strm, - 0, // Start offset in "data" - eFormatChar, // Print as characters - 1, // Size of item (1 byte for a char!) - len, // How many bytes to print? - UINT32_MAX, // num per line - LLDB_INVALID_ADDRESS,// base address - 0, // bitfield bit size - - 0); // bitfield bit offset - - total_len += bytes_read; - - if (len < k_buf_len) - break; - curr_address.SetOffset (curr_address.GetOffset() + bytes_read); - } - strm->PutChar ('"'); - return total_len; + // We couldn't make "deref_addr" into a section offset value, but we were + // able to read the address, so we return a section offset address with + // no section and "deref_addr" as the offset (address). + deref_so_addr.SetRawAddress(deref_addr); + return true; + } + return false; } -Address::Address (lldb::addr_t abs_addr) : - m_section_wp (), - m_offset (abs_addr) -{ -} +static bool DumpUInt(ExecutionContextScope *exe_scope, const Address &address, + uint32_t byte_size, Stream *strm) { + if (exe_scope == nullptr || byte_size == 0) + return 0; + std::vector<uint8_t> buf(byte_size, 0); -Address::Address (addr_t address, const SectionList *section_list) : - m_section_wp (), - m_offset (LLDB_INVALID_ADDRESS) -{ - ResolveAddressUsingFileSections(address, section_list); -} + if (ReadBytes(exe_scope, address, &buf[0], buf.size()) == buf.size()) { + ByteOrder byte_order = eByteOrderInvalid; + uint32_t addr_size = 0; + if (GetByteOrderAndAddressSize(exe_scope, address, byte_order, addr_size)) { + DataExtractor data(&buf.front(), buf.size(), byte_order, addr_size); -const Address& -Address::operator= (const Address& rhs) -{ - if (this != &rhs) - { - m_section_wp = rhs.m_section_wp; - m_offset = rhs.m_offset.load(); - } - return *this; -} + data.Dump(strm, + 0, // Start offset in "data" + eFormatHex, // Print as characters + buf.size(), // Size of item + 1, // Items count + UINT32_MAX, // num per line + LLDB_INVALID_ADDRESS, // base address + 0, // bitfield bit size + 0); // bitfield bit offset -bool -Address::ResolveAddressUsingFileSections (addr_t file_addr, const SectionList *section_list) -{ - if (section_list) - { - SectionSP section_sp (section_list->FindSectionContainingFileAddress(file_addr)); - m_section_wp = section_sp; - if (section_sp) - { - assert( section_sp->ContainsFileAddress(file_addr) ); - m_offset = file_addr - section_sp->GetFileAddress(); - return true; // Successfully transformed addr into a section offset address - } + return true; } - m_offset = file_addr; - return false; // Failed to resolve this address to a section offset value + } + return false; } -ModuleSP -Address::GetModule () const -{ - lldb::ModuleSP module_sp; - SectionSP section_sp (GetSection()); - if (section_sp) - module_sp = section_sp->GetModule(); - return module_sp; +static size_t ReadCStringFromMemory(ExecutionContextScope *exe_scope, + const Address &address, Stream *strm) { + if (exe_scope == nullptr) + return 0; + const size_t k_buf_len = 256; + char buf[k_buf_len + 1]; + buf[k_buf_len] = '\0'; // NULL terminate + + // Byte order and address size don't matter for C string dumping.. + DataExtractor data(buf, sizeof(buf), endian::InlHostByteOrder(), 4); + size_t total_len = 0; + size_t bytes_read; + Address curr_address(address); + strm->PutChar('"'); + while ((bytes_read = ReadBytes(exe_scope, curr_address, buf, k_buf_len)) > + 0) { + size_t len = strlen(buf); + if (len == 0) + break; + if (len > bytes_read) + len = bytes_read; + + data.Dump(strm, + 0, // Start offset in "data" + eFormatChar, // Print as characters + 1, // Size of item (1 byte for a char!) + len, // How many bytes to print? + UINT32_MAX, // num per line + LLDB_INVALID_ADDRESS, // base address + 0, // bitfield bit size + + 0); // bitfield bit offset + + total_len += bytes_read; + + if (len < k_buf_len) + break; + curr_address.SetOffset(curr_address.GetOffset() + bytes_read); + } + strm->PutChar('"'); + return total_len; +} + +Address::Address(lldb::addr_t abs_addr) : m_section_wp(), m_offset(abs_addr) {} + +Address::Address(addr_t address, const SectionList *section_list) + : m_section_wp(), m_offset(LLDB_INVALID_ADDRESS) { + ResolveAddressUsingFileSections(address, section_list); +} + +const Address &Address::operator=(const Address &rhs) { + if (this != &rhs) { + m_section_wp = rhs.m_section_wp; + m_offset = rhs.m_offset; + } + return *this; +} + +bool Address::ResolveAddressUsingFileSections(addr_t file_addr, + const SectionList *section_list) { + if (section_list) { + SectionSP section_sp( + section_list->FindSectionContainingFileAddress(file_addr)); + m_section_wp = section_sp; + if (section_sp) { + assert(section_sp->ContainsFileAddress(file_addr)); + m_offset = file_addr - section_sp->GetFileAddress(); + return true; // Successfully transformed addr into a section offset + // address + } + } + m_offset = file_addr; + return false; // Failed to resolve this address to a section offset value +} + +ModuleSP Address::GetModule() const { + lldb::ModuleSP module_sp; + SectionSP section_sp(GetSection()); + if (section_sp) + module_sp = section_sp->GetModule(); + return module_sp; +} + +addr_t Address::GetFileAddress() const { + SectionSP section_sp(GetSection()); + if (section_sp) { + addr_t sect_file_addr = section_sp->GetFileAddress(); + if (sect_file_addr == LLDB_INVALID_ADDRESS) { + // Section isn't resolved, we can't return a valid file address + return LLDB_INVALID_ADDRESS; + } + // We have a valid file range, so we can return the file based + // address by adding the file base address to our offset + return sect_file_addr + m_offset; + } else if (SectionWasDeletedPrivate()) { + // Used to have a valid section but it got deleted so the + // offset doesn't mean anything without the section + return LLDB_INVALID_ADDRESS; + } + // No section, we just return the offset since it is the value in this case + return m_offset; } -addr_t -Address::GetFileAddress () const -{ - SectionSP section_sp (GetSection()); - if (section_sp) - { - addr_t sect_file_addr = section_sp->GetFileAddress(); - if (sect_file_addr == LLDB_INVALID_ADDRESS) - { - // Section isn't resolved, we can't return a valid file address - return LLDB_INVALID_ADDRESS; - } +addr_t Address::GetLoadAddress(Target *target) const { + SectionSP section_sp(GetSection()); + if (section_sp) { + if (target) { + addr_t sect_load_addr = section_sp->GetLoadBaseAddress(target); + + if (sect_load_addr != LLDB_INVALID_ADDRESS) { // We have a valid file range, so we can return the file based // address by adding the file base address to our offset - return sect_file_addr + m_offset; - } - else if (SectionWasDeletedPrivate()) - { - // Used to have a valid section but it got deleted so the - // offset doesn't mean anything without the section - return LLDB_INVALID_ADDRESS; + return sect_load_addr + m_offset; + } } - // No section, we just return the offset since it is the value in this case + } else if (SectionWasDeletedPrivate()) { + // Used to have a valid section but it got deleted so the + // offset doesn't mean anything without the section + return LLDB_INVALID_ADDRESS; + } else { + // We don't have a section so the offset is the load address return m_offset; + } + // The section isn't resolved or an invalid target was passed in + // so we can't return a valid load address. + return LLDB_INVALID_ADDRESS; } -addr_t -Address::GetLoadAddress (Target *target) const -{ - SectionSP section_sp (GetSection()); - if (section_sp) - { - if (target) - { - addr_t sect_load_addr = section_sp->GetLoadBaseAddress (target); - - if (sect_load_addr != LLDB_INVALID_ADDRESS) - { - // We have a valid file range, so we can return the file based - // address by adding the file base address to our offset - return sect_load_addr + m_offset; - } - } - } - else if (SectionWasDeletedPrivate()) - { - // Used to have a valid section but it got deleted so the - // offset doesn't mean anything without the section - return LLDB_INVALID_ADDRESS; - } - else - { - // We don't have a section so the offset is the load address - return m_offset; - } - // The section isn't resolved or an invalid target was passed in - // so we can't return a valid load address. - return LLDB_INVALID_ADDRESS; -} +addr_t Address::GetCallableLoadAddress(Target *target, bool is_indirect) const { + addr_t code_addr = LLDB_INVALID_ADDRESS; -addr_t -Address::GetCallableLoadAddress (Target *target, bool is_indirect) const -{ - addr_t code_addr = LLDB_INVALID_ADDRESS; - - if (is_indirect && target) - { - ProcessSP processSP = target->GetProcessSP(); - Error error; - if (processSP) - { - code_addr = processSP->ResolveIndirectFunction(this, error); - if (!error.Success()) - code_addr = LLDB_INVALID_ADDRESS; - } - } - else - { - code_addr = GetLoadAddress (target); + if (is_indirect && target) { + ProcessSP processSP = target->GetProcessSP(); + Error error; + if (processSP) { + code_addr = processSP->ResolveIndirectFunction(this, error); + if (!error.Success()) + code_addr = LLDB_INVALID_ADDRESS; } - - if (code_addr == LLDB_INVALID_ADDRESS) - return code_addr; - - if (target) - return target->GetCallableLoadAddress (code_addr, GetAddressClass()); + } else { + code_addr = GetLoadAddress(target); + } + + if (code_addr == LLDB_INVALID_ADDRESS) return code_addr; -} -bool -Address::SetCallableLoadAddress (lldb::addr_t load_addr, Target *target) -{ - if (SetLoadAddress (load_addr, target)) - { - if (target) - m_offset = target->GetCallableLoadAddress(m_offset, GetAddressClass()); - return true; - } - return false; + if (target) + return target->GetCallableLoadAddress(code_addr, GetAddressClass()); + return code_addr; } -addr_t -Address::GetOpcodeLoadAddress (Target *target, AddressClass addr_class) const -{ - addr_t code_addr = GetLoadAddress (target); - if (code_addr != LLDB_INVALID_ADDRESS) - { - if (addr_class == eAddressClassInvalid) - addr_class = GetAddressClass(); - code_addr = target->GetOpcodeLoadAddress (code_addr, addr_class); - } - return code_addr; +bool Address::SetCallableLoadAddress(lldb::addr_t load_addr, Target *target) { + if (SetLoadAddress(load_addr, target)) { + if (target) + m_offset = target->GetCallableLoadAddress(m_offset, GetAddressClass()); + return true; + } + return false; } -bool -Address::SetOpcodeLoadAddress (lldb::addr_t load_addr, Target *target, AddressClass addr_class) -{ - if (SetLoadAddress (load_addr, target)) - { - if (target) - { - if (addr_class == eAddressClassInvalid) - addr_class = GetAddressClass(); - m_offset = target->GetOpcodeLoadAddress (m_offset, addr_class); - } - return true; - } - return false; +addr_t Address::GetOpcodeLoadAddress(Target *target, + AddressClass addr_class) const { + addr_t code_addr = GetLoadAddress(target); + if (code_addr != LLDB_INVALID_ADDRESS) { + if (addr_class == eAddressClassInvalid) + addr_class = GetAddressClass(); + code_addr = target->GetOpcodeLoadAddress(code_addr, addr_class); + } + return code_addr; } -bool -Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style, uint32_t addr_size) const -{ - // If the section was nullptr, only load address is going to work unless we are - // trying to deref a pointer - SectionSP section_sp (GetSection()); - if (!section_sp && style != DumpStyleResolvedPointerDescription) - style = DumpStyleLoadAddress; - - ExecutionContext exe_ctx (exe_scope); - Target *target = exe_ctx.GetTargetPtr(); - // If addr_byte_size is UINT32_MAX, then determine the correct address - // byte size for the process or default to the size of addr_t - if (addr_size == UINT32_MAX) - { - if (target) - addr_size = target->GetArchitecture().GetAddressByteSize (); - else - addr_size = sizeof(addr_t); +bool Address::SetOpcodeLoadAddress(lldb::addr_t load_addr, Target *target, + AddressClass addr_class) { + if (SetLoadAddress(load_addr, target)) { + if (target) { + if (addr_class == eAddressClassInvalid) + addr_class = GetAddressClass(); + m_offset = target->GetOpcodeLoadAddress(m_offset, addr_class); } + return true; + } + return false; +} + +bool Address::Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, + DumpStyle fallback_style, uint32_t addr_size) const { + // If the section was nullptr, only load address is going to work unless we + // are + // trying to deref a pointer + SectionSP section_sp(GetSection()); + if (!section_sp && style != DumpStyleResolvedPointerDescription) + style = DumpStyleLoadAddress; + + ExecutionContext exe_ctx(exe_scope); + Target *target = exe_ctx.GetTargetPtr(); + // If addr_byte_size is UINT32_MAX, then determine the correct address + // byte size for the process or default to the size of addr_t + if (addr_size == UINT32_MAX) { + if (target) + addr_size = target->GetArchitecture().GetAddressByteSize(); + else + addr_size = sizeof(addr_t); + } - Address so_addr; - switch (style) - { - case DumpStyleInvalid: - return false; - - case DumpStyleSectionNameOffset: - if (section_sp) - { - section_sp->DumpName(s); - s->Printf (" + %" PRIu64, m_offset.load()); - } - else - { - s->Address(m_offset, addr_size); - } - break; - - case DumpStyleSectionPointerOffset: - s->Printf("(Section *)%p + ", static_cast<void*>(section_sp.get())); - s->Address(m_offset, addr_size); - break; - - case DumpStyleModuleWithFileAddress: - if (section_sp) - { - ModuleSP module_sp = section_sp->GetModule(); - if (module_sp) - s->Printf("%s[", module_sp->GetFileSpec().GetFilename().AsCString("<Unknown>")); - else - s->Printf("%s[","<Unknown>"); - } - LLVM_FALLTHROUGH; - case DumpStyleFileAddress: - { - addr_t file_addr = GetFileAddress(); - if (file_addr == LLDB_INVALID_ADDRESS) - { - if (fallback_style != DumpStyleInvalid) - return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); - return false; - } - s->Address (file_addr, addr_size); - if (style == DumpStyleModuleWithFileAddress && section_sp) - s->PutChar(']'); - } - break; - - case DumpStyleLoadAddress: - { - addr_t load_addr = GetLoadAddress (target); - - /* - * MIPS: - * Display address in compressed form for MIPS16 or microMIPS - * if the address belongs to eAddressClassCodeAlternateISA. - */ - if (target) - { - const llvm::Triple::ArchType llvm_arch = target->GetArchitecture().GetMachine(); - if (llvm_arch == llvm::Triple::mips || llvm_arch == llvm::Triple::mipsel - || llvm_arch == llvm::Triple::mips64 || llvm_arch == llvm::Triple::mips64el) - load_addr = GetCallableLoadAddress (target); - } + Address so_addr; + switch (style) { + case DumpStyleInvalid: + return false; - if (load_addr == LLDB_INVALID_ADDRESS) - { - if (fallback_style != DumpStyleInvalid) - return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); - return false; - } - s->Address (load_addr, addr_size); - } - break; - - case DumpStyleResolvedDescription: - case DumpStyleResolvedDescriptionNoModule: - case DumpStyleResolvedDescriptionNoFunctionArguments: - case DumpStyleNoFunctionName: - if (IsSectionOffset()) - { - uint32_t pointer_size = 4; - ModuleSP module_sp (GetModule()); - if (target) - pointer_size = target->GetArchitecture().GetAddressByteSize(); - else if (module_sp) - pointer_size = module_sp->GetArchitecture().GetAddressByteSize(); - - bool showed_info = false; - if (section_sp) - { - SectionType sect_type = section_sp->GetType(); - switch (sect_type) - { - case eSectionTypeData: - if (module_sp) - { - SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); - if (sym_vendor) - { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab) - { - const addr_t file_Addr = GetFileAddress(); - Symbol *symbol = symtab->FindSymbolContainingFileAddress (file_Addr); - if (symbol) - { - const char *symbol_name = symbol->GetName().AsCString(); - if (symbol_name) - { - s->PutCString(symbol_name); - addr_t delta = file_Addr - symbol->GetAddressRef().GetFileAddress(); - if (delta) - s->Printf(" + %" PRIu64, delta); - showed_info = true; - } - } - } - } - } - break; - - case eSectionTypeDataCString: - // Read the C string from memory and display it + case DumpStyleSectionNameOffset: + if (section_sp) { + section_sp->DumpName(s); + s->Printf(" + %" PRIu64, m_offset); + } else { + s->Address(m_offset, addr_size); + } + break; + + case DumpStyleSectionPointerOffset: + s->Printf("(Section *)%p + ", static_cast<void *>(section_sp.get())); + s->Address(m_offset, addr_size); + break; + + case DumpStyleModuleWithFileAddress: + if (section_sp) { + ModuleSP module_sp = section_sp->GetModule(); + if (module_sp) + s->Printf("%s[", module_sp->GetFileSpec().GetFilename().AsCString( + "<Unknown>")); + else + s->Printf("%s[", "<Unknown>"); + } + LLVM_FALLTHROUGH; + case DumpStyleFileAddress: { + addr_t file_addr = GetFileAddress(); + if (file_addr == LLDB_INVALID_ADDRESS) { + if (fallback_style != DumpStyleInvalid) + return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); + return false; + } + s->Address(file_addr, addr_size); + if (style == DumpStyleModuleWithFileAddress && section_sp) + s->PutChar(']'); + } break; + + case DumpStyleLoadAddress: { + addr_t load_addr = GetLoadAddress(target); + + /* + * MIPS: + * Display address in compressed form for MIPS16 or microMIPS + * if the address belongs to eAddressClassCodeAlternateISA. + */ + if (target) { + const llvm::Triple::ArchType llvm_arch = + target->GetArchitecture().GetMachine(); + if (llvm_arch == llvm::Triple::mips || + llvm_arch == llvm::Triple::mipsel || + llvm_arch == llvm::Triple::mips64 || + llvm_arch == llvm::Triple::mips64el) + load_addr = GetCallableLoadAddress(target); + } + + if (load_addr == LLDB_INVALID_ADDRESS) { + if (fallback_style != DumpStyleInvalid) + return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); + return false; + } + s->Address(load_addr, addr_size); + } break; + + case DumpStyleResolvedDescription: + case DumpStyleResolvedDescriptionNoModule: + case DumpStyleResolvedDescriptionNoFunctionArguments: + case DumpStyleNoFunctionName: + if (IsSectionOffset()) { + uint32_t pointer_size = 4; + ModuleSP module_sp(GetModule()); + if (target) + pointer_size = target->GetArchitecture().GetAddressByteSize(); + else if (module_sp) + pointer_size = module_sp->GetArchitecture().GetAddressByteSize(); + + bool showed_info = false; + if (section_sp) { + SectionType sect_type = section_sp->GetType(); + switch (sect_type) { + case eSectionTypeData: + if (module_sp) { + SymbolVendor *sym_vendor = module_sp->GetSymbolVendor(); + if (sym_vendor) { + Symtab *symtab = sym_vendor->GetSymtab(); + if (symtab) { + const addr_t file_Addr = GetFileAddress(); + Symbol *symbol = + symtab->FindSymbolContainingFileAddress(file_Addr); + if (symbol) { + const char *symbol_name = symbol->GetName().AsCString(); + if (symbol_name) { + s->PutCString(symbol_name); + addr_t delta = + file_Addr - symbol->GetAddressRef().GetFileAddress(); + if (delta) + s->Printf(" + %" PRIu64, delta); showed_info = true; - ReadCStringFromMemory (exe_scope, *this, s); - break; + } + } + } + } + } + break; + + case eSectionTypeDataCString: + // Read the C string from memory and display it + showed_info = true; + ReadCStringFromMemory(exe_scope, *this, s); + break; - case eSectionTypeDataCStringPointers: - if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) - { + case eSectionTypeDataCStringPointers: + if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) { #if VERBOSE_OUTPUT - s->PutCString("(char *)"); - so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress); - s->PutCString(": "); + s->PutCString("(char *)"); + so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, + DumpStyleFileAddress); + s->PutCString(": "); #endif - showed_info = true; - ReadCStringFromMemory(exe_scope, so_addr, s); - } - break; - - case eSectionTypeDataObjCMessageRefs: - if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) - { - if (target && so_addr.IsSectionOffset()) - { - SymbolContext func_sc; - target->GetImages().ResolveSymbolContextForAddress(so_addr, - eSymbolContextEverything, - func_sc); - if (func_sc.function != nullptr || func_sc.symbol != nullptr) - { - showed_info = true; + showed_info = true; + ReadCStringFromMemory(exe_scope, so_addr, s); + } + break; + + case eSectionTypeDataObjCMessageRefs: + if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) { + if (target && so_addr.IsSectionOffset()) { + SymbolContext func_sc; + target->GetImages().ResolveSymbolContextForAddress( + so_addr, eSymbolContextEverything, func_sc); + if (func_sc.function != nullptr || func_sc.symbol != nullptr) { + showed_info = true; #if VERBOSE_OUTPUT - s->PutCString ("(objc_msgref *) -> { (func*)"); - so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress); + s->PutCString("(objc_msgref *) -> { (func*)"); + so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, + DumpStyleFileAddress); #else - s->PutCString ("{ "); + s->PutCString("{ "); #endif - Address cstr_addr(*this); - cstr_addr.SetOffset(cstr_addr.GetOffset() + pointer_size); - func_sc.DumpStopContext(s, exe_scope, so_addr, true, true, false, true, true); - if (ReadAddress(exe_scope, cstr_addr, pointer_size, so_addr)) - { + Address cstr_addr(*this); + cstr_addr.SetOffset(cstr_addr.GetOffset() + pointer_size); + func_sc.DumpStopContext(s, exe_scope, so_addr, true, true, + false, true, true); + if (ReadAddress(exe_scope, cstr_addr, pointer_size, so_addr)) { #if VERBOSE_OUTPUT - s->PutCString("), (char *)"); - so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress); - s->PutCString(" ("); + s->PutCString("), (char *)"); + so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, + DumpStyleFileAddress); + s->PutCString(" ("); #else - s->PutCString(", "); + s->PutCString(", "); #endif - ReadCStringFromMemory (exe_scope, so_addr, s); - } + ReadCStringFromMemory(exe_scope, so_addr, s); + } #if VERBOSE_OUTPUT - s->PutCString(") }"); + s->PutCString(") }"); #else - s->PutCString(" }"); + s->PutCString(" }"); #endif - } - } - } - break; - - case eSectionTypeDataObjCCFStrings: - { - Address cfstring_data_addr(*this); - cfstring_data_addr.SetOffset(cfstring_data_addr.GetOffset() + (2 * pointer_size)); - if (ReadAddress (exe_scope, cfstring_data_addr, pointer_size, so_addr)) - { + } + } + } + break; + + case eSectionTypeDataObjCCFStrings: { + Address cfstring_data_addr(*this); + cfstring_data_addr.SetOffset(cfstring_data_addr.GetOffset() + + (2 * pointer_size)); + if (ReadAddress(exe_scope, cfstring_data_addr, pointer_size, + so_addr)) { #if VERBOSE_OUTPUT - s->PutCString("(CFString *) "); - cfstring_data_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress); - s->PutCString(" -> @"); + s->PutCString("(CFString *) "); + cfstring_data_addr.Dump(s, exe_scope, DumpStyleLoadAddress, + DumpStyleFileAddress); + s->PutCString(" -> @"); #else - s->PutChar('@'); + s->PutChar('@'); #endif - if (so_addr.Dump(s, exe_scope, DumpStyleResolvedDescription)) - showed_info = true; - } - } - break; - - case eSectionTypeData4: - // Read the 4 byte data and display it - showed_info = true; - s->PutCString("(uint32_t) "); - DumpUInt (exe_scope, *this, 4, s); - break; - - case eSectionTypeData8: - // Read the 8 byte data and display it - showed_info = true; - s->PutCString("(uint64_t) "); - DumpUInt (exe_scope, *this, 8, s); - break; - - case eSectionTypeData16: - // Read the 16 byte data and display it - showed_info = true; - s->PutCString("(uint128_t) "); - DumpUInt (exe_scope, *this, 16, s); - break; - - case eSectionTypeDataPointers: - // Read the pointer data and display it - if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) - { - s->PutCString ("(void *)"); - so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, DumpStyleFileAddress); - - showed_info = true; - if (so_addr.IsSectionOffset()) - { - SymbolContext pointer_sc; - if (target) - { - target->GetImages().ResolveSymbolContextForAddress(so_addr, - eSymbolContextEverything, - pointer_sc); - if (pointer_sc.function != nullptr || pointer_sc.symbol != nullptr) - { - s->PutCString(": "); - pointer_sc.DumpStopContext(s, exe_scope, so_addr, true, false, false, true, true); - } - } - } - } - break; - - default: - break; + if (so_addr.Dump(s, exe_scope, DumpStyleResolvedDescription)) + showed_info = true; + } + } break; + + case eSectionTypeData4: + // Read the 4 byte data and display it + showed_info = true; + s->PutCString("(uint32_t) "); + DumpUInt(exe_scope, *this, 4, s); + break; + + case eSectionTypeData8: + // Read the 8 byte data and display it + showed_info = true; + s->PutCString("(uint64_t) "); + DumpUInt(exe_scope, *this, 8, s); + break; + + case eSectionTypeData16: + // Read the 16 byte data and display it + showed_info = true; + s->PutCString("(uint128_t) "); + DumpUInt(exe_scope, *this, 16, s); + break; + + case eSectionTypeDataPointers: + // Read the pointer data and display it + if (ReadAddress(exe_scope, *this, pointer_size, so_addr)) { + s->PutCString("(void *)"); + so_addr.Dump(s, exe_scope, DumpStyleLoadAddress, + DumpStyleFileAddress); + + showed_info = true; + if (so_addr.IsSectionOffset()) { + SymbolContext pointer_sc; + if (target) { + target->GetImages().ResolveSymbolContextForAddress( + so_addr, eSymbolContextEverything, pointer_sc); + if (pointer_sc.function != nullptr || + pointer_sc.symbol != nullptr) { + s->PutCString(": "); + pointer_sc.DumpStopContext(s, exe_scope, so_addr, true, false, + false, true, true); } + } } + } + break; - if (!showed_info) - { - if (module_sp) - { - SymbolContext sc; - module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextEverything, sc); - if (sc.function || sc.symbol) - { - bool show_stop_context = true; - const bool show_module = (style == DumpStyleResolvedDescription); - const bool show_fullpaths = false; - const bool show_inlined_frames = true; - const bool show_function_arguments = (style != DumpStyleResolvedDescriptionNoFunctionArguments); - const bool show_function_name = (style != DumpStyleNoFunctionName); - if (sc.function == nullptr && sc.symbol != nullptr) - { - // If we have just a symbol make sure it is in the right section - if (sc.symbol->ValueIsAddress()) - { - if (sc.symbol->GetAddressRef().GetSection() != GetSection()) - { - // don't show the module if the symbol is a trampoline symbol - show_stop_context = false; - } - } - } - if (show_stop_context) - { - // We have a function or a symbol from the same - // sections as this address. - sc.DumpStopContext (s, - exe_scope, - *this, - show_fullpaths, - show_module, - show_inlined_frames, - show_function_arguments, - show_function_name); - } - else - { - // We found a symbol but it was in a different - // section so it isn't the symbol we should be - // showing, just show the section name + offset - Dump (s, exe_scope, DumpStyleSectionNameOffset); - } - } - } - } - } - else - { - if (fallback_style != DumpStyleInvalid) - return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); - return false; + default: + break; } - break; - - case DumpStyleDetailedSymbolContext: - if (IsSectionOffset()) - { - ModuleSP module_sp (GetModule()); - if (module_sp) - { - SymbolContext sc; - module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextEverything | eSymbolContextVariable, sc); - if (sc.symbol) - { - // If we have just a symbol make sure it is in the same section - // as our address. If it isn't, then we might have just found - // the last symbol that came before the address that we are - // looking up that has nothing to do with our address lookup. - if (sc.symbol->ValueIsAddress() && sc.symbol->GetAddressRef().GetSection() != GetSection()) - sc.symbol = nullptr; - } - sc.GetDescription(s, eDescriptionLevelBrief, target); - - if (sc.block) - { - bool can_create = true; - bool get_parent_variables = true; - bool stop_if_block_is_inlined_function = false; - VariableList variable_list; - sc.block->AppendVariables (can_create, - get_parent_variables, - stop_if_block_is_inlined_function, - [](Variable*) { return true; }, - &variable_list); - - const size_t num_variables = variable_list.GetSize(); - for (size_t var_idx = 0; var_idx < num_variables; ++var_idx) - { - Variable *var = variable_list.GetVariableAtIndex (var_idx).get(); - if (var && var->LocationIsValidForAddress (*this)) - { - s->Indent(); - s->Printf (" Variable: id = {0x%8.8" PRIx64 "}, name = \"%s\"", - var->GetID(), - var->GetName().GetCString()); - Type *type = var->GetType(); - if (type) - s->Printf(", type = \"%s\"", type->GetName().GetCString()); - else - s->PutCString(", type = <unknown>"); - s->PutCString(", location = "); - var->DumpLocationForAddress(s, *this); - s->PutCString(", decl = "); - var->GetDeclaration().DumpStopContext(s, false); - s->EOL(); - } - } + } + + if (!showed_info) { + if (module_sp) { + SymbolContext sc; + module_sp->ResolveSymbolContextForAddress( + *this, eSymbolContextEverything, sc); + if (sc.function || sc.symbol) { + bool show_stop_context = true; + const bool show_module = (style == DumpStyleResolvedDescription); + const bool show_fullpaths = false; + const bool show_inlined_frames = true; + const bool show_function_arguments = + (style != DumpStyleResolvedDescriptionNoFunctionArguments); + const bool show_function_name = (style != DumpStyleNoFunctionName); + if (sc.function == nullptr && sc.symbol != nullptr) { + // If we have just a symbol make sure it is in the right section + if (sc.symbol->ValueIsAddress()) { + if (sc.symbol->GetAddressRef().GetSection() != GetSection()) { + // don't show the module if the symbol is a trampoline symbol + show_stop_context = false; } + } } - } - else - { - if (fallback_style != DumpStyleInvalid) - return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); - return false; - } - break; - - case DumpStyleResolvedPointerDescription: - { - Process *process = exe_ctx.GetProcessPtr(); - if (process) - { - addr_t load_addr = GetLoadAddress (target); - if (load_addr != LLDB_INVALID_ADDRESS) - { - Error memory_error; - addr_t dereferenced_load_addr = process->ReadPointerFromMemory(load_addr, memory_error); - if (dereferenced_load_addr != LLDB_INVALID_ADDRESS) - { - Address dereferenced_addr; - if (dereferenced_addr.SetLoadAddress(dereferenced_load_addr, target)) - { - StreamString strm; - if (dereferenced_addr.Dump (&strm, exe_scope, DumpStyleResolvedDescription, DumpStyleInvalid, addr_size)) - { - s->Address (dereferenced_load_addr, addr_size, " -> ", " "); - s->Write(strm.GetData(), strm.GetSize()); - return true; - } - } - } - } + if (show_stop_context) { + // We have a function or a symbol from the same + // sections as this address. + sc.DumpStopContext(s, exe_scope, *this, show_fullpaths, + show_module, show_inlined_frames, + show_function_arguments, show_function_name); + } else { + // We found a symbol but it was in a different + // section so it isn't the symbol we should be + // showing, just show the section name + offset + Dump(s, exe_scope, DumpStyleSectionNameOffset); } - if (fallback_style != DumpStyleInvalid) - return Dump (s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); - return false; - } - break; - } - - return true; -} - -bool -Address::SectionWasDeleted() const -{ - if (GetSection()) - return false; - return SectionWasDeletedPrivate(); -} - -bool -Address::SectionWasDeletedPrivate() const -{ - lldb::SectionWP empty_section_wp; - - // If either call to "std::weak_ptr::owner_before(...) value returns true, this - // indicates that m_section_wp once contained (possibly still does) a reference - // to a valid shared pointer. This helps us know if we had a valid reference to - // a section which is now invalid because the module it was in was unloaded/deleted, - // or if the address doesn't have a valid reference to a section. - return empty_section_wp.owner_before(m_section_wp) || m_section_wp.owner_before(empty_section_wp); -} - -uint32_t -Address::CalculateSymbolContext (SymbolContext *sc, uint32_t resolve_scope) const -{ - sc->Clear(false); - // Absolute addresses don't have enough information to reconstruct even their target. - - SectionSP section_sp (GetSection()); - if (section_sp) - { - ModuleSP module_sp (section_sp->GetModule()); - if (module_sp) - { - sc->module_sp = module_sp; - if (sc->module_sp) - return sc->module_sp->ResolveSymbolContextForAddress (*this, resolve_scope, *sc); + } } - } - return 0; -} - -ModuleSP -Address::CalculateSymbolContextModule () const -{ - SectionSP section_sp (GetSection()); - if (section_sp) - return section_sp->GetModule(); - return ModuleSP(); -} - -CompileUnit * -Address::CalculateSymbolContextCompileUnit () const -{ - SectionSP section_sp (GetSection()); - if (section_sp) - { - SymbolContext sc; - sc.module_sp = section_sp->GetModule(); - if (sc.module_sp) - { - sc.module_sp->ResolveSymbolContextForAddress (*this, eSymbolContextCompUnit, sc); - return sc.comp_unit; - } - } - return nullptr; -} - -Function * -Address::CalculateSymbolContextFunction () const -{ - SectionSP section_sp (GetSection()); - if (section_sp) - { + } + } else { + if (fallback_style != DumpStyleInvalid) + return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); + return false; + } + break; + + case DumpStyleDetailedSymbolContext: + if (IsSectionOffset()) { + ModuleSP module_sp(GetModule()); + if (module_sp) { SymbolContext sc; - sc.module_sp = section_sp->GetModule(); - if (sc.module_sp) - { - sc.module_sp->ResolveSymbolContextForAddress (*this, eSymbolContextFunction, sc); - return sc.function; + module_sp->ResolveSymbolContextForAddress( + *this, eSymbolContextEverything | eSymbolContextVariable, sc); + if (sc.symbol) { + // If we have just a symbol make sure it is in the same section + // as our address. If it isn't, then we might have just found + // the last symbol that came before the address that we are + // looking up that has nothing to do with our address lookup. + if (sc.symbol->ValueIsAddress() && + sc.symbol->GetAddressRef().GetSection() != GetSection()) + sc.symbol = nullptr; } - } - return nullptr; -} - -Block * -Address::CalculateSymbolContextBlock () const -{ - SectionSP section_sp (GetSection()); - if (section_sp) - { - SymbolContext sc; - sc.module_sp = section_sp->GetModule(); - if (sc.module_sp) - { - sc.module_sp->ResolveSymbolContextForAddress (*this, eSymbolContextBlock, sc); - return sc.block; - } - } - return nullptr; -} - -Symbol * -Address::CalculateSymbolContextSymbol () const -{ - SectionSP section_sp (GetSection()); - if (section_sp) - { - SymbolContext sc; - sc.module_sp = section_sp->GetModule(); - if (sc.module_sp) - { - sc.module_sp->ResolveSymbolContextForAddress (*this, eSymbolContextSymbol, sc); - return sc.symbol; + sc.GetDescription(s, eDescriptionLevelBrief, target); + + if (sc.block) { + bool can_create = true; + bool get_parent_variables = true; + bool stop_if_block_is_inlined_function = false; + VariableList variable_list; + sc.block->AppendVariables(can_create, get_parent_variables, + stop_if_block_is_inlined_function, + [](Variable *) { return true; }, + &variable_list); + + const size_t num_variables = variable_list.GetSize(); + for (size_t var_idx = 0; var_idx < num_variables; ++var_idx) { + Variable *var = variable_list.GetVariableAtIndex(var_idx).get(); + if (var && var->LocationIsValidForAddress(*this)) { + s->Indent(); + s->Printf(" Variable: id = {0x%8.8" PRIx64 "}, name = \"%s\"", + var->GetID(), var->GetName().GetCString()); + Type *type = var->GetType(); + if (type) + s->Printf(", type = \"%s\"", type->GetName().GetCString()); + else + s->PutCString(", type = <unknown>"); + s->PutCString(", location = "); + var->DumpLocationForAddress(s, *this); + s->PutCString(", decl = "); + var->GetDeclaration().DumpStopContext(s, false); + s->EOL(); + } + } } - } - return nullptr; -} - -bool -Address::CalculateSymbolContextLineEntry (LineEntry &line_entry) const -{ - SectionSP section_sp (GetSection()); - if (section_sp) - { - SymbolContext sc; - sc.module_sp = section_sp->GetModule(); - if (sc.module_sp) - { - sc.module_sp->ResolveSymbolContextForAddress (*this, eSymbolContextLineEntry, sc); - if (sc.line_entry.IsValid()) - { - line_entry = sc.line_entry; - return true; + } + } else { + if (fallback_style != DumpStyleInvalid) + return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); + return false; + } + break; + + case DumpStyleResolvedPointerDescription: { + Process *process = exe_ctx.GetProcessPtr(); + if (process) { + addr_t load_addr = GetLoadAddress(target); + if (load_addr != LLDB_INVALID_ADDRESS) { + Error memory_error; + addr_t dereferenced_load_addr = + process->ReadPointerFromMemory(load_addr, memory_error); + if (dereferenced_load_addr != LLDB_INVALID_ADDRESS) { + Address dereferenced_addr; + if (dereferenced_addr.SetLoadAddress(dereferenced_load_addr, + target)) { + StreamString strm; + if (dereferenced_addr.Dump(&strm, exe_scope, + DumpStyleResolvedDescription, + DumpStyleInvalid, addr_size)) { + s->Address(dereferenced_load_addr, addr_size, " -> ", " "); + s->Write(strm.GetString().data(), strm.GetSize()); + return true; } + } } + } } - line_entry.Clear(); + if (fallback_style != DumpStyleInvalid) + return Dump(s, exe_scope, fallback_style, DumpStyleInvalid, addr_size); return false; -} + } break; + } -int -Address::CompareFileAddress (const Address& a, const Address& b) -{ - addr_t a_file_addr = a.GetFileAddress(); - addr_t b_file_addr = b.GetFileAddress(); - if (a_file_addr < b_file_addr) - return -1; - if (a_file_addr > b_file_addr) - return +1; - return 0; -} - -int -Address::CompareLoadAddress (const Address& a, const Address& b, Target *target) -{ - assert(target != nullptr); - addr_t a_load_addr = a.GetLoadAddress (target); - addr_t b_load_addr = b.GetLoadAddress (target); - if (a_load_addr < b_load_addr) - return -1; - if (a_load_addr > b_load_addr) - return +1; - return 0; + return true; } -int -Address::CompareModulePointerAndOffset (const Address& a, const Address& b) -{ - ModuleSP a_module_sp (a.GetModule()); - ModuleSP b_module_sp (b.GetModule()); - Module *a_module = a_module_sp.get(); - Module *b_module = b_module_sp.get(); - if (a_module < b_module) - return -1; - if (a_module > b_module) - return +1; - // Modules are the same, just compare the file address since they should - // be unique - addr_t a_file_addr = a.GetFileAddress(); - addr_t b_file_addr = b.GetFileAddress(); - if (a_file_addr < b_file_addr) - return -1; - if (a_file_addr > b_file_addr) - return +1; - return 0; -} - -size_t -Address::MemorySize () const -{ - // Noting special for the memory size of a single Address object, - // it is just the size of itself. - return sizeof(Address); +bool Address::SectionWasDeleted() const { + if (GetSection()) + return false; + return SectionWasDeletedPrivate(); +} + +bool Address::SectionWasDeletedPrivate() const { + lldb::SectionWP empty_section_wp; + + // If either call to "std::weak_ptr::owner_before(...) value returns true, + // this + // indicates that m_section_wp once contained (possibly still does) a + // reference + // to a valid shared pointer. This helps us know if we had a valid reference + // to + // a section which is now invalid because the module it was in was + // unloaded/deleted, + // or if the address doesn't have a valid reference to a section. + return empty_section_wp.owner_before(m_section_wp) || + m_section_wp.owner_before(empty_section_wp); +} + +uint32_t Address::CalculateSymbolContext(SymbolContext *sc, + uint32_t resolve_scope) const { + sc->Clear(false); + // Absolute addresses don't have enough information to reconstruct even their + // target. + + SectionSP section_sp(GetSection()); + if (section_sp) { + ModuleSP module_sp(section_sp->GetModule()); + if (module_sp) { + sc->module_sp = module_sp; + if (sc->module_sp) + return sc->module_sp->ResolveSymbolContextForAddress( + *this, resolve_scope, *sc); + } + } + return 0; +} + +ModuleSP Address::CalculateSymbolContextModule() const { + SectionSP section_sp(GetSection()); + if (section_sp) + return section_sp->GetModule(); + return ModuleSP(); +} + +CompileUnit *Address::CalculateSymbolContextCompileUnit() const { + SectionSP section_sp(GetSection()); + if (section_sp) { + SymbolContext sc; + sc.module_sp = section_sp->GetModule(); + if (sc.module_sp) { + sc.module_sp->ResolveSymbolContextForAddress(*this, + eSymbolContextCompUnit, sc); + return sc.comp_unit; + } + } + return nullptr; +} + +Function *Address::CalculateSymbolContextFunction() const { + SectionSP section_sp(GetSection()); + if (section_sp) { + SymbolContext sc; + sc.module_sp = section_sp->GetModule(); + if (sc.module_sp) { + sc.module_sp->ResolveSymbolContextForAddress(*this, + eSymbolContextFunction, sc); + return sc.function; + } + } + return nullptr; +} + +Block *Address::CalculateSymbolContextBlock() const { + SectionSP section_sp(GetSection()); + if (section_sp) { + SymbolContext sc; + sc.module_sp = section_sp->GetModule(); + if (sc.module_sp) { + sc.module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextBlock, + sc); + return sc.block; + } + } + return nullptr; +} + +Symbol *Address::CalculateSymbolContextSymbol() const { + SectionSP section_sp(GetSection()); + if (section_sp) { + SymbolContext sc; + sc.module_sp = section_sp->GetModule(); + if (sc.module_sp) { + sc.module_sp->ResolveSymbolContextForAddress(*this, eSymbolContextSymbol, + sc); + return sc.symbol; + } + } + return nullptr; +} + +bool Address::CalculateSymbolContextLineEntry(LineEntry &line_entry) const { + SectionSP section_sp(GetSection()); + if (section_sp) { + SymbolContext sc; + sc.module_sp = section_sp->GetModule(); + if (sc.module_sp) { + sc.module_sp->ResolveSymbolContextForAddress(*this, + eSymbolContextLineEntry, sc); + if (sc.line_entry.IsValid()) { + line_entry = sc.line_entry; + return true; + } + } + } + line_entry.Clear(); + return false; +} + +int Address::CompareFileAddress(const Address &a, const Address &b) { + addr_t a_file_addr = a.GetFileAddress(); + addr_t b_file_addr = b.GetFileAddress(); + if (a_file_addr < b_file_addr) + return -1; + if (a_file_addr > b_file_addr) + return +1; + return 0; +} + +int Address::CompareLoadAddress(const Address &a, const Address &b, + Target *target) { + assert(target != nullptr); + addr_t a_load_addr = a.GetLoadAddress(target); + addr_t b_load_addr = b.GetLoadAddress(target); + if (a_load_addr < b_load_addr) + return -1; + if (a_load_addr > b_load_addr) + return +1; + return 0; +} + +int Address::CompareModulePointerAndOffset(const Address &a, const Address &b) { + ModuleSP a_module_sp(a.GetModule()); + ModuleSP b_module_sp(b.GetModule()); + Module *a_module = a_module_sp.get(); + Module *b_module = b_module_sp.get(); + if (a_module < b_module) + return -1; + if (a_module > b_module) + return +1; + // Modules are the same, just compare the file address since they should + // be unique + addr_t a_file_addr = a.GetFileAddress(); + addr_t b_file_addr = b.GetFileAddress(); + if (a_file_addr < b_file_addr) + return -1; + if (a_file_addr > b_file_addr) + return +1; + return 0; +} + +size_t Address::MemorySize() const { + // Noting special for the memory size of a single Address object, + // it is just the size of itself. + return sizeof(Address); } //---------------------------------------------------------------------- -// NOTE: Be careful using this operator. It can correctly compare two -// addresses from the same Module correctly. It can't compare two +// NOTE: Be careful using this operator. It can correctly compare two +// addresses from the same Module correctly. It can't compare two // addresses from different modules in any meaningful way, but it will // compare the module pointers. -// +// // To sum things up: // - works great for addresses within the same module // - it works for addresses across multiple modules, but don't expect the // address results to make much sense // -// This basically lets Address objects be used in ordered collection +// This basically lets Address objects be used in ordered collection // classes. //---------------------------------------------------------------------- -bool -lldb_private::operator< (const Address& lhs, const Address& rhs) -{ - ModuleSP lhs_module_sp (lhs.GetModule()); - ModuleSP rhs_module_sp (rhs.GetModule()); - Module *lhs_module = lhs_module_sp.get(); - Module *rhs_module = rhs_module_sp.get(); - if (lhs_module == rhs_module) - { - // Addresses are in the same module, just compare the file addresses - return lhs.GetFileAddress() < rhs.GetFileAddress(); - } - else - { - // The addresses are from different modules, just use the module - // pointer value to get consistent ordering - return lhs_module < rhs_module; - } -} - -bool -lldb_private::operator> (const Address& lhs, const Address& rhs) -{ - ModuleSP lhs_module_sp (lhs.GetModule()); - ModuleSP rhs_module_sp (rhs.GetModule()); - Module *lhs_module = lhs_module_sp.get(); - Module *rhs_module = rhs_module_sp.get(); - if (lhs_module == rhs_module) - { - // Addresses are in the same module, just compare the file addresses - return lhs.GetFileAddress() > rhs.GetFileAddress(); - } - else - { - // The addresses are from different modules, just use the module - // pointer value to get consistent ordering - return lhs_module > rhs_module; - } +bool lldb_private::operator<(const Address &lhs, const Address &rhs) { + ModuleSP lhs_module_sp(lhs.GetModule()); + ModuleSP rhs_module_sp(rhs.GetModule()); + Module *lhs_module = lhs_module_sp.get(); + Module *rhs_module = rhs_module_sp.get(); + if (lhs_module == rhs_module) { + // Addresses are in the same module, just compare the file addresses + return lhs.GetFileAddress() < rhs.GetFileAddress(); + } else { + // The addresses are from different modules, just use the module + // pointer value to get consistent ordering + return lhs_module < rhs_module; + } +} + +bool lldb_private::operator>(const Address &lhs, const Address &rhs) { + ModuleSP lhs_module_sp(lhs.GetModule()); + ModuleSP rhs_module_sp(rhs.GetModule()); + Module *lhs_module = lhs_module_sp.get(); + Module *rhs_module = rhs_module_sp.get(); + if (lhs_module == rhs_module) { + // Addresses are in the same module, just compare the file addresses + return lhs.GetFileAddress() > rhs.GetFileAddress(); + } else { + // The addresses are from different modules, just use the module + // pointer value to get consistent ordering + return lhs_module > rhs_module; + } } // The operator == checks for exact equality only (same section, same offset) -bool -lldb_private::operator== (const Address& a, const Address& rhs) -{ - return a.GetOffset() == rhs.GetOffset() && - a.GetSection() == rhs.GetSection(); +bool lldb_private::operator==(const Address &a, const Address &rhs) { + return a.GetOffset() == rhs.GetOffset() && a.GetSection() == rhs.GetSection(); } // The operator != checks for exact inequality only (differing section, or // different offset) -bool -lldb_private::operator!= (const Address& a, const Address& rhs) -{ - return a.GetOffset() != rhs.GetOffset() || - a.GetSection() != rhs.GetSection(); +bool lldb_private::operator!=(const Address &a, const Address &rhs) { + return a.GetOffset() != rhs.GetOffset() || a.GetSection() != rhs.GetSection(); } -AddressClass -Address::GetAddressClass () const -{ - ModuleSP module_sp (GetModule()); - if (module_sp) - { - ObjectFile *obj_file = module_sp->GetObjectFile(); - if (obj_file) - { - // Give the symbol vendor a chance to add to the unified section list. - module_sp->GetSymbolVendor(); - return obj_file->GetAddressClass (GetFileAddress()); - } +AddressClass Address::GetAddressClass() const { + ModuleSP module_sp(GetModule()); + if (module_sp) { + ObjectFile *obj_file = module_sp->GetObjectFile(); + if (obj_file) { + // Give the symbol vendor a chance to add to the unified section list. + module_sp->GetSymbolVendor(); + return obj_file->GetAddressClass(GetFileAddress()); } - return eAddressClassUnknown; + } + return eAddressClassUnknown; } -bool -Address::SetLoadAddress (lldb::addr_t load_addr, Target *target) -{ - if (target && target->GetSectionLoadList().ResolveLoadAddress(load_addr, *this)) - return true; - m_section_wp.reset(); - m_offset = load_addr; - return false; +bool Address::SetLoadAddress(lldb::addr_t load_addr, Target *target) { + if (target && + target->GetSectionLoadList().ResolveLoadAddress(load_addr, *this)) + return true; + m_section_wp.reset(); + m_offset = load_addr; + return false; } diff --git a/source/Core/AddressRange.cpp b/source/Core/AddressRange.cpp index 072c2450836c..e03d721b566d 100644 --- a/source/Core/AddressRange.cpp +++ b/source/Core/AddressRange.cpp @@ -16,194 +16,165 @@ using namespace lldb; using namespace lldb_private; -AddressRange::AddressRange () : - m_base_addr(), - m_byte_size(0) -{ -} +AddressRange::AddressRange() : m_base_addr(), m_byte_size(0) {} -AddressRange::AddressRange (addr_t file_addr, addr_t byte_size, const SectionList *section_list) : - m_base_addr(file_addr, section_list), - m_byte_size(byte_size) -{ -} +AddressRange::AddressRange(addr_t file_addr, addr_t byte_size, + const SectionList *section_list) + : m_base_addr(file_addr, section_list), m_byte_size(byte_size) {} -AddressRange::AddressRange (const lldb::SectionSP §ion, addr_t offset, addr_t byte_size) : - m_base_addr(section, offset), - m_byte_size(byte_size) -{ -} +AddressRange::AddressRange(const lldb::SectionSP §ion, addr_t offset, + addr_t byte_size) + : m_base_addr(section, offset), m_byte_size(byte_size) {} -AddressRange::AddressRange (const Address& so_addr, addr_t byte_size) : - m_base_addr(so_addr), - m_byte_size(byte_size) -{ -} +AddressRange::AddressRange(const Address &so_addr, addr_t byte_size) + : m_base_addr(so_addr), m_byte_size(byte_size) {} -AddressRange::~AddressRange () -{ -} +AddressRange::~AddressRange() {} -//bool -//AddressRange::Contains (const Address &addr) const +// bool +// AddressRange::Contains (const Address &addr) const //{ // const addr_t byte_size = GetByteSize(); // if (byte_size) -// return addr.GetSection() == m_base_addr.GetSection() && (addr.GetOffset() - m_base_addr.GetOffset()) < byte_size; +// return addr.GetSection() == m_base_addr.GetSection() && +// (addr.GetOffset() - m_base_addr.GetOffset()) < byte_size; //} // -//bool -//AddressRange::Contains (const Address *addr) const +// bool +// AddressRange::Contains (const Address *addr) const //{ // if (addr) // return Contains (*addr); // return false; //} -bool -AddressRange::ContainsFileAddress (const Address &addr) const -{ - if (addr.GetSection() == m_base_addr.GetSection()) - return (addr.GetOffset() - m_base_addr.GetOffset()) < GetByteSize(); - addr_t file_base_addr = GetBaseAddress().GetFileAddress(); - if (file_base_addr == LLDB_INVALID_ADDRESS) - return false; +bool AddressRange::ContainsFileAddress(const Address &addr) const { + if (addr.GetSection() == m_base_addr.GetSection()) + return (addr.GetOffset() - m_base_addr.GetOffset()) < GetByteSize(); + addr_t file_base_addr = GetBaseAddress().GetFileAddress(); + if (file_base_addr == LLDB_INVALID_ADDRESS) + return false; - addr_t file_addr = addr.GetFileAddress(); - if (file_addr == LLDB_INVALID_ADDRESS) - return false; + addr_t file_addr = addr.GetFileAddress(); + if (file_addr == LLDB_INVALID_ADDRESS) + return false; - if (file_base_addr <= file_addr) - return (file_addr - file_base_addr) < GetByteSize(); + if (file_base_addr <= file_addr) + return (file_addr - file_base_addr) < GetByteSize(); - return false; + return false; } -bool -AddressRange::ContainsFileAddress (addr_t file_addr) const -{ - if (file_addr == LLDB_INVALID_ADDRESS) - return false; +bool AddressRange::ContainsFileAddress(addr_t file_addr) const { + if (file_addr == LLDB_INVALID_ADDRESS) + return false; - addr_t file_base_addr = GetBaseAddress().GetFileAddress(); - if (file_base_addr == LLDB_INVALID_ADDRESS) - return false; + addr_t file_base_addr = GetBaseAddress().GetFileAddress(); + if (file_base_addr == LLDB_INVALID_ADDRESS) + return false; - if (file_base_addr <= file_addr) - return (file_addr - file_base_addr) < GetByteSize(); + if (file_base_addr <= file_addr) + return (file_addr - file_base_addr) < GetByteSize(); - return false; + return false; } +bool AddressRange::ContainsLoadAddress(const Address &addr, + Target *target) const { + if (addr.GetSection() == m_base_addr.GetSection()) + return (addr.GetOffset() - m_base_addr.GetOffset()) < GetByteSize(); + addr_t load_base_addr = GetBaseAddress().GetLoadAddress(target); + if (load_base_addr == LLDB_INVALID_ADDRESS) + return false; -bool -AddressRange::ContainsLoadAddress (const Address &addr, Target *target) const -{ - if (addr.GetSection() == m_base_addr.GetSection()) - return (addr.GetOffset() - m_base_addr.GetOffset()) < GetByteSize(); - addr_t load_base_addr = GetBaseAddress().GetLoadAddress(target); - if (load_base_addr == LLDB_INVALID_ADDRESS) - return false; - - addr_t load_addr = addr.GetLoadAddress(target); - if (load_addr == LLDB_INVALID_ADDRESS) - return false; + addr_t load_addr = addr.GetLoadAddress(target); + if (load_addr == LLDB_INVALID_ADDRESS) + return false; - if (load_base_addr <= load_addr) - return (load_addr - load_base_addr) < GetByteSize(); + if (load_base_addr <= load_addr) + return (load_addr - load_base_addr) < GetByteSize(); - return false; + return false; } -bool -AddressRange::ContainsLoadAddress (addr_t load_addr, Target *target) const -{ - if (load_addr == LLDB_INVALID_ADDRESS) - return false; +bool AddressRange::ContainsLoadAddress(addr_t load_addr, Target *target) const { + if (load_addr == LLDB_INVALID_ADDRESS) + return false; - addr_t load_base_addr = GetBaseAddress().GetLoadAddress(target); - if (load_base_addr == LLDB_INVALID_ADDRESS) - return false; + addr_t load_base_addr = GetBaseAddress().GetLoadAddress(target); + if (load_base_addr == LLDB_INVALID_ADDRESS) + return false; - if (load_base_addr <= load_addr) - return (load_addr - load_base_addr) < GetByteSize(); + if (load_base_addr <= load_addr) + return (load_addr - load_base_addr) < GetByteSize(); - return false; + return false; } -void -AddressRange::Clear() -{ - m_base_addr.Clear(); - m_byte_size = 0; +void AddressRange::Clear() { + m_base_addr.Clear(); + m_byte_size = 0; } -bool -AddressRange::Dump(Stream *s, Target *target, Address::DumpStyle style, Address::DumpStyle fallback_style) const -{ - addr_t vmaddr = LLDB_INVALID_ADDRESS; - int addr_size = sizeof (addr_t); - if (target) - addr_size = target->GetArchitecture().GetAddressByteSize (); - - bool show_module = false; - switch (style) - { - default: - break; - case Address::DumpStyleSectionNameOffset: - case Address::DumpStyleSectionPointerOffset: - s->PutChar ('['); - m_base_addr.Dump(s, target, style, fallback_style); - s->PutChar ('-'); - s->Address (m_base_addr.GetOffset() + GetByteSize(), addr_size); - s->PutChar (')'); - return true; - break; - - case Address::DumpStyleModuleWithFileAddress: - show_module = true; - LLVM_FALLTHROUGH; - case Address::DumpStyleFileAddress: - vmaddr = m_base_addr.GetFileAddress(); - break; - - case Address::DumpStyleLoadAddress: - vmaddr = m_base_addr.GetLoadAddress(target); - break; +bool AddressRange::Dump(Stream *s, Target *target, Address::DumpStyle style, + Address::DumpStyle fallback_style) const { + addr_t vmaddr = LLDB_INVALID_ADDRESS; + int addr_size = sizeof(addr_t); + if (target) + addr_size = target->GetArchitecture().GetAddressByteSize(); + + bool show_module = false; + switch (style) { + default: + break; + case Address::DumpStyleSectionNameOffset: + case Address::DumpStyleSectionPointerOffset: + s->PutChar('['); + m_base_addr.Dump(s, target, style, fallback_style); + s->PutChar('-'); + s->Address(m_base_addr.GetOffset() + GetByteSize(), addr_size); + s->PutChar(')'); + return true; + break; + + case Address::DumpStyleModuleWithFileAddress: + show_module = true; + LLVM_FALLTHROUGH; + case Address::DumpStyleFileAddress: + vmaddr = m_base_addr.GetFileAddress(); + break; + + case Address::DumpStyleLoadAddress: + vmaddr = m_base_addr.GetLoadAddress(target); + break; + } + + if (vmaddr != LLDB_INVALID_ADDRESS) { + if (show_module) { + ModuleSP module_sp(GetBaseAddress().GetModule()); + if (module_sp) + s->Printf("%s", module_sp->GetFileSpec().GetFilename().AsCString( + "<Unknown>")); } + s->AddressRange(vmaddr, vmaddr + GetByteSize(), addr_size); + return true; + } else if (fallback_style != Address::DumpStyleInvalid) { + return Dump(s, target, fallback_style, Address::DumpStyleInvalid); + } - if (vmaddr != LLDB_INVALID_ADDRESS) - { - if (show_module) - { - ModuleSP module_sp (GetBaseAddress().GetModule()); - if (module_sp) - s->Printf("%s", module_sp->GetFileSpec().GetFilename().AsCString("<Unknown>")); - } - s->AddressRange(vmaddr, vmaddr + GetByteSize(), addr_size); - return true; - } - else if (fallback_style != Address::DumpStyleInvalid) - { - return Dump(s, target, fallback_style, Address::DumpStyleInvalid); - } - - return false; + return false; } - -void -AddressRange::DumpDebug (Stream *s) const -{ - s->Printf("%p: AddressRange section = %p, offset = 0x%16.16" PRIx64 ", byte_size = 0x%16.16" PRIx64 "\n", - static_cast<const void*>(this), - static_cast<void*>(m_base_addr.GetSection().get()), - m_base_addr.GetOffset(), GetByteSize()); +void AddressRange::DumpDebug(Stream *s) const { + s->Printf("%p: AddressRange section = %p, offset = 0x%16.16" PRIx64 + ", byte_size = 0x%16.16" PRIx64 "\n", + static_cast<const void *>(this), + static_cast<void *>(m_base_addr.GetSection().get()), + m_base_addr.GetOffset(), GetByteSize()); } // -//bool -//lldb::operator== (const AddressRange& lhs, const AddressRange& rhs) +// bool +// lldb::operator== (const AddressRange& lhs, const AddressRange& rhs) //{ // if (lhs.GetBaseAddress() == rhs.GetBaseAddress()) // return lhs.GetByteSize() == rhs.GetByteSize(); diff --git a/source/Core/AddressResolver.cpp b/source/Core/AddressResolver.cpp index aa457015b4fd..40f4d55340ec 100644 --- a/source/Core/AddressResolver.cpp +++ b/source/Core/AddressResolver.cpp @@ -9,7 +9,6 @@ #include "lldb/Core/AddressResolver.h" - // Project includes #include "lldb/Core/Address.h" @@ -26,41 +25,27 @@ using namespace lldb_private; //---------------------------------------------------------------------- // AddressResolver: //---------------------------------------------------------------------- -AddressResolver::AddressResolver () -{ -} +AddressResolver::AddressResolver() {} -AddressResolver::~AddressResolver () -{ - -} +AddressResolver::~AddressResolver() {} -void -AddressResolver::ResolveAddressInModules (SearchFilter &filter, ModuleList &modules) -{ - filter.SearchInModuleList(*this, modules); +void AddressResolver::ResolveAddressInModules(SearchFilter &filter, + ModuleList &modules) { + filter.SearchInModuleList(*this, modules); } -void -AddressResolver::ResolveAddress (SearchFilter &filter) -{ - filter.Search (*this); +void AddressResolver::ResolveAddress(SearchFilter &filter) { + filter.Search(*this); } -std::vector<AddressRange> & -AddressResolver::GetAddressRanges () -{ - return m_address_ranges; +std::vector<AddressRange> &AddressResolver::GetAddressRanges() { + return m_address_ranges; } -size_t -AddressResolver::GetNumberOfAddresses () -{ - return m_address_ranges.size(); +size_t AddressResolver::GetNumberOfAddresses() { + return m_address_ranges.size(); } -AddressRange & -AddressResolver::GetAddressRangeAtIndex (size_t idx) -{ +AddressRange &AddressResolver::GetAddressRangeAtIndex(size_t idx) { return m_address_ranges[idx]; } diff --git a/source/Core/AddressResolverFileLine.cpp b/source/Core/AddressResolverFileLine.cpp index e45076e9bfc6..939cf45f3e88 100644 --- a/source/Core/AddressResolverFileLine.cpp +++ b/source/Core/AddressResolverFileLine.cpp @@ -21,81 +21,58 @@ using namespace lldb_private; //---------------------------------------------------------------------- // AddressResolverFileLine: //---------------------------------------------------------------------- -AddressResolverFileLine::AddressResolverFileLine -( - const FileSpec &file_spec, - uint32_t line_no, - bool check_inlines -) : - AddressResolver (), - m_file_spec (file_spec), - m_line_number (line_no), - m_inlines (check_inlines) -{ -} +AddressResolverFileLine::AddressResolverFileLine(const FileSpec &file_spec, + uint32_t line_no, + bool check_inlines) + : AddressResolver(), m_file_spec(file_spec), m_line_number(line_no), + m_inlines(check_inlines) {} -AddressResolverFileLine::~AddressResolverFileLine () -{ -} +AddressResolverFileLine::~AddressResolverFileLine() {} Searcher::CallbackReturn -AddressResolverFileLine::SearchCallback -( - SearchFilter &filter, - SymbolContext &context, - Address *addr, - bool containing -) -{ - SymbolContextList sc_list; - uint32_t sc_list_size; - CompileUnit *cu = context.comp_unit; +AddressResolverFileLine::SearchCallback(SearchFilter &filter, + SymbolContext &context, Address *addr, + bool containing) { + SymbolContextList sc_list; + uint32_t sc_list_size; + CompileUnit *cu = context.comp_unit; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - sc_list_size = cu->ResolveSymbolContext (m_file_spec, m_line_number, m_inlines, false, eSymbolContextEverything, - sc_list); - for (uint32_t i = 0; i < sc_list_size; i++) - { - SymbolContext sc; - if (sc_list.GetContextAtIndex(i, sc)) - { - Address line_start = sc.line_entry.range.GetBaseAddress(); - addr_t byte_size = sc.line_entry.range.GetByteSize(); - if (line_start.IsValid()) - { - AddressRange new_range (line_start, byte_size); - m_address_ranges.push_back (new_range); - if (log) - { - StreamString s; - //new_bp_loc->GetDescription (&s, lldb::eDescriptionLevelVerbose); - //log->Printf ("Added address: %s\n", s.GetData()); - } - } - else - { - if (log) - log->Printf ("error: Unable to resolve address at file address 0x%" PRIx64 " for %s:%d\n", - line_start.GetFileAddress(), - m_file_spec.GetFilename().AsCString("<Unknown>"), - m_line_number); - } + sc_list_size = + cu->ResolveSymbolContext(m_file_spec, m_line_number, m_inlines, false, + eSymbolContextEverything, sc_list); + for (uint32_t i = 0; i < sc_list_size; i++) { + SymbolContext sc; + if (sc_list.GetContextAtIndex(i, sc)) { + Address line_start = sc.line_entry.range.GetBaseAddress(); + addr_t byte_size = sc.line_entry.range.GetByteSize(); + if (line_start.IsValid()) { + AddressRange new_range(line_start, byte_size); + m_address_ranges.push_back(new_range); + if (log) { + StreamString s; + // new_bp_loc->GetDescription (&s, lldb::eDescriptionLevelVerbose); + // log->Printf ("Added address: %s\n", s.GetData()); } + } else { + if (log) + log->Printf( + "error: Unable to resolve address at file address 0x%" PRIx64 + " for %s:%d\n", + line_start.GetFileAddress(), + m_file_spec.GetFilename().AsCString("<Unknown>"), m_line_number); + } } - return Searcher::eCallbackReturnContinue; + } + return Searcher::eCallbackReturnContinue; } -Searcher::Depth -AddressResolverFileLine::GetDepth() -{ - return Searcher::eDepthCompUnit; +Searcher::Depth AddressResolverFileLine::GetDepth() { + return Searcher::eDepthCompUnit; } -void -AddressResolverFileLine::GetDescription (Stream *s) -{ - s->Printf ("File and line address - file: \"%s\" line: %u", m_file_spec.GetFilename().AsCString("<Unknown>"), m_line_number); +void AddressResolverFileLine::GetDescription(Stream *s) { + s->Printf("File and line address - file: \"%s\" line: %u", + m_file_spec.GetFilename().AsCString("<Unknown>"), m_line_number); } - - diff --git a/source/Core/AddressResolverName.cpp b/source/Core/AddressResolverName.cpp index dacc7d777f85..d9b6dad5e4e3 100644 --- a/source/Core/AddressResolverName.cpp +++ b/source/Core/AddressResolverName.cpp @@ -17,223 +17,176 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Symbol/Function.h" -#include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/SymbolContext.h" using namespace lldb; using namespace lldb_private; AddressResolverName::AddressResolverName(const char *func_name, - AddressResolver::MatchType type) : - AddressResolver(), - m_func_name(func_name), - m_class_name(nullptr), - m_regex(), - m_match_type(type) -{ - if (m_match_type == AddressResolver::Regexp) - { - if (!m_regex.Compile (m_func_name.AsCString())) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - - if (log) - log->Warning ("function name regexp: \"%s\" did not compile.", m_func_name.AsCString()); - } + AddressResolver::MatchType type) + : AddressResolver(), m_func_name(func_name), m_class_name(nullptr), + m_regex(), m_match_type(type) { + if (m_match_type == AddressResolver::Regexp) { + if (!m_regex.Compile(m_func_name.GetStringRef())) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + + if (log) + log->Warning("function name regexp: \"%s\" did not compile.", + m_func_name.AsCString()); } + } } -AddressResolverName::AddressResolverName(RegularExpression &func_regex) : - AddressResolver(), - m_func_name(nullptr), - m_class_name(nullptr), - m_regex(func_regex), - m_match_type(AddressResolver::Regexp) -{ -} +AddressResolverName::AddressResolverName(RegularExpression &func_regex) + : AddressResolver(), m_func_name(nullptr), m_class_name(nullptr), + m_regex(func_regex), m_match_type(AddressResolver::Regexp) {} AddressResolverName::AddressResolverName(const char *class_name, const char *method, - AddressResolver::MatchType type) : - AddressResolver (), - m_func_name (method), - m_class_name (class_name), - m_regex (), - m_match_type (type) -{ -} + AddressResolver::MatchType type) + : AddressResolver(), m_func_name(method), m_class_name(class_name), + m_regex(), m_match_type(type) {} AddressResolverName::~AddressResolverName() = default; -// FIXME: Right now we look at the module level, and call the module's "FindFunctions". -// Greg says he will add function tables, maybe at the CompileUnit level to accelerate function -// lookup. At that point, we should switch the depth to CompileUnit, and look in these tables. +// FIXME: Right now we look at the module level, and call the module's +// "FindFunctions". +// Greg says he will add function tables, maybe at the CompileUnit level to +// accelerate function +// lookup. At that point, we should switch the depth to CompileUnit, and look +// in these tables. Searcher::CallbackReturn AddressResolverName::SearchCallback(SearchFilter &filter, - SymbolContext &context, - Address *addr, - bool containing) -{ - SymbolContextList func_list; - SymbolContextList sym_list; - - bool skip_prologue = true; - uint32_t i; - SymbolContext sc; - Address func_addr; - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); - - if (m_class_name) - { - if (log) - log->Warning ("Class/method function specification not supported yet.\n"); - return Searcher::eCallbackReturnStop; + SymbolContext &context, Address *addr, + bool containing) { + SymbolContextList func_list; + SymbolContextList sym_list; + + bool skip_prologue = true; + uint32_t i; + SymbolContext sc; + Address func_addr; + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + + if (m_class_name) { + if (log) + log->Warning("Class/method function specification not supported yet.\n"); + return Searcher::eCallbackReturnStop; + } + + const bool include_symbols = false; + const bool include_inlines = true; + const bool append = false; + switch (m_match_type) { + case AddressResolver::Exact: + if (context.module_sp) { + context.module_sp->FindSymbolsWithNameAndType(m_func_name, + eSymbolTypeCode, sym_list); + context.module_sp->FindFunctions(m_func_name, nullptr, + eFunctionNameTypeAuto, include_symbols, + include_inlines, append, func_list); } - - const bool include_symbols = false; - const bool include_inlines = true; - const bool append = false; - switch (m_match_type) - { - case AddressResolver::Exact: - if (context.module_sp) - { - context.module_sp->FindSymbolsWithNameAndType (m_func_name, - eSymbolTypeCode, - sym_list); - context.module_sp->FindFunctions(m_func_name, - nullptr, - eFunctionNameTypeAuto, - include_symbols, - include_inlines, - append, - func_list); - } - break; - - case AddressResolver::Regexp: - if (context.module_sp) - { - context.module_sp->FindSymbolsMatchingRegExAndType (m_regex, - eSymbolTypeCode, - sym_list); - context.module_sp->FindFunctions (m_regex, - include_symbols, - include_inlines, - append, - func_list); + break; + + case AddressResolver::Regexp: + if (context.module_sp) { + context.module_sp->FindSymbolsMatchingRegExAndType( + m_regex, eSymbolTypeCode, sym_list); + context.module_sp->FindFunctions(m_regex, include_symbols, + include_inlines, append, func_list); + } + break; + + case AddressResolver::Glob: + if (log) + log->Warning("glob is not supported yet."); + break; + } + + // Remove any duplicates between the function list and the symbol list + if (func_list.GetSize()) { + for (i = 0; i < func_list.GetSize(); i++) { + if (!func_list.GetContextAtIndex(i, sc)) + continue; + + if (sc.function == nullptr) + continue; + uint32_t j = 0; + while (j < sym_list.GetSize()) { + SymbolContext symbol_sc; + if (sym_list.GetContextAtIndex(j, symbol_sc)) { + if (symbol_sc.symbol && symbol_sc.symbol->ValueIsAddress()) { + if (sc.function->GetAddressRange().GetBaseAddress() == + symbol_sc.symbol->GetAddressRef()) { + sym_list.RemoveContextAtIndex(j); + continue; // Don't increment j + } + } } - break; - case AddressResolver::Glob: - if (log) - log->Warning ("glob is not supported yet."); - break; + j++; + } } - // Remove any duplicates between the function list and the symbol list - if (func_list.GetSize()) - { - for (i = 0; i < func_list.GetSize(); i++) - { - if (!func_list.GetContextAtIndex(i, sc)) - continue; - - if (sc.function == nullptr) - continue; - uint32_t j = 0; - while (j < sym_list.GetSize()) - { - SymbolContext symbol_sc; - if (sym_list.GetContextAtIndex(j, symbol_sc)) - { - if (symbol_sc.symbol && symbol_sc.symbol->ValueIsAddress()) - { - if (sc.function->GetAddressRange().GetBaseAddress() == symbol_sc.symbol->GetAddressRef()) - { - sym_list.RemoveContextAtIndex(j); - continue; // Don't increment j - } - } - } - - j++; + for (i = 0; i < func_list.GetSize(); i++) { + if (func_list.GetContextAtIndex(i, sc)) { + if (sc.function) { + func_addr = sc.function->GetAddressRange().GetBaseAddress(); + addr_t byte_size = sc.function->GetAddressRange().GetByteSize(); + if (skip_prologue) { + const uint32_t prologue_byte_size = + sc.function->GetPrologueByteSize(); + if (prologue_byte_size) { + func_addr.SetOffset(func_addr.GetOffset() + prologue_byte_size); + byte_size -= prologue_byte_size; } - } + } - for (i = 0; i < func_list.GetSize(); i++) - { - if (func_list.GetContextAtIndex(i, sc)) - { - if (sc.function) - { - func_addr = sc.function->GetAddressRange().GetBaseAddress(); - addr_t byte_size = sc.function->GetAddressRange().GetByteSize(); - if (skip_prologue) - { - const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); - if (prologue_byte_size) - { - func_addr.SetOffset (func_addr.GetOffset() + prologue_byte_size); - byte_size -= prologue_byte_size; - } - } - - if (filter.AddressPasses (func_addr)) - { - AddressRange new_range (func_addr, byte_size); - m_address_ranges.push_back (new_range); - } - } - } + if (filter.AddressPasses(func_addr)) { + AddressRange new_range(func_addr, byte_size); + m_address_ranges.push_back(new_range); + } } + } } + } + + for (i = 0; i < sym_list.GetSize(); i++) { + if (sym_list.GetContextAtIndex(i, sc)) { + if (sc.symbol && sc.symbol->ValueIsAddress()) { + func_addr = sc.symbol->GetAddressRef(); + addr_t byte_size = sc.symbol->GetByteSize(); + + if (skip_prologue) { + const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize(); + if (prologue_byte_size) { + func_addr.SetOffset(func_addr.GetOffset() + prologue_byte_size); + byte_size -= prologue_byte_size; + } + } - for (i = 0; i < sym_list.GetSize(); i++) - { - if (sym_list.GetContextAtIndex(i, sc)) - { - if (sc.symbol && sc.symbol->ValueIsAddress()) - { - func_addr = sc.symbol->GetAddressRef(); - addr_t byte_size = sc.symbol->GetByteSize(); - - if (skip_prologue) - { - const uint32_t prologue_byte_size = sc.symbol->GetPrologueByteSize(); - if (prologue_byte_size) - { - func_addr.SetOffset (func_addr.GetOffset() + prologue_byte_size); - byte_size -= prologue_byte_size; - } - } - - if (filter.AddressPasses (func_addr)) - { - AddressRange new_range (func_addr, byte_size); - m_address_ranges.push_back (new_range); - } - } + if (filter.AddressPasses(func_addr)) { + AddressRange new_range(func_addr, byte_size); + m_address_ranges.push_back(new_range); } + } } - return Searcher::eCallbackReturnContinue; + } + return Searcher::eCallbackReturnContinue; } -Searcher::Depth -AddressResolverName::GetDepth() -{ - return Searcher::eDepthModule; +Searcher::Depth AddressResolverName::GetDepth() { + return Searcher::eDepthModule; } -void -AddressResolverName::GetDescription (Stream *s) -{ - s->PutCString("Address by function name: "); +void AddressResolverName::GetDescription(Stream *s) { + s->PutCString("Address by function name: "); - if (m_match_type == AddressResolver::Regexp) - s->Printf("'%s' (regular expression)", m_regex.GetText()); - else - s->Printf("'%s'", m_func_name.AsCString()); + if (m_match_type == AddressResolver::Regexp) + s->Printf("'%s' (regular expression)", m_regex.GetText().str().c_str()); + else + s->Printf("'%s'", m_func_name.AsCString()); } diff --git a/source/Core/ArchSpec.cpp b/source/Core/ArchSpec.cpp index efdbf11d93e3..cf7afb83dabd 100644 --- a/source/Core/ArchSpec.cpp +++ b/source/Core/ArchSpec.cpp @@ -11,8 +11,8 @@ // C Includes // C++ Includes -#include <cstdio> #include <cerrno> +#include <cstdio> #include <string> // Other libraries and framework includes @@ -22,6 +22,8 @@ #include "llvm/Support/Host.h" // Project includes +#include "Plugins/Process/Utility/ARMDefines.h" +#include "Plugins/Process/Utility/InstructionUtils.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/StringList.h" #include "lldb/Host/Endian.h" @@ -32,166 +34,239 @@ #include "lldb/Target/Thread.h" #include "lldb/Utility/NameMatches.h" #include "lldb/Utility/SafeMachO.h" -#include "Plugins/Process/Utility/ARMDefines.h" -#include "Plugins/Process/Utility/InstructionUtils.h" using namespace lldb; using namespace lldb_private; -static bool cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_inverse, bool enforce_exact_match); +static bool cores_match(const ArchSpec::Core core1, const ArchSpec::Core core2, + bool try_inverse, bool enforce_exact_match); namespace lldb_private { - struct CoreDefinition - { - ByteOrder default_byte_order; - uint32_t addr_byte_size; - uint32_t min_opcode_byte_size; - uint32_t max_opcode_byte_size; - llvm::Triple::ArchType machine; - ArchSpec::Core core; - const char * const name; - }; +struct CoreDefinition { + ByteOrder default_byte_order; + uint32_t addr_byte_size; + uint32_t min_opcode_byte_size; + uint32_t max_opcode_byte_size; + llvm::Triple::ArchType machine; + ArchSpec::Core core; + const char *const name; +}; } // namespace lldb_private // This core information can be looked using the ArchSpec::Core as the index -static const CoreDefinition g_core_definitions[] = -{ - { eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_generic , "arm" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv4 , "armv4" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv4t , "armv4t" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv5 , "armv5" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv5e , "armv5e" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv5t , "armv5t" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv6 , "armv6" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv6m , "armv6m" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv7 , "armv7" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv7f , "armv7f" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv7s , "armv7s" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv7k , "armv7k" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv7m , "armv7m" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_armv7em , "armv7em" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::arm , ArchSpec::eCore_arm_xscale , "xscale" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumb , "thumb" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv4t , "thumbv4t" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv5 , "thumbv5" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv5e , "thumbv5e" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv6 , "thumbv6" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv6m , "thumbv6m" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv7 , "thumbv7" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv7f , "thumbv7f" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv7s , "thumbv7s" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv7k , "thumbv7k" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv7m , "thumbv7m" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb , ArchSpec::eCore_thumbv7em , "thumbv7em" }, - { eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64, ArchSpec::eCore_arm_arm64 , "arm64" }, - { eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64, ArchSpec::eCore_arm_armv8 , "armv8" }, - { eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64, ArchSpec::eCore_arm_aarch64 , "aarch64" }, +static const CoreDefinition g_core_definitions[] = { + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_generic, + "arm"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_armv4, + "armv4"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_armv4t, + "armv4t"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_armv5, + "armv5"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_armv5e, + "armv5e"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_armv5t, + "armv5t"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_armv6, + "armv6"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_armv6m, + "armv6m"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_armv7, + "armv7"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_armv7f, + "armv7f"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_armv7s, + "armv7s"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_armv7k, + "armv7k"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_armv7m, + "armv7m"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_armv7em, + "armv7em"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::arm, ArchSpec::eCore_arm_xscale, + "xscale"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb, ArchSpec::eCore_thumb, + "thumb"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb, ArchSpec::eCore_thumbv4t, + "thumbv4t"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb, ArchSpec::eCore_thumbv5, + "thumbv5"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb, ArchSpec::eCore_thumbv5e, + "thumbv5e"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb, ArchSpec::eCore_thumbv6, + "thumbv6"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb, ArchSpec::eCore_thumbv6m, + "thumbv6m"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb, ArchSpec::eCore_thumbv7, + "thumbv7"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb, ArchSpec::eCore_thumbv7f, + "thumbv7f"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb, ArchSpec::eCore_thumbv7s, + "thumbv7s"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb, ArchSpec::eCore_thumbv7k, + "thumbv7k"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb, ArchSpec::eCore_thumbv7m, + "thumbv7m"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::thumb, ArchSpec::eCore_thumbv7em, + "thumbv7em"}, + {eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64, + ArchSpec::eCore_arm_arm64, "arm64"}, + {eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64, + ArchSpec::eCore_arm_armv8, "armv8"}, + {eByteOrderLittle, 8, 4, 4, llvm::Triple::aarch64, + ArchSpec::eCore_arm_aarch64, "aarch64"}, // mips32, mips32r2, mips32r3, mips32r5, mips32r6 - { eByteOrderBig , 4, 2, 4, llvm::Triple::mips , ArchSpec::eCore_mips32 , "mips" }, - { eByteOrderBig , 4, 2, 4, llvm::Triple::mips , ArchSpec::eCore_mips32r2 , "mipsr2" }, - { eByteOrderBig , 4, 2, 4, llvm::Triple::mips , ArchSpec::eCore_mips32r3 , "mipsr3" }, - { eByteOrderBig , 4, 2, 4, llvm::Triple::mips , ArchSpec::eCore_mips32r5 , "mipsr5" }, - { eByteOrderBig , 4, 2, 4, llvm::Triple::mips , ArchSpec::eCore_mips32r6 , "mipsr6" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32el , "mipsel" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32r2el , "mipsr2el" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32r3el , "mipsr3el" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32r5el , "mipsr5el" }, - { eByteOrderLittle, 4, 2, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32r6el , "mipsr6el" }, - - // mips64, mips64r2, mips64r3, mips64r5, mips64r6 - { eByteOrderBig , 8, 2, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64 , "mips64" }, - { eByteOrderBig , 8, 2, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64r2 , "mips64r2" }, - { eByteOrderBig , 8, 2, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64r3 , "mips64r3" }, - { eByteOrderBig , 8, 2, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64r5 , "mips64r5" }, - { eByteOrderBig , 8, 2, 4, llvm::Triple::mips64 , ArchSpec::eCore_mips64r6 , "mips64r6" }, - { eByteOrderLittle, 8, 2, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64el , "mips64el" }, - { eByteOrderLittle, 8, 2, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64r2el , "mips64r2el" }, - { eByteOrderLittle, 8, 2, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64r3el , "mips64r3el" }, - { eByteOrderLittle, 8, 2, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64r5el , "mips64r5el" }, - { eByteOrderLittle, 8, 2, 4, llvm::Triple::mips64el, ArchSpec::eCore_mips64r6el , "mips64r6el" }, - - { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_generic , "powerpc" }, - { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc601 , "ppc601" }, - { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc602 , "ppc602" }, - { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc603 , "ppc603" }, - { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc603e , "ppc603e" }, - { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc603ev , "ppc603ev" }, - { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc604 , "ppc604" }, - { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc604e , "ppc604e" }, - { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc620 , "ppc620" }, - { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc750 , "ppc750" }, - { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc7400 , "ppc7400" }, - { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc7450 , "ppc7450" }, - { eByteOrderBig , 4, 4, 4, llvm::Triple::ppc , ArchSpec::eCore_ppc_ppc970 , "ppc970" }, - - { eByteOrderBig , 8, 4, 4, llvm::Triple::ppc64 , ArchSpec::eCore_ppc64_generic , "powerpc64" }, - { eByteOrderBig , 8, 4, 4, llvm::Triple::ppc64 , ArchSpec::eCore_ppc64_ppc970_64 , "ppc970-64" }, - - { eByteOrderBig , 8, 2, 6, llvm::Triple::systemz, ArchSpec::eCore_s390x_generic , "s390x" }, - - { eByteOrderLittle, 4, 4, 4, llvm::Triple::sparc , ArchSpec::eCore_sparc_generic , "sparc" }, - { eByteOrderLittle, 8, 4, 4, llvm::Triple::sparcv9, ArchSpec::eCore_sparc9_generic , "sparcv9" }, - - { eByteOrderLittle, 4, 1, 15, llvm::Triple::x86 , ArchSpec::eCore_x86_32_i386 , "i386" }, - { eByteOrderLittle, 4, 1, 15, llvm::Triple::x86 , ArchSpec::eCore_x86_32_i486 , "i486" }, - { eByteOrderLittle, 4, 1, 15, llvm::Triple::x86 , ArchSpec::eCore_x86_32_i486sx , "i486sx" }, - { eByteOrderLittle, 4, 1, 15, llvm::Triple::x86 , ArchSpec::eCore_x86_32_i686 , "i686" }, - - { eByteOrderLittle, 8, 1, 15, llvm::Triple::x86_64 , ArchSpec::eCore_x86_64_x86_64 , "x86_64" }, - { eByteOrderLittle, 8, 1, 15, llvm::Triple::x86_64 , ArchSpec::eCore_x86_64_x86_64h , "x86_64h" }, - { eByteOrderLittle, 4, 4, 4, llvm::Triple::hexagon , ArchSpec::eCore_hexagon_generic, "hexagon" }, - { eByteOrderLittle, 4, 4, 4, llvm::Triple::hexagon , ArchSpec::eCore_hexagon_hexagonv4, "hexagonv4" }, - { eByteOrderLittle, 4, 4, 4, llvm::Triple::hexagon , ArchSpec::eCore_hexagon_hexagonv5, "hexagonv5" }, - - { eByteOrderLittle, 4, 4, 4 , llvm::Triple::UnknownArch , ArchSpec::eCore_uknownMach32 , "unknown-mach-32" }, - { eByteOrderLittle, 8, 4, 4 , llvm::Triple::UnknownArch , ArchSpec::eCore_uknownMach64 , "unknown-mach-64" }, - - { eByteOrderBig , 4, 1, 1 , llvm::Triple::kalimba , ArchSpec::eCore_kalimba3 , "kalimba3" }, - { eByteOrderLittle, 4, 1, 1 , llvm::Triple::kalimba , ArchSpec::eCore_kalimba4 , "kalimba4" }, - { eByteOrderLittle, 4, 1, 1 , llvm::Triple::kalimba , ArchSpec::eCore_kalimba5 , "kalimba5" } -}; + {eByteOrderBig, 4, 2, 4, llvm::Triple::mips, ArchSpec::eCore_mips32, + "mips"}, + {eByteOrderBig, 4, 2, 4, llvm::Triple::mips, ArchSpec::eCore_mips32r2, + "mipsr2"}, + {eByteOrderBig, 4, 2, 4, llvm::Triple::mips, ArchSpec::eCore_mips32r3, + "mipsr3"}, + {eByteOrderBig, 4, 2, 4, llvm::Triple::mips, ArchSpec::eCore_mips32r5, + "mipsr5"}, + {eByteOrderBig, 4, 2, 4, llvm::Triple::mips, ArchSpec::eCore_mips32r6, + "mipsr6"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::mipsel, ArchSpec::eCore_mips32el, + "mipsel"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::mipsel, + ArchSpec::eCore_mips32r2el, "mipsr2el"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::mipsel, + ArchSpec::eCore_mips32r3el, "mipsr3el"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::mipsel, + ArchSpec::eCore_mips32r5el, "mipsr5el"}, + {eByteOrderLittle, 4, 2, 4, llvm::Triple::mipsel, + ArchSpec::eCore_mips32r6el, "mipsr6el"}, -// Ensure that we have an entry in the g_core_definitions for each core. If you comment out an entry above, + // mips64, mips64r2, mips64r3, mips64r5, mips64r6 + {eByteOrderBig, 8, 2, 4, llvm::Triple::mips64, ArchSpec::eCore_mips64, + "mips64"}, + {eByteOrderBig, 8, 2, 4, llvm::Triple::mips64, ArchSpec::eCore_mips64r2, + "mips64r2"}, + {eByteOrderBig, 8, 2, 4, llvm::Triple::mips64, ArchSpec::eCore_mips64r3, + "mips64r3"}, + {eByteOrderBig, 8, 2, 4, llvm::Triple::mips64, ArchSpec::eCore_mips64r5, + "mips64r5"}, + {eByteOrderBig, 8, 2, 4, llvm::Triple::mips64, ArchSpec::eCore_mips64r6, + "mips64r6"}, + {eByteOrderLittle, 8, 2, 4, llvm::Triple::mips64el, + ArchSpec::eCore_mips64el, "mips64el"}, + {eByteOrderLittle, 8, 2, 4, llvm::Triple::mips64el, + ArchSpec::eCore_mips64r2el, "mips64r2el"}, + {eByteOrderLittle, 8, 2, 4, llvm::Triple::mips64el, + ArchSpec::eCore_mips64r3el, "mips64r3el"}, + {eByteOrderLittle, 8, 2, 4, llvm::Triple::mips64el, + ArchSpec::eCore_mips64r5el, "mips64r5el"}, + {eByteOrderLittle, 8, 2, 4, llvm::Triple::mips64el, + ArchSpec::eCore_mips64r6el, "mips64r6el"}, + + {eByteOrderBig, 4, 4, 4, llvm::Triple::ppc, ArchSpec::eCore_ppc_generic, + "powerpc"}, + {eByteOrderBig, 4, 4, 4, llvm::Triple::ppc, ArchSpec::eCore_ppc_ppc601, + "ppc601"}, + {eByteOrderBig, 4, 4, 4, llvm::Triple::ppc, ArchSpec::eCore_ppc_ppc602, + "ppc602"}, + {eByteOrderBig, 4, 4, 4, llvm::Triple::ppc, ArchSpec::eCore_ppc_ppc603, + "ppc603"}, + {eByteOrderBig, 4, 4, 4, llvm::Triple::ppc, ArchSpec::eCore_ppc_ppc603e, + "ppc603e"}, + {eByteOrderBig, 4, 4, 4, llvm::Triple::ppc, ArchSpec::eCore_ppc_ppc603ev, + "ppc603ev"}, + {eByteOrderBig, 4, 4, 4, llvm::Triple::ppc, ArchSpec::eCore_ppc_ppc604, + "ppc604"}, + {eByteOrderBig, 4, 4, 4, llvm::Triple::ppc, ArchSpec::eCore_ppc_ppc604e, + "ppc604e"}, + {eByteOrderBig, 4, 4, 4, llvm::Triple::ppc, ArchSpec::eCore_ppc_ppc620, + "ppc620"}, + {eByteOrderBig, 4, 4, 4, llvm::Triple::ppc, ArchSpec::eCore_ppc_ppc750, + "ppc750"}, + {eByteOrderBig, 4, 4, 4, llvm::Triple::ppc, ArchSpec::eCore_ppc_ppc7400, + "ppc7400"}, + {eByteOrderBig, 4, 4, 4, llvm::Triple::ppc, ArchSpec::eCore_ppc_ppc7450, + "ppc7450"}, + {eByteOrderBig, 4, 4, 4, llvm::Triple::ppc, ArchSpec::eCore_ppc_ppc970, + "ppc970"}, + + {eByteOrderBig, 8, 4, 4, llvm::Triple::ppc64, ArchSpec::eCore_ppc64_generic, + "powerpc64"}, + {eByteOrderBig, 8, 4, 4, llvm::Triple::ppc64, + ArchSpec::eCore_ppc64_ppc970_64, "ppc970-64"}, + + {eByteOrderBig, 8, 2, 6, llvm::Triple::systemz, + ArchSpec::eCore_s390x_generic, "s390x"}, + + {eByteOrderLittle, 4, 4, 4, llvm::Triple::sparc, + ArchSpec::eCore_sparc_generic, "sparc"}, + {eByteOrderLittle, 8, 4, 4, llvm::Triple::sparcv9, + ArchSpec::eCore_sparc9_generic, "sparcv9"}, + + {eByteOrderLittle, 4, 1, 15, llvm::Triple::x86, ArchSpec::eCore_x86_32_i386, + "i386"}, + {eByteOrderLittle, 4, 1, 15, llvm::Triple::x86, ArchSpec::eCore_x86_32_i486, + "i486"}, + {eByteOrderLittle, 4, 1, 15, llvm::Triple::x86, + ArchSpec::eCore_x86_32_i486sx, "i486sx"}, + {eByteOrderLittle, 4, 1, 15, llvm::Triple::x86, ArchSpec::eCore_x86_32_i686, + "i686"}, + + {eByteOrderLittle, 8, 1, 15, llvm::Triple::x86_64, + ArchSpec::eCore_x86_64_x86_64, "x86_64"}, + {eByteOrderLittle, 8, 1, 15, llvm::Triple::x86_64, + ArchSpec::eCore_x86_64_x86_64h, "x86_64h"}, + {eByteOrderLittle, 4, 4, 4, llvm::Triple::hexagon, + ArchSpec::eCore_hexagon_generic, "hexagon"}, + {eByteOrderLittle, 4, 4, 4, llvm::Triple::hexagon, + ArchSpec::eCore_hexagon_hexagonv4, "hexagonv4"}, + {eByteOrderLittle, 4, 4, 4, llvm::Triple::hexagon, + ArchSpec::eCore_hexagon_hexagonv5, "hexagonv5"}, + + {eByteOrderLittle, 4, 4, 4, llvm::Triple::UnknownArch, + ArchSpec::eCore_uknownMach32, "unknown-mach-32"}, + {eByteOrderLittle, 8, 4, 4, llvm::Triple::UnknownArch, + ArchSpec::eCore_uknownMach64, "unknown-mach-64"}, + + {eByteOrderBig, 4, 1, 1, llvm::Triple::kalimba, ArchSpec::eCore_kalimba3, + "kalimba3"}, + {eByteOrderLittle, 4, 1, 1, llvm::Triple::kalimba, ArchSpec::eCore_kalimba4, + "kalimba4"}, + {eByteOrderLittle, 4, 1, 1, llvm::Triple::kalimba, ArchSpec::eCore_kalimba5, + "kalimba5"}}; + +// Ensure that we have an entry in the g_core_definitions for each core. If you +// comment out an entry above, // you will need to comment out the corresponding ArchSpec::Core enumeration. -static_assert(sizeof(g_core_definitions) / sizeof(CoreDefinition) == ArchSpec::kNumCores, "make sure we have one core definition for each core"); - -struct ArchDefinitionEntry -{ - ArchSpec::Core core; - uint32_t cpu; - uint32_t sub; - uint32_t cpu_mask; - uint32_t sub_mask; +static_assert(sizeof(g_core_definitions) / sizeof(CoreDefinition) == + ArchSpec::kNumCores, + "make sure we have one core definition for each core"); + +struct ArchDefinitionEntry { + ArchSpec::Core core; + uint32_t cpu; + uint32_t sub; + uint32_t cpu_mask; + uint32_t sub_mask; }; -struct ArchDefinition -{ - ArchitectureType type; - size_t num_entries; - const ArchDefinitionEntry *entries; - const char *name; +struct ArchDefinition { + ArchitectureType type; + size_t num_entries; + const ArchDefinitionEntry *entries; + const char *name; }; -size_t -ArchSpec::AutoComplete (const char *name, StringList &matches) -{ - if (name && name[0]) - { - for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) - { - if (NameMatches(g_core_definitions[i].name, eNameMatchStartsWith, name)) - matches.AppendString (g_core_definitions[i].name); - } +size_t ArchSpec::AutoComplete(llvm::StringRef name, StringList &matches) { + if (!name.empty()) { + for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) { + if (NameMatches(g_core_definitions[i].name, eNameMatchStartsWith, name)) + matches.AppendString(g_core_definitions[i].name); } - else - { - for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) - matches.AppendString (g_core_definitions[i].name); - } - return matches.GetSize(); + } else { + for (uint32_t i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) + matches.AppendString(g_core_definitions[i].name); + } + return matches.GetSize(); } #define CPU_ANY (UINT32_MAX) @@ -203,267 +278,305 @@ ArchSpec::AutoComplete (const char *name, StringList &matches) // allows the precedence to be set when the table is built. #define SUBTYPE_MASK 0x00FFFFFFu -static const ArchDefinitionEntry g_macho_arch_entries[] = -{ - { ArchSpec::eCore_arm_generic , llvm::MachO::CPU_TYPE_ARM , CPU_ANY, UINT32_MAX , UINT32_MAX }, - { ArchSpec::eCore_arm_generic , llvm::MachO::CPU_TYPE_ARM , 0 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_armv4 , llvm::MachO::CPU_TYPE_ARM , 5 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_armv4t , llvm::MachO::CPU_TYPE_ARM , 5 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_armv6 , llvm::MachO::CPU_TYPE_ARM , 6 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_armv6m , llvm::MachO::CPU_TYPE_ARM , 14 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_armv5 , llvm::MachO::CPU_TYPE_ARM , 7 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_armv5e , llvm::MachO::CPU_TYPE_ARM , 7 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_armv5t , llvm::MachO::CPU_TYPE_ARM , 7 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_xscale , llvm::MachO::CPU_TYPE_ARM , 8 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_armv7 , llvm::MachO::CPU_TYPE_ARM , 9 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_armv7f , llvm::MachO::CPU_TYPE_ARM , 10 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_armv7s , llvm::MachO::CPU_TYPE_ARM , 11 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_armv7k , llvm::MachO::CPU_TYPE_ARM , 12 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_armv7m , llvm::MachO::CPU_TYPE_ARM , 15 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_armv7em , llvm::MachO::CPU_TYPE_ARM , 16 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_arm64 , llvm::MachO::CPU_TYPE_ARM64 , 1 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_arm64 , llvm::MachO::CPU_TYPE_ARM64 , 0 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_arm64 , llvm::MachO::CPU_TYPE_ARM64 , 13 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_arm_arm64 , llvm::MachO::CPU_TYPE_ARM64 , CPU_ANY, UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_thumb , llvm::MachO::CPU_TYPE_ARM , 0 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_thumbv4t , llvm::MachO::CPU_TYPE_ARM , 5 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_thumbv5 , llvm::MachO::CPU_TYPE_ARM , 7 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_thumbv5e , llvm::MachO::CPU_TYPE_ARM , 7 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_thumbv6 , llvm::MachO::CPU_TYPE_ARM , 6 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_thumbv6m , llvm::MachO::CPU_TYPE_ARM , 14 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_thumbv7 , llvm::MachO::CPU_TYPE_ARM , 9 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_thumbv7f , llvm::MachO::CPU_TYPE_ARM , 10 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_thumbv7s , llvm::MachO::CPU_TYPE_ARM , 11 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_thumbv7k , llvm::MachO::CPU_TYPE_ARM , 12 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_thumbv7m , llvm::MachO::CPU_TYPE_ARM , 15 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_thumbv7em , llvm::MachO::CPU_TYPE_ARM , 16 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_ppc_generic , llvm::MachO::CPU_TYPE_POWERPC , CPU_ANY, UINT32_MAX , UINT32_MAX }, - { ArchSpec::eCore_ppc_generic , llvm::MachO::CPU_TYPE_POWERPC , 0 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_ppc_ppc601 , llvm::MachO::CPU_TYPE_POWERPC , 1 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_ppc_ppc602 , llvm::MachO::CPU_TYPE_POWERPC , 2 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_ppc_ppc603 , llvm::MachO::CPU_TYPE_POWERPC , 3 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_ppc_ppc603e , llvm::MachO::CPU_TYPE_POWERPC , 4 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_ppc_ppc603ev , llvm::MachO::CPU_TYPE_POWERPC , 5 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_ppc_ppc604 , llvm::MachO::CPU_TYPE_POWERPC , 6 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_ppc_ppc604e , llvm::MachO::CPU_TYPE_POWERPC , 7 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_ppc_ppc620 , llvm::MachO::CPU_TYPE_POWERPC , 8 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_ppc_ppc750 , llvm::MachO::CPU_TYPE_POWERPC , 9 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_ppc_ppc7400 , llvm::MachO::CPU_TYPE_POWERPC , 10 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_ppc_ppc7450 , llvm::MachO::CPU_TYPE_POWERPC , 11 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_ppc_ppc970 , llvm::MachO::CPU_TYPE_POWERPC , 100 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_ppc64_generic , llvm::MachO::CPU_TYPE_POWERPC64 , 0 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_ppc64_ppc970_64 , llvm::MachO::CPU_TYPE_POWERPC64 , 100 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_x86_32_i386 , llvm::MachO::CPU_TYPE_I386 , 3 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_x86_32_i486 , llvm::MachO::CPU_TYPE_I386 , 4 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_x86_32_i486sx , llvm::MachO::CPU_TYPE_I386 , 0x84 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_x86_32_i386 , llvm::MachO::CPU_TYPE_I386 , CPU_ANY, UINT32_MAX , UINT32_MAX }, - { ArchSpec::eCore_x86_64_x86_64 , llvm::MachO::CPU_TYPE_X86_64 , 3 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_x86_64_x86_64 , llvm::MachO::CPU_TYPE_X86_64 , 4 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_x86_64_x86_64h , llvm::MachO::CPU_TYPE_X86_64 , 8 , UINT32_MAX , SUBTYPE_MASK }, - { ArchSpec::eCore_x86_64_x86_64 , llvm::MachO::CPU_TYPE_X86_64 , CPU_ANY, UINT32_MAX , UINT32_MAX }, - // Catch any unknown mach architectures so we can always use the object and symbol mach-o files - { ArchSpec::eCore_uknownMach32 , 0 , 0 , 0xFF000000u, 0x00000000u }, - { ArchSpec::eCore_uknownMach64 , llvm::MachO::CPU_ARCH_ABI64 , 0 , 0xFF000000u, 0x00000000u } -}; +static const ArchDefinitionEntry g_macho_arch_entries[] = { + {ArchSpec::eCore_arm_generic, llvm::MachO::CPU_TYPE_ARM, CPU_ANY, + UINT32_MAX, UINT32_MAX}, + {ArchSpec::eCore_arm_generic, llvm::MachO::CPU_TYPE_ARM, 0, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_armv4, llvm::MachO::CPU_TYPE_ARM, 5, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_armv4t, llvm::MachO::CPU_TYPE_ARM, 5, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_armv6, llvm::MachO::CPU_TYPE_ARM, 6, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_armv6m, llvm::MachO::CPU_TYPE_ARM, 14, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_armv5, llvm::MachO::CPU_TYPE_ARM, 7, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_armv5e, llvm::MachO::CPU_TYPE_ARM, 7, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_armv5t, llvm::MachO::CPU_TYPE_ARM, 7, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_xscale, llvm::MachO::CPU_TYPE_ARM, 8, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_armv7, llvm::MachO::CPU_TYPE_ARM, 9, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_armv7f, llvm::MachO::CPU_TYPE_ARM, 10, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_armv7s, llvm::MachO::CPU_TYPE_ARM, 11, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_armv7k, llvm::MachO::CPU_TYPE_ARM, 12, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_armv7m, llvm::MachO::CPU_TYPE_ARM, 15, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_armv7em, llvm::MachO::CPU_TYPE_ARM, 16, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_arm64, llvm::MachO::CPU_TYPE_ARM64, 1, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_arm64, llvm::MachO::CPU_TYPE_ARM64, 0, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_arm64, llvm::MachO::CPU_TYPE_ARM64, 13, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_arm_arm64, llvm::MachO::CPU_TYPE_ARM64, CPU_ANY, + UINT32_MAX, SUBTYPE_MASK}, + {ArchSpec::eCore_thumb, llvm::MachO::CPU_TYPE_ARM, 0, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_thumbv4t, llvm::MachO::CPU_TYPE_ARM, 5, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_thumbv5, llvm::MachO::CPU_TYPE_ARM, 7, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_thumbv5e, llvm::MachO::CPU_TYPE_ARM, 7, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_thumbv6, llvm::MachO::CPU_TYPE_ARM, 6, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_thumbv6m, llvm::MachO::CPU_TYPE_ARM, 14, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_thumbv7, llvm::MachO::CPU_TYPE_ARM, 9, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_thumbv7f, llvm::MachO::CPU_TYPE_ARM, 10, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_thumbv7s, llvm::MachO::CPU_TYPE_ARM, 11, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_thumbv7k, llvm::MachO::CPU_TYPE_ARM, 12, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_thumbv7m, llvm::MachO::CPU_TYPE_ARM, 15, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_thumbv7em, llvm::MachO::CPU_TYPE_ARM, 16, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_ppc_generic, llvm::MachO::CPU_TYPE_POWERPC, CPU_ANY, + UINT32_MAX, UINT32_MAX}, + {ArchSpec::eCore_ppc_generic, llvm::MachO::CPU_TYPE_POWERPC, 0, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_ppc_ppc601, llvm::MachO::CPU_TYPE_POWERPC, 1, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_ppc_ppc602, llvm::MachO::CPU_TYPE_POWERPC, 2, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_ppc_ppc603, llvm::MachO::CPU_TYPE_POWERPC, 3, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_ppc_ppc603e, llvm::MachO::CPU_TYPE_POWERPC, 4, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_ppc_ppc603ev, llvm::MachO::CPU_TYPE_POWERPC, 5, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_ppc_ppc604, llvm::MachO::CPU_TYPE_POWERPC, 6, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_ppc_ppc604e, llvm::MachO::CPU_TYPE_POWERPC, 7, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_ppc_ppc620, llvm::MachO::CPU_TYPE_POWERPC, 8, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_ppc_ppc750, llvm::MachO::CPU_TYPE_POWERPC, 9, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_ppc_ppc7400, llvm::MachO::CPU_TYPE_POWERPC, 10, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_ppc_ppc7450, llvm::MachO::CPU_TYPE_POWERPC, 11, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_ppc_ppc970, llvm::MachO::CPU_TYPE_POWERPC, 100, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_ppc64_generic, llvm::MachO::CPU_TYPE_POWERPC64, 0, + UINT32_MAX, SUBTYPE_MASK}, + {ArchSpec::eCore_ppc64_ppc970_64, llvm::MachO::CPU_TYPE_POWERPC64, 100, + UINT32_MAX, SUBTYPE_MASK}, + {ArchSpec::eCore_x86_32_i386, llvm::MachO::CPU_TYPE_I386, 3, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_x86_32_i486, llvm::MachO::CPU_TYPE_I386, 4, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_x86_32_i486sx, llvm::MachO::CPU_TYPE_I386, 0x84, + UINT32_MAX, SUBTYPE_MASK}, + {ArchSpec::eCore_x86_32_i386, llvm::MachO::CPU_TYPE_I386, CPU_ANY, + UINT32_MAX, UINT32_MAX}, + {ArchSpec::eCore_x86_64_x86_64, llvm::MachO::CPU_TYPE_X86_64, 3, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_x86_64_x86_64, llvm::MachO::CPU_TYPE_X86_64, 4, UINT32_MAX, + SUBTYPE_MASK}, + {ArchSpec::eCore_x86_64_x86_64h, llvm::MachO::CPU_TYPE_X86_64, 8, + UINT32_MAX, SUBTYPE_MASK}, + {ArchSpec::eCore_x86_64_x86_64, llvm::MachO::CPU_TYPE_X86_64, CPU_ANY, + UINT32_MAX, UINT32_MAX}, + // Catch any unknown mach architectures so we can always use the object and + // symbol mach-o files + {ArchSpec::eCore_uknownMach32, 0, 0, 0xFF000000u, 0x00000000u}, + {ArchSpec::eCore_uknownMach64, llvm::MachO::CPU_ARCH_ABI64, 0, 0xFF000000u, + 0x00000000u}}; static const ArchDefinition g_macho_arch_def = { - eArchTypeMachO, - llvm::array_lengthof(g_macho_arch_entries), - g_macho_arch_entries, - "mach-o" -}; + eArchTypeMachO, llvm::array_lengthof(g_macho_arch_entries), + g_macho_arch_entries, "mach-o"}; //===----------------------------------------------------------------------===// // A table that gets searched linearly for matches. This table is used to // convert cpu type and subtypes to architecture names, and to convert // architecture names to cpu types and subtypes. The ordering is important and // allows the precedence to be set when the table is built. -static const ArchDefinitionEntry g_elf_arch_entries[] = -{ - { ArchSpec::eCore_sparc_generic , llvm::ELF::EM_SPARC , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // Sparc - { ArchSpec::eCore_x86_32_i386 , llvm::ELF::EM_386 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // Intel 80386 - { ArchSpec::eCore_x86_32_i486 , llvm::ELF::EM_IAMCU , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // Intel MCU // FIXME: is this correct? - { ArchSpec::eCore_ppc_generic , llvm::ELF::EM_PPC , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // PowerPC - { ArchSpec::eCore_ppc64_generic , llvm::ELF::EM_PPC64 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // PowerPC64 - { ArchSpec::eCore_arm_generic , llvm::ELF::EM_ARM , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARM - { ArchSpec::eCore_arm_aarch64 , llvm::ELF::EM_AARCH64, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARM64 - { ArchSpec::eCore_s390x_generic , llvm::ELF::EM_S390 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // SystemZ - { ArchSpec::eCore_sparc9_generic , llvm::ELF::EM_SPARCV9, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // SPARC V9 - { ArchSpec::eCore_x86_64_x86_64 , llvm::ELF::EM_X86_64 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // AMD64 - { ArchSpec::eCore_mips32 , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips32, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips32 - { ArchSpec::eCore_mips32r2 , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips32r2, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips32r2 - { ArchSpec::eCore_mips32r6 , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips32r6, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips32r6 - { ArchSpec::eCore_mips32el , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips32el, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips32el - { ArchSpec::eCore_mips32r2el , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips32r2el, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips32r2el - { ArchSpec::eCore_mips32r6el , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips32r6el, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips32r6el - { ArchSpec::eCore_mips64 , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips64, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips64 - { ArchSpec::eCore_mips64r2 , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips64r2, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips64r2 - { ArchSpec::eCore_mips64r6 , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips64r6, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips64r6 - { ArchSpec::eCore_mips64el , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips64el, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips64el - { ArchSpec::eCore_mips64r2el , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips64r2el, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips64r2el - { ArchSpec::eCore_mips64r6el , llvm::ELF::EM_MIPS , ArchSpec::eMIPSSubType_mips64r6el, 0xFFFFFFFFu, 0xFFFFFFFFu }, // mips64r6el - { ArchSpec::eCore_hexagon_generic , llvm::ELF::EM_HEXAGON, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // HEXAGON - { ArchSpec::eCore_kalimba3 , llvm::ELF::EM_CSR_KALIMBA, llvm::Triple::KalimbaSubArch_v3, 0xFFFFFFFFu, 0xFFFFFFFFu }, // KALIMBA - { ArchSpec::eCore_kalimba4 , llvm::ELF::EM_CSR_KALIMBA, llvm::Triple::KalimbaSubArch_v4, 0xFFFFFFFFu, 0xFFFFFFFFu }, // KALIMBA - { ArchSpec::eCore_kalimba5 , llvm::ELF::EM_CSR_KALIMBA, llvm::Triple::KalimbaSubArch_v5, 0xFFFFFFFFu, 0xFFFFFFFFu } // KALIMBA +static const ArchDefinitionEntry g_elf_arch_entries[] = { + {ArchSpec::eCore_sparc_generic, llvm::ELF::EM_SPARC, LLDB_INVALID_CPUTYPE, + 0xFFFFFFFFu, 0xFFFFFFFFu}, // Sparc + {ArchSpec::eCore_x86_32_i386, llvm::ELF::EM_386, LLDB_INVALID_CPUTYPE, + 0xFFFFFFFFu, 0xFFFFFFFFu}, // Intel 80386 + {ArchSpec::eCore_x86_32_i486, llvm::ELF::EM_IAMCU, LLDB_INVALID_CPUTYPE, + 0xFFFFFFFFu, 0xFFFFFFFFu}, // Intel MCU // FIXME: is this correct? + {ArchSpec::eCore_ppc_generic, llvm::ELF::EM_PPC, LLDB_INVALID_CPUTYPE, + 0xFFFFFFFFu, 0xFFFFFFFFu}, // PowerPC + {ArchSpec::eCore_ppc64_generic, llvm::ELF::EM_PPC64, LLDB_INVALID_CPUTYPE, + 0xFFFFFFFFu, 0xFFFFFFFFu}, // PowerPC64 + {ArchSpec::eCore_arm_generic, llvm::ELF::EM_ARM, LLDB_INVALID_CPUTYPE, + 0xFFFFFFFFu, 0xFFFFFFFFu}, // ARM + {ArchSpec::eCore_arm_aarch64, llvm::ELF::EM_AARCH64, LLDB_INVALID_CPUTYPE, + 0xFFFFFFFFu, 0xFFFFFFFFu}, // ARM64 + {ArchSpec::eCore_s390x_generic, llvm::ELF::EM_S390, LLDB_INVALID_CPUTYPE, + 0xFFFFFFFFu, 0xFFFFFFFFu}, // SystemZ + {ArchSpec::eCore_sparc9_generic, llvm::ELF::EM_SPARCV9, + LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // SPARC V9 + {ArchSpec::eCore_x86_64_x86_64, llvm::ELF::EM_X86_64, LLDB_INVALID_CPUTYPE, + 0xFFFFFFFFu, 0xFFFFFFFFu}, // AMD64 + {ArchSpec::eCore_mips32, llvm::ELF::EM_MIPS, ArchSpec::eMIPSSubType_mips32, + 0xFFFFFFFFu, 0xFFFFFFFFu}, // mips32 + {ArchSpec::eCore_mips32r2, llvm::ELF::EM_MIPS, + ArchSpec::eMIPSSubType_mips32r2, 0xFFFFFFFFu, 0xFFFFFFFFu}, // mips32r2 + {ArchSpec::eCore_mips32r6, llvm::ELF::EM_MIPS, + ArchSpec::eMIPSSubType_mips32r6, 0xFFFFFFFFu, 0xFFFFFFFFu}, // mips32r6 + {ArchSpec::eCore_mips32el, llvm::ELF::EM_MIPS, + ArchSpec::eMIPSSubType_mips32el, 0xFFFFFFFFu, 0xFFFFFFFFu}, // mips32el + {ArchSpec::eCore_mips32r2el, llvm::ELF::EM_MIPS, + ArchSpec::eMIPSSubType_mips32r2el, 0xFFFFFFFFu, 0xFFFFFFFFu}, // mips32r2el + {ArchSpec::eCore_mips32r6el, llvm::ELF::EM_MIPS, + ArchSpec::eMIPSSubType_mips32r6el, 0xFFFFFFFFu, 0xFFFFFFFFu}, // mips32r6el + {ArchSpec::eCore_mips64, llvm::ELF::EM_MIPS, ArchSpec::eMIPSSubType_mips64, + 0xFFFFFFFFu, 0xFFFFFFFFu}, // mips64 + {ArchSpec::eCore_mips64r2, llvm::ELF::EM_MIPS, + ArchSpec::eMIPSSubType_mips64r2, 0xFFFFFFFFu, 0xFFFFFFFFu}, // mips64r2 + {ArchSpec::eCore_mips64r6, llvm::ELF::EM_MIPS, + ArchSpec::eMIPSSubType_mips64r6, 0xFFFFFFFFu, 0xFFFFFFFFu}, // mips64r6 + {ArchSpec::eCore_mips64el, llvm::ELF::EM_MIPS, + ArchSpec::eMIPSSubType_mips64el, 0xFFFFFFFFu, 0xFFFFFFFFu}, // mips64el + {ArchSpec::eCore_mips64r2el, llvm::ELF::EM_MIPS, + ArchSpec::eMIPSSubType_mips64r2el, 0xFFFFFFFFu, 0xFFFFFFFFu}, // mips64r2el + {ArchSpec::eCore_mips64r6el, llvm::ELF::EM_MIPS, + ArchSpec::eMIPSSubType_mips64r6el, 0xFFFFFFFFu, 0xFFFFFFFFu}, // mips64r6el + {ArchSpec::eCore_hexagon_generic, llvm::ELF::EM_HEXAGON, + LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // HEXAGON + {ArchSpec::eCore_kalimba3, llvm::ELF::EM_CSR_KALIMBA, + llvm::Triple::KalimbaSubArch_v3, 0xFFFFFFFFu, 0xFFFFFFFFu}, // KALIMBA + {ArchSpec::eCore_kalimba4, llvm::ELF::EM_CSR_KALIMBA, + llvm::Triple::KalimbaSubArch_v4, 0xFFFFFFFFu, 0xFFFFFFFFu}, // KALIMBA + {ArchSpec::eCore_kalimba5, llvm::ELF::EM_CSR_KALIMBA, + llvm::Triple::KalimbaSubArch_v5, 0xFFFFFFFFu, 0xFFFFFFFFu} // KALIMBA }; static const ArchDefinition g_elf_arch_def = { - eArchTypeELF, - llvm::array_lengthof(g_elf_arch_entries), - g_elf_arch_entries, + eArchTypeELF, llvm::array_lengthof(g_elf_arch_entries), g_elf_arch_entries, "elf", }; -static const ArchDefinitionEntry g_coff_arch_entries[] = -{ - { ArchSpec::eCore_x86_32_i386 , llvm::COFF::IMAGE_FILE_MACHINE_I386 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // Intel 80x86 - { ArchSpec::eCore_ppc_generic , llvm::COFF::IMAGE_FILE_MACHINE_POWERPC , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // PowerPC - { ArchSpec::eCore_ppc_generic , llvm::COFF::IMAGE_FILE_MACHINE_POWERPCFP, LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // PowerPC (with FPU) - { ArchSpec::eCore_arm_generic , llvm::COFF::IMAGE_FILE_MACHINE_ARM , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARM - { ArchSpec::eCore_arm_armv7 , llvm::COFF::IMAGE_FILE_MACHINE_ARMNT , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARMv7 - { ArchSpec::eCore_thumb , llvm::COFF::IMAGE_FILE_MACHINE_THUMB , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu }, // ARMv7 - { ArchSpec::eCore_x86_64_x86_64, llvm::COFF::IMAGE_FILE_MACHINE_AMD64 , LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu } // AMD64 +static const ArchDefinitionEntry g_coff_arch_entries[] = { + {ArchSpec::eCore_x86_32_i386, llvm::COFF::IMAGE_FILE_MACHINE_I386, + LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // Intel 80x86 + {ArchSpec::eCore_ppc_generic, llvm::COFF::IMAGE_FILE_MACHINE_POWERPC, + LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // PowerPC + {ArchSpec::eCore_ppc_generic, llvm::COFF::IMAGE_FILE_MACHINE_POWERPCFP, + LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // PowerPC (with FPU) + {ArchSpec::eCore_arm_generic, llvm::COFF::IMAGE_FILE_MACHINE_ARM, + LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // ARM + {ArchSpec::eCore_arm_armv7, llvm::COFF::IMAGE_FILE_MACHINE_ARMNT, + LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // ARMv7 + {ArchSpec::eCore_thumb, llvm::COFF::IMAGE_FILE_MACHINE_THUMB, + LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu}, // ARMv7 + {ArchSpec::eCore_x86_64_x86_64, llvm::COFF::IMAGE_FILE_MACHINE_AMD64, + LLDB_INVALID_CPUTYPE, 0xFFFFFFFFu, 0xFFFFFFFFu} // AMD64 }; static const ArchDefinition g_coff_arch_def = { - eArchTypeCOFF, - llvm::array_lengthof(g_coff_arch_entries), - g_coff_arch_entries, - "pe-coff", + eArchTypeCOFF, llvm::array_lengthof(g_coff_arch_entries), + g_coff_arch_entries, "pe-coff", }; //===----------------------------------------------------------------------===// // Table of all ArchDefinitions static const ArchDefinition *g_arch_definitions[] = { - &g_macho_arch_def, - &g_elf_arch_def, - &g_coff_arch_def -}; + &g_macho_arch_def, &g_elf_arch_def, &g_coff_arch_def}; -static const size_t k_num_arch_definitions = llvm::array_lengthof(g_arch_definitions); +static const size_t k_num_arch_definitions = + llvm::array_lengthof(g_arch_definitions); //===----------------------------------------------------------------------===// // Static helper functions. // Get the architecture definition for a given object type. -static const ArchDefinition * -FindArchDefinition (ArchitectureType arch_type) -{ - for (unsigned int i = 0; i < k_num_arch_definitions; ++i) - { - const ArchDefinition *def = g_arch_definitions[i]; - if (def->type == arch_type) - return def; - } - return nullptr; +static const ArchDefinition *FindArchDefinition(ArchitectureType arch_type) { + for (unsigned int i = 0; i < k_num_arch_definitions; ++i) { + const ArchDefinition *def = g_arch_definitions[i]; + if (def->type == arch_type) + return def; + } + return nullptr; } // Get an architecture definition by name. -static const CoreDefinition * -FindCoreDefinition (llvm::StringRef name) -{ - for (unsigned int i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) - { - if (name.equals_lower(g_core_definitions[i].name)) - return &g_core_definitions[i]; - } - return nullptr; +static const CoreDefinition *FindCoreDefinition(llvm::StringRef name) { + for (unsigned int i = 0; i < llvm::array_lengthof(g_core_definitions); ++i) { + if (name.equals_lower(g_core_definitions[i].name)) + return &g_core_definitions[i]; + } + return nullptr; } -static inline const CoreDefinition * -FindCoreDefinition (ArchSpec::Core core) -{ - if (core >= 0 && core < llvm::array_lengthof(g_core_definitions)) - return &g_core_definitions[core]; - return nullptr; +static inline const CoreDefinition *FindCoreDefinition(ArchSpec::Core core) { + if (core >= 0 && core < llvm::array_lengthof(g_core_definitions)) + return &g_core_definitions[core]; + return nullptr; } // Get a definition entry by cpu type and subtype. static const ArchDefinitionEntry * -FindArchDefinitionEntry (const ArchDefinition *def, uint32_t cpu, uint32_t sub) -{ - if (def == nullptr) - return nullptr; - - const ArchDefinitionEntry *entries = def->entries; - for (size_t i = 0; i < def->num_entries; ++i) - { - if (entries[i].cpu == (cpu & entries[i].cpu_mask)) - if (entries[i].sub == (sub & entries[i].sub_mask)) - return &entries[i]; - } +FindArchDefinitionEntry(const ArchDefinition *def, uint32_t cpu, uint32_t sub) { + if (def == nullptr) return nullptr; + + const ArchDefinitionEntry *entries = def->entries; + for (size_t i = 0; i < def->num_entries; ++i) { + if (entries[i].cpu == (cpu & entries[i].cpu_mask)) + if (entries[i].sub == (sub & entries[i].sub_mask)) + return &entries[i]; + } + return nullptr; } static const ArchDefinitionEntry * -FindArchDefinitionEntry (const ArchDefinition *def, ArchSpec::Core core) -{ - if (def == nullptr) - return nullptr; - - const ArchDefinitionEntry *entries = def->entries; - for (size_t i = 0; i < def->num_entries; ++i) - { - if (entries[i].core == core) - return &entries[i]; - } +FindArchDefinitionEntry(const ArchDefinition *def, ArchSpec::Core core) { + if (def == nullptr) return nullptr; + + const ArchDefinitionEntry *entries = def->entries; + for (size_t i = 0; i < def->num_entries; ++i) { + if (entries[i].core == core) + return &entries[i]; + } + return nullptr; } //===----------------------------------------------------------------------===// // Constructors and destructors. -ArchSpec::ArchSpec() : - m_triple (), - m_core (kCore_invalid), - m_byte_order (eByteOrderInvalid), - m_flags (0), - m_distribution_id () -{ -} +ArchSpec::ArchSpec() {} -ArchSpec::ArchSpec (const char *triple_cstr, Platform *platform) : - m_triple (), - m_core (kCore_invalid), - m_byte_order (eByteOrderInvalid), - m_flags (0), - m_distribution_id () -{ - if (triple_cstr) - SetTriple(triple_cstr, platform); +ArchSpec::ArchSpec(const char *triple_cstr, Platform *platform) { + if (triple_cstr) + SetTriple(triple_cstr, platform); } - -ArchSpec::ArchSpec (const char *triple_cstr) : - m_triple (), - m_core (kCore_invalid), - m_byte_order (eByteOrderInvalid), - m_flags (0), - m_distribution_id () -{ - if (triple_cstr) - SetTriple(triple_cstr); +ArchSpec::ArchSpec(llvm::StringRef triple_str, Platform *platform) { + SetTriple(triple_str, platform); } -ArchSpec::ArchSpec(const llvm::Triple &triple) : - m_triple (), - m_core (kCore_invalid), - m_byte_order (eByteOrderInvalid), - m_flags (0), - m_distribution_id () -{ - SetTriple(triple); +ArchSpec::ArchSpec(const char *triple_cstr) { + if (triple_cstr) + SetTriple(triple_cstr); } -ArchSpec::ArchSpec (ArchitectureType arch_type, uint32_t cpu, uint32_t subtype) : - m_triple (), - m_core (kCore_invalid), - m_byte_order (eByteOrderInvalid), - m_flags (0), - m_distribution_id () -{ - SetArchitecture (arch_type, cpu, subtype); +ArchSpec::ArchSpec(llvm::StringRef triple_str) { SetTriple(triple_str); } + +ArchSpec::ArchSpec(const llvm::Triple &triple) { SetTriple(triple); } + +ArchSpec::ArchSpec(ArchitectureType arch_type, uint32_t cpu, uint32_t subtype) { + SetArchitecture(arch_type, cpu, subtype); } ArchSpec::~ArchSpec() = default; @@ -471,55 +584,43 @@ ArchSpec::~ArchSpec() = default; //===----------------------------------------------------------------------===// // Assignment and initialization. -const ArchSpec& -ArchSpec::operator= (const ArchSpec& rhs) -{ - if (this != &rhs) - { - m_triple = rhs.m_triple; - m_core = rhs.m_core; - m_byte_order = rhs.m_byte_order; - m_distribution_id = rhs.m_distribution_id; - m_flags = rhs.m_flags; - } - return *this; +const ArchSpec &ArchSpec::operator=(const ArchSpec &rhs) { + if (this != &rhs) { + m_triple = rhs.m_triple; + m_core = rhs.m_core; + m_byte_order = rhs.m_byte_order; + m_distribution_id = rhs.m_distribution_id; + m_flags = rhs.m_flags; + } + return *this; } -void -ArchSpec::Clear() -{ - m_triple = llvm::Triple(); - m_core = kCore_invalid; - m_byte_order = eByteOrderInvalid; - m_distribution_id.Clear (); - m_flags = 0; +void ArchSpec::Clear() { + m_triple = llvm::Triple(); + m_core = kCore_invalid; + m_byte_order = eByteOrderInvalid; + m_distribution_id.Clear(); + m_flags = 0; } //===----------------------------------------------------------------------===// // Predicates. -const char * -ArchSpec::GetArchitectureName () const -{ - const CoreDefinition *core_def = FindCoreDefinition (m_core); - if (core_def) - return core_def->name; - return "unknown"; +const char *ArchSpec::GetArchitectureName() const { + const CoreDefinition *core_def = FindCoreDefinition(m_core); + if (core_def) + return core_def->name; + return "unknown"; } -bool -ArchSpec::IsMIPS() const -{ - const llvm::Triple::ArchType machine = GetMachine(); - if(machine == llvm::Triple::mips || - machine == llvm::Triple::mipsel || - machine == llvm::Triple::mips64 || - machine == llvm::Triple::mips64el) - return true; - return false; +bool ArchSpec::IsMIPS() const { + const llvm::Triple::ArchType machine = GetMachine(); + if (machine == llvm::Triple::mips || machine == llvm::Triple::mipsel || + machine == llvm::Triple::mips64 || machine == llvm::Triple::mips64el) + return true; + return false; } - std::string ArchSpec::GetTargetABI() const { std::string abi; @@ -560,953 +661,894 @@ std::string ArchSpec::GetClangTargetCPU() { std::string cpu; const llvm::Triple::ArchType machine = GetMachine(); - if (machine == llvm::Triple::mips || - machine == llvm::Triple::mipsel || - machine == llvm::Triple::mips64 || - machine == llvm::Triple::mips64el) - { - switch (m_core) - { - case ArchSpec::eCore_mips32: - case ArchSpec::eCore_mips32el: - cpu = "mips32"; break; - case ArchSpec::eCore_mips32r2: - case ArchSpec::eCore_mips32r2el: - cpu = "mips32r2"; break; - case ArchSpec::eCore_mips32r3: - case ArchSpec::eCore_mips32r3el: - cpu = "mips32r3"; break; - case ArchSpec::eCore_mips32r5: - case ArchSpec::eCore_mips32r5el: - cpu = "mips32r5"; break; - case ArchSpec::eCore_mips32r6: - case ArchSpec::eCore_mips32r6el: - cpu = "mips32r6"; break; - case ArchSpec::eCore_mips64: - case ArchSpec::eCore_mips64el: - cpu = "mips64"; break; - case ArchSpec::eCore_mips64r2: - case ArchSpec::eCore_mips64r2el: - cpu = "mips64r2"; break; - case ArchSpec::eCore_mips64r3: - case ArchSpec::eCore_mips64r3el: - cpu = "mips64r3"; break; - case ArchSpec::eCore_mips64r5: - case ArchSpec::eCore_mips64r5el: - cpu = "mips64r5"; break; - case ArchSpec::eCore_mips64r6: - case ArchSpec::eCore_mips64r6el: - cpu = "mips64r6"; break; - default: - break; - } + if (machine == llvm::Triple::mips || machine == llvm::Triple::mipsel || + machine == llvm::Triple::mips64 || machine == llvm::Triple::mips64el) { + switch (m_core) { + case ArchSpec::eCore_mips32: + case ArchSpec::eCore_mips32el: + cpu = "mips32"; + break; + case ArchSpec::eCore_mips32r2: + case ArchSpec::eCore_mips32r2el: + cpu = "mips32r2"; + break; + case ArchSpec::eCore_mips32r3: + case ArchSpec::eCore_mips32r3el: + cpu = "mips32r3"; + break; + case ArchSpec::eCore_mips32r5: + case ArchSpec::eCore_mips32r5el: + cpu = "mips32r5"; + break; + case ArchSpec::eCore_mips32r6: + case ArchSpec::eCore_mips32r6el: + cpu = "mips32r6"; + break; + case ArchSpec::eCore_mips64: + case ArchSpec::eCore_mips64el: + cpu = "mips64"; + break; + case ArchSpec::eCore_mips64r2: + case ArchSpec::eCore_mips64r2el: + cpu = "mips64r2"; + break; + case ArchSpec::eCore_mips64r3: + case ArchSpec::eCore_mips64r3el: + cpu = "mips64r3"; + break; + case ArchSpec::eCore_mips64r5: + case ArchSpec::eCore_mips64r5el: + cpu = "mips64r5"; + break; + case ArchSpec::eCore_mips64r6: + case ArchSpec::eCore_mips64r6el: + cpu = "mips64r6"; + break; + default: + break; } - return cpu; + } + return cpu; } -uint32_t -ArchSpec::GetMachOCPUType () const -{ - const CoreDefinition *core_def = FindCoreDefinition (m_core); - if (core_def) - { - const ArchDefinitionEntry *arch_def = FindArchDefinitionEntry (&g_macho_arch_def, core_def->core); - if (arch_def) - { - return arch_def->cpu; - } +uint32_t ArchSpec::GetMachOCPUType() const { + const CoreDefinition *core_def = FindCoreDefinition(m_core); + if (core_def) { + const ArchDefinitionEntry *arch_def = + FindArchDefinitionEntry(&g_macho_arch_def, core_def->core); + if (arch_def) { + return arch_def->cpu; } - return LLDB_INVALID_CPUTYPE; + } + return LLDB_INVALID_CPUTYPE; } -uint32_t -ArchSpec::GetMachOCPUSubType () const -{ - const CoreDefinition *core_def = FindCoreDefinition (m_core); - if (core_def) - { - const ArchDefinitionEntry *arch_def = FindArchDefinitionEntry (&g_macho_arch_def, core_def->core); - if (arch_def) - { - return arch_def->sub; - } +uint32_t ArchSpec::GetMachOCPUSubType() const { + const CoreDefinition *core_def = FindCoreDefinition(m_core); + if (core_def) { + const ArchDefinitionEntry *arch_def = + FindArchDefinitionEntry(&g_macho_arch_def, core_def->core); + if (arch_def) { + return arch_def->sub; } - return LLDB_INVALID_CPUTYPE; + } + return LLDB_INVALID_CPUTYPE; } -uint32_t -ArchSpec::GetDataByteSize () const -{ - switch (m_core) - { - case eCore_kalimba3: - return 4; - case eCore_kalimba4: - return 1; - case eCore_kalimba5: - return 4; - default: - return 1; - } +uint32_t ArchSpec::GetDataByteSize() const { + switch (m_core) { + case eCore_kalimba3: + return 4; + case eCore_kalimba4: + return 1; + case eCore_kalimba5: + return 4; + default: return 1; + } + return 1; } -uint32_t -ArchSpec::GetCodeByteSize () const -{ - switch (m_core) - { - case eCore_kalimba3: - return 4; - case eCore_kalimba4: - return 1; - case eCore_kalimba5: - return 1; - default: - return 1; - } +uint32_t ArchSpec::GetCodeByteSize() const { + switch (m_core) { + case eCore_kalimba3: + return 4; + case eCore_kalimba4: return 1; + case eCore_kalimba5: + return 1; + default: + return 1; + } + return 1; } -llvm::Triple::ArchType -ArchSpec::GetMachine () const -{ - const CoreDefinition *core_def = FindCoreDefinition (m_core); - if (core_def) - return core_def->machine; +llvm::Triple::ArchType ArchSpec::GetMachine() const { + const CoreDefinition *core_def = FindCoreDefinition(m_core); + if (core_def) + return core_def->machine; - return llvm::Triple::UnknownArch; + return llvm::Triple::UnknownArch; } -const ConstString& -ArchSpec::GetDistributionId () const -{ - return m_distribution_id; +const ConstString &ArchSpec::GetDistributionId() const { + return m_distribution_id; } -void -ArchSpec::SetDistributionId (const char* distribution_id) -{ - m_distribution_id.SetCString (distribution_id); +void ArchSpec::SetDistributionId(const char *distribution_id) { + m_distribution_id.SetCString(distribution_id); } -uint32_t -ArchSpec::GetAddressByteSize() const -{ - const CoreDefinition *core_def = FindCoreDefinition (m_core); - if (core_def) - { - if (core_def->machine == llvm::Triple::mips64 || core_def->machine == llvm::Triple::mips64el) - { - // For N32/O32 applications Address size is 4 bytes. - if (m_flags & (eMIPSABI_N32 | eMIPSABI_O32)) - return 4; - } - return core_def->addr_byte_size; +uint32_t ArchSpec::GetAddressByteSize() const { + const CoreDefinition *core_def = FindCoreDefinition(m_core); + if (core_def) { + if (core_def->machine == llvm::Triple::mips64 || + core_def->machine == llvm::Triple::mips64el) { + // For N32/O32 applications Address size is 4 bytes. + if (m_flags & (eMIPSABI_N32 | eMIPSABI_O32)) + return 4; } - return 0; + return core_def->addr_byte_size; + } + return 0; } -ByteOrder -ArchSpec::GetDefaultEndian () const -{ - const CoreDefinition *core_def = FindCoreDefinition (m_core); - if (core_def) - return core_def->default_byte_order; - return eByteOrderInvalid; +ByteOrder ArchSpec::GetDefaultEndian() const { + const CoreDefinition *core_def = FindCoreDefinition(m_core); + if (core_def) + return core_def->default_byte_order; + return eByteOrderInvalid; } -bool -ArchSpec::CharIsSignedByDefault () const -{ - switch (m_triple.getArch()) { - default: - return true; - - case llvm::Triple::aarch64: - case llvm::Triple::aarch64_be: - case llvm::Triple::arm: - case llvm::Triple::armeb: - case llvm::Triple::thumb: - case llvm::Triple::thumbeb: - return m_triple.isOSDarwin() || m_triple.isOSWindows(); - - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - return m_triple.isOSDarwin(); - - case llvm::Triple::ppc64le: - case llvm::Triple::systemz: - case llvm::Triple::xcore: - return false; - } +bool ArchSpec::CharIsSignedByDefault() const { + switch (m_triple.getArch()) { + default: + return true; + + case llvm::Triple::aarch64: + case llvm::Triple::aarch64_be: + case llvm::Triple::arm: + case llvm::Triple::armeb: + case llvm::Triple::thumb: + case llvm::Triple::thumbeb: + return m_triple.isOSDarwin() || m_triple.isOSWindows(); + + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + return m_triple.isOSDarwin(); + + case llvm::Triple::ppc64le: + case llvm::Triple::systemz: + case llvm::Triple::xcore: + return false; + } } -lldb::ByteOrder -ArchSpec::GetByteOrder () const -{ - if (m_byte_order == eByteOrderInvalid) - return GetDefaultEndian(); - return m_byte_order; +lldb::ByteOrder ArchSpec::GetByteOrder() const { + if (m_byte_order == eByteOrderInvalid) + return GetDefaultEndian(); + return m_byte_order; } //===----------------------------------------------------------------------===// // Mutators. -bool -ArchSpec::SetTriple (const llvm::Triple &triple) -{ - m_triple = triple; - - llvm::StringRef arch_name (m_triple.getArchName()); - const CoreDefinition *core_def = FindCoreDefinition (arch_name); - if (core_def) - { - m_core = core_def->core; - // Set the byte order to the default byte order for an architecture. - // This can be modified if needed for cases when cores handle both - // big and little endian - m_byte_order = core_def->default_byte_order; - } - else - { - Clear(); - } +bool ArchSpec::SetTriple(const llvm::Triple &triple) { + m_triple = triple; + + llvm::StringRef arch_name(m_triple.getArchName()); + const CoreDefinition *core_def = FindCoreDefinition(arch_name); + if (core_def) { + m_core = core_def->core; + // Set the byte order to the default byte order for an architecture. + // This can be modified if needed for cases when cores handle both + // big and little endian + m_byte_order = core_def->default_byte_order; + } else { + Clear(); + } - return IsValid(); + return IsValid(); } -static bool -ParseMachCPUDashSubtypeTriple (const char *triple_cstr, ArchSpec &arch) -{ - // Accept "12-10" or "12.10" as cpu type/subtype - if (isdigit(triple_cstr[0])) - { - char *end = nullptr; - errno = 0; - uint32_t cpu = (uint32_t)::strtoul (triple_cstr, &end, 0); - if (errno == 0 && cpu != 0 && end && ((*end == '-') || (*end == '.'))) - { - errno = 0; - uint32_t sub = (uint32_t)::strtoul (end + 1, &end, 0); - if (errno == 0 && end && ((*end == '-') || (*end == '.') || (*end == '\0'))) - { - if (arch.SetArchitecture (eArchTypeMachO, cpu, sub)) - { - if (*end == '-') - { - llvm::StringRef vendor_os (end + 1); - size_t dash_pos = vendor_os.find('-'); - if (dash_pos != llvm::StringRef::npos) - { - llvm::StringRef vendor_str(vendor_os.substr(0, dash_pos)); - arch.GetTriple().setVendorName(vendor_str); - const size_t vendor_start_pos = dash_pos+1; - dash_pos = vendor_os.find('-', vendor_start_pos); - if (dash_pos == llvm::StringRef::npos) - { - if (vendor_start_pos < vendor_os.size()) - arch.GetTriple().setOSName(vendor_os.substr(vendor_start_pos)); - } - else - { - arch.GetTriple().setOSName(vendor_os.substr(vendor_start_pos, dash_pos - vendor_start_pos)); - } - } - } - return true; - } - } - } - } +bool lldb_private::ParseMachCPUDashSubtypeTriple(llvm::StringRef triple_str, + ArchSpec &arch) { + // Accept "12-10" or "12.10" as cpu type/subtype + if (triple_str.empty()) + return false; + + size_t pos = triple_str.find_first_of("-."); + if (pos == llvm::StringRef::npos) + return false; + + llvm::StringRef cpu_str = triple_str.substr(0, pos); + llvm::StringRef remainder = triple_str.substr(pos + 1); + if (cpu_str.empty() || remainder.empty()) return false; + + llvm::StringRef sub_str; + llvm::StringRef vendor; + llvm::StringRef os; + std::tie(sub_str, remainder) = remainder.split('-'); + std::tie(vendor, os) = remainder.split('-'); + + uint32_t cpu = 0; + uint32_t sub = 0; + if (cpu_str.getAsInteger(10, cpu) || sub_str.getAsInteger(10, sub)) + return false; + + if (!arch.SetArchitecture(eArchTypeMachO, cpu, sub)) + return false; + if (!vendor.empty() && !os.empty()) { + arch.GetTriple().setVendorName(vendor); + arch.GetTriple().setOSName(os); + } + + return true; } -bool -ArchSpec::SetTriple (const char *triple_cstr) -{ - if (triple_cstr && triple_cstr[0]) - { - if (ParseMachCPUDashSubtypeTriple (triple_cstr, *this)) - return true; - - llvm::StringRef triple_stref (triple_cstr); - if (triple_stref.startswith (LLDB_ARCH_DEFAULT)) - { - // Special case for the current host default architectures... - if (triple_stref.equals (LLDB_ARCH_DEFAULT_32BIT)) - *this = HostInfo::GetArchitecture(HostInfo::eArchKind32); - else if (triple_stref.equals (LLDB_ARCH_DEFAULT_64BIT)) - *this = HostInfo::GetArchitecture(HostInfo::eArchKind64); - else if (triple_stref.equals (LLDB_ARCH_DEFAULT)) - *this = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); - } - else - { - std::string normalized_triple_sstr (llvm::Triple::normalize(triple_stref)); - triple_stref = normalized_triple_sstr; - SetTriple (llvm::Triple (triple_stref)); - } - } - else - Clear(); - return IsValid(); +bool ArchSpec::SetTriple(const char *triple_cstr) { + llvm::StringRef str(triple_cstr ? triple_cstr : ""); + return SetTriple(str); } -bool -ArchSpec::SetTriple (const char *triple_cstr, Platform *platform) -{ - if (triple_cstr && triple_cstr[0]) - { - if (ParseMachCPUDashSubtypeTriple (triple_cstr, *this)) - return true; - - llvm::StringRef triple_stref (triple_cstr); - if (triple_stref.startswith (LLDB_ARCH_DEFAULT)) - { - // Special case for the current host default architectures... - if (triple_stref.equals (LLDB_ARCH_DEFAULT_32BIT)) - *this = HostInfo::GetArchitecture(HostInfo::eArchKind32); - else if (triple_stref.equals (LLDB_ARCH_DEFAULT_64BIT)) - *this = HostInfo::GetArchitecture(HostInfo::eArchKind64); - else if (triple_stref.equals (LLDB_ARCH_DEFAULT)) - *this = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); - } - else - { - ArchSpec raw_arch (triple_cstr); - - std::string normalized_triple_sstr (llvm::Triple::normalize(triple_stref)); - triple_stref = normalized_triple_sstr; - llvm::Triple normalized_triple (triple_stref); - - const bool os_specified = normalized_triple.getOSName().size() > 0; - const bool vendor_specified = normalized_triple.getVendorName().size() > 0; - const bool env_specified = normalized_triple.getEnvironmentName().size() > 0; - - // If we got an arch only, then default the vendor, os, environment - // to match the platform if one is supplied - if (!(os_specified || vendor_specified || env_specified)) - { - if (platform) - { - // If we were given a platform, use the platform's system - // architecture. If this is not available (might not be - // connected) use the first supported architecture. - ArchSpec compatible_arch; - if (platform->IsCompatibleArchitecture (raw_arch, false, &compatible_arch)) - { - if (compatible_arch.IsValid()) - { - const llvm::Triple &compatible_triple = compatible_arch.GetTriple(); - if (!vendor_specified) - normalized_triple.setVendor(compatible_triple.getVendor()); - if (!os_specified) - normalized_triple.setOS(compatible_triple.getOS()); - if (!env_specified && compatible_triple.getEnvironmentName().size()) - normalized_triple.setEnvironment(compatible_triple.getEnvironment()); - } - } - else - { - *this = raw_arch; - return IsValid(); - } - } - else - { - // No platform specified, fall back to the host system for - // the default vendor, os, and environment. - llvm::Triple host_triple(llvm::sys::getDefaultTargetTriple()); - if (!vendor_specified) - normalized_triple.setVendor(host_triple.getVendor()); - if (!vendor_specified) - normalized_triple.setOS(host_triple.getOS()); - if (!env_specified && host_triple.getEnvironmentName().size()) - normalized_triple.setEnvironment(host_triple.getEnvironment()); - } - } - SetTriple (normalized_triple); - } - } - else - Clear(); +bool ArchSpec::SetTriple(const char *triple_cstr, Platform *platform) { + llvm::StringRef str(triple_cstr ? triple_cstr : ""); + return SetTriple(str, platform); +} + +bool ArchSpec::SetTriple(llvm::StringRef triple) { + if (triple.empty()) { + Clear(); + return false; + } + + if (ParseMachCPUDashSubtypeTriple(triple, *this)) + return true; + + if (triple.startswith(LLDB_ARCH_DEFAULT)) { + // Special case for the current host default architectures... + if (triple.equals(LLDB_ARCH_DEFAULT_32BIT)) + *this = HostInfo::GetArchitecture(HostInfo::eArchKind32); + else if (triple.equals(LLDB_ARCH_DEFAULT_64BIT)) + *this = HostInfo::GetArchitecture(HostInfo::eArchKind64); + else if (triple.equals(LLDB_ARCH_DEFAULT)) + *this = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); + } else { + SetTriple(llvm::Triple(llvm::Triple::normalize(triple))); + } + return IsValid(); +} + +bool ArchSpec::SetTriple(llvm::StringRef triple, Platform *platform) { + if (triple.empty()) { + Clear(); + return false; + } + if (ParseMachCPUDashSubtypeTriple(triple, *this)) + return true; + + if (triple.startswith(LLDB_ARCH_DEFAULT)) { + // Special case for the current host default architectures... + if (triple.equals(LLDB_ARCH_DEFAULT_32BIT)) + *this = HostInfo::GetArchitecture(HostInfo::eArchKind32); + else if (triple.equals(LLDB_ARCH_DEFAULT_64BIT)) + *this = HostInfo::GetArchitecture(HostInfo::eArchKind64); + else if (triple.equals(LLDB_ARCH_DEFAULT)) + *this = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); + return IsValid(); + } + + ArchSpec raw_arch(triple); + + llvm::Triple normalized_triple(llvm::Triple::normalize(triple)); + + const bool os_specified = !normalized_triple.getOSName().empty(); + const bool vendor_specified = !normalized_triple.getVendorName().empty(); + const bool env_specified = !normalized_triple.getEnvironmentName().empty(); + + if (os_specified || vendor_specified || env_specified) { + SetTriple(normalized_triple); + return IsValid(); + } + + // We got an arch only. If there is no platform, fallback to the host system + // for defaults. + if (!platform) { + llvm::Triple host_triple(llvm::sys::getDefaultTargetTriple()); + if (!vendor_specified) + normalized_triple.setVendor(host_triple.getVendor()); + if (!vendor_specified) + normalized_triple.setOS(host_triple.getOS()); + if (!env_specified && host_triple.getEnvironmentName().size()) + normalized_triple.setEnvironment(host_triple.getEnvironment()); + SetTriple(normalized_triple); + return IsValid(); + } + + // If we were given a platform, use the platform's system architecture. If + // this is not available (might not be connected) use the first supported + // architecture. + ArchSpec compatible_arch; + if (!platform->IsCompatibleArchitecture(raw_arch, false, &compatible_arch)) { + *this = raw_arch; return IsValid(); + } + + if (compatible_arch.IsValid()) { + const llvm::Triple &compatible_triple = compatible_arch.GetTriple(); + if (!vendor_specified) + normalized_triple.setVendor(compatible_triple.getVendor()); + if (!os_specified) + normalized_triple.setOS(compatible_triple.getOS()); + if (!env_specified && compatible_triple.hasEnvironment()) + normalized_triple.setEnvironment(compatible_triple.getEnvironment()); + } + + SetTriple(normalized_triple); + return IsValid(); } -void -ArchSpec::MergeFrom(const ArchSpec &other) -{ - if (TripleVendorIsUnspecifiedUnknown() && !other.TripleVendorIsUnspecifiedUnknown()) - GetTriple().setVendor(other.GetTriple().getVendor()); - if (TripleOSIsUnspecifiedUnknown() && !other.TripleOSIsUnspecifiedUnknown()) - GetTriple().setOS(other.GetTriple().getOS()); - if (GetTriple().getArch() == llvm::Triple::UnknownArch) - GetTriple().setArch(other.GetTriple().getArch()); - if (GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && !TripleVendorWasSpecified()) - { - if (other.TripleVendorWasSpecified()) - GetTriple().setEnvironment(other.GetTriple().getEnvironment()); - } - // If this and other are both arm ArchSpecs and this ArchSpec is a generic "some kind of arm" - // spec but the other ArchSpec is a specific arm core, adopt the specific arm core. - if (GetTriple().getArch() == llvm::Triple::arm - && other.GetTriple().getArch() == llvm::Triple::arm - && IsCompatibleMatch (other) - && GetCore() == ArchSpec::eCore_arm_generic - && other.GetCore() != ArchSpec::eCore_arm_generic) - { - m_core = other.GetCore(); - CoreUpdated (true); - } +void ArchSpec::MergeFrom(const ArchSpec &other) { + if (TripleVendorIsUnspecifiedUnknown() && + !other.TripleVendorIsUnspecifiedUnknown()) + GetTriple().setVendor(other.GetTriple().getVendor()); + if (TripleOSIsUnspecifiedUnknown() && !other.TripleOSIsUnspecifiedUnknown()) + GetTriple().setOS(other.GetTriple().getOS()); + if (GetTriple().getArch() == llvm::Triple::UnknownArch) + GetTriple().setArch(other.GetTriple().getArch()); + if (GetTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && + !TripleVendorWasSpecified()) { + if (other.TripleVendorWasSpecified()) + GetTriple().setEnvironment(other.GetTriple().getEnvironment()); + } + // If this and other are both arm ArchSpecs and this ArchSpec is a generic + // "some kind of arm" + // spec but the other ArchSpec is a specific arm core, adopt the specific arm + // core. + if (GetTriple().getArch() == llvm::Triple::arm && + other.GetTriple().getArch() == llvm::Triple::arm && + IsCompatibleMatch(other) && GetCore() == ArchSpec::eCore_arm_generic && + other.GetCore() != ArchSpec::eCore_arm_generic) { + m_core = other.GetCore(); + CoreUpdated(true); + } } -bool -ArchSpec::SetArchitecture (ArchitectureType arch_type, uint32_t cpu, uint32_t sub, uint32_t os) -{ - m_core = kCore_invalid; - bool update_triple = true; - const ArchDefinition *arch_def = FindArchDefinition(arch_type); - if (arch_def) - { - const ArchDefinitionEntry *arch_def_entry = FindArchDefinitionEntry (arch_def, cpu, sub); - if (arch_def_entry) - { - const CoreDefinition *core_def = FindCoreDefinition (arch_def_entry->core); - if (core_def) - { - m_core = core_def->core; - update_triple = false; - // Always use the architecture name because it might be more descriptive - // than the architecture enum ("armv7" -> llvm::Triple::arm). - m_triple.setArchName(llvm::StringRef(core_def->name)); - if (arch_type == eArchTypeMachO) - { - m_triple.setVendor (llvm::Triple::Apple); - - // Don't set the OS. It could be simulator, macosx, ios, watchos, tvos. We could - // get close with the cpu type - but we can't get it right all of the time. Better - // to leave this unset so other sections of code will set it when they have more - // information. - // NB: don't call m_triple.setOS (llvm::Triple::UnknownOS). That sets the OSName to - // "unknown" and the ArchSpec::TripleVendorWasSpecified() method says that any - // OSName setting means it was specified. - } - else if (arch_type == eArchTypeELF) - { - switch (os) - { - case llvm::ELF::ELFOSABI_AIX: m_triple.setOS (llvm::Triple::OSType::AIX); break; - case llvm::ELF::ELFOSABI_FREEBSD: m_triple.setOS (llvm::Triple::OSType::FreeBSD); break; - case llvm::ELF::ELFOSABI_GNU: m_triple.setOS (llvm::Triple::OSType::Linux); break; - case llvm::ELF::ELFOSABI_NETBSD: m_triple.setOS (llvm::Triple::OSType::NetBSD); break; - case llvm::ELF::ELFOSABI_OPENBSD: m_triple.setOS (llvm::Triple::OSType::OpenBSD); break; - case llvm::ELF::ELFOSABI_SOLARIS: m_triple.setOS (llvm::Triple::OSType::Solaris); break; - } - } - else - { - m_triple.setVendor (llvm::Triple::UnknownVendor); - m_triple.setOS (llvm::Triple::UnknownOS); - } - // Fall back onto setting the machine type if the arch by name failed... - if (m_triple.getArch () == llvm::Triple::UnknownArch) - m_triple.setArch (core_def->machine); - } +bool ArchSpec::SetArchitecture(ArchitectureType arch_type, uint32_t cpu, + uint32_t sub, uint32_t os) { + m_core = kCore_invalid; + bool update_triple = true; + const ArchDefinition *arch_def = FindArchDefinition(arch_type); + if (arch_def) { + const ArchDefinitionEntry *arch_def_entry = + FindArchDefinitionEntry(arch_def, cpu, sub); + if (arch_def_entry) { + const CoreDefinition *core_def = FindCoreDefinition(arch_def_entry->core); + if (core_def) { + m_core = core_def->core; + update_triple = false; + // Always use the architecture name because it might be more descriptive + // than the architecture enum ("armv7" -> llvm::Triple::arm). + m_triple.setArchName(llvm::StringRef(core_def->name)); + if (arch_type == eArchTypeMachO) { + m_triple.setVendor(llvm::Triple::Apple); + + // Don't set the OS. It could be simulator, macosx, ios, watchos, + // tvos. We could + // get close with the cpu type - but we can't get it right all of the + // time. Better + // to leave this unset so other sections of code will set it when they + // have more + // information. + // NB: don't call m_triple.setOS (llvm::Triple::UnknownOS). That sets + // the OSName to + // "unknown" and the ArchSpec::TripleVendorWasSpecified() method says + // that any + // OSName setting means it was specified. + } else if (arch_type == eArchTypeELF) { + switch (os) { + case llvm::ELF::ELFOSABI_AIX: + m_triple.setOS(llvm::Triple::OSType::AIX); + break; + case llvm::ELF::ELFOSABI_FREEBSD: + m_triple.setOS(llvm::Triple::OSType::FreeBSD); + break; + case llvm::ELF::ELFOSABI_GNU: + m_triple.setOS(llvm::Triple::OSType::Linux); + break; + case llvm::ELF::ELFOSABI_NETBSD: + m_triple.setOS(llvm::Triple::OSType::NetBSD); + break; + case llvm::ELF::ELFOSABI_OPENBSD: + m_triple.setOS(llvm::Triple::OSType::OpenBSD); + break; + case llvm::ELF::ELFOSABI_SOLARIS: + m_triple.setOS(llvm::Triple::OSType::Solaris); + break; + } + } else if (arch_type == eArchTypeCOFF && os == llvm::Triple::Win32) { + m_triple.setVendor(llvm::Triple::PC); + m_triple.setOS(llvm::Triple::Win32); + } else { + m_triple.setVendor(llvm::Triple::UnknownVendor); + m_triple.setOS(llvm::Triple::UnknownOS); } + // Fall back onto setting the machine type if the arch by name failed... + if (m_triple.getArch() == llvm::Triple::UnknownArch) + m_triple.setArch(core_def->machine); + } } - CoreUpdated(update_triple); - return IsValid(); + } + CoreUpdated(update_triple); + return IsValid(); } -uint32_t -ArchSpec::GetMinimumOpcodeByteSize() const -{ - const CoreDefinition *core_def = FindCoreDefinition (m_core); - if (core_def) - return core_def->min_opcode_byte_size; - return 0; +uint32_t ArchSpec::GetMinimumOpcodeByteSize() const { + const CoreDefinition *core_def = FindCoreDefinition(m_core); + if (core_def) + return core_def->min_opcode_byte_size; + return 0; } -uint32_t -ArchSpec::GetMaximumOpcodeByteSize() const -{ - const CoreDefinition *core_def = FindCoreDefinition (m_core); - if (core_def) - return core_def->max_opcode_byte_size; - return 0; +uint32_t ArchSpec::GetMaximumOpcodeByteSize() const { + const CoreDefinition *core_def = FindCoreDefinition(m_core); + if (core_def) + return core_def->max_opcode_byte_size; + return 0; } -bool -ArchSpec::IsExactMatch (const ArchSpec& rhs) const -{ - return IsEqualTo (rhs, true); +bool ArchSpec::IsExactMatch(const ArchSpec &rhs) const { + return IsEqualTo(rhs, true); } -bool -ArchSpec::IsCompatibleMatch (const ArchSpec& rhs) const -{ - return IsEqualTo (rhs, false); +bool ArchSpec::IsCompatibleMatch(const ArchSpec &rhs) const { + return IsEqualTo(rhs, false); } -static bool -isCompatibleEnvironment(llvm::Triple::EnvironmentType lhs, llvm::Triple::EnvironmentType rhs) -{ - if (lhs == rhs) - return true; +static bool isCompatibleEnvironment(llvm::Triple::EnvironmentType lhs, + llvm::Triple::EnvironmentType rhs) { + if (lhs == rhs) + return true; + + // If any of the environment is unknown then they are compatible + if (lhs == llvm::Triple::UnknownEnvironment || + rhs == llvm::Triple::UnknownEnvironment) + return true; + + // If one of the environment is Android and the other one is EABI then they + // are considered to + // be compatible. This is required as a workaround for shared libraries + // compiled for Android + // without the NOTE section indicating that they are using the Android ABI. + if ((lhs == llvm::Triple::Android && rhs == llvm::Triple::EABI) || + (rhs == llvm::Triple::Android && lhs == llvm::Triple::EABI) || + (lhs == llvm::Triple::GNUEABI && rhs == llvm::Triple::EABI) || + (rhs == llvm::Triple::GNUEABI && lhs == llvm::Triple::EABI) || + (lhs == llvm::Triple::GNUEABIHF && rhs == llvm::Triple::EABIHF) || + (rhs == llvm::Triple::GNUEABIHF && lhs == llvm::Triple::EABIHF)) + return true; + + return false; +} - // If any of the environment is unknown then they are compatible - if (lhs == llvm::Triple::UnknownEnvironment || rhs == llvm::Triple::UnknownEnvironment) - return true; - - // If one of the environment is Android and the other one is EABI then they are considered to - // be compatible. This is required as a workaround for shared libraries compiled for Android - // without the NOTE section indicating that they are using the Android ABI. - if ((lhs == llvm::Triple::Android && rhs == llvm::Triple::EABI) || - (rhs == llvm::Triple::Android && lhs == llvm::Triple::EABI) || - (lhs == llvm::Triple::GNUEABI && rhs == llvm::Triple::EABI) || - (rhs == llvm::Triple::GNUEABI && lhs == llvm::Triple::EABI) || - (lhs == llvm::Triple::GNUEABIHF && rhs == llvm::Triple::EABIHF) || - (rhs == llvm::Triple::GNUEABIHF && lhs == llvm::Triple::EABIHF)) - return true; +bool ArchSpec::IsEqualTo(const ArchSpec &rhs, bool exact_match) const { + // explicitly ignoring m_distribution_id in this method. + if (GetByteOrder() != rhs.GetByteOrder()) return false; -} -bool -ArchSpec::IsEqualTo (const ArchSpec& rhs, bool exact_match) const -{ - // explicitly ignoring m_distribution_id in this method. + const ArchSpec::Core lhs_core = GetCore(); + const ArchSpec::Core rhs_core = rhs.GetCore(); - if (GetByteOrder() != rhs.GetByteOrder()) + const bool core_match = cores_match(lhs_core, rhs_core, true, exact_match); + + if (core_match) { + const llvm::Triple &lhs_triple = GetTriple(); + const llvm::Triple &rhs_triple = rhs.GetTriple(); + + const llvm::Triple::VendorType lhs_triple_vendor = lhs_triple.getVendor(); + const llvm::Triple::VendorType rhs_triple_vendor = rhs_triple.getVendor(); + if (lhs_triple_vendor != rhs_triple_vendor) { + const bool rhs_vendor_specified = rhs.TripleVendorWasSpecified(); + const bool lhs_vendor_specified = TripleVendorWasSpecified(); + // Both architectures had the vendor specified, so if they aren't + // equal then we return false + if (rhs_vendor_specified && lhs_vendor_specified) return false; - - const ArchSpec::Core lhs_core = GetCore (); - const ArchSpec::Core rhs_core = rhs.GetCore (); - - const bool core_match = cores_match (lhs_core, rhs_core, true, exact_match); - - if (core_match) - { - const llvm::Triple &lhs_triple = GetTriple(); - const llvm::Triple &rhs_triple = rhs.GetTriple(); - - const llvm::Triple::VendorType lhs_triple_vendor = lhs_triple.getVendor(); - const llvm::Triple::VendorType rhs_triple_vendor = rhs_triple.getVendor(); - if (lhs_triple_vendor != rhs_triple_vendor) - { - const bool rhs_vendor_specified = rhs.TripleVendorWasSpecified(); - const bool lhs_vendor_specified = TripleVendorWasSpecified(); - // Both architectures had the vendor specified, so if they aren't - // equal then we return false - if (rhs_vendor_specified && lhs_vendor_specified) - return false; - - // Only fail if both vendor types are not unknown - if (lhs_triple_vendor != llvm::Triple::UnknownVendor && - rhs_triple_vendor != llvm::Triple::UnknownVendor) - return false; - } - - const llvm::Triple::OSType lhs_triple_os = lhs_triple.getOS(); - const llvm::Triple::OSType rhs_triple_os = rhs_triple.getOS(); - if (lhs_triple_os != rhs_triple_os) - { - const bool rhs_os_specified = rhs.TripleOSWasSpecified(); - const bool lhs_os_specified = TripleOSWasSpecified(); - // Both architectures had the OS specified, so if they aren't - // equal then we return false - if (rhs_os_specified && lhs_os_specified) - return false; - - // Only fail if both os types are not unknown - if (lhs_triple_os != llvm::Triple::UnknownOS && - rhs_triple_os != llvm::Triple::UnknownOS) - return false; - } - const llvm::Triple::EnvironmentType lhs_triple_env = lhs_triple.getEnvironment(); - const llvm::Triple::EnvironmentType rhs_triple_env = rhs_triple.getEnvironment(); - - if (!isCompatibleEnvironment(lhs_triple_env, rhs_triple_env)) - return false; - return true; + // Only fail if both vendor types are not unknown + if (lhs_triple_vendor != llvm::Triple::UnknownVendor && + rhs_triple_vendor != llvm::Triple::UnknownVendor) + return false; } - return false; + + const llvm::Triple::OSType lhs_triple_os = lhs_triple.getOS(); + const llvm::Triple::OSType rhs_triple_os = rhs_triple.getOS(); + if (lhs_triple_os != rhs_triple_os) { + const bool rhs_os_specified = rhs.TripleOSWasSpecified(); + const bool lhs_os_specified = TripleOSWasSpecified(); + // Both architectures had the OS specified, so if they aren't + // equal then we return false + if (rhs_os_specified && lhs_os_specified) + return false; + + // Only fail if both os types are not unknown + if (lhs_triple_os != llvm::Triple::UnknownOS && + rhs_triple_os != llvm::Triple::UnknownOS) + return false; + } + + const llvm::Triple::EnvironmentType lhs_triple_env = + lhs_triple.getEnvironment(); + const llvm::Triple::EnvironmentType rhs_triple_env = + rhs_triple.getEnvironment(); + + if (!isCompatibleEnvironment(lhs_triple_env, rhs_triple_env)) + return false; + return true; + } + return false; } //===----------------------------------------------------------------------===// // Helper methods. -void -ArchSpec::CoreUpdated (bool update_triple) -{ - const CoreDefinition *core_def = FindCoreDefinition (m_core); - if (core_def) - { - if (update_triple) - m_triple = llvm::Triple(core_def->name, "unknown", "unknown"); - m_byte_order = core_def->default_byte_order; - } - else - { - if (update_triple) - m_triple = llvm::Triple(); - m_byte_order = eByteOrderInvalid; - } +void ArchSpec::CoreUpdated(bool update_triple) { + const CoreDefinition *core_def = FindCoreDefinition(m_core); + if (core_def) { + if (update_triple) + m_triple = llvm::Triple(core_def->name, "unknown", "unknown"); + m_byte_order = core_def->default_byte_order; + } else { + if (update_triple) + m_triple = llvm::Triple(); + m_byte_order = eByteOrderInvalid; + } } //===----------------------------------------------------------------------===// // Operators. -static bool -cores_match (const ArchSpec::Core core1, const ArchSpec::Core core2, bool try_inverse, bool enforce_exact_match) -{ - if (core1 == core2) +static bool cores_match(const ArchSpec::Core core1, const ArchSpec::Core core2, + bool try_inverse, bool enforce_exact_match) { + if (core1 == core2) + return true; + + switch (core1) { + case ArchSpec::kCore_any: + return true; + + case ArchSpec::eCore_arm_generic: + if (enforce_exact_match) + break; + LLVM_FALLTHROUGH; + case ArchSpec::kCore_arm_any: + if (core2 >= ArchSpec::kCore_arm_first && core2 <= ArchSpec::kCore_arm_last) + return true; + if (core2 >= ArchSpec::kCore_thumb_first && + core2 <= ArchSpec::kCore_thumb_last) + return true; + if (core2 == ArchSpec::kCore_arm_any) + return true; + break; + + case ArchSpec::kCore_x86_32_any: + if ((core2 >= ArchSpec::kCore_x86_32_first && + core2 <= ArchSpec::kCore_x86_32_last) || + (core2 == ArchSpec::kCore_x86_32_any)) + return true; + break; + + case ArchSpec::kCore_x86_64_any: + if ((core2 >= ArchSpec::kCore_x86_64_first && + core2 <= ArchSpec::kCore_x86_64_last) || + (core2 == ArchSpec::kCore_x86_64_any)) + return true; + break; + + case ArchSpec::kCore_ppc_any: + if ((core2 >= ArchSpec::kCore_ppc_first && + core2 <= ArchSpec::kCore_ppc_last) || + (core2 == ArchSpec::kCore_ppc_any)) + return true; + break; + + case ArchSpec::kCore_ppc64_any: + if ((core2 >= ArchSpec::kCore_ppc64_first && + core2 <= ArchSpec::kCore_ppc64_last) || + (core2 == ArchSpec::kCore_ppc64_any)) + return true; + break; + + case ArchSpec::eCore_arm_armv6m: + if (!enforce_exact_match) { + if (core2 == ArchSpec::eCore_arm_generic) + return true; + try_inverse = false; + if (core2 == ArchSpec::eCore_arm_armv7) + return true; + if (core2 == ArchSpec::eCore_arm_armv6m) + return true; + } + break; + + case ArchSpec::kCore_hexagon_any: + if ((core2 >= ArchSpec::kCore_hexagon_first && + core2 <= ArchSpec::kCore_hexagon_last) || + (core2 == ArchSpec::kCore_hexagon_any)) + return true; + break; + + // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization + // Cortex-M0 - ARMv6-M - armv6m + // Cortex-M3 - ARMv7-M - armv7m + // Cortex-M4 - ARMv7E-M - armv7em + case ArchSpec::eCore_arm_armv7em: + if (!enforce_exact_match) { + if (core2 == ArchSpec::eCore_arm_generic) + return true; + if (core2 == ArchSpec::eCore_arm_armv7m) + return true; + if (core2 == ArchSpec::eCore_arm_armv6m) + return true; + if (core2 == ArchSpec::eCore_arm_armv7) + return true; + try_inverse = true; + } + break; + + // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization + // Cortex-M0 - ARMv6-M - armv6m + // Cortex-M3 - ARMv7-M - armv7m + // Cortex-M4 - ARMv7E-M - armv7em + case ArchSpec::eCore_arm_armv7m: + if (!enforce_exact_match) { + if (core2 == ArchSpec::eCore_arm_generic) + return true; + if (core2 == ArchSpec::eCore_arm_armv6m) + return true; + if (core2 == ArchSpec::eCore_arm_armv7) return true; + if (core2 == ArchSpec::eCore_arm_armv7em) + return true; + try_inverse = true; + } + break; - switch (core1) - { - case ArchSpec::kCore_any: + case ArchSpec::eCore_arm_armv7f: + case ArchSpec::eCore_arm_armv7k: + case ArchSpec::eCore_arm_armv7s: + if (!enforce_exact_match) { + if (core2 == ArchSpec::eCore_arm_generic) + return true; + if (core2 == ArchSpec::eCore_arm_armv7) return true; + try_inverse = false; + } + break; - case ArchSpec::eCore_arm_generic: - if (enforce_exact_match) - break; - LLVM_FALLTHROUGH; - case ArchSpec::kCore_arm_any: - if (core2 >= ArchSpec::kCore_arm_first && core2 <= ArchSpec::kCore_arm_last) - return true; - if (core2 >= ArchSpec::kCore_thumb_first && core2 <= ArchSpec::kCore_thumb_last) - return true; - if (core2 == ArchSpec::kCore_arm_any) - return true; - break; - - case ArchSpec::kCore_x86_32_any: - if ((core2 >= ArchSpec::kCore_x86_32_first && core2 <= ArchSpec::kCore_x86_32_last) || (core2 == ArchSpec::kCore_x86_32_any)) - return true; - break; - - case ArchSpec::kCore_x86_64_any: - if ((core2 >= ArchSpec::kCore_x86_64_first && core2 <= ArchSpec::kCore_x86_64_last) || (core2 == ArchSpec::kCore_x86_64_any)) - return true; - break; - - case ArchSpec::kCore_ppc_any: - if ((core2 >= ArchSpec::kCore_ppc_first && core2 <= ArchSpec::kCore_ppc_last) || (core2 == ArchSpec::kCore_ppc_any)) - return true; - break; - - case ArchSpec::kCore_ppc64_any: - if ((core2 >= ArchSpec::kCore_ppc64_first && core2 <= ArchSpec::kCore_ppc64_last) || (core2 == ArchSpec::kCore_ppc64_any)) - return true; - break; - - case ArchSpec::eCore_arm_armv6m: - if (!enforce_exact_match) - { - if (core2 == ArchSpec::eCore_arm_generic) - return true; - try_inverse = false; - if (core2 == ArchSpec::eCore_arm_armv7) - return true; - if (core2 == ArchSpec::eCore_arm_armv6m) - return true; - } - break; - - case ArchSpec::kCore_hexagon_any: - if ((core2 >= ArchSpec::kCore_hexagon_first && core2 <= ArchSpec::kCore_hexagon_last) || (core2 == ArchSpec::kCore_hexagon_any)) - return true; - break; - - // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization - // Cortex-M0 - ARMv6-M - armv6m - // Cortex-M3 - ARMv7-M - armv7m - // Cortex-M4 - ARMv7E-M - armv7em - case ArchSpec::eCore_arm_armv7em: - if (!enforce_exact_match) - { - if (core2 == ArchSpec::eCore_arm_generic) - return true; - if (core2 == ArchSpec::eCore_arm_armv7m) - return true; - if (core2 == ArchSpec::eCore_arm_armv6m) - return true; - if (core2 == ArchSpec::eCore_arm_armv7) - return true; - try_inverse = true; - } - break; - - // v. https://en.wikipedia.org/wiki/ARM_Cortex-M#Silicon_customization - // Cortex-M0 - ARMv6-M - armv6m - // Cortex-M3 - ARMv7-M - armv7m - // Cortex-M4 - ARMv7E-M - armv7em - case ArchSpec::eCore_arm_armv7m: - if (!enforce_exact_match) - { - if (core2 == ArchSpec::eCore_arm_generic) - return true; - if (core2 == ArchSpec::eCore_arm_armv6m) - return true; - if (core2 == ArchSpec::eCore_arm_armv7) - return true; - if (core2 == ArchSpec::eCore_arm_armv7em) - return true; - try_inverse = true; - } - break; - - case ArchSpec::eCore_arm_armv7f: - case ArchSpec::eCore_arm_armv7k: - case ArchSpec::eCore_arm_armv7s: - if (!enforce_exact_match) - { - if (core2 == ArchSpec::eCore_arm_generic) - return true; - if (core2 == ArchSpec::eCore_arm_armv7) - return true; - try_inverse = false; - } - break; - - case ArchSpec::eCore_x86_64_x86_64h: - if (!enforce_exact_match) - { - try_inverse = false; - if (core2 == ArchSpec::eCore_x86_64_x86_64) - return true; - } - break; - - case ArchSpec::eCore_arm_armv8: - if (!enforce_exact_match) - { - if (core2 == ArchSpec::eCore_arm_arm64) - return true; - if (core2 == ArchSpec::eCore_arm_aarch64) - return true; - try_inverse = false; - } - break; - - case ArchSpec::eCore_arm_aarch64: - if (!enforce_exact_match) - { - if (core2 == ArchSpec::eCore_arm_arm64) - return true; - if (core2 == ArchSpec::eCore_arm_armv8) - return true; - try_inverse = false; - } - break; - - case ArchSpec::eCore_arm_arm64: - if (!enforce_exact_match) - { - if (core2 == ArchSpec::eCore_arm_aarch64) - return true; - if (core2 == ArchSpec::eCore_arm_armv8) - return true; - try_inverse = false; - } - break; + case ArchSpec::eCore_x86_64_x86_64h: + if (!enforce_exact_match) { + try_inverse = false; + if (core2 == ArchSpec::eCore_x86_64_x86_64) + return true; + } + break; - case ArchSpec::eCore_mips32: - if (!enforce_exact_match) - { - if (core2 >= ArchSpec::kCore_mips32_first && core2 <= ArchSpec::kCore_mips32_last) - return true; - try_inverse = false; - } - break; + case ArchSpec::eCore_arm_armv8: + if (!enforce_exact_match) { + if (core2 == ArchSpec::eCore_arm_arm64) + return true; + if (core2 == ArchSpec::eCore_arm_aarch64) + return true; + try_inverse = false; + } + break; - case ArchSpec::eCore_mips32el: - if (!enforce_exact_match) - { - if (core2 >= ArchSpec::kCore_mips32el_first && core2 <= ArchSpec::kCore_mips32el_last) - return true; - try_inverse = false; - } - break; + case ArchSpec::eCore_arm_aarch64: + if (!enforce_exact_match) { + if (core2 == ArchSpec::eCore_arm_arm64) + return true; + if (core2 == ArchSpec::eCore_arm_armv8) + return true; + try_inverse = false; + } + break; - case ArchSpec::eCore_mips64: - if (!enforce_exact_match) - { - if (core2 >= ArchSpec::kCore_mips32_first && core2 <= ArchSpec::kCore_mips32_last) - return true; - if (core2 >= ArchSpec::kCore_mips64_first && core2 <= ArchSpec::kCore_mips64_last) - return true; - try_inverse = false; - } - break; + case ArchSpec::eCore_arm_arm64: + if (!enforce_exact_match) { + if (core2 == ArchSpec::eCore_arm_aarch64) + return true; + if (core2 == ArchSpec::eCore_arm_armv8) + return true; + try_inverse = false; + } + break; - case ArchSpec::eCore_mips64el: - if (!enforce_exact_match) - { - if (core2 >= ArchSpec::kCore_mips32el_first && core2 <= ArchSpec::kCore_mips32el_last) - return true; - if (core2 >= ArchSpec::kCore_mips64el_first && core2 <= ArchSpec::kCore_mips64el_last) - return true; - try_inverse = false; - } - break; + case ArchSpec::eCore_mips32: + if (!enforce_exact_match) { + if (core2 >= ArchSpec::kCore_mips32_first && + core2 <= ArchSpec::kCore_mips32_last) + return true; + try_inverse = false; + } + break; - case ArchSpec::eCore_mips64r2: - case ArchSpec::eCore_mips64r3: - case ArchSpec::eCore_mips64r5: - if (!enforce_exact_match) - { - if (core2 >= ArchSpec::kCore_mips32_first && core2 <= (core1 - 10)) - return true; - if (core2 >= ArchSpec::kCore_mips64_first && core2 <= (core1 - 1)) - return true; - try_inverse = false; - } - break; + case ArchSpec::eCore_mips32el: + if (!enforce_exact_match) { + if (core2 >= ArchSpec::kCore_mips32el_first && + core2 <= ArchSpec::kCore_mips32el_last) + return true; + try_inverse = false; + } + break; - case ArchSpec::eCore_mips64r2el: - case ArchSpec::eCore_mips64r3el: - case ArchSpec::eCore_mips64r5el: - if (!enforce_exact_match) - { - if (core2 >= ArchSpec::kCore_mips32el_first && core2 <= (core1 - 10)) - return true; - if (core2 >= ArchSpec::kCore_mips64el_first && core2 <= (core1 - 1)) - return true; - try_inverse = false; - } - break; + case ArchSpec::eCore_mips64: + if (!enforce_exact_match) { + if (core2 >= ArchSpec::kCore_mips32_first && + core2 <= ArchSpec::kCore_mips32_last) + return true; + if (core2 >= ArchSpec::kCore_mips64_first && + core2 <= ArchSpec::kCore_mips64_last) + return true; + try_inverse = false; + } + break; - case ArchSpec::eCore_mips32r2: - case ArchSpec::eCore_mips32r3: - case ArchSpec::eCore_mips32r5: - if (!enforce_exact_match) - { - if (core2 >= ArchSpec::kCore_mips32_first && core2 <= core1) - return true; - } - break; + case ArchSpec::eCore_mips64el: + if (!enforce_exact_match) { + if (core2 >= ArchSpec::kCore_mips32el_first && + core2 <= ArchSpec::kCore_mips32el_last) + return true; + if (core2 >= ArchSpec::kCore_mips64el_first && + core2 <= ArchSpec::kCore_mips64el_last) + return true; + try_inverse = false; + } + break; - case ArchSpec::eCore_mips32r2el: - case ArchSpec::eCore_mips32r3el: - case ArchSpec::eCore_mips32r5el: - if (!enforce_exact_match) - { - if (core2 >= ArchSpec::kCore_mips32el_first && core2 <= core1) - return true; - } - break; + case ArchSpec::eCore_mips64r2: + case ArchSpec::eCore_mips64r3: + case ArchSpec::eCore_mips64r5: + if (!enforce_exact_match) { + if (core2 >= ArchSpec::kCore_mips32_first && core2 <= (core1 - 10)) + return true; + if (core2 >= ArchSpec::kCore_mips64_first && core2 <= (core1 - 1)) + return true; + try_inverse = false; + } + break; - case ArchSpec::eCore_mips32r6: - if (!enforce_exact_match) - { - if (core2 == ArchSpec::eCore_mips32 || core2 == ArchSpec::eCore_mips32r6) - return true; - } - break; + case ArchSpec::eCore_mips64r2el: + case ArchSpec::eCore_mips64r3el: + case ArchSpec::eCore_mips64r5el: + if (!enforce_exact_match) { + if (core2 >= ArchSpec::kCore_mips32el_first && core2 <= (core1 - 10)) + return true; + if (core2 >= ArchSpec::kCore_mips64el_first && core2 <= (core1 - 1)) + return true; + try_inverse = false; + } + break; - case ArchSpec::eCore_mips32r6el: - if (!enforce_exact_match) - { - if (core2 == ArchSpec::eCore_mips32el || core2 == ArchSpec::eCore_mips32r6el) - return true; - } - break; + case ArchSpec::eCore_mips32r2: + case ArchSpec::eCore_mips32r3: + case ArchSpec::eCore_mips32r5: + if (!enforce_exact_match) { + if (core2 >= ArchSpec::kCore_mips32_first && core2 <= core1) + return true; + } + break; - case ArchSpec::eCore_mips64r6: - if (!enforce_exact_match) - { - if (core2 == ArchSpec::eCore_mips32 || core2 == ArchSpec::eCore_mips32r6) - return true; - if (core2 == ArchSpec::eCore_mips64 || core2 == ArchSpec::eCore_mips64r6) - return true; - } - break; + case ArchSpec::eCore_mips32r2el: + case ArchSpec::eCore_mips32r3el: + case ArchSpec::eCore_mips32r5el: + if (!enforce_exact_match) { + if (core2 >= ArchSpec::kCore_mips32el_first && core2 <= core1) + return true; + } + break; - case ArchSpec::eCore_mips64r6el: - if (!enforce_exact_match) - { - if (core2 == ArchSpec::eCore_mips32el || core2 == ArchSpec::eCore_mips32r6el) - return true; - if (core2 == ArchSpec::eCore_mips64el || core2 == ArchSpec::eCore_mips64r6el) - return true; - } - break; + case ArchSpec::eCore_mips32r6: + if (!enforce_exact_match) { + if (core2 == ArchSpec::eCore_mips32 || core2 == ArchSpec::eCore_mips32r6) + return true; + } + break; - default: - break; + case ArchSpec::eCore_mips32r6el: + if (!enforce_exact_match) { + if (core2 == ArchSpec::eCore_mips32el || + core2 == ArchSpec::eCore_mips32r6el) + return true; } - if (try_inverse) - return cores_match (core2, core1, false, enforce_exact_match); - return false; + break; + + case ArchSpec::eCore_mips64r6: + if (!enforce_exact_match) { + if (core2 == ArchSpec::eCore_mips32 || core2 == ArchSpec::eCore_mips32r6) + return true; + if (core2 == ArchSpec::eCore_mips64 || core2 == ArchSpec::eCore_mips64r6) + return true; + } + break; + + case ArchSpec::eCore_mips64r6el: + if (!enforce_exact_match) { + if (core2 == ArchSpec::eCore_mips32el || + core2 == ArchSpec::eCore_mips32r6el) + return true; + if (core2 == ArchSpec::eCore_mips64el || + core2 == ArchSpec::eCore_mips64r6el) + return true; + } + break; + + default: + break; + } + if (try_inverse) + return cores_match(core2, core1, false, enforce_exact_match); + return false; } -bool -lldb_private::operator<(const ArchSpec& lhs, const ArchSpec& rhs) -{ - const ArchSpec::Core lhs_core = lhs.GetCore (); - const ArchSpec::Core rhs_core = rhs.GetCore (); - return lhs_core < rhs_core; +bool lldb_private::operator<(const ArchSpec &lhs, const ArchSpec &rhs) { + const ArchSpec::Core lhs_core = lhs.GetCore(); + const ArchSpec::Core rhs_core = rhs.GetCore(); + return lhs_core < rhs_core; } -static void -StopInfoOverrideCallbackTypeARM(lldb_private::Thread &thread) -{ - // We need to check if we are stopped in Thumb mode in a IT instruction - // and detect if the condition doesn't pass. If this is the case it means - // we won't actually execute this instruction. If this happens we need to - // clear the stop reason to no thread plans think we are stopped for a - // reason and the plans should keep going. - // - // We do this because when single stepping many ARM processes, debuggers - // often use the BVR/BCR registers that says "stop when the PC is not - // equal to its current value". This method of stepping means we can end - // up stopping on instructions inside an if/then block that wouldn't get - // executed. By fixing this we can stop the debugger from seeming like - // you stepped through both the "if" _and_ the "else" clause when source - // level stepping because the debugger stops regardless due to the BVR/BCR - // triggering a stop. - // - // It also means we can set breakpoints on instructions inside an an - // if/then block and correctly skip them if we use the BKPT instruction. - // The ARM and Thumb BKPT instructions are unconditional even when executed - // in a Thumb IT block. - // - // If your debugger inserts software traps in ARM/Thumb code, it will - // need to use 16 and 32 bit instruction for 16 and 32 bit thumb - // instructions respectively. If your debugger inserts a 16 bit thumb - // trap on top of a 32 bit thumb instruction for an opcode that is inside - // an if/then, it will change the it/then to conditionally execute your - // 16 bit trap and then cause your program to crash if it executes the - // trailing 16 bits (the second half of the 32 bit thumb instruction you - // partially overwrote). - - RegisterContextSP reg_ctx_sp (thread.GetRegisterContext()); - if (reg_ctx_sp) - { - const uint32_t cpsr = reg_ctx_sp->GetFlags(0); - if (cpsr != 0) - { - // Read the J and T bits to get the ISETSTATE - const uint32_t J = Bit32(cpsr, 24); - const uint32_t T = Bit32(cpsr, 5); - const uint32_t ISETSTATE = J << 1 | T; - if (ISETSTATE == 0) - { - // NOTE: I am pretty sure we want to enable the code below - // that detects when we stop on an instruction in ARM mode - // that is conditional and the condition doesn't pass. This - // can happen if you set a breakpoint on an instruction that - // is conditional. We currently will _always_ stop on the - // instruction which is bad. You can also run into this while - // single stepping and you could appear to run code in the "if" - // and in the "else" clause because it would stop at all of the - // conditional instructions in both. - // In such cases, we really don't want to stop at this location. - // I will check with the lldb-dev list first before I enable this. +static void StopInfoOverrideCallbackTypeARM(lldb_private::Thread &thread) { + // We need to check if we are stopped in Thumb mode in a IT instruction + // and detect if the condition doesn't pass. If this is the case it means + // we won't actually execute this instruction. If this happens we need to + // clear the stop reason to no thread plans think we are stopped for a + // reason and the plans should keep going. + // + // We do this because when single stepping many ARM processes, debuggers + // often use the BVR/BCR registers that says "stop when the PC is not + // equal to its current value". This method of stepping means we can end + // up stopping on instructions inside an if/then block that wouldn't get + // executed. By fixing this we can stop the debugger from seeming like + // you stepped through both the "if" _and_ the "else" clause when source + // level stepping because the debugger stops regardless due to the BVR/BCR + // triggering a stop. + // + // It also means we can set breakpoints on instructions inside an an + // if/then block and correctly skip them if we use the BKPT instruction. + // The ARM and Thumb BKPT instructions are unconditional even when executed + // in a Thumb IT block. + // + // If your debugger inserts software traps in ARM/Thumb code, it will + // need to use 16 and 32 bit instruction for 16 and 32 bit thumb + // instructions respectively. If your debugger inserts a 16 bit thumb + // trap on top of a 32 bit thumb instruction for an opcode that is inside + // an if/then, it will change the it/then to conditionally execute your + // 16 bit trap and then cause your program to crash if it executes the + // trailing 16 bits (the second half of the 32 bit thumb instruction you + // partially overwrote). + + RegisterContextSP reg_ctx_sp(thread.GetRegisterContext()); + if (reg_ctx_sp) { + const uint32_t cpsr = reg_ctx_sp->GetFlags(0); + if (cpsr != 0) { + // Read the J and T bits to get the ISETSTATE + const uint32_t J = Bit32(cpsr, 24); + const uint32_t T = Bit32(cpsr, 5); + const uint32_t ISETSTATE = J << 1 | T; + if (ISETSTATE == 0) { +// NOTE: I am pretty sure we want to enable the code below +// that detects when we stop on an instruction in ARM mode +// that is conditional and the condition doesn't pass. This +// can happen if you set a breakpoint on an instruction that +// is conditional. We currently will _always_ stop on the +// instruction which is bad. You can also run into this while +// single stepping and you could appear to run code in the "if" +// and in the "else" clause because it would stop at all of the +// conditional instructions in both. +// In such cases, we really don't want to stop at this location. +// I will check with the lldb-dev list first before I enable this. #if 0 // ARM mode: check for condition on intsruction const addr_t pc = reg_ctx_sp->GetPC(); @@ -1527,120 +1569,101 @@ StopInfoOverrideCallbackTypeARM(lldb_private::Thread &thread) } } #endif - } - else if (ISETSTATE == 1) - { - // Thumb mode - const uint32_t ITSTATE = Bits32 (cpsr, 15, 10) << 2 | Bits32 (cpsr, 26, 25); - if (ITSTATE != 0) - { - const uint32_t condition = Bits32(ITSTATE, 7, 4); - if (!ARMConditionPassed(condition, cpsr)) - { - // We ARE stopped in a Thumb IT instruction on an instruction whose - // condition doesn't pass so this instruction won't get executed. - // Regardless of why it stopped, we need to clear the stop info - thread.SetStopInfo (StopInfoSP()); - } - } - } + } else if (ISETSTATE == 1) { + // Thumb mode + const uint32_t ITSTATE = + Bits32(cpsr, 15, 10) << 2 | Bits32(cpsr, 26, 25); + if (ITSTATE != 0) { + const uint32_t condition = Bits32(ITSTATE, 7, 4); + if (!ARMConditionPassed(condition, cpsr)) { + // We ARE stopped in a Thumb IT instruction on an instruction whose + // condition doesn't pass so this instruction won't get executed. + // Regardless of why it stopped, we need to clear the stop info + thread.SetStopInfo(StopInfoSP()); + } } + } } + } } ArchSpec::StopInfoOverrideCallbackType -ArchSpec::GetStopInfoOverrideCallback () const -{ - const llvm::Triple::ArchType machine = GetMachine(); - if (machine == llvm::Triple::arm) - return StopInfoOverrideCallbackTypeARM; - return nullptr; +ArchSpec::GetStopInfoOverrideCallback() const { + const llvm::Triple::ArchType machine = GetMachine(); + if (machine == llvm::Triple::arm) + return StopInfoOverrideCallbackTypeARM; + return nullptr; } -bool -ArchSpec::IsFullySpecifiedTriple () const -{ - const auto& user_specified_triple = GetTriple(); - - bool user_triple_fully_specified = false; - - if ((user_specified_triple.getOS() != llvm::Triple::UnknownOS) || TripleOSWasSpecified()) - { - if ((user_specified_triple.getVendor() != llvm::Triple::UnknownVendor) || TripleVendorWasSpecified()) - { - const unsigned unspecified = 0; - if (user_specified_triple.getOSMajorVersion() != unspecified) - { - user_triple_fully_specified = true; - } - } +bool ArchSpec::IsFullySpecifiedTriple() const { + const auto &user_specified_triple = GetTriple(); + + bool user_triple_fully_specified = false; + + if ((user_specified_triple.getOS() != llvm::Triple::UnknownOS) || + TripleOSWasSpecified()) { + if ((user_specified_triple.getVendor() != llvm::Triple::UnknownVendor) || + TripleVendorWasSpecified()) { + const unsigned unspecified = 0; + if (user_specified_triple.getOSMajorVersion() != unspecified) { + user_triple_fully_specified = true; + } } - - return user_triple_fully_specified; + } + + return user_triple_fully_specified; } -void -ArchSpec::PiecewiseTripleCompare (const ArchSpec &other, - bool &arch_different, - bool &vendor_different, - bool &os_different, - bool &os_version_different, - bool &env_different) -{ - const llvm::Triple &me(GetTriple()); - const llvm::Triple &them(other.GetTriple()); - - arch_different = (me.getArch() != them.getArch()); - - vendor_different = (me.getVendor() != them.getVendor()); - - os_different = (me.getOS() != them.getOS()); - - os_version_different = (me.getOSMajorVersion() != them.getOSMajorVersion()); - - env_different = (me.getEnvironment() != them.getEnvironment()); +void ArchSpec::PiecewiseTripleCompare( + const ArchSpec &other, bool &arch_different, bool &vendor_different, + bool &os_different, bool &os_version_different, bool &env_different) { + const llvm::Triple &me(GetTriple()); + const llvm::Triple &them(other.GetTriple()); + + arch_different = (me.getArch() != them.getArch()); + + vendor_different = (me.getVendor() != them.getVendor()); + + os_different = (me.getOS() != them.getOS()); + + os_version_different = (me.getOSMajorVersion() != them.getOSMajorVersion()); + + env_different = (me.getEnvironment() != them.getEnvironment()); } -bool -ArchSpec::IsAlwaysThumbInstructions () const -{ - std::string Error; - if (GetTriple().getArch() == llvm::Triple::arm || GetTriple().getArch() == llvm::Triple::thumb) - { - // v. https://en.wikipedia.org/wiki/ARM_Cortex-M - // - // Cortex-M0 through Cortex-M7 are ARM processor cores which can only - // execute thumb instructions. We map the cores to arch names like this: - // - // Cortex-M0, Cortex-M0+, Cortex-M1: armv6m - // Cortex-M3: armv7m - // Cortex-M4, Cortex-M7: armv7em - - if (GetCore() == ArchSpec::Core::eCore_arm_armv7m - || GetCore() == ArchSpec::Core::eCore_arm_armv7em - || GetCore() == ArchSpec::Core::eCore_arm_armv6m) - { - return true; - } +bool ArchSpec::IsAlwaysThumbInstructions() const { + std::string Error; + if (GetTriple().getArch() == llvm::Triple::arm || + GetTriple().getArch() == llvm::Triple::thumb) { + // v. https://en.wikipedia.org/wiki/ARM_Cortex-M + // + // Cortex-M0 through Cortex-M7 are ARM processor cores which can only + // execute thumb instructions. We map the cores to arch names like this: + // + // Cortex-M0, Cortex-M0+, Cortex-M1: armv6m + // Cortex-M3: armv7m + // Cortex-M4, Cortex-M7: armv7em + + if (GetCore() == ArchSpec::Core::eCore_arm_armv7m || + GetCore() == ArchSpec::Core::eCore_arm_armv7em || + GetCore() == ArchSpec::Core::eCore_arm_armv6m) { + return true; } - return false; + } + return false; } -void -ArchSpec::DumpTriple(Stream &s) const -{ - const llvm::Triple &triple = GetTriple(); - llvm::StringRef arch_str = triple.getArchName(); - llvm::StringRef vendor_str = triple.getVendorName(); - llvm::StringRef os_str = triple.getOSName(); - llvm::StringRef environ_str = triple.getEnvironmentName(); - - s.Printf("%s-%s-%s", - arch_str.empty() ? "*" : arch_str.str().c_str(), - vendor_str.empty() ? "*" : vendor_str.str().c_str(), - os_str.empty() ? "*" : os_str.str().c_str() - ); - - if (!environ_str.empty()) - s.Printf("-%s", environ_str.str().c_str()); +void ArchSpec::DumpTriple(Stream &s) const { + const llvm::Triple &triple = GetTriple(); + llvm::StringRef arch_str = triple.getArchName(); + llvm::StringRef vendor_str = triple.getVendorName(); + llvm::StringRef os_str = triple.getOSName(); + llvm::StringRef environ_str = triple.getEnvironmentName(); + + s.Printf("%s-%s-%s", arch_str.empty() ? "*" : arch_str.str().c_str(), + vendor_str.empty() ? "*" : vendor_str.str().c_str(), + os_str.empty() ? "*" : os_str.str().c_str()); + + if (!environ_str.empty()) + s.Printf("-%s", environ_str.str().c_str()); } diff --git a/source/Core/Baton.cpp b/source/Core/Baton.cpp index 8bed01be8839..998a5dffca9c 100644 --- a/source/Core/Baton.cpp +++ b/source/Core/Baton.cpp @@ -18,7 +18,5 @@ using namespace lldb; using namespace lldb_private; -void -Baton::GetDescription (Stream *s, lldb::DescriptionLevel level) const -{ -} +void UntypedBaton::GetDescription(Stream *s, + lldb::DescriptionLevel level) const {} diff --git a/source/Core/Broadcaster.cpp b/source/Core/Broadcaster.cpp index 30bc78b48220..d2cca7a2a654 100644 --- a/source/Core/Broadcaster.cpp +++ b/source/Core/Broadcaster.cpp @@ -13,571 +13,463 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Core/Log.h" #include "lldb/Core/Event.h" #include "lldb/Core/Listener.h" +#include "lldb/Core/Log.h" #include "lldb/Core/StreamString.h" using namespace lldb; using namespace lldb_private; -Broadcaster::Broadcaster(BroadcasterManagerSP manager_sp, const char *name) : - m_broadcaster_sp(new BroadcasterImpl(*this)), - m_manager_sp(manager_sp), - m_broadcaster_name(name) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf ("%p Broadcaster::Broadcaster(\"%s\")", - static_cast<void*>(this), GetBroadcasterName().AsCString()); +Broadcaster::Broadcaster(BroadcasterManagerSP manager_sp, const char *name) + : m_broadcaster_sp(new BroadcasterImpl(*this)), m_manager_sp(manager_sp), + m_broadcaster_name(name) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p Broadcaster::Broadcaster(\"%s\")", + static_cast<void *>(this), GetBroadcasterName().AsCString()); } Broadcaster::BroadcasterImpl::BroadcasterImpl(Broadcaster &broadcaster) - : m_broadcaster(broadcaster), m_listeners(), m_listeners_mutex(), m_hijacking_listeners(), m_hijacking_masks() -{ -} + : m_broadcaster(broadcaster), m_listeners(), m_listeners_mutex(), + m_hijacking_listeners(), m_hijacking_masks() {} -Broadcaster::~Broadcaster() -{ - Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); - if (log) - log->Printf ("%p Broadcaster::~Broadcaster(\"%s\")", - static_cast<void*>(this), m_broadcaster_name.AsCString()); +Broadcaster::~Broadcaster() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + if (log) + log->Printf("%p Broadcaster::~Broadcaster(\"%s\")", + static_cast<void *>(this), m_broadcaster_name.AsCString()); - Clear(); + Clear(); } -void -Broadcaster::CheckInWithManager () -{ - if (m_manager_sp) - { - m_manager_sp->SignUpListenersForBroadcaster(*this); - } +void Broadcaster::CheckInWithManager() { + if (m_manager_sp) { + m_manager_sp->SignUpListenersForBroadcaster(*this); + } } -void -Broadcaster::BroadcasterImpl::ListenerIterator (std::function <bool (const lldb::ListenerSP &listener_sp, uint32_t &event_mask)> const &callback) -{ - // Private iterator that should be used by everyone except BroadcasterImpl::RemoveListener(). - // We have weak pointers to our listeners which means that at any point the listener can - // expire which means we will need to take it out of our list. To take care of this, we - // iterate and check that the weak pointer can be made into a valid shared pointer before - // we call the callback. If the weak pointer has expired, we remove it from our list. - collection::iterator pos = m_listeners.begin(); - while (pos != m_listeners.end()) - { - lldb::ListenerSP curr_listener_sp(pos->first.lock()); - if (curr_listener_sp) - { - if (callback(curr_listener_sp, pos->second)) - ++pos; // Keep iterating - else - return; // Done iterating - } - else - { - // The listener has been expired. Remove this entry. - pos = m_listeners.erase(pos); - } - } +llvm::SmallVector<std::pair<ListenerSP, uint32_t &>, 4> +Broadcaster::BroadcasterImpl::GetListeners() { + llvm::SmallVector<std::pair<ListenerSP, uint32_t &>, 4> listeners; + listeners.reserve(m_listeners.size()); + + for (auto it = m_listeners.begin(); it != m_listeners.end();) { + lldb::ListenerSP curr_listener_sp(it->first.lock()); + if (curr_listener_sp && it->second) { + listeners.emplace_back(std::move(curr_listener_sp), it->second); + ++it; + } else + it = m_listeners.erase(it); + } + + return listeners; } -void -Broadcaster::BroadcasterImpl::Clear() -{ - std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); - - // Make sure the listener forgets about this broadcaster. We do - // this in the broadcaster in case the broadcaster object initiates - // the removal. - - ListenerIterator([this](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool { - curr_listener_sp->BroadcasterWillDestruct (&m_broadcaster); - return true; // Keep iterating - }); - - m_listeners.clear(); +void Broadcaster::BroadcasterImpl::Clear() { + std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); + + // Make sure the listener forgets about this broadcaster. We do + // this in the broadcaster in case the broadcaster object initiates + // the removal. + for (auto &pair : GetListeners()) + pair.first->BroadcasterWillDestruct(&m_broadcaster); + + m_listeners.clear(); } -Broadcaster * -Broadcaster::BroadcasterImpl::GetBroadcaster() -{ - return &m_broadcaster; +Broadcaster *Broadcaster::BroadcasterImpl::GetBroadcaster() { + return &m_broadcaster; } -bool -Broadcaster::BroadcasterImpl::GetEventNames (Stream &s, uint32_t event_mask, bool prefix_with_broadcaster_name) const -{ - uint32_t num_names_added = 0; - if (event_mask && !m_event_names.empty()) - { - event_names_map::const_iterator end = m_event_names.end(); - for (uint32_t bit=1u, mask=event_mask; mask != 0 && bit != 0; bit <<= 1, mask >>= 1) - { - if (mask & 1) - { - event_names_map::const_iterator pos = m_event_names.find(bit); - if (pos != end) - { - if (num_names_added > 0) - s.PutCString(", "); - - if (prefix_with_broadcaster_name) - { - s.PutCString (GetBroadcasterName()); - s.PutChar('.'); - } - s.PutCString(pos->second.c_str()); - ++num_names_added; - } - } +bool Broadcaster::BroadcasterImpl::GetEventNames( + Stream &s, uint32_t event_mask, bool prefix_with_broadcaster_name) const { + uint32_t num_names_added = 0; + if (event_mask && !m_event_names.empty()) { + event_names_map::const_iterator end = m_event_names.end(); + for (uint32_t bit = 1u, mask = event_mask; mask != 0 && bit != 0; + bit <<= 1, mask >>= 1) { + if (mask & 1) { + event_names_map::const_iterator pos = m_event_names.find(bit); + if (pos != end) { + if (num_names_added > 0) + s.PutCString(", "); + + if (prefix_with_broadcaster_name) { + s.PutCString(GetBroadcasterName()); + s.PutChar('.'); + } + s.PutCString(pos->second); + ++num_names_added; } + } } - return num_names_added > 0; + } + return num_names_added > 0; } -void -Broadcaster::AddInitialEventsToListener (const lldb::ListenerSP &listener_sp, uint32_t requested_events) -{ -} +void Broadcaster::AddInitialEventsToListener( + const lldb::ListenerSP &listener_sp, uint32_t requested_events) {} uint32_t -Broadcaster::BroadcasterImpl::AddListener (const lldb::ListenerSP &listener_sp, uint32_t event_mask) -{ - if (!listener_sp) - return 0; +Broadcaster::BroadcasterImpl::AddListener(const lldb::ListenerSP &listener_sp, + uint32_t event_mask) { + if (!listener_sp) + return 0; - std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); + std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); - // See if we already have this listener, and if so, update its mask + // See if we already have this listener, and if so, update its mask - bool handled = false; + bool handled = false; - ListenerIterator([this, &listener_sp, &handled, event_mask](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool { - if (curr_listener_sp == listener_sp) - { - handled = true; - curr_event_mask |= event_mask; - m_broadcaster.AddInitialEventsToListener (listener_sp, event_mask); - return false; // Stop iterating - } - return true; // Keep iterating - }); + for (auto &pair : GetListeners()) { + if (pair.first == listener_sp) { + handled = true; + pair.second |= event_mask; + m_broadcaster.AddInitialEventsToListener(listener_sp, event_mask); + break; + } + } - if (!handled) - { - // Grant a new listener the available event bits - m_listeners.push_back(std::make_pair(lldb::ListenerWP(listener_sp), event_mask)); + if (!handled) { + // Grant a new listener the available event bits + m_listeners.push_back( + std::make_pair(lldb::ListenerWP(listener_sp), event_mask)); - // Individual broadcasters decide whether they have outstanding data when a - // listener attaches, and insert it into the listener with this method. - m_broadcaster.AddInitialEventsToListener (listener_sp, event_mask); - } + // Individual broadcasters decide whether they have outstanding data when a + // listener attaches, and insert it into the listener with this method. + m_broadcaster.AddInitialEventsToListener(listener_sp, event_mask); + } - // Return the event bits that were granted to the listener - return event_mask; + // Return the event bits that were granted to the listener + return event_mask; } -bool -Broadcaster::BroadcasterImpl::EventTypeHasListeners (uint32_t event_type) -{ - std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); - - if (!m_hijacking_listeners.empty() && event_type & m_hijacking_masks.back()) - return true; - - if (m_listeners.empty()) - return false; +bool Broadcaster::BroadcasterImpl::EventTypeHasListeners(uint32_t event_type) { + std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); - bool result = false; - ListenerIterator([this, event_type, &result](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool { + if (!m_hijacking_listeners.empty() && event_type & m_hijacking_masks.back()) + return true; - if (curr_event_mask & event_type) - { - result = true; - return false; // Stop iterating - } - else - { - return true; // Keep iterating - } - }); - return result; + for (auto &pair : GetListeners()) { + if (pair.second & event_type) + return true; + } + return false; } -bool -Broadcaster::BroadcasterImpl::RemoveListener (lldb_private::Listener *listener, uint32_t event_mask) -{ - if (listener) - { - std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); - collection::iterator pos = m_listeners.begin(); - // See if we already have this listener, and if so, update its mask - while (pos != m_listeners.end()) - { - lldb::ListenerSP curr_listener_sp(pos->first.lock()); - if (curr_listener_sp) - { - if (curr_listener_sp.get() == listener) - { - // Relinquish all event bits in "event_mask" - pos->second &= ~event_mask; - // If all bits have been relinquished then remove this listener - if (pos->second == 0) - m_listeners.erase (pos); - return true; - } - ++pos; - } - else - { - // The listener has been destroyed since we couldn't turn the std::weak_ptr - // into a valid shared pointer, so we can remove it. - pos = m_listeners.erase (pos); - } - } - } +bool Broadcaster::BroadcasterImpl::RemoveListener( + lldb_private::Listener *listener, uint32_t event_mask) { + if (!listener) return false; + + std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); + for (auto &pair : GetListeners()) { + if (pair.first.get() == listener) { + pair.second &= ~event_mask; + return true; + } + } + return false; } -bool -Broadcaster::BroadcasterImpl::RemoveListener (const lldb::ListenerSP &listener_sp, uint32_t event_mask) -{ - return RemoveListener (listener_sp.get(), event_mask); +bool Broadcaster::BroadcasterImpl::RemoveListener( + const lldb::ListenerSP &listener_sp, uint32_t event_mask) { + return RemoveListener(listener_sp.get(), event_mask); } -void -Broadcaster::BroadcasterImpl::BroadcastEvent (EventSP &event_sp) -{ - return PrivateBroadcastEvent (event_sp, false); +void Broadcaster::BroadcasterImpl::BroadcastEvent(EventSP &event_sp) { + return PrivateBroadcastEvent(event_sp, false); } -void -Broadcaster::BroadcasterImpl::BroadcastEventIfUnique (EventSP &event_sp) -{ - return PrivateBroadcastEvent (event_sp, true); +void Broadcaster::BroadcasterImpl::BroadcastEventIfUnique(EventSP &event_sp) { + return PrivateBroadcastEvent(event_sp, true); } -void -Broadcaster::BroadcasterImpl::PrivateBroadcastEvent (EventSP &event_sp, bool unique) -{ - // Can't add a nullptr event... - if (!event_sp) - return; +void Broadcaster::BroadcasterImpl::PrivateBroadcastEvent(EventSP &event_sp, + bool unique) { + // Can't add a nullptr event... + if (!event_sp) + return; - // Update the broadcaster on this event - event_sp->SetBroadcaster (&m_broadcaster); + // Update the broadcaster on this event + event_sp->SetBroadcaster(&m_broadcaster); - const uint32_t event_type = event_sp->GetType(); + const uint32_t event_type = event_sp->GetType(); - std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); + std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); - ListenerSP hijacking_listener_sp; + ListenerSP hijacking_listener_sp; - if (!m_hijacking_listeners.empty()) - { - assert (!m_hijacking_masks.empty()); - hijacking_listener_sp = m_hijacking_listeners.back(); - if ((event_type & m_hijacking_masks.back()) == 0) - hijacking_listener_sp.reset(); - } + if (!m_hijacking_listeners.empty()) { + assert(!m_hijacking_masks.empty()); + hijacking_listener_sp = m_hijacking_listeners.back(); + if ((event_type & m_hijacking_masks.back()) == 0) + hijacking_listener_sp.reset(); + } - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS)); - if (log) - { - StreamString event_description; - event_sp->Dump (&event_description); - log->Printf ("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, unique =%i) hijack = %p", - static_cast<void*>(this), GetBroadcasterName(), - event_description.GetData(), unique, - static_cast<void*>(hijacking_listener_sp.get())); - } + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS)); + if (log) { + StreamString event_description; + event_sp->Dump(&event_description); + log->Printf("%p Broadcaster(\"%s\")::BroadcastEvent (event_sp = {%s}, " + "unique =%i) hijack = %p", + static_cast<void *>(this), GetBroadcasterName(), + event_description.GetData(), unique, + static_cast<void *>(hijacking_listener_sp.get())); + } - if (hijacking_listener_sp) - { - if (unique && hijacking_listener_sp->PeekAtNextEventForBroadcasterWithType (&m_broadcaster, event_type)) - return; - hijacking_listener_sp->AddEvent (event_sp); - } - else - { + if (hijacking_listener_sp) { + if (unique && + hijacking_listener_sp->PeekAtNextEventForBroadcasterWithType( + &m_broadcaster, event_type)) + return; + hijacking_listener_sp->AddEvent(event_sp); + } else { + for (auto &pair : GetListeners()) { + if (!(pair.second & event_type)) + continue; + if (unique && + pair.first->PeekAtNextEventForBroadcasterWithType(&m_broadcaster, + event_type)) + continue; - ListenerIterator([this, unique, event_type, &event_sp](const lldb::ListenerSP &curr_listener_sp, uint32_t &curr_event_mask) -> bool { - - if (event_type & curr_event_mask) - { - if (!unique || curr_listener_sp->PeekAtNextEventForBroadcasterWithType (&m_broadcaster, event_type) == nullptr) - curr_listener_sp->AddEvent (event_sp); - } - return true; // Keep iterating - }); + pair.first->AddEvent(event_sp); } + } } -void -Broadcaster::BroadcasterImpl::BroadcastEvent (uint32_t event_type, EventData *event_data) -{ - EventSP event_sp (new Event (event_type, event_data)); - PrivateBroadcastEvent (event_sp, false); +void Broadcaster::BroadcasterImpl::BroadcastEvent(uint32_t event_type, + EventData *event_data) { + EventSP event_sp(new Event(event_type, event_data)); + PrivateBroadcastEvent(event_sp, false); } -void -Broadcaster::BroadcasterImpl::BroadcastEvent (uint32_t event_type, const lldb::EventDataSP &event_data_sp) -{ - EventSP event_sp (new Event (event_type, event_data_sp)); - PrivateBroadcastEvent (event_sp, false); +void Broadcaster::BroadcasterImpl::BroadcastEvent( + uint32_t event_type, const lldb::EventDataSP &event_data_sp) { + EventSP event_sp(new Event(event_type, event_data_sp)); + PrivateBroadcastEvent(event_sp, false); } -void -Broadcaster::BroadcasterImpl::BroadcastEventIfUnique (uint32_t event_type, EventData *event_data) -{ - EventSP event_sp (new Event (event_type, event_data)); - PrivateBroadcastEvent (event_sp, true); +void Broadcaster::BroadcasterImpl::BroadcastEventIfUnique( + uint32_t event_type, EventData *event_data) { + EventSP event_sp(new Event(event_type, event_data)); + PrivateBroadcastEvent(event_sp, true); } -bool -Broadcaster::BroadcasterImpl::HijackBroadcaster (const lldb::ListenerSP &listener_sp, uint32_t event_mask) -{ - std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); - - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS)); - if (log) - log->Printf ("%p Broadcaster(\"%s\")::HijackBroadcaster (listener(\"%s\")=%p)", - static_cast<void*>(this), GetBroadcasterName(), - listener_sp->m_name.c_str(), static_cast<void*>(listener_sp.get())); - m_hijacking_listeners.push_back(listener_sp); - m_hijacking_masks.push_back(event_mask); - return true; +bool Broadcaster::BroadcasterImpl::HijackBroadcaster( + const lldb::ListenerSP &listener_sp, uint32_t event_mask) { + std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); + + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS)); + if (log) + log->Printf( + "%p Broadcaster(\"%s\")::HijackBroadcaster (listener(\"%s\")=%p)", + static_cast<void *>(this), GetBroadcasterName(), + listener_sp->m_name.c_str(), static_cast<void *>(listener_sp.get())); + m_hijacking_listeners.push_back(listener_sp); + m_hijacking_masks.push_back(event_mask); + return true; } -bool -Broadcaster::BroadcasterImpl::IsHijackedForEvent (uint32_t event_mask) -{ - std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); +bool Broadcaster::BroadcasterImpl::IsHijackedForEvent(uint32_t event_mask) { + std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); - if (!m_hijacking_listeners.empty()) - return (event_mask & m_hijacking_masks.back()) != 0; - return false; + if (!m_hijacking_listeners.empty()) + return (event_mask & m_hijacking_masks.back()) != 0; + return false; } -const char * -Broadcaster::BroadcasterImpl::GetHijackingListenerName() -{ - if (m_hijacking_listeners.size()) - { - return m_hijacking_listeners.back()->GetName(); - } - else - { - return nullptr; - } +const char *Broadcaster::BroadcasterImpl::GetHijackingListenerName() { + if (m_hijacking_listeners.size()) { + return m_hijacking_listeners.back()->GetName(); + } else { + return nullptr; + } } -void -Broadcaster::BroadcasterImpl::RestoreBroadcaster () -{ - std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); - - if (!m_hijacking_listeners.empty()) - { - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EVENTS)); - if (log) - { - ListenerSP listener_sp = m_hijacking_listeners.back(); - log->Printf ("%p Broadcaster(\"%s\")::RestoreBroadcaster (about to pop listener(\"%s\")=%p)", - static_cast<void*>(this), - GetBroadcasterName(), - listener_sp->m_name.c_str(), static_cast<void*>(listener_sp.get())); - } - m_hijacking_listeners.pop_back(); +void Broadcaster::BroadcasterImpl::RestoreBroadcaster() { + std::lock_guard<std::recursive_mutex> guard(m_listeners_mutex); + + if (!m_hijacking_listeners.empty()) { + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EVENTS)); + if (log) { + ListenerSP listener_sp = m_hijacking_listeners.back(); + log->Printf("%p Broadcaster(\"%s\")::RestoreBroadcaster (about to pop " + "listener(\"%s\")=%p)", + static_cast<void *>(this), GetBroadcasterName(), + listener_sp->m_name.c_str(), + static_cast<void *>(listener_sp.get())); } - if (!m_hijacking_masks.empty()) - m_hijacking_masks.pop_back(); + m_hijacking_listeners.pop_back(); + } + if (!m_hijacking_masks.empty()) + m_hijacking_masks.pop_back(); } -ConstString & -Broadcaster::GetBroadcasterClass() const -{ - static ConstString class_name ("lldb.anonymous"); - return class_name; +ConstString &Broadcaster::GetBroadcasterClass() const { + static ConstString class_name("lldb.anonymous"); + return class_name; } BroadcastEventSpec::BroadcastEventSpec(const BroadcastEventSpec &rhs) = default; -bool -BroadcastEventSpec::operator< (const BroadcastEventSpec &rhs) const -{ - if (GetBroadcasterClass() == rhs.GetBroadcasterClass()) - { - return GetEventBits() < rhs.GetEventBits(); - } - else - { - return GetBroadcasterClass() < rhs.GetBroadcasterClass(); - } +bool BroadcastEventSpec::operator<(const BroadcastEventSpec &rhs) const { + if (GetBroadcasterClass() == rhs.GetBroadcasterClass()) { + return GetEventBits() < rhs.GetEventBits(); + } else { + return GetBroadcasterClass() < rhs.GetBroadcasterClass(); + } } -BroadcastEventSpec & -BroadcastEventSpec::operator=(const BroadcastEventSpec &rhs) = default; +BroadcastEventSpec &BroadcastEventSpec:: +operator=(const BroadcastEventSpec &rhs) = default; + +BroadcasterManager::BroadcasterManager() : m_manager_mutex() {} -BroadcasterManager::BroadcasterManager() : m_manager_mutex() -{ +lldb::BroadcasterManagerSP BroadcasterManager::MakeBroadcasterManager() { + return BroadcasterManagerSP(new BroadcasterManager()); } -lldb::BroadcasterManagerSP -BroadcasterManager::MakeBroadcasterManager() -{ - return BroadcasterManagerSP(new BroadcasterManager()); +uint32_t BroadcasterManager::RegisterListenerForEvents( + const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec) { + std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); + + collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end(); + uint32_t available_bits = event_spec.GetEventBits(); + + while (iter != end_iter && + (iter = find_if(iter, end_iter, + BroadcasterClassMatches( + event_spec.GetBroadcasterClass()))) != end_iter) { + available_bits &= ~((*iter).first.GetEventBits()); + iter++; + } + + if (available_bits != 0) { + m_event_map.insert(event_listener_key( + BroadcastEventSpec(event_spec.GetBroadcasterClass(), available_bits), + listener_sp)); + m_listeners.insert(listener_sp); + } + + return available_bits; } -uint32_t -BroadcasterManager::RegisterListenerForEvents (const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec) -{ - std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); - - collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end(); - uint32_t available_bits = event_spec.GetEventBits(); - - while (iter != end_iter - && (iter = find_if (iter, end_iter, BroadcasterClassMatches(event_spec.GetBroadcasterClass()))) != end_iter) - { - available_bits &= ~((*iter).first.GetEventBits()); - iter++; - } - - if (available_bits != 0) - { - m_event_map.insert (event_listener_key (BroadcastEventSpec (event_spec.GetBroadcasterClass(), available_bits), listener_sp)); - m_listeners.insert(listener_sp); +bool BroadcasterManager::UnregisterListenerForEvents( + const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec) { + std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); + bool removed_some = false; + + if (m_listeners.erase(listener_sp) == 0) + return false; + + ListenerMatchesAndSharedBits predicate(event_spec, listener_sp); + std::vector<BroadcastEventSpec> to_be_readded; + uint32_t event_bits_to_remove = event_spec.GetEventBits(); + + // Go through the map and delete the exact matches, and build a list of + // matches that weren't exact to re-add: + while (true) { + collection::iterator iter, end_iter = m_event_map.end(); + iter = find_if(m_event_map.begin(), end_iter, predicate); + if (iter == end_iter) { + break; + } else { + uint32_t iter_event_bits = (*iter).first.GetEventBits(); + removed_some = true; + + if (event_bits_to_remove != iter_event_bits) { + uint32_t new_event_bits = iter_event_bits & ~event_bits_to_remove; + to_be_readded.push_back(BroadcastEventSpec( + event_spec.GetBroadcasterClass(), new_event_bits)); + } + m_event_map.erase(iter); } - - return available_bits; + } + + // Okay now add back the bits that weren't completely removed: + for (size_t i = 0; i < to_be_readded.size(); i++) { + m_event_map.insert(event_listener_key(to_be_readded[i], listener_sp)); + } + + return removed_some; } -bool -BroadcasterManager::UnregisterListenerForEvents (const lldb::ListenerSP &listener_sp, BroadcastEventSpec event_spec) -{ - std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); - bool removed_some = false; - - if (m_listeners.erase(listener_sp) == 0) - return false; - - ListenerMatchesAndSharedBits predicate (event_spec, listener_sp); - std::vector<BroadcastEventSpec> to_be_readded; - uint32_t event_bits_to_remove = event_spec.GetEventBits(); - - // Go through the map and delete the exact matches, and build a list of matches that weren't exact to re-add: - while (true) - { - collection::iterator iter, end_iter = m_event_map.end(); - iter = find_if (m_event_map.begin(), end_iter, predicate); - if (iter == end_iter) - { - break; - } - else - { - uint32_t iter_event_bits = (*iter).first.GetEventBits(); - removed_some = true; - - if (event_bits_to_remove != iter_event_bits) - { - uint32_t new_event_bits = iter_event_bits & ~event_bits_to_remove; - to_be_readded.push_back(BroadcastEventSpec (event_spec.GetBroadcasterClass(), new_event_bits)); - } - m_event_map.erase (iter); - } - } - - // Okay now add back the bits that weren't completely removed: - for (size_t i = 0; i < to_be_readded.size(); i++) - { - m_event_map.insert (event_listener_key (to_be_readded[i], listener_sp)); - } - - return removed_some; +ListenerSP BroadcasterManager::GetListenerForEventSpec( + BroadcastEventSpec event_spec) const { + std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); + + collection::const_iterator iter, end_iter = m_event_map.end(); + iter = find_if(m_event_map.begin(), end_iter, + BroadcastEventSpecMatches(event_spec)); + if (iter != end_iter) + return (*iter).second; + else + return nullptr; } - -ListenerSP -BroadcasterManager::GetListenerForEventSpec (BroadcastEventSpec event_spec) const -{ - std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); - - collection::const_iterator iter, end_iter = m_event_map.end(); - iter = find_if (m_event_map.begin(), end_iter, BroadcastEventSpecMatches (event_spec)); - if (iter != end_iter) - return (*iter).second; + +void BroadcasterManager::RemoveListener(Listener *listener) { + std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); + ListenerMatchesPointer predicate(listener); + listener_collection::iterator iter = m_listeners.begin(), + end_iter = m_listeners.end(); + + std::find_if(iter, end_iter, predicate); + if (iter != end_iter) + m_listeners.erase(iter); + + while (true) { + collection::iterator iter, end_iter = m_event_map.end(); + iter = find_if(m_event_map.begin(), end_iter, predicate); + if (iter == end_iter) + break; else - return nullptr; + m_event_map.erase(iter); + } } -void -BroadcasterManager::RemoveListener(Listener *listener) -{ - std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); - ListenerMatchesPointer predicate (listener); - listener_collection::iterator iter = m_listeners.begin(), end_iter = m_listeners.end(); - - std::find_if (iter, end_iter, predicate); - if (iter != end_iter) - m_listeners.erase(iter); - - while (true) - { - collection::iterator iter, end_iter = m_event_map.end(); - iter = find_if (m_event_map.begin(), end_iter, predicate); - if (iter == end_iter) - break; - else - m_event_map.erase(iter); - } -} +void BroadcasterManager::RemoveListener(const lldb::ListenerSP &listener_sp) { + std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); + ListenerMatches predicate(listener_sp); -void -BroadcasterManager::RemoveListener (const lldb::ListenerSP &listener_sp) -{ - std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); - ListenerMatches predicate (listener_sp); - - if (m_listeners.erase (listener_sp) == 0) - return; - - while (true) - { - collection::iterator iter, end_iter = m_event_map.end(); - iter = find_if (m_event_map.begin(), end_iter, predicate); - if (iter == end_iter) - break; - else - m_event_map.erase(iter); - } + if (m_listeners.erase(listener_sp) == 0) + return; + + while (true) { + collection::iterator iter, end_iter = m_event_map.end(); + iter = find_if(m_event_map.begin(), end_iter, predicate); + if (iter == end_iter) + break; + else + m_event_map.erase(iter); + } } - -void -BroadcasterManager::SignUpListenersForBroadcaster (Broadcaster &broadcaster) -{ - std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); - - collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end(); - - while (iter != end_iter - && (iter = find_if (iter, end_iter, BroadcasterClassMatches(broadcaster.GetBroadcasterClass()))) != end_iter) - { - (*iter).second->StartListeningForEvents (&broadcaster, (*iter).first.GetEventBits()); - iter++; - } + +void BroadcasterManager::SignUpListenersForBroadcaster( + Broadcaster &broadcaster) { + std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); + + collection::iterator iter = m_event_map.begin(), end_iter = m_event_map.end(); + + while (iter != end_iter && + (iter = find_if(iter, end_iter, + BroadcasterClassMatches( + broadcaster.GetBroadcasterClass()))) != end_iter) { + (*iter).second->StartListeningForEvents(&broadcaster, + (*iter).first.GetEventBits()); + iter++; + } } -void -BroadcasterManager::Clear () -{ - std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); - listener_collection::iterator end_iter = m_listeners.end(); - - for (listener_collection::iterator iter = m_listeners.begin(); iter != end_iter; iter++) - (*iter)->BroadcasterManagerWillDestruct(this->shared_from_this()); - m_listeners.clear(); - m_event_map.clear(); +void BroadcasterManager::Clear() { + std::lock_guard<std::recursive_mutex> guard(m_manager_mutex); + listener_collection::iterator end_iter = m_listeners.end(); + + for (listener_collection::iterator iter = m_listeners.begin(); + iter != end_iter; iter++) + (*iter)->BroadcasterManagerWillDestruct(this->shared_from_this()); + m_listeners.clear(); + m_event_map.clear(); } diff --git a/source/Core/CMakeLists.txt b/source/Core/CMakeLists.txt index b975fb88e784..2bbe7455418a 100644 --- a/source/Core/CMakeLists.txt +++ b/source/Core/CMakeLists.txt @@ -9,10 +9,7 @@ add_lldb_library(lldbCore Broadcaster.cpp Communication.cpp Connection.cpp - ConnectionMachPort.cpp - ConnectionSharedMemory.cpp ConstString.cpp - CxaDemangle.cpp DataBufferHeap.cpp DataBufferMemoryMap.cpp DataEncoder.cpp diff --git a/source/Core/Communication.cpp b/source/Core/Communication.cpp index f1dcb95e8af0..3d3abea62489 100644 --- a/source/Core/Communication.cpp +++ b/source/Core/Communication.cpp @@ -15,10 +15,10 @@ // Project includes #include "lldb/Core/Communication.h" #include "lldb/Core/Connection.h" +#include "lldb/Core/Event.h" #include "lldb/Core/Listener.h" #include "lldb/Core/Log.h" #include "lldb/Core/Timer.h" -#include "lldb/Core/Event.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/ThreadLauncher.h" @@ -26,445 +26,392 @@ using namespace lldb; using namespace lldb_private; -ConstString & -Communication::GetStaticBroadcasterClass () -{ - static ConstString class_name ("lldb.communication"); - return class_name; +ConstString &Communication::GetStaticBroadcasterClass() { + static ConstString class_name("lldb.communication"); + return class_name; } Communication::Communication(const char *name) - : Broadcaster(nullptr, name), - m_connection_sp(), - m_read_thread_enabled(false), - m_read_thread_did_exit(false), - m_bytes(), - m_bytes_mutex(), - m_write_mutex(), - m_synchronize_mutex(), - m_callback(nullptr), - m_callback_baton(nullptr), - m_close_on_eof(true) + : Broadcaster(nullptr, name), m_connection_sp(), + m_read_thread_enabled(false), m_read_thread_did_exit(false), m_bytes(), + m_bytes_mutex(), m_write_mutex(), m_synchronize_mutex(), + m_callback(nullptr), m_callback_baton(nullptr), m_close_on_eof(true) { - lldb_private::LogIfAnyCategoriesSet(LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION, - "%p Communication::Communication (name = %s)", this, name); - - SetEventName(eBroadcastBitDisconnected, "disconnected"); - SetEventName(eBroadcastBitReadThreadGotBytes, "got bytes"); - SetEventName(eBroadcastBitReadThreadDidExit, "read thread did exit"); - SetEventName(eBroadcastBitReadThreadShouldExit, "read thread should exit"); - SetEventName(eBroadcastBitPacketAvailable, "packet available"); - SetEventName(eBroadcastBitNoMorePendingInput, "no more pending input"); - - CheckInWithManager(); + lldb_private::LogIfAnyCategoriesSet( + LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION, + "%p Communication::Communication (name = %s)", this, name); + + SetEventName(eBroadcastBitDisconnected, "disconnected"); + SetEventName(eBroadcastBitReadThreadGotBytes, "got bytes"); + SetEventName(eBroadcastBitReadThreadDidExit, "read thread did exit"); + SetEventName(eBroadcastBitReadThreadShouldExit, "read thread should exit"); + SetEventName(eBroadcastBitPacketAvailable, "packet available"); + SetEventName(eBroadcastBitNoMorePendingInput, "no more pending input"); + + CheckInWithManager(); } -Communication::~Communication() -{ - lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION, - "%p Communication::~Communication (name = %s)", - this, GetBroadcasterName().AsCString()); - Clear(); +Communication::~Communication() { + lldb_private::LogIfAnyCategoriesSet( + LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_COMMUNICATION, + "%p Communication::~Communication (name = %s)", this, + GetBroadcasterName().AsCString()); + Clear(); } -void -Communication::Clear() -{ - SetReadThreadBytesReceivedCallback(nullptr, nullptr); - Disconnect(nullptr); - StopReadThread(nullptr); +void Communication::Clear() { + SetReadThreadBytesReceivedCallback(nullptr, nullptr); + Disconnect(nullptr); + StopReadThread(nullptr); } -ConnectionStatus -Communication::Connect (const char *url, Error *error_ptr) -{ - Clear(); +ConnectionStatus Communication::Connect(const char *url, Error *error_ptr) { + Clear(); - lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Connect (url = %s)", this, url); + lldb_private::LogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION, + "%p Communication::Connect (url = %s)", + this, url); - lldb::ConnectionSP connection_sp (m_connection_sp); - if (connection_sp) - return connection_sp->Connect (url, error_ptr); - if (error_ptr) - error_ptr->SetErrorString("Invalid connection."); - return eConnectionStatusNoConnection; + lldb::ConnectionSP connection_sp(m_connection_sp); + if (connection_sp) + return connection_sp->Connect(url, error_ptr); + if (error_ptr) + error_ptr->SetErrorString("Invalid connection."); + return eConnectionStatusNoConnection; } -ConnectionStatus -Communication::Disconnect (Error *error_ptr) -{ - lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, "%p Communication::Disconnect ()", this); - - lldb::ConnectionSP connection_sp (m_connection_sp); - if (connection_sp) - { - ConnectionStatus status = connection_sp->Disconnect (error_ptr); - // We currently don't protect connection_sp with any mutex for - // multi-threaded environments. So lets not nuke our connection class - // without putting some multi-threaded protections in. We also probably - // don't want to pay for the overhead it might cause if every time we - // access the connection we have to take a lock. - // - // This unique pointer will cleanup after itself when this object goes away, - // so there is no need to currently have it destroy itself immediately - // upon disconnnect. - //connection_sp.reset(); - return status; - } - return eConnectionStatusNoConnection; +ConnectionStatus Communication::Disconnect(Error *error_ptr) { + lldb_private::LogIfAnyCategoriesSet(LIBLLDB_LOG_COMMUNICATION, + "%p Communication::Disconnect ()", this); + + lldb::ConnectionSP connection_sp(m_connection_sp); + if (connection_sp) { + ConnectionStatus status = connection_sp->Disconnect(error_ptr); + // We currently don't protect connection_sp with any mutex for + // multi-threaded environments. So lets not nuke our connection class + // without putting some multi-threaded protections in. We also probably + // don't want to pay for the overhead it might cause if every time we + // access the connection we have to take a lock. + // + // This unique pointer will cleanup after itself when this object goes away, + // so there is no need to currently have it destroy itself immediately + // upon disconnnect. + // connection_sp.reset(); + return status; + } + return eConnectionStatusNoConnection; } -bool -Communication::IsConnected () const -{ - lldb::ConnectionSP connection_sp(m_connection_sp); - return (connection_sp ? connection_sp->IsConnected() : false); +bool Communication::IsConnected() const { + lldb::ConnectionSP connection_sp(m_connection_sp); + return (connection_sp ? connection_sp->IsConnected() : false); } -bool -Communication::HasConnection () const -{ - return m_connection_sp.get() != nullptr; +bool Communication::HasConnection() const { + return m_connection_sp.get() != nullptr; } -size_t -Communication::Read (void *dst, size_t dst_len, uint32_t timeout_usec, ConnectionStatus &status, Error *error_ptr) -{ - lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, - "%p Communication::Read (dst = %p, dst_len = %" PRIu64 ", timeout = %u usec) connection = %p", - this, - dst, - (uint64_t)dst_len, - timeout_usec, - m_connection_sp.get()); - - if (m_read_thread_enabled) - { - // We have a dedicated read thread that is getting data for us - size_t cached_bytes = GetCachedBytes (dst, dst_len); - if (cached_bytes > 0 || timeout_usec == 0) - { - status = eConnectionStatusSuccess; - return cached_bytes; - } - - if (!m_connection_sp) - { - if (error_ptr) - error_ptr->SetErrorString("Invalid connection."); - status = eConnectionStatusNoConnection; - return 0; - } - // Set the timeout appropriately - TimeValue timeout_time; - if (timeout_usec != UINT32_MAX) - { - timeout_time = TimeValue::Now(); - timeout_time.OffsetWithMicroSeconds (timeout_usec); - } - - ListenerSP listener_sp(Listener::MakeListener("Communication::Read")); - listener_sp->StartListeningForEvents (this, eBroadcastBitReadThreadGotBytes | eBroadcastBitReadThreadDidExit); - EventSP event_sp; - while (listener_sp->WaitForEvent (timeout_time.IsValid() ? &timeout_time : nullptr, event_sp)) - { - const uint32_t event_type = event_sp->GetType(); - if (event_type & eBroadcastBitReadThreadGotBytes) - { - return GetCachedBytes (dst, dst_len); - } - - if (event_type & eBroadcastBitReadThreadDidExit) - { - if (GetCloseOnEOF ()) - Disconnect(nullptr); - break; - } - } - return 0; +size_t Communication::Read(void *dst, size_t dst_len, + const Timeout<std::micro> &timeout, + ConnectionStatus &status, Error *error_ptr) { + lldb_private::LogIfAnyCategoriesSet( + LIBLLDB_LOG_COMMUNICATION, + "%p Communication::Read (dst = %p, dst_len = %" PRIu64 + ", timeout = %u usec) connection = %p", + this, dst, (uint64_t)dst_len, timeout ? timeout->count() : -1, + m_connection_sp.get()); + + if (m_read_thread_enabled) { + // We have a dedicated read thread that is getting data for us + size_t cached_bytes = GetCachedBytes(dst, dst_len); + if (cached_bytes > 0 || (timeout && timeout->count() == 0)) { + status = eConnectionStatusSuccess; + return cached_bytes; } - // We aren't using a read thread, just read the data synchronously in this - // thread. - lldb::ConnectionSP connection_sp (m_connection_sp); - if (connection_sp) - { - return connection_sp->Read (dst, dst_len, timeout_usec, status, error_ptr); + if (!m_connection_sp) { + if (error_ptr) + error_ptr->SetErrorString("Invalid connection."); + status = eConnectionStatusNoConnection; + return 0; } - if (error_ptr) - error_ptr->SetErrorString("Invalid connection."); - status = eConnectionStatusNoConnection; + ListenerSP listener_sp(Listener::MakeListener("Communication::Read")); + listener_sp->StartListeningForEvents( + this, eBroadcastBitReadThreadGotBytes | eBroadcastBitReadThreadDidExit); + EventSP event_sp; + while (listener_sp->GetEvent(event_sp, timeout)) { + const uint32_t event_type = event_sp->GetType(); + if (event_type & eBroadcastBitReadThreadGotBytes) { + return GetCachedBytes(dst, dst_len); + } + + if (event_type & eBroadcastBitReadThreadDidExit) { + if (GetCloseOnEOF()) + Disconnect(nullptr); + break; + } + } return 0; + } + + // We aren't using a read thread, just read the data synchronously in this + // thread. + return ReadFromConnection(dst, dst_len, timeout, status, error_ptr); } -size_t -Communication::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr) -{ - lldb::ConnectionSP connection_sp (m_connection_sp); +size_t Communication::Write(const void *src, size_t src_len, + ConnectionStatus &status, Error *error_ptr) { + lldb::ConnectionSP connection_sp(m_connection_sp); - std::lock_guard<std::mutex> guard(m_write_mutex); - lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, - "%p Communication::Write (src = %p, src_len = %" PRIu64 ") connection = %p", - this, - src, - (uint64_t)src_len, - connection_sp.get()); + std::lock_guard<std::mutex> guard(m_write_mutex); + lldb_private::LogIfAnyCategoriesSet( + LIBLLDB_LOG_COMMUNICATION, + "%p Communication::Write (src = %p, src_len = %" PRIu64 + ") connection = %p", + this, src, (uint64_t)src_len, connection_sp.get()); - if (connection_sp) - return connection_sp->Write (src, src_len, status, error_ptr); + if (connection_sp) + return connection_sp->Write(src, src_len, status, error_ptr); - if (error_ptr) - error_ptr->SetErrorString("Invalid connection."); - status = eConnectionStatusNoConnection; - return 0; + if (error_ptr) + error_ptr->SetErrorString("Invalid connection."); + status = eConnectionStatusNoConnection; + return 0; } -bool -Communication::StartReadThread (Error *error_ptr) -{ - if (error_ptr) - error_ptr->Clear(); +bool Communication::StartReadThread(Error *error_ptr) { + if (error_ptr) + error_ptr->Clear(); - if (m_read_thread.IsJoinable()) - return true; + if (m_read_thread.IsJoinable()) + return true; - lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, - "%p Communication::StartReadThread ()", this); + lldb_private::LogIfAnyCategoriesSet( + LIBLLDB_LOG_COMMUNICATION, "%p Communication::StartReadThread ()", this); - char thread_name[1024]; - snprintf(thread_name, sizeof(thread_name), "<lldb.comm.%s>", GetBroadcasterName().AsCString()); + char thread_name[1024]; + snprintf(thread_name, sizeof(thread_name), "<lldb.comm.%s>", + GetBroadcasterName().AsCString()); - m_read_thread_enabled = true; - m_read_thread_did_exit = false; - m_read_thread = ThreadLauncher::LaunchThread(thread_name, Communication::ReadThread, this, error_ptr); - if (!m_read_thread.IsJoinable()) - m_read_thread_enabled = false; - return m_read_thread_enabled; + m_read_thread_enabled = true; + m_read_thread_did_exit = false; + m_read_thread = ThreadLauncher::LaunchThread( + thread_name, Communication::ReadThread, this, error_ptr); + if (!m_read_thread.IsJoinable()) + m_read_thread_enabled = false; + return m_read_thread_enabled; } -bool -Communication::StopReadThread (Error *error_ptr) -{ - if (!m_read_thread.IsJoinable()) - return true; +bool Communication::StopReadThread(Error *error_ptr) { + if (!m_read_thread.IsJoinable()) + return true; - lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, - "%p Communication::StopReadThread ()", this); + lldb_private::LogIfAnyCategoriesSet( + LIBLLDB_LOG_COMMUNICATION, "%p Communication::StopReadThread ()", this); - m_read_thread_enabled = false; + m_read_thread_enabled = false; - BroadcastEvent(eBroadcastBitReadThreadShouldExit, nullptr); + BroadcastEvent(eBroadcastBitReadThreadShouldExit, nullptr); - // error = m_read_thread.Cancel(); + // error = m_read_thread.Cancel(); - Error error = m_read_thread.Join(nullptr); - return error.Success(); + Error error = m_read_thread.Join(nullptr); + return error.Success(); } -bool -Communication::JoinReadThread (Error *error_ptr) -{ - if (!m_read_thread.IsJoinable()) - return true; +bool Communication::JoinReadThread(Error *error_ptr) { + if (!m_read_thread.IsJoinable()) + return true; - Error error = m_read_thread.Join(nullptr); - return error.Success(); + Error error = m_read_thread.Join(nullptr); + return error.Success(); } -size_t -Communication::GetCachedBytes (void *dst, size_t dst_len) -{ - std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex); - if (!m_bytes.empty()) - { - // If DST is nullptr and we have a thread, then return the number - // of bytes that are available so the caller can call again - if (dst == nullptr) - return m_bytes.size(); +size_t Communication::GetCachedBytes(void *dst, size_t dst_len) { + std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex); + if (!m_bytes.empty()) { + // If DST is nullptr and we have a thread, then return the number + // of bytes that are available so the caller can call again + if (dst == nullptr) + return m_bytes.size(); - const size_t len = std::min<size_t>(dst_len, m_bytes.size()); + const size_t len = std::min<size_t>(dst_len, m_bytes.size()); - ::memcpy (dst, m_bytes.c_str(), len); - m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len); + ::memcpy(dst, m_bytes.c_str(), len); + m_bytes.erase(m_bytes.begin(), m_bytes.begin() + len); - return len; - } - return 0; + return len; + } + return 0; } -void -Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, ConnectionStatus status) -{ - lldb_private::LogIfAnyCategoriesSet (LIBLLDB_LOG_COMMUNICATION, - "%p Communication::AppendBytesToCache (src = %p, src_len = %" PRIu64 ", broadcast = %i)", - this, bytes, (uint64_t)len, broadcast); - if ((bytes == nullptr || len == 0) - && (status != lldb::eConnectionStatusEndOfFile)) - return; - if (m_callback) - { - // If the user registered a callback, then call it and do not broadcast - m_callback (m_callback_baton, bytes, len); - } - else if (bytes != nullptr && len > 0) - { - std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex); - m_bytes.append ((const char *)bytes, len); - if (broadcast) - BroadcastEventIfUnique (eBroadcastBitReadThreadGotBytes); - } +void Communication::AppendBytesToCache(const uint8_t *bytes, size_t len, + bool broadcast, + ConnectionStatus status) { + lldb_private::LogIfAnyCategoriesSet( + LIBLLDB_LOG_COMMUNICATION, + "%p Communication::AppendBytesToCache (src = %p, src_len = %" PRIu64 + ", broadcast = %i)", + this, bytes, (uint64_t)len, broadcast); + if ((bytes == nullptr || len == 0) && + (status != lldb::eConnectionStatusEndOfFile)) + return; + if (m_callback) { + // If the user registered a callback, then call it and do not broadcast + m_callback(m_callback_baton, bytes, len); + } else if (bytes != nullptr && len > 0) { + std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex); + m_bytes.append((const char *)bytes, len); + if (broadcast) + BroadcastEventIfUnique(eBroadcastBitReadThreadGotBytes); + } } -size_t -Communication::ReadFromConnection (void *dst, - size_t dst_len, - uint32_t timeout_usec, - ConnectionStatus &status, - Error *error_ptr) -{ - lldb::ConnectionSP connection_sp(m_connection_sp); - return (connection_sp ? connection_sp->Read(dst, dst_len, timeout_usec, status, error_ptr) : 0); +size_t Communication::ReadFromConnection(void *dst, size_t dst_len, + const Timeout<std::micro> &timeout, + ConnectionStatus &status, + Error *error_ptr) { + lldb::ConnectionSP connection_sp(m_connection_sp); + if (connection_sp) + return connection_sp->Read(dst, dst_len, timeout, status, error_ptr); + + if (error_ptr) + error_ptr->SetErrorString("Invalid connection."); + status = eConnectionStatusNoConnection; + return 0; } -bool -Communication::ReadThreadIsRunning () -{ - return m_read_thread_enabled; -} +bool Communication::ReadThreadIsRunning() { return m_read_thread_enabled; } -lldb::thread_result_t -Communication::ReadThread (lldb::thread_arg_t p) -{ - Communication *comm = (Communication *)p; - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION)); - - if (log) - log->Printf ("%p Communication::ReadThread () thread starting...", p); - - uint8_t buf[1024]; - - Error error; - ConnectionStatus status = eConnectionStatusSuccess; - bool done = false; - while (!done && comm->m_read_thread_enabled) - { - size_t bytes_read = comm->ReadFromConnection (buf, sizeof(buf), 5 * TimeValue::MicroSecPerSec, status, &error); - if (bytes_read > 0) - comm->AppendBytesToCache (buf, bytes_read, true, status); - else if ((bytes_read == 0) - && status == eConnectionStatusEndOfFile) - { - if (comm->GetCloseOnEOF ()) - comm->Disconnect (); - comm->AppendBytesToCache (buf, bytes_read, true, status); - } - - switch (status) - { - case eConnectionStatusSuccess: - break; - - case eConnectionStatusEndOfFile: - done = true; - break; - case eConnectionStatusError: // Check GetError() for details - if (error.GetType() == eErrorTypePOSIX && error.GetError() == EIO) - { - // EIO on a pipe is usually caused by remote shutdown - comm->Disconnect (); - done = true; - } - if (log) - error.LogIfError (log, - "%p Communication::ReadFromConnection () => status = %s", - p, - Communication::ConnectionStatusAsCString (status)); - break; - case eConnectionStatusInterrupted: // Synchronization signal from SynchronizeWithReadThread() - // The connection returns eConnectionStatusInterrupted only when there is no - // input pending to be read, so we can signal that. - comm->BroadcastEvent (eBroadcastBitNoMorePendingInput); - break; - case eConnectionStatusNoConnection: // No connection - case eConnectionStatusLostConnection: // Lost connection while connected to a valid connection - done = true; - LLVM_FALLTHROUGH; - case eConnectionStatusTimedOut: // Request timed out - if (log) - error.LogIfError (log, - "%p Communication::ReadFromConnection () => status = %s", - p, - Communication::ConnectionStatusAsCString (status)); - break; - } +lldb::thread_result_t Communication::ReadThread(lldb::thread_arg_t p) { + Communication *comm = (Communication *)p; + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMUNICATION)); + + if (log) + log->Printf("%p Communication::ReadThread () thread starting...", p); + + uint8_t buf[1024]; + + Error error; + ConnectionStatus status = eConnectionStatusSuccess; + bool done = false; + while (!done && comm->m_read_thread_enabled) { + size_t bytes_read = comm->ReadFromConnection( + buf, sizeof(buf), std::chrono::seconds(5), status, &error); + if (bytes_read > 0) + comm->AppendBytesToCache(buf, bytes_read, true, status); + else if ((bytes_read == 0) && status == eConnectionStatusEndOfFile) { + if (comm->GetCloseOnEOF()) + comm->Disconnect(); + comm->AppendBytesToCache(buf, bytes_read, true, status); } - log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMUNICATION); - if (log) - log->Printf ("%p Communication::ReadThread () thread exiting...", p); - - comm->m_read_thread_did_exit = true; - // Let clients know that this thread is exiting - comm->BroadcastEvent (eBroadcastBitNoMorePendingInput); - comm->BroadcastEvent (eBroadcastBitReadThreadDidExit); - return NULL; + + switch (status) { + case eConnectionStatusSuccess: + break; + + case eConnectionStatusEndOfFile: + done = true; + break; + case eConnectionStatusError: // Check GetError() for details + if (error.GetType() == eErrorTypePOSIX && error.GetError() == EIO) { + // EIO on a pipe is usually caused by remote shutdown + comm->Disconnect(); + done = true; + } + if (log) + error.LogIfError( + log, "%p Communication::ReadFromConnection () => status = %s", p, + Communication::ConnectionStatusAsCString(status)); + break; + case eConnectionStatusInterrupted: // Synchronization signal from + // SynchronizeWithReadThread() + // The connection returns eConnectionStatusInterrupted only when there is + // no + // input pending to be read, so we can signal that. + comm->BroadcastEvent(eBroadcastBitNoMorePendingInput); + break; + case eConnectionStatusNoConnection: // No connection + case eConnectionStatusLostConnection: // Lost connection while connected to + // a valid connection + done = true; + LLVM_FALLTHROUGH; + case eConnectionStatusTimedOut: // Request timed out + if (log) + error.LogIfError( + log, "%p Communication::ReadFromConnection () => status = %s", p, + Communication::ConnectionStatusAsCString(status)); + break; + } + } + log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_COMMUNICATION); + if (log) + log->Printf("%p Communication::ReadThread () thread exiting...", p); + + comm->m_read_thread_did_exit = true; + // Let clients know that this thread is exiting + comm->BroadcastEvent(eBroadcastBitNoMorePendingInput); + comm->BroadcastEvent(eBroadcastBitReadThreadDidExit); + return NULL; } -void -Communication::SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived callback, - void *callback_baton) -{ - m_callback = callback; - m_callback_baton = callback_baton; +void Communication::SetReadThreadBytesReceivedCallback( + ReadThreadBytesReceived callback, void *callback_baton) { + m_callback = callback; + m_callback_baton = callback_baton; } -void -Communication::SynchronizeWithReadThread () -{ - // Only one thread can do the synchronization dance at a time. - std::lock_guard<std::mutex> guard(m_synchronize_mutex); +void Communication::SynchronizeWithReadThread() { + // Only one thread can do the synchronization dance at a time. + std::lock_guard<std::mutex> guard(m_synchronize_mutex); - // First start listening for the synchronization event. - ListenerSP listener_sp(Listener::MakeListener("Communication::SyncronizeWithReadThread")); - listener_sp->StartListeningForEvents(this, eBroadcastBitNoMorePendingInput); + // First start listening for the synchronization event. + ListenerSP listener_sp( + Listener::MakeListener("Communication::SyncronizeWithReadThread")); + listener_sp->StartListeningForEvents(this, eBroadcastBitNoMorePendingInput); - // If the thread is not running, there is no point in synchronizing. - if (!m_read_thread_enabled || m_read_thread_did_exit) - return; + // If the thread is not running, there is no point in synchronizing. + if (!m_read_thread_enabled || m_read_thread_did_exit) + return; - // Notify the read thread. - m_connection_sp->InterruptRead(); + // Notify the read thread. + m_connection_sp->InterruptRead(); - // Wait for the synchronization event. - EventSP event_sp; - listener_sp->WaitForEvent(nullptr, event_sp); + // Wait for the synchronization event. + EventSP event_sp; + listener_sp->GetEvent(event_sp, llvm::None); } -void -Communication::SetConnection (Connection *connection) -{ - Disconnect(nullptr); - StopReadThread(nullptr); - m_connection_sp.reset(connection); +void Communication::SetConnection(Connection *connection) { + Disconnect(nullptr); + StopReadThread(nullptr); + m_connection_sp.reset(connection); } const char * -Communication::ConnectionStatusAsCString (lldb::ConnectionStatus status) -{ - switch (status) - { - case eConnectionStatusSuccess: return "success"; - case eConnectionStatusError: return "error"; - case eConnectionStatusTimedOut: return "timed out"; - case eConnectionStatusNoConnection: return "no connection"; - case eConnectionStatusLostConnection: return "lost connection"; - case eConnectionStatusEndOfFile: return "end of file"; - case eConnectionStatusInterrupted: return "interrupted"; - } - - static char unknown_state_string[64]; - snprintf(unknown_state_string, sizeof (unknown_state_string), "ConnectionStatus = %i", status); - return unknown_state_string; +Communication::ConnectionStatusAsCString(lldb::ConnectionStatus status) { + switch (status) { + case eConnectionStatusSuccess: + return "success"; + case eConnectionStatusError: + return "error"; + case eConnectionStatusTimedOut: + return "timed out"; + case eConnectionStatusNoConnection: + return "no connection"; + case eConnectionStatusLostConnection: + return "lost connection"; + case eConnectionStatusEndOfFile: + return "end of file"; + case eConnectionStatusInterrupted: + return "interrupted"; + } + + static char unknown_state_string[64]; + snprintf(unknown_state_string, sizeof(unknown_state_string), + "ConnectionStatus = %i", status); + return unknown_state_string; } diff --git a/source/Core/Connection.cpp b/source/Core/Connection.cpp index 3f740a1ed82a..1ae046b8a018 100644 --- a/source/Core/Connection.cpp +++ b/source/Core/Connection.cpp @@ -21,20 +21,14 @@ using namespace lldb_private; -Connection::Connection () -{ -} +Connection::Connection() {} -Connection::~Connection () -{ -} +Connection::~Connection() {} -Connection * -Connection::CreateDefaultConnection(const char *url) -{ +Connection *Connection::CreateDefaultConnection(const char *url) { #if defined(_WIN32) - if (strstr(url, "file://") == url) - return new ConnectionGenericFile(); + if (strstr(url, "file://") == url) + return new ConnectionGenericFile(); #endif - return new ConnectionFileDescriptor(); + return new ConnectionFileDescriptor(); } diff --git a/source/Core/ConnectionMachPort.cpp b/source/Core/ConnectionMachPort.cpp deleted file mode 100644 index e04c48905570..000000000000 --- a/source/Core/ConnectionMachPort.cpp +++ /dev/null @@ -1,331 +0,0 @@ -//===-- ConnectionMachPort.cpp ----------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -#if defined(__APPLE__) - -#include "lldb/Core/ConnectionMachPort.h" - -// C Includes -#include <mach/mach.h> -#include <servers/bootstrap.h> - -// C++ Includes -// Other libraries and framework includes -// Project includes -#include "lldb/Core/Communication.h" -#include "lldb/Core/Log.h" - -using namespace lldb; -using namespace lldb_private; - -struct MessageType -{ - mach_msg_header_t head; - ConnectionMachPort::PayloadType payload; -}; - - - -ConnectionMachPort::ConnectionMachPort () : - Connection(), - m_task(mach_task_self()), - m_port(MACH_PORT_TYPE_NONE) -{ -} - -ConnectionMachPort::~ConnectionMachPort () -{ - Disconnect (NULL); -} - -bool -ConnectionMachPort::IsConnected () const -{ - return m_port != MACH_PORT_TYPE_NONE; -} - -ConnectionStatus -ConnectionMachPort::Connect (const char *s, Error *error_ptr) -{ - if (IsConnected()) - { - if (error_ptr) - error_ptr->SetErrorString ("already connected"); - return eConnectionStatusError; - } - - if (s == NULL || s[0] == '\0') - { - if (error_ptr) - error_ptr->SetErrorString ("empty connect URL"); - return eConnectionStatusError; - } - - ConnectionStatus status = eConnectionStatusError; - - if (0 == strncmp (s, "bootstrap-checkin://", strlen("bootstrap-checkin://"))) - { - s += strlen("bootstrap-checkin://"); - - if (*s) - { - status = BootstrapCheckIn (s, error_ptr); - } - else - { - if (error_ptr) - error_ptr->SetErrorString ("bootstrap port name is empty"); - } - } - else if (0 == strncmp (s, "bootstrap-lookup://", strlen("bootstrap-lookup://"))) - { - s += strlen("bootstrap-lookup://"); - if (*s) - { - status = BootstrapLookup (s, error_ptr); - } - else - { - if (error_ptr) - error_ptr->SetErrorString ("bootstrap port name is empty"); - } - } - else - { - if (error_ptr) - error_ptr->SetErrorStringWithFormat ("unsupported connection URL: '%s'", s); - } - - - if (status == eConnectionStatusSuccess) - { - if (error_ptr) - error_ptr->Clear(); - m_uri.assign(s); - } - else - { - Disconnect(NULL); - } - - return status; -} - -ConnectionStatus -ConnectionMachPort::BootstrapCheckIn (const char *port, Error *error_ptr) -{ - mach_port_t bootstrap_port = MACH_PORT_TYPE_NONE; - - /* Getting bootstrap server port */ - kern_return_t kret = task_get_bootstrap_port(mach_task_self(), &bootstrap_port); - if (kret == KERN_SUCCESS) - { - name_t port_name; - int len = snprintf(port_name, sizeof(port_name), "%s", port); - if (static_cast<size_t>(len) < sizeof(port_name)) - { - kret = ::bootstrap_check_in (bootstrap_port, - port_name, - &m_port); - } - else - { - Disconnect(NULL); - if (error_ptr) - error_ptr->SetErrorString ("bootstrap is too long"); - return eConnectionStatusError; - } - } - - if (kret != KERN_SUCCESS) - { - Disconnect(NULL); - if (error_ptr) - error_ptr->SetError (kret, eErrorTypeMachKernel); - return eConnectionStatusError; - } - return eConnectionStatusSuccess; -} - -lldb::ConnectionStatus -ConnectionMachPort::BootstrapLookup (const char *port, - Error *error_ptr) -{ - name_t port_name; - - if (port && port[0]) - { - if (static_cast<size_t>(::snprintf (port_name, sizeof (port_name), "%s", port)) >= sizeof (port_name)) - { - if (error_ptr) - error_ptr->SetErrorString ("port netname is too long"); - return eConnectionStatusError; - } - } - else - { - if (error_ptr) - error_ptr->SetErrorString ("empty port netname"); - return eConnectionStatusError; - } - - mach_port_t bootstrap_port = MACH_PORT_TYPE_NONE; - - /* Getting bootstrap server port */ - kern_return_t kret = task_get_bootstrap_port(mach_task_self(), &bootstrap_port); - if (kret == KERN_SUCCESS) - { - kret = ::bootstrap_look_up (bootstrap_port, - port_name, - &m_port); - } - - if (kret != KERN_SUCCESS) - { - if (error_ptr) - error_ptr->SetError (kret, eErrorTypeMachKernel); - return eConnectionStatusError; - } - - return eConnectionStatusSuccess; -} - -ConnectionStatus -ConnectionMachPort::Disconnect (Error *error_ptr) -{ - kern_return_t kret; - - // TODO: verify if we need to netname_check_out for - // either or both - if (m_port != MACH_PORT_TYPE_NONE) - { - kret = ::mach_port_deallocate (m_task, m_port); - if (error_ptr) - error_ptr->SetError (kret, eErrorTypeMachKernel); - m_port = MACH_PORT_TYPE_NONE; - } - m_uri.clear(); - - return eConnectionStatusSuccess; -} - -size_t -ConnectionMachPort::Read (void *dst, - size_t dst_len, - uint32_t timeout_usec, - ConnectionStatus &status, - Error *error_ptr) -{ - PayloadType payload; - - kern_return_t kret = Receive (payload); - if (kret == KERN_SUCCESS) - { - memcpy (dst, payload.data, payload.data_length); - status = eConnectionStatusSuccess; - return payload.data_length; - } - - if (error_ptr) - error_ptr->SetError (kret, eErrorTypeMachKernel); - status = eConnectionStatusError; - return 0; -} - -size_t -ConnectionMachPort::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr) -{ - PayloadType payload; - payload.command = 0; - payload.data_length = src_len; - const size_t max_payload_size = sizeof(payload.data); - if (src_len > max_payload_size) - payload.data_length = max_payload_size; - memcpy (payload.data, src, payload.data_length); - - if (Send (payload) == KERN_SUCCESS) - { - status = eConnectionStatusSuccess; - return payload.data_length; - } - status = eConnectionStatusError; - return 0; -} - -std::string -ConnectionMachPort::GetURI() -{ - return m_uri; -} - -ConnectionStatus -ConnectionMachPort::BytesAvailable (uint32_t timeout_usec, Error *error_ptr) -{ - return eConnectionStatusLostConnection; -} - -kern_return_t -ConnectionMachPort::Send (const PayloadType &payload) -{ - struct MessageType message; - - /* (i) Form the message : */ - - /* (i.a) Fill the header fields : */ - message.head.msgh_bits = MACH_MSGH_BITS_REMOTE (MACH_MSG_TYPE_MAKE_SEND) | - MACH_MSGH_BITS_OTHER (MACH_MSGH_BITS_COMPLEX); - message.head.msgh_size = sizeof(MessageType); - message.head.msgh_local_port = MACH_PORT_NULL; - message.head.msgh_remote_port = m_port; - - /* (i.b) Explain the message type ( an integer ) */ - // message.type.msgt_name = MACH_MSG_TYPE_INTEGER_32; - // message.type.msgt_size = 32; - // message.type.msgt_number = 1; - // message.type.msgt_inline = TRUE; - // message.type.msgt_longform = FALSE; - // message.type.msgt_deallocate = FALSE; - /* message.type.msgt_unused = 0; */ /* not needed, I think */ - - /* (i.c) Fill the message with the given integer : */ - message.payload = payload; - - /* (ii) Send the message : */ - kern_return_t kret = ::mach_msg (&message.head, - MACH_SEND_MSG, - message.head.msgh_size, - 0, - MACH_PORT_NULL, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL); - - return kret; -} - -kern_return_t -ConnectionMachPort::Receive (PayloadType &payload) -{ - MessageType message; - message.head.msgh_size = sizeof(MessageType); - - kern_return_t kret = ::mach_msg (&message.head, - MACH_RCV_MSG, - 0, - sizeof(MessageType), - m_port, - MACH_MSG_TIMEOUT_NONE, - MACH_PORT_NULL); - - if (kret == KERN_SUCCESS) - payload = message.payload; - - return kret; -} - - -#endif // #if defined(__APPLE__) diff --git a/source/Core/ConnectionSharedMemory.cpp b/source/Core/ConnectionSharedMemory.cpp deleted file mode 100644 index 707644d36b1c..000000000000 --- a/source/Core/ConnectionSharedMemory.cpp +++ /dev/null @@ -1,171 +0,0 @@ -//===-- ConnectionSharedMemory.cpp ------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef __ANDROID_NDK__ - -#include "lldb/Core/ConnectionSharedMemory.h" - -// C Includes -#ifdef _WIN32 -#include "lldb/Host/windows/windows.h" -#else -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <fcntl.h> -#endif - -// C++ Includes -#include <cerrno> -#include <cstdlib> - -// Other libraries and framework includes -#include "llvm/Support/MathExtras.h" - -// Project includes -#include "lldb/Core/Communication.h" -#include "lldb/Core/Log.h" - -#include "llvm/Support/ConvertUTF.h" - -using namespace lldb; -using namespace lldb_private; - -ConnectionSharedMemory::ConnectionSharedMemory () : - Connection(), - m_name(), - m_fd (-1), - m_mmap() -{ -} - -ConnectionSharedMemory::~ConnectionSharedMemory () -{ - Disconnect(nullptr); -} - -bool -ConnectionSharedMemory::IsConnected () const -{ - return m_fd >= 0; -} - -ConnectionStatus -ConnectionSharedMemory::Connect (const char *s, Error *error_ptr) -{ -// if (s && s[0]) -// { -// if (strstr(s, "shm-create://")) -// { -// } -// else if (strstr(s, "shm-connect://")) -// { -// } -// if (error_ptr) -// error_ptr->SetErrorStringWithFormat ("unsupported connection URL: '%s'", s); -// return eConnectionStatusError; -// } - if (error_ptr) - error_ptr->SetErrorString("invalid connect arguments"); - return eConnectionStatusError; -} - -ConnectionStatus -ConnectionSharedMemory::Disconnect (Error *error_ptr) -{ - m_mmap.Clear(); - if (!m_name.empty()) - { -#ifdef _WIN32 - close(m_fd); - m_fd = -1; -#else - shm_unlink (m_name.c_str()); -#endif - m_name.clear(); - } - return eConnectionStatusSuccess; -} - -size_t -ConnectionSharedMemory::Read (void *dst, - size_t dst_len, - uint32_t timeout_usec, - ConnectionStatus &status, - Error *error_ptr) -{ - status = eConnectionStatusSuccess; - return 0; -} - -size_t -ConnectionSharedMemory::Write (const void *src, size_t src_len, ConnectionStatus &status, Error *error_ptr) -{ - status = eConnectionStatusSuccess; - return 0; -} - -std::string -ConnectionSharedMemory::GetURI() -{ - // TODO: fix when Connect is fixed? - return ""; -} - -ConnectionStatus -ConnectionSharedMemory::BytesAvailable (uint32_t timeout_usec, Error *error_ptr) -{ - return eConnectionStatusLostConnection; -} - -ConnectionStatus -ConnectionSharedMemory::Open (bool create, const char *name, size_t size, Error *error_ptr) -{ - if (m_fd != -1) - { - if (error_ptr) - error_ptr->SetErrorString("already open"); - return eConnectionStatusError; - } - - m_name.assign (name); - -#ifdef _WIN32 - HANDLE handle = INVALID_HANDLE_VALUE; - std::wstring wname; - if (llvm::ConvertUTF8toWide(name, wname)) - { - if (create) - { - handle = CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, llvm::Hi_32(size), - llvm::Lo_32(size), wname.c_str()); - } - else - handle = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, wname.c_str()); - } - - m_fd = _open_osfhandle((intptr_t)handle, 0); -#else - int oflag = O_RDWR; - if (create) - oflag |= O_CREAT; - m_fd = ::shm_open (m_name.c_str(), oflag, S_IRUSR|S_IWUSR); - - if (create) - ::ftruncate (m_fd, size); -#endif - - if (m_mmap.MemoryMapFromFileDescriptor(m_fd, 0, size, true, false) == size) - return eConnectionStatusSuccess; - - Disconnect(nullptr); - return eConnectionStatusError; -} - -#endif // __ANDROID_NDK__ diff --git a/source/Core/ConstString.cpp b/source/Core/ConstString.cpp index f983f1444d7c..21b4d3d76f1c 100644 --- a/source/Core/ConstString.cpp +++ b/source/Core/ConstString.cpp @@ -15,8 +15,8 @@ #include <mutex> // Other libraries and framework includes -#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" #include "llvm/Support/RWMutex.h" // Project includes @@ -24,180 +24,159 @@ using namespace lldb_private; -class Pool -{ +class Pool { public: - typedef const char * StringPoolValueType; - typedef llvm::StringMap<StringPoolValueType, llvm::BumpPtrAllocator> StringPool; - typedef llvm::StringMapEntry<StringPoolValueType> StringPoolEntryType; - - static StringPoolEntryType & - GetStringMapEntryFromKeyData (const char *keyData) - { - char *ptr = const_cast<char*>(keyData) - sizeof (StringPoolEntryType); - return *reinterpret_cast<StringPoolEntryType*>(ptr); - } - - size_t - GetConstCStringLength (const char *ccstr) const - { - if (ccstr != nullptr) - { - const uint8_t h = hash (llvm::StringRef(ccstr)); - llvm::sys::SmartScopedReader<false> rlock(m_string_pools[h].m_mutex); - const StringPoolEntryType& entry = GetStringMapEntryFromKeyData (ccstr); - return entry.getKey().size(); - } - return 0; + typedef const char *StringPoolValueType; + typedef llvm::StringMap<StringPoolValueType, llvm::BumpPtrAllocator> + StringPool; + typedef llvm::StringMapEntry<StringPoolValueType> StringPoolEntryType; + + static StringPoolEntryType & + GetStringMapEntryFromKeyData(const char *keyData) { + char *ptr = const_cast<char *>(keyData) - sizeof(StringPoolEntryType); + return *reinterpret_cast<StringPoolEntryType *>(ptr); + } + + size_t GetConstCStringLength(const char *ccstr) const { + if (ccstr != nullptr) { + const uint8_t h = hash(llvm::StringRef(ccstr)); + llvm::sys::SmartScopedReader<false> rlock(m_string_pools[h].m_mutex); + const StringPoolEntryType &entry = GetStringMapEntryFromKeyData(ccstr); + return entry.getKey().size(); } - - StringPoolValueType - GetMangledCounterpart (const char *ccstr) const - { - if (ccstr != nullptr) - { - const uint8_t h = hash (llvm::StringRef(ccstr)); - llvm::sys::SmartScopedReader<false> rlock(m_string_pools[h].m_mutex); - return GetStringMapEntryFromKeyData (ccstr).getValue(); - } - return nullptr; + return 0; + } + + StringPoolValueType GetMangledCounterpart(const char *ccstr) const { + if (ccstr != nullptr) { + const uint8_t h = hash(llvm::StringRef(ccstr)); + llvm::sys::SmartScopedReader<false> rlock(m_string_pools[h].m_mutex); + return GetStringMapEntryFromKeyData(ccstr).getValue(); } - - bool - SetMangledCounterparts (const char *key_ccstr, const char *value_ccstr) - { - if (key_ccstr != nullptr && value_ccstr != nullptr) - { - { - const uint8_t h = hash (llvm::StringRef(key_ccstr)); - llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex); - GetStringMapEntryFromKeyData (key_ccstr).setValue(value_ccstr); - } - { - const uint8_t h = hash (llvm::StringRef(value_ccstr)); - llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex); - GetStringMapEntryFromKeyData (value_ccstr).setValue(key_ccstr); - } - return true; - } - return false; + return nullptr; + } + + bool SetMangledCounterparts(const char *key_ccstr, const char *value_ccstr) { + if (key_ccstr != nullptr && value_ccstr != nullptr) { + { + const uint8_t h = hash(llvm::StringRef(key_ccstr)); + llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex); + GetStringMapEntryFromKeyData(key_ccstr).setValue(value_ccstr); + } + { + const uint8_t h = hash(llvm::StringRef(value_ccstr)); + llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex); + GetStringMapEntryFromKeyData(value_ccstr).setValue(key_ccstr); + } + return true; } + return false; + } - const char * - GetConstCString (const char *cstr) - { - if (cstr != nullptr) - return GetConstCStringWithLength (cstr, strlen (cstr)); - return nullptr; - } + const char *GetConstCString(const char *cstr) { + if (cstr != nullptr) + return GetConstCStringWithLength(cstr, strlen(cstr)); + return nullptr; + } - const char * - GetConstCStringWithLength (const char *cstr, size_t cstr_len) - { - if (cstr != nullptr) - return GetConstCStringWithStringRef(llvm::StringRef(cstr, cstr_len)); - return nullptr; + const char *GetConstCStringWithLength(const char *cstr, size_t cstr_len) { + if (cstr != nullptr) + return GetConstCStringWithStringRef(llvm::StringRef(cstr, cstr_len)); + return nullptr; + } + + const char *GetConstCStringWithStringRef(const llvm::StringRef &string_ref) { + if (string_ref.data()) { + const uint8_t h = hash(string_ref); + + { + llvm::sys::SmartScopedReader<false> rlock(m_string_pools[h].m_mutex); + auto it = m_string_pools[h].m_string_map.find(string_ref); + if (it != m_string_pools[h].m_string_map.end()) + return it->getKeyData(); + } + + llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex); + StringPoolEntryType &entry = + *m_string_pools[h] + .m_string_map.insert(std::make_pair(string_ref, nullptr)) + .first; + return entry.getKeyData(); } - - const char * - GetConstCStringWithStringRef (const llvm::StringRef &string_ref) - { - if (string_ref.data()) - { - const uint8_t h = hash (string_ref); - - { - llvm::sys::SmartScopedReader<false> rlock(m_string_pools[h].m_mutex); - auto it = m_string_pools[h].m_string_map.find (string_ref); - if (it != m_string_pools[h].m_string_map.end()) - return it->getKeyData(); - } - - llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex); - StringPoolEntryType& entry = *m_string_pools[h].m_string_map.insert (std::make_pair (string_ref, nullptr)).first; - return entry.getKeyData(); - } - return nullptr; + return nullptr; + } + + const char * + GetConstCStringAndSetMangledCounterPart(const char *demangled_cstr, + const char *mangled_ccstr) { + if (demangled_cstr != nullptr) { + const char *demangled_ccstr = nullptr; + + { + llvm::StringRef string_ref(demangled_cstr); + const uint8_t h = hash(string_ref); + llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex); + + // Make string pool entry with the mangled counterpart already set + StringPoolEntryType &entry = + *m_string_pools[h] + .m_string_map.insert(std::make_pair(string_ref, mangled_ccstr)) + .first; + + // Extract the const version of the demangled_cstr + demangled_ccstr = entry.getKeyData(); + } + + { + // Now assign the demangled const string as the counterpart of the + // mangled const string... + const uint8_t h = hash(llvm::StringRef(mangled_ccstr)); + llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex); + GetStringMapEntryFromKeyData(mangled_ccstr).setValue(demangled_ccstr); + } + + // Return the constant demangled C string + return demangled_ccstr; } - - const char * - GetConstCStringAndSetMangledCounterPart (const char *demangled_cstr, const char *mangled_ccstr) - { - if (demangled_cstr != nullptr) - { - const char *demangled_ccstr = nullptr; - - { - llvm::StringRef string_ref (demangled_cstr); - const uint8_t h = hash (string_ref); - llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex); - - // Make string pool entry with the mangled counterpart already set - StringPoolEntryType& entry = *m_string_pools[h].m_string_map.insert ( - std::make_pair (string_ref, mangled_ccstr)).first; - - // Extract the const version of the demangled_cstr - demangled_ccstr = entry.getKeyData(); - } - - { - // Now assign the demangled const string as the counterpart of the - // mangled const string... - const uint8_t h = hash (llvm::StringRef(mangled_ccstr)); - llvm::sys::SmartScopedWriter<false> wlock(m_string_pools[h].m_mutex); - GetStringMapEntryFromKeyData (mangled_ccstr).setValue(demangled_ccstr); - } - - // Return the constant demangled C string - return demangled_ccstr; - } - return nullptr; + return nullptr; + } + + const char *GetConstTrimmedCStringWithLength(const char *cstr, + size_t cstr_len) { + if (cstr != nullptr) { + const size_t trimmed_len = std::min<size_t>(strlen(cstr), cstr_len); + return GetConstCStringWithLength(cstr, trimmed_len); } - - const char * - GetConstTrimmedCStringWithLength (const char *cstr, size_t cstr_len) - { - if (cstr != nullptr) - { - const size_t trimmed_len = std::min<size_t> (strlen (cstr), cstr_len); - return GetConstCStringWithLength (cstr, trimmed_len); - } - return nullptr; - } - - //------------------------------------------------------------------ - // Return the size in bytes that this object and any items in its - // collection of uniqued strings + data count values takes in - // memory. - //------------------------------------------------------------------ - size_t - MemorySize() const - { - size_t mem_size = sizeof(Pool); - for (const auto& pool : m_string_pools) - { - llvm::sys::SmartScopedReader<false> rlock(pool.m_mutex); - for (const auto& entry : pool.m_string_map) - mem_size += sizeof(StringPoolEntryType) + entry.getKey().size(); - } - return mem_size; + return nullptr; + } + + //------------------------------------------------------------------ + // Return the size in bytes that this object and any items in its + // collection of uniqued strings + data count values takes in + // memory. + //------------------------------------------------------------------ + size_t MemorySize() const { + size_t mem_size = sizeof(Pool); + for (const auto &pool : m_string_pools) { + llvm::sys::SmartScopedReader<false> rlock(pool.m_mutex); + for (const auto &entry : pool.m_string_map) + mem_size += sizeof(StringPoolEntryType) + entry.getKey().size(); } + return mem_size; + } protected: - uint8_t - hash(const llvm::StringRef &s) const - { - uint32_t h = llvm::HashString(s); - return ((h >> 24) ^ (h >> 16) ^ (h >> 8) ^ h) & 0xff; - } + uint8_t hash(const llvm::StringRef &s) const { + uint32_t h = llvm::HashString(s); + return ((h >> 24) ^ (h >> 16) ^ (h >> 8) ^ h) & 0xff; + } - struct PoolEntry - { - mutable llvm::sys::SmartRWMutex<false> m_mutex; - StringPool m_string_map; - }; + struct PoolEntry { + mutable llvm::sys::SmartRWMutex<false> m_mutex; + StringPool m_string_map; + }; - std::array<PoolEntry, 256> m_string_pools; + std::array<PoolEntry, 256> m_string_pools; }; //---------------------------------------------------------------------- @@ -211,177 +190,147 @@ protected: // global destructor chain is run, and trying to make sure no destructors // touch ConstStrings is difficult. So we leak the pool instead. //---------------------------------------------------------------------- -static Pool & -StringPool() -{ - static std::once_flag g_pool_initialization_flag; - static Pool *g_string_pool = nullptr; - - std::call_once(g_pool_initialization_flag, [] () { - g_string_pool = new Pool(); - }); - - return *g_string_pool; -} +static Pool &StringPool() { + static std::once_flag g_pool_initialization_flag; + static Pool *g_string_pool = nullptr; -ConstString::ConstString (const char *cstr) : - m_string (StringPool().GetConstCString (cstr)) -{ -} + std::call_once(g_pool_initialization_flag, + []() { g_string_pool = new Pool(); }); -ConstString::ConstString (const char *cstr, size_t cstr_len) : - m_string (StringPool().GetConstCStringWithLength (cstr, cstr_len)) -{ + return *g_string_pool; } -ConstString::ConstString (const llvm::StringRef &s) : - m_string (StringPool().GetConstCStringWithLength (s.data(), s.size())) -{ -} +ConstString::ConstString(const char *cstr) + : m_string(StringPool().GetConstCString(cstr)) {} -bool -ConstString::operator < (const ConstString& rhs) const -{ - if (m_string == rhs.m_string) - return false; +ConstString::ConstString(const char *cstr, size_t cstr_len) + : m_string(StringPool().GetConstCStringWithLength(cstr, cstr_len)) {} - llvm::StringRef lhs_string_ref (m_string, StringPool().GetConstCStringLength (m_string)); - llvm::StringRef rhs_string_ref (rhs.m_string, StringPool().GetConstCStringLength (rhs.m_string)); +ConstString::ConstString(const llvm::StringRef &s) + : m_string(StringPool().GetConstCStringWithLength(s.data(), s.size())) {} - // If both have valid C strings, then return the comparison - if (lhs_string_ref.data() && rhs_string_ref.data()) - return lhs_string_ref < rhs_string_ref; +bool ConstString::operator<(const ConstString &rhs) const { + if (m_string == rhs.m_string) + return false; - // Else one of them was nullptr, so if LHS is nullptr then it is less than - return lhs_string_ref.data() == nullptr; + llvm::StringRef lhs_string_ref(m_string, + StringPool().GetConstCStringLength(m_string)); + llvm::StringRef rhs_string_ref( + rhs.m_string, StringPool().GetConstCStringLength(rhs.m_string)); + + // If both have valid C strings, then return the comparison + if (lhs_string_ref.data() && rhs_string_ref.data()) + return lhs_string_ref < rhs_string_ref; + + // Else one of them was nullptr, so if LHS is nullptr then it is less than + return lhs_string_ref.data() == nullptr; } -Stream& -lldb_private::operator << (Stream& s, const ConstString& str) -{ - const char *cstr = str.GetCString(); - if (cstr != nullptr) - s << cstr; +Stream &lldb_private::operator<<(Stream &s, const ConstString &str) { + const char *cstr = str.GetCString(); + if (cstr != nullptr) + s << cstr; - return s; + return s; } -size_t -ConstString::GetLength () const -{ - return StringPool().GetConstCStringLength (m_string); +size_t ConstString::GetLength() const { + return StringPool().GetConstCStringLength(m_string); } -bool -ConstString::Equals(const ConstString &lhs, const ConstString &rhs, const bool case_sensitive) -{ - if (lhs.m_string == rhs.m_string) - return true; - - // Since the pointers weren't equal, and identical ConstStrings always have identical pointers, - // the result must be false for case sensitive equality test. - if (case_sensitive) - return false; - - // perform case insensitive equality test - llvm::StringRef lhs_string_ref(lhs.m_string, StringPool().GetConstCStringLength(lhs.m_string)); - llvm::StringRef rhs_string_ref(rhs.m_string, StringPool().GetConstCStringLength(rhs.m_string)); - return lhs_string_ref.equals_lower(rhs_string_ref); +bool ConstString::Equals(const ConstString &lhs, const ConstString &rhs, + const bool case_sensitive) { + if (lhs.m_string == rhs.m_string) + return true; + + // Since the pointers weren't equal, and identical ConstStrings always have + // identical pointers, + // the result must be false for case sensitive equality test. + if (case_sensitive) + return false; + + // perform case insensitive equality test + llvm::StringRef lhs_string_ref( + lhs.m_string, StringPool().GetConstCStringLength(lhs.m_string)); + llvm::StringRef rhs_string_ref( + rhs.m_string, StringPool().GetConstCStringLength(rhs.m_string)); + return lhs_string_ref.equals_lower(rhs_string_ref); } -int -ConstString::Compare(const ConstString &lhs, const ConstString &rhs, const bool case_sensitive) -{ - // If the iterators are the same, this is the same string - const char *lhs_cstr = lhs.m_string; - const char *rhs_cstr = rhs.m_string; - if (lhs_cstr == rhs_cstr) - return 0; - if (lhs_cstr && rhs_cstr) - { - llvm::StringRef lhs_string_ref (lhs_cstr, StringPool().GetConstCStringLength (lhs_cstr)); - llvm::StringRef rhs_string_ref (rhs_cstr, StringPool().GetConstCStringLength (rhs_cstr)); - - if (case_sensitive) - { - return lhs_string_ref.compare(rhs_string_ref); - } - else - { - return lhs_string_ref.compare_lower(rhs_string_ref); - } +int ConstString::Compare(const ConstString &lhs, const ConstString &rhs, + const bool case_sensitive) { + // If the iterators are the same, this is the same string + const char *lhs_cstr = lhs.m_string; + const char *rhs_cstr = rhs.m_string; + if (lhs_cstr == rhs_cstr) + return 0; + if (lhs_cstr && rhs_cstr) { + llvm::StringRef lhs_string_ref( + lhs_cstr, StringPool().GetConstCStringLength(lhs_cstr)); + llvm::StringRef rhs_string_ref( + rhs_cstr, StringPool().GetConstCStringLength(rhs_cstr)); + + if (case_sensitive) { + return lhs_string_ref.compare(rhs_string_ref); + } else { + return lhs_string_ref.compare_lower(rhs_string_ref); } + } - if (lhs_cstr) - return +1; // LHS isn't nullptr but RHS is - else - return -1; // LHS is nullptr but RHS isn't + if (lhs_cstr) + return +1; // LHS isn't nullptr but RHS is + else + return -1; // LHS is nullptr but RHS isn't } -void -ConstString::Dump(Stream *s, const char *fail_value) const -{ - if (s != nullptr) - { - const char *cstr = AsCString (fail_value); - if (cstr != nullptr) - s->PutCString (cstr); - } +void ConstString::Dump(Stream *s, const char *fail_value) const { + if (s != nullptr) { + const char *cstr = AsCString(fail_value); + if (cstr != nullptr) + s->PutCString(cstr); + } } -void -ConstString::DumpDebug(Stream *s) const -{ - const char *cstr = GetCString (); - size_t cstr_len = GetLength(); - // Only print the parens if we have a non-nullptr string - const char *parens = cstr ? "\"" : ""; - s->Printf("%*p: ConstString, string = %s%s%s, length = %" PRIu64, - static_cast<int>(sizeof(void*) * 2), - static_cast<const void*>(this), parens, cstr, parens, - static_cast<uint64_t>(cstr_len)); +void ConstString::DumpDebug(Stream *s) const { + const char *cstr = GetCString(); + size_t cstr_len = GetLength(); + // Only print the parens if we have a non-nullptr string + const char *parens = cstr ? "\"" : ""; + s->Printf("%*p: ConstString, string = %s%s%s, length = %" PRIu64, + static_cast<int>(sizeof(void *) * 2), + static_cast<const void *>(this), parens, cstr, parens, + static_cast<uint64_t>(cstr_len)); } -void -ConstString::SetCString (const char *cstr) -{ - m_string = StringPool().GetConstCString (cstr); +void ConstString::SetCString(const char *cstr) { + m_string = StringPool().GetConstCString(cstr); } -void -ConstString::SetString (const llvm::StringRef &s) -{ - m_string = StringPool().GetConstCStringWithLength (s.data(), s.size()); +void ConstString::SetString(const llvm::StringRef &s) { + m_string = StringPool().GetConstCStringWithLength(s.data(), s.size()); } -void -ConstString::SetCStringWithMangledCounterpart (const char *demangled, const ConstString &mangled) -{ - m_string = StringPool().GetConstCStringAndSetMangledCounterPart (demangled, mangled.m_string); +void ConstString::SetCStringWithMangledCounterpart(const char *demangled, + const ConstString &mangled) { + m_string = StringPool().GetConstCStringAndSetMangledCounterPart( + demangled, mangled.m_string); } -bool -ConstString::GetMangledCounterpart (ConstString &counterpart) const -{ - counterpart.m_string = StringPool().GetMangledCounterpart(m_string); - return (bool)counterpart; +bool ConstString::GetMangledCounterpart(ConstString &counterpart) const { + counterpart.m_string = StringPool().GetMangledCounterpart(m_string); + return (bool)counterpart; } -void -ConstString::SetCStringWithLength (const char *cstr, size_t cstr_len) -{ - m_string = StringPool().GetConstCStringWithLength(cstr, cstr_len); +void ConstString::SetCStringWithLength(const char *cstr, size_t cstr_len) { + m_string = StringPool().GetConstCStringWithLength(cstr, cstr_len); } -void -ConstString::SetTrimmedCStringWithLength (const char *cstr, size_t cstr_len) -{ - m_string = StringPool().GetConstTrimmedCStringWithLength (cstr, cstr_len); +void ConstString::SetTrimmedCStringWithLength(const char *cstr, + size_t cstr_len) { + m_string = StringPool().GetConstTrimmedCStringWithLength(cstr, cstr_len); } -size_t -ConstString::StaticMemorySize() -{ - // Get the size of the static string pool - return StringPool().MemorySize(); +size_t ConstString::StaticMemorySize() { + // Get the size of the static string pool + return StringPool().MemorySize(); } diff --git a/source/Core/CxaDemangle.cpp b/source/Core/CxaDemangle.cpp deleted file mode 100644 index 62335a9175cd..000000000000 --- a/source/Core/CxaDemangle.cpp +++ /dev/null @@ -1,5014 +0,0 @@ -//---------------------------------------------------------------------- -// Inlined copy of: -// http://llvm.org/svn/llvm-project/libcxxabi/trunk/src/cxa_demangle.cpp -// revision 238263. -// -// Changes include: -// - Renamed the "__cxxabiv1" namespace to "lldb_private" -// - Stripped GCC attributes() -// - Removed extern "C" from the cxa_demangle function -// - Added "#undef _LIBCPP_EXTERN_TEMPLATE" to avoid warning -// - Implemented missing rebind, construct, destroy in malloc_alloc -// - Replaced noexcept, constexpr, alignas with their LLVM_* equivalents -// - Included win32.h for snprintf implementation for MSVC -// - Removed constexpr member initialization for MSVC -// - Changed argument to alignas() to a literal for MSVC -// - Include <cstdio> for fprintf, stderr like entities. -//---------------------------------------------------------------------- - -#if defined(_MSC_VER) -#include "lldb/Host/windows/win32.h" // snprintf -#endif -#include "llvm/Support/Compiler.h" // LLVM_{NOEXCEPT, CONSTEXPR, ALIGNAS} -#include "lldb/lldb-private.h" -#undef _LIBCPP_EXTERN_TEMPLATE // Avoid warning below - -//===-------------------------- cxa_demangle.cpp --------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is dual licensed under the MIT and the University of Illinois Open -// Source Licenses. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#define _LIBCPP_EXTERN_TEMPLATE(...) -#define _LIBCPP_NO_EXCEPTIONS - -#include <vector> -#include <algorithm> -#include <string> -#include <numeric> -#include <cstdlib> -#include <cstring> -#include <cctype> -#include <cstdio> - -namespace lldb_private -{ - -namespace -{ - -enum -{ - unknown_error = -4, - invalid_args = -3, - invalid_mangled_name, - memory_alloc_failure, - success -}; - -template <class C> - const char* parse_type(const char* first, const char* last, C& db); -template <class C> - const char* parse_encoding(const char* first, const char* last, C& db); -template <class C> - const char* parse_name(const char* first, const char* last, C& db, - bool* ends_with_template_args = 0); -template <class C> - const char* parse_expression(const char* first, const char* last, C& db); -template <class C> - const char* parse_template_args(const char* first, const char* last, C& db); -template <class C> - const char* parse_operator_name(const char* first, const char* last, C& db); -template <class C> - const char* parse_unqualified_name(const char* first, const char* last, C& db); -template <class C> - const char* parse_decltype(const char* first, const char* last, C& db); - -template <class C> -void -print_stack(const C& db) -{ - fprintf(stderr, "---------\n"); - fprintf(stderr, "names:\n"); - for (auto& s : db.names) - fprintf(stderr, "{%s#%s}\n", s.first.c_str(), s.second.c_str()); - int i = -1; - fprintf(stderr, "subs:\n"); - for (auto& v : db.subs) - { - if (i >= 0) - fprintf(stderr, "S%i_ = {", i); - else - fprintf(stderr, "S_ = {"); - for (auto& s : v) - fprintf(stderr, "{%s#%s}", s.first.c_str(), s.second.c_str()); - fprintf(stderr, "}\n"); - ++i; - } - fprintf(stderr, "template_param:\n"); - for (auto& t : db.template_param) - { - fprintf(stderr, "--\n"); - i = -1; - for (auto& v : t) - { - if (i >= 0) - fprintf(stderr, "T%i_ = {", i); - else - fprintf(stderr, "T_ = {"); - for (auto& s : v) - fprintf(stderr, "{%s#%s}", s.first.c_str(), s.second.c_str()); - fprintf(stderr, "}\n"); - ++i; - } - } - fprintf(stderr, "---------\n\n"); -} - -template <class C> -void -print_state(const char* msg, const char* first, const char* last, const C& db) -{ - fprintf(stderr, "%s: ", msg); - for (; first != last; ++first) - fprintf(stderr, "%c", *first); - fprintf(stderr, "\n"); - print_stack(db); -} - -// <number> ::= [n] <non-negative decimal integer> - -const char* -parse_number(const char* first, const char* last) -{ - if (first != last) - { - const char* t = first; - if (*t == 'n') - ++t; - if (t != last) - { - if (*t == '0') - { - first = t+1; - } - else if ('1' <= *t && *t <= '9') - { - first = t+1; - while (first != last && std::isdigit(*first)) - ++first; - } - } - } - return first; -} - -template <class Float> -struct float_data; - -template <> -struct float_data<float> -{ - static const size_t mangled_size = 8; - static const size_t max_demangled_size = 24; - static const char* spec; -}; - -const char* float_data<float>::spec = "%af"; - -template <> -struct float_data<double> -{ - static const size_t mangled_size = 16; - static const size_t max_demangled_size = 32; - static const char* spec; -}; - -const char* float_data<double>::spec = "%a"; - -template <> -struct float_data<long double> -{ -#if defined(__arm__) - static const size_t mangled_size = 16; -#else - static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms -#endif - static const size_t max_demangled_size = 40; - static const char* spec; -}; - -const char* float_data<long double>::spec = "%LaL"; - -template <class Float, class C> -const char* -parse_floating_number(const char* first, const char* last, C& db) -{ - const size_t N = float_data<Float>::mangled_size; - if (static_cast<std::size_t>(last - first) > N) - { - last = first + N; - union - { - Float value; - char buf[sizeof(Float)]; - }; - const char* t = first; - char* e = buf; - for (; t != last; ++t, ++e) - { - if (!isxdigit(*t)) - return first; - unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0') : - static_cast<unsigned>(*t - 'a' + 10); - ++t; - unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0') : - static_cast<unsigned>(*t - 'a' + 10); - *e = static_cast<char>((d1 << 4) + d0); - } - if (*t == 'E') - { -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - std::reverse(buf, e); -#endif - char num[float_data<Float>::max_demangled_size] = {0}; - int n = snprintf(num, sizeof(num), float_data<Float>::spec, value); - if (static_cast<std::size_t>(n) >= sizeof(num)) - return first; - db.names.push_back(typename C::String(num, static_cast<std::size_t>(n))); - first = t+1; - } - } - return first; -} - -// <source-name> ::= <positive length number> <identifier> - -template <class C> -const char* -parse_source_name(const char* first, const char* last, C& db) -{ - if (first != last) - { - char c = *first; - if (isdigit(c) && first+1 != last) - { - const char* t = first+1; - size_t n = static_cast<size_t>(c - '0'); - for (c = *t; isdigit(c); c = *t) - { - n = n * 10 + static_cast<size_t>(c - '0'); - if (++t == last) - return first; - } - if (static_cast<size_t>(last - t) >= n) - { - typename C::String r(t, n); - if (r.substr(0, 10) == "_GLOBAL__N") - db.names.push_back("(anonymous namespace)"); - else - db.names.push_back(std::move(r)); - first = t + n; - } - } - } - return first; -} - -// <substitution> ::= S <seq-id> _ -// ::= S_ -// <substitution> ::= Sa # ::std::allocator -// <substitution> ::= Sb # ::std::basic_string -// <substitution> ::= Ss # ::std::basic_string < char, -// ::std::char_traits<char>, -// ::std::allocator<char> > -// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> > -// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> > -// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> > - -template <class C> -const char* -parse_substitution(const char* first, const char* last, C& db) -{ - if (last - first >= 2) - { - if (*first == 'S') - { - switch (first[1]) - { - case 'a': - db.names.push_back("std::allocator"); - first += 2; - break; - case 'b': - db.names.push_back("std::basic_string"); - first += 2; - break; - case 's': - db.names.push_back("std::string"); - first += 2; - break; - case 'i': - db.names.push_back("std::istream"); - first += 2; - break; - case 'o': - db.names.push_back("std::ostream"); - first += 2; - break; - case 'd': - db.names.push_back("std::iostream"); - first += 2; - break; - case '_': - if (!db.subs.empty()) - { - for (const auto& n : db.subs.front()) - db.names.push_back(n); - first += 2; - } - break; - default: - if (std::isdigit(first[1]) || std::isupper(first[1])) - { - size_t sub = 0; - const char* t = first+1; - if (std::isdigit(*t)) - sub = static_cast<size_t>(*t - '0'); - else - sub = static_cast<size_t>(*t - 'A') + 10; - for (++t; t != last && (std::isdigit(*t) || std::isupper(*t)); ++t) - { - sub *= 36; - if (std::isdigit(*t)) - sub += static_cast<size_t>(*t - '0'); - else - sub += static_cast<size_t>(*t - 'A') + 10; - } - if (t == last || *t != '_') - return first; - ++sub; - if (sub < db.subs.size()) - { - for (const auto& n : db.subs[sub]) - db.names.push_back(n); - first = t+1; - } - } - break; - } - } - } - return first; -} - -// <builtin-type> ::= v # void -// ::= w # wchar_t -// ::= b # bool -// ::= c # char -// ::= a # signed char -// ::= h # unsigned char -// ::= s # short -// ::= t # unsigned short -// ::= i # int -// ::= j # unsigned int -// ::= l # long -// ::= m # unsigned long -// ::= x # long long, __int64 -// ::= y # unsigned long long, __int64 -// ::= n # __int128 -// ::= o # unsigned __int128 -// ::= f # float -// ::= d # double -// ::= e # long double, __float80 -// ::= g # __float128 -// ::= z # ellipsis -// ::= Dd # IEEE 754r decimal floating point (64 bits) -// ::= De # IEEE 754r decimal floating point (128 bits) -// ::= Df # IEEE 754r decimal floating point (32 bits) -// ::= Dh # IEEE 754r half-precision floating point (16 bits) -// ::= Di # char32_t -// ::= Ds # char16_t -// ::= Da # auto (in dependent new-expressions) -// ::= Dc # decltype(auto) -// ::= Dn # std::nullptr_t (i.e., decltype(nullptr)) -// ::= u <source-name> # vendor extended type - -template <class C> -const char* -parse_builtin_type(const char* first, const char* last, C& db) -{ - if (first != last) - { - switch (*first) - { - case 'v': - db.names.push_back("void"); - ++first; - break; - case 'w': - db.names.push_back("wchar_t"); - ++first; - break; - case 'b': - db.names.push_back("bool"); - ++first; - break; - case 'c': - db.names.push_back("char"); - ++first; - break; - case 'a': - db.names.push_back("signed char"); - ++first; - break; - case 'h': - db.names.push_back("unsigned char"); - ++first; - break; - case 's': - db.names.push_back("short"); - ++first; - break; - case 't': - db.names.push_back("unsigned short"); - ++first; - break; - case 'i': - db.names.push_back("int"); - ++first; - break; - case 'j': - db.names.push_back("unsigned int"); - ++first; - break; - case 'l': - db.names.push_back("long"); - ++first; - break; - case 'm': - db.names.push_back("unsigned long"); - ++first; - break; - case 'x': - db.names.push_back("long long"); - ++first; - break; - case 'y': - db.names.push_back("unsigned long long"); - ++first; - break; - case 'n': - db.names.push_back("__int128"); - ++first; - break; - case 'o': - db.names.push_back("unsigned __int128"); - ++first; - break; - case 'f': - db.names.push_back("float"); - ++first; - break; - case 'd': - db.names.push_back("double"); - ++first; - break; - case 'e': - db.names.push_back("long double"); - ++first; - break; - case 'g': - db.names.push_back("__float128"); - ++first; - break; - case 'z': - db.names.push_back("..."); - ++first; - break; - case 'u': - { - const char*t = parse_source_name(first+1, last, db); - if (t != first+1) - first = t; - } - break; - case 'D': - if (first+1 != last) - { - switch (first[1]) - { - case 'd': - db.names.push_back("decimal64"); - first += 2; - break; - case 'e': - db.names.push_back("decimal128"); - first += 2; - break; - case 'f': - db.names.push_back("decimal32"); - first += 2; - break; - case 'h': - db.names.push_back("decimal16"); - first += 2; - break; - case 'i': - db.names.push_back("char32_t"); - first += 2; - break; - case 's': - db.names.push_back("char16_t"); - first += 2; - break; - case 'a': - db.names.push_back("auto"); - first += 2; - break; - case 'c': - db.names.push_back("decltype(auto)"); - first += 2; - break; - case 'n': - db.names.push_back("std::nullptr_t"); - first += 2; - break; - } - } - break; - } - } - return first; -} - -// <CV-qualifiers> ::= [r] [V] [K] - -const char* -parse_cv_qualifiers(const char* first, const char* last, unsigned& cv) -{ - cv = 0; - if (first != last) - { - if (*first == 'r') - { - cv |= 4; - ++first; - } - if (*first == 'V') - { - cv |= 2; - ++first; - } - if (*first == 'K') - { - cv |= 1; - ++first; - } - } - return first; -} - -// <template-param> ::= T_ # first template parameter -// ::= T <parameter-2 non-negative number> _ - -template <class C> -const char* -parse_template_param(const char* first, const char* last, C& db) -{ - if (last - first >= 2) - { - if (*first == 'T') - { - if (first[1] == '_') - { - if (db.template_param.empty()) - return first; - if (!db.template_param.back().empty()) - { - for (auto& t : db.template_param.back().front()) - db.names.push_back(t); - first += 2; - } - else - { - db.names.push_back("T_"); - first += 2; - db.fix_forward_references = true; - } - } - else if (isdigit(first[1])) - { - const char* t = first+1; - size_t sub = static_cast<size_t>(*t - '0'); - for (++t; t != last && isdigit(*t); ++t) - { - sub *= 10; - sub += static_cast<size_t>(*t - '0'); - } - if (t == last || *t != '_' || db.template_param.empty()) - return first; - ++sub; - if (sub < db.template_param.back().size()) - { - for (auto& temp : db.template_param.back()[sub]) - db.names.push_back(temp); - first = t+1; - } - else - { - db.names.push_back(typename C::String(first, t+1)); - first = t+1; - db.fix_forward_references = true; - } - } - } - } - return first; -} - -// cc <type> <expression> # const_cast<type> (expression) - -template <class C> -const char* -parse_const_cast_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'c' && first[1] == 'c') - { - const char* t = parse_type(first+2, last, db); - if (t != first+2) - { - const char* t1 = parse_expression(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto expr = db.names.back().move_full(); - db.names.pop_back(); - db.names.back() = "const_cast<" + db.names.back().move_full() + ">(" + expr + ")"; - first = t1; - } - } - } - return first; -} - -// dc <type> <expression> # dynamic_cast<type> (expression) - -template <class C> -const char* -parse_dynamic_cast_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'd' && first[1] == 'c') - { - const char* t = parse_type(first+2, last, db); - if (t != first+2) - { - const char* t1 = parse_expression(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto expr = db.names.back().move_full(); - db.names.pop_back(); - db.names.back() = "dynamic_cast<" + db.names.back().move_full() + ">(" + expr + ")"; - first = t1; - } - } - } - return first; -} - -// rc <type> <expression> # reinterpret_cast<type> (expression) - -template <class C> -const char* -parse_reinterpret_cast_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'r' && first[1] == 'c') - { - const char* t = parse_type(first+2, last, db); - if (t != first+2) - { - const char* t1 = parse_expression(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto expr = db.names.back().move_full(); - db.names.pop_back(); - db.names.back() = "reinterpret_cast<" + db.names.back().move_full() + ">(" + expr + ")"; - first = t1; - } - } - } - return first; -} - -// sc <type> <expression> # static_cast<type> (expression) - -template <class C> -const char* -parse_static_cast_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 's' && first[1] == 'c') - { - const char* t = parse_type(first+2, last, db); - if (t != first+2) - { - const char* t1 = parse_expression(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto expr = db.names.back().move_full(); - db.names.pop_back(); - db.names.back() = "static_cast<" + db.names.back().move_full() + ">(" + expr + ")"; - first = t1; - } - } - } - return first; -} - -// sp <expression> # pack expansion - -template <class C> -const char* -parse_pack_expansion(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 's' && first[1] == 'p') - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2) - first = t; - } - return first; -} - -// st <type> # sizeof (a type) - -template <class C> -const char* -parse_sizeof_type_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 's' && first[1] == 't') - { - const char* t = parse_type(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back() = "sizeof (" + db.names.back().move_full() + ")"; - first = t; - } - } - return first; -} - -// sz <expr> # sizeof (a expression) - -template <class C> -const char* -parse_sizeof_expr_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 's' && first[1] == 'z') - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back() = "sizeof (" + db.names.back().move_full() + ")"; - first = t; - } - } - return first; -} - -// sZ <template-param> # size of a parameter pack - -template <class C> -const char* -parse_sizeof_param_pack_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 's' && first[1] == 'Z' && first[2] == 'T') - { - size_t k0 = db.names.size(); - const char* t = parse_template_param(first+2, last, db); - size_t k1 = db.names.size(); - if (t != first+2) - { - typename C::String tmp("sizeof...("); - size_t k = k0; - if (k != k1) - { - tmp += db.names[k].move_full(); - for (++k; k != k1; ++k) - tmp += ", " + db.names[k].move_full(); - } - tmp += ")"; - for (; k1 != k0; --k1) - db.names.pop_back(); - db.names.push_back(std::move(tmp)); - first = t; - } - } - return first; -} - -// <function-param> ::= fp <top-level CV-qualifiers> _ # L == 0, first parameter -// ::= fp <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters -// ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> _ # L > 0, first parameter -// ::= fL <L-1 non-negative number> p <top-level CV-qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters - -template <class C> -const char* -parse_function_param(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && *first == 'f') - { - if (first[1] == 'p') - { - unsigned cv; - const char* t = parse_cv_qualifiers(first+2, last, cv); - const char* t1 = parse_number(t, last); - if (t1 != last && *t1 == '_') - { - db.names.push_back("fp" + typename C::String(t, t1)); - first = t1+1; - } - } - else if (first[1] == 'L') - { - unsigned cv; - const char* t0 = parse_number(first+2, last); - if (t0 != last && *t0 == 'p') - { - ++t0; - const char* t = parse_cv_qualifiers(t0, last, cv); - const char* t1 = parse_number(t, last); - if (t1 != last && *t1 == '_') - { - db.names.push_back("fp" + typename C::String(t, t1)); - first = t1+1; - } - } - } - } - return first; -} - -// sZ <function-param> # size of a function parameter pack - -template <class C> -const char* -parse_sizeof_function_param_pack_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 's' && first[1] == 'Z' && first[2] == 'f') - { - const char* t = parse_function_param(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back() = "sizeof...(" + db.names.back().move_full() + ")"; - first = t; - } - } - return first; -} - -// te <expression> # typeid (expression) -// ti <type> # typeid (type) - -template <class C> -const char* -parse_typeid_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 't' && (first[1] == 'e' || first[1] == 'i')) - { - const char* t; - if (first[1] == 'e') - t = parse_expression(first+2, last, db); - else - t = parse_type(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back() = "typeid(" + db.names.back().move_full() + ")"; - first = t; - } - } - return first; -} - -// tw <expression> # throw expression - -template <class C> -const char* -parse_throw_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 't' && first[1] == 'w') - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back() = "throw " + db.names.back().move_full(); - first = t; - } - } - return first; -} - -// ds <expression> <expression> # expr.*expr - -template <class C> -const char* -parse_dot_star_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'd' && first[1] == 's') - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2) - { - const char* t1 = parse_expression(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto expr = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += ".*" + expr; - first = t1; - } - } - } - return first; -} - -// <simple-id> ::= <source-name> [ <template-args> ] - -template <class C> -const char* -parse_simple_id(const char* first, const char* last, C& db) -{ - if (first != last) - { - const char* t = parse_source_name(first, last, db); - if (t != first) - { - const char* t1 = parse_template_args(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto args = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += std::move(args); - } - first = t1; - } - else - first = t; - } - return first; -} - -// <unresolved-type> ::= <template-param> -// ::= <decltype> -// ::= <substitution> - -template <class C> -const char* -parse_unresolved_type(const char* first, const char* last, C& db) -{ - if (first != last) - { - const char* t = first; - switch (*first) - { - case 'T': - { - size_t k0 = db.names.size(); - t = parse_template_param(first, last, db); - size_t k1 = db.names.size(); - if (t != first && k1 == k0 + 1) - { - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t; - } - else - { - for (; k1 != k0; --k1) - db.names.pop_back(); - } - break; - } - case 'D': - t = parse_decltype(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t; - } - break; - case 'S': - t = parse_substitution(first, last, db); - if (t != first) - first = t; - else - { - if (last - first > 2 && first[1] == 't') - { - t = parse_unqualified_name(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "std::"); - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t; - } - } - } - break; - } - } - return first; -} - -// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f()) -// ::= <simple-id> # e.g., ~A<2*N> - -template <class C> -const char* -parse_destructor_name(const char* first, const char* last, C& db) -{ - if (first != last) - { - const char* t = parse_unresolved_type(first, last, db); - if (t == first) - t = parse_simple_id(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "~"); - first = t; - } - } - return first; -} - -// <base-unresolved-name> ::= <simple-id> # unresolved name -// extension ::= <operator-name> # unresolved operator-function-id -// extension ::= <operator-name> <template-args> # unresolved operator template-id -// ::= on <operator-name> # unresolved operator-function-id -// ::= on <operator-name> <template-args> # unresolved operator template-id -// ::= dn <destructor-name> # destructor or pseudo-destructor; -// # e.g. ~X or ~X<N-1> - -template <class C> -const char* -parse_base_unresolved_name(const char* first, const char* last, C& db) -{ - if (last - first >= 2) - { - if ((first[0] == 'o' || first[0] == 'd') && first[1] == 'n') - { - if (first[0] == 'o') - { - const char* t = parse_operator_name(first+2, last, db); - if (t != first+2) - { - first = parse_template_args(t, last, db); - if (first != t) - { - if (db.names.size() < 2) - return first; - auto args = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += std::move(args); - } - } - } - else - { - const char* t = parse_destructor_name(first+2, last, db); - if (t != first+2) - first = t; - } - } - else - { - const char* t = parse_simple_id(first, last, db); - if (t == first) - { - t = parse_operator_name(first, last, db); - if (t != first) - { - first = parse_template_args(t, last, db); - if (first != t) - { - if (db.names.size() < 2) - return first; - auto args = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += std::move(args); - } - } - } - else - first = t; - } - } - return first; -} - -// <unresolved-qualifier-level> ::= <simple-id> - -template <class C> -const char* -parse_unresolved_qualifier_level(const char* first, const char* last, C& db) -{ - return parse_simple_id(first, last, db); -} - -// <unresolved-name> -// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name> -// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x -// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name> -// # A::x, N::y, A<T>::z; "gs" means leading "::" -// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x -// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name> -// # T::N::x /decltype(p)::N::x -// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name> - -template <class C> -const char* -parse_unresolved_name(const char* first, const char* last, C& db) -{ - if (last - first > 2) - { - const char* t = first; - bool global = false; - if (t[0] == 'g' && t[1] == 's') - { - global = true; - t += 2; - } - const char* t2 = parse_base_unresolved_name(t, last, db); - if (t2 != t) - { - if (global) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "::"); - } - first = t2; - } - else if (last - t > 2 && t[0] == 's' && t[1] == 'r') - { - if (t[2] == 'N') - { - t += 3; - const char* t1 = parse_unresolved_type(t, last, db); - if (t1 == t || t1 == last) - return first; - t = t1; - t1 = parse_template_args(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto args = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += std::move(args); - t = t1; - if (t == last) - { - db.names.pop_back(); - return first; - } - } - while (*t != 'E') - { - t1 = parse_unresolved_qualifier_level(t, last, db); - if (t1 == t || t1 == last || db.names.size() < 2) - return first; - auto s = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += "::" + std::move(s); - t = t1; - } - ++t; - t1 = parse_base_unresolved_name(t, last, db); - if (t1 == t) - { - if (!db.names.empty()) - db.names.pop_back(); - return first; - } - if (db.names.size() < 2) - return first; - auto s = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += "::" + std::move(s); - first = t1; - } - else - { - t += 2; - const char* t1 = parse_unresolved_type(t, last, db); - if (t1 != t) - { - t = t1; - t1 = parse_template_args(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto args = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += std::move(args); - t = t1; - } - t1 = parse_base_unresolved_name(t, last, db); - if (t1 == t) - { - if (!db.names.empty()) - db.names.pop_back(); - return first; - } - if (db.names.size() < 2) - return first; - auto s = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += "::" + std::move(s); - first = t1; - } - else - { - t1 = parse_unresolved_qualifier_level(t, last, db); - if (t1 == t || t1 == last) - return first; - t = t1; - if (global) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "::"); - } - while (*t != 'E') - { - t1 = parse_unresolved_qualifier_level(t, last, db); - if (t1 == t || t1 == last || db.names.size() < 2) - return first; - auto s = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += "::" + std::move(s); - t = t1; - } - ++t; - t1 = parse_base_unresolved_name(t, last, db); - if (t1 == t) - { - if (!db.names.empty()) - db.names.pop_back(); - return first; - } - if (db.names.size() < 2) - return first; - auto s = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += "::" + std::move(s); - first = t1; - } - } - } - } - return first; -} - -// dt <expression> <unresolved-name> # expr.name - -template <class C> -const char* -parse_dot_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'd' && first[1] == 't') - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2) - { - const char* t1 = parse_unresolved_name(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto name = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += "." + name; - first = t1; - } - } - } - return first; -} - -// cl <expression>+ E # call - -template <class C> -const char* -parse_call_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 4 && first[0] == 'c' && first[1] == 'l') - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2) - { - if (t == last) - return first; - if (db.names.empty()) - return first; - db.names.back().first += db.names.back().second; - db.names.back().second = typename C::String(); - db.names.back().first.append("("); - bool first_expr = true; - while (*t != 'E') - { - const char* t1 = parse_expression(t, last, db); - if (t1 == t || t1 == last) - return first; - if (db.names.empty()) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - if (!tmp.empty()) - { - if (db.names.empty()) - return first; - if (!first_expr) - { - db.names.back().first.append(", "); - first_expr = false; - } - db.names.back().first.append(tmp); - } - t = t1; - } - ++t; - if (db.names.empty()) - return first; - db.names.back().first.append(")"); - first = t; - } - } - return first; -} - -// [gs] nw <expression>* _ <type> E # new (expr-list) type -// [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init) -// [gs] na <expression>* _ <type> E # new[] (expr-list) type -// [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init) -// <initializer> ::= pi <expression>* E # parenthesized initialization - -template <class C> -const char* -parse_new_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 4) - { - const char* t = first; - bool parsed_gs = false; - if (t[0] == 'g' && t[1] == 's') - { - t += 2; - parsed_gs = true; - } - if (t[0] == 'n' && (t[1] == 'w' || t[1] == 'a')) - { - bool is_array = t[1] == 'a'; - t += 2; - if (t == last) - return first; - bool has_expr_list = false; - bool first_expr = true; - while (*t != '_') - { - const char* t1 = parse_expression(t, last, db); - if (t1 == t || t1 == last) - return first; - has_expr_list = true; - if (!first_expr) - { - if (db.names.empty()) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - if (!tmp.empty()) - { - if (db.names.empty()) - return first; - db.names.back().first.append(", "); - db.names.back().first.append(tmp); - first_expr = false; - } - } - t = t1; - } - ++t; - const char* t1 = parse_type(t, last, db); - if (t1 == t || t1 == last) - return first; - t = t1; - bool has_init = false; - if (last - t >= 3 && t[0] == 'p' && t[1] == 'i') - { - t += 2; - has_init = true; - first_expr = true; - while (*t != 'E') - { - t1 = parse_expression(t, last, db); - if (t1 == t || t1 == last) - return first; - if (!first_expr) - { - if (db.names.empty()) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - if (!tmp.empty()) - { - if (db.names.empty()) - return first; - db.names.back().first.append(", "); - db.names.back().first.append(tmp); - first_expr = false; - } - } - t = t1; - } - } - if (*t != 'E') - return first; - typename C::String init_list; - if (has_init) - { - if (db.names.empty()) - return first; - init_list = db.names.back().move_full(); - db.names.pop_back(); - } - if (db.names.empty()) - return first; - auto type = db.names.back().move_full(); - db.names.pop_back(); - typename C::String expr_list; - if (has_expr_list) - { - if (db.names.empty()) - return first; - expr_list = db.names.back().move_full(); - db.names.pop_back(); - } - typename C::String r; - if (parsed_gs) - r = "::"; - if (is_array) - r += "[] "; - else - r += " "; - if (has_expr_list) - r += "(" + expr_list + ") "; - r += type; - if (has_init) - r += " (" + init_list + ")"; - db.names.push_back(std::move(r)); - first = t+1; - } - } - return first; -} - -// cv <type> <expression> # conversion with one argument -// cv <type> _ <expression>* E # conversion with a different number of arguments - -template <class C> -const char* -parse_conversion_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'c' && first[1] == 'v') - { - bool try_to_parse_template_args = db.try_to_parse_template_args; - db.try_to_parse_template_args = false; - const char* t = parse_type(first+2, last, db); - db.try_to_parse_template_args = try_to_parse_template_args; - if (t != first+2 && t != last) - { - if (*t != '_') - { - const char* t1 = parse_expression(t, last, db); - if (t1 == t) - return first; - t = t1; - } - else - { - ++t; - if (t == last) - return first; - if (*t == 'E') - db.names.emplace_back(); - else - { - bool first_expr = true; - while (*t != 'E') - { - const char* t1 = parse_expression(t, last, db); - if (t1 == t || t1 == last) - return first; - if (!first_expr) - { - if (db.names.empty()) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - if (!tmp.empty()) - { - if (db.names.empty()) - return first; - db.names.back().first.append(", "); - db.names.back().first.append(tmp); - first_expr = false; - } - } - t = t1; - } - } - ++t; - } - if (db.names.size() < 2) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - db.names.back() = "(" + db.names.back().move_full() + ")(" + tmp + ")"; - first = t; - } - } - return first; -} - -// pt <expression> <expression> # expr->name - -template <class C> -const char* -parse_arrow_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'p' && first[1] == 't') - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2) - { - const char* t1 = parse_expression(t, last, db); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += "->"; - db.names.back().first += tmp; - first = t1; - } - } - } - return first; -} - -// <ref-qualifier> ::= R # & ref-qualifier -// <ref-qualifier> ::= O # && ref-qualifier - -// <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E - -template <class C> -const char* -parse_function_type(const char* first, const char* last, C& db) -{ - if (first != last && *first == 'F') - { - const char* t = first+1; - if (t != last) - { - if (*t == 'Y') - { - /* extern "C" */ - if (++t == last) - return first; - } - const char* t1 = parse_type(t, last, db); - if (t1 != t) - { - t = t1; - typename C::String sig("("); - int ref_qual = 0; - while (true) - { - if (t == last) - { - db.names.pop_back(); - return first; - } - if (*t == 'E') - { - ++t; - break; - } - if (*t == 'v') - { - ++t; - continue; - } - if (*t == 'R' && t+1 != last && t[1] == 'E') - { - ref_qual = 1; - ++t; - continue; - } - if (*t == 'O' && t+1 != last && t[1] == 'E') - { - ref_qual = 2; - ++t; - continue; - } - size_t k0 = db.names.size(); - t1 = parse_type(t, last, db); - size_t k1 = db.names.size(); - if (t1 == t || t1 == last) - return first; - for (size_t k = k0; k < k1; ++k) - { - if (sig.size() > 1) - sig += ", "; - sig += db.names[k].move_full(); - } - for (size_t k = k0; k < k1; ++k) - db.names.pop_back(); - t = t1; - } - sig += ")"; - switch (ref_qual) - { - case 1: - sig += " &"; - break; - case 2: - sig += " &&"; - break; - } - if (db.names.empty()) - return first; - db.names.back().first += " "; - db.names.back().second.insert(0, sig); - first = t; - } - } - } - return first; -} - -// <pointer-to-member-type> ::= M <class type> <member type> - -template <class C> -const char* -parse_pointer_to_member_type(const char* first, const char* last, C& db) -{ - if (first != last && *first == 'M') - { - const char* t = parse_type(first+1, last, db); - if (t != first+1) - { - const char* t2 = parse_type(t, last, db); - if (t2 != t) - { - if (db.names.size() < 2) - return first; - auto func = std::move(db.names.back()); - db.names.pop_back(); - auto class_type = std::move(db.names.back()); - if (!func.second.empty() && func.second.front() == '(') - { - db.names.back().first = std::move(func.first) + "(" + class_type.move_full() + "::*"; - db.names.back().second = ")" + std::move(func.second); - } - else - { - db.names.back().first = std::move(func.first) + " " + class_type.move_full() + "::*"; - db.names.back().second = std::move(func.second); - } - first = t2; - } - } - } - return first; -} - -// <array-type> ::= A <positive dimension number> _ <element type> -// ::= A [<dimension expression>] _ <element type> - -template <class C> -const char* -parse_array_type(const char* first, const char* last, C& db) -{ - if (first != last && *first == 'A' && first+1 != last) - { - if (first[1] == '_') - { - const char* t = parse_type(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - if (db.names.back().second.substr(0, 2) == " [") - db.names.back().second.erase(0, 1); - db.names.back().second.insert(0, " []"); - first = t; - } - } - else if ('1' <= first[1] && first[1] <= '9') - { - const char* t = parse_number(first+1, last); - if (t != last && *t == '_') - { - const char* t2 = parse_type(t+1, last, db); - if (t2 != t+1) - { - if (db.names.empty()) - return first; - if (db.names.back().second.substr(0, 2) == " [") - db.names.back().second.erase(0, 1); - db.names.back().second.insert(0, " [" + typename C::String(first+1, t) + "]"); - first = t2; - } - } - } - else - { - const char* t = parse_expression(first+1, last, db); - if (t != first+1 && t != last && *t == '_') - { - const char* t2 = parse_type(++t, last, db); - if (t2 != t) - { - if (db.names.size() < 2) - return first; - auto type = std::move(db.names.back()); - db.names.pop_back(); - auto expr = std::move(db.names.back()); - db.names.back().first = std::move(type.first); - if (type.second.substr(0, 2) == " [") - type.second.erase(0, 1); - db.names.back().second = " [" + expr.move_full() + "]" + std::move(type.second); - first = t2; - } - } - } - } - return first; -} - -// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x) -// ::= DT <expression> E # decltype of an expression (C++0x) - -template <class C> -const char* -parse_decltype(const char* first, const char* last, C& db) -{ - if (last - first >= 4 && first[0] == 'D') - { - switch (first[1]) - { - case 't': - case 'T': - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2 && t != last && *t == 'E') - { - if (db.names.empty()) - return first; - db.names.back() = "decltype(" + db.names.back().move_full() + ")"; - first = t+1; - } - } - break; - } - } - return first; -} - -// extension: -// <vector-type> ::= Dv <positive dimension number> _ -// <extended element type> -// ::= Dv [<dimension expression>] _ <element type> -// <extended element type> ::= <element type> -// ::= p # AltiVec vector pixel - -template <class C> -const char* -parse_vector_type(const char* first, const char* last, C& db) -{ - if (last - first > 3 && first[0] == 'D' && first[1] == 'v') - { - if ('1' <= first[2] && first[2] <= '9') - { - const char* t = parse_number(first+2, last); - if (t == last || *t != '_') - return first; - const char* num = first + 2; - size_t sz = static_cast<size_t>(t - num); - if (++t != last) - { - if (*t != 'p') - { - const char* t1 = parse_type(t, last, db); - if (t1 != t) - { - if (db.names.empty()) - return first; - db.names.back().first += " vector[" + typename C::String(num, sz) + "]"; - first = t1; - } - } - else - { - ++t; - db.names.push_back("pixel vector[" + typename C::String(num, sz) + "]"); - first = t; - } - } - } - else - { - typename C::String num; - const char* t1 = first+2; - if (*t1 != '_') - { - const char* t = parse_expression(t1, last, db); - if (t != t1) - { - if (db.names.empty()) - return first; - num = db.names.back().move_full(); - db.names.pop_back(); - t1 = t; - } - } - if (t1 != last && *t1 == '_' && ++t1 != last) - { - const char* t = parse_type(t1, last, db); - if (t != t1) - { - if (db.names.empty()) - return first; - db.names.back().first += " vector[" + num + "]"; - first = t; - } - } - } - } - return first; -} - -// <type> ::= <builtin-type> -// ::= <function-type> -// ::= <class-enum-type> -// ::= <array-type> -// ::= <pointer-to-member-type> -// ::= <template-param> -// ::= <template-template-param> <template-args> -// ::= <decltype> -// ::= <substitution> -// ::= <CV-qualifiers> <type> -// ::= P <type> # pointer-to -// ::= R <type> # reference-to -// ::= O <type> # rvalue reference-to (C++0x) -// ::= C <type> # complex pair (C 2000) -// ::= G <type> # imaginary (C 2000) -// ::= Dp <type> # pack expansion (C++0x) -// ::= U <source-name> <type> # vendor extended type qualifier -// extension := U <objc-name> <objc-type> # objc-type<identifier> -// extension := <vector-type> # <vector-type> starts with Dv - -// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1 -// <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name> - -template <class C> -const char* -parse_type(const char* first, const char* last, C& db) -{ - if (first != last) - { - switch (*first) - { - case 'r': - case 'V': - case 'K': - { - unsigned cv = 0; - const char* t = parse_cv_qualifiers(first, last, cv); - if (t != first) - { - bool is_function = *t == 'F'; - size_t k0 = db.names.size(); - const char* t1 = parse_type(t, last, db); - size_t k1 = db.names.size(); - if (t1 != t) - { - if (is_function) - db.subs.pop_back(); - db.subs.emplace_back(db.names.get_allocator()); - for (size_t k = k0; k < k1; ++k) - { - if (is_function) - { - size_t p = db.names[k].second.size(); - if (db.names[k].second[p-2] == '&') - p -= 3; - else if (db.names[k].second.back() == '&') - p -= 2; - if (cv & 1) - { - db.names[k].second.insert(p, " const"); - p += 6; - } - if (cv & 2) - { - db.names[k].second.insert(p, " volatile"); - p += 9; - } - if (cv & 4) - db.names[k].second.insert(p, " restrict"); - } - else - { - if (cv & 1) - db.names[k].first.append(" const"); - if (cv & 2) - db.names[k].first.append(" volatile"); - if (cv & 4) - db.names[k].first.append(" restrict"); - } - db.subs.back().push_back(db.names[k]); - } - first = t1; - } - } - } - break; - default: - { - const char* t = parse_builtin_type(first, last, db); - if (t != first) - { - first = t; - } - else - { - switch (*first) - { - case 'A': - t = parse_array_type(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - first = t; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - } - break; - case 'C': - t = parse_type(first+1, last, db); - if (t != first+1) - { - if (db.names.empty()) - return first; - db.names.back().first.append(" complex"); - first = t; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - } - break; - case 'F': - t = parse_function_type(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - first = t; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - } - break; - case 'G': - t = parse_type(first+1, last, db); - if (t != first+1) - { - if (db.names.empty()) - return first; - db.names.back().first.append(" imaginary"); - first = t; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - } - break; - case 'M': - t = parse_pointer_to_member_type(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - first = t; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - } - break; - case 'O': - { - size_t k0 = db.names.size(); - t = parse_type(first+1, last, db); - size_t k1 = db.names.size(); - if (t != first+1) - { - db.subs.emplace_back(db.names.get_allocator()); - for (size_t k = k0; k < k1; ++k) - { - if (db.names[k].second.substr(0, 2) == " [") - { - db.names[k].first += " ("; - db.names[k].second.insert(0, ")"); - } - else if (!db.names[k].second.empty() && - db.names[k].second.front() == '(') - { - db.names[k].first += "("; - db.names[k].second.insert(0, ")"); - } - db.names[k].first.append("&&"); - db.subs.back().push_back(db.names[k]); - } - first = t; - } - break; - } - case 'P': - { - size_t k0 = db.names.size(); - t = parse_type(first+1, last, db); - size_t k1 = db.names.size(); - if (t != first+1) - { - db.subs.emplace_back(db.names.get_allocator()); - for (size_t k = k0; k < k1; ++k) - { - if (db.names[k].second.substr(0, 2) == " [") - { - db.names[k].first += " ("; - db.names[k].second.insert(0, ")"); - } - else if (!db.names[k].second.empty() && - db.names[k].second.front() == '(') - { - db.names[k].first += "("; - db.names[k].second.insert(0, ")"); - } - if (first[1] != 'U' || db.names[k].first.substr(0, 12) != "objc_object<") - { - db.names[k].first.append("*"); - } - else - { - db.names[k].first.replace(0, 11, "id"); - } - db.subs.back().push_back(db.names[k]); - } - first = t; - } - break; - } - case 'R': - { - size_t k0 = db.names.size(); - t = parse_type(first+1, last, db); - size_t k1 = db.names.size(); - if (t != first+1) - { - db.subs.emplace_back(db.names.get_allocator()); - for (size_t k = k0; k < k1; ++k) - { - if (db.names[k].second.substr(0, 2) == " [") - { - db.names[k].first += " ("; - db.names[k].second.insert(0, ")"); - } - else if (!db.names[k].second.empty() && - db.names[k].second.front() == '(') - { - db.names[k].first += "("; - db.names[k].second.insert(0, ")"); - } - db.names[k].first.append("&"); - db.subs.back().push_back(db.names[k]); - } - first = t; - } - break; - } - case 'T': - { - size_t k0 = db.names.size(); - t = parse_template_param(first, last, db); - size_t k1 = db.names.size(); - if (t != first) - { - db.subs.emplace_back(db.names.get_allocator()); - for (size_t k = k0; k < k1; ++k) - db.subs.back().push_back(db.names[k]); - if (db.try_to_parse_template_args && k1 == k0+1) - { - const char* t1 = parse_template_args(t, last, db); - if (t1 != t) - { - auto args = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += std::move(args); - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - t = t1; - } - } - first = t; - } - break; - } - case 'U': - if (first+1 != last) - { - t = parse_source_name(first+1, last, db); - if (t != first+1) - { - const char* t2 = parse_type(t, last, db); - if (t2 != t) - { - if (db.names.size() < 2) - return first; - auto type = db.names.back().move_full(); - db.names.pop_back(); - if (db.names.back().first.substr(0, 9) != "objcproto") - { - db.names.back() = type + " " + db.names.back().move_full(); - } - else - { - auto proto = db.names.back().move_full(); - db.names.pop_back(); - t = parse_source_name(proto.data() + 9, proto.data() + proto.size(), db); - if (t != proto.data() + 9) - { - db.names.back() = type + "<" + db.names.back().move_full() + ">"; - } - else - { - db.names.push_back(type + " " + proto); - } - } - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t2; - } - } - } - break; - case 'S': - if (first+1 != last && first[1] == 't') - { - t = parse_name(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t; - } - } - else - { - t = parse_substitution(first, last, db); - if (t != first) - { - first = t; - // Parsed a substitution. If the substitution is a - // <template-param> it might be followed by <template-args>. - t = parse_template_args(first, last, db); - if (t != first) - { - if (db.names.size() < 2) - return first; - auto template_args = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += template_args; - // Need to create substitution for <template-template-param> <template-args> - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t; - } - } - } - break; - case 'D': - if (first+1 != last) - { - switch (first[1]) - { - case 'p': - { - size_t k0 = db.names.size(); - t = parse_type(first+2, last, db); - size_t k1 = db.names.size(); - if (t != first+2) - { - db.subs.emplace_back(db.names.get_allocator()); - for (size_t k = k0; k < k1; ++k) - db.subs.back().push_back(db.names[k]); - first = t; - return first; - } - break; - } - case 't': - case 'T': - t = parse_decltype(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t; - return first; - } - break; - case 'v': - t = parse_vector_type(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t; - return first; - } - break; - } - } - LLVM_FALLTHROUGH; - default: - // must check for builtin-types before class-enum-types to avoid - // ambiguities with operator-names - t = parse_builtin_type(first, last, db); - if (t != first) - { - first = t; - } - else - { - t = parse_name(first, last, db); - if (t != first) - { - if (db.names.empty()) - return first; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - first = t; - } - } - break; - } - } - break; - } - } - } - return first; -} - -// <operator-name> -// ::= aa # && -// ::= ad # & (unary) -// ::= an # & -// ::= aN # &= -// ::= aS # = -// ::= cl # () -// ::= cm # , -// ::= co # ~ -// ::= cv <type> # (cast) -// ::= da # delete[] -// ::= de # * (unary) -// ::= dl # delete -// ::= dv # / -// ::= dV # /= -// ::= eo # ^ -// ::= eO # ^= -// ::= eq # == -// ::= ge # >= -// ::= gt # > -// ::= ix # [] -// ::= le # <= -// ::= li <source-name> # operator "" -// ::= ls # << -// ::= lS # <<= -// ::= lt # < -// ::= mi # - -// ::= mI # -= -// ::= ml # * -// ::= mL # *= -// ::= mm # -- (postfix in <expression> context) -// ::= na # new[] -// ::= ne # != -// ::= ng # - (unary) -// ::= nt # ! -// ::= nw # new -// ::= oo # || -// ::= or # | -// ::= oR # |= -// ::= pm # ->* -// ::= pl # + -// ::= pL # += -// ::= pp # ++ (postfix in <expression> context) -// ::= ps # + (unary) -// ::= pt # -> -// ::= qu # ? -// ::= rm # % -// ::= rM # %= -// ::= rs # >> -// ::= rS # >>= -// ::= v <digit> <source-name> # vendor extended operator - -template <class C> -const char* -parse_operator_name(const char* first, const char* last, C& db) -{ - if (last - first >= 2) - { - switch (first[0]) - { - case 'a': - switch (first[1]) - { - case 'a': - db.names.push_back("operator&&"); - first += 2; - break; - case 'd': - case 'n': - db.names.push_back("operator&"); - first += 2; - break; - case 'N': - db.names.push_back("operator&="); - first += 2; - break; - case 'S': - db.names.push_back("operator="); - first += 2; - break; - } - break; - case 'c': - switch (first[1]) - { - case 'l': - db.names.push_back("operator()"); - first += 2; - break; - case 'm': - db.names.push_back("operator,"); - first += 2; - break; - case 'o': - db.names.push_back("operator~"); - first += 2; - break; - case 'v': - { - bool try_to_parse_template_args = db.try_to_parse_template_args; - db.try_to_parse_template_args = false; - const char* t = parse_type(first+2, last, db); - db.try_to_parse_template_args = try_to_parse_template_args; - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "operator "); - db.parsed_ctor_dtor_cv = true; - first = t; - } - } - break; - } - break; - case 'd': - switch (first[1]) - { - case 'a': - db.names.push_back("operator delete[]"); - first += 2; - break; - case 'e': - db.names.push_back("operator*"); - first += 2; - break; - case 'l': - db.names.push_back("operator delete"); - first += 2; - break; - case 'v': - db.names.push_back("operator/"); - first += 2; - break; - case 'V': - db.names.push_back("operator/="); - first += 2; - break; - } - break; - case 'e': - switch (first[1]) - { - case 'o': - db.names.push_back("operator^"); - first += 2; - break; - case 'O': - db.names.push_back("operator^="); - first += 2; - break; - case 'q': - db.names.push_back("operator=="); - first += 2; - break; - } - break; - case 'g': - switch (first[1]) - { - case 'e': - db.names.push_back("operator>="); - first += 2; - break; - case 't': - db.names.push_back("operator>"); - first += 2; - break; - } - break; - case 'i': - if (first[1] == 'x') - { - db.names.push_back("operator[]"); - first += 2; - } - break; - case 'l': - switch (first[1]) - { - case 'e': - db.names.push_back("operator<="); - first += 2; - break; - case 'i': - { - const char* t = parse_source_name(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "operator\"\" "); - first = t; - } - } - break; - case 's': - db.names.push_back("operator<<"); - first += 2; - break; - case 'S': - db.names.push_back("operator<<="); - first += 2; - break; - case 't': - db.names.push_back("operator<"); - first += 2; - break; - } - break; - case 'm': - switch (first[1]) - { - case 'i': - db.names.push_back("operator-"); - first += 2; - break; - case 'I': - db.names.push_back("operator-="); - first += 2; - break; - case 'l': - db.names.push_back("operator*"); - first += 2; - break; - case 'L': - db.names.push_back("operator*="); - first += 2; - break; - case 'm': - db.names.push_back("operator--"); - first += 2; - break; - } - break; - case 'n': - switch (first[1]) - { - case 'a': - db.names.push_back("operator new[]"); - first += 2; - break; - case 'e': - db.names.push_back("operator!="); - first += 2; - break; - case 'g': - db.names.push_back("operator-"); - first += 2; - break; - case 't': - db.names.push_back("operator!"); - first += 2; - break; - case 'w': - db.names.push_back("operator new"); - first += 2; - break; - } - break; - case 'o': - switch (first[1]) - { - case 'o': - db.names.push_back("operator||"); - first += 2; - break; - case 'r': - db.names.push_back("operator|"); - first += 2; - break; - case 'R': - db.names.push_back("operator|="); - first += 2; - break; - } - break; - case 'p': - switch (first[1]) - { - case 'm': - db.names.push_back("operator->*"); - first += 2; - break; - case 'l': - db.names.push_back("operator+"); - first += 2; - break; - case 'L': - db.names.push_back("operator+="); - first += 2; - break; - case 'p': - db.names.push_back("operator++"); - first += 2; - break; - case 's': - db.names.push_back("operator+"); - first += 2; - break; - case 't': - db.names.push_back("operator->"); - first += 2; - break; - } - break; - case 'q': - if (first[1] == 'u') - { - db.names.push_back("operator?"); - first += 2; - } - break; - case 'r': - switch (first[1]) - { - case 'm': - db.names.push_back("operator%"); - first += 2; - break; - case 'M': - db.names.push_back("operator%="); - first += 2; - break; - case 's': - db.names.push_back("operator>>"); - first += 2; - break; - case 'S': - db.names.push_back("operator>>="); - first += 2; - break; - } - break; - case 'v': - if (std::isdigit(first[1])) - { - const char* t = parse_source_name(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "operator "); - first = t; - } - } - break; - } - } - return first; -} - -template <class C> -const char* -parse_integer_literal(const char* first, const char* last, const typename C::String& lit, C& db) -{ - const char* t = parse_number(first, last); - if (t != first && t != last && *t == 'E') - { - if (lit.size() > 3) - db.names.push_back("(" + lit + ")"); - else - db.names.emplace_back(); - if (*first == 'n') - { - db.names.back().first += '-'; - ++first; - } - db.names.back().first.append(first, t); - if (lit.size() <= 3) - db.names.back().first += lit; - first = t+1; - } - return first; -} - -// <expr-primary> ::= L <type> <value number> E # integer literal -// ::= L <type> <value float> E # floating literal -// ::= L <string type> E # string literal -// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE") -// ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000) -// ::= L <mangled-name> E # external name - -template <class C> -const char* -parse_expr_primary(const char* first, const char* last, C& db) -{ - if (last - first >= 4 && *first == 'L') - { - switch (first[1]) - { - case 'w': - { - const char* t = parse_integer_literal(first+2, last, "wchar_t", db); - if (t != first+2) - first = t; - } - break; - case 'b': - if (first[3] == 'E') - { - switch (first[2]) - { - case '0': - db.names.push_back("false"); - first += 4; - break; - case '1': - db.names.push_back("true"); - first += 4; - break; - } - } - break; - case 'c': - { - const char* t = parse_integer_literal(first+2, last, "char", db); - if (t != first+2) - first = t; - } - break; - case 'a': - { - const char* t = parse_integer_literal(first+2, last, "signed char", db); - if (t != first+2) - first = t; - } - break; - case 'h': - { - const char* t = parse_integer_literal(first+2, last, "unsigned char", db); - if (t != first+2) - first = t; - } - break; - case 's': - { - const char* t = parse_integer_literal(first+2, last, "short", db); - if (t != first+2) - first = t; - } - break; - case 't': - { - const char* t = parse_integer_literal(first+2, last, "unsigned short", db); - if (t != first+2) - first = t; - } - break; - case 'i': - { - const char* t = parse_integer_literal(first+2, last, "", db); - if (t != first+2) - first = t; - } - break; - case 'j': - { - const char* t = parse_integer_literal(first+2, last, "u", db); - if (t != first+2) - first = t; - } - break; - case 'l': - { - const char* t = parse_integer_literal(first+2, last, "l", db); - if (t != first+2) - first = t; - } - break; - case 'm': - { - const char* t = parse_integer_literal(first+2, last, "ul", db); - if (t != first+2) - first = t; - } - break; - case 'x': - { - const char* t = parse_integer_literal(first+2, last, "ll", db); - if (t != first+2) - first = t; - } - break; - case 'y': - { - const char* t = parse_integer_literal(first+2, last, "ull", db); - if (t != first+2) - first = t; - } - break; - case 'n': - { - const char* t = parse_integer_literal(first+2, last, "__int128", db); - if (t != first+2) - first = t; - } - break; - case 'o': - { - const char* t = parse_integer_literal(first+2, last, "unsigned __int128", db); - if (t != first+2) - first = t; - } - break; - case 'f': - { - const char* t = parse_floating_number<float>(first+2, last, db); - if (t != first+2) - first = t; - } - break; - case 'd': - { - const char* t = parse_floating_number<double>(first+2, last, db); - if (t != first+2) - first = t; - } - break; - case 'e': - { - const char* t = parse_floating_number<long double>(first+2, last, db); - if (t != first+2) - first = t; - } - break; - case '_': - if (first[2] == 'Z') - { - const char* t = parse_encoding(first+3, last, db); - if (t != first+3 && t != last && *t == 'E') - first = t+1; - } - break; - case 'T': - // Invalid mangled name per - // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html - break; - default: - { - // might be named type - const char* t = parse_type(first+1, last, db); - if (t != first+1 && t != last) - { - if (*t != 'E') - { - const char* n = t; - for (; n != last && isdigit(*n); ++n) - ; - if (n != t && n != last && *n == 'E') - { - if (db.names.empty()) - return first; - db.names.back() = "(" + db.names.back().move_full() + ")" + typename C::String(t, n); - first = n+1; - break; - } - } - else - { - first = t+1; - break; - } - } - } - } - } - return first; -} - -template <class String> -String -base_name(String& s) -{ - if (s.empty()) - return s; - if (s == "std::string") - { - s = "std::basic_string<char, std::char_traits<char>, std::allocator<char> >"; - return "basic_string"; - } - if (s == "std::istream") - { - s = "std::basic_istream<char, std::char_traits<char> >"; - return "basic_istream"; - } - if (s == "std::ostream") - { - s = "std::basic_ostream<char, std::char_traits<char> >"; - return "basic_ostream"; - } - if (s == "std::iostream") - { - s = "std::basic_iostream<char, std::char_traits<char> >"; - return "basic_iostream"; - } - const char* const pf = s.data(); - const char* pe = pf + s.size(); - if (pe[-1] == '>') - { - unsigned c = 1; - while (true) - { - if (--pe == pf) - return String(); - if (pe[-1] == '<') - { - if (--c == 0) - { - --pe; - break; - } - } - else if (pe[-1] == '>') - ++c; - } - } - const char* p0 = pe - 1; - for (; p0 != pf; --p0) - { - if (*p0 == ':') - { - ++p0; - break; - } - } - return String(p0, pe); -} - -// <ctor-dtor-name> ::= C1 # complete object constructor -// ::= C2 # base object constructor -// ::= C3 # complete object allocating constructor -// extension ::= C5 # ? -// ::= D0 # deleting destructor -// ::= D1 # complete object destructor -// ::= D2 # base object destructor -// extension ::= D5 # ? - -template <class C> -const char* -parse_ctor_dtor_name(const char* first, const char* last, C& db) -{ - if (last-first >= 2 && !db.names.empty()) - { - switch (first[0]) - { - case 'C': - switch (first[1]) - { - case '1': - case '2': - case '3': - case '5': - if (db.names.empty()) - return first; - db.names.push_back(base_name(db.names.back().first)); - first += 2; - db.parsed_ctor_dtor_cv = true; - break; - } - break; - case 'D': - switch (first[1]) - { - case '0': - case '1': - case '2': - case '5': - if (db.names.empty()) - return first; - db.names.push_back("~" + base_name(db.names.back().first)); - first += 2; - db.parsed_ctor_dtor_cv = true; - break; - } - break; - } - } - return first; -} - -// <unnamed-type-name> ::= Ut [ <nonnegative number> ] _ -// ::= <closure-type-name> -// -// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ -// -// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters - -template <class C> -const char* -parse_unnamed_type_name(const char* first, const char* last, C& db) -{ - if (last - first > 2 && first[0] == 'U') - { - char type = first[1]; - switch (type) - { - case 't': - { - db.names.push_back(typename C::String("'unnamed")); - const char* t0 = first+2; - if (t0 == last) - { - db.names.pop_back(); - return first; - } - if (std::isdigit(*t0)) - { - const char* t1 = t0 + 1; - while (t1 != last && std::isdigit(*t1)) - ++t1; - db.names.back().first.append(t0, t1); - t0 = t1; - } - db.names.back().first.push_back('\''); - if (t0 == last || *t0 != '_') - { - db.names.pop_back(); - return first; - } - first = t0 + 1; - } - break; - case 'l': - { - db.names.push_back(typename C::String("'lambda'(")); - const char* t0 = first+2; - if (first[2] == 'v') - { - db.names.back().first += ')'; - ++t0; - } - else - { - const char* t1 = parse_type(t0, last, db); - if (t1 == t0) - { - db.names.pop_back(); - return first; - } - if (db.names.size() < 2) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first.append(tmp); - t0 = t1; - while (true) - { - t1 = parse_type(t0, last, db); - if (t1 == t0) - break; - if (db.names.size() < 2) - return first; - tmp = db.names.back().move_full(); - db.names.pop_back(); - if (!tmp.empty()) - { - db.names.back().first.append(", "); - db.names.back().first.append(tmp); - } - t0 = t1; - } - db.names.back().first.append(")"); - } - if (t0 == last || *t0 != 'E') - { - db.names.pop_back(); - return first; - } - ++t0; - if (t0 == last) - { - db.names.pop_back(); - return first; - } - if (std::isdigit(*t0)) - { - const char* t1 = t0 + 1; - while (t1 != last && std::isdigit(*t1)) - ++t1; - db.names.back().first.insert(db.names.back().first.begin()+7, t0, t1); - t0 = t1; - } - if (t0 == last || *t0 != '_') - { - db.names.pop_back(); - return first; - } - first = t0 + 1; - } - break; - } - } - return first; -} - -// <unqualified-name> ::= <operator-name> -// ::= <ctor-dtor-name> -// ::= <source-name> -// ::= <unnamed-type-name> - -template <class C> -const char* -parse_unqualified_name(const char* first, const char* last, C& db) -{ - if (first != last) - { - const char* t; - switch (*first) - { - case 'C': - case 'D': - t = parse_ctor_dtor_name(first, last, db); - if (t != first) - first = t; - break; - case 'U': - t = parse_unnamed_type_name(first, last, db); - if (t != first) - first = t; - break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - t = parse_source_name(first, last, db); - if (t != first) - first = t; - break; - default: - t = parse_operator_name(first, last, db); - if (t != first) - first = t; - break; - }; - } - return first; -} - -// <unscoped-name> ::= <unqualified-name> -// ::= St <unqualified-name> # ::std:: -// extension ::= StL<unqualified-name> - -template <class C> -const char* -parse_unscoped_name(const char* first, const char* last, C& db) -{ - if (last - first >= 2) - { - const char* t0 = first; - bool St = false; - if (first[0] == 'S' && first[1] == 't') - { - t0 += 2; - St = true; - if (t0 != last && *t0 == 'L') - ++t0; - } - const char* t1 = parse_unqualified_name(t0, last, db); - if (t1 != t0) - { - if (St) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "std::"); - } - first = t1; - } - } - return first; -} - -// at <type> # alignof (a type) - -template <class C> -const char* -parse_alignof_type(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'a' && first[1] == 't') - { - const char* t = parse_type(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first = "alignof (" + db.names.back().move_full() + ")"; - first = t; - } - } - return first; -} - -// az <expression> # alignof (a expression) - -template <class C> -const char* -parse_alignof_expr(const char* first, const char* last, C& db) -{ - if (last - first >= 3 && first[0] == 'a' && first[1] == 'z') - { - const char* t = parse_expression(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first = "alignof (" + db.names.back().move_full() + ")"; - first = t; - } - } - return first; -} - -template <class C> -const char* -parse_noexcept_expression(const char* first, const char* last, C& db) -{ - const char* t1 = parse_expression(first, last, db); - if (t1 != first) - { - if (db.names.empty()) - return first; - db.names.back().first = "noexcept (" + db.names.back().move_full() + ")"; - first = t1; - } - return first; -} - -template <class C> -const char* -parse_prefix_expression(const char* first, const char* last, const typename C::String& op, C& db) -{ - const char* t1 = parse_expression(first, last, db); - if (t1 != first) - { - if (db.names.empty()) - return first; - db.names.back().first = op + "(" + db.names.back().move_full() + ")"; - first = t1; - } - return first; -} - -template <class C> -const char* -parse_binary_expression(const char* first, const char* last, const typename C::String& op, C& db) -{ - const char* t1 = parse_expression(first, last, db); - if (t1 != first) - { - const char* t2 = parse_expression(t1, last, db); - if (t2 != t1) - { - if (db.names.size() < 2) - return first; - auto op2 = db.names.back().move_full(); - db.names.pop_back(); - auto op1 = db.names.back().move_full(); - auto& nm = db.names.back().first; - nm.clear(); - if (op == ">") - nm += '('; - nm += "(" + op1 + ") " + op + " (" + op2 + ")"; - if (op == ">") - nm += ')'; - first = t2; - } - else - db.names.pop_back(); - } - return first; -} - -// <expression> ::= <unary operator-name> <expression> -// ::= <binary operator-name> <expression> <expression> -// ::= <ternary operator-name> <expression> <expression> <expression> -// ::= cl <expression>+ E # call -// ::= cv <type> <expression> # conversion with one argument -// ::= cv <type> _ <expression>* E # conversion with a different number of arguments -// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type -// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init) -// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type -// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init) -// ::= [gs] dl <expression> # delete expression -// ::= [gs] da <expression> # delete[] expression -// ::= pp_ <expression> # prefix ++ -// ::= mm_ <expression> # prefix -- -// ::= ti <type> # typeid (type) -// ::= te <expression> # typeid (expression) -// ::= dc <type> <expression> # dynamic_cast<type> (expression) -// ::= sc <type> <expression> # static_cast<type> (expression) -// ::= cc <type> <expression> # const_cast<type> (expression) -// ::= rc <type> <expression> # reinterpret_cast<type> (expression) -// ::= st <type> # sizeof (a type) -// ::= sz <expression> # sizeof (an expression) -// ::= at <type> # alignof (a type) -// ::= az <expression> # alignof (an expression) -// ::= nx <expression> # noexcept (expression) -// ::= <template-param> -// ::= <function-param> -// ::= dt <expression> <unresolved-name> # expr.name -// ::= pt <expression> <unresolved-name> # expr->name -// ::= ds <expression> <expression> # expr.*expr -// ::= sZ <template-param> # size of a parameter pack -// ::= sZ <function-param> # size of a function parameter pack -// ::= sp <expression> # pack expansion -// ::= tw <expression> # throw expression -// ::= tr # throw with no operand (rethrow) -// ::= <unresolved-name> # f(p), N::f(p), ::f(p), -// # freestanding dependent name (e.g., T::x), -// # objectless nonstatic member reference -// ::= <expr-primary> - -template <class C> -const char* -parse_expression(const char* first, const char* last, C& db) -{ - if (last - first >= 2) - { - const char* t = first; - bool parsed_gs = false; - if (last - first >= 4 && t[0] == 'g' && t[1] == 's') - { - t += 2; - parsed_gs = true; - } - switch (*t) - { - case 'L': - first = parse_expr_primary(first, last, db); - break; - case 'T': - first = parse_template_param(first, last, db); - break; - case 'f': - first = parse_function_param(first, last, db); - break; - case 'a': - switch (t[1]) - { - case 'a': - t = parse_binary_expression(first+2, last, "&&", db); - if (t != first+2) - first = t; - break; - case 'd': - t = parse_prefix_expression(first+2, last, "&", db); - if (t != first+2) - first = t; - break; - case 'n': - t = parse_binary_expression(first+2, last, "&", db); - if (t != first+2) - first = t; - break; - case 'N': - t = parse_binary_expression(first+2, last, "&=", db); - if (t != first+2) - first = t; - break; - case 'S': - t = parse_binary_expression(first+2, last, "=", db); - if (t != first+2) - first = t; - break; - case 't': - first = parse_alignof_type(first, last, db); - break; - case 'z': - first = parse_alignof_expr(first, last, db); - break; - } - break; - case 'c': - switch (t[1]) - { - case 'c': - first = parse_const_cast_expr(first, last, db); - break; - case 'l': - first = parse_call_expr(first, last, db); - break; - case 'm': - t = parse_binary_expression(first+2, last, ",", db); - if (t != first+2) - first = t; - break; - case 'o': - t = parse_prefix_expression(first+2, last, "~", db); - if (t != first+2) - first = t; - break; - case 'v': - first = parse_conversion_expr(first, last, db); - break; - } - break; - case 'd': - switch (t[1]) - { - case 'a': - { - const char* t1 = parse_expression(t+2, last, db); - if (t1 != t+2) - { - if (db.names.empty()) - return first; - db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) + - "delete[] " + db.names.back().move_full(); - first = t1; - } - } - break; - case 'c': - first = parse_dynamic_cast_expr(first, last, db); - break; - case 'e': - t = parse_prefix_expression(first+2, last, "*", db); - if (t != first+2) - first = t; - break; - case 'l': - { - const char* t1 = parse_expression(t+2, last, db); - if (t1 != t+2) - { - if (db.names.empty()) - return first; - db.names.back().first = (parsed_gs ? typename C::String("::") : typename C::String()) + - "delete " + db.names.back().move_full(); - first = t1; - } - } - break; - case 'n': - return parse_unresolved_name(first, last, db); - case 's': - first = parse_dot_star_expr(first, last, db); - break; - case 't': - first = parse_dot_expr(first, last, db); - break; - case 'v': - t = parse_binary_expression(first+2, last, "/", db); - if (t != first+2) - first = t; - break; - case 'V': - t = parse_binary_expression(first+2, last, "/=", db); - if (t != first+2) - first = t; - break; - } - break; - case 'e': - switch (t[1]) - { - case 'o': - t = parse_binary_expression(first+2, last, "^", db); - if (t != first+2) - first = t; - break; - case 'O': - t = parse_binary_expression(first+2, last, "^=", db); - if (t != first+2) - first = t; - break; - case 'q': - t = parse_binary_expression(first+2, last, "==", db); - if (t != first+2) - first = t; - break; - } - break; - case 'g': - switch (t[1]) - { - case 'e': - t = parse_binary_expression(first+2, last, ">=", db); - if (t != first+2) - first = t; - break; - case 't': - t = parse_binary_expression(first+2, last, ">", db); - if (t != first+2) - first = t; - break; - } - break; - case 'i': - if (t[1] == 'x') - { - const char* t1 = parse_expression(first+2, last, db); - if (t1 != first+2) - { - const char* t2 = parse_expression(t1, last, db); - if (t2 != t1) - { - if (db.names.size() < 2) - return first; - auto op2 = db.names.back().move_full(); - db.names.pop_back(); - auto op1 = db.names.back().move_full(); - db.names.back() = "(" + op1 + ")[" + op2 + "]"; - first = t2; - } - else - db.names.pop_back(); - } - } - break; - case 'l': - switch (t[1]) - { - case 'e': - t = parse_binary_expression(first+2, last, "<=", db); - if (t != first+2) - first = t; - break; - case 's': - t = parse_binary_expression(first+2, last, "<<", db); - if (t != first+2) - first = t; - break; - case 'S': - t = parse_binary_expression(first+2, last, "<<=", db); - if (t != first+2) - first = t; - break; - case 't': - t = parse_binary_expression(first+2, last, "<", db); - if (t != first+2) - first = t; - break; - } - break; - case 'm': - switch (t[1]) - { - case 'i': - t = parse_binary_expression(first+2, last, "-", db); - if (t != first+2) - first = t; - break; - case 'I': - t = parse_binary_expression(first+2, last, "-=", db); - if (t != first+2) - first = t; - break; - case 'l': - t = parse_binary_expression(first+2, last, "*", db); - if (t != first+2) - first = t; - break; - case 'L': - t = parse_binary_expression(first+2, last, "*=", db); - if (t != first+2) - first = t; - break; - case 'm': - if (first+2 != last && first[2] == '_') - { - t = parse_prefix_expression(first+3, last, "--", db); - if (t != first+3) - first = t; - } - else - { - const char* t1 = parse_expression(first+2, last, db); - if (t1 != first+2) - { - if (db.names.empty()) - return first; - db.names.back() = "(" + db.names.back().move_full() + ")--"; - first = t1; - } - } - break; - } - break; - case 'n': - switch (t[1]) - { - case 'a': - case 'w': - first = parse_new_expr(first, last, db); - break; - case 'e': - t = parse_binary_expression(first+2, last, "!=", db); - if (t != first+2) - first = t; - break; - case 'g': - t = parse_prefix_expression(first+2, last, "-", db); - if (t != first+2) - first = t; - break; - case 't': - t = parse_prefix_expression(first+2, last, "!", db); - if (t != first+2) - first = t; - break; - case 'x': - t = parse_noexcept_expression(first+2, last, db); - if (t != first+2) - first = t; - break; - } - break; - case 'o': - switch (t[1]) - { - case 'n': - return parse_unresolved_name(first, last, db); - case 'o': - t = parse_binary_expression(first+2, last, "||", db); - if (t != first+2) - first = t; - break; - case 'r': - t = parse_binary_expression(first+2, last, "|", db); - if (t != first+2) - first = t; - break; - case 'R': - t = parse_binary_expression(first+2, last, "|=", db); - if (t != first+2) - first = t; - break; - } - break; - case 'p': - switch (t[1]) - { - case 'm': - t = parse_binary_expression(first+2, last, "->*", db); - if (t != first+2) - first = t; - break; - case 'l': - t = parse_binary_expression(first+2, last, "+", db); - if (t != first+2) - first = t; - break; - case 'L': - t = parse_binary_expression(first+2, last, "+=", db); - if (t != first+2) - first = t; - break; - case 'p': - if (first+2 != last && first[2] == '_') - { - t = parse_prefix_expression(first+3, last, "++", db); - if (t != first+3) - first = t; - } - else - { - const char* t1 = parse_expression(first+2, last, db); - if (t1 != first+2) - { - if (db.names.empty()) - return first; - db.names.back() = "(" + db.names.back().move_full() + ")++"; - first = t1; - } - } - break; - case 's': - t = parse_prefix_expression(first+2, last, "+", db); - if (t != first+2) - first = t; - break; - case 't': - first = parse_arrow_expr(first, last, db); - break; - } - break; - case 'q': - if (t[1] == 'u') - { - const char* t1 = parse_expression(first+2, last, db); - if (t1 != first+2) - { - const char* t2 = parse_expression(t1, last, db); - if (t2 != t1) - { - const char* t3 = parse_expression(t2, last, db); - if (t3 != t2) - { - if (db.names.size() < 3) - return first; - auto op3 = db.names.back().move_full(); - db.names.pop_back(); - auto op2 = db.names.back().move_full(); - db.names.pop_back(); - auto op1 = db.names.back().move_full(); - db.names.back() = "(" + op1 + ") ? (" + op2 + ") : (" + op3 + ")"; - first = t3; - } - else - { - db.names.pop_back(); - db.names.pop_back(); - } - } - else - db.names.pop_back(); - } - } - break; - case 'r': - switch (t[1]) - { - case 'c': - first = parse_reinterpret_cast_expr(first, last, db); - break; - case 'm': - t = parse_binary_expression(first+2, last, "%", db); - if (t != first+2) - first = t; - break; - case 'M': - t = parse_binary_expression(first+2, last, "%=", db); - if (t != first+2) - first = t; - break; - case 's': - t = parse_binary_expression(first+2, last, ">>", db); - if (t != first+2) - first = t; - break; - case 'S': - t = parse_binary_expression(first+2, last, ">>=", db); - if (t != first+2) - first = t; - break; - } - break; - case 's': - switch (t[1]) - { - case 'c': - first = parse_static_cast_expr(first, last, db); - break; - case 'p': - first = parse_pack_expansion(first, last, db); - break; - case 'r': - return parse_unresolved_name(first, last, db); - case 't': - first = parse_sizeof_type_expr(first, last, db); - break; - case 'z': - first = parse_sizeof_expr_expr(first, last, db); - break; - case 'Z': - if (last - t >= 3) - { - switch (t[2]) - { - case 'T': - first = parse_sizeof_param_pack_expr(first, last, db); - break; - case 'f': - first = parse_sizeof_function_param_pack_expr(first, last, db); - break; - } - } - break; - } - break; - case 't': - switch (t[1]) - { - case 'e': - case 'i': - first = parse_typeid_expr(first, last, db); - break; - case 'r': - db.names.push_back("throw"); - first += 2; - break; - case 'w': - first = parse_throw_expr(first, last, db); - break; - } - break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return parse_unresolved_name(first, last, db); - } - } - return first; -} - -// <template-arg> ::= <type> # type or template -// ::= X <expression> E # expression -// ::= <expr-primary> # simple expressions -// ::= J <template-arg>* E # argument pack -// ::= LZ <encoding> E # extension - -template <class C> -const char* -parse_template_arg(const char* first, const char* last, C& db) -{ - if (first != last) - { - const char* t; - switch (*first) - { - case 'X': - t = parse_expression(first+1, last, db); - if (t != first+1) - { - if (t != last && *t == 'E') - first = t+1; - } - break; - case 'J': - t = first+1; - if (t == last) - return first; - while (*t != 'E') - { - const char* t1 = parse_template_arg(t, last, db); - if (t1 == t) - return first; - t = t1; - } - first = t+1; - break; - case 'L': - // <expr-primary> or LZ <encoding> E - if (first+1 != last && first[1] == 'Z') - { - t = parse_encoding(first+2, last, db); - if (t != first+2 && t != last && *t == 'E') - first = t+1; - } - else - first = parse_expr_primary(first, last, db); - break; - default: - // <type> - first = parse_type(first, last, db); - break; - } - } - return first; -} - -// <template-args> ::= I <template-arg>* E -// extension, the abi says <template-arg>+ - -template <class C> -const char* -parse_template_args(const char* first, const char* last, C& db) -{ - if (last - first >= 2 && *first == 'I') - { - if (db.tag_templates) - db.template_param.back().clear(); - const char* t = first+1; - typename C::String args("<"); - while (*t != 'E') - { - if (db.tag_templates) - db.template_param.emplace_back(db.names.get_allocator()); - size_t k0 = db.names.size(); - const char* t1 = parse_template_arg(t, last, db); - size_t k1 = db.names.size(); - if (db.tag_templates) - db.template_param.pop_back(); - if (t1 == t || t1 == last) - return first; - if (db.tag_templates) - { - db.template_param.back().emplace_back(db.names.get_allocator()); - for (size_t k = k0; k < k1; ++k) - db.template_param.back().back().push_back(db.names[k]); - } - for (size_t k = k0; k < k1; ++k) - { - if (args.size() > 1) - args += ", "; - args += db.names[k].move_full(); - } - for (; k1 != k0; --k1) - db.names.pop_back(); - t = t1; - } - first = t + 1; - if (args.back() != '>') - args += ">"; - else - args += " >"; - db.names.push_back(std::move(args)); - - } - return first; -} - -// <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E -// ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E -// -// <prefix> ::= <prefix> <unqualified-name> -// ::= <template-prefix> <template-args> -// ::= <template-param> -// ::= <decltype> -// ::= # empty -// ::= <substitution> -// ::= <prefix> <data-member-prefix> -// extension ::= L -// -// <template-prefix> ::= <prefix> <template unqualified-name> -// ::= <template-param> -// ::= <substitution> - -template <class C> -const char* -parse_nested_name(const char* first, const char* last, C& db, - bool* ends_with_template_args) -{ - if (first != last && *first == 'N') - { - unsigned cv; - const char* t0 = parse_cv_qualifiers(first+1, last, cv); - if (t0 == last) - return first; - db.ref = 0; - if (*t0 == 'R') - { - db.ref = 1; - ++t0; - } - else if (*t0 == 'O') - { - db.ref = 2; - ++t0; - } - db.names.emplace_back(); - if (last - t0 >= 2 && t0[0] == 'S' && t0[1] == 't') - { - t0 += 2; - db.names.back().first = "std"; - } - if (t0 == last) - { - db.names.pop_back(); - return first; - } - bool pop_subs = false; - bool component_ends_with_template_args = false; - while (*t0 != 'E') - { - component_ends_with_template_args = false; - const char* t1; - switch (*t0) - { - case 'S': - if (t0 + 1 != last && t0[1] == 't') - goto do_parse_unqualified_name; - t1 = parse_substitution(t0, last, db); - if (t1 != t0 && t1 != last) - { - auto name = db.names.back().move_full(); - db.names.pop_back(); - if (!db.names.back().first.empty()) - { - db.names.back().first += "::" + name; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - } - else - db.names.back().first = name; - pop_subs = true; - t0 = t1; - } - else - return first; - break; - case 'T': - t1 = parse_template_param(t0, last, db); - if (t1 != t0 && t1 != last) - { - auto name = db.names.back().move_full(); - db.names.pop_back(); - if (!db.names.back().first.empty()) - db.names.back().first += "::" + name; - else - db.names.back().first = name; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - pop_subs = true; - t0 = t1; - } - else - return first; - break; - case 'D': - if (t0 + 1 != last && t0[1] != 't' && t0[1] != 'T') - goto do_parse_unqualified_name; - t1 = parse_decltype(t0, last, db); - if (t1 != t0 && t1 != last) - { - auto name = db.names.back().move_full(); - db.names.pop_back(); - if (!db.names.back().first.empty()) - db.names.back().first += "::" + name; - else - db.names.back().first = name; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - pop_subs = true; - t0 = t1; - } - else - return first; - break; - case 'I': - t1 = parse_template_args(t0, last, db); - if (t1 != t0 && t1 != last) - { - auto name = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += name; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - t0 = t1; - component_ends_with_template_args = true; - } - else - return first; - break; - case 'L': - if (++t0 == last) - return first; - break; - default: - do_parse_unqualified_name: - t1 = parse_unqualified_name(t0, last, db); - if (t1 != t0 && t1 != last) - { - auto name = db.names.back().move_full(); - db.names.pop_back(); - if (!db.names.back().first.empty()) - db.names.back().first += "::" + name; - else - db.names.back().first = name; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - pop_subs = true; - t0 = t1; - } - else - return first; - } - } - first = t0 + 1; - db.cv = cv; - if (pop_subs && !db.subs.empty()) - db.subs.pop_back(); - if (ends_with_template_args) - *ends_with_template_args = component_ends_with_template_args; - } - return first; -} - -// <discriminator> := _ <non-negative number> # when number < 10 -// := __ <non-negative number> _ # when number >= 10 -// extension := decimal-digit+ - -const char* -parse_discriminator(const char* first, const char* last) -{ - // parse but ignore discriminator - if (first != last) - { - if (*first == '_') - { - const char* t1 = first+1; - if (t1 != last) - { - if (std::isdigit(*t1)) - first = t1+1; - else if (*t1 == '_') - { - for (++t1; t1 != last && std::isdigit(*t1); ++t1) - ; - if (t1 != last && *t1 == '_') - first = t1 + 1; - } - } - } - else if (std::isdigit(*first)) - { - const char* t1 = first+1; - for (; t1 != last && std::isdigit(*t1); ++t1) - ; - first = t1; - } - } - return first; -} - -// <local-name> := Z <function encoding> E <entity name> [<discriminator>] -// := Z <function encoding> E s [<discriminator>] -// := Z <function encoding> Ed [ <parameter number> ] _ <entity name> - -template <class C> -const char* -parse_local_name(const char* first, const char* last, C& db, - bool* ends_with_template_args) -{ - if (first != last && *first == 'Z') - { - const char* t = parse_encoding(first+1, last, db); - if (t != first+1 && t != last && *t == 'E' && ++t != last) - { - switch (*t) - { - case 's': - first = parse_discriminator(t+1, last); - if (db.names.empty()) - return first; - db.names.back().first.append("::string literal"); - break; - case 'd': - if (++t != last) - { - const char* t1 = parse_number(t, last); - if (t1 != last && *t1 == '_') - { - t = t1 + 1; - t1 = parse_name(t, last, db, - ends_with_template_args); - if (t1 != t) - { - if (db.names.size() < 2) - return first; - auto name = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first.append("::"); - db.names.back().first.append(name); - first = t1; - } - else - db.names.pop_back(); - } - } - break; - default: - { - const char* t1 = parse_name(t, last, db, - ends_with_template_args); - if (t1 != t) - { - // parse but ignore discriminator - first = parse_discriminator(t1, last); - if (db.names.size() < 2) - return first; - auto name = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first.append("::"); - db.names.back().first.append(name); - } - else - db.names.pop_back(); - } - break; - } - } - } - return first; -} - -// <name> ::= <nested-name> // N -// ::= <local-name> # See Scope Encoding below // Z -// ::= <unscoped-template-name> <template-args> -// ::= <unscoped-name> - -// <unscoped-template-name> ::= <unscoped-name> -// ::= <substitution> - -template <class C> -const char* -parse_name(const char* first, const char* last, C& db, - bool* ends_with_template_args) -{ - if (last - first >= 2) - { - const char* t0 = first; - // extension: ignore L here - if (*t0 == 'L') - ++t0; - switch (*t0) - { - case 'N': - { - const char* t1 = parse_nested_name(t0, last, db, - ends_with_template_args); - if (t1 != t0) - first = t1; - break; - } - case 'Z': - { - const char* t1 = parse_local_name(t0, last, db, - ends_with_template_args); - if (t1 != t0) - first = t1; - break; - } - default: - { - const char* t1 = parse_unscoped_name(t0, last, db); - if (t1 != t0) - { - if (t1 != last && *t1 == 'I') // <unscoped-template-name> <template-args> - { - if (db.names.empty()) - return first; - db.subs.push_back(typename C::sub_type(1, db.names.back(), db.names.get_allocator())); - t0 = t1; - t1 = parse_template_args(t0, last, db); - if (t1 != t0) - { - if (db.names.size() < 2) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += tmp; - first = t1; - if (ends_with_template_args) - *ends_with_template_args = true; - } - } - else // <unscoped-name> - first = t1; - } - else - { // try <substitution> <template-args> - t1 = parse_substitution(t0, last, db); - if (t1 != t0 && t1 != last && *t1 == 'I') - { - t0 = t1; - t1 = parse_template_args(t0, last, db); - if (t1 != t0) - { - if (db.names.size() < 2) - return first; - auto tmp = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first += tmp; - first = t1; - if (ends_with_template_args) - *ends_with_template_args = true; - } - } - } - break; - } - } - } - return first; -} - -// <call-offset> ::= h <nv-offset> _ -// ::= v <v-offset> _ -// -// <nv-offset> ::= <offset number> -// # non-virtual base override -// -// <v-offset> ::= <offset number> _ <virtual offset number> -// # virtual base override, with vcall offset - -const char* -parse_call_offset(const char* first, const char* last) -{ - if (first != last) - { - switch (*first) - { - case 'h': - { - const char* t = parse_number(first + 1, last); - if (t != first + 1 && t != last && *t == '_') - first = t + 1; - } - break; - case 'v': - { - const char* t = parse_number(first + 1, last); - if (t != first + 1 && t != last && *t == '_') - { - const char* t2 = parse_number(++t, last); - if (t2 != t && t2 != last && *t2 == '_') - first = t2 + 1; - } - } - break; - } - } - return first; -} - -// <special-name> ::= TV <type> # virtual table -// ::= TT <type> # VTT structure (construction vtable index) -// ::= TI <type> # typeinfo structure -// ::= TS <type> # typeinfo name (null-terminated byte string) -// ::= Tc <call-offset> <call-offset> <base encoding> -// # base is the nominal target function of thunk -// # first call-offset is 'this' adjustment -// # second call-offset is result adjustment -// ::= T <call-offset> <base encoding> -// # base is the nominal target function of thunk -// ::= GV <object name> # Guard variable for one-time initialization -// # No <type> -// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first -// extension ::= GR <object name> # reference temporary for object - -template <class C> -const char* -parse_special_name(const char* first, const char* last, C& db) -{ - if (last - first > 2) - { - const char* t; - switch (*first) - { - case 'T': - switch (first[1]) - { - case 'V': - // TV <type> # virtual table - t = parse_type(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "vtable for "); - first = t; - } - break; - case 'T': - // TT <type> # VTT structure (construction vtable index) - t = parse_type(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "VTT for "); - first = t; - } - break; - case 'I': - // TI <type> # typeinfo structure - t = parse_type(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "typeinfo for "); - first = t; - } - break; - case 'S': - // TS <type> # typeinfo name (null-terminated byte string) - t = parse_type(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "typeinfo name for "); - first = t; - } - break; - case 'c': - // Tc <call-offset> <call-offset> <base encoding> - { - const char* t0 = parse_call_offset(first+2, last); - if (t0 == first+2) - break; - const char* t1 = parse_call_offset(t0, last); - if (t1 == t0) - break; - t = parse_encoding(t1, last, db); - if (t != t1) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "covariant return thunk to "); - first = t; - } - } - break; - case 'C': - // extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first - t = parse_type(first+2, last, db); - if (t != first+2) - { - const char* t0 = parse_number(t, last); - if (t0 != t && t0 != last && *t0 == '_') - { - const char* t1 = parse_type(++t0, last, db); - if (t1 != t0) - { - if (db.names.size() < 2) - return first; - auto left = db.names.back().move_full(); - db.names.pop_back(); - db.names.back().first = "construction vtable for " + - std::move(left) + "-in-" + - db.names.back().move_full(); - first = t1; - } - } - } - break; - default: - // T <call-offset> <base encoding> - { - const char* t0 = parse_call_offset(first+1, last); - if (t0 == first+1) - break; - t = parse_encoding(t0, last, db); - if (t != t0) - { - if (db.names.empty()) - return first; - if (first[2] == 'v') - { - db.names.back().first.insert(0, "virtual thunk to "); - first = t; - } - else - { - db.names.back().first.insert(0, "non-virtual thunk to "); - first = t; - } - } - } - break; - } - break; - case 'G': - switch (first[1]) - { - case 'V': - // GV <object name> # Guard variable for one-time initialization - t = parse_name(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "guard variable for "); - first = t; - } - break; - case 'R': - // extension ::= GR <object name> # reference temporary for object - t = parse_name(first+2, last, db); - if (t != first+2) - { - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "reference temporary for "); - first = t; - } - break; - } - break; - } - } - return first; -} - -template <class T> -class save_value -{ - T& restore_; - T original_value_; -public: - save_value(T& restore) - : restore_(restore), - original_value_(restore) - {} - - ~save_value() - { - restore_ = std::move(original_value_); - } - - save_value(const save_value&) = delete; - save_value& operator=(const save_value&) = delete; -}; - -// <encoding> ::= <function name> <bare-function-type> -// ::= <data name> -// ::= <special-name> - -template <class C> -const char* -parse_encoding(const char* first, const char* last, C& db) -{ - if (first != last) - { - save_value<decltype(db.encoding_depth)> su(db.encoding_depth); - ++db.encoding_depth; - save_value<decltype(db.tag_templates)> sb(db.tag_templates); - if (db.encoding_depth > 1) - db.tag_templates = true; - switch (*first) - { - case 'G': - case 'T': - first = parse_special_name(first, last, db); - break; - default: - { - bool ends_with_template_args = false; - const char* t = parse_name(first, last, db, - &ends_with_template_args); - unsigned cv = db.cv; - unsigned ref = db.ref; - if (t != first) - { - if (t != last && *t != 'E' && *t != '.') - { - save_value<bool> sb2(db.tag_templates); - db.tag_templates = false; - const char* t2; - typename C::String ret2; - if (db.names.empty()) - return first; - const typename C::String& nm = db.names.back().first; - if (nm.empty()) - return first; - if (!db.parsed_ctor_dtor_cv && ends_with_template_args) - { - t2 = parse_type(t, last, db); - if (t2 == t) - return first; - if (db.names.size() < 2) - return first; - auto ret1 = std::move(db.names.back().first); - ret2 = std::move(db.names.back().second); - if (ret2.empty()) - ret1 += ' '; - db.names.pop_back(); - db.names.back().first.insert(0, ret1); - t = t2; - } - db.names.back().first += '('; - if (t != last && *t == 'v') - { - ++t; - } - else - { - bool first_arg = true; - while (true) - { - size_t k0 = db.names.size(); - t2 = parse_type(t, last, db); - size_t k1 = db.names.size(); - if (t2 == t) - break; - if (k1 > k0) - { - typename C::String tmp; - for (size_t k = k0; k < k1; ++k) - { - if (!tmp.empty()) - tmp += ", "; - tmp += db.names[k].move_full(); - } - for (size_t k = k0; k < k1; ++k) - db.names.pop_back(); - if (!tmp.empty()) - { - if (db.names.empty()) - return first; - if (!first_arg) - db.names.back().first += ", "; - else - first_arg = false; - db.names.back().first += tmp; - } - } - t = t2; - } - } - if (db.names.empty()) - return first; - db.names.back().first += ')'; - if (cv & 1) - db.names.back().first.append(" const"); - if (cv & 2) - db.names.back().first.append(" volatile"); - if (cv & 4) - db.names.back().first.append(" restrict"); - if (ref == 1) - db.names.back().first.append(" &"); - else if (ref == 2) - db.names.back().first.append(" &&"); - db.names.back().first += ret2; - first = t; - } - else - first = t; - } - break; - } - } - } - return first; -} - -// _block_invoke -// _block_invoke<decimal-digit>+ -// _block_invoke_<decimal-digit>+ - -template <class C> -const char* -parse_block_invoke(const char* first, const char* last, C& db) -{ - if (last - first >= 13) - { - const char test[] = "_block_invoke"; - const char* t = first; - for (int i = 0; i < 13; ++i, ++t) - { - if (*t != test[i]) - return first; - } - if (t != last) - { - if (*t == '_') - { - // must have at least 1 decimal digit - if (++t == last || !std::isdigit(*t)) - return first; - ++t; - } - // parse zero or more digits - while (t != last && isdigit(*t)) - ++t; - } - if (db.names.empty()) - return first; - db.names.back().first.insert(0, "invocation function for block in "); - first = t; - } - return first; -} - -// extension -// <dot-suffix> := .<anything and everything> - -template <class C> -const char* -parse_dot_suffix(const char* first, const char* last, C& db) -{ - if (first != last && *first == '.') - { - if (db.names.empty()) - return first; - db.names.back().first += " (" + typename C::String(first, last) + ")"; - first = last; - } - return first; -} - -// <block-involcaton-function> ___Z<encoding>_block_invoke -// <block-involcaton-function> ___Z<encoding>_block_invoke<decimal-digit>+ -// <block-involcaton-function> ___Z<encoding>_block_invoke_<decimal-digit>+ -// <mangled-name> ::= _Z<encoding> -// ::= <type> - -template <class C> -void -demangle(const char* first, const char* last, C& db, int& status) -{ - if (first >= last) - { - status = invalid_mangled_name; - return; - } - if (*first == '_') - { - if (last - first >= 4) - { - if (first[1] == 'Z') - { - const char* t = parse_encoding(first+2, last, db); - if (t != first+2 && t != last && *t == '.') - t = parse_dot_suffix(t, last, db); - if (t != last) - status = invalid_mangled_name; - } - else if (first[1] == '_' && first[2] == '_' && first[3] == 'Z') - { - const char* t = parse_encoding(first+4, last, db); - if (t != first+4 && t != last) - { - const char* t1 = parse_block_invoke(t, last, db); - if (t1 != last) - status = invalid_mangled_name; - } - else - status = invalid_mangled_name; - } - else - status = invalid_mangled_name; - } - else - status = invalid_mangled_name; - } - else - { - const char* t = parse_type(first, last, db); - if (t != last) - status = invalid_mangled_name; - } - if (status == success && db.names.empty()) - status = invalid_mangled_name; -} - -template <std::size_t N> -class arena -{ - static const std::size_t alignment = 16; - LLVM_ALIGNAS(16) char buf_[N]; - char* ptr_; - - std::size_t - align_up(std::size_t n) LLVM_NOEXCEPT - {return (n + (alignment-1)) & ~(alignment-1);} - - bool - pointer_in_buffer(char* p) LLVM_NOEXCEPT - {return buf_ <= p && p <= buf_ + N;} - -public: - arena() LLVM_NOEXCEPT : ptr_(buf_) {} - ~arena() {ptr_ = nullptr;} - arena(const arena&) = delete; - arena& operator=(const arena&) = delete; - - char* allocate(std::size_t n); - void deallocate(char* p, std::size_t n) LLVM_NOEXCEPT; - - static LLVM_CONSTEXPR std::size_t size() {return N;} - std::size_t used() const {return static_cast<std::size_t>(ptr_ - buf_);} - void reset() {ptr_ = buf_;} -}; - -template <std::size_t N> -char* -arena<N>::allocate(std::size_t n) -{ - n = align_up(n); - if (static_cast<std::size_t>(buf_ + N - ptr_) >= n) - { - char* r = ptr_; - ptr_ += n; - return r; - } - return static_cast<char*>(std::malloc(n)); -} - -template <std::size_t N> -void -arena<N>::deallocate(char* p, std::size_t n) LLVM_NOEXCEPT -{ - if (pointer_in_buffer(p)) - { - n = align_up(n); - if (p + n == ptr_) - ptr_ = p; - } - else - std::free(p); -} - -template <class T, std::size_t N> -class short_alloc -{ - arena<N>& a_; -public: - typedef T value_type; - -public: - template <class _Up> struct rebind {typedef short_alloc<_Up, N> other;}; - - short_alloc(arena<N>& a) LLVM_NOEXCEPT : a_(a) {} - template <class U> - short_alloc(const short_alloc<U, N>& a) LLVM_NOEXCEPT - : a_(a.a_) {} - short_alloc(const short_alloc&) = default; - short_alloc& operator=(const short_alloc&) = delete; - - T* allocate(std::size_t n) - { - return reinterpret_cast<T*>(a_.allocate(n*sizeof(T))); - } - void deallocate(T* p, std::size_t n) LLVM_NOEXCEPT - { - a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T)); - } - - template <class T1, std::size_t N1, class U, std::size_t M> - friend - bool - operator==(const short_alloc<T1, N1>& x, const short_alloc<U, M>& y) LLVM_NOEXCEPT; - - template <class U, std::size_t M> friend class short_alloc; -}; - -template <class T, std::size_t N, class U, std::size_t M> -inline -bool -operator==(const short_alloc<T, N>& x, const short_alloc<U, M>& y) LLVM_NOEXCEPT -{ - return N == M && &x.a_ == &y.a_; -} - -template <class T, std::size_t N, class U, std::size_t M> -inline -bool -operator!=(const short_alloc<T, N>& x, const short_alloc<U, M>& y) LLVM_NOEXCEPT -{ - return !(x == y); -} - -template <class T> -class malloc_alloc -{ -public: - typedef T value_type; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef T* pointer; - typedef const T* const_pointer; - typedef T& reference; - typedef const T& const_reference; - - malloc_alloc() = default; - template <class U> malloc_alloc(const malloc_alloc<U>&) LLVM_NOEXCEPT {} - - T* allocate(std::size_t n) - { - return static_cast<T*>(std::malloc(n*sizeof(T))); - } - void deallocate(T* p, std::size_t) LLVM_NOEXCEPT - { - std::free(p); - } - template<class Other> - struct rebind - { - typedef malloc_alloc<Other> other; - }; - void construct(T *p) - { - ::new (p) T(); - } - void construct(T *p, const T& t) - { - ::new (p) T(t); - } - void destroy(T *p) - { - p->~T(); - } -}; - -template <class T, class U> -inline -bool -operator==(const malloc_alloc<T>&, const malloc_alloc<U>&) LLVM_NOEXCEPT -{ - return true; -} - -template <class T, class U> -inline -bool -operator!=(const malloc_alloc<T>& x, const malloc_alloc<U>& y) LLVM_NOEXCEPT -{ - return !(x == y); -} - -const size_t bs = 4 * 1024; -template <class T> using Alloc = short_alloc<T, bs>; -template <class T> using Vector = std::vector<T, Alloc<T>>; - -template <class StrT> -struct string_pair -{ - StrT first; - StrT second; - - string_pair() = default; - string_pair(StrT f) : first(std::move(f)) {} - string_pair(StrT f, StrT s) - : first(std::move(f)), second(std::move(s)) {} - template <size_t N> - string_pair(const char (&s)[N]) : first(s, N-1) {} - - size_t size() const {return first.size() + second.size();} - StrT full() const {return first + second;} - StrT move_full() {return std::move(first) + std::move(second);} -}; - -struct Db -{ - typedef std::basic_string<char, std::char_traits<char>, - malloc_alloc<char>> String; - typedef Vector<string_pair<String>> sub_type; - typedef Vector<sub_type> template_param_type; - sub_type names; - template_param_type subs; - Vector<template_param_type> template_param; - unsigned cv; - unsigned ref; - unsigned encoding_depth; - bool parsed_ctor_dtor_cv; - bool tag_templates; - bool fix_forward_references; - bool try_to_parse_template_args; - - template <size_t N> - Db(arena<N>& ar) : - names(ar), - subs(0, names, ar), - template_param(0, subs, ar) - {} -}; - -} // unnamed namespace - -char* -__cxa_demangle(const char* mangled_name, char* buf, size_t* n, int* status) -{ - if (mangled_name == nullptr || (buf != nullptr && n == nullptr)) - { - if (status) - *status = invalid_args; - return nullptr; - } - size_t internal_size = buf != nullptr ? *n : 0; - arena<bs> a; - Db db(a); - db.cv = 0; - db.ref = 0; - db.encoding_depth = 0; - db.parsed_ctor_dtor_cv = false; - db.tag_templates = true; - db.template_param.emplace_back(a); - db.fix_forward_references = false; - db.try_to_parse_template_args = true; - int internal_status = success; - size_t len = std::strlen(mangled_name); - demangle(mangled_name, mangled_name + len, db, - internal_status); - if (internal_status == success && db.fix_forward_references && - !db.template_param.empty() && !db.template_param.front().empty()) - { - db.fix_forward_references = false; - db.tag_templates = false; - db.names.clear(); - db.subs.clear(); - demangle(mangled_name, mangled_name + len, db, internal_status); - if (db.fix_forward_references) - internal_status = invalid_mangled_name; - } - if (internal_status == success) - { - size_t sz = db.names.back().size() + 1; - if (sz > internal_size) - { - char* newbuf = static_cast<char*>(std::realloc(buf, sz)); - if (newbuf == nullptr) - { - internal_status = memory_alloc_failure; - buf = nullptr; - } - else - { - buf = newbuf; - if (n != nullptr) - *n = sz; - } - } - if (buf != nullptr) - { - db.names.back().first += db.names.back().second; - std::memcpy(buf, db.names.back().first.data(), sz-1); - buf[sz-1] = char(0); - } - } - else - buf = nullptr; - if (status) - *status = internal_status; - return buf; -} - -} // lldb_private diff --git a/source/Core/DataBufferHeap.cpp b/source/Core/DataBufferHeap.cpp index 4e5389e053e9..cdd37bfdf0fc 100644 --- a/source/Core/DataBufferHeap.cpp +++ b/source/Core/DataBufferHeap.cpp @@ -19,30 +19,24 @@ using namespace lldb_private; //---------------------------------------------------------------------- // Default constructor //---------------------------------------------------------------------- -DataBufferHeap::DataBufferHeap () : - m_data() -{ -} +DataBufferHeap::DataBufferHeap() : m_data() {} //---------------------------------------------------------------------- // Initialize this class with "n" characters and fill the buffer // with "ch". //---------------------------------------------------------------------- -DataBufferHeap::DataBufferHeap (lldb::offset_t n, uint8_t ch) : - m_data() -{ - if (n < m_data.max_size()) - m_data.assign (n, ch); +DataBufferHeap::DataBufferHeap(lldb::offset_t n, uint8_t ch) : m_data() { + if (n < m_data.max_size()) + m_data.assign(n, ch); } //---------------------------------------------------------------------- // Initialize this class with a copy of the "n" bytes from the "bytes" // buffer. //---------------------------------------------------------------------- -DataBufferHeap::DataBufferHeap (const void *src, lldb::offset_t src_len) : - m_data() -{ - CopyData (src, src_len); +DataBufferHeap::DataBufferHeap(const void *src, lldb::offset_t src_len) + : m_data() { + CopyData(src, src_len); } //---------------------------------------------------------------------- @@ -55,61 +49,46 @@ DataBufferHeap::~DataBufferHeap() = default; // Return a pointer to the bytes owned by this object, or nullptr if // the object contains no bytes. //---------------------------------------------------------------------- -uint8_t * -DataBufferHeap::GetBytes () -{ - return (m_data.empty() ? nullptr : m_data.data()); +uint8_t *DataBufferHeap::GetBytes() { + return (m_data.empty() ? nullptr : m_data.data()); } //---------------------------------------------------------------------- // Return a const pointer to the bytes owned by this object, or nullptr // if the object contains no bytes. //---------------------------------------------------------------------- -const uint8_t * -DataBufferHeap::GetBytes () const -{ - return (m_data.empty() ? nullptr : m_data.data()); +const uint8_t *DataBufferHeap::GetBytes() const { + return (m_data.empty() ? nullptr : m_data.data()); } //---------------------------------------------------------------------- // Return the number of bytes this object currently contains. //---------------------------------------------------------------------- -uint64_t -DataBufferHeap::GetByteSize () const -{ - return m_data.size(); -} +uint64_t DataBufferHeap::GetByteSize() const { return m_data.size(); } //---------------------------------------------------------------------- // Sets the number of bytes that this object should be able to // contain. This can be used prior to copying data into the buffer. //---------------------------------------------------------------------- -uint64_t -DataBufferHeap::SetByteSize (uint64_t new_size) -{ - m_data.resize(new_size); - return m_data.size(); +uint64_t DataBufferHeap::SetByteSize(uint64_t new_size) { + m_data.resize(new_size); + return m_data.size(); } -void -DataBufferHeap::CopyData (const void *src, uint64_t src_len) -{ - const uint8_t *src_u8 = (const uint8_t *)src; - if (src && src_len > 0) - m_data.assign (src_u8, src_u8 + src_len); - else - m_data.clear(); +void DataBufferHeap::CopyData(const void *src, uint64_t src_len) { + const uint8_t *src_u8 = (const uint8_t *)src; + if (src && src_len > 0) + m_data.assign(src_u8, src_u8 + src_len); + else + m_data.clear(); } -void -DataBufferHeap::AppendData (const void *src, uint64_t src_len) -{ - m_data.insert(m_data.end(), (const uint8_t *)src, (const uint8_t *)src + src_len); +void DataBufferHeap::AppendData(const void *src, uint64_t src_len) { + m_data.insert(m_data.end(), (const uint8_t *)src, + (const uint8_t *)src + src_len); } -void -DataBufferHeap::Clear() -{ - buffer_t empty; - m_data.swap(empty); +void DataBufferHeap::Clear() { + buffer_t empty; + m_data.swap(empty); } diff --git a/source/Core/DataBufferMemoryMap.cpp b/source/Core/DataBufferMemoryMap.cpp index 48fe9e58d07d..70e8a394f69e 100644 --- a/source/Core/DataBufferMemoryMap.cpp +++ b/source/Core/DataBufferMemoryMap.cpp @@ -17,7 +17,7 @@ #define MAP_EXTRA_HOST_READ_FLAGS 0 -#if defined (__APPLE__) +#if defined(__APPLE__) //---------------------------------------------------------------------- // Newer versions of MacOSX have a flag that will allow us to read from // binaries whose code signature is invalid without crashing by using @@ -27,12 +27,12 @@ // MAP_RESILIENT_MEDIA flag. //---------------------------------------------------------------------- #if defined(MAP_RESILIENT_CODESIGN) - #undef MAP_EXTRA_HOST_READ_FLAGS - #if defined(MAP_RESILIENT_MEDIA) - #define MAP_EXTRA_HOST_READ_FLAGS MAP_RESILIENT_CODESIGN | MAP_RESILIENT_MEDIA - #else - #define MAP_EXTRA_HOST_READ_FLAGS MAP_RESILIENT_CODESIGN - #endif +#undef MAP_EXTRA_HOST_READ_FLAGS +#if defined(MAP_RESILIENT_MEDIA) +#define MAP_EXTRA_HOST_READ_FLAGS MAP_RESILIENT_CODESIGN | MAP_RESILIENT_MEDIA +#else +#define MAP_EXTRA_HOST_READ_FLAGS MAP_RESILIENT_CODESIGN +#endif #endif // #if defined(MAP_RESILIENT_CODESIGN) #endif // #if defined (__APPLE__) @@ -47,10 +47,10 @@ // Project includes #include "lldb/Core/DataBufferMemoryMap.h" #include "lldb/Core/Error.h" +#include "lldb/Core/Log.h" #include "lldb/Host/File.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/HostInfo.h" -#include "lldb/Core/Log.h" using namespace lldb; using namespace lldb_private; @@ -58,75 +58,53 @@ using namespace lldb_private; //---------------------------------------------------------------------- // Default Constructor //---------------------------------------------------------------------- -DataBufferMemoryMap::DataBufferMemoryMap() : - m_mmap_addr(nullptr), - m_mmap_size(0), - m_data(nullptr), - m_size(0) -{ -} +DataBufferMemoryMap::DataBufferMemoryMap() + : m_mmap_addr(nullptr), m_mmap_size(0), m_data(nullptr), m_size(0) {} //---------------------------------------------------------------------- // Virtual destructor since this class inherits from a pure virtual // base class. //---------------------------------------------------------------------- -DataBufferMemoryMap::~DataBufferMemoryMap() -{ - Clear(); -} +DataBufferMemoryMap::~DataBufferMemoryMap() { Clear(); } //---------------------------------------------------------------------- // Return a pointer to the bytes owned by this object, or nullptr if // the object contains no bytes. //---------------------------------------------------------------------- -uint8_t * -DataBufferMemoryMap::GetBytes() -{ - return m_data; -} +uint8_t *DataBufferMemoryMap::GetBytes() { return m_data; } //---------------------------------------------------------------------- // Return a const pointer to the bytes owned by this object, or nullptr // if the object contains no bytes. //---------------------------------------------------------------------- -const uint8_t * -DataBufferMemoryMap::GetBytes() const -{ - return m_data; -} +const uint8_t *DataBufferMemoryMap::GetBytes() const { return m_data; } //---------------------------------------------------------------------- // Return the number of bytes this object currently contains. //---------------------------------------------------------------------- -uint64_t -DataBufferMemoryMap::GetByteSize() const -{ - return m_size; -} +uint64_t DataBufferMemoryMap::GetByteSize() const { return m_size; } //---------------------------------------------------------------------- // Reverts this object to an empty state by unmapping any memory // that is currently owned. //---------------------------------------------------------------------- -void -DataBufferMemoryMap::Clear() -{ - if (m_mmap_addr != nullptr) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MMAP)); - if (log) - log->Printf("DataBufferMemoryMap::Clear() m_mmap_addr = %p, m_mmap_size = %" PRIu64 "", (void *)m_mmap_addr, - (uint64_t)m_mmap_size); +void DataBufferMemoryMap::Clear() { + if (m_mmap_addr != nullptr) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MMAP)); + if (log) + log->Printf("DataBufferMemoryMap::Clear() m_mmap_addr = %p, m_mmap_size " + "= %" PRIu64 "", + (void *)m_mmap_addr, (uint64_t)m_mmap_size); #ifdef _WIN32 - UnmapViewOfFile(m_mmap_addr); + UnmapViewOfFile(m_mmap_addr); #else - ::munmap((void *)m_mmap_addr, m_mmap_size); + ::munmap((void *)m_mmap_addr, m_mmap_size); #endif - m_mmap_addr = nullptr; - m_mmap_size = 0; - m_data = nullptr; - m_size = 0; - } + m_mmap_addr = nullptr; + m_mmap_size = 0; + m_data = nullptr; + m_size = 0; + } } //---------------------------------------------------------------------- @@ -137,48 +115,41 @@ DataBufferMemoryMap::Clear() // Returns the number of bytes mapped starting from the requested // offset. //---------------------------------------------------------------------- -size_t -DataBufferMemoryMap::MemoryMapFromFileSpec (const FileSpec* filespec, - lldb::offset_t offset, - size_t length, - bool writeable) -{ - if (filespec != nullptr) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MMAP)); - if (log) - { - log->Printf("DataBufferMemoryMap::MemoryMapFromFileSpec(file=\"%s\", offset=0x%" PRIx64 ", length=0x%" PRIx64 ", writeable=%i", - filespec->GetPath().c_str(), - offset, - (uint64_t)length, - writeable); - } - char path[PATH_MAX]; - if (filespec->GetPath(path, sizeof(path))) - { - uint32_t options = File::eOpenOptionRead; - if (writeable) - options |= File::eOpenOptionWrite; +size_t DataBufferMemoryMap::MemoryMapFromFileSpec(const FileSpec *filespec, + lldb::offset_t offset, + size_t length, + bool writeable) { + if (filespec != nullptr) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MMAP)); + if (log) { + log->Printf("DataBufferMemoryMap::MemoryMapFromFileSpec(file=\"%s\", " + "offset=0x%" PRIx64 ", length=0x%" PRIx64 ", writeable=%i", + filespec->GetPath().c_str(), offset, (uint64_t)length, + writeable); + } + char path[PATH_MAX]; + if (filespec->GetPath(path, sizeof(path))) { + uint32_t options = File::eOpenOptionRead; + if (writeable) + options |= File::eOpenOptionWrite; - File file; - Error error (file.Open(path, options)); - if (error.Success()) - { - const bool fd_is_file = true; - return MemoryMapFromFileDescriptor (file.GetDescriptor(), offset, length, writeable, fd_is_file); - } - } + File file; + Error error(file.Open(path, options)); + if (error.Success()) { + const bool fd_is_file = true; + return MemoryMapFromFileDescriptor(file.GetDescriptor(), offset, length, + writeable, fd_is_file); + } } - // We should only get here if there was an error - Clear(); - return 0; + } + // We should only get here if there was an error + Clear(); + return 0; } #ifdef _WIN32 static size_t win32memmapalignment = 0; -void LoadWin32MemMapAlignment () -{ +void LoadWin32MemMapAlignment() { SYSTEM_INFO data; GetSystemInfo(&data); win32memmapalignment = data.dwAllocationGranularity; @@ -197,151 +168,140 @@ void LoadWin32MemMapAlignment () // RETURNS // Number of bytes mapped starting from the requested offset. //---------------------------------------------------------------------- -size_t -DataBufferMemoryMap::MemoryMapFromFileDescriptor (int fd, - lldb::offset_t offset, - size_t length, - bool writeable, - bool fd_is_file) -{ - Clear(); - if (fd >= 0) - { - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_MMAP|LIBLLDB_LOG_VERBOSE)); - if (log) - { - log->Printf("DataBufferMemoryMap::MemoryMapFromFileDescriptor(fd=%i, offset=0x%" PRIx64 ", length=0x%" PRIx64 ", writeable=%i, fd_is_file=%i)", - fd, - offset, - (uint64_t)length, - writeable, - fd_is_file); - } +size_t DataBufferMemoryMap::MemoryMapFromFileDescriptor(int fd, + lldb::offset_t offset, + size_t length, + bool writeable, + bool fd_is_file) { + Clear(); + if (fd >= 0) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_MMAP | + LIBLLDB_LOG_VERBOSE)); + if (log) { + log->Printf("DataBufferMemoryMap::MemoryMapFromFileDescriptor(fd=%i, " + "offset=0x%" PRIx64 ", length=0x%" PRIx64 + ", writeable=%i, fd_is_file=%i)", + fd, offset, (uint64_t)length, writeable, fd_is_file); + } #ifdef _WIN32 - HANDLE handle = (HANDLE)_get_osfhandle(fd); - DWORD file_size_low, file_size_high; - file_size_low = GetFileSize(handle, &file_size_high); - const lldb::offset_t file_size = llvm::Make_64(file_size_high, file_size_low); - const lldb::offset_t max_bytes_available = file_size - offset; - const size_t max_bytes_mappable = (size_t)std::min<lldb::offset_t>(SIZE_MAX, max_bytes_available); - if (length == SIZE_MAX || length > max_bytes_mappable) - { - // Cap the length if too much data was requested - length = max_bytes_mappable; - } + HANDLE handle = (HANDLE)_get_osfhandle(fd); + DWORD file_size_low, file_size_high; + file_size_low = GetFileSize(handle, &file_size_high); + const lldb::offset_t file_size = + llvm::Make_64(file_size_high, file_size_low); + const lldb::offset_t max_bytes_available = file_size - offset; + const size_t max_bytes_mappable = + (size_t)std::min<lldb::offset_t>(SIZE_MAX, max_bytes_available); + if (length == SIZE_MAX || length > max_bytes_mappable) { + // Cap the length if too much data was requested + length = max_bytes_mappable; + } - if (length > 0) - { - HANDLE fileMapping = CreateFileMapping(handle, nullptr, writeable ? PAGE_READWRITE : PAGE_READONLY, file_size_high, file_size_low, nullptr); - if (fileMapping != nullptr) - { - if (win32memmapalignment == 0) LoadWin32MemMapAlignment(); - lldb::offset_t realoffset = offset; - lldb::offset_t delta = 0; - if (realoffset % win32memmapalignment != 0) { - realoffset = realoffset / win32memmapalignment * win32memmapalignment; - delta = offset - realoffset; - } + if (length > 0) { + HANDLE fileMapping = CreateFileMapping( + handle, nullptr, writeable ? PAGE_READWRITE : PAGE_READONLY, + file_size_high, file_size_low, nullptr); + if (fileMapping != nullptr) { + if (win32memmapalignment == 0) + LoadWin32MemMapAlignment(); + lldb::offset_t realoffset = offset; + lldb::offset_t delta = 0; + if (realoffset % win32memmapalignment != 0) { + realoffset = realoffset / win32memmapalignment * win32memmapalignment; + delta = offset - realoffset; + } - LPVOID data = MapViewOfFile(fileMapping, writeable ? FILE_MAP_WRITE : FILE_MAP_READ, 0, realoffset, length + delta); - m_mmap_addr = (uint8_t *)data; - if (!data) { - Error error; - error.SetErrorToErrno (); - } else { - m_data = m_mmap_addr + delta; - m_size = length; - } - CloseHandle(fileMapping); - } + LPVOID data = MapViewOfFile(fileMapping, + writeable ? FILE_MAP_WRITE : FILE_MAP_READ, + 0, realoffset, length + delta); + m_mmap_addr = (uint8_t *)data; + if (!data) { + Error error; + error.SetErrorToErrno(); + } else { + m_data = m_mmap_addr + delta; + m_size = length; } + CloseHandle(fileMapping); + } + } #else - struct stat stat; - if (::fstat(fd, &stat) == 0) - { - if (S_ISREG(stat.st_mode) && - (stat.st_size > static_cast<off_t>(offset))) - { - const size_t max_bytes_available = stat.st_size - offset; - if (length == SIZE_MAX) - { - length = max_bytes_available; - } - else if (length > max_bytes_available) - { - // Cap the length if too much data was requested - length = max_bytes_available; - } + struct stat stat; + if (::fstat(fd, &stat) == 0) { + if (S_ISREG(stat.st_mode) && + (stat.st_size > static_cast<off_t>(offset))) { + const size_t max_bytes_available = stat.st_size - offset; + if (length == SIZE_MAX) { + length = max_bytes_available; + } else if (length > max_bytes_available) { + // Cap the length if too much data was requested + length = max_bytes_available; + } - if (length > 0) - { - int prot = PROT_READ; - int flags = MAP_PRIVATE; - if (writeable) - prot |= PROT_WRITE; - else - flags |= MAP_EXTRA_HOST_READ_FLAGS; + if (length > 0) { + int prot = PROT_READ; + int flags = MAP_PRIVATE; + if (writeable) + prot |= PROT_WRITE; + else + flags |= MAP_EXTRA_HOST_READ_FLAGS; - if (fd_is_file) - flags |= MAP_FILE; + if (fd_is_file) + flags |= MAP_FILE; - m_mmap_addr = (uint8_t *)::mmap(nullptr, length, prot, flags, fd, offset); - Error error; + m_mmap_addr = + (uint8_t *)::mmap(nullptr, length, prot, flags, fd, offset); + Error error; - if (m_mmap_addr == (void*)-1) - { - error.SetErrorToErrno (); - if (error.GetError() == EINVAL) - { - // We may still have a shot at memory mapping if we align things correctly - size_t page_offset = offset % HostInfo::GetPageSize(); - if (page_offset != 0) - { - m_mmap_addr = (uint8_t *)::mmap(nullptr, length + page_offset, prot, flags, fd, offset - page_offset); - if (m_mmap_addr == (void*)-1) - { - // Failed to map file - m_mmap_addr = nullptr; - } - else if (m_mmap_addr != nullptr) - { - // We recovered and were able to memory map - // after we aligned things to page boundaries + if (m_mmap_addr == (void *)-1) { + error.SetErrorToErrno(); + if (error.GetError() == EINVAL) { + // We may still have a shot at memory mapping if we align things + // correctly + size_t page_offset = offset % HostInfo::GetPageSize(); + if (page_offset != 0) { + m_mmap_addr = + (uint8_t *)::mmap(nullptr, length + page_offset, prot, + flags, fd, offset - page_offset); + if (m_mmap_addr == (void *)-1) { + // Failed to map file + m_mmap_addr = nullptr; + } else if (m_mmap_addr != nullptr) { + // We recovered and were able to memory map + // after we aligned things to page boundaries - // Save the actual mmap'ed size - m_mmap_size = length + page_offset; - // Our data is at an offset into the mapped data - m_data = m_mmap_addr + page_offset; - // Our pretend size is the size that was requested - m_size = length; - } - } - } - if (error.GetError() == ENOMEM) - { - error.SetErrorStringWithFormat("could not allocate %" PRId64 " bytes of memory to mmap in file", (uint64_t) length); - } - } - else - { - // We were able to map the requested data in one chunk - // where our mmap and actual data are the same. - m_mmap_size = length; - m_data = m_mmap_addr; - m_size = length; - } - - if (log) - { - log->Printf( - "DataBufferMemoryMap::MemoryMapFromFileSpec() m_mmap_addr = %p, m_mmap_size = %" PRIu64 - ", error = %s", - (void *)m_mmap_addr, (uint64_t)m_mmap_size, error.AsCString()); - } + // Save the actual mmap'ed size + m_mmap_size = length + page_offset; + // Our data is at an offset into the mapped data + m_data = m_mmap_addr + page_offset; + // Our pretend size is the size that was requested + m_size = length; } + } } + if (error.GetError() == ENOMEM) { + error.SetErrorStringWithFormat("could not allocate %" PRId64 + " bytes of memory to mmap in file", + (uint64_t)length); + } + } else { + // We were able to map the requested data in one chunk + // where our mmap and actual data are the same. + m_mmap_size = length; + m_data = m_mmap_addr; + m_size = length; + } + + if (log) { + log->Printf( + "DataBufferMemoryMap::MemoryMapFromFileSpec() m_mmap_addr = " + "%p, m_mmap_size = %" PRIu64 ", error = %s", + (void *)m_mmap_addr, (uint64_t)m_mmap_size, error.AsCString()); + } } -#endif + } } - return GetByteSize (); +#endif + } + return GetByteSize(); } diff --git a/source/Core/DataEncoder.cpp b/source/Core/DataEncoder.cpp index 3ef829507704..dd6adc0a8688 100644 --- a/source/Core/DataEncoder.cpp +++ b/source/Core/DataEncoder.cpp @@ -24,66 +24,52 @@ using namespace lldb; using namespace lldb_private; -static inline void -WriteInt16(unsigned char* ptr, unsigned offset, uint16_t value) -{ - *(uint16_t *)(ptr + offset) = value; +static inline void WriteInt16(unsigned char *ptr, unsigned offset, + uint16_t value) { + *(uint16_t *)(ptr + offset) = value; } -static inline void -WriteInt32 (unsigned char* ptr, unsigned offset, uint32_t value) -{ - *(uint32_t *)(ptr + offset) = value; +static inline void WriteInt32(unsigned char *ptr, unsigned offset, + uint32_t value) { + *(uint32_t *)(ptr + offset) = value; } -static inline void -WriteInt64(unsigned char* ptr, unsigned offset, uint64_t value) -{ - *(uint64_t *)(ptr + offset) = value; +static inline void WriteInt64(unsigned char *ptr, unsigned offset, + uint64_t value) { + *(uint64_t *)(ptr + offset) = value; } -static inline void -WriteSwappedInt16(unsigned char* ptr, unsigned offset, uint16_t value) -{ - *(uint16_t *)(ptr + offset) = llvm::ByteSwap_16(value); +static inline void WriteSwappedInt16(unsigned char *ptr, unsigned offset, + uint16_t value) { + *(uint16_t *)(ptr + offset) = llvm::ByteSwap_16(value); } -static inline void -WriteSwappedInt32 (unsigned char* ptr, unsigned offset, uint32_t value) -{ - *(uint32_t *)(ptr + offset) = llvm::ByteSwap_32(value); +static inline void WriteSwappedInt32(unsigned char *ptr, unsigned offset, + uint32_t value) { + *(uint32_t *)(ptr + offset) = llvm::ByteSwap_32(value); } -static inline void -WriteSwappedInt64(unsigned char* ptr, unsigned offset, uint64_t value) -{ - *(uint64_t *)(ptr + offset) = llvm::ByteSwap_64(value); +static inline void WriteSwappedInt64(unsigned char *ptr, unsigned offset, + uint64_t value) { + *(uint64_t *)(ptr + offset) = llvm::ByteSwap_64(value); } //---------------------------------------------------------------------- // Default constructor. //---------------------------------------------------------------------- -DataEncoder::DataEncoder () : - m_start(nullptr), - m_end(nullptr), - m_byte_order(endian::InlHostByteOrder()), - m_addr_size(sizeof(void*)), - m_data_sp() -{ -} +DataEncoder::DataEncoder() + : m_start(nullptr), m_end(nullptr), + m_byte_order(endian::InlHostByteOrder()), m_addr_size(sizeof(void *)), + m_data_sp() {} //---------------------------------------------------------------------- // This constructor allows us to use data that is owned by someone else. // The data must stay around as long as this object is valid. //---------------------------------------------------------------------- -DataEncoder::DataEncoder (void* data, uint32_t length, ByteOrder endian, uint8_t addr_size) : - m_start ((uint8_t*)data), - m_end ((uint8_t*)data + length), - m_byte_order(endian), - m_addr_size (addr_size), - m_data_sp () -{ -} +DataEncoder::DataEncoder(void *data, uint32_t length, ByteOrder endian, + uint8_t addr_size) + : m_start((uint8_t *)data), m_end((uint8_t *)data + length), + m_byte_order(endian), m_addr_size(addr_size), m_data_sp() {} //---------------------------------------------------------------------- // Make a shared pointer reference to the shared data in "data_sp" and @@ -92,14 +78,11 @@ DataEncoder::DataEncoder (void* data, uint32_t length, ByteOrder endian, uint8_t // as long as any DataEncoder objects exist that have a reference to // this data. //---------------------------------------------------------------------- -DataEncoder::DataEncoder (const DataBufferSP& data_sp, ByteOrder endian, uint8_t addr_size) : - m_start(nullptr), - m_end(nullptr), - m_byte_order(endian), - m_addr_size(addr_size), - m_data_sp() -{ - SetData (data_sp); +DataEncoder::DataEncoder(const DataBufferSP &data_sp, ByteOrder endian, + uint8_t addr_size) + : m_start(nullptr), m_end(nullptr), m_byte_order(endian), + m_addr_size(addr_size), m_data_sp() { + SetData(data_sp); } DataEncoder::~DataEncoder() = default; @@ -109,37 +92,30 @@ DataEncoder::~DataEncoder() = default; // release any references to shared data that this object may // contain. //------------------------------------------------------------------ -void -DataEncoder::Clear () -{ - m_start = nullptr; - m_end = nullptr; - m_byte_order = endian::InlHostByteOrder(); - m_addr_size = sizeof(void*); - m_data_sp.reset(); +void DataEncoder::Clear() { + m_start = nullptr; + m_end = nullptr; + m_byte_order = endian::InlHostByteOrder(); + m_addr_size = sizeof(void *); + m_data_sp.reset(); } //------------------------------------------------------------------ // If this object contains shared data, this function returns the // offset into that shared data. Else zero is returned. //------------------------------------------------------------------ -size_t -DataEncoder::GetSharedDataOffset () const -{ - if (m_start != nullptr) - { - const DataBuffer * data = m_data_sp.get(); - if (data != nullptr) - { - const uint8_t * data_bytes = data->GetBytes(); - if (data_bytes != nullptr) - { - assert(m_start >= data_bytes); - return m_start - data_bytes; - } - } +size_t DataEncoder::GetSharedDataOffset() const { + if (m_start != nullptr) { + const DataBuffer *data = m_data_sp.get(); + if (data != nullptr) { + const uint8_t *data_bytes = data->GetBytes(); + if (data_bytes != nullptr) { + assert(m_start >= data_bytes); + return m_start - data_bytes; + } } - return 0; + } + return 0; } //---------------------------------------------------------------------- @@ -152,22 +128,17 @@ DataEncoder::GetSharedDataOffset () const // reference to that data will be released. Is SWAP is set to true, // any data extracted will be endian swapped. //---------------------------------------------------------------------- -uint32_t -DataEncoder::SetData (void *bytes, uint32_t length, ByteOrder endian) -{ - m_byte_order = endian; - m_data_sp.reset(); - if (bytes == nullptr || length == 0) - { - m_start = nullptr; - m_end = nullptr; - } - else - { - m_start = (uint8_t *)bytes; - m_end = m_start + length; - } - return GetByteSize(); +uint32_t DataEncoder::SetData(void *bytes, uint32_t length, ByteOrder endian) { + m_byte_order = endian; + m_data_sp.reset(); + if (bytes == nullptr || length == 0) { + m_start = nullptr; + m_end = nullptr; + } else { + m_start = (uint8_t *)bytes; + m_end = m_start + length; + } + return GetByteSize(); } //---------------------------------------------------------------------- @@ -184,38 +155,35 @@ DataEncoder::SetData (void *bytes, uint32_t length, ByteOrder endian) // around as long as it is needed. The address size and endian swap // settings will remain unchanged from their current settings. //---------------------------------------------------------------------- -uint32_t -DataEncoder::SetData (const DataBufferSP& data_sp, uint32_t data_offset, uint32_t data_length) -{ - m_start = m_end = nullptr; - - if (data_length > 0) - { - m_data_sp = data_sp; - if (data_sp) - { - const size_t data_size = data_sp->GetByteSize(); - if (data_offset < data_size) - { - m_start = data_sp->GetBytes() + data_offset; - const size_t bytes_left = data_size - data_offset; - // Cap the length of we asked for too many - if (data_length <= bytes_left) - m_end = m_start + data_length; // We got all the bytes we wanted - else - m_end = m_start + bytes_left; // Not all the bytes requested were available in the shared data - } - } +uint32_t DataEncoder::SetData(const DataBufferSP &data_sp, uint32_t data_offset, + uint32_t data_length) { + m_start = m_end = nullptr; + + if (data_length > 0) { + m_data_sp = data_sp; + if (data_sp) { + const size_t data_size = data_sp->GetByteSize(); + if (data_offset < data_size) { + m_start = data_sp->GetBytes() + data_offset; + const size_t bytes_left = data_size - data_offset; + // Cap the length of we asked for too many + if (data_length <= bytes_left) + m_end = m_start + data_length; // We got all the bytes we wanted + else + m_end = m_start + bytes_left; // Not all the bytes requested were + // available in the shared data + } } + } - uint32_t new_size = GetByteSize(); + uint32_t new_size = GetByteSize(); - // Don't hold a shared pointer to the data buffer if we don't share - // any valid bytes in the shared buffer. - if (new_size == 0) - m_data_sp.reset(); + // Don't hold a shared pointer to the data buffer if we don't share + // any valid bytes in the shared buffer. + if (new_size == 0) + m_data_sp.reset(); - return new_size; + return new_size; } //---------------------------------------------------------------------- @@ -224,60 +192,48 @@ DataEncoder::SetData (const DataBufferSP& data_sp, uint32_t data_offset, uint32_ // // RETURNS the byte that was extracted, or zero on failure. //---------------------------------------------------------------------- -uint32_t -DataEncoder::PutU8 (uint32_t offset, uint8_t value) -{ - if (ValidOffset(offset)) - { - m_start[offset] = value; - return offset + 1; - } - return UINT32_MAX; +uint32_t DataEncoder::PutU8(uint32_t offset, uint8_t value) { + if (ValidOffset(offset)) { + m_start[offset] = value; + return offset + 1; + } + return UINT32_MAX; } -uint32_t -DataEncoder::PutU16 (uint32_t offset, uint16_t value) -{ - if (ValidOffsetForDataOfSize(offset, sizeof(value))) - { - if (m_byte_order != endian::InlHostByteOrder()) - WriteSwappedInt16 (m_start, offset, value); - else - WriteInt16 (m_start, offset, value); +uint32_t DataEncoder::PutU16(uint32_t offset, uint16_t value) { + if (ValidOffsetForDataOfSize(offset, sizeof(value))) { + if (m_byte_order != endian::InlHostByteOrder()) + WriteSwappedInt16(m_start, offset, value); + else + WriteInt16(m_start, offset, value); - return offset + sizeof (value); - } - return UINT32_MAX; + return offset + sizeof(value); + } + return UINT32_MAX; } -uint32_t -DataEncoder::PutU32 (uint32_t offset, uint32_t value) -{ - if (ValidOffsetForDataOfSize(offset, sizeof(value))) - { - if (m_byte_order != endian::InlHostByteOrder()) - WriteSwappedInt32 (m_start, offset, value); - else - WriteInt32 (m_start, offset, value); - - return offset + sizeof (value); - } - return UINT32_MAX; +uint32_t DataEncoder::PutU32(uint32_t offset, uint32_t value) { + if (ValidOffsetForDataOfSize(offset, sizeof(value))) { + if (m_byte_order != endian::InlHostByteOrder()) + WriteSwappedInt32(m_start, offset, value); + else + WriteInt32(m_start, offset, value); + + return offset + sizeof(value); + } + return UINT32_MAX; } -uint32_t -DataEncoder::PutU64 (uint32_t offset, uint64_t value) -{ - if (ValidOffsetForDataOfSize(offset, sizeof(value))) - { - if (m_byte_order != endian::InlHostByteOrder()) - WriteSwappedInt64 (m_start, offset, value); - else - WriteInt64 (m_start, offset, value); - - return offset + sizeof (value); - } - return UINT32_MAX; +uint32_t DataEncoder::PutU64(uint32_t offset, uint64_t value) { + if (ValidOffsetForDataOfSize(offset, sizeof(value))) { + if (m_byte_order != endian::InlHostByteOrder()) + WriteSwappedInt64(m_start, offset, value); + else + WriteInt64(m_start, offset, value); + + return offset + sizeof(value); + } + return UINT32_MAX; } //---------------------------------------------------------------------- @@ -290,46 +246,42 @@ DataEncoder::PutU64 (uint32_t offset, uint64_t value) // // RETURNS the integer value that was extracted, or zero on failure. //---------------------------------------------------------------------- -uint32_t -DataEncoder::PutMaxU64 (uint32_t offset, uint32_t byte_size, uint64_t value) -{ - switch (byte_size) - { - case 1: return PutU8 (offset, value); - case 2: return PutU16(offset, value); - case 4: return PutU32(offset, value); - case 8: return PutU64(offset, value); - default: - assert(!"GetMax64 unhandled case!"); - break; - } - return UINT32_MAX; +uint32_t DataEncoder::PutMaxU64(uint32_t offset, uint32_t byte_size, + uint64_t value) { + switch (byte_size) { + case 1: + return PutU8(offset, value); + case 2: + return PutU16(offset, value); + case 4: + return PutU32(offset, value); + case 8: + return PutU64(offset, value); + default: + assert(!"GetMax64 unhandled case!"); + break; + } + return UINT32_MAX; } -uint32_t -DataEncoder::PutData (uint32_t offset, const void *src, uint32_t src_len) -{ - if (src == nullptr || src_len == 0) - return offset; +uint32_t DataEncoder::PutData(uint32_t offset, const void *src, + uint32_t src_len) { + if (src == nullptr || src_len == 0) + return offset; - if (ValidOffsetForDataOfSize(offset, src_len)) - { - memcpy (m_start + offset, src, src_len); - return offset + src_len; - } - return UINT32_MAX; + if (ValidOffsetForDataOfSize(offset, src_len)) { + memcpy(m_start + offset, src, src_len); + return offset + src_len; + } + return UINT32_MAX; } -uint32_t -DataEncoder::PutAddress (uint32_t offset, lldb::addr_t addr) -{ - return PutMaxU64 (offset, GetAddressByteSize(), addr); +uint32_t DataEncoder::PutAddress(uint32_t offset, lldb::addr_t addr) { + return PutMaxU64(offset, GetAddressByteSize(), addr); } -uint32_t -DataEncoder::PutCString (uint32_t offset, const char *cstr) -{ - if (cstr != nullptr) - return PutData (offset, cstr, strlen(cstr) + 1); - return UINT32_MAX; +uint32_t DataEncoder::PutCString(uint32_t offset, const char *cstr) { + if (cstr != nullptr) + return PutData(offset, cstr, strlen(cstr) + 1); + return UINT32_MAX; } diff --git a/source/Core/DataExtractor.cpp b/source/Core/DataExtractor.cpp index 84446147a363..fbc6e80bea07 100644 --- a/source/Core/DataExtractor.cpp +++ b/source/Core/DataExtractor.cpp @@ -11,8 +11,8 @@ // C++ Includes #include <bitset> #include <cassert> -#include <cstddef> #include <cmath> +#include <cstddef> #include <sstream> #include <string> @@ -21,15 +21,15 @@ #include "llvm/ADT/APInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/MD5.h" +#include "llvm/Support/MathExtras.h" #include "clang/AST/ASTContext.h" // Project includes +#include "lldb/Core/DataBuffer.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataExtractor.h" -#include "lldb/Core/DataBuffer.h" #include "lldb/Core/Disassembler.h" #include "lldb/Core/Log.h" #include "lldb/Core/Stream.h" @@ -46,112 +46,92 @@ using namespace lldb; using namespace lldb_private; -static inline uint16_t -ReadInt16(const unsigned char* ptr, offset_t offset) -{ - uint16_t value; - memcpy (&value, ptr + offset, 2); - return value; +static inline uint16_t ReadInt16(const unsigned char *ptr, offset_t offset) { + uint16_t value; + memcpy(&value, ptr + offset, 2); + return value; } -static inline uint32_t -ReadInt32 (const unsigned char* ptr, offset_t offset = 0) -{ - uint32_t value; - memcpy (&value, ptr + offset, 4); - return value; +static inline uint32_t ReadInt32(const unsigned char *ptr, + offset_t offset = 0) { + uint32_t value; + memcpy(&value, ptr + offset, 4); + return value; } -static inline uint64_t -ReadInt64(const unsigned char* ptr, offset_t offset = 0) -{ - uint64_t value; - memcpy (&value, ptr + offset, 8); - return value; +static inline uint64_t ReadInt64(const unsigned char *ptr, + offset_t offset = 0) { + uint64_t value; + memcpy(&value, ptr + offset, 8); + return value; } -static inline uint16_t -ReadInt16(const void* ptr) -{ - uint16_t value; - memcpy (&value, ptr, 2); - return value; +static inline uint16_t ReadInt16(const void *ptr) { + uint16_t value; + memcpy(&value, ptr, 2); + return value; } -static inline uint16_t -ReadSwapInt16(const unsigned char* ptr, offset_t offset) -{ - uint16_t value; - memcpy (&value, ptr + offset, 2); - return llvm::ByteSwap_16(value); +static inline uint16_t ReadSwapInt16(const unsigned char *ptr, + offset_t offset) { + uint16_t value; + memcpy(&value, ptr + offset, 2); + return llvm::ByteSwap_16(value); } -static inline uint32_t -ReadSwapInt32 (const unsigned char* ptr, offset_t offset) -{ - uint32_t value; - memcpy (&value, ptr + offset, 4); - return llvm::ByteSwap_32(value); +static inline uint32_t ReadSwapInt32(const unsigned char *ptr, + offset_t offset) { + uint32_t value; + memcpy(&value, ptr + offset, 4); + return llvm::ByteSwap_32(value); } -static inline uint64_t -ReadSwapInt64(const unsigned char* ptr, offset_t offset) -{ - uint64_t value; - memcpy (&value, ptr + offset, 8); - return llvm::ByteSwap_64(value); +static inline uint64_t ReadSwapInt64(const unsigned char *ptr, + offset_t offset) { + uint64_t value; + memcpy(&value, ptr + offset, 8); + return llvm::ByteSwap_64(value); } -static inline uint16_t -ReadSwapInt16(const void* ptr) -{ - uint16_t value; - memcpy (&value, ptr, 2); - return llvm::ByteSwap_16(value); +static inline uint16_t ReadSwapInt16(const void *ptr) { + uint16_t value; + memcpy(&value, ptr, 2); + return llvm::ByteSwap_16(value); } -static inline uint32_t -ReadSwapInt32 (const void* ptr) -{ - uint32_t value; - memcpy (&value, ptr, 4); - return llvm::ByteSwap_32(value); +static inline uint32_t ReadSwapInt32(const void *ptr) { + uint32_t value; + memcpy(&value, ptr, 4); + return llvm::ByteSwap_32(value); } -static inline uint64_t -ReadSwapInt64(const void* ptr) -{ - uint64_t value; - memcpy (&value, ptr, 8); - return llvm::ByteSwap_64(value); +static inline uint64_t ReadSwapInt64(const void *ptr) { + uint64_t value; + memcpy(&value, ptr, 8); + return llvm::ByteSwap_64(value); } #define NON_PRINTABLE_CHAR '.' -DataExtractor::DataExtractor () : - m_start(nullptr), - m_end(nullptr), - m_byte_order(endian::InlHostByteOrder()), - m_addr_size(sizeof(void *)), - m_data_sp(), - m_target_byte_size(1) -{ -} +DataExtractor::DataExtractor() + : m_start(nullptr), m_end(nullptr), + m_byte_order(endian::InlHostByteOrder()), m_addr_size(sizeof(void *)), + m_data_sp(), m_target_byte_size(1) {} //---------------------------------------------------------------------- // This constructor allows us to use data that is owned by someone else. // The data must stay around as long as this object is valid. //---------------------------------------------------------------------- -DataExtractor::DataExtractor (const void* data, offset_t length, ByteOrder endian, uint32_t addr_size, uint32_t target_byte_size/*=1*/) : - m_start (const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(data))), - m_end (const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(data)) + length), - m_byte_order(endian), - m_addr_size (addr_size), - m_data_sp (), - m_target_byte_size(target_byte_size) -{ +DataExtractor::DataExtractor(const void *data, offset_t length, + ByteOrder endian, uint32_t addr_size, + uint32_t target_byte_size /*=1*/) + : m_start(const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(data))), + m_end(const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(data)) + + length), + m_byte_order(endian), m_addr_size(addr_size), m_data_sp(), + m_target_byte_size(target_byte_size) { #ifdef LLDB_CONFIGURATION_DEBUG - assert (addr_size == 4 || addr_size == 8); + assert(addr_size == 4 || addr_size == 8); #endif } @@ -162,18 +142,16 @@ DataExtractor::DataExtractor (const void* data, offset_t length, ByteOrder endia // as long as any DataExtractor objects exist that have a reference to // this data. //---------------------------------------------------------------------- -DataExtractor::DataExtractor (const DataBufferSP& data_sp, ByteOrder endian, uint32_t addr_size, uint32_t target_byte_size/*=1*/) : - m_start(nullptr), - m_end(nullptr), - m_byte_order(endian), - m_addr_size(addr_size), - m_data_sp(), - m_target_byte_size(target_byte_size) -{ +DataExtractor::DataExtractor(const DataBufferSP &data_sp, ByteOrder endian, + uint32_t addr_size, + uint32_t target_byte_size /*=1*/) + : m_start(nullptr), m_end(nullptr), m_byte_order(endian), + m_addr_size(addr_size), m_data_sp(), + m_target_byte_size(target_byte_size) { #ifdef LLDB_CONFIGURATION_DEBUG - assert (addr_size == 4 || addr_size == 8); + assert(addr_size == 4 || addr_size == 8); #endif - SetData (data_sp); + SetData(data_sp); } //---------------------------------------------------------------------- @@ -183,54 +161,43 @@ DataExtractor::DataExtractor (const DataBufferSP& data_sp, ByteOrder endian, uin // as any object contains a reference to that data. The endian // swap and address size settings are copied from "data". //---------------------------------------------------------------------- -DataExtractor::DataExtractor (const DataExtractor& data, offset_t offset, offset_t length, uint32_t target_byte_size/*=1*/) : - m_start(nullptr), - m_end(nullptr), - m_byte_order(data.m_byte_order), - m_addr_size(data.m_addr_size), - m_data_sp(), - m_target_byte_size(target_byte_size) -{ +DataExtractor::DataExtractor(const DataExtractor &data, offset_t offset, + offset_t length, uint32_t target_byte_size /*=1*/) + : m_start(nullptr), m_end(nullptr), m_byte_order(data.m_byte_order), + m_addr_size(data.m_addr_size), m_data_sp(), + m_target_byte_size(target_byte_size) { #ifdef LLDB_CONFIGURATION_DEBUG - assert (m_addr_size == 4 || m_addr_size == 8); + assert(m_addr_size == 4 || m_addr_size == 8); #endif - if (data.ValidOffset(offset)) - { - offset_t bytes_available = data.GetByteSize() - offset; - if (length > bytes_available) - length = bytes_available; - SetData(data, offset, length); - } -} - -DataExtractor::DataExtractor (const DataExtractor& rhs) : - m_start (rhs.m_start), - m_end (rhs.m_end), - m_byte_order (rhs.m_byte_order), - m_addr_size (rhs.m_addr_size), - m_data_sp (rhs.m_data_sp), - m_target_byte_size(rhs.m_target_byte_size) -{ + if (data.ValidOffset(offset)) { + offset_t bytes_available = data.GetByteSize() - offset; + if (length > bytes_available) + length = bytes_available; + SetData(data, offset, length); + } +} + +DataExtractor::DataExtractor(const DataExtractor &rhs) + : m_start(rhs.m_start), m_end(rhs.m_end), m_byte_order(rhs.m_byte_order), + m_addr_size(rhs.m_addr_size), m_data_sp(rhs.m_data_sp), + m_target_byte_size(rhs.m_target_byte_size) { #ifdef LLDB_CONFIGURATION_DEBUG - assert (m_addr_size == 4 || m_addr_size == 8); + assert(m_addr_size == 4 || m_addr_size == 8); #endif } //---------------------------------------------------------------------- // Assignment operator //---------------------------------------------------------------------- -const DataExtractor& -DataExtractor::operator= (const DataExtractor& rhs) -{ - if (this != &rhs) - { - m_start = rhs.m_start; - m_end = rhs.m_end; - m_byte_order = rhs.m_byte_order; - m_addr_size = rhs.m_addr_size; - m_data_sp = rhs.m_data_sp; - } - return *this; +const DataExtractor &DataExtractor::operator=(const DataExtractor &rhs) { + if (this != &rhs) { + m_start = rhs.m_start; + m_end = rhs.m_end; + m_byte_order = rhs.m_byte_order; + m_addr_size = rhs.m_addr_size; + m_data_sp = rhs.m_data_sp; + } + return *this; } DataExtractor::~DataExtractor() = default; @@ -240,37 +207,30 @@ DataExtractor::~DataExtractor() = default; // release any references to shared data that this object may // contain. //------------------------------------------------------------------ -void -DataExtractor::Clear () -{ - m_start = nullptr; - m_end = nullptr; - m_byte_order = endian::InlHostByteOrder(); - m_addr_size = sizeof(void *); - m_data_sp.reset(); +void DataExtractor::Clear() { + m_start = nullptr; + m_end = nullptr; + m_byte_order = endian::InlHostByteOrder(); + m_addr_size = sizeof(void *); + m_data_sp.reset(); } //------------------------------------------------------------------ // If this object contains shared data, this function returns the // offset into that shared data. Else zero is returned. //------------------------------------------------------------------ -size_t -DataExtractor::GetSharedDataOffset () const -{ - if (m_start != nullptr) - { - const DataBuffer * data = m_data_sp.get(); - if (data != nullptr) - { - const uint8_t * data_bytes = data->GetBytes(); - if (data_bytes != nullptr) - { - assert(m_start >= data_bytes); - return m_start - data_bytes; - } - } +size_t DataExtractor::GetSharedDataOffset() const { + if (m_start != nullptr) { + const DataBuffer *data = m_data_sp.get(); + if (data != nullptr) { + const uint8_t *data_bytes = data->GetBytes(); + if (data_bytes != nullptr) { + assert(m_start >= data_bytes); + return m_start - data_bytes; + } } - return 0; + } + return 0; } //---------------------------------------------------------------------- @@ -283,22 +243,18 @@ DataExtractor::GetSharedDataOffset () const // reference to that data will be released. Is SWAP is set to true, // any data extracted will be endian swapped. //---------------------------------------------------------------------- -lldb::offset_t -DataExtractor::SetData (const void *bytes, offset_t length, ByteOrder endian) -{ - m_byte_order = endian; - m_data_sp.reset(); - if (bytes == nullptr || length == 0) - { - m_start = nullptr; - m_end = nullptr; - } - else - { - m_start = const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(bytes)); - m_end = m_start + length; - } - return GetByteSize(); +lldb::offset_t DataExtractor::SetData(const void *bytes, offset_t length, + ByteOrder endian) { + m_byte_order = endian; + m_data_sp.reset(); + if (bytes == nullptr || length == 0) { + m_start = nullptr; + m_end = nullptr; + } else { + m_start = const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(bytes)); + m_end = m_start + length; + } + return GetByteSize(); } //---------------------------------------------------------------------- @@ -315,28 +271,28 @@ DataExtractor::SetData (const void *bytes, offset_t length, ByteOrder endian) // refers to those bytes. The address size and endian swap settings // are copied from the current values in "data". //---------------------------------------------------------------------- -lldb::offset_t -DataExtractor::SetData (const DataExtractor& data, offset_t data_offset, offset_t data_length) -{ - m_addr_size = data.m_addr_size; +lldb::offset_t DataExtractor::SetData(const DataExtractor &data, + offset_t data_offset, + offset_t data_length) { + m_addr_size = data.m_addr_size; #ifdef LLDB_CONFIGURATION_DEBUG - assert (m_addr_size == 4 || m_addr_size == 8); + assert(m_addr_size == 4 || m_addr_size == 8); #endif - // If "data" contains shared pointer to data, then we can use that - if (data.m_data_sp) - { - m_byte_order = data.m_byte_order; - return SetData(data.m_data_sp, data.GetSharedDataOffset() + data_offset, data_length); - } - - // We have a DataExtractor object that just has a pointer to bytes - if (data.ValidOffset(data_offset)) - { - if (data_length > data.GetByteSize() - data_offset) - data_length = data.GetByteSize() - data_offset; - return SetData (data.GetDataStart() + data_offset, data_length, data.GetByteOrder()); - } - return 0; + // If "data" contains shared pointer to data, then we can use that + if (data.m_data_sp) { + m_byte_order = data.m_byte_order; + return SetData(data.m_data_sp, data.GetSharedDataOffset() + data_offset, + data_length); + } + + // We have a DataExtractor object that just has a pointer to bytes + if (data.ValidOffset(data_offset)) { + if (data_length > data.GetByteSize() - data_offset) + data_length = data.GetByteSize() - data_offset; + return SetData(data.GetDataStart() + data_offset, data_length, + data.GetByteOrder()); + } + return 0; } //---------------------------------------------------------------------- @@ -353,38 +309,36 @@ DataExtractor::SetData (const DataExtractor& data, offset_t data_offset, offset_ // around as long as it is needed. The address size and endian swap // settings will remain unchanged from their current settings. //---------------------------------------------------------------------- -lldb::offset_t -DataExtractor::SetData (const DataBufferSP& data_sp, offset_t data_offset, offset_t data_length) -{ - m_start = m_end = nullptr; - - if (data_length > 0) - { - m_data_sp = data_sp; - if (data_sp) - { - const size_t data_size = data_sp->GetByteSize(); - if (data_offset < data_size) - { - m_start = data_sp->GetBytes() + data_offset; - const size_t bytes_left = data_size - data_offset; - // Cap the length of we asked for too many - if (data_length <= bytes_left) - m_end = m_start + data_length; // We got all the bytes we wanted - else - m_end = m_start + bytes_left; // Not all the bytes requested were available in the shared data - } - } +lldb::offset_t DataExtractor::SetData(const DataBufferSP &data_sp, + offset_t data_offset, + offset_t data_length) { + m_start = m_end = nullptr; + + if (data_length > 0) { + m_data_sp = data_sp; + if (data_sp) { + const size_t data_size = data_sp->GetByteSize(); + if (data_offset < data_size) { + m_start = data_sp->GetBytes() + data_offset; + const size_t bytes_left = data_size - data_offset; + // Cap the length of we asked for too many + if (data_length <= bytes_left) + m_end = m_start + data_length; // We got all the bytes we wanted + else + m_end = m_start + bytes_left; // Not all the bytes requested were + // available in the shared data + } } + } - size_t new_size = GetByteSize(); + size_t new_size = GetByteSize(); - // Don't hold a shared pointer to the data buffer if we don't share - // any valid bytes in the shared buffer. - if (new_size == 0) - m_data_sp.reset(); + // Don't hold a shared pointer to the data buffer if we don't share + // any valid bytes in the shared buffer. + if (new_size == 0) + m_data_sp.reset(); - return new_size; + return new_size; } //---------------------------------------------------------------------- @@ -393,13 +347,11 @@ DataExtractor::SetData (const DataBufferSP& data_sp, offset_t data_offset, offse // // RETURNS the byte that was extracted, or zero on failure. //---------------------------------------------------------------------- -uint8_t -DataExtractor::GetU8 (offset_t *offset_ptr) const -{ - const uint8_t *data = (const uint8_t *)GetData (offset_ptr, 1); - if (data) - return *data; - return 0; +uint8_t DataExtractor::GetU8(offset_t *offset_ptr) const { + const uint8_t *data = (const uint8_t *)GetData(offset_ptr, 1); + if (data) + return *data; + return 0; } //---------------------------------------------------------------------- @@ -411,18 +363,17 @@ DataExtractor::GetU8 (offset_t *offset_ptr) const // all the requested bytes, or nullptr when the data is not available in // the buffer due to being out of bounds, or insufficient data. //---------------------------------------------------------------------- -void * -DataExtractor::GetU8 (offset_t *offset_ptr, void *dst, uint32_t count) const -{ - const uint8_t *data = (const uint8_t *)GetData (offset_ptr, count); - if (data) - { - // Copy the data into the buffer - memcpy (dst, data, count); - // Return a non-nullptr pointer to the converted data as an indicator of success - return dst; - } - return nullptr; +void *DataExtractor::GetU8(offset_t *offset_ptr, void *dst, + uint32_t count) const { + const uint8_t *data = (const uint8_t *)GetData(offset_ptr, count); + if (data) { + // Copy the data into the buffer + memcpy(dst, data, count); + // Return a non-nullptr pointer to the converted data as an indicator of + // success + return dst; + } + return nullptr; } //---------------------------------------------------------------------- @@ -431,55 +382,46 @@ DataExtractor::GetU8 (offset_t *offset_ptr, void *dst, uint32_t count) const // // RETURNS the uint16_t that was extracted, or zero on failure. //---------------------------------------------------------------------- -uint16_t -DataExtractor::GetU16 (offset_t *offset_ptr) const -{ - uint16_t val = 0; - const uint8_t *data = (const uint8_t *)GetData (offset_ptr, sizeof(val)); - if (data) - { - if (m_byte_order != endian::InlHostByteOrder()) - val = ReadSwapInt16(data); - else - val = ReadInt16 (data); - } - return val; +uint16_t DataExtractor::GetU16(offset_t *offset_ptr) const { + uint16_t val = 0; + const uint8_t *data = (const uint8_t *)GetData(offset_ptr, sizeof(val)); + if (data) { + if (m_byte_order != endian::InlHostByteOrder()) + val = ReadSwapInt16(data); + else + val = ReadInt16(data); + } + return val; } -uint16_t -DataExtractor::GetU16_unchecked (offset_t *offset_ptr) const -{ - uint16_t val; - if (m_byte_order == endian::InlHostByteOrder()) - val = ReadInt16 (m_start, *offset_ptr); - else - val = ReadSwapInt16(m_start, *offset_ptr); - *offset_ptr += sizeof(val); - return val; +uint16_t DataExtractor::GetU16_unchecked(offset_t *offset_ptr) const { + uint16_t val; + if (m_byte_order == endian::InlHostByteOrder()) + val = ReadInt16(m_start, *offset_ptr); + else + val = ReadSwapInt16(m_start, *offset_ptr); + *offset_ptr += sizeof(val); + return val; } -uint32_t -DataExtractor::GetU32_unchecked (offset_t *offset_ptr) const -{ - uint32_t val; - if (m_byte_order == endian::InlHostByteOrder()) - val = ReadInt32 (m_start, *offset_ptr); - else - val = ReadSwapInt32 (m_start, *offset_ptr); - *offset_ptr += sizeof(val); - return val; +uint32_t DataExtractor::GetU32_unchecked(offset_t *offset_ptr) const { + uint32_t val; + if (m_byte_order == endian::InlHostByteOrder()) + val = ReadInt32(m_start, *offset_ptr); + else + val = ReadSwapInt32(m_start, *offset_ptr); + *offset_ptr += sizeof(val); + return val; } -uint64_t -DataExtractor::GetU64_unchecked (offset_t *offset_ptr) const -{ - uint64_t val; - if (m_byte_order == endian::InlHostByteOrder()) - val = ReadInt64 (m_start, *offset_ptr); - else - val = ReadSwapInt64 (m_start, *offset_ptr); - *offset_ptr += sizeof(val); - return val; +uint64_t DataExtractor::GetU64_unchecked(offset_t *offset_ptr) const { + uint64_t val; + if (m_byte_order == endian::InlHostByteOrder()) + val = ReadInt64(m_start, *offset_ptr); + else + val = ReadSwapInt64(m_start, *offset_ptr); + *offset_ptr += sizeof(val); + return val; } //---------------------------------------------------------------------- @@ -491,33 +433,28 @@ DataExtractor::GetU64_unchecked (offset_t *offset_ptr) const // all the requested bytes, or nullptr when the data is not available // in the buffer due to being out of bounds, or insufficient data. //---------------------------------------------------------------------- -void * -DataExtractor::GetU16 (offset_t *offset_ptr, void *void_dst, uint32_t count) const -{ - const size_t src_size = sizeof(uint16_t) * count; - const uint16_t *src = (const uint16_t *)GetData (offset_ptr, src_size); - if (src) - { - if (m_byte_order != endian::InlHostByteOrder()) - { - uint16_t *dst_pos = (uint16_t *)void_dst; - uint16_t *dst_end = dst_pos + count; - const uint16_t *src_pos = src; - while (dst_pos < dst_end) - { - *dst_pos = ReadSwapInt16 (src_pos); - ++dst_pos; - ++src_pos; - } - } - else - { - memcpy (void_dst, src, src_size); - } - // Return a non-nullptr pointer to the converted data as an indicator of success - return void_dst; +void *DataExtractor::GetU16(offset_t *offset_ptr, void *void_dst, + uint32_t count) const { + const size_t src_size = sizeof(uint16_t) * count; + const uint16_t *src = (const uint16_t *)GetData(offset_ptr, src_size); + if (src) { + if (m_byte_order != endian::InlHostByteOrder()) { + uint16_t *dst_pos = (uint16_t *)void_dst; + uint16_t *dst_end = dst_pos + count; + const uint16_t *src_pos = src; + while (dst_pos < dst_end) { + *dst_pos = ReadSwapInt16(src_pos); + ++dst_pos; + ++src_pos; + } + } else { + memcpy(void_dst, src, src_size); } - return nullptr; + // Return a non-nullptr pointer to the converted data as an indicator of + // success + return void_dst; + } + return nullptr; } //---------------------------------------------------------------------- @@ -526,23 +463,17 @@ DataExtractor::GetU16 (offset_t *offset_ptr, void *void_dst, uint32_t count) con // // RETURNS the uint32_t that was extracted, or zero on failure. //---------------------------------------------------------------------- -uint32_t -DataExtractor::GetU32 (offset_t *offset_ptr) const -{ - uint32_t val = 0; - const uint8_t *data = (const uint8_t *)GetData (offset_ptr, sizeof(val)); - if (data) - { - if (m_byte_order != endian::InlHostByteOrder()) - { - val = ReadSwapInt32 (data); - } - else - { - memcpy (&val, data, 4); - } +uint32_t DataExtractor::GetU32(offset_t *offset_ptr) const { + uint32_t val = 0; + const uint8_t *data = (const uint8_t *)GetData(offset_ptr, sizeof(val)); + if (data) { + if (m_byte_order != endian::InlHostByteOrder()) { + val = ReadSwapInt32(data); + } else { + memcpy(&val, data, 4); } - return val; + } + return val; } //---------------------------------------------------------------------- @@ -554,33 +485,28 @@ DataExtractor::GetU32 (offset_t *offset_ptr) const // all the requested bytes, or nullptr when the data is not available // in the buffer due to being out of bounds, or insufficient data. //---------------------------------------------------------------------- -void * -DataExtractor::GetU32 (offset_t *offset_ptr, void *void_dst, uint32_t count) const -{ - const size_t src_size = sizeof(uint32_t) * count; - const uint32_t *src = (const uint32_t *)GetData (offset_ptr, src_size); - if (src) - { - if (m_byte_order != endian::InlHostByteOrder()) - { - uint32_t *dst_pos = (uint32_t *)void_dst; - uint32_t *dst_end = dst_pos + count; - const uint32_t *src_pos = src; - while (dst_pos < dst_end) - { - *dst_pos = ReadSwapInt32 (src_pos); - ++dst_pos; - ++src_pos; - } - } - else - { - memcpy (void_dst, src, src_size); - } - // Return a non-nullptr pointer to the converted data as an indicator of success - return void_dst; +void *DataExtractor::GetU32(offset_t *offset_ptr, void *void_dst, + uint32_t count) const { + const size_t src_size = sizeof(uint32_t) * count; + const uint32_t *src = (const uint32_t *)GetData(offset_ptr, src_size); + if (src) { + if (m_byte_order != endian::InlHostByteOrder()) { + uint32_t *dst_pos = (uint32_t *)void_dst; + uint32_t *dst_end = dst_pos + count; + const uint32_t *src_pos = src; + while (dst_pos < dst_end) { + *dst_pos = ReadSwapInt32(src_pos); + ++dst_pos; + ++src_pos; + } + } else { + memcpy(void_dst, src, src_size); } - return nullptr; + // Return a non-nullptr pointer to the converted data as an indicator of + // success + return void_dst; + } + return nullptr; } //---------------------------------------------------------------------- @@ -589,23 +515,17 @@ DataExtractor::GetU32 (offset_t *offset_ptr, void *void_dst, uint32_t count) con // // RETURNS the uint64_t that was extracted, or zero on failure. //---------------------------------------------------------------------- -uint64_t -DataExtractor::GetU64 (offset_t *offset_ptr) const -{ - uint64_t val = 0; - const uint8_t *data = (const uint8_t *)GetData (offset_ptr, sizeof(val)); - if (data) - { - if (m_byte_order != endian::InlHostByteOrder()) - { - val = ReadSwapInt64 (data); - } - else - { - memcpy (&val, data, 8); - } +uint64_t DataExtractor::GetU64(offset_t *offset_ptr) const { + uint64_t val = 0; + const uint8_t *data = (const uint8_t *)GetData(offset_ptr, sizeof(val)); + if (data) { + if (m_byte_order != endian::InlHostByteOrder()) { + val = ReadSwapInt64(data); + } else { + memcpy(&val, data, 8); } - return val; + } + return val; } //---------------------------------------------------------------------- @@ -615,33 +535,28 @@ DataExtractor::GetU64 (offset_t *offset_ptr) const // read succeeds and increment the offset pointed to by offset_ptr, else // return false and leave the offset pointed to by offset_ptr unchanged. //---------------------------------------------------------------------- -void * -DataExtractor::GetU64 (offset_t *offset_ptr, void *void_dst, uint32_t count) const -{ - const size_t src_size = sizeof(uint64_t) * count; - const uint64_t *src = (const uint64_t *)GetData (offset_ptr, src_size); - if (src) - { - if (m_byte_order != endian::InlHostByteOrder()) - { - uint64_t *dst_pos = (uint64_t *)void_dst; - uint64_t *dst_end = dst_pos + count; - const uint64_t *src_pos = src; - while (dst_pos < dst_end) - { - *dst_pos = ReadSwapInt64 (src_pos); - ++dst_pos; - ++src_pos; - } - } - else - { - memcpy (void_dst, src, src_size); - } - // Return a non-nullptr pointer to the converted data as an indicator of success - return void_dst; +void *DataExtractor::GetU64(offset_t *offset_ptr, void *void_dst, + uint32_t count) const { + const size_t src_size = sizeof(uint64_t) * count; + const uint64_t *src = (const uint64_t *)GetData(offset_ptr, src_size); + if (src) { + if (m_byte_order != endian::InlHostByteOrder()) { + uint64_t *dst_pos = (uint64_t *)void_dst; + uint64_t *dst_end = dst_pos + count; + const uint64_t *src_pos = src; + while (dst_pos < dst_end) { + *dst_pos = ReadSwapInt64(src_pos); + ++dst_pos; + ++src_pos; + } + } else { + memcpy(void_dst, src, src_size); } - return nullptr; + // Return a non-nullptr pointer to the converted data as an indicator of + // success + return void_dst; + } + return nullptr; } //---------------------------------------------------------------------- @@ -654,19 +569,23 @@ DataExtractor::GetU64 (offset_t *offset_ptr, void *void_dst, uint32_t count) con // // RETURNS the integer value that was extracted, or zero on failure. //---------------------------------------------------------------------- -uint32_t -DataExtractor::GetMaxU32 (offset_t *offset_ptr, size_t byte_size) const -{ - switch (byte_size) - { - case 1: return GetU8 (offset_ptr); break; - case 2: return GetU16(offset_ptr); break; - case 4: return GetU32(offset_ptr); break; - default: - assert(false && "GetMaxU32 unhandled case!"); - break; - } - return 0; +uint32_t DataExtractor::GetMaxU32(offset_t *offset_ptr, + size_t byte_size) const { + switch (byte_size) { + case 1: + return GetU8(offset_ptr); + break; + case 2: + return GetU16(offset_ptr); + break; + case 4: + return GetU32(offset_ptr); + break; + default: + assert(false && "GetMaxU32 unhandled case!"); + break; + } + return 0; } //---------------------------------------------------------------------- @@ -679,153 +598,154 @@ DataExtractor::GetMaxU32 (offset_t *offset_ptr, size_t byte_size) const // // RETURNS the integer value that was extracted, or zero on failure. //---------------------------------------------------------------------- -uint64_t -DataExtractor::GetMaxU64 (offset_t *offset_ptr, size_t size) const -{ - switch (size) - { - case 1: return GetU8 (offset_ptr); break; - case 2: return GetU16(offset_ptr); break; - case 4: return GetU32(offset_ptr); break; - case 8: return GetU64(offset_ptr); break; - default: - assert(false && "GetMax64 unhandled case!"); - break; - } - return 0; -} - -uint64_t -DataExtractor::GetMaxU64_unchecked (offset_t *offset_ptr, size_t size) const -{ - switch (size) - { - case 1: return GetU8_unchecked (offset_ptr); break; - case 2: return GetU16_unchecked (offset_ptr); break; - case 4: return GetU32_unchecked (offset_ptr); break; - case 8: return GetU64_unchecked (offset_ptr); break; - default: - assert(false && "GetMax64 unhandled case!"); - break; - } - return 0; -} - -int64_t -DataExtractor::GetMaxS64 (offset_t *offset_ptr, size_t size) const -{ - switch (size) - { - case 1: return (int8_t)GetU8 (offset_ptr); break; - case 2: return (int16_t)GetU16(offset_ptr); break; - case 4: return (int32_t)GetU32(offset_ptr); break; - case 8: return (int64_t)GetU64(offset_ptr); break; - default: - assert(false && "GetMax64 unhandled case!"); - break; - } - return 0; -} - -uint64_t -DataExtractor::GetMaxU64Bitfield (offset_t *offset_ptr, size_t size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset) const -{ - uint64_t uval64 = GetMaxU64 (offset_ptr, size); - if (bitfield_bit_size > 0) - { - int32_t lsbcount = bitfield_bit_offset; - if (m_byte_order == eByteOrderBig) - lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size; - if (lsbcount > 0) - uval64 >>= lsbcount; - uint64_t bitfield_mask = ((1ul << bitfield_bit_size) - 1); - if (!bitfield_mask && bitfield_bit_offset == 0 && bitfield_bit_size == 64) - return uval64; - uval64 &= bitfield_mask; +uint64_t DataExtractor::GetMaxU64(offset_t *offset_ptr, size_t size) const { + switch (size) { + case 1: + return GetU8(offset_ptr); + break; + case 2: + return GetU16(offset_ptr); + break; + case 4: + return GetU32(offset_ptr); + break; + case 8: + return GetU64(offset_ptr); + break; + default: + assert(false && "GetMax64 unhandled case!"); + break; + } + return 0; +} + +uint64_t DataExtractor::GetMaxU64_unchecked(offset_t *offset_ptr, + size_t size) const { + switch (size) { + case 1: + return GetU8_unchecked(offset_ptr); + break; + case 2: + return GetU16_unchecked(offset_ptr); + break; + case 4: + return GetU32_unchecked(offset_ptr); + break; + case 8: + return GetU64_unchecked(offset_ptr); + break; + default: + assert(false && "GetMax64 unhandled case!"); + break; + } + return 0; +} + +int64_t DataExtractor::GetMaxS64(offset_t *offset_ptr, size_t size) const { + switch (size) { + case 1: + return (int8_t)GetU8(offset_ptr); + break; + case 2: + return (int16_t)GetU16(offset_ptr); + break; + case 4: + return (int32_t)GetU32(offset_ptr); + break; + case 8: + return (int64_t)GetU64(offset_ptr); + break; + default: + assert(false && "GetMax64 unhandled case!"); + break; + } + return 0; +} + +uint64_t DataExtractor::GetMaxU64Bitfield(offset_t *offset_ptr, size_t size, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset) const { + uint64_t uval64 = GetMaxU64(offset_ptr, size); + if (bitfield_bit_size > 0) { + int32_t lsbcount = bitfield_bit_offset; + if (m_byte_order == eByteOrderBig) + lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size; + if (lsbcount > 0) + uval64 >>= lsbcount; + uint64_t bitfield_mask = ((1ul << bitfield_bit_size) - 1); + if (!bitfield_mask && bitfield_bit_offset == 0 && bitfield_bit_size == 64) + return uval64; + uval64 &= bitfield_mask; + } + return uval64; +} + +int64_t DataExtractor::GetMaxS64Bitfield(offset_t *offset_ptr, size_t size, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset) const { + int64_t sval64 = GetMaxS64(offset_ptr, size); + if (bitfield_bit_size > 0) { + int32_t lsbcount = bitfield_bit_offset; + if (m_byte_order == eByteOrderBig) + lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size; + if (lsbcount > 0) + sval64 >>= lsbcount; + uint64_t bitfield_mask = (((uint64_t)1) << bitfield_bit_size) - 1; + sval64 &= bitfield_mask; + // sign extend if needed + if (sval64 & (((uint64_t)1) << (bitfield_bit_size - 1))) + sval64 |= ~bitfield_mask; + } + return sval64; +} + +float DataExtractor::GetFloat(offset_t *offset_ptr) const { + typedef float float_type; + float_type val = 0.0; + const size_t src_size = sizeof(float_type); + const float_type *src = (const float_type *)GetData(offset_ptr, src_size); + if (src) { + if (m_byte_order != endian::InlHostByteOrder()) { + const uint8_t *src_data = (const uint8_t *)src; + uint8_t *dst_data = (uint8_t *)&val; + for (size_t i = 0; i < sizeof(float_type); ++i) + dst_data[sizeof(float_type) - 1 - i] = src_data[i]; + } else { + val = *src; } - return uval64; -} - -int64_t -DataExtractor::GetMaxS64Bitfield (offset_t *offset_ptr, size_t size, uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset) const -{ - int64_t sval64 = GetMaxS64 (offset_ptr, size); - if (bitfield_bit_size > 0) - { - int32_t lsbcount = bitfield_bit_offset; - if (m_byte_order == eByteOrderBig) - lsbcount = size * 8 - bitfield_bit_offset - bitfield_bit_size; - if (lsbcount > 0) - sval64 >>= lsbcount; - uint64_t bitfield_mask = (((uint64_t)1) << bitfield_bit_size) - 1; - sval64 &= bitfield_mask; - // sign extend if needed - if (sval64 & (((uint64_t)1) << (bitfield_bit_size - 1))) - sval64 |= ~bitfield_mask; - } - return sval64; -} - - -float -DataExtractor::GetFloat (offset_t *offset_ptr) const -{ - typedef float float_type; - float_type val = 0.0; - const size_t src_size = sizeof(float_type); - const float_type *src = (const float_type *)GetData (offset_ptr, src_size); - if (src) - { - if (m_byte_order != endian::InlHostByteOrder()) - { - const uint8_t *src_data = (const uint8_t *)src; - uint8_t *dst_data = (uint8_t *)&val; - for (size_t i = 0; i < sizeof(float_type); ++i) - dst_data[sizeof(float_type) - 1 - i] = src_data[i]; - } - else - { - val = *src; - } - } - return val; -} - -double -DataExtractor::GetDouble (offset_t *offset_ptr) const -{ - typedef double float_type; - float_type val = 0.0; - const size_t src_size = sizeof(float_type); - const float_type *src = (const float_type *)GetData (offset_ptr, src_size); - if (src) - { - if (m_byte_order != endian::InlHostByteOrder()) - { - const uint8_t *src_data = (const uint8_t *)src; - uint8_t *dst_data = (uint8_t *)&val; - for (size_t i = 0; i < sizeof(float_type); ++i) - dst_data[sizeof(float_type) - 1 - i] = src_data[i]; - } - else - { - val = *src; - } + } + return val; +} + +double DataExtractor::GetDouble(offset_t *offset_ptr) const { + typedef double float_type; + float_type val = 0.0; + const size_t src_size = sizeof(float_type); + const float_type *src = (const float_type *)GetData(offset_ptr, src_size); + if (src) { + if (m_byte_order != endian::InlHostByteOrder()) { + const uint8_t *src_data = (const uint8_t *)src; + uint8_t *dst_data = (uint8_t *)&val; + for (size_t i = 0; i < sizeof(float_type); ++i) + dst_data[sizeof(float_type) - 1 - i] = src_data[i]; + } else { + val = *src; } - return val; + } + return val; } - -long double -DataExtractor::GetLongDouble (offset_t *offset_ptr) const -{ - long double val = 0.0; -#if defined (__i386__) || defined (__amd64__) || defined (__x86_64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_X64) - *offset_ptr += CopyByteOrderedData (*offset_ptr, 10, &val, sizeof(val), endian::InlHostByteOrder()); +long double DataExtractor::GetLongDouble(offset_t *offset_ptr) const { + long double val = 0.0; +#if defined(__i386__) || defined(__amd64__) || defined(__x86_64__) || \ + defined(_M_IX86) || defined(_M_IA64) || defined(_M_X64) + *offset_ptr += CopyByteOrderedData(*offset_ptr, 10, &val, sizeof(val), + endian::InlHostByteOrder()); #else - *offset_ptr += CopyByteOrderedData (*offset_ptr, sizeof(val), &val, sizeof(val), endian::InlHostByteOrder()); + *offset_ptr += CopyByteOrderedData(*offset_ptr, sizeof(val), &val, + sizeof(val), endian::InlHostByteOrder()); #endif - return val; + return val; } //------------------------------------------------------------------ @@ -836,22 +756,18 @@ DataExtractor::GetLongDouble (offset_t *offset_ptr) const // // RETURNS the address that was extracted, or zero on failure. //------------------------------------------------------------------ -uint64_t -DataExtractor::GetAddress (offset_t *offset_ptr) const -{ +uint64_t DataExtractor::GetAddress(offset_t *offset_ptr) const { #ifdef LLDB_CONFIGURATION_DEBUG - assert (m_addr_size == 4 || m_addr_size == 8); + assert(m_addr_size == 4 || m_addr_size == 8); #endif - return GetMaxU64 (offset_ptr, m_addr_size); + return GetMaxU64(offset_ptr, m_addr_size); } -uint64_t -DataExtractor::GetAddress_unchecked (offset_t *offset_ptr) const -{ +uint64_t DataExtractor::GetAddress_unchecked(offset_t *offset_ptr) const { #ifdef LLDB_CONFIGURATION_DEBUG - assert (m_addr_size == 4 || m_addr_size == 8); + assert(m_addr_size == 4 || m_addr_size == 8); #endif - return GetMaxU64_unchecked (offset_ptr, m_addr_size); + return GetMaxU64_unchecked(offset_ptr, m_addr_size); } //------------------------------------------------------------------ @@ -862,13 +778,11 @@ DataExtractor::GetAddress_unchecked (offset_t *offset_ptr) const // // RETURNS the pointer that was extracted, or zero on failure. //------------------------------------------------------------------ -uint64_t -DataExtractor::GetPointer (offset_t *offset_ptr) const -{ +uint64_t DataExtractor::GetPointer(offset_t *offset_ptr) const { #ifdef LLDB_CONFIGURATION_DEBUG - assert (m_addr_size == 4 || m_addr_size == 8); + assert(m_addr_size == 4 || m_addr_size == 8); #endif - return GetMaxU64 (offset_ptr, m_addr_size); + return GetMaxU64(offset_ptr, m_addr_size); } //---------------------------------------------------------------------- @@ -878,256 +792,239 @@ DataExtractor::GetPointer (offset_t *offset_ptr) const // pointer encoding. //---------------------------------------------------------------------- -uint64_t -DataExtractor::GetGNUEHPointer (offset_t *offset_ptr, uint32_t eh_ptr_enc, lldb::addr_t pc_rel_addr, lldb::addr_t text_addr, lldb::addr_t data_addr)//, BSDRelocs *data_relocs) const +uint64_t DataExtractor::GetGNUEHPointer( + offset_t *offset_ptr, uint32_t eh_ptr_enc, lldb::addr_t pc_rel_addr, + lldb::addr_t text_addr, + lldb::addr_t data_addr) //, BSDRelocs *data_relocs) const { - if (eh_ptr_enc == DW_EH_PE_omit) - return ULLONG_MAX; // Value isn't in the buffer... + if (eh_ptr_enc == DW_EH_PE_omit) + return ULLONG_MAX; // Value isn't in the buffer... - uint64_t baseAddress = 0; - uint64_t addressValue = 0; - const uint32_t addr_size = GetAddressByteSize(); + uint64_t baseAddress = 0; + uint64_t addressValue = 0; + const uint32_t addr_size = GetAddressByteSize(); #ifdef LLDB_CONFIGURATION_DEBUG - assert (addr_size == 4 || addr_size == 8); + assert(addr_size == 4 || addr_size == 8); #endif - bool signExtendValue = false; - // Decode the base part or adjust our offset - switch (eh_ptr_enc & 0x70) - { - case DW_EH_PE_pcrel: - signExtendValue = true; - baseAddress = *offset_ptr; - if (pc_rel_addr != LLDB_INVALID_ADDRESS) - baseAddress += pc_rel_addr; -// else -// Log::GlobalWarning ("PC relative pointer encoding found with invalid pc relative address."); - break; - - case DW_EH_PE_textrel: - signExtendValue = true; - if (text_addr != LLDB_INVALID_ADDRESS) - baseAddress = text_addr; -// else -// Log::GlobalWarning ("text relative pointer encoding being decoded with invalid text section address, setting base address to zero."); - break; - - case DW_EH_PE_datarel: - signExtendValue = true; - if (data_addr != LLDB_INVALID_ADDRESS) - baseAddress = data_addr; -// else -// Log::GlobalWarning ("data relative pointer encoding being decoded with invalid data section address, setting base address to zero."); - break; - - case DW_EH_PE_funcrel: - signExtendValue = true; - break; - - case DW_EH_PE_aligned: - { - // SetPointerSize should be called prior to extracting these so the - // pointer size is cached - assert(addr_size != 0); - if (addr_size) - { - // Align to a address size boundary first - uint32_t alignOffset = *offset_ptr % addr_size; - if (alignOffset) - offset_ptr += addr_size - alignOffset; - } - } - break; - - default: - break; - } - - // Decode the value part - switch (eh_ptr_enc & DW_EH_PE_MASK_ENCODING) - { - case DW_EH_PE_absptr : - { - addressValue = GetAddress (offset_ptr); -// if (data_relocs) -// addressValue = data_relocs->Relocate(*offset_ptr - addr_size, *this, addressValue); - } - break; - case DW_EH_PE_uleb128 : addressValue = GetULEB128(offset_ptr); break; - case DW_EH_PE_udata2 : addressValue = GetU16(offset_ptr); break; - case DW_EH_PE_udata4 : addressValue = GetU32(offset_ptr); break; - case DW_EH_PE_udata8 : addressValue = GetU64(offset_ptr); break; - case DW_EH_PE_sleb128 : addressValue = GetSLEB128(offset_ptr); break; - case DW_EH_PE_sdata2 : addressValue = (int16_t)GetU16(offset_ptr); break; - case DW_EH_PE_sdata4 : addressValue = (int32_t)GetU32(offset_ptr); break; - case DW_EH_PE_sdata8 : addressValue = (int64_t)GetU64(offset_ptr); break; - default: - // Unhandled encoding type - assert(eh_ptr_enc); - break; + bool signExtendValue = false; + // Decode the base part or adjust our offset + switch (eh_ptr_enc & 0x70) { + case DW_EH_PE_pcrel: + signExtendValue = true; + baseAddress = *offset_ptr; + if (pc_rel_addr != LLDB_INVALID_ADDRESS) + baseAddress += pc_rel_addr; + // else + // Log::GlobalWarning ("PC relative pointer encoding found with + // invalid pc relative address."); + break; + + case DW_EH_PE_textrel: + signExtendValue = true; + if (text_addr != LLDB_INVALID_ADDRESS) + baseAddress = text_addr; + // else + // Log::GlobalWarning ("text relative pointer encoding being + // decoded with invalid text section address, setting base address + // to zero."); + break; + + case DW_EH_PE_datarel: + signExtendValue = true; + if (data_addr != LLDB_INVALID_ADDRESS) + baseAddress = data_addr; + // else + // Log::GlobalWarning ("data relative pointer encoding being + // decoded with invalid data section address, setting base address + // to zero."); + break; + + case DW_EH_PE_funcrel: + signExtendValue = true; + break; + + case DW_EH_PE_aligned: { + // SetPointerSize should be called prior to extracting these so the + // pointer size is cached + assert(addr_size != 0); + if (addr_size) { + // Align to a address size boundary first + uint32_t alignOffset = *offset_ptr % addr_size; + if (alignOffset) + offset_ptr += addr_size - alignOffset; } - - // Since we promote everything to 64 bit, we may need to sign extend - if (signExtendValue && addr_size < sizeof(baseAddress)) - { - uint64_t sign_bit = 1ull << ((addr_size * 8ull) - 1ull); - if (sign_bit & addressValue) - { - uint64_t mask = ~sign_bit + 1; - addressValue |= mask; - } + } break; + + default: + break; + } + + // Decode the value part + switch (eh_ptr_enc & DW_EH_PE_MASK_ENCODING) { + case DW_EH_PE_absptr: { + addressValue = GetAddress(offset_ptr); + // if (data_relocs) + // addressValue = data_relocs->Relocate(*offset_ptr - + // addr_size, *this, addressValue); + } break; + case DW_EH_PE_uleb128: + addressValue = GetULEB128(offset_ptr); + break; + case DW_EH_PE_udata2: + addressValue = GetU16(offset_ptr); + break; + case DW_EH_PE_udata4: + addressValue = GetU32(offset_ptr); + break; + case DW_EH_PE_udata8: + addressValue = GetU64(offset_ptr); + break; + case DW_EH_PE_sleb128: + addressValue = GetSLEB128(offset_ptr); + break; + case DW_EH_PE_sdata2: + addressValue = (int16_t)GetU16(offset_ptr); + break; + case DW_EH_PE_sdata4: + addressValue = (int32_t)GetU32(offset_ptr); + break; + case DW_EH_PE_sdata8: + addressValue = (int64_t)GetU64(offset_ptr); + break; + default: + // Unhandled encoding type + assert(eh_ptr_enc); + break; + } + + // Since we promote everything to 64 bit, we may need to sign extend + if (signExtendValue && addr_size < sizeof(baseAddress)) { + uint64_t sign_bit = 1ull << ((addr_size * 8ull) - 1ull); + if (sign_bit & addressValue) { + uint64_t mask = ~sign_bit + 1; + addressValue |= mask; } - return baseAddress + addressValue; + } + return baseAddress + addressValue; } -size_t -DataExtractor::ExtractBytes (offset_t offset, offset_t length, ByteOrder dst_byte_order, void *dst) const -{ - const uint8_t *src = PeekData (offset, length); - if (src) - { - if (dst_byte_order != GetByteOrder()) - { - // Validate that only a word- or register-sized dst is byte swapped - assert (length == 1 || length == 2 || length == 4 || length == 8 || - length == 10 || length == 16 || length == 32); - - for (uint32_t i = 0; i < length; ++i) - ((uint8_t*)dst)[i] = src[length - i - 1]; - } - else - ::memcpy (dst, src, length); - return length; - } - return 0; +size_t DataExtractor::ExtractBytes(offset_t offset, offset_t length, + ByteOrder dst_byte_order, void *dst) const { + const uint8_t *src = PeekData(offset, length); + if (src) { + if (dst_byte_order != GetByteOrder()) { + // Validate that only a word- or register-sized dst is byte swapped + assert(length == 1 || length == 2 || length == 4 || length == 8 || + length == 10 || length == 16 || length == 32); + + for (uint32_t i = 0; i < length; ++i) + ((uint8_t *)dst)[i] = src[length - i - 1]; + } else + ::memcpy(dst, src, length); + return length; + } + return 0; } // Extract data as it exists in target memory -lldb::offset_t -DataExtractor::CopyData (offset_t offset, - offset_t length, - void *dst) const -{ - const uint8_t *src = PeekData (offset, length); - if (src) - { - ::memcpy (dst, src, length); - return length; - } - return 0; +lldb::offset_t DataExtractor::CopyData(offset_t offset, offset_t length, + void *dst) const { + const uint8_t *src = PeekData(offset, length); + if (src) { + ::memcpy(dst, src, length); + return length; + } + return 0; } // Extract data and swap if needed when doing the copy lldb::offset_t -DataExtractor::CopyByteOrderedData (offset_t src_offset, - offset_t src_len, - void *dst_void_ptr, - offset_t dst_len, - ByteOrder dst_byte_order) const -{ - // Validate the source info - if (!ValidOffsetForDataOfSize(src_offset, src_len)) - assert (ValidOffsetForDataOfSize(src_offset, src_len)); - assert (src_len > 0); - assert (m_byte_order == eByteOrderBig || m_byte_order == eByteOrderLittle); - - // Validate the destination info - assert(dst_void_ptr != nullptr); - assert (dst_len > 0); - assert (dst_byte_order == eByteOrderBig || dst_byte_order == eByteOrderLittle); - - // Validate that only a word- or register-sized dst is byte swapped - assert (dst_byte_order == m_byte_order || dst_len == 1 || dst_len == 2 || - dst_len == 4 || dst_len == 8 || dst_len == 10 || dst_len == 16 || - dst_len == 32); - - // Must have valid byte orders set in this object and for destination - if (!(dst_byte_order == eByteOrderBig || dst_byte_order == eByteOrderLittle) || - !(m_byte_order == eByteOrderBig || m_byte_order == eByteOrderLittle)) - return 0; - - uint8_t* dst = (uint8_t*)dst_void_ptr; - const uint8_t* src = (const uint8_t *)PeekData (src_offset, src_len); - if (src) - { - if (dst_len >= src_len) - { - // We are copying the entire value from src into dst. - // Calculate how many, if any, zeroes we need for the most - // significant bytes if "dst_len" is greater than "src_len"... - const size_t num_zeroes = dst_len - src_len; - if (dst_byte_order == eByteOrderBig) - { - // Big endian, so we lead with zeroes... - if (num_zeroes > 0) - ::memset (dst, 0, num_zeroes); - // Then either copy or swap the rest - if (m_byte_order == eByteOrderBig) - { - ::memcpy (dst + num_zeroes, src, src_len); - } - else - { - for (uint32_t i = 0; i < src_len; ++i) - dst[i+num_zeroes] = src[src_len - 1 - i]; - } - } - else - { - // Little endian destination, so we lead the value bytes - if (m_byte_order == eByteOrderBig) - { - for (uint32_t i = 0; i < src_len; ++i) - dst[i] = src[src_len - 1 - i]; - } - else - { - ::memcpy (dst, src, src_len); - } - // And zero the rest... - if (num_zeroes > 0) - ::memset (dst + src_len, 0, num_zeroes); - } - return src_len; +DataExtractor::CopyByteOrderedData(offset_t src_offset, offset_t src_len, + void *dst_void_ptr, offset_t dst_len, + ByteOrder dst_byte_order) const { + // Validate the source info + if (!ValidOffsetForDataOfSize(src_offset, src_len)) + assert(ValidOffsetForDataOfSize(src_offset, src_len)); + assert(src_len > 0); + assert(m_byte_order == eByteOrderBig || m_byte_order == eByteOrderLittle); + + // Validate the destination info + assert(dst_void_ptr != nullptr); + assert(dst_len > 0); + assert(dst_byte_order == eByteOrderBig || dst_byte_order == eByteOrderLittle); + + // Validate that only a word- or register-sized dst is byte swapped + assert(dst_byte_order == m_byte_order || dst_len == 1 || dst_len == 2 || + dst_len == 4 || dst_len == 8 || dst_len == 10 || dst_len == 16 || + dst_len == 32); + + // Must have valid byte orders set in this object and for destination + if (!(dst_byte_order == eByteOrderBig || + dst_byte_order == eByteOrderLittle) || + !(m_byte_order == eByteOrderBig || m_byte_order == eByteOrderLittle)) + return 0; + + uint8_t *dst = (uint8_t *)dst_void_ptr; + const uint8_t *src = (const uint8_t *)PeekData(src_offset, src_len); + if (src) { + if (dst_len >= src_len) { + // We are copying the entire value from src into dst. + // Calculate how many, if any, zeroes we need for the most + // significant bytes if "dst_len" is greater than "src_len"... + const size_t num_zeroes = dst_len - src_len; + if (dst_byte_order == eByteOrderBig) { + // Big endian, so we lead with zeroes... + if (num_zeroes > 0) + ::memset(dst, 0, num_zeroes); + // Then either copy or swap the rest + if (m_byte_order == eByteOrderBig) { + ::memcpy(dst + num_zeroes, src, src_len); + } else { + for (uint32_t i = 0; i < src_len; ++i) + dst[i + num_zeroes] = src[src_len - 1 - i]; } - else - { - // We are only copying some of the value from src into dst.. - - if (dst_byte_order == eByteOrderBig) - { - // Big endian dst - if (m_byte_order == eByteOrderBig) - { - // Big endian dst, with big endian src - ::memcpy (dst, src + (src_len - dst_len), dst_len); - } - else - { - // Big endian dst, with little endian src - for (uint32_t i = 0; i < dst_len; ++i) - dst[i] = src[dst_len - 1 - i]; - } - } - else - { - // Little endian dst - if (m_byte_order == eByteOrderBig) - { - // Little endian dst, with big endian src - for (uint32_t i = 0; i < dst_len; ++i) - dst[i] = src[src_len - 1 - i]; - } - else - { - // Little endian dst, with big endian src - ::memcpy (dst, src, dst_len); - } - } - return dst_len; - } + } else { + // Little endian destination, so we lead the value bytes + if (m_byte_order == eByteOrderBig) { + for (uint32_t i = 0; i < src_len; ++i) + dst[i] = src[src_len - 1 - i]; + } else { + ::memcpy(dst, src, src_len); + } + // And zero the rest... + if (num_zeroes > 0) + ::memset(dst + src_len, 0, num_zeroes); + } + return src_len; + } else { + // We are only copying some of the value from src into dst.. + + if (dst_byte_order == eByteOrderBig) { + // Big endian dst + if (m_byte_order == eByteOrderBig) { + // Big endian dst, with big endian src + ::memcpy(dst, src + (src_len - dst_len), dst_len); + } else { + // Big endian dst, with little endian src + for (uint32_t i = 0; i < dst_len; ++i) + dst[i] = src[dst_len - 1 - i]; + } + } else { + // Little endian dst + if (m_byte_order == eByteOrderBig) { + // Little endian dst, with big endian src + for (uint32_t i = 0; i < dst_len; ++i) + dst[i] = src[src_len - 1 - i]; + } else { + // Little endian dst, with big endian src + ::memcpy(dst, src, dst_len); + } + } + return dst_len; } - return 0; + } + return 0; } //---------------------------------------------------------------------- @@ -1141,32 +1038,28 @@ DataExtractor::CopyByteOrderedData (offset_t src_offset, // bytes, nullptr will be returned and "offset_ptr" will not be // updated. //---------------------------------------------------------------------- -const char* -DataExtractor::GetCStr (offset_t *offset_ptr) const -{ - const char *cstr = (const char *)PeekData (*offset_ptr, 1); - if (cstr) - { - const char *cstr_end = cstr; - const char *end = (const char *)m_end; - while (cstr_end < end && *cstr_end) - ++cstr_end; - - // Now we are either at the end of the data or we point to the - // NULL C string terminator with cstr_end... - if (*cstr_end == '\0') - { - // Advance the offset with one extra byte for the NULL terminator - *offset_ptr += (cstr_end - cstr + 1); - return cstr; - } - - // We reached the end of the data without finding a NULL C string - // terminator. Fall through and return nullptr otherwise anyone that - // would have used the result as a C string can wander into - // unknown memory... +const char *DataExtractor::GetCStr(offset_t *offset_ptr) const { + const char *cstr = (const char *)PeekData(*offset_ptr, 1); + if (cstr) { + const char *cstr_end = cstr; + const char *end = (const char *)m_end; + while (cstr_end < end && *cstr_end) + ++cstr_end; + + // Now we are either at the end of the data or we point to the + // NULL C string terminator with cstr_end... + if (*cstr_end == '\0') { + // Advance the offset with one extra byte for the NULL terminator + *offset_ptr += (cstr_end - cstr + 1); + return cstr; } - return nullptr; + + // We reached the end of the data without finding a NULL C string + // terminator. Fall through and return nullptr otherwise anyone that + // would have used the result as a C string can wander into + // unknown memory... + } + return nullptr; } //---------------------------------------------------------------------- @@ -1180,20 +1073,16 @@ DataExtractor::GetCStr (offset_t *offset_ptr) const // field does not contain a NULL terminator byte, nullptr will be returned // and "offset_ptr" will not be updated. //---------------------------------------------------------------------- -const char* -DataExtractor::GetCStr (offset_t *offset_ptr, offset_t len) const -{ - const char *cstr = (const char *)PeekData (*offset_ptr, len); - if (cstr != nullptr) - { - if (memchr(cstr, '\0', len) == nullptr) - { - return nullptr; - } - *offset_ptr += len; - return cstr; +const char *DataExtractor::GetCStr(offset_t *offset_ptr, offset_t len) const { + const char *cstr = (const char *)PeekData(*offset_ptr, len); + if (cstr != nullptr) { + if (memchr(cstr, '\0', len) == nullptr) { + return nullptr; } - return nullptr; + *offset_ptr += len; + return cstr; + } + return nullptr; } //------------------------------------------------------------------ @@ -1204,10 +1093,8 @@ DataExtractor::GetCStr (offset_t *offset_ptr, offset_t len) const // Returns a valid C string pointer if "offset" is a valid offset in // this object's data, else nullptr is returned. //------------------------------------------------------------------ -const char * -DataExtractor::PeekCStr (offset_t offset) const -{ - return (const char *)PeekData (offset, 1); +const char *DataExtractor::PeekCStr(offset_t offset) const { + return (const char *)PeekData(offset, 1); } //---------------------------------------------------------------------- @@ -1218,36 +1105,31 @@ DataExtractor::PeekCStr (offset_t offset) const // // Returned the extracted integer value. //---------------------------------------------------------------------- -uint64_t -DataExtractor::GetULEB128 (offset_t *offset_ptr) const -{ - const uint8_t *src = (const uint8_t *)PeekData (*offset_ptr, 1); - if (src == nullptr) - return 0; - - const uint8_t *end = m_end; - - if (src < end) - { - uint64_t result = *src++; - if (result >= 0x80) - { - result &= 0x7f; - int shift = 7; - while (src < end) - { - uint8_t byte = *src++; - result |= (uint64_t)(byte & 0x7f) << shift; - if ((byte & 0x80) == 0) - break; - shift += 7; - } - } - *offset_ptr = src - m_start; - return result; - } - +uint64_t DataExtractor::GetULEB128(offset_t *offset_ptr) const { + const uint8_t *src = (const uint8_t *)PeekData(*offset_ptr, 1); + if (src == nullptr) return 0; + + const uint8_t *end = m_end; + + if (src < end) { + uint64_t result = *src++; + if (result >= 0x80) { + result &= 0x7f; + int shift = 7; + while (src < end) { + uint8_t byte = *src++; + result |= (uint64_t)(byte & 0x7f) << shift; + if ((byte & 0x80) == 0) + break; + shift += 7; + } + } + *offset_ptr = src - m_start; + return result; + } + + return 0; } //---------------------------------------------------------------------- @@ -1258,42 +1140,38 @@ DataExtractor::GetULEB128 (offset_t *offset_ptr) const // // Returned the extracted integer value. //---------------------------------------------------------------------- -int64_t -DataExtractor::GetSLEB128 (offset_t *offset_ptr) const -{ - const uint8_t *src = (const uint8_t *)PeekData (*offset_ptr, 1); - if (src == nullptr) - return 0; - - const uint8_t *end = m_end; - - if (src < end) - { - int64_t result = 0; - int shift = 0; - int size = sizeof (int64_t) * 8; - - uint8_t byte = 0; - int bytecount = 0; - - while (src < end) - { - bytecount++; - byte = *src++; - result |= (int64_t)(byte & 0x7f) << shift; - shift += 7; - if ((byte & 0x80) == 0) - break; - } +int64_t DataExtractor::GetSLEB128(offset_t *offset_ptr) const { + const uint8_t *src = (const uint8_t *)PeekData(*offset_ptr, 1); + if (src == nullptr) + return 0; - // Sign bit of byte is 2nd high order bit (0x40) - if (shift < size && (byte & 0x40)) - result |= - (1 << shift); + const uint8_t *end = m_end; - *offset_ptr += bytecount; - return result; + if (src < end) { + int64_t result = 0; + int shift = 0; + int size = sizeof(int64_t) * 8; + + uint8_t byte = 0; + int bytecount = 0; + + while (src < end) { + bytecount++; + byte = *src++; + result |= (int64_t)(byte & 0x7f) << shift; + shift += 7; + if ((byte & 0x80) == 0) + break; } - return 0; + + // Sign bit of byte is 2nd high order bit (0x40) + if (shift < size && (byte & 0x40)) + result |= -(1 << shift); + + *offset_ptr += bytecount; + return result; + } + return 0; } //---------------------------------------------------------------------- @@ -1304,761 +1182,774 @@ DataExtractor::GetSLEB128 (offset_t *offset_ptr) const // // Returns the number of bytes consumed during the extraction. //---------------------------------------------------------------------- -uint32_t -DataExtractor::Skip_LEB128 (offset_t *offset_ptr) const -{ - uint32_t bytes_consumed = 0; - const uint8_t *src = (const uint8_t *)PeekData (*offset_ptr, 1); - if (src == nullptr) - return 0; - - const uint8_t *end = m_end; - - if (src < end) - { - const uint8_t *src_pos = src; - while ((src_pos < end) && (*src_pos++ & 0x80)) - ++bytes_consumed; - *offset_ptr += src_pos - src; - } - return bytes_consumed; -} +uint32_t DataExtractor::Skip_LEB128(offset_t *offset_ptr) const { + uint32_t bytes_consumed = 0; + const uint8_t *src = (const uint8_t *)PeekData(*offset_ptr, 1); + if (src == nullptr) + return 0; -static bool -GetAPInt (const DataExtractor &data, lldb::offset_t *offset_ptr, lldb::offset_t byte_size, llvm::APInt &result) -{ - llvm::SmallVector<uint64_t, 2> uint64_array; - lldb::offset_t bytes_left = byte_size; - uint64_t u64; - const lldb::ByteOrder byte_order = data.GetByteOrder(); - if (byte_order == lldb::eByteOrderLittle) - { - while (bytes_left > 0) - { - if (bytes_left >= 8) - { - u64 = data.GetU64(offset_ptr); - bytes_left -= 8; - } - else - { - u64 = data.GetMaxU64(offset_ptr, (uint32_t)bytes_left); - bytes_left = 0; - } - uint64_array.push_back(u64); - } - result = llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array)); - return true; - } - else if (byte_order == lldb::eByteOrderBig) - { - lldb::offset_t be_offset = *offset_ptr + byte_size; - lldb::offset_t temp_offset; - while (bytes_left > 0) - { - if (bytes_left >= 8) - { - be_offset -= 8; - temp_offset = be_offset; - u64 = data.GetU64(&temp_offset); - bytes_left -= 8; - } - else - { - be_offset -= bytes_left; - temp_offset = be_offset; - u64 = data.GetMaxU64(&temp_offset, (uint32_t)bytes_left); - bytes_left = 0; - } - uint64_array.push_back(u64); - } - *offset_ptr += byte_size; - result = llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array)); - return true; + const uint8_t *end = m_end; + + if (src < end) { + const uint8_t *src_pos = src; + while ((src_pos < end) && (*src_pos++ & 0x80)) + ++bytes_consumed; + *offset_ptr += src_pos - src; + } + return bytes_consumed; +} + +static bool GetAPInt(const DataExtractor &data, lldb::offset_t *offset_ptr, + lldb::offset_t byte_size, llvm::APInt &result) { + llvm::SmallVector<uint64_t, 2> uint64_array; + lldb::offset_t bytes_left = byte_size; + uint64_t u64; + const lldb::ByteOrder byte_order = data.GetByteOrder(); + if (byte_order == lldb::eByteOrderLittle) { + while (bytes_left > 0) { + if (bytes_left >= 8) { + u64 = data.GetU64(offset_ptr); + bytes_left -= 8; + } else { + u64 = data.GetMaxU64(offset_ptr, (uint32_t)bytes_left); + bytes_left = 0; + } + uint64_array.push_back(u64); } - return false; -} - -static lldb::offset_t -DumpAPInt (Stream *s, const DataExtractor &data, lldb::offset_t offset, lldb::offset_t byte_size, bool is_signed, unsigned radix) -{ - llvm::APInt apint; - if (GetAPInt (data, &offset, byte_size, apint)) - { - std::string apint_str(apint.toString(radix, is_signed)); - switch (radix) - { - case 2: - s->Write ("0b", 2); - break; - case 8: - s->Write ("0", 1); - break; - case 10: - break; - } - s->Write(apint_str.c_str(), apint_str.size()); + result = llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array)); + return true; + } else if (byte_order == lldb::eByteOrderBig) { + lldb::offset_t be_offset = *offset_ptr + byte_size; + lldb::offset_t temp_offset; + while (bytes_left > 0) { + if (bytes_left >= 8) { + be_offset -= 8; + temp_offset = be_offset; + u64 = data.GetU64(&temp_offset); + bytes_left -= 8; + } else { + be_offset -= bytes_left; + temp_offset = be_offset; + u64 = data.GetMaxU64(&temp_offset, (uint32_t)bytes_left); + bytes_left = 0; + } + uint64_array.push_back(u64); } - return offset; -} - -static float -half2float (uint16_t half) -{ - union { float f; uint32_t u; } u; - int32_t v = (int16_t) half; - - if (0 == (v & 0x7c00)) - { - u.u = v & 0x80007FFFU; - return u.f * ldexpf(1, 125); + *offset_ptr += byte_size; + result = llvm::APInt(byte_size * 8, llvm::ArrayRef<uint64_t>(uint64_array)); + return true; + } + return false; +} + +static lldb::offset_t DumpAPInt(Stream *s, const DataExtractor &data, + lldb::offset_t offset, lldb::offset_t byte_size, + bool is_signed, unsigned radix) { + llvm::APInt apint; + if (GetAPInt(data, &offset, byte_size, apint)) { + std::string apint_str(apint.toString(radix, is_signed)); + switch (radix) { + case 2: + s->Write("0b", 2); + break; + case 8: + s->Write("0", 1); + break; + case 10: + break; } + s->Write(apint_str.c_str(), apint_str.size()); + } + return offset; +} + +static float half2float(uint16_t half) { + union { + float f; + uint32_t u; + } u; + int32_t v = (int16_t)half; + + if (0 == (v & 0x7c00)) { + u.u = v & 0x80007FFFU; + return u.f * ldexpf(1, 125); + } + + v <<= 13; + u.u = v | 0x70000000U; + return u.f * ldexpf(1, -112); +} + +lldb::offset_t DataExtractor::Dump( + Stream *s, offset_t start_offset, lldb::Format item_format, + size_t item_byte_size, size_t item_count, size_t num_per_line, + uint64_t base_addr, + uint32_t item_bit_size, // If zero, this is not a bitfield value, if + // non-zero, the value is a bitfield + uint32_t item_bit_offset, // If "item_bit_size" is non-zero, this is the + // shift amount to apply to a bitfield + ExecutionContextScope *exe_scope) const { + if (s == nullptr) + return start_offset; + + if (item_format == eFormatPointer) { + if (item_byte_size != 4 && item_byte_size != 8) + item_byte_size = s->GetAddressByteSize(); + } + + offset_t offset = start_offset; + + if (item_format == eFormatInstruction) { + TargetSP target_sp; + if (exe_scope) + target_sp = exe_scope->CalculateTarget(); + if (target_sp) { + DisassemblerSP disassembler_sp(Disassembler::FindPlugin( + target_sp->GetArchitecture(), nullptr, nullptr)); + if (disassembler_sp) { + lldb::addr_t addr = base_addr + start_offset; + lldb_private::Address so_addr; + bool data_from_file = true; + if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) { + data_from_file = false; + } else { + if (target_sp->GetSectionLoadList().IsEmpty() || + !target_sp->GetImages().ResolveFileAddress(addr, so_addr)) + so_addr.SetRawAddress(addr); + } - v <<= 13; - u.u = v | 0x70000000U; - return u.f * ldexpf(1, -112); -} - -lldb::offset_t -DataExtractor::Dump (Stream *s, - offset_t start_offset, - lldb::Format item_format, - size_t item_byte_size, - size_t item_count, - size_t num_per_line, - uint64_t base_addr, - uint32_t item_bit_size, // If zero, this is not a bitfield value, if non-zero, the value is a bitfield - uint32_t item_bit_offset, // If "item_bit_size" is non-zero, this is the shift amount to apply to a bitfield - ExecutionContextScope *exe_scope) const -{ - if (s == nullptr) - return start_offset; - - if (item_format == eFormatPointer) - { - if (item_byte_size != 4 && item_byte_size != 8) - item_byte_size = s->GetAddressByteSize(); - } - - offset_t offset = start_offset; - - if (item_format == eFormatInstruction) - { - TargetSP target_sp; - if (exe_scope) - target_sp = exe_scope->CalculateTarget(); - if (target_sp) - { - DisassemblerSP disassembler_sp(Disassembler::FindPlugin(target_sp->GetArchitecture(), nullptr, nullptr)); - if (disassembler_sp) - { - lldb::addr_t addr = base_addr + start_offset; - lldb_private::Address so_addr; - bool data_from_file = true; - if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) - { - data_from_file = false; - } - else - { - if (target_sp->GetSectionLoadList().IsEmpty() || !target_sp->GetImages().ResolveFileAddress(addr, so_addr)) - so_addr.SetRawAddress(addr); - } - - size_t bytes_consumed = disassembler_sp->DecodeInstructions (so_addr, *this, start_offset, item_count, false, data_from_file); - - if (bytes_consumed) - { - offset += bytes_consumed; - const bool show_address = base_addr != LLDB_INVALID_ADDRESS; - const bool show_bytes = true; - ExecutionContext exe_ctx; - exe_scope->CalculateExecutionContext(exe_ctx); - disassembler_sp->GetInstructionList().Dump (s, show_address, show_bytes, &exe_ctx); - } - } + size_t bytes_consumed = disassembler_sp->DecodeInstructions( + so_addr, *this, start_offset, item_count, false, data_from_file); + + if (bytes_consumed) { + offset += bytes_consumed; + const bool show_address = base_addr != LLDB_INVALID_ADDRESS; + const bool show_bytes = true; + ExecutionContext exe_ctx; + exe_scope->CalculateExecutionContext(exe_ctx); + disassembler_sp->GetInstructionList().Dump(s, show_address, + show_bytes, &exe_ctx); } - else - s->Printf ("invalid target"); + } + } else + s->Printf("invalid target"); - return offset; + return offset; + } + + if ((item_format == eFormatOSType || item_format == eFormatAddressInfo) && + item_byte_size > 8) + item_format = eFormatHex; + + lldb::offset_t line_start_offset = start_offset; + for (uint32_t count = 0; ValidOffset(offset) && count < item_count; ++count) { + if ((count % num_per_line) == 0) { + if (count > 0) { + if (item_format == eFormatBytesWithASCII && + offset > line_start_offset) { + s->Printf("%*s", + static_cast<int>( + (num_per_line - (offset - line_start_offset)) * 3 + 2), + ""); + Dump(s, line_start_offset, eFormatCharPrintable, 1, + offset - line_start_offset, SIZE_MAX, LLDB_INVALID_ADDRESS, 0, + 0); + } + s->EOL(); + } + if (base_addr != LLDB_INVALID_ADDRESS) + s->Printf("0x%8.8" PRIx64 ": ", + (uint64_t)(base_addr + + (offset - start_offset) / m_target_byte_size)); + + line_start_offset = offset; + } else if (item_format != eFormatChar && + item_format != eFormatCharPrintable && + item_format != eFormatCharArray && count > 0) { + s->PutChar(' '); } - if ((item_format == eFormatOSType || item_format == eFormatAddressInfo) && item_byte_size > 8) - item_format = eFormatHex; - - lldb::offset_t line_start_offset = start_offset; - for (uint32_t count = 0; ValidOffset(offset) && count < item_count; ++count) - { - if ((count % num_per_line) == 0) - { - if (count > 0) - { - if (item_format == eFormatBytesWithASCII && offset > line_start_offset) - { - s->Printf("%*s", static_cast<int>((num_per_line - (offset - line_start_offset)) * 3 + 2), ""); - Dump(s, line_start_offset, eFormatCharPrintable, 1, offset - line_start_offset, SIZE_MAX, LLDB_INVALID_ADDRESS, 0, 0); - } - s->EOL(); - } - if (base_addr != LLDB_INVALID_ADDRESS) - s->Printf ("0x%8.8" PRIx64 ": ", - (uint64_t)(base_addr + (offset - start_offset)/m_target_byte_size )); - - line_start_offset = offset; - } - else if (item_format != eFormatChar && - item_format != eFormatCharPrintable && - item_format != eFormatCharArray && - count > 0) - { - s->PutChar(' '); + switch (item_format) { + case eFormatBoolean: + if (item_byte_size <= 8) + s->Printf("%s", GetMaxU64Bitfield(&offset, item_byte_size, + item_bit_size, item_bit_offset) + ? "true" + : "false"); + else { + s->Printf("error: unsupported byte size (%" PRIu64 + ") for boolean format", + (uint64_t)item_byte_size); + return offset; + } + break; + + case eFormatBinary: + if (item_byte_size <= 8) { + uint64_t uval64 = GetMaxU64Bitfield(&offset, item_byte_size, + item_bit_size, item_bit_offset); + // Avoid std::bitset<64>::to_string() since it is missing in + // earlier C++ libraries + std::string binary_value(64, '0'); + std::bitset<64> bits(uval64); + for (uint32_t i = 0; i < 64; ++i) + if (bits[i]) + binary_value[64 - 1 - i] = '1'; + if (item_bit_size > 0) + s->Printf("0b%s", binary_value.c_str() + 64 - item_bit_size); + else if (item_byte_size > 0 && item_byte_size <= 8) + s->Printf("0b%s", binary_value.c_str() + 64 - item_byte_size * 8); + } else { + const bool is_signed = false; + const unsigned radix = 2; + offset = DumpAPInt(s, *this, offset, item_byte_size, is_signed, radix); + } + break; + + case eFormatBytes: + case eFormatBytesWithASCII: + for (uint32_t i = 0; i < item_byte_size; ++i) { + s->Printf("%2.2x", GetU8(&offset)); + } + + // Put an extra space between the groups of bytes if more than one + // is being dumped in a group (item_byte_size is more than 1). + if (item_byte_size > 1) + s->PutChar(' '); + break; + + case eFormatChar: + case eFormatCharPrintable: + case eFormatCharArray: { + // If we are only printing one character surround it with single + // quotes + if (item_count == 1 && item_format == eFormatChar) + s->PutChar('\''); + + const uint64_t ch = GetMaxU64Bitfield(&offset, item_byte_size, + item_bit_size, item_bit_offset); + if (isprint(ch)) + s->Printf("%c", (char)ch); + else if (item_format != eFormatCharPrintable) { + switch (ch) { + case '\033': + s->Printf("\\e"); + break; + case '\a': + s->Printf("\\a"); + break; + case '\b': + s->Printf("\\b"); + break; + case '\f': + s->Printf("\\f"); + break; + case '\n': + s->Printf("\\n"); + break; + case '\r': + s->Printf("\\r"); + break; + case '\t': + s->Printf("\\t"); + break; + case '\v': + s->Printf("\\v"); + break; + case '\0': + s->Printf("\\0"); + break; + default: + if (item_byte_size == 1) + s->Printf("\\x%2.2x", (uint8_t)ch); + else + s->Printf("%" PRIu64, ch); + break; } - - switch (item_format) - { - case eFormatBoolean: - if (item_byte_size <= 8) - s->Printf ("%s", GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset) ? "true" : "false"); - else - { - s->Printf("error: unsupported byte size (%" PRIu64 ") for boolean format", (uint64_t)item_byte_size); - return offset; - } + } else { + s->PutChar(NON_PRINTABLE_CHAR); + } + + // If we are only printing one character surround it with single quotes + if (item_count == 1 && item_format == eFormatChar) + s->PutChar('\''); + } break; + + case eFormatEnum: // Print enum value as a signed integer when we don't get + // the enum type + case eFormatDecimal: + if (item_byte_size <= 8) + s->Printf("%" PRId64, + GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size, + item_bit_offset)); + else { + const bool is_signed = true; + const unsigned radix = 10; + offset = DumpAPInt(s, *this, offset, item_byte_size, is_signed, radix); + } + break; + + case eFormatUnsigned: + if (item_byte_size <= 8) + s->Printf("%" PRIu64, + GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, + item_bit_offset)); + else { + const bool is_signed = false; + const unsigned radix = 10; + offset = DumpAPInt(s, *this, offset, item_byte_size, is_signed, radix); + } + break; + + case eFormatOctal: + if (item_byte_size <= 8) + s->Printf("0%" PRIo64, + GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size, + item_bit_offset)); + else { + const bool is_signed = false; + const unsigned radix = 8; + offset = DumpAPInt(s, *this, offset, item_byte_size, is_signed, radix); + } + break; + + case eFormatOSType: { + uint64_t uval64 = GetMaxU64Bitfield(&offset, item_byte_size, + item_bit_size, item_bit_offset); + s->PutChar('\''); + for (uint32_t i = 0; i < item_byte_size; ++i) { + uint8_t ch = (uint8_t)(uval64 >> ((item_byte_size - i - 1) * 8)); + if (isprint(ch)) + s->Printf("%c", ch); + else { + switch (ch) { + case '\033': + s->Printf("\\e"); break; - - case eFormatBinary: - if (item_byte_size <= 8) - { - uint64_t uval64 = GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset); - // Avoid std::bitset<64>::to_string() since it is missing in - // earlier C++ libraries - std::string binary_value(64, '0'); - std::bitset<64> bits(uval64); - for (uint32_t i = 0; i < 64; ++i) - if (bits[i]) - binary_value[64 - 1 - i] = '1'; - if (item_bit_size > 0) - s->Printf("0b%s", binary_value.c_str() + 64 - item_bit_size); - else if (item_byte_size > 0 && item_byte_size <= 8) - s->Printf("0b%s", binary_value.c_str() + 64 - item_byte_size * 8); - } - else - { - const bool is_signed = false; - const unsigned radix = 2; - offset = DumpAPInt (s, *this, offset, item_byte_size, is_signed, radix); - } + case '\a': + s->Printf("\\a"); break; - - case eFormatBytes: - case eFormatBytesWithASCII: - for (uint32_t i = 0; i < item_byte_size; ++i) - { - s->Printf ("%2.2x", GetU8(&offset)); - } - - // Put an extra space between the groups of bytes if more than one - // is being dumped in a group (item_byte_size is more than 1). - if (item_byte_size > 1) - s->PutChar(' '); + case '\b': + s->Printf("\\b"); break; - - case eFormatChar: - case eFormatCharPrintable: - case eFormatCharArray: - { - // If we are only printing one character surround it with single - // quotes - if (item_count == 1 && item_format == eFormatChar) - s->PutChar('\''); - - const uint64_t ch = GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset); - if (isprint(ch)) - s->Printf ("%c", (char)ch); - else if (item_format != eFormatCharPrintable) - { - switch (ch) - { - case '\033': s->Printf ("\\e"); break; - case '\a': s->Printf ("\\a"); break; - case '\b': s->Printf ("\\b"); break; - case '\f': s->Printf ("\\f"); break; - case '\n': s->Printf ("\\n"); break; - case '\r': s->Printf ("\\r"); break; - case '\t': s->Printf ("\\t"); break; - case '\v': s->Printf ("\\v"); break; - case '\0': s->Printf ("\\0"); break; - default: - if (item_byte_size == 1) - s->Printf ("\\x%2.2x", (uint8_t)ch); - else - s->Printf ("%" PRIu64, ch); - break; - } - } - else - { - s->PutChar(NON_PRINTABLE_CHAR); - } - - // If we are only printing one character surround it with single quotes - if (item_count == 1 && item_format == eFormatChar) - s->PutChar('\''); - } + case '\f': + s->Printf("\\f"); break; - - case eFormatEnum: // Print enum value as a signed integer when we don't get the enum type - case eFormatDecimal: - if (item_byte_size <= 8) - s->Printf ("%" PRId64, GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset)); - else - { - const bool is_signed = true; - const unsigned radix = 10; - offset = DumpAPInt (s, *this, offset, item_byte_size, is_signed, radix); - } + case '\n': + s->Printf("\\n"); break; - - case eFormatUnsigned: - if (item_byte_size <= 8) - s->Printf ("%" PRIu64, GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset)); - else - { - const bool is_signed = false; - const unsigned radix = 10; - offset = DumpAPInt (s, *this, offset, item_byte_size, is_signed, radix); - } + case '\r': + s->Printf("\\r"); break; - - case eFormatOctal: - if (item_byte_size <= 8) - s->Printf ("0%" PRIo64, GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset)); - else - { - const bool is_signed = false; - const unsigned radix = 8; - offset = DumpAPInt (s, *this, offset, item_byte_size, is_signed, radix); - } + case '\t': + s->Printf("\\t"); break; - - case eFormatOSType: - { - uint64_t uval64 = GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset); - s->PutChar('\''); - for (uint32_t i = 0; i < item_byte_size; ++i) - { - uint8_t ch = (uint8_t)(uval64 >> ((item_byte_size - i - 1) * 8)); - if (isprint(ch)) - s->Printf ("%c", ch); - else - { - switch (ch) - { - case '\033': s->Printf ("\\e"); break; - case '\a': s->Printf ("\\a"); break; - case '\b': s->Printf ("\\b"); break; - case '\f': s->Printf ("\\f"); break; - case '\n': s->Printf ("\\n"); break; - case '\r': s->Printf ("\\r"); break; - case '\t': s->Printf ("\\t"); break; - case '\v': s->Printf ("\\v"); break; - case '\0': s->Printf ("\\0"); break; - default: s->Printf ("\\x%2.2x", ch); break; - } - } - } - s->PutChar('\''); - } + case '\v': + s->Printf("\\v"); break; - - case eFormatCString: - { - const char *cstr = GetCStr(&offset); - - if (!cstr) - { - s->Printf("NULL"); - offset = LLDB_INVALID_OFFSET; - } - else - { - s->PutChar('\"'); - - while (const char c = *cstr) - { - if (isprint(c)) - { - s->PutChar(c); - } - else - { - switch (c) - { - case '\033': s->Printf ("\\e"); break; - case '\a': s->Printf ("\\a"); break; - case '\b': s->Printf ("\\b"); break; - case '\f': s->Printf ("\\f"); break; - case '\n': s->Printf ("\\n"); break; - case '\r': s->Printf ("\\r"); break; - case '\t': s->Printf ("\\t"); break; - case '\v': s->Printf ("\\v"); break; - default: s->Printf ("\\x%2.2x", c); break; - } - } - - ++cstr; - } - - s->PutChar('\"'); - } - } + case '\0': + s->Printf("\\0"); break; - - - case eFormatPointer: - s->Address(GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset), sizeof (addr_t)); + default: + s->Printf("\\x%2.2x", ch); break; - - - case eFormatComplexInteger: - { - size_t complex_int_byte_size = item_byte_size / 2; - - if (complex_int_byte_size > 0 && complex_int_byte_size <= 8) - { - s->Printf("%" PRIu64, GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0)); - s->Printf(" + %" PRIu64 "i", GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0)); - } - else - { - s->Printf("error: unsupported byte size (%" PRIu64 ") for complex integer format", (uint64_t)item_byte_size); - return offset; - } - } - break; - - case eFormatComplex: - if (sizeof(float) * 2 == item_byte_size) - { - float f32_1 = GetFloat (&offset); - float f32_2 = GetFloat (&offset); - - s->Printf ("%g + %gi", f32_1, f32_2); - break; + } + } + } + s->PutChar('\''); + } break; + + case eFormatCString: { + const char *cstr = GetCStr(&offset); + + if (!cstr) { + s->Printf("NULL"); + offset = LLDB_INVALID_OFFSET; + } else { + s->PutChar('\"'); + + while (const char c = *cstr) { + if (isprint(c)) { + s->PutChar(c); + } else { + switch (c) { + case '\033': + s->Printf("\\e"); + break; + case '\a': + s->Printf("\\a"); + break; + case '\b': + s->Printf("\\b"); + break; + case '\f': + s->Printf("\\f"); + break; + case '\n': + s->Printf("\\n"); + break; + case '\r': + s->Printf("\\r"); + break; + case '\t': + s->Printf("\\t"); + break; + case '\v': + s->Printf("\\v"); + break; + default: + s->Printf("\\x%2.2x", c); + break; } - else if (sizeof(double) * 2 == item_byte_size) - { - double d64_1 = GetDouble (&offset); - double d64_2 = GetDouble (&offset); + } - s->Printf ("%lg + %lgi", d64_1, d64_2); - break; - } - else if (sizeof(long double) * 2 == item_byte_size) - { - long double ld64_1 = GetLongDouble (&offset); - long double ld64_2 = GetLongDouble (&offset); - s->Printf ("%Lg + %Lgi", ld64_1, ld64_2); - break; - } - else - { - s->Printf("error: unsupported byte size (%" PRIu64 ") for complex float format", (uint64_t)item_byte_size); - return offset; - } - break; + ++cstr; + } - default: - case eFormatDefault: - case eFormatHex: - case eFormatHexUppercase: - { - bool wantsuppercase = (item_format == eFormatHexUppercase); - switch (item_byte_size) - { - case 1: - case 2: - case 4: - case 8: - s->Printf(wantsuppercase ? "0x%*.*" PRIX64 : "0x%*.*" PRIx64, (int)(2 * item_byte_size), (int)(2 * item_byte_size), GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset)); - break; - default: - { - assert (item_bit_size == 0 && item_bit_offset == 0); - const uint8_t *bytes = (const uint8_t* )GetData(&offset, item_byte_size); - if (bytes) - { - s->PutCString("0x"); - uint32_t idx; - if (m_byte_order == eByteOrderBig) - { - for (idx = 0; idx < item_byte_size; ++idx) - s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[idx]); - } - else - { - for (idx = 0; idx < item_byte_size; ++idx) - s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[item_byte_size - 1 - idx]); - } - } - } - break; - } - } - break; + s->PutChar('\"'); + } + } break; + + case eFormatPointer: + s->Address(GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, + item_bit_offset), + sizeof(addr_t)); + break; + + case eFormatComplexInteger: { + size_t complex_int_byte_size = item_byte_size / 2; + + if (complex_int_byte_size > 0 && complex_int_byte_size <= 8) { + s->Printf("%" PRIu64, + GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0)); + s->Printf(" + %" PRIu64 "i", + GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0)); + } else { + s->Printf("error: unsupported byte size (%" PRIu64 + ") for complex integer format", + (uint64_t)item_byte_size); + return offset; + } + } break; - case eFormatFloat: - { - TargetSP target_sp; - bool used_apfloat = false; - if (exe_scope) - target_sp = exe_scope->CalculateTarget(); - if (target_sp) - { - ClangASTContext *clang_ast = target_sp->GetScratchClangASTContext(); - if (clang_ast) - { - clang::ASTContext *ast = clang_ast->getASTContext(); - if (ast) - { - llvm::SmallVector<char, 256> sv; - // Show full precision when printing float values - const unsigned format_precision = 0; - const unsigned format_max_padding = 100; - size_t item_bit_size = item_byte_size * 8; - - if (item_bit_size == ast->getTypeSize(ast->FloatTy)) - { - llvm::APInt apint(item_bit_size, this->GetMaxU64(&offset, item_byte_size)); - llvm::APFloat apfloat (ast->getFloatTypeSemantics(ast->FloatTy), apint); - apfloat.toString(sv, format_precision, format_max_padding); - } - else if (item_bit_size == ast->getTypeSize(ast->DoubleTy)) - { - llvm::APInt apint; - if (GetAPInt (*this, &offset, item_byte_size, apint)) - { - llvm::APFloat apfloat (ast->getFloatTypeSemantics(ast->DoubleTy), apint); - apfloat.toString(sv, format_precision, format_max_padding); - } - } - else if (item_bit_size == ast->getTypeSize(ast->LongDoubleTy)) - { - const auto &semantics = ast->getFloatTypeSemantics(ast->LongDoubleTy); - const auto byte_size = (llvm::APFloat::getSizeInBits(semantics) + 7) / 8; - - llvm::APInt apint; - if (GetAPInt(*this, &offset, byte_size, apint)) - { - llvm::APFloat apfloat(semantics, apint); - apfloat.toString(sv, format_precision, format_max_padding); - } - } - else if (item_bit_size == ast->getTypeSize(ast->HalfTy)) - { - llvm::APInt apint(item_bit_size, this->GetU16(&offset)); - llvm::APFloat apfloat (ast->getFloatTypeSemantics(ast->HalfTy), apint); - apfloat.toString(sv, format_precision, format_max_padding); - } - - if (!sv.empty()) - { - s->Printf("%*.*s", (int)sv.size(), (int)sv.size(), sv.data()); - used_apfloat = true; - } - } - } - } - - if (!used_apfloat) - { - std::ostringstream ss; - if (item_byte_size == sizeof(float) || item_byte_size == 2) - { - float f; - if (item_byte_size == 2) - { - uint16_t half = this->GetU16(&offset); - f = half2float(half); - } - else - { - f = GetFloat (&offset); - } - ss.precision(std::numeric_limits<float>::digits10); - ss << f; - } - else if (item_byte_size == sizeof(double)) - { - ss.precision(std::numeric_limits<double>::digits10); - ss << GetDouble(&offset); - } - else if (item_byte_size == sizeof(long double) || item_byte_size == 10) - { - ss.precision(std::numeric_limits<long double>::digits10); - ss << GetLongDouble(&offset); - } - else - { - s->Printf("error: unsupported byte size (%" PRIu64 ") for float format", (uint64_t)item_byte_size); - return offset; - } - ss.flush(); - s->Printf("%s", ss.str().c_str()); - } - } - break; + case eFormatComplex: + if (sizeof(float) * 2 == item_byte_size) { + float f32_1 = GetFloat(&offset); + float f32_2 = GetFloat(&offset); - case eFormatUnicode16: - s->Printf("U+%4.4x", GetU16 (&offset)); - break; + s->Printf("%g + %gi", f32_1, f32_2); + break; + } else if (sizeof(double) * 2 == item_byte_size) { + double d64_1 = GetDouble(&offset); + double d64_2 = GetDouble(&offset); - case eFormatUnicode32: - s->Printf("U+0x%8.8x", GetU32 (&offset)); - break; + s->Printf("%lg + %lgi", d64_1, d64_2); + break; + } else if (sizeof(long double) * 2 == item_byte_size) { + long double ld64_1 = GetLongDouble(&offset); + long double ld64_2 = GetLongDouble(&offset); + s->Printf("%Lg + %Lgi", ld64_1, ld64_2); + break; + } else { + s->Printf("error: unsupported byte size (%" PRIu64 + ") for complex float format", + (uint64_t)item_byte_size); + return offset; + } + break; - case eFormatAddressInfo: - { - addr_t addr = GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset); - s->Printf("0x%*.*" PRIx64, (int)(2 * item_byte_size), (int)(2 * item_byte_size), addr); - if (exe_scope) - { - TargetSP target_sp (exe_scope->CalculateTarget()); - lldb_private::Address so_addr; - if (target_sp) - { - if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) - { - s->PutChar(' '); - so_addr.Dump (s, - exe_scope, - Address::DumpStyleResolvedDescription, - Address::DumpStyleModuleWithFileAddress); - } - else - { - so_addr.SetOffset(addr); - so_addr.Dump (s, exe_scope, Address::DumpStyleResolvedPointerDescription); - } - } - } + default: + case eFormatDefault: + case eFormatHex: + case eFormatHexUppercase: { + bool wantsuppercase = (item_format == eFormatHexUppercase); + switch (item_byte_size) { + case 1: + case 2: + case 4: + case 8: + s->Printf(wantsuppercase ? "0x%*.*" PRIX64 : "0x%*.*" PRIx64, + (int)(2 * item_byte_size), (int)(2 * item_byte_size), + GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, + item_bit_offset)); + break; + default: { + assert(item_bit_size == 0 && item_bit_offset == 0); + const uint8_t *bytes = + (const uint8_t *)GetData(&offset, item_byte_size); + if (bytes) { + s->PutCString("0x"); + uint32_t idx; + if (m_byte_order == eByteOrderBig) { + for (idx = 0; idx < item_byte_size; ++idx) + s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[idx]); + } else { + for (idx = 0; idx < item_byte_size; ++idx) + s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", + bytes[item_byte_size - 1 - idx]); + } + } + } break; + } + } break; + + case eFormatFloat: { + TargetSP target_sp; + bool used_apfloat = false; + if (exe_scope) + target_sp = exe_scope->CalculateTarget(); + if (target_sp) { + ClangASTContext *clang_ast = target_sp->GetScratchClangASTContext(); + if (clang_ast) { + clang::ASTContext *ast = clang_ast->getASTContext(); + if (ast) { + llvm::SmallVector<char, 256> sv; + // Show full precision when printing float values + const unsigned format_precision = 0; + const unsigned format_max_padding = 100; + size_t item_bit_size = item_byte_size * 8; + + if (item_bit_size == ast->getTypeSize(ast->FloatTy)) { + llvm::APInt apint(item_bit_size, + this->GetMaxU64(&offset, item_byte_size)); + llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->FloatTy), + apint); + apfloat.toString(sv, format_precision, format_max_padding); + } else if (item_bit_size == ast->getTypeSize(ast->DoubleTy)) { + llvm::APInt apint; + if (GetAPInt(*this, &offset, item_byte_size, apint)) { + llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->DoubleTy), + apint); + apfloat.toString(sv, format_precision, format_max_padding); + } + } else if (item_bit_size == ast->getTypeSize(ast->LongDoubleTy)) { + const auto &semantics = + ast->getFloatTypeSemantics(ast->LongDoubleTy); + const auto byte_size = + (llvm::APFloat::getSizeInBits(semantics) + 7) / 8; + + llvm::APInt apint; + if (GetAPInt(*this, &offset, byte_size, apint)) { + llvm::APFloat apfloat(semantics, apint); + apfloat.toString(sv, format_precision, format_max_padding); + } + } else if (item_bit_size == ast->getTypeSize(ast->HalfTy)) { + llvm::APInt apint(item_bit_size, this->GetU16(&offset)); + llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->HalfTy), + apint); + apfloat.toString(sv, format_precision, format_max_padding); } - break; - case eFormatHexFloat: - if (sizeof(float) == item_byte_size) - { - char float_cstr[256]; - llvm::APFloat ap_float (GetFloat (&offset)); - ap_float.convertToHexString (float_cstr, 0, false, llvm::APFloat::rmNearestTiesToEven); - s->Printf ("%s", float_cstr); - break; - } - else if (sizeof(double) == item_byte_size) - { - char float_cstr[256]; - llvm::APFloat ap_float (GetDouble (&offset)); - ap_float.convertToHexString (float_cstr, 0, false, llvm::APFloat::rmNearestTiesToEven); - s->Printf ("%s", float_cstr); - break; + if (!sv.empty()) { + s->Printf("%*.*s", (int)sv.size(), (int)sv.size(), sv.data()); + used_apfloat = true; } - else - { - s->Printf("error: unsupported byte size (%" PRIu64 ") for hex float format", (uint64_t)item_byte_size); - return offset; - } - break; - -// please keep the single-item formats below in sync with FormatManager::GetSingleItemFormat -// if you fail to do so, users will start getting different outputs depending on internal -// implementation details they should not care about || - case eFormatVectorOfChar: // || - s->PutChar('{'); // \/ - offset = Dump (s, offset, eFormatCharArray, 1, item_byte_size, item_byte_size, LLDB_INVALID_ADDRESS, 0, 0); - s->PutChar('}'); - break; - - case eFormatVectorOfSInt8: - s->PutChar('{'); - offset = Dump (s, offset, eFormatDecimal, 1, item_byte_size, item_byte_size, LLDB_INVALID_ADDRESS, 0, 0); - s->PutChar('}'); - break; - - case eFormatVectorOfUInt8: - s->PutChar('{'); - offset = Dump (s, offset, eFormatHex, 1, item_byte_size, item_byte_size, LLDB_INVALID_ADDRESS, 0, 0); - s->PutChar('}'); - break; - - case eFormatVectorOfSInt16: - s->PutChar('{'); - offset = Dump (s, offset, eFormatDecimal, sizeof(uint16_t), item_byte_size / sizeof(uint16_t), item_byte_size / sizeof(uint16_t), LLDB_INVALID_ADDRESS, 0, 0); - s->PutChar('}'); - break; - - case eFormatVectorOfUInt16: - s->PutChar('{'); - offset = Dump (s, offset, eFormatHex, sizeof(uint16_t), item_byte_size / sizeof(uint16_t), item_byte_size / sizeof(uint16_t), LLDB_INVALID_ADDRESS, 0, 0); - s->PutChar('}'); - break; - - case eFormatVectorOfSInt32: - s->PutChar('{'); - offset = Dump (s, offset, eFormatDecimal, sizeof(uint32_t), item_byte_size / sizeof(uint32_t), item_byte_size / sizeof(uint32_t), LLDB_INVALID_ADDRESS, 0, 0); - s->PutChar('}'); - break; - - case eFormatVectorOfUInt32: - s->PutChar('{'); - offset = Dump (s, offset, eFormatHex, sizeof(uint32_t), item_byte_size / sizeof(uint32_t), item_byte_size / sizeof(uint32_t), LLDB_INVALID_ADDRESS, 0, 0); - s->PutChar('}'); - break; - - case eFormatVectorOfSInt64: - s->PutChar('{'); - offset = Dump (s, offset, eFormatDecimal, sizeof(uint64_t), item_byte_size / sizeof(uint64_t), item_byte_size / sizeof(uint64_t), LLDB_INVALID_ADDRESS, 0, 0); - s->PutChar('}'); - break; - - case eFormatVectorOfUInt64: - s->PutChar('{'); - offset = Dump (s, offset, eFormatHex, sizeof(uint64_t), item_byte_size / sizeof(uint64_t), item_byte_size / sizeof(uint64_t), LLDB_INVALID_ADDRESS, 0, 0); - s->PutChar('}'); - break; - - case eFormatVectorOfFloat16: - s->PutChar('{'); - offset = Dump (s, offset, eFormatFloat, 2, item_byte_size / 2, item_byte_size / 2, LLDB_INVALID_ADDRESS, 0, 0); - s->PutChar('}'); - break; - - case eFormatVectorOfFloat32: - s->PutChar('{'); - offset = Dump (s, offset, eFormatFloat, 4, item_byte_size / 4, item_byte_size / 4, LLDB_INVALID_ADDRESS, 0, 0); - s->PutChar('}'); - break; - - case eFormatVectorOfFloat64: - s->PutChar('{'); - offset = Dump (s, offset, eFormatFloat, 8, item_byte_size / 8, item_byte_size / 8, LLDB_INVALID_ADDRESS, 0, 0); - s->PutChar('}'); - break; - - case eFormatVectorOfUInt128: - s->PutChar('{'); - offset = Dump (s, offset, eFormatHex, 16, item_byte_size / 16, item_byte_size / 16, LLDB_INVALID_ADDRESS, 0, 0); - s->PutChar('}'); - break; + } + } + } + + if (!used_apfloat) { + std::ostringstream ss; + if (item_byte_size == sizeof(float) || item_byte_size == 2) { + float f; + if (item_byte_size == 2) { + uint16_t half = this->GetU16(&offset); + f = half2float(half); + } else { + f = GetFloat(&offset); + } + ss.precision(std::numeric_limits<float>::digits10); + ss << f; + } else if (item_byte_size == sizeof(double)) { + ss.precision(std::numeric_limits<double>::digits10); + ss << GetDouble(&offset); + } else if (item_byte_size == sizeof(long double) || + item_byte_size == 10) { + ss.precision(std::numeric_limits<long double>::digits10); + ss << GetLongDouble(&offset); + } else { + s->Printf("error: unsupported byte size (%" PRIu64 + ") for float format", + (uint64_t)item_byte_size); + return offset; + } + ss.flush(); + s->Printf("%s", ss.str().c_str()); + } + } break; + + case eFormatUnicode16: + s->Printf("U+%4.4x", GetU16(&offset)); + break; + + case eFormatUnicode32: + s->Printf("U+0x%8.8x", GetU32(&offset)); + break; + + case eFormatAddressInfo: { + addr_t addr = GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, + item_bit_offset); + s->Printf("0x%*.*" PRIx64, (int)(2 * item_byte_size), + (int)(2 * item_byte_size), addr); + if (exe_scope) { + TargetSP target_sp(exe_scope->CalculateTarget()); + lldb_private::Address so_addr; + if (target_sp) { + if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, + so_addr)) { + s->PutChar(' '); + so_addr.Dump(s, exe_scope, Address::DumpStyleResolvedDescription, + Address::DumpStyleModuleWithFileAddress); + } else { + so_addr.SetOffset(addr); + so_addr.Dump(s, exe_scope, + Address::DumpStyleResolvedPointerDescription); + } } + } + } break; + + case eFormatHexFloat: + if (sizeof(float) == item_byte_size) { + char float_cstr[256]; + llvm::APFloat ap_float(GetFloat(&offset)); + ap_float.convertToHexString(float_cstr, 0, false, + llvm::APFloat::rmNearestTiesToEven); + s->Printf("%s", float_cstr); + break; + } else if (sizeof(double) == item_byte_size) { + char float_cstr[256]; + llvm::APFloat ap_float(GetDouble(&offset)); + ap_float.convertToHexString(float_cstr, 0, false, + llvm::APFloat::rmNearestTiesToEven); + s->Printf("%s", float_cstr); + break; + } else { + s->Printf("error: unsupported byte size (%" PRIu64 + ") for hex float format", + (uint64_t)item_byte_size); + return offset; + } + break; + + // please keep the single-item formats below in sync with + // FormatManager::GetSingleItemFormat + // if you fail to do so, users will start getting different outputs + // depending on internal + // implementation details they should not care about || + case eFormatVectorOfChar: // || + s->PutChar('{'); // \/ + offset = Dump(s, offset, eFormatCharArray, 1, item_byte_size, + item_byte_size, LLDB_INVALID_ADDRESS, 0, 0); + s->PutChar('}'); + break; + + case eFormatVectorOfSInt8: + s->PutChar('{'); + offset = Dump(s, offset, eFormatDecimal, 1, item_byte_size, + item_byte_size, LLDB_INVALID_ADDRESS, 0, 0); + s->PutChar('}'); + break; + + case eFormatVectorOfUInt8: + s->PutChar('{'); + offset = Dump(s, offset, eFormatHex, 1, item_byte_size, item_byte_size, + LLDB_INVALID_ADDRESS, 0, 0); + s->PutChar('}'); + break; + + case eFormatVectorOfSInt16: + s->PutChar('{'); + offset = + Dump(s, offset, eFormatDecimal, sizeof(uint16_t), + item_byte_size / sizeof(uint16_t), + item_byte_size / sizeof(uint16_t), LLDB_INVALID_ADDRESS, 0, 0); + s->PutChar('}'); + break; + + case eFormatVectorOfUInt16: + s->PutChar('{'); + offset = + Dump(s, offset, eFormatHex, sizeof(uint16_t), + item_byte_size / sizeof(uint16_t), + item_byte_size / sizeof(uint16_t), LLDB_INVALID_ADDRESS, 0, 0); + s->PutChar('}'); + break; + + case eFormatVectorOfSInt32: + s->PutChar('{'); + offset = + Dump(s, offset, eFormatDecimal, sizeof(uint32_t), + item_byte_size / sizeof(uint32_t), + item_byte_size / sizeof(uint32_t), LLDB_INVALID_ADDRESS, 0, 0); + s->PutChar('}'); + break; + + case eFormatVectorOfUInt32: + s->PutChar('{'); + offset = + Dump(s, offset, eFormatHex, sizeof(uint32_t), + item_byte_size / sizeof(uint32_t), + item_byte_size / sizeof(uint32_t), LLDB_INVALID_ADDRESS, 0, 0); + s->PutChar('}'); + break; + + case eFormatVectorOfSInt64: + s->PutChar('{'); + offset = + Dump(s, offset, eFormatDecimal, sizeof(uint64_t), + item_byte_size / sizeof(uint64_t), + item_byte_size / sizeof(uint64_t), LLDB_INVALID_ADDRESS, 0, 0); + s->PutChar('}'); + break; + + case eFormatVectorOfUInt64: + s->PutChar('{'); + offset = + Dump(s, offset, eFormatHex, sizeof(uint64_t), + item_byte_size / sizeof(uint64_t), + item_byte_size / sizeof(uint64_t), LLDB_INVALID_ADDRESS, 0, 0); + s->PutChar('}'); + break; + + case eFormatVectorOfFloat16: + s->PutChar('{'); + offset = Dump(s, offset, eFormatFloat, 2, item_byte_size / 2, + item_byte_size / 2, LLDB_INVALID_ADDRESS, 0, 0); + s->PutChar('}'); + break; + + case eFormatVectorOfFloat32: + s->PutChar('{'); + offset = Dump(s, offset, eFormatFloat, 4, item_byte_size / 4, + item_byte_size / 4, LLDB_INVALID_ADDRESS, 0, 0); + s->PutChar('}'); + break; + + case eFormatVectorOfFloat64: + s->PutChar('{'); + offset = Dump(s, offset, eFormatFloat, 8, item_byte_size / 8, + item_byte_size / 8, LLDB_INVALID_ADDRESS, 0, 0); + s->PutChar('}'); + break; + + case eFormatVectorOfUInt128: + s->PutChar('{'); + offset = Dump(s, offset, eFormatHex, 16, item_byte_size / 16, + item_byte_size / 16, LLDB_INVALID_ADDRESS, 0, 0); + s->PutChar('}'); + break; } + } - if (item_format == eFormatBytesWithASCII && offset > line_start_offset) - { - s->Printf("%*s", static_cast<int>((num_per_line - (offset - line_start_offset)) * 3 + 2), ""); - Dump(s, line_start_offset, eFormatCharPrintable, 1, offset - line_start_offset, SIZE_MAX, LLDB_INVALID_ADDRESS, 0, 0); - } - return offset; // Return the offset at which we ended up + if (item_format == eFormatBytesWithASCII && offset > line_start_offset) { + s->Printf("%*s", static_cast<int>( + (num_per_line - (offset - line_start_offset)) * 3 + 2), + ""); + Dump(s, line_start_offset, eFormatCharPrintable, 1, + offset - line_start_offset, SIZE_MAX, LLDB_INVALID_ADDRESS, 0, 0); + } + return offset; // Return the offset at which we ended up } //---------------------------------------------------------------------- @@ -2073,59 +1964,65 @@ DataExtractor::Dump (Stream *s, // string will be used for the supplied "type". If the stream "s" // is nullptr, then the output will be send to Log(). //---------------------------------------------------------------------- -lldb::offset_t -DataExtractor::PutToLog(Log *log, - offset_t start_offset, - offset_t length, - uint64_t base_addr, - uint32_t num_per_line, - DataExtractor::Type type, - const char *format) const -{ - if (log == nullptr) - return start_offset; - - offset_t offset; - offset_t end_offset; - uint32_t count; - StreamString sstr; - for (offset = start_offset, end_offset = offset + length, count = 0; ValidOffset(offset) && offset < end_offset; ++count) - { - if ((count % num_per_line) == 0) - { - // Print out any previous string - if (sstr.GetSize() > 0) - { - log->Printf("%s", sstr.GetData()); - sstr.Clear(); - } - // Reset string offset and fill the current line string with address: - if (base_addr != LLDB_INVALID_ADDRESS) - sstr.Printf("0x%8.8" PRIx64 ":", (uint64_t)(base_addr + (offset - start_offset))); - } +lldb::offset_t DataExtractor::PutToLog(Log *log, offset_t start_offset, + offset_t length, uint64_t base_addr, + uint32_t num_per_line, + DataExtractor::Type type, + const char *format) const { + if (log == nullptr) + return start_offset; + + offset_t offset; + offset_t end_offset; + uint32_t count; + StreamString sstr; + for (offset = start_offset, end_offset = offset + length, count = 0; + ValidOffset(offset) && offset < end_offset; ++count) { + if ((count % num_per_line) == 0) { + // Print out any previous string + if (sstr.GetSize() > 0) { + log->PutString(sstr.GetString()); + sstr.Clear(); + } + // Reset string offset and fill the current line string with address: + if (base_addr != LLDB_INVALID_ADDRESS) + sstr.Printf("0x%8.8" PRIx64 ":", + (uint64_t)(base_addr + (offset - start_offset))); + } - switch (type) - { - case TypeUInt8: sstr.Printf (format ? format : " %2.2x", GetU8(&offset)); break; - case TypeChar: - { - char ch = GetU8(&offset); - sstr.Printf (format ? format : " %c", isprint(ch) ? ch : ' '); - } - break; - case TypeUInt16: sstr.Printf (format ? format : " %4.4x", GetU16(&offset)); break; - case TypeUInt32: sstr.Printf (format ? format : " %8.8x", GetU32(&offset)); break; - case TypeUInt64: sstr.Printf (format ? format : " %16.16" PRIx64, GetU64(&offset)); break; - case TypePointer: sstr.Printf (format ? format : " 0x%" PRIx64, GetAddress(&offset)); break; - case TypeULEB128: sstr.Printf (format ? format : " 0x%" PRIx64, GetULEB128(&offset)); break; - case TypeSLEB128: sstr.Printf (format ? format : " %" PRId64, GetSLEB128(&offset)); break; - } + switch (type) { + case TypeUInt8: + sstr.Printf(format ? format : " %2.2x", GetU8(&offset)); + break; + case TypeChar: { + char ch = GetU8(&offset); + sstr.Printf(format ? format : " %c", isprint(ch) ? ch : ' '); + } break; + case TypeUInt16: + sstr.Printf(format ? format : " %4.4x", GetU16(&offset)); + break; + case TypeUInt32: + sstr.Printf(format ? format : " %8.8x", GetU32(&offset)); + break; + case TypeUInt64: + sstr.Printf(format ? format : " %16.16" PRIx64, GetU64(&offset)); + break; + case TypePointer: + sstr.Printf(format ? format : " 0x%" PRIx64, GetAddress(&offset)); + break; + case TypeULEB128: + sstr.Printf(format ? format : " 0x%" PRIx64, GetULEB128(&offset)); + break; + case TypeSLEB128: + sstr.Printf(format ? format : " %" PRId64, GetSLEB128(&offset)); + break; } + } - if (sstr.GetSize() > 0) - log->Printf("%s", sstr.GetData()); + if (!sstr.Empty()) + log->PutString(sstr.GetString()); - return offset; // Return the offset at which we ended up + return offset; // Return the offset at which we ended up } //---------------------------------------------------------------------- @@ -2133,137 +2030,114 @@ DataExtractor::PutToLog(Log *log, // // Dump out a UUID starting at 'offset' bytes into the buffer //---------------------------------------------------------------------- -void -DataExtractor::DumpUUID (Stream *s, offset_t offset) const -{ - if (s) - { - const uint8_t *uuid_data = PeekData(offset, 16); - if ( uuid_data ) - { - lldb_private::UUID uuid(uuid_data, 16); - uuid.Dump(s); - } - else - { - s->Printf("<not enough data for UUID at offset 0x%8.8" PRIx64 ">", offset); - } +void DataExtractor::DumpUUID(Stream *s, offset_t offset) const { + if (s) { + const uint8_t *uuid_data = PeekData(offset, 16); + if (uuid_data) { + lldb_private::UUID uuid(uuid_data, 16); + uuid.Dump(s); + } else { + s->Printf("<not enough data for UUID at offset 0x%8.8" PRIx64 ">", + offset); } -} - -void -DataExtractor::DumpHexBytes (Stream *s, - const void *src, - size_t src_len, - uint32_t bytes_per_line, - addr_t base_addr) -{ - DataExtractor data (src, src_len, eByteOrderLittle, 4); - data.Dump (s, - 0, // Offset into "src" - eFormatBytes, // Dump as hex bytes - 1, // Size of each item is 1 for single bytes - src_len, // Number of bytes - bytes_per_line, // Num bytes per line - base_addr, // Base address - 0, 0); // Bitfield info -} - -size_t -DataExtractor::Copy (DataExtractor &dest_data) const -{ - if (m_data_sp) - { - // we can pass along the SP to the data - dest_data.SetData(m_data_sp); - } - else - { - const uint8_t *base_ptr = m_start; - size_t data_size = GetByteSize(); - dest_data.SetData(DataBufferSP(new DataBufferHeap(base_ptr, data_size))); - } - return GetByteSize(); -} + } +} + +void DataExtractor::DumpHexBytes(Stream *s, const void *src, size_t src_len, + uint32_t bytes_per_line, addr_t base_addr) { + DataExtractor data(src, src_len, eByteOrderLittle, 4); + data.Dump(s, + 0, // Offset into "src" + eFormatBytes, // Dump as hex bytes + 1, // Size of each item is 1 for single bytes + src_len, // Number of bytes + bytes_per_line, // Num bytes per line + base_addr, // Base address + 0, 0); // Bitfield info +} + +size_t DataExtractor::Copy(DataExtractor &dest_data) const { + if (m_data_sp) { + // we can pass along the SP to the data + dest_data.SetData(m_data_sp); + } else { + const uint8_t *base_ptr = m_start; + size_t data_size = GetByteSize(); + dest_data.SetData(DataBufferSP(new DataBufferHeap(base_ptr, data_size))); + } + return GetByteSize(); +} + +bool DataExtractor::Append(DataExtractor &rhs) { + if (rhs.GetByteOrder() != GetByteOrder()) + return false; -bool -DataExtractor::Append(DataExtractor& rhs) -{ - if (rhs.GetByteOrder() != GetByteOrder()) - return false; - - if (rhs.GetByteSize() == 0) - return true; - - if (GetByteSize() == 0) - return (rhs.Copy(*this) > 0); - - size_t bytes = GetByteSize() + rhs.GetByteSize(); - - DataBufferHeap *buffer_heap_ptr = nullptr; - DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0)); - - if (!buffer_sp || buffer_heap_ptr == nullptr) - return false; - - uint8_t* bytes_ptr = buffer_heap_ptr->GetBytes(); - - memcpy(bytes_ptr, GetDataStart(), GetByteSize()); - memcpy(bytes_ptr + GetByteSize(), rhs.GetDataStart(), rhs.GetByteSize()); - - SetData(buffer_sp); - + if (rhs.GetByteSize() == 0) return true; + + if (GetByteSize() == 0) + return (rhs.Copy(*this) > 0); + + size_t bytes = GetByteSize() + rhs.GetByteSize(); + + DataBufferHeap *buffer_heap_ptr = nullptr; + DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0)); + + if (!buffer_sp || buffer_heap_ptr == nullptr) + return false; + + uint8_t *bytes_ptr = buffer_heap_ptr->GetBytes(); + + memcpy(bytes_ptr, GetDataStart(), GetByteSize()); + memcpy(bytes_ptr + GetByteSize(), rhs.GetDataStart(), rhs.GetByteSize()); + + SetData(buffer_sp); + + return true; } -bool -DataExtractor::Append(void* buf, offset_t length) -{ - if (buf == nullptr) - return false; - - if (length == 0) - return true; - - size_t bytes = GetByteSize() + length; - - DataBufferHeap *buffer_heap_ptr = nullptr; - DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0)); - - if (!buffer_sp || buffer_heap_ptr == nullptr) - return false; - - uint8_t* bytes_ptr = buffer_heap_ptr->GetBytes(); - - if (GetByteSize() > 0) - memcpy(bytes_ptr, GetDataStart(), GetByteSize()); - - memcpy(bytes_ptr + GetByteSize(), buf, length); - - SetData(buffer_sp); - +bool DataExtractor::Append(void *buf, offset_t length) { + if (buf == nullptr) + return false; + + if (length == 0) return true; + + size_t bytes = GetByteSize() + length; + + DataBufferHeap *buffer_heap_ptr = nullptr; + DataBufferSP buffer_sp(buffer_heap_ptr = new DataBufferHeap(bytes, 0)); + + if (!buffer_sp || buffer_heap_ptr == nullptr) + return false; + + uint8_t *bytes_ptr = buffer_heap_ptr->GetBytes(); + + if (GetByteSize() > 0) + memcpy(bytes_ptr, GetDataStart(), GetByteSize()); + + memcpy(bytes_ptr + GetByteSize(), buf, length); + + SetData(buffer_sp); + + return true; } -void -DataExtractor::Checksum (llvm::SmallVectorImpl<uint8_t> &dest, - uint64_t max_data) -{ - if (max_data == 0) - max_data = GetByteSize(); - else - max_data = std::min(max_data, GetByteSize()); +void DataExtractor::Checksum(llvm::SmallVectorImpl<uint8_t> &dest, + uint64_t max_data) { + if (max_data == 0) + max_data = GetByteSize(); + else + max_data = std::min(max_data, GetByteSize()); - llvm::MD5 md5; + llvm::MD5 md5; - const llvm::ArrayRef<uint8_t> data(GetDataStart(),max_data); - md5.update(data); + const llvm::ArrayRef<uint8_t> data(GetDataStart(), max_data); + md5.update(data); - llvm::MD5::MD5Result result; - md5.final(result); + llvm::MD5::MD5Result result; + md5.final(result); - dest.resize(16); - std::copy(result, - result+16, - dest.begin()); + dest.resize(16); + std::copy(result, result + 16, dest.begin()); } diff --git a/source/Core/Debugger.cpp b/source/Core/Debugger.cpp index 34608d0193fc..8f888a518d5b 100644 --- a/source/Core/Debugger.cpp +++ b/source/Core/Debugger.cpp @@ -19,7 +19,6 @@ #include "llvm/Support/DynamicLibrary.h" // Project includes -#include "lldb/lldb-private.h" #include "lldb/Core/FormatEntity.h" #include "lldb/Core/Module.h" #include "lldb/Core/PluginInterface.h" @@ -50,15 +49,17 @@ #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/VariableList.h" -#include "lldb/Target/TargetList.h" #include "lldb/Target/Language.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/StopInfo.h" +#include "lldb/Target/StructuredDataPlugin.h" #include "lldb/Target/Target.h" +#include "lldb/Target/TargetList.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/AnsiTerminal.h" +#include "lldb/lldb-private.h" using namespace lldb; using namespace lldb_private; @@ -69,1124 +70,1052 @@ static size_t g_debugger_event_thread_stack_bytes = 8 * 1024 * 1024; #pragma mark Static Functions typedef std::vector<DebuggerSP> DebuggerList; -static std::recursive_mutex *g_debugger_list_mutex_ptr = nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain -static DebuggerList *g_debugger_list_ptr = nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain - -OptionEnumValueElement -g_show_disassembly_enum_values[] = -{ - { Debugger::eStopDisassemblyTypeNever, "never", "Never show disassembly when displaying a stop context."}, - { Debugger::eStopDisassemblyTypeNoDebugInfo, "no-debuginfo", "Show disassembly when there is no debug information."}, - { Debugger::eStopDisassemblyTypeNoSource, "no-source", "Show disassembly when there is no source information, or the source file is missing when displaying a stop context."}, - { Debugger::eStopDisassemblyTypeAlways, "always", "Always show disassembly when displaying a stop context."}, - { 0, nullptr, nullptr } -}; - -OptionEnumValueElement -g_language_enumerators[] = -{ - { eScriptLanguageNone, "none", "Disable scripting languages."}, - { eScriptLanguagePython, "python", "Select python as the default scripting language."}, - { eScriptLanguageDefault, "default", "Select the lldb default as the default scripting language."}, - { 0, nullptr, nullptr } -}; - -#define MODULE_WITH_FUNC "{ ${module.file.basename}{`${function.name-with-args}${function.pc-offset}}}" +static std::recursive_mutex *g_debugger_list_mutex_ptr = + nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain +static DebuggerList *g_debugger_list_ptr = + nullptr; // NOTE: intentional leak to avoid issues with C++ destructor chain + +OptionEnumValueElement g_show_disassembly_enum_values[] = { + {Debugger::eStopDisassemblyTypeNever, "never", + "Never show disassembly when displaying a stop context."}, + {Debugger::eStopDisassemblyTypeNoDebugInfo, "no-debuginfo", + "Show disassembly when there is no debug information."}, + {Debugger::eStopDisassemblyTypeNoSource, "no-source", + "Show disassembly when there is no source information, or the source file " + "is missing when displaying a stop context."}, + {Debugger::eStopDisassemblyTypeAlways, "always", + "Always show disassembly when displaying a stop context."}, + {0, nullptr, nullptr}}; + +OptionEnumValueElement g_language_enumerators[] = { + {eScriptLanguageNone, "none", "Disable scripting languages."}, + {eScriptLanguagePython, "python", + "Select python as the default scripting language."}, + {eScriptLanguageDefault, "default", + "Select the lldb default as the default scripting language."}, + {0, nullptr, nullptr}}; + +#define MODULE_WITH_FUNC \ + "{ " \ + "${module.file.basename}{`${function.name-with-args}" \ + "{${frame.no-debug}${function.pc-offset}}}}" #define FILE_AND_LINE "{ at ${line.file.basename}:${line.number}}" #define IS_OPTIMIZED "{${function.is-optimized} [opt]}" -#define DEFAULT_THREAD_FORMAT "thread #${thread.index}: tid = ${thread.id%tid}"\ - "{, ${frame.pc}}"\ - MODULE_WITH_FUNC\ - FILE_AND_LINE\ - "{, name = '${thread.name}'}"\ - "{, queue = '${thread.queue}'}"\ - "{, activity = '${thread.info.activity.name}'}" \ - "{, ${thread.info.trace_messages} messages}" \ - "{, stop reason = ${thread.stop-reason}}"\ - "{\\nReturn value: ${thread.return-value}}"\ - "{\\nCompleted expression: ${thread.completed-expression}}"\ - "\\n" - -#define DEFAULT_FRAME_FORMAT "frame #${frame.index}: ${frame.pc}"\ - MODULE_WITH_FUNC\ - FILE_AND_LINE\ - IS_OPTIMIZED\ - "\\n" +#define DEFAULT_THREAD_FORMAT \ + "thread #${thread.index}: tid = ${thread.id%tid}" \ + "{, ${frame.pc}}" MODULE_WITH_FUNC FILE_AND_LINE \ + "{, name = '${thread.name}'}" \ + "{, queue = '${thread.queue}'}" \ + "{, activity = '${thread.info.activity.name}'}" \ + "{, ${thread.info.trace_messages} messages}" \ + "{, stop reason = ${thread.stop-reason}}" \ + "{\\nReturn value: ${thread.return-value}}" \ + "{\\nCompleted expression: ${thread.completed-expression}}" \ + "\\n" + +#define DEFAULT_THREAD_STOP_FORMAT \ + "thread #${thread.index}{, name = '${thread.name}'}" \ + "{, queue = '${thread.queue}'}" \ + "{, activity = '${thread.info.activity.name}'}" \ + "{, ${thread.info.trace_messages} messages}" \ + "{, stop reason = ${thread.stop-reason}}" \ + "{\\nReturn value: ${thread.return-value}}" \ + "{\\nCompleted expression: ${thread.completed-expression}}" \ + "\\n" + +#define DEFAULT_FRAME_FORMAT \ + "frame #${frame.index}:{ ${frame.no-debug}${frame.pc}}" MODULE_WITH_FUNC FILE_AND_LINE \ + IS_OPTIMIZED "\\n" // Three parts to this disassembly format specification: // 1. If this is a new function/symbol (no previous symbol/function), print // dylib`funcname:\n -// 2. If this is a symbol context change (different from previous symbol/function), print +// 2. If this is a symbol context change (different from previous +// symbol/function), print // dylib`funcname:\n -// 3. print -// address <+offset>: -#define DEFAULT_DISASSEMBLY_FORMAT "{${function.initial-function}{${module.file.basename}`}{${function.name-without-args}}:\n}{${function.changed}\n{${module.file.basename}`}{${function.name-without-args}}:\n}{${current-pc-arrow} }${addr-file-or-load}{ <${function.concrete-only-addr-offset-no-padding}>}: " +// 3. print +// address <+offset>: +#define DEFAULT_DISASSEMBLY_FORMAT \ + "{${function.initial-function}{${module.file.basename}`}{${function.name-" \ + "without-args}}:\n}{${function.changed}\n{${module.file.basename}`}{${" \ + "function.name-without-args}}:\n}{${current-pc-arrow} " \ + "}${addr-file-or-load}{ " \ + "<${function.concrete-only-addr-offset-no-padding}>}: " // gdb's disassembly format can be emulated with -// ${current-pc-arrow}${addr-file-or-load}{ <${function.name-without-args}${function.concrete-only-addr-offset-no-padding}>}: +// ${current-pc-arrow}${addr-file-or-load}{ +// <${function.name-without-args}${function.concrete-only-addr-offset-no-padding}>}: // lldb's original format for disassembly would look like this format string - -// {${function.initial-function}{${module.file.basename}`}{${function.name-without-args}}:\n}{${function.changed}\n{${module.file.basename}`}{${function.name-without-args}}:\n}{${current-pc-arrow} }{${addr-file-or-load}}: - -static PropertyDefinition -g_properties[] = -{ -{ "auto-confirm", OptionValue::eTypeBoolean , true, false, nullptr, nullptr, "If true all confirmation prompts will receive their default reply." }, -{ "disassembly-format", OptionValue::eTypeFormatEntity, true, 0 , DEFAULT_DISASSEMBLY_FORMAT, nullptr, "The default disassembly format string to use when disassembling instruction sequences." }, -{ "frame-format", OptionValue::eTypeFormatEntity, true, 0 , DEFAULT_FRAME_FORMAT, nullptr, "The default frame format string to use when displaying stack frame information for threads." }, -{ "notify-void", OptionValue::eTypeBoolean , true, false, nullptr, nullptr, "Notify the user explicitly if an expression returns void (default: false)." }, -{ "prompt", OptionValue::eTypeString , true, OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", nullptr, "The debugger command line prompt displayed for the user." }, -{ "script-lang", OptionValue::eTypeEnum , true, eScriptLanguagePython, nullptr, g_language_enumerators, "The script language to be used for evaluating user-written scripts." }, -{ "stop-disassembly-count", OptionValue::eTypeSInt64 , true, 4 , nullptr, nullptr, "The number of disassembly lines to show when displaying a stopped context." }, -{ "stop-disassembly-display", OptionValue::eTypeEnum , true, Debugger::eStopDisassemblyTypeNoDebugInfo, nullptr, g_show_disassembly_enum_values, "Control when to display disassembly when displaying a stopped context." }, -{ "stop-line-count-after", OptionValue::eTypeSInt64 , true, 3 , nullptr, nullptr, "The number of sources lines to display that come after the current source line when displaying a stopped context." }, -{ "stop-line-count-before", OptionValue::eTypeSInt64 , true, 3 , nullptr, nullptr, "The number of sources lines to display that come before the current source line when displaying a stopped context." }, -{ "term-width", OptionValue::eTypeSInt64 , true, 80 , nullptr, nullptr, "The maximum number of columns to use for displaying text." }, -{ "thread-format", OptionValue::eTypeFormatEntity, true, 0 , DEFAULT_THREAD_FORMAT, nullptr, "The default thread format string to use when displaying thread information." }, -{ "use-external-editor", OptionValue::eTypeBoolean , true, false, nullptr, nullptr, "Whether to use an external editor or not." }, -{ "use-color", OptionValue::eTypeBoolean , true, true , nullptr, nullptr, "Whether to use Ansi color codes or not." }, -{ "auto-one-line-summaries", OptionValue::eTypeBoolean , true, true, nullptr, nullptr, "If true, LLDB will automatically display small structs in one-liner format (default: true)." }, -{ "auto-indent", OptionValue::eTypeBoolean , true, true , nullptr, nullptr, "If true, LLDB will auto indent/outdent code. Currently only supported in the REPL (default: true)." }, -{ "print-decls", OptionValue::eTypeBoolean , true, true , nullptr, nullptr, "If true, LLDB will print the values of variables declared in an expression. Currently only supported in the REPL (default: true)." }, -{ "tab-size", OptionValue::eTypeUInt64 , true, 4 , nullptr, nullptr, "The tab size to use when indenting code in multi-line input mode (default: 4)." }, -{ "escape-non-printables", OptionValue::eTypeBoolean , true, true, nullptr, nullptr, "If true, LLDB will automatically escape non-printable and escape characters when formatting strings." }, -{ nullptr, OptionValue::eTypeInvalid , true, 0 , nullptr, nullptr, nullptr } -}; - -enum -{ - ePropertyAutoConfirm = 0, - ePropertyDisassemblyFormat, - ePropertyFrameFormat, - ePropertyNotiftVoid, - ePropertyPrompt, - ePropertyScriptLanguage, - ePropertyStopDisassemblyCount, - ePropertyStopDisassemblyDisplay, - ePropertyStopLineCountAfter, - ePropertyStopLineCountBefore, - ePropertyTerminalWidth, - ePropertyThreadFormat, - ePropertyUseExternalEditor, - ePropertyUseColor, - ePropertyAutoOneLineSummaries, - ePropertyAutoIndent, - ePropertyPrintDecls, - ePropertyTabSize, - ePropertyEscapeNonPrintables +// {${function.initial-function}{${module.file.basename}`}{${function.name-without-args}}:\n}{${function.changed}\n{${module.file.basename}`}{${function.name-without-args}}:\n}{${current-pc-arrow} +// }{${addr-file-or-load}}: + +#define DEFAULT_STOP_SHOW_COLUMN_ANSI_PREFIX "${ansi.underline}" +#define DEFAULT_STOP_SHOW_COLUMN_ANSI_SUFFIX "${ansi.normal}" + +static OptionEnumValueElement s_stop_show_column_values[] = { + {eStopShowColumnAnsiOrCaret, "ansi-or-caret", + "Highlight the stop column with ANSI terminal codes when color/ANSI mode " + "is enabled; otherwise, fall back to using a text-only caret (^) as if " + "\"caret-only\" mode was selected."}, + {eStopShowColumnAnsi, "ansi", "Highlight the stop column with ANSI " + "terminal codes when running LLDB with " + "color/ANSI enabled."}, + {eStopShowColumnCaret, "caret", + "Highlight the stop column with a caret character (^) underneath the stop " + "column. This method introduces a new line in source listings that " + "display thread stop locations."}, + {eStopShowColumnNone, "none", "Do not highlight the stop column."}, + {0, nullptr, nullptr}}; + +static PropertyDefinition g_properties[] = { + {"auto-confirm", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, + "If true all confirmation prompts will receive their default reply."}, + {"disassembly-format", OptionValue::eTypeFormatEntity, true, 0, + DEFAULT_DISASSEMBLY_FORMAT, nullptr, "The default disassembly format " + "string to use when disassembling " + "instruction sequences."}, + {"frame-format", OptionValue::eTypeFormatEntity, true, 0, + DEFAULT_FRAME_FORMAT, nullptr, "The default frame format string to use " + "when displaying stack frame information " + "for threads."}, + {"notify-void", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, + "Notify the user explicitly if an expression returns void (default: " + "false)."}, + {"prompt", OptionValue::eTypeString, true, + OptionValueString::eOptionEncodeCharacterEscapeSequences, "(lldb) ", + nullptr, "The debugger command line prompt displayed for the user."}, + {"script-lang", OptionValue::eTypeEnum, true, eScriptLanguagePython, + nullptr, g_language_enumerators, + "The script language to be used for evaluating user-written scripts."}, + {"stop-disassembly-count", OptionValue::eTypeSInt64, true, 4, nullptr, + nullptr, "The number of disassembly lines to show when displaying a " + "stopped context."}, + {"stop-disassembly-display", OptionValue::eTypeEnum, true, + Debugger::eStopDisassemblyTypeNoDebugInfo, nullptr, + g_show_disassembly_enum_values, + "Control when to display disassembly when displaying a stopped context."}, + {"stop-line-count-after", OptionValue::eTypeSInt64, true, 3, nullptr, + nullptr, "The number of sources lines to display that come after the " + "current source line when displaying a stopped context."}, + {"stop-line-count-before", OptionValue::eTypeSInt64, true, 3, nullptr, + nullptr, "The number of sources lines to display that come before the " + "current source line when displaying a stopped context."}, + {"stop-show-column", OptionValue::eTypeEnum, false, + eStopShowColumnAnsiOrCaret, nullptr, s_stop_show_column_values, + "If true, LLDB will use the column information from the debug info to " + "mark the current position when displaying a stopped context."}, + {"stop-show-column-ansi-prefix", OptionValue::eTypeFormatEntity, true, 0, + DEFAULT_STOP_SHOW_COLUMN_ANSI_PREFIX, nullptr, + "When displaying the column marker in a color-enabled (i.e. ANSI) " + "terminal, use the ANSI terminal code specified in this format at the " + "immediately before the column to be marked."}, + {"stop-show-column-ansi-suffix", OptionValue::eTypeFormatEntity, true, 0, + DEFAULT_STOP_SHOW_COLUMN_ANSI_SUFFIX, nullptr, + "When displaying the column marker in a color-enabled (i.e. ANSI) " + "terminal, use the ANSI terminal code specified in this format " + "immediately after the column to be marked."}, + {"term-width", OptionValue::eTypeSInt64, true, 80, nullptr, nullptr, + "The maximum number of columns to use for displaying text."}, + {"thread-format", OptionValue::eTypeFormatEntity, true, 0, + DEFAULT_THREAD_FORMAT, nullptr, "The default thread format string to use " + "when displaying thread information."}, + {"thread-stop-format", OptionValue::eTypeFormatEntity, true, 0, + DEFAULT_THREAD_STOP_FORMAT, nullptr, "The default thread format " + "string to usewhen displaying thread " + "information as part of the stop display."}, + {"use-external-editor", OptionValue::eTypeBoolean, true, false, nullptr, + nullptr, "Whether to use an external editor or not."}, + {"use-color", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, + "Whether to use Ansi color codes or not."}, + {"auto-one-line-summaries", OptionValue::eTypeBoolean, true, true, nullptr, + nullptr, "If true, LLDB will automatically display small structs in " + "one-liner format (default: true)."}, + {"auto-indent", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, + "If true, LLDB will auto indent/outdent code. Currently only supported in " + "the REPL (default: true)."}, + {"print-decls", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, + "If true, LLDB will print the values of variables declared in an " + "expression. Currently only supported in the REPL (default: true)."}, + {"tab-size", OptionValue::eTypeUInt64, true, 4, nullptr, nullptr, + "The tab size to use when indenting code in multi-line input mode " + "(default: 4)."}, + {"escape-non-printables", OptionValue::eTypeBoolean, true, true, nullptr, + nullptr, "If true, LLDB will automatically escape non-printable and " + "escape characters when formatting strings."}, + {nullptr, OptionValue::eTypeInvalid, true, 0, nullptr, nullptr, nullptr}}; + +enum { + ePropertyAutoConfirm = 0, + ePropertyDisassemblyFormat, + ePropertyFrameFormat, + ePropertyNotiftVoid, + ePropertyPrompt, + ePropertyScriptLanguage, + ePropertyStopDisassemblyCount, + ePropertyStopDisassemblyDisplay, + ePropertyStopLineCountAfter, + ePropertyStopLineCountBefore, + ePropertyStopShowColumn, + ePropertyStopShowColumnAnsiPrefix, + ePropertyStopShowColumnAnsiSuffix, + ePropertyTerminalWidth, + ePropertyThreadFormat, + ePropertyThreadStopFormat, + ePropertyUseExternalEditor, + ePropertyUseColor, + ePropertyAutoOneLineSummaries, + ePropertyAutoIndent, + ePropertyPrintDecls, + ePropertyTabSize, + ePropertyEscapeNonPrintables }; LoadPluginCallbackType Debugger::g_load_plugin_callback = nullptr; -Error -Debugger::SetPropertyValue (const ExecutionContext *exe_ctx, - VarSetOperationType op, - const char *property_path, - const char *value) -{ - bool is_load_script = strcmp(property_path,"target.load-script-from-symbol-file") == 0; - bool is_escape_non_printables = strcmp(property_path, "escape-non-printables") == 0; - TargetSP target_sp; - LoadScriptFromSymFile load_script_old_value; - if (is_load_script && exe_ctx->GetTargetSP()) - { - target_sp = exe_ctx->GetTargetSP(); - load_script_old_value = target_sp->TargetProperties::GetLoadScriptFromSymbolFile(); - } - Error error (Properties::SetPropertyValue (exe_ctx, op, property_path, value)); - if (error.Success()) - { - // FIXME it would be nice to have "on-change" callbacks for properties - if (strcmp(property_path, g_properties[ePropertyPrompt].name) == 0) - { - const char *new_prompt = GetPrompt(); - std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor()); - if (str.length()) - new_prompt = str.c_str(); - GetCommandInterpreter().UpdatePrompt(new_prompt); - EventSP prompt_change_event_sp (new Event(CommandInterpreter::eBroadcastBitResetPrompt, new EventDataBytes (new_prompt))); - GetCommandInterpreter().BroadcastEvent (prompt_change_event_sp); - } - else if (strcmp(property_path, g_properties[ePropertyUseColor].name) == 0) - { - // use-color changed. Ping the prompt so it can reset the ansi terminal codes. - SetPrompt (GetPrompt()); - } - else if (is_load_script && target_sp && load_script_old_value == eLoadScriptFromSymFileWarn) - { - if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() == eLoadScriptFromSymFileTrue) - { - std::list<Error> errors; - StreamString feedback_stream; - if (!target_sp->LoadScriptingResources(errors,&feedback_stream)) - { - StreamFileSP stream_sp (GetErrorFile()); - if (stream_sp) - { - for (auto error : errors) - { - stream_sp->Printf("%s\n",error.AsCString()); - } - if (feedback_stream.GetSize()) - stream_sp->Printf("%s",feedback_stream.GetData()); - } - } +Error Debugger::SetPropertyValue(const ExecutionContext *exe_ctx, + VarSetOperationType op, + llvm::StringRef property_path, llvm::StringRef value) { + bool is_load_script = (property_path == "target.load-script-from-symbol-file"); + bool is_escape_non_printables = (property_path == "escape-non-printables"); + TargetSP target_sp; + LoadScriptFromSymFile load_script_old_value; + if (is_load_script && exe_ctx->GetTargetSP()) { + target_sp = exe_ctx->GetTargetSP(); + load_script_old_value = + target_sp->TargetProperties::GetLoadScriptFromSymbolFile(); + } + Error error(Properties::SetPropertyValue(exe_ctx, op, property_path, value)); + if (error.Success()) { + // FIXME it would be nice to have "on-change" callbacks for properties + if (property_path == g_properties[ePropertyPrompt].name) { + llvm::StringRef new_prompt = GetPrompt(); + std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes( + new_prompt, GetUseColor()); + if (str.length()) + new_prompt = str; + GetCommandInterpreter().UpdatePrompt(new_prompt); + EventSP prompt_change_event_sp( + new Event(CommandInterpreter::eBroadcastBitResetPrompt, + new EventDataBytes(new_prompt))); + GetCommandInterpreter().BroadcastEvent(prompt_change_event_sp); + } else if (property_path == g_properties[ePropertyUseColor].name) { + // use-color changed. Ping the prompt so it can reset the ansi terminal + // codes. + SetPrompt(GetPrompt()); + } else if (is_load_script && target_sp && + load_script_old_value == eLoadScriptFromSymFileWarn) { + if (target_sp->TargetProperties::GetLoadScriptFromSymbolFile() == + eLoadScriptFromSymFileTrue) { + std::list<Error> errors; + StreamString feedback_stream; + if (!target_sp->LoadScriptingResources(errors, &feedback_stream)) { + StreamFileSP stream_sp(GetErrorFile()); + if (stream_sp) { + for (auto error : errors) { + stream_sp->Printf("%s\n", error.AsCString()); } + if (feedback_stream.GetSize()) + stream_sp->PutCString(feedback_stream.GetString()); + } } - else if (is_escape_non_printables) - { - DataVisualization::ForceUpdate(); - } + } + } else if (is_escape_non_printables) { + DataVisualization::ForceUpdate(); } - return error; + } + return error; } -bool -Debugger::GetAutoConfirm () const -{ - const uint32_t idx = ePropertyAutoConfirm; - return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0); +bool Debugger::GetAutoConfirm() const { + const uint32_t idx = ePropertyAutoConfirm; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_properties[idx].default_uint_value != 0); } -const FormatEntity::Entry * -Debugger::GetDisassemblyFormat() const -{ - const uint32_t idx = ePropertyDisassemblyFormat; - return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); +const FormatEntity::Entry *Debugger::GetDisassemblyFormat() const { + const uint32_t idx = ePropertyDisassemblyFormat; + return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); } -const FormatEntity::Entry * -Debugger::GetFrameFormat() const -{ - const uint32_t idx = ePropertyFrameFormat; - return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); +const FormatEntity::Entry *Debugger::GetFrameFormat() const { + const uint32_t idx = ePropertyFrameFormat; + return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); } -bool -Debugger::GetNotifyVoid () const -{ - const uint32_t idx = ePropertyNotiftVoid; - return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0); +bool Debugger::GetNotifyVoid() const { + const uint32_t idx = ePropertyNotiftVoid; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_properties[idx].default_uint_value != 0); } -const char * -Debugger::GetPrompt() const -{ - const uint32_t idx = ePropertyPrompt; - return m_collection_sp->GetPropertyAtIndexAsString(nullptr, idx, g_properties[idx].default_cstr_value); +llvm::StringRef Debugger::GetPrompt() const { + const uint32_t idx = ePropertyPrompt; + return m_collection_sp->GetPropertyAtIndexAsString( + nullptr, idx, g_properties[idx].default_cstr_value); } -void -Debugger::SetPrompt(const char *p) -{ - const uint32_t idx = ePropertyPrompt; - m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p); - const char *new_prompt = GetPrompt(); - std::string str = lldb_utility::ansi::FormatAnsiTerminalCodes (new_prompt, GetUseColor()); - if (str.length()) - new_prompt = str.c_str(); - GetCommandInterpreter().UpdatePrompt(new_prompt); +void Debugger::SetPrompt(llvm::StringRef p) { + const uint32_t idx = ePropertyPrompt; + m_collection_sp->SetPropertyAtIndexAsString(nullptr, idx, p); + llvm::StringRef new_prompt = GetPrompt(); + std::string str = + lldb_utility::ansi::FormatAnsiTerminalCodes(new_prompt, GetUseColor()); + if (str.length()) + new_prompt = str; + GetCommandInterpreter().UpdatePrompt(new_prompt); } -const FormatEntity::Entry * -Debugger::GetThreadFormat() const -{ - const uint32_t idx = ePropertyThreadFormat; - return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); +const FormatEntity::Entry *Debugger::GetThreadFormat() const { + const uint32_t idx = ePropertyThreadFormat; + return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); } -lldb::ScriptLanguage -Debugger::GetScriptLanguage() const -{ - const uint32_t idx = ePropertyScriptLanguage; - return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration(nullptr, idx, g_properties[idx].default_uint_value); +const FormatEntity::Entry *Debugger::GetThreadStopFormat() const { + const uint32_t idx = ePropertyThreadStopFormat; + return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); } -bool -Debugger::SetScriptLanguage (lldb::ScriptLanguage script_lang) -{ - const uint32_t idx = ePropertyScriptLanguage; - return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx, script_lang); +lldb::ScriptLanguage Debugger::GetScriptLanguage() const { + const uint32_t idx = ePropertyScriptLanguage; + return (lldb::ScriptLanguage)m_collection_sp->GetPropertyAtIndexAsEnumeration( + nullptr, idx, g_properties[idx].default_uint_value); } -uint32_t -Debugger::GetTerminalWidth () const -{ - const uint32_t idx = ePropertyTerminalWidth; - return m_collection_sp->GetPropertyAtIndexAsSInt64(nullptr, idx, g_properties[idx].default_uint_value); +bool Debugger::SetScriptLanguage(lldb::ScriptLanguage script_lang) { + const uint32_t idx = ePropertyScriptLanguage; + return m_collection_sp->SetPropertyAtIndexAsEnumeration(nullptr, idx, + script_lang); } -bool -Debugger::SetTerminalWidth (uint32_t term_width) -{ - const uint32_t idx = ePropertyTerminalWidth; - return m_collection_sp->SetPropertyAtIndexAsSInt64(nullptr, idx, term_width); +uint32_t Debugger::GetTerminalWidth() const { + const uint32_t idx = ePropertyTerminalWidth; + return m_collection_sp->GetPropertyAtIndexAsSInt64( + nullptr, idx, g_properties[idx].default_uint_value); } -bool -Debugger::GetUseExternalEditor () const -{ - const uint32_t idx = ePropertyUseExternalEditor; - return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0); +bool Debugger::SetTerminalWidth(uint32_t term_width) { + const uint32_t idx = ePropertyTerminalWidth; + return m_collection_sp->SetPropertyAtIndexAsSInt64(nullptr, idx, term_width); } -bool -Debugger::SetUseExternalEditor (bool b) -{ - const uint32_t idx = ePropertyUseExternalEditor; - return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); +bool Debugger::GetUseExternalEditor() const { + const uint32_t idx = ePropertyUseExternalEditor; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_properties[idx].default_uint_value != 0); } -bool -Debugger::GetUseColor () const -{ - const uint32_t idx = ePropertyUseColor; - return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, g_properties[idx].default_uint_value != 0); +bool Debugger::SetUseExternalEditor(bool b) { + const uint32_t idx = ePropertyUseExternalEditor; + return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); } -bool -Debugger::SetUseColor (bool b) -{ - const uint32_t idx = ePropertyUseColor; - bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); - SetPrompt (GetPrompt()); - return ret; +bool Debugger::GetUseColor() const { + const uint32_t idx = ePropertyUseColor; + return m_collection_sp->GetPropertyAtIndexAsBoolean( + nullptr, idx, g_properties[idx].default_uint_value != 0); } -uint32_t -Debugger::GetStopSourceLineCount (bool before) const -{ - const uint32_t idx = before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter; - return m_collection_sp->GetPropertyAtIndexAsSInt64(nullptr, idx, g_properties[idx].default_uint_value); +bool Debugger::SetUseColor(bool b) { + const uint32_t idx = ePropertyUseColor; + bool ret = m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); + SetPrompt(GetPrompt()); + return ret; } -Debugger::StopDisassemblyType -Debugger::GetStopDisassemblyDisplay () const -{ - const uint32_t idx = ePropertyStopDisassemblyDisplay; - return (Debugger::StopDisassemblyType)m_collection_sp->GetPropertyAtIndexAsEnumeration(nullptr, idx, g_properties[idx].default_uint_value); +StopShowColumn Debugger::GetStopShowColumn() const { + const uint32_t idx = ePropertyStopShowColumn; + return (lldb::StopShowColumn)m_collection_sp->GetPropertyAtIndexAsEnumeration( + nullptr, idx, g_properties[idx].default_uint_value); } -uint32_t -Debugger::GetDisassemblyLineCount () const -{ - const uint32_t idx = ePropertyStopDisassemblyCount; - return m_collection_sp->GetPropertyAtIndexAsSInt64(nullptr, idx, g_properties[idx].default_uint_value); +const FormatEntity::Entry *Debugger::GetStopShowColumnAnsiPrefix() const { + const uint32_t idx = ePropertyStopShowColumnAnsiPrefix; + return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); } -bool -Debugger::GetAutoOneLineSummaries () const -{ - const uint32_t idx = ePropertyAutoOneLineSummaries; - return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); +const FormatEntity::Entry *Debugger::GetStopShowColumnAnsiSuffix() const { + const uint32_t idx = ePropertyStopShowColumnAnsiSuffix; + return m_collection_sp->GetPropertyAtIndexAsFormatEntity(nullptr, idx); } -bool -Debugger::GetEscapeNonPrintables () const -{ - const uint32_t idx = ePropertyEscapeNonPrintables; - return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); +uint32_t Debugger::GetStopSourceLineCount(bool before) const { + const uint32_t idx = + before ? ePropertyStopLineCountBefore : ePropertyStopLineCountAfter; + return m_collection_sp->GetPropertyAtIndexAsSInt64( + nullptr, idx, g_properties[idx].default_uint_value); } -bool -Debugger::GetAutoIndent () const -{ - const uint32_t idx = ePropertyAutoIndent; - return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); +Debugger::StopDisassemblyType Debugger::GetStopDisassemblyDisplay() const { + const uint32_t idx = ePropertyStopDisassemblyDisplay; + return (Debugger::StopDisassemblyType) + m_collection_sp->GetPropertyAtIndexAsEnumeration( + nullptr, idx, g_properties[idx].default_uint_value); } -bool -Debugger::SetAutoIndent (bool b) -{ - const uint32_t idx = ePropertyAutoIndent; - return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); +uint32_t Debugger::GetDisassemblyLineCount() const { + const uint32_t idx = ePropertyStopDisassemblyCount; + return m_collection_sp->GetPropertyAtIndexAsSInt64( + nullptr, idx, g_properties[idx].default_uint_value); } -bool -Debugger::GetPrintDecls () const -{ - const uint32_t idx = ePropertyPrintDecls; - return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); +bool Debugger::GetAutoOneLineSummaries() const { + const uint32_t idx = ePropertyAutoOneLineSummaries; + return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); } -bool -Debugger::SetPrintDecls (bool b) -{ - const uint32_t idx = ePropertyPrintDecls; - return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); +bool Debugger::GetEscapeNonPrintables() const { + const uint32_t idx = ePropertyEscapeNonPrintables; + return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); } -uint32_t -Debugger::GetTabSize () const -{ - const uint32_t idx = ePropertyTabSize; - return m_collection_sp->GetPropertyAtIndexAsUInt64(nullptr, idx, g_properties[idx].default_uint_value); +bool Debugger::GetAutoIndent() const { + const uint32_t idx = ePropertyAutoIndent; + return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); } -bool -Debugger::SetTabSize (uint32_t tab_size) -{ - const uint32_t idx = ePropertyTabSize; - return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size); +bool Debugger::SetAutoIndent(bool b) { + const uint32_t idx = ePropertyAutoIndent; + return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); +} + +bool Debugger::GetPrintDecls() const { + const uint32_t idx = ePropertyPrintDecls; + return m_collection_sp->GetPropertyAtIndexAsBoolean(nullptr, idx, true); +} + +bool Debugger::SetPrintDecls(bool b) { + const uint32_t idx = ePropertyPrintDecls; + return m_collection_sp->SetPropertyAtIndexAsBoolean(nullptr, idx, b); +} + +uint32_t Debugger::GetTabSize() const { + const uint32_t idx = ePropertyTabSize; + return m_collection_sp->GetPropertyAtIndexAsUInt64( + nullptr, idx, g_properties[idx].default_uint_value); +} + +bool Debugger::SetTabSize(uint32_t tab_size) { + const uint32_t idx = ePropertyTabSize; + return m_collection_sp->SetPropertyAtIndexAsUInt64(nullptr, idx, tab_size); } #pragma mark Debugger -//const DebuggerPropertiesSP & -//Debugger::GetSettings() const +// const DebuggerPropertiesSP & +// Debugger::GetSettings() const //{ // return m_properties_sp; //} // -void -Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) -{ - assert(g_debugger_list_ptr == nullptr && "Debugger::Initialize called more than once!"); - g_debugger_list_mutex_ptr = new std::recursive_mutex(); - g_debugger_list_ptr = new DebuggerList(); - g_load_plugin_callback = load_plugin_callback; +void Debugger::Initialize(LoadPluginCallbackType load_plugin_callback) { + assert(g_debugger_list_ptr == nullptr && + "Debugger::Initialize called more than once!"); + g_debugger_list_mutex_ptr = new std::recursive_mutex(); + g_debugger_list_ptr = new DebuggerList(); + g_load_plugin_callback = load_plugin_callback; } -void -Debugger::Terminate () -{ - assert(g_debugger_list_ptr && "Debugger::Terminate called without a matching Debugger::Initialize!"); +void Debugger::Terminate() { + assert(g_debugger_list_ptr && + "Debugger::Terminate called without a matching Debugger::Initialize!"); - if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) + if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { + // Clear our master list of debugger objects { - // Clear our master list of debugger objects - { - std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); - for (const auto& debugger: *g_debugger_list_ptr) - debugger->Clear(); - g_debugger_list_ptr->clear(); - } + std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); + for (const auto &debugger : *g_debugger_list_ptr) + debugger->Clear(); + g_debugger_list_ptr->clear(); } + } } -void -Debugger::SettingsInitialize () -{ - Target::SettingsInitialize (); -} +void Debugger::SettingsInitialize() { Target::SettingsInitialize(); } -void -Debugger::SettingsTerminate () -{ - Target::SettingsTerminate (); -} +void Debugger::SettingsTerminate() { Target::SettingsTerminate(); } -bool -Debugger::LoadPlugin (const FileSpec& spec, Error& error) -{ - if (g_load_plugin_callback) - { - llvm::sys::DynamicLibrary dynlib = g_load_plugin_callback (shared_from_this(), spec, error); - if (dynlib.isValid()) - { - m_loaded_plugins.push_back(dynlib); - return true; - } +bool Debugger::LoadPlugin(const FileSpec &spec, Error &error) { + if (g_load_plugin_callback) { + llvm::sys::DynamicLibrary dynlib = + g_load_plugin_callback(shared_from_this(), spec, error); + if (dynlib.isValid()) { + m_loaded_plugins.push_back(dynlib); + return true; } - else - { - // The g_load_plugin_callback is registered in SBDebugger::Initialize() - // and if the public API layer isn't available (code is linking against - // all of the internal LLDB static libraries), then we can't load plugins - error.SetErrorString("Public API layer is not available"); - } - return false; + } else { + // The g_load_plugin_callback is registered in SBDebugger::Initialize() + // and if the public API layer isn't available (code is linking against + // all of the internal LLDB static libraries), then we can't load plugins + error.SetErrorString("Public API layer is not available"); + } + return false; } static FileSpec::EnumerateDirectoryResult -LoadPluginCallback(void *baton, - FileSpec::FileType file_type, - const FileSpec &file_spec) -{ - Error error; - - static ConstString g_dylibext("dylib"); - static ConstString g_solibext("so"); - - if (!baton) - return FileSpec::eEnumerateDirectoryResultQuit; - - Debugger *debugger = (Debugger*)baton; - - // If we have a regular file, a symbolic link or unknown file type, try - // and process the file. We must handle unknown as sometimes the directory - // enumeration might be enumerating a file system that doesn't have correct - // file type information. - if (file_type == FileSpec::eFileTypeRegular || - file_type == FileSpec::eFileTypeSymbolicLink || - file_type == FileSpec::eFileTypeUnknown ) - { - FileSpec plugin_file_spec (file_spec); - plugin_file_spec.ResolvePath (); - - if (plugin_file_spec.GetFileNameExtension() != g_dylibext && - plugin_file_spec.GetFileNameExtension() != g_solibext) - { - return FileSpec::eEnumerateDirectoryResultNext; - } - - Error plugin_load_error; - debugger->LoadPlugin (plugin_file_spec, plugin_load_error); - - return FileSpec::eEnumerateDirectoryResultNext; - } - else if (file_type == FileSpec::eFileTypeUnknown || - file_type == FileSpec::eFileTypeDirectory || - file_type == FileSpec::eFileTypeSymbolicLink ) - { - // Try and recurse into anything that a directory or symbolic link. - // We must also do this for unknown as sometimes the directory enumeration - // might be enumerating a file system that doesn't have correct file type - // information. - return FileSpec::eEnumerateDirectoryResultEnter; +LoadPluginCallback(void *baton, FileSpec::FileType file_type, + const FileSpec &file_spec) { + Error error; + + static ConstString g_dylibext("dylib"); + static ConstString g_solibext("so"); + + if (!baton) + return FileSpec::eEnumerateDirectoryResultQuit; + + Debugger *debugger = (Debugger *)baton; + + // If we have a regular file, a symbolic link or unknown file type, try + // and process the file. We must handle unknown as sometimes the directory + // enumeration might be enumerating a file system that doesn't have correct + // file type information. + if (file_type == FileSpec::eFileTypeRegular || + file_type == FileSpec::eFileTypeSymbolicLink || + file_type == FileSpec::eFileTypeUnknown) { + FileSpec plugin_file_spec(file_spec); + plugin_file_spec.ResolvePath(); + + if (plugin_file_spec.GetFileNameExtension() != g_dylibext && + plugin_file_spec.GetFileNameExtension() != g_solibext) { + return FileSpec::eEnumerateDirectoryResultNext; } - - return FileSpec::eEnumerateDirectoryResultNext; -} -void -Debugger::InstanceInitialize () -{ - FileSpec dir_spec; - const bool find_directories = true; - const bool find_files = true; - const bool find_other = true; - char dir_path[PATH_MAX]; - if (HostInfo::GetLLDBPath(ePathTypeLLDBSystemPlugins, dir_spec)) - { - if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) - { - FileSpec::EnumerateDirectory (dir_path, - find_directories, - find_files, - find_other, - LoadPluginCallback, - this); - } + Error plugin_load_error; + debugger->LoadPlugin(plugin_file_spec, plugin_load_error); + + return FileSpec::eEnumerateDirectoryResultNext; + } else if (file_type == FileSpec::eFileTypeUnknown || + file_type == FileSpec::eFileTypeDirectory || + file_type == FileSpec::eFileTypeSymbolicLink) { + // Try and recurse into anything that a directory or symbolic link. + // We must also do this for unknown as sometimes the directory enumeration + // might be enumerating a file system that doesn't have correct file type + // information. + return FileSpec::eEnumerateDirectoryResultEnter; + } + + return FileSpec::eEnumerateDirectoryResultNext; +} + +void Debugger::InstanceInitialize() { + FileSpec dir_spec; + const bool find_directories = true; + const bool find_files = true; + const bool find_other = true; + char dir_path[PATH_MAX]; + if (HostInfo::GetLLDBPath(ePathTypeLLDBSystemPlugins, dir_spec)) { + if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) { + FileSpec::EnumerateDirectory(dir_path, find_directories, find_files, + find_other, LoadPluginCallback, this); } + } - if (HostInfo::GetLLDBPath(ePathTypeLLDBUserPlugins, dir_spec)) - { - if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) - { - FileSpec::EnumerateDirectory (dir_path, - find_directories, - find_files, - find_other, - LoadPluginCallback, - this); - } + if (HostInfo::GetLLDBPath(ePathTypeLLDBUserPlugins, dir_spec)) { + if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) { + FileSpec::EnumerateDirectory(dir_path, find_directories, find_files, + find_other, LoadPluginCallback, this); } - - PluginManager::DebuggerInitialize (*this); + } + + PluginManager::DebuggerInitialize(*this); } -DebuggerSP -Debugger::CreateInstance (lldb::LogOutputCallback log_callback, void *baton) -{ - DebuggerSP debugger_sp (new Debugger(log_callback, baton)); - if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) - { - std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); - g_debugger_list_ptr->push_back(debugger_sp); - } - debugger_sp->InstanceInitialize (); - return debugger_sp; +DebuggerSP Debugger::CreateInstance(lldb::LogOutputCallback log_callback, + void *baton) { + DebuggerSP debugger_sp(new Debugger(log_callback, baton)); + if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { + std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); + g_debugger_list_ptr->push_back(debugger_sp); + } + debugger_sp->InstanceInitialize(); + return debugger_sp; } -void -Debugger::Destroy (DebuggerSP &debugger_sp) -{ - if (!debugger_sp) - return; - - debugger_sp->Clear(); +void Debugger::Destroy(DebuggerSP &debugger_sp) { + if (!debugger_sp) + return; - if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) - { - std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); - DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); - for (pos = g_debugger_list_ptr->begin (); pos != end; ++pos) - { - if ((*pos).get() == debugger_sp.get()) - { - g_debugger_list_ptr->erase (pos); - return; - } - } + debugger_sp->Clear(); + + if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { + std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); + DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); + for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { + if ((*pos).get() == debugger_sp.get()) { + g_debugger_list_ptr->erase(pos); + return; + } } + } } DebuggerSP -Debugger::FindDebuggerWithInstanceName (const ConstString &instance_name) -{ - DebuggerSP debugger_sp; - if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) - { - std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); - DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); - for (pos = g_debugger_list_ptr->begin (); pos != end; ++pos) - { - if ((*pos)->m_instance_name == instance_name) - { - debugger_sp = *pos; - break; - } - } +Debugger::FindDebuggerWithInstanceName(const ConstString &instance_name) { + DebuggerSP debugger_sp; + if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { + std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); + DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); + for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { + if ((*pos)->m_instance_name == instance_name) { + debugger_sp = *pos; + break; + } } - return debugger_sp; -} - -TargetSP -Debugger::FindTargetWithProcessID (lldb::pid_t pid) -{ - TargetSP target_sp; - if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) - { - std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); - DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); - for (pos = g_debugger_list_ptr->begin (); pos != end; ++pos) - { - target_sp = (*pos)->GetTargetList().FindTargetWithProcessID (pid); - if (target_sp) - break; - } + } + return debugger_sp; +} + +TargetSP Debugger::FindTargetWithProcessID(lldb::pid_t pid) { + TargetSP target_sp; + if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { + std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); + DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); + for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { + target_sp = (*pos)->GetTargetList().FindTargetWithProcessID(pid); + if (target_sp) + break; } - return target_sp; -} - -TargetSP -Debugger::FindTargetWithProcess (Process *process) -{ - TargetSP target_sp; - if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) - { - std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); - DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); - for (pos = g_debugger_list_ptr->begin (); pos != end; ++pos) - { - target_sp = (*pos)->GetTargetList().FindTargetWithProcess (process); - if (target_sp) - break; - } + } + return target_sp; +} + +TargetSP Debugger::FindTargetWithProcess(Process *process) { + TargetSP target_sp; + if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { + std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); + DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); + for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { + target_sp = (*pos)->GetTargetList().FindTargetWithProcess(process); + if (target_sp) + break; } - return target_sp; -} - -Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) : - UserID(g_unique_id++), - Properties(OptionValuePropertiesSP(new OptionValueProperties())), - m_input_file_sp(new StreamFile(stdin, false)), - m_output_file_sp(new StreamFile(stdout, false)), - m_error_file_sp(new StreamFile(stderr, false)), - m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()), - m_terminal_state(), - m_target_list(*this), - m_platform_list(), - m_listener_sp(Listener::MakeListener("lldb.Debugger")), - m_source_manager_ap(), - m_source_file_cache(), - m_command_interpreter_ap(new CommandInterpreter(*this, eScriptLanguageDefault, false)), - m_input_reader_stack(), - m_instance_name(), - m_loaded_plugins(), - m_event_handler_thread(), - m_io_handler_thread(), - m_sync_broadcaster(nullptr, "lldb.debugger.sync"), - m_forward_listener_sp(), - m_clear_once() -{ - char instance_cstr[256]; - snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID()); - m_instance_name.SetCString(instance_cstr); - if (log_callback) - m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); - m_command_interpreter_ap->Initialize (); - // Always add our default platform to the platform list - PlatformSP default_platform_sp (Platform::GetHostPlatform()); - assert(default_platform_sp); - m_platform_list.Append (default_platform_sp, true); - - m_collection_sp->Initialize (g_properties); - m_collection_sp->AppendProperty (ConstString("target"), - ConstString("Settings specify to debugging targets."), - true, - Target::GetGlobalProperties()->GetValueProperties()); - m_collection_sp->AppendProperty (ConstString("platform"), - ConstString("Platform settings."), - true, - Platform::GetGlobalPlatformProperties()->GetValueProperties()); - if (m_command_interpreter_ap) - { - m_collection_sp->AppendProperty (ConstString("interpreter"), - ConstString("Settings specify to the debugger's command interpreter."), - true, - m_command_interpreter_ap->GetValueProperties()); + } + return target_sp; +} + +Debugger::Debugger(lldb::LogOutputCallback log_callback, void *baton) + : UserID(g_unique_id++), + Properties(OptionValuePropertiesSP(new OptionValueProperties())), + m_input_file_sp(new StreamFile(stdin, false)), + m_output_file_sp(new StreamFile(stdout, false)), + m_error_file_sp(new StreamFile(stderr, false)), + m_broadcaster_manager_sp(BroadcasterManager::MakeBroadcasterManager()), + m_terminal_state(), m_target_list(*this), m_platform_list(), + m_listener_sp(Listener::MakeListener("lldb.Debugger")), + m_source_manager_ap(), m_source_file_cache(), + m_command_interpreter_ap( + new CommandInterpreter(*this, eScriptLanguageDefault, false)), + m_input_reader_stack(), m_instance_name(), m_loaded_plugins(), + m_event_handler_thread(), m_io_handler_thread(), + m_sync_broadcaster(nullptr, "lldb.debugger.sync"), + m_forward_listener_sp(), m_clear_once() { + char instance_cstr[256]; + snprintf(instance_cstr, sizeof(instance_cstr), "debugger_%d", (int)GetID()); + m_instance_name.SetCString(instance_cstr); + if (log_callback) + m_log_callback_stream_sp.reset(new StreamCallback(log_callback, baton)); + m_command_interpreter_ap->Initialize(); + // Always add our default platform to the platform list + PlatformSP default_platform_sp(Platform::GetHostPlatform()); + assert(default_platform_sp); + m_platform_list.Append(default_platform_sp, true); + + m_collection_sp->Initialize(g_properties); + m_collection_sp->AppendProperty( + ConstString("target"), + ConstString("Settings specify to debugging targets."), true, + Target::GetGlobalProperties()->GetValueProperties()); + m_collection_sp->AppendProperty( + ConstString("platform"), ConstString("Platform settings."), true, + Platform::GetGlobalPlatformProperties()->GetValueProperties()); + if (m_command_interpreter_ap) { + m_collection_sp->AppendProperty( + ConstString("interpreter"), + ConstString("Settings specify to the debugger's command interpreter."), + true, m_command_interpreter_ap->GetValueProperties()); + } + OptionValueSInt64 *term_width = + m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64( + nullptr, ePropertyTerminalWidth); + term_width->SetMinimumValue(10); + term_width->SetMaximumValue(1024); + + // Turn off use-color if this is a dumb terminal. + const char *term = getenv("TERM"); + if (term && !strcmp(term, "dumb")) + SetUseColor(false); +} + +Debugger::~Debugger() { Clear(); } + +void Debugger::Clear() { + //---------------------------------------------------------------------- + // Make sure we call this function only once. With the C++ global + // destructor chain having a list of debuggers and with code that can be + // running on other threads, we need to ensure this doesn't happen + // multiple times. + // + // The following functions call Debugger::Clear(): + // Debugger::~Debugger(); + // static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp); + // static void Debugger::Terminate(); + //---------------------------------------------------------------------- + std::call_once(m_clear_once, [this]() { + ClearIOHandlers(); + StopIOHandlerThread(); + StopEventHandlerThread(); + m_listener_sp->Clear(); + int num_targets = m_target_list.GetNumTargets(); + for (int i = 0; i < num_targets; i++) { + TargetSP target_sp(m_target_list.GetTargetAtIndex(i)); + if (target_sp) { + ProcessSP process_sp(target_sp->GetProcessSP()); + if (process_sp) + process_sp->Finalize(); + target_sp->Destroy(); + } } - OptionValueSInt64 *term_width = m_collection_sp->GetPropertyAtIndexAsOptionValueSInt64(nullptr, ePropertyTerminalWidth); - term_width->SetMinimumValue(10); - term_width->SetMaximumValue(1024); + m_broadcaster_manager_sp->Clear(); + + // Close the input file _before_ we close the input read communications + // class + // as it does NOT own the input file, our m_input_file does. + m_terminal_state.Clear(); + if (m_input_file_sp) + m_input_file_sp->GetFile().Close(); - // Turn off use-color if this is a dumb terminal. - const char *term = getenv ("TERM"); - if (term && !strcmp (term, "dumb")) - SetUseColor (false); + m_command_interpreter_ap->Clear(); + }); } -Debugger::~Debugger () -{ - Clear(); +bool Debugger::GetCloseInputOnEOF() const { + // return m_input_comm.GetCloseOnEOF(); + return false; } -void -Debugger::Clear() -{ - //---------------------------------------------------------------------- - // Make sure we call this function only once. With the C++ global - // destructor chain having a list of debuggers and with code that can be - // running on other threads, we need to ensure this doesn't happen - // multiple times. - // - // The following functions call Debugger::Clear(): - // Debugger::~Debugger(); - // static void Debugger::Destroy(lldb::DebuggerSP &debugger_sp); - // static void Debugger::Terminate(); - //---------------------------------------------------------------------- - std::call_once(m_clear_once, [this]() { - ClearIOHandlers(); - StopIOHandlerThread(); - StopEventHandlerThread(); - m_listener_sp->Clear(); - int num_targets = m_target_list.GetNumTargets(); - for (int i = 0; i < num_targets; i++) - { - TargetSP target_sp (m_target_list.GetTargetAtIndex (i)); - if (target_sp) - { - ProcessSP process_sp (target_sp->GetProcessSP()); - if (process_sp) - process_sp->Finalize(); - target_sp->Destroy(); - } - } - m_broadcaster_manager_sp->Clear (); - - // Close the input file _before_ we close the input read communications class - // as it does NOT own the input file, our m_input_file does. - m_terminal_state.Clear(); - if (m_input_file_sp) - m_input_file_sp->GetFile().Close (); - - m_command_interpreter_ap->Clear(); - }); -} - -bool -Debugger::GetCloseInputOnEOF () const -{ -// return m_input_comm.GetCloseOnEOF(); - return false; +void Debugger::SetCloseInputOnEOF(bool b) { + // m_input_comm.SetCloseOnEOF(b); } -void -Debugger::SetCloseInputOnEOF (bool b) -{ -// m_input_comm.SetCloseOnEOF(b); +bool Debugger::GetAsyncExecution() { + return !m_command_interpreter_ap->GetSynchronous(); } -bool -Debugger::GetAsyncExecution () -{ - return !m_command_interpreter_ap->GetSynchronous(); +void Debugger::SetAsyncExecution(bool async_execution) { + m_command_interpreter_ap->SetSynchronous(!async_execution); } -void -Debugger::SetAsyncExecution (bool async_execution) -{ - m_command_interpreter_ap->SetSynchronous (!async_execution); +void Debugger::SetInputFileHandle(FILE *fh, bool tranfer_ownership) { + if (m_input_file_sp) + m_input_file_sp->GetFile().SetStream(fh, tranfer_ownership); + else + m_input_file_sp.reset(new StreamFile(fh, tranfer_ownership)); + + File &in_file = m_input_file_sp->GetFile(); + if (!in_file.IsValid()) + in_file.SetStream(stdin, true); + + // Save away the terminal state if that is relevant, so that we can restore it + // in RestoreInputState. + SaveInputTerminalState(); } -void -Debugger::SetInputFileHandle (FILE *fh, bool tranfer_ownership) -{ - if (m_input_file_sp) - m_input_file_sp->GetFile().SetStream (fh, tranfer_ownership); - else - m_input_file_sp.reset (new StreamFile (fh, tranfer_ownership)); +void Debugger::SetOutputFileHandle(FILE *fh, bool tranfer_ownership) { + if (m_output_file_sp) + m_output_file_sp->GetFile().SetStream(fh, tranfer_ownership); + else + m_output_file_sp.reset(new StreamFile(fh, tranfer_ownership)); - File &in_file = m_input_file_sp->GetFile(); - if (!in_file.IsValid()) - in_file.SetStream (stdin, true); + File &out_file = m_output_file_sp->GetFile(); + if (!out_file.IsValid()) + out_file.SetStream(stdout, false); - // Save away the terminal state if that is relevant, so that we can restore it in RestoreInputState. - SaveInputTerminalState (); + // do not create the ScriptInterpreter just for setting the output file handle + // as the constructor will know how to do the right thing on its own + const bool can_create = false; + ScriptInterpreter *script_interpreter = + GetCommandInterpreter().GetScriptInterpreter(can_create); + if (script_interpreter) + script_interpreter->ResetOutputFileHandle(fh); } -void -Debugger::SetOutputFileHandle (FILE *fh, bool tranfer_ownership) -{ - if (m_output_file_sp) - m_output_file_sp->GetFile().SetStream (fh, tranfer_ownership); - else - m_output_file_sp.reset (new StreamFile (fh, tranfer_ownership)); - - File &out_file = m_output_file_sp->GetFile(); - if (!out_file.IsValid()) - out_file.SetStream (stdout, false); - - // do not create the ScriptInterpreter just for setting the output file handle - // as the constructor will know how to do the right thing on its own - const bool can_create = false; - ScriptInterpreter* script_interpreter = GetCommandInterpreter().GetScriptInterpreter(can_create); - if (script_interpreter) - script_interpreter->ResetOutputFileHandle (fh); -} - -void -Debugger::SetErrorFileHandle (FILE *fh, bool tranfer_ownership) -{ - if (m_error_file_sp) - m_error_file_sp->GetFile().SetStream (fh, tranfer_ownership); - else - m_error_file_sp.reset (new StreamFile (fh, tranfer_ownership)); - - File &err_file = m_error_file_sp->GetFile(); - if (!err_file.IsValid()) - err_file.SetStream (stderr, false); +void Debugger::SetErrorFileHandle(FILE *fh, bool tranfer_ownership) { + if (m_error_file_sp) + m_error_file_sp->GetFile().SetStream(fh, tranfer_ownership); + else + m_error_file_sp.reset(new StreamFile(fh, tranfer_ownership)); + + File &err_file = m_error_file_sp->GetFile(); + if (!err_file.IsValid()) + err_file.SetStream(stderr, false); } -void -Debugger::SaveInputTerminalState () -{ - if (m_input_file_sp) - { - File &in_file = m_input_file_sp->GetFile(); - if (in_file.GetDescriptor() != File::kInvalidDescriptor) - m_terminal_state.Save(in_file.GetDescriptor(), true); +void Debugger::SaveInputTerminalState() { + if (m_input_file_sp) { + File &in_file = m_input_file_sp->GetFile(); + if (in_file.GetDescriptor() != File::kInvalidDescriptor) + m_terminal_state.Save(in_file.GetDescriptor(), true); + } +} + +void Debugger::RestoreInputTerminalState() { m_terminal_state.Restore(); } + +ExecutionContext Debugger::GetSelectedExecutionContext() { + ExecutionContext exe_ctx; + TargetSP target_sp(GetSelectedTarget()); + exe_ctx.SetTargetSP(target_sp); + + if (target_sp) { + ProcessSP process_sp(target_sp->GetProcessSP()); + exe_ctx.SetProcessSP(process_sp); + if (process_sp && !process_sp->IsRunning()) { + ThreadSP thread_sp(process_sp->GetThreadList().GetSelectedThread()); + if (thread_sp) { + exe_ctx.SetThreadSP(thread_sp); + exe_ctx.SetFrameSP(thread_sp->GetSelectedFrame()); + if (exe_ctx.GetFramePtr() == nullptr) + exe_ctx.SetFrameSP(thread_sp->GetStackFrameAtIndex(0)); + } } + } + return exe_ctx; } -void -Debugger::RestoreInputTerminalState () -{ - m_terminal_state.Restore(); +void Debugger::DispatchInputInterrupt() { + std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); + IOHandlerSP reader_sp(m_input_reader_stack.Top()); + if (reader_sp) + reader_sp->Interrupt(); } -ExecutionContext -Debugger::GetSelectedExecutionContext () -{ - ExecutionContext exe_ctx; - TargetSP target_sp(GetSelectedTarget()); - exe_ctx.SetTargetSP (target_sp); - - if (target_sp) - { - ProcessSP process_sp (target_sp->GetProcessSP()); - exe_ctx.SetProcessSP (process_sp); - if (process_sp && !process_sp->IsRunning()) - { - ThreadSP thread_sp (process_sp->GetThreadList().GetSelectedThread()); - if (thread_sp) - { - exe_ctx.SetThreadSP (thread_sp); - exe_ctx.SetFrameSP (thread_sp->GetSelectedFrame()); - if (exe_ctx.GetFramePtr() == nullptr) - exe_ctx.SetFrameSP (thread_sp->GetStackFrameAtIndex (0)); - } - } - } - return exe_ctx; +void Debugger::DispatchInputEndOfFile() { + std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); + IOHandlerSP reader_sp(m_input_reader_stack.Top()); + if (reader_sp) + reader_sp->GotEOF(); } -void -Debugger::DispatchInputInterrupt() -{ - std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); +void Debugger::ClearIOHandlers() { + // The bottom input reader should be the main debugger input reader. We do + // not want to close that one here. + std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); + while (m_input_reader_stack.GetSize() > 1) { IOHandlerSP reader_sp(m_input_reader_stack.Top()); if (reader_sp) - reader_sp->Interrupt(); + PopIOHandler(reader_sp); + } } -void -Debugger::DispatchInputEndOfFile() -{ - std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); +void Debugger::ExecuteIOHandlers() { + while (true) { IOHandlerSP reader_sp(m_input_reader_stack.Top()); - if (reader_sp) - reader_sp->GotEOF(); -} + if (!reader_sp) + break; -void -Debugger::ClearIOHandlers() -{ - // The bottom input reader should be the main debugger input reader. We do not want to close that one here. - std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); - while (m_input_reader_stack.GetSize() > 1) - { - IOHandlerSP reader_sp(m_input_reader_stack.Top()); - if (reader_sp) - PopIOHandler(reader_sp); - } -} + reader_sp->Run(); -void -Debugger::ExecuteIOHandlers() -{ - while (true) - { - IOHandlerSP reader_sp(m_input_reader_stack.Top()); - if (!reader_sp) - break; - - reader_sp->Run(); - - // Remove all input readers that are done from the top of the stack - while (true) - { - IOHandlerSP top_reader_sp = m_input_reader_stack.Top(); - if (top_reader_sp && top_reader_sp->GetIsDone()) - PopIOHandler (top_reader_sp); - else - break; - } + // Remove all input readers that are done from the top of the stack + while (true) { + IOHandlerSP top_reader_sp = m_input_reader_stack.Top(); + if (top_reader_sp && top_reader_sp->GetIsDone()) + PopIOHandler(top_reader_sp); + else + break; } - ClearIOHandlers(); + } + ClearIOHandlers(); } -bool -Debugger::IsTopIOHandler (const lldb::IOHandlerSP& reader_sp) -{ - return m_input_reader_stack.IsTop (reader_sp); +bool Debugger::IsTopIOHandler(const lldb::IOHandlerSP &reader_sp) { + return m_input_reader_stack.IsTop(reader_sp); } -bool -Debugger::CheckTopIOHandlerTypes (IOHandler::Type top_type, IOHandler::Type second_top_type) -{ - return m_input_reader_stack.CheckTopIOHandlerTypes (top_type, second_top_type); +bool Debugger::CheckTopIOHandlerTypes(IOHandler::Type top_type, + IOHandler::Type second_top_type) { + return m_input_reader_stack.CheckTopIOHandlerTypes(top_type, second_top_type); } -void -Debugger::PrintAsync (const char *s, size_t len, bool is_stdout) -{ - lldb::StreamFileSP stream = is_stdout ? GetOutputFile() : GetErrorFile(); - m_input_reader_stack.PrintAsync(stream.get(), s, len); +void Debugger::PrintAsync(const char *s, size_t len, bool is_stdout) { + lldb::StreamFileSP stream = is_stdout ? GetOutputFile() : GetErrorFile(); + m_input_reader_stack.PrintAsync(stream.get(), s, len); } -ConstString -Debugger::GetTopIOHandlerControlSequence(char ch) -{ - return m_input_reader_stack.GetTopIOHandlerControlSequence (ch); +ConstString Debugger::GetTopIOHandlerControlSequence(char ch) { + return m_input_reader_stack.GetTopIOHandlerControlSequence(ch); } -const char * -Debugger::GetIOHandlerCommandPrefix() -{ - return m_input_reader_stack.GetTopIOHandlerCommandPrefix(); +const char *Debugger::GetIOHandlerCommandPrefix() { + return m_input_reader_stack.GetTopIOHandlerCommandPrefix(); } -const char * -Debugger::GetIOHandlerHelpPrologue() -{ - return m_input_reader_stack.GetTopIOHandlerHelpPrologue(); +const char *Debugger::GetIOHandlerHelpPrologue() { + return m_input_reader_stack.GetTopIOHandlerHelpPrologue(); } -void -Debugger::RunIOHandler (const IOHandlerSP& reader_sp) -{ - PushIOHandler (reader_sp); +void Debugger::RunIOHandler(const IOHandlerSP &reader_sp) { + PushIOHandler(reader_sp); - IOHandlerSP top_reader_sp = reader_sp; - while (top_reader_sp) - { - top_reader_sp->Run(); + IOHandlerSP top_reader_sp = reader_sp; + while (top_reader_sp) { + top_reader_sp->Run(); - if (top_reader_sp.get() == reader_sp.get()) - { - if (PopIOHandler (reader_sp)) - break; - } + if (top_reader_sp.get() == reader_sp.get()) { + if (PopIOHandler(reader_sp)) + break; + } - while (true) - { - top_reader_sp = m_input_reader_stack.Top(); - if (top_reader_sp && top_reader_sp->GetIsDone()) - PopIOHandler (top_reader_sp); - else - break; - } + while (true) { + top_reader_sp = m_input_reader_stack.Top(); + if (top_reader_sp && top_reader_sp->GetIsDone()) + PopIOHandler(top_reader_sp); + else + break; } -} + } +} + +void Debugger::AdoptTopIOHandlerFilesIfInvalid(StreamFileSP &in, + StreamFileSP &out, + StreamFileSP &err) { + // Before an IOHandler runs, it must have in/out/err streams. + // This function is called when one ore more of the streams + // are nullptr. We use the top input reader's in/out/err streams, + // or fall back to the debugger file handles, or we fall back + // onto stdin/stdout/stderr as a last resort. + + std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); + IOHandlerSP top_reader_sp(m_input_reader_stack.Top()); + // If no STDIN has been set, then set it appropriately + if (!in) { + if (top_reader_sp) + in = top_reader_sp->GetInputStreamFile(); + else + in = GetInputFile(); -void -Debugger::AdoptTopIOHandlerFilesIfInvalid(StreamFileSP &in, StreamFileSP &out, StreamFileSP &err) -{ - // Before an IOHandler runs, it must have in/out/err streams. - // This function is called when one ore more of the streams - // are nullptr. We use the top input reader's in/out/err streams, - // or fall back to the debugger file handles, or we fall back - // onto stdin/stdout/stderr as a last resort. - - std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); - IOHandlerSP top_reader_sp(m_input_reader_stack.Top()); - // If no STDIN has been set, then set it appropriately + // If there is nothing, use stdin if (!in) - { - if (top_reader_sp) - in = top_reader_sp->GetInputStreamFile(); - else - in = GetInputFile(); - - // If there is nothing, use stdin - if (!in) - in = StreamFileSP(new StreamFile(stdin, false)); - } - // If no STDOUT has been set, then set it appropriately + in = StreamFileSP(new StreamFile(stdin, false)); + } + // If no STDOUT has been set, then set it appropriately + if (!out) { + if (top_reader_sp) + out = top_reader_sp->GetOutputStreamFile(); + else + out = GetOutputFile(); + + // If there is nothing, use stdout if (!out) - { - if (top_reader_sp) - out = top_reader_sp->GetOutputStreamFile(); - else - out = GetOutputFile(); - - // If there is nothing, use stdout - if (!out) - out = StreamFileSP(new StreamFile(stdout, false)); - } - // If no STDERR has been set, then set it appropriately + out = StreamFileSP(new StreamFile(stdout, false)); + } + // If no STDERR has been set, then set it appropriately + if (!err) { + if (top_reader_sp) + err = top_reader_sp->GetErrorStreamFile(); + else + err = GetErrorFile(); + + // If there is nothing, use stderr if (!err) - { - if (top_reader_sp) - err = top_reader_sp->GetErrorStreamFile(); - else - err = GetErrorFile(); - - // If there is nothing, use stderr - if (!err) - err = StreamFileSP(new StreamFile(stdout, false)); - } + err = StreamFileSP(new StreamFile(stdout, false)); + } } -void -Debugger::PushIOHandler(const IOHandlerSP &reader_sp) -{ - if (!reader_sp) - return; +void Debugger::PushIOHandler(const IOHandlerSP &reader_sp) { + if (!reader_sp) + return; - std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); + std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); - // Get the current top input reader... - IOHandlerSP top_reader_sp(m_input_reader_stack.Top()); + // Get the current top input reader... + IOHandlerSP top_reader_sp(m_input_reader_stack.Top()); - // Don't push the same IO handler twice... - if (reader_sp == top_reader_sp) - return; + // Don't push the same IO handler twice... + if (reader_sp == top_reader_sp) + return; - // Push our new input reader - m_input_reader_stack.Push(reader_sp); - reader_sp->Activate(); + // Push our new input reader + m_input_reader_stack.Push(reader_sp); + reader_sp->Activate(); - // Interrupt the top input reader to it will exit its Run() function - // and let this new input reader take over - if (top_reader_sp) - { - top_reader_sp->Deactivate(); - top_reader_sp->Cancel(); - } + // Interrupt the top input reader to it will exit its Run() function + // and let this new input reader take over + if (top_reader_sp) { + top_reader_sp->Deactivate(); + top_reader_sp->Cancel(); + } } -bool -Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) -{ - if (!pop_reader_sp) - return false; +bool Debugger::PopIOHandler(const IOHandlerSP &pop_reader_sp) { + if (!pop_reader_sp) + return false; - std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); + std::lock_guard<std::recursive_mutex> guard(m_input_reader_stack.GetMutex()); - // The reader on the stop of the stack is done, so let the next - // read on the stack refresh its prompt and if there is one... - if (m_input_reader_stack.IsEmpty()) - return false; + // The reader on the stop of the stack is done, so let the next + // read on the stack refresh its prompt and if there is one... + if (m_input_reader_stack.IsEmpty()) + return false; - IOHandlerSP reader_sp(m_input_reader_stack.Top()); + IOHandlerSP reader_sp(m_input_reader_stack.Top()); - if (pop_reader_sp != reader_sp) - return false; + if (pop_reader_sp != reader_sp) + return false; - reader_sp->Deactivate(); - reader_sp->Cancel(); - m_input_reader_stack.Pop(); + reader_sp->Deactivate(); + reader_sp->Cancel(); + m_input_reader_stack.Pop(); - reader_sp = m_input_reader_stack.Top(); - if (reader_sp) - reader_sp->Activate(); + reader_sp = m_input_reader_stack.Top(); + if (reader_sp) + reader_sp->Activate(); - return true; + return true; } -StreamSP -Debugger::GetAsyncOutputStream () -{ - return StreamSP (new StreamAsynchronousIO (*this, true)); +StreamSP Debugger::GetAsyncOutputStream() { + return StreamSP(new StreamAsynchronousIO(*this, true)); } -StreamSP -Debugger::GetAsyncErrorStream () -{ - return StreamSP (new StreamAsynchronousIO (*this, false)); -} +StreamSP Debugger::GetAsyncErrorStream() { + return StreamSP(new StreamAsynchronousIO(*this, false)); +} -size_t -Debugger::GetNumDebuggers() -{ - if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) - { - std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); - return g_debugger_list_ptr->size(); - } - return 0; +size_t Debugger::GetNumDebuggers() { + if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { + std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); + return g_debugger_list_ptr->size(); + } + return 0; } -lldb::DebuggerSP -Debugger::GetDebuggerAtIndex (size_t index) -{ - DebuggerSP debugger_sp; - - if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) - { - std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); - if (index < g_debugger_list_ptr->size()) - debugger_sp = g_debugger_list_ptr->at(index); - } +lldb::DebuggerSP Debugger::GetDebuggerAtIndex(size_t index) { + DebuggerSP debugger_sp; - return debugger_sp; + if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { + std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); + if (index < g_debugger_list_ptr->size()) + debugger_sp = g_debugger_list_ptr->at(index); + } + + return debugger_sp; } -DebuggerSP -Debugger::FindDebuggerWithID (lldb::user_id_t id) -{ - DebuggerSP debugger_sp; +DebuggerSP Debugger::FindDebuggerWithID(lldb::user_id_t id) { + DebuggerSP debugger_sp; - if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) - { - std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); - DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); - for (pos = g_debugger_list_ptr->begin (); pos != end; ++pos) - { - if ((*pos)->GetID() == id) - { - debugger_sp = *pos; - break; - } - } + if (g_debugger_list_ptr && g_debugger_list_mutex_ptr) { + std::lock_guard<std::recursive_mutex> guard(*g_debugger_list_mutex_ptr); + DebuggerList::iterator pos, end = g_debugger_list_ptr->end(); + for (pos = g_debugger_list_ptr->begin(); pos != end; ++pos) { + if ((*pos)->GetID() == id) { + debugger_sp = *pos; + break; + } } - return debugger_sp; + } + return debugger_sp; } #if 0 @@ -1258,582 +1187,535 @@ TestPromptFormats (StackFrame *frame) } #endif -bool -Debugger::FormatDisassemblerAddress (const FormatEntity::Entry *format, - const SymbolContext *sc, - const SymbolContext *prev_sc, - const ExecutionContext *exe_ctx, - const Address *addr, - Stream &s) -{ - FormatEntity::Entry format_entry; - - if (format == nullptr) - { - if (exe_ctx != nullptr && exe_ctx->HasTargetScope()) - format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); - if (format == nullptr) - { - FormatEntity::Parse("${addr}: ", format_entry); - format = &format_entry; - } +bool Debugger::FormatDisassemblerAddress(const FormatEntity::Entry *format, + const SymbolContext *sc, + const SymbolContext *prev_sc, + const ExecutionContext *exe_ctx, + const Address *addr, Stream &s) { + FormatEntity::Entry format_entry; + + if (format == nullptr) { + if (exe_ctx != nullptr && exe_ctx->HasTargetScope()) + format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); + if (format == nullptr) { + FormatEntity::Parse("${addr}: ", format_entry); + format = &format_entry; } - bool function_changed = false; - bool initial_function = false; - if (prev_sc && (prev_sc->function || prev_sc->symbol)) - { - if (sc && (sc->function || sc->symbol)) - { - if (prev_sc->symbol && sc->symbol) - { - if (!sc->symbol->Compare (prev_sc->symbol->GetName(), prev_sc->symbol->GetType())) - { - function_changed = true; - } - } - else if (prev_sc->function && sc->function) - { - if (prev_sc->function->GetMangled() != sc->function->GetMangled()) - { - function_changed = true; - } - } + } + bool function_changed = false; + bool initial_function = false; + if (prev_sc && (prev_sc->function || prev_sc->symbol)) { + if (sc && (sc->function || sc->symbol)) { + if (prev_sc->symbol && sc->symbol) { + if (!sc->symbol->Compare(prev_sc->symbol->GetName(), + prev_sc->symbol->GetType())) { + function_changed = true; + } + } else if (prev_sc->function && sc->function) { + if (prev_sc->function->GetMangled() != sc->function->GetMangled()) { + function_changed = true; } + } } - // The first context on a list of instructions will have a prev_sc that - // has no Function or Symbol -- if SymbolContext had an IsValid() method, it - // would return false. But we do get a prev_sc pointer. - if ((sc && (sc->function || sc->symbol)) - && prev_sc && (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) - { - initial_function = true; + } + // The first context on a list of instructions will have a prev_sc that + // has no Function or Symbol -- if SymbolContext had an IsValid() method, it + // would return false. But we do get a prev_sc pointer. + if ((sc && (sc->function || sc->symbol)) && prev_sc && + (prev_sc->function == nullptr && prev_sc->symbol == nullptr)) { + initial_function = true; + } + return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr, + function_changed, initial_function); +} + +void Debugger::SetLoggingCallback(lldb::LogOutputCallback log_callback, + void *baton) { + // For simplicity's sake, I am not going to deal with how to close down any + // open logging streams, I just redirect everything from here on out to the + // callback. + m_log_callback_stream_sp.reset(new StreamCallback(log_callback, baton)); +} + +bool Debugger::EnableLog(const char *channel, const char **categories, + const char *log_file, uint32_t log_options, + Stream &error_stream) { + StreamSP log_stream_sp; + if (m_log_callback_stream_sp) { + log_stream_sp = m_log_callback_stream_sp; + // For now when using the callback mode you always get thread & timestamp. + log_options |= + LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; + } else if (log_file == nullptr || *log_file == '\0') { + log_stream_sp = GetOutputFile(); + } else { + LogStreamMap::iterator pos = m_log_streams.find(log_file); + if (pos != m_log_streams.end()) + log_stream_sp = pos->second.lock(); + if (!log_stream_sp) { + uint32_t options = File::eOpenOptionWrite | File::eOpenOptionCanCreate | + File::eOpenOptionCloseOnExec | File::eOpenOptionAppend; + if (!(log_options & LLDB_LOG_OPTION_APPEND)) + options |= File::eOpenOptionTruncate; + + log_stream_sp.reset(new StreamFile(log_file, options)); + m_log_streams[log_file] = log_stream_sp; } - return FormatEntity::Format(*format, s, sc, exe_ctx, addr, nullptr, function_changed, initial_function); -} + } + assert(log_stream_sp); -void -Debugger::SetLoggingCallback (lldb::LogOutputCallback log_callback, void *baton) -{ - // For simplicity's sake, I am not going to deal with how to close down any - // open logging streams, I just redirect everything from here on out to the - // callback. - m_log_callback_stream_sp.reset (new StreamCallback (log_callback, baton)); -} + if (log_options == 0) + log_options = + LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE; -bool -Debugger::EnableLog (const char *channel, const char **categories, const char *log_file, uint32_t log_options, Stream &error_stream) -{ - StreamSP log_stream_sp; - if (m_log_callback_stream_sp) - { - log_stream_sp = m_log_callback_stream_sp; - // For now when using the callback mode you always get thread & timestamp. - log_options |= LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_THREAD_NAME; - } - else if (log_file == nullptr || *log_file == '\0') - { - log_stream_sp = GetOutputFile(); - } - else - { - LogStreamMap::iterator pos = m_log_streams.find(log_file); - if (pos != m_log_streams.end()) - log_stream_sp = pos->second.lock(); - if (!log_stream_sp) - { - uint32_t options = File::eOpenOptionWrite | File::eOpenOptionCanCreate - | File::eOpenOptionCloseOnExec | File::eOpenOptionAppend; - if (! (log_options & LLDB_LOG_OPTION_APPEND)) - options |= File::eOpenOptionTruncate; - - log_stream_sp.reset (new StreamFile (log_file, options)); - m_log_streams[log_file] = log_stream_sp; - } - } - assert(log_stream_sp); - - if (log_options == 0) - log_options = LLDB_LOG_OPTION_PREPEND_THREAD_NAME | LLDB_LOG_OPTION_THREADSAFE; - - return Log::EnableLogChannel(log_stream_sp, log_options, channel, categories, error_stream); + return Log::EnableLogChannel(log_stream_sp, log_options, channel, categories, + error_stream); } -SourceManager & -Debugger::GetSourceManager () -{ - if (!m_source_manager_ap) - m_source_manager_ap.reset (new SourceManager (shared_from_this())); - return *m_source_manager_ap; +SourceManager &Debugger::GetSourceManager() { + if (!m_source_manager_ap) + m_source_manager_ap.reset(new SourceManager(shared_from_this())); + return *m_source_manager_ap; } // This function handles events that were broadcast by the process. -void -Debugger::HandleBreakpointEvent (const EventSP &event_sp) -{ - using namespace lldb; - const uint32_t event_type = Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent (event_sp); - -// if (event_type & eBreakpointEventTypeAdded -// || event_type & eBreakpointEventTypeRemoved -// || event_type & eBreakpointEventTypeEnabled -// || event_type & eBreakpointEventTypeDisabled -// || event_type & eBreakpointEventTypeCommandChanged -// || event_type & eBreakpointEventTypeConditionChanged -// || event_type & eBreakpointEventTypeIgnoreChanged -// || event_type & eBreakpointEventTypeLocationsResolved) -// { -// // Don't do anything about these events, since the breakpoint commands already echo these actions. -// } -// - if (event_type & eBreakpointEventTypeLocationsAdded) - { - uint32_t num_new_locations = Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent(event_sp); - if (num_new_locations > 0) - { - BreakpointSP breakpoint = Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp); - StreamSP output_sp (GetAsyncOutputStream()); - if (output_sp) - { - output_sp->Printf("%d location%s added to breakpoint %d\n", - num_new_locations, - num_new_locations == 1 ? "" : "s", - breakpoint->GetID()); - output_sp->Flush(); - } - } +void Debugger::HandleBreakpointEvent(const EventSP &event_sp) { + using namespace lldb; + const uint32_t event_type = + Breakpoint::BreakpointEventData::GetBreakpointEventTypeFromEvent( + event_sp); + + // if (event_type & eBreakpointEventTypeAdded + // || event_type & eBreakpointEventTypeRemoved + // || event_type & eBreakpointEventTypeEnabled + // || event_type & eBreakpointEventTypeDisabled + // || event_type & eBreakpointEventTypeCommandChanged + // || event_type & eBreakpointEventTypeConditionChanged + // || event_type & eBreakpointEventTypeIgnoreChanged + // || event_type & eBreakpointEventTypeLocationsResolved) + // { + // // Don't do anything about these events, since the breakpoint + // commands already echo these actions. + // } + // + if (event_type & eBreakpointEventTypeLocationsAdded) { + uint32_t num_new_locations = + Breakpoint::BreakpointEventData::GetNumBreakpointLocationsFromEvent( + event_sp); + if (num_new_locations > 0) { + BreakpointSP breakpoint = + Breakpoint::BreakpointEventData::GetBreakpointFromEvent(event_sp); + StreamSP output_sp(GetAsyncOutputStream()); + if (output_sp) { + output_sp->Printf("%d location%s added to breakpoint %d\n", + num_new_locations, num_new_locations == 1 ? "" : "s", + breakpoint->GetID()); + output_sp->Flush(); + } } -// else if (event_type & eBreakpointEventTypeLocationsRemoved) -// { -// // These locations just get disabled, not sure it is worth spamming folks about this on the command line. -// } -// else if (event_type & eBreakpointEventTypeLocationsResolved) -// { -// // This might be an interesting thing to note, but I'm going to leave it quiet for now, it just looked noisy. -// } -} - -size_t -Debugger::GetProcessSTDOUT (Process *process, Stream *stream) -{ - size_t total_bytes = 0; - if (stream == nullptr) - stream = GetOutputFile().get(); - - if (stream) - { - // The process has stuff waiting for stdout; get it and write it out to the appropriate place. - if (process == nullptr) - { - TargetSP target_sp = GetTargetList().GetSelectedTarget(); - if (target_sp) - process = target_sp->GetProcessSP().get(); - } - if (process) - { - Error error; - size_t len; - char stdio_buffer[1024]; - while ((len = process->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0) - { - stream->Write(stdio_buffer, len); - total_bytes += len; - } - } - stream->Flush(); + } + // else if (event_type & eBreakpointEventTypeLocationsRemoved) + // { + // // These locations just get disabled, not sure it is worth spamming + // folks about this on the command line. + // } + // else if (event_type & eBreakpointEventTypeLocationsResolved) + // { + // // This might be an interesting thing to note, but I'm going to + // leave it quiet for now, it just looked noisy. + // } +} + +size_t Debugger::GetProcessSTDOUT(Process *process, Stream *stream) { + size_t total_bytes = 0; + if (stream == nullptr) + stream = GetOutputFile().get(); + + if (stream) { + // The process has stuff waiting for stdout; get it and write it out to the + // appropriate place. + if (process == nullptr) { + TargetSP target_sp = GetTargetList().GetSelectedTarget(); + if (target_sp) + process = target_sp->GetProcessSP().get(); } - return total_bytes; -} - -size_t -Debugger::GetProcessSTDERR (Process *process, Stream *stream) -{ - size_t total_bytes = 0; - if (stream == nullptr) - stream = GetOutputFile().get(); - - if (stream) - { - // The process has stuff waiting for stderr; get it and write it out to the appropriate place. - if (process == nullptr) - { - TargetSP target_sp = GetTargetList().GetSelectedTarget(); - if (target_sp) - process = target_sp->GetProcessSP().get(); - } - if (process) - { - Error error; - size_t len; - char stdio_buffer[1024]; - while ((len = process->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0) - { - stream->Write(stdio_buffer, len); - total_bytes += len; - } - } - stream->Flush(); + if (process) { + Error error; + size_t len; + char stdio_buffer[1024]; + while ((len = process->GetSTDOUT(stdio_buffer, sizeof(stdio_buffer), + error)) > 0) { + stream->Write(stdio_buffer, len); + total_bytes += len; + } + } + stream->Flush(); + } + return total_bytes; +} + +size_t Debugger::GetProcessSTDERR(Process *process, Stream *stream) { + size_t total_bytes = 0; + if (stream == nullptr) + stream = GetOutputFile().get(); + + if (stream) { + // The process has stuff waiting for stderr; get it and write it out to the + // appropriate place. + if (process == nullptr) { + TargetSP target_sp = GetTargetList().GetSelectedTarget(); + if (target_sp) + process = target_sp->GetProcessSP().get(); } - return total_bytes; + if (process) { + Error error; + size_t len; + char stdio_buffer[1024]; + while ((len = process->GetSTDERR(stdio_buffer, sizeof(stdio_buffer), + error)) > 0) { + stream->Write(stdio_buffer, len); + total_bytes += len; + } + } + stream->Flush(); + } + return total_bytes; } - // This function handles events that were broadcast by the process. -void -Debugger::HandleProcessEvent (const EventSP &event_sp) -{ - using namespace lldb; - const uint32_t event_type = event_sp->GetType(); - ProcessSP process_sp = Process::ProcessEventData::GetProcessFromEvent(event_sp.get()); - - StreamSP output_stream_sp = GetAsyncOutputStream(); - StreamSP error_stream_sp = GetAsyncErrorStream(); - const bool gui_enabled = IsForwardingEvents(); - - if (!gui_enabled) - { - bool pop_process_io_handler = false; - assert (process_sp); - - bool state_is_stopped = false; - const bool got_state_changed = (event_type & Process::eBroadcastBitStateChanged) != 0; - const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0; - const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0; - if (got_state_changed) - { - StateType event_state = Process::ProcessEventData::GetStateFromEvent (event_sp.get()); - state_is_stopped = StateIsStoppedState(event_state, false); - } - - // Display running state changes first before any STDIO - if (got_state_changed && !state_is_stopped) - { - Process::HandleProcessStateChangedEvent (event_sp, output_stream_sp.get(), pop_process_io_handler); - } - - // Now display and STDOUT - if (got_stdout || got_state_changed) - { - GetProcessSTDOUT (process_sp.get(), output_stream_sp.get()); - } - - // Now display and STDERR - if (got_stderr || got_state_changed) - { - GetProcessSTDERR (process_sp.get(), error_stream_sp.get()); - } +void Debugger::HandleProcessEvent(const EventSP &event_sp) { + using namespace lldb; + const uint32_t event_type = event_sp->GetType(); + ProcessSP process_sp = + (event_type == Process::eBroadcastBitStructuredData) + ? EventDataStructuredData::GetProcessFromEvent(event_sp.get()) + : Process::ProcessEventData::GetProcessFromEvent(event_sp.get()); + + StreamSP output_stream_sp = GetAsyncOutputStream(); + StreamSP error_stream_sp = GetAsyncErrorStream(); + const bool gui_enabled = IsForwardingEvents(); + + if (!gui_enabled) { + bool pop_process_io_handler = false; + assert(process_sp); + + bool state_is_stopped = false; + const bool got_state_changed = + (event_type & Process::eBroadcastBitStateChanged) != 0; + const bool got_stdout = (event_type & Process::eBroadcastBitSTDOUT) != 0; + const bool got_stderr = (event_type & Process::eBroadcastBitSTDERR) != 0; + const bool got_structured_data = + (event_type & Process::eBroadcastBitStructuredData) != 0; + + if (got_state_changed) { + StateType event_state = + Process::ProcessEventData::GetStateFromEvent(event_sp.get()); + state_is_stopped = StateIsStoppedState(event_state, false); + } - // Now display any stopped state changes after any STDIO - if (got_state_changed && state_is_stopped) - { - Process::HandleProcessStateChangedEvent (event_sp, output_stream_sp.get(), pop_process_io_handler); - } + // Display running state changes first before any STDIO + if (got_state_changed && !state_is_stopped) { + Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(), + pop_process_io_handler); + } - output_stream_sp->Flush(); - error_stream_sp->Flush(); + // Now display and STDOUT + if (got_stdout || got_state_changed) { + GetProcessSTDOUT(process_sp.get(), output_stream_sp.get()); + } - if (pop_process_io_handler) - process_sp->PopProcessIOHandler(); + // Now display and STDERR + if (got_stderr || got_state_changed) { + GetProcessSTDERR(process_sp.get(), error_stream_sp.get()); } -} -void -Debugger::HandleThreadEvent (const EventSP &event_sp) -{ - // At present the only thread event we handle is the Frame Changed event, - // and all we do for that is just reprint the thread status for that thread. - using namespace lldb; - const uint32_t event_type = event_sp->GetType(); - if (event_type == Thread::eBroadcastBitStackChanged || - event_type == Thread::eBroadcastBitThreadSelected ) - { - ThreadSP thread_sp (Thread::ThreadEventData::GetThreadFromEvent (event_sp.get())); - if (thread_sp) - { - thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1); + // Give structured data events an opportunity to display. + if (got_structured_data) { + StructuredDataPluginSP plugin_sp = + EventDataStructuredData::GetPluginFromEvent(event_sp.get()); + if (plugin_sp) { + auto structured_data_sp = + EventDataStructuredData::GetObjectFromEvent(event_sp.get()); + if (output_stream_sp) { + StreamString content_stream; + Error error = + plugin_sp->GetDescription(structured_data_sp, content_stream); + if (error.Success()) { + if (!content_stream.GetString().empty()) { + // Add newline. + content_stream.PutChar('\n'); + content_stream.Flush(); + + // Print it. + output_stream_sp->PutCString(content_stream.GetString()); + } + } else { + error_stream_sp->Printf("Failed to print structured " + "data with plugin %s: %s", + plugin_sp->GetPluginName().AsCString(), + error.AsCString()); + } } + } } -} - -bool -Debugger::IsForwardingEvents () -{ - return (bool)m_forward_listener_sp; -} - -void -Debugger::EnableForwardEvents (const ListenerSP &listener_sp) -{ - m_forward_listener_sp = listener_sp; -} - -void -Debugger::CancelForwardEvents (const ListenerSP &listener_sp) -{ - m_forward_listener_sp.reset(); -} + // Now display any stopped state changes after any STDIO + if (got_state_changed && state_is_stopped) { + Process::HandleProcessStateChangedEvent(event_sp, output_stream_sp.get(), + pop_process_io_handler); + } -void -Debugger::DefaultEventHandler() -{ - ListenerSP listener_sp(GetListener()); - ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass()); - ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass()); - ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass()); - BroadcastEventSpec target_event_spec (broadcaster_class_target, - Target::eBroadcastBitBreakpointChanged); - - BroadcastEventSpec process_event_spec (broadcaster_class_process, - Process::eBroadcastBitStateChanged | - Process::eBroadcastBitSTDOUT | - Process::eBroadcastBitSTDERR); - - BroadcastEventSpec thread_event_spec (broadcaster_class_thread, - Thread::eBroadcastBitStackChanged | - Thread::eBroadcastBitThreadSelected ); - - listener_sp->StartListeningForEventSpec (m_broadcaster_manager_sp, target_event_spec); - listener_sp->StartListeningForEventSpec (m_broadcaster_manager_sp, process_event_spec); - listener_sp->StartListeningForEventSpec (m_broadcaster_manager_sp, thread_event_spec); - listener_sp->StartListeningForEvents (m_command_interpreter_ap.get(), - CommandInterpreter::eBroadcastBitQuitCommandReceived | - CommandInterpreter::eBroadcastBitAsynchronousOutputData | - CommandInterpreter::eBroadcastBitAsynchronousErrorData ); - - // Let the thread that spawned us know that we have started up and - // that we are now listening to all required events so no events get missed - m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening); - - bool done = false; - while (!done) - { - EventSP event_sp; - if (listener_sp->WaitForEvent(nullptr, event_sp)) - { - if (event_sp) - { - Broadcaster *broadcaster = event_sp->GetBroadcaster(); - if (broadcaster) - { - uint32_t event_type = event_sp->GetType(); - ConstString broadcaster_class (broadcaster->GetBroadcasterClass()); - if (broadcaster_class == broadcaster_class_process) - { - HandleProcessEvent (event_sp); - } - else if (broadcaster_class == broadcaster_class_target) - { - if (Breakpoint::BreakpointEventData::GetEventDataFromEvent(event_sp.get())) - { - HandleBreakpointEvent (event_sp); - } - } - else if (broadcaster_class == broadcaster_class_thread) - { - HandleThreadEvent (event_sp); - } - else if (broadcaster == m_command_interpreter_ap.get()) - { - if (event_type & CommandInterpreter::eBroadcastBitQuitCommandReceived) - { - done = true; - } - else if (event_type & CommandInterpreter::eBroadcastBitAsynchronousErrorData) - { - const char *data = reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event_sp.get())); - if (data && data[0]) - { - StreamSP error_sp (GetAsyncErrorStream()); - if (error_sp) - { - error_sp->PutCString(data); - error_sp->Flush(); - } - } - } - else if (event_type & CommandInterpreter::eBroadcastBitAsynchronousOutputData) - { - const char *data = reinterpret_cast<const char *>(EventDataBytes::GetBytesFromEvent (event_sp.get())); - if (data && data[0]) - { - StreamSP output_sp (GetAsyncOutputStream()); - if (output_sp) - { - output_sp->PutCString(data); - output_sp->Flush(); - } - } - } - } + output_stream_sp->Flush(); + error_stream_sp->Flush(); + + if (pop_process_io_handler) + process_sp->PopProcessIOHandler(); + } +} + +void Debugger::HandleThreadEvent(const EventSP &event_sp) { + // At present the only thread event we handle is the Frame Changed event, + // and all we do for that is just reprint the thread status for that thread. + using namespace lldb; + const uint32_t event_type = event_sp->GetType(); + const bool stop_format = true; + if (event_type == Thread::eBroadcastBitStackChanged || + event_type == Thread::eBroadcastBitThreadSelected) { + ThreadSP thread_sp( + Thread::ThreadEventData::GetThreadFromEvent(event_sp.get())); + if (thread_sp) { + thread_sp->GetStatus(*GetAsyncOutputStream(), 0, 1, 1, stop_format); + } + } +} + +bool Debugger::IsForwardingEvents() { return (bool)m_forward_listener_sp; } + +void Debugger::EnableForwardEvents(const ListenerSP &listener_sp) { + m_forward_listener_sp = listener_sp; +} + +void Debugger::CancelForwardEvents(const ListenerSP &listener_sp) { + m_forward_listener_sp.reset(); +} + +void Debugger::DefaultEventHandler() { + ListenerSP listener_sp(GetListener()); + ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass()); + ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass()); + ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass()); + BroadcastEventSpec target_event_spec(broadcaster_class_target, + Target::eBroadcastBitBreakpointChanged); + + BroadcastEventSpec process_event_spec( + broadcaster_class_process, + Process::eBroadcastBitStateChanged | Process::eBroadcastBitSTDOUT | + Process::eBroadcastBitSTDERR | Process::eBroadcastBitStructuredData); + + BroadcastEventSpec thread_event_spec(broadcaster_class_thread, + Thread::eBroadcastBitStackChanged | + Thread::eBroadcastBitThreadSelected); + + listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp, + target_event_spec); + listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp, + process_event_spec); + listener_sp->StartListeningForEventSpec(m_broadcaster_manager_sp, + thread_event_spec); + listener_sp->StartListeningForEvents( + m_command_interpreter_ap.get(), + CommandInterpreter::eBroadcastBitQuitCommandReceived | + CommandInterpreter::eBroadcastBitAsynchronousOutputData | + CommandInterpreter::eBroadcastBitAsynchronousErrorData); + + // Let the thread that spawned us know that we have started up and + // that we are now listening to all required events so no events get missed + m_sync_broadcaster.BroadcastEvent(eBroadcastBitEventThreadIsListening); + + bool done = false; + while (!done) { + EventSP event_sp; + if (listener_sp->GetEvent(event_sp, llvm::None)) { + if (event_sp) { + Broadcaster *broadcaster = event_sp->GetBroadcaster(); + if (broadcaster) { + uint32_t event_type = event_sp->GetType(); + ConstString broadcaster_class(broadcaster->GetBroadcasterClass()); + if (broadcaster_class == broadcaster_class_process) { + HandleProcessEvent(event_sp); + } else if (broadcaster_class == broadcaster_class_target) { + if (Breakpoint::BreakpointEventData::GetEventDataFromEvent( + event_sp.get())) { + HandleBreakpointEvent(event_sp); + } + } else if (broadcaster_class == broadcaster_class_thread) { + HandleThreadEvent(event_sp); + } else if (broadcaster == m_command_interpreter_ap.get()) { + if (event_type & + CommandInterpreter::eBroadcastBitQuitCommandReceived) { + done = true; + } else if (event_type & + CommandInterpreter::eBroadcastBitAsynchronousErrorData) { + const char *data = reinterpret_cast<const char *>( + EventDataBytes::GetBytesFromEvent(event_sp.get())); + if (data && data[0]) { + StreamSP error_sp(GetAsyncErrorStream()); + if (error_sp) { + error_sp->PutCString(data); + error_sp->Flush(); + } + } + } else if (event_type & CommandInterpreter:: + eBroadcastBitAsynchronousOutputData) { + const char *data = reinterpret_cast<const char *>( + EventDataBytes::GetBytesFromEvent(event_sp.get())); + if (data && data[0]) { + StreamSP output_sp(GetAsyncOutputStream()); + if (output_sp) { + output_sp->PutCString(data); + output_sp->Flush(); } - - if (m_forward_listener_sp) - m_forward_listener_sp->AddEvent(event_sp); + } } + } } - } -} - -lldb::thread_result_t -Debugger::EventHandlerThread (lldb::thread_arg_t arg) -{ - ((Debugger *)arg)->DefaultEventHandler(); - return NULL; -} -bool -Debugger::StartEventHandlerThread() -{ - if (!m_event_handler_thread.IsJoinable()) - { - // We must synchronize with the DefaultEventHandler() thread to ensure - // it is up and running and listening to events before we return from - // this function. We do this by listening to events for the - // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster - ListenerSP listener_sp(Listener::MakeListener("lldb.debugger.event-handler")); - listener_sp->StartListeningForEvents(&m_sync_broadcaster, eBroadcastBitEventThreadIsListening); - - // Use larger 8MB stack for this thread - m_event_handler_thread = ThreadLauncher::LaunchThread("lldb.debugger.event-handler", - EventHandlerThread, - this, - nullptr, - g_debugger_event_thread_stack_bytes); - - // Make sure DefaultEventHandler() is running and listening to events before we return - // from this function. We are only listening for events of type - // eBroadcastBitEventThreadIsListening so we don't need to check the event, we just need - // to wait an infinite amount of time for it (nullptr timeout as the first parameter) - lldb::EventSP event_sp; - listener_sp->WaitForEvent(nullptr, event_sp); + if (m_forward_listener_sp) + m_forward_listener_sp->AddEvent(event_sp); + } } - return m_event_handler_thread.IsJoinable(); + } +} + +lldb::thread_result_t Debugger::EventHandlerThread(lldb::thread_arg_t arg) { + ((Debugger *)arg)->DefaultEventHandler(); + return NULL; +} + +bool Debugger::StartEventHandlerThread() { + if (!m_event_handler_thread.IsJoinable()) { + // We must synchronize with the DefaultEventHandler() thread to ensure + // it is up and running and listening to events before we return from + // this function. We do this by listening to events for the + // eBroadcastBitEventThreadIsListening from the m_sync_broadcaster + ListenerSP listener_sp( + Listener::MakeListener("lldb.debugger.event-handler")); + listener_sp->StartListeningForEvents(&m_sync_broadcaster, + eBroadcastBitEventThreadIsListening); + + // Use larger 8MB stack for this thread + m_event_handler_thread = ThreadLauncher::LaunchThread( + "lldb.debugger.event-handler", EventHandlerThread, this, nullptr, + g_debugger_event_thread_stack_bytes); + + // Make sure DefaultEventHandler() is running and listening to events before + // we return + // from this function. We are only listening for events of type + // eBroadcastBitEventThreadIsListening so we don't need to check the event, + // we just need + // to wait an infinite amount of time for it (nullptr timeout as the first + // parameter) + lldb::EventSP event_sp; + listener_sp->GetEvent(event_sp, llvm::None); + } + return m_event_handler_thread.IsJoinable(); +} + +void Debugger::StopEventHandlerThread() { + if (m_event_handler_thread.IsJoinable()) { + GetCommandInterpreter().BroadcastEvent( + CommandInterpreter::eBroadcastBitQuitCommandReceived); + m_event_handler_thread.Join(nullptr); + } +} + +lldb::thread_result_t Debugger::IOHandlerThread(lldb::thread_arg_t arg) { + Debugger *debugger = (Debugger *)arg; + debugger->ExecuteIOHandlers(); + debugger->StopEventHandlerThread(); + return NULL; +} + +bool Debugger::HasIOHandlerThread() { return m_io_handler_thread.IsJoinable(); } + +bool Debugger::StartIOHandlerThread() { + if (!m_io_handler_thread.IsJoinable()) + m_io_handler_thread = ThreadLauncher::LaunchThread( + "lldb.debugger.io-handler", IOHandlerThread, this, nullptr, + 8 * 1024 * 1024); // Use larger 8MB stack for this thread + return m_io_handler_thread.IsJoinable(); +} + +void Debugger::StopIOHandlerThread() { + if (m_io_handler_thread.IsJoinable()) { + if (m_input_file_sp) + m_input_file_sp->GetFile().Close(); + m_io_handler_thread.Join(nullptr); + } } -void -Debugger::StopEventHandlerThread() -{ - if (m_event_handler_thread.IsJoinable()) - { - GetCommandInterpreter().BroadcastEvent(CommandInterpreter::eBroadcastBitQuitCommandReceived); - m_event_handler_thread.Join(nullptr); - } +void Debugger::JoinIOHandlerThread() { + if (HasIOHandlerThread()) { + thread_result_t result; + m_io_handler_thread.Join(&result); + m_io_handler_thread = LLDB_INVALID_HOST_THREAD; + } } -lldb::thread_result_t -Debugger::IOHandlerThread (lldb::thread_arg_t arg) -{ - Debugger *debugger = (Debugger *)arg; - debugger->ExecuteIOHandlers(); - debugger->StopEventHandlerThread(); - return NULL; +Target *Debugger::GetDummyTarget() { + return m_target_list.GetDummyTarget(*this).get(); } -bool -Debugger::HasIOHandlerThread() -{ - return m_io_handler_thread.IsJoinable(); -} +Target *Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) { + Target *target = nullptr; + if (!prefer_dummy) { + target = m_target_list.GetSelectedTarget().get(); + if (target) + return target; + } -bool -Debugger::StartIOHandlerThread() -{ - if (!m_io_handler_thread.IsJoinable()) - m_io_handler_thread = ThreadLauncher::LaunchThread("lldb.debugger.io-handler", - IOHandlerThread, - this, - nullptr, - 8*1024*1024); // Use larger 8MB stack for this thread - return m_io_handler_thread.IsJoinable(); + return GetDummyTarget(); } -void -Debugger::StopIOHandlerThread() -{ - if (m_io_handler_thread.IsJoinable()) - { - if (m_input_file_sp) - m_input_file_sp->GetFile().Close(); - m_io_handler_thread.Join(nullptr); - } -} +Error Debugger::RunREPL(LanguageType language, const char *repl_options) { + Error err; + FileSpec repl_executable; -void -Debugger::JoinIOHandlerThread() -{ - if (HasIOHandlerThread()) - { - thread_result_t result; - m_io_handler_thread.Join(&result); - m_io_handler_thread = LLDB_INVALID_HOST_THREAD; - } -} + if (language == eLanguageTypeUnknown) { + std::set<LanguageType> repl_languages; -Target * -Debugger::GetDummyTarget() -{ - return m_target_list.GetDummyTarget (*this).get(); -} + Language::GetLanguagesSupportingREPLs(repl_languages); -Target * -Debugger::GetSelectedOrDummyTarget(bool prefer_dummy) -{ - Target *target = nullptr; - if (!prefer_dummy) - { - target = m_target_list.GetSelectedTarget().get(); - if (target) - return target; + if (repl_languages.size() == 1) { + language = *repl_languages.begin(); + } else if (repl_languages.empty()) { + err.SetErrorStringWithFormat( + "LLDB isn't configured with REPL support for any languages."); + return err; + } else { + err.SetErrorStringWithFormat( + "Multiple possible REPL languages. Please specify a language."); + return err; } - - return GetDummyTarget(); -} + } -Error -Debugger::RunREPL (LanguageType language, const char *repl_options) -{ - Error err; - FileSpec repl_executable; - - if (language == eLanguageTypeUnknown) - { - std::set<LanguageType> repl_languages; - - Language::GetLanguagesSupportingREPLs(repl_languages); - - if (repl_languages.size() == 1) - { - language = *repl_languages.begin(); - } - else if (repl_languages.empty()) - { - err.SetErrorStringWithFormat("LLDB isn't configured with REPL support for any languages."); - return err; - } - else - { - err.SetErrorStringWithFormat("Multiple possible REPL languages. Please specify a language."); - return err; - } - } + Target *const target = + nullptr; // passing in an empty target means the REPL must create one - Target *const target = nullptr; // passing in an empty target means the REPL must create one - - REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options)); + REPLSP repl_sp(REPL::Create(err, language, this, target, repl_options)); - if (!err.Success()) - { - return err; - } - - if (!repl_sp) - { - err.SetErrorStringWithFormat("couldn't find a REPL for %s", Language::GetNameForLanguageType(language)); - return err; - } - - repl_sp->SetCompilerOptions(repl_options); - repl_sp->RunLoop(); - + if (!err.Success()) { + return err; + } + + if (!repl_sp) { + err.SetErrorStringWithFormat("couldn't find a REPL for %s", + Language::GetNameForLanguageType(language)); return err; + } + + repl_sp->SetCompilerOptions(repl_options); + repl_sp->RunLoop(); + + return err; } diff --git a/source/Core/Disassembler.cpp b/source/Core/Disassembler.cpp index 1e6a245261bb..7cac29491c8c 100644 --- a/source/Core/Disassembler.cpp +++ b/source/Core/Disassembler.cpp @@ -29,6 +29,7 @@ #include "lldb/Interpreter/OptionValue.h" #include "lldb/Interpreter/OptionValueArray.h" #include "lldb/Interpreter/OptionValueDictionary.h" +#include "lldb/Interpreter/OptionValueRegex.h" #include "lldb/Interpreter/OptionValueString.h" #include "lldb/Interpreter/OptionValueUInt64.h" #include "lldb/Symbol/Function.h" @@ -45,1271 +46,1405 @@ using namespace lldb; using namespace lldb_private; -DisassemblerSP -Disassembler::FindPlugin (const ArchSpec &arch, const char *flavor, const char *plugin_name) -{ - Timer scoped_timer (__PRETTY_FUNCTION__, - "Disassembler::FindPlugin (arch = %s, plugin_name = %s)", - arch.GetArchitectureName(), - plugin_name); - - DisassemblerCreateInstance create_callback = nullptr; - - if (plugin_name) - { - ConstString const_plugin_name (plugin_name); - create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName (const_plugin_name); - if (create_callback) - { - DisassemblerSP disassembler_sp(create_callback(arch, flavor)); - - if (disassembler_sp) - return disassembler_sp; - } +DisassemblerSP Disassembler::FindPlugin(const ArchSpec &arch, + const char *flavor, + const char *plugin_name) { + Timer scoped_timer(LLVM_PRETTY_FUNCTION, + "Disassembler::FindPlugin (arch = %s, plugin_name = %s)", + arch.GetArchitectureName(), plugin_name); + + DisassemblerCreateInstance create_callback = nullptr; + + if (plugin_name) { + ConstString const_plugin_name(plugin_name); + create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName( + const_plugin_name); + if (create_callback) { + DisassemblerSP disassembler_sp(create_callback(arch, flavor)); + + if (disassembler_sp) + return disassembler_sp; } - else - { - for (uint32_t idx = 0; (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(idx)) != nullptr; ++idx) - { - DisassemblerSP disassembler_sp(create_callback(arch, flavor)); - - if (disassembler_sp) - return disassembler_sp; - } + } else { + for (uint32_t idx = 0; + (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex( + idx)) != nullptr; + ++idx) { + DisassemblerSP disassembler_sp(create_callback(arch, flavor)); + + if (disassembler_sp) + return disassembler_sp; } - return DisassemblerSP(); + } + return DisassemblerSP(); } -DisassemblerSP -Disassembler::FindPluginForTarget(const TargetSP target_sp, const ArchSpec &arch, const char *flavor, const char *plugin_name) -{ - if (target_sp && flavor == nullptr) - { - // FIXME - we don't have the mechanism in place to do per-architecture settings. But since we know that for now - // we only support flavors on x86 & x86_64, - if (arch.GetTriple().getArch() == llvm::Triple::x86 - || arch.GetTriple().getArch() == llvm::Triple::x86_64) - flavor = target_sp->GetDisassemblyFlavor(); - } - return FindPlugin(arch, flavor, plugin_name); +DisassemblerSP Disassembler::FindPluginForTarget(const TargetSP target_sp, + const ArchSpec &arch, + const char *flavor, + const char *plugin_name) { + if (target_sp && flavor == nullptr) { + // FIXME - we don't have the mechanism in place to do per-architecture + // settings. But since we know that for now + // we only support flavors on x86 & x86_64, + if (arch.GetTriple().getArch() == llvm::Triple::x86 || + arch.GetTriple().getArch() == llvm::Triple::x86_64) + flavor = target_sp->GetDisassemblyFlavor(); + } + return FindPlugin(arch, flavor, plugin_name); } -static void -ResolveAddress (const ExecutionContext &exe_ctx, - const Address &addr, - Address &resolved_addr) -{ - if (!addr.IsSectionOffset()) - { - // If we weren't passed in a section offset address range, - // try and resolve it to something - Target *target = exe_ctx.GetTargetPtr(); - if (target) - { - if (target->GetSectionLoadList().IsEmpty()) - { - target->GetImages().ResolveFileAddress (addr.GetOffset(), resolved_addr); - } - else - { - target->GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), resolved_addr); - } - // We weren't able to resolve the address, just treat it as a - // raw address - if (resolved_addr.IsValid()) - return; - } +static void ResolveAddress(const ExecutionContext &exe_ctx, const Address &addr, + Address &resolved_addr) { + if (!addr.IsSectionOffset()) { + // If we weren't passed in a section offset address range, + // try and resolve it to something + Target *target = exe_ctx.GetTargetPtr(); + if (target) { + if (target->GetSectionLoadList().IsEmpty()) { + target->GetImages().ResolveFileAddress(addr.GetOffset(), resolved_addr); + } else { + target->GetSectionLoadList().ResolveLoadAddress(addr.GetOffset(), + resolved_addr); + } + // We weren't able to resolve the address, just treat it as a + // raw address + if (resolved_addr.IsValid()) + return; } - resolved_addr = addr; + } + resolved_addr = addr; } -size_t -Disassembler::Disassemble(Debugger &debugger, - const ArchSpec &arch, - const char *plugin_name, - const char *flavor, - const ExecutionContext &exe_ctx, - SymbolContextList &sc_list, - uint32_t num_instructions, - uint32_t num_mixed_context_lines, - uint32_t options, - Stream &strm) -{ - size_t success_count = 0; - const size_t count = sc_list.GetSize(); - SymbolContext sc; - AddressRange range; - const uint32_t scope = eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol; - const bool use_inline_block_range = true; - for (size_t i = 0; i < count; ++i) - { - if (!sc_list.GetContextAtIndex(i, sc)) - break; - for (uint32_t range_idx = 0; sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); ++range_idx) - { - if (Disassemble (debugger, - arch, - plugin_name, - flavor, - exe_ctx, - range, - num_instructions, - num_mixed_context_lines, - options, - strm)) - { - ++success_count; - strm.EOL(); - } - } +size_t Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, + const char *plugin_name, const char *flavor, + const ExecutionContext &exe_ctx, + SymbolContextList &sc_list, + uint32_t num_instructions, + bool mixed_source_and_assembly, + uint32_t num_mixed_context_lines, + uint32_t options, Stream &strm) { + size_t success_count = 0; + const size_t count = sc_list.GetSize(); + SymbolContext sc; + AddressRange range; + const uint32_t scope = + eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol; + const bool use_inline_block_range = true; + for (size_t i = 0; i < count; ++i) { + if (!sc_list.GetContextAtIndex(i, sc)) + break; + for (uint32_t range_idx = 0; + sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); + ++range_idx) { + if (Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, range, + num_instructions, mixed_source_and_assembly, + num_mixed_context_lines, options, strm)) { + ++success_count; + strm.EOL(); + } } - return success_count; + } + return success_count; } -bool -Disassembler::Disassemble(Debugger &debugger, - const ArchSpec &arch, - const char *plugin_name, - const char *flavor, - const ExecutionContext &exe_ctx, - const ConstString &name, - Module *module, - uint32_t num_instructions, - uint32_t num_mixed_context_lines, - uint32_t options, - Stream &strm) -{ - SymbolContextList sc_list; - if (name) - { - const bool include_symbols = true; - const bool include_inlines = true; - if (module) - { - module->FindFunctions(name, - nullptr, - eFunctionNameTypeAuto, - include_symbols, - include_inlines, - true, - sc_list); - } - else if (exe_ctx.GetTargetPtr()) - { - exe_ctx.GetTargetPtr()->GetImages().FindFunctions (name, - eFunctionNameTypeAuto, - include_symbols, - include_inlines, - false, - sc_list); - } +bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, + const char *plugin_name, const char *flavor, + const ExecutionContext &exe_ctx, + const ConstString &name, Module *module, + uint32_t num_instructions, + bool mixed_source_and_assembly, + uint32_t num_mixed_context_lines, + uint32_t options, Stream &strm) { + SymbolContextList sc_list; + if (name) { + const bool include_symbols = true; + const bool include_inlines = true; + if (module) { + module->FindFunctions(name, nullptr, eFunctionNameTypeAuto, + include_symbols, include_inlines, true, sc_list); + } else if (exe_ctx.GetTargetPtr()) { + exe_ctx.GetTargetPtr()->GetImages().FindFunctions( + name, eFunctionNameTypeAuto, include_symbols, include_inlines, false, + sc_list); } - - if (sc_list.GetSize ()) - { - return Disassemble (debugger, - arch, - plugin_name, - flavor, - exe_ctx, - sc_list, - num_instructions, - num_mixed_context_lines, - options, - strm); + } + + if (sc_list.GetSize()) { + return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, sc_list, + num_instructions, mixed_source_and_assembly, + num_mixed_context_lines, options, strm); + } + return false; +} + +lldb::DisassemblerSP Disassembler::DisassembleRange( + const ArchSpec &arch, const char *plugin_name, const char *flavor, + const ExecutionContext &exe_ctx, const AddressRange &range, + bool prefer_file_cache) { + lldb::DisassemblerSP disasm_sp; + if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid()) { + disasm_sp = Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, + flavor, plugin_name); + + if (disasm_sp) { + size_t bytes_disassembled = disasm_sp->ParseInstructions( + &exe_ctx, range, nullptr, prefer_file_cache); + if (bytes_disassembled == 0) + disasm_sp.reset(); } - return false; + } + return disasm_sp; } lldb::DisassemblerSP -Disassembler::DisassembleRange(const ArchSpec &arch, - const char *plugin_name, - const char *flavor, - const ExecutionContext &exe_ctx, - const AddressRange &range, - bool prefer_file_cache) -{ - lldb::DisassemblerSP disasm_sp; - if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid()) - { - disasm_sp = Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, flavor, plugin_name); - - if (disasm_sp) - { - size_t bytes_disassembled = disasm_sp->ParseInstructions(&exe_ctx, range, nullptr, prefer_file_cache); - if (bytes_disassembled == 0) - disasm_sp.reset(); - } +Disassembler::DisassembleBytes(const ArchSpec &arch, const char *plugin_name, + const char *flavor, const Address &start, + const void *src, size_t src_len, + uint32_t num_instructions, bool data_from_file) { + lldb::DisassemblerSP disasm_sp; + + if (src) { + disasm_sp = Disassembler::FindPlugin(arch, flavor, plugin_name); + + if (disasm_sp) { + DataExtractor data(src, src_len, arch.GetByteOrder(), + arch.GetAddressByteSize()); + + (void)disasm_sp->DecodeInstructions(start, data, 0, num_instructions, + false, data_from_file); } - return disasm_sp; + } + + return disasm_sp; } -lldb::DisassemblerSP -Disassembler::DisassembleBytes (const ArchSpec &arch, - const char *plugin_name, - const char *flavor, - const Address &start, - const void *src, - size_t src_len, - uint32_t num_instructions, - bool data_from_file) -{ - lldb::DisassemblerSP disasm_sp; - - if (src) - { - disasm_sp = Disassembler::FindPlugin(arch, flavor, plugin_name); - - if (disasm_sp) - { - DataExtractor data(src, src_len, arch.GetByteOrder(), arch.GetAddressByteSize()); - - (void)disasm_sp->DecodeInstructions (start, - data, - 0, - num_instructions, - false, - data_from_file); - } +bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, + const char *plugin_name, const char *flavor, + const ExecutionContext &exe_ctx, + const AddressRange &disasm_range, + uint32_t num_instructions, + bool mixed_source_and_assembly, + uint32_t num_mixed_context_lines, + uint32_t options, Stream &strm) { + if (disasm_range.GetByteSize()) { + lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget( + exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); + + if (disasm_sp) { + AddressRange range; + ResolveAddress(exe_ctx, disasm_range.GetBaseAddress(), + range.GetBaseAddress()); + range.SetByteSize(disasm_range.GetByteSize()); + const bool prefer_file_cache = false; + size_t bytes_disassembled = disasm_sp->ParseInstructions( + &exe_ctx, range, &strm, prefer_file_cache); + if (bytes_disassembled == 0) + return false; + + return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx, + num_instructions, mixed_source_and_assembly, + num_mixed_context_lines, options, strm); } - - return disasm_sp; + } + return false; } -bool -Disassembler::Disassemble(Debugger &debugger, - const ArchSpec &arch, - const char *plugin_name, - const char *flavor, - const ExecutionContext &exe_ctx, - const AddressRange &disasm_range, - uint32_t num_instructions, - uint32_t num_mixed_context_lines, - uint32_t options, - Stream &strm) -{ - if (disasm_range.GetByteSize()) - { - lldb::DisassemblerSP disasm_sp (Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); - - if (disasm_sp) - { - AddressRange range; - ResolveAddress (exe_ctx, disasm_range.GetBaseAddress(), range.GetBaseAddress()); - range.SetByteSize (disasm_range.GetByteSize()); - const bool prefer_file_cache = false; - size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range, &strm, prefer_file_cache); - if (bytes_disassembled == 0) - return false; - - return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx, num_instructions, - num_mixed_context_lines, options, strm); - } +bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, + const char *plugin_name, const char *flavor, + const ExecutionContext &exe_ctx, + const Address &start_address, + uint32_t num_instructions, + bool mixed_source_and_assembly, + uint32_t num_mixed_context_lines, + uint32_t options, Stream &strm) { + if (num_instructions > 0) { + lldb::DisassemblerSP disasm_sp(Disassembler::FindPluginForTarget( + exe_ctx.GetTargetSP(), arch, flavor, plugin_name)); + if (disasm_sp) { + Address addr; + ResolveAddress(exe_ctx, start_address, addr); + const bool prefer_file_cache = false; + size_t bytes_disassembled = disasm_sp->ParseInstructions( + &exe_ctx, addr, num_instructions, prefer_file_cache); + if (bytes_disassembled == 0) + return false; + return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx, + num_instructions, mixed_source_and_assembly, + num_mixed_context_lines, options, strm); } - return false; + } + return false; } - -bool -Disassembler::Disassemble(Debugger &debugger, - const ArchSpec &arch, - const char *plugin_name, - const char *flavor, - const ExecutionContext &exe_ctx, - const Address &start_address, - uint32_t num_instructions, - uint32_t num_mixed_context_lines, - uint32_t options, - Stream &strm) -{ - if (num_instructions > 0) - { - lldb::DisassemblerSP disasm_sp (Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), - arch, - flavor, - plugin_name)); - if (disasm_sp) - { - Address addr; - ResolveAddress (exe_ctx, start_address, addr); - const bool prefer_file_cache = false; - size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, - addr, - num_instructions, - prefer_file_cache); - if (bytes_disassembled == 0) - return false; - return PrintInstructions(disasm_sp.get(), debugger, arch, exe_ctx, num_instructions, - num_mixed_context_lines, options, strm); - } + +Disassembler::SourceLine +Disassembler::GetFunctionDeclLineEntry(const SymbolContext &sc) { + SourceLine decl_line; + if (sc.function && sc.line_entry.IsValid()) { + LineEntry prologue_end_line = sc.line_entry; + FileSpec func_decl_file; + uint32_t func_decl_line; + sc.function->GetStartLineSourceInfo(func_decl_file, func_decl_line); + if (func_decl_file == prologue_end_line.file || + func_decl_file == prologue_end_line.original_file) { + decl_line.file = func_decl_file; + decl_line.line = func_decl_line; + // TODO do we care about column on these entries? If so, we need to + // plumb that through GetStartLineSourceInfo. + decl_line.column = 0; } - return false; + } + return decl_line; } -bool -Disassembler::PrintInstructions(Disassembler *disasm_ptr, Debugger &debugger, const ArchSpec &arch, - const ExecutionContext &exe_ctx, uint32_t num_instructions, - uint32_t num_mixed_context_lines, uint32_t options, Stream &strm) -{ - // We got some things disassembled... - size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize(); - - if (num_instructions > 0 && num_instructions < num_instructions_found) - num_instructions_found = num_instructions; - - const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize (); - uint32_t offset = 0; - SymbolContext sc; - SymbolContext prev_sc; - AddressRange sc_range; - const Address *pc_addr_ptr = nullptr; - StackFrame *frame = exe_ctx.GetFramePtr(); - - TargetSP target_sp (exe_ctx.GetTargetSP()); - SourceManager &source_manager = target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager(); - - if (frame) - { - pc_addr_ptr = &frame->GetFrameCodeAddress(); +void Disassembler::AddLineToSourceLineTables( + SourceLine &line, + std::map<FileSpec, std::set<uint32_t>> &source_lines_seen) { + if (line.IsValid()) { + auto source_lines_seen_pos = source_lines_seen.find(line.file); + if (source_lines_seen_pos == source_lines_seen.end()) { + std::set<uint32_t> lines; + lines.insert(line.line); + source_lines_seen.emplace(line.file, lines); + } else { + source_lines_seen_pos->second.insert(line.line); } - const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol; - const bool use_inline_block_range = false; - - const FormatEntity::Entry *disassembly_format = nullptr; - FormatEntity::Entry format; - if (exe_ctx.HasTargetScope()) - { - disassembly_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat (); + } +} + +bool Disassembler::ElideMixedSourceAndDisassemblyLine( + const ExecutionContext &exe_ctx, const SymbolContext &sc, + SourceLine &line) { + + // TODO: should we also check target.process.thread.step-avoid-libraries ? + + const RegularExpression *avoid_regex = nullptr; + + // Skip any line #0 entries - they are implementation details + if (line.line == 0) + return false; + + ThreadSP thread_sp = exe_ctx.GetThreadSP(); + if (thread_sp) { + avoid_regex = thread_sp->GetSymbolsToAvoidRegexp(); + } else { + TargetSP target_sp = exe_ctx.GetTargetSP(); + if (target_sp) { + Error error; + OptionValueSP value_sp = target_sp->GetDebugger().GetPropertyValue( + &exe_ctx, "target.process.thread.step-avoid-regexp", false, error); + if (value_sp && value_sp->GetType() == OptionValue::eTypeRegex) { + OptionValueRegex *re = value_sp->GetAsRegex(); + if (re) { + avoid_regex = re->GetCurrentValue(); + } + } } - else - { - FormatEntity::Parse("${addr}: ", format); - disassembly_format = &format; + } + if (avoid_regex && sc.symbol != nullptr) { + const char *function_name = + sc.GetFunctionName(Mangled::ePreferDemangledWithoutArguments) + .GetCString(); + if (function_name) { + RegularExpression::Match regex_match(1); + if (avoid_regex->Execute(function_name, ®ex_match)) { + // skip this source line + return true; + } } + } + // don't skip this source line + return false; +} - // First pass: step through the list of instructions, - // find how long the initial addresses strings are, insert padding - // in the second pass so the opcodes all line up nicely. - size_t address_text_size = 0; - for (size_t i = 0; i < num_instructions_found; ++i) - { - Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get(); - if (inst) - { - const Address &addr = inst->GetAddress(); - ModuleSP module_sp (addr.GetModule()); - if (module_sp) - { - const uint32_t resolve_mask = eSymbolContextFunction | eSymbolContextSymbol; - uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc); - if (resolved_mask) - { - StreamString strmstr; - Debugger::FormatDisassemblerAddress(disassembly_format, &sc, nullptr, &exe_ctx, &addr, strmstr); - size_t cur_line = strmstr.GetSizeOfLastLine(); - if (cur_line > address_text_size) - address_text_size = cur_line; - } - sc.Clear(false); +bool Disassembler::PrintInstructions(Disassembler *disasm_ptr, + Debugger &debugger, const ArchSpec &arch, + const ExecutionContext &exe_ctx, + uint32_t num_instructions, + bool mixed_source_and_assembly, + uint32_t num_mixed_context_lines, + uint32_t options, Stream &strm) { + // We got some things disassembled... + size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize(); + + if (num_instructions > 0 && num_instructions < num_instructions_found) + num_instructions_found = num_instructions; + + const uint32_t max_opcode_byte_size = + disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize(); + SymbolContext sc; + SymbolContext prev_sc; + AddressRange current_source_line_range; + const Address *pc_addr_ptr = nullptr; + StackFrame *frame = exe_ctx.GetFramePtr(); + + TargetSP target_sp(exe_ctx.GetTargetSP()); + SourceManager &source_manager = + target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager(); + + if (frame) { + pc_addr_ptr = &frame->GetFrameCodeAddress(); + } + const uint32_t scope = + eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol; + const bool use_inline_block_range = false; + + const FormatEntity::Entry *disassembly_format = nullptr; + FormatEntity::Entry format; + if (exe_ctx.HasTargetScope()) { + disassembly_format = + exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat(); + } else { + FormatEntity::Parse("${addr}: ", format); + disassembly_format = &format; + } + + // First pass: step through the list of instructions, + // find how long the initial addresses strings are, insert padding + // in the second pass so the opcodes all line up nicely. + + // Also build up the source line mapping if this is mixed source & assembly + // mode. + // Calculate the source line for each assembly instruction (eliding inlined + // functions + // which the user wants to skip). + + std::map<FileSpec, std::set<uint32_t>> source_lines_seen; + Symbol *previous_symbol = nullptr; + + size_t address_text_size = 0; + for (size_t i = 0; i < num_instructions_found; ++i) { + Instruction *inst = + disasm_ptr->GetInstructionList().GetInstructionAtIndex(i).get(); + if (inst) { + const Address &addr = inst->GetAddress(); + ModuleSP module_sp(addr.GetModule()); + if (module_sp) { + const uint32_t resolve_mask = eSymbolContextFunction | + eSymbolContextSymbol | + eSymbolContextLineEntry; + uint32_t resolved_mask = + module_sp->ResolveSymbolContextForAddress(addr, resolve_mask, sc); + if (resolved_mask) { + StreamString strmstr; + Debugger::FormatDisassemblerAddress(disassembly_format, &sc, nullptr, + &exe_ctx, &addr, strmstr); + size_t cur_line = strmstr.GetSizeOfLastLine(); + if (cur_line > address_text_size) + address_text_size = cur_line; + + // Add entries to our "source_lines_seen" map+set which list which + // sources lines occur in this disassembly session. We will print + // lines of context around a source line, but we don't want to print + // a source line that has a line table entry of its own - we'll leave + // that source line to be printed when it actually occurs in the + // disassembly. + + if (mixed_source_and_assembly && sc.line_entry.IsValid()) { + if (sc.symbol != previous_symbol) { + SourceLine decl_line = GetFunctionDeclLineEntry(sc); + if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, decl_line) == + false) + AddLineToSourceLineTables(decl_line, source_lines_seen); + } + if (sc.line_entry.IsValid()) { + SourceLine this_line; + this_line.file = sc.line_entry.file; + this_line.line = sc.line_entry.line; + this_line.column = sc.line_entry.column; + if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, this_line) == + false) + AddLineToSourceLineTables(this_line, source_lines_seen); } + } } + sc.Clear(false); + } } + } + + previous_symbol = nullptr; + SourceLine previous_line; + for (size_t i = 0; i < num_instructions_found; ++i) { + Instruction *inst = + disasm_ptr->GetInstructionList().GetInstructionAtIndex(i).get(); + + if (inst) { + const Address &addr = inst->GetAddress(); + const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr; + SourceLinesToDisplay source_lines_to_display; + + prev_sc = sc; + + ModuleSP module_sp(addr.GetModule()); + if (module_sp) { + uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress( + addr, eSymbolContextEverything, sc); + if (resolved_mask) { + if (mixed_source_and_assembly) { + + // If we've started a new function (non-inlined), print all of the + // source lines from the + // function declaration until the first line table entry - typically + // the opening curly brace of + // the function. + if (previous_symbol != sc.symbol) { + // The default disassembly format puts an extra blank line between + // functions - so + // when we're displaying the source context for a function, we + // don't want to add + // a blank line after the source context or we'll end up with two + // of them. + if (previous_symbol != nullptr) + source_lines_to_display.print_source_context_end_eol = false; + + previous_symbol = sc.symbol; + if (sc.function && sc.line_entry.IsValid()) { + LineEntry prologue_end_line = sc.line_entry; + if (ElideMixedSourceAndDisassemblyLine( + exe_ctx, sc, prologue_end_line) == false) { + FileSpec func_decl_file; + uint32_t func_decl_line; + sc.function->GetStartLineSourceInfo(func_decl_file, + func_decl_line); + if (func_decl_file == prologue_end_line.file || + func_decl_file == prologue_end_line.original_file) { + // Add all the lines between the function declaration + // and the first non-prologue source line to the list + // of lines to print. + for (uint32_t lineno = func_decl_line; + lineno <= prologue_end_line.line; lineno++) { + SourceLine this_line; + this_line.file = func_decl_file; + this_line.line = lineno; + source_lines_to_display.lines.push_back(this_line); + } + // Mark the last line as the "current" one. Usually + // this is the open curly brace. + if (source_lines_to_display.lines.size() > 0) + source_lines_to_display.current_source_line = + source_lines_to_display.lines.size() - 1; + } + } + } + sc.GetAddressRange(scope, 0, use_inline_block_range, + current_source_line_range); + } - for (size_t i = 0; i < num_instructions_found; ++i) - { - Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get(); - if (inst) - { - const Address &addr = inst->GetAddress(); - const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr; - - prev_sc = sc; - - ModuleSP module_sp (addr.GetModule()); - if (module_sp) - { - uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); - if (resolved_mask) - { - if (num_mixed_context_lines) - { - if (!sc_range.ContainsFileAddress (addr)) - { - sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range); - - if (sc != prev_sc) - { - if (offset != 0) - strm.EOL(); - - sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false, false, true); - strm.EOL(); - - if (sc.comp_unit && sc.line_entry.IsValid()) - { - source_manager.DisplaySourceLinesWithLineNumbers (sc.line_entry.file, - sc.line_entry.line, - num_mixed_context_lines, - num_mixed_context_lines, - ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""), - &strm); - } - } + // If we've left a previous source line's address range, print a new + // source line + if (!current_source_line_range.ContainsFileAddress(addr)) { + sc.GetAddressRange(scope, 0, use_inline_block_range, + current_source_line_range); + + if (sc != prev_sc && sc.comp_unit && sc.line_entry.IsValid()) { + SourceLine this_line; + this_line.file = sc.line_entry.file; + this_line.line = sc.line_entry.line; + + if (ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, + this_line) == false) { + // Only print this source line if it is different from the + // last source line we printed. There may have been inlined + // functions between these lines that we elided, resulting in + // the same line being printed twice in a row for a contiguous + // block of assembly instructions. + if (this_line != previous_line) { + + std::vector<uint32_t> previous_lines; + for (uint32_t i = 0; + i < num_mixed_context_lines && + (this_line.line - num_mixed_context_lines) > 0; + i++) { + uint32_t line = + this_line.line - num_mixed_context_lines + i; + auto pos = source_lines_seen.find(this_line.file); + if (pos != source_lines_seen.end()) { + if (pos->second.count(line) == 1) { + previous_lines.clear(); + } else { + previous_lines.push_back(line); } + } } + for (size_t i = 0; i < previous_lines.size(); i++) { + SourceLine previous_line; + previous_line.file = this_line.file; + previous_line.line = previous_lines[i]; + auto pos = source_lines_seen.find(previous_line.file); + if (pos != source_lines_seen.end()) { + pos->second.insert(previous_line.line); + } + source_lines_to_display.lines.push_back(previous_line); + } + + source_lines_to_display.lines.push_back(this_line); + source_lines_to_display.current_source_line = + source_lines_to_display.lines.size() - 1; + + for (uint32_t i = 0; i < num_mixed_context_lines; i++) { + SourceLine next_line; + next_line.file = this_line.file; + next_line.line = this_line.line + i + 1; + auto pos = source_lines_seen.find(next_line.file); + if (pos != source_lines_seen.end()) { + if (pos->second.count(next_line.line) == 1) + break; + pos->second.insert(next_line.line); + } + source_lines_to_display.lines.push_back(next_line); + } + } + previous_line = this_line; } - else - { - sc.Clear(true); - } + } } - - const bool show_bytes = (options & eOptionShowBytes) != 0; - inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, &prev_sc, nullptr, address_text_size); - strm.EOL(); + } + } else { + sc.Clear(true); } - else - { - break; + } + + if (source_lines_to_display.lines.size() > 0) { + strm.EOL(); + for (size_t idx = 0; idx < source_lines_to_display.lines.size(); + idx++) { + SourceLine ln = source_lines_to_display.lines[idx]; + const char *line_highlight = ""; + if (inst_is_at_pc && (options & eOptionMarkPCSourceLine)) { + line_highlight = "->"; + } else if (idx == source_lines_to_display.current_source_line) { + line_highlight = "**"; + } + source_manager.DisplaySourceLinesWithLineNumbers( + ln.file, ln.line, ln.column, 0, 0, line_highlight, &strm); } + if (source_lines_to_display.print_source_context_end_eol) + strm.EOL(); + } + + const bool show_bytes = (options & eOptionShowBytes) != 0; + inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, &sc, + &prev_sc, nullptr, address_text_size); + strm.EOL(); + } else { + break; } - - return true; -} + } -bool -Disassembler::Disassemble(Debugger &debugger, - const ArchSpec &arch, - const char *plugin_name, - const char *flavor, - const ExecutionContext &exe_ctx, - uint32_t num_instructions, - uint32_t num_mixed_context_lines, - uint32_t options, - Stream &strm) -{ - AddressRange range; - StackFrame *frame = exe_ctx.GetFramePtr(); - if (frame) - { - SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); - if (sc.function) - { - range = sc.function->GetAddressRange(); - } - else if (sc.symbol && sc.symbol->ValueIsAddress()) - { - range.GetBaseAddress() = sc.symbol->GetAddressRef(); - range.SetByteSize (sc.symbol->GetByteSize()); - } - else - { - range.GetBaseAddress() = frame->GetFrameCodeAddress(); - } + return true; +} - if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0) - range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE); +bool Disassembler::Disassemble(Debugger &debugger, const ArchSpec &arch, + const char *plugin_name, const char *flavor, + const ExecutionContext &exe_ctx, + uint32_t num_instructions, + bool mixed_source_and_assembly, + uint32_t num_mixed_context_lines, + uint32_t options, Stream &strm) { + AddressRange range; + StackFrame *frame = exe_ctx.GetFramePtr(); + if (frame) { + SymbolContext sc( + frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); + if (sc.function) { + range = sc.function->GetAddressRange(); + } else if (sc.symbol && sc.symbol->ValueIsAddress()) { + range.GetBaseAddress() = sc.symbol->GetAddressRef(); + range.SetByteSize(sc.symbol->GetByteSize()); + } else { + range.GetBaseAddress() = frame->GetFrameCodeAddress(); } - return Disassemble (debugger, - arch, - plugin_name, - flavor, - exe_ctx, - range, - num_instructions, - num_mixed_context_lines, - options, - strm); -} + if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0) + range.SetByteSize(DEFAULT_DISASM_BYTE_SIZE); + } -Instruction::Instruction(const Address &address, AddressClass addr_class) : - m_address (address), - m_address_class (addr_class), - m_opcode(), - m_calculated_strings(false) -{ + return Disassemble(debugger, arch, plugin_name, flavor, exe_ctx, range, + num_instructions, mixed_source_and_assembly, + num_mixed_context_lines, options, strm); } +Instruction::Instruction(const Address &address, AddressClass addr_class) + : m_address(address), m_address_class(addr_class), m_opcode(), + m_calculated_strings(false) {} + Instruction::~Instruction() = default; -AddressClass -Instruction::GetAddressClass () -{ - if (m_address_class == eAddressClassInvalid) - m_address_class = m_address.GetAddressClass(); - return m_address_class; +AddressClass Instruction::GetAddressClass() { + if (m_address_class == eAddressClassInvalid) + m_address_class = m_address.GetAddressClass(); + return m_address_class; } -void -Instruction::Dump (lldb_private::Stream *s, - uint32_t max_opcode_byte_size, - bool show_address, - bool show_bytes, - const ExecutionContext* exe_ctx, - const SymbolContext *sym_ctx, - const SymbolContext *prev_sym_ctx, - const FormatEntity::Entry *disassembly_addr_format, - size_t max_address_text_size) -{ - size_t opcode_column_width = 7; - const size_t operand_column_width = 25; - - CalculateMnemonicOperandsAndCommentIfNeeded (exe_ctx); - - StreamString ss; - - if (show_address) - { - Debugger::FormatDisassemblerAddress (disassembly_addr_format, sym_ctx, prev_sym_ctx, exe_ctx, &m_address, ss); - ss.FillLastLineToColumn (max_address_text_size, ' '); - } - - if (show_bytes) - { - if (m_opcode.GetType() == Opcode::eTypeBytes) - { - // x86_64 and i386 are the only ones that use bytes right now so - // pad out the byte dump to be able to always show 15 bytes (3 chars each) - // plus a space - if (max_opcode_byte_size > 0) - m_opcode.Dump (&ss, max_opcode_byte_size * 3 + 1); - else - m_opcode.Dump (&ss, 15 * 3 + 1); - } - else - { - // Else, we have ARM or MIPS which can show up to a uint32_t - // 0x00000000 (10 spaces) plus two for padding... - if (max_opcode_byte_size > 0) - m_opcode.Dump (&ss, max_opcode_byte_size * 3 + 1); - else - m_opcode.Dump (&ss, 12); - } - } - - const size_t opcode_pos = ss.GetSizeOfLastLine(); - - // The default opcode size of 7 characters is plenty for most architectures - // but some like arm can pull out the occasional vqrshrun.s16. We won't get - // consistent column spacing in these cases, unfortunately. - if (m_opcode_name.length() >= opcode_column_width) - { - opcode_column_width = m_opcode_name.length() + 1; - } - - ss.PutCString (m_opcode_name.c_str()); - ss.FillLastLineToColumn (opcode_pos + opcode_column_width, ' '); - ss.PutCString (m_mnemonics.c_str()); - - if (!m_comment.empty()) - { - ss.FillLastLineToColumn (opcode_pos + opcode_column_width + operand_column_width, ' '); - ss.PutCString (" ; "); - ss.PutCString (m_comment.c_str()); +void Instruction::Dump(lldb_private::Stream *s, uint32_t max_opcode_byte_size, + bool show_address, bool show_bytes, + const ExecutionContext *exe_ctx, + const SymbolContext *sym_ctx, + const SymbolContext *prev_sym_ctx, + const FormatEntity::Entry *disassembly_addr_format, + size_t max_address_text_size) { + size_t opcode_column_width = 7; + const size_t operand_column_width = 25; + + CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); + + StreamString ss; + + if (show_address) { + Debugger::FormatDisassemblerAddress(disassembly_addr_format, sym_ctx, + prev_sym_ctx, exe_ctx, &m_address, ss); + ss.FillLastLineToColumn(max_address_text_size, ' '); + } + + if (show_bytes) { + if (m_opcode.GetType() == Opcode::eTypeBytes) { + // x86_64 and i386 are the only ones that use bytes right now so + // pad out the byte dump to be able to always show 15 bytes (3 chars each) + // plus a space + if (max_opcode_byte_size > 0) + m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1); + else + m_opcode.Dump(&ss, 15 * 3 + 1); + } else { + // Else, we have ARM or MIPS which can show up to a uint32_t + // 0x00000000 (10 spaces) plus two for padding... + if (max_opcode_byte_size > 0) + m_opcode.Dump(&ss, max_opcode_byte_size * 3 + 1); + else + m_opcode.Dump(&ss, 12); } - s->Write (ss.GetData(), ss.GetSize()); + } + + const size_t opcode_pos = ss.GetSizeOfLastLine(); + + // The default opcode size of 7 characters is plenty for most architectures + // but some like arm can pull out the occasional vqrshrun.s16. We won't get + // consistent column spacing in these cases, unfortunately. + if (m_opcode_name.length() >= opcode_column_width) { + opcode_column_width = m_opcode_name.length() + 1; + } + + ss.PutCString(m_opcode_name); + ss.FillLastLineToColumn(opcode_pos + opcode_column_width, ' '); + ss.PutCString(m_mnemonics); + + if (!m_comment.empty()) { + ss.FillLastLineToColumn( + opcode_pos + opcode_column_width + operand_column_width, ' '); + ss.PutCString(" ; "); + ss.PutCString(m_comment); + } + s->PutCString(ss.GetString()); } -bool -Instruction::DumpEmulation (const ArchSpec &arch) -{ - std::unique_ptr<EmulateInstruction> insn_emulator_ap(EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); - if (insn_emulator_ap) - { - insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr); - return insn_emulator_ap->EvaluateInstruction (0); - } +bool Instruction::DumpEmulation(const ArchSpec &arch) { + std::unique_ptr<EmulateInstruction> insn_emulator_ap( + EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); + if (insn_emulator_ap) { + insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr); + return insn_emulator_ap->EvaluateInstruction(0); + } - return false; + return false; } -bool -Instruction::HasDelaySlot () -{ - // Default is false. - return false; +bool Instruction::HasDelaySlot() { + // Default is false. + return false; } -OptionValueSP -Instruction::ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type) -{ - bool done = false; - char buffer[1024]; - - OptionValueSP option_value_sp (new OptionValueArray (1u << data_type)); - - int idx = 0; - while (!done) - { - if (!fgets (buffer, 1023, in_file)) - { - out_stream->Printf ("Instruction::ReadArray: Error reading file (fgets).\n"); - option_value_sp.reset (); - return option_value_sp; - } +OptionValueSP Instruction::ReadArray(FILE *in_file, Stream *out_stream, + OptionValue::Type data_type) { + bool done = false; + char buffer[1024]; - std::string line (buffer); - - size_t len = line.size(); - if (line[len-1] == '\n') - { - line[len-1] = '\0'; - line.resize (len-1); - } + OptionValueSP option_value_sp(new OptionValueArray(1u << data_type)); - if ((line.size() == 1) && line[0] == ']') - { - done = true; - line.clear(); - } + int idx = 0; + while (!done) { + if (!fgets(buffer, 1023, in_file)) { + out_stream->Printf( + "Instruction::ReadArray: Error reading file (fgets).\n"); + option_value_sp.reset(); + return option_value_sp; + } - if (!line.empty()) - { - std::string value; - static RegularExpression g_reg_exp ("^[ \t]*([^ \t]+)[ \t]*$"); - RegularExpression::Match regex_match(1); - bool reg_exp_success = g_reg_exp.Execute (line.c_str(), ®ex_match); - if (reg_exp_success) - regex_match.GetMatchAtIndex (line.c_str(), 1, value); - else - value = line; - - OptionValueSP data_value_sp; - switch (data_type) - { - case OptionValue::eTypeUInt64: - data_value_sp.reset (new OptionValueUInt64 (0, 0)); - data_value_sp->SetValueFromString (value); - break; - // Other types can be added later as needed. - default: - data_value_sp.reset (new OptionValueString (value.c_str(), "")); - break; - } + std::string line(buffer); - option_value_sp->GetAsArray()->InsertValue (idx, data_value_sp); - ++idx; - } + size_t len = line.size(); + if (line[len - 1] == '\n') { + line[len - 1] = '\0'; + line.resize(len - 1); } - - return option_value_sp; -} -OptionValueSP -Instruction::ReadDictionary (FILE *in_file, Stream *out_stream) -{ - bool done = false; - char buffer[1024]; - - OptionValueSP option_value_sp (new OptionValueDictionary()); - static ConstString encoding_key ("data_encoding"); - OptionValue::Type data_type = OptionValue::eTypeInvalid; - - - while (!done) - { - // Read the next line in the file - if (!fgets (buffer, 1023, in_file)) - { - out_stream->Printf ("Instruction::ReadDictionary: Error reading file (fgets).\n"); - option_value_sp.reset (); - return option_value_sp; - } - - // Check to see if the line contains the end-of-dictionary marker ("}") - std::string line (buffer); - - size_t len = line.size(); - if (line[len-1] == '\n') - { - line[len-1] = '\0'; - line.resize (len-1); - } - - if ((line.size() == 1) && (line[0] == '}')) - { - done = true; - line.clear(); - } - - // Try to find a key-value pair in the current line and add it to the dictionary. - if (!line.empty()) - { - static RegularExpression g_reg_exp ("^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$"); - RegularExpression::Match regex_match(2); - - bool reg_exp_success = g_reg_exp.Execute (line.c_str(), ®ex_match); - std::string key; - std::string value; - if (reg_exp_success) - { - regex_match.GetMatchAtIndex (line.c_str(), 1, key); - regex_match.GetMatchAtIndex (line.c_str(), 2, value); - } - else - { - out_stream->Printf ("Instruction::ReadDictionary: Failure executing regular expression.\n"); - option_value_sp.reset(); - return option_value_sp; - } - - ConstString const_key (key.c_str()); - // Check value to see if it's the start of an array or dictionary. - - lldb::OptionValueSP value_sp; - assert (value.empty() == false); - assert (key.empty() == false); - - if (value[0] == '{') - { - assert (value.size() == 1); - // value is a dictionary - value_sp = ReadDictionary (in_file, out_stream); - if (!value_sp) - { - option_value_sp.reset (); - return option_value_sp; - } - } - else if (value[0] == '[') - { - assert (value.size() == 1); - // value is an array - value_sp = ReadArray (in_file, out_stream, data_type); - if (!value_sp) - { - option_value_sp.reset (); - return option_value_sp; - } - // We've used the data_type to read an array; re-set the type to Invalid - data_type = OptionValue::eTypeInvalid; - } - else if ((value[0] == '0') && (value[1] == 'x')) - { - value_sp.reset (new OptionValueUInt64 (0, 0)); - value_sp->SetValueFromString (value); - } - else - { - size_t len = value.size(); - if ((value[0] == '"') && (value[len-1] == '"')) - value = value.substr (1, len-2); - value_sp.reset (new OptionValueString (value.c_str(), "")); - } + if ((line.size() == 1) && line[0] == ']') { + done = true; + line.clear(); + } - if (const_key == encoding_key) - { - // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data indicating the - // data type of an upcoming array (usually the next bit of data to be read in). - if (strcmp (value.c_str(), "uint32_t") == 0) - data_type = OptionValue::eTypeUInt64; - } - else - option_value_sp->GetAsDictionary()->SetValueForKey (const_key, value_sp, false); - } + if (!line.empty()) { + std::string value; + static RegularExpression g_reg_exp( + llvm::StringRef("^[ \t]*([^ \t]+)[ \t]*$")); + RegularExpression::Match regex_match(1); + bool reg_exp_success = g_reg_exp.Execute(line, ®ex_match); + if (reg_exp_success) + regex_match.GetMatchAtIndex(line.c_str(), 1, value); + else + value = line; + + OptionValueSP data_value_sp; + switch (data_type) { + case OptionValue::eTypeUInt64: + data_value_sp.reset(new OptionValueUInt64(0, 0)); + data_value_sp->SetValueFromString(value); + break; + // Other types can be added later as needed. + default: + data_value_sp.reset(new OptionValueString(value.c_str(), "")); + break; + } + + option_value_sp->GetAsArray()->InsertValue(idx, data_value_sp); + ++idx; } - - return option_value_sp; -} + } -bool -Instruction::TestEmulation (Stream *out_stream, const char *file_name) -{ - if (!out_stream) - return false; + return option_value_sp; +} - if (!file_name) - { - out_stream->Printf ("Instruction::TestEmulation: Missing file_name."); - return false; +OptionValueSP Instruction::ReadDictionary(FILE *in_file, Stream *out_stream) { + bool done = false; + char buffer[1024]; + + OptionValueSP option_value_sp(new OptionValueDictionary()); + static ConstString encoding_key("data_encoding"); + OptionValue::Type data_type = OptionValue::eTypeInvalid; + + while (!done) { + // Read the next line in the file + if (!fgets(buffer, 1023, in_file)) { + out_stream->Printf( + "Instruction::ReadDictionary: Error reading file (fgets).\n"); + option_value_sp.reset(); + return option_value_sp; } - FILE *test_file = FileSystem::Fopen(file_name, "r"); - if (!test_file) - { - out_stream->Printf ("Instruction::TestEmulation: Attempt to open test file failed."); - return false; + + // Check to see if the line contains the end-of-dictionary marker ("}") + std::string line(buffer); + + size_t len = line.size(); + if (line[len - 1] == '\n') { + line[len - 1] = '\0'; + line.resize(len - 1); } - char buffer[256]; - if (!fgets (buffer, 255, test_file)) - { - out_stream->Printf ("Instruction::TestEmulation: Error reading first line of test file.\n"); - fclose (test_file); - return false; + if ((line.size() == 1) && (line[0] == '}')) { + done = true; + line.clear(); } - - if (strncmp (buffer, "InstructionEmulationState={", 27) != 0) - { - out_stream->Printf ("Instructin::TestEmulation: Test file does not contain emulation state dictionary\n"); - fclose (test_file); - return false; + + // Try to find a key-value pair in the current line and add it to the + // dictionary. + if (!line.empty()) { + static RegularExpression g_reg_exp(llvm::StringRef( + "^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$")); + RegularExpression::Match regex_match(2); + + bool reg_exp_success = g_reg_exp.Execute(line, ®ex_match); + std::string key; + std::string value; + if (reg_exp_success) { + regex_match.GetMatchAtIndex(line.c_str(), 1, key); + regex_match.GetMatchAtIndex(line.c_str(), 2, value); + } else { + out_stream->Printf("Instruction::ReadDictionary: Failure executing " + "regular expression.\n"); + option_value_sp.reset(); + return option_value_sp; + } + + ConstString const_key(key.c_str()); + // Check value to see if it's the start of an array or dictionary. + + lldb::OptionValueSP value_sp; + assert(value.empty() == false); + assert(key.empty() == false); + + if (value[0] == '{') { + assert(value.size() == 1); + // value is a dictionary + value_sp = ReadDictionary(in_file, out_stream); + if (!value_sp) { + option_value_sp.reset(); + return option_value_sp; + } + } else if (value[0] == '[') { + assert(value.size() == 1); + // value is an array + value_sp = ReadArray(in_file, out_stream, data_type); + if (!value_sp) { + option_value_sp.reset(); + return option_value_sp; + } + // We've used the data_type to read an array; re-set the type to Invalid + data_type = OptionValue::eTypeInvalid; + } else if ((value[0] == '0') && (value[1] == 'x')) { + value_sp.reset(new OptionValueUInt64(0, 0)); + value_sp->SetValueFromString(value); + } else { + size_t len = value.size(); + if ((value[0] == '"') && (value[len - 1] == '"')) + value = value.substr(1, len - 2); + value_sp.reset(new OptionValueString(value.c_str(), "")); + } + + if (const_key == encoding_key) { + // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data + // indicating the + // data type of an upcoming array (usually the next bit of data to be + // read in). + if (strcmp(value.c_str(), "uint32_t") == 0) + data_type = OptionValue::eTypeUInt64; + } else + option_value_sp->GetAsDictionary()->SetValueForKey(const_key, value_sp, + false); } + } - // Read all the test information from the test file into an OptionValueDictionary. + return option_value_sp; +} - OptionValueSP data_dictionary_sp (ReadDictionary (test_file, out_stream)); - if (!data_dictionary_sp) - { - out_stream->Printf ("Instruction::TestEmulation: Error reading Dictionary Object.\n"); - fclose (test_file); - return false; - } +bool Instruction::TestEmulation(Stream *out_stream, const char *file_name) { + if (!out_stream) + return false; - fclose (test_file); + if (!file_name) { + out_stream->Printf("Instruction::TestEmulation: Missing file_name."); + return false; + } + FILE *test_file = FileSystem::Fopen(file_name, "r"); + if (!test_file) { + out_stream->Printf( + "Instruction::TestEmulation: Attempt to open test file failed."); + return false; + } - OptionValueDictionary *data_dictionary = data_dictionary_sp->GetAsDictionary(); - static ConstString description_key ("assembly_string"); - static ConstString triple_key ("triple"); + char buffer[256]; + if (!fgets(buffer, 255, test_file)) { + out_stream->Printf( + "Instruction::TestEmulation: Error reading first line of test file.\n"); + fclose(test_file); + return false; + } - OptionValueSP value_sp = data_dictionary->GetValueForKey (description_key); - - if (!value_sp) - { - out_stream->Printf ("Instruction::TestEmulation: Test file does not contain description string.\n"); - return false; - } + if (strncmp(buffer, "InstructionEmulationState={", 27) != 0) { + out_stream->Printf("Instructin::TestEmulation: Test file does not contain " + "emulation state dictionary\n"); + fclose(test_file); + return false; + } - SetDescription (value_sp->GetStringValue()); + // Read all the test information from the test file into an + // OptionValueDictionary. - value_sp = data_dictionary->GetValueForKey (triple_key); - if (!value_sp) - { - out_stream->Printf ("Instruction::TestEmulation: Test file does not contain triple.\n"); - return false; - } - - ArchSpec arch; - arch.SetTriple (llvm::Triple (value_sp->GetStringValue())); - - bool success = false; - std::unique_ptr<EmulateInstruction> insn_emulator_ap(EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); - if (insn_emulator_ap) - success = insn_emulator_ap->TestEmulation (out_stream, arch, data_dictionary); - - if (success) - out_stream->Printf ("Emulation test succeeded."); - else - out_stream->Printf ("Emulation test failed."); - - return success; -} + OptionValueSP data_dictionary_sp(ReadDictionary(test_file, out_stream)); + if (!data_dictionary_sp) { + out_stream->Printf( + "Instruction::TestEmulation: Error reading Dictionary Object.\n"); + fclose(test_file); + return false; + } -bool -Instruction::Emulate (const ArchSpec &arch, - uint32_t evaluate_options, - void *baton, - EmulateInstruction::ReadMemoryCallback read_mem_callback, - EmulateInstruction::WriteMemoryCallback write_mem_callback, - EmulateInstruction::ReadRegisterCallback read_reg_callback, - EmulateInstruction::WriteRegisterCallback write_reg_callback) -{ - std::unique_ptr<EmulateInstruction> insn_emulator_ap(EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); - if (insn_emulator_ap) - { - insn_emulator_ap->SetBaton(baton); - insn_emulator_ap->SetCallbacks(read_mem_callback, write_mem_callback, read_reg_callback, write_reg_callback); - insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr); - return insn_emulator_ap->EvaluateInstruction(evaluate_options); - } + fclose(test_file); + + OptionValueDictionary *data_dictionary = + data_dictionary_sp->GetAsDictionary(); + static ConstString description_key("assembly_string"); + static ConstString triple_key("triple"); + + OptionValueSP value_sp = data_dictionary->GetValueForKey(description_key); + if (!value_sp) { + out_stream->Printf("Instruction::TestEmulation: Test file does not " + "contain description string.\n"); return false; -} + } -uint32_t -Instruction::GetData (DataExtractor &data) -{ - return m_opcode.GetData(data); -} + SetDescription(value_sp->GetStringValue()); -InstructionList::InstructionList() : - m_instructions() -{ -} + value_sp = data_dictionary->GetValueForKey(triple_key); + if (!value_sp) { + out_stream->Printf( + "Instruction::TestEmulation: Test file does not contain triple.\n"); + return false; + } -InstructionList::~InstructionList() = default; + ArchSpec arch; + arch.SetTriple(llvm::Triple(value_sp->GetStringValue())); -size_t -InstructionList::GetSize() const -{ - return m_instructions.size(); + bool success = false; + std::unique_ptr<EmulateInstruction> insn_emulator_ap( + EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); + if (insn_emulator_ap) + success = + insn_emulator_ap->TestEmulation(out_stream, arch, data_dictionary); + + if (success) + out_stream->Printf("Emulation test succeeded."); + else + out_stream->Printf("Emulation test failed."); + + return success; } -uint32_t -InstructionList::GetMaxOpcocdeByteSize () const -{ - uint32_t max_inst_size = 0; - collection::const_iterator pos, end; - for (pos = m_instructions.begin(), end = m_instructions.end(); - pos != end; - ++pos) - { - uint32_t inst_size = (*pos)->GetOpcode().GetByteSize(); - if (max_inst_size < inst_size) - max_inst_size = inst_size; - } - return max_inst_size; +bool Instruction::Emulate( + const ArchSpec &arch, uint32_t evaluate_options, void *baton, + EmulateInstruction::ReadMemoryCallback read_mem_callback, + EmulateInstruction::WriteMemoryCallback write_mem_callback, + EmulateInstruction::ReadRegisterCallback read_reg_callback, + EmulateInstruction::WriteRegisterCallback write_reg_callback) { + std::unique_ptr<EmulateInstruction> insn_emulator_ap( + EmulateInstruction::FindPlugin(arch, eInstructionTypeAny, nullptr)); + if (insn_emulator_ap) { + insn_emulator_ap->SetBaton(baton); + insn_emulator_ap->SetCallbacks(read_mem_callback, write_mem_callback, + read_reg_callback, write_reg_callback); + insn_emulator_ap->SetInstruction(GetOpcode(), GetAddress(), nullptr); + return insn_emulator_ap->EvaluateInstruction(evaluate_options); + } + + return false; } -InstructionSP -InstructionList::GetInstructionAtIndex (size_t idx) const -{ - InstructionSP inst_sp; - if (idx < m_instructions.size()) - inst_sp = m_instructions[idx]; - return inst_sp; +uint32_t Instruction::GetData(DataExtractor &data) { + return m_opcode.GetData(data); } -void -InstructionList::Dump (Stream *s, - bool show_address, - bool show_bytes, - const ExecutionContext* exe_ctx) -{ - const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize(); - collection::const_iterator pos, begin, end; - - const FormatEntity::Entry *disassembly_format = nullptr; - FormatEntity::Entry format; - if (exe_ctx && exe_ctx->HasTargetScope()) - { - disassembly_format = exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat (); - } - else - { - FormatEntity::Parse("${addr}: ", format); - disassembly_format = &format; - } +InstructionList::InstructionList() : m_instructions() {} - for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin; - pos != end; - ++pos) - { - if (pos != begin) - s->EOL(); - (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx, nullptr, nullptr, disassembly_format, 0); - } +InstructionList::~InstructionList() = default; + +size_t InstructionList::GetSize() const { return m_instructions.size(); } + +uint32_t InstructionList::GetMaxOpcocdeByteSize() const { + uint32_t max_inst_size = 0; + collection::const_iterator pos, end; + for (pos = m_instructions.begin(), end = m_instructions.end(); pos != end; + ++pos) { + uint32_t inst_size = (*pos)->GetOpcode().GetByteSize(); + if (max_inst_size < inst_size) + max_inst_size = inst_size; + } + return max_inst_size; } -void -InstructionList::Clear() -{ - m_instructions.clear(); +InstructionSP InstructionList::GetInstructionAtIndex(size_t idx) const { + InstructionSP inst_sp; + if (idx < m_instructions.size()) + inst_sp = m_instructions[idx]; + return inst_sp; } -void -InstructionList::Append (lldb::InstructionSP &inst_sp) -{ - if (inst_sp) - m_instructions.push_back(inst_sp); +void InstructionList::Dump(Stream *s, bool show_address, bool show_bytes, + const ExecutionContext *exe_ctx) { + const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize(); + collection::const_iterator pos, begin, end; + + const FormatEntity::Entry *disassembly_format = nullptr; + FormatEntity::Entry format; + if (exe_ctx && exe_ctx->HasTargetScope()) { + disassembly_format = + exe_ctx->GetTargetRef().GetDebugger().GetDisassemblyFormat(); + } else { + FormatEntity::Parse("${addr}: ", format); + disassembly_format = &format; + } + + for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin; + pos != end; ++pos) { + if (pos != begin) + s->EOL(); + (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx, + nullptr, nullptr, disassembly_format, 0); + } +} + +void InstructionList::Clear() { m_instructions.clear(); } + +void InstructionList::Append(lldb::InstructionSP &inst_sp) { + if (inst_sp) + m_instructions.push_back(inst_sp); } uint32_t -InstructionList::GetIndexOfNextBranchInstruction(uint32_t start, Target &target) const -{ - size_t num_instructions = m_instructions.size(); - - uint32_t next_branch = UINT32_MAX; - size_t i; - for (i = start; i < num_instructions; i++) - { - if (m_instructions[i]->DoesBranch()) - { - next_branch = i; - break; - } +InstructionList::GetIndexOfNextBranchInstruction(uint32_t start, + Target &target) const { + size_t num_instructions = m_instructions.size(); + + uint32_t next_branch = UINT32_MAX; + size_t i; + for (i = start; i < num_instructions; i++) { + if (m_instructions[i]->DoesBranch()) { + next_branch = i; + break; + } + } + + // Hexagon needs the first instruction of the packet with the branch. + // Go backwards until we find an instruction marked end-of-packet, or + // until we hit start. + if (target.GetArchitecture().GetTriple().getArch() == llvm::Triple::hexagon) { + // If we didn't find a branch, find the last packet start. + if (next_branch == UINT32_MAX) { + i = num_instructions - 1; } - // Hexagon needs the first instruction of the packet with the branch. - // Go backwards until we find an instruction marked end-of-packet, or - // until we hit start. - if (target.GetArchitecture().GetTriple().getArch() == llvm::Triple::hexagon) - { - // If we didn't find a branch, find the last packet start. - if (next_branch == UINT32_MAX) - { - i = num_instructions - 1; - } - - while (i > start) - { - --i; - - Error error; - uint32_t inst_bytes; - bool prefer_file_cache = false; // Read from process if process is running - lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; - target.ReadMemory(m_instructions[i]->GetAddress(), - prefer_file_cache, - &inst_bytes, - sizeof(inst_bytes), - error, - &load_addr); - // If we have an error reading memory, return start - if (!error.Success()) - return start; - // check if this is the last instruction in a packet - // bits 15:14 will be 11b or 00b for a duplex - if (((inst_bytes & 0xC000) == 0xC000) || - ((inst_bytes & 0xC000) == 0x0000)) - { - // instruction after this should be the start of next packet - next_branch = i + 1; - break; - } - } + while (i > start) { + --i; + + Error error; + uint32_t inst_bytes; + bool prefer_file_cache = false; // Read from process if process is running + lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; + target.ReadMemory(m_instructions[i]->GetAddress(), prefer_file_cache, + &inst_bytes, sizeof(inst_bytes), error, &load_addr); + // If we have an error reading memory, return start + if (!error.Success()) + return start; + // check if this is the last instruction in a packet + // bits 15:14 will be 11b or 00b for a duplex + if (((inst_bytes & 0xC000) == 0xC000) || + ((inst_bytes & 0xC000) == 0x0000)) { + // instruction after this should be the start of next packet + next_branch = i + 1; + break; + } + } - if (next_branch == UINT32_MAX) - { - // We couldn't find the previous packet, so return start - next_branch = start; - } + if (next_branch == UINT32_MAX) { + // We couldn't find the previous packet, so return start + next_branch = start; } - return next_branch; + } + return next_branch; } uint32_t -InstructionList::GetIndexOfInstructionAtAddress (const Address &address) -{ - size_t num_instructions = m_instructions.size(); - uint32_t index = UINT32_MAX; - for (size_t i = 0; i < num_instructions; i++) - { - if (m_instructions[i]->GetAddress() == address) - { - index = i; - break; - } +InstructionList::GetIndexOfInstructionAtAddress(const Address &address) { + size_t num_instructions = m_instructions.size(); + uint32_t index = UINT32_MAX; + for (size_t i = 0; i < num_instructions; i++) { + if (m_instructions[i]->GetAddress() == address) { + index = i; + break; } - return index; + } + return index; } uint32_t -InstructionList::GetIndexOfInstructionAtLoadAddress (lldb::addr_t load_addr, Target &target) -{ - Address address; - address.SetLoadAddress(load_addr, &target); - return GetIndexOfInstructionAtAddress(address); +InstructionList::GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr, + Target &target) { + Address address; + address.SetLoadAddress(load_addr, &target); + return GetIndexOfInstructionAtAddress(address); } -size_t -Disassembler::ParseInstructions (const ExecutionContext *exe_ctx, - const AddressRange &range, - Stream *error_strm_ptr, - bool prefer_file_cache) -{ - if (exe_ctx) - { - Target *target = exe_ctx->GetTargetPtr(); - const addr_t byte_size = range.GetByteSize(); - if (target == nullptr || byte_size == 0 || !range.GetBaseAddress().IsValid()) - return 0; - - DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0'); - DataBufferSP data_sp(heap_buffer); - - Error error; - lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; - const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(), - prefer_file_cache, - heap_buffer->GetBytes(), - heap_buffer->GetByteSize(), - error, - &load_addr); - - if (bytes_read > 0) - { - if (bytes_read != heap_buffer->GetByteSize()) - heap_buffer->SetByteSize (bytes_read); - DataExtractor data (data_sp, - m_arch.GetByteOrder(), - m_arch.GetAddressByteSize()); - const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; - return DecodeInstructions(range.GetBaseAddress(), data, 0, UINT32_MAX, false, - data_from_file); - } - else if (error_strm_ptr) - { - const char *error_cstr = error.AsCString(); - if (error_cstr) - { - error_strm_ptr->Printf("error: %s\n", error_cstr); - } - } - } - else if (error_strm_ptr) - { - error_strm_ptr->PutCString("error: invalid execution context\n"); +size_t Disassembler::ParseInstructions(const ExecutionContext *exe_ctx, + const AddressRange &range, + Stream *error_strm_ptr, + bool prefer_file_cache) { + if (exe_ctx) { + Target *target = exe_ctx->GetTargetPtr(); + const addr_t byte_size = range.GetByteSize(); + if (target == nullptr || byte_size == 0 || + !range.GetBaseAddress().IsValid()) + return 0; + + DataBufferHeap *heap_buffer = new DataBufferHeap(byte_size, '\0'); + DataBufferSP data_sp(heap_buffer); + + Error error; + lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; + const size_t bytes_read = target->ReadMemory( + range.GetBaseAddress(), prefer_file_cache, heap_buffer->GetBytes(), + heap_buffer->GetByteSize(), error, &load_addr); + + if (bytes_read > 0) { + if (bytes_read != heap_buffer->GetByteSize()) + heap_buffer->SetByteSize(bytes_read); + DataExtractor data(data_sp, m_arch.GetByteOrder(), + m_arch.GetAddressByteSize()); + const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; + return DecodeInstructions(range.GetBaseAddress(), data, 0, UINT32_MAX, + false, data_from_file); + } else if (error_strm_ptr) { + const char *error_cstr = error.AsCString(); + if (error_cstr) { + error_strm_ptr->Printf("error: %s\n", error_cstr); + } } - return 0; + } else if (error_strm_ptr) { + error_strm_ptr->PutCString("error: invalid execution context\n"); + } + return 0; } -size_t -Disassembler::ParseInstructions (const ExecutionContext *exe_ctx, - const Address &start, - uint32_t num_instructions, - bool prefer_file_cache) -{ - m_instruction_list.Clear(); +size_t Disassembler::ParseInstructions(const ExecutionContext *exe_ctx, + const Address &start, + uint32_t num_instructions, + bool prefer_file_cache) { + m_instruction_list.Clear(); - if (exe_ctx == nullptr || num_instructions == 0 || !start.IsValid()) - return 0; - - Target *target = exe_ctx->GetTargetPtr(); - // Calculate the max buffer size we will need in order to disassemble - const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize(); - - if (target == nullptr || byte_size == 0) - return 0; + if (exe_ctx == nullptr || num_instructions == 0 || !start.IsValid()) + return 0; - DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0'); - DataBufferSP data_sp (heap_buffer); + Target *target = exe_ctx->GetTargetPtr(); + // Calculate the max buffer size we will need in order to disassemble + const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize(); - Error error; - lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; - const size_t bytes_read = target->ReadMemory (start, - prefer_file_cache, - heap_buffer->GetBytes(), - byte_size, - error, - &load_addr); - - const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; - - if (bytes_read == 0) - return 0; - DataExtractor data (data_sp, - m_arch.GetByteOrder(), - m_arch.GetAddressByteSize()); - - const bool append_instructions = true; - DecodeInstructions (start, - data, - 0, - num_instructions, - append_instructions, - data_from_file); - - return m_instruction_list.GetSize(); + if (target == nullptr || byte_size == 0) + return 0; + + DataBufferHeap *heap_buffer = new DataBufferHeap(byte_size, '\0'); + DataBufferSP data_sp(heap_buffer); + + Error error; + lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; + const size_t bytes_read = + target->ReadMemory(start, prefer_file_cache, heap_buffer->GetBytes(), + byte_size, error, &load_addr); + + const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS; + + if (bytes_read == 0) + return 0; + DataExtractor data(data_sp, m_arch.GetByteOrder(), + m_arch.GetAddressByteSize()); + + const bool append_instructions = true; + DecodeInstructions(start, data, 0, num_instructions, append_instructions, + data_from_file); + + return m_instruction_list.GetSize(); } //---------------------------------------------------------------------- // Disassembler copy constructor //---------------------------------------------------------------------- -Disassembler::Disassembler(const ArchSpec& arch, const char *flavor) : - m_arch (arch), - m_instruction_list(), - m_base_addr(LLDB_INVALID_ADDRESS), - m_flavor () -{ - if (flavor == nullptr) - m_flavor.assign("default"); - else - m_flavor.assign(flavor); - - // If this is an arm variant that can only include thumb (T16, T32) - // instructions, force the arch triple to be "thumbv.." instead of - // "armv..." - if (arch.IsAlwaysThumbInstructions()) - { - std::string thumb_arch_name (arch.GetTriple().getArchName().str()); - // Replace "arm" with "thumb" so we get all thumb variants correct - if (thumb_arch_name.size() > 3) - { - thumb_arch_name.erase(0, 3); - thumb_arch_name.insert(0, "thumb"); - } - m_arch.SetTriple (thumb_arch_name.c_str()); +Disassembler::Disassembler(const ArchSpec &arch, const char *flavor) + : m_arch(arch), m_instruction_list(), m_base_addr(LLDB_INVALID_ADDRESS), + m_flavor() { + if (flavor == nullptr) + m_flavor.assign("default"); + else + m_flavor.assign(flavor); + + // If this is an arm variant that can only include thumb (T16, T32) + // instructions, force the arch triple to be "thumbv.." instead of + // "armv..." + if (arch.IsAlwaysThumbInstructions()) { + std::string thumb_arch_name(arch.GetTriple().getArchName().str()); + // Replace "arm" with "thumb" so we get all thumb variants correct + if (thumb_arch_name.size() > 3) { + thumb_arch_name.erase(0, 3); + thumb_arch_name.insert(0, "thumb"); } + m_arch.SetTriple(thumb_arch_name.c_str()); + } } Disassembler::~Disassembler() = default; -InstructionList & -Disassembler::GetInstructionList () -{ - return m_instruction_list; +InstructionList &Disassembler::GetInstructionList() { + return m_instruction_list; } -const InstructionList & -Disassembler::GetInstructionList () const -{ - return m_instruction_list; +const InstructionList &Disassembler::GetInstructionList() const { + return m_instruction_list; } //---------------------------------------------------------------------- // Class PseudoInstruction //---------------------------------------------------------------------- -PseudoInstruction::PseudoInstruction () : - Instruction (Address(), eAddressClassUnknown), - m_description () -{ -} +PseudoInstruction::PseudoInstruction() + : Instruction(Address(), eAddressClassUnknown), m_description() {} PseudoInstruction::~PseudoInstruction() = default; - -bool -PseudoInstruction::DoesBranch () -{ - // This is NOT a valid question for a pseudo instruction. - return false; + +bool PseudoInstruction::DoesBranch() { + // This is NOT a valid question for a pseudo instruction. + return false; } - -bool -PseudoInstruction::HasDelaySlot () -{ - // This is NOT a valid question for a pseudo instruction. - return false; + +bool PseudoInstruction::HasDelaySlot() { + // This is NOT a valid question for a pseudo instruction. + return false; } -size_t -PseudoInstruction::Decode (const lldb_private::Disassembler &disassembler, - const lldb_private::DataExtractor &data, - lldb::offset_t data_offset) -{ - return m_opcode.GetByteSize(); +size_t PseudoInstruction::Decode(const lldb_private::Disassembler &disassembler, + const lldb_private::DataExtractor &data, + lldb::offset_t data_offset) { + return m_opcode.GetByteSize(); } -void -PseudoInstruction::SetOpcode (size_t opcode_size, void *opcode_data) -{ - if (!opcode_data) - return; +void PseudoInstruction::SetOpcode(size_t opcode_size, void *opcode_data) { + if (!opcode_data) + return; + + switch (opcode_size) { + case 8: { + uint8_t value8 = *((uint8_t *)opcode_data); + m_opcode.SetOpcode8(value8, eByteOrderInvalid); + break; + } + case 16: { + uint16_t value16 = *((uint16_t *)opcode_data); + m_opcode.SetOpcode16(value16, eByteOrderInvalid); + break; + } + case 32: { + uint32_t value32 = *((uint32_t *)opcode_data); + m_opcode.SetOpcode32(value32, eByteOrderInvalid); + break; + } + case 64: { + uint64_t value64 = *((uint64_t *)opcode_data); + m_opcode.SetOpcode64(value64, eByteOrderInvalid); + break; + } + default: + break; + } +} + +void PseudoInstruction::SetDescription(llvm::StringRef description) { + m_description = description; +} + +Instruction::Operand Instruction::Operand::BuildRegister(ConstString &r) { + Operand ret; + ret.m_type = Type::Register; + ret.m_register = r; + return ret; +} + +Instruction::Operand Instruction::Operand::BuildImmediate(lldb::addr_t imm, + bool neg) { + Operand ret; + ret.m_type = Type::Immediate; + ret.m_immediate = imm; + ret.m_negative = neg; + return ret; +} + +Instruction::Operand Instruction::Operand::BuildImmediate(int64_t imm) { + Operand ret; + ret.m_type = Type::Immediate; + if (imm < 0) { + ret.m_immediate = -imm; + ret.m_negative = true; + } else { + ret.m_immediate = imm; + ret.m_negative = false; + } + return ret; +} + +Instruction::Operand +Instruction::Operand::BuildDereference(const Operand &ref) { + Operand ret; + ret.m_type = Type::Dereference; + ret.m_children = {ref}; + return ret; +} + +Instruction::Operand Instruction::Operand::BuildSum(const Operand &lhs, + const Operand &rhs) { + Operand ret; + ret.m_type = Type::Sum; + ret.m_children = {lhs, rhs}; + return ret; +} + +Instruction::Operand Instruction::Operand::BuildProduct(const Operand &lhs, + const Operand &rhs) { + Operand ret; + ret.m_type = Type::Product; + ret.m_children = {lhs, rhs}; + return ret; +} + +std::function<bool(const Instruction::Operand &)> +lldb_private::OperandMatchers::MatchBinaryOp( + std::function<bool(const Instruction::Operand &)> base, + std::function<bool(const Instruction::Operand &)> left, + std::function<bool(const Instruction::Operand &)> right) { + return [base, left, right](const Instruction::Operand &op) -> bool { + return (base(op) && op.m_children.size() == 2 && + ((left(op.m_children[0]) && right(op.m_children[1])) || + (left(op.m_children[1]) && right(op.m_children[0])))); + }; +} - switch (opcode_size) - { - case 8: - { - uint8_t value8 = *((uint8_t *) opcode_data); - m_opcode.SetOpcode8 (value8, eByteOrderInvalid); - break; - } - case 16: - { - uint16_t value16 = *((uint16_t *) opcode_data); - m_opcode.SetOpcode16 (value16, eByteOrderInvalid); - break; - } - case 32: - { - uint32_t value32 = *((uint32_t *) opcode_data); - m_opcode.SetOpcode32 (value32, eByteOrderInvalid); - break; - } - case 64: - { - uint64_t value64 = *((uint64_t *) opcode_data); - m_opcode.SetOpcode64 (value64, eByteOrderInvalid); - break; - } - default: - break; +std::function<bool(const Instruction::Operand &)> +lldb_private::OperandMatchers::MatchUnaryOp( + std::function<bool(const Instruction::Operand &)> base, + std::function<bool(const Instruction::Operand &)> child) { + return [base, child](const Instruction::Operand &op) -> bool { + return (base(op) && op.m_children.size() == 1 && child(op.m_children[0])); + }; +} + +std::function<bool(const Instruction::Operand &)> +lldb_private::OperandMatchers::MatchRegOp(const RegisterInfo &info) { + return [&info](const Instruction::Operand &op) { + return (op.m_type == Instruction::Operand::Type::Register && + (op.m_register == ConstString(info.name) || + op.m_register == ConstString(info.alt_name))); + }; +} + +std::function<bool(const Instruction::Operand &)> +lldb_private::OperandMatchers::FetchRegOp(ConstString ®) { + return [®](const Instruction::Operand &op) { + if (op.m_type != Instruction::Operand::Type::Register) { + return false; } + reg = op.m_register; + return true; + }; } -void -PseudoInstruction::SetDescription (const char *description) -{ - if (description && strlen (description) > 0) - m_description = description; +std::function<bool(const Instruction::Operand &)> +lldb_private::OperandMatchers::MatchImmOp(int64_t imm) { + return [imm](const Instruction::Operand &op) { + return (op.m_type == Instruction::Operand::Type::Immediate && + ((op.m_negative && op.m_immediate == (uint64_t)-imm) || + (!op.m_negative && op.m_immediate == (uint64_t)imm))); + }; } + +std::function<bool(const Instruction::Operand &)> +lldb_private::OperandMatchers::FetchImmOp(int64_t &imm) { + return [&imm](const Instruction::Operand &op) { + if (op.m_type != Instruction::Operand::Type::Immediate) { + return false; + } + if (op.m_negative) { + imm = -((int64_t)op.m_immediate); + } else { + imm = ((int64_t)op.m_immediate); + } + return true; + }; +} + +std::function<bool(const Instruction::Operand &)> +lldb_private::OperandMatchers::MatchOpType(Instruction::Operand::Type type) { + return [type](const Instruction::Operand &op) { return op.m_type == type; }; +} + diff --git a/source/Core/DynamicLoader.cpp b/source/Core/DynamicLoader.cpp index f41ff4a80c83..69c5ea30dad2 100644 --- a/source/Core/DynamicLoader.cpp +++ b/source/Core/DynamicLoader.cpp @@ -11,49 +11,49 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Target/DynamicLoader.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" -#include "lldb/Core/PluginManager.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Core/Section.h" +#include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" +#include "lldb/lldb-private.h" using namespace lldb; using namespace lldb_private; -DynamicLoader* -DynamicLoader::FindPlugin (Process *process, const char *plugin_name) -{ - DynamicLoaderCreateInstance create_callback = nullptr; - if (plugin_name) - { - ConstString const_plugin_name(plugin_name); - create_callback = PluginManager::GetDynamicLoaderCreateCallbackForPluginName (const_plugin_name); - if (create_callback) - { - std::unique_ptr<DynamicLoader> instance_ap(create_callback(process, true)); - if (instance_ap) - return instance_ap.release(); - } +DynamicLoader *DynamicLoader::FindPlugin(Process *process, + const char *plugin_name) { + DynamicLoaderCreateInstance create_callback = nullptr; + if (plugin_name) { + ConstString const_plugin_name(plugin_name); + create_callback = + PluginManager::GetDynamicLoaderCreateCallbackForPluginName( + const_plugin_name); + if (create_callback) { + std::unique_ptr<DynamicLoader> instance_ap( + create_callback(process, true)); + if (instance_ap) + return instance_ap.release(); } - else - { - for (uint32_t idx = 0; (create_callback = PluginManager::GetDynamicLoaderCreateCallbackAtIndex(idx)) != nullptr; ++idx) - { - std::unique_ptr<DynamicLoader> instance_ap(create_callback(process, false)); - if (instance_ap) - return instance_ap.release(); - } + } else { + for (uint32_t idx = 0; + (create_callback = + PluginManager::GetDynamicLoaderCreateCallbackAtIndex(idx)) != + nullptr; + ++idx) { + std::unique_ptr<DynamicLoader> instance_ap( + create_callback(process, false)); + if (instance_ap) + return instance_ap.release(); } - return nullptr; + } + return nullptr; } -DynamicLoader::DynamicLoader(Process *process) : - m_process (process) -{ -} +DynamicLoader::DynamicLoader(Process *process) : m_process(process) {} DynamicLoader::~DynamicLoader() = default; @@ -62,173 +62,174 @@ DynamicLoader::~DynamicLoader() = default; // (shared library) loading/unloading. //---------------------------------------------------------------------- -bool -DynamicLoader::GetStopWhenImagesChange () const -{ - return m_process->GetStopOnSharedLibraryEvents(); +bool DynamicLoader::GetStopWhenImagesChange() const { + return m_process->GetStopOnSharedLibraryEvents(); } -void -DynamicLoader::SetStopWhenImagesChange (bool stop) -{ - m_process->SetStopOnSharedLibraryEvents (stop); +void DynamicLoader::SetStopWhenImagesChange(bool stop) { + m_process->SetStopOnSharedLibraryEvents(stop); } -ModuleSP -DynamicLoader::GetTargetExecutable() -{ - Target &target = m_process->GetTarget(); - ModuleSP executable = target.GetExecutableModule(); - - if (executable) - { - if (executable->GetFileSpec().Exists()) - { - ModuleSpec module_spec (executable->GetFileSpec(), executable->GetArchitecture()); - ModuleSP module_sp (new Module (module_spec)); - - // Check if the executable has changed and set it to the target executable if they differ. - if (module_sp && module_sp->GetUUID().IsValid() && executable->GetUUID().IsValid()) - { - if (module_sp->GetUUID() != executable->GetUUID()) - executable.reset(); - } - else if (executable->FileHasChanged()) - { - executable.reset(); - } - - if (!executable) - { - executable = target.GetSharedModule(module_spec); - if (executable.get() != target.GetExecutableModulePointer()) - { - // Don't load dependent images since we are in dyld where we will know - // and find out about all images that are loaded - const bool get_dependent_images = false; - target.SetExecutableModule(executable, get_dependent_images); - } - } +ModuleSP DynamicLoader::GetTargetExecutable() { + Target &target = m_process->GetTarget(); + ModuleSP executable = target.GetExecutableModule(); + + if (executable) { + if (executable->GetFileSpec().Exists()) { + ModuleSpec module_spec(executable->GetFileSpec(), + executable->GetArchitecture()); + ModuleSP module_sp(new Module(module_spec)); + + // Check if the executable has changed and set it to the target executable + // if they differ. + if (module_sp && module_sp->GetUUID().IsValid() && + executable->GetUUID().IsValid()) { + if (module_sp->GetUUID() != executable->GetUUID()) + executable.reset(); + } else if (executable->FileHasChanged()) { + executable.reset(); + } + + if (!executable) { + executable = target.GetSharedModule(module_spec); + if (executable.get() != target.GetExecutableModulePointer()) { + // Don't load dependent images since we are in dyld where we will know + // and find out about all images that are loaded + const bool get_dependent_images = false; + target.SetExecutableModule(executable, get_dependent_images); } + } } - return executable; + } + return executable; } -void -DynamicLoader::UpdateLoadedSections(ModuleSP module, - addr_t link_map_addr, - addr_t base_addr, - bool base_addr_is_offset) -{ - UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset); +void DynamicLoader::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, + addr_t base_addr, + bool base_addr_is_offset) { + UpdateLoadedSectionsCommon(module, base_addr, base_addr_is_offset); } -void -DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module, - addr_t base_addr, - bool base_addr_is_offset) -{ - bool changed; - module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset, changed); +void DynamicLoader::UpdateLoadedSectionsCommon(ModuleSP module, + addr_t base_addr, + bool base_addr_is_offset) { + bool changed; + module->SetLoadAddress(m_process->GetTarget(), base_addr, base_addr_is_offset, + changed); } -void -DynamicLoader::UnloadSections(const ModuleSP module) -{ - UnloadSectionsCommon(module); +void DynamicLoader::UnloadSections(const ModuleSP module) { + UnloadSectionsCommon(module); } -void -DynamicLoader::UnloadSectionsCommon(const ModuleSP module) -{ - Target &target = m_process->GetTarget(); - const SectionList *sections = GetSectionListFromModule(module); +void DynamicLoader::UnloadSectionsCommon(const ModuleSP module) { + Target &target = m_process->GetTarget(); + const SectionList *sections = GetSectionListFromModule(module); - assert(sections && "SectionList missing from unloaded module."); + assert(sections && "SectionList missing from unloaded module."); - const size_t num_sections = sections->GetSize(); - for (size_t i = 0; i < num_sections; ++i) - { - SectionSP section_sp (sections->GetSectionAtIndex(i)); - target.SetSectionUnloaded(section_sp); - } + const size_t num_sections = sections->GetSize(); + for (size_t i = 0; i < num_sections; ++i) { + SectionSP section_sp(sections->GetSectionAtIndex(i)); + target.SetSectionUnloaded(section_sp); + } } const SectionList * -DynamicLoader::GetSectionListFromModule(const ModuleSP module) const -{ - SectionList *sections = nullptr; - if (module) - { - ObjectFile *obj_file = module->GetObjectFile(); - if (obj_file != nullptr) - { - sections = obj_file->GetSectionList(); - } +DynamicLoader::GetSectionListFromModule(const ModuleSP module) const { + SectionList *sections = nullptr; + if (module) { + ObjectFile *obj_file = module->GetObjectFile(); + if (obj_file != nullptr) { + sections = obj_file->GetSectionList(); } - return sections; + } + return sections; } -ModuleSP -DynamicLoader::LoadModuleAtAddress(const FileSpec &file, - addr_t link_map_addr, - addr_t base_addr, - bool base_addr_is_offset) -{ - Target &target = m_process->GetTarget(); - ModuleList &modules = target.GetImages(); - ModuleSP module_sp; - - ModuleSpec module_spec (file, target.GetArchitecture()); - if ((module_sp = modules.FindFirstModule (module_spec))) - { - UpdateLoadedSections(module_sp, link_map_addr, base_addr, base_addr_is_offset); +ModuleSP DynamicLoader::LoadModuleAtAddress(const FileSpec &file, + addr_t link_map_addr, + addr_t base_addr, + bool base_addr_is_offset) { + Target &target = m_process->GetTarget(); + ModuleList &modules = target.GetImages(); + ModuleSpec module_spec(file, target.GetArchitecture()); + ModuleSP module_sp; + + if ((module_sp = modules.FindFirstModule(module_spec))) { + UpdateLoadedSections(module_sp, link_map_addr, base_addr, + base_addr_is_offset); + return module_sp; + } + + if ((module_sp = target.GetSharedModule(module_spec))) { + UpdateLoadedSections(module_sp, link_map_addr, base_addr, + base_addr_is_offset); + return module_sp; + } + + bool check_alternative_file_name = true; + if (base_addr_is_offset) { + // Try to fetch the load address of the file from the process as we need + // absolute load + // address to read the file out of the memory instead of a load bias. + bool is_loaded = false; + lldb::addr_t load_addr; + Error error = m_process->GetFileLoadAddress(file, is_loaded, load_addr); + if (error.Success() && is_loaded) { + check_alternative_file_name = false; + base_addr = load_addr; } - else if ((module_sp = target.GetSharedModule(module_spec))) - { - UpdateLoadedSections(module_sp, link_map_addr, base_addr, base_addr_is_offset); + } + + // We failed to find the module based on its name. Lets try to check if we can + // find a + // different name based on the memory region info. + if (check_alternative_file_name) { + MemoryRegionInfo memory_info; + Error error = m_process->GetMemoryRegionInfo(base_addr, memory_info); + if (error.Success() && memory_info.GetMapped() && + memory_info.GetRange().GetRangeBase() == base_addr) { + ModuleSpec new_module_spec( + FileSpec(memory_info.GetName().AsCString(), false), + target.GetArchitecture()); + + if ((module_sp = modules.FindFirstModule(new_module_spec))) { + UpdateLoadedSections(module_sp, link_map_addr, base_addr, false); + return module_sp; + } + + if ((module_sp = target.GetSharedModule(new_module_spec))) { + UpdateLoadedSections(module_sp, link_map_addr, base_addr, false); + return module_sp; + } } - else - { - if (base_addr_is_offset) - { - // Try to fetch the load address of the file from the process as we need absolute load - // address to read the file out of the memory instead of a load bias. - bool is_loaded = false; - lldb::addr_t load_addr; - Error error = m_process->GetFileLoadAddress(file, is_loaded, load_addr); - if (error.Success() && is_loaded) - base_addr = load_addr; - } + } - if ((module_sp = m_process->ReadModuleFromMemory(file, base_addr))) - { - UpdateLoadedSections(module_sp, link_map_addr, base_addr, false); - target.GetImages().AppendIfNeeded(module_sp); - } - } + if ((module_sp = m_process->ReadModuleFromMemory(file, base_addr))) { + UpdateLoadedSections(module_sp, link_map_addr, base_addr, false); + target.GetImages().AppendIfNeeded(module_sp); + } - return module_sp; + return module_sp; } -int64_t -DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr, int size_in_bytes) -{ - Error error; - uint64_t value = m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error); - if (error.Fail()) - return -1; - else - return (int64_t)value; +int64_t DynamicLoader::ReadUnsignedIntWithSizeInBytes(addr_t addr, + int size_in_bytes) { + Error error; + uint64_t value = + m_process->ReadUnsignedIntegerFromMemory(addr, size_in_bytes, 0, error); + if (error.Fail()) + return -1; + else + return (int64_t)value; } -addr_t -DynamicLoader::ReadPointer(addr_t addr) -{ - Error error; - addr_t value = m_process->ReadPointerFromMemory(addr, error); - if (error.Fail()) - return LLDB_INVALID_ADDRESS; - else - return value; +addr_t DynamicLoader::ReadPointer(addr_t addr) { + Error error; + addr_t value = m_process->ReadPointerFromMemory(addr, error); + if (error.Fail()) + return LLDB_INVALID_ADDRESS; + else + return value; } diff --git a/source/Core/EmulateInstruction.cpp b/source/Core/EmulateInstruction.cpp index e46cfb2d8945..bc32fb2f35eb 100644 --- a/source/Core/EmulateInstruction.cpp +++ b/source/Core/EmulateInstruction.cpp @@ -1,4 +1,4 @@ -//===-- EmulateInstruction.h ------------------------------------*- C++ -*-===// +//===-- EmulateInstruction.cpp ----------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -32,621 +32,553 @@ using namespace lldb; using namespace lldb_private; -EmulateInstruction* -EmulateInstruction::FindPlugin (const ArchSpec &arch, InstructionType supported_inst_type, const char *plugin_name) -{ - EmulateInstructionCreateInstance create_callback = nullptr; - if (plugin_name) - { - ConstString const_plugin_name (plugin_name); - create_callback = PluginManager::GetEmulateInstructionCreateCallbackForPluginName (const_plugin_name); - if (create_callback) - { - EmulateInstruction *emulate_insn_ptr = create_callback(arch, supported_inst_type); - if (emulate_insn_ptr) - return emulate_insn_ptr; - } +EmulateInstruction * +EmulateInstruction::FindPlugin(const ArchSpec &arch, + InstructionType supported_inst_type, + const char *plugin_name) { + EmulateInstructionCreateInstance create_callback = nullptr; + if (plugin_name) { + ConstString const_plugin_name(plugin_name); + create_callback = + PluginManager::GetEmulateInstructionCreateCallbackForPluginName( + const_plugin_name); + if (create_callback) { + EmulateInstruction *emulate_insn_ptr = + create_callback(arch, supported_inst_type); + if (emulate_insn_ptr) + return emulate_insn_ptr; } - else - { - for (uint32_t idx = 0; (create_callback = PluginManager::GetEmulateInstructionCreateCallbackAtIndex(idx)) != nullptr; ++idx) - { - EmulateInstruction *emulate_insn_ptr = create_callback(arch, supported_inst_type); - if (emulate_insn_ptr) - return emulate_insn_ptr; - } + } else { + for (uint32_t idx = 0; + (create_callback = + PluginManager::GetEmulateInstructionCreateCallbackAtIndex(idx)) != + nullptr; + ++idx) { + EmulateInstruction *emulate_insn_ptr = + create_callback(arch, supported_inst_type); + if (emulate_insn_ptr) + return emulate_insn_ptr; } - return nullptr; -} - -EmulateInstruction::EmulateInstruction (const ArchSpec &arch) : - m_arch(arch), - m_baton(nullptr), - m_read_mem_callback(&ReadMemoryDefault), - m_write_mem_callback(&WriteMemoryDefault), - m_read_reg_callback(&ReadRegisterDefault), - m_write_reg_callback(&WriteRegisterDefault), - m_addr(LLDB_INVALID_ADDRESS) -{ - ::memset (&m_opcode, 0, sizeof (m_opcode)); -} - -bool -EmulateInstruction::ReadRegister (const RegisterInfo *reg_info, RegisterValue& reg_value) -{ - if (m_read_reg_callback != nullptr) - return m_read_reg_callback (this, m_baton, reg_info, reg_value); - return false; -} - -bool -EmulateInstruction::ReadRegister (lldb::RegisterKind reg_kind, uint32_t reg_num, RegisterValue& reg_value) -{ - RegisterInfo reg_info; - if (GetRegisterInfo(reg_kind, reg_num, reg_info)) - return ReadRegister (®_info, reg_value); - return false; -} - -uint64_t -EmulateInstruction::ReadRegisterUnsigned (lldb::RegisterKind reg_kind, - uint32_t reg_num, - uint64_t fail_value, - bool *success_ptr) -{ - RegisterValue reg_value; - if (ReadRegister (reg_kind, reg_num, reg_value)) - return reg_value.GetAsUInt64(fail_value, success_ptr); - if (success_ptr) - *success_ptr = false; - return fail_value; -} - -uint64_t -EmulateInstruction::ReadRegisterUnsigned (const RegisterInfo *reg_info, - uint64_t fail_value, - bool *success_ptr) -{ + } + return nullptr; +} + +EmulateInstruction::EmulateInstruction(const ArchSpec &arch) + : m_arch(arch), m_baton(nullptr), m_read_mem_callback(&ReadMemoryDefault), + m_write_mem_callback(&WriteMemoryDefault), + m_read_reg_callback(&ReadRegisterDefault), + m_write_reg_callback(&WriteRegisterDefault), + m_addr(LLDB_INVALID_ADDRESS) { + ::memset(&m_opcode, 0, sizeof(m_opcode)); +} + +bool EmulateInstruction::ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) { + if (m_read_reg_callback != nullptr) + return m_read_reg_callback(this, m_baton, reg_info, reg_value); + return false; +} + +bool EmulateInstruction::ReadRegister(lldb::RegisterKind reg_kind, + uint32_t reg_num, + RegisterValue ®_value) { + RegisterInfo reg_info; + if (GetRegisterInfo(reg_kind, reg_num, reg_info)) + return ReadRegister(®_info, reg_value); + return false; +} + +uint64_t EmulateInstruction::ReadRegisterUnsigned(lldb::RegisterKind reg_kind, + uint32_t reg_num, + uint64_t fail_value, + bool *success_ptr) { + RegisterValue reg_value; + if (ReadRegister(reg_kind, reg_num, reg_value)) + return reg_value.GetAsUInt64(fail_value, success_ptr); + if (success_ptr) + *success_ptr = false; + return fail_value; +} + +uint64_t EmulateInstruction::ReadRegisterUnsigned(const RegisterInfo *reg_info, + uint64_t fail_value, + bool *success_ptr) { + RegisterValue reg_value; + if (ReadRegister(reg_info, reg_value)) + return reg_value.GetAsUInt64(fail_value, success_ptr); + if (success_ptr) + *success_ptr = false; + return fail_value; +} + +bool EmulateInstruction::WriteRegister(const Context &context, + const RegisterInfo *reg_info, + const RegisterValue ®_value) { + if (m_write_reg_callback != nullptr) + return m_write_reg_callback(this, m_baton, context, reg_info, reg_value); + return false; +} + +bool EmulateInstruction::WriteRegister(const Context &context, + lldb::RegisterKind reg_kind, + uint32_t reg_num, + const RegisterValue ®_value) { + RegisterInfo reg_info; + if (GetRegisterInfo(reg_kind, reg_num, reg_info)) + return WriteRegister(context, ®_info, reg_value); + return false; +} + +bool EmulateInstruction::WriteRegisterUnsigned(const Context &context, + lldb::RegisterKind reg_kind, + uint32_t reg_num, + uint64_t uint_value) { + RegisterInfo reg_info; + if (GetRegisterInfo(reg_kind, reg_num, reg_info)) { RegisterValue reg_value; - if (ReadRegister (reg_info, reg_value)) - return reg_value.GetAsUInt64(fail_value, success_ptr); - if (success_ptr) - *success_ptr = false; - return fail_value; -} - -bool -EmulateInstruction::WriteRegister (const Context &context, - const RegisterInfo *reg_info, - const RegisterValue& reg_value) -{ - if (m_write_reg_callback != nullptr) - return m_write_reg_callback (this, m_baton, context, reg_info, reg_value); - return false; -} - -bool -EmulateInstruction::WriteRegister (const Context &context, - lldb::RegisterKind reg_kind, - uint32_t reg_num, - const RegisterValue& reg_value) -{ - RegisterInfo reg_info; - if (GetRegisterInfo(reg_kind, reg_num, reg_info)) - return WriteRegister (context, ®_info, reg_value); - return false; + if (reg_value.SetUInt(uint_value, reg_info.byte_size)) + return WriteRegister(context, ®_info, reg_value); + } + return false; } -bool -EmulateInstruction::WriteRegisterUnsigned (const Context &context, - lldb::RegisterKind reg_kind, - uint32_t reg_num, - uint64_t uint_value) -{ - RegisterInfo reg_info; - if (GetRegisterInfo(reg_kind, reg_num, reg_info)) - { - RegisterValue reg_value; - if (reg_value.SetUInt(uint_value, reg_info.byte_size)) - return WriteRegister (context, ®_info, reg_value); +bool EmulateInstruction::WriteRegisterUnsigned(const Context &context, + const RegisterInfo *reg_info, + uint64_t uint_value) { + if (reg_info != nullptr) { + RegisterValue reg_value; + if (reg_value.SetUInt(uint_value, reg_info->byte_size)) + return WriteRegister(context, reg_info, reg_value); + } + return false; +} + +size_t EmulateInstruction::ReadMemory(const Context &context, lldb::addr_t addr, + void *dst, size_t dst_len) { + if (m_read_mem_callback != nullptr) + return m_read_mem_callback(this, m_baton, context, addr, dst, dst_len) == + dst_len; + return false; +} + +uint64_t EmulateInstruction::ReadMemoryUnsigned(const Context &context, + lldb::addr_t addr, + size_t byte_size, + uint64_t fail_value, + bool *success_ptr) { + uint64_t uval64 = 0; + bool success = false; + if (byte_size <= 8) { + uint8_t buf[sizeof(uint64_t)]; + size_t bytes_read = + m_read_mem_callback(this, m_baton, context, addr, buf, byte_size); + if (bytes_read == byte_size) { + lldb::offset_t offset = 0; + DataExtractor data(buf, byte_size, GetByteOrder(), GetAddressByteSize()); + uval64 = data.GetMaxU64(&offset, byte_size); + success = true; } - return false; -} + } -bool -EmulateInstruction::WriteRegisterUnsigned (const Context &context, - const RegisterInfo *reg_info, - uint64_t uint_value) -{ - if (reg_info != nullptr) - { - RegisterValue reg_value; - if (reg_value.SetUInt(uint_value, reg_info->byte_size)) - return WriteRegister (context, reg_info, reg_value); - } - return false; -} + if (success_ptr) + *success_ptr = success; -size_t -EmulateInstruction::ReadMemory (const Context &context, - lldb::addr_t addr, - void *dst, - size_t dst_len) -{ - if (m_read_mem_callback != nullptr) - return m_read_mem_callback (this, m_baton, context, addr, dst, dst_len) == dst_len; - return false; + if (!success) + uval64 = fail_value; + return uval64; } -uint64_t -EmulateInstruction::ReadMemoryUnsigned (const Context &context, lldb::addr_t addr, size_t byte_size, uint64_t fail_value, bool *success_ptr) -{ - uint64_t uval64 = 0; - bool success = false; - if (byte_size <= 8) - { - uint8_t buf[sizeof(uint64_t)]; - size_t bytes_read = m_read_mem_callback (this, m_baton, context, addr, buf, byte_size); - if (bytes_read == byte_size) - { - lldb::offset_t offset = 0; - DataExtractor data (buf, byte_size, GetByteOrder(), GetAddressByteSize()); - uval64 = data.GetMaxU64 (&offset, byte_size); - success = true; - } - } +bool EmulateInstruction::WriteMemoryUnsigned(const Context &context, + lldb::addr_t addr, uint64_t uval, + size_t uval_byte_size) { + StreamString strm(Stream::eBinary, GetAddressByteSize(), GetByteOrder()); + strm.PutMaxHex64(uval, uval_byte_size); - if (success_ptr) - *success_ptr = success; - - if (!success) - uval64 = fail_value; - return uval64; -} - -bool -EmulateInstruction::WriteMemoryUnsigned (const Context &context, - lldb::addr_t addr, - uint64_t uval, - size_t uval_byte_size) -{ - StreamString strm(Stream::eBinary, GetAddressByteSize(), GetByteOrder()); - strm.PutMaxHex64 (uval, uval_byte_size); - - size_t bytes_written = m_write_mem_callback (this, m_baton, context, addr, strm.GetData(), uval_byte_size); - return (bytes_written == uval_byte_size); -} - -bool -EmulateInstruction::WriteMemory (const Context &context, - lldb::addr_t addr, - const void *src, - size_t src_len) -{ - if (m_write_mem_callback != nullptr) - return m_write_mem_callback (this, m_baton, context, addr, src, src_len) == src_len; - return false; + size_t bytes_written = m_write_mem_callback( + this, m_baton, context, addr, strm.GetString().data(), uval_byte_size); + return (bytes_written == uval_byte_size); } -void -EmulateInstruction::SetBaton (void *baton) -{ - m_baton = baton; +bool EmulateInstruction::WriteMemory(const Context &context, lldb::addr_t addr, + const void *src, size_t src_len) { + if (m_write_mem_callback != nullptr) + return m_write_mem_callback(this, m_baton, context, addr, src, src_len) == + src_len; + return false; } -void -EmulateInstruction::SetCallbacks (ReadMemoryCallback read_mem_callback, - WriteMemoryCallback write_mem_callback, - ReadRegisterCallback read_reg_callback, - WriteRegisterCallback write_reg_callback) -{ - m_read_mem_callback = read_mem_callback; - m_write_mem_callback = write_mem_callback; - m_read_reg_callback = read_reg_callback; - m_write_reg_callback = write_reg_callback; +void EmulateInstruction::SetBaton(void *baton) { m_baton = baton; } + +void EmulateInstruction::SetCallbacks( + ReadMemoryCallback read_mem_callback, + WriteMemoryCallback write_mem_callback, + ReadRegisterCallback read_reg_callback, + WriteRegisterCallback write_reg_callback) { + m_read_mem_callback = read_mem_callback; + m_write_mem_callback = write_mem_callback; + m_read_reg_callback = read_reg_callback; + m_write_reg_callback = write_reg_callback; } -void -EmulateInstruction::SetReadMemCallback (ReadMemoryCallback read_mem_callback) -{ - m_read_mem_callback = read_mem_callback; +void EmulateInstruction::SetReadMemCallback( + ReadMemoryCallback read_mem_callback) { + m_read_mem_callback = read_mem_callback; } -void -EmulateInstruction::SetWriteMemCallback (WriteMemoryCallback write_mem_callback) -{ - m_write_mem_callback = write_mem_callback; +void EmulateInstruction::SetWriteMemCallback( + WriteMemoryCallback write_mem_callback) { + m_write_mem_callback = write_mem_callback; } -void -EmulateInstruction::SetReadRegCallback (ReadRegisterCallback read_reg_callback) -{ - m_read_reg_callback = read_reg_callback; +void EmulateInstruction::SetReadRegCallback( + ReadRegisterCallback read_reg_callback) { + m_read_reg_callback = read_reg_callback; } -void -EmulateInstruction::SetWriteRegCallback (WriteRegisterCallback write_reg_callback) -{ - m_write_reg_callback = write_reg_callback; +void EmulateInstruction::SetWriteRegCallback( + WriteRegisterCallback write_reg_callback) { + m_write_reg_callback = write_reg_callback; } // // Read & Write Memory and Registers callback functions. // -size_t -EmulateInstruction::ReadMemoryFrame (EmulateInstruction *instruction, - void *baton, - const Context &context, - lldb::addr_t addr, - void *dst, - size_t dst_len) -{ - if (baton == nullptr || dst == nullptr || dst_len == 0) - return 0; - - StackFrame *frame = (StackFrame *) baton; - - ProcessSP process_sp (frame->CalculateProcess()); - if (process_sp) - { - Error error; - return process_sp->ReadMemory (addr, dst, dst_len, error); - } +size_t EmulateInstruction::ReadMemoryFrame(EmulateInstruction *instruction, + void *baton, const Context &context, + lldb::addr_t addr, void *dst, + size_t dst_len) { + if (baton == nullptr || dst == nullptr || dst_len == 0) return 0; + + StackFrame *frame = (StackFrame *)baton; + + ProcessSP process_sp(frame->CalculateProcess()); + if (process_sp) { + Error error; + return process_sp->ReadMemory(addr, dst, dst_len, error); + } + return 0; } -size_t -EmulateInstruction::WriteMemoryFrame (EmulateInstruction *instruction, - void *baton, - const Context &context, - lldb::addr_t addr, - const void *src, - size_t src_len) -{ - if (baton == nullptr || src == nullptr || src_len == 0) - return 0; - - StackFrame *frame = (StackFrame *) baton; - - ProcessSP process_sp (frame->CalculateProcess()); - if (process_sp) - { - Error error; - return process_sp->WriteMemory (addr, src, src_len, error); - } - +size_t EmulateInstruction::WriteMemoryFrame(EmulateInstruction *instruction, + void *baton, const Context &context, + lldb::addr_t addr, const void *src, + size_t src_len) { + if (baton == nullptr || src == nullptr || src_len == 0) return 0; -} -bool -EmulateInstruction::ReadRegisterFrame (EmulateInstruction *instruction, - void *baton, - const RegisterInfo *reg_info, - RegisterValue ®_value) -{ - if (baton == nullptr) - return false; - - StackFrame *frame = (StackFrame *) baton; - return frame->GetRegisterContext()->ReadRegister (reg_info, reg_value); -} - -bool -EmulateInstruction::WriteRegisterFrame (EmulateInstruction *instruction, - void *baton, - const Context &context, - const RegisterInfo *reg_info, - const RegisterValue ®_value) -{ - if (baton == nullptr) - return false; - - StackFrame *frame = (StackFrame *) baton; - return frame->GetRegisterContext()->WriteRegister (reg_info, reg_value); -} - -size_t -EmulateInstruction::ReadMemoryDefault (EmulateInstruction *instruction, - void *baton, - const Context &context, - lldb::addr_t addr, - void *dst, - size_t length) -{ - StreamFile strm (stdout, false); - strm.Printf (" Read from Memory (address = 0x%" PRIx64 ", length = %" PRIu64 ", context = ", addr, (uint64_t)length); - context.Dump (strm, instruction); - strm.EOL(); - *((uint64_t *) dst) = 0xdeadbeef; - return length; -} - -size_t -EmulateInstruction::WriteMemoryDefault (EmulateInstruction *instruction, - void *baton, - const Context &context, - lldb::addr_t addr, - const void *dst, - size_t length) -{ - StreamFile strm (stdout, false); - strm.Printf (" Write to Memory (address = 0x%" PRIx64 ", length = %" PRIu64 ", context = ", addr, (uint64_t)length); - context.Dump (strm, instruction); - strm.EOL(); - return length; -} - -bool -EmulateInstruction::ReadRegisterDefault (EmulateInstruction *instruction, - void *baton, - const RegisterInfo *reg_info, - RegisterValue ®_value) -{ - StreamFile strm (stdout, false); - strm.Printf (" Read Register (%s)\n", reg_info->name); - lldb::RegisterKind reg_kind; - uint32_t reg_num; - if (GetBestRegisterKindAndNumber (reg_info, reg_kind, reg_num)) - reg_value.SetUInt64((uint64_t)reg_kind << 24 | reg_num); - else - reg_value.SetUInt64(0); + StackFrame *frame = (StackFrame *)baton; - return true; -} + ProcessSP process_sp(frame->CalculateProcess()); + if (process_sp) { + Error error; + return process_sp->WriteMemory(addr, src, src_len, error); + } -bool -EmulateInstruction::WriteRegisterDefault (EmulateInstruction *instruction, - void *baton, - const Context &context, - const RegisterInfo *reg_info, - const RegisterValue ®_value) -{ - StreamFile strm (stdout, false); - strm.Printf (" Write to Register (name = %s, value = " , reg_info->name); - reg_value.Dump(&strm, reg_info, false, false, eFormatDefault); - strm.PutCString (", context = "); - context.Dump (strm, instruction); - strm.EOL(); - return true; + return 0; } -void -EmulateInstruction::Context::Dump (Stream &strm, - EmulateInstruction *instruction) const -{ - switch (type) - { - case eContextReadOpcode: - strm.PutCString ("reading opcode"); - break; - - case eContextImmediate: - strm.PutCString ("immediate"); - break; - - case eContextPushRegisterOnStack: - strm.PutCString ("push register"); - break; - - case eContextPopRegisterOffStack: - strm.PutCString ("pop register"); - break; - - case eContextAdjustStackPointer: - strm.PutCString ("adjust sp"); - break; - - case eContextSetFramePointer: - strm.PutCString ("set frame pointer"); - break; - - case eContextAdjustBaseRegister: - strm.PutCString ("adjusting (writing value back to) a base register"); - break; - - case eContextRegisterPlusOffset: - strm.PutCString ("register + offset"); - break; - - case eContextRegisterStore: - strm.PutCString ("store register"); - break; - - case eContextRegisterLoad: - strm.PutCString ("load register"); - break; - - case eContextRelativeBranchImmediate: - strm.PutCString ("relative branch immediate"); - break; - - case eContextAbsoluteBranchRegister: - strm.PutCString ("absolute branch register"); - break; - - case eContextSupervisorCall: - strm.PutCString ("supervisor call"); - break; - - case eContextTableBranchReadMemory: - strm.PutCString ("table branch read memory"); - break; - - case eContextWriteRegisterRandomBits: - strm.PutCString ("write random bits to a register"); - break; - - case eContextWriteMemoryRandomBits: - strm.PutCString ("write random bits to a memory address"); - break; - - case eContextArithmetic: - strm.PutCString ("arithmetic"); - break; - - case eContextReturnFromException: - strm.PutCString ("return from exception"); - break; - - default: - strm.PutCString ("unrecognized context."); - break; - } - - switch (info_type) - { - case eInfoTypeRegisterPlusOffset: - strm.Printf(" (reg_plus_offset = %s%+" PRId64 ")", - info.RegisterPlusOffset.reg.name, - info.RegisterPlusOffset.signed_offset); - break; - - case eInfoTypeRegisterPlusIndirectOffset: - strm.Printf(" (reg_plus_reg = %s + %s)", - info.RegisterPlusIndirectOffset.base_reg.name, - info.RegisterPlusIndirectOffset.offset_reg.name); - break; - - case eInfoTypeRegisterToRegisterPlusOffset: - strm.Printf(" (base_and_imm_offset = %s%+" PRId64 ", data_reg = %s)", - info.RegisterToRegisterPlusOffset.base_reg.name, - info.RegisterToRegisterPlusOffset.offset, - info.RegisterToRegisterPlusOffset.data_reg.name); - break; - - case eInfoTypeRegisterToRegisterPlusIndirectOffset: - strm.Printf(" (base_and_reg_offset = %s + %s, data_reg = %s)", - info.RegisterToRegisterPlusIndirectOffset.base_reg.name, - info.RegisterToRegisterPlusIndirectOffset.offset_reg.name, - info.RegisterToRegisterPlusIndirectOffset.data_reg.name); - break; - - case eInfoTypeRegisterRegisterOperands: - strm.Printf(" (register to register binary op: %s and %s)", - info.RegisterRegisterOperands.operand1.name, - info.RegisterRegisterOperands.operand2.name); - break; - - case eInfoTypeOffset: - strm.Printf (" (signed_offset = %+" PRId64 ")", info.signed_offset); - break; - - case eInfoTypeRegister: - strm.Printf (" (reg = %s)", info.reg.name); - break; - - case eInfoTypeImmediate: - strm.Printf (" (unsigned_immediate = %" PRIu64 " (0x%16.16" PRIx64 "))", - info.unsigned_immediate, - info.unsigned_immediate); - break; - - case eInfoTypeImmediateSigned: - strm.Printf (" (signed_immediate = %+" PRId64 " (0x%16.16" PRIx64 "))", - info.signed_immediate, - info.signed_immediate); - break; - - case eInfoTypeAddress: - strm.Printf (" (address = 0x%" PRIx64 ")", info.address); - break; - - case eInfoTypeISAAndImmediate: - strm.Printf (" (isa = %u, unsigned_immediate = %u (0x%8.8x))", - info.ISAAndImmediate.isa, - info.ISAAndImmediate.unsigned_data32, - info.ISAAndImmediate.unsigned_data32); - break; - - case eInfoTypeISAAndImmediateSigned: - strm.Printf (" (isa = %u, signed_immediate = %i (0x%8.8x))", - info.ISAAndImmediateSigned.isa, - info.ISAAndImmediateSigned.signed_data32, - info.ISAAndImmediateSigned.signed_data32); - break; - - case eInfoTypeISA: - strm.Printf (" (isa = %u)", info.isa); - break; - - case eInfoTypeNoArgs: - break; - } +bool EmulateInstruction::ReadRegisterFrame(EmulateInstruction *instruction, + void *baton, + const RegisterInfo *reg_info, + RegisterValue ®_value) { + if (baton == nullptr) + return false; + + StackFrame *frame = (StackFrame *)baton; + return frame->GetRegisterContext()->ReadRegister(reg_info, reg_value); } -bool -EmulateInstruction::SetInstruction (const Opcode &opcode, const Address &inst_addr, Target *target) -{ - m_opcode = opcode; - m_addr = LLDB_INVALID_ADDRESS; - if (inst_addr.IsValid()) - { - if (target != nullptr) - m_addr = inst_addr.GetLoadAddress (target); - if (m_addr == LLDB_INVALID_ADDRESS) - m_addr = inst_addr.GetFileAddress (); - } +bool EmulateInstruction::WriteRegisterFrame(EmulateInstruction *instruction, + void *baton, const Context &context, + const RegisterInfo *reg_info, + const RegisterValue ®_value) { + if (baton == nullptr) + return false; + + StackFrame *frame = (StackFrame *)baton; + return frame->GetRegisterContext()->WriteRegister(reg_info, reg_value); +} + +size_t EmulateInstruction::ReadMemoryDefault(EmulateInstruction *instruction, + void *baton, + const Context &context, + lldb::addr_t addr, void *dst, + size_t length) { + StreamFile strm(stdout, false); + strm.Printf(" Read from Memory (address = 0x%" PRIx64 ", length = %" PRIu64 + ", context = ", + addr, (uint64_t)length); + context.Dump(strm, instruction); + strm.EOL(); + *((uint64_t *)dst) = 0xdeadbeef; + return length; +} + +size_t EmulateInstruction::WriteMemoryDefault(EmulateInstruction *instruction, + void *baton, + const Context &context, + lldb::addr_t addr, + const void *dst, size_t length) { + StreamFile strm(stdout, false); + strm.Printf(" Write to Memory (address = 0x%" PRIx64 ", length = %" PRIu64 + ", context = ", + addr, (uint64_t)length); + context.Dump(strm, instruction); + strm.EOL(); + return length; +} + +bool EmulateInstruction::ReadRegisterDefault(EmulateInstruction *instruction, + void *baton, + const RegisterInfo *reg_info, + RegisterValue ®_value) { + StreamFile strm(stdout, false); + strm.Printf(" Read Register (%s)\n", reg_info->name); + lldb::RegisterKind reg_kind; + uint32_t reg_num; + if (GetBestRegisterKindAndNumber(reg_info, reg_kind, reg_num)) + reg_value.SetUInt64((uint64_t)reg_kind << 24 | reg_num); + else + reg_value.SetUInt64(0); + + return true; +} + +bool EmulateInstruction::WriteRegisterDefault(EmulateInstruction *instruction, + void *baton, + const Context &context, + const RegisterInfo *reg_info, + const RegisterValue ®_value) { + StreamFile strm(stdout, false); + strm.Printf(" Write to Register (name = %s, value = ", reg_info->name); + reg_value.Dump(&strm, reg_info, false, false, eFormatDefault); + strm.PutCString(", context = "); + context.Dump(strm, instruction); + strm.EOL(); + return true; +} + +void EmulateInstruction::Context::Dump(Stream &strm, + EmulateInstruction *instruction) const { + switch (type) { + case eContextReadOpcode: + strm.PutCString("reading opcode"); + break; + + case eContextImmediate: + strm.PutCString("immediate"); + break; + + case eContextPushRegisterOnStack: + strm.PutCString("push register"); + break; + + case eContextPopRegisterOffStack: + strm.PutCString("pop register"); + break; + + case eContextAdjustStackPointer: + strm.PutCString("adjust sp"); + break; + + case eContextSetFramePointer: + strm.PutCString("set frame pointer"); + break; + + case eContextAdjustBaseRegister: + strm.PutCString("adjusting (writing value back to) a base register"); + break; + + case eContextRegisterPlusOffset: + strm.PutCString("register + offset"); + break; + + case eContextRegisterStore: + strm.PutCString("store register"); + break; + + case eContextRegisterLoad: + strm.PutCString("load register"); + break; + + case eContextRelativeBranchImmediate: + strm.PutCString("relative branch immediate"); + break; + + case eContextAbsoluteBranchRegister: + strm.PutCString("absolute branch register"); + break; + + case eContextSupervisorCall: + strm.PutCString("supervisor call"); + break; + + case eContextTableBranchReadMemory: + strm.PutCString("table branch read memory"); + break; + + case eContextWriteRegisterRandomBits: + strm.PutCString("write random bits to a register"); + break; + + case eContextWriteMemoryRandomBits: + strm.PutCString("write random bits to a memory address"); + break; + + case eContextArithmetic: + strm.PutCString("arithmetic"); + break; + + case eContextReturnFromException: + strm.PutCString("return from exception"); + break; + + default: + strm.PutCString("unrecognized context."); + break; + } + + switch (info_type) { + case eInfoTypeRegisterPlusOffset: + strm.Printf(" (reg_plus_offset = %s%+" PRId64 ")", + info.RegisterPlusOffset.reg.name, + info.RegisterPlusOffset.signed_offset); + break; + + case eInfoTypeRegisterPlusIndirectOffset: + strm.Printf(" (reg_plus_reg = %s + %s)", + info.RegisterPlusIndirectOffset.base_reg.name, + info.RegisterPlusIndirectOffset.offset_reg.name); + break; + + case eInfoTypeRegisterToRegisterPlusOffset: + strm.Printf(" (base_and_imm_offset = %s%+" PRId64 ", data_reg = %s)", + info.RegisterToRegisterPlusOffset.base_reg.name, + info.RegisterToRegisterPlusOffset.offset, + info.RegisterToRegisterPlusOffset.data_reg.name); + break; + + case eInfoTypeRegisterToRegisterPlusIndirectOffset: + strm.Printf(" (base_and_reg_offset = %s + %s, data_reg = %s)", + info.RegisterToRegisterPlusIndirectOffset.base_reg.name, + info.RegisterToRegisterPlusIndirectOffset.offset_reg.name, + info.RegisterToRegisterPlusIndirectOffset.data_reg.name); + break; + + case eInfoTypeRegisterRegisterOperands: + strm.Printf(" (register to register binary op: %s and %s)", + info.RegisterRegisterOperands.operand1.name, + info.RegisterRegisterOperands.operand2.name); + break; + + case eInfoTypeOffset: + strm.Printf(" (signed_offset = %+" PRId64 ")", info.signed_offset); + break; + + case eInfoTypeRegister: + strm.Printf(" (reg = %s)", info.reg.name); + break; + + case eInfoTypeImmediate: + strm.Printf(" (unsigned_immediate = %" PRIu64 " (0x%16.16" PRIx64 "))", + info.unsigned_immediate, info.unsigned_immediate); + break; + + case eInfoTypeImmediateSigned: + strm.Printf(" (signed_immediate = %+" PRId64 " (0x%16.16" PRIx64 "))", + info.signed_immediate, info.signed_immediate); + break; + + case eInfoTypeAddress: + strm.Printf(" (address = 0x%" PRIx64 ")", info.address); + break; + + case eInfoTypeISAAndImmediate: + strm.Printf(" (isa = %u, unsigned_immediate = %u (0x%8.8x))", + info.ISAAndImmediate.isa, info.ISAAndImmediate.unsigned_data32, + info.ISAAndImmediate.unsigned_data32); + break; + + case eInfoTypeISAAndImmediateSigned: + strm.Printf(" (isa = %u, signed_immediate = %i (0x%8.8x))", + info.ISAAndImmediateSigned.isa, + info.ISAAndImmediateSigned.signed_data32, + info.ISAAndImmediateSigned.signed_data32); + break; + + case eInfoTypeISA: + strm.Printf(" (isa = %u)", info.isa); + break; + + case eInfoTypeNoArgs: + break; + } +} + +bool EmulateInstruction::SetInstruction(const Opcode &opcode, + const Address &inst_addr, + Target *target) { + m_opcode = opcode; + m_addr = LLDB_INVALID_ADDRESS; + if (inst_addr.IsValid()) { + if (target != nullptr) + m_addr = inst_addr.GetLoadAddress(target); + if (m_addr == LLDB_INVALID_ADDRESS) + m_addr = inst_addr.GetFileAddress(); + } + return true; +} + +bool EmulateInstruction::GetBestRegisterKindAndNumber( + const RegisterInfo *reg_info, lldb::RegisterKind ®_kind, + uint32_t ®_num) { + // Generic and DWARF should be the two most popular register kinds when + // emulating instructions since they are the most platform agnostic... + reg_num = reg_info->kinds[eRegisterKindGeneric]; + if (reg_num != LLDB_INVALID_REGNUM) { + reg_kind = eRegisterKindGeneric; return true; -} + } -bool -EmulateInstruction::GetBestRegisterKindAndNumber (const RegisterInfo *reg_info, - lldb::RegisterKind ®_kind, - uint32_t ®_num) -{ - // Generic and DWARF should be the two most popular register kinds when - // emulating instructions since they are the most platform agnostic... - reg_num = reg_info->kinds[eRegisterKindGeneric]; - if (reg_num != LLDB_INVALID_REGNUM) - { - reg_kind = eRegisterKindGeneric; - return true; - } - - reg_num = reg_info->kinds[eRegisterKindDWARF]; - if (reg_num != LLDB_INVALID_REGNUM) - { - reg_kind = eRegisterKindDWARF; - return true; - } + reg_num = reg_info->kinds[eRegisterKindDWARF]; + if (reg_num != LLDB_INVALID_REGNUM) { + reg_kind = eRegisterKindDWARF; + return true; + } - reg_num = reg_info->kinds[eRegisterKindLLDB]; - if (reg_num != LLDB_INVALID_REGNUM) - { - reg_kind = eRegisterKindLLDB; - return true; - } + reg_num = reg_info->kinds[eRegisterKindLLDB]; + if (reg_num != LLDB_INVALID_REGNUM) { + reg_kind = eRegisterKindLLDB; + return true; + } - reg_num = reg_info->kinds[eRegisterKindEHFrame]; - if (reg_num != LLDB_INVALID_REGNUM) - { - reg_kind = eRegisterKindEHFrame; - return true; - } + reg_num = reg_info->kinds[eRegisterKindEHFrame]; + if (reg_num != LLDB_INVALID_REGNUM) { + reg_kind = eRegisterKindEHFrame; + return true; + } - reg_num = reg_info->kinds[eRegisterKindProcessPlugin]; - if (reg_num != LLDB_INVALID_REGNUM) - { - reg_kind = eRegisterKindProcessPlugin; - return true; - } - return false; + reg_num = reg_info->kinds[eRegisterKindProcessPlugin]; + if (reg_num != LLDB_INVALID_REGNUM) { + reg_kind = eRegisterKindProcessPlugin; + return true; + } + return false; } uint32_t -EmulateInstruction::GetInternalRegisterNumber (RegisterContext *reg_ctx, const RegisterInfo ®_info) -{ - lldb::RegisterKind reg_kind; - uint32_t reg_num; - if (reg_ctx && GetBestRegisterKindAndNumber (®_info, reg_kind, reg_num)) - return reg_ctx->ConvertRegisterKindToRegisterNumber (reg_kind, reg_num); - return LLDB_INVALID_REGNUM; -} - -bool -EmulateInstruction::CreateFunctionEntryUnwind (UnwindPlan &unwind_plan) -{ - unwind_plan.Clear(); - return false; +EmulateInstruction::GetInternalRegisterNumber(RegisterContext *reg_ctx, + const RegisterInfo ®_info) { + lldb::RegisterKind reg_kind; + uint32_t reg_num; + if (reg_ctx && GetBestRegisterKindAndNumber(®_info, reg_kind, reg_num)) + return reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); + return LLDB_INVALID_REGNUM; +} + +bool EmulateInstruction::CreateFunctionEntryUnwind(UnwindPlan &unwind_plan) { + unwind_plan.Clear(); + return false; } diff --git a/source/Core/Error.cpp b/source/Core/Error.cpp index 97c2c4cc5b67..23696127d3b4 100644 --- a/source/Core/Error.cpp +++ b/source/Core/Error.cpp @@ -22,63 +22,47 @@ // Project includes #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" +#include "lldb/Host/PosixApi.h" using namespace lldb; using namespace lldb_private; -Error::Error (): - m_code (0), - m_type (eErrorTypeInvalid), - m_string () -{ -} +Error::Error() : m_code(0), m_type(eErrorTypeInvalid), m_string() {} -Error::Error(ValueType err, ErrorType type) : - m_code (err), - m_type (type), - m_string () -{ -} +Error::Error(ValueType err, ErrorType type) + : m_code(err), m_type(type), m_string() {} Error::Error(const Error &rhs) = default; -Error::Error (const char* format, ...): - m_code (0), - m_type (eErrorTypeInvalid), - m_string () -{ - va_list args; - va_start (args, format); - SetErrorToGenericError (); - SetErrorStringWithVarArg (format, args); - va_end (args); +Error::Error(const char *format, ...) + : m_code(0), m_type(eErrorTypeInvalid), m_string() { + va_list args; + va_start(args, format); + SetErrorToGenericError(); + SetErrorStringWithVarArg(format, args); + va_end(args); } //---------------------------------------------------------------------- // Assignment operator //---------------------------------------------------------------------- -const Error& -Error::operator = (const Error& rhs) -{ - if (this != &rhs) - { - m_code = rhs.m_code; - m_type = rhs.m_type; - m_string = rhs.m_string; - } - return *this; +const Error &Error::operator=(const Error &rhs) { + if (this != &rhs) { + m_code = rhs.m_code; + m_type = rhs.m_type; + m_string = rhs.m_string; + } + return *this; } //---------------------------------------------------------------------- // Assignment operator //---------------------------------------------------------------------- -const Error& -Error::operator = (uint32_t err) -{ - m_code = err; - m_type = eErrorTypeMachKernel; - m_string.clear(); - return *this; +const Error &Error::operator=(uint32_t err) { + m_code = err; + m_type = eErrorTypeMachKernel; + m_string.clear(); + return *this; } Error::~Error() = default; @@ -88,81 +72,62 @@ Error::~Error() = default; // fetched and cached on demand. The cached error string value will // remain until the error value is changed or cleared. //---------------------------------------------------------------------- -const char * -Error::AsCString(const char *default_error_str) const -{ - if (Success()) - return nullptr; - - if (m_string.empty()) - { - const char *s = nullptr; - switch (m_type) - { - case eErrorTypeMachKernel: -#if defined (__APPLE__) - s = ::mach_error_string (m_code); +const char *Error::AsCString(const char *default_error_str) const { + if (Success()) + return nullptr; + + if (m_string.empty()) { + const char *s = nullptr; + switch (m_type) { + case eErrorTypeMachKernel: +#if defined(__APPLE__) + s = ::mach_error_string(m_code); #endif - break; + break; - case eErrorTypePOSIX: - s = ::strerror (m_code); - break; + case eErrorTypePOSIX: + s = ::strerror(m_code); + break; - default: - break; - } - if (s != nullptr) - m_string.assign(s); + default: + break; } - if (m_string.empty()) - { - if (default_error_str) - m_string.assign(default_error_str); - else - return nullptr; // User wanted a nullptr string back... - } - return m_string.c_str(); + if (s != nullptr) + m_string.assign(s); + } + if (m_string.empty()) { + if (default_error_str) + m_string.assign(default_error_str); + else + return nullptr; // User wanted a nullptr string back... + } + return m_string.c_str(); } //---------------------------------------------------------------------- // Clear the error and any cached error string that it might contain. //---------------------------------------------------------------------- -void -Error::Clear () -{ - m_code = 0; - m_type = eErrorTypeInvalid; - m_string.clear(); +void Error::Clear() { + m_code = 0; + m_type = eErrorTypeInvalid; + m_string.clear(); } //---------------------------------------------------------------------- // Access the error value. //---------------------------------------------------------------------- -Error::ValueType -Error::GetError () const -{ - return m_code; -} +Error::ValueType Error::GetError() const { return m_code; } //---------------------------------------------------------------------- // Access the error type. //---------------------------------------------------------------------- -ErrorType -Error::GetType () const -{ - return m_type; -} +ErrorType Error::GetType() const { return m_type; } //---------------------------------------------------------------------- -// Retuns true if this object contains an value that describes an +// Returns true if this object contains a value that describes an // error or otherwise non-success result. //---------------------------------------------------------------------- -bool -Error::Fail () const -{ - return m_code != 0; -} +bool Error::Fail() const { return m_code != 0; } //---------------------------------------------------------------------- // Log the error given a string with format. If the this object @@ -173,34 +138,29 @@ Error::Fail () const // cached in this object. Logging always occurs even when the error // code contains a non-error value. //---------------------------------------------------------------------- -void -Error::PutToLog (Log *log, const char *format, ...) -{ - char *arg_msg = nullptr; - va_list args; - va_start (args, format); - ::vasprintf (&arg_msg, format, args); - va_end (args); - - if (arg_msg != nullptr) - { - if (Fail()) - { - const char *err_str = AsCString(); - if (err_str == nullptr) - err_str = "???"; - - SetErrorStringWithFormat("error: %s err = %s (0x%8.8x)", arg_msg, err_str, m_code); - if (log != nullptr) - log->Error("%s", m_string.c_str()); - } - else - { - if (log != nullptr) - log->Printf("%s err = 0x%8.8x", arg_msg, m_code); - } - ::free (arg_msg); +void Error::PutToLog(Log *log, const char *format, ...) { + char *arg_msg = nullptr; + va_list args; + va_start(args, format); + ::vasprintf(&arg_msg, format, args); + va_end(args); + + if (arg_msg != nullptr) { + if (Fail()) { + const char *err_str = AsCString(); + if (err_str == nullptr) + err_str = "???"; + + SetErrorStringWithFormat("error: %s err = %s (0x%8.8x)", arg_msg, err_str, + m_code); + if (log != nullptr) + log->Error("%s", m_string.c_str()); + } else { + if (log != nullptr) + log->Printf("%s err = 0x%8.8x", arg_msg, m_code); } + ::free(arg_msg); + } } //---------------------------------------------------------------------- @@ -212,106 +172,90 @@ Error::PutToLog (Log *log, const char *format, ...) // cached in this object. Logging only occurs even when the error // code contains a error value. //---------------------------------------------------------------------- -void -Error::LogIfError (Log *log, const char *format, ...) -{ - if (Fail()) - { - char *arg_msg = nullptr; - va_list args; - va_start (args, format); - ::vasprintf (&arg_msg, format, args); - va_end (args); - - if (arg_msg != nullptr) - { - const char *err_str = AsCString(); - if (err_str == nullptr) - err_str = "???"; - - SetErrorStringWithFormat("%s err = %s (0x%8.8x)", arg_msg, err_str, m_code); - if (log != nullptr) - log->Error("%s", m_string.c_str()); - - ::free (arg_msg); - } +void Error::LogIfError(Log *log, const char *format, ...) { + if (Fail()) { + char *arg_msg = nullptr; + va_list args; + va_start(args, format); + ::vasprintf(&arg_msg, format, args); + va_end(args); + + if (arg_msg != nullptr) { + const char *err_str = AsCString(); + if (err_str == nullptr) + err_str = "???"; + + SetErrorStringWithFormat("%s err = %s (0x%8.8x)", arg_msg, err_str, + m_code); + if (log != nullptr) + log->Error("%s", m_string.c_str()); + + ::free(arg_msg); } + } } //---------------------------------------------------------------------- // Set accesssor for the error value to "err" and the type to // "eErrorTypeMachKernel" //---------------------------------------------------------------------- -void -Error::SetMachError (uint32_t err) -{ - m_code = err; - m_type = eErrorTypeMachKernel; - m_string.clear(); +void Error::SetMachError(uint32_t err) { + m_code = err; + m_type = eErrorTypeMachKernel; + m_string.clear(); } -void -Error::SetExpressionError (lldb::ExpressionResults result, const char *mssg) -{ - m_code = result; - m_type = eErrorTypeExpression; - m_string = mssg; +void Error::SetExpressionError(lldb::ExpressionResults result, + const char *mssg) { + m_code = result; + m_type = eErrorTypeExpression; + m_string = mssg; } -int -Error::SetExpressionErrorWithFormat (lldb::ExpressionResults result, const char *format, ...) -{ - int length = 0; - - if (format != nullptr && format[0]) - { - va_list args; - va_start (args, format); - length = SetErrorStringWithVarArg (format, args); - va_end (args); - } - else - { - m_string.clear(); - } - m_code = result; - m_type = eErrorTypeExpression; - return length; +int Error::SetExpressionErrorWithFormat(lldb::ExpressionResults result, + const char *format, ...) { + int length = 0; + + if (format != nullptr && format[0]) { + va_list args; + va_start(args, format); + length = SetErrorStringWithVarArg(format, args); + va_end(args); + } else { + m_string.clear(); + } + m_code = result; + m_type = eErrorTypeExpression; + return length; } //---------------------------------------------------------------------- // Set accesssor for the error value and type. //---------------------------------------------------------------------- -void -Error::SetError (ValueType err, ErrorType type) -{ - m_code = err; - m_type = type; - m_string.clear(); +void Error::SetError(ValueType err, ErrorType type) { + m_code = err; + m_type = type; + m_string.clear(); } //---------------------------------------------------------------------- // Update the error value to be "errno" and update the type to // be "POSIX". //---------------------------------------------------------------------- -void -Error::SetErrorToErrno() -{ - m_code = errno; - m_type = eErrorTypePOSIX; - m_string.clear(); +void Error::SetErrorToErrno() { + m_code = errno; + m_type = eErrorTypePOSIX; + m_string.clear(); } //---------------------------------------------------------------------- // Update the error value to be LLDB_GENERIC_ERROR and update the type // to be "Generic". //---------------------------------------------------------------------- -void -Error::SetErrorToGenericError () -{ - m_code = LLDB_GENERIC_ERROR; - m_type = eErrorTypeGeneric; - m_string.clear(); +void Error::SetErrorToGenericError() { + m_code = LLDB_GENERIC_ERROR; + m_type = eErrorTypeGeneric; + m_string.clear(); } //---------------------------------------------------------------------- @@ -320,19 +264,14 @@ Error::SetErrorToGenericError () // The error string value will remain until the error value is // cleared or a new error value/type is assigned. //---------------------------------------------------------------------- -void -Error::SetErrorString (const char *err_str) -{ - if (err_str != nullptr && err_str[0]) - { - // If we have an error string, we should always at least have - // an error set to a generic value. - if (Success()) - SetErrorToGenericError(); - m_string = err_str; - } - else - m_string.clear(); +void Error::SetErrorString(llvm::StringRef err_str) { + if (!err_str.empty()) { + // If we have an error string, we should always at least have an error + // set to a generic value. + if (Success()) + SetErrorToGenericError(); + } + m_string = err_str; } //------------------------------------------------------------------ @@ -341,74 +280,57 @@ Error::SetErrorString (const char *err_str) /// @param format /// A printf style format string //------------------------------------------------------------------ -int -Error::SetErrorStringWithFormat (const char *format, ...) -{ - if (format != nullptr && format[0]) - { - va_list args; - va_start (args, format); - int length = SetErrorStringWithVarArg (format, args); - va_end (args); - return length; - } - else - { - m_string.clear(); - } - return 0; +int Error::SetErrorStringWithFormat(const char *format, ...) { + if (format != nullptr && format[0]) { + va_list args; + va_start(args, format); + int length = SetErrorStringWithVarArg(format, args); + va_end(args); + return length; + } else { + m_string.clear(); + } + return 0; } -int -Error::SetErrorStringWithVarArg (const char *format, va_list args) -{ - if (format != nullptr && format[0]) - { - // If we have an error string, we should always at least have - // an error set to a generic value. - if (Success()) - SetErrorToGenericError(); - - // Try and fit our error into a 1024 byte buffer first... - llvm::SmallVector<char, 1024> buf; - buf.resize(1024); - // Copy in case our first call to vsnprintf doesn't fit into our - // allocated buffer above - va_list copy_args; - va_copy (copy_args, args); - unsigned length = ::vsnprintf (buf.data(), buf.size(), format, args); - if (length >= buf.size()) - { - // The error formatted string didn't fit into our buffer, resize it - // to the exact needed size, and retry - buf.resize(length + 1); - length = ::vsnprintf (buf.data(), buf.size(), format, copy_args); - va_end (copy_args); - assert (length < buf.size()); - } - m_string.assign(buf.data(), length); - va_end (args); - return length; - } - else - { - m_string.clear(); +int Error::SetErrorStringWithVarArg(const char *format, va_list args) { + if (format != nullptr && format[0]) { + // If we have an error string, we should always at least have + // an error set to a generic value. + if (Success()) + SetErrorToGenericError(); + + // Try and fit our error into a 1024 byte buffer first... + llvm::SmallVector<char, 1024> buf; + buf.resize(1024); + // Copy in case our first call to vsnprintf doesn't fit into our + // allocated buffer above + va_list copy_args; + va_copy(copy_args, args); + unsigned length = ::vsnprintf(buf.data(), buf.size(), format, args); + if (length >= buf.size()) { + // The error formatted string didn't fit into our buffer, resize it + // to the exact needed size, and retry + buf.resize(length + 1); + length = ::vsnprintf(buf.data(), buf.size(), format, copy_args); + va_end(copy_args); + assert(length < buf.size()); } - return 0; + m_string.assign(buf.data(), length); + va_end(args); + return length; + } else { + m_string.clear(); + } + return 0; } //---------------------------------------------------------------------- // Returns true if the error code in this object is considered a // successful return value. //---------------------------------------------------------------------- -bool -Error::Success() const -{ - return m_code == 0; -} +bool Error::Success() const { return m_code == 0; } -bool -Error::WasInterrupted() const -{ - return (m_type == eErrorTypePOSIX && m_code == EINTR); +bool Error::WasInterrupted() const { + return (m_type == eErrorTypePOSIX && m_code == EINTR); } diff --git a/source/Core/Event.cpp b/source/Core/Event.cpp index 6b07e4d91987..bd57198f5487 100644 --- a/source/Core/Event.cpp +++ b/source/Core/Event.cpp @@ -13,9 +13,9 @@ // Other libraries and framework includes // Project includes -#include "lldb/Core/Event.h" #include "lldb/Core/Broadcaster.h" #include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Event.h" #include "lldb/Core/Log.h" #include "lldb/Core/State.h" #include "lldb/Core/Stream.h" @@ -25,202 +25,280 @@ using namespace lldb; using namespace lldb_private; -Event::Event (Broadcaster *broadcaster, uint32_t event_type, EventData *data) : - m_broadcaster_wp(broadcaster->GetBroadcasterImpl()), - m_type(event_type), - m_data_sp(data) -{ -} +#pragma mark - +#pragma mark Event -Event::Event (Broadcaster *broadcaster, uint32_t event_type, const EventDataSP &event_data_sp) : - m_broadcaster_wp(broadcaster->GetBroadcasterImpl()), - m_type(event_type), - m_data_sp(event_data_sp) -{ -} +//------------------------------------------------------------------ +// Event functions +//------------------------------------------------------------------ -Event::Event(uint32_t event_type, EventData *data) : - m_broadcaster_wp(), - m_type(event_type), - m_data_sp(data) -{ -} +Event::Event(Broadcaster *broadcaster, uint32_t event_type, EventData *data) + : m_broadcaster_wp(broadcaster->GetBroadcasterImpl()), m_type(event_type), + m_data_sp(data) {} -Event::Event(uint32_t event_type, const EventDataSP &event_data_sp) : - m_broadcaster_wp(), - m_type(event_type), - m_data_sp(event_data_sp) -{ -} +Event::Event(Broadcaster *broadcaster, uint32_t event_type, + const EventDataSP &event_data_sp) + : m_broadcaster_wp(broadcaster->GetBroadcasterImpl()), m_type(event_type), + m_data_sp(event_data_sp) {} + +Event::Event(uint32_t event_type, EventData *data) + : m_broadcaster_wp(), m_type(event_type), m_data_sp(data) {} + +Event::Event(uint32_t event_type, const EventDataSP &event_data_sp) + : m_broadcaster_wp(), m_type(event_type), m_data_sp(event_data_sp) {} Event::~Event() = default; -void -Event::Dump (Stream *s) const -{ - Broadcaster *broadcaster; - Broadcaster::BroadcasterImplSP broadcaster_impl_sp(m_broadcaster_wp.lock()); - if (broadcaster_impl_sp) - broadcaster = broadcaster_impl_sp->GetBroadcaster(); - else - broadcaster = nullptr; - - if (broadcaster) - { - StreamString event_name; - if (broadcaster->GetEventNames (event_name, m_type, false)) - s->Printf("%p Event: broadcaster = %p (%s), type = 0x%8.8x (%s), data = ", - static_cast<const void*>(this), - static_cast<void*>(broadcaster), - broadcaster->GetBroadcasterName().GetCString(), - m_type, event_name.GetString().c_str()); - else - s->Printf("%p Event: broadcaster = %p (%s), type = 0x%8.8x, data = ", - static_cast<const void*>(this), - static_cast<void*>(broadcaster), - broadcaster->GetBroadcasterName().GetCString(), m_type); - } - else - s->Printf("%p Event: broadcaster = NULL, type = 0x%8.8x, data = ", - static_cast<const void*>(this), m_type); - - if (m_data_sp) - { - s->PutChar('{'); - m_data_sp->Dump (s); - s->PutChar('}'); - } +void Event::Dump(Stream *s) const { + Broadcaster *broadcaster; + Broadcaster::BroadcasterImplSP broadcaster_impl_sp(m_broadcaster_wp.lock()); + if (broadcaster_impl_sp) + broadcaster = broadcaster_impl_sp->GetBroadcaster(); + else + broadcaster = nullptr; + + if (broadcaster) { + StreamString event_name; + if (broadcaster->GetEventNames(event_name, m_type, false)) + s->Printf("%p Event: broadcaster = %p (%s), type = 0x%8.8x (%s), data = ", + static_cast<const void *>(this), + static_cast<void *>(broadcaster), + broadcaster->GetBroadcasterName().GetCString(), m_type, + event_name.GetData()); else - s->Printf ("<NULL>"); + s->Printf("%p Event: broadcaster = %p (%s), type = 0x%8.8x, data = ", + static_cast<const void *>(this), + static_cast<void *>(broadcaster), + broadcaster->GetBroadcasterName().GetCString(), m_type); + } else + s->Printf("%p Event: broadcaster = NULL, type = 0x%8.8x, data = ", + static_cast<const void *>(this), m_type); + + if (m_data_sp) { + s->PutChar('{'); + m_data_sp->Dump(s); + s->PutChar('}'); + } else + s->Printf("<NULL>"); } -void -Event::DoOnRemoval () -{ - if (m_data_sp) - m_data_sp->DoOnRemoval (this); +void Event::DoOnRemoval() { + if (m_data_sp) + m_data_sp->DoOnRemoval(this); } +#pragma mark - +#pragma mark EventData + +//------------------------------------------------------------------ +// EventData functions +//------------------------------------------------------------------ + EventData::EventData() = default; EventData::~EventData() = default; -void -EventData::Dump (Stream *s) const -{ - s->PutCString ("Generic Event Data"); -} +void EventData::Dump(Stream *s) const { s->PutCString("Generic Event Data"); } -EventDataBytes::EventDataBytes () : - m_bytes() -{ +#pragma mark - +#pragma mark EventDataBytes + +//------------------------------------------------------------------ +// EventDataBytes functions +//------------------------------------------------------------------ + +EventDataBytes::EventDataBytes() : m_bytes() {} + +EventDataBytes::EventDataBytes(const char *cstr) : m_bytes() { + SetBytesFromCString(cstr); } -EventDataBytes::EventDataBytes (const char *cstr) : - m_bytes() -{ - SetBytesFromCString (cstr); +EventDataBytes::EventDataBytes(llvm::StringRef str) : m_bytes() { + SetBytes(str.data(), str.size()); } -EventDataBytes::EventDataBytes (const void *src, size_t src_len) : - m_bytes() -{ - SetBytes (src, src_len); +EventDataBytes::EventDataBytes(const void *src, size_t src_len) : m_bytes() { + SetBytes(src, src_len); } EventDataBytes::~EventDataBytes() = default; -const ConstString & -EventDataBytes::GetFlavorString () -{ - static ConstString g_flavor ("EventDataBytes"); - return g_flavor; +const ConstString &EventDataBytes::GetFlavorString() { + static ConstString g_flavor("EventDataBytes"); + return g_flavor; } -const ConstString & -EventDataBytes::GetFlavor () const -{ - return EventDataBytes::GetFlavorString (); +const ConstString &EventDataBytes::GetFlavor() const { + return EventDataBytes::GetFlavorString(); } -void -EventDataBytes::Dump (Stream *s) const -{ - size_t num_printable_chars = std::count_if (m_bytes.begin(), m_bytes.end(), isprint); - if (num_printable_chars == m_bytes.size()) - { - s->Printf("\"%s\"", m_bytes.c_str()); - } - else if (!m_bytes.empty()) - { - DataExtractor data; - data.SetData(m_bytes.data(), m_bytes.size(), endian::InlHostByteOrder()); - data.Dump(s, 0, eFormatBytes, 1, m_bytes.size(), 32, LLDB_INVALID_ADDRESS, 0, 0); - } +void EventDataBytes::Dump(Stream *s) const { + size_t num_printable_chars = + std::count_if(m_bytes.begin(), m_bytes.end(), isprint); + if (num_printable_chars == m_bytes.size()) { + s->Printf("\"%s\"", m_bytes.c_str()); + } else if (!m_bytes.empty()) { + DataExtractor data; + data.SetData(m_bytes.data(), m_bytes.size(), endian::InlHostByteOrder()); + data.Dump(s, 0, eFormatBytes, 1, m_bytes.size(), 32, LLDB_INVALID_ADDRESS, + 0, 0); + } } -const void * -EventDataBytes::GetBytes() const -{ - return (m_bytes.empty() ? nullptr : m_bytes.data()); +const void *EventDataBytes::GetBytes() const { + return (m_bytes.empty() ? nullptr : m_bytes.data()); } -size_t -EventDataBytes::GetByteSize() const -{ - return m_bytes.size (); -} +size_t EventDataBytes::GetByteSize() const { return m_bytes.size(); } -void -EventDataBytes::SetBytes (const void *src, size_t src_len) -{ - if (src != nullptr && src_len > 0) - m_bytes.assign ((const char *)src, src_len); - else - m_bytes.clear(); +void EventDataBytes::SetBytes(const void *src, size_t src_len) { + if (src != nullptr && src_len > 0) + m_bytes.assign((const char *)src, src_len); + else + m_bytes.clear(); } -void -EventDataBytes::SetBytesFromCString (const char *cstr) -{ - if (cstr != nullptr && cstr[0]) - m_bytes.assign (cstr); - else - m_bytes.clear(); +void EventDataBytes::SetBytesFromCString(const char *cstr) { + if (cstr != nullptr && cstr[0]) + m_bytes.assign(cstr); + else + m_bytes.clear(); } -const void * -EventDataBytes::GetBytesFromEvent (const Event *event_ptr) -{ - const EventDataBytes *e = GetEventDataFromEvent (event_ptr); - if (e != nullptr) - return e->GetBytes(); - return nullptr; +const void *EventDataBytes::GetBytesFromEvent(const Event *event_ptr) { + const EventDataBytes *e = GetEventDataFromEvent(event_ptr); + if (e != nullptr) + return e->GetBytes(); + return nullptr; } -size_t -EventDataBytes::GetByteSizeFromEvent (const Event *event_ptr) -{ - const EventDataBytes *e = GetEventDataFromEvent (event_ptr); - if (e != nullptr) - return e->GetByteSize(); - return 0; +size_t EventDataBytes::GetByteSizeFromEvent(const Event *event_ptr) { + const EventDataBytes *e = GetEventDataFromEvent(event_ptr); + if (e != nullptr) + return e->GetByteSize(); + return 0; } const EventDataBytes * -EventDataBytes::GetEventDataFromEvent (const Event *event_ptr) -{ - if (event_ptr != nullptr) - { - const EventData *event_data = event_ptr->GetData(); - if (event_data && event_data->GetFlavor() == EventDataBytes::GetFlavorString()) - return static_cast <const EventDataBytes *> (event_data); - } +EventDataBytes::GetEventDataFromEvent(const Event *event_ptr) { + if (event_ptr != nullptr) { + const EventData *event_data = event_ptr->GetData(); + if (event_data && + event_data->GetFlavor() == EventDataBytes::GetFlavorString()) + return static_cast<const EventDataBytes *>(event_data); + } + return nullptr; +} + +void EventDataBytes::SwapBytes(std::string &new_bytes) { + m_bytes.swap(new_bytes); +} + +#pragma mark - +#pragma mark EventStructuredData + +//------------------------------------------------------------------ +// EventDataStructuredData definitions +//------------------------------------------------------------------ + +EventDataStructuredData::EventDataStructuredData() + : EventData(), m_process_sp(), m_object_sp(), m_plugin_sp() {} + +EventDataStructuredData::EventDataStructuredData( + const ProcessSP &process_sp, const StructuredData::ObjectSP &object_sp, + const lldb::StructuredDataPluginSP &plugin_sp) + : EventData(), m_process_sp(process_sp), m_object_sp(object_sp), + m_plugin_sp(plugin_sp) {} + +EventDataStructuredData::~EventDataStructuredData() {} + +//------------------------------------------------------------------ +// EventDataStructuredData member functions +//------------------------------------------------------------------ + +const ConstString &EventDataStructuredData::GetFlavor() const { + return EventDataStructuredData::GetFlavorString(); +} + +void EventDataStructuredData::Dump(Stream *s) const { + if (!s) + return; + + if (m_object_sp) + m_object_sp->Dump(*s); +} + +const ProcessSP &EventDataStructuredData::GetProcess() const { + return m_process_sp; +} + +const StructuredData::ObjectSP &EventDataStructuredData::GetObject() const { + return m_object_sp; +} + +const lldb::StructuredDataPluginSP & +EventDataStructuredData::GetStructuredDataPlugin() const { + return m_plugin_sp; +} + +void EventDataStructuredData::SetProcess(const ProcessSP &process_sp) { + m_process_sp = process_sp; +} + +void EventDataStructuredData::SetObject( + const StructuredData::ObjectSP &object_sp) { + m_object_sp = object_sp; +} + +void EventDataStructuredData::SetStructuredDataPlugin( + const lldb::StructuredDataPluginSP &plugin_sp) { + m_plugin_sp = plugin_sp; +} + +//------------------------------------------------------------------ +// EventDataStructuredData static functions +//------------------------------------------------------------------ + +const EventDataStructuredData * +EventDataStructuredData::GetEventDataFromEvent(const Event *event_ptr) { + if (event_ptr == nullptr) + return nullptr; + + const EventData *event_data = event_ptr->GetData(); + if (!event_data || + event_data->GetFlavor() != EventDataStructuredData::GetFlavorString()) return nullptr; + + return static_cast<const EventDataStructuredData *>(event_data); +} + +ProcessSP EventDataStructuredData::GetProcessFromEvent(const Event *event_ptr) { + auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr); + if (event_data) + return event_data->GetProcess(); + else + return ProcessSP(); +} + +StructuredData::ObjectSP +EventDataStructuredData::GetObjectFromEvent(const Event *event_ptr) { + auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr); + if (event_data) + return event_data->GetObject(); + else + return StructuredData::ObjectSP(); +} + +lldb::StructuredDataPluginSP +EventDataStructuredData::GetPluginFromEvent(const Event *event_ptr) { + auto event_data = EventDataStructuredData::GetEventDataFromEvent(event_ptr); + if (event_data) + return event_data->GetStructuredDataPlugin(); + else + return StructuredDataPluginSP(); } -void -EventDataBytes::SwapBytes (std::string &new_bytes) -{ - m_bytes.swap (new_bytes); +const ConstString &EventDataStructuredData::GetFlavorString() { + static ConstString s_flavor("EventDataStructuredData"); + return s_flavor; } diff --git a/source/Core/FastDemangle.cpp b/source/Core/FastDemangle.cpp index 528f7f6bd88d..0bed4a1f20ad 100644 --- a/source/Core/FastDemangle.cpp +++ b/source/Core/FastDemangle.cpp @@ -8,9 +8,12 @@ //===----------------------------------------------------------------------===// #include <stdio.h> -#include <string.h> #include <stdlib.h> +#include <string.h> + +#include <functional> +#include "lldb/Core/FastDemangle.h" #include "lldb/lldb-private.h" //#define DEBUG_FAILURES 1 @@ -23,57 +26,52 @@ namespace { /// @brief Represents the collection of qualifiers on a type -enum Qualifiers -{ - QualifierNone = 0, - QualifierConst = 1, - QualifierRestrict = 2, - QualifierVolatile = 4, - QualifierReference = 8, - QualifierRValueReference = 16, - QualifierPointer = 32 +enum Qualifiers { + QualifierNone = 0, + QualifierConst = 1, + QualifierRestrict = 2, + QualifierVolatile = 4, + QualifierReference = 8, + QualifierRValueReference = 16, + QualifierPointer = 32 }; /// @brief Categorizes the recognized operators -enum class OperatorKind -{ - Unary, - Postfix, - Binary, - Ternary, - Other, - ConversionOperator, - Vendor, - NoMatch +enum class OperatorKind { + Unary, + Postfix, + Binary, + Ternary, + Other, + ConversionOperator, + Vendor, + NoMatch }; /// @brief Represents one of the recognized two-character operator /// abbreviations used when parsing operators as names and expressions -struct Operator -{ - const char *name; - OperatorKind kind; +struct Operator { + const char *name; + OperatorKind kind; }; /// @brief Represents a range of characters in the output buffer, typically for /// use with RewriteRange() -struct BufferRange -{ - int offset; - int length; +struct BufferRange { + int offset; + int length; }; /// @brief Transient state required while parsing a name -struct NameState -{ - bool parse_function_params; - bool is_last_generic; - bool has_no_return_type; - BufferRange last_name_range; +struct NameState { + bool parse_function_params; + bool is_last_generic; + bool has_no_return_type; + BufferRange last_name_range; }; /// @brief LLDB's fast C++ demangler @@ -86,942 +84,919 @@ struct NameState /// Over time the full mangling spec should be supported without compromising /// performance for the most common cases. -class SymbolDemangler -{ +class SymbolDemangler { public: - - //---------------------------------------------------- - // Public API - //---------------------------------------------------- - - /// @brief Create a SymbolDemangler - /// - /// The newly created demangler allocates and owns scratch memory sufficient - /// for demangling typical symbols. Additional memory will be allocated if - /// needed and managed by the demangler instance. - - SymbolDemangler() - { - m_buffer = (char *) malloc(8192); - m_buffer_end = m_buffer + 8192; - m_owns_buffer = true; - - m_rewrite_ranges = (BufferRange *) malloc(128 * sizeof (BufferRange)); - m_rewrite_ranges_size = 128; - m_owns_m_rewrite_ranges = true; - } - - /// @brief Create a SymbolDemangler that uses provided scratch memory - /// - /// The provided memory is not owned by the demangler. It will be - /// overwritten during calls to GetDemangledCopy() but can be used for - /// other purposes between calls. The provided memory will not be freed - /// when this instance is destroyed. - /// - /// If demangling a symbol requires additional space it will be allocated - /// and managed by the demangler instance. - /// - /// @param storage_ptr Valid pointer to at least storage_size bytes of - /// space that the SymbolDemangler can use during demangling - /// - /// @param storage_size Number of bytes of space available scratch memory - /// referenced by storage_ptr - - SymbolDemangler(void *storage_ptr, int storage_size) - { - // Use up to 1/8th of the provided space for rewrite ranges - m_rewrite_ranges_size = (storage_size >> 3) / sizeof (BufferRange); - m_rewrite_ranges = (BufferRange *) storage_ptr; - m_owns_m_rewrite_ranges = false; - - // Use the rest for the character buffer - m_buffer = (char *) storage_ptr + m_rewrite_ranges_size * sizeof (BufferRange); - m_buffer_end = (const char *)storage_ptr + storage_size; - m_owns_buffer = false; - } - - /// @brief Destroys the SymbolDemangler and deallocates any scratch - /// memory that it owns - - ~SymbolDemangler() - { - if (m_owns_buffer) - free(m_buffer); - if (m_owns_m_rewrite_ranges) - free(m_rewrite_ranges); - } + //---------------------------------------------------- + // Public API + //---------------------------------------------------- + + /// @brief Create a SymbolDemangler + /// + /// The newly created demangler allocates and owns scratch memory sufficient + /// for demangling typical symbols. Additional memory will be allocated if + /// needed and managed by the demangler instance. + + SymbolDemangler() { + m_buffer = (char *)malloc(8192); + m_buffer_end = m_buffer + 8192; + m_owns_buffer = true; + + m_rewrite_ranges = (BufferRange *)malloc(128 * sizeof(BufferRange)); + m_rewrite_ranges_size = 128; + m_owns_m_rewrite_ranges = true; + } + + /// @brief Create a SymbolDemangler that uses provided scratch memory + /// + /// The provided memory is not owned by the demangler. It will be + /// overwritten during calls to GetDemangledCopy() but can be used for + /// other purposes between calls. The provided memory will not be freed + /// when this instance is destroyed. + /// + /// If demangling a symbol requires additional space it will be allocated + /// and managed by the demangler instance. + /// + /// @param storage_ptr Valid pointer to at least storage_size bytes of + /// space that the SymbolDemangler can use during demangling + /// + /// @param storage_size Number of bytes of space available scratch memory + /// referenced by storage_ptr + + SymbolDemangler(void *storage_ptr, size_t storage_size, + std::function<void(const char *)> builtins_hook = nullptr) + : m_builtins_hook(builtins_hook) { + // Use up to 1/8th of the provided space for rewrite ranges + m_rewrite_ranges_size = (storage_size >> 3) / sizeof(BufferRange); + m_rewrite_ranges = (BufferRange *)storage_ptr; + m_owns_m_rewrite_ranges = false; + + // Use the rest for the character buffer + m_buffer = + (char *)storage_ptr + m_rewrite_ranges_size * sizeof(BufferRange); + m_buffer_end = (const char *)storage_ptr + storage_size; + m_owns_buffer = false; + } + + /// @brief Destroys the SymbolDemangler and deallocates any scratch + /// memory that it owns + + ~SymbolDemangler() { + if (m_owns_buffer) + free(m_buffer); + if (m_owns_m_rewrite_ranges) + free(m_rewrite_ranges); + } #ifdef DEBUG_HIGHWATER - int highwater_store = 0; - int highwater_buffer = 0; + int highwater_store = 0; + int highwater_buffer = 0; #endif - /// @brief Parses the provided mangled name and returns a newly allocated - /// demangling - /// - /// @param mangled_name Valid null-terminated C++ mangled name following - /// the Itanium C++ ABI mangling specification as implemented by Clang - /// - /// @result Newly allocated null-terminated demangled name when demangling - /// is successful, and nullptr when demangling fails. The caller is - /// responsible for freeing the allocated memory. - - char * - GetDemangledCopy(const char *mangled_name, - long mangled_name_length = 0) - { - if (!ParseMangling(mangled_name, mangled_name_length)) - return nullptr; + /// @brief Parses the provided mangled name and returns a newly allocated + /// demangling + /// + /// @param mangled_name Valid null-terminated C++ mangled name following + /// the Itanium C++ ABI mangling specification as implemented by Clang + /// + /// @result Newly allocated null-terminated demangled name when demangling + /// is successful, and nullptr when demangling fails. The caller is + /// responsible for freeing the allocated memory. + + char *GetDemangledCopy(const char *mangled_name, + long mangled_name_length = 0) { + if (!ParseMangling(mangled_name, mangled_name_length)) + return nullptr; #ifdef DEBUG_HIGHWATER - int rewrite_count = m_next_substitute_index + - (m_rewrite_ranges_size - 1 - m_next_template_arg_index); - int buffer_size = (int)(m_write_ptr - m_buffer); - if (rewrite_count > highwater_store) - highwater_store = rewrite_count; - if (buffer_size > highwater_buffer) - highwater_buffer = buffer_size; + int rewrite_count = m_next_substitute_index + + (m_rewrite_ranges_size - 1 - m_next_template_arg_index); + int buffer_size = (int)(m_write_ptr - m_buffer); + if (rewrite_count > highwater_store) + highwater_store = rewrite_count; + if (buffer_size > highwater_buffer) + highwater_buffer = buffer_size; #endif - int length = (int)(m_write_ptr - m_buffer); - char *copy = (char *)malloc(length + 1); - memcpy(copy, m_buffer, length); - copy[length] = '\0'; - return copy; - } + int length = (int)(m_write_ptr - m_buffer); + char *copy = (char *)malloc(length + 1); + memcpy(copy, m_buffer, length); + copy[length] = '\0'; + return copy; + } private: - - //---------------------------------------------------- - // Grow methods - // - // Manage the storage used during demangling - //---------------------------------------------------- - - void GrowBuffer(long min_growth = 0) - { - // By default, double the size of the buffer - long growth = m_buffer_end - m_buffer; - - // Avoid growing by more than 1MB at a time - if (growth > 1 << 20) - growth = 1 << 20; - - // ... but never grow by less than requested, - // or 1K, whichever is greater - if (min_growth < 1024) - min_growth = 1024; - if (growth < min_growth) - growth = min_growth; - - // Allocate the new m_buffer and migrate content - long new_size = (m_buffer_end - m_buffer) + growth; - char *new_buffer = (char *) malloc(new_size); - memcpy(new_buffer, m_buffer, m_write_ptr - m_buffer); - if (m_owns_buffer) - free(m_buffer); - m_owns_buffer = true; - - // Update references to the new buffer - m_write_ptr = new_buffer + (m_write_ptr - m_buffer); - m_buffer = new_buffer; - m_buffer_end = m_buffer + new_size; - } - - void - GrowRewriteRanges() - { - // By default, double the size of the array - int growth = m_rewrite_ranges_size; - - // Apply reasonable minimum and maximum sizes for growth - if (growth > 128) - growth = 128; - if (growth < 16) - growth = 16; - - // Allocate the new array and migrate content - int bytes = (m_rewrite_ranges_size + growth) * sizeof (BufferRange); - BufferRange *new_ranges = (BufferRange *) malloc (bytes); - for (int index = 0; index < m_next_substitute_index; index++) - { - new_ranges[index] = m_rewrite_ranges[index]; - } - for (int index = m_rewrite_ranges_size - 1; - index > m_next_template_arg_index; index--) - { - new_ranges[index + growth] = m_rewrite_ranges[index]; - } - if (m_owns_m_rewrite_ranges) - free(m_rewrite_ranges); - m_owns_m_rewrite_ranges = true; - - // Update references to the new array - m_rewrite_ranges = new_ranges; - m_rewrite_ranges_size += growth; - m_next_template_arg_index += growth; - } - - //---------------------------------------------------- - // Range and state management - //---------------------------------------------------- - - int - GetStartCookie() - { - return (int)(m_write_ptr - m_buffer); - } - - BufferRange - EndRange(int start_cookie) - { - return { start_cookie, (int)(m_write_ptr - (m_buffer + start_cookie)) }; - } - - void - ReorderRange(BufferRange source_range, int insertion_point_cookie) - { - // Ensure there's room the preserve the source range - if (m_write_ptr + source_range.length > m_buffer_end) - { - GrowBuffer(m_write_ptr + source_range.length - m_buffer_end); - } - - // Reorder the content - memcpy(m_write_ptr, m_buffer + source_range.offset, source_range.length); - memmove(m_buffer + insertion_point_cookie + source_range.length, - m_buffer + insertion_point_cookie, - source_range.offset - insertion_point_cookie); - memcpy(m_buffer + insertion_point_cookie, m_write_ptr, source_range.length); - - // Fix up rewritable ranges, covering both substitutions and templates - int index = 0; - while (true) - { - if (index == m_next_substitute_index) - index = m_next_template_arg_index + 1; - if (index == m_rewrite_ranges_size) - break; - - // Affected ranges are either shuffled forward when after the - // insertion but before the source, or backward when inside the - // source - int candidate_offset = m_rewrite_ranges[index].offset; - if (candidate_offset >= insertion_point_cookie) - { - if (candidate_offset < source_range.offset) - { - m_rewrite_ranges[index].offset += source_range.length; - } - else if (candidate_offset >= source_range.offset) - { - m_rewrite_ranges[index].offset -= (source_range.offset - insertion_point_cookie); - } - } - ++index; + //---------------------------------------------------- + // Grow methods + // + // Manage the storage used during demangling + //---------------------------------------------------- + + void GrowBuffer(long min_growth = 0) { + // By default, double the size of the buffer + long growth = m_buffer_end - m_buffer; + + // Avoid growing by more than 1MB at a time + if (growth > 1 << 20) + growth = 1 << 20; + + // ... but never grow by less than requested, + // or 1K, whichever is greater + if (min_growth < 1024) + min_growth = 1024; + if (growth < min_growth) + growth = min_growth; + + // Allocate the new m_buffer and migrate content + long new_size = (m_buffer_end - m_buffer) + growth; + char *new_buffer = (char *)malloc(new_size); + memcpy(new_buffer, m_buffer, m_write_ptr - m_buffer); + if (m_owns_buffer) + free(m_buffer); + m_owns_buffer = true; + + // Update references to the new buffer + m_write_ptr = new_buffer + (m_write_ptr - m_buffer); + m_buffer = new_buffer; + m_buffer_end = m_buffer + new_size; + } + + void GrowRewriteRanges() { + // By default, double the size of the array + int growth = m_rewrite_ranges_size; + + // Apply reasonable minimum and maximum sizes for growth + if (growth > 128) + growth = 128; + if (growth < 16) + growth = 16; + + // Allocate the new array and migrate content + int bytes = (m_rewrite_ranges_size + growth) * sizeof(BufferRange); + BufferRange *new_ranges = (BufferRange *)malloc(bytes); + for (int index = 0; index < m_next_substitute_index; index++) { + new_ranges[index] = m_rewrite_ranges[index]; + } + for (int index = m_rewrite_ranges_size - 1; + index > m_next_template_arg_index; index--) { + new_ranges[index + growth] = m_rewrite_ranges[index]; + } + if (m_owns_m_rewrite_ranges) + free(m_rewrite_ranges); + m_owns_m_rewrite_ranges = true; + + // Update references to the new array + m_rewrite_ranges = new_ranges; + m_rewrite_ranges_size += growth; + m_next_template_arg_index += growth; + } + + //---------------------------------------------------- + // Range and state management + //---------------------------------------------------- + + int GetStartCookie() { return (int)(m_write_ptr - m_buffer); } + + BufferRange EndRange(int start_cookie) { + return {start_cookie, (int)(m_write_ptr - (m_buffer + start_cookie))}; + } + + void ReorderRange(BufferRange source_range, int insertion_point_cookie) { + // Ensure there's room the preserve the source range + if (m_write_ptr + source_range.length > m_buffer_end) { + GrowBuffer(m_write_ptr + source_range.length - m_buffer_end); + } + + // Reorder the content + memcpy(m_write_ptr, m_buffer + source_range.offset, source_range.length); + memmove(m_buffer + insertion_point_cookie + source_range.length, + m_buffer + insertion_point_cookie, + source_range.offset - insertion_point_cookie); + memcpy(m_buffer + insertion_point_cookie, m_write_ptr, source_range.length); + + // Fix up rewritable ranges, covering both substitutions and templates + int index = 0; + while (true) { + if (index == m_next_substitute_index) + index = m_next_template_arg_index + 1; + if (index == m_rewrite_ranges_size) + break; + + // Affected ranges are either shuffled forward when after the + // insertion but before the source, or backward when inside the + // source + int candidate_offset = m_rewrite_ranges[index].offset; + if (candidate_offset >= insertion_point_cookie) { + if (candidate_offset < source_range.offset) { + m_rewrite_ranges[index].offset += source_range.length; + } else if (candidate_offset >= source_range.offset) { + m_rewrite_ranges[index].offset -= + (source_range.offset - insertion_point_cookie); } + } + ++index; } + } - void - EndSubstitution(int start_cookie) - { - if (m_next_substitute_index == m_next_template_arg_index) - GrowRewriteRanges(); + void EndSubstitution(int start_cookie) { + if (m_next_substitute_index == m_next_template_arg_index) + GrowRewriteRanges(); - int index = m_next_substitute_index++; - m_rewrite_ranges[index] = EndRange(start_cookie); + int index = m_next_substitute_index++; + m_rewrite_ranges[index] = EndRange(start_cookie); #ifdef DEBUG_SUBSTITUTIONS - printf("Saved substitution # %d = %.*s\n", index, - m_rewrite_ranges[index].length, m_buffer + start_cookie); + printf("Saved substitution # %d = %.*s\n", index, + m_rewrite_ranges[index].length, m_buffer + start_cookie); #endif - } + } - void - EndTemplateArg(int start_cookie) - { - if (m_next_substitute_index == m_next_template_arg_index) - GrowRewriteRanges(); + void EndTemplateArg(int start_cookie) { + if (m_next_substitute_index == m_next_template_arg_index) + GrowRewriteRanges(); - int index = m_next_template_arg_index--; - m_rewrite_ranges[index] = EndRange(start_cookie); + int index = m_next_template_arg_index--; + m_rewrite_ranges[index] = EndRange(start_cookie); #ifdef DEBUG_TEMPLATE_ARGS - printf("Saved template arg # %d = %.*s\n", - m_rewrite_ranges_size - index - 1, - m_rewrite_ranges[index].length, m_buffer + start_cookie); + printf("Saved template arg # %d = %.*s\n", + m_rewrite_ranges_size - index - 1, m_rewrite_ranges[index].length, + m_buffer + start_cookie); #endif - } - - void - ResetTemplateArgs() - { - //TODO: this works, but is it the right thing to do? - // Should we push/pop somehow at the call sites? - m_next_template_arg_index = m_rewrite_ranges_size - 1; - } - - //---------------------------------------------------- - // Write methods - // - // Appends content to the existing output buffer - //---------------------------------------------------- - - void - Write(char character) - { - if (m_write_ptr == m_buffer_end) - GrowBuffer(); - *m_write_ptr++ = character; - } - - void - Write(const char *content) - { - Write(content, strlen(content)); - } - - void - Write(const char *content, long content_length) - { - char *end_m_write_ptr = m_write_ptr + content_length; - if (end_m_write_ptr > m_buffer_end) - { - if (content >= m_buffer && content < m_buffer_end) - { - long offset = content - m_buffer; - GrowBuffer (end_m_write_ptr - m_buffer_end); - content = m_buffer + offset; - } - else - { - GrowBuffer (end_m_write_ptr - m_buffer_end); - } - end_m_write_ptr = m_write_ptr + content_length; - } - memcpy (m_write_ptr, content, content_length); - m_write_ptr = end_m_write_ptr; - } -#define WRITE(x) Write(x, sizeof (x) - 1) - - void - WriteTemplateStart() - { - Write('<'); - } - - void - WriteTemplateEnd() - { - // Put a space between terminal > characters when nesting templates - if (m_write_ptr != m_buffer && *(m_write_ptr - 1) == '>') - WRITE(" >"); - else Write('>'); - } - - void - WriteCommaSpace() - { - WRITE(", "); - } - - void - WriteNamespaceSeparator() - { - WRITE("::"); - } - - void - WriteStdPrefix() - { - WRITE("std::"); - } - - void - WriteQualifiers(int qualifiers, bool space_before_reference = true) - { - if (qualifiers & QualifierPointer) - Write('*'); - if (qualifiers & QualifierConst) - WRITE(" const"); - if (qualifiers & QualifierVolatile) - WRITE(" volatile"); - if (qualifiers & QualifierRestrict) - WRITE(" restrict"); - if (qualifiers & QualifierReference) - { - if (space_before_reference) - WRITE(" &"); - else Write('&'); - } - if (qualifiers & QualifierRValueReference) - { - if (space_before_reference) - WRITE(" &&"); - else WRITE("&&"); - } - } - - //---------------------------------------------------- - // Rewrite methods - // - // Write another copy of content already present - // earlier in the output buffer - //---------------------------------------------------- - - void - RewriteRange(BufferRange range) - { - Write(m_buffer + range.offset, range.length); - } - - bool - RewriteSubstitution(int index) - { - if (index < 0 || index >= m_next_substitute_index) - { + } + + void ResetTemplateArgs() { + // TODO: this works, but is it the right thing to do? + // Should we push/pop somehow at the call sites? + m_next_template_arg_index = m_rewrite_ranges_size - 1; + } + + //---------------------------------------------------- + // Write methods + // + // Appends content to the existing output buffer + //---------------------------------------------------- + + void Write(char character) { + if (m_write_ptr == m_buffer_end) + GrowBuffer(); + *m_write_ptr++ = character; + } + + void Write(const char *content) { Write(content, strlen(content)); } + + void Write(const char *content, long content_length) { + char *end_m_write_ptr = m_write_ptr + content_length; + if (end_m_write_ptr > m_buffer_end) { + if (content >= m_buffer && content < m_buffer_end) { + long offset = content - m_buffer; + GrowBuffer(end_m_write_ptr - m_buffer_end); + content = m_buffer + offset; + } else { + GrowBuffer(end_m_write_ptr - m_buffer_end); + } + end_m_write_ptr = m_write_ptr + content_length; + } + memcpy(m_write_ptr, content, content_length); + m_write_ptr = end_m_write_ptr; + } +#define WRITE(x) Write(x, sizeof(x) - 1) + + void WriteTemplateStart() { Write('<'); } + + void WriteTemplateEnd() { + // Put a space between terminal > characters when nesting templates + if (m_write_ptr != m_buffer && *(m_write_ptr - 1) == '>') + WRITE(" >"); + else + Write('>'); + } + + void WriteCommaSpace() { WRITE(", "); } + + void WriteNamespaceSeparator() { WRITE("::"); } + + void WriteStdPrefix() { WRITE("std::"); } + + void WriteQualifiers(int qualifiers, bool space_before_reference = true) { + if (qualifiers & QualifierPointer) + Write('*'); + if (qualifiers & QualifierConst) + WRITE(" const"); + if (qualifiers & QualifierVolatile) + WRITE(" volatile"); + if (qualifiers & QualifierRestrict) + WRITE(" restrict"); + if (qualifiers & QualifierReference) { + if (space_before_reference) + WRITE(" &"); + else + Write('&'); + } + if (qualifiers & QualifierRValueReference) { + if (space_before_reference) + WRITE(" &&"); + else + WRITE("&&"); + } + } + + //---------------------------------------------------- + // Rewrite methods + // + // Write another copy of content already present + // earlier in the output buffer + //---------------------------------------------------- + + void RewriteRange(BufferRange range) { + Write(m_buffer + range.offset, range.length); + } + + bool RewriteSubstitution(int index) { + if (index < 0 || index >= m_next_substitute_index) { #ifdef DEBUG_FAILURES - printf("*** Invalid substitution #%d\n", index); + printf("*** Invalid substitution #%d\n", index); #endif - return false; - } - RewriteRange(m_rewrite_ranges[index]); - return true; + return false; } + RewriteRange(m_rewrite_ranges[index]); + return true; + } - bool - RewriteTemplateArg(int template_index) - { - int index = m_rewrite_ranges_size - 1 - template_index; - if (template_index < 0 || index <= m_next_template_arg_index) - { + bool RewriteTemplateArg(int template_index) { + int index = m_rewrite_ranges_size - 1 - template_index; + if (template_index < 0 || index <= m_next_template_arg_index) { #ifdef DEBUG_FAILURES - printf("*** Invalid template arg reference #%d\n", template_index); + printf("*** Invalid template arg reference #%d\n", template_index); #endif - return false; - } - RewriteRange(m_rewrite_ranges[index]); - return true; + return false; + } + RewriteRange(m_rewrite_ranges[index]); + return true; + } + + //---------------------------------------------------- + // TryParse methods + // + // Provide information with return values instead of + // writing to the output buffer + // + // Values indicating failure guarantee that the pre- + // call m_read_ptr is unchanged + //---------------------------------------------------- + + int TryParseNumber() { + unsigned char digit = *m_read_ptr - '0'; + if (digit > 9) + return -1; + + int count = digit; + while (true) { + digit = *++m_read_ptr - '0'; + if (digit > 9) + break; + + count = count * 10 + digit; + } + return count; + } + + int TryParseBase36Number() { + char digit = *m_read_ptr; + int count; + if (digit >= '0' && digit <= '9') + count = digit -= '0'; + else if (digit >= 'A' && digit <= 'Z') + count = digit -= ('A' - 10); + else + return -1; + + while (true) { + digit = *++m_read_ptr; + if (digit >= '0' && digit <= '9') + digit -= '0'; + else if (digit >= 'A' && digit <= 'Z') + digit -= ('A' - 10); + else + break; + + count = count * 36 + digit; + } + return count; + } + + // <builtin-type> ::= v # void + // ::= w # wchar_t + // ::= b # bool + // ::= c # char + // ::= a # signed char + // ::= h # unsigned char + // ::= s # short + // ::= t # unsigned short + // ::= i # int + // ::= j # unsigned int + // ::= l # long + // ::= m # unsigned long + // ::= x # long long, __int64 + // ::= y # unsigned long long, __int64 + // ::= n # __int128 + // ::= o # unsigned __int128 + // ::= f # float + // ::= d # double + // ::= e # long double, __float80 + // ::= g # __float128 + // ::= z # ellipsis + // ::= Dd # IEEE 754r decimal floating point (64 bits) + // ::= De # IEEE 754r decimal floating point (128 bits) + // ::= Df # IEEE 754r decimal floating point (32 bits) + // ::= Dh # IEEE 754r half-precision floating point (16 bits) + // ::= Di # char32_t + // ::= Ds # char16_t + // ::= Da # auto (in dependent new-expressions) + // ::= Dn # std::nullptr_t (i.e., decltype(nullptr)) + // ::= u <source-name> # vendor extended type + + const char *TryParseBuiltinType() { + if (m_builtins_hook) + m_builtins_hook(m_read_ptr); + + switch (*m_read_ptr++) { + case 'v': + return "void"; + case 'w': + return "wchar_t"; + case 'b': + return "bool"; + case 'c': + return "char"; + case 'a': + return "signed char"; + case 'h': + return "unsigned char"; + case 's': + return "short"; + case 't': + return "unsigned short"; + case 'i': + return "int"; + case 'j': + return "unsigned int"; + case 'l': + return "long"; + case 'm': + return "unsigned long"; + case 'x': + return "long long"; + case 'y': + return "unsigned long long"; + case 'n': + return "__int128"; + case 'o': + return "unsigned __int128"; + case 'f': + return "float"; + case 'd': + return "double"; + case 'e': + return "long double"; + case 'g': + return "__float128"; + case 'z': + return "..."; + case 'D': { + switch (*m_read_ptr++) { + case 'd': + return "decimal64"; + case 'e': + return "decimal128"; + case 'f': + return "decimal32"; + case 'h': + return "decimal16"; + case 'i': + return "char32_t"; + case 's': + return "char16_t"; + case 'a': + return "auto"; + case 'c': + return "decltype(auto)"; + case 'n': + return "std::nullptr_t"; + default: + --m_read_ptr; + } + } + } + --m_read_ptr; + return nullptr; + } + + // <operator-name> + // ::= aa # && + // ::= ad # & (unary) + // ::= an # & + // ::= aN # &= + // ::= aS # = + // ::= cl # () + // ::= cm # , + // ::= co # ~ + // ::= da # delete[] + // ::= de # * (unary) + // ::= dl # delete + // ::= dv # / + // ::= dV # /= + // ::= eo # ^ + // ::= eO # ^= + // ::= eq # == + // ::= ge # >= + // ::= gt # > + // ::= ix # [] + // ::= le # <= + // ::= ls # << + // ::= lS # <<= + // ::= lt # < + // ::= mi # - + // ::= mI # -= + // ::= ml # * + // ::= mL # *= + // ::= mm # -- (postfix in <expression> context) + // ::= na # new[] + // ::= ne # != + // ::= ng # - (unary) + // ::= nt # ! + // ::= nw # new + // ::= oo # || + // ::= or # | + // ::= oR # |= + // ::= pm # ->* + // ::= pl # + + // ::= pL # += + // ::= pp # ++ (postfix in <expression> context) + // ::= ps # + (unary) + // ::= pt # -> + // ::= qu # ? + // ::= rm # % + // ::= rM # %= + // ::= rs # >> + // ::= rS # >>= + // ::= cv <type> # (cast) + // ::= v <digit> <source-name> # vendor extended + // operator + + Operator TryParseOperator() { + switch (*m_read_ptr++) { + case 'a': + switch (*m_read_ptr++) { + case 'a': + return {"&&", OperatorKind::Binary}; + case 'd': + return {"&", OperatorKind::Unary}; + case 'n': + return {"&", OperatorKind::Binary}; + case 'N': + return {"&=", OperatorKind::Binary}; + case 'S': + return {"=", OperatorKind::Binary}; + } + --m_read_ptr; + break; + case 'c': + switch (*m_read_ptr++) { + case 'l': + return {"()", OperatorKind::Other}; + case 'm': + return {",", OperatorKind::Other}; + case 'o': + return {"~", OperatorKind::Unary}; + case 'v': + return {nullptr, OperatorKind::ConversionOperator}; + } + --m_read_ptr; + break; + case 'd': + switch (*m_read_ptr++) { + case 'a': + return {" delete[]", OperatorKind::Other}; + case 'e': + return {"*", OperatorKind::Unary}; + case 'l': + return {" delete", OperatorKind::Other}; + case 'v': + return {"/", OperatorKind::Binary}; + case 'V': + return {"/=", OperatorKind::Binary}; + } + --m_read_ptr; + break; + case 'e': + switch (*m_read_ptr++) { + case 'o': + return {"^", OperatorKind::Binary}; + case 'O': + return {"^=", OperatorKind::Binary}; + case 'q': + return {"==", OperatorKind::Binary}; + } + --m_read_ptr; + break; + case 'g': + switch (*m_read_ptr++) { + case 'e': + return {">=", OperatorKind::Binary}; + case 't': + return {">", OperatorKind::Binary}; + } + --m_read_ptr; + break; + case 'i': + switch (*m_read_ptr++) { + case 'x': + return {"[]", OperatorKind::Other}; + } + --m_read_ptr; + break; + case 'l': + switch (*m_read_ptr++) { + case 'e': + return {"<=", OperatorKind::Binary}; + case 's': + return {"<<", OperatorKind::Binary}; + case 'S': + return {"<<=", OperatorKind::Binary}; + case 't': + return {"<", OperatorKind::Binary}; + // case 'i': return { "?", OperatorKind::Binary }; + } + --m_read_ptr; + break; + case 'm': + switch (*m_read_ptr++) { + case 'i': + return {"-", OperatorKind::Binary}; + case 'I': + return {"-=", OperatorKind::Binary}; + case 'l': + return {"*", OperatorKind::Binary}; + case 'L': + return {"*=", OperatorKind::Binary}; + case 'm': + return {"--", OperatorKind::Postfix}; + } + --m_read_ptr; + break; + case 'n': + switch (*m_read_ptr++) { + case 'a': + return {" new[]", OperatorKind::Other}; + case 'e': + return {"!=", OperatorKind::Binary}; + case 'g': + return {"-", OperatorKind::Unary}; + case 't': + return {"!", OperatorKind::Unary}; + case 'w': + return {" new", OperatorKind::Other}; + } + --m_read_ptr; + break; + case 'o': + switch (*m_read_ptr++) { + case 'o': + return {"||", OperatorKind::Binary}; + case 'r': + return {"|", OperatorKind::Binary}; + case 'R': + return {"|=", OperatorKind::Binary}; + } + --m_read_ptr; + break; + case 'p': + switch (*m_read_ptr++) { + case 'm': + return {"->*", OperatorKind::Binary}; + case 's': + return {"+", OperatorKind::Unary}; + case 'l': + return {"+", OperatorKind::Binary}; + case 'L': + return {"+=", OperatorKind::Binary}; + case 'p': + return {"++", OperatorKind::Postfix}; + case 't': + return {"->", OperatorKind::Binary}; + } + --m_read_ptr; + break; + case 'q': + switch (*m_read_ptr++) { + case 'u': + return {"?", OperatorKind::Ternary}; + } + --m_read_ptr; + break; + case 'r': + switch (*m_read_ptr++) { + case 'm': + return {"%", OperatorKind::Binary}; + case 'M': + return {"%=", OperatorKind::Binary}; + case 's': + return {">>", OperatorKind::Binary}; + case 'S': + return {">=", OperatorKind::Binary}; + } + --m_read_ptr; + break; + case 'v': + char digit = *m_read_ptr; + if (digit >= '0' && digit <= '9') { + m_read_ptr++; + return {nullptr, OperatorKind::Vendor}; + } + --m_read_ptr; + break; + } + --m_read_ptr; + return {nullptr, OperatorKind::NoMatch}; + } + + // <CV-qualifiers> ::= [r] [V] [K] + // <ref-qualifier> ::= R # & ref-qualifier + // <ref-qualifier> ::= O # && ref-qualifier + + int TryParseQualifiers(bool allow_cv, bool allow_ro) { + int qualifiers = QualifierNone; + char next = *m_read_ptr; + if (allow_cv) { + if (next == 'r') // restrict + { + qualifiers |= QualifierRestrict; + next = *++m_read_ptr; + } + if (next == 'V') // volatile + { + qualifiers |= QualifierVolatile; + next = *++m_read_ptr; + } + if (next == 'K') // const + { + qualifiers |= QualifierConst; + next = *++m_read_ptr; + } + } + if (allow_ro) { + if (next == 'R') { + ++m_read_ptr; + qualifiers |= QualifierReference; + } else if (next == 'O') { + ++m_read_ptr; + qualifiers |= QualifierRValueReference; + } } + return qualifiers; + } - //---------------------------------------------------- - // TryParse methods - // - // Provide information with return values instead of - // writing to the output buffer - // - // Values indicating failure guarantee that the pre- - // call m_read_ptr is unchanged - //---------------------------------------------------- - - int - TryParseNumber() - { - unsigned char digit = *m_read_ptr - '0'; - if (digit > 9) - return -1; - - int count = digit; - while (true) - { - digit = *++m_read_ptr - '0'; - if (digit > 9) - break; + // <discriminator> := _ <non-negative number> # when number < 10 + // := __ <non-negative number> _ # when number >= 10 + // extension := decimal-digit+ - count = count * 10 + digit; - } - return count; - } + int TryParseDiscriminator() { + const char *discriminator_start = m_read_ptr; - int - TryParseBase36Number() - { - char digit = *m_read_ptr; - int count; - if (digit >= '0' && digit <= '9') - count = digit -= '0'; - else if (digit >= 'A' && digit <= 'Z') - count = digit -= ('A' - 10); - else return -1; + // Test the extension first, since it's what Clang uses + int discriminator_value = TryParseNumber(); + if (discriminator_value != -1) + return discriminator_value; - while (true) - { - digit = *++m_read_ptr; - if (digit >= '0' && digit <= '9') - digit -= '0'; - else if (digit >= 'A' && digit <= 'Z') - digit -= ('A' - 10); - else break; - - count = count * 36 + digit; + char next = *m_read_ptr; + if (next == '_') { + next = *++m_read_ptr; + if (next == '_') { + ++m_read_ptr; + discriminator_value = TryParseNumber(); + if (discriminator_value != -1 && *m_read_ptr++ != '_') { + return discriminator_value; } - return count; - } + } else if (next >= '0' && next <= '9') { + ++m_read_ptr; + return next - '0'; + } + } + + // Not a valid discriminator + m_read_ptr = discriminator_start; + return -1; + } + + //---------------------------------------------------- + // Parse methods + // + // Consume input starting from m_read_ptr and produce + // buffered output at m_write_ptr + // + // Failures return false and may leave m_read_ptr in an + // indeterminate state + //---------------------------------------------------- + + bool Parse(char character) { + if (*m_read_ptr++ == character) + return true; +#ifdef DEBUG_FAILURES + printf("*** Expected '%c'\n", character); +#endif + return false; + } - // <builtin-type> ::= v # void - // ::= w # wchar_t - // ::= b # bool - // ::= c # char - // ::= a # signed char - // ::= h # unsigned char - // ::= s # short - // ::= t # unsigned short - // ::= i # int - // ::= j # unsigned int - // ::= l # long - // ::= m # unsigned long - // ::= x # long long, __int64 - // ::= y # unsigned long long, __int64 - // ::= n # __int128 - // ::= o # unsigned __int128 - // ::= f # float - // ::= d # double - // ::= e # long double, __float80 - // ::= g # __float128 - // ::= z # ellipsis - // ::= Dd # IEEE 754r decimal floating point (64 bits) - // ::= De # IEEE 754r decimal floating point (128 bits) - // ::= Df # IEEE 754r decimal floating point (32 bits) - // ::= Dh # IEEE 754r half-precision floating point (16 bits) - // ::= Di # char32_t - // ::= Ds # char16_t - // ::= Da # auto (in dependent new-expressions) - // ::= Dn # std::nullptr_t (i.e., decltype(nullptr)) - // ::= u <source-name> # vendor extended type - - const char * - TryParseBuiltinType() - { - switch (*m_read_ptr++) - { - case 'v': return "void"; - case 'w': return "wchar_t"; - case 'b': return "bool"; - case 'c': return "char"; - case 'a': return "signed char"; - case 'h': return "unsigned char"; - case 's': return "short"; - case 't': return "unsigned short"; - case 'i': return "int"; - case 'j': return "unsigned int"; - case 'l': return "long"; - case 'm': return "unsigned long"; - case 'x': return "long long"; - case 'y': return "unsigned long long"; - case 'n': return "__int128"; - case 'o': return "unsigned __int128"; - case 'f': return "float"; - case 'd': return "double"; - case 'e': return "long double"; - case 'g': return "__float128"; - case 'z': return "..."; - case 'D': - { - switch (*m_read_ptr++) - { - case 'd': return "decimal64"; - case 'e': return "decimal128"; - case 'f': return "decimal32"; - case 'h': return "decimal16"; - case 'i': return "char32_t"; - case 's': return "char16_t"; - case 'a': return "auto"; - case 'c': return "decltype(auto)"; - case 'n': return "std::nullptr_t"; - default: - --m_read_ptr; - } - } - } - --m_read_ptr; - return nullptr; - } + // <number> ::= [n] <non-negative decimal integer> - // <operator-name> - // ::= aa # && - // ::= ad # & (unary) - // ::= an # & - // ::= aN # &= - // ::= aS # = - // ::= cl # () - // ::= cm # , - // ::= co # ~ - // ::= da # delete[] - // ::= de # * (unary) - // ::= dl # delete - // ::= dv # / - // ::= dV # /= - // ::= eo # ^ - // ::= eO # ^= - // ::= eq # == - // ::= ge # >= - // ::= gt # > - // ::= ix # [] - // ::= le # <= - // ::= ls # << - // ::= lS # <<= - // ::= lt # < - // ::= mi # - - // ::= mI # -= - // ::= ml # * - // ::= mL # *= - // ::= mm # -- (postfix in <expression> context) - // ::= na # new[] - // ::= ne # != - // ::= ng # - (unary) - // ::= nt # ! - // ::= nw # new - // ::= oo # || - // ::= or # | - // ::= oR # |= - // ::= pm # ->* - // ::= pl # + - // ::= pL # += - // ::= pp # ++ (postfix in <expression> context) - // ::= ps # + (unary) - // ::= pt # -> - // ::= qu # ? - // ::= rm # % - // ::= rM # %= - // ::= rs # >> - // ::= rS # >>= - // ::= cv <type> # (cast) - // ::= v <digit> <source-name> # vendor extended operator - - Operator - TryParseOperator() - { - switch (*m_read_ptr++) - { - case 'a': - switch (*m_read_ptr++) - { - case 'a': return { "&&", OperatorKind::Binary }; - case 'd': return { "&", OperatorKind::Unary }; - case 'n': return { "&", OperatorKind::Binary }; - case 'N': return { "&=", OperatorKind::Binary }; - case 'S': return { "=", OperatorKind::Binary }; - } - --m_read_ptr; - break; - case 'c': - switch (*m_read_ptr++) - { - case 'l': return { "()", OperatorKind::Other }; - case 'm': return { ",", OperatorKind::Other }; - case 'o': return { "~", OperatorKind::Unary }; - case 'v': return { nullptr, OperatorKind::ConversionOperator }; - } - --m_read_ptr; - break; - case 'd': - switch (*m_read_ptr++) - { - case 'a': return { " delete[]", OperatorKind::Other }; - case 'e': return { "*", OperatorKind::Unary }; - case 'l': return { " delete", OperatorKind::Other }; - case 'v': return { "/", OperatorKind::Binary }; - case 'V': return { "/=", OperatorKind::Binary }; - } - --m_read_ptr; - break; - case 'e': - switch (*m_read_ptr++) - { - case 'o': return { "^", OperatorKind::Binary }; - case 'O': return { "^=", OperatorKind::Binary }; - case 'q': return { "==", OperatorKind::Binary }; - } - --m_read_ptr; - break; - case 'g': - switch (*m_read_ptr++) - { - case 'e': return { ">=", OperatorKind::Binary }; - case 't': return { ">", OperatorKind::Binary }; - } - --m_read_ptr; - break; - case 'i': - switch (*m_read_ptr++) - { - case 'x': return { "[]", OperatorKind::Other }; - } - --m_read_ptr; - break; - case 'l': - switch (*m_read_ptr++) - { - case 'e': return { "<=", OperatorKind::Binary }; - case 's': return { "<<", OperatorKind::Binary }; - case 'S': return { "<<=", OperatorKind::Binary }; - case 't': return { "<", OperatorKind::Binary }; - // case 'i': return { "?", OperatorKind::Binary }; - } - --m_read_ptr; - break; - case 'm': - switch (*m_read_ptr++) - { - case 'i': return { "-", OperatorKind::Binary }; - case 'I': return { "-=", OperatorKind::Binary }; - case 'l': return { "*", OperatorKind::Binary }; - case 'L': return { "*=", OperatorKind::Binary }; - case 'm': return { "--", OperatorKind::Postfix }; - } - --m_read_ptr; - break; - case 'n': - switch (*m_read_ptr++) - { - case 'a': return { " new[]", OperatorKind::Other }; - case 'e': return { "!=", OperatorKind::Binary }; - case 'g': return { "-", OperatorKind::Unary }; - case 't': return { "!", OperatorKind::Unary }; - case 'w': return { " new", OperatorKind::Other }; - } - --m_read_ptr; - break; - case 'o': - switch (*m_read_ptr++) - { - case 'o': return { "||", OperatorKind::Binary }; - case 'r': return { "|", OperatorKind::Binary }; - case 'R': return { "|=", OperatorKind::Binary }; - } - --m_read_ptr; - break; - case 'p': - switch (*m_read_ptr++) - { - case 'm': return { "->*", OperatorKind::Binary }; - case 's': return { "+", OperatorKind::Unary }; - case 'l': return { "+", OperatorKind::Binary }; - case 'L': return { "+=", OperatorKind::Binary }; - case 'p': return { "++", OperatorKind::Postfix }; - case 't': return { "->", OperatorKind::Binary }; - } - --m_read_ptr; - break; - case 'q': - switch (*m_read_ptr++) - { - case 'u': return { "?", OperatorKind::Ternary }; - } - --m_read_ptr; - break; - case 'r': - switch (*m_read_ptr++) - { - case 'm': return { "%", OperatorKind::Binary }; - case 'M': return { "%=", OperatorKind::Binary }; - case 's': return { ">>", OperatorKind::Binary }; - case 'S': return { ">=", OperatorKind::Binary }; - } - --m_read_ptr; - break; - case 'v': - char digit = *m_read_ptr; - if (digit >= '0' && digit <= '9') - { - m_read_ptr++; - return { nullptr, OperatorKind::Vendor }; - } - --m_read_ptr; - break; - } - --m_read_ptr; - return { nullptr, OperatorKind::NoMatch }; + bool ParseNumber(bool allow_negative = false) { + if (allow_negative && *m_read_ptr == 'n') { + Write('-'); + ++m_read_ptr; } - - // <CV-qualifiers> ::= [r] [V] [K] - // <ref-qualifier> ::= R # & ref-qualifier - // <ref-qualifier> ::= O # && ref-qualifier - - int - TryParseQualifiers(bool allow_cv, bool allow_ro) - { - int qualifiers = QualifierNone; - char next = *m_read_ptr; - if (allow_cv) - { - if (next == 'r') // restrict - { - qualifiers |= QualifierRestrict; - next = *++m_read_ptr; - } - if (next == 'V') // volatile - { - qualifiers |= QualifierVolatile; - next = *++m_read_ptr; - } - if (next == 'K') // const - { - qualifiers |= QualifierConst; - next = *++m_read_ptr; - } - } - if (allow_ro) - { - if (next == 'R') - { - ++m_read_ptr; - qualifiers |= QualifierReference; - } - else if (next =='O') - { - ++m_read_ptr; - qualifiers |= QualifierRValueReference; - } - } - return qualifiers; + const char *before_digits = m_read_ptr; + while (true) { + unsigned char digit = *m_read_ptr - '0'; + if (digit > 9) + break; + ++m_read_ptr; } - - // <discriminator> := _ <non-negative number> # when number < 10 - // := __ <non-negative number> _ # when number >= 10 - // extension := decimal-digit+ - - int - TryParseDiscriminator() - { - const char *discriminator_start = m_read_ptr; - - // Test the extension first, since it's what Clang uses - int discriminator_value = TryParseNumber(); - if (discriminator_value != -1) - return discriminator_value; - - char next = *m_read_ptr; - if (next == '_') - { - next = *++m_read_ptr; - if (next == '_') - { - ++m_read_ptr; - discriminator_value = TryParseNumber(); - if (discriminator_value != -1 && *m_read_ptr++ != '_') - { - return discriminator_value; - } - } - else if (next >= '0' && next <= '9') - { - ++m_read_ptr; - return next - '0'; - } - } - - // Not a valid discriminator - m_read_ptr = discriminator_start; - return -1; + if (int digit_count = (int)(m_read_ptr - before_digits)) { + Write(before_digits, digit_count); + return true; } - - //---------------------------------------------------- - // Parse methods - // - // Consume input starting from m_read_ptr and produce - // buffered output at m_write_ptr - // - // Failures return false and may leave m_read_ptr in an - // indeterminate state - //---------------------------------------------------- - - bool - Parse(char character) - { - if (*m_read_ptr++ == character) - return true; #ifdef DEBUG_FAILURES - printf("*** Expected '%c'\n", character); + printf("*** Expected number\n"); #endif - return false; - } - - // <number> ::= [n] <non-negative decimal integer> - - bool - ParseNumber(bool allow_negative = false) - { - if (allow_negative && *m_read_ptr == 'n') - { - Write('-'); - ++m_read_ptr; - } - const char *before_digits = m_read_ptr; - while (true) - { - unsigned char digit = *m_read_ptr - '0'; - if (digit > 9) - break; - ++m_read_ptr; - } - if (int digit_count = (int)(m_read_ptr - before_digits)) - { - Write(before_digits, digit_count); - return true; - } + return false; + } + + // <substitution> ::= S <seq-id> _ + // ::= S_ + // <substitution> ::= Sa # ::std::allocator + // <substitution> ::= Sb # ::std::basic_string + // <substitution> ::= Ss # ::std::basic_string < char, + // ::std::char_traits<char>, + // ::std::allocator<char> > + // <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> + // > + // <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> + // > + // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> + // > + + bool ParseSubstitution() { + const char *substitution; + switch (*m_read_ptr) { + case 'a': + substitution = "std::allocator"; + break; + case 'b': + substitution = "std::basic_string"; + break; + case 's': + substitution = "std::string"; + break; + case 'i': + substitution = "std::istream"; + break; + case 'o': + substitution = "std::ostream"; + break; + case 'd': + substitution = "std::iostream"; + break; + default: + // A failed attempt to parse a number will return -1 which turns out to be + // perfect here as S_ is the first substitution, S0_ the next and so forth + int substitution_index = TryParseBase36Number(); + if (*m_read_ptr++ != '_') { #ifdef DEBUG_FAILURES - printf("*** Expected number\n"); + printf("*** Expected terminal _ in substitution\n"); #endif return false; + } + return RewriteSubstitution(substitution_index + 1); } + Write(substitution); + ++m_read_ptr; + return true; + } - // <substitution> ::= S <seq-id> _ - // ::= S_ - // <substitution> ::= Sa # ::std::allocator - // <substitution> ::= Sb # ::std::basic_string - // <substitution> ::= Ss # ::std::basic_string < char, - // ::std::char_traits<char>, - // ::std::allocator<char> > - // <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> > - // <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> > - // <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> > - - bool - ParseSubstitution() - { - const char *substitution; - switch (*m_read_ptr) - { - case 'a': substitution = "std::allocator"; break; - case 'b': substitution = "std::basic_string"; break; - case 's': substitution = "std::string"; break; - case 'i': substitution = "std::istream"; break; - case 'o': substitution = "std::ostream"; break; - case 'd': substitution = "std::iostream"; break; - default: - // A failed attempt to parse a number will return -1 which turns out to be - // perfect here as S_ is the first substitution, S0_ the next and so forth - int substitution_index = TryParseBase36Number(); - if (*m_read_ptr++ != '_') - { -#ifdef DEBUG_FAILURES - printf("*** Expected terminal _ in substitution\n"); -#endif - return false; - } - return RewriteSubstitution (substitution_index + 1); - } - Write(substitution); - ++m_read_ptr; - return true; - } + // <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E + // + // <bare-function-type> ::= <signature type>+ # types are possible return + // type, then parameter types - // <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E - // - // <bare-function-type> ::= <signature type>+ # types are possible return type, then parameter types - - bool - ParseFunctionType (int inner_qualifiers = QualifierNone) - { + bool ParseFunctionType(int inner_qualifiers = QualifierNone) { #ifdef DEBUG_FAILURES - printf("*** Function types not supported\n"); + printf("*** Function types not supported\n"); #endif - //TODO: first steps toward an implementation follow, but they're far - // from complete. Function types tend to bracket other types eg: - // int (*)() when used as the type for "name" becomes int (*name)(). - // This makes substitution et al ... interesting. - return false; + // TODO: first steps toward an implementation follow, but they're far + // from complete. Function types tend to bracket other types eg: + // int (*)() when used as the type for "name" becomes int (*name)(). + // This makes substitution et al ... interesting. + return false; -#if 0 // TODO +#if 0 // TODO if (*m_read_ptr == 'Y') ++m_read_ptr; @@ -1083,28 +1058,26 @@ private: ReorderRange (EndRange (qualifier_start_cookie), insert_cookie); } return true; -#endif // TODO - } +#endif // TODO + } - // <array-type> ::= A <positive dimension number> _ <element type> - // ::= A [<dimension expression>] _ <element type> + // <array-type> ::= A <positive dimension number> _ <element type> + // ::= A [<dimension expression>] _ <element type> - bool - ParseArrayType(int qualifiers = QualifierNone) - { + bool ParseArrayType(int qualifiers = QualifierNone) { #ifdef DEBUG_FAILURES - printf("*** Array type unsupported\n"); + printf("*** Array type unsupported\n"); #endif - //TODO: We fail horribly when recalling these as substitutions or - // templates and trying to constify them eg: - // _ZN4llvm2cl5applyIA28_cNS0_3optIbLb0ENS0_6parserIbEEEEEEvRKT_PT0_ - // - //TODO: Chances are we don't do any better with references and pointers - // that should be type (&) [] instead of type & [] + // TODO: We fail horribly when recalling these as substitutions or + // templates and trying to constify them eg: + // _ZN4llvm2cl5applyIA28_cNS0_3optIbLb0ENS0_6parserIbEEEEEEvRKT_PT0_ + // + // TODO: Chances are we don't do any better with references and pointers + // that should be type (&) [] instead of type & [] - return false; + return false; -#if 0 // TODO +#if 0 // TODO if (*m_read_ptr == '_') { ++m_read_ptr; @@ -1152,589 +1125,593 @@ private: return true; } #endif // TODO - } - - // <pointer-to-member-type> ::= M <class type> <member type> - - //TODO: Determine how to handle pointers to function members correctly, - // currently not an issue because we don't have function types at all... - bool - ParsePointerToMemberType() - { - int insertion_cookie = GetStartCookie(); - Write(' '); - if (!ParseType()) - return false; - WRITE("::*"); - - int type_cookie = GetStartCookie(); - if (!ParseType()) - return false; - ReorderRange (EndRange (type_cookie), insertion_cookie); - return true; - } - - // <template-param> ::= T_ # first template parameter - // ::= T <parameter-2 non-negative number> _ - - bool - ParseTemplateParam() - { - int count = TryParseNumber(); - if (!Parse('_')) - return false; - - // When no number is present we get -1, which is convenient since - // T_ is the zeroth element T0_ is element 1, and so on - return RewriteTemplateArg (count + 1); - } - - // <type> ::= <builtin-type> - // ::= <function-type> - // ::= <class-enum-type> - // ::= <array-type> - // ::= <pointer-to-member-type> - // ::= <template-param> - // ::= <template-template-param> <template-args> - // ::= <decltype> - // ::= <substitution> - // ::= <CV-qualifiers> <type> - // ::= P <type> # pointer-to - // ::= R <type> # reference-to - // ::= O <type> # rvalue reference-to (C++0x) - // ::= C <type> # complex pair (C 2000) - // ::= G <type> # imaginary (C 2000) - // ::= Dp <type> # pack expansion (C++0x) - // ::= U <source-name> <type> # vendor extended type qualifier - // extension := U <objc-name> <objc-type> # objc-type<identifier> - // extension := <vector-type> # <vector-type> starts with Dv - - // <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k1 - // <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name> - - bool - ParseType() - { + } + + // <pointer-to-member-type> ::= M <class type> <member type> + + // TODO: Determine how to handle pointers to function members correctly, + // currently not an issue because we don't have function types at all... + bool ParsePointerToMemberType() { + int insertion_cookie = GetStartCookie(); + Write(' '); + if (!ParseType()) + return false; + WRITE("::*"); + + int type_cookie = GetStartCookie(); + if (!ParseType()) + return false; + ReorderRange(EndRange(type_cookie), insertion_cookie); + return true; + } + + // <template-param> ::= T_ # first template parameter + // ::= T <parameter-2 non-negative number> _ + + bool ParseTemplateParam() { + int count = TryParseNumber(); + if (!Parse('_')) + return false; + + // When no number is present we get -1, which is convenient since + // T_ is the zeroth element T0_ is element 1, and so on + return RewriteTemplateArg(count + 1); + } + + // <vector-type> + // Dv <dimension number> _ <vector type> + bool TryParseVectorType() { + const int dimension = TryParseNumber(); + if (dimension == -1) + return false; + + if (*m_read_ptr++ != '_') + return false; + + char vec_dimens[32] = {'\0'}; + ::snprintf(vec_dimens, sizeof vec_dimens - 1, " __vector(%d)", dimension); + ParseType(); + Write(vec_dimens); + return true; + } + + // <type> ::= <builtin-type> + // ::= <function-type> + // ::= <class-enum-type> + // ::= <array-type> + // ::= <pointer-to-member-type> + // ::= <template-param> + // ::= <template-template-param> <template-args> + // ::= <decltype> + // ::= <substitution> + // ::= <CV-qualifiers> <type> + // ::= P <type> # pointer-to + // ::= R <type> # reference-to + // ::= O <type> # rvalue reference-to (C++0x) + // ::= C <type> # complex pair (C 2000) + // ::= G <type> # imaginary (C 2000) + // ::= Dp <type> # pack expansion (C++0x) + // ::= U <source-name> <type> # vendor extended type qualifier + // extension := U <objc-name> <objc-type> # objc-type<identifier> + // extension := <vector-type> # <vector-type> starts with Dv + + // <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + + // <number of digits in k1> + k1 + // <objc-type> := <source-name> # PU<11+>objcproto 11objc_object<source-name> + // 11objc_object -> id<source-name> + + bool ParseType() { #ifdef DEBUG_FAILURES - const char *failed_type = m_read_ptr; + const char *failed_type = m_read_ptr; #endif - int type_start_cookie = GetStartCookie(); - bool suppress_substitution = false; - - int qualifiers = TryParseQualifiers (true, false); - switch (*m_read_ptr) - { - case 'D': - ++m_read_ptr; - switch (*m_read_ptr++) - { - case 'p': - if (!ParseType()) - return false; - break; - case 'T': - case 't': - case 'v': - default: + int type_start_cookie = GetStartCookie(); + bool suppress_substitution = false; + + int qualifiers = TryParseQualifiers(true, false); + switch (*m_read_ptr) { + case 'D': + ++m_read_ptr; + switch (*m_read_ptr++) { + case 'p': + if (!ParseType()) + return false; + break; + case 'v': + if (!TryParseVectorType()) + return false; + break; + case 'T': + case 't': + default: #ifdef DEBUG_FAILURES - printf("*** Unsupported type: %.3s\n", failed_type); + printf("*** Unsupported type: %.3s\n", failed_type); #endif - return false; - } - break; - case 'T': - ++m_read_ptr; - if (!ParseTemplateParam()) - return false; - break; - case 'M': - ++m_read_ptr; - if (!ParsePointerToMemberType()) - return false; - break; - case 'A': - ++m_read_ptr; - if (!ParseArrayType()) - return false; - break; - case 'F': - ++m_read_ptr; - if (!ParseFunctionType()) - return false; - break; - case 'S': - if (*++m_read_ptr == 't') - { - ++m_read_ptr; - WriteStdPrefix(); - if (!ParseName()) - return false; - } - else - { - suppress_substitution = true; - if (!ParseSubstitution()) - return false; - } - break; - case 'P': - { - switch (*++m_read_ptr) - { - case 'F': - ++m_read_ptr; - if (!ParseFunctionType(QualifierPointer)) - return false; - break; - default: - if (!ParseType()) - return false; - Write('*'); - break; - } - break; - } - case 'R': - { - ++m_read_ptr; - if (!ParseType()) - return false; - Write('&'); - break; - } - case 'O': - { - ++m_read_ptr; - if (!ParseType()) - return false; - Write('&'); - Write('&'); - break; - } - case 'C': - case 'G': - case 'U': + return false; + } + break; + case 'T': + ++m_read_ptr; + if (!ParseTemplateParam()) + return false; + break; + case 'M': + ++m_read_ptr; + if (!ParsePointerToMemberType()) + return false; + break; + case 'A': + ++m_read_ptr; + if (!ParseArrayType()) + return false; + break; + case 'F': + ++m_read_ptr; + if (!ParseFunctionType()) + return false; + break; + case 'S': + if (*++m_read_ptr == 't') { + ++m_read_ptr; + WriteStdPrefix(); + if (!ParseName()) + return false; + } else { + suppress_substitution = true; + if (!ParseSubstitution()) + return false; + } + break; + case 'P': { + switch (*++m_read_ptr) { + case 'F': + ++m_read_ptr; + if (!ParseFunctionType(QualifierPointer)) + return false; + break; + default: + if (!ParseType()) + return false; + Write('*'); + break; + } + break; + } + case 'R': { + ++m_read_ptr; + if (!ParseType()) + return false; + Write('&'); + break; + } + case 'O': { + ++m_read_ptr; + if (!ParseType()) + return false; + Write('&'); + Write('&'); + break; + } + case 'C': + case 'G': + case 'U': #ifdef DEBUG_FAILURES - printf("*** Unsupported type: %.3s\n", failed_type); + printf("*** Unsupported type: %.3s\n", failed_type); #endif - return false; - // Test for common cases to avoid TryParseBuiltinType() overhead - case 'N': - case 'Z': - case 'L': - if (!ParseName()) - return false; - break; - default: - if (const char *builtin = TryParseBuiltinType()) - { - Write(builtin); - suppress_substitution = true; - } - else - { - if (!ParseName()) - return false; - } - break; - } - - // Allow base substitutions to be suppressed, but always record - // substitutions for the qualified variant - if (!suppress_substitution) - EndSubstitution(type_start_cookie); - if (qualifiers) - { - WriteQualifiers(qualifiers, false); - EndSubstitution(type_start_cookie); - } - return true; + return false; + // Test for common cases to avoid TryParseBuiltinType() overhead + case 'N': + case 'Z': + case 'L': + if (!ParseName()) + return false; + break; + default: + if (const char *builtin = TryParseBuiltinType()) { + Write(builtin); + suppress_substitution = true; + } else { + if (!ParseName()) + return false; + } + break; + } + + // Allow base substitutions to be suppressed, but always record + // substitutions for the qualified variant + if (!suppress_substitution) + EndSubstitution(type_start_cookie); + if (qualifiers) { + WriteQualifiers(qualifiers, false); + EndSubstitution(type_start_cookie); + } + return true; + } + + // <unnamed-type-name> ::= Ut [ <nonnegative number> ] _ + // ::= <closure-type-name> + // + // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ + // + // <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda + // has no parameters + + bool ParseUnnamedTypeName(NameState &name_state) { + switch (*m_read_ptr++) { + case 't': { + int cookie = GetStartCookie(); + WRITE("'unnamed"); + const char *before_digits = m_read_ptr; + if (TryParseNumber() != -1) + Write(before_digits, m_read_ptr - before_digits); + if (!Parse('_')) + return false; + Write('\''); + name_state.last_name_range = EndRange(cookie); + return true; + } + case 'b': { + int cookie = GetStartCookie(); + WRITE("'block"); + const char *before_digits = m_read_ptr; + if (TryParseNumber() != -1) + Write(before_digits, m_read_ptr - before_digits); + if (!Parse('_')) + return false; + Write('\''); + name_state.last_name_range = EndRange(cookie); + return true; } - - // <unnamed-type-name> ::= Ut [ <nonnegative number> ] _ - // ::= <closure-type-name> - // - // <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ - // - // <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters - - bool - ParseUnnamedTypeName(NameState & name_state) - { - switch (*m_read_ptr++) - { - case 't': - { - int cookie = GetStartCookie(); - WRITE("'unnamed"); - const char *before_digits = m_read_ptr; - if (TryParseNumber() != -1) Write (before_digits, - m_read_ptr - before_digits); - if (!Parse('_')) - return false; - Write('\''); - name_state.last_name_range = EndRange (cookie); - return true; - } - case 'b': - { - int cookie = GetStartCookie(); - WRITE("'block"); - const char *before_digits = m_read_ptr; - if (TryParseNumber() != -1) Write (before_digits, - m_read_ptr - before_digits); - if (!Parse('_')) - return false; - Write('\''); - name_state.last_name_range = EndRange (cookie); - return true; - } - case 'l': + case 'l': #ifdef DEBUG_FAILURES - printf("*** Lambda type names unsupported\n"); + printf("*** Lambda type names unsupported\n"); #endif - return false; - } + return false; + } #ifdef DEBUG_FAILURES - printf("*** Unknown unnamed type %.3s\n", m_read_ptr - 2); + printf("*** Unknown unnamed type %.3s\n", m_read_ptr - 2); #endif - return false; - } + return false; + } - // <ctor-dtor-name> ::= C1 # complete object constructor - // ::= C2 # base object constructor - // ::= C3 # complete object allocating constructor + // <ctor-dtor-name> ::= C1 # complete object constructor + // ::= C2 # base object constructor + // ::= C3 # complete object allocating constructor - bool - ParseCtor(NameState & name_state) - { - char next = *m_read_ptr; - if (next == '1' || next == '2' || next == '3' || next == '5') - { - RewriteRange (name_state.last_name_range); - name_state.has_no_return_type = true; - ++m_read_ptr; - return true; - } + bool ParseCtor(NameState &name_state) { + char next = *m_read_ptr; + if (next == '1' || next == '2' || next == '3' || next == '5') { + RewriteRange(name_state.last_name_range); + name_state.has_no_return_type = true; + ++m_read_ptr; + return true; + } #ifdef DEBUG_FAILURES - printf("*** Broken constructor\n"); + printf("*** Broken constructor\n"); #endif - return false; + return false; + } + + // <ctor-dtor-name> ::= D0 # deleting destructor + // ::= D1 # complete object destructor + // ::= D2 # base object destructor + + bool ParseDtor(NameState &name_state) { + char next = *m_read_ptr; + if (next == '0' || next == '1' || next == '2' || next == '5') { + Write('~'); + RewriteRange(name_state.last_name_range); + name_state.has_no_return_type = true; + ++m_read_ptr; + return true; } - - // <ctor-dtor-name> ::= D0 # deleting destructor - // ::= D1 # complete object destructor - // ::= D2 # base object destructor - - bool - ParseDtor(NameState & name_state) - { - char next = *m_read_ptr; - if (next == '0' || next == '1' || next == '2' || next == '5') - { - Write('~'); - RewriteRange(name_state.last_name_range); - name_state.has_no_return_type = true; - ++m_read_ptr; - return true; - } #ifdef DEBUG_FAILURES - printf("*** Broken destructor\n"); + printf("*** Broken destructor\n"); #endif - return false; - } + return false; + } - // See TryParseOperator() + // See TryParseOperator() - bool - ParseOperatorName(NameState & name_state) - { + bool ParseOperatorName(NameState &name_state) { #ifdef DEBUG_FAILURES - const char *operator_ptr = m_read_ptr; + const char *operator_ptr = m_read_ptr; #endif - Operator parsed_operator = TryParseOperator(); - if (parsed_operator.name) - { - WRITE("operator"); - Write(parsed_operator.name); - return true; - } - - // Handle special operators - switch (parsed_operator.kind) - { - case OperatorKind::Vendor: - WRITE("operator "); - return ParseSourceName(); - case OperatorKind::ConversionOperator: - ResetTemplateArgs(); - name_state.has_no_return_type = true; - WRITE("operator "); - return ParseType(); - default: + Operator parsed_operator = TryParseOperator(); + if (parsed_operator.name) { + WRITE("operator"); + Write(parsed_operator.name); + return true; + } + + // Handle special operators + switch (parsed_operator.kind) { + case OperatorKind::Vendor: + WRITE("operator "); + return ParseSourceName(); + case OperatorKind::ConversionOperator: + ResetTemplateArgs(); + name_state.has_no_return_type = true; + WRITE("operator "); + return ParseType(); + default: #ifdef DEBUG_FAILURES - printf("*** Unknown operator: %.2s\n", operator_ptr); + printf("*** Unknown operator: %.2s\n", operator_ptr); #endif - return false; - } + return false; } + } - // <source-name> ::= <positive length number> <identifier> + // <source-name> ::= <positive length number> <identifier> - bool - ParseSourceName() - { - int count = TryParseNumber(); - if (count == -1) - { + bool ParseSourceName() { + int count = TryParseNumber(); + if (count == -1) { #ifdef DEBUG_FAILURES - printf("*** Malformed source name, missing length count\n"); + printf("*** Malformed source name, missing length count\n"); #endif - return false; - } + return false; + } - const char *next_m_read_ptr = m_read_ptr + count; - if (next_m_read_ptr > m_read_end) - { + const char *next_m_read_ptr = m_read_ptr + count; + if (next_m_read_ptr > m_read_end) { #ifdef DEBUG_FAILURES - printf("*** Malformed source name, premature termination\n"); + printf("*** Malformed source name, premature termination\n"); #endif - return false; - } - - if (count >= 10 && strncmp(m_read_ptr, "_GLOBAL__N", 10) == 0) - WRITE("(anonymous namespace)"); - else Write(m_read_ptr, count); - - m_read_ptr = next_m_read_ptr; - return true; - } - - // <unqualified-name> ::= <operator-name> - // ::= <ctor-dtor-name> - // ::= <source-name> - // ::= <unnamed-type-name> - - bool - ParseUnqualifiedName(NameState & name_state) - { - // Note that these are detected directly in ParseNestedName for - // performance rather than switching on the same options twice - char next = *m_read_ptr; - switch (next) - { - case 'C': - ++m_read_ptr; - return ParseCtor(name_state); - case 'D': - ++m_read_ptr; - return ParseDtor(name_state); - case 'U': - ++m_read_ptr; - return ParseUnnamedTypeName(name_state); - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - int name_start_cookie = GetStartCookie(); - if (!ParseSourceName()) - return false; - name_state.last_name_range = EndRange(name_start_cookie); - return true; - } - default: - return ParseOperatorName(name_state); - }; - } - - // <unscoped-name> ::= <unqualified-name> - // ::= St <unqualified-name> # ::std:: - // extension ::= StL<unqualified-name> - - bool - ParseUnscopedName(NameState & name_state) - { - if (*m_read_ptr == 'S' && *(m_read_ptr + 1) == 't') - { - WriteStdPrefix(); - if (*(m_read_ptr += 2) == 'L') - ++m_read_ptr; - } - return ParseUnqualifiedName(name_state); - } - - bool - ParseIntegerLiteral(const char *prefix, const char *suffix, - bool allow_negative) - { - if (prefix) - Write(prefix); - if (!ParseNumber(allow_negative)) - return false; - if (suffix) - Write(suffix); - return Parse('E'); + return false; + } + + if (count >= 10 && strncmp(m_read_ptr, "_GLOBAL__N", 10) == 0) + WRITE("(anonymous namespace)"); + else + Write(m_read_ptr, count); + + m_read_ptr = next_m_read_ptr; + return true; + } + + // <unqualified-name> ::= <operator-name> + // ::= <ctor-dtor-name> + // ::= <source-name> + // ::= <unnamed-type-name> + + bool ParseUnqualifiedName(NameState &name_state) { + // Note that these are detected directly in ParseNestedName for + // performance rather than switching on the same options twice + char next = *m_read_ptr; + switch (next) { + case 'C': + ++m_read_ptr; + return ParseCtor(name_state); + case 'D': + ++m_read_ptr; + return ParseDtor(name_state); + case 'U': + ++m_read_ptr; + return ParseUnnamedTypeName(name_state); + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { + int name_start_cookie = GetStartCookie(); + if (!ParseSourceName()) + return false; + name_state.last_name_range = EndRange(name_start_cookie); + return true; + } + default: + return ParseOperatorName(name_state); + }; + } + + // <unscoped-name> ::= <unqualified-name> + // ::= St <unqualified-name> # ::std:: + // extension ::= StL<unqualified-name> + + bool ParseUnscopedName(NameState &name_state) { + if (*m_read_ptr == 'S' && *(m_read_ptr + 1) == 't') { + WriteStdPrefix(); + if (*(m_read_ptr += 2) == 'L') + ++m_read_ptr; } - - bool - ParseBooleanLiteral() - { - switch (*m_read_ptr++) - { - case '0': WRITE("false"); break; - case '1': WRITE("true"); break; - default: + return ParseUnqualifiedName(name_state); + } + + bool ParseIntegerLiteral(const char *prefix, const char *suffix, + bool allow_negative) { + if (prefix) + Write(prefix); + if (!ParseNumber(allow_negative)) + return false; + if (suffix) + Write(suffix); + return Parse('E'); + } + + bool ParseBooleanLiteral() { + switch (*m_read_ptr++) { + case '0': + WRITE("false"); + break; + case '1': + WRITE("true"); + break; + default: #ifdef DEBUG_FAILURES - printf("*** Boolean literal not 0 or 1\n"); + printf("*** Boolean literal not 0 or 1\n"); #endif - return false; - } + return false; + } + return Parse('E'); + } + + // <expr-primary> ::= L <type> <value number> E # + // integer literal + // ::= L <type> <value float> E # + // floating literal + // ::= L <string type> E # + // string literal + // ::= L <nullptr type> E # + // nullptr literal (i.e., "LDnE") + // ::= L <type> <real-part float> _ <imag-part float> E # + // complex floating point literal (C 2000) + // ::= L <mangled-name> E # + // external name + + bool ParseExpressionPrimary() { + switch (*m_read_ptr++) { + case 'b': + return ParseBooleanLiteral(); + case 'x': + return ParseIntegerLiteral(nullptr, "ll", true); + case 'l': + return ParseIntegerLiteral(nullptr, "l", true); + case 'i': + return ParseIntegerLiteral(nullptr, nullptr, true); + case 'n': + return ParseIntegerLiteral("(__int128)", nullptr, true); + case 'j': + return ParseIntegerLiteral(nullptr, "u", false); + case 'm': + return ParseIntegerLiteral(nullptr, "ul", false); + case 'y': + return ParseIntegerLiteral(nullptr, "ull", false); + case 'o': + return ParseIntegerLiteral("(unsigned __int128)", nullptr, false); + case '_': + if (*m_read_ptr++ == 'Z') { + if (!ParseEncoding()) + return false; return Parse('E'); - } - - // <expr-primary> ::= L <type> <value number> E # integer literal - // ::= L <type> <value float> E # floating literal - // ::= L <string type> E # string literal - // ::= L <nullptr type> E # nullptr literal (i.e., "LDnE") - // ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000) - // ::= L <mangled-name> E # external name - - bool - ParseExpressionPrimary() - { - switch (*m_read_ptr++) - { - case 'b': return ParseBooleanLiteral(); - case 'x': return ParseIntegerLiteral(nullptr, "ll", true); - case 'l': return ParseIntegerLiteral(nullptr, "l", true); - case 'i': return ParseIntegerLiteral(nullptr, nullptr, true); - case 'n': return ParseIntegerLiteral("(__int128)", nullptr, true); - case 'j': return ParseIntegerLiteral(nullptr, "u", false); - case 'm': return ParseIntegerLiteral(nullptr, "ul", false); - case 'y': return ParseIntegerLiteral(nullptr, "ull", false); - case 'o': return ParseIntegerLiteral("(unsigned __int128)", - nullptr, false); - case '_': - if (*m_read_ptr++ == 'Z') - { - if (!ParseEncoding()) - return false; - return Parse('E'); - } - --m_read_ptr; - LLVM_FALLTHROUGH; - case 'w': - case 'c': - case 'a': - case 'h': - case 's': - case 't': - case 'f': - case 'd': - case 'e': + } + --m_read_ptr; + LLVM_FALLTHROUGH; + case 'w': + case 'c': + case 'a': + case 'h': + case 's': + case 't': + case 'f': + case 'd': + case 'e': #ifdef DEBUG_FAILURES - printf("*** Unsupported primary expression %.5s\n", m_read_ptr - 1); + printf("*** Unsupported primary expression %.5s\n", m_read_ptr - 1); #endif - return false; - case 'T': - // Invalid mangled name per - // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html + return false; + case 'T': +// Invalid mangled name per +// http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html #ifdef DEBUG_FAILURES - printf("*** Invalid primary expr encoding\n"); + printf("*** Invalid primary expr encoding\n"); #endif - return false; - default: - --m_read_ptr; - Write('('); - if (!ParseType()) - return false; - Write(')'); - if (!ParseNumber()) - return false; - return Parse('E'); - } + return false; + default: + --m_read_ptr; + Write('('); + if (!ParseType()) + return false; + Write(')'); + if (!ParseNumber()) + return false; + return Parse('E'); } + } - // <unresolved-type> ::= <template-param> - // ::= <decltype> - // ::= <substitution> + // <unresolved-type> ::= <template-param> + // ::= <decltype> + // ::= <substitution> - bool - ParseUnresolvedType() - { - int type_start_cookie = GetStartCookie(); - switch (*m_read_ptr++) - { - case 'T': - if (!ParseTemplateParam()) - return false; - EndSubstitution(type_start_cookie); - return true; - case 'S': - { - if (*m_read_ptr != 't') - return ParseSubstitution(); - - ++m_read_ptr; - WriteStdPrefix(); - NameState type_name = {}; - if (!ParseUnqualifiedName(type_name)) - return false; - EndSubstitution(type_start_cookie); - return true; - - } - case 'D': - default: + bool ParseUnresolvedType() { + int type_start_cookie = GetStartCookie(); + switch (*m_read_ptr++) { + case 'T': + if (!ParseTemplateParam()) + return false; + EndSubstitution(type_start_cookie); + return true; + case 'S': { + if (*m_read_ptr != 't') + return ParseSubstitution(); + + ++m_read_ptr; + WriteStdPrefix(); + NameState type_name = {}; + if (!ParseUnqualifiedName(type_name)) + return false; + EndSubstitution(type_start_cookie); + return true; + } + case 'D': + default: #ifdef DEBUG_FAILURES - printf("*** Unsupported unqualified type: %3s\n", m_read_ptr - 1); + printf("*** Unsupported unqualified type: %3s\n", m_read_ptr - 1); #endif - return false; - } - } - - // <base-unresolved-name> ::= <simple-id> # unresolved name - // extension ::= <operator-name> # unresolved operator-function-id - // extension ::= <operator-name> <template-args> # unresolved operator template-id - // ::= on <operator-name> # unresolved operator-function-id - // ::= on <operator-name> <template-args> # unresolved operator template-id - // ::= dn <destructor-name> # destructor or pseudo-destructor; - // # e.g. ~X or ~X<N-1> - - bool - ParseBaseUnresolvedName() - { + return false; + } + } + + // <base-unresolved-name> ::= <simple-id> # + // unresolved name + // extension ::= <operator-name> # + // unresolved operator-function-id + // extension ::= <operator-name> <template-args> # + // unresolved operator template-id + // ::= on <operator-name> # + // unresolved operator-function-id + // ::= on <operator-name> <template-args> # + // unresolved operator template-id + // ::= dn <destructor-name> # + // destructor or pseudo-destructor; + // # + // e.g. + // ~X + // or + // ~X<N-1> + + bool ParseBaseUnresolvedName() { #ifdef DEBUG_FAILURES - printf("*** Base unresolved name unsupported\n"); + printf("*** Base unresolved name unsupported\n"); #endif - return false; - } - - // <unresolved-name> - // extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name> - // ::= [gs] <base-unresolved-name> # x or (with "gs") ::x - // ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name> - // # A::x, N::y, A<T>::z; "gs" means leading "::" - // ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x - // extension ::= sr <unresolved-type> <template-args> <base-unresolved-name> - // # T::N::x /decltype(p)::N::x - // (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name> - - bool - ParseUnresolvedName() - { + return false; + } + + // <unresolved-name> + // extension ::= srN <unresolved-type> [<template-args>] + // <unresolved-qualifier-level>* E <base-unresolved-name> + // ::= [gs] <base-unresolved-name> # x + // or (with "gs") ::x + // ::= [gs] sr <unresolved-qualifier-level>+ E + // <base-unresolved-name> + // # + // A::x, + // N::y, + // A<T>::z; + // "gs" + // means + // leading + // "::" + // ::= sr <unresolved-type> <base-unresolved-name> # + // T::x / decltype(p)::x + // extension ::= sr <unresolved-type> <template-args> + // <base-unresolved-name> + // # + // T::N::x + // /decltype(p)::N::x + // (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ + // E <base-unresolved-name> + + bool ParseUnresolvedName() { #ifdef DEBUG_FAILURES - printf("*** Unresolved names not supported\n"); + printf("*** Unresolved names not supported\n"); #endif - //TODO: grammar for all of this seems unclear... - return false; + // TODO: grammar for all of this seems unclear... + return false; #if 0 // TODO if (*m_read_ptr == 'g' && *(m_read_ptr + 1) == 's') @@ -1743,677 +1720,677 @@ private: WriteNamespaceSeparator(); } #endif // TODO - } - - // <expression> ::= <unary operator-name> <expression> - // ::= <binary operator-name> <expression> <expression> - // ::= <ternary operator-name> <expression> <expression> <expression> - // ::= cl <expression>+ E # call - // ::= cv <type> <expression> # conversion with one argument - // ::= cv <type> _ <expression>* E # conversion with a different number of arguments - // ::= [gs] nw <expression>* _ <type> E # new (expr-list) type - // ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init) - // ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type - // ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init) - // ::= [gs] dl <expression> # delete expression - // ::= [gs] da <expression> # delete[] expression - // ::= pp_ <expression> # prefix ++ - // ::= mm_ <expression> # prefix -- - // ::= ti <type> # typeid (type) - // ::= te <expression> # typeid (expression) - // ::= dc <type> <expression> # dynamic_cast<type> (expression) - // ::= sc <type> <expression> # static_cast<type> (expression) - // ::= cc <type> <expression> # const_cast<type> (expression) - // ::= rc <type> <expression> # reinterpret_cast<type> (expression) - // ::= st <type> # sizeof (a type) - // ::= sz <expression> # sizeof (an expression) - // ::= at <type> # alignof (a type) - // ::= az <expression> # alignof (an expression) - // ::= nx <expression> # noexcept (expression) - // ::= <template-param> - // ::= <function-param> - // ::= dt <expression> <unresolved-name> # expr.name - // ::= pt <expression> <unresolved-name> # expr->name - // ::= ds <expression> <expression> # expr.*expr - // ::= sZ <template-param> # size of a parameter pack - // ::= sZ <function-param> # size of a function parameter pack - // ::= sp <expression> # pack expansion - // ::= tw <expression> # throw expression - // ::= tr # throw with no operand (rethrow) - // ::= <unresolved-name> # f(p), N::f(p), ::f(p), - // # freestanding dependent name (e.g., T::x), - // # objectless nonstatic member reference - // ::= <expr-primary> - - bool - ParseExpression() - { - Operator expression_operator = TryParseOperator(); - switch (expression_operator.kind) - { - case OperatorKind::Unary: - Write(expression_operator.name); - Write('('); - if (!ParseExpression()) - return false; - Write(')'); - return true; - case OperatorKind::Binary: - if (!ParseExpression()) - return false; - Write(expression_operator.name); - return ParseExpression(); - case OperatorKind::Ternary: - if (!ParseExpression()) - return false; - Write('?'); - if (!ParseExpression()) - return false; - Write(':'); - return ParseExpression(); - case OperatorKind::NoMatch: - break; - case OperatorKind::Other: - default: + } + + // <expression> ::= <unary operator-name> <expression> + // ::= <binary operator-name> <expression> <expression> + // ::= <ternary operator-name> <expression> <expression> + // <expression> + // ::= cl <expression>+ E # + // call + // ::= cv <type> <expression> # + // conversion with one argument + // ::= cv <type> _ <expression>* E # + // conversion with a different number of arguments + // ::= [gs] nw <expression>* _ <type> E # new + // (expr-list) type + // ::= [gs] nw <expression>* _ <type> <initializer> # new + // (expr-list) type (init) + // ::= [gs] na <expression>* _ <type> E # + // new[] (expr-list) type + // ::= [gs] na <expression>* _ <type> <initializer> # + // new[] (expr-list) type (init) + // ::= [gs] dl <expression> # + // delete expression + // ::= [gs] da <expression> # + // delete[] expression + // ::= pp_ <expression> # + // prefix ++ + // ::= mm_ <expression> # + // prefix -- + // ::= ti <type> # + // typeid (type) + // ::= te <expression> # + // typeid (expression) + // ::= dc <type> <expression> # + // dynamic_cast<type> (expression) + // ::= sc <type> <expression> # + // static_cast<type> (expression) + // ::= cc <type> <expression> # + // const_cast<type> (expression) + // ::= rc <type> <expression> # + // reinterpret_cast<type> (expression) + // ::= st <type> # + // sizeof (a type) + // ::= sz <expression> # + // sizeof (an expression) + // ::= at <type> # + // alignof (a type) + // ::= az <expression> # + // alignof (an expression) + // ::= nx <expression> # + // noexcept (expression) + // ::= <template-param> + // ::= <function-param> + // ::= dt <expression> <unresolved-name> # + // expr.name + // ::= pt <expression> <unresolved-name> # + // expr->name + // ::= ds <expression> <expression> # + // expr.*expr + // ::= sZ <template-param> # + // size of a parameter pack + // ::= sZ <function-param> # + // size of a function parameter pack + // ::= sp <expression> # + // pack expansion + // ::= tw <expression> # + // throw expression + // ::= tr # + // throw with no operand (rethrow) + // ::= <unresolved-name> # + // f(p), N::f(p), ::f(p), + // # + // freestanding + // dependent + // name + // (e.g., + // T::x), + // # + // objectless + // nonstatic + // member + // reference + // ::= <expr-primary> + + bool ParseExpression() { + Operator expression_operator = TryParseOperator(); + switch (expression_operator.kind) { + case OperatorKind::Unary: + Write(expression_operator.name); + Write('('); + if (!ParseExpression()) + return false; + Write(')'); + return true; + case OperatorKind::Binary: + if (!ParseExpression()) + return false; + Write(expression_operator.name); + return ParseExpression(); + case OperatorKind::Ternary: + if (!ParseExpression()) + return false; + Write('?'); + if (!ParseExpression()) + return false; + Write(':'); + return ParseExpression(); + case OperatorKind::NoMatch: + break; + case OperatorKind::Other: + default: #ifdef DEBUG_FAILURES - printf("*** Unsupported operator: %s\n", expression_operator.name); + printf("*** Unsupported operator: %s\n", expression_operator.name); #endif - return false; - } - - switch (*m_read_ptr++) - { - case 'T': return ParseTemplateParam(); - case 'L': return ParseExpressionPrimary(); - case 's': - if (*m_read_ptr++ == 'r') - return ParseUnresolvedName(); - --m_read_ptr; - LLVM_FALLTHROUGH; - default: - return ParseExpressionPrimary(); - } - } - - // <template-arg> ::= <type> # type or template - // ::= X <expression> E # expression - // ::= <expr-primary> # simple expressions - // ::= J <template-arg>* E # argument pack - // ::= LZ <encoding> E # extension - - bool - ParseTemplateArg() - { - switch (*m_read_ptr) { - case 'J': + return false; + } + + switch (*m_read_ptr++) { + case 'T': + return ParseTemplateParam(); + case 'L': + return ParseExpressionPrimary(); + case 's': + if (*m_read_ptr++ == 'r') + return ParseUnresolvedName(); + --m_read_ptr; + LLVM_FALLTHROUGH; + default: + return ParseExpressionPrimary(); + } + } + + // <template-arg> ::= <type> # + // type or template + // ::= X <expression> E # + // expression + // ::= <expr-primary> # + // simple expressions + // ::= J <template-arg>* E # + // argument pack + // ::= LZ <encoding> E # + // extension + + bool ParseTemplateArg() { + switch (*m_read_ptr) { + case 'J': #ifdef DEBUG_FAILURES - printf("*** Template argument packs unsupported\n"); + printf("*** Template argument packs unsupported\n"); #endif - return false; - case 'X': - ++m_read_ptr; - if (!ParseExpression()) - return false; - return Parse('E'); - case 'L': - ++m_read_ptr; - return ParseExpressionPrimary(); - default: - return ParseType(); - } - } - - // <template-args> ::= I <template-arg>* E - // extension, the abi says <template-arg>+ - - bool - ParseTemplateArgs(bool record_template_args = false) - { - if (record_template_args) - ResetTemplateArgs(); + return false; + case 'X': + ++m_read_ptr; + if (!ParseExpression()) + return false; + return Parse('E'); + case 'L': + ++m_read_ptr; + return ParseExpressionPrimary(); + default: + return ParseType(); + } + } + + // <template-args> ::= I <template-arg>* E + // extension, the abi says <template-arg>+ + + bool ParseTemplateArgs(bool record_template_args = false) { + if (record_template_args) + ResetTemplateArgs(); + + bool first_arg = true; + while (*m_read_ptr != 'E') { + if (first_arg) + first_arg = false; + else + WriteCommaSpace(); + + int template_start_cookie = GetStartCookie(); + if (!ParseTemplateArg()) + return false; + if (record_template_args) + EndTemplateArg(template_start_cookie); + } + ++m_read_ptr; + return true; + } + + // <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> + // <unqualified-name> E + // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> + // <template-args> E + // + // <prefix> ::= <prefix> <unqualified-name> + // ::= <template-prefix> <template-args> + // ::= <template-param> + // ::= <decltype> + // ::= # empty + // ::= <substitution> + // ::= <prefix> <data-member-prefix> + // extension ::= L + // + // <template-prefix> ::= <prefix> <template unqualified-name> + // ::= <template-param> + // ::= <substitution> + // + // <unqualified-name> ::= <operator-name> + // ::= <ctor-dtor-name> + // ::= <source-name> + // ::= <unnamed-type-name> + + bool ParseNestedName(NameState &name_state, + bool parse_discriminator = false) { + int qualifiers = TryParseQualifiers(true, true); + bool first_part = true; + bool suppress_substitution = true; + int name_start_cookie = GetStartCookie(); + while (true) { + char next = *m_read_ptr; + if (next == 'E') { + ++m_read_ptr; + break; + } - bool first_arg = true; - while (*m_read_ptr != 'E') - { - if (first_arg) - first_arg = false; - else WriteCommaSpace(); + // Record a substitution candidate for all prefixes, but not the full name + if (suppress_substitution) + suppress_substitution = false; + else + EndSubstitution(name_start_cookie); - int template_start_cookie = GetStartCookie(); - if (!ParseTemplateArg()) - return false; - if (record_template_args) - EndTemplateArg(template_start_cookie); - } + if (next == 'I') { ++m_read_ptr; - return true; - } - - // <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E - // ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E - // - // <prefix> ::= <prefix> <unqualified-name> - // ::= <template-prefix> <template-args> - // ::= <template-param> - // ::= <decltype> - // ::= # empty - // ::= <substitution> - // ::= <prefix> <data-member-prefix> - // extension ::= L - // - // <template-prefix> ::= <prefix> <template unqualified-name> - // ::= <template-param> - // ::= <substitution> - // - // <unqualified-name> ::= <operator-name> - // ::= <ctor-dtor-name> - // ::= <source-name> - // ::= <unnamed-type-name> - - bool - ParseNestedName(NameState & name_state, bool parse_discriminator = false) - { - int qualifiers = TryParseQualifiers(true, true); - bool first_part = true; - bool suppress_substitution = true; + name_state.is_last_generic = true; + WriteTemplateStart(); + if (!ParseTemplateArgs(name_state.parse_function_params)) + return false; + WriteTemplateEnd(); + continue; + } + + if (first_part) + first_part = false; + else + WriteNamespaceSeparator(); + + name_state.is_last_generic = false; + switch (next) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': { int name_start_cookie = GetStartCookie(); - while (true) - { - char next = *m_read_ptr; - if (next == 'E') - { - ++m_read_ptr; - break; - } - - // Record a substitution candidate for all prefixes, but not the full name - if (suppress_substitution) - suppress_substitution = false; - else EndSubstitution(name_start_cookie); - - if (next == 'I') - { - ++m_read_ptr; - name_state.is_last_generic = true; - WriteTemplateStart(); - if (!ParseTemplateArgs(name_state.parse_function_params)) - return false; - WriteTemplateEnd(); - continue; - } - - if (first_part) - first_part = false; - else WriteNamespaceSeparator(); - - name_state.is_last_generic = false; - switch (next) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - int name_start_cookie = GetStartCookie(); - if (!ParseSourceName()) - return false; - name_state.last_name_range = EndRange(name_start_cookie); - continue; - } - case 'S': - if (*++m_read_ptr == 't') - { - WriteStdPrefix(); - ++m_read_ptr; - if (!ParseUnqualifiedName(name_state)) - return false; - } - else - { - if (!ParseSubstitution()) - return false; - suppress_substitution = true; - } - continue; - case 'T': - ++m_read_ptr; - if (!ParseTemplateParam()) - return false; - continue; - case 'C': - ++m_read_ptr; - if (!ParseCtor(name_state)) - return false; - continue; - case 'D': - { - switch (*(m_read_ptr + 1)) - { - case 't': - case 'T': -#ifdef DEBUG_FAILURES - printf("*** Decltype unsupported\n"); -#endif - return false; - } - ++m_read_ptr; - if (!ParseDtor(name_state)) - return false; - continue; - } - case 'U': - ++m_read_ptr; - if (!ParseUnnamedTypeName(name_state)) - return false; - continue; - case 'L': - ++m_read_ptr; - if (!ParseUnqualifiedName(name_state)) - return false; - continue; - default: - if (!ParseOperatorName(name_state)) - return false; - } - } - - if (parse_discriminator) - TryParseDiscriminator(); - if (name_state.parse_function_params - && !ParseFunctionArgs(name_state, name_start_cookie)) - { - return false; - } - if (qualifiers) - WriteQualifiers(qualifiers); - return true; - } - - // <local-name> := Z <function encoding> E <entity name> [<discriminator>] - // := Z <function encoding> E s [<discriminator>] - // := Z <function encoding> Ed [ <parameter number> ] _ <entity name> - - bool - ParseLocalName(bool parse_function_params) - { - if (!ParseEncoding()) + if (!ParseSourceName()) + return false; + name_state.last_name_range = EndRange(name_start_cookie); + continue; + } + case 'S': + if (*++m_read_ptr == 't') { + WriteStdPrefix(); + ++m_read_ptr; + if (!ParseUnqualifiedName(name_state)) return false; - if (!Parse('E')) + } else { + if (!ParseSubstitution()) return false; - - switch (*m_read_ptr) - { - case 's': - ++m_read_ptr; - TryParseDiscriminator(); // Optional and ignored - WRITE("::string literal"); - break; - case 'd': - ++m_read_ptr; - TryParseNumber(); // Optional and ignored - if (!Parse('_')) - return false; - WriteNamespaceSeparator(); - if (!ParseName()) - return false; - break; - default: - WriteNamespaceSeparator(); - if (!ParseName(parse_function_params, true)) - return false; - TryParseDiscriminator(); // Optional and ignored + suppress_substitution = true; } - return true; - } - - // <name> ::= <nested-name> - // ::= <local-name> - // ::= <unscoped-template-name> <template-args> - // ::= <unscoped-name> - - // <unscoped-template-name> ::= <unscoped-name> - // ::= <substitution> - - bool - ParseName(bool parse_function_params = false, - bool parse_discriminator = false) - { - NameState name_state = { parse_function_params, false, false, {0, 0}}; - int name_start_cookie = GetStartCookie(); - - switch (*m_read_ptr) - { - case 'N': - ++m_read_ptr; - return ParseNestedName(name_state, parse_discriminator); - case 'Z': - { - ++m_read_ptr; - if (!ParseLocalName(parse_function_params)) - return false; - break; - } - case 'L': - ++m_read_ptr; - LLVM_FALLTHROUGH; - default: - { - if (!ParseUnscopedName(name_state)) - return false; - - if (*m_read_ptr == 'I') - { - EndSubstitution(name_start_cookie); - - ++m_read_ptr; - name_state.is_last_generic = true; - WriteTemplateStart(); - if (!ParseTemplateArgs(parse_function_params)) - return false; - WriteTemplateEnd(); - } - break; - } - } - if (parse_discriminator) - TryParseDiscriminator(); - if (parse_function_params && - !ParseFunctionArgs(name_state, name_start_cookie)) - { - return false; + continue; + case 'T': + ++m_read_ptr; + if (!ParseTemplateParam()) + return false; + continue; + case 'C': + ++m_read_ptr; + if (!ParseCtor(name_state)) + return false; + continue; + case 'D': { + switch (*(m_read_ptr + 1)) { + case 't': + case 'T': +#ifdef DEBUG_FAILURES + printf("*** Decltype unsupported\n"); +#endif + return false; } - return true; + ++m_read_ptr; + if (!ParseDtor(name_state)) + return false; + continue; + } + case 'U': + ++m_read_ptr; + if (!ParseUnnamedTypeName(name_state)) + return false; + continue; + case 'L': + ++m_read_ptr; + if (!ParseUnqualifiedName(name_state)) + return false; + continue; + default: + if (!ParseOperatorName(name_state)) + return false; + } + } + + if (parse_discriminator) + TryParseDiscriminator(); + if (name_state.parse_function_params && + !ParseFunctionArgs(name_state, name_start_cookie)) { + return false; + } + if (qualifiers) + WriteQualifiers(qualifiers); + return true; + } + + // <local-name> := Z <function encoding> E <entity name> [<discriminator>] + // := Z <function encoding> E s [<discriminator>] + // := Z <function encoding> Ed [ <parameter number> ] _ <entity + // name> + + bool ParseLocalName(bool parse_function_params) { + if (!ParseEncoding()) + return false; + if (!Parse('E')) + return false; + + switch (*m_read_ptr) { + case 's': + ++m_read_ptr; + TryParseDiscriminator(); // Optional and ignored + WRITE("::string literal"); + break; + case 'd': + ++m_read_ptr; + TryParseNumber(); // Optional and ignored + if (!Parse('_')) + return false; + WriteNamespaceSeparator(); + if (!ParseName()) + return false; + break; + default: + WriteNamespaceSeparator(); + if (!ParseName(parse_function_params, true)) + return false; + TryParseDiscriminator(); // Optional and ignored + } + return true; + } + + // <name> ::= <nested-name> + // ::= <local-name> + // ::= <unscoped-template-name> <template-args> + // ::= <unscoped-name> + + // <unscoped-template-name> ::= <unscoped-name> + // ::= <substitution> + + bool ParseName(bool parse_function_params = false, + bool parse_discriminator = false) { + NameState name_state = {parse_function_params, false, false, {0, 0}}; + int name_start_cookie = GetStartCookie(); + + switch (*m_read_ptr) { + case 'N': + ++m_read_ptr; + return ParseNestedName(name_state, parse_discriminator); + case 'Z': { + ++m_read_ptr; + if (!ParseLocalName(parse_function_params)) + return false; + break; } + case 'L': + ++m_read_ptr; + LLVM_FALLTHROUGH; + default: { + if (!ParseUnscopedName(name_state)) + return false; - // <call-offset> ::= h <nv-offset> _ - // ::= v <v-offset> _ - // - // <nv-offset> ::= <offset number> - // # non-virtual base override - // - // <v-offset> ::= <offset number> _ <virtual offset number> - // # virtual base override, with vcall offset + if (*m_read_ptr == 'I') { + EndSubstitution(name_start_cookie); - bool - ParseCallOffset() - { - switch (*m_read_ptr++) - { - case 'h': - if (*m_read_ptr == 'n') - ++m_read_ptr; - if (TryParseNumber() == -1 || *m_read_ptr++ != '_') - break; - return true; - case 'v': - if (*m_read_ptr == 'n') - ++m_read_ptr; - if (TryParseNumber() == -1 || *m_read_ptr++ != '_') - break; - if (*m_read_ptr == 'n') - ++m_read_ptr; - if (TryParseNumber() == -1 || *m_read_ptr++ != '_') - break; - return true; - } + ++m_read_ptr; + name_state.is_last_generic = true; + WriteTemplateStart(); + if (!ParseTemplateArgs(parse_function_params)) + return false; + WriteTemplateEnd(); + } + break; + } + } + if (parse_discriminator) + TryParseDiscriminator(); + if (parse_function_params && + !ParseFunctionArgs(name_state, name_start_cookie)) { + return false; + } + return true; + } + + // <call-offset> ::= h <nv-offset> _ + // ::= v <v-offset> _ + // + // <nv-offset> ::= <offset number> + // # non-virtual base override + // + // <v-offset> ::= <offset number> _ <virtual offset number> + // # virtual base override, with vcall offset + + bool ParseCallOffset() { + switch (*m_read_ptr++) { + case 'h': + if (*m_read_ptr == 'n') + ++m_read_ptr; + if (TryParseNumber() == -1 || *m_read_ptr++ != '_') + break; + return true; + case 'v': + if (*m_read_ptr == 'n') + ++m_read_ptr; + if (TryParseNumber() == -1 || *m_read_ptr++ != '_') + break; + if (*m_read_ptr == 'n') + ++m_read_ptr; + if (TryParseNumber() == -1 || *m_read_ptr++ != '_') + break; + return true; + } #ifdef DEBUG_FAILURES - printf("*** Malformed call offset\n"); + printf("*** Malformed call offset\n"); #endif - return false; - } - - // <special-name> ::= TV <type> # virtual table - // ::= TT <type> # VTT structure (construction vtable index) - // ::= TI <type> # typeinfo structure - // ::= TS <type> # typeinfo name (null-terminated byte string) - // ::= Tc <call-offset> <call-offset> <base encoding> - // # base is the nominal target function of thunk - // # first call-offset is 'this' adjustment - // # second call-offset is result adjustment - // ::= T <call-offset> <base encoding> - // # base is the nominal target function of thunk - // extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first - - bool - ParseSpecialNameT() - { - switch (*m_read_ptr++) - { - case 'V': - WRITE("vtable for "); - return ParseType(); - case 'T': - WRITE("VTT for "); - return ParseType(); - case 'I': - WRITE("typeinfo for "); - return ParseType(); - case 'S': - WRITE("typeinfo name for "); - return ParseType(); - case 'c': - case 'C': + return false; + } + + // <special-name> ::= TV <type> # virtual table + // ::= TT <type> # VTT structure (construction vtable index) + // ::= TI <type> # typeinfo structure + // ::= TS <type> # typeinfo name (null-terminated byte + // string) + // ::= Tc <call-offset> <call-offset> <base encoding> + // # base is the nominal target function of thunk + // # first call-offset is 'this' adjustment + // # second call-offset is result adjustment + // ::= T <call-offset> <base encoding> + // # base is the nominal target function of thunk + // extension ::= TC <first type> <number> _ <second type> # construction + // vtable for second-in-first + + bool ParseSpecialNameT() { + switch (*m_read_ptr++) { + case 'V': + WRITE("vtable for "); + return ParseType(); + case 'T': + WRITE("VTT for "); + return ParseType(); + case 'I': + WRITE("typeinfo for "); + return ParseType(); + case 'S': + WRITE("typeinfo name for "); + return ParseType(); + case 'c': + case 'C': #ifdef DEBUG_FAILURES - printf("*** Unsupported thunk or construction vtable name: %.3s\n", m_read_ptr - 1); + printf("*** Unsupported thunk or construction vtable name: %.3s\n", + m_read_ptr - 1); #endif - return false; - default: - if (*--m_read_ptr == 'v') - { - WRITE("virtual thunk to "); - } - else - { - WRITE("non-virtual thunk to "); - } - if (!ParseCallOffset()) - return false; - return ParseEncoding(); - } + return false; + default: + if (*--m_read_ptr == 'v') { + WRITE("virtual thunk to "); + } else { + WRITE("non-virtual thunk to "); + } + if (!ParseCallOffset()) + return false; + return ParseEncoding(); } + } - // <special-name> ::= GV <object name> # Guard variable for one-time initialization - // # No <type> - // extension ::= GR <object name> # reference temporary for object + // <special-name> ::= GV <object name> # Guard variable for one-time + // initialization + // # No <type> + // extension ::= GR <object name> # reference temporary for object - bool - ParseSpecialNameG() - { - switch (*m_read_ptr++) - { - case 'V': - WRITE("guard variable for "); - if (!ParseName(true)) - return false; - break; - case 'R': - WRITE("reference temporary for "); - if (!ParseName(true)) - return false; - break; - default: + bool ParseSpecialNameG() { + switch (*m_read_ptr++) { + case 'V': + WRITE("guard variable for "); + if (!ParseName(true)) + return false; + break; + case 'R': + WRITE("reference temporary for "); + if (!ParseName(true)) + return false; + break; + default: #ifdef DEBUG_FAILURES - printf("*** Unknown G encoding\n"); + printf("*** Unknown G encoding\n"); #endif - return false; - } - return true; + return false; } + return true; + } - // <bare-function-type> ::= <signature type>+ # types are possible return type, then parameter types - - bool - ParseFunctionArgs(NameState & name_state, int return_insert_cookie) - { - char next = *m_read_ptr; - if (next == 'E' || next == '\0' || next == '.') - return true; - - // Clang has a bad habit of making unique manglings by just sticking numbers on the end of a symbol, - // which is ambiguous with malformed source name manglings - const char *before_clang_uniquing_test = m_read_ptr; - if (TryParseNumber()) - { - if (*m_read_ptr == '\0') - return true; - m_read_ptr = before_clang_uniquing_test; - } + // <bare-function-type> ::= <signature type>+ # types are possible + // return type, then parameter types - if (name_state.is_last_generic && !name_state.has_no_return_type) - { - int return_type_start_cookie = GetStartCookie(); - if (!ParseType()) - return false; - Write(' '); - ReorderRange(EndRange(return_type_start_cookie), - return_insert_cookie); - } - - Write('('); - bool first_param = true; - while (true) - { - switch (*m_read_ptr) - { - case '\0': - case 'E': - case '.': - break; - case 'v': - ++m_read_ptr; - continue; - case '_': - // Not a formal part of the mangling specification, but clang emits suffixes starting with _block_invoke - if (strncmp(m_read_ptr, "_block_invoke", 13) == 0) - { - m_read_ptr += strlen(m_read_ptr); - break; - } - LLVM_FALLTHROUGH; - default: - if (first_param) - first_param = false; - else WriteCommaSpace(); + bool ParseFunctionArgs(NameState &name_state, int return_insert_cookie) { + char next = *m_read_ptr; + if (next == 'E' || next == '\0' || next == '.') + return true; - if (!ParseType()) - return false; - continue; - } - break; - } - Write(')'); + // Clang has a bad habit of making unique manglings by just sticking numbers + // on the end of a symbol, + // which is ambiguous with malformed source name manglings + const char *before_clang_uniquing_test = m_read_ptr; + if (TryParseNumber()) { + if (*m_read_ptr == '\0') return true; + m_read_ptr = before_clang_uniquing_test; } - // <encoding> ::= <function name> <bare-function-type> - // ::= <data name> - // ::= <special-name> - - bool - ParseEncoding() - { - switch (*m_read_ptr) - { - case 'T': - ++m_read_ptr; - if (!ParseSpecialNameT()) - return false; - break; - case 'G': - ++m_read_ptr; - if (!ParseSpecialNameG()) - return false; - break; - default: - if (!ParseName(true)) - return false; - break; + if (name_state.is_last_generic && !name_state.has_no_return_type) { + int return_type_start_cookie = GetStartCookie(); + if (!ParseType()) + return false; + Write(' '); + ReorderRange(EndRange(return_type_start_cookie), return_insert_cookie); + } + + Write('('); + bool first_param = true; + while (true) { + switch (*m_read_ptr) { + case '\0': + case 'E': + case '.': + break; + case 'v': + ++m_read_ptr; + continue; + case '_': + // Not a formal part of the mangling specification, but clang emits + // suffixes starting with _block_invoke + if (strncmp(m_read_ptr, "_block_invoke", 13) == 0) { + m_read_ptr += strlen(m_read_ptr); + break; } - return true; + LLVM_FALLTHROUGH; + default: + if (first_param) + first_param = false; + else + WriteCommaSpace(); + + if (!ParseType()) + return false; + continue; + } + break; + } + Write(')'); + return true; + } + + // <encoding> ::= <function name> <bare-function-type> + // ::= <data name> + // ::= <special-name> + + bool ParseEncoding() { + switch (*m_read_ptr) { + case 'T': + ++m_read_ptr; + if (!ParseSpecialNameT()) + return false; + break; + case 'G': + ++m_read_ptr; + if (!ParseSpecialNameG()) + return false; + break; + default: + if (!ParseName(true)) + return false; + break; } + return true; + } - bool - ParseMangling(const char *mangled_name, long mangled_name_length = 0) - { - if (!mangled_name_length) - mangled_name_length = strlen(mangled_name); - m_read_end = mangled_name + mangled_name_length; - m_read_ptr = mangled_name; - m_write_ptr = m_buffer; - m_next_substitute_index = 0; - m_next_template_arg_index = m_rewrite_ranges_size - 1; - - if (*m_read_ptr++ != '_' || *m_read_ptr++ != 'Z') - { + bool ParseMangling(const char *mangled_name, long mangled_name_length = 0) { + if (!mangled_name_length) + mangled_name_length = strlen(mangled_name); + m_read_end = mangled_name + mangled_name_length; + m_read_ptr = mangled_name; + m_write_ptr = m_buffer; + m_next_substitute_index = 0; + m_next_template_arg_index = m_rewrite_ranges_size - 1; + + if (*m_read_ptr++ != '_' || *m_read_ptr++ != 'Z') { #ifdef DEBUG_FAILURES - printf("*** Missing _Z prefix\n"); + printf("*** Missing _Z prefix\n"); #endif - return false; - } - if (!ParseEncoding()) - return false; - switch (*m_read_ptr) - { - case '.': - Write(' '); - Write('('); - Write(m_read_ptr, m_read_end - m_read_ptr); - Write(')'); - LLVM_FALLTHROUGH; - case '\0': - return true; - default: + return false; + } + if (!ParseEncoding()) + return false; + switch (*m_read_ptr) { + case '.': + Write(' '); + Write('('); + Write(m_read_ptr, m_read_end - m_read_ptr); + Write(')'); + LLVM_FALLTHROUGH; + case '\0': + return true; + default: #ifdef DEBUG_FAILURES - printf("*** Unparsed mangled content\n"); + printf("*** Unparsed mangled content\n"); #endif - return false; - } + return false; } + } private: - - // External scratch storage used during demanglings - - char *m_buffer; - const char *m_buffer_end; - BufferRange *m_rewrite_ranges; - int m_rewrite_ranges_size; - bool m_owns_buffer; - bool m_owns_m_rewrite_ranges; - - // Internal state used during demangling - - const char *m_read_ptr; - const char *m_read_end; - char *m_write_ptr; - int m_next_template_arg_index; - int m_next_substitute_index; + // External scratch storage used during demanglings + + char *m_buffer; + const char *m_buffer_end; + BufferRange *m_rewrite_ranges; + int m_rewrite_ranges_size; + bool m_owns_buffer; + bool m_owns_m_rewrite_ranges; + + // Internal state used during demangling + + const char *m_read_ptr; + const char *m_read_end; + char *m_write_ptr; + int m_next_template_arg_index; + int m_next_substitute_index; + std::function<void(const char *s)> m_builtins_hook; }; } // Anonymous namespace // Public entry points referenced from Mangled.cpp -namespace lldb_private -{ - char * - FastDemangle(const char *mangled_name) - { - char buffer[16384]; - SymbolDemangler demangler(buffer, sizeof (buffer)); - return demangler.GetDemangledCopy(mangled_name); - } - - char * - FastDemangle(const char *mangled_name, long mangled_name_length) - { - char buffer[16384]; - SymbolDemangler demangler(buffer, sizeof (buffer)); - return demangler.GetDemangledCopy(mangled_name, mangled_name_length); - } +namespace lldb_private { +char *FastDemangle(const char *mangled_name) { + char buffer[16384]; + SymbolDemangler demangler(buffer, sizeof(buffer)); + return demangler.GetDemangledCopy(mangled_name); +} + +char *FastDemangle(const char *mangled_name, size_t mangled_name_length, + std::function<void(const char *s)> builtins_hook) { + char buffer[16384]; + SymbolDemangler demangler(buffer, sizeof(buffer), builtins_hook); + return demangler.GetDemangledCopy(mangled_name, mangled_name_length); +} } // lldb_private namespace diff --git a/source/Core/FileLineResolver.cpp b/source/Core/FileLineResolver.cpp index e8ef87f009d9..db56cae9e9bc 100644 --- a/source/Core/FileLineResolver.cpp +++ b/source/Core/FileLineResolver.cpp @@ -21,96 +21,66 @@ using namespace lldb_private; //---------------------------------------------------------------------- // FileLineResolver: //---------------------------------------------------------------------- -FileLineResolver::FileLineResolver -( - const FileSpec &file_spec, - uint32_t line_no, - bool check_inlines -) : - Searcher (), - m_file_spec (file_spec), - m_line_number (line_no), - m_inlines (check_inlines) -{ -} +FileLineResolver::FileLineResolver(const FileSpec &file_spec, uint32_t line_no, + bool check_inlines) + : Searcher(), m_file_spec(file_spec), m_line_number(line_no), + m_inlines(check_inlines) {} -FileLineResolver::~FileLineResolver () -{ -} +FileLineResolver::~FileLineResolver() {} Searcher::CallbackReturn -FileLineResolver::SearchCallback -( - SearchFilter &filter, - SymbolContext &context, - Address *addr, - bool containing -) -{ - CompileUnit *cu = context.comp_unit; +FileLineResolver::SearchCallback(SearchFilter &filter, SymbolContext &context, + Address *addr, bool containing) { + CompileUnit *cu = context.comp_unit; - if (m_inlines || m_file_spec.Compare(*cu, m_file_spec, (bool)m_file_spec.GetDirectory())) - { - uint32_t start_file_idx = 0; - uint32_t file_idx = cu->GetSupportFiles().FindFileIndex(start_file_idx, m_file_spec, false); - if (file_idx != UINT32_MAX) - { - LineTable *line_table = cu->GetLineTable(); - if (line_table) - { - if (m_line_number == 0) - { - // Match all lines in a file... - const bool append = true; - while (file_idx != UINT32_MAX) - { - line_table->FineLineEntriesForFileIndex (file_idx, append, m_sc_list); - // Get the next file index in case we have multiple file - // entries for the same file - file_idx = cu->GetSupportFiles().FindFileIndex(file_idx + 1, m_file_spec, false); - } - } - else - { - // Match a specific line in a file... - } - } + if (m_inlines || + m_file_spec.Compare(*cu, m_file_spec, (bool)m_file_spec.GetDirectory())) { + uint32_t start_file_idx = 0; + uint32_t file_idx = + cu->GetSupportFiles().FindFileIndex(start_file_idx, m_file_spec, false); + if (file_idx != UINT32_MAX) { + LineTable *line_table = cu->GetLineTable(); + if (line_table) { + if (m_line_number == 0) { + // Match all lines in a file... + const bool append = true; + while (file_idx != UINT32_MAX) { + line_table->FineLineEntriesForFileIndex(file_idx, append, + m_sc_list); + // Get the next file index in case we have multiple file + // entries for the same file + file_idx = cu->GetSupportFiles().FindFileIndex(file_idx + 1, + m_file_spec, false); + } + } else { + // Match a specific line in a file... } + } } - return Searcher::eCallbackReturnContinue; + } + return Searcher::eCallbackReturnContinue; } -Searcher::Depth -FileLineResolver::GetDepth() -{ - return Searcher::eDepthCompUnit; +Searcher::Depth FileLineResolver::GetDepth() { + return Searcher::eDepthCompUnit; } -void -FileLineResolver::GetDescription (Stream *s) -{ - s->Printf ("File and line resolver for file: \"%s\" line: %u", - m_file_spec.GetPath().c_str(), - m_line_number); +void FileLineResolver::GetDescription(Stream *s) { + s->Printf("File and line resolver for file: \"%s\" line: %u", + m_file_spec.GetPath().c_str(), m_line_number); } -void -FileLineResolver::Clear() -{ - m_file_spec.Clear(); - m_line_number = UINT32_MAX; - m_sc_list.Clear(); - m_inlines = true; +void FileLineResolver::Clear() { + m_file_spec.Clear(); + m_line_number = UINT32_MAX; + m_sc_list.Clear(); + m_inlines = true; } -void -FileLineResolver::Reset (const FileSpec &file_spec, - uint32_t line, - bool check_inlines) -{ - m_file_spec = file_spec; - m_line_number = line; - m_sc_list.Clear(); - m_inlines = check_inlines; +void FileLineResolver::Reset(const FileSpec &file_spec, uint32_t line, + bool check_inlines) { + m_file_spec = file_spec; + m_line_number = line; + m_sc_list.Clear(); + m_inlines = check_inlines; } - diff --git a/source/Core/FileSpecList.cpp b/source/Core/FileSpecList.cpp index cef1bfba41b0..d4ce4b787aad 100644 --- a/source/Core/FileSpecList.cpp +++ b/source/Core/FileSpecList.cpp @@ -20,33 +20,26 @@ using namespace lldb_private; using namespace std; -FileSpecList::FileSpecList() : - m_files() -{ -} +FileSpecList::FileSpecList() : m_files() {} -FileSpecList::FileSpecList(const FileSpecList& rhs) = default; +FileSpecList::FileSpecList(const FileSpecList &rhs) = default; FileSpecList::~FileSpecList() = default; //------------------------------------------------------------------ // Assignment operator //------------------------------------------------------------------ -const FileSpecList& -FileSpecList::operator= (const FileSpecList& rhs) -{ - if (this != &rhs) - m_files = rhs.m_files; - return *this; +const FileSpecList &FileSpecList::operator=(const FileSpecList &rhs) { + if (this != &rhs) + m_files = rhs.m_files; + return *this; } //------------------------------------------------------------------ // Append the "file_spec" to the end of the file spec list. //------------------------------------------------------------------ -void -FileSpecList::Append(const FileSpec &file_spec) -{ - m_files.push_back(file_spec); +void FileSpecList::Append(const FileSpec &file_spec) { + m_files.push_back(file_spec); } //------------------------------------------------------------------ @@ -56,40 +49,30 @@ FileSpecList::Append(const FileSpec &file_spec) // Returns true if "file_spec" was added, false if this list already // contained a copy of "file_spec". //------------------------------------------------------------------ -bool -FileSpecList::AppendIfUnique(const FileSpec &file_spec) -{ - collection::iterator pos, end = m_files.end(); - if (find(m_files.begin(), end, file_spec) == end) - { - m_files.push_back(file_spec); - return true; - } - return false; +bool FileSpecList::AppendIfUnique(const FileSpec &file_spec) { + collection::iterator pos, end = m_files.end(); + if (find(m_files.begin(), end, file_spec) == end) { + m_files.push_back(file_spec); + return true; + } + return false; } //------------------------------------------------------------------ // Clears the file list. //------------------------------------------------------------------ -void -FileSpecList::Clear() -{ - m_files.clear(); -} +void FileSpecList::Clear() { m_files.clear(); } //------------------------------------------------------------------ // Dumps the file list to the supplied stream pointer "s". //------------------------------------------------------------------ -void -FileSpecList::Dump(Stream *s, const char *separator_cstr) const -{ - collection::const_iterator pos, end = m_files.end(); - for (pos = m_files.begin(); pos != end; ++pos) - { - pos->Dump(s); - if (separator_cstr && ((pos + 1) != end)) - s->PutCString(separator_cstr); - } +void FileSpecList::Dump(Stream *s, const char *separator_cstr) const { + collection::const_iterator pos, end = m_files.end(); + for (pos = m_files.begin(); pos != end; ++pos) { + pos->Dump(s); + if (separator_cstr && ((pos + 1) != end)) + s->PutCString(separator_cstr); + } } //------------------------------------------------------------------ @@ -99,53 +82,45 @@ FileSpecList::Dump(Stream *s, const char *separator_cstr) const // Returns the valid index of the file that matches "file_spec" if // it is found, else std::numeric_limits<uint32_t>::max() is returned. //------------------------------------------------------------------ -size_t -FileSpecList::FindFileIndex (size_t start_idx, const FileSpec &file_spec, bool full, bool remove_dots) const -{ - const size_t num_files = m_files.size(); - - // When looking for files, we will compare only the filename if the - // FILE_SPEC argument is empty - bool compare_filename_only = file_spec.GetDirectory().IsEmpty(); - - for (size_t idx = start_idx; idx < num_files; ++idx) - { - if (compare_filename_only) - { - if (ConstString::Equals(m_files[idx].GetFilename(), file_spec.GetFilename(), - file_spec.IsCaseSensitive() || m_files[idx].IsCaseSensitive())) - return idx; - } - else - { - if (FileSpec::Equal (m_files[idx], file_spec, full, remove_dots)) - return idx; - } +size_t FileSpecList::FindFileIndex(size_t start_idx, const FileSpec &file_spec, + bool full, bool remove_dots) const { + const size_t num_files = m_files.size(); + + // When looking for files, we will compare only the filename if the + // FILE_SPEC argument is empty + bool compare_filename_only = file_spec.GetDirectory().IsEmpty(); + + for (size_t idx = start_idx; idx < num_files; ++idx) { + if (compare_filename_only) { + if (ConstString::Equals( + m_files[idx].GetFilename(), file_spec.GetFilename(), + file_spec.IsCaseSensitive() || m_files[idx].IsCaseSensitive())) + return idx; + } else { + if (FileSpec::Equal(m_files[idx], file_spec, full, remove_dots)) + return idx; } + } - // We didn't find the file, return an invalid index - return UINT32_MAX; + // We didn't find the file, return an invalid index + return UINT32_MAX; } //------------------------------------------------------------------ // Returns the FileSpec object at index "idx". If "idx" is out of // range, then an empty FileSpec object will be returned. //------------------------------------------------------------------ -const FileSpec & -FileSpecList::GetFileSpecAtIndex(size_t idx) const -{ - if (idx < m_files.size()) - return m_files[idx]; - static FileSpec g_empty_file_spec; - return g_empty_file_spec; +const FileSpec &FileSpecList::GetFileSpecAtIndex(size_t idx) const { + if (idx < m_files.size()) + return m_files[idx]; + static FileSpec g_empty_file_spec; + return g_empty_file_spec; } -const FileSpec * -FileSpecList::GetFileSpecPointerAtIndex(size_t idx) const -{ - if (idx < m_files.size()) - return &m_files[idx]; - return nullptr; +const FileSpec *FileSpecList::GetFileSpecPointerAtIndex(size_t idx) const { + if (idx < m_files.size()) + return &m_files[idx]; + return nullptr; } //------------------------------------------------------------------ @@ -155,32 +130,25 @@ FileSpecList::GetFileSpecPointerAtIndex(size_t idx) const // doesn't not include the string values for the directories any // filenames as those are in shared string pools. //------------------------------------------------------------------ -size_t -FileSpecList::MemorySize () const -{ - size_t mem_size = sizeof(FileSpecList); - collection::const_iterator pos, end = m_files.end(); - for (pos = m_files.begin(); pos != end; ++pos) - { - mem_size += pos->MemorySize(); - } +size_t FileSpecList::MemorySize() const { + size_t mem_size = sizeof(FileSpecList); + collection::const_iterator pos, end = m_files.end(); + for (pos = m_files.begin(); pos != end; ++pos) { + mem_size += pos->MemorySize(); + } - return mem_size; + return mem_size; } //------------------------------------------------------------------ // Return the number of files in the file spec list. //------------------------------------------------------------------ -size_t -FileSpecList::GetSize() const -{ - return m_files.size(); -} +size_t FileSpecList::GetSize() const { return m_files.size(); } -size_t -FileSpecList::GetFilesMatchingPartialPath (const char *path, bool dir_okay, FileSpecList &matches) -{ -#if 0 // FIXME: Just sketching... +size_t FileSpecList::GetFilesMatchingPartialPath(const char *path, + bool dir_okay, + FileSpecList &matches) { +#if 0 // FIXME: Just sketching... matches.Clear(); FileSpec path_spec = FileSpec (path); if (path_spec.Exists ()) @@ -220,5 +188,5 @@ FileSpecList::GetFilesMatchingPartialPath (const char *path, bool dir_okay, File } } #endif - return 0; + return 0; } diff --git a/source/Core/FormatEntity.cpp b/source/Core/FormatEntity.cpp index e2097cc72b85..08166d208aee 100644 --- a/source/Core/FormatEntity.cpp +++ b/source/Core/FormatEntity.cpp @@ -49,251 +49,245 @@ using namespace lldb; using namespace lldb_private; -enum FileKind -{ - FileError = 0, - Basename, - Dirname, - Fullpath +enum FileKind { FileError = 0, Basename, Dirname, Fullpath }; + +#define ENTRY(n, t, f) \ + { \ + n, nullptr, FormatEntity::Entry::Type::t, \ + FormatEntity::Entry::FormatType::f, 0, 0, nullptr, false \ + } +#define ENTRY_VALUE(n, t, f, v) \ + { \ + n, nullptr, FormatEntity::Entry::Type::t, \ + FormatEntity::Entry::FormatType::f, v, 0, nullptr, false \ + } +#define ENTRY_CHILDREN(n, t, f, c) \ + { \ + n, nullptr, FormatEntity::Entry::Type::t, \ + FormatEntity::Entry::FormatType::f, 0, llvm::array_lengthof(c), c, \ + false \ + } +#define ENTRY_CHILDREN_KEEP_SEP(n, t, f, c) \ + { \ + n, nullptr, FormatEntity::Entry::Type::t, \ + FormatEntity::Entry::FormatType::f, 0, llvm::array_lengthof(c), c, \ + true \ + } +#define ENTRY_STRING(n, s) \ + { \ + n, s, FormatEntity::Entry::Type::InsertString, \ + FormatEntity::Entry::FormatType::None, 0, 0, nullptr, false \ + } +static FormatEntity::Entry::Definition g_string_entry[] = { + ENTRY("*", ParentString, None)}; + +static FormatEntity::Entry::Definition g_addr_entries[] = { + ENTRY("load", AddressLoad, UInt64), ENTRY("file", AddressFile, UInt64), + ENTRY("load", AddressLoadOrFile, UInt64), }; -#define ENTRY(n,t,f) { n, nullptr, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0, 0, nullptr, false} -#define ENTRY_VALUE(n,t,f,v) { n, nullptr, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, v, 0, nullptr, false} -#define ENTRY_CHILDREN(n,t,f,c) { n, nullptr, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0, llvm::array_lengthof(c), c, false} -#define ENTRY_CHILDREN_KEEP_SEP(n,t,f,c) { n, nullptr, FormatEntity::Entry::Type::t, FormatEntity::Entry::FormatType::f, 0, llvm::array_lengthof(c), c, true} -#define ENTRY_STRING(n,s) { n, s, FormatEntity::Entry::Type::InsertString, FormatEntity::Entry::FormatType::None, 0, 0, nullptr, false} -static FormatEntity::Entry::Definition g_string_entry[] = -{ - ENTRY("*", ParentString, None) -}; - -static FormatEntity::Entry::Definition g_addr_entries[] = -{ - ENTRY ("load", AddressLoad , UInt64), - ENTRY ("file", AddressFile , UInt64), - ENTRY ("load", AddressLoadOrFile, UInt64), -}; - -static FormatEntity::Entry::Definition g_file_child_entries[] = -{ +static FormatEntity::Entry::Definition g_file_child_entries[] = { ENTRY_VALUE("basename", ParentNumber, CString, FileKind::Basename), ENTRY_VALUE("dirname", ParentNumber, CString, FileKind::Dirname), - ENTRY_VALUE("fullpath", ParentNumber, CString, FileKind::Fullpath) -}; - -static FormatEntity::Entry::Definition g_frame_child_entries[] = -{ - ENTRY ("index", FrameIndex , UInt32), - ENTRY ("pc" , FrameRegisterPC , UInt64), - ENTRY ("fp" , FrameRegisterFP , UInt64), - ENTRY ("sp" , FrameRegisterSP , UInt64), - ENTRY ("flags", FrameRegisterFlags, UInt64), - ENTRY_CHILDREN ("reg", FrameRegisterByName, UInt64, g_string_entry), + ENTRY_VALUE("fullpath", ParentNumber, CString, FileKind::Fullpath)}; + +static FormatEntity::Entry::Definition g_frame_child_entries[] = { + ENTRY("index", FrameIndex, UInt32), + ENTRY("pc", FrameRegisterPC, UInt64), + ENTRY("fp", FrameRegisterFP, UInt64), + ENTRY("sp", FrameRegisterSP, UInt64), + ENTRY("flags", FrameRegisterFlags, UInt64), + ENTRY("no-debug", FrameNoDebug, None), + ENTRY_CHILDREN("reg", FrameRegisterByName, UInt64, g_string_entry), }; -static FormatEntity::Entry::Definition g_function_child_entries[] = -{ - ENTRY ("id" , FunctionID , UInt64), - ENTRY ("name" , FunctionName , CString), - ENTRY ("name-without-args" , FunctionNameNoArgs , CString), - ENTRY ("name-with-args" , FunctionNameWithArgs , CString), - ENTRY ("addr-offset" , FunctionAddrOffset , UInt64), - ENTRY ("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete, UInt64), - ENTRY ("line-offset" , FunctionLineOffset , UInt64), - ENTRY ("pc-offset" , FunctionPCOffset , UInt64), - ENTRY ("initial-function" , FunctionInitial , None), - ENTRY ("changed" , FunctionChanged , None), - ENTRY ("is-optimized" , FunctionIsOptimized , None) +static FormatEntity::Entry::Definition g_function_child_entries[] = { + ENTRY("id", FunctionID, UInt64), ENTRY("name", FunctionName, CString), + ENTRY("name-without-args", FunctionNameNoArgs, CString), + ENTRY("name-with-args", FunctionNameWithArgs, CString), + ENTRY("addr-offset", FunctionAddrOffset, UInt64), + ENTRY("concrete-only-addr-offset-no-padding", FunctionAddrOffsetConcrete, + UInt64), + ENTRY("line-offset", FunctionLineOffset, UInt64), + ENTRY("pc-offset", FunctionPCOffset, UInt64), + ENTRY("initial-function", FunctionInitial, None), + ENTRY("changed", FunctionChanged, None), + ENTRY("is-optimized", FunctionIsOptimized, None)}; + +static FormatEntity::Entry::Definition g_line_child_entries[] = { + ENTRY_CHILDREN("file", LineEntryFile, None, g_file_child_entries), + ENTRY("number", LineEntryLineNumber, UInt32), + ENTRY("start-addr", LineEntryStartAddress, UInt64), + ENTRY("end-addr", LineEntryEndAddress, UInt64), }; -static FormatEntity::Entry::Definition g_line_child_entries[] = -{ - ENTRY_CHILDREN("file", LineEntryFile , None , g_file_child_entries), - ENTRY("number" , LineEntryLineNumber , UInt32), - ENTRY("start-addr" , LineEntryStartAddress, UInt64), - ENTRY("end-addr" , LineEntryEndAddress , UInt64), -}; - -static FormatEntity::Entry::Definition g_module_child_entries[] = -{ +static FormatEntity::Entry::Definition g_module_child_entries[] = { ENTRY_CHILDREN("file", ModuleFile, None, g_file_child_entries), }; -static FormatEntity::Entry::Definition g_process_child_entries[] = -{ - ENTRY ( "id" , ProcessID , UInt64 ), - ENTRY_VALUE ( "name" , ProcessFile , CString , FileKind::Basename), - ENTRY_CHILDREN ( "file" , ProcessFile , None , g_file_child_entries), +static FormatEntity::Entry::Definition g_process_child_entries[] = { + ENTRY("id", ProcessID, UInt64), + ENTRY_VALUE("name", ProcessFile, CString, FileKind::Basename), + ENTRY_CHILDREN("file", ProcessFile, None, g_file_child_entries), }; -static FormatEntity::Entry::Definition g_svar_child_entries[] = -{ - ENTRY ( "*" , ParentString , None) +static FormatEntity::Entry::Definition g_svar_child_entries[] = { + ENTRY("*", ParentString, None)}; + +static FormatEntity::Entry::Definition g_var_child_entries[] = { + ENTRY("*", ParentString, None)}; + +static FormatEntity::Entry::Definition g_thread_child_entries[] = { + ENTRY("id", ThreadID, UInt64), + ENTRY("protocol_id", ThreadProtocolID, UInt64), + ENTRY("index", ThreadIndexID, UInt32), + ENTRY_CHILDREN("info", ThreadInfo, None, g_string_entry), + ENTRY("queue", ThreadQueue, CString), + ENTRY("name", ThreadName, CString), + ENTRY("stop-reason", ThreadStopReason, CString), + ENTRY("return-value", ThreadReturnValue, CString), + ENTRY("completed-expression", ThreadCompletedExpression, CString), }; -static FormatEntity::Entry::Definition g_var_child_entries[] = -{ - ENTRY ( "*" , ParentString , None) -}; - -static FormatEntity::Entry::Definition g_thread_child_entries[] = -{ - ENTRY ( "id" , ThreadID , UInt64 ), - ENTRY ( "protocol_id" , ThreadProtocolID , UInt64 ), - ENTRY ( "index" , ThreadIndexID , UInt32 ), - ENTRY_CHILDREN ( "info" , ThreadInfo , None , g_string_entry), - ENTRY ( "queue" , ThreadQueue , CString ), - ENTRY ( "name" , ThreadName , CString ), - ENTRY ( "stop-reason" , ThreadStopReason , CString ), - ENTRY ( "return-value" , ThreadReturnValue , CString ), - ENTRY ( "completed-expression", ThreadCompletedExpression , CString ), -}; - -static FormatEntity::Entry::Definition g_target_child_entries[] = -{ - ENTRY ( "arch" , TargetArch , CString ), +static FormatEntity::Entry::Definition g_target_child_entries[] = { + ENTRY("arch", TargetArch, CString), }; #define _TO_STR2(_val) #_val #define _TO_STR(_val) _TO_STR2(_val) -static FormatEntity::Entry::Definition g_ansi_fg_entries[] = -{ - ENTRY_STRING ("black" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END), - ENTRY_STRING ("red" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END), - ENTRY_STRING ("green" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END), - ENTRY_STRING ("yellow" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END), - ENTRY_STRING ("blue" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END), - ENTRY_STRING ("purple" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END), - ENTRY_STRING ("cyan" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END), - ENTRY_STRING ("white" , ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END), +static FormatEntity::Entry::Definition g_ansi_fg_entries[] = { + ENTRY_STRING("black", + ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLACK) ANSI_ESC_END), + ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_RED) ANSI_ESC_END), + ENTRY_STRING("green", + ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_GREEN) ANSI_ESC_END), + ENTRY_STRING("yellow", + ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_YELLOW) ANSI_ESC_END), + ENTRY_STRING("blue", + ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_BLUE) ANSI_ESC_END), + ENTRY_STRING("purple", + ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_PURPLE) ANSI_ESC_END), + ENTRY_STRING("cyan", + ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_CYAN) ANSI_ESC_END), + ENTRY_STRING("white", + ANSI_ESC_START _TO_STR(ANSI_FG_COLOR_WHITE) ANSI_ESC_END), }; -static FormatEntity::Entry::Definition g_ansi_bg_entries[] = -{ - ENTRY_STRING ("black" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END), - ENTRY_STRING ("red" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END), - ENTRY_STRING ("green" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END), - ENTRY_STRING ("yellow" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END), - ENTRY_STRING ("blue" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END), - ENTRY_STRING ("purple" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END), - ENTRY_STRING ("cyan" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END), - ENTRY_STRING ("white" , ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END), +static FormatEntity::Entry::Definition g_ansi_bg_entries[] = { + ENTRY_STRING("black", + ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLACK) ANSI_ESC_END), + ENTRY_STRING("red", ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_RED) ANSI_ESC_END), + ENTRY_STRING("green", + ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_GREEN) ANSI_ESC_END), + ENTRY_STRING("yellow", + ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_YELLOW) ANSI_ESC_END), + ENTRY_STRING("blue", + ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_BLUE) ANSI_ESC_END), + ENTRY_STRING("purple", + ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_PURPLE) ANSI_ESC_END), + ENTRY_STRING("cyan", + ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_CYAN) ANSI_ESC_END), + ENTRY_STRING("white", + ANSI_ESC_START _TO_STR(ANSI_BG_COLOR_WHITE) ANSI_ESC_END), }; -static FormatEntity::Entry::Definition g_ansi_entries[] = -{ - ENTRY_CHILDREN ( "fg" , Invalid , None , g_ansi_fg_entries), - ENTRY_CHILDREN ( "bg" , Invalid , None , g_ansi_bg_entries), - ENTRY_STRING ( "normal" , ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END), - ENTRY_STRING ( "bold" , ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END), - ENTRY_STRING ( "faint" , ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END), - ENTRY_STRING ( "italic" , ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END), - ENTRY_STRING ( "underline" , ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END), - ENTRY_STRING ( "slow-blink" , ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END), - ENTRY_STRING ( "fast-blink" , ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END), - ENTRY_STRING ( "negative" , ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END), - ENTRY_STRING ( "conceal" , ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END), - ENTRY_STRING ( "crossed-out" , ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END), +static FormatEntity::Entry::Definition g_ansi_entries[] = { + ENTRY_CHILDREN("fg", Invalid, None, g_ansi_fg_entries), + ENTRY_CHILDREN("bg", Invalid, None, g_ansi_bg_entries), + ENTRY_STRING("normal", + ANSI_ESC_START _TO_STR(ANSI_CTRL_NORMAL) ANSI_ESC_END), + ENTRY_STRING("bold", ANSI_ESC_START _TO_STR(ANSI_CTRL_BOLD) ANSI_ESC_END), + ENTRY_STRING("faint", ANSI_ESC_START _TO_STR(ANSI_CTRL_FAINT) ANSI_ESC_END), + ENTRY_STRING("italic", + ANSI_ESC_START _TO_STR(ANSI_CTRL_ITALIC) ANSI_ESC_END), + ENTRY_STRING("underline", + ANSI_ESC_START _TO_STR(ANSI_CTRL_UNDERLINE) ANSI_ESC_END), + ENTRY_STRING("slow-blink", + ANSI_ESC_START _TO_STR(ANSI_CTRL_SLOW_BLINK) ANSI_ESC_END), + ENTRY_STRING("fast-blink", + ANSI_ESC_START _TO_STR(ANSI_CTRL_FAST_BLINK) ANSI_ESC_END), + ENTRY_STRING("negative", + ANSI_ESC_START _TO_STR(ANSI_CTRL_IMAGE_NEGATIVE) ANSI_ESC_END), + ENTRY_STRING("conceal", + ANSI_ESC_START _TO_STR(ANSI_CTRL_CONCEAL) ANSI_ESC_END), + ENTRY_STRING("crossed-out", + ANSI_ESC_START _TO_STR(ANSI_CTRL_CROSSED_OUT) ANSI_ESC_END), }; -static FormatEntity::Entry::Definition g_script_child_entries[] = -{ - ENTRY ( "frame" , ScriptFrame , None), - ENTRY ( "process" , ScriptProcess , None), - ENTRY ( "target" , ScriptTarget , None), - ENTRY ( "thread" , ScriptThread , None), - ENTRY ( "var" , ScriptVariable , None), - ENTRY ( "svar" , ScriptVariableSynthetic , None), - ENTRY ( "thread" , ScriptThread , None), +static FormatEntity::Entry::Definition g_script_child_entries[] = { + ENTRY("frame", ScriptFrame, None), + ENTRY("process", ScriptProcess, None), + ENTRY("target", ScriptTarget, None), + ENTRY("thread", ScriptThread, None), + ENTRY("var", ScriptVariable, None), + ENTRY("svar", ScriptVariableSynthetic, None), + ENTRY("thread", ScriptThread, None), }; -static FormatEntity::Entry::Definition g_top_level_entries[] = -{ - ENTRY_CHILDREN ("addr" , AddressLoadOrFile , UInt64 , g_addr_entries), - ENTRY ("addr-file-or-load" , AddressLoadOrFile , UInt64 ), - ENTRY_CHILDREN ("ansi" , Invalid , None , g_ansi_entries), - ENTRY ("current-pc-arrow" , CurrentPCArrow , CString ), - ENTRY_CHILDREN ("file" , File , CString , g_file_child_entries), - ENTRY ("language" , Lang , CString), - ENTRY_CHILDREN ("frame" , Invalid , None , g_frame_child_entries), - ENTRY_CHILDREN ("function" , Invalid , None , g_function_child_entries), - ENTRY_CHILDREN ("line" , Invalid , None , g_line_child_entries), - ENTRY_CHILDREN ("module" , Invalid , None , g_module_child_entries), - ENTRY_CHILDREN ("process" , Invalid , None , g_process_child_entries), - ENTRY_CHILDREN ("script" , Invalid , None , g_script_child_entries), - ENTRY_CHILDREN_KEEP_SEP ("svar" , VariableSynthetic , None , g_svar_child_entries), - ENTRY_CHILDREN ("thread" , Invalid , None , g_thread_child_entries), - ENTRY_CHILDREN ("target" , Invalid , None , g_target_child_entries), - ENTRY_CHILDREN_KEEP_SEP ("var" , Variable , None , g_var_child_entries), +static FormatEntity::Entry::Definition g_top_level_entries[] = { + ENTRY_CHILDREN("addr", AddressLoadOrFile, UInt64, g_addr_entries), + ENTRY("addr-file-or-load", AddressLoadOrFile, UInt64), + ENTRY_CHILDREN("ansi", Invalid, None, g_ansi_entries), + ENTRY("current-pc-arrow", CurrentPCArrow, CString), + ENTRY_CHILDREN("file", File, CString, g_file_child_entries), + ENTRY("language", Lang, CString), + ENTRY_CHILDREN("frame", Invalid, None, g_frame_child_entries), + ENTRY_CHILDREN("function", Invalid, None, g_function_child_entries), + ENTRY_CHILDREN("line", Invalid, None, g_line_child_entries), + ENTRY_CHILDREN("module", Invalid, None, g_module_child_entries), + ENTRY_CHILDREN("process", Invalid, None, g_process_child_entries), + ENTRY_CHILDREN("script", Invalid, None, g_script_child_entries), + ENTRY_CHILDREN_KEEP_SEP("svar", VariableSynthetic, None, + g_svar_child_entries), + ENTRY_CHILDREN("thread", Invalid, None, g_thread_child_entries), + ENTRY_CHILDREN("target", Invalid, None, g_target_child_entries), + ENTRY_CHILDREN_KEEP_SEP("var", Variable, None, g_var_child_entries), }; -static FormatEntity::Entry::Definition g_root = ENTRY_CHILDREN ("<root>", Root, None, g_top_level_entries); - -FormatEntity::Entry::Entry (llvm::StringRef s) : - string (s.data(), s.size()), - printf_format (), - children (), - definition(nullptr), - type (Type::String), - fmt (lldb::eFormatDefault), - number (0), - deref (false) -{ -} +static FormatEntity::Entry::Definition g_root = + ENTRY_CHILDREN("<root>", Root, None, g_top_level_entries); -FormatEntity::Entry::Entry (char ch) : - string (1, ch), - printf_format (), - children (), - definition(nullptr), - type (Type::String), - fmt (lldb::eFormatDefault), - number (0), - deref (false) -{ -} +FormatEntity::Entry::Entry(llvm::StringRef s) + : string(s.data(), s.size()), printf_format(), children(), + definition(nullptr), type(Type::String), fmt(lldb::eFormatDefault), + number(0), deref(false) {} -void -FormatEntity::Entry::AppendChar (char ch) -{ - if (children.empty() || children.back().type != Entry::Type::String) - children.push_back(Entry(ch)); - else - children.back().string.append(1, ch); +FormatEntity::Entry::Entry(char ch) + : string(1, ch), printf_format(), children(), definition(nullptr), + type(Type::String), fmt(lldb::eFormatDefault), number(0), deref(false) {} + +void FormatEntity::Entry::AppendChar(char ch) { + if (children.empty() || children.back().type != Entry::Type::String) + children.push_back(Entry(ch)); + else + children.back().string.append(1, ch); } -void -FormatEntity::Entry::AppendText (const llvm::StringRef &s) -{ - if (children.empty() || children.back().type != Entry::Type::String) - children.push_back(Entry(s)); - else - children.back().string.append(s.data(), s.size()); +void FormatEntity::Entry::AppendText(const llvm::StringRef &s) { + if (children.empty() || children.back().type != Entry::Type::String) + children.push_back(Entry(s)); + else + children.back().string.append(s.data(), s.size()); } -void -FormatEntity::Entry::AppendText (const char *cstr) -{ - return AppendText (llvm::StringRef(cstr)); +void FormatEntity::Entry::AppendText(const char *cstr) { + return AppendText(llvm::StringRef(cstr)); } -Error -FormatEntity::Parse (const llvm::StringRef &format_str, Entry &entry) -{ - entry.Clear(); - entry.type = Entry::Type::Root; - llvm::StringRef modifiable_format (format_str); - return ParseInternal (modifiable_format, entry, 0); +Error FormatEntity::Parse(const llvm::StringRef &format_str, Entry &entry) { + entry.Clear(); + entry.type = Entry::Type::Root; + llvm::StringRef modifiable_format(format_str); + return ParseInternal(modifiable_format, entry, 0); } -#define ENUM_TO_CSTR(eee) case FormatEntity::Entry::Type::eee: return #eee +#define ENUM_TO_CSTR(eee) \ + case FormatEntity::Entry::Type::eee: \ + return #eee -const char * -FormatEntity::Entry::TypeToCString (Type t) -{ - switch (t) - { +const char *FormatEntity::Entry::TypeToCString(Type t) { + switch (t) { ENUM_TO_CSTR(Invalid); ENUM_TO_CSTR(ParentNumber); ENUM_TO_CSTR(ParentString); @@ -327,6 +321,7 @@ FormatEntity::Entry::TypeToCString (Type t) ENUM_TO_CSTR(File); ENUM_TO_CSTR(Lang); ENUM_TO_CSTR(FrameIndex); + ENUM_TO_CSTR(FrameNoDebug); ENUM_TO_CSTR(FrameRegisterPC); ENUM_TO_CSTR(FrameRegisterSP); ENUM_TO_CSTR(FrameRegisterFP); @@ -351,2280 +346,2044 @@ FormatEntity::Entry::TypeToCString (Type t) ENUM_TO_CSTR(LineEntryStartAddress); ENUM_TO_CSTR(LineEntryEndAddress); ENUM_TO_CSTR(CurrentPCArrow); - } - return "???"; + } + return "???"; } #undef ENUM_TO_CSTR -void -FormatEntity::Entry::Dump (Stream &s, int depth) const -{ - s.Printf ("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type)); - if (fmt != eFormatDefault) - s.Printf ("lldb-format = %s, ", FormatManager::GetFormatAsCString (fmt)); - if (!string.empty()) - s.Printf ("string = \"%s\"", string.c_str()); - if (!printf_format.empty()) - s.Printf ("printf_format = \"%s\"", printf_format.c_str()); - if (number != 0) - s.Printf ("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number); - if (deref) - s.Printf ("deref = true, "); - s.EOL(); - for (const auto &child : children) - { - child.Dump(s, depth + 1); - } +void FormatEntity::Entry::Dump(Stream &s, int depth) const { + s.Printf("%*.*s%-20s: ", depth * 2, depth * 2, "", TypeToCString(type)); + if (fmt != eFormatDefault) + s.Printf("lldb-format = %s, ", FormatManager::GetFormatAsCString(fmt)); + if (!string.empty()) + s.Printf("string = \"%s\"", string.c_str()); + if (!printf_format.empty()) + s.Printf("printf_format = \"%s\"", printf_format.c_str()); + if (number != 0) + s.Printf("number = %" PRIu64 " (0x%" PRIx64 "), ", number, number); + if (deref) + s.Printf("deref = true, "); + s.EOL(); + for (const auto &child : children) { + child.Dump(s, depth + 1); + } } template <typename T> -static bool RunScriptFormatKeyword(Stream &s, - const SymbolContext *sc, - const ExecutionContext *exe_ctx, - T t, - const char *script_function_name) -{ - Target *target = Target::GetTargetFromContexts (exe_ctx, sc); - - if (target) - { - ScriptInterpreter *script_interpreter = target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); - if (script_interpreter) - { - Error error; - std::string script_output; - - if (script_interpreter->RunScriptFormatKeyword(script_function_name, t, script_output, error) && error.Success()) - { - s.Printf("%s", script_output.c_str()); - return true; - } - else - { - s.Printf("<error: %s>",error.AsCString()); - } - } +static bool RunScriptFormatKeyword(Stream &s, const SymbolContext *sc, + const ExecutionContext *exe_ctx, T t, + const char *script_function_name) { + Target *target = Target::GetTargetFromContexts(exe_ctx, sc); + + if (target) { + ScriptInterpreter *script_interpreter = + target->GetDebugger().GetCommandInterpreter().GetScriptInterpreter(); + if (script_interpreter) { + Error error; + std::string script_output; + + if (script_interpreter->RunScriptFormatKeyword(script_function_name, t, + script_output, error) && + error.Success()) { + s.Printf("%s", script_output.c_str()); + return true; + } else { + s.Printf("<error: %s>", error.AsCString()); + } } - return false; + } + return false; } -static bool -DumpAddress (Stream &s, - const SymbolContext *sc, - const ExecutionContext *exe_ctx, - const Address &addr, - bool print_file_addr_or_load_addr) -{ - Target *target = Target::GetTargetFromContexts (exe_ctx, sc); - addr_t vaddr = LLDB_INVALID_ADDRESS; - if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) - vaddr = addr.GetLoadAddress (target); - if (vaddr == LLDB_INVALID_ADDRESS) - vaddr = addr.GetFileAddress (); - - if (vaddr != LLDB_INVALID_ADDRESS) - { - int addr_width = 0; - if (exe_ctx && target) - { - addr_width = target->GetArchitecture().GetAddressByteSize() * 2; - } - if (addr_width == 0) - addr_width = 16; - if (print_file_addr_or_load_addr) - { - ExecutionContextScope *exe_scope = nullptr; - if (exe_ctx) - exe_scope = exe_ctx->GetBestExecutionContextScope(); - addr.Dump (&s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0); - } - else - { - s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); - } - return true; +static bool DumpAddress(Stream &s, const SymbolContext *sc, + const ExecutionContext *exe_ctx, const Address &addr, + bool print_file_addr_or_load_addr) { + Target *target = Target::GetTargetFromContexts(exe_ctx, sc); + addr_t vaddr = LLDB_INVALID_ADDRESS; + if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) + vaddr = addr.GetLoadAddress(target); + if (vaddr == LLDB_INVALID_ADDRESS) + vaddr = addr.GetFileAddress(); + + if (vaddr != LLDB_INVALID_ADDRESS) { + int addr_width = 0; + if (exe_ctx && target) { + addr_width = target->GetArchitecture().GetAddressByteSize() * 2; } - return false; + if (addr_width == 0) + addr_width = 16; + if (print_file_addr_or_load_addr) { + ExecutionContextScope *exe_scope = nullptr; + if (exe_ctx) + exe_scope = exe_ctx->GetBestExecutionContextScope(); + addr.Dump(&s, exe_scope, Address::DumpStyleLoadAddress, + Address::DumpStyleModuleWithFileAddress, 0); + } else { + s.Printf("0x%*.*" PRIx64, addr_width, addr_width, vaddr); + } + return true; + } + return false; } -static bool -DumpAddressOffsetFromFunction (Stream &s, - const SymbolContext *sc, - const ExecutionContext *exe_ctx, - const Address &format_addr, - bool concrete_only, - bool no_padding, - bool print_zero_offsets) -{ - if (format_addr.IsValid()) - { - Address func_addr; - - if (sc) - { - if (sc->function) - { - func_addr = sc->function->GetAddressRange().GetBaseAddress(); - if (sc->block && !concrete_only) - { - // Check to make sure we aren't in an inline - // function. If we are, use the inline block - // range that contains "format_addr" since - // blocks can be discontiguous. - Block *inline_block = sc->block->GetContainingInlinedBlock (); - AddressRange inline_range; - if (inline_block && inline_block->GetRangeContainingAddress (format_addr, inline_range)) - func_addr = inline_range.GetBaseAddress(); - } - } - else if (sc->symbol && sc->symbol->ValueIsAddress()) - func_addr = sc->symbol->GetAddressRef(); +static bool DumpAddressOffsetFromFunction(Stream &s, const SymbolContext *sc, + const ExecutionContext *exe_ctx, + const Address &format_addr, + bool concrete_only, bool no_padding, + bool print_zero_offsets) { + if (format_addr.IsValid()) { + Address func_addr; + + if (sc) { + if (sc->function) { + func_addr = sc->function->GetAddressRange().GetBaseAddress(); + if (sc->block && !concrete_only) { + // Check to make sure we aren't in an inline + // function. If we are, use the inline block + // range that contains "format_addr" since + // blocks can be discontiguous. + Block *inline_block = sc->block->GetContainingInlinedBlock(); + AddressRange inline_range; + if (inline_block && + inline_block->GetRangeContainingAddress(format_addr, + inline_range)) + func_addr = inline_range.GetBaseAddress(); } + } else if (sc->symbol && sc->symbol->ValueIsAddress()) + func_addr = sc->symbol->GetAddressRef(); + } - if (func_addr.IsValid()) - { - const char *addr_offset_padding = no_padding ? "" : " "; - - if (func_addr.GetSection() == format_addr.GetSection()) - { - addr_t func_file_addr = func_addr.GetFileAddress(); - addr_t addr_file_addr = format_addr.GetFileAddress(); - if (addr_file_addr > func_file_addr - || (addr_file_addr == func_file_addr && print_zero_offsets)) - { - s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_file_addr - func_file_addr); - } - else if (addr_file_addr < func_file_addr) - { - s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_file_addr - addr_file_addr); - } - return true; - } - else - { - Target *target = Target::GetTargetFromContexts (exe_ctx, sc); - if (target) - { - addr_t func_load_addr = func_addr.GetLoadAddress (target); - addr_t addr_load_addr = format_addr.GetLoadAddress (target); - if (addr_load_addr > func_load_addr - || (addr_load_addr == func_load_addr && print_zero_offsets)) - { - s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, addr_load_addr - func_load_addr); - } - else if (addr_load_addr < func_load_addr) - { - s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, func_load_addr - addr_load_addr); - } - return true; - } - } + if (func_addr.IsValid()) { + const char *addr_offset_padding = no_padding ? "" : " "; + + if (func_addr.GetSection() == format_addr.GetSection()) { + addr_t func_file_addr = func_addr.GetFileAddress(); + addr_t addr_file_addr = format_addr.GetFileAddress(); + if (addr_file_addr > func_file_addr || + (addr_file_addr == func_file_addr && print_zero_offsets)) { + s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, + addr_file_addr - func_file_addr); + } else if (addr_file_addr < func_file_addr) { + s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, + func_file_addr - addr_file_addr); + } + return true; + } else { + Target *target = Target::GetTargetFromContexts(exe_ctx, sc); + if (target) { + addr_t func_load_addr = func_addr.GetLoadAddress(target); + addr_t addr_load_addr = format_addr.GetLoadAddress(target); + if (addr_load_addr > func_load_addr || + (addr_load_addr == func_load_addr && print_zero_offsets)) { + s.Printf("%s+%s%" PRIu64, addr_offset_padding, addr_offset_padding, + addr_load_addr - func_load_addr); + } else if (addr_load_addr < func_load_addr) { + s.Printf("%s-%s%" PRIu64, addr_offset_padding, addr_offset_padding, + func_load_addr - addr_load_addr); + } + return true; } + } } - return false; + } + return false; } -static bool -ScanBracketedRange (llvm::StringRef subpath, - size_t& close_bracket_index, - const char*& var_name_final_if_array_range, - int64_t& index_lower, - int64_t& index_higher) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); - close_bracket_index = llvm::StringRef::npos; - const size_t open_bracket_index = subpath.find('['); - if (open_bracket_index == llvm::StringRef::npos) - { +static bool ScanBracketedRange(llvm::StringRef subpath, + size_t &close_bracket_index, + const char *&var_name_final_if_array_range, + int64_t &index_lower, int64_t &index_higher) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); + close_bracket_index = llvm::StringRef::npos; + const size_t open_bracket_index = subpath.find('['); + if (open_bracket_index == llvm::StringRef::npos) { + if (log) + log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); + return false; + } + + close_bracket_index = subpath.find(']', open_bracket_index + 1); + + if (close_bracket_index == llvm::StringRef::npos) { + if (log) + log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); + return false; + } else { + var_name_final_if_array_range = subpath.data() + open_bracket_index; + + if (close_bracket_index - open_bracket_index == 1) { + if (log) + log->Printf( + "[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); + index_lower = 0; + } else { + const size_t separator_index = subpath.find('-', open_bracket_index + 1); + + if (separator_index == llvm::StringRef::npos) { + const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; + index_lower = ::strtoul(index_lower_cstr, nullptr, 0); + index_higher = index_lower; if (log) - log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); - return false; + log->Printf("[ScanBracketedRange] [%" PRId64 + "] detected, high index is same", + index_lower); + } else { + const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; + const char *index_higher_cstr = subpath.data() + separator_index + 1; + index_lower = ::strtoul(index_lower_cstr, nullptr, 0); + index_higher = ::strtoul(index_higher_cstr, nullptr, 0); + if (log) + log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", + index_lower, index_higher); + } + if (index_lower > index_higher && index_higher > 0) { + if (log) + log->Printf("[ScanBracketedRange] swapping indices"); + const int64_t temp = index_lower; + index_lower = index_higher; + index_higher = temp; + } } + } + return true; +} - close_bracket_index = subpath.find(']', open_bracket_index + 1); +static bool DumpFile(Stream &s, const FileSpec &file, FileKind file_kind) { + switch (file_kind) { + case FileKind::FileError: + break; - if (close_bracket_index == llvm::StringRef::npos) - { - if (log) - log->Printf("[ScanBracketedRange] no bracketed range, skipping entirely"); - return false; + case FileKind::Basename: + if (file.GetFilename()) { + s << file.GetFilename(); + return true; } - else - { - var_name_final_if_array_range = subpath.data() + open_bracket_index; + break; - if (close_bracket_index - open_bracket_index == 1) - { - if (log) - log->Printf("[ScanBracketedRange] '[]' detected.. going from 0 to end of data"); - index_lower = 0; - } - else - { - const size_t separator_index = subpath.find('-', open_bracket_index + 1); - - if (separator_index == llvm::StringRef::npos) - { - const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; - index_lower = ::strtoul(index_lower_cstr, nullptr, 0); - index_higher = index_lower; - if (log) - log->Printf("[ScanBracketedRange] [%" PRId64 "] detected, high index is same", index_lower); - } - else - { - const char *index_lower_cstr = subpath.data() + open_bracket_index + 1; - const char *index_higher_cstr = subpath.data() + separator_index + 1; - index_lower = ::strtoul(index_lower_cstr, nullptr, 0); - index_higher = ::strtoul(index_higher_cstr, nullptr, 0); - if (log) - log->Printf("[ScanBracketedRange] [%" PRId64 "-%" PRId64 "] detected", index_lower, index_higher); - } - if (index_lower > index_higher && index_higher > 0) - { - if (log) - log->Printf("[ScanBracketedRange] swapping indices"); - const int64_t temp = index_lower; - index_lower = index_higher; - index_higher = temp; - } - } + case FileKind::Dirname: + if (file.GetDirectory()) { + s << file.GetDirectory(); + return true; } - return true; + break; + + case FileKind::Fullpath: + if (file) { + s << file; + return true; + } + break; + } + return false; } -static bool -DumpFile (Stream &s, const FileSpec &file, FileKind file_kind) -{ - switch (file_kind) - { - case FileKind::FileError: - break; +static bool DumpRegister(Stream &s, StackFrame *frame, RegisterKind reg_kind, + uint32_t reg_num, Format format) - case FileKind::Basename: - if (file.GetFilename()) - { - s << file.GetFilename(); +{ + if (frame) { + RegisterContext *reg_ctx = frame->GetRegisterContext().get(); + + if (reg_ctx) { + const uint32_t lldb_reg_num = + reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); + if (lldb_reg_num != LLDB_INVALID_REGNUM) { + const RegisterInfo *reg_info = + reg_ctx->GetRegisterInfoAtIndex(lldb_reg_num); + if (reg_info) { + RegisterValue reg_value; + if (reg_ctx->ReadRegister(reg_info, reg_value)) { + reg_value.Dump(&s, reg_info, false, false, format); return true; + } } - break; + } + } + } + return false; +} - case FileKind::Dirname: - if (file.GetDirectory()) - { - s << file.GetDirectory(); - return true; - } - break; +static ValueObjectSP ExpandIndexedExpression(ValueObject *valobj, size_t index, + StackFrame *frame, + bool deref_pointer) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); + const char *ptr_deref_format = "[%d]"; + std::string ptr_deref_buffer(10, 0); + ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); + if (log) + log->Printf("[ExpandIndexedExpression] name to deref: %s", + ptr_deref_buffer.c_str()); + ValueObject::GetValueForExpressionPathOptions options; + ValueObject::ExpressionPathEndResultType final_value_type; + ValueObject::ExpressionPathScanEndReason reason_to_stop; + ValueObject::ExpressionPathAftermath what_next = + (deref_pointer ? ValueObject::eExpressionPathAftermathDereference + : ValueObject::eExpressionPathAftermathNothing); + ValueObjectSP item = valobj->GetValueForExpressionPath( + ptr_deref_buffer.c_str(), &reason_to_stop, &final_value_type, options, + &what_next); + if (!item) { + if (log) + log->Printf("[ExpandIndexedExpression] ERROR: why stopping = %d," + " final_value_type %d", + reason_to_stop, final_value_type); + } else { + if (log) + log->Printf("[ExpandIndexedExpression] ALL RIGHT: why stopping = %d," + " final_value_type %d", + reason_to_stop, final_value_type); + } + return item; +} - case FileKind::Fullpath: - if (file) - { - s << file; - return true; - } - break; +static char ConvertValueObjectStyleToChar( + ValueObject::ValueObjectRepresentationStyle style) { + switch (style) { + case ValueObject::eValueObjectRepresentationStyleLanguageSpecific: + return '@'; + case ValueObject::eValueObjectRepresentationStyleValue: + return 'V'; + case ValueObject::eValueObjectRepresentationStyleLocation: + return 'L'; + case ValueObject::eValueObjectRepresentationStyleSummary: + return 'S'; + case ValueObject::eValueObjectRepresentationStyleChildrenCount: + return '#'; + case ValueObject::eValueObjectRepresentationStyleType: + return 'T'; + case ValueObject::eValueObjectRepresentationStyleName: + return 'N'; + case ValueObject::eValueObjectRepresentationStyleExpressionPath: + return '>'; + } + return '\0'; +} + +static bool DumpValue(Stream &s, const SymbolContext *sc, + const ExecutionContext *exe_ctx, + const FormatEntity::Entry &entry, ValueObject *valobj) { + if (valobj == nullptr) + return false; + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); + Format custom_format = eFormatInvalid; + ValueObject::ValueObjectRepresentationStyle val_obj_display = + entry.string.empty() + ? ValueObject::eValueObjectRepresentationStyleValue + : ValueObject::eValueObjectRepresentationStyleSummary; + + bool do_deref_pointer = entry.deref; + bool is_script = false; + switch (entry.type) { + case FormatEntity::Entry::Type::ScriptVariable: + is_script = true; + break; + + case FormatEntity::Entry::Type::Variable: + custom_format = entry.fmt; + val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; + break; + + case FormatEntity::Entry::Type::ScriptVariableSynthetic: + is_script = true; + LLVM_FALLTHROUGH; + case FormatEntity::Entry::Type::VariableSynthetic: + custom_format = entry.fmt; + val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; + if (!valobj->IsSynthetic()) { + valobj = valobj->GetSyntheticValue().get(); + if (valobj == nullptr) + return false; } + break; + + default: + return false; + } + + if (valobj == nullptr) return false; -} -static bool -DumpRegister (Stream &s, - StackFrame *frame, - RegisterKind reg_kind, - uint32_t reg_num, - Format format) + ValueObject::ExpressionPathAftermath what_next = + (do_deref_pointer ? ValueObject::eExpressionPathAftermathDereference + : ValueObject::eExpressionPathAftermathNothing); + ValueObject::GetValueForExpressionPathOptions options; + options.DontCheckDotVsArrowSyntax() + .DoAllowBitfieldSyntax() + .DoAllowFragileIVar() + .SetSyntheticChildrenTraversal( + ValueObject::GetValueForExpressionPathOptions:: + SyntheticChildrenTraversal::Both); + ValueObject *target = nullptr; + const char *var_name_final_if_array_range = nullptr; + size_t close_bracket_index = llvm::StringRef::npos; + int64_t index_lower = -1; + int64_t index_higher = -1; + bool is_array_range = false; + bool was_plain_var = false; + bool was_var_format = false; + bool was_var_indexed = false; + ValueObject::ExpressionPathScanEndReason reason_to_stop = + ValueObject::eExpressionPathScanEndReasonEndOfString; + ValueObject::ExpressionPathEndResultType final_value_type = + ValueObject::eExpressionPathEndResultTypePlain; + + if (is_script) { + return RunScriptFormatKeyword(s, sc, exe_ctx, valobj, entry.string.c_str()); + } + + llvm::StringRef subpath(entry.string); + // simplest case ${var}, just print valobj's value + if (entry.string.empty()) { + if (entry.printf_format.empty() && entry.fmt == eFormatDefault && + entry.number == ValueObject::eValueObjectRepresentationStyleValue) + was_plain_var = true; + else + was_var_format = true; + target = valobj; + } else // this is ${var.something} or multiple .something nested + { + if (entry.string[0] == '[') + was_var_indexed = true; + ScanBracketedRange(subpath, close_bracket_index, + var_name_final_if_array_range, index_lower, + index_higher); -{ - if (frame) - { - RegisterContext *reg_ctx = frame->GetRegisterContext().get(); + Error error; - if (reg_ctx) - { - const uint32_t lldb_reg_num = reg_ctx->ConvertRegisterKindToRegisterNumber(reg_kind, reg_num); - if (lldb_reg_num != LLDB_INVALID_REGNUM) - { - const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoAtIndex (lldb_reg_num); - if (reg_info) - { - RegisterValue reg_value; - if (reg_ctx->ReadRegister (reg_info, reg_value)) - { - reg_value.Dump(&s, reg_info, false, false, format); - return true; - } - } - } - } + const std::string &expr_path = entry.string; + + if (log) + log->Printf("[Debugger::FormatPrompt] symbol to expand: %s", + expr_path.c_str()); + + target = + valobj + ->GetValueForExpressionPath(expr_path.c_str(), &reason_to_stop, + &final_value_type, options, &what_next) + .get(); + + if (!target) { + if (log) + log->Printf("[Debugger::FormatPrompt] ERROR: why stopping = %d," + " final_value_type %d", + reason_to_stop, final_value_type); + return false; + } else { + if (log) + log->Printf("[Debugger::FormatPrompt] ALL RIGHT: why stopping = %d," + " final_value_type %d", + reason_to_stop, final_value_type); + target = target + ->GetQualifiedRepresentationIfAvailable( + target->GetDynamicValueType(), true) + .get(); + } + } + + is_array_range = + (final_value_type == + ValueObject::eExpressionPathEndResultTypeBoundedRange || + final_value_type == + ValueObject::eExpressionPathEndResultTypeUnboundedRange); + + do_deref_pointer = + (what_next == ValueObject::eExpressionPathAftermathDereference); + + if (do_deref_pointer && !is_array_range) { + // I have not deref-ed yet, let's do it + // this happens when we are not going through + // GetValueForVariableExpressionPath + // to get to the target ValueObject + Error error; + target = target->Dereference(error).get(); + if (error.Fail()) { + if (log) + log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", + error.AsCString("unknown")); + return false; } + do_deref_pointer = false; + } + + if (!target) { + if (log) + log->Printf("[Debugger::FormatPrompt] could not calculate target for " + "prompt expression"); return false; -} + } + + // we do not want to use the summary for a bitfield of type T:n + // if we were originally dealing with just a T - that would get + // us into an endless recursion + if (target->IsBitfield() && was_var_indexed) { + // TODO: check for a (T:n)-specific summary - we should still obey that + StreamString bitfield_name; + bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), + target->GetBitfieldBitSize()); + lldb::TypeNameSpecifierImplSP type_sp( + new TypeNameSpecifierImpl(bitfield_name.GetString(), false)); + if (val_obj_display == + ValueObject::eValueObjectRepresentationStyleSummary && + !DataVisualization::GetSummaryForType(type_sp)) + val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; + } + + // TODO use flags for these + const uint32_t type_info_flags = + target->GetCompilerType().GetTypeInfo(nullptr); + bool is_array = (type_info_flags & eTypeIsArray) != 0; + bool is_pointer = (type_info_flags & eTypeIsPointer) != 0; + bool is_aggregate = target->GetCompilerType().IsAggregateType(); + + if ((is_array || is_pointer) && (!is_array_range) && + val_obj_display == + ValueObject::eValueObjectRepresentationStyleValue) // this should be + // wrong, but there + // are some + // exceptions + { + StreamString str_temp; + if (log) + log->Printf( + "[Debugger::FormatPrompt] I am into array || pointer && !range"); + + if (target->HasSpecialPrintableRepresentation(val_obj_display, + custom_format)) { + // try to use the special cases + bool success = target->DumpPrintableRepresentation( + str_temp, val_obj_display, custom_format); + if (log) + log->Printf("[Debugger::FormatPrompt] special cases did%s match", + success ? "" : "n't"); + + // should not happen + if (success) + s << str_temp.GetString(); + return true; + } else { + if (was_plain_var) // if ${var} + { + s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); + } else if (is_pointer) // if pointer, value is the address stored + { + target->DumpPrintableRepresentation( + s, val_obj_display, custom_format, + ValueObject::PrintableRepresentationSpecialCases::eDisable); + } + return true; + } + } -static ValueObjectSP -ExpandIndexedExpression (ValueObject* valobj, - size_t index, - StackFrame* frame, - bool deref_pointer) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); - const char* ptr_deref_format = "[%d]"; - std::string ptr_deref_buffer(10,0); - ::sprintf(&ptr_deref_buffer[0], ptr_deref_format, index); + // if directly trying to print ${var}, and this is an aggregate, display a + // nice + // type @ location message + if (is_aggregate && was_plain_var) { + s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); + return true; + } + + // if directly trying to print ${var%V}, and this is an aggregate, do not let + // the user do it + if (is_aggregate && + ((was_var_format && + val_obj_display == + ValueObject::eValueObjectRepresentationStyleValue))) { + s << "<invalid use of aggregate type>"; + return true; + } + + if (!is_array_range) { if (log) - log->Printf("[ExpandIndexedExpression] name to deref: %s",ptr_deref_buffer.c_str()); - const char* first_unparsed; - ValueObject::GetValueForExpressionPathOptions options; - ValueObject::ExpressionPathEndResultType final_value_type; - ValueObject::ExpressionPathScanEndReason reason_to_stop; - ValueObject::ExpressionPathAftermath what_next = (deref_pointer ? ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); - ValueObjectSP item = valobj->GetValueForExpressionPath (ptr_deref_buffer.c_str(), - &first_unparsed, - &reason_to_stop, - &final_value_type, - options, - &what_next); - if (!item) - { - if (log) - log->Printf("[ExpandIndexedExpression] ERROR: unparsed portion = %s, why stopping = %d," - " final_value_type %d", - first_unparsed, reason_to_stop, final_value_type); + log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); + return target->DumpPrintableRepresentation(s, val_obj_display, + custom_format); + } else { + if (log) + log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); + if (!is_array && !is_pointer) + return false; + if (log) + log->Printf("[Debugger::FormatPrompt] handle as array"); + StreamString special_directions_stream; + llvm::StringRef special_directions; + if (close_bracket_index != llvm::StringRef::npos && + subpath.size() > close_bracket_index) { + ConstString additional_data(subpath.drop_front(close_bracket_index + 1)); + special_directions_stream.Printf("${%svar%s", do_deref_pointer ? "*" : "", + additional_data.GetCString()); + + if (entry.fmt != eFormatDefault) { + const char format_char = + FormatManager::GetFormatAsFormatChar(entry.fmt); + if (format_char != '\0') + special_directions_stream.Printf("%%%c", format_char); + else { + const char *format_cstr = + FormatManager::GetFormatAsCString(entry.fmt); + special_directions_stream.Printf("%%%s", format_cstr); + } + } else if (entry.number != 0) { + const char style_char = ConvertValueObjectStyleToChar( + (ValueObject::ValueObjectRepresentationStyle)entry.number); + if (style_char) + special_directions_stream.Printf("%%%c", style_char); + } + special_directions_stream.PutChar('}'); + special_directions = + llvm::StringRef(special_directions_stream.GetString()); } - else - { + + // let us display items index_lower thru index_higher of this array + s.PutChar('['); + + if (index_higher < 0) + index_higher = valobj->GetNumChildren() - 1; + + uint32_t max_num_children = + target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); + + bool success = true; + for (int64_t index = index_lower; index <= index_higher; ++index) { + ValueObject *item = + ExpandIndexedExpression(target, index, exe_ctx->GetFramePtr(), false) + .get(); + + if (!item) { + if (log) + log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at " + "index %" PRId64, + index); + } else { if (log) - log->Printf("[ExpandIndexedExpression] ALL RIGHT: unparsed portion = %s, why stopping = %d," - " final_value_type %d", - first_unparsed, reason_to_stop, final_value_type); + log->Printf( + "[Debugger::FormatPrompt] special_directions for child item: %s", + special_directions.data() ? special_directions.data() : ""); + } + + if (special_directions.empty()) { + success &= item->DumpPrintableRepresentation(s, val_obj_display, + custom_format); + } else { + success &= FormatEntity::FormatStringRef( + special_directions, s, sc, exe_ctx, nullptr, item, false, false); + } + + if (--max_num_children == 0) { + s.PutCString(", ..."); + break; + } + + if (index < index_higher) + s.PutChar(','); } - return item; + s.PutChar(']'); + return success; + } } -static char -ConvertValueObjectStyleToChar(ValueObject::ValueObjectRepresentationStyle style) -{ - switch (style) - { - case ValueObject::eValueObjectRepresentationStyleLanguageSpecific: return '@'; - case ValueObject::eValueObjectRepresentationStyleValue: return 'V'; - case ValueObject::eValueObjectRepresentationStyleLocation: return 'L'; - case ValueObject::eValueObjectRepresentationStyleSummary: return 'S'; - case ValueObject::eValueObjectRepresentationStyleChildrenCount: return '#'; - case ValueObject::eValueObjectRepresentationStyleType: return 'T'; - case ValueObject::eValueObjectRepresentationStyleName: return 'N'; - case ValueObject::eValueObjectRepresentationStyleExpressionPath: return '>'; - } - return '\0'; +static bool DumpRegister(Stream &s, StackFrame *frame, const char *reg_name, + Format format) { + if (frame) { + RegisterContext *reg_ctx = frame->GetRegisterContext().get(); + + if (reg_ctx) { + const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); + if (reg_info) { + RegisterValue reg_value; + if (reg_ctx->ReadRegister(reg_info, reg_value)) { + reg_value.Dump(&s, reg_info, false, false, format); + return true; + } + } + } + } + return false; } -static bool -DumpValue (Stream &s, - const SymbolContext *sc, - const ExecutionContext *exe_ctx, - const FormatEntity::Entry &entry, - ValueObject *valobj) -{ - if (valobj == nullptr) - return false; - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); - Format custom_format = eFormatInvalid; - ValueObject::ValueObjectRepresentationStyle val_obj_display = entry.string.empty() ? ValueObject::eValueObjectRepresentationStyleValue : ValueObject::eValueObjectRepresentationStyleSummary; +static bool FormatThreadExtendedInfoRecurse( + const FormatEntity::Entry &entry, + const StructuredData::ObjectSP &thread_info_dictionary, + const SymbolContext *sc, const ExecutionContext *exe_ctx, Stream &s) { + llvm::StringRef path(entry.string); + + StructuredData::ObjectSP value = + thread_info_dictionary->GetObjectForDotSeparatedPath(path); + + if (value) { + if (value->GetType() == StructuredData::Type::eTypeInteger) { + const char *token_format = "0x%4.4" PRIx64; + if (!entry.printf_format.empty()) + token_format = entry.printf_format.c_str(); + s.Printf(token_format, value->GetAsInteger()->GetValue()); + return true; + } else if (value->GetType() == StructuredData::Type::eTypeFloat) { + s.Printf("%f", value->GetAsFloat()->GetValue()); + return true; + } else if (value->GetType() == StructuredData::Type::eTypeString) { + s.Printf("%s", value->GetAsString()->GetValue().c_str()); + return true; + } else if (value->GetType() == StructuredData::Type::eTypeArray) { + if (value->GetAsArray()->GetSize() > 0) { + s.Printf("%zu", value->GetAsArray()->GetSize()); + return true; + } + } else if (value->GetType() == StructuredData::Type::eTypeDictionary) { + s.Printf("%zu", + value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize()); + return true; + } + } - bool do_deref_pointer = entry.deref; - bool is_script = false; - switch (entry.type) - { - case FormatEntity::Entry::Type::ScriptVariable: - is_script = true; - break; + return false; +} - case FormatEntity::Entry::Type::Variable: - custom_format = entry.fmt; - val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; - break; +static inline bool IsToken(const char *var_name_begin, const char *var) { + return (::strncmp(var_name_begin, var, strlen(var)) == 0); +} - case FormatEntity::Entry::Type::ScriptVariableSynthetic: - is_script = true; - LLVM_FALLTHROUGH; - case FormatEntity::Entry::Type::VariableSynthetic: - custom_format = entry.fmt; - val_obj_display = (ValueObject::ValueObjectRepresentationStyle)entry.number; - if (!valobj->IsSynthetic()) - { - valobj = valobj->GetSyntheticValue().get(); - if (valobj == nullptr) - return false; - } - break; +bool FormatEntity::FormatStringRef(const llvm::StringRef &format_str, Stream &s, + const SymbolContext *sc, + const ExecutionContext *exe_ctx, + const Address *addr, ValueObject *valobj, + bool function_changed, + bool initial_function) { + if (!format_str.empty()) { + FormatEntity::Entry root; + Error error = FormatEntity::Parse(format_str, root); + if (error.Success()) { + return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj, + function_changed, initial_function); + } + } + return false; +} - default: - return false; +bool FormatEntity::FormatCString(const char *format, Stream &s, + const SymbolContext *sc, + const ExecutionContext *exe_ctx, + const Address *addr, ValueObject *valobj, + bool function_changed, bool initial_function) { + if (format && format[0]) { + FormatEntity::Entry root; + llvm::StringRef format_str(format); + Error error = FormatEntity::Parse(format_str, root); + if (error.Success()) { + return FormatEntity::Format(root, s, sc, exe_ctx, addr, valobj, + function_changed, initial_function); } + } + return false; +} - if (valobj == nullptr) - return false; +bool FormatEntity::Format(const Entry &entry, Stream &s, + const SymbolContext *sc, + const ExecutionContext *exe_ctx, const Address *addr, + ValueObject *valobj, bool function_changed, + bool initial_function) { + switch (entry.type) { + case Entry::Type::Invalid: + case Entry::Type::ParentNumber: // Only used for + // FormatEntity::Entry::Definition encoding + case Entry::Type::ParentString: // Only used for + // FormatEntity::Entry::Definition encoding + case Entry::Type::InsertString: // Only used for + // FormatEntity::Entry::Definition encoding + return false; - ValueObject::ExpressionPathAftermath what_next = (do_deref_pointer ? - ValueObject::eExpressionPathAftermathDereference : ValueObject::eExpressionPathAftermathNothing); - ValueObject::GetValueForExpressionPathOptions options; - options.DontCheckDotVsArrowSyntax().DoAllowBitfieldSyntax().DoAllowFragileIVar().SetSyntheticChildrenTraversal(ValueObject::GetValueForExpressionPathOptions::SyntheticChildrenTraversal::Both); - ValueObject* target = nullptr; - const char* var_name_final_if_array_range = nullptr; - size_t close_bracket_index = llvm::StringRef::npos; - int64_t index_lower = -1; - int64_t index_higher = -1; - bool is_array_range = false; - const char* first_unparsed; - bool was_plain_var = false; - bool was_var_format = false; - bool was_var_indexed = false; - ValueObject::ExpressionPathScanEndReason reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; - ValueObject::ExpressionPathEndResultType final_value_type = ValueObject::eExpressionPathEndResultTypePlain; - - if (is_script) - { - return RunScriptFormatKeyword (s, sc, exe_ctx, valobj, entry.string.c_str()); - } - - llvm::StringRef subpath (entry.string); - // simplest case ${var}, just print valobj's value - if (entry.string.empty()) - { - if (entry.printf_format.empty() && entry.fmt == eFormatDefault && entry.number == ValueObject::eValueObjectRepresentationStyleValue) - was_plain_var = true; - else - was_var_format = true; - target = valobj; + case Entry::Type::Root: + for (const auto &child : entry.children) { + if (!Format(child, s, sc, exe_ctx, addr, valobj, function_changed, + initial_function)) { + return false; // If any item of root fails, then the formatting fails + } } - else // this is ${var.something} or multiple .something nested - { - if (entry.string[0] == '[') - was_var_indexed = true; - ScanBracketedRange (subpath, - close_bracket_index, - var_name_final_if_array_range, - index_lower, - index_higher); + return true; // Only return true if all items succeeded - Error error; + case Entry::Type::String: + s.PutCString(entry.string); + return true; - const std::string &expr_path = entry.string; + case Entry::Type::Scope: { + StreamString scope_stream; + bool success = false; + for (const auto &child : entry.children) { + success = Format(child, scope_stream, sc, exe_ctx, addr, valobj, + function_changed, initial_function); + if (!success) + break; + } + // Only if all items in a scope succeed, then do we + // print the output into the main stream + if (success) + s.Write(scope_stream.GetString().data(), scope_stream.GetString().size()); + } + return true; // Scopes always successfully print themselves + + case Entry::Type::Variable: + case Entry::Type::VariableSynthetic: + case Entry::Type::ScriptVariable: + case Entry::Type::ScriptVariableSynthetic: + return DumpValue(s, sc, exe_ctx, entry, valobj); + + case Entry::Type::AddressFile: + case Entry::Type::AddressLoad: + case Entry::Type::AddressLoadOrFile: + return (addr != nullptr && addr->IsValid() && + DumpAddress(s, sc, exe_ctx, *addr, + entry.type == Entry::Type::AddressLoadOrFile)); + + case Entry::Type::ProcessID: + if (exe_ctx) { + Process *process = exe_ctx->GetProcessPtr(); + if (process) { + const char *format = "%" PRIu64; + if (!entry.printf_format.empty()) + format = entry.printf_format.c_str(); + s.Printf(format, process->GetID()); + return true; + } + } + return false; - if (log) - log->Printf("[Debugger::FormatPrompt] symbol to expand: %s",expr_path.c_str()); + case Entry::Type::ProcessFile: + if (exe_ctx) { + Process *process = exe_ctx->GetProcessPtr(); + if (process) { + Module *exe_module = process->GetTarget().GetExecutableModulePointer(); + if (exe_module) { + if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number)) + return true; + } + } + } + return false; - target = valobj->GetValueForExpressionPath(expr_path.c_str(), - &first_unparsed, - &reason_to_stop, - &final_value_type, - options, - &what_next).get(); + case Entry::Type::ScriptProcess: + if (exe_ctx) { + Process *process = exe_ctx->GetProcessPtr(); + if (process) + return RunScriptFormatKeyword(s, sc, exe_ctx, process, + entry.string.c_str()); + } + return false; - if (!target) - { - if (log) - log->Printf("[Debugger::FormatPrompt] ERROR: unparsed portion = %s, why stopping = %d," - " final_value_type %d", - first_unparsed, reason_to_stop, final_value_type); - return false; - } - else - { - if (log) - log->Printf("[Debugger::FormatPrompt] ALL RIGHT: unparsed portion = %s, why stopping = %d," - " final_value_type %d", - first_unparsed, reason_to_stop, final_value_type); - target = target->GetQualifiedRepresentationIfAvailable(target->GetDynamicValueType(), true).get(); + case Entry::Type::ThreadID: + if (exe_ctx) { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) { + const char *format = "0x%4.4" PRIx64; + if (!entry.printf_format.empty()) { + // Watch for the special "tid" format... + if (entry.printf_format == "tid") { + // TODO(zturner): Rather than hardcoding this to be platform + // specific, it should be controlled by a + // setting and the default value of the setting can be different + // depending on the platform. + Target &target = thread->GetProcess()->GetTarget(); + ArchSpec arch(target.GetArchitecture()); + llvm::Triple::OSType ostype = arch.IsValid() + ? arch.GetTriple().getOS() + : llvm::Triple::UnknownOS; + if ((ostype == llvm::Triple::FreeBSD) || + (ostype == llvm::Triple::Linux)) { + format = "%" PRIu64; + } + } else { + format = entry.printf_format.c_str(); + } } + s.Printf(format, thread->GetID()); + return true; + } } + return false; - is_array_range = (final_value_type == ValueObject::eExpressionPathEndResultTypeBoundedRange || - final_value_type == ValueObject::eExpressionPathEndResultTypeUnboundedRange); + case Entry::Type::ThreadProtocolID: + if (exe_ctx) { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) { + const char *format = "0x%4.4" PRIx64; + if (!entry.printf_format.empty()) + format = entry.printf_format.c_str(); + s.Printf(format, thread->GetProtocolID()); + return true; + } + } + return false; - do_deref_pointer = (what_next == ValueObject::eExpressionPathAftermathDereference); + case Entry::Type::ThreadIndexID: + if (exe_ctx) { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) { + const char *format = "%" PRIu32; + if (!entry.printf_format.empty()) + format = entry.printf_format.c_str(); + s.Printf(format, thread->GetIndexID()); + return true; + } + } + return false; - if (do_deref_pointer && !is_array_range) - { - // I have not deref-ed yet, let's do it - // this happens when we are not going through GetValueForVariableExpressionPath - // to get to the target ValueObject - Error error; - target = target->Dereference(error).get(); - if (error.Fail()) - { - if (log) - log->Printf("[Debugger::FormatPrompt] ERROR: %s\n", error.AsCString("unknown")); \ - return false; + case Entry::Type::ThreadName: + if (exe_ctx) { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) { + const char *cstr = thread->GetName(); + if (cstr && cstr[0]) { + s.PutCString(cstr); + return true; } - do_deref_pointer = false; + } } + return false; - if (!target) - { - if (log) - log->Printf("[Debugger::FormatPrompt] could not calculate target for prompt expression"); - return false; + case Entry::Type::ThreadQueue: + if (exe_ctx) { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) { + const char *cstr = thread->GetQueueName(); + if (cstr && cstr[0]) { + s.PutCString(cstr); + return true; + } + } } + return false; - // we do not want to use the summary for a bitfield of type T:n - // if we were originally dealing with just a T - that would get - // us into an endless recursion - if (target->IsBitfield() && was_var_indexed) - { - // TODO: check for a (T:n)-specific summary - we should still obey that - StreamString bitfield_name; - bitfield_name.Printf("%s:%d", target->GetTypeName().AsCString(), target->GetBitfieldBitSize()); - lldb::TypeNameSpecifierImplSP type_sp(new TypeNameSpecifierImpl(bitfield_name.GetData(),false)); - if (val_obj_display == ValueObject::eValueObjectRepresentationStyleSummary && !DataVisualization::GetSummaryForType(type_sp)) - val_obj_display = ValueObject::eValueObjectRepresentationStyleValue; - } - - // TODO use flags for these - const uint32_t type_info_flags = target->GetCompilerType().GetTypeInfo(nullptr); - bool is_array = (type_info_flags & eTypeIsArray) != 0; - bool is_pointer = (type_info_flags & eTypeIsPointer) != 0; - bool is_aggregate = target->GetCompilerType().IsAggregateType(); - - if ((is_array || is_pointer) && (!is_array_range) && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) // this should be wrong, but there are some exceptions - { - StreamString str_temp; - if (log) - log->Printf("[Debugger::FormatPrompt] I am into array || pointer && !range"); - - if (target->HasSpecialPrintableRepresentation(val_obj_display, custom_format)) - { - // try to use the special cases - bool success = target->DumpPrintableRepresentation(str_temp, - val_obj_display, - custom_format); - if (log) - log->Printf("[Debugger::FormatPrompt] special cases did%s match", success ? "" : "n't"); - - // should not happen - if (success) - s << str_temp.GetData(); + case Entry::Type::ThreadStopReason: + if (exe_ctx) { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) { + StopInfoSP stop_info_sp = thread->GetStopInfo(); + if (stop_info_sp && stop_info_sp->IsValid()) { + const char *cstr = stop_info_sp->GetDescription(); + if (cstr && cstr[0]) { + s.PutCString(cstr); return true; + } } - else - { - if (was_plain_var) // if ${var} - { - s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); - } - else if (is_pointer) // if pointer, value is the address stored - { - target->DumpPrintableRepresentation (s, - val_obj_display, - custom_format, - ValueObject::ePrintableRepresentationSpecialCasesDisable); - } + } + } + return false; + + case Entry::Type::ThreadReturnValue: + if (exe_ctx) { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) { + StopInfoSP stop_info_sp = thread->GetStopInfo(); + if (stop_info_sp && stop_info_sp->IsValid()) { + ValueObjectSP return_valobj_sp = + StopInfo::GetReturnValueObject(stop_info_sp); + if (return_valobj_sp) { + return_valobj_sp->Dump(s); return true; + } } + } } + return false; - // if directly trying to print ${var}, and this is an aggregate, display a nice - // type @ location message - if (is_aggregate && was_plain_var) - { - s << target->GetTypeName() << " @ " << target->GetLocationAsCString(); - return true; + case Entry::Type::ThreadCompletedExpression: + if (exe_ctx) { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) { + StopInfoSP stop_info_sp = thread->GetStopInfo(); + if (stop_info_sp && stop_info_sp->IsValid()) { + ExpressionVariableSP expression_var_sp = + StopInfo::GetExpressionVariable(stop_info_sp); + if (expression_var_sp && expression_var_sp->GetValueObject()) { + expression_var_sp->GetValueObject()->Dump(s); + return true; + } + } + } } + return false; - // if directly trying to print ${var%V}, and this is an aggregate, do not let the user do it - if (is_aggregate && ((was_var_format && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue))) - { - s << "<invalid use of aggregate type>"; - return true; + case Entry::Type::ScriptThread: + if (exe_ctx) { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) + return RunScriptFormatKeyword(s, sc, exe_ctx, thread, + entry.string.c_str()); } + return false; - if (!is_array_range) - { - if (log) - log->Printf("[Debugger::FormatPrompt] dumping ordinary printable output"); - return target->DumpPrintableRepresentation(s,val_obj_display, custom_format); - } - else - { - if (log) - log->Printf("[Debugger::FormatPrompt] checking if I can handle as array"); - if (!is_array && !is_pointer) - return false; - if (log) - log->Printf("[Debugger::FormatPrompt] handle as array"); - StreamString special_directions_stream; - llvm::StringRef special_directions; - if (close_bracket_index != llvm::StringRef::npos && subpath.size() > close_bracket_index) - { - ConstString additional_data (subpath.drop_front(close_bracket_index+1)); - special_directions_stream.Printf("${%svar%s", - do_deref_pointer ? "*" : "", - additional_data.GetCString()); - - if (entry.fmt != eFormatDefault) - { - const char format_char = FormatManager::GetFormatAsFormatChar(entry.fmt); - if (format_char != '\0') - special_directions_stream.Printf("%%%c", format_char); - else - { - const char *format_cstr = FormatManager::GetFormatAsCString(entry.fmt); - special_directions_stream.Printf("%%%s", format_cstr); - } - } - else if (entry.number != 0) - { - const char style_char = ConvertValueObjectStyleToChar ((ValueObject::ValueObjectRepresentationStyle)entry.number); - if (style_char) - special_directions_stream.Printf("%%%c", style_char); - } - special_directions_stream.PutChar('}'); - special_directions = llvm::StringRef(special_directions_stream.GetString()); + case Entry::Type::ThreadInfo: + if (exe_ctx) { + Thread *thread = exe_ctx->GetThreadPtr(); + if (thread) { + StructuredData::ObjectSP object_sp = thread->GetExtendedInfo(); + if (object_sp && + object_sp->GetType() == StructuredData::Type::eTypeDictionary) { + if (FormatThreadExtendedInfoRecurse(entry, object_sp, sc, exe_ctx, s)) + return true; } + } + } + return false; - // let us display items index_lower thru index_higher of this array - s.PutChar('['); + case Entry::Type::TargetArch: + if (exe_ctx) { + Target *target = exe_ctx->GetTargetPtr(); + if (target) { + const ArchSpec &arch = target->GetArchitecture(); + if (arch.IsValid()) { + s.PutCString(arch.GetArchitectureName()); + return true; + } + } + } + return false; - if (index_higher < 0) - index_higher = valobj->GetNumChildren() - 1; + case Entry::Type::ScriptTarget: + if (exe_ctx) { + Target *target = exe_ctx->GetTargetPtr(); + if (target) + return RunScriptFormatKeyword(s, sc, exe_ctx, target, + entry.string.c_str()); + } + return false; - uint32_t max_num_children = target->GetTargetSP()->GetMaximumNumberOfChildrenToDisplay(); + case Entry::Type::ModuleFile: + if (sc) { + Module *module = sc->module_sp.get(); + if (module) { + if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number)) + return true; + } + } + return false; - bool success = true; - for (int64_t index = index_lower;index<=index_higher; ++index) - { - ValueObject* item = ExpandIndexedExpression (target, - index, - exe_ctx->GetFramePtr(), - false).get(); - - if (!item) - { - if (log) - log->Printf("[Debugger::FormatPrompt] ERROR in getting child item at index %" PRId64, index); - } - else - { - if (log) - log->Printf("[Debugger::FormatPrompt] special_directions for child item: %s",special_directions.data() ? special_directions.data() : ""); - } + case Entry::Type::File: + if (sc) { + CompileUnit *cu = sc->comp_unit; + if (cu) { + // CompileUnit is a FileSpec + if (DumpFile(s, *cu, (FileKind)entry.number)) + return true; + } + } + return false; - if (special_directions.empty()) - { - success &= item->DumpPrintableRepresentation(s,val_obj_display, custom_format); - } - else - { - success &= FormatEntity::FormatStringRef(special_directions, s, sc, exe_ctx, nullptr, item, false, false); - } + case Entry::Type::Lang: + if (sc) { + CompileUnit *cu = sc->comp_unit; + if (cu) { + const char *lang_name = + Language::GetNameForLanguageType(cu->GetLanguage()); + if (lang_name) { + s.PutCString(lang_name); + return true; + } + } + } + return false; - if (--max_num_children == 0) - { - s.PutCString(", ..."); - break; - } + case Entry::Type::FrameIndex: + if (exe_ctx) { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) { + const char *format = "%" PRIu32; + if (!entry.printf_format.empty()) + format = entry.printf_format.c_str(); + s.Printf(format, frame->GetFrameIndex()); + return true; + } + } + return false; - if (index < index_higher) - s.PutChar(','); + case Entry::Type::FrameRegisterPC: + if (exe_ctx) { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) { + const Address &pc_addr = frame->GetFrameCodeAddress(); + if (pc_addr.IsValid()) { + if (DumpAddress(s, sc, exe_ctx, pc_addr, false)) + return true; } - s.PutChar(']'); - return success; + } } -} + return false; -static bool -DumpRegister (Stream &s, - StackFrame *frame, - const char *reg_name, - Format format) -{ - if (frame) - { - RegisterContext *reg_ctx = frame->GetRegisterContext().get(); + case Entry::Type::FrameRegisterSP: + if (exe_ctx) { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) { + if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, + (lldb::Format)entry.number)) + return true; + } + } + return false; - if (reg_ctx) - { - const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(reg_name); - if (reg_info) - { - RegisterValue reg_value; - if (reg_ctx->ReadRegister (reg_info, reg_value)) - { - reg_value.Dump(&s, reg_info, false, false, format); - return true; - } - } - } + case Entry::Type::FrameRegisterFP: + if (exe_ctx) { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) { + if (DumpRegister(s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, + (lldb::Format)entry.number)) + return true; + } } return false; -} -static bool -FormatThreadExtendedInfoRecurse(const FormatEntity::Entry &entry, - const StructuredData::ObjectSP &thread_info_dictionary, - const SymbolContext *sc, - const ExecutionContext *exe_ctx, - Stream &s) -{ - llvm::StringRef path(entry.string); + case Entry::Type::FrameRegisterFlags: + if (exe_ctx) { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) { + if (DumpRegister(s, frame, eRegisterKindGeneric, + LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number)) + return true; + } + } + return false; - StructuredData::ObjectSP value = thread_info_dictionary->GetObjectForDotSeparatedPath (path); + case Entry::Type::FrameNoDebug: + if (exe_ctx) { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) { + return !frame->HasDebugInformation(); + } + } + return true; - if (value) - { - if (value->GetType() == StructuredData::Type::eTypeInteger) - { - const char *token_format = "0x%4.4" PRIx64; - if (!entry.printf_format.empty()) - token_format = entry.printf_format.c_str(); - s.Printf(token_format, value->GetAsInteger()->GetValue()); - return true; - } - else if (value->GetType() == StructuredData::Type::eTypeFloat) - { - s.Printf ("%f", value->GetAsFloat()->GetValue()); - return true; - } - else if (value->GetType() == StructuredData::Type::eTypeString) - { - s.Printf("%s", value->GetAsString()->GetValue().c_str()); - return true; - } - else if (value->GetType() == StructuredData::Type::eTypeArray) - { - if (value->GetAsArray()->GetSize() > 0) - { - s.Printf ("%zu", value->GetAsArray()->GetSize()); - return true; - } - } - else if (value->GetType() == StructuredData::Type::eTypeDictionary) - { - s.Printf ("%zu", value->GetAsDictionary()->GetKeys()->GetAsArray()->GetSize()); - return true; - } + case Entry::Type::FrameRegisterByName: + if (exe_ctx) { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) { + if (DumpRegister(s, frame, entry.string.c_str(), + (lldb::Format)entry.number)) + return true; + } } + return false; + case Entry::Type::ScriptFrame: + if (exe_ctx) { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) + return RunScriptFormatKeyword(s, sc, exe_ctx, frame, + entry.string.c_str()); + } return false; -} -static inline bool -IsToken(const char *var_name_begin, const char *var) -{ - return (::strncmp (var_name_begin, var, strlen(var)) == 0); -} + case Entry::Type::FunctionID: + if (sc) { + if (sc->function) { + s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); + return true; + } else if (sc->symbol) { + s.Printf("symbol[%u]", sc->symbol->GetID()); + return true; + } + } + return false; -bool -FormatEntity::FormatStringRef (const llvm::StringRef &format_str, - Stream &s, - const SymbolContext *sc, - const ExecutionContext *exe_ctx, - const Address *addr, - ValueObject* valobj, - bool function_changed, - bool initial_function) -{ - if (!format_str.empty()) - { - FormatEntity::Entry root; - Error error = FormatEntity::Parse(format_str, root); - if (error.Success()) - { - return FormatEntity::Format (root, - s, - sc, - exe_ctx, - addr, - valobj, - function_changed, - initial_function); + case Entry::Type::FunctionDidChange: + return function_changed; + + case Entry::Type::FunctionInitialFunction: + return initial_function; + + case Entry::Type::FunctionName: { + Language *language_plugin = nullptr; + bool language_plugin_handled = false; + StreamString ss; + if (sc->function) + language_plugin = Language::FindPlugin(sc->function->GetLanguage()); + else if (sc->symbol) + language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); + if (language_plugin) { + language_plugin_handled = language_plugin->GetFunctionDisplayName( + sc, exe_ctx, Language::FunctionNameRepresentation::eName, ss); + } + if (language_plugin_handled) { + s << ss.GetString(); + return true; + } else { + const char *name = nullptr; + if (sc->function) + name = sc->function->GetName().AsCString(nullptr); + else if (sc->symbol) + name = sc->symbol->GetName().AsCString(nullptr); + if (name) { + s.PutCString(name); + + if (sc->block) { + Block *inline_block = sc->block->GetContainingInlinedBlock(); + if (inline_block) { + const InlineFunctionInfo *inline_info = + sc->block->GetInlinedFunctionInfo(); + if (inline_info) { + s.PutCString(" [inlined] "); + inline_info->GetName(sc->function->GetLanguage()).Dump(&s); + } + } } + return true; + } } + } return false; -} -bool -FormatEntity::FormatCString (const char *format, - Stream &s, - const SymbolContext *sc, - const ExecutionContext *exe_ctx, - const Address *addr, - ValueObject* valobj, - bool function_changed, - bool initial_function) -{ - if (format && format[0]) - { - FormatEntity::Entry root; - llvm::StringRef format_str(format); - Error error = FormatEntity::Parse(format_str, root); - if (error.Success()) - { - return FormatEntity::Format (root, - s, - sc, - exe_ctx, - addr, - valobj, - function_changed, - initial_function); - } + case Entry::Type::FunctionNameNoArgs: { + Language *language_plugin = nullptr; + bool language_plugin_handled = false; + StreamString ss; + if (sc->function) + language_plugin = Language::FindPlugin(sc->function->GetLanguage()); + else if (sc->symbol) + language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); + if (language_plugin) { + language_plugin_handled = language_plugin->GetFunctionDisplayName( + sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithNoArgs, + ss); + } + if (language_plugin_handled) { + s << ss.GetString(); + return true; + } else { + ConstString name; + if (sc->function) + name = sc->function->GetNameNoArguments(); + else if (sc->symbol) + name = sc->symbol->GetNameNoArguments(); + if (name) { + s.PutCString(name.GetCString()); + return true; + } } + } return false; -} -bool -FormatEntity::Format (const Entry &entry, - Stream &s, - const SymbolContext *sc, - const ExecutionContext *exe_ctx, - const Address *addr, - ValueObject* valobj, - bool function_changed, - bool initial_function) -{ - switch (entry.type) - { - case Entry::Type::Invalid: - case Entry::Type::ParentNumber: // Only used for FormatEntity::Entry::Definition encoding - case Entry::Type::ParentString: // Only used for FormatEntity::Entry::Definition encoding - case Entry::Type::InsertString: // Only used for FormatEntity::Entry::Definition encoding - return false; - - case Entry::Type::Root: - for (const auto &child : entry.children) - { - if (!Format(child, - s, - sc, - exe_ctx, - addr, - valobj, - function_changed, - initial_function)) - { - return false; // If any item of root fails, then the formatting fails - } + case Entry::Type::FunctionNameWithArgs: { + Language *language_plugin = nullptr; + bool language_plugin_handled = false; + StreamString ss; + if (sc->function) + language_plugin = Language::FindPlugin(sc->function->GetLanguage()); + else if (sc->symbol) + language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); + if (language_plugin) { + language_plugin_handled = language_plugin->GetFunctionDisplayName( + sc, exe_ctx, Language::FunctionNameRepresentation::eNameWithArgs, ss); + } + if (language_plugin_handled) { + s << ss.GetString(); + return true; + } else { + // Print the function name with arguments in it + if (sc->function) { + ExecutionContextScope *exe_scope = + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; + const char *cstr = sc->function->GetName().AsCString(nullptr); + if (cstr) { + const InlineFunctionInfo *inline_info = nullptr; + VariableListSP variable_list_sp; + bool get_function_vars = true; + if (sc->block) { + Block *inline_block = sc->block->GetContainingInlinedBlock(); + + if (inline_block) { + get_function_vars = false; + inline_info = sc->block->GetInlinedFunctionInfo(); + if (inline_info) + variable_list_sp = inline_block->GetBlockVariableList(true); + } + } + + if (get_function_vars) { + variable_list_sp = + sc->function->GetBlock(true).GetBlockVariableList(true); + } + + if (inline_info) { + s.PutCString(cstr); + s.PutCString(" [inlined] "); + cstr = + inline_info->GetName(sc->function->GetLanguage()).GetCString(); + } + + VariableList args; + if (variable_list_sp) + variable_list_sp->AppendVariablesWithScope( + eValueTypeVariableArgument, args); + if (args.GetSize() > 0) { + const char *open_paren = strchr(cstr, '('); + const char *close_paren = nullptr; + const char *generic = strchr(cstr, '<'); + // if before the arguments list begins there is a template sign + // then scan to the end of the generic args before you try to find + // the arguments list + if (generic && open_paren && generic < open_paren) { + int generic_depth = 1; + ++generic; + for (; *generic && generic_depth > 0; generic++) { + if (*generic == '<') + generic_depth++; + if (*generic == '>') + generic_depth--; + } + if (*generic) + open_paren = strchr(generic, '('); + else + open_paren = nullptr; + } + if (open_paren) { + if (IsToken(open_paren, "(anonymous namespace)")) { + open_paren = + strchr(open_paren + strlen("(anonymous namespace)"), '('); + if (open_paren) + close_paren = strchr(open_paren, ')'); + } else + close_paren = strchr(open_paren, ')'); + } + + if (open_paren) + s.Write(cstr, open_paren - cstr + 1); + else { + s.PutCString(cstr); + s.PutChar('('); + } + const size_t num_args = args.GetSize(); + for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) { + std::string buffer; + + VariableSP var_sp(args.GetVariableAtIndex(arg_idx)); + ValueObjectSP var_value_sp( + ValueObjectVariable::Create(exe_scope, var_sp)); + StreamString ss; + llvm::StringRef var_representation; + const char *var_name = var_value_sp->GetName().GetCString(); + if (var_value_sp->GetCompilerType().IsValid()) { + if (var_value_sp && exe_scope->CalculateTarget()) + var_value_sp = + var_value_sp->GetQualifiedRepresentationIfAvailable( + exe_scope->CalculateTarget() + ->TargetProperties::GetPreferDynamicValue(), + exe_scope->CalculateTarget() + ->TargetProperties::GetEnableSyntheticValue()); + if (var_value_sp->GetCompilerType().IsAggregateType() && + DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) { + static StringSummaryFormat format( + TypeSummaryImpl::Flags() + .SetHideItemNames(false) + .SetShowMembersOneLiner(true), + ""); + format.FormatObject(var_value_sp.get(), buffer, + TypeSummaryOptions()); + var_representation = buffer; + } else + var_value_sp->DumpPrintableRepresentation( + ss, ValueObject::ValueObjectRepresentationStyle:: + eValueObjectRepresentationStyleSummary, + eFormatDefault, + ValueObject::PrintableRepresentationSpecialCases::eAllow, + false); + } + + if (!ss.GetString().empty()) + var_representation = ss.GetString(); + if (arg_idx > 0) + s.PutCString(", "); + if (var_value_sp->GetError().Success()) { + if (!var_representation.empty()) + s.Printf("%s=%s", var_name, var_representation.str().c_str()); + else + s.Printf("%s=%s at %s", var_name, + var_value_sp->GetTypeName().GetCString(), + var_value_sp->GetLocationAsCString()); + } else + s.Printf("%s=<unavailable>", var_name); } - return true; // Only return true if all items succeeded - case Entry::Type::String: - s.PutCString(entry.string.c_str()); - return true; + if (close_paren) + s.PutCString(close_paren); + else + s.PutChar(')'); - case Entry::Type::Scope: - { - StreamString scope_stream; - bool success = false; - for (const auto &child : entry.children) - { - success = Format (child, scope_stream, sc, exe_ctx, addr, valobj, function_changed, initial_function); - if (!success) - break; - } - // Only if all items in a scope succeed, then do we - // print the output into the main stream - if (success) - s.Write(scope_stream.GetString().data(), scope_stream.GetString().size()); - } - return true; // Scopes always successfully print themselves - - case Entry::Type::Variable: - case Entry::Type::VariableSynthetic: - case Entry::Type::ScriptVariable: - case Entry::Type::ScriptVariableSynthetic: - return DumpValue(s, sc, exe_ctx, entry, valobj); - - case Entry::Type::AddressFile: - case Entry::Type::AddressLoad: - case Entry::Type::AddressLoadOrFile: - return (addr != nullptr && addr->IsValid() && - DumpAddress(s, sc, exe_ctx, *addr, entry.type == Entry::Type::AddressLoadOrFile)); - - case Entry::Type::ProcessID: - if (exe_ctx) - { - Process *process = exe_ctx->GetProcessPtr(); - if (process) - { - const char *format = "%" PRIu64; - if (!entry.printf_format.empty()) - format = entry.printf_format.c_str(); - s.Printf(format, process->GetID()); - return true; - } - } - return false; - - case Entry::Type::ProcessFile: - if (exe_ctx) - { - Process *process = exe_ctx->GetProcessPtr(); - if (process) - { - Module *exe_module = process->GetTarget().GetExecutableModulePointer(); - if (exe_module) - { - if (DumpFile(s, exe_module->GetFileSpec(), (FileKind)entry.number)) - return true; - } - } - } - return false; - - case Entry::Type::ScriptProcess: - if (exe_ctx) - { - Process *process = exe_ctx->GetProcessPtr(); - if (process) - return RunScriptFormatKeyword (s, sc, exe_ctx, process, entry.string.c_str()); - } - return false; - - case Entry::Type::ThreadID: - if (exe_ctx) - { - Thread *thread = exe_ctx->GetThreadPtr(); - if (thread) - { - const char *format = "0x%4.4" PRIx64; - if (!entry.printf_format.empty()) - { - // Watch for the special "tid" format... - if (entry.printf_format == "tid") - { - // TODO(zturner): Rather than hardcoding this to be platform specific, it should be controlled by a - // setting and the default value of the setting can be different depending on the platform. - Target &target = thread->GetProcess()->GetTarget(); - ArchSpec arch (target.GetArchitecture ()); - llvm::Triple::OSType ostype = arch.IsValid() ? arch.GetTriple().getOS() : llvm::Triple::UnknownOS; - if ((ostype == llvm::Triple::FreeBSD) || (ostype == llvm::Triple::Linux)) - { - format = "%" PRIu64; - } - } - else - { - format = entry.printf_format.c_str(); - } - } - s.Printf(format, thread->GetID()); - return true; - } - } - return false; - - case Entry::Type::ThreadProtocolID: - if (exe_ctx) - { - Thread *thread = exe_ctx->GetThreadPtr(); - if (thread) - { - const char *format = "0x%4.4" PRIx64; - if (!entry.printf_format.empty()) - format = entry.printf_format.c_str(); - s.Printf(format, thread->GetProtocolID()); - return true; - } - } - return false; - - case Entry::Type::ThreadIndexID: - if (exe_ctx) - { - Thread *thread = exe_ctx->GetThreadPtr(); - if (thread) - { - const char *format = "%" PRIu32; - if (!entry.printf_format.empty()) - format = entry.printf_format.c_str(); - s.Printf(format, thread->GetIndexID()); - return true; - } - } - return false; - - case Entry::Type::ThreadName: - if (exe_ctx) - { - Thread *thread = exe_ctx->GetThreadPtr(); - if (thread) - { - const char *cstr = thread->GetName(); - if (cstr && cstr[0]) - { - s.PutCString(cstr); - return true; - } - } - } - return false; - - case Entry::Type::ThreadQueue: - if (exe_ctx) - { - Thread *thread = exe_ctx->GetThreadPtr(); - if (thread) - { - const char *cstr = thread->GetQueueName(); - if (cstr && cstr[0]) - { - s.PutCString(cstr); - return true; - } - } - } - return false; - - case Entry::Type::ThreadStopReason: - if (exe_ctx) - { - Thread *thread = exe_ctx->GetThreadPtr(); - if (thread) - { - StopInfoSP stop_info_sp = thread->GetStopInfo (); - if (stop_info_sp && stop_info_sp->IsValid()) - { - const char *cstr = stop_info_sp->GetDescription(); - if (cstr && cstr[0]) - { - s.PutCString(cstr); - return true; - } - } - } - } - return false; - - case Entry::Type::ThreadReturnValue: - if (exe_ctx) - { - Thread *thread = exe_ctx->GetThreadPtr(); - if (thread) - { - StopInfoSP stop_info_sp = thread->GetStopInfo (); - if (stop_info_sp && stop_info_sp->IsValid()) - { - ValueObjectSP return_valobj_sp = StopInfo::GetReturnValueObject (stop_info_sp); - if (return_valobj_sp) - { - return_valobj_sp->Dump(s); - return true; - } - } - } - } - return false; - - case Entry::Type::ThreadCompletedExpression: - if (exe_ctx) - { - Thread *thread = exe_ctx->GetThreadPtr(); - if (thread) - { - StopInfoSP stop_info_sp = thread->GetStopInfo (); - if (stop_info_sp && stop_info_sp->IsValid()) - { - ExpressionVariableSP expression_var_sp = StopInfo::GetExpressionVariable (stop_info_sp); - if (expression_var_sp && expression_var_sp->GetValueObject()) - { - expression_var_sp->GetValueObject()->Dump(s); - return true; - } - } - } - } - return false; - - case Entry::Type::ScriptThread: - if (exe_ctx) - { - Thread *thread = exe_ctx->GetThreadPtr(); - if (thread) - return RunScriptFormatKeyword (s, sc, exe_ctx, thread, entry.string.c_str()); - } - return false; - - case Entry::Type::ThreadInfo: - if (exe_ctx) - { - Thread *thread = exe_ctx->GetThreadPtr(); - if (thread) - { - StructuredData::ObjectSP object_sp = thread->GetExtendedInfo(); - if (object_sp && object_sp->GetType() == StructuredData::Type::eTypeDictionary) - { - if (FormatThreadExtendedInfoRecurse (entry, object_sp, sc, exe_ctx, s)) - return true; - } - } - } - return false; - - case Entry::Type::TargetArch: - if (exe_ctx) - { - Target *target = exe_ctx->GetTargetPtr(); - if (target) - { - const ArchSpec &arch = target->GetArchitecture (); - if (arch.IsValid()) - { - s.PutCString (arch.GetArchitectureName()); - return true; - } - } - } - return false; - - case Entry::Type::ScriptTarget: - if (exe_ctx) - { - Target *target = exe_ctx->GetTargetPtr(); - if (target) - return RunScriptFormatKeyword (s, sc, exe_ctx, target, entry.string.c_str()); - } - return false; - - case Entry::Type::ModuleFile: - if (sc) - { - Module *module = sc->module_sp.get(); - if (module) - { - if (DumpFile(s, module->GetFileSpec(), (FileKind)entry.number)) - return true; - } - } - return false; - - case Entry::Type::File: - if (sc) - { - CompileUnit *cu = sc->comp_unit; - if (cu) - { - // CompileUnit is a FileSpec - if (DumpFile(s, *cu, (FileKind)entry.number)) - return true; - } - } - return false; - - case Entry::Type::Lang: - if (sc) - { - CompileUnit *cu = sc->comp_unit; - if (cu) - { - const char *lang_name = Language::GetNameForLanguageType(cu->GetLanguage()); - if (lang_name) - { - s.PutCString(lang_name); - return true; - } - } - } - return false; - - case Entry::Type::FrameIndex: - if (exe_ctx) - { - StackFrame *frame = exe_ctx->GetFramePtr(); - if (frame) - { - const char *format = "%" PRIu32; - if (!entry.printf_format.empty()) - format = entry.printf_format.c_str(); - s.Printf(format, frame->GetFrameIndex()); - return true; - } - } - return false; - - case Entry::Type::FrameRegisterPC: - if (exe_ctx) - { - StackFrame *frame = exe_ctx->GetFramePtr(); - if (frame) - { - const Address &pc_addr = frame->GetFrameCodeAddress(); - if (pc_addr.IsValid()) - { - if (DumpAddress(s, sc, exe_ctx, pc_addr, false)) - return true; - } - } - } - return false; - - case Entry::Type::FrameRegisterSP: - if (exe_ctx) - { - StackFrame *frame = exe_ctx->GetFramePtr(); - if (frame) - { - if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP, (lldb::Format)entry.number)) - return true; - } - } - return false; - - case Entry::Type::FrameRegisterFP: - if (exe_ctx) - { - StackFrame *frame = exe_ctx->GetFramePtr(); - if (frame) - { - if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP, (lldb::Format)entry.number)) - return true; - } - } - return false; - - case Entry::Type::FrameRegisterFlags: - if (exe_ctx) - { - StackFrame *frame = exe_ctx->GetFramePtr(); - if (frame) - { - if (DumpRegister (s, frame, eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS, (lldb::Format)entry.number)) - return true; - } - } - return false; - - case Entry::Type::FrameRegisterByName: - if (exe_ctx) - { - StackFrame *frame = exe_ctx->GetFramePtr(); - if (frame) - { - if (DumpRegister (s, frame, entry.string.c_str(), (lldb::Format)entry.number)) - return true; - } - } - return false; - - case Entry::Type::ScriptFrame: - if (exe_ctx) - { - StackFrame *frame = exe_ctx->GetFramePtr(); - if (frame) - return RunScriptFormatKeyword (s, sc, exe_ctx, frame, entry.string.c_str()); - } - return false; - - case Entry::Type::FunctionID: - if (sc) - { - if (sc->function) - { - s.Printf("function{0x%8.8" PRIx64 "}", sc->function->GetID()); - return true; - } - else if (sc->symbol) - { - s.Printf("symbol[%u]", sc->symbol->GetID()); - return true; - } - } - return false; - - case Entry::Type::FunctionDidChange: - return function_changed; - - case Entry::Type::FunctionInitialFunction: - return initial_function; - - case Entry::Type::FunctionName: - { - Language *language_plugin = nullptr; - bool language_plugin_handled = false; - StreamString ss; - if (sc->function) - language_plugin = Language::FindPlugin(sc->function->GetLanguage()); - else if (sc->symbol) - language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); - if (language_plugin) - { - language_plugin_handled = language_plugin->GetFunctionDisplayName(sc, - exe_ctx, - Language::FunctionNameRepresentation::eName, - ss); - } - if (language_plugin_handled) - { - s.PutCString(ss.GetData()); - return true; - } - else - { - const char *name = nullptr; - if (sc->function) - name = sc->function->GetName().AsCString(nullptr); - else if (sc->symbol) - name = sc->symbol->GetName().AsCString(nullptr); - if (name) - { - s.PutCString(name); - - if (sc->block) - { - Block *inline_block = sc->block->GetContainingInlinedBlock (); - if (inline_block) - { - const InlineFunctionInfo *inline_info = sc->block->GetInlinedFunctionInfo(); - if (inline_info) - { - s.PutCString(" [inlined] "); - inline_info->GetName(sc->function->GetLanguage()).Dump(&s); - } - } - } - return true; - } - } - } - return false; - - case Entry::Type::FunctionNameNoArgs: - { - Language *language_plugin = nullptr; - bool language_plugin_handled = false; - StreamString ss; - if (sc->function) - language_plugin = Language::FindPlugin(sc->function->GetLanguage()); - else if (sc->symbol) - language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); - if (language_plugin) - { - language_plugin_handled = language_plugin->GetFunctionDisplayName(sc, - exe_ctx, - Language::FunctionNameRepresentation::eNameWithNoArgs, - ss); - } - if (language_plugin_handled) - { - s.PutCString(ss.GetData()); - return true; - } - else - { - ConstString name; - if (sc->function) - name = sc->function->GetNameNoArguments(); - else if (sc->symbol) - name = sc->symbol->GetNameNoArguments(); - if (name) - { - s.PutCString(name.GetCString()); - return true; - } - } - } - return false; - - case Entry::Type::FunctionNameWithArgs: - { - Language *language_plugin = nullptr; - bool language_plugin_handled = false; - StreamString ss; - if (sc->function) - language_plugin = Language::FindPlugin(sc->function->GetLanguage()); - else if (sc->symbol) - language_plugin = Language::FindPlugin(sc->symbol->GetLanguage()); - if (language_plugin) - { - language_plugin_handled = language_plugin->GetFunctionDisplayName(sc, - exe_ctx, - Language::FunctionNameRepresentation::eNameWithArgs, - ss); - } - if (language_plugin_handled) - { - s.PutCString(ss.GetData()); - return true; - } - else - { - // Print the function name with arguments in it - if (sc->function) - { - ExecutionContextScope *exe_scope = exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr; - const char *cstr = sc->function->GetName().AsCString(nullptr); - if (cstr) - { - const InlineFunctionInfo *inline_info = nullptr; - VariableListSP variable_list_sp; - bool get_function_vars = true; - if (sc->block) - { - Block *inline_block = sc->block->GetContainingInlinedBlock (); - - if (inline_block) - { - get_function_vars = false; - inline_info = sc->block->GetInlinedFunctionInfo(); - if (inline_info) - variable_list_sp = inline_block->GetBlockVariableList (true); - } - } - - if (get_function_vars) - { - variable_list_sp = sc->function->GetBlock(true).GetBlockVariableList (true); - } - - if (inline_info) - { - s.PutCString (cstr); - s.PutCString (" [inlined] "); - cstr = inline_info->GetName(sc->function->GetLanguage()).GetCString(); - } - - VariableList args; - if (variable_list_sp) - variable_list_sp->AppendVariablesWithScope(eValueTypeVariableArgument, args); - if (args.GetSize() > 0) - { - const char *open_paren = strchr (cstr, '('); - const char *close_paren = nullptr; - const char *generic = strchr(cstr, '<'); - // if before the arguments list begins there is a template sign - // then scan to the end of the generic args before you try to find - // the arguments list - if (generic && open_paren && generic < open_paren) - { - int generic_depth = 1; - ++generic; - for (; - *generic && generic_depth > 0; - generic++) - { - if (*generic == '<') - generic_depth++; - if (*generic == '>') - generic_depth--; - } - if (*generic) - open_paren = strchr(generic, '('); - else - open_paren = nullptr; - } - if (open_paren) - { - if (IsToken (open_paren, "(anonymous namespace)")) - { - open_paren = strchr (open_paren + strlen("(anonymous namespace)"), '('); - if (open_paren) - close_paren = strchr (open_paren, ')'); - } - else - close_paren = strchr (open_paren, ')'); - } - - if (open_paren) - s.Write(cstr, open_paren - cstr + 1); - else - { - s.PutCString (cstr); - s.PutChar ('('); - } - const size_t num_args = args.GetSize(); - for (size_t arg_idx = 0; arg_idx < num_args; ++arg_idx) - { - std::string buffer; - - VariableSP var_sp (args.GetVariableAtIndex (arg_idx)); - ValueObjectSP var_value_sp (ValueObjectVariable::Create (exe_scope, var_sp)); - StreamString ss; - const char *var_representation = nullptr; - const char *var_name = var_value_sp->GetName().GetCString(); - if (var_value_sp->GetCompilerType().IsValid()) - { - if (var_value_sp && exe_scope->CalculateTarget()) - var_value_sp = var_value_sp->GetQualifiedRepresentationIfAvailable(exe_scope->CalculateTarget()->TargetProperties::GetPreferDynamicValue(), - exe_scope->CalculateTarget()->TargetProperties::GetEnableSyntheticValue()); - if (var_value_sp->GetCompilerType().IsAggregateType() && - DataVisualization::ShouldPrintAsOneLiner(*var_value_sp)) - { - static StringSummaryFormat format(TypeSummaryImpl::Flags() - .SetHideItemNames(false) - .SetShowMembersOneLiner(true), - ""); - format.FormatObject(var_value_sp.get(), buffer, TypeSummaryOptions()); - var_representation = buffer.c_str(); - } - else - var_value_sp->DumpPrintableRepresentation(ss, - ValueObject::ValueObjectRepresentationStyle::eValueObjectRepresentationStyleSummary, - eFormatDefault, - ValueObject::PrintableRepresentationSpecialCases::ePrintableRepresentationSpecialCasesAllow, - false); - } - - if (ss.GetData() && ss.GetSize()) - var_representation = ss.GetData(); - if (arg_idx > 0) - s.PutCString (", "); - if (var_value_sp->GetError().Success()) - { - if (var_representation) - s.Printf ("%s=%s", var_name, var_representation); - else - s.Printf ("%s=%s at %s", var_name, var_value_sp->GetTypeName().GetCString(), var_value_sp->GetLocationAsCString()); - } - else - s.Printf ("%s=<unavailable>", var_name); - } - - if (close_paren) - s.PutCString (close_paren); - else - s.PutChar(')'); - - } - else - { - s.PutCString(cstr); - } - return true; - } - } - else if (sc->symbol) - { - const char *cstr = sc->symbol->GetName().AsCString(nullptr); - if (cstr) - { - s.PutCString(cstr); - return true; - } - } - } - } - return false; + } else { + s.PutCString(cstr); + } + return true; + } + } else if (sc->symbol) { + const char *cstr = sc->symbol->GetName().AsCString(nullptr); + if (cstr) { + s.PutCString(cstr); + return true; + } + } + } + } + return false; - case Entry::Type::FunctionAddrOffset: - if (addr) - { - if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, *addr, false, false, false)) - return true; - } - return false; + case Entry::Type::FunctionAddrOffset: + if (addr) { + if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, false, false, + false)) + return true; + } + return false; - case Entry::Type::FunctionAddrOffsetConcrete: - if (addr) - { - if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, *addr, true, true, true)) - return true; - } - return false; - - case Entry::Type::FunctionLineOffset: - return (DumpAddressOffsetFromFunction (s, sc, exe_ctx, sc->line_entry.range.GetBaseAddress(), false, false, false)); - - case Entry::Type::FunctionPCOffset: - if (exe_ctx) - { - StackFrame *frame = exe_ctx->GetFramePtr(); - if (frame) - { - if (DumpAddressOffsetFromFunction (s, sc, exe_ctx, frame->GetFrameCodeAddress(), false, false, false)) - return true; - } - } - return false; + case Entry::Type::FunctionAddrOffsetConcrete: + if (addr) { + if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, *addr, true, true, + true)) + return true; + } + return false; - case Entry::Type::FunctionChanged: - return function_changed; + case Entry::Type::FunctionLineOffset: + return (DumpAddressOffsetFromFunction(s, sc, exe_ctx, + sc->line_entry.range.GetBaseAddress(), + false, false, false)); + + case Entry::Type::FunctionPCOffset: + if (exe_ctx) { + StackFrame *frame = exe_ctx->GetFramePtr(); + if (frame) { + if (DumpAddressOffsetFromFunction(s, sc, exe_ctx, + frame->GetFrameCodeAddress(), false, + false, false)) + return true; + } + } + return false; - case Entry::Type::FunctionIsOptimized: - { - bool is_optimized = false; - if (sc->function && sc->function->GetIsOptimized()) - { - is_optimized = true; - } - return is_optimized; - } + case Entry::Type::FunctionChanged: + return function_changed; - case Entry::Type::FunctionInitial: - return initial_function; - - case Entry::Type::LineEntryFile: - if (sc && sc->line_entry.IsValid()) - { - Module *module = sc->module_sp.get(); - if (module) - { - if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number)) - return true; - } - } - return false; - - case Entry::Type::LineEntryLineNumber: - if (sc && sc->line_entry.IsValid()) - { - const char *format = "%" PRIu32; - if (!entry.printf_format.empty()) - format = entry.printf_format.c_str(); - s.Printf(format, sc->line_entry.line); - return true; - } - return false; - - case Entry::Type::LineEntryStartAddress: - case Entry::Type::LineEntryEndAddress: - if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) - { - Address addr = sc->line_entry.range.GetBaseAddress(); - - if (entry.type == Entry::Type::LineEntryEndAddress) - addr.Slide(sc->line_entry.range.GetByteSize()); - if (DumpAddress(s, sc, exe_ctx, addr, false)) - return true; - } - return false; - - case Entry::Type::CurrentPCArrow: - if (addr && exe_ctx && exe_ctx->GetFramePtr()) - { - RegisterContextSP reg_ctx = exe_ctx->GetFramePtr()->GetRegisterContextSP(); - if (reg_ctx) - { - addr_t pc_loadaddr = reg_ctx->GetPC(); - if (pc_loadaddr != LLDB_INVALID_ADDRESS) - { - Address pc; - pc.SetLoadAddress (pc_loadaddr, exe_ctx->GetTargetPtr()); - if (pc == *addr) - { - s.Printf ("-> "); - return true; - } - } - } - s.Printf(" "); - return true; - } - return false; + case Entry::Type::FunctionIsOptimized: { + bool is_optimized = false; + if (sc->function && sc->function->GetIsOptimized()) { + is_optimized = true; + } + return is_optimized; + } + + case Entry::Type::FunctionInitial: + return initial_function; + + case Entry::Type::LineEntryFile: + if (sc && sc->line_entry.IsValid()) { + Module *module = sc->module_sp.get(); + if (module) { + if (DumpFile(s, sc->line_entry.file, (FileKind)entry.number)) + return true; + } } return false; -} -static bool -DumpCommaSeparatedChildEntryNames (Stream &s, const FormatEntity::Entry::Definition *parent) -{ - if (parent->children) - { - const size_t n = parent->num_children; - for (size_t i = 0; i < n; ++i) - { - if (i > 0) - s.PutCString(", "); - s.Printf ("\"%s\"", parent->children[i].name); - } - return true; + case Entry::Type::LineEntryLineNumber: + if (sc && sc->line_entry.IsValid()) { + const char *format = "%" PRIu32; + if (!entry.printf_format.empty()) + format = entry.printf_format.c_str(); + s.Printf(format, sc->line_entry.line); + return true; } return false; -} -static Error -ParseEntry (const llvm::StringRef &format_str, - const FormatEntity::Entry::Definition *parent, - FormatEntity::Entry &entry) -{ - Error error; + case Entry::Type::LineEntryStartAddress: + case Entry::Type::LineEntryEndAddress: + if (sc && sc->line_entry.range.GetBaseAddress().IsValid()) { + Address addr = sc->line_entry.range.GetBaseAddress(); - const size_t sep_pos = format_str.find_first_of(".[:"); - const char sep_char = (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos]; - llvm::StringRef key = format_str.substr(0, sep_pos); + if (entry.type == Entry::Type::LineEntryEndAddress) + addr.Slide(sc->line_entry.range.GetByteSize()); + if (DumpAddress(s, sc, exe_ctx, addr, false)) + return true; + } + return false; - const size_t n = parent->num_children; - for (size_t i = 0; i < n; ++i) - { - const FormatEntity::Entry::Definition *entry_def = parent->children + i; - if (key.equals(entry_def->name) || entry_def->name[0] == '*') - { - llvm::StringRef value; - if (sep_char) - value = format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1)); - switch (entry_def->type) - { - case FormatEntity::Entry::Type::ParentString: - entry.string = format_str.str(); - return error; // Success - - case FormatEntity::Entry::Type::ParentNumber: - entry.number = entry_def->data; - return error; // Success - - case FormatEntity::Entry::Type::InsertString: - entry.type = entry_def->type; - entry.string = entry_def->string; - return error; // Success + case Entry::Type::CurrentPCArrow: + if (addr && exe_ctx && exe_ctx->GetFramePtr()) { + RegisterContextSP reg_ctx = + exe_ctx->GetFramePtr()->GetRegisterContextSP(); + if (reg_ctx) { + addr_t pc_loadaddr = reg_ctx->GetPC(); + if (pc_loadaddr != LLDB_INVALID_ADDRESS) { + Address pc; + pc.SetLoadAddress(pc_loadaddr, exe_ctx->GetTargetPtr()); + if (pc == *addr) { + s.Printf("-> "); + return true; + } + } + } + s.Printf(" "); + return true; + } + return false; + } + return false; +} - default: - entry.type = entry_def->type; - break; - } +static bool DumpCommaSeparatedChildEntryNames( + Stream &s, const FormatEntity::Entry::Definition *parent) { + if (parent->children) { + const size_t n = parent->num_children; + for (size_t i = 0; i < n; ++i) { + if (i > 0) + s.PutCString(", "); + s.Printf("\"%s\"", parent->children[i].name); + } + return true; + } + return false; +} - if (value.empty()) - { - if (entry_def->type == FormatEntity::Entry::Type::Invalid) - { - if (entry_def->children) - { - StreamString error_strm; - error_strm.Printf("'%s' can't be specified on its own, you must access one of its children: ", entry_def->name); - DumpCommaSeparatedChildEntryNames (error_strm, entry_def); - error.SetErrorStringWithFormat("%s", error_strm.GetString().c_str()); - } - else if (sep_char == ':') - { - // Any value whose separator is a with a ':' means this value has a string argument - // that needs to be stored in the entry (like "${script.var:}"). - // In this case the string value is the empty string which is ok. - } - else - { - error.SetErrorStringWithFormat("%s", "invalid entry definitions"); - } - } - } - else - { - if (entry_def->children) - { - error = ParseEntry (value, entry_def, entry); - } - else if (sep_char == ':') - { - // Any value whose separator is a with a ':' means this value has a string argument - // that needs to be stored in the entry (like "${script.var:modulename.function}") - entry.string = value.str(); - } - else - { - error.SetErrorStringWithFormat("'%s' followed by '%s' but it has no children", - key.str().c_str(), - value.str().c_str()); - } - } - return error; +static Error ParseEntry(const llvm::StringRef &format_str, + const FormatEntity::Entry::Definition *parent, + FormatEntity::Entry &entry) { + Error error; + + const size_t sep_pos = format_str.find_first_of(".[:"); + const char sep_char = + (sep_pos == llvm::StringRef::npos) ? '\0' : format_str[sep_pos]; + llvm::StringRef key = format_str.substr(0, sep_pos); + + const size_t n = parent->num_children; + for (size_t i = 0; i < n; ++i) { + const FormatEntity::Entry::Definition *entry_def = parent->children + i; + if (key.equals(entry_def->name) || entry_def->name[0] == '*') { + llvm::StringRef value; + if (sep_char) + value = + format_str.substr(sep_pos + (entry_def->keep_separator ? 0 : 1)); + switch (entry_def->type) { + case FormatEntity::Entry::Type::ParentString: + entry.string = format_str.str(); + return error; // Success + + case FormatEntity::Entry::Type::ParentNumber: + entry.number = entry_def->data; + return error; // Success + + case FormatEntity::Entry::Type::InsertString: + entry.type = entry_def->type; + entry.string = entry_def->string; + return error; // Success + + default: + entry.type = entry_def->type; + break; + } + + if (value.empty()) { + if (entry_def->type == FormatEntity::Entry::Type::Invalid) { + if (entry_def->children) { + StreamString error_strm; + error_strm.Printf("'%s' can't be specified on its own, you must " + "access one of its children: ", + entry_def->name); + DumpCommaSeparatedChildEntryNames(error_strm, entry_def); + error.SetErrorStringWithFormat("%s", error_strm.GetData()); + } else if (sep_char == ':') { + // Any value whose separator is a with a ':' means this value has a + // string argument + // that needs to be stored in the entry (like "${script.var:}"). + // In this case the string value is the empty string which is ok. + } else { + error.SetErrorStringWithFormat("%s", "invalid entry definitions"); + } + } + } else { + if (entry_def->children) { + error = ParseEntry(value, entry_def, entry); + } else if (sep_char == ':') { + // Any value whose separator is a with a ':' means this value has a + // string argument + // that needs to be stored in the entry (like + // "${script.var:modulename.function}") + entry.string = value.str(); + } else { + error.SetErrorStringWithFormat( + "'%s' followed by '%s' but it has no children", key.str().c_str(), + value.str().c_str()); } + } + return error; } - StreamString error_strm; - if (parent->type == FormatEntity::Entry::Type::Root) - error_strm.Printf("invalid top level item '%s'. Valid top level items are: ", key.str().c_str()); - else - error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ", key.str().c_str(), parent->name); - DumpCommaSeparatedChildEntryNames (error_strm, parent); - error.SetErrorStringWithFormat("%s", error_strm.GetString().c_str()); - return error; + } + StreamString error_strm; + if (parent->type == FormatEntity::Entry::Type::Root) + error_strm.Printf( + "invalid top level item '%s'. Valid top level items are: ", + key.str().c_str()); + else + error_strm.Printf("invalid member '%s' in '%s'. Valid members are: ", + key.str().c_str(), parent->name); + DumpCommaSeparatedChildEntryNames(error_strm, parent); + error.SetErrorStringWithFormat("%s", error_strm.GetData()); + return error; } static const FormatEntity::Entry::Definition * -FindEntry (const llvm::StringRef &format_str, const FormatEntity::Entry::Definition *parent, llvm::StringRef &remainder) -{ - Error error; - - std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.'); - const size_t n = parent->num_children; - for (size_t i = 0; i < n; ++i) - { - const FormatEntity::Entry::Definition *entry_def = parent->children + i; - if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') - { - if (p.second.empty()) - { - if (format_str.back() == '.') - remainder = format_str.drop_front(format_str.size() - 1); - else - remainder = llvm::StringRef(); // Exact match - return entry_def; - } - else - { - if (entry_def->children) - { - return FindEntry (p.second, entry_def, remainder); - } - else - { - remainder = p.second; - return entry_def; - } - } +FindEntry(const llvm::StringRef &format_str, + const FormatEntity::Entry::Definition *parent, + llvm::StringRef &remainder) { + Error error; + + std::pair<llvm::StringRef, llvm::StringRef> p = format_str.split('.'); + const size_t n = parent->num_children; + for (size_t i = 0; i < n; ++i) { + const FormatEntity::Entry::Definition *entry_def = parent->children + i; + if (p.first.equals(entry_def->name) || entry_def->name[0] == '*') { + if (p.second.empty()) { + if (format_str.back() == '.') + remainder = format_str.drop_front(format_str.size() - 1); + else + remainder = llvm::StringRef(); // Exact match + return entry_def; + } else { + if (entry_def->children) { + return FindEntry(p.second, entry_def, remainder); + } else { + remainder = p.second; + return entry_def; } + } } - remainder = format_str; - return parent; + } + remainder = format_str; + return parent; } -Error -FormatEntity::ParseInternal (llvm::StringRef &format, Entry &parent_entry, uint32_t depth) -{ - Error error; - while (!format.empty() && error.Success()) - { - const size_t non_special_chars = format.find_first_of("${}\\"); +Error FormatEntity::ParseInternal(llvm::StringRef &format, Entry &parent_entry, + uint32_t depth) { + Error error; + while (!format.empty() && error.Success()) { + const size_t non_special_chars = format.find_first_of("${}\\"); + + if (non_special_chars == llvm::StringRef::npos) { + // No special characters, just string bytes so add them and we are done + parent_entry.AppendText(format); + return error; + } + + if (non_special_chars > 0) { + // We have a special character, so add all characters before these as a + // plain string + parent_entry.AppendText(format.substr(0, non_special_chars)); + format = format.drop_front(non_special_chars); + } - if (non_special_chars == llvm::StringRef::npos) + switch (format[0]) { + case '\0': + return error; + + case '{': { + format = format.drop_front(); // Skip the '{' + Entry scope_entry(Entry::Type::Scope); + error = FormatEntity::ParseInternal(format, scope_entry, depth + 1); + if (error.Fail()) + return error; + parent_entry.AppendEntry(std::move(scope_entry)); + } break; + + case '}': + if (depth == 0) + error.SetErrorString("unmatched '}' character"); + else + format = + format + .drop_front(); // Skip the '}' as we are at the end of the scope + return error; + + case '\\': { + format = format.drop_front(); // Skip the '\' character + if (format.empty()) { + error.SetErrorString( + "'\\' character was not followed by another character"); + return error; + } + + const char desens_char = format[0]; + format = format.drop_front(); // Skip the desensitized char character + switch (desens_char) { + case 'a': + parent_entry.AppendChar('\a'); + break; + case 'b': + parent_entry.AppendChar('\b'); + break; + case 'f': + parent_entry.AppendChar('\f'); + break; + case 'n': + parent_entry.AppendChar('\n'); + break; + case 'r': + parent_entry.AppendChar('\r'); + break; + case 't': + parent_entry.AppendChar('\t'); + break; + case 'v': + parent_entry.AppendChar('\v'); + break; + case '\'': + parent_entry.AppendChar('\''); + break; + case '\\': + parent_entry.AppendChar('\\'); + break; + case '0': + // 1 to 3 octal chars { - // No special characters, just string bytes so add them and we are done - parent_entry.AppendText(format); + // Make a string that can hold onto the initial zero char, + // up to 3 octal digits, and a terminating NULL. + char oct_str[5] = {0, 0, 0, 0, 0}; + + int i; + for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i) + oct_str[i] = format[i]; + + // We don't want to consume the last octal character since + // the main for loop will do this for us, so we advance p by + // one less than i (even if i is zero) + format = format.drop_front(i); + unsigned long octal_value = ::strtoul(oct_str, nullptr, 8); + if (octal_value <= UINT8_MAX) { + parent_entry.AppendChar((char)octal_value); + } else { + error.SetErrorString("octal number is larger than a single byte"); return error; + } } + break; - if (non_special_chars > 0) - { - // We have a special character, so add all characters before these as a plain string - parent_entry.AppendText(format.substr(0,non_special_chars)); - format = format.drop_front(non_special_chars); + case 'x': + // hex number in the format + if (isxdigit(format[0])) { + // Make a string that can hold onto two hex chars plus a + // NULL terminator + char hex_str[3] = {0, 0, 0}; + hex_str[0] = format[0]; + + format = format.drop_front(); + + if (isxdigit(format[0])) { + hex_str[1] = format[0]; + format = format.drop_front(); + } + + unsigned long hex_value = strtoul(hex_str, nullptr, 16); + if (hex_value <= UINT8_MAX) { + parent_entry.AppendChar((char)hex_value); + } else { + error.SetErrorString("hex number is larger than a single byte"); + return error; + } + } else { + parent_entry.AppendChar(desens_char); } + break; - switch (format[0]) - { - case '\0': + default: + // Just desensitize any other character by just printing what + // came after the '\' + parent_entry.AppendChar(desens_char); + break; + } + } break; + + case '$': + if (format.size() == 1) { + // '$' at the end of a format string, just print the '$' + parent_entry.AppendText("$"); + } else { + format = format.drop_front(); // Skip the '$' + + if (format[0] == '{') { + format = format.drop_front(); // Skip the '{' + + llvm::StringRef variable, variable_format; + error = FormatEntity::ExtractVariableInfo(format, variable, + variable_format); + if (error.Fail()) + return error; + bool verify_is_thread_id = false; + Entry entry; + if (!variable_format.empty()) { + entry.printf_format = variable_format.str(); + + // If the format contains a '%' we are going to assume this is + // a printf style format. So if you want to format your thread ID + // using "0x%llx" you can use: + // ${thread.id%0x%llx} + // + // If there is no '%' in the format, then it is assumed to be a + // LLDB format name, or one of the extended formats specified in + // the switch statement below. + + if (entry.printf_format.find('%') == std::string::npos) { + bool clear_printf = false; + + if (FormatManager::GetFormatFromCString( + entry.printf_format.c_str(), false, entry.fmt)) { + // We have an LLDB format, so clear the printf format + clear_printf = true; + } else if (entry.printf_format.size() == 1) { + switch (entry.printf_format[0]) { + case '@': // if this is an @ sign, print ObjC description + entry.number = ValueObject:: + eValueObjectRepresentationStyleLanguageSpecific; + clear_printf = true; + break; + case 'V': // if this is a V, print the value using the default + // format + entry.number = + ValueObject::eValueObjectRepresentationStyleValue; + clear_printf = true; + break; + case 'L': // if this is an L, print the location of the value + entry.number = + ValueObject::eValueObjectRepresentationStyleLocation; + clear_printf = true; + break; + case 'S': // if this is an S, print the summary after all + entry.number = + ValueObject::eValueObjectRepresentationStyleSummary; + clear_printf = true; + break; + case '#': // if this is a '#', print the number of children + entry.number = + ValueObject::eValueObjectRepresentationStyleChildrenCount; + clear_printf = true; + break; + case 'T': // if this is a 'T', print the type + entry.number = + ValueObject::eValueObjectRepresentationStyleType; + clear_printf = true; + break; + case 'N': // if this is a 'N', print the name + entry.number = + ValueObject::eValueObjectRepresentationStyleName; + clear_printf = true; + break; + case '>': // if this is a '>', print the expression path + entry.number = ValueObject:: + eValueObjectRepresentationStyleExpressionPath; + clear_printf = true; + break; + default: + error.SetErrorStringWithFormat("invalid format: '%s'", + entry.printf_format.c_str()); + return error; + } + } else if (FormatManager::GetFormatFromCString( + entry.printf_format.c_str(), true, entry.fmt)) { + clear_printf = true; + } else if (entry.printf_format == "tid") { + verify_is_thread_id = true; + } else { + error.SetErrorStringWithFormat("invalid format: '%s'", + entry.printf_format.c_str()); return error; + } - case '{': - { - format = format.drop_front(); // Skip the '{' - Entry scope_entry(Entry::Type::Scope); - error = FormatEntity::ParseInternal (format, scope_entry, depth+1); - if (error.Fail()) - return error; - parent_entry.AppendEntry(std::move(scope_entry)); - } - break; + // Our format string turned out to not be a printf style format + // so lets clear the string + if (clear_printf) + entry.printf_format.clear(); + } + } - case '}': - if (depth == 0) - error.SetErrorString("unmatched '}' character"); - else - format = format.drop_front(); // Skip the '}' as we are at the end of the scope - return error; + // Check for dereferences + if (variable[0] == '*') { + entry.deref = true; + variable = variable.drop_front(); + } - case '\\': - { - format = format.drop_front(); // Skip the '\' character - if (format.empty()) - { - error.SetErrorString("'\\' character was not followed by another character"); - return error; - } - - const char desens_char = format[0]; - format = format.drop_front(); // Skip the desensitized char character - switch (desens_char) - { - case 'a': parent_entry.AppendChar('\a'); break; - case 'b': parent_entry.AppendChar('\b'); break; - case 'f': parent_entry.AppendChar('\f'); break; - case 'n': parent_entry.AppendChar('\n'); break; - case 'r': parent_entry.AppendChar('\r'); break; - case 't': parent_entry.AppendChar('\t'); break; - case 'v': parent_entry.AppendChar('\v'); break; - case '\'': parent_entry.AppendChar('\''); break; - case '\\': parent_entry.AppendChar('\\'); break; - case '0': - // 1 to 3 octal chars - { - // Make a string that can hold onto the initial zero char, - // up to 3 octal digits, and a terminating NULL. - char oct_str[5] = { 0, 0, 0, 0, 0 }; - - int i; - for (i = 0; (format[i] >= '0' && format[i] <= '7') && i < 4; ++i) - oct_str[i] = format[i]; - - // We don't want to consume the last octal character since - // the main for loop will do this for us, so we advance p by - // one less than i (even if i is zero) - format = format.drop_front(i); - unsigned long octal_value = ::strtoul(oct_str, nullptr, 8); - if (octal_value <= UINT8_MAX) - { - parent_entry.AppendChar((char)octal_value); - } - else - { - error.SetErrorString("octal number is larger than a single byte"); - return error; - } - } - break; - - case 'x': - // hex number in the format - if (isxdigit(format[0])) - { - // Make a string that can hold onto two hex chars plus a - // NULL terminator - char hex_str[3] = { 0,0,0 }; - hex_str[0] = format[0]; - - format = format.drop_front(); - - if (isxdigit(format[0])) - { - hex_str[1] = format[0]; - format = format.drop_front(); - } - - unsigned long hex_value = strtoul(hex_str, nullptr, 16); - if (hex_value <= UINT8_MAX) - { - parent_entry.AppendChar((char)hex_value); - } - else - { - error.SetErrorString("hex number is larger than a single byte"); - return error; - } - } - else - { - parent_entry.AppendChar(desens_char); - } - break; - - default: - // Just desensitize any other character by just printing what - // came after the '\' - parent_entry.AppendChar(desens_char); - break; - } - } - break; + error = ParseEntry(variable, &g_root, entry); + if (error.Fail()) + return error; - case '$': - if (format.size() == 1) - { - // '$' at the end of a format string, just print the '$' - parent_entry.AppendText("$"); - } - else - { - format = format.drop_front(); // Skip the '$' - - if (format[0] == '{') - { - format = format.drop_front(); // Skip the '{' - - llvm::StringRef variable, variable_format; - error = FormatEntity::ExtractVariableInfo (format, variable, variable_format); - if (error.Fail()) - return error; - bool verify_is_thread_id = false; - Entry entry; - if (!variable_format.empty()) - { - entry.printf_format = variable_format.str(); - - // If the format contains a '%' we are going to assume this is - // a printf style format. So if you want to format your thread ID - // using "0x%llx" you can use: - // ${thread.id%0x%llx} - // - // If there is no '%' in the format, then it is assumed to be a - // LLDB format name, or one of the extended formats specified in - // the switch statement below. - - if (entry.printf_format.find('%') == std::string::npos) - { - bool clear_printf = false; - - if (FormatManager::GetFormatFromCString(entry.printf_format.c_str(), - false, - entry.fmt)) - { - // We have an LLDB format, so clear the printf format - clear_printf = true; - } - else if (entry.printf_format.size() == 1) - { - switch (entry.printf_format[0]) - { - case '@': // if this is an @ sign, print ObjC description - entry.number = ValueObject::eValueObjectRepresentationStyleLanguageSpecific; - clear_printf = true; - break; - case 'V': // if this is a V, print the value using the default format - entry.number = ValueObject::eValueObjectRepresentationStyleValue; - clear_printf = true; - break; - case 'L': // if this is an L, print the location of the value - entry.number = ValueObject::eValueObjectRepresentationStyleLocation; - clear_printf = true; - break; - case 'S': // if this is an S, print the summary after all - entry.number = ValueObject::eValueObjectRepresentationStyleSummary; - clear_printf = true; - break; - case '#': // if this is a '#', print the number of children - entry.number = ValueObject::eValueObjectRepresentationStyleChildrenCount; - clear_printf = true; - break; - case 'T': // if this is a 'T', print the type - entry.number = ValueObject::eValueObjectRepresentationStyleType; - clear_printf = true; - break; - case 'N': // if this is a 'N', print the name - entry.number = ValueObject::eValueObjectRepresentationStyleName; - clear_printf = true; - break; - case '>': // if this is a '>', print the expression path - entry.number = ValueObject::eValueObjectRepresentationStyleExpressionPath; - clear_printf = true; - break; - default: - error.SetErrorStringWithFormat("invalid format: '%s'", entry.printf_format.c_str()); - return error; - } - } - else if (FormatManager::GetFormatFromCString(entry.printf_format.c_str(), - true, - entry.fmt)) - { - clear_printf = true; - } - else if (entry.printf_format == "tid") - { - verify_is_thread_id = true; - } - else - { - error.SetErrorStringWithFormat("invalid format: '%s'", entry.printf_format.c_str()); - return error; - } - - // Our format string turned out to not be a printf style format - // so lets clear the string - if (clear_printf) - entry.printf_format.clear(); - } - } - - // Check for dereferences - if (variable[0] == '*') - { - entry.deref = true; - variable = variable.drop_front(); - } - - error = ParseEntry (variable, &g_root, entry); - if (error.Fail()) - return error; - - if (verify_is_thread_id) - { - if (entry.type != Entry::Type::ThreadID && - entry.type != Entry::Type::ThreadProtocolID) - { - error.SetErrorString("the 'tid' format can only be used on ${thread.id} and ${thread.protocol_id}"); - } - } - - switch (entry.type) - { - case Entry::Type::Variable: - case Entry::Type::VariableSynthetic: - if (entry.number == 0) - { - if (entry.string.empty()) - entry.number = ValueObject::eValueObjectRepresentationStyleValue; - else - entry.number = ValueObject::eValueObjectRepresentationStyleSummary; - } - break; - default: - // Make sure someone didn't try to dereference anything but ${var} or ${svar} - if (entry.deref) - { - error.SetErrorStringWithFormat("${%s} can't be dereferenced, only ${var} and ${svar} can.", variable.str().c_str()); - return error; - } - } - // Check if this entry just wants to insert a constant string - // value into the parent_entry, if so, insert the string with - // AppendText, else append the entry to the parent_entry. - if (entry.type == Entry::Type::InsertString) - parent_entry.AppendText(entry.string.c_str()); - else - parent_entry.AppendEntry(std::move(entry)); - } - } - break; + if (verify_is_thread_id) { + if (entry.type != Entry::Type::ThreadID && + entry.type != Entry::Type::ThreadProtocolID) { + error.SetErrorString("the 'tid' format can only be used on " + "${thread.id} and ${thread.protocol_id}"); + } + } + + switch (entry.type) { + case Entry::Type::Variable: + case Entry::Type::VariableSynthetic: + if (entry.number == 0) { + if (entry.string.empty()) + entry.number = + ValueObject::eValueObjectRepresentationStyleValue; + else + entry.number = + ValueObject::eValueObjectRepresentationStyleSummary; + } + break; + default: + // Make sure someone didn't try to dereference anything but ${var} + // or ${svar} + if (entry.deref) { + error.SetErrorStringWithFormat( + "${%s} can't be dereferenced, only ${var} and ${svar} can.", + variable.str().c_str()); + return error; + } + } + // Check if this entry just wants to insert a constant string + // value into the parent_entry, if so, insert the string with + // AppendText, else append the entry to the parent_entry. + if (entry.type == Entry::Type::InsertString) + parent_entry.AppendText(entry.string.c_str()); + else + parent_entry.AppendEntry(std::move(entry)); } + } + break; } - return error; + } + return error; } -Error -FormatEntity::ExtractVariableInfo (llvm::StringRef &format_str, llvm::StringRef &variable_name, llvm::StringRef &variable_format) -{ - Error error; - variable_name = llvm::StringRef(); - variable_format = llvm::StringRef(); - - const size_t paren_pos = format_str.find('}'); - if (paren_pos != llvm::StringRef::npos) - { - const size_t percent_pos = format_str.find('%'); - if (percent_pos < paren_pos) - { - if (percent_pos > 0) - { - if (percent_pos > 1) - variable_name = format_str.substr(0, percent_pos); - variable_format = format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1)); - } - } - else - { - variable_name = format_str.substr(0, paren_pos); - } - // Strip off elements and the formatting and the trailing '}' - format_str = format_str.substr(paren_pos + 1); +Error FormatEntity::ExtractVariableInfo(llvm::StringRef &format_str, + llvm::StringRef &variable_name, + llvm::StringRef &variable_format) { + Error error; + variable_name = llvm::StringRef(); + variable_format = llvm::StringRef(); + + const size_t paren_pos = format_str.find('}'); + if (paren_pos != llvm::StringRef::npos) { + const size_t percent_pos = format_str.find('%'); + if (percent_pos < paren_pos) { + if (percent_pos > 0) { + if (percent_pos > 1) + variable_name = format_str.substr(0, percent_pos); + variable_format = + format_str.substr(percent_pos + 1, paren_pos - (percent_pos + 1)); + } + } else { + variable_name = format_str.substr(0, paren_pos); } - else - { - error.SetErrorStringWithFormat("missing terminating '}' character for '${%s'", format_str.str().c_str()); - } - return error; + // Strip off elements and the formatting and the trailing '}' + format_str = format_str.substr(paren_pos + 1); + } else { + error.SetErrorStringWithFormat( + "missing terminating '}' character for '${%s'", + format_str.str().c_str()); + } + return error; } -bool -FormatEntity::FormatFileSpec (const FileSpec &file_spec, Stream &s, llvm::StringRef variable_name, llvm::StringRef variable_format) -{ - if (variable_name.empty() || variable_name.equals(".fullpath")) - { - file_spec.Dump(&s); - return true; - } - else if (variable_name.equals(".basename")) - { - s.PutCString(file_spec.GetFilename().AsCString("")); - return true; - } - else if (variable_name.equals(".dirname")) - { - s.PutCString(file_spec.GetFilename().AsCString("")); - return true; - } - return false; +bool FormatEntity::FormatFileSpec(const FileSpec &file_spec, Stream &s, + llvm::StringRef variable_name, + llvm::StringRef variable_format) { + if (variable_name.empty() || variable_name.equals(".fullpath")) { + file_spec.Dump(&s); + return true; + } else if (variable_name.equals(".basename")) { + s.PutCString(file_spec.GetFilename().AsCString("")); + return true; + } else if (variable_name.equals(".dirname")) { + s.PutCString(file_spec.GetFilename().AsCString("")); + return true; + } + return false; } -static std::string -MakeMatch (const llvm::StringRef &prefix, const char *suffix) -{ - std::string match(prefix.str()); - match.append(suffix); - return match; +static std::string MakeMatch(const llvm::StringRef &prefix, + const char *suffix) { + std::string match(prefix.str()); + match.append(suffix); + return match; } -static void -AddMatches (const FormatEntity::Entry::Definition *def, - const llvm::StringRef &prefix, - const llvm::StringRef &match_prefix, - StringList &matches) -{ - const size_t n = def->num_children; - if (n > 0) - { - for (size_t i = 0; i < n; ++i) - { - std::string match = prefix.str(); - if (match_prefix.empty()) - matches.AppendString(MakeMatch (prefix, def->children[i].name)); - else if (strncmp(def->children[i].name, match_prefix.data(), match_prefix.size()) == 0) - matches.AppendString(MakeMatch (prefix, def->children[i].name + match_prefix.size())); - } +static void AddMatches(const FormatEntity::Entry::Definition *def, + const llvm::StringRef &prefix, + const llvm::StringRef &match_prefix, + StringList &matches) { + const size_t n = def->num_children; + if (n > 0) { + for (size_t i = 0; i < n; ++i) { + std::string match = prefix.str(); + if (match_prefix.empty()) + matches.AppendString(MakeMatch(prefix, def->children[i].name)); + else if (strncmp(def->children[i].name, match_prefix.data(), + match_prefix.size()) == 0) + matches.AppendString( + MakeMatch(prefix, def->children[i].name + match_prefix.size())); } + } } -size_t -FormatEntity::AutoComplete (const char *s, - int match_start_point, - int max_return_elements, - bool &word_complete, - StringList &matches) -{ - word_complete = false; - llvm::StringRef str(s + match_start_point); - matches.Clear(); - - const size_t dollar_pos = str.rfind('$'); - if (dollar_pos != llvm::StringRef::npos) - { - // Hitting TAB after $ at the end of the string add a "{" - if (dollar_pos == str.size() - 1) - { - std::string match = str.str(); - match.append("{"); - matches.AppendString(std::move(match)); - } - else if (str[dollar_pos + 1] == '{') - { - const size_t close_pos = str.find('}', dollar_pos + 2); - if (close_pos == llvm::StringRef::npos) - { - const size_t format_pos = str.find('%', dollar_pos + 2); - if (format_pos == llvm::StringRef::npos) - { - llvm::StringRef partial_variable (str.substr(dollar_pos + 2)); - if (partial_variable.empty()) - { - // Suggest all top level entites as we are just past "${" - AddMatches(&g_root, str, llvm::StringRef(), matches); - } - else - { - // We have a partially specified variable, find it - llvm::StringRef remainder; - const FormatEntity::Entry::Definition* entry_def = FindEntry (partial_variable, &g_root, remainder); - if (entry_def) - { - const size_t n = entry_def->num_children; - - if (remainder.empty()) - { - // Exact match - if (n > 0) - { - // "${thread.info" <TAB> - matches.AppendString(MakeMatch(str, ".")); - } - else - { - // "${thread.id" <TAB> - matches.AppendString(MakeMatch (str, "}")); - word_complete = true; - } - } - else if (remainder.equals(".")) - { - // "${thread." <TAB> - AddMatches(entry_def, str, llvm::StringRef(), matches); - } - else - { - // We have a partial match - // "${thre" <TAB> - AddMatches(entry_def, str, remainder, matches); - } - } - } - } - } - } - } +size_t FormatEntity::AutoComplete(llvm::StringRef str, int match_start_point, + int max_return_elements, bool &word_complete, + StringList &matches) { + word_complete = false; + str = str.drop_front(match_start_point); + matches.Clear(); + + const size_t dollar_pos = str.rfind('$'); + if (dollar_pos == llvm::StringRef::npos) + return 0; + + // Hitting TAB after $ at the end of the string add a "{" + if (dollar_pos == str.size() - 1) { + std::string match = str.str(); + match.append("{"); + matches.AppendString(match); + return 1; + } + + if (str[dollar_pos + 1] != '{') + return 0; + + const size_t close_pos = str.find('}', dollar_pos + 2); + if (close_pos != llvm::StringRef::npos) + return 0; + + const size_t format_pos = str.find('%', dollar_pos + 2); + if (format_pos != llvm::StringRef::npos) + return 0; + + llvm::StringRef partial_variable(str.substr(dollar_pos + 2)); + if (partial_variable.empty()) { + // Suggest all top level entites as we are just past "${" + AddMatches(&g_root, str, llvm::StringRef(), matches); return matches.GetSize(); + } + + // We have a partially specified variable, find it + llvm::StringRef remainder; + const FormatEntity::Entry::Definition *entry_def = + FindEntry(partial_variable, &g_root, remainder); + if (!entry_def) + return 0; + + const size_t n = entry_def->num_children; + + if (remainder.empty()) { + // Exact match + if (n > 0) { + // "${thread.info" <TAB> + matches.AppendString(MakeMatch(str, ".")); + } else { + // "${thread.id" <TAB> + matches.AppendString(MakeMatch(str, "}")); + word_complete = true; + } + } else if (remainder.equals(".")) { + // "${thread." <TAB> + AddMatches(entry_def, str, llvm::StringRef(), matches); + } else { + // We have a partial match + // "${thre" <TAB> + AddMatches(entry_def, str, remainder, matches); + } + return matches.GetSize(); } diff --git a/source/Core/History.cpp b/source/Core/History.cpp index 0105dce730d2..0466a83da519 100644 --- a/source/Core/History.cpp +++ b/source/Core/History.cpp @@ -19,8 +19,6 @@ using namespace lldb; using namespace lldb_private; -void -HistorySourceUInt::DumpHistoryEvent (Stream &strm, HistoryEvent event) -{ - strm.Printf ("%s %" PRIu64, m_name.c_str(), (uint64_t)((uintptr_t)event)); +void HistorySourceUInt::DumpHistoryEvent(Stream &strm, HistoryEvent event) { + strm.Printf("%s %" PRIu64, m_name.c_str(), (uint64_t)((uintptr_t)event)); } diff --git a/source/Core/IOHandler.cpp b/source/Core/IOHandler.cpp index bab0263a0c6e..9c5e6ca80c20 100644 --- a/source/Core/IOHandler.cpp +++ b/source/Core/IOHandler.cpp @@ -22,8 +22,8 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointLocation.h" -#include "lldb/Core/IOHandler.h" #include "lldb/Core/Debugger.h" +#include "lldb/Core/IOHandler.h" #include "lldb/Core/Module.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamFile.h" @@ -41,10 +41,10 @@ #ifndef LLDB_DISABLE_CURSES #include "lldb/Core/ValueObject.h" #include "lldb/Symbol/VariableList.h" -#include "lldb/Target/Target.h" #include "lldb/Target/Process.h" -#include "lldb/Target/Thread.h" #include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" #endif #ifdef _MSC_VER @@ -54,771 +54,584 @@ using namespace lldb; using namespace lldb_private; -IOHandler::IOHandler (Debugger &debugger, IOHandler::Type type) : - IOHandler (debugger, - type, - StreamFileSP(), // Adopt STDIN from top input reader - StreamFileSP(), // Adopt STDOUT from top input reader - StreamFileSP(), // Adopt STDERR from top input reader - 0) // Flags -{ -} - -IOHandler::IOHandler (Debugger &debugger, - IOHandler::Type type, - const lldb::StreamFileSP &input_sp, - const lldb::StreamFileSP &output_sp, - const lldb::StreamFileSP &error_sp, - uint32_t flags) : - m_debugger (debugger), - m_input_sp (input_sp), - m_output_sp (output_sp), - m_error_sp (error_sp), - m_popped (false), - m_flags (flags), - m_type (type), - m_user_data(nullptr), - m_done (false), - m_active (false) -{ - // If any files are not specified, then adopt them from the top input reader. - if (!m_input_sp || !m_output_sp || !m_error_sp) - debugger.AdoptTopIOHandlerFilesIfInvalid (m_input_sp, - m_output_sp, - m_error_sp); +IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type) + : IOHandler(debugger, type, + StreamFileSP(), // Adopt STDIN from top input reader + StreamFileSP(), // Adopt STDOUT from top input reader + StreamFileSP(), // Adopt STDERR from top input reader + 0) // Flags +{} + +IOHandler::IOHandler(Debugger &debugger, IOHandler::Type type, + const lldb::StreamFileSP &input_sp, + const lldb::StreamFileSP &output_sp, + const lldb::StreamFileSP &error_sp, uint32_t flags) + : m_debugger(debugger), m_input_sp(input_sp), m_output_sp(output_sp), + m_error_sp(error_sp), m_popped(false), m_flags(flags), m_type(type), + m_user_data(nullptr), m_done(false), m_active(false) { + // If any files are not specified, then adopt them from the top input reader. + if (!m_input_sp || !m_output_sp || !m_error_sp) + debugger.AdoptTopIOHandlerFilesIfInvalid(m_input_sp, m_output_sp, + m_error_sp); } IOHandler::~IOHandler() = default; -int -IOHandler::GetInputFD() -{ - return (m_input_sp ? m_input_sp->GetFile().GetDescriptor() : -1); +int IOHandler::GetInputFD() { + return (m_input_sp ? m_input_sp->GetFile().GetDescriptor() : -1); } -int -IOHandler::GetOutputFD() -{ - return (m_output_sp ? m_output_sp->GetFile().GetDescriptor() : -1); +int IOHandler::GetOutputFD() { + return (m_output_sp ? m_output_sp->GetFile().GetDescriptor() : -1); } -int -IOHandler::GetErrorFD() -{ - return (m_error_sp ? m_error_sp->GetFile().GetDescriptor() : -1); +int IOHandler::GetErrorFD() { + return (m_error_sp ? m_error_sp->GetFile().GetDescriptor() : -1); } -FILE * -IOHandler::GetInputFILE() -{ - return (m_input_sp ? m_input_sp->GetFile().GetStream() : nullptr); +FILE *IOHandler::GetInputFILE() { + return (m_input_sp ? m_input_sp->GetFile().GetStream() : nullptr); } -FILE * -IOHandler::GetOutputFILE() -{ - return (m_output_sp ? m_output_sp->GetFile().GetStream() : nullptr); +FILE *IOHandler::GetOutputFILE() { + return (m_output_sp ? m_output_sp->GetFile().GetStream() : nullptr); } -FILE * -IOHandler::GetErrorFILE() -{ - return (m_error_sp ? m_error_sp->GetFile().GetStream() : nullptr); +FILE *IOHandler::GetErrorFILE() { + return (m_error_sp ? m_error_sp->GetFile().GetStream() : nullptr); } -StreamFileSP & -IOHandler::GetInputStreamFile() -{ - return m_input_sp; -} +StreamFileSP &IOHandler::GetInputStreamFile() { return m_input_sp; } -StreamFileSP & -IOHandler::GetOutputStreamFile() -{ - return m_output_sp; -} +StreamFileSP &IOHandler::GetOutputStreamFile() { return m_output_sp; } -StreamFileSP & -IOHandler::GetErrorStreamFile() -{ - return m_error_sp; -} +StreamFileSP &IOHandler::GetErrorStreamFile() { return m_error_sp; } -bool -IOHandler::GetIsInteractive () -{ - return GetInputStreamFile()->GetFile().GetIsInteractive (); +bool IOHandler::GetIsInteractive() { + return GetInputStreamFile()->GetFile().GetIsInteractive(); } -bool -IOHandler::GetIsRealTerminal () -{ - return GetInputStreamFile()->GetFile().GetIsRealTerminal(); +bool IOHandler::GetIsRealTerminal() { + return GetInputStreamFile()->GetFile().GetIsRealTerminal(); } -void -IOHandler::SetPopped (bool b) -{ - m_popped.SetValue(b, eBroadcastOnChange); -} +void IOHandler::SetPopped(bool b) { m_popped.SetValue(b, eBroadcastOnChange); } -void -IOHandler::WaitForPop () -{ - m_popped.WaitForValueEqualTo(true); -} +void IOHandler::WaitForPop() { m_popped.WaitForValueEqualTo(true); } -void -IOHandlerStack::PrintAsync(Stream *stream, const char *s, size_t len) -{ - if (stream) - { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - if (m_top) - m_top->PrintAsync(stream, s, len); - } +void IOHandlerStack::PrintAsync(Stream *stream, const char *s, size_t len) { + if (stream) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + if (m_top) + m_top->PrintAsync(stream, s, len); + } } -IOHandlerConfirm::IOHandlerConfirm (Debugger &debugger, - const char *prompt, - bool default_response) : - IOHandlerEditline(debugger, - IOHandler::Type::Confirm, - nullptr, // nullptr editline_name means no history loaded/saved - nullptr, // No prompt - nullptr, // No continuation prompt - false, // Multi-line - false, // Don't colorize the prompt (i.e. the confirm message.) - 0, - *this), - m_default_response (default_response), - m_user_response (default_response) -{ - StreamString prompt_stream; - prompt_stream.PutCString(prompt); - if (m_default_response) - prompt_stream.Printf(": [Y/n] "); - else - prompt_stream.Printf(": [y/N] "); - - SetPrompt (prompt_stream.GetString().c_str()); +IOHandlerConfirm::IOHandlerConfirm(Debugger &debugger, llvm::StringRef prompt, + bool default_response) + : IOHandlerEditline( + debugger, IOHandler::Type::Confirm, + nullptr, // nullptr editline_name means no history loaded/saved + llvm::StringRef(), // No prompt + llvm::StringRef(), // No continuation prompt + false, // Multi-line + false, // Don't colorize the prompt (i.e. the confirm message.) + 0, *this), + m_default_response(default_response), m_user_response(default_response) { + StreamString prompt_stream; + prompt_stream.PutCString(prompt); + if (m_default_response) + prompt_stream.Printf(": [Y/n] "); + else + prompt_stream.Printf(": [y/N] "); + + SetPrompt(prompt_stream.GetString()); } IOHandlerConfirm::~IOHandlerConfirm() = default; -int -IOHandlerConfirm::IOHandlerComplete (IOHandler &io_handler, - const char *current_line, - const char *cursor, - const char *last_char, - int skip_first_n_matches, - int max_matches, - StringList &matches) -{ - if (current_line == cursor) - { - if (m_default_response) - { - matches.AppendString("y"); - } - else - { - matches.AppendString("n"); - } +int IOHandlerConfirm::IOHandlerComplete(IOHandler &io_handler, + const char *current_line, + const char *cursor, + const char *last_char, + int skip_first_n_matches, + int max_matches, StringList &matches) { + if (current_line == cursor) { + if (m_default_response) { + matches.AppendString("y"); + } else { + matches.AppendString("n"); } - return matches.GetSize(); + } + return matches.GetSize(); } -void -IOHandlerConfirm::IOHandlerInputComplete (IOHandler &io_handler, std::string &line) -{ - if (line.empty()) - { - // User just hit enter, set the response to the default - m_user_response = m_default_response; - io_handler.SetIsDone(true); - return; - } - - if (line.size() == 1) - { - switch (line[0]) - { - case 'y': - case 'Y': - m_user_response = true; - io_handler.SetIsDone(true); - return; - case 'n': - case 'N': - m_user_response = false; - io_handler.SetIsDone(true); - return; - default: - break; - } - } - - if (line == "yes" || line == "YES" || line == "Yes") - { - m_user_response = true; - io_handler.SetIsDone(true); - } - else if (line == "no" || line == "NO" || line == "No") - { - m_user_response = false; - io_handler.SetIsDone(true); +void IOHandlerConfirm::IOHandlerInputComplete(IOHandler &io_handler, + std::string &line) { + if (line.empty()) { + // User just hit enter, set the response to the default + m_user_response = m_default_response; + io_handler.SetIsDone(true); + return; + } + + if (line.size() == 1) { + switch (line[0]) { + case 'y': + case 'Y': + m_user_response = true; + io_handler.SetIsDone(true); + return; + case 'n': + case 'N': + m_user_response = false; + io_handler.SetIsDone(true); + return; + default: + break; } + } + + if (line == "yes" || line == "YES" || line == "Yes") { + m_user_response = true; + io_handler.SetIsDone(true); + } else if (line == "no" || line == "NO" || line == "No") { + m_user_response = false; + io_handler.SetIsDone(true); + } } -int -IOHandlerDelegate::IOHandlerComplete (IOHandler &io_handler, - const char *current_line, - const char *cursor, - const char *last_char, - int skip_first_n_matches, - int max_matches, - StringList &matches) -{ - switch (m_completion) - { - case Completion::None: - break; - - case Completion::LLDBCommand: - return io_handler.GetDebugger().GetCommandInterpreter().HandleCompletion (current_line, - cursor, - last_char, - skip_first_n_matches, - max_matches, - matches); - - case Completion::Expression: - { - bool word_complete = false; - const char *word_start = cursor; - if (cursor > current_line) - --word_start; - while (word_start > current_line && !isspace(*word_start)) - --word_start; - CommandCompletions::InvokeCommonCompletionCallbacks(io_handler.GetDebugger().GetCommandInterpreter(), - CommandCompletions::eVariablePathCompletion, - word_start, - skip_first_n_matches, - max_matches, - nullptr, - word_complete, - matches); - - size_t num_matches = matches.GetSize(); - if (num_matches > 0) - { - std::string common_prefix; - matches.LongestCommonPrefix (common_prefix); - const size_t partial_name_len = strlen(word_start); - - // If we matched a unique single command, add a space... - // Only do this if the completer told us this was a complete word, however... - if (num_matches == 1 && word_complete) - { - common_prefix.push_back(' '); - } - common_prefix.erase (0, partial_name_len); - matches.InsertStringAtIndex(0, std::move(common_prefix)); - } - return num_matches; - } - break; +int IOHandlerDelegate::IOHandlerComplete(IOHandler &io_handler, + const char *current_line, + const char *cursor, + const char *last_char, + int skip_first_n_matches, + int max_matches, StringList &matches) { + switch (m_completion) { + case Completion::None: + break; + + case Completion::LLDBCommand: + return io_handler.GetDebugger().GetCommandInterpreter().HandleCompletion( + current_line, cursor, last_char, skip_first_n_matches, max_matches, + matches); + + case Completion::Expression: { + bool word_complete = false; + const char *word_start = cursor; + if (cursor > current_line) + --word_start; + while (word_start > current_line && !isspace(*word_start)) + --word_start; + CommandCompletions::InvokeCommonCompletionCallbacks( + io_handler.GetDebugger().GetCommandInterpreter(), + CommandCompletions::eVariablePathCompletion, word_start, + skip_first_n_matches, max_matches, nullptr, word_complete, matches); + + size_t num_matches = matches.GetSize(); + if (num_matches > 0) { + std::string common_prefix; + matches.LongestCommonPrefix(common_prefix); + const size_t partial_name_len = strlen(word_start); + + // If we matched a unique single command, add a space... + // Only do this if the completer told us this was a complete word, + // however... + if (num_matches == 1 && word_complete) { + common_prefix.push_back(' '); + } + common_prefix.erase(0, partial_name_len); + matches.InsertStringAtIndex(0, std::move(common_prefix)); } - - return 0; -} + return num_matches; + } break; + } -IOHandlerEditline::IOHandlerEditline (Debugger &debugger, - IOHandler::Type type, - const char *editline_name, // Used for saving history files - const char *prompt, - const char *continuation_prompt, - bool multi_line, - bool color_prompts, - uint32_t line_number_start, - IOHandlerDelegate &delegate) : - IOHandlerEditline(debugger, - type, - StreamFileSP(), // Inherit input from top input reader - StreamFileSP(), // Inherit output from top input reader - StreamFileSP(), // Inherit error from top input reader - 0, // Flags - editline_name, // Used for saving history files - prompt, - continuation_prompt, - multi_line, - color_prompts, - line_number_start, - delegate) -{ + return 0; } -IOHandlerEditline::IOHandlerEditline (Debugger &debugger, - IOHandler::Type type, - const lldb::StreamFileSP &input_sp, - const lldb::StreamFileSP &output_sp, - const lldb::StreamFileSP &error_sp, - uint32_t flags, - const char *editline_name, // Used for saving history files - const char *prompt, - const char *continuation_prompt, - bool multi_line, - bool color_prompts, - uint32_t line_number_start, - IOHandlerDelegate &delegate) : - IOHandler (debugger, type, input_sp, output_sp, error_sp, flags), +IOHandlerEditline::IOHandlerEditline( + Debugger &debugger, IOHandler::Type type, + const char *editline_name, // Used for saving history files + llvm::StringRef prompt, llvm::StringRef continuation_prompt, + bool multi_line, bool color_prompts, uint32_t line_number_start, + IOHandlerDelegate &delegate) + : IOHandlerEditline(debugger, type, + StreamFileSP(), // Inherit input from top input reader + StreamFileSP(), // Inherit output from top input reader + StreamFileSP(), // Inherit error from top input reader + 0, // Flags + editline_name, // Used for saving history files + prompt, continuation_prompt, multi_line, color_prompts, + line_number_start, delegate) {} + +IOHandlerEditline::IOHandlerEditline( + Debugger &debugger, IOHandler::Type type, + const lldb::StreamFileSP &input_sp, const lldb::StreamFileSP &output_sp, + const lldb::StreamFileSP &error_sp, uint32_t flags, + const char *editline_name, // Used for saving history files + llvm::StringRef prompt, llvm::StringRef continuation_prompt, + bool multi_line, bool color_prompts, uint32_t line_number_start, + IOHandlerDelegate &delegate) + : IOHandler(debugger, type, input_sp, output_sp, error_sp, flags), #ifndef LLDB_DISABLE_LIBEDIT - m_editline_ap (), + m_editline_ap(), #endif - m_delegate (delegate), - m_prompt (), - m_continuation_prompt(), - m_current_lines_ptr(nullptr), - m_base_line_number (line_number_start), - m_curr_line_idx (UINT32_MAX), - m_multi_line (multi_line), - m_color_prompts (color_prompts), - m_interrupt_exits (true), - m_editing (false) -{ - SetPrompt(prompt); + m_delegate(delegate), m_prompt(), m_continuation_prompt(), + m_current_lines_ptr(nullptr), m_base_line_number(line_number_start), + m_curr_line_idx(UINT32_MAX), m_multi_line(multi_line), + m_color_prompts(color_prompts), m_interrupt_exits(true), + m_editing(false) { + SetPrompt(prompt); #ifndef LLDB_DISABLE_LIBEDIT - bool use_editline = false; - - use_editline = m_input_sp->GetFile().GetIsRealTerminal(); - - if (use_editline) - { - m_editline_ap.reset(new Editline (editline_name, - GetInputFILE (), - GetOutputFILE (), - GetErrorFILE (), - m_color_prompts)); - m_editline_ap->SetIsInputCompleteCallback (IsInputCompleteCallback, this); - m_editline_ap->SetAutoCompleteCallback (AutoCompleteCallback, this); - // See if the delegate supports fixing indentation - const char *indent_chars = delegate.IOHandlerGetFixIndentationCharacters(); - if (indent_chars) - { - // The delegate does support indentation, hook it up so when any indentation - // character is typed, the delegate gets a chance to fix it - m_editline_ap->SetFixIndentationCallback (FixIndentationCallback, this, indent_chars); - } + bool use_editline = false; + + use_editline = m_input_sp->GetFile().GetIsRealTerminal(); + + if (use_editline) { + m_editline_ap.reset(new Editline(editline_name, GetInputFILE(), + GetOutputFILE(), GetErrorFILE(), + m_color_prompts)); + m_editline_ap->SetIsInputCompleteCallback(IsInputCompleteCallback, this); + m_editline_ap->SetAutoCompleteCallback(AutoCompleteCallback, this); + // See if the delegate supports fixing indentation + const char *indent_chars = delegate.IOHandlerGetFixIndentationCharacters(); + if (indent_chars) { + // The delegate does support indentation, hook it up so when any + // indentation + // character is typed, the delegate gets a chance to fix it + m_editline_ap->SetFixIndentationCallback(FixIndentationCallback, this, + indent_chars); } + } #endif - SetBaseLineNumber (m_base_line_number); - SetPrompt(prompt ? prompt : ""); - SetContinuationPrompt(continuation_prompt); + SetBaseLineNumber(m_base_line_number); + SetPrompt(prompt); + SetContinuationPrompt(continuation_prompt); } -IOHandlerEditline::~IOHandlerEditline () -{ +IOHandlerEditline::~IOHandlerEditline() { #ifndef LLDB_DISABLE_LIBEDIT - m_editline_ap.reset(); + m_editline_ap.reset(); #endif } -void -IOHandlerEditline::Activate () -{ - IOHandler::Activate(); - m_delegate.IOHandlerActivated(*this); +void IOHandlerEditline::Activate() { + IOHandler::Activate(); + m_delegate.IOHandlerActivated(*this); } -void -IOHandlerEditline::Deactivate () -{ - IOHandler::Deactivate(); - m_delegate.IOHandlerDeactivated(*this); +void IOHandlerEditline::Deactivate() { + IOHandler::Deactivate(); + m_delegate.IOHandlerDeactivated(*this); } -bool -IOHandlerEditline::GetLine (std::string &line, bool &interrupted) -{ +bool IOHandlerEditline::GetLine(std::string &line, bool &interrupted) { #ifndef LLDB_DISABLE_LIBEDIT - if (m_editline_ap) - { - return m_editline_ap->GetLine (line, interrupted); - } - else - { + if (m_editline_ap) { + return m_editline_ap->GetLine(line, interrupted); + } else { #endif - line.clear(); - - FILE *in = GetInputFILE(); - if (in) - { - if (GetIsInteractive()) - { - const char *prompt = nullptr; - - if (m_multi_line && m_curr_line_idx > 0) - prompt = GetContinuationPrompt(); - - if (prompt == nullptr) - prompt = GetPrompt(); - - if (prompt && prompt[0]) - { - FILE *out = GetOutputFILE(); - if (out) - { - ::fprintf(out, "%s", prompt); - ::fflush(out); - } - } - } - char buffer[256]; - bool done = false; - bool got_line = false; - m_editing = true; - while (!done) - { - if (fgets(buffer, sizeof(buffer), in) == nullptr) - { - const int saved_errno = errno; - if (feof(in)) - done = true; - else if (ferror(in)) - { - if (saved_errno != EINTR) - done = true; - } - } - else - { - got_line = true; - size_t buffer_len = strlen(buffer); - assert (buffer[buffer_len] == '\0'); - char last_char = buffer[buffer_len-1]; - if (last_char == '\r' || last_char == '\n') - { - done = true; - // Strip trailing newlines - while (last_char == '\r' || last_char == '\n') - { - --buffer_len; - if (buffer_len == 0) - break; - last_char = buffer[buffer_len-1]; - } - } - line.append(buffer, buffer_len); - } + line.clear(); + + FILE *in = GetInputFILE(); + if (in) { + if (GetIsInteractive()) { + const char *prompt = nullptr; + + if (m_multi_line && m_curr_line_idx > 0) + prompt = GetContinuationPrompt(); + + if (prompt == nullptr) + prompt = GetPrompt(); + + if (prompt && prompt[0]) { + FILE *out = GetOutputFILE(); + if (out) { + ::fprintf(out, "%s", prompt); + ::fflush(out); + } + } + } + char buffer[256]; + bool done = false; + bool got_line = false; + m_editing = true; + while (!done) { + if (fgets(buffer, sizeof(buffer), in) == nullptr) { + const int saved_errno = errno; + if (feof(in)) + done = true; + else if (ferror(in)) { + if (saved_errno != EINTR) + done = true; + } + } else { + got_line = true; + size_t buffer_len = strlen(buffer); + assert(buffer[buffer_len] == '\0'); + char last_char = buffer[buffer_len - 1]; + if (last_char == '\r' || last_char == '\n') { + done = true; + // Strip trailing newlines + while (last_char == '\r' || last_char == '\n') { + --buffer_len; + if (buffer_len == 0) + break; + last_char = buffer[buffer_len - 1]; } - m_editing = false; - // We might have gotten a newline on a line by itself - // make sure to return true in this case. - return got_line; - } - else - { - // No more input file, we are done... - SetIsDone(true); - } - return false; -#ifndef LLDB_DISABLE_LIBEDIT + } + line.append(buffer, buffer_len); + } + } + m_editing = false; + // We might have gotten a newline on a line by itself + // make sure to return true in this case. + return got_line; + } else { + // No more input file, we are done... + SetIsDone(true); } + return false; +#ifndef LLDB_DISABLE_LIBEDIT + } #endif } #ifndef LLDB_DISABLE_LIBEDIT -bool -IOHandlerEditline::IsInputCompleteCallback (Editline *editline, - StringList &lines, - void *baton) -{ - IOHandlerEditline *editline_reader = (IOHandlerEditline *) baton; - return editline_reader->m_delegate.IOHandlerIsInputComplete(*editline_reader, lines); +bool IOHandlerEditline::IsInputCompleteCallback(Editline *editline, + StringList &lines, + void *baton) { + IOHandlerEditline *editline_reader = (IOHandlerEditline *)baton; + return editline_reader->m_delegate.IOHandlerIsInputComplete(*editline_reader, + lines); } -int -IOHandlerEditline::FixIndentationCallback (Editline *editline, - const StringList &lines, - int cursor_position, - void *baton) -{ - IOHandlerEditline *editline_reader = (IOHandlerEditline *) baton; - return editline_reader->m_delegate.IOHandlerFixIndentation(*editline_reader, lines, cursor_position); +int IOHandlerEditline::FixIndentationCallback(Editline *editline, + const StringList &lines, + int cursor_position, + void *baton) { + IOHandlerEditline *editline_reader = (IOHandlerEditline *)baton; + return editline_reader->m_delegate.IOHandlerFixIndentation( + *editline_reader, lines, cursor_position); } -int -IOHandlerEditline::AutoCompleteCallback (const char *current_line, - const char *cursor, - const char *last_char, - int skip_first_n_matches, - int max_matches, - StringList &matches, - void *baton) -{ - IOHandlerEditline *editline_reader = (IOHandlerEditline *) baton; - if (editline_reader) - return editline_reader->m_delegate.IOHandlerComplete (*editline_reader, - current_line, - cursor, - last_char, - skip_first_n_matches, - max_matches, - matches); - return 0; +int IOHandlerEditline::AutoCompleteCallback(const char *current_line, + const char *cursor, + const char *last_char, + int skip_first_n_matches, + int max_matches, + StringList &matches, void *baton) { + IOHandlerEditline *editline_reader = (IOHandlerEditline *)baton; + if (editline_reader) + return editline_reader->m_delegate.IOHandlerComplete( + *editline_reader, current_line, cursor, last_char, skip_first_n_matches, + max_matches, matches); + return 0; } #endif -const char * -IOHandlerEditline::GetPrompt () -{ +const char *IOHandlerEditline::GetPrompt() { #ifndef LLDB_DISABLE_LIBEDIT - if (m_editline_ap) - { - return m_editline_ap->GetPrompt (); - } - else - { + if (m_editline_ap) { + return m_editline_ap->GetPrompt(); + } else { #endif - if (m_prompt.empty()) - return nullptr; + if (m_prompt.empty()) + return nullptr; #ifndef LLDB_DISABLE_LIBEDIT - } + } #endif - return m_prompt.c_str(); + return m_prompt.c_str(); } -bool -IOHandlerEditline::SetPrompt (const char *p) -{ - if (p && p[0]) - m_prompt = p; - else - m_prompt.clear(); +bool IOHandlerEditline::SetPrompt(llvm::StringRef prompt) { + m_prompt = prompt; + #ifndef LLDB_DISABLE_LIBEDIT - if (m_editline_ap) - m_editline_ap->SetPrompt(m_prompt.empty() ? nullptr : m_prompt.c_str()); + if (m_editline_ap) + m_editline_ap->SetPrompt(m_prompt.empty() ? nullptr : m_prompt.c_str()); #endif - return true; + return true; } -const char * -IOHandlerEditline::GetContinuationPrompt () -{ - return (m_continuation_prompt.empty() ? nullptr : m_continuation_prompt.c_str()); +const char *IOHandlerEditline::GetContinuationPrompt() { + return (m_continuation_prompt.empty() ? nullptr + : m_continuation_prompt.c_str()); } -void -IOHandlerEditline::SetContinuationPrompt (const char *p) -{ - if (p && p[0]) - m_continuation_prompt = p; - else - m_continuation_prompt.clear(); +void IOHandlerEditline::SetContinuationPrompt(llvm::StringRef prompt) { + m_continuation_prompt = prompt; #ifndef LLDB_DISABLE_LIBEDIT - if (m_editline_ap) - m_editline_ap->SetContinuationPrompt(m_continuation_prompt.empty() ? nullptr : m_continuation_prompt.c_str()); + if (m_editline_ap) + m_editline_ap->SetContinuationPrompt(m_continuation_prompt.empty() + ? nullptr + : m_continuation_prompt.c_str()); #endif } -void -IOHandlerEditline::SetBaseLineNumber (uint32_t line) -{ - m_base_line_number = line; +void IOHandlerEditline::SetBaseLineNumber(uint32_t line) { + m_base_line_number = line; } -uint32_t -IOHandlerEditline::GetCurrentLineIndex () const -{ +uint32_t IOHandlerEditline::GetCurrentLineIndex() const { #ifndef LLDB_DISABLE_LIBEDIT - if (m_editline_ap) - return m_editline_ap->GetCurrentLine(); + if (m_editline_ap) + return m_editline_ap->GetCurrentLine(); #endif - return m_curr_line_idx; + return m_curr_line_idx; } -bool -IOHandlerEditline::GetLines (StringList &lines, bool &interrupted) -{ - m_current_lines_ptr = &lines; - - bool success = false; +bool IOHandlerEditline::GetLines(StringList &lines, bool &interrupted) { + m_current_lines_ptr = &lines; + + bool success = false; #ifndef LLDB_DISABLE_LIBEDIT - if (m_editline_ap) - { - return m_editline_ap->GetLines (m_base_line_number, lines, interrupted); - } - else - { + if (m_editline_ap) { + return m_editline_ap->GetLines(m_base_line_number, lines, interrupted); + } else { #endif - bool done = false; - Error error; - - while (!done) - { - // Show line numbers if we are asked to - std::string line; - if (m_base_line_number > 0 && GetIsInteractive()) - { - FILE *out = GetOutputFILE(); - if (out) - ::fprintf(out, "%u%s", m_base_line_number + (uint32_t)lines.GetSize(), GetPrompt() == nullptr ? " " : ""); - } - - m_curr_line_idx = lines.GetSize(); - - bool interrupted = false; - if (GetLine(line, interrupted) && !interrupted) - { - lines.AppendString(line); - done = m_delegate.IOHandlerIsInputComplete(*this, lines); - } - else - { - done = true; - } - } - success = lines.GetSize() > 0; -#ifndef LLDB_DISABLE_LIBEDIT + bool done = false; + Error error; + + while (!done) { + // Show line numbers if we are asked to + std::string line; + if (m_base_line_number > 0 && GetIsInteractive()) { + FILE *out = GetOutputFILE(); + if (out) + ::fprintf(out, "%u%s", m_base_line_number + (uint32_t)lines.GetSize(), + GetPrompt() == nullptr ? " " : ""); + } + + m_curr_line_idx = lines.GetSize(); + + bool interrupted = false; + if (GetLine(line, interrupted) && !interrupted) { + lines.AppendString(line); + done = m_delegate.IOHandlerIsInputComplete(*this, lines); + } else { + done = true; + } } + success = lines.GetSize() > 0; +#ifndef LLDB_DISABLE_LIBEDIT + } #endif - return success; + return success; } // Each IOHandler gets to run until it is done. It should read data // from the "in" and place output into "out" and "err and return // when done. -void -IOHandlerEditline::Run () -{ - std::string line; - while (IsActive()) - { - bool interrupted = false; - if (m_multi_line) - { - StringList lines; - if (GetLines (lines, interrupted)) - { - if (interrupted) - { - m_done = m_interrupt_exits; - m_delegate.IOHandlerInputInterrupted (*this, line); - - } - else - { - line = lines.CopyList(); - m_delegate.IOHandlerInputComplete (*this, line); - } - } - else - { - m_done = true; - } - } +void IOHandlerEditline::Run() { + std::string line; + while (IsActive()) { + bool interrupted = false; + if (m_multi_line) { + StringList lines; + if (GetLines(lines, interrupted)) { + if (interrupted) { + m_done = m_interrupt_exits; + m_delegate.IOHandlerInputInterrupted(*this, line); + + } else { + line = lines.CopyList(); + m_delegate.IOHandlerInputComplete(*this, line); + } + } else { + m_done = true; + } + } else { + if (GetLine(line, interrupted)) { + if (interrupted) + m_delegate.IOHandlerInputInterrupted(*this, line); else - { - if (GetLine(line, interrupted)) - { - if (interrupted) - m_delegate.IOHandlerInputInterrupted (*this, line); - else - m_delegate.IOHandlerInputComplete (*this, line); - } - else - { - m_done = true; - } - } + m_delegate.IOHandlerInputComplete(*this, line); + } else { + m_done = true; + } } + } } -void -IOHandlerEditline::Cancel () -{ +void IOHandlerEditline::Cancel() { #ifndef LLDB_DISABLE_LIBEDIT - if (m_editline_ap) - m_editline_ap->Cancel (); + if (m_editline_ap) + m_editline_ap->Cancel(); #endif } -bool -IOHandlerEditline::Interrupt () -{ - // Let the delgate handle it first - if (m_delegate.IOHandlerInterrupt(*this)) - return true; +bool IOHandlerEditline::Interrupt() { + // Let the delgate handle it first + if (m_delegate.IOHandlerInterrupt(*this)) + return true; #ifndef LLDB_DISABLE_LIBEDIT - if (m_editline_ap) - return m_editline_ap->Interrupt(); + if (m_editline_ap) + return m_editline_ap->Interrupt(); #endif - return false; + return false; } -void -IOHandlerEditline::GotEOF() -{ +void IOHandlerEditline::GotEOF() { #ifndef LLDB_DISABLE_LIBEDIT - if (m_editline_ap) - m_editline_ap->Interrupt(); + if (m_editline_ap) + m_editline_ap->Interrupt(); #endif } -void -IOHandlerEditline::PrintAsync (Stream *stream, const char *s, size_t len) -{ +void IOHandlerEditline::PrintAsync(Stream *stream, const char *s, size_t len) { #ifndef LLDB_DISABLE_LIBEDIT - if (m_editline_ap) - m_editline_ap->PrintAsync(stream, s, len); - else + if (m_editline_ap) + m_editline_ap->PrintAsync(stream, s, len); + else #endif - { - const char *prompt = GetPrompt(); + { #ifdef _MSC_VER - if (prompt) - { - // Back up over previous prompt using Windows API - CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info; - HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE); - GetConsoleScreenBufferInfo(console_handle, &screen_buffer_info); - COORD coord = screen_buffer_info.dwCursorPosition; - coord.X -= strlen(prompt); - if (coord.X < 0) - coord.X = 0; - SetConsoleCursorPosition(console_handle, coord); - } -#endif - IOHandler::PrintAsync(stream, s, len); - if (prompt) - IOHandler::PrintAsync(GetOutputStreamFile().get(), prompt, strlen(prompt)); + const char *prompt = GetPrompt(); + if (prompt) { + // Back up over previous prompt using Windows API + CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info; + HANDLE console_handle = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(console_handle, &screen_buffer_info); + COORD coord = screen_buffer_info.dwCursorPosition; + coord.X -= strlen(prompt); + if (coord.X < 0) + coord.X = 0; + SetConsoleCursorPosition(console_handle, coord); } +#endif + IOHandler::PrintAsync(stream, s, len); +#ifdef _MSC_VER + if (prompt) + IOHandler::PrintAsync(GetOutputStreamFile().get(), prompt, + strlen(prompt)); +#endif + } } // we may want curses to be disabled for some builds // for instance, windows #ifndef LLDB_DISABLE_CURSES -#define KEY_RETURN 10 -#define KEY_ESCAPE 27 - -namespace curses -{ - class Menu; - class MenuDelegate; - class Window; - class WindowDelegate; - typedef std::shared_ptr<Menu> MenuSP; - typedef std::shared_ptr<MenuDelegate> MenuDelegateSP; - typedef std::shared_ptr<Window> WindowSP; - typedef std::shared_ptr<WindowDelegate> WindowDelegateSP; - typedef std::vector<MenuSP> Menus; - typedef std::vector<WindowSP> Windows; - typedef std::vector<WindowDelegateSP> WindowDelegates; +#define KEY_RETURN 10 +#define KEY_ESCAPE 27 + +namespace curses { +class Menu; +class MenuDelegate; +class Window; +class WindowDelegate; +typedef std::shared_ptr<Menu> MenuSP; +typedef std::shared_ptr<MenuDelegate> MenuDelegateSP; +typedef std::shared_ptr<Window> WindowSP; +typedef std::shared_ptr<WindowDelegate> WindowDelegateSP; +typedef std::vector<MenuSP> Menus; +typedef std::vector<WindowSP> Windows; +typedef std::vector<WindowDelegateSP> WindowDelegates; #if 0 type summary add -s "x=${var.x}, y=${var.y}" curses::Point @@ -826,4754 +639,4029 @@ type summary add -s "w=${var.width}, h=${var.height}" curses::Size type summary add -s "${var.origin%S} ${var.size%S}" curses::Rect #endif - struct Point - { - int x; - int y; - - Point (int _x = 0, int _y = 0) : - x(_x), - y(_y) - { - } +struct Point { + int x; + int y; - void - Clear () - { - x = 0; - y = 0; - } - - Point & - operator += (const Point &rhs) - { - x += rhs.x; - y += rhs.y; - return *this; - } - - void - Dump () - { - printf ("(x=%i, y=%i)\n", x, y); - } - }; - - bool operator == (const Point &lhs, const Point &rhs) - { - return lhs.x == rhs.x && lhs.y == rhs.y; - } + Point(int _x = 0, int _y = 0) : x(_x), y(_y) {} - bool operator != (const Point &lhs, const Point &rhs) - { - return lhs.x != rhs.x || lhs.y != rhs.y; - } + void Clear() { + x = 0; + y = 0; + } - struct Size - { - int width; - int height; - Size (int w = 0, int h = 0) : - width (w), - height (h) - { - } - - void - Clear () - { - width = 0; - height = 0; - } + Point &operator+=(const Point &rhs) { + x += rhs.x; + y += rhs.y; + return *this; + } - void - Dump () - { - printf ("(w=%i, h=%i)\n", width, height); - } - }; - - bool operator == (const Size &lhs, const Size &rhs) - { - return lhs.width == rhs.width && lhs.height == rhs.height; + void Dump() { printf("(x=%i, y=%i)\n", x, y); } +}; + +bool operator==(const Point &lhs, const Point &rhs) { + return lhs.x == rhs.x && lhs.y == rhs.y; +} + +bool operator!=(const Point &lhs, const Point &rhs) { + return lhs.x != rhs.x || lhs.y != rhs.y; +} + +struct Size { + int width; + int height; + Size(int w = 0, int h = 0) : width(w), height(h) {} + + void Clear() { + width = 0; + height = 0; + } + + void Dump() { printf("(w=%i, h=%i)\n", width, height); } +}; + +bool operator==(const Size &lhs, const Size &rhs) { + return lhs.width == rhs.width && lhs.height == rhs.height; +} + +bool operator!=(const Size &lhs, const Size &rhs) { + return lhs.width != rhs.width || lhs.height != rhs.height; +} + +struct Rect { + Point origin; + Size size; + + Rect() : origin(), size() {} + + Rect(const Point &p, const Size &s) : origin(p), size(s) {} + + void Clear() { + origin.Clear(); + size.Clear(); + } + + void Dump() { + printf("(x=%i, y=%i), w=%i, h=%i)\n", origin.x, origin.y, size.width, + size.height); + } + + void Inset(int w, int h) { + if (size.width > w * 2) + size.width -= w * 2; + origin.x += w; + + if (size.height > h * 2) + size.height -= h * 2; + origin.y += h; + } + + // Return a status bar rectangle which is the last line of + // this rectangle. This rectangle will be modified to not + // include the status bar area. + Rect MakeStatusBar() { + Rect status_bar; + if (size.height > 1) { + status_bar.origin.x = origin.x; + status_bar.origin.y = size.height; + status_bar.size.width = size.width; + status_bar.size.height = 1; + --size.height; + } + return status_bar; + } + + // Return a menubar rectangle which is the first line of + // this rectangle. This rectangle will be modified to not + // include the menubar area. + Rect MakeMenuBar() { + Rect menubar; + if (size.height > 1) { + menubar.origin.x = origin.x; + menubar.origin.y = origin.y; + menubar.size.width = size.width; + menubar.size.height = 1; + ++origin.y; + --size.height; } + return menubar; + } + + void HorizontalSplitPercentage(float top_percentage, Rect &top, + Rect &bottom) const { + float top_height = top_percentage * size.height; + HorizontalSplit(top_height, top, bottom); + } + + void HorizontalSplit(int top_height, Rect &top, Rect &bottom) const { + top = *this; + if (top_height < size.height) { + top.size.height = top_height; + bottom.origin.x = origin.x; + bottom.origin.y = origin.y + top.size.height; + bottom.size.width = size.width; + bottom.size.height = size.height - top.size.height; + } else { + bottom.Clear(); + } + } + + void VerticalSplitPercentage(float left_percentage, Rect &left, + Rect &right) const { + float left_width = left_percentage * size.width; + VerticalSplit(left_width, left, right); + } + + void VerticalSplit(int left_width, Rect &left, Rect &right) const { + left = *this; + if (left_width < size.width) { + left.size.width = left_width; + right.origin.x = origin.x + left.size.width; + right.origin.y = origin.y; + right.size.width = size.width - left.size.width; + right.size.height = size.height; + } else { + right.Clear(); + } + } +}; - bool operator != (const Size &lhs, const Size &rhs) - { - return lhs.width != rhs.width || lhs.height != rhs.height; +bool operator==(const Rect &lhs, const Rect &rhs) { + return lhs.origin == rhs.origin && lhs.size == rhs.size; +} + +bool operator!=(const Rect &lhs, const Rect &rhs) { + return lhs.origin != rhs.origin || lhs.size != rhs.size; +} + +enum HandleCharResult { + eKeyNotHandled = 0, + eKeyHandled = 1, + eQuitApplication = 2 +}; + +enum class MenuActionResult { + Handled, + NotHandled, + Quit // Exit all menus and quit +}; + +struct KeyHelp { + int ch; + const char *description; +}; + +class WindowDelegate { +public: + virtual ~WindowDelegate() = default; + + virtual bool WindowDelegateDraw(Window &window, bool force) { + return false; // Drawing not handled + } + + virtual HandleCharResult WindowDelegateHandleChar(Window &window, int key) { + return eKeyNotHandled; + } + + virtual const char *WindowDelegateGetHelpText() { return nullptr; } + + virtual KeyHelp *WindowDelegateGetKeyHelp() { return nullptr; } +}; + +class HelpDialogDelegate : public WindowDelegate { +public: + HelpDialogDelegate(const char *text, KeyHelp *key_help_array); + + ~HelpDialogDelegate() override; + + bool WindowDelegateDraw(Window &window, bool force) override; + + HandleCharResult WindowDelegateHandleChar(Window &window, int key) override; + + size_t GetNumLines() const { return m_text.GetSize(); } + + size_t GetMaxLineLength() const { return m_text.GetMaxStringLength(); } + +protected: + StringList m_text; + int m_first_visible_line; +}; + +class Window { +public: + Window(const char *name) + : m_name(name), m_window(nullptr), m_panel(nullptr), m_parent(nullptr), + m_subwindows(), m_delegate_sp(), m_curr_active_window_idx(UINT32_MAX), + m_prev_active_window_idx(UINT32_MAX), m_delete(false), + m_needs_update(true), m_can_activate(true), m_is_subwin(false) {} + + Window(const char *name, WINDOW *w, bool del = true) + : m_name(name), m_window(nullptr), m_panel(nullptr), m_parent(nullptr), + m_subwindows(), m_delegate_sp(), m_curr_active_window_idx(UINT32_MAX), + m_prev_active_window_idx(UINT32_MAX), m_delete(del), + m_needs_update(true), m_can_activate(true), m_is_subwin(false) { + if (w) + Reset(w); + } + + Window(const char *name, const Rect &bounds) + : m_name(name), m_window(nullptr), m_parent(nullptr), m_subwindows(), + m_delegate_sp(), m_curr_active_window_idx(UINT32_MAX), + m_prev_active_window_idx(UINT32_MAX), m_delete(true), + m_needs_update(true), m_can_activate(true), m_is_subwin(false) { + Reset(::newwin(bounds.size.height, bounds.size.width, bounds.origin.y, + bounds.origin.y)); + } + + virtual ~Window() { + RemoveSubWindows(); + Reset(); + } + + void Reset(WINDOW *w = nullptr, bool del = true) { + if (m_window == w) + return; + + if (m_panel) { + ::del_panel(m_panel); + m_panel = nullptr; + } + if (m_window && m_delete) { + ::delwin(m_window); + m_window = nullptr; + m_delete = false; } + if (w) { + m_window = w; + m_panel = ::new_panel(m_window); + m_delete = del; + } + } + + void AttributeOn(attr_t attr) { ::wattron(m_window, attr); } + void AttributeOff(attr_t attr) { ::wattroff(m_window, attr); } + void Box(chtype v_char = ACS_VLINE, chtype h_char = ACS_HLINE) { + ::box(m_window, v_char, h_char); + } + void Clear() { ::wclear(m_window); } + void Erase() { ::werase(m_window); } + Rect GetBounds() { + return Rect(GetParentOrigin(), GetSize()); + } // Get the rectangle in our parent window + int GetChar() { return ::wgetch(m_window); } + int GetCursorX() { return getcurx(m_window); } + int GetCursorY() { return getcury(m_window); } + Rect GetFrame() { + return Rect(Point(), GetSize()); + } // Get our rectangle in our own coordinate system + Point GetParentOrigin() { return Point(GetParentX(), GetParentY()); } + Size GetSize() { return Size(GetWidth(), GetHeight()); } + int GetParentX() { return getparx(m_window); } + int GetParentY() { return getpary(m_window); } + int GetMaxX() { return getmaxx(m_window); } + int GetMaxY() { return getmaxy(m_window); } + int GetWidth() { return GetMaxX(); } + int GetHeight() { return GetMaxY(); } + void MoveCursor(int x, int y) { ::wmove(m_window, y, x); } + void MoveWindow(int x, int y) { MoveWindow(Point(x, y)); } + void Resize(int w, int h) { ::wresize(m_window, h, w); } + void Resize(const Size &size) { + ::wresize(m_window, size.height, size.width); + } + void PutChar(int ch) { ::waddch(m_window, ch); } + void PutCString(const char *s, int len = -1) { ::waddnstr(m_window, s, len); } + void Refresh() { ::wrefresh(m_window); } + void DeferredRefresh() { + // We are using panels, so we don't need to call this... + //::wnoutrefresh(m_window); + } + void SetBackground(int color_pair_idx) { + ::wbkgd(m_window, COLOR_PAIR(color_pair_idx)); + } + void UnderlineOn() { AttributeOn(A_UNDERLINE); } + void UnderlineOff() { AttributeOff(A_UNDERLINE); } + + void PutCStringTruncated(const char *s, int right_pad) { + int bytes_left = GetWidth() - GetCursorX(); + if (bytes_left > right_pad) { + bytes_left -= right_pad; + ::waddnstr(m_window, s, bytes_left); + } + } + + void MoveWindow(const Point &origin) { + const bool moving_window = origin != GetParentOrigin(); + if (m_is_subwin && moving_window) { + // Can't move subwindows, must delete and re-create + Size size = GetSize(); + Reset(::subwin(m_parent->m_window, size.height, size.width, origin.y, + origin.x), + true); + } else { + ::mvwin(m_window, origin.y, origin.x); + } + } + + void SetBounds(const Rect &bounds) { + const bool moving_window = bounds.origin != GetParentOrigin(); + if (m_is_subwin && moving_window) { + // Can't move subwindows, must delete and re-create + Reset(::subwin(m_parent->m_window, bounds.size.height, bounds.size.width, + bounds.origin.y, bounds.origin.x), + true); + } else { + if (moving_window) + MoveWindow(bounds.origin); + Resize(bounds.size); + } + } + + void Printf(const char *format, ...) __attribute__((format(printf, 2, 3))) { + va_list args; + va_start(args, format); + vwprintw(m_window, format, args); + va_end(args); + } + + void Touch() { + ::touchwin(m_window); + if (m_parent) + m_parent->Touch(); + } + + WindowSP CreateSubWindow(const char *name, const Rect &bounds, + bool make_active) { + WindowSP subwindow_sp; + if (m_window) { + subwindow_sp.reset(new Window( + name, ::subwin(m_window, bounds.size.height, bounds.size.width, + bounds.origin.y, bounds.origin.x), + true)); + subwindow_sp->m_is_subwin = true; + } else { + subwindow_sp.reset( + new Window(name, ::newwin(bounds.size.height, bounds.size.width, + bounds.origin.y, bounds.origin.x), + true)); + subwindow_sp->m_is_subwin = false; + } + subwindow_sp->m_parent = this; + if (make_active) { + m_prev_active_window_idx = m_curr_active_window_idx; + m_curr_active_window_idx = m_subwindows.size(); + } + m_subwindows.push_back(subwindow_sp); + ::top_panel(subwindow_sp->m_panel); + m_needs_update = true; + return subwindow_sp; + } + + bool RemoveSubWindow(Window *window) { + Windows::iterator pos, end = m_subwindows.end(); + size_t i = 0; + for (pos = m_subwindows.begin(); pos != end; ++pos, ++i) { + if ((*pos).get() == window) { + if (m_prev_active_window_idx == i) + m_prev_active_window_idx = UINT32_MAX; + else if (m_prev_active_window_idx != UINT32_MAX && + m_prev_active_window_idx > i) + --m_prev_active_window_idx; + + if (m_curr_active_window_idx == i) + m_curr_active_window_idx = UINT32_MAX; + else if (m_curr_active_window_idx != UINT32_MAX && + m_curr_active_window_idx > i) + --m_curr_active_window_idx; + window->Erase(); + m_subwindows.erase(pos); + m_needs_update = true; + if (m_parent) + m_parent->Touch(); + else + ::touchwin(stdscr); + return true; + } + } + return false; + } + + WindowSP FindSubWindow(const char *name) { + Windows::iterator pos, end = m_subwindows.end(); + size_t i = 0; + for (pos = m_subwindows.begin(); pos != end; ++pos, ++i) { + if ((*pos)->m_name.compare(name) == 0) + return *pos; + } + return WindowSP(); + } + + void RemoveSubWindows() { + m_curr_active_window_idx = UINT32_MAX; + m_prev_active_window_idx = UINT32_MAX; + for (Windows::iterator pos = m_subwindows.begin(); + pos != m_subwindows.end(); pos = m_subwindows.erase(pos)) { + (*pos)->Erase(); + } + if (m_parent) + m_parent->Touch(); + else + ::touchwin(stdscr); + } - struct Rect - { - Point origin; - Size size; - - Rect () : - origin(), - size() - { - } - - Rect (const Point &p, const Size &s) : - origin (p), - size (s) - { - } - - void - Clear () - { - origin.Clear(); - size.Clear(); - } - - void - Dump () - { - printf ("(x=%i, y=%i), w=%i, h=%i)\n", origin.x, origin.y, size.width, size.height); - } - - void - Inset (int w, int h) - { - if (size.width > w*2) - size.width -= w*2; - origin.x += w; - - if (size.height > h*2) - size.height -= h*2; - origin.y += h; - } + WINDOW *get() { return m_window; } - // Return a status bar rectangle which is the last line of - // this rectangle. This rectangle will be modified to not - // include the status bar area. - Rect - MakeStatusBar () - { - Rect status_bar; - if (size.height > 1) - { - status_bar.origin.x = origin.x; - status_bar.origin.y = size.height; - status_bar.size.width = size.width; - status_bar.size.height = 1; - --size.height; - } - return status_bar; - } + operator WINDOW *() { return m_window; } - // Return a menubar rectangle which is the first line of - // this rectangle. This rectangle will be modified to not - // include the menubar area. - Rect - MakeMenuBar () - { - Rect menubar; - if (size.height > 1) - { - menubar.origin.x = origin.x; - menubar.origin.y = origin.y; - menubar.size.width = size.width; - menubar.size.height = 1; - ++origin.y; - --size.height; - } - return menubar; - } + //---------------------------------------------------------------------- + // Window drawing utilities + //---------------------------------------------------------------------- + void DrawTitleBox(const char *title, const char *bottom_message = nullptr) { + attr_t attr = 0; + if (IsActive()) + attr = A_BOLD | COLOR_PAIR(2); + else + attr = 0; + if (attr) + AttributeOn(attr); - void - HorizontalSplitPercentage (float top_percentage, Rect &top, Rect &bottom) const - { - float top_height = top_percentage * size.height; - HorizontalSplit (top_height, top, bottom); - } + Box(); + MoveCursor(3, 0); - void - HorizontalSplit (int top_height, Rect &top, Rect &bottom) const - { - top = *this; - if (top_height < size.height) - { - top.size.height = top_height; - bottom.origin.x = origin.x; - bottom.origin.y = origin.y + top.size.height; - bottom.size.width = size.width; - bottom.size.height = size.height - top.size.height; - } - else - { - bottom.Clear(); - } - } - - void - VerticalSplitPercentage (float left_percentage, Rect &left, Rect &right) const - { - float left_width = left_percentage * size.width; - VerticalSplit (left_width, left, right); - } + if (title && title[0]) { + PutChar('<'); + PutCString(title); + PutChar('>'); + } - void - VerticalSplit (int left_width, Rect &left, Rect &right) const - { - left = *this; - if (left_width < size.width) - { - left.size.width = left_width; - right.origin.x = origin.x + left.size.width; - right.origin.y = origin.y; - right.size.width = size.width - left.size.width; - right.size.height = size.height; - } - else - { - right.Clear(); + if (bottom_message && bottom_message[0]) { + int bottom_message_length = strlen(bottom_message); + int x = GetWidth() - 3 - (bottom_message_length + 2); + + if (x > 0) { + MoveCursor(x, GetHeight() - 1); + PutChar('['); + PutCString(bottom_message); + PutChar(']'); + } else { + MoveCursor(1, GetHeight() - 1); + PutChar('['); + PutCStringTruncated(bottom_message, 1); + } + } + if (attr) + AttributeOff(attr); + } + + virtual void Draw(bool force) { + if (m_delegate_sp && m_delegate_sp->WindowDelegateDraw(*this, force)) + return; + + for (auto &subwindow_sp : m_subwindows) + subwindow_sp->Draw(force); + } + + bool CreateHelpSubwindow() { + if (m_delegate_sp) { + const char *text = m_delegate_sp->WindowDelegateGetHelpText(); + KeyHelp *key_help = m_delegate_sp->WindowDelegateGetKeyHelp(); + if ((text && text[0]) || key_help) { + std::auto_ptr<HelpDialogDelegate> help_delegate_ap( + new HelpDialogDelegate(text, key_help)); + const size_t num_lines = help_delegate_ap->GetNumLines(); + const size_t max_length = help_delegate_ap->GetMaxLineLength(); + Rect bounds = GetBounds(); + bounds.Inset(1, 1); + if (max_length + 4 < static_cast<size_t>(bounds.size.width)) { + bounds.origin.x += (bounds.size.width - max_length + 4) / 2; + bounds.size.width = max_length + 4; + } else { + if (bounds.size.width > 100) { + const int inset_w = bounds.size.width / 4; + bounds.origin.x += inset_w; + bounds.size.width -= 2 * inset_w; + } + } + + if (num_lines + 2 < static_cast<size_t>(bounds.size.height)) { + bounds.origin.y += (bounds.size.height - num_lines + 2) / 2; + bounds.size.height = num_lines + 2; + } else { + if (bounds.size.height > 100) { + const int inset_h = bounds.size.height / 4; + bounds.origin.y += inset_h; + bounds.size.height -= 2 * inset_h; + } + } + WindowSP help_window_sp; + Window *parent_window = GetParent(); + if (parent_window) + help_window_sp = parent_window->CreateSubWindow("Help", bounds, true); + else + help_window_sp = CreateSubWindow("Help", bounds, true); + help_window_sp->SetDelegate( + WindowDelegateSP(help_delegate_ap.release())); + return true; + } + } + return false; + } + + virtual HandleCharResult HandleChar(int key) { + // Always check the active window first + HandleCharResult result = eKeyNotHandled; + WindowSP active_window_sp = GetActiveWindow(); + if (active_window_sp) { + result = active_window_sp->HandleChar(key); + if (result != eKeyNotHandled) + return result; + } + + if (m_delegate_sp) { + result = m_delegate_sp->WindowDelegateHandleChar(*this, key); + if (result != eKeyNotHandled) + return result; + } + + // Then check for any windows that want any keys + // that weren't handled. This is typically only + // for a menubar. + // Make a copy of the subwindows in case any HandleChar() + // functions muck with the subwindows. If we don't do this, + // we can crash when iterating over the subwindows. + Windows subwindows(m_subwindows); + for (auto subwindow_sp : subwindows) { + if (!subwindow_sp->m_can_activate) { + HandleCharResult result = subwindow_sp->HandleChar(key); + if (result != eKeyNotHandled) + return result; + } + } + + return eKeyNotHandled; + } + + bool SetActiveWindow(Window *window) { + const size_t num_subwindows = m_subwindows.size(); + for (size_t i = 0; i < num_subwindows; ++i) { + if (m_subwindows[i].get() == window) { + m_prev_active_window_idx = m_curr_active_window_idx; + ::top_panel(window->m_panel); + m_curr_active_window_idx = i; + return true; + } + } + return false; + } + + WindowSP GetActiveWindow() { + if (!m_subwindows.empty()) { + if (m_curr_active_window_idx >= m_subwindows.size()) { + if (m_prev_active_window_idx < m_subwindows.size()) { + m_curr_active_window_idx = m_prev_active_window_idx; + m_prev_active_window_idx = UINT32_MAX; + } else if (IsActive()) { + m_prev_active_window_idx = UINT32_MAX; + m_curr_active_window_idx = UINT32_MAX; + + // Find first window that wants to be active if this window is active + const size_t num_subwindows = m_subwindows.size(); + for (size_t i = 0; i < num_subwindows; ++i) { + if (m_subwindows[i]->GetCanBeActive()) { + m_curr_active_window_idx = i; + break; } + } } - }; + } - bool operator == (const Rect &lhs, const Rect &rhs) - { - return lhs.origin == rhs.origin && lhs.size == rhs.size; + if (m_curr_active_window_idx < m_subwindows.size()) + return m_subwindows[m_curr_active_window_idx]; } + return WindowSP(); + } - bool operator != (const Rect &lhs, const Rect &rhs) - { - return lhs.origin != rhs.origin || lhs.size != rhs.size; - } + bool GetCanBeActive() const { return m_can_activate; } - enum HandleCharResult - { - eKeyNotHandled = 0, - eKeyHandled = 1, - eQuitApplication = 2 - }; - - enum class MenuActionResult - { - Handled, - NotHandled, - Quit // Exit all menus and quit - }; + void SetCanBeActive(bool b) { m_can_activate = b; } - struct KeyHelp - { - int ch; - const char *description; - }; + const WindowDelegateSP &GetDelegate() const { return m_delegate_sp; } - class WindowDelegate - { - public: - virtual - ~WindowDelegate() = default; - - virtual bool - WindowDelegateDraw (Window &window, bool force) - { - return false; // Drawing not handled - } - - virtual HandleCharResult - WindowDelegateHandleChar (Window &window, int key) - { - return eKeyNotHandled; - } - - virtual const char * - WindowDelegateGetHelpText () - { - return nullptr; - } + void SetDelegate(const WindowDelegateSP &delegate_sp) { + m_delegate_sp = delegate_sp; + } + + Window *GetParent() const { return m_parent; } - virtual KeyHelp * - WindowDelegateGetKeyHelp () - { - return nullptr; + bool IsActive() const { + if (m_parent) + return m_parent->GetActiveWindow().get() == this; + else + return true; // Top level window is always active + } + + void SelectNextWindowAsActive() { + // Move active focus to next window + const size_t num_subwindows = m_subwindows.size(); + if (m_curr_active_window_idx == UINT32_MAX) { + uint32_t idx = 0; + for (auto subwindow_sp : m_subwindows) { + if (subwindow_sp->GetCanBeActive()) { + m_curr_active_window_idx = idx; + break; + } + ++idx; + } + } else if (m_curr_active_window_idx + 1 < num_subwindows) { + bool handled = false; + m_prev_active_window_idx = m_curr_active_window_idx; + for (size_t idx = m_curr_active_window_idx + 1; idx < num_subwindows; + ++idx) { + if (m_subwindows[idx]->GetCanBeActive()) { + m_curr_active_window_idx = idx; + handled = true; + break; + } + } + if (!handled) { + for (size_t idx = 0; idx <= m_prev_active_window_idx; ++idx) { + if (m_subwindows[idx]->GetCanBeActive()) { + m_curr_active_window_idx = idx; + break; + } } - }; - - class HelpDialogDelegate : - public WindowDelegate - { - public: - HelpDialogDelegate (const char *text, KeyHelp *key_help_array); - - ~HelpDialogDelegate() override; - - bool - WindowDelegateDraw (Window &window, bool force) override; - - HandleCharResult - WindowDelegateHandleChar (Window &window, int key) override; - - size_t - GetNumLines() const - { - return m_text.GetSize(); + } + } else { + m_prev_active_window_idx = m_curr_active_window_idx; + for (size_t idx = 0; idx < num_subwindows; ++idx) { + if (m_subwindows[idx]->GetCanBeActive()) { + m_curr_active_window_idx = idx; + break; } + } + } + } - size_t - GetMaxLineLength () const - { - return m_text.GetMaxStringLength(); - } + const char *GetName() const { return m_name.c_str(); } - protected: - StringList m_text; - int m_first_visible_line; - }; +protected: + std::string m_name; + WINDOW *m_window; + PANEL *m_panel; + Window *m_parent; + Windows m_subwindows; + WindowDelegateSP m_delegate_sp; + uint32_t m_curr_active_window_idx; + uint32_t m_prev_active_window_idx; + bool m_delete; + bool m_needs_update; + bool m_can_activate; + bool m_is_subwin; + +private: + DISALLOW_COPY_AND_ASSIGN(Window); +}; - class Window - { - public: - Window (const char *name) : - m_name (name), - m_window(nullptr), - m_panel(nullptr), - m_parent(nullptr), - m_subwindows (), - m_delegate_sp (), - m_curr_active_window_idx (UINT32_MAX), - m_prev_active_window_idx (UINT32_MAX), - m_delete (false), - m_needs_update (true), - m_can_activate (true), - m_is_subwin (false) - { - } - - Window (const char *name, WINDOW *w, bool del = true) : - m_name (name), - m_window(nullptr), - m_panel(nullptr), - m_parent(nullptr), - m_subwindows (), - m_delegate_sp (), - m_curr_active_window_idx (UINT32_MAX), - m_prev_active_window_idx (UINT32_MAX), - m_delete (del), - m_needs_update (true), - m_can_activate (true), - m_is_subwin (false) - { - if (w) - Reset(w); - } - - Window (const char *name, const Rect &bounds) : - m_name (name), - m_window(nullptr), - m_parent(nullptr), - m_subwindows (), - m_delegate_sp (), - m_curr_active_window_idx (UINT32_MAX), - m_prev_active_window_idx (UINT32_MAX), - m_delete (true), - m_needs_update (true), - m_can_activate (true), - m_is_subwin (false) - { - Reset (::newwin (bounds.size.height, bounds.size.width, bounds.origin.y, bounds.origin.y)); - } - - virtual - ~Window () - { - RemoveSubWindows (); - Reset (); - } - - void - Reset(WINDOW *w = nullptr, bool del = true) - { - if (m_window == w) - return; - - if (m_panel) - { - ::del_panel (m_panel); - m_panel = nullptr; - } - if (m_window && m_delete) - { - ::delwin (m_window); - m_window = nullptr; - m_delete = false; - } - if (w) - { - m_window = w; - m_panel = ::new_panel (m_window); - m_delete = del; - } - } - - void AttributeOn (attr_t attr) { ::wattron (m_window, attr); } - void AttributeOff (attr_t attr) { ::wattroff (m_window, attr); } - void Box (chtype v_char = ACS_VLINE, chtype h_char = ACS_HLINE) { ::box(m_window, v_char, h_char); } - void Clear () { ::wclear (m_window); } - void Erase () { ::werase (m_window); } - Rect GetBounds () { return Rect (GetParentOrigin(), GetSize()); } // Get the rectangle in our parent window - int GetChar () { return ::wgetch (m_window); } - int GetCursorX () { return getcurx (m_window); } - int GetCursorY () { return getcury (m_window); } - Rect GetFrame () { return Rect (Point(), GetSize()); } // Get our rectangle in our own coordinate system - Point GetParentOrigin() { return Point (GetParentX(), GetParentY()); } - Size GetSize() { return Size (GetWidth(), GetHeight()); } - int GetParentX () { return getparx (m_window); } - int GetParentY () { return getpary (m_window); } - int GetMaxX() { return getmaxx (m_window); } - int GetMaxY() { return getmaxy (m_window); } - int GetWidth() { return GetMaxX(); } - int GetHeight() { return GetMaxY(); } - void MoveCursor (int x, int y) { ::wmove (m_window, y, x); } - void MoveWindow (int x, int y) { MoveWindow(Point(x,y)); } - void Resize (int w, int h) { ::wresize(m_window, h, w); } - void Resize (const Size &size) { ::wresize(m_window, size.height, size.width); } - void PutChar (int ch) { ::waddch (m_window, ch); } - void PutCString (const char *s, int len = -1) { ::waddnstr (m_window, s, len); } - void Refresh () { ::wrefresh (m_window); } - void DeferredRefresh () - { - // We are using panels, so we don't need to call this... - //::wnoutrefresh(m_window); - } - void SetBackground (int color_pair_idx) { ::wbkgd (m_window,COLOR_PAIR(color_pair_idx)); } - void UnderlineOn () { AttributeOn(A_UNDERLINE); } - void UnderlineOff () { AttributeOff(A_UNDERLINE); } - - void PutCStringTruncated (const char *s, int right_pad) - { - int bytes_left = GetWidth() - GetCursorX(); - if (bytes_left > right_pad) - { - bytes_left -= right_pad; - ::waddnstr (m_window, s, bytes_left); - } - } +class MenuDelegate { +public: + virtual ~MenuDelegate() = default; - void - MoveWindow (const Point &origin) - { - const bool moving_window = origin != GetParentOrigin(); - if (m_is_subwin && moving_window) - { - // Can't move subwindows, must delete and re-create - Size size = GetSize(); - Reset (::subwin (m_parent->m_window, - size.height, - size.width, - origin.y, - origin.x), true); - } - else - { - ::mvwin (m_window, origin.y, origin.x); - } - } + virtual MenuActionResult MenuDelegateAction(Menu &menu) = 0; +}; - void - SetBounds (const Rect &bounds) - { - const bool moving_window = bounds.origin != GetParentOrigin(); - if (m_is_subwin && moving_window) - { - // Can't move subwindows, must delete and re-create - Reset (::subwin (m_parent->m_window, - bounds.size.height, - bounds.size.width, - bounds.origin.y, - bounds.origin.x), true); - } - else - { - if (moving_window) - MoveWindow(bounds.origin); - Resize (bounds.size); - } - } +class Menu : public WindowDelegate { +public: + enum class Type { Invalid, Bar, Item, Separator }; - void - Printf (const char *format, ...) __attribute__ ((format (printf, 2, 3))) - { - va_list args; - va_start (args, format); - vwprintw(m_window, format, args); - va_end (args); - } + // Menubar or separator constructor + Menu(Type type); - void - Touch () - { - ::touchwin (m_window); - if (m_parent) - m_parent->Touch(); - } + // Menuitem constructor + Menu(const char *name, const char *key_name, int key_value, + uint64_t identifier); - WindowSP - CreateSubWindow (const char *name, const Rect &bounds, bool make_active) - { - WindowSP subwindow_sp; - if (m_window) - { - subwindow_sp.reset(new Window(name, ::subwin (m_window, - bounds.size.height, - bounds.size.width, - bounds.origin.y, - bounds.origin.x), true)); - subwindow_sp->m_is_subwin = true; - } - else - { - subwindow_sp.reset(new Window(name, ::newwin (bounds.size.height, - bounds.size.width, - bounds.origin.y, - bounds.origin.x), true)); - subwindow_sp->m_is_subwin = false; - } - subwindow_sp->m_parent = this; - if (make_active) - { - m_prev_active_window_idx = m_curr_active_window_idx; - m_curr_active_window_idx = m_subwindows.size(); - } - m_subwindows.push_back(subwindow_sp); - ::top_panel (subwindow_sp->m_panel); - m_needs_update = true; - return subwindow_sp; - } - - bool - RemoveSubWindow (Window *window) - { - Windows::iterator pos, end = m_subwindows.end(); - size_t i = 0; - for (pos = m_subwindows.begin(); pos != end; ++pos, ++i) - { - if ((*pos).get() == window) - { - if (m_prev_active_window_idx == i) - m_prev_active_window_idx = UINT32_MAX; - else if (m_prev_active_window_idx != UINT32_MAX && m_prev_active_window_idx > i) - --m_prev_active_window_idx; - - if (m_curr_active_window_idx == i) - m_curr_active_window_idx = UINT32_MAX; - else if (m_curr_active_window_idx != UINT32_MAX && m_curr_active_window_idx > i) - --m_curr_active_window_idx; - window->Erase(); - m_subwindows.erase(pos); - m_needs_update = true; - if (m_parent) - m_parent->Touch(); - else - ::touchwin (stdscr); - return true; - } - } - return false; - } - - WindowSP - FindSubWindow (const char *name) - { - Windows::iterator pos, end = m_subwindows.end(); - size_t i = 0; - for (pos = m_subwindows.begin(); pos != end; ++pos, ++i) - { - if ((*pos)->m_name.compare(name) == 0) - return *pos; - } - return WindowSP(); - } - - void - RemoveSubWindows () - { - m_curr_active_window_idx = UINT32_MAX; - m_prev_active_window_idx = UINT32_MAX; - for (Windows::iterator pos = m_subwindows.begin(); - pos != m_subwindows.end(); - pos = m_subwindows.erase(pos)) - { - (*pos)->Erase(); - } - if (m_parent) - m_parent->Touch(); - else - ::touchwin (stdscr); - } + ~Menu() override = default; - WINDOW * - get() - { - return m_window; - } + const MenuDelegateSP &GetDelegate() const { return m_delegate_sp; } - operator WINDOW *() - { - return m_window; - } - - //---------------------------------------------------------------------- - // Window drawing utilities - //---------------------------------------------------------------------- - void - DrawTitleBox(const char *title, const char *bottom_message = nullptr) - { - attr_t attr = 0; - if (IsActive()) - attr = A_BOLD | COLOR_PAIR(2); - else - attr = 0; - if (attr) - AttributeOn(attr); - - Box(); - MoveCursor(3, 0); - - if (title && title[0]) - { - PutChar ('<'); - PutCString (title); - PutChar ('>'); - } - - if (bottom_message && bottom_message[0]) - { - int bottom_message_length = strlen(bottom_message); - int x = GetWidth() - 3 - (bottom_message_length + 2); - - if (x > 0) - { - MoveCursor (x, GetHeight() - 1); - PutChar ('['); - PutCString(bottom_message); - PutChar (']'); - } - else - { - MoveCursor (1, GetHeight() - 1); - PutChar ('['); - PutCStringTruncated (bottom_message, 1); - } - } - if (attr) - AttributeOff(attr); - } + void SetDelegate(const MenuDelegateSP &delegate_sp) { + m_delegate_sp = delegate_sp; + } - virtual void - Draw (bool force) - { - if (m_delegate_sp && m_delegate_sp->WindowDelegateDraw (*this, force)) - return; + void RecalculateNameLengths(); - for (auto &subwindow_sp : m_subwindows) - subwindow_sp->Draw(force); - } + void AddSubmenu(const MenuSP &menu_sp); - bool - CreateHelpSubwindow () - { - if (m_delegate_sp) - { - const char *text = m_delegate_sp->WindowDelegateGetHelpText (); - KeyHelp *key_help = m_delegate_sp->WindowDelegateGetKeyHelp (); - if ((text && text[0]) || key_help) - { - std::auto_ptr<HelpDialogDelegate> help_delegate_ap(new HelpDialogDelegate(text, key_help)); - const size_t num_lines = help_delegate_ap->GetNumLines(); - const size_t max_length = help_delegate_ap->GetMaxLineLength(); - Rect bounds = GetBounds(); - bounds.Inset(1, 1); - if (max_length + 4 < static_cast<size_t>(bounds.size.width)) - { - bounds.origin.x += (bounds.size.width - max_length + 4)/2; - bounds.size.width = max_length + 4; - } - else - { - if (bounds.size.width > 100) - { - const int inset_w = bounds.size.width / 4; - bounds.origin.x += inset_w; - bounds.size.width -= 2*inset_w; - } - } - - if (num_lines + 2 < static_cast<size_t>(bounds.size.height)) - { - bounds.origin.y += (bounds.size.height - num_lines + 2)/2; - bounds.size.height = num_lines + 2; - } - else - { - if (bounds.size.height > 100) - { - const int inset_h = bounds.size.height / 4; - bounds.origin.y += inset_h; - bounds.size.height -= 2*inset_h; - } - } - WindowSP help_window_sp; - Window *parent_window = GetParent(); - if (parent_window) - help_window_sp = parent_window->CreateSubWindow("Help", bounds, true); - else - help_window_sp = CreateSubWindow("Help", bounds, true); - help_window_sp->SetDelegate(WindowDelegateSP(help_delegate_ap.release())); - return true; - } - } - return false; - } + int DrawAndRunMenu(Window &window); - virtual HandleCharResult - HandleChar (int key) - { - // Always check the active window first - HandleCharResult result = eKeyNotHandled; - WindowSP active_window_sp = GetActiveWindow (); - if (active_window_sp) - { - result = active_window_sp->HandleChar (key); - if (result != eKeyNotHandled) - return result; - } - - if (m_delegate_sp) - { - result = m_delegate_sp->WindowDelegateHandleChar (*this, key); - if (result != eKeyNotHandled) - return result; - } + void DrawMenuTitle(Window &window, bool highlight); - // Then check for any windows that want any keys - // that weren't handled. This is typically only - // for a menubar. - // Make a copy of the subwindows in case any HandleChar() - // functions muck with the subwindows. If we don't do this, - // we can crash when iterating over the subwindows. - Windows subwindows (m_subwindows); - for (auto subwindow_sp : subwindows) - { - if (!subwindow_sp->m_can_activate) - { - HandleCharResult result = subwindow_sp->HandleChar(key); - if (result != eKeyNotHandled) - return result; - } - } + bool WindowDelegateDraw(Window &window, bool force) override; - return eKeyNotHandled; - } + HandleCharResult WindowDelegateHandleChar(Window &window, int key) override; - bool - SetActiveWindow (Window *window) - { - const size_t num_subwindows = m_subwindows.size(); - for (size_t i = 0; i < num_subwindows; ++i) - { - if (m_subwindows[i].get() == window) - { - m_prev_active_window_idx = m_curr_active_window_idx; - ::top_panel (window->m_panel); - m_curr_active_window_idx = i; - return true; - } - } - return false; - } + MenuActionResult ActionPrivate(Menu &menu) { + MenuActionResult result = MenuActionResult::NotHandled; + if (m_delegate_sp) { + result = m_delegate_sp->MenuDelegateAction(menu); + if (result != MenuActionResult::NotHandled) + return result; + } else if (m_parent) { + result = m_parent->ActionPrivate(menu); + if (result != MenuActionResult::NotHandled) + return result; + } + return m_canned_result; + } - WindowSP - GetActiveWindow () - { - if (!m_subwindows.empty()) - { - if (m_curr_active_window_idx >= m_subwindows.size()) - { - if (m_prev_active_window_idx < m_subwindows.size()) - { - m_curr_active_window_idx = m_prev_active_window_idx; - m_prev_active_window_idx = UINT32_MAX; - } - else if (IsActive()) - { - m_prev_active_window_idx = UINT32_MAX; - m_curr_active_window_idx = UINT32_MAX; - - // Find first window that wants to be active if this window is active - const size_t num_subwindows = m_subwindows.size(); - for (size_t i = 0; i < num_subwindows; ++i) - { - if (m_subwindows[i]->GetCanBeActive()) - { - m_curr_active_window_idx = i; - break; - } - } - } - } - - if (m_curr_active_window_idx < m_subwindows.size()) - return m_subwindows[m_curr_active_window_idx]; - } - return WindowSP(); - } - - bool - GetCanBeActive () const - { - return m_can_activate; - } + MenuActionResult Action() { + // Call the recursive action so it can try to handle it + // with the menu delegate, and if not, try our parent menu + return ActionPrivate(*this); + } - void - SetCanBeActive (bool b) - { - m_can_activate = b; - } - - const WindowDelegateSP & - GetDelegate () const - { - return m_delegate_sp; - } + void SetCannedResult(MenuActionResult result) { m_canned_result = result; } - void - SetDelegate (const WindowDelegateSP &delegate_sp) - { - m_delegate_sp = delegate_sp; - } - - Window * - GetParent () const - { - return m_parent; - } - - bool - IsActive () const - { - if (m_parent) - return m_parent->GetActiveWindow().get() == this; - else - return true; // Top level window is always active - } - - void - SelectNextWindowAsActive () - { - // Move active focus to next window - const size_t num_subwindows = m_subwindows.size(); - if (m_curr_active_window_idx == UINT32_MAX) - { - uint32_t idx = 0; - for (auto subwindow_sp : m_subwindows) - { - if (subwindow_sp->GetCanBeActive()) - { - m_curr_active_window_idx = idx; - break; - } - ++idx; - } - } - else if (m_curr_active_window_idx + 1 < num_subwindows) - { - bool handled = false; - m_prev_active_window_idx = m_curr_active_window_idx; - for (size_t idx=m_curr_active_window_idx + 1; idx<num_subwindows; ++idx) - { - if (m_subwindows[idx]->GetCanBeActive()) - { - m_curr_active_window_idx = idx; - handled = true; - break; - } - } - if (!handled) - { - for (size_t idx=0; idx<=m_prev_active_window_idx; ++idx) - { - if (m_subwindows[idx]->GetCanBeActive()) - { - m_curr_active_window_idx = idx; - break; - } - } - } - } - else - { - m_prev_active_window_idx = m_curr_active_window_idx; - for (size_t idx=0; idx<num_subwindows; ++idx) - { - if (m_subwindows[idx]->GetCanBeActive()) - { - m_curr_active_window_idx = idx; - break; - } - } - } - } + Menus &GetSubmenus() { return m_submenus; } - const char * - GetName () const - { - return m_name.c_str(); - } + const Menus &GetSubmenus() const { return m_submenus; } - protected: - std::string m_name; - WINDOW *m_window; - PANEL *m_panel; - Window *m_parent; - Windows m_subwindows; - WindowDelegateSP m_delegate_sp; - uint32_t m_curr_active_window_idx; - uint32_t m_prev_active_window_idx; - bool m_delete; - bool m_needs_update; - bool m_can_activate; - bool m_is_subwin; - - private: - DISALLOW_COPY_AND_ASSIGN(Window); - }; - - class MenuDelegate - { - public: - virtual ~MenuDelegate() = default; + int GetSelectedSubmenuIndex() const { return m_selected; } - virtual MenuActionResult - MenuDelegateAction (Menu &menu) = 0; - }; + void SetSelectedSubmenuIndex(int idx) { m_selected = idx; } - class Menu : public WindowDelegate - { - public: - enum class Type - { - Invalid, - Bar, - Item, - Separator - }; - - // Menubar or separator constructor - Menu (Type type); - - // Menuitem constructor - Menu (const char *name, - const char *key_name, - int key_value, - uint64_t identifier); - - ~Menu() override = default; - - const MenuDelegateSP & - GetDelegate () const - { - return m_delegate_sp; - } - - void - SetDelegate (const MenuDelegateSP &delegate_sp) - { - m_delegate_sp = delegate_sp; - } - - void - RecalculateNameLengths(); - - void - AddSubmenu (const MenuSP &menu_sp); - - int - DrawAndRunMenu (Window &window); - - void - DrawMenuTitle (Window &window, bool highlight); - - bool - WindowDelegateDraw (Window &window, bool force) override; - - HandleCharResult - WindowDelegateHandleChar (Window &window, int key) override; - - MenuActionResult - ActionPrivate (Menu &menu) - { - MenuActionResult result = MenuActionResult::NotHandled; - if (m_delegate_sp) - { - result = m_delegate_sp->MenuDelegateAction (menu); - if (result != MenuActionResult::NotHandled) - return result; - } - else if (m_parent) - { - result = m_parent->ActionPrivate(menu); - if (result != MenuActionResult::NotHandled) - return result; - } - return m_canned_result; - } + Type GetType() const { return m_type; } - MenuActionResult - Action () - { - // Call the recursive action so it can try to handle it - // with the menu delegate, and if not, try our parent menu - return ActionPrivate (*this); - } - - void - SetCannedResult (MenuActionResult result) - { - m_canned_result = result; - } + int GetStartingColumn() const { return m_start_col; } - Menus & - GetSubmenus() - { - return m_submenus; - } + void SetStartingColumn(int col) { m_start_col = col; } - const Menus & - GetSubmenus() const - { - return m_submenus; - } + int GetKeyValue() const { return m_key_value; } - int - GetSelectedSubmenuIndex () const - { - return m_selected; - } - - void - SetSelectedSubmenuIndex (int idx) - { - m_selected = idx; - } + void SetKeyValue(int key_value) { m_key_value = key_value; } - Type - GetType () const - { - return m_type; - } - - int - GetStartingColumn() const - { - return m_start_col; - } + std::string &GetName() { return m_name; } - void - SetStartingColumn(int col) - { - m_start_col = col; - } + std::string &GetKeyName() { return m_key_name; } - int - GetKeyValue() const - { - return m_key_value; - } - - void - SetKeyValue(int key_value) - { - m_key_value = key_value; - } + int GetDrawWidth() const { + return m_max_submenu_name_length + m_max_submenu_key_name_length + 8; + } - std::string & - GetName() - { - return m_name; - } + uint64_t GetIdentifier() const { return m_identifier; } - std::string & - GetKeyName() - { - return m_key_name; - } + void SetIdentifier(uint64_t identifier) { m_identifier = identifier; } - int - GetDrawWidth () const - { - return m_max_submenu_name_length + m_max_submenu_key_name_length + 8; - } +protected: + std::string m_name; + std::string m_key_name; + uint64_t m_identifier; + Type m_type; + int m_key_value; + int m_start_col; + int m_max_submenu_name_length; + int m_max_submenu_key_name_length; + int m_selected; + Menu *m_parent; + Menus m_submenus; + WindowSP m_menu_window_sp; + MenuActionResult m_canned_result; + MenuDelegateSP m_delegate_sp; +}; - uint64_t - GetIdentifier() const - { - return m_identifier; - } +// Menubar or separator constructor +Menu::Menu(Type type) + : m_name(), m_key_name(), m_identifier(0), m_type(type), m_key_value(0), + m_start_col(0), m_max_submenu_name_length(0), + m_max_submenu_key_name_length(0), m_selected(0), m_parent(nullptr), + m_submenus(), m_canned_result(MenuActionResult::NotHandled), + m_delegate_sp() {} + +// Menuitem constructor +Menu::Menu(const char *name, const char *key_name, int key_value, + uint64_t identifier) + : m_name(), m_key_name(), m_identifier(identifier), m_type(Type::Invalid), + m_key_value(key_value), m_start_col(0), m_max_submenu_name_length(0), + m_max_submenu_key_name_length(0), m_selected(0), m_parent(nullptr), + m_submenus(), m_canned_result(MenuActionResult::NotHandled), + m_delegate_sp() { + if (name && name[0]) { + m_name = name; + m_type = Type::Item; + if (key_name && key_name[0]) + m_key_name = key_name; + } else { + m_type = Type::Separator; + } +} - void - SetIdentifier (uint64_t identifier) - { - m_identifier = identifier; - } +void Menu::RecalculateNameLengths() { + m_max_submenu_name_length = 0; + m_max_submenu_key_name_length = 0; + Menus &submenus = GetSubmenus(); + const size_t num_submenus = submenus.size(); + for (size_t i = 0; i < num_submenus; ++i) { + Menu *submenu = submenus[i].get(); + if (static_cast<size_t>(m_max_submenu_name_length) < submenu->m_name.size()) + m_max_submenu_name_length = submenu->m_name.size(); + if (static_cast<size_t>(m_max_submenu_key_name_length) < + submenu->m_key_name.size()) + m_max_submenu_key_name_length = submenu->m_key_name.size(); + } +} - protected: - std::string m_name; - std::string m_key_name; - uint64_t m_identifier; - Type m_type; - int m_key_value; - int m_start_col; - int m_max_submenu_name_length; - int m_max_submenu_key_name_length; - int m_selected; - Menu *m_parent; - Menus m_submenus; - WindowSP m_menu_window_sp; - MenuActionResult m_canned_result; - MenuDelegateSP m_delegate_sp; - }; - - // Menubar or separator constructor - Menu::Menu (Type type) : - m_name (), - m_key_name (), - m_identifier (0), - m_type (type), - m_key_value (0), - m_start_col (0), - m_max_submenu_name_length (0), - m_max_submenu_key_name_length (0), - m_selected (0), - m_parent(nullptr), - m_submenus (), - m_canned_result (MenuActionResult::NotHandled), - m_delegate_sp() - { +void Menu::AddSubmenu(const MenuSP &menu_sp) { + menu_sp->m_parent = this; + if (static_cast<size_t>(m_max_submenu_name_length) < menu_sp->m_name.size()) + m_max_submenu_name_length = menu_sp->m_name.size(); + if (static_cast<size_t>(m_max_submenu_key_name_length) < + menu_sp->m_key_name.size()) + m_max_submenu_key_name_length = menu_sp->m_key_name.size(); + m_submenus.push_back(menu_sp); +} + +void Menu::DrawMenuTitle(Window &window, bool highlight) { + if (m_type == Type::Separator) { + window.MoveCursor(0, window.GetCursorY()); + window.PutChar(ACS_LTEE); + int width = window.GetWidth(); + if (width > 2) { + width -= 2; + for (int i = 0; i < width; ++i) + window.PutChar(ACS_HLINE); + } + window.PutChar(ACS_RTEE); + } else { + const int shortcut_key = m_key_value; + bool underlined_shortcut = false; + const attr_t hilgight_attr = A_REVERSE; + if (highlight) + window.AttributeOn(hilgight_attr); + if (isprint(shortcut_key)) { + size_t lower_pos = m_name.find(tolower(shortcut_key)); + size_t upper_pos = m_name.find(toupper(shortcut_key)); + const char *name = m_name.c_str(); + size_t pos = std::min<size_t>(lower_pos, upper_pos); + if (pos != std::string::npos) { + underlined_shortcut = true; + if (pos > 0) { + window.PutCString(name, pos); + name += pos; + } + const attr_t shortcut_attr = A_UNDERLINE | A_BOLD; + window.AttributeOn(shortcut_attr); + window.PutChar(name[0]); + window.AttributeOff(shortcut_attr); + name++; + if (name[0]) + window.PutCString(name); + } } - // Menuitem constructor - Menu::Menu (const char *name, - const char *key_name, - int key_value, - uint64_t identifier) : - m_name (), - m_key_name (), - m_identifier (identifier), - m_type (Type::Invalid), - m_key_value (key_value), - m_start_col (0), - m_max_submenu_name_length (0), - m_max_submenu_key_name_length (0), - m_selected (0), - m_parent(nullptr), - m_submenus (), - m_canned_result (MenuActionResult::NotHandled), - m_delegate_sp() - { - if (name && name[0]) - { - m_name = name; - m_type = Type::Item; - if (key_name && key_name[0]) - m_key_name = key_name; - } - else - { - m_type = Type::Separator; - } + if (!underlined_shortcut) { + window.PutCString(m_name.c_str()); } - void - Menu::RecalculateNameLengths() - { - m_max_submenu_name_length = 0; - m_max_submenu_key_name_length = 0; - Menus &submenus = GetSubmenus(); - const size_t num_submenus = submenus.size(); - for (size_t i = 0; i < num_submenus; ++i) - { - Menu *submenu = submenus[i].get(); - if (static_cast<size_t>(m_max_submenu_name_length) < submenu->m_name.size()) - m_max_submenu_name_length = submenu->m_name.size(); - if (static_cast<size_t>(m_max_submenu_key_name_length) < submenu->m_key_name.size()) - m_max_submenu_key_name_length = submenu->m_key_name.size(); - } + if (highlight) + window.AttributeOff(hilgight_attr); + + if (m_key_name.empty()) { + if (!underlined_shortcut && isprint(m_key_value)) { + window.AttributeOn(COLOR_PAIR(3)); + window.Printf(" (%c)", m_key_value); + window.AttributeOff(COLOR_PAIR(3)); + } + } else { + window.AttributeOn(COLOR_PAIR(3)); + window.Printf(" (%s)", m_key_name.c_str()); + window.AttributeOff(COLOR_PAIR(3)); } + } +} - void - Menu::AddSubmenu (const MenuSP &menu_sp) - { - menu_sp->m_parent = this; - if (static_cast<size_t>(m_max_submenu_name_length) < menu_sp->m_name.size()) - m_max_submenu_name_length = menu_sp->m_name.size(); - if (static_cast<size_t>(m_max_submenu_key_name_length) < menu_sp->m_key_name.size()) - m_max_submenu_key_name_length = menu_sp->m_key_name.size(); - m_submenus.push_back(menu_sp); +bool Menu::WindowDelegateDraw(Window &window, bool force) { + Menus &submenus = GetSubmenus(); + const size_t num_submenus = submenus.size(); + const int selected_idx = GetSelectedSubmenuIndex(); + Menu::Type menu_type = GetType(); + switch (menu_type) { + case Menu::Type::Bar: { + window.SetBackground(2); + window.MoveCursor(0, 0); + for (size_t i = 0; i < num_submenus; ++i) { + Menu *menu = submenus[i].get(); + if (i > 0) + window.PutChar(' '); + menu->SetStartingColumn(window.GetCursorX()); + window.PutCString("| "); + menu->DrawMenuTitle(window, false); } + window.PutCString(" |"); + window.DeferredRefresh(); + } break; - void - Menu::DrawMenuTitle (Window &window, bool highlight) - { - if (m_type == Type::Separator) - { - window.MoveCursor(0, window.GetCursorY()); - window.PutChar(ACS_LTEE); - int width = window.GetWidth(); - if (width > 2) - { - width -= 2; - for (int i = 0; i < width; ++i) - window.PutChar(ACS_HLINE); - } - window.PutChar(ACS_RTEE); - } - else - { - const int shortcut_key = m_key_value; - bool underlined_shortcut = false; - const attr_t hilgight_attr = A_REVERSE; - if (highlight) - window.AttributeOn(hilgight_attr); - if (isprint(shortcut_key)) - { - size_t lower_pos = m_name.find(tolower(shortcut_key)); - size_t upper_pos = m_name.find(toupper(shortcut_key)); - const char *name = m_name.c_str(); - size_t pos = std::min<size_t>(lower_pos, upper_pos); - if (pos != std::string::npos) - { - underlined_shortcut = true; - if (pos > 0) - { - window.PutCString(name, pos); - name += pos; - } - const attr_t shortcut_attr = A_UNDERLINE|A_BOLD; - window.AttributeOn (shortcut_attr); - window.PutChar(name[0]); - window.AttributeOff(shortcut_attr); - name++; - if (name[0]) - window.PutCString(name); - } - } - - if (!underlined_shortcut) - { - window.PutCString(m_name.c_str()); - } + case Menu::Type::Item: { + int y = 1; + int x = 3; + // Draw the menu + int cursor_x = 0; + int cursor_y = 0; + window.Erase(); + window.SetBackground(2); + window.Box(); + for (size_t i = 0; i < num_submenus; ++i) { + const bool is_selected = (i == static_cast<size_t>(selected_idx)); + window.MoveCursor(x, y + i); + if (is_selected) { + // Remember where we want the cursor to be + cursor_x = x - 1; + cursor_y = y + i; + } + submenus[i]->DrawMenuTitle(window, is_selected); + } + window.MoveCursor(cursor_x, cursor_y); + window.DeferredRefresh(); + } break; + + default: + case Menu::Type::Separator: + break; + } + return true; // Drawing handled... +} - if (highlight) - window.AttributeOff(hilgight_attr); +HandleCharResult Menu::WindowDelegateHandleChar(Window &window, int key) { + HandleCharResult result = eKeyNotHandled; + + Menus &submenus = GetSubmenus(); + const size_t num_submenus = submenus.size(); + const int selected_idx = GetSelectedSubmenuIndex(); + Menu::Type menu_type = GetType(); + if (menu_type == Menu::Type::Bar) { + MenuSP run_menu_sp; + switch (key) { + case KEY_DOWN: + case KEY_UP: + // Show last menu or first menu + if (selected_idx < static_cast<int>(num_submenus)) + run_menu_sp = submenus[selected_idx]; + else if (!submenus.empty()) + run_menu_sp = submenus.front(); + result = eKeyHandled; + break; + + case KEY_RIGHT: + ++m_selected; + if (m_selected >= static_cast<int>(num_submenus)) + m_selected = 0; + if (m_selected < static_cast<int>(num_submenus)) + run_menu_sp = submenus[m_selected]; + else if (!submenus.empty()) + run_menu_sp = submenus.front(); + result = eKeyHandled; + break; + + case KEY_LEFT: + --m_selected; + if (m_selected < 0) + m_selected = num_submenus - 1; + if (m_selected < static_cast<int>(num_submenus)) + run_menu_sp = submenus[m_selected]; + else if (!submenus.empty()) + run_menu_sp = submenus.front(); + result = eKeyHandled; + break; + + default: + for (size_t i = 0; i < num_submenus; ++i) { + if (submenus[i]->GetKeyValue() == key) { + SetSelectedSubmenuIndex(i); + run_menu_sp = submenus[i]; + result = eKeyHandled; + break; + } + } + break; + } - if (m_key_name.empty()) - { - if (!underlined_shortcut && isprint(m_key_value)) - { - window.AttributeOn (COLOR_PAIR(3)); - window.Printf (" (%c)", m_key_value); - window.AttributeOff (COLOR_PAIR(3)); - } - } - else - { - window.AttributeOn (COLOR_PAIR(3)); - window.Printf (" (%s)", m_key_name.c_str()); - window.AttributeOff (COLOR_PAIR(3)); - } - } + if (run_menu_sp) { + // Run the action on this menu in case we need to populate the + // menu with dynamic content and also in case check marks, and + // any other menu decorations need to be calculated + if (run_menu_sp->Action() == MenuActionResult::Quit) + return eQuitApplication; + + Rect menu_bounds; + menu_bounds.origin.x = run_menu_sp->GetStartingColumn(); + menu_bounds.origin.y = 1; + menu_bounds.size.width = run_menu_sp->GetDrawWidth(); + menu_bounds.size.height = run_menu_sp->GetSubmenus().size() + 2; + if (m_menu_window_sp) + window.GetParent()->RemoveSubWindow(m_menu_window_sp.get()); + + m_menu_window_sp = window.GetParent()->CreateSubWindow( + run_menu_sp->GetName().c_str(), menu_bounds, true); + m_menu_window_sp->SetDelegate(run_menu_sp); } - - bool - Menu::WindowDelegateDraw (Window &window, bool force) - { - Menus &submenus = GetSubmenus(); - const size_t num_submenus = submenus.size(); - const int selected_idx = GetSelectedSubmenuIndex(); - Menu::Type menu_type = GetType (); - switch (menu_type) - { - case Menu::Type::Bar: - { - window.SetBackground(2); - window.MoveCursor(0, 0); - for (size_t i = 0; i < num_submenus; ++i) - { - Menu *menu = submenus[i].get(); - if (i > 0) - window.PutChar(' '); - menu->SetStartingColumn (window.GetCursorX()); - window.PutCString("| "); - menu->DrawMenuTitle (window, false); - } - window.PutCString(" |"); - window.DeferredRefresh(); - } + } else if (menu_type == Menu::Type::Item) { + switch (key) { + case KEY_DOWN: + if (m_submenus.size() > 1) { + const int start_select = m_selected; + while (++m_selected != start_select) { + if (static_cast<size_t>(m_selected) >= num_submenus) + m_selected = 0; + if (m_submenus[m_selected]->GetType() == Type::Separator) + continue; + else break; - - case Menu::Type::Item: - { - int y = 1; - int x = 3; - // Draw the menu - int cursor_x = 0; - int cursor_y = 0; - window.Erase(); - window.SetBackground(2); - window.Box(); - for (size_t i = 0; i < num_submenus; ++i) - { - const bool is_selected = - (i == static_cast<size_t>(selected_idx)); - window.MoveCursor(x, y + i); - if (is_selected) - { - // Remember where we want the cursor to be - cursor_x = x-1; - cursor_y = y+i; - } - submenus[i]->DrawMenuTitle (window, is_selected); - } - window.MoveCursor(cursor_x, cursor_y); - window.DeferredRefresh(); - } - break; - - default: - case Menu::Type::Separator: + } + return eKeyHandled; + } + break; + + case KEY_UP: + if (m_submenus.size() > 1) { + const int start_select = m_selected; + while (--m_selected != start_select) { + if (m_selected < static_cast<int>(0)) + m_selected = num_submenus - 1; + if (m_submenus[m_selected]->GetType() == Type::Separator) + continue; + else break; } - return true; // Drawing handled... + return eKeyHandled; + } + break; + + case KEY_RETURN: + if (static_cast<size_t>(selected_idx) < num_submenus) { + if (submenus[selected_idx]->Action() == MenuActionResult::Quit) + return eQuitApplication; + window.GetParent()->RemoveSubWindow(&window); + return eKeyHandled; + } + break; + + case KEY_ESCAPE: // Beware: pressing escape key has 1 to 2 second delay in + // case other chars are entered for escaped sequences + window.GetParent()->RemoveSubWindow(&window); + return eKeyHandled; + + default: + for (size_t i = 0; i < num_submenus; ++i) { + Menu *menu = submenus[i].get(); + if (menu->GetKeyValue() == key) { + SetSelectedSubmenuIndex(i); + window.GetParent()->RemoveSubWindow(&window); + if (menu->Action() == MenuActionResult::Quit) + return eQuitApplication; + return eKeyHandled; + } + } + break; } - - HandleCharResult - Menu::WindowDelegateHandleChar (Window &window, int key) - { - HandleCharResult result = eKeyNotHandled; - - Menus &submenus = GetSubmenus(); - const size_t num_submenus = submenus.size(); - const int selected_idx = GetSelectedSubmenuIndex(); - Menu::Type menu_type = GetType (); - if (menu_type == Menu::Type::Bar) - { - MenuSP run_menu_sp; - switch (key) - { - case KEY_DOWN: - case KEY_UP: - // Show last menu or first menu - if (selected_idx < static_cast<int>(num_submenus)) - run_menu_sp = submenus[selected_idx]; - else if (!submenus.empty()) - run_menu_sp = submenus.front(); - result = eKeyHandled; - break; - - case KEY_RIGHT: - ++m_selected; - if (m_selected >= static_cast<int>(num_submenus)) - m_selected = 0; - if (m_selected < static_cast<int>(num_submenus)) - run_menu_sp = submenus[m_selected]; - else if (!submenus.empty()) - run_menu_sp = submenus.front(); - result = eKeyHandled; - break; - - case KEY_LEFT: - --m_selected; - if (m_selected < 0) - m_selected = num_submenus - 1; - if (m_selected < static_cast<int>(num_submenus)) - run_menu_sp = submenus[m_selected]; - else if (!submenus.empty()) - run_menu_sp = submenus.front(); - result = eKeyHandled; - break; - - default: - for (size_t i = 0; i < num_submenus; ++i) - { - if (submenus[i]->GetKeyValue() == key) - { - SetSelectedSubmenuIndex(i); - run_menu_sp = submenus[i]; - result = eKeyHandled; - break; - } - } - break; - } - - if (run_menu_sp) - { - // Run the action on this menu in case we need to populate the - // menu with dynamic content and also in case check marks, and - // any other menu decorations need to be calculated - if (run_menu_sp->Action() == MenuActionResult::Quit) - return eQuitApplication; - - Rect menu_bounds; - menu_bounds.origin.x = run_menu_sp->GetStartingColumn(); - menu_bounds.origin.y = 1; - menu_bounds.size.width = run_menu_sp->GetDrawWidth(); - menu_bounds.size.height = run_menu_sp->GetSubmenus().size() + 2; - if (m_menu_window_sp) - window.GetParent()->RemoveSubWindow(m_menu_window_sp.get()); - - m_menu_window_sp = window.GetParent()->CreateSubWindow (run_menu_sp->GetName().c_str(), - menu_bounds, - true); - m_menu_window_sp->SetDelegate (run_menu_sp); - } - } - else if (menu_type == Menu::Type::Item) - { - switch (key) - { - case KEY_DOWN: - if (m_submenus.size() > 1) - { - const int start_select = m_selected; - while (++m_selected != start_select) - { - if (static_cast<size_t>(m_selected) >= num_submenus) - m_selected = 0; - if (m_submenus[m_selected]->GetType() == Type::Separator) - continue; - else - break; - } - return eKeyHandled; - } - break; - - case KEY_UP: - if (m_submenus.size() > 1) - { - const int start_select = m_selected; - while (--m_selected != start_select) - { - if (m_selected < static_cast<int>(0)) - m_selected = num_submenus - 1; - if (m_submenus[m_selected]->GetType() == Type::Separator) - continue; - else - break; - } - return eKeyHandled; - } - break; - - case KEY_RETURN: - if (static_cast<size_t>(selected_idx) < num_submenus) - { - if (submenus[selected_idx]->Action() == MenuActionResult::Quit) - return eQuitApplication; - window.GetParent()->RemoveSubWindow(&window); - return eKeyHandled; - } - break; - - case KEY_ESCAPE: // Beware: pressing escape key has 1 to 2 second delay in case other chars are entered for escaped sequences - window.GetParent()->RemoveSubWindow(&window); - return eKeyHandled; - - default: - for (size_t i = 0; i < num_submenus; ++i) - { - Menu *menu = submenus[i].get(); - if (menu->GetKeyValue() == key) - { - SetSelectedSubmenuIndex(i); - window.GetParent()->RemoveSubWindow(&window); - if (menu->Action() == MenuActionResult::Quit) - return eQuitApplication; - return eKeyHandled; - } - } - break; - } - } - else if (menu_type == Menu::Type::Separator) - { - } - return result; + } else if (menu_type == Menu::Type::Separator) { + } + return result; +} + +class Application { +public: + Application(FILE *in, FILE *out) + : m_window_sp(), m_screen(nullptr), m_in(in), m_out(out) {} + + ~Application() { + m_window_delegates.clear(); + m_window_sp.reset(); + if (m_screen) { + ::delscreen(m_screen); + m_screen = nullptr; } + } - class Application - { - public: - Application (FILE *in, FILE *out) : - m_window_sp(), - m_screen(nullptr), - m_in (in), - m_out (out) - { - } - - ~Application () - { - m_window_delegates.clear(); - m_window_sp.reset(); - if (m_screen) - { - ::delscreen(m_screen); - m_screen = nullptr; - } - } - - void - Initialize () - { - ::setlocale(LC_ALL, ""); - ::setlocale(LC_CTYPE, ""); + void Initialize() { + ::setlocale(LC_ALL, ""); + ::setlocale(LC_CTYPE, ""); #if 0 ::initscr(); #else - m_screen = ::newterm(nullptr, m_out, m_in); + m_screen = ::newterm(nullptr, m_out, m_in); #endif - ::start_color(); - ::curs_set(0); - ::noecho(); - ::keypad(stdscr,TRUE); - } - - void - Terminate () - { - ::endwin(); - } - - void - Run (Debugger &debugger) - { - bool done = false; - int delay_in_tenths_of_a_second = 1; - - // Alas the threading model in curses is a bit lame so we need to - // resort to polling every 0.5 seconds. We could poll for stdin - // ourselves and then pass the keys down but then we need to - // translate all of the escape sequences ourselves. So we resort to - // polling for input because we need to receive async process events - // while in this loop. - - halfdelay(delay_in_tenths_of_a_second); // Poll using some number of tenths of seconds seconds when calling Window::GetChar() - - ListenerSP listener_sp (Listener::MakeListener("lldb.IOHandler.curses.Application")); - ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass()); - ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass()); - ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass()); - debugger.EnableForwardEvents (listener_sp); - - bool update = true; + ::start_color(); + ::curs_set(0); + ::noecho(); + ::keypad(stdscr, TRUE); + } + + void Terminate() { ::endwin(); } + + void Run(Debugger &debugger) { + bool done = false; + int delay_in_tenths_of_a_second = 1; + + // Alas the threading model in curses is a bit lame so we need to + // resort to polling every 0.5 seconds. We could poll for stdin + // ourselves and then pass the keys down but then we need to + // translate all of the escape sequences ourselves. So we resort to + // polling for input because we need to receive async process events + // while in this loop. + + halfdelay(delay_in_tenths_of_a_second); // Poll using some number of tenths + // of seconds seconds when calling + // Window::GetChar() + + ListenerSP listener_sp( + Listener::MakeListener("lldb.IOHandler.curses.Application")); + ConstString broadcaster_class_target(Target::GetStaticBroadcasterClass()); + ConstString broadcaster_class_process(Process::GetStaticBroadcasterClass()); + ConstString broadcaster_class_thread(Thread::GetStaticBroadcasterClass()); + debugger.EnableForwardEvents(listener_sp); + + bool update = true; #if defined(__APPLE__) - std::deque<int> escape_chars; + std::deque<int> escape_chars; #endif - - while (!done) - { - if (update) - { - m_window_sp->Draw(false); - // All windows should be calling Window::DeferredRefresh() instead - // of Window::Refresh() so we can do a single update and avoid - // any screen blinking - update_panels(); - - // Cursor hiding isn't working on MacOSX, so hide it in the top left corner - m_window_sp->MoveCursor(0, 0); - - doupdate(); - update = false; - } - + + while (!done) { + if (update) { + m_window_sp->Draw(false); + // All windows should be calling Window::DeferredRefresh() instead + // of Window::Refresh() so we can do a single update and avoid + // any screen blinking + update_panels(); + + // Cursor hiding isn't working on MacOSX, so hide it in the top left + // corner + m_window_sp->MoveCursor(0, 0); + + doupdate(); + update = false; + } + #if defined(__APPLE__) - // Terminal.app doesn't map its function keys correctly, F1-F4 default to: - // \033OP, \033OQ, \033OR, \033OS, so lets take care of this here if possible - int ch; - if (escape_chars.empty()) - ch = m_window_sp->GetChar(); - else - { - ch = escape_chars.front(); - escape_chars.pop_front(); - } - if (ch == KEY_ESCAPE) - { - int ch2 = m_window_sp->GetChar(); - if (ch2 == 'O') - { - int ch3 = m_window_sp->GetChar(); - switch (ch3) - { - case 'P': ch = KEY_F(1); break; - case 'Q': ch = KEY_F(2); break; - case 'R': ch = KEY_F(3); break; - case 'S': ch = KEY_F(4); break; - default: - escape_chars.push_back(ch2); - if (ch3 != -1) - escape_chars.push_back(ch3); - break; - } - } - else if (ch2 != -1) - escape_chars.push_back(ch2); - } + // Terminal.app doesn't map its function keys correctly, F1-F4 default to: + // \033OP, \033OQ, \033OR, \033OS, so lets take care of this here if + // possible + int ch; + if (escape_chars.empty()) + ch = m_window_sp->GetChar(); + else { + ch = escape_chars.front(); + escape_chars.pop_front(); + } + if (ch == KEY_ESCAPE) { + int ch2 = m_window_sp->GetChar(); + if (ch2 == 'O') { + int ch3 = m_window_sp->GetChar(); + switch (ch3) { + case 'P': + ch = KEY_F(1); + break; + case 'Q': + ch = KEY_F(2); + break; + case 'R': + ch = KEY_F(3); + break; + case 'S': + ch = KEY_F(4); + break; + default: + escape_chars.push_back(ch2); + if (ch3 != -1) + escape_chars.push_back(ch3); + break; + } + } else if (ch2 != -1) + escape_chars.push_back(ch2); + } #else - int ch = m_window_sp->GetChar(); + int ch = m_window_sp->GetChar(); #endif - if (ch == -1) - { - if (feof(m_in) || ferror(m_in)) - { - done = true; - } - else - { - // Just a timeout from using halfdelay(), check for events - EventSP event_sp; - while (listener_sp->PeekAtNextEvent()) - { - listener_sp->GetNextEvent(event_sp); - - if (event_sp) - { - Broadcaster *broadcaster = event_sp->GetBroadcaster(); - if (broadcaster) - { - //uint32_t event_type = event_sp->GetType(); - ConstString broadcaster_class (broadcaster->GetBroadcasterClass()); - if (broadcaster_class == broadcaster_class_process) - { - debugger.GetCommandInterpreter().UpdateExecutionContext(nullptr); - update = true; - continue; // Don't get any key, just update our view - } - } - } - } - } - } - else - { - HandleCharResult key_result = m_window_sp->HandleChar(ch); - switch (key_result) - { - case eKeyHandled: - debugger.GetCommandInterpreter().UpdateExecutionContext(nullptr); - update = true; - break; - case eKeyNotHandled: - break; - case eQuitApplication: - done = true; - break; - } + if (ch == -1) { + if (feof(m_in) || ferror(m_in)) { + done = true; + } else { + // Just a timeout from using halfdelay(), check for events + EventSP event_sp; + while (listener_sp->PeekAtNextEvent()) { + listener_sp->GetEvent(event_sp, std::chrono::seconds(0)); + + if (event_sp) { + Broadcaster *broadcaster = event_sp->GetBroadcaster(); + if (broadcaster) { + // uint32_t event_type = event_sp->GetType(); + ConstString broadcaster_class( + broadcaster->GetBroadcasterClass()); + if (broadcaster_class == broadcaster_class_process) { + debugger.GetCommandInterpreter().UpdateExecutionContext( + nullptr); + update = true; + continue; // Don't get any key, just update our view } + } } - - debugger.CancelForwardEvents (listener_sp); - } - - WindowSP & - GetMainWindow () - { - if (!m_window_sp) - m_window_sp.reset (new Window ("main", stdscr, false)); - return m_window_sp; - } - - WindowDelegates & - GetWindowDelegates () - { - return m_window_delegates; - } + } + } + } else { + HandleCharResult key_result = m_window_sp->HandleChar(ch); + switch (key_result) { + case eKeyHandled: + debugger.GetCommandInterpreter().UpdateExecutionContext(nullptr); + update = true; + break; + case eKeyNotHandled: + break; + case eQuitApplication: + done = true; + break; + } + } + } + + debugger.CancelForwardEvents(listener_sp); + } + + WindowSP &GetMainWindow() { + if (!m_window_sp) + m_window_sp.reset(new Window("main", stdscr, false)); + return m_window_sp; + } - protected: - WindowSP m_window_sp; - WindowDelegates m_window_delegates; - SCREEN *m_screen; - FILE *m_in; - FILE *m_out; - }; + WindowDelegates &GetWindowDelegates() { return m_window_delegates; } + +protected: + WindowSP m_window_sp; + WindowDelegates m_window_delegates; + SCREEN *m_screen; + FILE *m_in; + FILE *m_out; +}; } // namespace curses using namespace curses; -struct Row -{ - ValueObjectSP valobj; - Row *parent; - int row_idx; - int x; - int y; - bool might_have_children; - bool expanded; - bool calculated_children; - std::vector<Row> children; - - Row (const ValueObjectSP &v, Row *p) : - valobj (v), - parent (p), - row_idx(0), - x(1), - y(1), - might_have_children (v ? v->MightHaveChildren() : false), - expanded (false), - calculated_children (false), - children() - { - } - - size_t - GetDepth () const - { - if (parent) - return 1 + parent->GetDepth(); - return 0; - } - - void - Expand() - { - expanded = true; - if (!calculated_children) - { - calculated_children = true; - if (valobj) - { - const size_t num_children = valobj->GetNumChildren(); - for (size_t i = 0; i < num_children; ++i) - { - children.push_back(Row (valobj->GetChildAtIndex(i, true), this)); - } - } - } +struct Row { + ValueObjectManager value; + Row *parent; + // The process stop ID when the children were calculated. + uint32_t children_stop_id; + int row_idx; + int x; + int y; + bool might_have_children; + bool expanded; + bool calculated_children; + std::vector<Row> children; + + Row(const ValueObjectSP &v, Row *p) + : value(v, lldb::eDynamicDontRunTarget, true), parent(p), row_idx(0), + x(1), y(1), might_have_children(v ? v->MightHaveChildren() : false), + expanded(false), calculated_children(false), children() {} + + size_t GetDepth() const { + if (parent) + return 1 + parent->GetDepth(); + return 0; + } + + void Expand() { + expanded = true; + } + + std::vector<Row> &GetChildren() { + ProcessSP process_sp = value.GetProcessSP(); + auto stop_id = process_sp->GetStopID(); + if (process_sp && stop_id != children_stop_id) { + children_stop_id = stop_id; + calculated_children = false; } - - void - Unexpand () - { - expanded = false; + if (!calculated_children) { + children.clear(); + calculated_children = true; + ValueObjectSP valobj = value.GetSP(); + if (valobj) { + const size_t num_children = valobj->GetNumChildren(); + for (size_t i = 0; i < num_children; ++i) { + children.push_back(Row(valobj->GetChildAtIndex(i, true), this)); + } + } } - - void - DrawTree (Window &window) - { - if (parent) - parent->DrawTreeForChild (window, this, 0); - - if (might_have_children) - { - // It we can get UTF8 characters to work we should try to use the "symbol" - // UTF8 string below -// const char *symbol = ""; -// if (row.expanded) -// symbol = "\xe2\x96\xbd "; -// else -// symbol = "\xe2\x96\xb7 "; -// window.PutCString (symbol); - - // The ACS_DARROW and ACS_RARROW don't look very nice they are just a - // 'v' or '>' character... -// if (expanded) -// window.PutChar (ACS_DARROW); -// else -// window.PutChar (ACS_RARROW); - // Since we can't find any good looking right arrow/down arrow - // symbols, just use a diamond... - window.PutChar (ACS_DIAMOND); - window.PutChar (ACS_HLINE); - } + return children; + } + + void Unexpand() { + expanded = false; + calculated_children = false; + children.clear(); + } + + void DrawTree(Window &window) { + if (parent) + parent->DrawTreeForChild(window, this, 0); + + if (might_have_children) { + // It we can get UTF8 characters to work we should try to use the "symbol" + // UTF8 string below + // const char *symbol = ""; + // if (row.expanded) + // symbol = "\xe2\x96\xbd "; + // else + // symbol = "\xe2\x96\xb7 "; + // window.PutCString (symbol); + + // The ACS_DARROW and ACS_RARROW don't look very nice they are just a + // 'v' or '>' character... + // if (expanded) + // window.PutChar (ACS_DARROW); + // else + // window.PutChar (ACS_RARROW); + // Since we can't find any good looking right arrow/down arrow + // symbols, just use a diamond... + window.PutChar(ACS_DIAMOND); + window.PutChar(ACS_HLINE); } - - void - DrawTreeForChild (Window &window, Row *child, uint32_t reverse_depth) - { - if (parent) - parent->DrawTreeForChild (window, this, reverse_depth + 1); - - if (&children.back() == child) - { - // Last child - if (reverse_depth == 0) - { - window.PutChar (ACS_LLCORNER); - window.PutChar (ACS_HLINE); - } - else - { - window.PutChar (' '); - window.PutChar (' '); - } - } - else - { - if (reverse_depth == 0) - { - window.PutChar (ACS_LTEE); - window.PutChar (ACS_HLINE); - } - else - { - window.PutChar (ACS_VLINE); - window.PutChar (' '); - } - } + } + + void DrawTreeForChild(Window &window, Row *child, uint32_t reverse_depth) { + if (parent) + parent->DrawTreeForChild(window, this, reverse_depth + 1); + + if (&GetChildren().back() == child) { + // Last child + if (reverse_depth == 0) { + window.PutChar(ACS_LLCORNER); + window.PutChar(ACS_HLINE); + } else { + window.PutChar(' '); + window.PutChar(' '); + } + } else { + if (reverse_depth == 0) { + window.PutChar(ACS_LTEE); + window.PutChar(ACS_HLINE); + } else { + window.PutChar(ACS_VLINE); + window.PutChar(' '); + } } + } }; -struct DisplayOptions -{ - bool show_types; +struct DisplayOptions { + bool show_types; }; class TreeItem; -class TreeDelegate -{ +class TreeDelegate { public: - TreeDelegate() = default; - virtual ~TreeDelegate() = default; + TreeDelegate() = default; + virtual ~TreeDelegate() = default; - virtual void TreeDelegateDrawTreeItem (TreeItem &item, Window &window) = 0; - virtual void TreeDelegateGenerateChildren (TreeItem &item) = 0; - virtual bool TreeDelegateItemSelected (TreeItem &item) = 0; // Return true if we need to update views + virtual void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) = 0; + virtual void TreeDelegateGenerateChildren(TreeItem &item) = 0; + virtual bool TreeDelegateItemSelected( + TreeItem &item) = 0; // Return true if we need to update views }; typedef std::shared_ptr<TreeDelegate> TreeDelegateSP; -class TreeItem -{ +class TreeItem { public: - TreeItem (TreeItem *parent, TreeDelegate &delegate, bool might_have_children) : - m_parent (parent), - m_delegate (delegate), - m_user_data(nullptr), - m_identifier (0), - m_row_idx (-1), - m_children (), - m_might_have_children (might_have_children), - m_is_expanded (false) - { + TreeItem(TreeItem *parent, TreeDelegate &delegate, bool might_have_children) + : m_parent(parent), m_delegate(delegate), m_user_data(nullptr), + m_identifier(0), m_row_idx(-1), m_children(), + m_might_have_children(might_have_children), m_is_expanded(false) {} + + TreeItem &operator=(const TreeItem &rhs) { + if (this != &rhs) { + m_parent = rhs.m_parent; + m_delegate = rhs.m_delegate; + m_user_data = rhs.m_user_data; + m_identifier = rhs.m_identifier; + m_row_idx = rhs.m_row_idx; + m_children = rhs.m_children; + m_might_have_children = rhs.m_might_have_children; + m_is_expanded = rhs.m_is_expanded; } + return *this; + } - TreeItem & - operator=(const TreeItem &rhs) - { - if (this != &rhs) - { - m_parent = rhs.m_parent; - m_delegate = rhs.m_delegate; - m_user_data = rhs.m_user_data; - m_identifier = rhs.m_identifier; - m_row_idx = rhs.m_row_idx; - m_children = rhs.m_children; - m_might_have_children = rhs.m_might_have_children; - m_is_expanded = rhs.m_is_expanded; - } - return *this; - } - - size_t - GetDepth () const - { - if (m_parent) - return 1 + m_parent->GetDepth(); - return 0; - } - - int - GetRowIndex () const - { - return m_row_idx; - } - - void - ClearChildren () - { - m_children.clear(); - } - - void - Resize (size_t n, const TreeItem &t) - { - m_children.resize(n, t); - } - - TreeItem & - operator [](size_t i) - { - return m_children[i]; - } + size_t GetDepth() const { + if (m_parent) + return 1 + m_parent->GetDepth(); + return 0; + } - void - SetRowIndex (int row_idx) - { - m_row_idx = row_idx; - } + int GetRowIndex() const { return m_row_idx; } - size_t - GetNumChildren () - { - m_delegate.TreeDelegateGenerateChildren (*this); - return m_children.size(); - } + void ClearChildren() { m_children.clear(); } - void - ItemWasSelected () - { - m_delegate.TreeDelegateItemSelected(*this); - } + void Resize(size_t n, const TreeItem &t) { m_children.resize(n, t); } - void - CalculateRowIndexes (int &row_idx) - { - SetRowIndex(row_idx); - ++row_idx; - - const bool expanded = IsExpanded(); - - // The root item must calculate its children, - // or we must calculate the number of children - // if the item is expanded - if (m_parent == nullptr || expanded) - GetNumChildren(); - - for (auto &item : m_children) - { - if (expanded) - item.CalculateRowIndexes(row_idx); - else - item.SetRowIndex(-1); - } - } + TreeItem &operator[](size_t i) { return m_children[i]; } - TreeItem * - GetParent () - { - return m_parent; - } + void SetRowIndex(int row_idx) { m_row_idx = row_idx; } - bool - IsExpanded () const - { - return m_is_expanded; - } + size_t GetNumChildren() { + m_delegate.TreeDelegateGenerateChildren(*this); + return m_children.size(); + } - void - Expand() - { - m_is_expanded = true; - } - - void - Unexpand () - { - m_is_expanded = false; - } - - bool - Draw (Window &window, - const int first_visible_row, - const uint32_t selected_row_idx, - int &row_idx, - int &num_rows_left) - { - if (num_rows_left <= 0) - return false; - - if (m_row_idx >= first_visible_row) - { - window.MoveCursor(2, row_idx + 1); - - if (m_parent) - m_parent->DrawTreeForChild (window, this, 0); - - if (m_might_have_children) - { - // It we can get UTF8 characters to work we should try to use the "symbol" - // UTF8 string below - // const char *symbol = ""; - // if (row.expanded) - // symbol = "\xe2\x96\xbd "; - // else - // symbol = "\xe2\x96\xb7 "; - // window.PutCString (symbol); - - // The ACS_DARROW and ACS_RARROW don't look very nice they are just a - // 'v' or '>' character... - // if (expanded) - // window.PutChar (ACS_DARROW); - // else - // window.PutChar (ACS_RARROW); - // Since we can't find any good looking right arrow/down arrow - // symbols, just use a diamond... - window.PutChar (ACS_DIAMOND); - window.PutChar (ACS_HLINE); - } - bool highlight = - (selected_row_idx == static_cast<size_t>(m_row_idx)) && window.IsActive(); + void ItemWasSelected() { m_delegate.TreeDelegateItemSelected(*this); } - if (highlight) - window.AttributeOn(A_REVERSE); + void CalculateRowIndexes(int &row_idx) { + SetRowIndex(row_idx); + ++row_idx; - m_delegate.TreeDelegateDrawTreeItem(*this, window); + const bool expanded = IsExpanded(); - if (highlight) - window.AttributeOff(A_REVERSE); - ++row_idx; - --num_rows_left; - } + // The root item must calculate its children, + // or we must calculate the number of children + // if the item is expanded + if (m_parent == nullptr || expanded) + GetNumChildren(); - if (num_rows_left <= 0) - return false; // We are done drawing... - - if (IsExpanded()) - { - for (auto &item : m_children) - { - // If we displayed all the rows and item.Draw() returns - // false we are done drawing and can exit this for loop - if (!item.Draw(window, first_visible_row, selected_row_idx, row_idx, num_rows_left)) - break; - } - } - return num_rows_left >= 0; // Return true if not done drawing yet + for (auto &item : m_children) { + if (expanded) + item.CalculateRowIndexes(row_idx); + else + item.SetRowIndex(-1); } - - void - DrawTreeForChild (Window &window, TreeItem *child, uint32_t reverse_depth) - { - if (m_parent) - m_parent->DrawTreeForChild (window, this, reverse_depth + 1); - - if (&m_children.back() == child) - { - // Last child - if (reverse_depth == 0) - { - window.PutChar (ACS_LLCORNER); - window.PutChar (ACS_HLINE); - } - else - { - window.PutChar (' '); - window.PutChar (' '); - } - } - else - { - if (reverse_depth == 0) - { - window.PutChar (ACS_LTEE); - window.PutChar (ACS_HLINE); - } - else - { - window.PutChar (ACS_VLINE); - window.PutChar (' '); - } - } + } + + TreeItem *GetParent() { return m_parent; } + + bool IsExpanded() const { return m_is_expanded; } + + void Expand() { m_is_expanded = true; } + + void Unexpand() { m_is_expanded = false; } + + bool Draw(Window &window, const int first_visible_row, + const uint32_t selected_row_idx, int &row_idx, int &num_rows_left) { + if (num_rows_left <= 0) + return false; + + if (m_row_idx >= first_visible_row) { + window.MoveCursor(2, row_idx + 1); + + if (m_parent) + m_parent->DrawTreeForChild(window, this, 0); + + if (m_might_have_children) { + // It we can get UTF8 characters to work we should try to use the + // "symbol" + // UTF8 string below + // const char *symbol = ""; + // if (row.expanded) + // symbol = "\xe2\x96\xbd "; + // else + // symbol = "\xe2\x96\xb7 "; + // window.PutCString (symbol); + + // The ACS_DARROW and ACS_RARROW don't look very nice they are just a + // 'v' or '>' character... + // if (expanded) + // window.PutChar (ACS_DARROW); + // else + // window.PutChar (ACS_RARROW); + // Since we can't find any good looking right arrow/down arrow + // symbols, just use a diamond... + window.PutChar(ACS_DIAMOND); + window.PutChar(ACS_HLINE); + } + bool highlight = (selected_row_idx == static_cast<size_t>(m_row_idx)) && + window.IsActive(); + + if (highlight) + window.AttributeOn(A_REVERSE); + + m_delegate.TreeDelegateDrawTreeItem(*this, window); + + if (highlight) + window.AttributeOff(A_REVERSE); + ++row_idx; + --num_rows_left; } - - TreeItem * - GetItemForRowIndex (uint32_t row_idx) - { - if (static_cast<uint32_t>(m_row_idx) == row_idx) - return this; - if (m_children.empty()) - return nullptr; - if (IsExpanded()) - { - for (auto &item : m_children) - { - TreeItem *selected_item_ptr = item.GetItemForRowIndex(row_idx); - if (selected_item_ptr) - return selected_item_ptr; - } - } - return nullptr; + + if (num_rows_left <= 0) + return false; // We are done drawing... + + if (IsExpanded()) { + for (auto &item : m_children) { + // If we displayed all the rows and item.Draw() returns + // false we are done drawing and can exit this for loop + if (!item.Draw(window, first_visible_row, selected_row_idx, row_idx, + num_rows_left)) + break; + } } - - void * - GetUserData() const - { - return m_user_data; + return num_rows_left >= 0; // Return true if not done drawing yet + } + + void DrawTreeForChild(Window &window, TreeItem *child, + uint32_t reverse_depth) { + if (m_parent) + m_parent->DrawTreeForChild(window, this, reverse_depth + 1); + + if (&m_children.back() == child) { + // Last child + if (reverse_depth == 0) { + window.PutChar(ACS_LLCORNER); + window.PutChar(ACS_HLINE); + } else { + window.PutChar(' '); + window.PutChar(' '); + } + } else { + if (reverse_depth == 0) { + window.PutChar(ACS_LTEE); + window.PutChar(ACS_HLINE); + } else { + window.PutChar(ACS_VLINE); + window.PutChar(' '); + } } - - void - SetUserData (void *user_data) - { - m_user_data = user_data; + } + + TreeItem *GetItemForRowIndex(uint32_t row_idx) { + if (static_cast<uint32_t>(m_row_idx) == row_idx) + return this; + if (m_children.empty()) + return nullptr; + if (IsExpanded()) { + for (auto &item : m_children) { + TreeItem *selected_item_ptr = item.GetItemForRowIndex(row_idx); + if (selected_item_ptr) + return selected_item_ptr; + } } + return nullptr; + } - uint64_t - GetIdentifier() const - { - return m_identifier; - } - - void - SetIdentifier (uint64_t identifier) - { - m_identifier = identifier; - } + void *GetUserData() const { return m_user_data; } - void - SetMightHaveChildren (bool b) - { - m_might_have_children = b; - } + void SetUserData(void *user_data) { m_user_data = user_data; } + + uint64_t GetIdentifier() const { return m_identifier; } + + void SetIdentifier(uint64_t identifier) { m_identifier = identifier; } + + void SetMightHaveChildren(bool b) { m_might_have_children = b; } protected: - TreeItem *m_parent; - TreeDelegate &m_delegate; - void *m_user_data; - uint64_t m_identifier; - int m_row_idx; // Zero based visible row index, -1 if not visible or for the root item - std::vector<TreeItem> m_children; - bool m_might_have_children; - bool m_is_expanded; + TreeItem *m_parent; + TreeDelegate &m_delegate; + void *m_user_data; + uint64_t m_identifier; + int m_row_idx; // Zero based visible row index, -1 if not visible or for the + // root item + std::vector<TreeItem> m_children; + bool m_might_have_children; + bool m_is_expanded; }; -class TreeWindowDelegate : public WindowDelegate -{ +class TreeWindowDelegate : public WindowDelegate { public: - TreeWindowDelegate (Debugger &debugger, const TreeDelegateSP &delegate_sp) : - m_debugger (debugger), - m_delegate_sp (delegate_sp), - m_root(nullptr, *delegate_sp, true), - m_selected_item(nullptr), - m_num_rows (0), - m_selected_row_idx (0), - m_first_visible_row (0), - m_min_x (0), - m_min_y (0), - m_max_x (0), - m_max_y (0) - { - } - - int - NumVisibleRows () const - { - return m_max_y - m_min_y; + TreeWindowDelegate(Debugger &debugger, const TreeDelegateSP &delegate_sp) + : m_debugger(debugger), m_delegate_sp(delegate_sp), + m_root(nullptr, *delegate_sp, true), m_selected_item(nullptr), + m_num_rows(0), m_selected_row_idx(0), m_first_visible_row(0), + m_min_x(0), m_min_y(0), m_max_x(0), m_max_y(0) {} + + int NumVisibleRows() const { return m_max_y - m_min_y; } + + bool WindowDelegateDraw(Window &window, bool force) override { + ExecutionContext exe_ctx( + m_debugger.GetCommandInterpreter().GetExecutionContext()); + Process *process = exe_ctx.GetProcessPtr(); + + bool display_content = false; + if (process) { + StateType state = process->GetState(); + if (StateIsStoppedState(state, true)) { + // We are stopped, so it is ok to + display_content = true; + } else if (StateIsRunningState(state)) { + return true; // Don't do any updating when we are running + } } - bool - WindowDelegateDraw (Window &window, bool force) override - { - ExecutionContext exe_ctx (m_debugger.GetCommandInterpreter().GetExecutionContext()); - Process *process = exe_ctx.GetProcessPtr(); - - bool display_content = false; - if (process) - { - StateType state = process->GetState(); - if (StateIsStoppedState(state, true)) - { - // We are stopped, so it is ok to - display_content = true; - } - else if (StateIsRunningState(state)) - { - return true; // Don't do any updating when we are running - } - } + m_min_x = 2; + m_min_y = 1; + m_max_x = window.GetWidth() - 1; + m_max_y = window.GetHeight() - 1; - m_min_x = 2; - m_min_y = 1; - m_max_x = window.GetWidth() - 1; - m_max_y = window.GetHeight() - 1; - - window.Erase(); - window.DrawTitleBox (window.GetName()); - - if (display_content) - { - const int num_visible_rows = NumVisibleRows(); - m_num_rows = 0; - m_root.CalculateRowIndexes(m_num_rows); - - // If we unexpanded while having something selected our - // total number of rows is less than the num visible rows, - // then make sure we show all the rows by setting the first - // visible row accordingly. - if (m_first_visible_row > 0 && m_num_rows < num_visible_rows) - m_first_visible_row = 0; - - // Make sure the selected row is always visible - if (m_selected_row_idx < m_first_visible_row) - m_first_visible_row = m_selected_row_idx; - else if (m_first_visible_row + num_visible_rows <= m_selected_row_idx) - m_first_visible_row = m_selected_row_idx - num_visible_rows + 1; - - int row_idx = 0; - int num_rows_left = num_visible_rows; - m_root.Draw (window, m_first_visible_row, m_selected_row_idx, row_idx, num_rows_left); - // Get the selected row - m_selected_item = m_root.GetItemForRowIndex (m_selected_row_idx); - } - else - { - m_selected_item = nullptr; - } - - window.DeferredRefresh(); + window.Erase(); + window.DrawTitleBox(window.GetName()); + + if (display_content) { + const int num_visible_rows = NumVisibleRows(); + m_num_rows = 0; + m_root.CalculateRowIndexes(m_num_rows); + + // If we unexpanded while having something selected our + // total number of rows is less than the num visible rows, + // then make sure we show all the rows by setting the first + // visible row accordingly. + if (m_first_visible_row > 0 && m_num_rows < num_visible_rows) + m_first_visible_row = 0; - return true; // Drawing handled + // Make sure the selected row is always visible + if (m_selected_row_idx < m_first_visible_row) + m_first_visible_row = m_selected_row_idx; + else if (m_first_visible_row + num_visible_rows <= m_selected_row_idx) + m_first_visible_row = m_selected_row_idx - num_visible_rows + 1; + + int row_idx = 0; + int num_rows_left = num_visible_rows; + m_root.Draw(window, m_first_visible_row, m_selected_row_idx, row_idx, + num_rows_left); + // Get the selected row + m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx); + } else { + m_selected_item = nullptr; } - const char * - WindowDelegateGetHelpText () override - { - return "Thread window keyboard shortcuts:"; - } - - KeyHelp * - WindowDelegateGetKeyHelp () override - { - static curses::KeyHelp g_source_view_key_help[] = { - { KEY_UP, "Select previous item" }, - { KEY_DOWN, "Select next item" }, - { KEY_RIGHT, "Expand the selected item" }, - { KEY_LEFT, "Unexpand the selected item or select parent if not expanded" }, - { KEY_PPAGE, "Page up" }, - { KEY_NPAGE, "Page down" }, - { 'h', "Show help dialog" }, - { ' ', "Toggle item expansion" }, - { ',', "Page up" }, - { '.', "Page down" }, - { '\0', nullptr } - }; - return g_source_view_key_help; - } - - HandleCharResult - WindowDelegateHandleChar (Window &window, int c) override - { - switch(c) - { - case ',': - case KEY_PPAGE: - // Page up key - if (m_first_visible_row > 0) - { - if (m_first_visible_row > m_max_y) - m_first_visible_row -= m_max_y; - else - m_first_visible_row = 0; - m_selected_row_idx = m_first_visible_row; - m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx); - if (m_selected_item) - m_selected_item->ItemWasSelected (); - } - return eKeyHandled; - - case '.': - case KEY_NPAGE: - // Page down key - if (m_num_rows > m_max_y) - { - if (m_first_visible_row + m_max_y < m_num_rows) - { - m_first_visible_row += m_max_y; - m_selected_row_idx = m_first_visible_row; - m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx); - if (m_selected_item) - m_selected_item->ItemWasSelected (); - } - } - return eKeyHandled; - - case KEY_UP: - if (m_selected_row_idx > 0) - { - --m_selected_row_idx; - m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx); - if (m_selected_item) - m_selected_item->ItemWasSelected (); - } - return eKeyHandled; - - case KEY_DOWN: - if (m_selected_row_idx + 1 < m_num_rows) - { - ++m_selected_row_idx; - m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx); - if (m_selected_item) - m_selected_item->ItemWasSelected (); - } - return eKeyHandled; - - case KEY_RIGHT: - if (m_selected_item) - { - if (!m_selected_item->IsExpanded()) - m_selected_item->Expand(); - } - return eKeyHandled; - - case KEY_LEFT: - if (m_selected_item) - { - if (m_selected_item->IsExpanded()) - m_selected_item->Unexpand(); - else if (m_selected_item->GetParent()) - { - m_selected_row_idx = m_selected_item->GetParent()->GetRowIndex(); - m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx); - if (m_selected_item) - m_selected_item->ItemWasSelected (); - } - } - return eKeyHandled; - - case ' ': - // Toggle expansion state when SPACE is pressed - if (m_selected_item) - { - if (m_selected_item->IsExpanded()) - m_selected_item->Unexpand(); - else - m_selected_item->Expand(); - } - return eKeyHandled; - - case 'h': - window.CreateHelpSubwindow (); - return eKeyHandled; - - default: - break; - } - return eKeyNotHandled; + window.DeferredRefresh(); + + return true; // Drawing handled + } + + const char *WindowDelegateGetHelpText() override { + return "Thread window keyboard shortcuts:"; + } + + KeyHelp *WindowDelegateGetKeyHelp() override { + static curses::KeyHelp g_source_view_key_help[] = { + {KEY_UP, "Select previous item"}, + {KEY_DOWN, "Select next item"}, + {KEY_RIGHT, "Expand the selected item"}, + {KEY_LEFT, + "Unexpand the selected item or select parent if not expanded"}, + {KEY_PPAGE, "Page up"}, + {KEY_NPAGE, "Page down"}, + {'h', "Show help dialog"}, + {' ', "Toggle item expansion"}, + {',', "Page up"}, + {'.', "Page down"}, + {'\0', nullptr}}; + return g_source_view_key_help; + } + + HandleCharResult WindowDelegateHandleChar(Window &window, int c) override { + switch (c) { + case ',': + case KEY_PPAGE: + // Page up key + if (m_first_visible_row > 0) { + if (m_first_visible_row > m_max_y) + m_first_visible_row -= m_max_y; + else + m_first_visible_row = 0; + m_selected_row_idx = m_first_visible_row; + m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx); + if (m_selected_item) + m_selected_item->ItemWasSelected(); + } + return eKeyHandled; + + case '.': + case KEY_NPAGE: + // Page down key + if (m_num_rows > m_max_y) { + if (m_first_visible_row + m_max_y < m_num_rows) { + m_first_visible_row += m_max_y; + m_selected_row_idx = m_first_visible_row; + m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx); + if (m_selected_item) + m_selected_item->ItemWasSelected(); + } + } + return eKeyHandled; + + case KEY_UP: + if (m_selected_row_idx > 0) { + --m_selected_row_idx; + m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx); + if (m_selected_item) + m_selected_item->ItemWasSelected(); + } + return eKeyHandled; + + case KEY_DOWN: + if (m_selected_row_idx + 1 < m_num_rows) { + ++m_selected_row_idx; + m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx); + if (m_selected_item) + m_selected_item->ItemWasSelected(); + } + return eKeyHandled; + + case KEY_RIGHT: + if (m_selected_item) { + if (!m_selected_item->IsExpanded()) + m_selected_item->Expand(); + } + return eKeyHandled; + + case KEY_LEFT: + if (m_selected_item) { + if (m_selected_item->IsExpanded()) + m_selected_item->Unexpand(); + else if (m_selected_item->GetParent()) { + m_selected_row_idx = m_selected_item->GetParent()->GetRowIndex(); + m_selected_item = m_root.GetItemForRowIndex(m_selected_row_idx); + if (m_selected_item) + m_selected_item->ItemWasSelected(); + } + } + return eKeyHandled; + + case ' ': + // Toggle expansion state when SPACE is pressed + if (m_selected_item) { + if (m_selected_item->IsExpanded()) + m_selected_item->Unexpand(); + else + m_selected_item->Expand(); + } + return eKeyHandled; + + case 'h': + window.CreateHelpSubwindow(); + return eKeyHandled; + + default: + break; } + return eKeyNotHandled; + } protected: - Debugger &m_debugger; - TreeDelegateSP m_delegate_sp; - TreeItem m_root; - TreeItem *m_selected_item; - int m_num_rows; - int m_selected_row_idx; - int m_first_visible_row; - int m_min_x; - int m_min_y; - int m_max_x; - int m_max_y; + Debugger &m_debugger; + TreeDelegateSP m_delegate_sp; + TreeItem m_root; + TreeItem *m_selected_item; + int m_num_rows; + int m_selected_row_idx; + int m_first_visible_row; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; }; -class FrameTreeDelegate : public TreeDelegate -{ +class FrameTreeDelegate : public TreeDelegate { public: - FrameTreeDelegate () : - TreeDelegate() - { - FormatEntity::Parse ("frame #${frame.index}: {${function.name}${function.pc-offset}}}", - m_format); + FrameTreeDelegate() : TreeDelegate() { + FormatEntity::Parse( + "frame #${frame.index}: {${function.name}${function.pc-offset}}}", + m_format); + } + + ~FrameTreeDelegate() override = default; + + void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override { + Thread *thread = (Thread *)item.GetUserData(); + if (thread) { + const uint64_t frame_idx = item.GetIdentifier(); + StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_idx); + if (frame_sp) { + StreamString strm; + const SymbolContext &sc = + frame_sp->GetSymbolContext(eSymbolContextEverything); + ExecutionContext exe_ctx(frame_sp); + if (FormatEntity::Format(m_format, strm, &sc, &exe_ctx, nullptr, + nullptr, false, false)) { + int right_pad = 1; + window.PutCStringTruncated(strm.GetString().str().c_str(), right_pad); + } + } } + } + + void TreeDelegateGenerateChildren(TreeItem &item) override { + // No children for frames yet... + } + + bool TreeDelegateItemSelected(TreeItem &item) override { + Thread *thread = (Thread *)item.GetUserData(); + if (thread) { + thread->GetProcess()->GetThreadList().SetSelectedThreadByID( + thread->GetID()); + const uint64_t frame_idx = item.GetIdentifier(); + thread->SetSelectedFrameByIndex(frame_idx); + return true; + } + return false; + } - ~FrameTreeDelegate() override = default; +protected: + FormatEntity::Entry m_format; +}; - void - TreeDelegateDrawTreeItem (TreeItem &item, Window &window) override - { - Thread* thread = (Thread*)item.GetUserData(); - if (thread) - { - const uint64_t frame_idx = item.GetIdentifier(); - StackFrameSP frame_sp = thread->GetStackFrameAtIndex(frame_idx); - if (frame_sp) - { - StreamString strm; - const SymbolContext &sc = frame_sp->GetSymbolContext(eSymbolContextEverything); - ExecutionContext exe_ctx (frame_sp); - if (FormatEntity::Format(m_format, strm, &sc, &exe_ctx, nullptr, nullptr, false, false)) - { - int right_pad = 1; - window.PutCStringTruncated(strm.GetString().c_str(), right_pad); - } - } - } +class ThreadTreeDelegate : public TreeDelegate { +public: + ThreadTreeDelegate(Debugger &debugger) + : TreeDelegate(), m_debugger(debugger), m_tid(LLDB_INVALID_THREAD_ID), + m_stop_id(UINT32_MAX) { + FormatEntity::Parse("thread #${thread.index}: tid = ${thread.id}{, stop " + "reason = ${thread.stop-reason}}", + m_format); + } + + ~ThreadTreeDelegate() override = default; + + ProcessSP GetProcess() { + return m_debugger.GetCommandInterpreter() + .GetExecutionContext() + .GetProcessSP(); + } + + ThreadSP GetThread(const TreeItem &item) { + ProcessSP process_sp = GetProcess(); + if (process_sp) + return process_sp->GetThreadList().FindThreadByID(item.GetIdentifier()); + return ThreadSP(); + } + + void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override { + ThreadSP thread_sp = GetThread(item); + if (thread_sp) { + StreamString strm; + ExecutionContext exe_ctx(thread_sp); + if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr, + nullptr, false, false)) { + int right_pad = 1; + window.PutCStringTruncated(strm.GetString().str().c_str(), right_pad); + } } - - void - TreeDelegateGenerateChildren (TreeItem &item) override - { - // No children for frames yet... + } + + void TreeDelegateGenerateChildren(TreeItem &item) override { + ProcessSP process_sp = GetProcess(); + if (process_sp && process_sp->IsAlive()) { + StateType state = process_sp->GetState(); + if (StateIsStoppedState(state, true)) { + ThreadSP thread_sp = GetThread(item); + if (thread_sp) { + if (m_stop_id == process_sp->GetStopID() && + thread_sp->GetID() == m_tid) + return; // Children are already up to date + if (!m_frame_delegate_sp) { + // Always expand the thread item the first time we show it + m_frame_delegate_sp.reset(new FrameTreeDelegate()); + } + + m_stop_id = process_sp->GetStopID(); + m_tid = thread_sp->GetID(); + + TreeItem t(&item, *m_frame_delegate_sp, false); + size_t num_frames = thread_sp->GetStackFrameCount(); + item.Resize(num_frames, t); + for (size_t i = 0; i < num_frames; ++i) { + item[i].SetUserData(thread_sp.get()); + item[i].SetIdentifier(i); + } + } + return; + } } - - bool - TreeDelegateItemSelected (TreeItem &item) override - { - Thread* thread = (Thread*)item.GetUserData(); - if (thread) - { - thread->GetProcess()->GetThreadList().SetSelectedThreadByID(thread->GetID()); - const uint64_t frame_idx = item.GetIdentifier(); - thread->SetSelectedFrameByIndex(frame_idx); + item.ClearChildren(); + } + + bool TreeDelegateItemSelected(TreeItem &item) override { + ProcessSP process_sp = GetProcess(); + if (process_sp && process_sp->IsAlive()) { + StateType state = process_sp->GetState(); + if (StateIsStoppedState(state, true)) { + ThreadSP thread_sp = GetThread(item); + if (thread_sp) { + ThreadList &thread_list = thread_sp->GetProcess()->GetThreadList(); + std::lock_guard<std::recursive_mutex> guard(thread_list.GetMutex()); + ThreadSP selected_thread_sp = thread_list.GetSelectedThread(); + if (selected_thread_sp->GetID() != thread_sp->GetID()) { + thread_list.SetSelectedThreadByID(thread_sp->GetID()); return true; + } } - return false; + } } + return false; + } protected: - FormatEntity::Entry m_format; + Debugger &m_debugger; + std::shared_ptr<FrameTreeDelegate> m_frame_delegate_sp; + lldb::user_id_t m_tid; + uint32_t m_stop_id; + FormatEntity::Entry m_format; }; -class ThreadTreeDelegate : public TreeDelegate -{ +class ThreadsTreeDelegate : public TreeDelegate { public: - ThreadTreeDelegate (Debugger &debugger) : - TreeDelegate(), - m_debugger (debugger), - m_tid (LLDB_INVALID_THREAD_ID), - m_stop_id (UINT32_MAX) - { - FormatEntity::Parse ("thread #${thread.index}: tid = ${thread.id}{, stop reason = ${thread.stop-reason}}", - m_format); + ThreadsTreeDelegate(Debugger &debugger) + : TreeDelegate(), m_thread_delegate_sp(), m_debugger(debugger), + m_stop_id(UINT32_MAX) { + FormatEntity::Parse("process ${process.id}{, name = ${process.name}}", + m_format); + } + + ~ThreadsTreeDelegate() override = default; + + ProcessSP GetProcess() { + return m_debugger.GetCommandInterpreter() + .GetExecutionContext() + .GetProcessSP(); + } + + void TreeDelegateDrawTreeItem(TreeItem &item, Window &window) override { + ProcessSP process_sp = GetProcess(); + if (process_sp && process_sp->IsAlive()) { + StreamString strm; + ExecutionContext exe_ctx(process_sp); + if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr, + nullptr, false, false)) { + int right_pad = 1; + window.PutCStringTruncated(strm.GetString().str().c_str(), right_pad); + } } - - ~ThreadTreeDelegate() override = default; - - ProcessSP - GetProcess () - { - return m_debugger.GetCommandInterpreter().GetExecutionContext().GetProcessSP(); - } - - ThreadSP - GetThread (const TreeItem &item) - { - ProcessSP process_sp = GetProcess (); - if (process_sp) - return process_sp->GetThreadList().FindThreadByID(item.GetIdentifier()); - return ThreadSP(); - } - - void - TreeDelegateDrawTreeItem (TreeItem &item, Window &window) override - { - ThreadSP thread_sp = GetThread (item); - if (thread_sp) - { - StreamString strm; - ExecutionContext exe_ctx (thread_sp); - if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr, nullptr, false, false)) - { - int right_pad = 1; - window.PutCStringTruncated(strm.GetString().c_str(), right_pad); - } + } + + void TreeDelegateGenerateChildren(TreeItem &item) override { + ProcessSP process_sp = GetProcess(); + if (process_sp && process_sp->IsAlive()) { + StateType state = process_sp->GetState(); + if (StateIsStoppedState(state, true)) { + const uint32_t stop_id = process_sp->GetStopID(); + if (m_stop_id == stop_id) + return; // Children are already up to date + + m_stop_id = stop_id; + + if (!m_thread_delegate_sp) { + // Always expand the thread item the first time we show it + // item.Expand(); + m_thread_delegate_sp.reset(new ThreadTreeDelegate(m_debugger)); + } + + TreeItem t(&item, *m_thread_delegate_sp, false); + ThreadList &threads = process_sp->GetThreadList(); + std::lock_guard<std::recursive_mutex> guard(threads.GetMutex()); + size_t num_threads = threads.GetSize(); + item.Resize(num_threads, t); + for (size_t i = 0; i < num_threads; ++i) { + item[i].SetIdentifier(threads.GetThreadAtIndex(i)->GetID()); + item[i].SetMightHaveChildren(true); } + return; + } } + item.ClearChildren(); + } - void - TreeDelegateGenerateChildren (TreeItem &item) override - { - ProcessSP process_sp = GetProcess (); - if (process_sp && process_sp->IsAlive()) - { - StateType state = process_sp->GetState(); - if (StateIsStoppedState(state, true)) - { - ThreadSP thread_sp = GetThread (item); - if (thread_sp) - { - if (m_stop_id == process_sp->GetStopID() && thread_sp->GetID() == m_tid) - return; // Children are already up to date - if (!m_frame_delegate_sp) - { - // Always expand the thread item the first time we show it - m_frame_delegate_sp.reset (new FrameTreeDelegate()); - } - - m_stop_id = process_sp->GetStopID(); - m_tid = thread_sp->GetID(); - - TreeItem t (&item, *m_frame_delegate_sp, false); - size_t num_frames = thread_sp->GetStackFrameCount(); - item.Resize (num_frames, t); - for (size_t i = 0; i < num_frames; ++i) - { - item[i].SetUserData(thread_sp.get()); - item[i].SetIdentifier(i); - } - } - return; - } - } - item.ClearChildren(); - } - - bool - TreeDelegateItemSelected (TreeItem &item) override - { - ProcessSP process_sp = GetProcess (); - if (process_sp && process_sp->IsAlive()) - { - StateType state = process_sp->GetState(); - if (StateIsStoppedState(state, true)) - { - ThreadSP thread_sp = GetThread (item); - if (thread_sp) - { - ThreadList &thread_list = thread_sp->GetProcess()->GetThreadList(); - std::lock_guard<std::recursive_mutex> guard(thread_list.GetMutex()); - ThreadSP selected_thread_sp = thread_list.GetSelectedThread(); - if (selected_thread_sp->GetID() != thread_sp->GetID()) - { - thread_list.SetSelectedThreadByID(thread_sp->GetID()); - return true; - } - } - } - } - return false; - } + bool TreeDelegateItemSelected(TreeItem &item) override { return false; } protected: - Debugger &m_debugger; - std::shared_ptr<FrameTreeDelegate> m_frame_delegate_sp; - lldb::user_id_t m_tid; - uint32_t m_stop_id; - FormatEntity::Entry m_format; + std::shared_ptr<ThreadTreeDelegate> m_thread_delegate_sp; + Debugger &m_debugger; + uint32_t m_stop_id; + FormatEntity::Entry m_format; }; -class ThreadsTreeDelegate : public TreeDelegate -{ +class ValueObjectListDelegate : public WindowDelegate { public: - ThreadsTreeDelegate (Debugger &debugger) : - TreeDelegate(), - m_thread_delegate_sp (), - m_debugger (debugger), - m_stop_id (UINT32_MAX) - { - FormatEntity::Parse("process ${process.id}{, name = ${process.name}}", - m_format); - } + ValueObjectListDelegate() + : m_rows(), m_selected_row(nullptr), + m_selected_row_idx(0), m_first_visible_row(0), m_num_rows(0), + m_max_x(0), m_max_y(0) {} + + ValueObjectListDelegate(ValueObjectList &valobj_list) + : m_rows(), m_selected_row(nullptr), + m_selected_row_idx(0), m_first_visible_row(0), m_num_rows(0), + m_max_x(0), m_max_y(0) { + SetValues(valobj_list); + } + + ~ValueObjectListDelegate() override = default; + + void SetValues(ValueObjectList &valobj_list) { + m_selected_row = nullptr; + m_selected_row_idx = 0; + m_first_visible_row = 0; + m_num_rows = 0; + m_rows.clear(); + for (auto &valobj_sp : valobj_list.GetObjects()) + m_rows.push_back(Row(valobj_sp, nullptr)); + } + + bool WindowDelegateDraw(Window &window, bool force) override { + m_num_rows = 0; + m_min_x = 2; + m_min_y = 1; + m_max_x = window.GetWidth() - 1; + m_max_y = window.GetHeight() - 1; - ~ThreadsTreeDelegate() override = default; + window.Erase(); + window.DrawTitleBox(window.GetName()); + + const int num_visible_rows = NumVisibleRows(); + const int num_rows = CalculateTotalNumberRows(m_rows); + + // If we unexpanded while having something selected our + // total number of rows is less than the num visible rows, + // then make sure we show all the rows by setting the first + // visible row accordingly. + if (m_first_visible_row > 0 && num_rows < num_visible_rows) + m_first_visible_row = 0; + + // Make sure the selected row is always visible + if (m_selected_row_idx < m_first_visible_row) + m_first_visible_row = m_selected_row_idx; + else if (m_first_visible_row + num_visible_rows <= m_selected_row_idx) + m_first_visible_row = m_selected_row_idx - num_visible_rows + 1; + + DisplayRows(window, m_rows, g_options); + + window.DeferredRefresh(); + + // Get the selected row + m_selected_row = GetRowForRowIndex(m_selected_row_idx); + // Keep the cursor on the selected row so the highlight and the cursor + // are always on the same line + if (m_selected_row) + window.MoveCursor(m_selected_row->x, m_selected_row->y); + + return true; // Drawing handled + } + + KeyHelp *WindowDelegateGetKeyHelp() override { + static curses::KeyHelp g_source_view_key_help[] = { + {KEY_UP, "Select previous item"}, + {KEY_DOWN, "Select next item"}, + {KEY_RIGHT, "Expand selected item"}, + {KEY_LEFT, "Unexpand selected item or select parent if not expanded"}, + {KEY_PPAGE, "Page up"}, + {KEY_NPAGE, "Page down"}, + {'A', "Format as annotated address"}, + {'b', "Format as binary"}, + {'B', "Format as hex bytes with ASCII"}, + {'c', "Format as character"}, + {'d', "Format as a signed integer"}, + {'D', "Format selected value using the default format for the type"}, + {'f', "Format as float"}, + {'h', "Show help dialog"}, + {'i', "Format as instructions"}, + {'o', "Format as octal"}, + {'p', "Format as pointer"}, + {'s', "Format as C string"}, + {'t', "Toggle showing/hiding type names"}, + {'u', "Format as an unsigned integer"}, + {'x', "Format as hex"}, + {'X', "Format as uppercase hex"}, + {' ', "Toggle item expansion"}, + {',', "Page up"}, + {'.', "Page down"}, + {'\0', nullptr}}; + return g_source_view_key_help; + } + + HandleCharResult WindowDelegateHandleChar(Window &window, int c) override { + switch (c) { + case 'x': + case 'X': + case 'o': + case 's': + case 'u': + case 'd': + case 'D': + case 'i': + case 'A': + case 'p': + case 'c': + case 'b': + case 'B': + case 'f': + // Change the format for the currently selected item + if (m_selected_row) { + auto valobj_sp = m_selected_row->value.GetSP(); + if (valobj_sp) + valobj_sp->SetFormat(FormatForChar(c)); + } + return eKeyHandled; + + case 't': + // Toggle showing type names + g_options.show_types = !g_options.show_types; + return eKeyHandled; + + case ',': + case KEY_PPAGE: + // Page up key + if (m_first_visible_row > 0) { + if (static_cast<int>(m_first_visible_row) > m_max_y) + m_first_visible_row -= m_max_y; + else + m_first_visible_row = 0; + m_selected_row_idx = m_first_visible_row; + } + return eKeyHandled; + + case '.': + case KEY_NPAGE: + // Page down key + if (m_num_rows > static_cast<size_t>(m_max_y)) { + if (m_first_visible_row + m_max_y < m_num_rows) { + m_first_visible_row += m_max_y; + m_selected_row_idx = m_first_visible_row; + } + } + return eKeyHandled; + + case KEY_UP: + if (m_selected_row_idx > 0) + --m_selected_row_idx; + return eKeyHandled; + + case KEY_DOWN: + if (m_selected_row_idx + 1 < m_num_rows) + ++m_selected_row_idx; + return eKeyHandled; + + case KEY_RIGHT: + if (m_selected_row) { + if (!m_selected_row->expanded) + m_selected_row->Expand(); + } + return eKeyHandled; + + case KEY_LEFT: + if (m_selected_row) { + if (m_selected_row->expanded) + m_selected_row->Unexpand(); + else if (m_selected_row->parent) + m_selected_row_idx = m_selected_row->parent->row_idx; + } + return eKeyHandled; + + case ' ': + // Toggle expansion state when SPACE is pressed + if (m_selected_row) { + if (m_selected_row->expanded) + m_selected_row->Unexpand(); + else + m_selected_row->Expand(); + } + return eKeyHandled; - ProcessSP - GetProcess () - { - return m_debugger.GetCommandInterpreter().GetExecutionContext().GetProcessSP(); - } + case 'h': + window.CreateHelpSubwindow(); + return eKeyHandled; - void - TreeDelegateDrawTreeItem (TreeItem &item, Window &window) override - { - ProcessSP process_sp = GetProcess (); - if (process_sp && process_sp->IsAlive()) - { - StreamString strm; - ExecutionContext exe_ctx (process_sp); - if (FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr, nullptr, false, false)) - { - int right_pad = 1; - window.PutCStringTruncated(strm.GetString().c_str(), right_pad); - } - } + default: + break; } + return eKeyNotHandled; + } - void - TreeDelegateGenerateChildren (TreeItem &item) override - { - ProcessSP process_sp = GetProcess (); - if (process_sp && process_sp->IsAlive()) - { - StateType state = process_sp->GetState(); - if (StateIsStoppedState(state, true)) - { - const uint32_t stop_id = process_sp->GetStopID(); - if (m_stop_id == stop_id) - return; // Children are already up to date - - m_stop_id = stop_id; - - if (!m_thread_delegate_sp) - { - // Always expand the thread item the first time we show it - //item.Expand(); - m_thread_delegate_sp.reset (new ThreadTreeDelegate(m_debugger)); - } - - TreeItem t (&item, *m_thread_delegate_sp, false); - ThreadList &threads = process_sp->GetThreadList(); - std::lock_guard<std::recursive_mutex> guard(threads.GetMutex()); - size_t num_threads = threads.GetSize(); - item.Resize (num_threads, t); - for (size_t i = 0; i < num_threads; ++i) - { - item[i].SetIdentifier(threads.GetThreadAtIndex(i)->GetID()); - item[i].SetMightHaveChildren(true); - } - return; - } - } - item.ClearChildren(); - } - - bool - TreeDelegateItemSelected (TreeItem &item) override - { - return false; - } - protected: - std::shared_ptr<ThreadTreeDelegate> m_thread_delegate_sp; - Debugger &m_debugger; - uint32_t m_stop_id; - FormatEntity::Entry m_format; -}; - -class ValueObjectListDelegate : public WindowDelegate -{ -public: - ValueObjectListDelegate () : - m_valobj_list (), - m_rows (), - m_selected_row(nullptr), - m_selected_row_idx (0), - m_first_visible_row (0), - m_num_rows (0), - m_max_x (0), - m_max_y (0) - { - } - - ValueObjectListDelegate (ValueObjectList &valobj_list) : - m_valobj_list (valobj_list), - m_rows (), - m_selected_row(nullptr), - m_selected_row_idx (0), - m_first_visible_row (0), - m_num_rows (0), - m_max_x (0), - m_max_y (0) - { - SetValues (valobj_list); + std::vector<Row> m_rows; + Row *m_selected_row; + uint32_t m_selected_row_idx; + uint32_t m_first_visible_row; + uint32_t m_num_rows; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; + + static Format FormatForChar(int c) { + switch (c) { + case 'x': + return eFormatHex; + case 'X': + return eFormatHexUppercase; + case 'o': + return eFormatOctal; + case 's': + return eFormatCString; + case 'u': + return eFormatUnsigned; + case 'd': + return eFormatDecimal; + case 'D': + return eFormatDefault; + case 'i': + return eFormatInstruction; + case 'A': + return eFormatAddressInfo; + case 'p': + return eFormatPointer; + case 'c': + return eFormatChar; + case 'b': + return eFormatBinary; + case 'B': + return eFormatBytesWithASCII; + case 'f': + return eFormatFloat; } + return eFormatDefault; + } - ~ValueObjectListDelegate() override = default; + bool DisplayRowObject(Window &window, Row &row, DisplayOptions &options, + bool highlight, bool last_child) { + ValueObject *valobj = row.value.GetSP().get(); - void - SetValues (ValueObjectList &valobj_list) - { - m_selected_row = nullptr; - m_selected_row_idx = 0; - m_first_visible_row = 0; - m_num_rows = 0; - m_rows.clear(); - m_valobj_list = valobj_list; - const size_t num_values = m_valobj_list.GetSize(); - for (size_t i = 0; i < num_values; ++i) - m_rows.push_back(Row(m_valobj_list.GetValueObjectAtIndex(i), nullptr)); - } - - bool - WindowDelegateDraw (Window &window, bool force) override - { - m_num_rows = 0; - m_min_x = 2; - m_min_y = 1; - m_max_x = window.GetWidth() - 1; - m_max_y = window.GetHeight() - 1; - - window.Erase(); - window.DrawTitleBox (window.GetName()); - - const int num_visible_rows = NumVisibleRows(); - const int num_rows = CalculateTotalNumberRows (m_rows); - - // If we unexpanded while having something selected our - // total number of rows is less than the num visible rows, - // then make sure we show all the rows by setting the first - // visible row accordingly. - if (m_first_visible_row > 0 && num_rows < num_visible_rows) - m_first_visible_row = 0; - - // Make sure the selected row is always visible - if (m_selected_row_idx < m_first_visible_row) - m_first_visible_row = m_selected_row_idx; - else if (m_first_visible_row + num_visible_rows <= m_selected_row_idx) - m_first_visible_row = m_selected_row_idx - num_visible_rows + 1; - - DisplayRows (window, m_rows, g_options); - - window.DeferredRefresh(); - - // Get the selected row - m_selected_row = GetRowForRowIndex (m_selected_row_idx); - // Keep the cursor on the selected row so the highlight and the cursor - // are always on the same line - if (m_selected_row) - window.MoveCursor (m_selected_row->x, - m_selected_row->y); - - return true; // Drawing handled - } - - KeyHelp * - WindowDelegateGetKeyHelp () override - { - static curses::KeyHelp g_source_view_key_help[] = { - { KEY_UP, "Select previous item" }, - { KEY_DOWN, "Select next item" }, - { KEY_RIGHT, "Expand selected item" }, - { KEY_LEFT, "Unexpand selected item or select parent if not expanded" }, - { KEY_PPAGE, "Page up" }, - { KEY_NPAGE, "Page down" }, - { 'A', "Format as annotated address" }, - { 'b', "Format as binary" }, - { 'B', "Format as hex bytes with ASCII" }, - { 'c', "Format as character" }, - { 'd', "Format as a signed integer" }, - { 'D', "Format selected value using the default format for the type" }, - { 'f', "Format as float" }, - { 'h', "Show help dialog" }, - { 'i', "Format as instructions" }, - { 'o', "Format as octal" }, - { 'p', "Format as pointer" }, - { 's', "Format as C string" }, - { 't', "Toggle showing/hiding type names" }, - { 'u', "Format as an unsigned integer" }, - { 'x', "Format as hex" }, - { 'X', "Format as uppercase hex" }, - { ' ', "Toggle item expansion" }, - { ',', "Page up" }, - { '.', "Page down" }, - { '\0', nullptr } - }; - return g_source_view_key_help; - } + if (valobj == nullptr) + return false; - HandleCharResult - WindowDelegateHandleChar (Window &window, int c) override - { - switch(c) - { - case 'x': - case 'X': - case 'o': - case 's': - case 'u': - case 'd': - case 'D': - case 'i': - case 'A': - case 'p': - case 'c': - case 'b': - case 'B': - case 'f': - // Change the format for the currently selected item - if (m_selected_row) - m_selected_row->valobj->SetFormat (FormatForChar (c)); - return eKeyHandled; - - case 't': - // Toggle showing type names - g_options.show_types = !g_options.show_types; - return eKeyHandled; - - case ',': - case KEY_PPAGE: - // Page up key - if (m_first_visible_row > 0) - { - if (static_cast<int>(m_first_visible_row) > m_max_y) - m_first_visible_row -= m_max_y; - else - m_first_visible_row = 0; - m_selected_row_idx = m_first_visible_row; - } - return eKeyHandled; - - case '.': - case KEY_NPAGE: - // Page down key - if (m_num_rows > static_cast<size_t>(m_max_y)) - { - if (m_first_visible_row + m_max_y < m_num_rows) - { - m_first_visible_row += m_max_y; - m_selected_row_idx = m_first_visible_row; - } - } - return eKeyHandled; - - case KEY_UP: - if (m_selected_row_idx > 0) - --m_selected_row_idx; - return eKeyHandled; - - case KEY_DOWN: - if (m_selected_row_idx + 1 < m_num_rows) - ++m_selected_row_idx; - return eKeyHandled; - - case KEY_RIGHT: - if (m_selected_row) - { - if (!m_selected_row->expanded) - m_selected_row->Expand(); - } - return eKeyHandled; - - case KEY_LEFT: - if (m_selected_row) - { - if (m_selected_row->expanded) - m_selected_row->Unexpand(); - else if (m_selected_row->parent) - m_selected_row_idx = m_selected_row->parent->row_idx; - } - return eKeyHandled; - - case ' ': - // Toggle expansion state when SPACE is pressed - if (m_selected_row) - { - if (m_selected_row->expanded) - m_selected_row->Unexpand(); - else - m_selected_row->Expand(); - } - return eKeyHandled; - - case 'h': - window.CreateHelpSubwindow (); - return eKeyHandled; + const char *type_name = + options.show_types ? valobj->GetTypeName().GetCString() : nullptr; + const char *name = valobj->GetName().GetCString(); + const char *value = valobj->GetValueAsCString(); + const char *summary = valobj->GetSummaryAsCString(); - default: - break; - } - return eKeyNotHandled; - } - -protected: - ValueObjectList m_valobj_list; - std::vector<Row> m_rows; - Row *m_selected_row; - uint32_t m_selected_row_idx; - uint32_t m_first_visible_row; - uint32_t m_num_rows; - int m_min_x; - int m_min_y; - int m_max_x; - int m_max_y; - - static Format - FormatForChar (int c) - { - switch (c) - { - case 'x': return eFormatHex; - case 'X': return eFormatHexUppercase; - case 'o': return eFormatOctal; - case 's': return eFormatCString; - case 'u': return eFormatUnsigned; - case 'd': return eFormatDecimal; - case 'D': return eFormatDefault; - case 'i': return eFormatInstruction; - case 'A': return eFormatAddressInfo; - case 'p': return eFormatPointer; - case 'c': return eFormatChar; - case 'b': return eFormatBinary; - case 'B': return eFormatBytesWithASCII; - case 'f': return eFormatFloat; - } - return eFormatDefault; - } - - bool - DisplayRowObject (Window &window, - Row &row, - DisplayOptions &options, - bool highlight, - bool last_child) - { - ValueObject *valobj = row.valobj.get(); - - if (valobj == nullptr) - return false; - - const char *type_name = options.show_types ? valobj->GetTypeName().GetCString() : nullptr; - const char *name = valobj->GetName().GetCString(); - const char *value = valobj->GetValueAsCString (); - const char *summary = valobj->GetSummaryAsCString (); - - window.MoveCursor (row.x, row.y); - - row.DrawTree (window); - - if (highlight) - window.AttributeOn(A_REVERSE); - - if (type_name && type_name[0]) - window.Printf ("(%s) ", type_name); - - if (name && name[0]) - window.PutCString(name); - - attr_t changd_attr = 0; - if (valobj->GetValueDidChange()) - changd_attr = COLOR_PAIR(5) | A_BOLD; - - if (value && value[0]) - { - window.PutCString(" = "); - if (changd_attr) - window.AttributeOn(changd_attr); - window.PutCString (value); - if (changd_attr) - window.AttributeOff(changd_attr); - } - - if (summary && summary[0]) - { - window.PutChar(' '); - if (changd_attr) - window.AttributeOn(changd_attr); - window.PutCString(summary); - if (changd_attr) - window.AttributeOff(changd_attr); - } - - if (highlight) - window.AttributeOff (A_REVERSE); - - return true; - } + window.MoveCursor(row.x, row.y); - void - DisplayRows (Window &window, - std::vector<Row> &rows, - DisplayOptions &options) - { - // > 0x25B7 - // \/ 0x25BD - - bool window_is_active = window.IsActive(); - for (auto &row : rows) - { - const bool last_child = row.parent && &rows[rows.size()-1] == &row; - // Save the row index in each Row structure - row.row_idx = m_num_rows; - if ((m_num_rows >= m_first_visible_row) && - ((m_num_rows - m_first_visible_row) < static_cast<size_t>(NumVisibleRows()))) - { - row.x = m_min_x; - row.y = m_num_rows - m_first_visible_row + 1; - if (DisplayRowObject (window, - row, - options, - window_is_active && m_num_rows == m_selected_row_idx, - last_child)) - { - ++m_num_rows; - } - else - { - row.x = 0; - row.y = 0; - } - } - else - { - row.x = 0; - row.y = 0; - ++m_num_rows; - } - - if (row.expanded && !row.children.empty()) - { - DisplayRows (window, - row.children, - options); - } - } + row.DrawTree(window); + + if (highlight) + window.AttributeOn(A_REVERSE); + + if (type_name && type_name[0]) + window.Printf("(%s) ", type_name); + + if (name && name[0]) + window.PutCString(name); + + attr_t changd_attr = 0; + if (valobj->GetValueDidChange()) + changd_attr = COLOR_PAIR(5) | A_BOLD; + + if (value && value[0]) { + window.PutCString(" = "); + if (changd_attr) + window.AttributeOn(changd_attr); + window.PutCString(value); + if (changd_attr) + window.AttributeOff(changd_attr); } - - int - CalculateTotalNumberRows (const std::vector<Row> &rows) - { - int row_count = 0; - for (const auto &row : rows) - { - ++row_count; - if (row.expanded) - row_count += CalculateTotalNumberRows(row.children); - } - return row_count; + + if (summary && summary[0]) { + window.PutChar(' '); + if (changd_attr) + window.AttributeOn(changd_attr); + window.PutCString(summary); + if (changd_attr) + window.AttributeOff(changd_attr); } - static Row * - GetRowForRowIndexImpl (std::vector<Row> &rows, size_t &row_index) - { - for (auto &row : rows) - { - if (row_index == 0) - return &row; - else - { - --row_index; - if (row.expanded && !row.children.empty()) - { - Row *result = GetRowForRowIndexImpl (row.children, row_index); - if (result) - return result; - } - } - } - return nullptr; + if (highlight) + window.AttributeOff(A_REVERSE); + + return true; + } + + void DisplayRows(Window &window, std::vector<Row> &rows, + DisplayOptions &options) { + // > 0x25B7 + // \/ 0x25BD + + bool window_is_active = window.IsActive(); + for (auto &row : rows) { + const bool last_child = row.parent && &rows[rows.size() - 1] == &row; + // Save the row index in each Row structure + row.row_idx = m_num_rows; + if ((m_num_rows >= m_first_visible_row) && + ((m_num_rows - m_first_visible_row) < + static_cast<size_t>(NumVisibleRows()))) { + row.x = m_min_x; + row.y = m_num_rows - m_first_visible_row + 1; + if (DisplayRowObject(window, row, options, + window_is_active && + m_num_rows == m_selected_row_idx, + last_child)) { + ++m_num_rows; + } else { + row.x = 0; + row.y = 0; + } + } else { + row.x = 0; + row.y = 0; + ++m_num_rows; + } + + auto &children = row.GetChildren(); + if (row.expanded && !children.empty()) { + DisplayRows(window, children, options); + } } - - Row * - GetRowForRowIndex (size_t row_index) - { - return GetRowForRowIndexImpl (m_rows, row_index); + } + + int CalculateTotalNumberRows(std::vector<Row> &rows) { + int row_count = 0; + for (auto &row : rows) { + ++row_count; + if (row.expanded) + row_count += CalculateTotalNumberRows(row.GetChildren()); } - - int - NumVisibleRows () const - { - return m_max_y - m_min_y; + return row_count; + } + + static Row *GetRowForRowIndexImpl(std::vector<Row> &rows, size_t &row_index) { + for (auto &row : rows) { + if (row_index == 0) + return &row; + else { + --row_index; + auto &children = row.GetChildren(); + if (row.expanded && !children.empty()) { + Row *result = GetRowForRowIndexImpl(children, row_index); + if (result) + return result; + } + } } + return nullptr; + } + + Row *GetRowForRowIndex(size_t row_index) { + return GetRowForRowIndexImpl(m_rows, row_index); + } - static DisplayOptions g_options; + int NumVisibleRows() const { return m_max_y - m_min_y; } + + static DisplayOptions g_options; }; -class FrameVariablesWindowDelegate : public ValueObjectListDelegate -{ +class FrameVariablesWindowDelegate : public ValueObjectListDelegate { public: - FrameVariablesWindowDelegate (Debugger &debugger) : - ValueObjectListDelegate (), - m_debugger (debugger), - m_frame_block(nullptr) - { + FrameVariablesWindowDelegate(Debugger &debugger) + : ValueObjectListDelegate(), m_debugger(debugger), + m_frame_block(nullptr) {} + + ~FrameVariablesWindowDelegate() override = default; + + const char *WindowDelegateGetHelpText() override { + return "Frame variable window keyboard shortcuts:"; + } + + bool WindowDelegateDraw(Window &window, bool force) override { + ExecutionContext exe_ctx( + m_debugger.GetCommandInterpreter().GetExecutionContext()); + Process *process = exe_ctx.GetProcessPtr(); + Block *frame_block = nullptr; + StackFrame *frame = nullptr; + + if (process) { + StateType state = process->GetState(); + if (StateIsStoppedState(state, true)) { + frame = exe_ctx.GetFramePtr(); + if (frame) + frame_block = frame->GetFrameBlock(); + } else if (StateIsRunningState(state)) { + return true; // Don't do any updating when we are running + } } - ~FrameVariablesWindowDelegate() override = default; - - const char * - WindowDelegateGetHelpText () override - { - return "Frame variable window keyboard shortcuts:"; - } - - bool - WindowDelegateDraw (Window &window, bool force) override - { - ExecutionContext exe_ctx (m_debugger.GetCommandInterpreter().GetExecutionContext()); - Process *process = exe_ctx.GetProcessPtr(); - Block *frame_block = nullptr; - StackFrame *frame = nullptr; - - if (process) - { - StateType state = process->GetState(); - if (StateIsStoppedState(state, true)) - { - frame = exe_ctx.GetFramePtr(); - if (frame) - frame_block = frame->GetFrameBlock (); - } - else if (StateIsRunningState(state)) - { - return true; // Don't do any updating when we are running + ValueObjectList local_values; + if (frame_block) { + // Only update the variables if they have changed + if (m_frame_block != frame_block) { + m_frame_block = frame_block; + + VariableList *locals = frame->GetVariableList(true); + if (locals) { + const DynamicValueType use_dynamic = eDynamicDontRunTarget; + const size_t num_locals = locals->GetSize(); + for (size_t i = 0; i < num_locals; ++i) { + ValueObjectSP value_sp = frame->GetValueObjectForFrameVariable( + locals->GetVariableAtIndex(i), use_dynamic); + if (value_sp) { + ValueObjectSP synthetic_value_sp = value_sp->GetSyntheticValue(); + if (synthetic_value_sp) + local_values.Append(synthetic_value_sp); + else + local_values.Append(value_sp); } - } - - ValueObjectList local_values; - if (frame_block) - { - // Only update the variables if they have changed - if (m_frame_block != frame_block) - { - m_frame_block = frame_block; - - VariableList *locals = frame->GetVariableList(true); - if (locals) - { - const DynamicValueType use_dynamic = eDynamicDontRunTarget; - const size_t num_locals = locals->GetSize(); - for (size_t i = 0; i < num_locals; ++i) - { - ValueObjectSP value_sp = frame->GetValueObjectForFrameVariable (locals->GetVariableAtIndex(i), use_dynamic); - if (value_sp) - { - ValueObjectSP synthetic_value_sp = value_sp->GetSyntheticValue(); - if (synthetic_value_sp) - local_values.Append(synthetic_value_sp); - else - local_values.Append(value_sp); - } - } - // Update the values - SetValues(local_values); - } - } - } - else - { - m_frame_block = nullptr; - // Update the values with an empty list if there is no frame - SetValues(local_values); - } - - return ValueObjectListDelegate::WindowDelegateDraw (window, force); + } + // Update the values + SetValues(local_values); + } + } + } else { + m_frame_block = nullptr; + // Update the values with an empty list if there is no frame + SetValues(local_values); } + return ValueObjectListDelegate::WindowDelegateDraw(window, force); + } + protected: - Debugger &m_debugger; - Block *m_frame_block; + Debugger &m_debugger; + Block *m_frame_block; }; -class RegistersWindowDelegate : public ValueObjectListDelegate -{ +class RegistersWindowDelegate : public ValueObjectListDelegate { public: - RegistersWindowDelegate (Debugger &debugger) : - ValueObjectListDelegate (), - m_debugger (debugger) - { + RegistersWindowDelegate(Debugger &debugger) + : ValueObjectListDelegate(), m_debugger(debugger) {} + + ~RegistersWindowDelegate() override = default; + + const char *WindowDelegateGetHelpText() override { + return "Register window keyboard shortcuts:"; + } + + bool WindowDelegateDraw(Window &window, bool force) override { + ExecutionContext exe_ctx( + m_debugger.GetCommandInterpreter().GetExecutionContext()); + StackFrame *frame = exe_ctx.GetFramePtr(); + + ValueObjectList value_list; + if (frame) { + if (frame->GetStackID() != m_stack_id) { + m_stack_id = frame->GetStackID(); + RegisterContextSP reg_ctx(frame->GetRegisterContext()); + if (reg_ctx) { + const uint32_t num_sets = reg_ctx->GetRegisterSetCount(); + for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) { + value_list.Append( + ValueObjectRegisterSet::Create(frame, reg_ctx, set_idx)); + } + } + SetValues(value_list); + } + } else { + Process *process = exe_ctx.GetProcessPtr(); + if (process && process->IsAlive()) + return true; // Don't do any updating if we are running + else { + // Update the values with an empty list if there + // is no process or the process isn't alive anymore + SetValues(value_list); + } } + return ValueObjectListDelegate::WindowDelegateDraw(window, force); + } - ~RegistersWindowDelegate() override = default; - - const char * - WindowDelegateGetHelpText () override - { - return "Register window keyboard shortcuts:"; - } - - bool - WindowDelegateDraw (Window &window, bool force) override - { - ExecutionContext exe_ctx (m_debugger.GetCommandInterpreter().GetExecutionContext()); - StackFrame *frame = exe_ctx.GetFramePtr(); - - ValueObjectList value_list; - if (frame) - { - if (frame->GetStackID() != m_stack_id) - { - m_stack_id = frame->GetStackID(); - RegisterContextSP reg_ctx (frame->GetRegisterContext()); - if (reg_ctx) - { - const uint32_t num_sets = reg_ctx->GetRegisterSetCount(); - for (uint32_t set_idx = 0; set_idx < num_sets; ++set_idx) - { - value_list.Append(ValueObjectRegisterSet::Create (frame, reg_ctx, set_idx)); - } - } - SetValues(value_list); - } - } - else - { - Process *process = exe_ctx.GetProcessPtr(); - if (process && process->IsAlive()) - return true; // Don't do any updating if we are running - else - { - // Update the values with an empty list if there - // is no process or the process isn't alive anymore - SetValues(value_list); - } - } - return ValueObjectListDelegate::WindowDelegateDraw (window, force); - } - protected: - Debugger &m_debugger; - StackID m_stack_id; + Debugger &m_debugger; + StackID m_stack_id; }; -static const char * -CursesKeyToCString (int ch) -{ - static char g_desc[32]; - if (ch >= KEY_F0 && ch < KEY_F0 + 64) - { - snprintf(g_desc, sizeof(g_desc), "F%u", ch - KEY_F0); - return g_desc; - } - switch (ch) - { - case KEY_DOWN: return "down"; - case KEY_UP: return "up"; - case KEY_LEFT: return "left"; - case KEY_RIGHT: return "right"; - case KEY_HOME: return "home"; - case KEY_BACKSPACE: return "backspace"; - case KEY_DL: return "delete-line"; - case KEY_IL: return "insert-line"; - case KEY_DC: return "delete-char"; - case KEY_IC: return "insert-char"; - case KEY_CLEAR: return "clear"; - case KEY_EOS: return "clear-to-eos"; - case KEY_EOL: return "clear-to-eol"; - case KEY_SF: return "scroll-forward"; - case KEY_SR: return "scroll-backward"; - case KEY_NPAGE: return "page-down"; - case KEY_PPAGE: return "page-up"; - case KEY_STAB: return "set-tab"; - case KEY_CTAB: return "clear-tab"; - case KEY_CATAB: return "clear-all-tabs"; - case KEY_ENTER: return "enter"; - case KEY_PRINT: return "print"; - case KEY_LL: return "lower-left key"; - case KEY_A1: return "upper left of keypad"; - case KEY_A3: return "upper right of keypad"; - case KEY_B2: return "center of keypad"; - case KEY_C1: return "lower left of keypad"; - case KEY_C3: return "lower right of keypad"; - case KEY_BTAB: return "back-tab key"; - case KEY_BEG: return "begin key"; - case KEY_CANCEL: return "cancel key"; - case KEY_CLOSE: return "close key"; - case KEY_COMMAND: return "command key"; - case KEY_COPY: return "copy key"; - case KEY_CREATE: return "create key"; - case KEY_END: return "end key"; - case KEY_EXIT: return "exit key"; - case KEY_FIND: return "find key"; - case KEY_HELP: return "help key"; - case KEY_MARK: return "mark key"; - case KEY_MESSAGE: return "message key"; - case KEY_MOVE: return "move key"; - case KEY_NEXT: return "next key"; - case KEY_OPEN: return "open key"; - case KEY_OPTIONS: return "options key"; - case KEY_PREVIOUS: return "previous key"; - case KEY_REDO: return "redo key"; - case KEY_REFERENCE: return "reference key"; - case KEY_REFRESH: return "refresh key"; - case KEY_REPLACE: return "replace key"; - case KEY_RESTART: return "restart key"; - case KEY_RESUME: return "resume key"; - case KEY_SAVE: return "save key"; - case KEY_SBEG: return "shifted begin key"; - case KEY_SCANCEL: return "shifted cancel key"; - case KEY_SCOMMAND: return "shifted command key"; - case KEY_SCOPY: return "shifted copy key"; - case KEY_SCREATE: return "shifted create key"; - case KEY_SDC: return "shifted delete-character key"; - case KEY_SDL: return "shifted delete-line key"; - case KEY_SELECT: return "select key"; - case KEY_SEND: return "shifted end key"; - case KEY_SEOL: return "shifted clear-to-end-of-line key"; - case KEY_SEXIT: return "shifted exit key"; - case KEY_SFIND: return "shifted find key"; - case KEY_SHELP: return "shifted help key"; - case KEY_SHOME: return "shifted home key"; - case KEY_SIC: return "shifted insert-character key"; - case KEY_SLEFT: return "shifted left-arrow key"; - case KEY_SMESSAGE: return "shifted message key"; - case KEY_SMOVE: return "shifted move key"; - case KEY_SNEXT: return "shifted next key"; - case KEY_SOPTIONS: return "shifted options key"; - case KEY_SPREVIOUS: return "shifted previous key"; - case KEY_SPRINT: return "shifted print key"; - case KEY_SREDO: return "shifted redo key"; - case KEY_SREPLACE: return "shifted replace key"; - case KEY_SRIGHT: return "shifted right-arrow key"; - case KEY_SRSUME: return "shifted resume key"; - case KEY_SSAVE: return "shifted save key"; - case KEY_SSUSPEND: return "shifted suspend key"; - case KEY_SUNDO: return "shifted undo key"; - case KEY_SUSPEND: return "suspend key"; - case KEY_UNDO: return "undo key"; - case KEY_MOUSE: return "Mouse event has occurred"; - case KEY_RESIZE: return "Terminal resize event"; +static const char *CursesKeyToCString(int ch) { + static char g_desc[32]; + if (ch >= KEY_F0 && ch < KEY_F0 + 64) { + snprintf(g_desc, sizeof(g_desc), "F%u", ch - KEY_F0); + return g_desc; + } + switch (ch) { + case KEY_DOWN: + return "down"; + case KEY_UP: + return "up"; + case KEY_LEFT: + return "left"; + case KEY_RIGHT: + return "right"; + case KEY_HOME: + return "home"; + case KEY_BACKSPACE: + return "backspace"; + case KEY_DL: + return "delete-line"; + case KEY_IL: + return "insert-line"; + case KEY_DC: + return "delete-char"; + case KEY_IC: + return "insert-char"; + case KEY_CLEAR: + return "clear"; + case KEY_EOS: + return "clear-to-eos"; + case KEY_EOL: + return "clear-to-eol"; + case KEY_SF: + return "scroll-forward"; + case KEY_SR: + return "scroll-backward"; + case KEY_NPAGE: + return "page-down"; + case KEY_PPAGE: + return "page-up"; + case KEY_STAB: + return "set-tab"; + case KEY_CTAB: + return "clear-tab"; + case KEY_CATAB: + return "clear-all-tabs"; + case KEY_ENTER: + return "enter"; + case KEY_PRINT: + return "print"; + case KEY_LL: + return "lower-left key"; + case KEY_A1: + return "upper left of keypad"; + case KEY_A3: + return "upper right of keypad"; + case KEY_B2: + return "center of keypad"; + case KEY_C1: + return "lower left of keypad"; + case KEY_C3: + return "lower right of keypad"; + case KEY_BTAB: + return "back-tab key"; + case KEY_BEG: + return "begin key"; + case KEY_CANCEL: + return "cancel key"; + case KEY_CLOSE: + return "close key"; + case KEY_COMMAND: + return "command key"; + case KEY_COPY: + return "copy key"; + case KEY_CREATE: + return "create key"; + case KEY_END: + return "end key"; + case KEY_EXIT: + return "exit key"; + case KEY_FIND: + return "find key"; + case KEY_HELP: + return "help key"; + case KEY_MARK: + return "mark key"; + case KEY_MESSAGE: + return "message key"; + case KEY_MOVE: + return "move key"; + case KEY_NEXT: + return "next key"; + case KEY_OPEN: + return "open key"; + case KEY_OPTIONS: + return "options key"; + case KEY_PREVIOUS: + return "previous key"; + case KEY_REDO: + return "redo key"; + case KEY_REFERENCE: + return "reference key"; + case KEY_REFRESH: + return "refresh key"; + case KEY_REPLACE: + return "replace key"; + case KEY_RESTART: + return "restart key"; + case KEY_RESUME: + return "resume key"; + case KEY_SAVE: + return "save key"; + case KEY_SBEG: + return "shifted begin key"; + case KEY_SCANCEL: + return "shifted cancel key"; + case KEY_SCOMMAND: + return "shifted command key"; + case KEY_SCOPY: + return "shifted copy key"; + case KEY_SCREATE: + return "shifted create key"; + case KEY_SDC: + return "shifted delete-character key"; + case KEY_SDL: + return "shifted delete-line key"; + case KEY_SELECT: + return "select key"; + case KEY_SEND: + return "shifted end key"; + case KEY_SEOL: + return "shifted clear-to-end-of-line key"; + case KEY_SEXIT: + return "shifted exit key"; + case KEY_SFIND: + return "shifted find key"; + case KEY_SHELP: + return "shifted help key"; + case KEY_SHOME: + return "shifted home key"; + case KEY_SIC: + return "shifted insert-character key"; + case KEY_SLEFT: + return "shifted left-arrow key"; + case KEY_SMESSAGE: + return "shifted message key"; + case KEY_SMOVE: + return "shifted move key"; + case KEY_SNEXT: + return "shifted next key"; + case KEY_SOPTIONS: + return "shifted options key"; + case KEY_SPREVIOUS: + return "shifted previous key"; + case KEY_SPRINT: + return "shifted print key"; + case KEY_SREDO: + return "shifted redo key"; + case KEY_SREPLACE: + return "shifted replace key"; + case KEY_SRIGHT: + return "shifted right-arrow key"; + case KEY_SRSUME: + return "shifted resume key"; + case KEY_SSAVE: + return "shifted save key"; + case KEY_SSUSPEND: + return "shifted suspend key"; + case KEY_SUNDO: + return "shifted undo key"; + case KEY_SUSPEND: + return "suspend key"; + case KEY_UNDO: + return "undo key"; + case KEY_MOUSE: + return "Mouse event has occurred"; + case KEY_RESIZE: + return "Terminal resize event"; #ifdef KEY_EVENT - case KEY_EVENT: return "We were interrupted by an event"; + case KEY_EVENT: + return "We were interrupted by an event"; #endif - case KEY_RETURN: return "return"; - case ' ': return "space"; - case '\t': return "tab"; - case KEY_ESCAPE: return "escape"; - default: - if (isprint(ch)) - snprintf(g_desc, sizeof(g_desc), "%c", ch); - else - snprintf(g_desc, sizeof(g_desc), "\\x%2.2x", ch); - return g_desc; - } - return nullptr; + case KEY_RETURN: + return "return"; + case ' ': + return "space"; + case '\t': + return "tab"; + case KEY_ESCAPE: + return "escape"; + default: + if (isprint(ch)) + snprintf(g_desc, sizeof(g_desc), "%c", ch); + else + snprintf(g_desc, sizeof(g_desc), "\\x%2.2x", ch); + return g_desc; + } + return nullptr; } -HelpDialogDelegate::HelpDialogDelegate (const char *text, KeyHelp *key_help_array) : - m_text (), - m_first_visible_line (0) -{ - if (text && text[0]) - { - m_text.SplitIntoLines(text); - m_text.AppendString(""); - } - if (key_help_array) - { - for (KeyHelp *key = key_help_array; key->ch; ++key) - { - StreamString key_description; - key_description.Printf("%10s - %s", CursesKeyToCString(key->ch), key->description); - m_text.AppendString(std::move(key_description.GetString())); - } +HelpDialogDelegate::HelpDialogDelegate(const char *text, + KeyHelp *key_help_array) + : m_text(), m_first_visible_line(0) { + if (text && text[0]) { + m_text.SplitIntoLines(text); + m_text.AppendString(""); + } + if (key_help_array) { + for (KeyHelp *key = key_help_array; key->ch; ++key) { + StreamString key_description; + key_description.Printf("%10s - %s", CursesKeyToCString(key->ch), + key->description); + m_text.AppendString(key_description.GetString()); } + } } HelpDialogDelegate::~HelpDialogDelegate() = default; - -bool -HelpDialogDelegate::WindowDelegateDraw (Window &window, bool force) -{ - window.Erase(); - const int window_height = window.GetHeight(); - int x = 2; - int y = 1; - const int min_y = y; - const int max_y = window_height - 1 - y; - const size_t num_visible_lines = max_y - min_y + 1; - const size_t num_lines = m_text.GetSize(); - const char *bottom_message; - if (num_lines <= num_visible_lines) - bottom_message = "Press any key to exit"; - else - bottom_message = "Use arrows to scroll, any other key to exit"; - window.DrawTitleBox(window.GetName(), bottom_message); - while (y <= max_y) - { - window.MoveCursor(x, y); - window.PutCStringTruncated(m_text.GetStringAtIndex(m_first_visible_line + y - min_y), 1); - ++y; - } - return true; -} - -HandleCharResult -HelpDialogDelegate::WindowDelegateHandleChar (Window &window, int key) -{ - bool done = false; - const size_t num_lines = m_text.GetSize(); - const size_t num_visible_lines = window.GetHeight() - 2; - - if (num_lines <= num_visible_lines) - { - done = true; - // If we have all lines visible and don't need scrolling, then any - // key press will cause us to exit - } - else - { - switch (key) - { - case KEY_UP: - if (m_first_visible_line > 0) - --m_first_visible_line; - break; - case KEY_DOWN: - if (m_first_visible_line + num_visible_lines < num_lines) - ++m_first_visible_line; - break; - - case KEY_PPAGE: - case ',': - if (m_first_visible_line > 0) - { - if (static_cast<size_t>(m_first_visible_line) >= num_visible_lines) - m_first_visible_line -= num_visible_lines; - else - m_first_visible_line = 0; - } - break; - - case KEY_NPAGE: - case '.': - if (m_first_visible_line + num_visible_lines < num_lines) - { - m_first_visible_line += num_visible_lines; - if (static_cast<size_t>(m_first_visible_line) > num_lines) - m_first_visible_line = num_lines - num_visible_lines; - } - break; +bool HelpDialogDelegate::WindowDelegateDraw(Window &window, bool force) { + window.Erase(); + const int window_height = window.GetHeight(); + int x = 2; + int y = 1; + const int min_y = y; + const int max_y = window_height - 1 - y; + const size_t num_visible_lines = max_y - min_y + 1; + const size_t num_lines = m_text.GetSize(); + const char *bottom_message; + if (num_lines <= num_visible_lines) + bottom_message = "Press any key to exit"; + else + bottom_message = "Use arrows to scroll, any other key to exit"; + window.DrawTitleBox(window.GetName(), bottom_message); + while (y <= max_y) { + window.MoveCursor(x, y); + window.PutCStringTruncated( + m_text.GetStringAtIndex(m_first_visible_line + y - min_y), 1); + ++y; + } + return true; +} - default: - done = true; - break; - } +HandleCharResult HelpDialogDelegate::WindowDelegateHandleChar(Window &window, + int key) { + bool done = false; + const size_t num_lines = m_text.GetSize(); + const size_t num_visible_lines = window.GetHeight() - 2; + + if (num_lines <= num_visible_lines) { + done = true; + // If we have all lines visible and don't need scrolling, then any + // key press will cause us to exit + } else { + switch (key) { + case KEY_UP: + if (m_first_visible_line > 0) + --m_first_visible_line; + break; + + case KEY_DOWN: + if (m_first_visible_line + num_visible_lines < num_lines) + ++m_first_visible_line; + break; + + case KEY_PPAGE: + case ',': + if (m_first_visible_line > 0) { + if (static_cast<size_t>(m_first_visible_line) >= num_visible_lines) + m_first_visible_line -= num_visible_lines; + else + m_first_visible_line = 0; + } + break; + + case KEY_NPAGE: + case '.': + if (m_first_visible_line + num_visible_lines < num_lines) { + m_first_visible_line += num_visible_lines; + if (static_cast<size_t>(m_first_visible_line) > num_lines) + m_first_visible_line = num_lines - num_visible_lines; + } + break; + + default: + done = true; + break; } - if (done) - window.GetParent()->RemoveSubWindow(&window); - return eKeyHandled; + } + if (done) + window.GetParent()->RemoveSubWindow(&window); + return eKeyHandled; } -class ApplicationDelegate : - public WindowDelegate, - public MenuDelegate -{ +class ApplicationDelegate : public WindowDelegate, public MenuDelegate { public: - enum { - eMenuID_LLDB = 1, - eMenuID_LLDBAbout, - eMenuID_LLDBExit, - - eMenuID_Target, - eMenuID_TargetCreate, - eMenuID_TargetDelete, - - eMenuID_Process, - eMenuID_ProcessAttach, - eMenuID_ProcessDetach, - eMenuID_ProcessLaunch, - eMenuID_ProcessContinue, - eMenuID_ProcessHalt, - eMenuID_ProcessKill, - - eMenuID_Thread, - eMenuID_ThreadStepIn, - eMenuID_ThreadStepOver, - eMenuID_ThreadStepOut, - - eMenuID_View, - eMenuID_ViewBacktrace, - eMenuID_ViewRegisters, - eMenuID_ViewSource, - eMenuID_ViewVariables, - - eMenuID_Help, - eMenuID_HelpGUIHelp - }; - - ApplicationDelegate (Application &app, Debugger &debugger) : - WindowDelegate (), - MenuDelegate (), - m_app (app), - m_debugger (debugger) - { + enum { + eMenuID_LLDB = 1, + eMenuID_LLDBAbout, + eMenuID_LLDBExit, + + eMenuID_Target, + eMenuID_TargetCreate, + eMenuID_TargetDelete, + + eMenuID_Process, + eMenuID_ProcessAttach, + eMenuID_ProcessDetach, + eMenuID_ProcessLaunch, + eMenuID_ProcessContinue, + eMenuID_ProcessHalt, + eMenuID_ProcessKill, + + eMenuID_Thread, + eMenuID_ThreadStepIn, + eMenuID_ThreadStepOver, + eMenuID_ThreadStepOut, + + eMenuID_View, + eMenuID_ViewBacktrace, + eMenuID_ViewRegisters, + eMenuID_ViewSource, + eMenuID_ViewVariables, + + eMenuID_Help, + eMenuID_HelpGUIHelp + }; + + ApplicationDelegate(Application &app, Debugger &debugger) + : WindowDelegate(), MenuDelegate(), m_app(app), m_debugger(debugger) {} + + ~ApplicationDelegate() override = default; + + bool WindowDelegateDraw(Window &window, bool force) override { + return false; // Drawing not handled, let standard window drawing happen + } + + HandleCharResult WindowDelegateHandleChar(Window &window, int key) override { + switch (key) { + case '\t': + window.SelectNextWindowAsActive(); + return eKeyHandled; + + case 'h': + window.CreateHelpSubwindow(); + return eKeyHandled; + + case KEY_ESCAPE: + return eQuitApplication; + + default: + break; + } + return eKeyNotHandled; + } + + const char *WindowDelegateGetHelpText() override { + return "Welcome to the LLDB curses GUI.\n\n" + "Press the TAB key to change the selected view.\n" + "Each view has its own keyboard shortcuts, press 'h' to open a " + "dialog to display them.\n\n" + "Common key bindings for all views:"; + } + + KeyHelp *WindowDelegateGetKeyHelp() override { + static curses::KeyHelp g_source_view_key_help[] = { + {'\t', "Select next view"}, + {'h', "Show help dialog with view specific key bindings"}, + {',', "Page up"}, + {'.', "Page down"}, + {KEY_UP, "Select previous"}, + {KEY_DOWN, "Select next"}, + {KEY_LEFT, "Unexpand or select parent"}, + {KEY_RIGHT, "Expand"}, + {KEY_PPAGE, "Page up"}, + {KEY_NPAGE, "Page down"}, + {'\0', nullptr}}; + return g_source_view_key_help; + } + + MenuActionResult MenuDelegateAction(Menu &menu) override { + switch (menu.GetIdentifier()) { + case eMenuID_ThreadStepIn: { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + if (exe_ctx.HasThreadScope()) { + Process *process = exe_ctx.GetProcessPtr(); + if (process && process->IsAlive() && + StateIsStoppedState(process->GetState(), true)) + exe_ctx.GetThreadRef().StepIn(true); + } } + return MenuActionResult::Handled; - ~ApplicationDelegate() override = default; + case eMenuID_ThreadStepOut: { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + if (exe_ctx.HasThreadScope()) { + Process *process = exe_ctx.GetProcessPtr(); + if (process && process->IsAlive() && + StateIsStoppedState(process->GetState(), true)) + exe_ctx.GetThreadRef().StepOut(); + } + } + return MenuActionResult::Handled; - bool - WindowDelegateDraw (Window &window, bool force) override - { - return false; // Drawing not handled, let standard window drawing happen + case eMenuID_ThreadStepOver: { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + if (exe_ctx.HasThreadScope()) { + Process *process = exe_ctx.GetProcessPtr(); + if (process && process->IsAlive() && + StateIsStoppedState(process->GetState(), true)) + exe_ctx.GetThreadRef().StepOver(true); + } } - - HandleCharResult - WindowDelegateHandleChar (Window &window, int key) override - { - switch (key) - { - case '\t': - window.SelectNextWindowAsActive(); - return eKeyHandled; + return MenuActionResult::Handled; - case 'h': - window.CreateHelpSubwindow(); - return eKeyHandled; + case eMenuID_ProcessContinue: { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + if (exe_ctx.HasProcessScope()) { + Process *process = exe_ctx.GetProcessPtr(); + if (process && process->IsAlive() && + StateIsStoppedState(process->GetState(), true)) + process->Resume(); + } + } + return MenuActionResult::Handled; - case KEY_ESCAPE: - return eQuitApplication; + case eMenuID_ProcessKill: { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + if (exe_ctx.HasProcessScope()) { + Process *process = exe_ctx.GetProcessPtr(); + if (process && process->IsAlive()) + process->Destroy(false); + } + } + return MenuActionResult::Handled; - default: - break; - } - return eKeyNotHandled; + case eMenuID_ProcessHalt: { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + if (exe_ctx.HasProcessScope()) { + Process *process = exe_ctx.GetProcessPtr(); + if (process && process->IsAlive()) + process->Halt(); + } } + return MenuActionResult::Handled; - const char * - WindowDelegateGetHelpText () override - { - return "Welcome to the LLDB curses GUI.\n\n" - "Press the TAB key to change the selected view.\n" - "Each view has its own keyboard shortcuts, press 'h' to open a dialog to display them.\n\n" - "Common key bindings for all views:"; + case eMenuID_ProcessDetach: { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + if (exe_ctx.HasProcessScope()) { + Process *process = exe_ctx.GetProcessPtr(); + if (process && process->IsAlive()) + process->Detach(false); + } } - - KeyHelp * - WindowDelegateGetKeyHelp () override - { - static curses::KeyHelp g_source_view_key_help[] = { - { '\t', "Select next view" }, - { 'h', "Show help dialog with view specific key bindings" }, - { ',', "Page up" }, - { '.', "Page down" }, - { KEY_UP, "Select previous" }, - { KEY_DOWN, "Select next" }, - { KEY_LEFT, "Unexpand or select parent" }, - { KEY_RIGHT, "Expand" }, - { KEY_PPAGE, "Page up" }, - { KEY_NPAGE, "Page down" }, - { '\0', nullptr } - }; - return g_source_view_key_help; + return MenuActionResult::Handled; + + case eMenuID_Process: { + // Populate the menu with all of the threads if the process is stopped + // when + // the Process menu gets selected and is about to display its submenu. + Menus &submenus = menu.GetSubmenus(); + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + Process *process = exe_ctx.GetProcessPtr(); + if (process && process->IsAlive() && + StateIsStoppedState(process->GetState(), true)) { + if (submenus.size() == 7) + menu.AddSubmenu(MenuSP(new Menu(Menu::Type::Separator))); + else if (submenus.size() > 8) + submenus.erase(submenus.begin() + 8, submenus.end()); + + ThreadList &threads = process->GetThreadList(); + std::lock_guard<std::recursive_mutex> guard(threads.GetMutex()); + size_t num_threads = threads.GetSize(); + for (size_t i = 0; i < num_threads; ++i) { + ThreadSP thread_sp = threads.GetThreadAtIndex(i); + char menu_char = '\0'; + if (i < 9) + menu_char = '1' + i; + StreamString thread_menu_title; + thread_menu_title.Printf("Thread %u", thread_sp->GetIndexID()); + const char *thread_name = thread_sp->GetName(); + if (thread_name && thread_name[0]) + thread_menu_title.Printf(" %s", thread_name); + else { + const char *queue_name = thread_sp->GetQueueName(); + if (queue_name && queue_name[0]) + thread_menu_title.Printf(" %s", queue_name); + } + menu.AddSubmenu( + MenuSP(new Menu(thread_menu_title.GetString().str().c_str(), + nullptr, menu_char, thread_sp->GetID()))); + } + } else if (submenus.size() > 7) { + // Remove the separator and any other thread submenu items + // that were previously added + submenus.erase(submenus.begin() + 7, submenus.end()); + } + // Since we are adding and removing items we need to recalculate the name + // lengths + menu.RecalculateNameLengths(); } - - MenuActionResult - MenuDelegateAction (Menu &menu) override - { - switch (menu.GetIdentifier()) - { - case eMenuID_ThreadStepIn: - { - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - if (exe_ctx.HasThreadScope()) - { - Process *process = exe_ctx.GetProcessPtr(); - if (process && process->IsAlive() && StateIsStoppedState (process->GetState(), true)) - exe_ctx.GetThreadRef().StepIn(true); - } - } - return MenuActionResult::Handled; - - case eMenuID_ThreadStepOut: - { - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - if (exe_ctx.HasThreadScope()) - { - Process *process = exe_ctx.GetProcessPtr(); - if (process && process->IsAlive() && StateIsStoppedState (process->GetState(), true)) - exe_ctx.GetThreadRef().StepOut(); - } - } - return MenuActionResult::Handled; - - case eMenuID_ThreadStepOver: - { - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - if (exe_ctx.HasThreadScope()) - { - Process *process = exe_ctx.GetProcessPtr(); - if (process && process->IsAlive() && StateIsStoppedState (process->GetState(), true)) - exe_ctx.GetThreadRef().StepOver(true); - } - } - return MenuActionResult::Handled; - - case eMenuID_ProcessContinue: - { - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - if (exe_ctx.HasProcessScope()) - { - Process *process = exe_ctx.GetProcessPtr(); - if (process && process->IsAlive() && StateIsStoppedState (process->GetState(), true)) - process->Resume(); - } - } - return MenuActionResult::Handled; - - case eMenuID_ProcessKill: - { - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - if (exe_ctx.HasProcessScope()) - { - Process *process = exe_ctx.GetProcessPtr(); - if (process && process->IsAlive()) - process->Destroy(false); - } - } - return MenuActionResult::Handled; - - case eMenuID_ProcessHalt: - { - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - if (exe_ctx.HasProcessScope()) - { - Process *process = exe_ctx.GetProcessPtr(); - if (process && process->IsAlive()) - process->Halt(); - } - } - return MenuActionResult::Handled; - - case eMenuID_ProcessDetach: - { - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - if (exe_ctx.HasProcessScope()) - { - Process *process = exe_ctx.GetProcessPtr(); - if (process && process->IsAlive()) - process->Detach(false); - } - } - return MenuActionResult::Handled; - - case eMenuID_Process: - { - // Populate the menu with all of the threads if the process is stopped when - // the Process menu gets selected and is about to display its submenu. - Menus &submenus = menu.GetSubmenus(); - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - Process *process = exe_ctx.GetProcessPtr(); - if (process && process->IsAlive() && StateIsStoppedState (process->GetState(), true)) - { - if (submenus.size() == 7) - menu.AddSubmenu (MenuSP (new Menu(Menu::Type::Separator))); - else if (submenus.size() > 8) - submenus.erase (submenus.begin() + 8, submenus.end()); - - ThreadList &threads = process->GetThreadList(); - std::lock_guard<std::recursive_mutex> guard(threads.GetMutex()); - size_t num_threads = threads.GetSize(); - for (size_t i = 0; i < num_threads; ++i) - { - ThreadSP thread_sp = threads.GetThreadAtIndex(i); - char menu_char = '\0'; - if (i < 9) - menu_char = '1' + i; - StreamString thread_menu_title; - thread_menu_title.Printf("Thread %u", thread_sp->GetIndexID()); - const char *thread_name = thread_sp->GetName(); - if (thread_name && thread_name[0]) - thread_menu_title.Printf (" %s", thread_name); - else - { - const char *queue_name = thread_sp->GetQueueName(); - if (queue_name && queue_name[0]) - thread_menu_title.Printf (" %s", queue_name); - } - menu.AddSubmenu(MenuSP(new Menu(thread_menu_title.GetString().c_str(), nullptr, menu_char, thread_sp->GetID()))); - } - } - else if (submenus.size() > 7) - { - // Remove the separator and any other thread submenu items - // that were previously added - submenus.erase (submenus.begin() + 7, submenus.end()); - } - // Since we are adding and removing items we need to recalculate the name lengths - menu.RecalculateNameLengths(); - } - return MenuActionResult::Handled; - - case eMenuID_ViewVariables: - { - WindowSP main_window_sp = m_app.GetMainWindow(); - WindowSP source_window_sp = main_window_sp->FindSubWindow("Source"); - WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables"); - WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers"); - const Rect source_bounds = source_window_sp->GetBounds(); - - if (variables_window_sp) - { - const Rect variables_bounds = variables_window_sp->GetBounds(); - - main_window_sp->RemoveSubWindow(variables_window_sp.get()); - - if (registers_window_sp) - { - // We have a registers window, so give all the area back to the registers window - Rect registers_bounds = variables_bounds; - registers_bounds.size.width = source_bounds.size.width; - registers_window_sp->SetBounds(registers_bounds); - } - else - { - // We have no registers window showing so give the bottom - // area back to the source view - source_window_sp->Resize (source_bounds.size.width, - source_bounds.size.height + variables_bounds.size.height); - } - } - else - { - Rect new_variables_rect; - if (registers_window_sp) - { - // We have a registers window so split the area of the registers - // window into two columns where the left hand side will be the - // variables and the right hand side will be the registers - const Rect variables_bounds = registers_window_sp->GetBounds(); - Rect new_registers_rect; - variables_bounds.VerticalSplitPercentage (0.50, new_variables_rect, new_registers_rect); - registers_window_sp->SetBounds (new_registers_rect); - } - else - { - // No variables window, grab the bottom part of the source window - Rect new_source_rect; - source_bounds.HorizontalSplitPercentage (0.70, new_source_rect, new_variables_rect); - source_window_sp->SetBounds (new_source_rect); - } - WindowSP new_window_sp = main_window_sp->CreateSubWindow ("Variables", - new_variables_rect, - false); - new_window_sp->SetDelegate (WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger))); - } - touchwin(stdscr); - } - return MenuActionResult::Handled; - - case eMenuID_ViewRegisters: - { - WindowSP main_window_sp = m_app.GetMainWindow(); - WindowSP source_window_sp = main_window_sp->FindSubWindow("Source"); - WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables"); - WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers"); - const Rect source_bounds = source_window_sp->GetBounds(); - - if (registers_window_sp) - { - if (variables_window_sp) - { - const Rect variables_bounds = variables_window_sp->GetBounds(); - - // We have a variables window, so give all the area back to the variables window - variables_window_sp->Resize (variables_bounds.size.width + registers_window_sp->GetWidth(), - variables_bounds.size.height); - } - else - { - // We have no variables window showing so give the bottom - // area back to the source view - source_window_sp->Resize (source_bounds.size.width, - source_bounds.size.height + registers_window_sp->GetHeight()); - } - main_window_sp->RemoveSubWindow(registers_window_sp.get()); - } - else - { - Rect new_regs_rect; - if (variables_window_sp) - { - // We have a variables window, split it into two columns - // where the left hand side will be the variables and the - // right hand side will be the registers - const Rect variables_bounds = variables_window_sp->GetBounds(); - Rect new_vars_rect; - variables_bounds.VerticalSplitPercentage (0.50, new_vars_rect, new_regs_rect); - variables_window_sp->SetBounds (new_vars_rect); - } - else - { - // No registers window, grab the bottom part of the source window - Rect new_source_rect; - source_bounds.HorizontalSplitPercentage (0.70, new_source_rect, new_regs_rect); - source_window_sp->SetBounds (new_source_rect); - } - WindowSP new_window_sp = main_window_sp->CreateSubWindow ("Registers", - new_regs_rect, - false); - new_window_sp->SetDelegate (WindowDelegateSP(new RegistersWindowDelegate(m_debugger))); - } - touchwin(stdscr); - } - return MenuActionResult::Handled; - - case eMenuID_HelpGUIHelp: - m_app.GetMainWindow ()->CreateHelpSubwindow(); - return MenuActionResult::Handled; - - default: - break; - } - - return MenuActionResult::NotHandled; + return MenuActionResult::Handled; + + case eMenuID_ViewVariables: { + WindowSP main_window_sp = m_app.GetMainWindow(); + WindowSP source_window_sp = main_window_sp->FindSubWindow("Source"); + WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables"); + WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers"); + const Rect source_bounds = source_window_sp->GetBounds(); + + if (variables_window_sp) { + const Rect variables_bounds = variables_window_sp->GetBounds(); + + main_window_sp->RemoveSubWindow(variables_window_sp.get()); + + if (registers_window_sp) { + // We have a registers window, so give all the area back to the + // registers window + Rect registers_bounds = variables_bounds; + registers_bounds.size.width = source_bounds.size.width; + registers_window_sp->SetBounds(registers_bounds); + } else { + // We have no registers window showing so give the bottom + // area back to the source view + source_window_sp->Resize(source_bounds.size.width, + source_bounds.size.height + + variables_bounds.size.height); + } + } else { + Rect new_variables_rect; + if (registers_window_sp) { + // We have a registers window so split the area of the registers + // window into two columns where the left hand side will be the + // variables and the right hand side will be the registers + const Rect variables_bounds = registers_window_sp->GetBounds(); + Rect new_registers_rect; + variables_bounds.VerticalSplitPercentage(0.50, new_variables_rect, + new_registers_rect); + registers_window_sp->SetBounds(new_registers_rect); + } else { + // No variables window, grab the bottom part of the source window + Rect new_source_rect; + source_bounds.HorizontalSplitPercentage(0.70, new_source_rect, + new_variables_rect); + source_window_sp->SetBounds(new_source_rect); + } + WindowSP new_window_sp = main_window_sp->CreateSubWindow( + "Variables", new_variables_rect, false); + new_window_sp->SetDelegate( + WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger))); + } + touchwin(stdscr); } -protected: - Application &m_app; - Debugger &m_debugger; -}; - -class StatusBarWindowDelegate : public WindowDelegate -{ -public: - StatusBarWindowDelegate (Debugger &debugger) : - m_debugger (debugger) - { - FormatEntity::Parse("Thread: ${thread.id%tid}", - m_format); + return MenuActionResult::Handled; + + case eMenuID_ViewRegisters: { + WindowSP main_window_sp = m_app.GetMainWindow(); + WindowSP source_window_sp = main_window_sp->FindSubWindow("Source"); + WindowSP variables_window_sp = main_window_sp->FindSubWindow("Variables"); + WindowSP registers_window_sp = main_window_sp->FindSubWindow("Registers"); + const Rect source_bounds = source_window_sp->GetBounds(); + + if (registers_window_sp) { + if (variables_window_sp) { + const Rect variables_bounds = variables_window_sp->GetBounds(); + + // We have a variables window, so give all the area back to the + // variables window + variables_window_sp->Resize(variables_bounds.size.width + + registers_window_sp->GetWidth(), + variables_bounds.size.height); + } else { + // We have no variables window showing so give the bottom + // area back to the source view + source_window_sp->Resize(source_bounds.size.width, + source_bounds.size.height + + registers_window_sp->GetHeight()); + } + main_window_sp->RemoveSubWindow(registers_window_sp.get()); + } else { + Rect new_regs_rect; + if (variables_window_sp) { + // We have a variables window, split it into two columns + // where the left hand side will be the variables and the + // right hand side will be the registers + const Rect variables_bounds = variables_window_sp->GetBounds(); + Rect new_vars_rect; + variables_bounds.VerticalSplitPercentage(0.50, new_vars_rect, + new_regs_rect); + variables_window_sp->SetBounds(new_vars_rect); + } else { + // No registers window, grab the bottom part of the source window + Rect new_source_rect; + source_bounds.HorizontalSplitPercentage(0.70, new_source_rect, + new_regs_rect); + source_window_sp->SetBounds(new_source_rect); + } + WindowSP new_window_sp = + main_window_sp->CreateSubWindow("Registers", new_regs_rect, false); + new_window_sp->SetDelegate( + WindowDelegateSP(new RegistersWindowDelegate(m_debugger))); + } + touchwin(stdscr); } + return MenuActionResult::Handled; - ~StatusBarWindowDelegate() override = default; - - bool - WindowDelegateDraw (Window &window, bool force) override - { - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - Process *process = exe_ctx.GetProcessPtr(); - Thread *thread = exe_ctx.GetThreadPtr(); - StackFrame *frame = exe_ctx.GetFramePtr(); - window.Erase(); - window.SetBackground(2); - window.MoveCursor (0, 0); - if (process) - { - const StateType state = process->GetState(); - window.Printf ("Process: %5" PRIu64 " %10s", process->GetID(), StateAsCString(state)); - - if (StateIsStoppedState(state, true)) - { - StreamString strm; - if (thread && FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, nullptr, nullptr, false, false)) - { - window.MoveCursor (40, 0); - window.PutCStringTruncated(strm.GetString().c_str(), 1); - } + case eMenuID_HelpGUIHelp: + m_app.GetMainWindow()->CreateHelpSubwindow(); + return MenuActionResult::Handled; - window.MoveCursor (60, 0); - if (frame) - window.Printf ("Frame: %3u PC = 0x%16.16" PRIx64, frame->GetFrameIndex(), frame->GetFrameCodeAddress().GetOpcodeLoadAddress (exe_ctx.GetTargetPtr())); - } - else if (state == eStateExited) - { - const char *exit_desc = process->GetExitDescription(); - const int exit_status = process->GetExitStatus(); - if (exit_desc && exit_desc[0]) - window.Printf (" with status = %i (%s)", exit_status, exit_desc); - else - window.Printf (" with status = %i", exit_status); - } - } - window.DeferredRefresh(); - return true; + default: + break; } + return MenuActionResult::NotHandled; + } + protected: - Debugger &m_debugger; - FormatEntity::Entry m_format; + Application &m_app; + Debugger &m_debugger; }; -class SourceFileWindowDelegate : public WindowDelegate -{ +class StatusBarWindowDelegate : public WindowDelegate { public: - SourceFileWindowDelegate (Debugger &debugger) : - WindowDelegate (), - m_debugger (debugger), - m_sc (), - m_file_sp (), - m_disassembly_scope(nullptr), - m_disassembly_sp (), - m_disassembly_range (), - m_title (), - m_line_width (4), - m_selected_line (0), - m_pc_line (0), - m_stop_id (0), - m_frame_idx (UINT32_MAX), - m_first_visible_line (0), - m_min_x (0), - m_min_y (0), - m_max_x (0), - m_max_y (0) - { - } - - ~SourceFileWindowDelegate() override = default; - - void - Update (const SymbolContext &sc) - { - m_sc = sc; - } - - uint32_t - NumVisibleLines () const - { - return m_max_y - m_min_y; + StatusBarWindowDelegate(Debugger &debugger) : m_debugger(debugger) { + FormatEntity::Parse("Thread: ${thread.id%tid}", m_format); + } + + ~StatusBarWindowDelegate() override = default; + + bool WindowDelegateDraw(Window &window, bool force) override { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + Process *process = exe_ctx.GetProcessPtr(); + Thread *thread = exe_ctx.GetThreadPtr(); + StackFrame *frame = exe_ctx.GetFramePtr(); + window.Erase(); + window.SetBackground(2); + window.MoveCursor(0, 0); + if (process) { + const StateType state = process->GetState(); + window.Printf("Process: %5" PRIu64 " %10s", process->GetID(), + StateAsCString(state)); + + if (StateIsStoppedState(state, true)) { + StreamString strm; + if (thread && FormatEntity::Format(m_format, strm, nullptr, &exe_ctx, + nullptr, nullptr, false, false)) { + window.MoveCursor(40, 0); + window.PutCStringTruncated(strm.GetString().str().c_str(), 1); + } + + window.MoveCursor(60, 0); + if (frame) + window.Printf("Frame: %3u PC = 0x%16.16" PRIx64, + frame->GetFrameIndex(), + frame->GetFrameCodeAddress().GetOpcodeLoadAddress( + exe_ctx.GetTargetPtr())); + } else if (state == eStateExited) { + const char *exit_desc = process->GetExitDescription(); + const int exit_status = process->GetExitStatus(); + if (exit_desc && exit_desc[0]) + window.Printf(" with status = %i (%s)", exit_status, exit_desc); + else + window.Printf(" with status = %i", exit_status); + } } + window.DeferredRefresh(); + return true; + } - const char * - WindowDelegateGetHelpText () override - { - return "Source/Disassembly window keyboard shortcuts:"; - } +protected: + Debugger &m_debugger; + FormatEntity::Entry m_format; +}; - KeyHelp * - WindowDelegateGetKeyHelp () override - { - static curses::KeyHelp g_source_view_key_help[] = { - { KEY_RETURN, "Run to selected line with one shot breakpoint" }, - { KEY_UP, "Select previous source line" }, - { KEY_DOWN, "Select next source line" }, - { KEY_PPAGE, "Page up" }, - { KEY_NPAGE, "Page down" }, - { 'b', "Set breakpoint on selected source/disassembly line" }, - { 'c', "Continue process" }, - { 'd', "Detach and resume process" }, - { 'D', "Detach with process suspended" }, - { 'h', "Show help dialog" }, - { 'k', "Kill process" }, - { 'n', "Step over (source line)" }, - { 'N', "Step over (single instruction)" }, - { 'o', "Step out" }, - { 's', "Step in (source line)" }, - { 'S', "Step in (single instruction)" }, - { ',', "Page up" }, - { '.', "Page down" }, - { '\0', nullptr } - }; - return g_source_view_key_help; +class SourceFileWindowDelegate : public WindowDelegate { +public: + SourceFileWindowDelegate(Debugger &debugger) + : WindowDelegate(), m_debugger(debugger), m_sc(), m_file_sp(), + m_disassembly_scope(nullptr), m_disassembly_sp(), m_disassembly_range(), + m_title(), m_line_width(4), m_selected_line(0), m_pc_line(0), + m_stop_id(0), m_frame_idx(UINT32_MAX), m_first_visible_line(0), + m_min_x(0), m_min_y(0), m_max_x(0), m_max_y(0) {} + + ~SourceFileWindowDelegate() override = default; + + void Update(const SymbolContext &sc) { m_sc = sc; } + + uint32_t NumVisibleLines() const { return m_max_y - m_min_y; } + + const char *WindowDelegateGetHelpText() override { + return "Source/Disassembly window keyboard shortcuts:"; + } + + KeyHelp *WindowDelegateGetKeyHelp() override { + static curses::KeyHelp g_source_view_key_help[] = { + {KEY_RETURN, "Run to selected line with one shot breakpoint"}, + {KEY_UP, "Select previous source line"}, + {KEY_DOWN, "Select next source line"}, + {KEY_PPAGE, "Page up"}, + {KEY_NPAGE, "Page down"}, + {'b', "Set breakpoint on selected source/disassembly line"}, + {'c', "Continue process"}, + {'d', "Detach and resume process"}, + {'D', "Detach with process suspended"}, + {'h', "Show help dialog"}, + {'k', "Kill process"}, + {'n', "Step over (source line)"}, + {'N', "Step over (single instruction)"}, + {'o', "Step out"}, + {'s', "Step in (source line)"}, + {'S', "Step in (single instruction)"}, + {',', "Page up"}, + {'.', "Page down"}, + {'\0', nullptr}}; + return g_source_view_key_help; + } + + bool WindowDelegateDraw(Window &window, bool force) override { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + Process *process = exe_ctx.GetProcessPtr(); + Thread *thread = nullptr; + + bool update_location = false; + if (process) { + StateType state = process->GetState(); + if (StateIsStoppedState(state, true)) { + // We are stopped, so it is ok to + update_location = true; + } } - bool - WindowDelegateDraw (Window &window, bool force) override - { - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - Process *process = exe_ctx.GetProcessPtr(); - Thread *thread = nullptr; - - bool update_location = false; - if (process) - { - StateType state = process->GetState(); - if (StateIsStoppedState(state, true)) - { - // We are stopped, so it is ok to - update_location = true; + m_min_x = 1; + m_min_y = 2; + m_max_x = window.GetMaxX() - 1; + m_max_y = window.GetMaxY() - 1; + + const uint32_t num_visible_lines = NumVisibleLines(); + StackFrameSP frame_sp; + bool set_selected_line_to_pc = false; + + if (update_location) { + const bool process_alive = process ? process->IsAlive() : false; + bool thread_changed = false; + if (process_alive) { + thread = exe_ctx.GetThreadPtr(); + if (thread) { + frame_sp = thread->GetSelectedFrame(); + auto tid = thread->GetID(); + thread_changed = tid != m_tid; + m_tid = tid; + } else { + if (m_tid != LLDB_INVALID_THREAD_ID) { + thread_changed = true; + m_tid = LLDB_INVALID_THREAD_ID; + } + } + } + const uint32_t stop_id = process ? process->GetStopID() : 0; + const bool stop_id_changed = stop_id != m_stop_id; + bool frame_changed = false; + m_stop_id = stop_id; + m_title.Clear(); + if (frame_sp) { + m_sc = frame_sp->GetSymbolContext(eSymbolContextEverything); + if (m_sc.module_sp) { + m_title.Printf( + "%s", m_sc.module_sp->GetFileSpec().GetFilename().GetCString()); + ConstString func_name = m_sc.GetFunctionName(); + if (func_name) + m_title.Printf("`%s", func_name.GetCString()); + } + const uint32_t frame_idx = frame_sp->GetFrameIndex(); + frame_changed = frame_idx != m_frame_idx; + m_frame_idx = frame_idx; + } else { + m_sc.Clear(true); + frame_changed = m_frame_idx != UINT32_MAX; + m_frame_idx = UINT32_MAX; + } + + const bool context_changed = + thread_changed || frame_changed || stop_id_changed; + + if (process_alive) { + if (m_sc.line_entry.IsValid()) { + m_pc_line = m_sc.line_entry.line; + if (m_pc_line != UINT32_MAX) + --m_pc_line; // Convert to zero based line number... + // Update the selected line if the stop ID changed... + if (context_changed) + m_selected_line = m_pc_line; + + if (m_file_sp && m_file_sp->FileSpecMatches(m_sc.line_entry.file)) { + // Same file, nothing to do, we should either have the + // lines or not (source file missing) + if (m_selected_line >= static_cast<size_t>(m_first_visible_line)) { + if (m_selected_line >= m_first_visible_line + num_visible_lines) + m_first_visible_line = m_selected_line - 10; + } else { + if (m_selected_line > 10) + m_first_visible_line = m_selected_line - 10; + else + m_first_visible_line = 0; } - } - - m_min_x = 1; - m_min_y = 2; - m_max_x = window.GetMaxX()-1; - m_max_y = window.GetMaxY()-1; - - const uint32_t num_visible_lines = NumVisibleLines(); - StackFrameSP frame_sp; - bool set_selected_line_to_pc = false; - - if (update_location) - { - const bool process_alive = process ? process->IsAlive() : false; - bool thread_changed = false; - if (process_alive) - { - thread = exe_ctx.GetThreadPtr(); - if (thread) - { - frame_sp = thread->GetSelectedFrame(); - auto tid = thread->GetID(); - thread_changed = tid != m_tid; - m_tid = tid; - } - else - { - if (m_tid != LLDB_INVALID_THREAD_ID) - { - thread_changed = true; - m_tid = LLDB_INVALID_THREAD_ID; - } - } + } else { + // File changed, set selected line to the line with the PC + m_selected_line = m_pc_line; + m_file_sp = + m_debugger.GetSourceManager().GetFile(m_sc.line_entry.file); + if (m_file_sp) { + const size_t num_lines = m_file_sp->GetNumLines(); + int m_line_width = 1; + for (size_t n = num_lines; n >= 10; n = n / 10) + ++m_line_width; + + snprintf(m_line_format, sizeof(m_line_format), " %%%iu ", + m_line_width); + if (num_lines < num_visible_lines || + m_selected_line < num_visible_lines) + m_first_visible_line = 0; + else + m_first_visible_line = m_selected_line - 10; } - const uint32_t stop_id = process ? process->GetStopID() : 0; - const bool stop_id_changed = stop_id != m_stop_id; - bool frame_changed = false; - m_stop_id = stop_id; - m_title.Clear(); - if (frame_sp) - { - m_sc = frame_sp->GetSymbolContext(eSymbolContextEverything); - if (m_sc.module_sp) - { - m_title.Printf("%s", m_sc.module_sp->GetFileSpec().GetFilename().GetCString()); - ConstString func_name = m_sc.GetFunctionName(); - if (func_name) - m_title.Printf("`%s", func_name.GetCString()); - } - const uint32_t frame_idx = frame_sp->GetFrameIndex(); - frame_changed = frame_idx != m_frame_idx; - m_frame_idx = frame_idx; + } + } else { + m_file_sp.reset(); + } + + if (!m_file_sp || m_file_sp->GetNumLines() == 0) { + // Show disassembly + bool prefer_file_cache = false; + if (m_sc.function) { + if (m_disassembly_scope != m_sc.function) { + m_disassembly_scope = m_sc.function; + m_disassembly_sp = m_sc.function->GetInstructions( + exe_ctx, nullptr, prefer_file_cache); + if (m_disassembly_sp) { + set_selected_line_to_pc = true; + m_disassembly_range = m_sc.function->GetAddressRange(); + } else { + m_disassembly_range.Clear(); + } + } else { + set_selected_line_to_pc = context_changed; } - else - { - m_sc.Clear(true); - frame_changed = m_frame_idx != UINT32_MAX; - m_frame_idx = UINT32_MAX; + } else if (m_sc.symbol) { + if (m_disassembly_scope != m_sc.symbol) { + m_disassembly_scope = m_sc.symbol; + m_disassembly_sp = m_sc.symbol->GetInstructions( + exe_ctx, nullptr, prefer_file_cache); + if (m_disassembly_sp) { + set_selected_line_to_pc = true; + m_disassembly_range.GetBaseAddress() = + m_sc.symbol->GetAddress(); + m_disassembly_range.SetByteSize(m_sc.symbol->GetByteSize()); + } else { + m_disassembly_range.Clear(); + } + } else { + set_selected_line_to_pc = context_changed; } + } + } + } else { + m_pc_line = UINT32_MAX; + } + } - const bool context_changed = thread_changed || frame_changed || stop_id_changed; - - if (process_alive) - { - if (m_sc.line_entry.IsValid()) - { - m_pc_line = m_sc.line_entry.line; - if (m_pc_line != UINT32_MAX) - --m_pc_line; // Convert to zero based line number... - // Update the selected line if the stop ID changed... - if (context_changed) - m_selected_line = m_pc_line; - - if (m_file_sp && m_file_sp->FileSpecMatches(m_sc.line_entry.file)) - { - // Same file, nothing to do, we should either have the - // lines or not (source file missing) - if (m_selected_line >= static_cast<size_t>(m_first_visible_line)) - { - if (m_selected_line >= m_first_visible_line + num_visible_lines) - m_first_visible_line = m_selected_line - 10; - } - else - { - if (m_selected_line > 10) - m_first_visible_line = m_selected_line - 10; - else - m_first_visible_line = 0; - } - } - else - { - // File changed, set selected line to the line with the PC - m_selected_line = m_pc_line; - m_file_sp = m_debugger.GetSourceManager().GetFile(m_sc.line_entry.file); - if (m_file_sp) - { - const size_t num_lines = m_file_sp->GetNumLines(); - int m_line_width = 1; - for (size_t n = num_lines; n >= 10; n = n / 10) - ++m_line_width; - - snprintf (m_line_format, sizeof(m_line_format), " %%%iu ", m_line_width); - if (num_lines < num_visible_lines || m_selected_line < num_visible_lines) - m_first_visible_line = 0; - else - m_first_visible_line = m_selected_line - 10; - } - } - } - else - { - m_file_sp.reset(); - } + const int window_width = window.GetWidth(); + window.Erase(); + window.DrawTitleBox("Sources"); + if (!m_title.GetString().empty()) { + window.AttributeOn(A_REVERSE); + window.MoveCursor(1, 1); + window.PutChar(' '); + window.PutCStringTruncated(m_title.GetString().str().c_str(), 1); + int x = window.GetCursorX(); + if (x < window_width - 1) { + window.Printf("%*s", window_width - x - 1, ""); + } + window.AttributeOff(A_REVERSE); + } - if (!m_file_sp || m_file_sp->GetNumLines() == 0) - { - // Show disassembly - bool prefer_file_cache = false; - if (m_sc.function) - { - if (m_disassembly_scope != m_sc.function) - { - m_disassembly_scope = m_sc.function; - m_disassembly_sp = m_sc.function->GetInstructions(exe_ctx, nullptr, prefer_file_cache); - if (m_disassembly_sp) - { - set_selected_line_to_pc = true; - m_disassembly_range = m_sc.function->GetAddressRange(); - } - else - { - m_disassembly_range.Clear(); - } - } - else - { - set_selected_line_to_pc = context_changed; - } - } - else if (m_sc.symbol) - { - if (m_disassembly_scope != m_sc.symbol) - { - m_disassembly_scope = m_sc.symbol; - m_disassembly_sp = m_sc.symbol->GetInstructions(exe_ctx, nullptr, prefer_file_cache); - if (m_disassembly_sp) - { - set_selected_line_to_pc = true; - m_disassembly_range.GetBaseAddress() = m_sc.symbol->GetAddress(); - m_disassembly_range.SetByteSize(m_sc.symbol->GetByteSize()); - } - else - { - m_disassembly_range.Clear(); - } - } - else - { - set_selected_line_to_pc = context_changed; - } - } - } + Target *target = exe_ctx.GetTargetPtr(); + const size_t num_source_lines = GetNumSourceLines(); + if (num_source_lines > 0) { + // Display source + BreakpointLines bp_lines; + if (target) { + BreakpointList &bp_list = target->GetBreakpointList(); + const size_t num_bps = bp_list.GetSize(); + for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) { + BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx); + const size_t num_bps_locs = bp_sp->GetNumLocations(); + for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs; ++bp_loc_idx) { + BreakpointLocationSP bp_loc_sp = + bp_sp->GetLocationAtIndex(bp_loc_idx); + LineEntry bp_loc_line_entry; + if (bp_loc_sp->GetAddress().CalculateSymbolContextLineEntry( + bp_loc_line_entry)) { + if (m_file_sp->GetFileSpec() == bp_loc_line_entry.file) { + bp_lines.insert(bp_loc_line_entry.line); + } } - else - { - m_pc_line = UINT32_MAX; - } - } - - const int window_width = window.GetWidth(); - window.Erase(); - window.DrawTitleBox ("Sources"); - if (!m_title.GetString().empty()) - { - window.AttributeOn(A_REVERSE); - window.MoveCursor(1, 1); + } + } + } + + const attr_t selected_highlight_attr = A_REVERSE; + const attr_t pc_highlight_attr = COLOR_PAIR(1); + + for (size_t i = 0; i < num_visible_lines; ++i) { + const uint32_t curr_line = m_first_visible_line + i; + if (curr_line < num_source_lines) { + const int line_y = m_min_y + i; + window.MoveCursor(1, line_y); + const bool is_pc_line = curr_line == m_pc_line; + const bool line_is_selected = m_selected_line == curr_line; + // Highlight the line as the PC line first, then if the selected line + // isn't the same as the PC line, highlight it differently + attr_t highlight_attr = 0; + attr_t bp_attr = 0; + if (is_pc_line) + highlight_attr = pc_highlight_attr; + else if (line_is_selected) + highlight_attr = selected_highlight_attr; + + if (bp_lines.find(curr_line + 1) != bp_lines.end()) + bp_attr = COLOR_PAIR(2); + + if (bp_attr) + window.AttributeOn(bp_attr); + + window.Printf(m_line_format, curr_line + 1); + + if (bp_attr) + window.AttributeOff(bp_attr); + + window.PutChar(ACS_VLINE); + // Mark the line with the PC with a diamond + if (is_pc_line) + window.PutChar(ACS_DIAMOND); + else window.PutChar(' '); - window.PutCStringTruncated(m_title.GetString().c_str(), 1); - int x = window.GetCursorX(); - if (x < window_width - 1) - { - window.Printf ("%*s", window_width - x - 1, ""); - } - window.AttributeOff(A_REVERSE); - } - Target *target = exe_ctx.GetTargetPtr(); - const size_t num_source_lines = GetNumSourceLines(); - if (num_source_lines > 0) - { - // Display source - BreakpointLines bp_lines; - if (target) - { - BreakpointList &bp_list = target->GetBreakpointList(); - const size_t num_bps = bp_list.GetSize(); - for (size_t bp_idx=0; bp_idx<num_bps; ++bp_idx) - { - BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx); - const size_t num_bps_locs = bp_sp->GetNumLocations(); - for (size_t bp_loc_idx=0; bp_loc_idx<num_bps_locs; ++bp_loc_idx) - { - BreakpointLocationSP bp_loc_sp = bp_sp->GetLocationAtIndex(bp_loc_idx); - LineEntry bp_loc_line_entry; - if (bp_loc_sp->GetAddress().CalculateSymbolContextLineEntry (bp_loc_line_entry)) - { - if (m_file_sp->GetFileSpec() == bp_loc_line_entry.file) - { - bp_lines.insert(bp_loc_line_entry.line); - } - } - } - } + if (highlight_attr) + window.AttributeOn(highlight_attr); + const uint32_t line_len = + m_file_sp->GetLineLength(curr_line + 1, false); + if (line_len > 0) + window.PutCString(m_file_sp->PeekLineData(curr_line + 1), line_len); + + if (is_pc_line && frame_sp && + frame_sp->GetConcreteFrameIndex() == 0) { + StopInfoSP stop_info_sp; + if (thread) + stop_info_sp = thread->GetStopInfo(); + if (stop_info_sp) { + const char *stop_description = stop_info_sp->GetDescription(); + if (stop_description && stop_description[0]) { + size_t stop_description_len = strlen(stop_description); + int desc_x = window_width - stop_description_len - 16; + window.Printf("%*s", desc_x - window.GetCursorX(), ""); + // window.MoveCursor(window_width - stop_description_len - 15, + // line_y); + window.Printf("<<< Thread %u: %s ", thread->GetIndexID(), + stop_description); + } + } else { + window.Printf("%*s", window_width - window.GetCursorX() - 1, ""); } - - const attr_t selected_highlight_attr = A_REVERSE; - const attr_t pc_highlight_attr = COLOR_PAIR(1); - - for (size_t i = 0; i < num_visible_lines; ++i) - { - const uint32_t curr_line = m_first_visible_line + i; - if (curr_line < num_source_lines) - { - const int line_y = m_min_y+i; - window.MoveCursor(1, line_y); - const bool is_pc_line = curr_line == m_pc_line; - const bool line_is_selected = m_selected_line == curr_line; - // Highlight the line as the PC line first, then if the selected line - // isn't the same as the PC line, highlight it differently - attr_t highlight_attr = 0; - attr_t bp_attr = 0; - if (is_pc_line) - highlight_attr = pc_highlight_attr; - else if (line_is_selected) - highlight_attr = selected_highlight_attr; - - if (bp_lines.find(curr_line+1) != bp_lines.end()) - bp_attr = COLOR_PAIR(2); - - if (bp_attr) - window.AttributeOn(bp_attr); - - window.Printf (m_line_format, curr_line + 1); - - if (bp_attr) - window.AttributeOff(bp_attr); - - window.PutChar(ACS_VLINE); - // Mark the line with the PC with a diamond - if (is_pc_line) - window.PutChar(ACS_DIAMOND); - else - window.PutChar(' '); - - if (highlight_attr) - window.AttributeOn(highlight_attr); - const uint32_t line_len = m_file_sp->GetLineLength(curr_line + 1, false); - if (line_len > 0) - window.PutCString(m_file_sp->PeekLineData(curr_line + 1), line_len); - - if (is_pc_line && frame_sp && frame_sp->GetConcreteFrameIndex() == 0) - { - StopInfoSP stop_info_sp; - if (thread) - stop_info_sp = thread->GetStopInfo(); - if (stop_info_sp) - { - const char *stop_description = stop_info_sp->GetDescription(); - if (stop_description && stop_description[0]) - { - size_t stop_description_len = strlen(stop_description); - int desc_x = window_width - stop_description_len - 16; - window.Printf ("%*s", desc_x - window.GetCursorX(), ""); - //window.MoveCursor(window_width - stop_description_len - 15, line_y); - window.Printf ("<<< Thread %u: %s ", thread->GetIndexID(), stop_description); - } - } - else - { - window.Printf ("%*s", window_width - window.GetCursorX() - 1, ""); - } - } - if (highlight_attr) - window.AttributeOff(highlight_attr); - } - else - { - break; - } + } + if (highlight_attr) + window.AttributeOff(highlight_attr); + } else { + break; + } + } + } else { + size_t num_disassembly_lines = GetNumDisassemblyLines(); + if (num_disassembly_lines > 0) { + // Display disassembly + BreakpointAddrs bp_file_addrs; + Target *target = exe_ctx.GetTargetPtr(); + if (target) { + BreakpointList &bp_list = target->GetBreakpointList(); + const size_t num_bps = bp_list.GetSize(); + for (size_t bp_idx = 0; bp_idx < num_bps; ++bp_idx) { + BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx); + const size_t num_bps_locs = bp_sp->GetNumLocations(); + for (size_t bp_loc_idx = 0; bp_loc_idx < num_bps_locs; + ++bp_loc_idx) { + BreakpointLocationSP bp_loc_sp = + bp_sp->GetLocationAtIndex(bp_loc_idx); + LineEntry bp_loc_line_entry; + const lldb::addr_t file_addr = + bp_loc_sp->GetAddress().GetFileAddress(); + if (file_addr != LLDB_INVALID_ADDRESS) { + if (m_disassembly_range.ContainsFileAddress(file_addr)) + bp_file_addrs.insert(file_addr); + } } + } } - else - { - size_t num_disassembly_lines = GetNumDisassemblyLines(); - if (num_disassembly_lines > 0) - { - // Display disassembly - BreakpointAddrs bp_file_addrs; - Target *target = exe_ctx.GetTargetPtr(); - if (target) - { - BreakpointList &bp_list = target->GetBreakpointList(); - const size_t num_bps = bp_list.GetSize(); - for (size_t bp_idx=0; bp_idx<num_bps; ++bp_idx) - { - BreakpointSP bp_sp = bp_list.GetBreakpointAtIndex(bp_idx); - const size_t num_bps_locs = bp_sp->GetNumLocations(); - for (size_t bp_loc_idx=0; bp_loc_idx<num_bps_locs; ++bp_loc_idx) - { - BreakpointLocationSP bp_loc_sp = bp_sp->GetLocationAtIndex(bp_loc_idx); - LineEntry bp_loc_line_entry; - const lldb::addr_t file_addr = bp_loc_sp->GetAddress().GetFileAddress(); - if (file_addr != LLDB_INVALID_ADDRESS) - { - if (m_disassembly_range.ContainsFileAddress(file_addr)) - bp_file_addrs.insert(file_addr); - } - } - } - } - const attr_t selected_highlight_attr = A_REVERSE; - const attr_t pc_highlight_attr = COLOR_PAIR(1); + const attr_t selected_highlight_attr = A_REVERSE; + const attr_t pc_highlight_attr = COLOR_PAIR(1); - StreamString strm; + StreamString strm; - InstructionList &insts = m_disassembly_sp->GetInstructionList(); - Address pc_address; + InstructionList &insts = m_disassembly_sp->GetInstructionList(); + Address pc_address; - if (frame_sp) - pc_address = frame_sp->GetFrameCodeAddress(); - const uint32_t pc_idx = pc_address.IsValid() ? insts.GetIndexOfInstructionAtAddress (pc_address) : UINT32_MAX; - if (set_selected_line_to_pc) - { - m_selected_line = pc_idx; - } + if (frame_sp) + pc_address = frame_sp->GetFrameCodeAddress(); + const uint32_t pc_idx = + pc_address.IsValid() + ? insts.GetIndexOfInstructionAtAddress(pc_address) + : UINT32_MAX; + if (set_selected_line_to_pc) { + m_selected_line = pc_idx; + } - const uint32_t non_visible_pc_offset = (num_visible_lines / 5); - if (static_cast<size_t>(m_first_visible_line) >= num_disassembly_lines) - m_first_visible_line = 0; + const uint32_t non_visible_pc_offset = (num_visible_lines / 5); + if (static_cast<size_t>(m_first_visible_line) >= num_disassembly_lines) + m_first_visible_line = 0; - if (pc_idx < num_disassembly_lines) - { - if (pc_idx < static_cast<uint32_t>(m_first_visible_line) || - pc_idx >= m_first_visible_line + num_visible_lines) - m_first_visible_line = pc_idx - non_visible_pc_offset; - } + if (pc_idx < num_disassembly_lines) { + if (pc_idx < static_cast<uint32_t>(m_first_visible_line) || + pc_idx >= m_first_visible_line + num_visible_lines) + m_first_visible_line = pc_idx - non_visible_pc_offset; + } - for (size_t i = 0; i < num_visible_lines; ++i) - { - const uint32_t inst_idx = m_first_visible_line + i; - Instruction *inst = insts.GetInstructionAtIndex(inst_idx).get(); - if (!inst) - break; - - const int line_y = m_min_y+i; - window.MoveCursor(1, line_y); - const bool is_pc_line = frame_sp && inst_idx == pc_idx; - const bool line_is_selected = m_selected_line == inst_idx; - // Highlight the line as the PC line first, then if the selected line - // isn't the same as the PC line, highlight it differently - attr_t highlight_attr = 0; - attr_t bp_attr = 0; - if (is_pc_line) - highlight_attr = pc_highlight_attr; - else if (line_is_selected) - highlight_attr = selected_highlight_attr; - - if (bp_file_addrs.find(inst->GetAddress().GetFileAddress()) != bp_file_addrs.end()) - bp_attr = COLOR_PAIR(2); - - if (bp_attr) - window.AttributeOn(bp_attr); - - window.Printf (" 0x%16.16llx ", - static_cast<unsigned long long>(inst->GetAddress().GetLoadAddress(target))); - - if (bp_attr) - window.AttributeOff(bp_attr); - - window.PutChar(ACS_VLINE); - // Mark the line with the PC with a diamond - if (is_pc_line) - window.PutChar(ACS_DIAMOND); - else - window.PutChar(' '); - - if (highlight_attr) - window.AttributeOn(highlight_attr); - - const char *mnemonic = inst->GetMnemonic(&exe_ctx); - const char *operands = inst->GetOperands(&exe_ctx); - const char *comment = inst->GetComment(&exe_ctx); - - if (mnemonic != nullptr && mnemonic[0] == '\0') - mnemonic = nullptr; - if (operands != nullptr && operands[0] == '\0') - operands = nullptr; - if (comment != nullptr && comment[0] == '\0') - comment = nullptr; - - strm.Clear(); - - if (mnemonic != nullptr && operands != nullptr && comment != nullptr) - strm.Printf ("%-8s %-25s ; %s", mnemonic, operands, comment); - else if (mnemonic != nullptr && operands != nullptr) - strm.Printf ("%-8s %s", mnemonic, operands); - else if (mnemonic != nullptr) - strm.Printf ("%s", mnemonic); - - int right_pad = 1; - window.PutCStringTruncated(strm.GetString().c_str(), right_pad); - - if (is_pc_line && frame_sp && frame_sp->GetConcreteFrameIndex() == 0) - { - StopInfoSP stop_info_sp; - if (thread) - stop_info_sp = thread->GetStopInfo(); - if (stop_info_sp) - { - const char *stop_description = stop_info_sp->GetDescription(); - if (stop_description && stop_description[0]) - { - size_t stop_description_len = strlen(stop_description); - int desc_x = window_width - stop_description_len - 16; - window.Printf ("%*s", desc_x - window.GetCursorX(), ""); - //window.MoveCursor(window_width - stop_description_len - 15, line_y); - window.Printf ("<<< Thread %u: %s ", thread->GetIndexID(), stop_description); - } - } - else - { - window.Printf ("%*s", window_width - window.GetCursorX() - 1, ""); - } - } - if (highlight_attr) - window.AttributeOff(highlight_attr); - } + for (size_t i = 0; i < num_visible_lines; ++i) { + const uint32_t inst_idx = m_first_visible_line + i; + Instruction *inst = insts.GetInstructionAtIndex(inst_idx).get(); + if (!inst) + break; + + const int line_y = m_min_y + i; + window.MoveCursor(1, line_y); + const bool is_pc_line = frame_sp && inst_idx == pc_idx; + const bool line_is_selected = m_selected_line == inst_idx; + // Highlight the line as the PC line first, then if the selected line + // isn't the same as the PC line, highlight it differently + attr_t highlight_attr = 0; + attr_t bp_attr = 0; + if (is_pc_line) + highlight_attr = pc_highlight_attr; + else if (line_is_selected) + highlight_attr = selected_highlight_attr; + + if (bp_file_addrs.find(inst->GetAddress().GetFileAddress()) != + bp_file_addrs.end()) + bp_attr = COLOR_PAIR(2); + + if (bp_attr) + window.AttributeOn(bp_attr); + + window.Printf(" 0x%16.16llx ", + static_cast<unsigned long long>( + inst->GetAddress().GetLoadAddress(target))); + + if (bp_attr) + window.AttributeOff(bp_attr); + + window.PutChar(ACS_VLINE); + // Mark the line with the PC with a diamond + if (is_pc_line) + window.PutChar(ACS_DIAMOND); + else + window.PutChar(' '); + + if (highlight_attr) + window.AttributeOn(highlight_attr); + + const char *mnemonic = inst->GetMnemonic(&exe_ctx); + const char *operands = inst->GetOperands(&exe_ctx); + const char *comment = inst->GetComment(&exe_ctx); + + if (mnemonic != nullptr && mnemonic[0] == '\0') + mnemonic = nullptr; + if (operands != nullptr && operands[0] == '\0') + operands = nullptr; + if (comment != nullptr && comment[0] == '\0') + comment = nullptr; + + strm.Clear(); + + if (mnemonic != nullptr && operands != nullptr && comment != nullptr) + strm.Printf("%-8s %-25s ; %s", mnemonic, operands, comment); + else if (mnemonic != nullptr && operands != nullptr) + strm.Printf("%-8s %s", mnemonic, operands); + else if (mnemonic != nullptr) + strm.Printf("%s", mnemonic); + + int right_pad = 1; + window.PutCStringTruncated(strm.GetData(), right_pad); + + if (is_pc_line && frame_sp && + frame_sp->GetConcreteFrameIndex() == 0) { + StopInfoSP stop_info_sp; + if (thread) + stop_info_sp = thread->GetStopInfo(); + if (stop_info_sp) { + const char *stop_description = stop_info_sp->GetDescription(); + if (stop_description && stop_description[0]) { + size_t stop_description_len = strlen(stop_description); + int desc_x = window_width - stop_description_len - 16; + window.Printf("%*s", desc_x - window.GetCursorX(), ""); + // window.MoveCursor(window_width - stop_description_len - 15, + // line_y); + window.Printf("<<< Thread %u: %s ", thread->GetIndexID(), + stop_description); + } + } else { + window.Printf("%*s", window_width - window.GetCursorX() - 1, ""); } + } + if (highlight_attr) + window.AttributeOff(highlight_attr); } - window.DeferredRefresh(); - return true; // Drawing handled + } } + window.DeferredRefresh(); + return true; // Drawing handled + } + + size_t GetNumLines() { + size_t num_lines = GetNumSourceLines(); + if (num_lines == 0) + num_lines = GetNumDisassemblyLines(); + return num_lines; + } + + size_t GetNumSourceLines() const { + if (m_file_sp) + return m_file_sp->GetNumLines(); + return 0; + } - size_t - GetNumLines () - { - size_t num_lines = GetNumSourceLines(); - if (num_lines == 0) - num_lines = GetNumDisassemblyLines(); - return num_lines; + size_t GetNumDisassemblyLines() const { + if (m_disassembly_sp) + return m_disassembly_sp->GetInstructionList().GetSize(); + return 0; + } + + HandleCharResult WindowDelegateHandleChar(Window &window, int c) override { + const uint32_t num_visible_lines = NumVisibleLines(); + const size_t num_lines = GetNumLines(); + + switch (c) { + case ',': + case KEY_PPAGE: + // Page up key + if (static_cast<uint32_t>(m_first_visible_line) > num_visible_lines) + m_first_visible_line -= num_visible_lines; + else + m_first_visible_line = 0; + m_selected_line = m_first_visible_line; + return eKeyHandled; + + case '.': + case KEY_NPAGE: + // Page down key + { + if (m_first_visible_line + num_visible_lines < num_lines) + m_first_visible_line += num_visible_lines; + else if (num_lines < num_visible_lines) + m_first_visible_line = 0; + else + m_first_visible_line = num_lines - num_visible_lines; + m_selected_line = m_first_visible_line; + } + return eKeyHandled; + + case KEY_UP: + if (m_selected_line > 0) { + m_selected_line--; + if (static_cast<size_t>(m_first_visible_line) > m_selected_line) + m_first_visible_line = m_selected_line; + } + return eKeyHandled; + + case KEY_DOWN: + if (m_selected_line + 1 < num_lines) { + m_selected_line++; + if (m_first_visible_line + num_visible_lines < m_selected_line) + m_first_visible_line++; + } + return eKeyHandled; + + case '\r': + case '\n': + case KEY_ENTER: + // Set a breakpoint and run to the line using a one shot breakpoint + if (GetNumSourceLines() > 0) { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + if (exe_ctx.HasProcessScope() && exe_ctx.GetProcessRef().IsAlive()) { + BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint( + nullptr, // Don't limit the breakpoint to certain modules + m_file_sp->GetFileSpec(), // Source file + m_selected_line + + 1, // Source line number (m_selected_line is zero based) + 0, // No offset + eLazyBoolCalculate, // Check inlines using global setting + eLazyBoolCalculate, // Skip prologue using global setting, + false, // internal + false, // request_hardware + eLazyBoolCalculate); // move_to_nearest_code + // Make breakpoint one shot + bp_sp->GetOptions()->SetOneShot(true); + exe_ctx.GetProcessRef().Resume(); + } + } else if (m_selected_line < GetNumDisassemblyLines()) { + const Instruction *inst = m_disassembly_sp->GetInstructionList() + .GetInstructionAtIndex(m_selected_line) + .get(); + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + if (exe_ctx.HasTargetScope()) { + Address addr = inst->GetAddress(); + BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint( + addr, // lldb_private::Address + false, // internal + false); // request_hardware + // Make breakpoint one shot + bp_sp->GetOptions()->SetOneShot(true); + exe_ctx.GetProcessRef().Resume(); + } + } + return eKeyHandled; + + case 'b': // 'b' == toggle breakpoint on currently selected line + if (m_selected_line < GetNumSourceLines()) { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + if (exe_ctx.HasTargetScope()) { + BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint( + nullptr, // Don't limit the breakpoint to certain modules + m_file_sp->GetFileSpec(), // Source file + m_selected_line + + 1, // Source line number (m_selected_line is zero based) + 0, // No offset + eLazyBoolCalculate, // Check inlines using global setting + eLazyBoolCalculate, // Skip prologue using global setting, + false, // internal + false, // request_hardware + eLazyBoolCalculate); // move_to_nearest_code + } + } else if (m_selected_line < GetNumDisassemblyLines()) { + const Instruction *inst = m_disassembly_sp->GetInstructionList() + .GetInstructionAtIndex(m_selected_line) + .get(); + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + if (exe_ctx.HasTargetScope()) { + Address addr = inst->GetAddress(); + BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint( + addr, // lldb_private::Address + false, // internal + false); // request_hardware + } + } + return eKeyHandled; + + case 'd': // 'd' == detach and let run + case 'D': // 'D' == detach and keep stopped + { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + if (exe_ctx.HasProcessScope()) + exe_ctx.GetProcessRef().Detach(c == 'D'); } - - size_t - GetNumSourceLines () const - { - if (m_file_sp) - return m_file_sp->GetNumLines(); - return 0; + return eKeyHandled; + + case 'k': + // 'k' == kill + { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + if (exe_ctx.HasProcessScope()) + exe_ctx.GetProcessRef().Destroy(false); + } + return eKeyHandled; + + case 'c': + // 'c' == continue + { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + if (exe_ctx.HasProcessScope()) + exe_ctx.GetProcessRef().Resume(); + } + return eKeyHandled; + + case 'o': + // 'o' == step out + { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + if (exe_ctx.HasThreadScope() && + StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) { + exe_ctx.GetThreadRef().StepOut(); + } + } + return eKeyHandled; + + case 'n': // 'n' == step over + case 'N': // 'N' == step over instruction + { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + if (exe_ctx.HasThreadScope() && + StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) { + bool source_step = (c == 'n'); + exe_ctx.GetThreadRef().StepOver(source_step); + } } - - size_t - GetNumDisassemblyLines () const - { - if (m_disassembly_sp) - return m_disassembly_sp->GetInstructionList().GetSize(); - return 0; + return eKeyHandled; + + case 's': // 's' == step into + case 'S': // 'S' == step into instruction + { + ExecutionContext exe_ctx = + m_debugger.GetCommandInterpreter().GetExecutionContext(); + if (exe_ctx.HasThreadScope() && + StateIsStoppedState(exe_ctx.GetProcessRef().GetState(), true)) { + bool source_step = (c == 's'); + exe_ctx.GetThreadRef().StepIn(source_step); + } } + return eKeyHandled; - HandleCharResult - WindowDelegateHandleChar (Window &window, int c) override - { - const uint32_t num_visible_lines = NumVisibleLines(); - const size_t num_lines = GetNumLines (); - - switch (c) - { - case ',': - case KEY_PPAGE: - // Page up key - if (static_cast<uint32_t>(m_first_visible_line) > num_visible_lines) - m_first_visible_line -= num_visible_lines; - else - m_first_visible_line = 0; - m_selected_line = m_first_visible_line; - return eKeyHandled; - - case '.': - case KEY_NPAGE: - // Page down key - { - if (m_first_visible_line + num_visible_lines < num_lines) - m_first_visible_line += num_visible_lines; - else if (num_lines < num_visible_lines) - m_first_visible_line = 0; - else - m_first_visible_line = num_lines - num_visible_lines; - m_selected_line = m_first_visible_line; - } - return eKeyHandled; - - case KEY_UP: - if (m_selected_line > 0) - { - m_selected_line--; - if (static_cast<size_t>(m_first_visible_line) > m_selected_line) - m_first_visible_line = m_selected_line; - } - return eKeyHandled; - - case KEY_DOWN: - if (m_selected_line + 1 < num_lines) - { - m_selected_line++; - if (m_first_visible_line + num_visible_lines < m_selected_line) - m_first_visible_line++; - } - return eKeyHandled; - - case '\r': - case '\n': - case KEY_ENTER: - // Set a breakpoint and run to the line using a one shot breakpoint - if (GetNumSourceLines() > 0) - { - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - if (exe_ctx.HasProcessScope() && exe_ctx.GetProcessRef().IsAlive()) - { - BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(nullptr, // Don't limit the breakpoint to certain modules - m_file_sp->GetFileSpec(), // Source file - m_selected_line + 1, // Source line number (m_selected_line is zero based) - 0, // No offset - eLazyBoolCalculate, // Check inlines using global setting - eLazyBoolCalculate, // Skip prologue using global setting, - false, // internal - false, // request_hardware - eLazyBoolCalculate); // move_to_nearest_code - // Make breakpoint one shot - bp_sp->GetOptions()->SetOneShot(true); - exe_ctx.GetProcessRef().Resume(); - } - } - else if (m_selected_line < GetNumDisassemblyLines()) - { - const Instruction *inst = m_disassembly_sp->GetInstructionList().GetInstructionAtIndex(m_selected_line).get(); - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - if (exe_ctx.HasTargetScope()) - { - Address addr = inst->GetAddress(); - BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint (addr, // lldb_private::Address - false, // internal - false); // request_hardware - // Make breakpoint one shot - bp_sp->GetOptions()->SetOneShot(true); - exe_ctx.GetProcessRef().Resume(); - } - } - return eKeyHandled; - - case 'b': // 'b' == toggle breakpoint on currently selected line - if (m_selected_line < GetNumSourceLines()) - { - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - if (exe_ctx.HasTargetScope()) - { - BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint(nullptr, // Don't limit the breakpoint to certain modules - m_file_sp->GetFileSpec(), // Source file - m_selected_line + 1, // Source line number (m_selected_line is zero based) - 0, // No offset - eLazyBoolCalculate, // Check inlines using global setting - eLazyBoolCalculate, // Skip prologue using global setting, - false, // internal - false, // request_hardware - eLazyBoolCalculate); // move_to_nearest_code - } - } - else if (m_selected_line < GetNumDisassemblyLines()) - { - const Instruction *inst = m_disassembly_sp->GetInstructionList().GetInstructionAtIndex(m_selected_line).get(); - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - if (exe_ctx.HasTargetScope()) - { - Address addr = inst->GetAddress(); - BreakpointSP bp_sp = exe_ctx.GetTargetRef().CreateBreakpoint (addr, // lldb_private::Address - false, // internal - false); // request_hardware - } - } - return eKeyHandled; - - case 'd': // 'd' == detach and let run - case 'D': // 'D' == detach and keep stopped - { - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - if (exe_ctx.HasProcessScope()) - exe_ctx.GetProcessRef().Detach(c == 'D'); - } - return eKeyHandled; - - case 'k': - // 'k' == kill - { - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - if (exe_ctx.HasProcessScope()) - exe_ctx.GetProcessRef().Destroy(false); - } - return eKeyHandled; - - case 'c': - // 'c' == continue - { - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - if (exe_ctx.HasProcessScope()) - exe_ctx.GetProcessRef().Resume(); - } - return eKeyHandled; - - case 'o': - // 'o' == step out - { - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - if (exe_ctx.HasThreadScope() && StateIsStoppedState (exe_ctx.GetProcessRef().GetState(), true)) - { - exe_ctx.GetThreadRef().StepOut(); - } - } - return eKeyHandled; - - case 'n': // 'n' == step over - case 'N': // 'N' == step over instruction - { - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - if (exe_ctx.HasThreadScope() && StateIsStoppedState (exe_ctx.GetProcessRef().GetState(), true)) - { - bool source_step = (c == 'n'); - exe_ctx.GetThreadRef().StepOver(source_step); - } - } - return eKeyHandled; - - case 's': // 's' == step into - case 'S': // 'S' == step into instruction - { - ExecutionContext exe_ctx = m_debugger.GetCommandInterpreter().GetExecutionContext(); - if (exe_ctx.HasThreadScope() && StateIsStoppedState (exe_ctx.GetProcessRef().GetState(), true)) - { - bool source_step = (c == 's'); - exe_ctx.GetThreadRef().StepIn(source_step); - } - } - return eKeyHandled; - - case 'h': - window.CreateHelpSubwindow (); - return eKeyHandled; + case 'h': + window.CreateHelpSubwindow(); + return eKeyHandled; - default: - break; - } - return eKeyNotHandled; + default: + break; } + return eKeyNotHandled; + } protected: - typedef std::set<uint32_t> BreakpointLines; - typedef std::set<lldb::addr_t> BreakpointAddrs; - - Debugger &m_debugger; - SymbolContext m_sc; - SourceManager::FileSP m_file_sp; - SymbolContextScope *m_disassembly_scope; - lldb::DisassemblerSP m_disassembly_sp; - AddressRange m_disassembly_range; - StreamString m_title; - lldb::user_id_t m_tid; - char m_line_format[8]; - int m_line_width; - uint32_t m_selected_line; // The selected line - uint32_t m_pc_line; // The line with the PC - uint32_t m_stop_id; - uint32_t m_frame_idx; - int m_first_visible_line; - int m_min_x; - int m_min_y; - int m_max_x; - int m_max_y; + typedef std::set<uint32_t> BreakpointLines; + typedef std::set<lldb::addr_t> BreakpointAddrs; + + Debugger &m_debugger; + SymbolContext m_sc; + SourceManager::FileSP m_file_sp; + SymbolContextScope *m_disassembly_scope; + lldb::DisassemblerSP m_disassembly_sp; + AddressRange m_disassembly_range; + StreamString m_title; + lldb::user_id_t m_tid; + char m_line_format[8]; + int m_line_width; + uint32_t m_selected_line; // The selected line + uint32_t m_pc_line; // The line with the PC + uint32_t m_stop_id; + uint32_t m_frame_idx; + int m_first_visible_line; + int m_min_x; + int m_min_y; + int m_max_x; + int m_max_y; }; -DisplayOptions ValueObjectListDelegate::g_options = { true }; - -IOHandlerCursesGUI::IOHandlerCursesGUI (Debugger &debugger) : - IOHandler (debugger, IOHandler::Type::Curses) -{ -} - -void -IOHandlerCursesGUI::Activate () -{ - IOHandler::Activate(); - if (!m_app_ap) - { - m_app_ap.reset (new Application (GetInputFILE(), GetOutputFILE())); - - // This is both a window and a menu delegate - std::shared_ptr<ApplicationDelegate> app_delegate_sp(new ApplicationDelegate(*m_app_ap, m_debugger)); - - MenuDelegateSP app_menu_delegate_sp = std::static_pointer_cast<MenuDelegate>(app_delegate_sp); - MenuSP lldb_menu_sp(new Menu("LLDB" , "F1", KEY_F(1), ApplicationDelegate::eMenuID_LLDB)); - MenuSP exit_menuitem_sp(new Menu("Exit", nullptr, 'x', ApplicationDelegate::eMenuID_LLDBExit)); - exit_menuitem_sp->SetCannedResult(MenuActionResult::Quit); - lldb_menu_sp->AddSubmenu (MenuSP (new Menu("About LLDB", nullptr, 'a', ApplicationDelegate::eMenuID_LLDBAbout))); - lldb_menu_sp->AddSubmenu (MenuSP (new Menu(Menu::Type::Separator))); - lldb_menu_sp->AddSubmenu (exit_menuitem_sp); - - MenuSP target_menu_sp(new Menu("Target" ,"F2", KEY_F(2), ApplicationDelegate::eMenuID_Target)); - target_menu_sp->AddSubmenu (MenuSP (new Menu("Create", nullptr, 'c', ApplicationDelegate::eMenuID_TargetCreate))); - target_menu_sp->AddSubmenu (MenuSP (new Menu("Delete", nullptr, 'd', ApplicationDelegate::eMenuID_TargetDelete))); - - MenuSP process_menu_sp(new Menu("Process", "F3", KEY_F(3), ApplicationDelegate::eMenuID_Process)); - process_menu_sp->AddSubmenu (MenuSP (new Menu("Attach" , nullptr, 'a', ApplicationDelegate::eMenuID_ProcessAttach))); - process_menu_sp->AddSubmenu (MenuSP (new Menu("Detach" , nullptr, 'd', ApplicationDelegate::eMenuID_ProcessDetach))); - process_menu_sp->AddSubmenu (MenuSP (new Menu("Launch" , nullptr, 'l', ApplicationDelegate::eMenuID_ProcessLaunch))); - process_menu_sp->AddSubmenu (MenuSP (new Menu(Menu::Type::Separator))); - process_menu_sp->AddSubmenu (MenuSP (new Menu("Continue", nullptr, 'c', ApplicationDelegate::eMenuID_ProcessContinue))); - process_menu_sp->AddSubmenu (MenuSP (new Menu("Halt" , nullptr, 'h', ApplicationDelegate::eMenuID_ProcessHalt))); - process_menu_sp->AddSubmenu (MenuSP (new Menu("Kill" , nullptr, 'k', ApplicationDelegate::eMenuID_ProcessKill))); - - MenuSP thread_menu_sp(new Menu("Thread", "F4", KEY_F(4), ApplicationDelegate::eMenuID_Thread)); - thread_menu_sp->AddSubmenu (MenuSP (new Menu("Step In" , nullptr, 'i', ApplicationDelegate::eMenuID_ThreadStepIn))); - thread_menu_sp->AddSubmenu (MenuSP (new Menu("Step Over", nullptr, 'v', ApplicationDelegate::eMenuID_ThreadStepOver))); - thread_menu_sp->AddSubmenu (MenuSP (new Menu("Step Out" , nullptr, 'o', ApplicationDelegate::eMenuID_ThreadStepOut))); - - MenuSP view_menu_sp(new Menu("View", "F5", KEY_F(5), ApplicationDelegate::eMenuID_View)); - view_menu_sp->AddSubmenu (MenuSP (new Menu("Backtrace", nullptr, 'b', ApplicationDelegate::eMenuID_ViewBacktrace))); - view_menu_sp->AddSubmenu (MenuSP (new Menu("Registers", nullptr, 'r', ApplicationDelegate::eMenuID_ViewRegisters))); - view_menu_sp->AddSubmenu (MenuSP (new Menu("Source" , nullptr, 's', ApplicationDelegate::eMenuID_ViewSource))); - view_menu_sp->AddSubmenu (MenuSP (new Menu("Variables", nullptr, 'v', ApplicationDelegate::eMenuID_ViewVariables))); - - MenuSP help_menu_sp(new Menu("Help", "F6", KEY_F(6), ApplicationDelegate::eMenuID_Help)); - help_menu_sp->AddSubmenu (MenuSP (new Menu("GUI Help", nullptr, 'g', ApplicationDelegate::eMenuID_HelpGUIHelp))); - - m_app_ap->Initialize(); - WindowSP &main_window_sp = m_app_ap->GetMainWindow(); - - MenuSP menubar_sp(new Menu(Menu::Type::Bar)); - menubar_sp->AddSubmenu (lldb_menu_sp); - menubar_sp->AddSubmenu (target_menu_sp); - menubar_sp->AddSubmenu (process_menu_sp); - menubar_sp->AddSubmenu (thread_menu_sp); - menubar_sp->AddSubmenu (view_menu_sp); - menubar_sp->AddSubmenu (help_menu_sp); - menubar_sp->SetDelegate(app_menu_delegate_sp); - - Rect content_bounds = main_window_sp->GetFrame(); - Rect menubar_bounds = content_bounds.MakeMenuBar(); - Rect status_bounds = content_bounds.MakeStatusBar(); - Rect source_bounds; - Rect variables_bounds; - Rect threads_bounds; - Rect source_variables_bounds; - content_bounds.VerticalSplitPercentage(0.80, source_variables_bounds, threads_bounds); - source_variables_bounds.HorizontalSplitPercentage(0.70, source_bounds, variables_bounds); - - WindowSP menubar_window_sp = main_window_sp->CreateSubWindow("Menubar", menubar_bounds, false); - // Let the menubar get keys if the active window doesn't handle the - // keys that are typed so it can respond to menubar key presses. - menubar_window_sp->SetCanBeActive(false); // Don't let the menubar become the active window - menubar_window_sp->SetDelegate(menubar_sp); - - WindowSP source_window_sp (main_window_sp->CreateSubWindow("Source", - source_bounds, - true)); - WindowSP variables_window_sp (main_window_sp->CreateSubWindow("Variables", - variables_bounds, - false)); - WindowSP threads_window_sp (main_window_sp->CreateSubWindow("Threads", - threads_bounds, - false)); - WindowSP status_window_sp (main_window_sp->CreateSubWindow("Status", - status_bounds, - false)); - status_window_sp->SetCanBeActive(false); // Don't let the status bar become the active window - main_window_sp->SetDelegate (std::static_pointer_cast<WindowDelegate>(app_delegate_sp)); - source_window_sp->SetDelegate (WindowDelegateSP(new SourceFileWindowDelegate(m_debugger))); - variables_window_sp->SetDelegate (WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger))); - TreeDelegateSP thread_delegate_sp (new ThreadsTreeDelegate(m_debugger)); - threads_window_sp->SetDelegate (WindowDelegateSP(new TreeWindowDelegate(m_debugger, thread_delegate_sp))); - status_window_sp->SetDelegate (WindowDelegateSP(new StatusBarWindowDelegate(m_debugger))); - - // Show the main help window once the first time the curses GUI is launched - static bool g_showed_help = false; - if (!g_showed_help) - { - g_showed_help = true; - main_window_sp->CreateHelpSubwindow(); - } - - init_pair (1, COLOR_WHITE , COLOR_BLUE ); - init_pair (2, COLOR_BLACK , COLOR_WHITE ); - init_pair (3, COLOR_MAGENTA , COLOR_WHITE ); - init_pair (4, COLOR_MAGENTA , COLOR_BLACK ); - init_pair (5, COLOR_RED , COLOR_BLACK ); +DisplayOptions ValueObjectListDelegate::g_options = {true}; + +IOHandlerCursesGUI::IOHandlerCursesGUI(Debugger &debugger) + : IOHandler(debugger, IOHandler::Type::Curses) {} + +void IOHandlerCursesGUI::Activate() { + IOHandler::Activate(); + if (!m_app_ap) { + m_app_ap.reset(new Application(GetInputFILE(), GetOutputFILE())); + + // This is both a window and a menu delegate + std::shared_ptr<ApplicationDelegate> app_delegate_sp( + new ApplicationDelegate(*m_app_ap, m_debugger)); + + MenuDelegateSP app_menu_delegate_sp = + std::static_pointer_cast<MenuDelegate>(app_delegate_sp); + MenuSP lldb_menu_sp( + new Menu("LLDB", "F1", KEY_F(1), ApplicationDelegate::eMenuID_LLDB)); + MenuSP exit_menuitem_sp( + new Menu("Exit", nullptr, 'x', ApplicationDelegate::eMenuID_LLDBExit)); + exit_menuitem_sp->SetCannedResult(MenuActionResult::Quit); + lldb_menu_sp->AddSubmenu(MenuSP(new Menu( + "About LLDB", nullptr, 'a', ApplicationDelegate::eMenuID_LLDBAbout))); + lldb_menu_sp->AddSubmenu(MenuSP(new Menu(Menu::Type::Separator))); + lldb_menu_sp->AddSubmenu(exit_menuitem_sp); + + MenuSP target_menu_sp(new Menu("Target", "F2", KEY_F(2), + ApplicationDelegate::eMenuID_Target)); + target_menu_sp->AddSubmenu(MenuSP(new Menu( + "Create", nullptr, 'c', ApplicationDelegate::eMenuID_TargetCreate))); + target_menu_sp->AddSubmenu(MenuSP(new Menu( + "Delete", nullptr, 'd', ApplicationDelegate::eMenuID_TargetDelete))); + + MenuSP process_menu_sp(new Menu("Process", "F3", KEY_F(3), + ApplicationDelegate::eMenuID_Process)); + process_menu_sp->AddSubmenu(MenuSP(new Menu( + "Attach", nullptr, 'a', ApplicationDelegate::eMenuID_ProcessAttach))); + process_menu_sp->AddSubmenu(MenuSP(new Menu( + "Detach", nullptr, 'd', ApplicationDelegate::eMenuID_ProcessDetach))); + process_menu_sp->AddSubmenu(MenuSP(new Menu( + "Launch", nullptr, 'l', ApplicationDelegate::eMenuID_ProcessLaunch))); + process_menu_sp->AddSubmenu(MenuSP(new Menu(Menu::Type::Separator))); + process_menu_sp->AddSubmenu( + MenuSP(new Menu("Continue", nullptr, 'c', + ApplicationDelegate::eMenuID_ProcessContinue))); + process_menu_sp->AddSubmenu(MenuSP(new Menu( + "Halt", nullptr, 'h', ApplicationDelegate::eMenuID_ProcessHalt))); + process_menu_sp->AddSubmenu(MenuSP(new Menu( + "Kill", nullptr, 'k', ApplicationDelegate::eMenuID_ProcessKill))); + + MenuSP thread_menu_sp(new Menu("Thread", "F4", KEY_F(4), + ApplicationDelegate::eMenuID_Thread)); + thread_menu_sp->AddSubmenu(MenuSP(new Menu( + "Step In", nullptr, 'i', ApplicationDelegate::eMenuID_ThreadStepIn))); + thread_menu_sp->AddSubmenu( + MenuSP(new Menu("Step Over", nullptr, 'v', + ApplicationDelegate::eMenuID_ThreadStepOver))); + thread_menu_sp->AddSubmenu(MenuSP(new Menu( + "Step Out", nullptr, 'o', ApplicationDelegate::eMenuID_ThreadStepOut))); + + MenuSP view_menu_sp( + new Menu("View", "F5", KEY_F(5), ApplicationDelegate::eMenuID_View)); + view_menu_sp->AddSubmenu( + MenuSP(new Menu("Backtrace", nullptr, 'b', + ApplicationDelegate::eMenuID_ViewBacktrace))); + view_menu_sp->AddSubmenu( + MenuSP(new Menu("Registers", nullptr, 'r', + ApplicationDelegate::eMenuID_ViewRegisters))); + view_menu_sp->AddSubmenu(MenuSP(new Menu( + "Source", nullptr, 's', ApplicationDelegate::eMenuID_ViewSource))); + view_menu_sp->AddSubmenu( + MenuSP(new Menu("Variables", nullptr, 'v', + ApplicationDelegate::eMenuID_ViewVariables))); + + MenuSP help_menu_sp( + new Menu("Help", "F6", KEY_F(6), ApplicationDelegate::eMenuID_Help)); + help_menu_sp->AddSubmenu(MenuSP(new Menu( + "GUI Help", nullptr, 'g', ApplicationDelegate::eMenuID_HelpGUIHelp))); + + m_app_ap->Initialize(); + WindowSP &main_window_sp = m_app_ap->GetMainWindow(); + + MenuSP menubar_sp(new Menu(Menu::Type::Bar)); + menubar_sp->AddSubmenu(lldb_menu_sp); + menubar_sp->AddSubmenu(target_menu_sp); + menubar_sp->AddSubmenu(process_menu_sp); + menubar_sp->AddSubmenu(thread_menu_sp); + menubar_sp->AddSubmenu(view_menu_sp); + menubar_sp->AddSubmenu(help_menu_sp); + menubar_sp->SetDelegate(app_menu_delegate_sp); + + Rect content_bounds = main_window_sp->GetFrame(); + Rect menubar_bounds = content_bounds.MakeMenuBar(); + Rect status_bounds = content_bounds.MakeStatusBar(); + Rect source_bounds; + Rect variables_bounds; + Rect threads_bounds; + Rect source_variables_bounds; + content_bounds.VerticalSplitPercentage(0.80, source_variables_bounds, + threads_bounds); + source_variables_bounds.HorizontalSplitPercentage(0.70, source_bounds, + variables_bounds); + + WindowSP menubar_window_sp = + main_window_sp->CreateSubWindow("Menubar", menubar_bounds, false); + // Let the menubar get keys if the active window doesn't handle the + // keys that are typed so it can respond to menubar key presses. + menubar_window_sp->SetCanBeActive( + false); // Don't let the menubar become the active window + menubar_window_sp->SetDelegate(menubar_sp); + + WindowSP source_window_sp( + main_window_sp->CreateSubWindow("Source", source_bounds, true)); + WindowSP variables_window_sp( + main_window_sp->CreateSubWindow("Variables", variables_bounds, false)); + WindowSP threads_window_sp( + main_window_sp->CreateSubWindow("Threads", threads_bounds, false)); + WindowSP status_window_sp( + main_window_sp->CreateSubWindow("Status", status_bounds, false)); + status_window_sp->SetCanBeActive( + false); // Don't let the status bar become the active window + main_window_sp->SetDelegate( + std::static_pointer_cast<WindowDelegate>(app_delegate_sp)); + source_window_sp->SetDelegate( + WindowDelegateSP(new SourceFileWindowDelegate(m_debugger))); + variables_window_sp->SetDelegate( + WindowDelegateSP(new FrameVariablesWindowDelegate(m_debugger))); + TreeDelegateSP thread_delegate_sp(new ThreadsTreeDelegate(m_debugger)); + threads_window_sp->SetDelegate(WindowDelegateSP( + new TreeWindowDelegate(m_debugger, thread_delegate_sp))); + status_window_sp->SetDelegate( + WindowDelegateSP(new StatusBarWindowDelegate(m_debugger))); + + // Show the main help window once the first time the curses GUI is launched + static bool g_showed_help = false; + if (!g_showed_help) { + g_showed_help = true; + main_window_sp->CreateHelpSubwindow(); } -} -void -IOHandlerCursesGUI::Deactivate () -{ - m_app_ap->Terminate(); + init_pair(1, COLOR_WHITE, COLOR_BLUE); + init_pair(2, COLOR_BLACK, COLOR_WHITE); + init_pair(3, COLOR_MAGENTA, COLOR_WHITE); + init_pair(4, COLOR_MAGENTA, COLOR_BLACK); + init_pair(5, COLOR_RED, COLOR_BLACK); + } } -void -IOHandlerCursesGUI::Run () -{ - m_app_ap->Run(m_debugger); - SetIsDone(true); +void IOHandlerCursesGUI::Deactivate() { m_app_ap->Terminate(); } + +void IOHandlerCursesGUI::Run() { + m_app_ap->Run(m_debugger); + SetIsDone(true); } IOHandlerCursesGUI::~IOHandlerCursesGUI() = default; -void -IOHandlerCursesGUI::Cancel () -{ -} +void IOHandlerCursesGUI::Cancel() {} -bool -IOHandlerCursesGUI::Interrupt () -{ - return false; -} +bool IOHandlerCursesGUI::Interrupt() { return false; } -void -IOHandlerCursesGUI::GotEOF() -{ -} +void IOHandlerCursesGUI::GotEOF() {} #endif // LLDB_DISABLE_CURSES diff --git a/source/Core/Listener.cpp b/source/Core/Listener.cpp index 15a698784681..3adb677f53d1 100644 --- a/source/Core/Listener.cpp +++ b/source/Core/Listener.cpp @@ -16,523 +16,460 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/Broadcaster.h" +#include "lldb/Core/Event.h" #include "lldb/Core/Log.h" #include "lldb/Core/StreamString.h" -#include "lldb/Core/Event.h" -#include "lldb/Host/TimeValue.h" using namespace lldb; using namespace lldb_private; -namespace -{ - class BroadcasterManagerWPMatcher - { - public: - BroadcasterManagerWPMatcher (BroadcasterManagerSP manager_sp) : m_manager_sp(manager_sp) {} - bool operator() (const BroadcasterManagerWP input_wp) const - { - BroadcasterManagerSP input_sp = input_wp.lock(); - return (input_sp && input_sp == m_manager_sp); - } - - BroadcasterManagerSP m_manager_sp; - }; +namespace { +class BroadcasterManagerWPMatcher { +public: + BroadcasterManagerWPMatcher(BroadcasterManagerSP manager_sp) + : m_manager_sp(manager_sp) {} + bool operator()(const BroadcasterManagerWP input_wp) const { + BroadcasterManagerSP input_sp = input_wp.lock(); + return (input_sp && input_sp == m_manager_sp); + } + + BroadcasterManagerSP m_manager_sp; +}; } // anonymous namespace Listener::Listener(const char *name) - : m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(), m_events_mutex(Mutex::eMutexTypeNormal) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); - if (log != nullptr) - log->Printf ("%p Listener::Listener('%s')", - static_cast<void*>(this), m_name.c_str()); + : m_name(name), m_broadcasters(), m_broadcasters_mutex(), m_events(), + m_events_mutex() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + if (log != nullptr) + log->Printf("%p Listener::Listener('%s')", static_cast<void *>(this), + m_name.c_str()); } -Listener::~Listener() -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); +Listener::~Listener() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); - Clear(); + Clear(); - if (log) - log->Printf("%p Listener::%s('%s')", static_cast<void *>(this), __FUNCTION__, m_name.c_str()); + if (log) + log->Printf("%p Listener::%s('%s')", static_cast<void *>(this), + __FUNCTION__, m_name.c_str()); } -void -Listener::Clear() -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT)); - std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); - broadcaster_collection::iterator pos, end = m_broadcasters.end(); - for (pos = m_broadcasters.begin(); pos != end; ++pos) - { - Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock()); - if (broadcaster_sp) - broadcaster_sp->RemoveListener (this, pos->second.event_mask); - } - m_broadcasters.clear(); - - Mutex::Locker event_locker(m_events_mutex); - m_events.clear(); - size_t num_managers = m_broadcaster_managers.size(); - - for (size_t i = 0; i < num_managers; i++) - { - BroadcasterManagerSP manager_sp(m_broadcaster_managers[i].lock()); - if (manager_sp) - manager_sp->RemoveListener(this); - } - - if (log) - log->Printf("%p Listener::%s('%s')", static_cast<void *>(this), __FUNCTION__, m_name.c_str()); +void Listener::Clear() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_OBJECT)); + std::lock_guard<std::recursive_mutex> broadcasters_guard( + m_broadcasters_mutex); + broadcaster_collection::iterator pos, end = m_broadcasters.end(); + for (pos = m_broadcasters.begin(); pos != end; ++pos) { + Broadcaster::BroadcasterImplSP broadcaster_sp(pos->first.lock()); + if (broadcaster_sp) + broadcaster_sp->RemoveListener(this, pos->second.event_mask); + } + m_broadcasters.clear(); + + std::lock_guard<std::mutex> events_guard(m_events_mutex); + m_events.clear(); + size_t num_managers = m_broadcaster_managers.size(); + + for (size_t i = 0; i < num_managers; i++) { + BroadcasterManagerSP manager_sp(m_broadcaster_managers[i].lock()); + if (manager_sp) + manager_sp->RemoveListener(this); + } + + if (log) + log->Printf("%p Listener::%s('%s')", static_cast<void *>(this), + __FUNCTION__, m_name.c_str()); } -uint32_t -Listener::StartListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask) -{ - if (broadcaster) +uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, + uint32_t event_mask) { + if (broadcaster) { + // Scope for "locker" + // Tell the broadcaster to add this object as a listener { - // Scope for "locker" - // Tell the broadcaster to add this object as a listener - { - std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); - Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl()); - m_broadcasters.insert(std::make_pair(impl_wp, BroadcasterInfo(event_mask))); - } - - uint32_t acquired_mask = broadcaster->AddListener (this->shared_from_this(), event_mask); + std::lock_guard<std::recursive_mutex> broadcasters_guard( + m_broadcasters_mutex); + Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl()); + m_broadcasters.insert( + std::make_pair(impl_wp, BroadcasterInfo(event_mask))); + } - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS)); - if (log != nullptr) - log->Printf ("%p Listener::StartListeningForEvents (broadcaster = %p, mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s", - static_cast<void*>(this), - static_cast<void*>(broadcaster), event_mask, - acquired_mask, m_name.c_str()); + uint32_t acquired_mask = + broadcaster->AddListener(this->shared_from_this(), event_mask); - return acquired_mask; - } - return 0; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); + if (log != nullptr) + log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, " + "mask = 0x%8.8x) acquired_mask = 0x%8.8x for %s", + static_cast<void *>(this), static_cast<void *>(broadcaster), + event_mask, acquired_mask, m_name.c_str()); + + return acquired_mask; + } + return 0; } -uint32_t -Listener::StartListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask, HandleBroadcastCallback callback, void *callback_user_data) -{ - if (broadcaster) +uint32_t Listener::StartListeningForEvents(Broadcaster *broadcaster, + uint32_t event_mask, + HandleBroadcastCallback callback, + void *callback_user_data) { + if (broadcaster) { + // Scope for "locker" + // Tell the broadcaster to add this object as a listener { - // Scope for "locker" - // Tell the broadcaster to add this object as a listener - { - std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); - Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl()); - m_broadcasters.insert(std::make_pair(impl_wp, - BroadcasterInfo(event_mask, callback, callback_user_data))); - } - - uint32_t acquired_mask = broadcaster->AddListener (this->shared_from_this(), event_mask); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS)); - if (log != nullptr) - { - void **pointer = reinterpret_cast<void**>(&callback); - log->Printf ("%p Listener::StartListeningForEvents (broadcaster = %p, mask = 0x%8.8x, callback = %p, user_data = %p) acquired_mask = 0x%8.8x for %s", - static_cast<void*>(this), - static_cast<void*>(broadcaster), event_mask, *pointer, - static_cast<void*>(callback_user_data), acquired_mask, - m_name.c_str()); - } + std::lock_guard<std::recursive_mutex> broadcasters_guard( + m_broadcasters_mutex); + Broadcaster::BroadcasterImplWP impl_wp(broadcaster->GetBroadcasterImpl()); + m_broadcasters.insert(std::make_pair( + impl_wp, BroadcasterInfo(event_mask, callback, callback_user_data))); + } - return acquired_mask; + uint32_t acquired_mask = + broadcaster->AddListener(this->shared_from_this(), event_mask); + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); + if (log != nullptr) { + void **pointer = reinterpret_cast<void **>(&callback); + log->Printf("%p Listener::StartListeningForEvents (broadcaster = %p, " + "mask = 0x%8.8x, callback = %p, user_data = %p) " + "acquired_mask = 0x%8.8x for %s", + static_cast<void *>(this), static_cast<void *>(broadcaster), + event_mask, *pointer, static_cast<void *>(callback_user_data), + acquired_mask, m_name.c_str()); } - return 0; + + return acquired_mask; + } + return 0; } -bool -Listener::StopListeningForEvents (Broadcaster* broadcaster, uint32_t event_mask) -{ - if (broadcaster) +bool Listener::StopListeningForEvents(Broadcaster *broadcaster, + uint32_t event_mask) { + if (broadcaster) { + // Scope for "locker" { - // Scope for "locker" - { - std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); - m_broadcasters.erase (broadcaster->GetBroadcasterImpl()); - } - // Remove the broadcaster from our set of broadcasters - return broadcaster->RemoveListener (this->shared_from_this(), event_mask); + std::lock_guard<std::recursive_mutex> broadcasters_guard( + m_broadcasters_mutex); + m_broadcasters.erase(broadcaster->GetBroadcasterImpl()); } + // Remove the broadcaster from our set of broadcasters + return broadcaster->RemoveListener(this->shared_from_this(), event_mask); + } - return false; + return false; } // Called when a Broadcaster is in its destructor. We need to remove all // knowledge of this broadcaster and any events that it may have queued up -void -Listener::BroadcasterWillDestruct (Broadcaster *broadcaster) -{ - // Scope for "broadcasters_locker" - { - std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); - m_broadcasters.erase (broadcaster->GetBroadcasterImpl()); - } - - // Scope for "event_locker" - { - Mutex::Locker event_locker(m_events_mutex); - // Remove all events for this broadcaster object. - event_collection::iterator pos = m_events.begin(); - while (pos != m_events.end()) - { - if ((*pos)->GetBroadcaster() == broadcaster) - pos = m_events.erase(pos); - else - ++pos; - } +void Listener::BroadcasterWillDestruct(Broadcaster *broadcaster) { + // Scope for "broadcasters_locker" + { + std::lock_guard<std::recursive_mutex> broadcasters_guard( + m_broadcasters_mutex); + m_broadcasters.erase(broadcaster->GetBroadcasterImpl()); + } + + // Scope for "event_locker" + { + std::lock_guard<std::mutex> events_guard(m_events_mutex); + // Remove all events for this broadcaster object. + event_collection::iterator pos = m_events.begin(); + while (pos != m_events.end()) { + if ((*pos)->GetBroadcaster() == broadcaster) + pos = m_events.erase(pos); + else + ++pos; } + } } -void -Listener::BroadcasterManagerWillDestruct (BroadcasterManagerSP manager_sp) -{ - // Just need to remove this broadcast manager from the list of managers: - broadcaster_manager_collection::iterator iter, end_iter = m_broadcaster_managers.end(); - BroadcasterManagerWP manager_wp; - - BroadcasterManagerWPMatcher matcher(manager_sp); - iter = std::find_if<broadcaster_manager_collection::iterator, BroadcasterManagerWPMatcher>(m_broadcaster_managers.begin(), end_iter, matcher); - if (iter != end_iter) - m_broadcaster_managers.erase (iter); +void Listener::BroadcasterManagerWillDestruct(BroadcasterManagerSP manager_sp) { + // Just need to remove this broadcast manager from the list of managers: + broadcaster_manager_collection::iterator iter, + end_iter = m_broadcaster_managers.end(); + BroadcasterManagerWP manager_wp; + + BroadcasterManagerWPMatcher matcher(manager_sp); + iter = std::find_if<broadcaster_manager_collection::iterator, + BroadcasterManagerWPMatcher>( + m_broadcaster_managers.begin(), end_iter, matcher); + if (iter != end_iter) + m_broadcaster_managers.erase(iter); } -void -Listener::AddEvent (EventSP &event_sp) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS)); - if (log != nullptr) - log->Printf ("%p Listener('%s')::AddEvent (event_sp = {%p})", - static_cast<void*>(this), m_name.c_str(), - static_cast<void*>(event_sp.get())); +void Listener::AddEvent(EventSP &event_sp) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); + if (log != nullptr) + log->Printf("%p Listener('%s')::AddEvent (event_sp = {%p})", + static_cast<void *>(this), m_name.c_str(), + static_cast<void *>(event_sp.get())); - Mutex::Locker locker(m_events_mutex); - m_events.push_back (event_sp); - m_events_condition.Broadcast(); + std::lock_guard<std::mutex> guard(m_events_mutex); + m_events.push_back(event_sp); + m_events_condition.notify_all(); } -class EventBroadcasterMatches -{ +class EventBroadcasterMatches { public: - EventBroadcasterMatches (Broadcaster *broadcaster) : - m_broadcaster (broadcaster) - { - } + EventBroadcasterMatches(Broadcaster *broadcaster) + : m_broadcaster(broadcaster) {} - bool operator() (const EventSP &event_sp) const - { - return event_sp->BroadcasterIs(m_broadcaster); - } + bool operator()(const EventSP &event_sp) const { + return event_sp->BroadcasterIs(m_broadcaster); + } private: - Broadcaster *m_broadcaster; + Broadcaster *m_broadcaster; }; -class EventMatcher -{ +class EventMatcher { public: - EventMatcher (Broadcaster *broadcaster, const ConstString *broadcaster_names, uint32_t num_broadcaster_names, uint32_t event_type_mask) : - m_broadcaster (broadcaster), - m_broadcaster_names (broadcaster_names), - m_num_broadcaster_names (num_broadcaster_names), - m_event_type_mask (event_type_mask) - { - } - - bool operator() (const EventSP &event_sp) const - { - if (m_broadcaster && !event_sp->BroadcasterIs(m_broadcaster)) - return false; - - if (m_broadcaster_names) - { - bool found_source = false; - const ConstString &event_broadcaster_name = event_sp->GetBroadcaster()->GetBroadcasterName(); - for (uint32_t i = 0; i < m_num_broadcaster_names; ++i) - { - if (m_broadcaster_names[i] == event_broadcaster_name) - { - found_source = true; - break; - } - } - if (!found_source) - return false; + EventMatcher(Broadcaster *broadcaster, const ConstString *broadcaster_names, + uint32_t num_broadcaster_names, uint32_t event_type_mask) + : m_broadcaster(broadcaster), m_broadcaster_names(broadcaster_names), + m_num_broadcaster_names(num_broadcaster_names), + m_event_type_mask(event_type_mask) {} + + bool operator()(const EventSP &event_sp) const { + if (m_broadcaster && !event_sp->BroadcasterIs(m_broadcaster)) + return false; + + if (m_broadcaster_names) { + bool found_source = false; + const ConstString &event_broadcaster_name = + event_sp->GetBroadcaster()->GetBroadcasterName(); + for (uint32_t i = 0; i < m_num_broadcaster_names; ++i) { + if (m_broadcaster_names[i] == event_broadcaster_name) { + found_source = true; + break; } - - if (m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType()) - return true; + } + if (!found_source) return false; } + if (m_event_type_mask == 0 || m_event_type_mask & event_sp->GetType()) + return true; + return false; + } + private: - Broadcaster *m_broadcaster; - const ConstString *m_broadcaster_names; - const uint32_t m_num_broadcaster_names; - const uint32_t m_event_type_mask; + Broadcaster *m_broadcaster; + const ConstString *m_broadcaster_names; + const uint32_t m_num_broadcaster_names; + const uint32_t m_event_type_mask; }; -bool -Listener::FindNextEventInternal -( - Mutex::Locker& lock, - Broadcaster *broadcaster, // nullptr for any broadcaster +bool Listener::FindNextEventInternal( + std::unique_lock<std::mutex> &lock, + Broadcaster *broadcaster, // nullptr for any broadcaster const ConstString *broadcaster_names, // nullptr for any event - uint32_t num_broadcaster_names, - uint32_t event_type_mask, - EventSP &event_sp, - bool remove) -{ - // NOTE: callers of this function must lock m_events_mutex using a Mutex::Locker - // and pass the locker as the first argument. m_events_mutex is no longer recursive. - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS)); - - if (m_events.empty()) - return false; + uint32_t num_broadcaster_names, uint32_t event_type_mask, EventSP &event_sp, + bool remove) { + // NOTE: callers of this function must lock m_events_mutex using a + // Mutex::Locker + // and pass the locker as the first argument. m_events_mutex is no longer + // recursive. + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); + + if (m_events.empty()) + return false; - Listener::event_collection::iterator pos = m_events.end(); + Listener::event_collection::iterator pos = m_events.end(); - if (broadcaster == nullptr && broadcaster_names == nullptr && event_type_mask == 0) - { - pos = m_events.begin(); - } - else - { - pos = std::find_if (m_events.begin(), m_events.end(), EventMatcher (broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask)); - } + if (broadcaster == nullptr && broadcaster_names == nullptr && + event_type_mask == 0) { + pos = m_events.begin(); + } else { + pos = std::find_if(m_events.begin(), m_events.end(), + EventMatcher(broadcaster, broadcaster_names, + num_broadcaster_names, event_type_mask)); + } - if (pos != m_events.end()) - { - event_sp = *pos; - - if (log != nullptr) - log->Printf ("%p '%s' Listener::FindNextEventInternal(broadcaster=%p, broadcaster_names=%p[%u], event_type_mask=0x%8.8x, remove=%i) event %p", - static_cast<void*>(this), GetName(), - static_cast<void*>(broadcaster), - static_cast<const void*>(broadcaster_names), - num_broadcaster_names, event_type_mask, remove, - static_cast<void*>(event_sp.get())); - - if (remove) - { - m_events.erase(pos); - // Unlock the event queue here. We've removed this event and are about to return - // it so it should be okay to get the next event off the queue here - and it might - // be useful to do that in the "DoOnRemoval". - lock.Unlock(); - event_sp->DoOnRemoval(); - } - return true; + if (pos != m_events.end()) { + event_sp = *pos; + + if (log != nullptr) + log->Printf("%p '%s' Listener::FindNextEventInternal(broadcaster=%p, " + "broadcaster_names=%p[%u], event_type_mask=0x%8.8x, " + "remove=%i) event %p", + static_cast<void *>(this), GetName(), + static_cast<void *>(broadcaster), + static_cast<const void *>(broadcaster_names), + num_broadcaster_names, event_type_mask, remove, + static_cast<void *>(event_sp.get())); + + if (remove) { + m_events.erase(pos); + // Unlock the event queue here. We've removed this event and are about to + // return + // it so it should be okay to get the next event off the queue here - and + // it might + // be useful to do that in the "DoOnRemoval". + lock.unlock(); + event_sp->DoOnRemoval(); } + return true; + } - event_sp.reset(); - return false; + event_sp.reset(); + return false; } -Event * -Listener::PeekAtNextEvent () -{ - Mutex::Locker lock(m_events_mutex); - EventSP event_sp; - if (FindNextEventInternal(lock, nullptr, nullptr, 0, 0, event_sp, false)) - return event_sp.get(); - return nullptr; +Event *Listener::PeekAtNextEvent() { + std::unique_lock<std::mutex> guard(m_events_mutex); + EventSP event_sp; + if (FindNextEventInternal(guard, nullptr, nullptr, 0, 0, event_sp, false)) + return event_sp.get(); + return nullptr; } -Event * -Listener::PeekAtNextEventForBroadcaster (Broadcaster *broadcaster) -{ - Mutex::Locker lock(m_events_mutex); - EventSP event_sp; - if (FindNextEventInternal(lock, broadcaster, nullptr, 0, 0, event_sp, false)) - return event_sp.get(); - return nullptr; +Event *Listener::PeekAtNextEventForBroadcaster(Broadcaster *broadcaster) { + std::unique_lock<std::mutex> guard(m_events_mutex); + EventSP event_sp; + if (FindNextEventInternal(guard, broadcaster, nullptr, 0, 0, event_sp, false)) + return event_sp.get(); + return nullptr; } Event * -Listener::PeekAtNextEventForBroadcasterWithType (Broadcaster *broadcaster, uint32_t event_type_mask) -{ - Mutex::Locker lock(m_events_mutex); - EventSP event_sp; - if (FindNextEventInternal(lock, broadcaster, nullptr, 0, event_type_mask, event_sp, false)) - return event_sp.get(); - return nullptr; -} - -bool -Listener::GetNextEventInternal(Broadcaster *broadcaster, // nullptr for any broadcaster - const ConstString *broadcaster_names, // nullptr for any event - uint32_t num_broadcaster_names, - uint32_t event_type_mask, - EventSP &event_sp) -{ - Mutex::Locker lock(m_events_mutex); - return FindNextEventInternal (lock, broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp, true); -} - -bool -Listener::GetNextEvent (EventSP &event_sp) -{ - return GetNextEventInternal(nullptr, nullptr, 0, 0, event_sp); -} - -bool -Listener::GetNextEventForBroadcaster (Broadcaster *broadcaster, EventSP &event_sp) -{ - return GetNextEventInternal(broadcaster, nullptr, 0, 0, event_sp); -} - -bool -Listener::GetNextEventForBroadcasterWithType (Broadcaster *broadcaster, uint32_t event_type_mask, EventSP &event_sp) -{ - return GetNextEventInternal(broadcaster, nullptr, 0, event_type_mask, event_sp); +Listener::PeekAtNextEventForBroadcasterWithType(Broadcaster *broadcaster, + uint32_t event_type_mask) { + std::unique_lock<std::mutex> guard(m_events_mutex); + EventSP event_sp; + if (FindNextEventInternal(guard, broadcaster, nullptr, 0, event_type_mask, + event_sp, false)) + return event_sp.get(); + return nullptr; } -bool -Listener::WaitForEventsInternal(const TimeValue *timeout, - Broadcaster *broadcaster, // nullptr for any broadcaster - const ConstString *broadcaster_names, // nullptr for any event - uint32_t num_broadcaster_names, - uint32_t event_type_mask, - EventSP &event_sp) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS)); - if (log != nullptr) - log->Printf ("%p Listener::WaitForEventsInternal (timeout = { %p }) for %s", - static_cast<void*>(this), static_cast<const void*>(timeout), - m_name.c_str()); - - Mutex::Locker lock(m_events_mutex); - - while (true) - { - if (FindNextEventInternal (lock, broadcaster, broadcaster_names, num_broadcaster_names, event_type_mask, event_sp, true)) - { - return true; - } - else - { - bool timed_out = false; - if (m_events_condition.Wait(m_events_mutex, timeout, &timed_out) != 0) - { - if (timed_out) - { - log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS); - if (log != nullptr) - log->Printf ("%p Listener::WaitForEventsInternal() timed out for %s", - static_cast<void*>(this), m_name.c_str()); - } - else - { - log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EVENTS); - if (log != nullptr) - log->Printf ("%p Listener::WaitForEventsInternal() unknown error for %s", - static_cast<void*>(this), m_name.c_str()); - } - return false; - } - } +bool Listener::GetEventInternal( + const Timeout<std::micro> &timeout, + Broadcaster *broadcaster, // nullptr for any broadcaster + const ConstString *broadcaster_names, // nullptr for any event + uint32_t num_broadcaster_names, uint32_t event_type_mask, + EventSP &event_sp) { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS)); + if (log != nullptr) + log->Printf("%p Listener::GetEventInternal (timeout = %llu us) for %s", + static_cast<void *>(this), static_cast<unsigned long long>( + timeout ? timeout->count() : -1), + m_name.c_str()); + + std::unique_lock<std::mutex> lock(m_events_mutex); + + while (true) { + if (FindNextEventInternal(lock, broadcaster, broadcaster_names, + num_broadcaster_names, event_type_mask, event_sp, + true)) { + return true; + } else { + std::cv_status result = std::cv_status::no_timeout; + if (!timeout) + m_events_condition.wait(lock); + else + result = m_events_condition.wait_for(lock, *timeout); + + if (result == std::cv_status::timeout) { + log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS); + if (log) + log->Printf("%p Listener::GetEventInternal() timed out for %s", + static_cast<void *>(this), m_name.c_str()); + return false; + } else if (result != std::cv_status::no_timeout) { + log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EVENTS); + if (log) + log->Printf("%p Listener::GetEventInternal() unknown error for %s", + static_cast<void *>(this), m_name.c_str()); + return false; + } } + } - return false; + return false; } -bool -Listener::WaitForEventForBroadcasterWithType(const TimeValue *timeout, - Broadcaster *broadcaster, - uint32_t event_type_mask, - EventSP &event_sp) -{ - return WaitForEventsInternal(timeout, broadcaster, nullptr, 0, event_type_mask, event_sp); +bool Listener::GetEventForBroadcasterWithType( + Broadcaster *broadcaster, uint32_t event_type_mask, EventSP &event_sp, + const Timeout<std::micro> &timeout) { + return GetEventInternal(timeout, broadcaster, nullptr, 0, event_type_mask, + event_sp); } -bool -Listener::WaitForEventForBroadcaster(const TimeValue *timeout, - Broadcaster *broadcaster, - EventSP &event_sp) -{ - return WaitForEventsInternal(timeout, broadcaster, nullptr, 0, 0, event_sp); +bool Listener::GetEventForBroadcaster(Broadcaster *broadcaster, + EventSP &event_sp, + const Timeout<std::micro> &timeout) { + return GetEventInternal(timeout, broadcaster, nullptr, 0, 0, event_sp); } -bool -Listener::WaitForEvent (const TimeValue *timeout, EventSP &event_sp) -{ - return WaitForEventsInternal(timeout, nullptr, nullptr, 0, 0, event_sp); +bool Listener::GetEvent(EventSP &event_sp, const Timeout<std::micro> &timeout) { + return GetEventInternal(timeout, nullptr, nullptr, 0, 0, event_sp); } -size_t -Listener::HandleBroadcastEvent (EventSP &event_sp) -{ - size_t num_handled = 0; - std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); - Broadcaster *broadcaster = event_sp->GetBroadcaster(); - if (!broadcaster) - return 0; - broadcaster_collection::iterator pos; - broadcaster_collection::iterator end = m_broadcasters.end(); - Broadcaster::BroadcasterImplSP broadcaster_impl_sp(broadcaster->GetBroadcasterImpl()); - for (pos = m_broadcasters.find (broadcaster_impl_sp); - pos != end && pos->first.lock() == broadcaster_impl_sp; - ++pos) - { - BroadcasterInfo info = pos->second; - if (event_sp->GetType () & info.event_mask) - { - if (info.callback != nullptr) - { - info.callback (event_sp, info.callback_user_data); - ++num_handled; - } - } +size_t Listener::HandleBroadcastEvent(EventSP &event_sp) { + size_t num_handled = 0; + std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); + Broadcaster *broadcaster = event_sp->GetBroadcaster(); + if (!broadcaster) + return 0; + broadcaster_collection::iterator pos; + broadcaster_collection::iterator end = m_broadcasters.end(); + Broadcaster::BroadcasterImplSP broadcaster_impl_sp( + broadcaster->GetBroadcasterImpl()); + for (pos = m_broadcasters.find(broadcaster_impl_sp); + pos != end && pos->first.lock() == broadcaster_impl_sp; ++pos) { + BroadcasterInfo info = pos->second; + if (event_sp->GetType() & info.event_mask) { + if (info.callback != nullptr) { + info.callback(event_sp, info.callback_user_data); + ++num_handled; + } } - return num_handled; + } + return num_handled; } uint32_t -Listener::StartListeningForEventSpec (BroadcasterManagerSP manager_sp, - const BroadcastEventSpec &event_spec) -{ - if (!manager_sp) - return 0; - - // The BroadcasterManager mutex must be locked before m_broadcasters_mutex - // to avoid violating the lock hierarchy (manager before broadcasters). - std::lock_guard<std::recursive_mutex> manager_guard(manager_sp->m_manager_mutex); - std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); - - uint32_t bits_acquired = manager_sp->RegisterListenerForEvents(this->shared_from_this(), event_spec); - if (bits_acquired) - { - broadcaster_manager_collection::iterator iter, end_iter = m_broadcaster_managers.end(); - BroadcasterManagerWP manager_wp(manager_sp); - BroadcasterManagerWPMatcher matcher(manager_sp); - iter = std::find_if<broadcaster_manager_collection::iterator, BroadcasterManagerWPMatcher>(m_broadcaster_managers.begin(), end_iter, matcher); - if (iter == end_iter) - m_broadcaster_managers.push_back(manager_wp); - } - - return bits_acquired; +Listener::StartListeningForEventSpec(BroadcasterManagerSP manager_sp, + const BroadcastEventSpec &event_spec) { + if (!manager_sp) + return 0; + + // The BroadcasterManager mutex must be locked before m_broadcasters_mutex + // to avoid violating the lock hierarchy (manager before broadcasters). + std::lock_guard<std::recursive_mutex> manager_guard( + manager_sp->m_manager_mutex); + std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); + + uint32_t bits_acquired = manager_sp->RegisterListenerForEvents( + this->shared_from_this(), event_spec); + if (bits_acquired) { + broadcaster_manager_collection::iterator iter, + end_iter = m_broadcaster_managers.end(); + BroadcasterManagerWP manager_wp(manager_sp); + BroadcasterManagerWPMatcher matcher(manager_sp); + iter = std::find_if<broadcaster_manager_collection::iterator, + BroadcasterManagerWPMatcher>( + m_broadcaster_managers.begin(), end_iter, matcher); + if (iter == end_iter) + m_broadcaster_managers.push_back(manager_wp); + } + + return bits_acquired; } - -bool -Listener::StopListeningForEventSpec (BroadcasterManagerSP manager_sp, - const BroadcastEventSpec &event_spec) -{ - if (!manager_sp) - return false; - std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); - return manager_sp->UnregisterListenerForEvents (this->shared_from_this(), event_spec); +bool Listener::StopListeningForEventSpec(BroadcasterManagerSP manager_sp, + const BroadcastEventSpec &event_spec) { + if (!manager_sp) + return false; + + std::lock_guard<std::recursive_mutex> guard(m_broadcasters_mutex); + return manager_sp->UnregisterListenerForEvents(this->shared_from_this(), + event_spec); } - -ListenerSP -Listener::MakeListener(const char *name) -{ - return ListenerSP(new Listener(name)); + +ListenerSP Listener::MakeListener(const char *name) { + return ListenerSP(new Listener(name)); } diff --git a/source/Core/Log.cpp b/source/Core/Log.cpp index a292df3ed525..b62df3c1fe97 100644 --- a/source/Core/Log.cpp +++ b/source/Core/Log.cpp @@ -7,20 +7,6 @@ // //===----------------------------------------------------------------------===// -// C Includes -// C++ Includes -#include <cstdarg> -#include <cstdio> -#include <cstdlib> -#include <map> -#include <mutex> -#include <string> - -// Other libraries and framework includes -#include "llvm/ADT/SmallString.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Signals.h" - // Project includes #include "lldb/Core/Log.h" #include "lldb/Core/PluginManager.h" @@ -28,69 +14,53 @@ #include "lldb/Core/StreamString.h" #include "lldb/Host/Host.h" #include "lldb/Host/ThisThread.h" -#include "lldb/Host/TimeValue.h" #include "lldb/Interpreter/Args.h" #include "lldb/Utility/NameMatches.h" +// Other libraries and framework includes +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Chrono.h" +#include "llvm/Support/Signals.h" +#include "llvm/Support/raw_ostream.h" + +// C Includes +// C++ Includes +#include <cstdarg> +#include <cstdio> +#include <cstdlib> +#include <map> +#include <mutex> +#include <string> + using namespace lldb; using namespace lldb_private; -Log::Log () : - m_stream_sp(), - m_options(0), - m_mask_bits(0) -{ -} +Log::Log() : m_stream_sp(), m_options(0), m_mask_bits(0) {} -Log::Log (const StreamSP &stream_sp) : - m_stream_sp(stream_sp), - m_options(0), - m_mask_bits(0) -{ -} +Log::Log(const StreamSP &stream_sp) + : m_stream_sp(stream_sp), m_options(0), m_mask_bits(0) {} Log::~Log() = default; -Flags & -Log::GetOptions() -{ - return m_options; -} +Flags &Log::GetOptions() { return m_options; } -const Flags & -Log::GetOptions() const -{ - return m_options; -} +const Flags &Log::GetOptions() const { return m_options; } -Flags & -Log::GetMask() -{ - return m_mask_bits; -} +Flags &Log::GetMask() { return m_mask_bits; } -const Flags & -Log::GetMask() const -{ - return m_mask_bits; -} +const Flags &Log::GetMask() const { return m_mask_bits; } -void -Log::PutCString(const char *cstr) -{ - Printf("%s", cstr); -} +void Log::PutCString(const char *cstr) { Printf("%s", cstr); } +void Log::PutString(llvm::StringRef str) { PutCString(str.str().c_str()); } //---------------------------------------------------------------------- // Simple variable argument logging with flags. //---------------------------------------------------------------------- -void -Log::Printf(const char *format, ...) -{ - va_list args; - va_start(args, format); - VAPrintf(format, args); - va_end(args); +void Log::Printf(const char *format, ...) { + va_list args; + va_start(args, format); + VAPrintf(format, args); + va_end(args); } //---------------------------------------------------------------------- @@ -98,459 +68,332 @@ Log::Printf(const char *format, ...) // a callback registered, then we call the logging callback. If we have // a valid file handle, we also log to the file. //---------------------------------------------------------------------- -void -Log::VAPrintf(const char *format, va_list args) -{ - // Make a copy of our stream shared pointer in case someone disables our - // log while we are logging and releases the stream - StreamSP stream_sp(m_stream_sp); - if (stream_sp) - { - static uint32_t g_sequence_id = 0; - StreamString header; - - // Add a sequence ID if requested - if (m_options.Test (LLDB_LOG_OPTION_PREPEND_SEQUENCE)) - header.Printf ("%u ", ++g_sequence_id); - - // Timestamp if requested - if (m_options.Test (LLDB_LOG_OPTION_PREPEND_TIMESTAMP)) - { - TimeValue now = TimeValue::Now(); - header.Printf ("%9d.%09.9d ", now.seconds(), now.nanoseconds()); - } - - // Add the process and thread if requested - if (m_options.Test (LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD)) - header.Printf ("[%4.4x/%4.4" PRIx64 "]: ", getpid(), Host::GetCurrentThreadID()); - - // Add the thread name if requested - if (m_options.Test (LLDB_LOG_OPTION_PREPEND_THREAD_NAME)) - { - llvm::SmallString<32> thread_name; - ThisThread::GetName(thread_name); - if (!thread_name.empty()) - header.Printf ("%s ", thread_name.c_str()); - } - - header.PrintfVarArg (format, args); - header.PutCString("\n"); - - if (m_options.Test(LLDB_LOG_OPTION_BACKTRACE)) - { - std::string back_trace; - llvm::raw_string_ostream stream(back_trace); - llvm::sys::PrintStackTrace(stream); - stream.flush(); - header.PutCString(back_trace.c_str()); - } - - if (m_options.Test(LLDB_LOG_OPTION_THREADSAFE)) - { - static std::recursive_mutex g_LogThreadedMutex; - std::lock_guard<std::recursive_mutex> guard(g_LogThreadedMutex); - stream_sp->PutCString(header.GetString().c_str()); - stream_sp->Flush(); - } - else - { - stream_sp->PutCString(header.GetString().c_str()); - stream_sp->Flush(); - } +void Log::VAPrintf(const char *format, va_list args) { + // Make a copy of our stream shared pointer in case someone disables our + // log while we are logging and releases the stream + StreamSP stream_sp(m_stream_sp); + if (stream_sp) { + static uint32_t g_sequence_id = 0; + StreamString header; + + // Add a sequence ID if requested + if (m_options.Test(LLDB_LOG_OPTION_PREPEND_SEQUENCE)) + header.Printf("%u ", ++g_sequence_id); + + // Timestamp if requested + if (m_options.Test(LLDB_LOG_OPTION_PREPEND_TIMESTAMP)) { + auto now = std::chrono::duration<double>( + std::chrono::system_clock::now().time_since_epoch()); + header.Printf("%.9f ", now.count()); } -} -//---------------------------------------------------------------------- -// Print debug strings if and only if the global debug option is set to -// a non-zero value. -//---------------------------------------------------------------------- -void -Log::Debug(const char *format, ...) -{ - if (!GetOptions().Test(LLDB_LOG_OPTION_DEBUG)) - return; - - va_list args; - va_start(args, format); - VAPrintf(format, args); - va_end(args); + // Add the process and thread if requested + if (m_options.Test(LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD)) + header.Printf("[%4.4x/%4.4" PRIx64 "]: ", getpid(), + Host::GetCurrentThreadID()); + + // Add the thread name if requested + if (m_options.Test(LLDB_LOG_OPTION_PREPEND_THREAD_NAME)) { + llvm::SmallString<32> thread_name; + ThisThread::GetName(thread_name); + if (!thread_name.empty()) + header.Printf("%s ", thread_name.c_str()); + } + + header.PrintfVarArg(format, args); + header.PutCString("\n"); + + if (m_options.Test(LLDB_LOG_OPTION_BACKTRACE)) { + std::string back_trace; + llvm::raw_string_ostream stream(back_trace); + llvm::sys::PrintStackTrace(stream); + stream.flush(); + header.PutCString(back_trace); + } + + if (m_options.Test(LLDB_LOG_OPTION_THREADSAFE)) { + static std::recursive_mutex g_LogThreadedMutex; + std::lock_guard<std::recursive_mutex> guard(g_LogThreadedMutex); + stream_sp->PutCString(header.GetString()); + stream_sp->Flush(); + } else { + stream_sp->PutCString(header.GetString()); + stream_sp->Flush(); + } + } } //---------------------------------------------------------------------- // Print debug strings if and only if the global debug option is set to // a non-zero value. //---------------------------------------------------------------------- -void -Log::DebugVerbose(const char *format, ...) -{ - if (!GetOptions().AllSet(LLDB_LOG_OPTION_DEBUG | LLDB_LOG_OPTION_VERBOSE)) - return; - - va_list args; - va_start(args, format); - VAPrintf(format, args); - va_end(args); +void Log::Debug(const char *format, ...) { + if (!GetOptions().Test(LLDB_LOG_OPTION_DEBUG)) + return; + + va_list args; + va_start(args, format); + VAPrintf(format, args); + va_end(args); } //---------------------------------------------------------------------- // Log only if all of the bits are set //---------------------------------------------------------------------- -void -Log::LogIf(uint32_t bits, const char *format, ...) -{ - if (!m_options.AllSet(bits)) - return; - - va_list args; - va_start(args, format); - VAPrintf(format, args); - va_end(args); +void Log::LogIf(uint32_t bits, const char *format, ...) { + if (!m_options.AllSet(bits)) + return; + + va_list args; + va_start(args, format); + VAPrintf(format, args); + va_end(args); } //---------------------------------------------------------------------- // Printing of errors that are not fatal. //---------------------------------------------------------------------- -void -Log::Error(const char *format, ...) -{ - va_list args; - va_start(args, format); - VAError(format, args); - va_end(args); +void Log::Error(const char *format, ...) { + va_list args; + va_start(args, format); + VAError(format, args); + va_end(args); } -void -Log::VAError(const char *format, va_list args) -{ - char *arg_msg = nullptr; - ::vasprintf(&arg_msg, format, args); - - if (arg_msg == nullptr) - return; +void Log::VAError(const char *format, va_list args) { + char *arg_msg = nullptr; + ::vasprintf(&arg_msg, format, args); - Printf("error: %s", arg_msg); - free(arg_msg); -} + if (arg_msg == nullptr) + return; -//---------------------------------------------------------------------- -// Printing of errors that ARE fatal. Exit with ERR exit code -// immediately. -//---------------------------------------------------------------------- -void -Log::FatalError(int err, const char *format, ...) -{ - char *arg_msg = nullptr; - va_list args; - va_start(args, format); - ::vasprintf(&arg_msg, format, args); - va_end(args); - - if (arg_msg != nullptr) - { - Printf("error: %s", arg_msg); - ::free(arg_msg); - } - ::exit(err); + Printf("error: %s", arg_msg); + free(arg_msg); } //---------------------------------------------------------------------- // Printing of warnings that are not fatal only if verbose mode is // enabled. //---------------------------------------------------------------------- -void -Log::Verbose(const char *format, ...) -{ - if (!m_options.Test(LLDB_LOG_OPTION_VERBOSE)) - return; - - va_list args; - va_start(args, format); - VAPrintf(format, args); - va_end(args); -} +void Log::Verbose(const char *format, ...) { + if (!m_options.Test(LLDB_LOG_OPTION_VERBOSE)) + return; -//---------------------------------------------------------------------- -// Printing of warnings that are not fatal only if verbose mode is -// enabled. -//---------------------------------------------------------------------- -void -Log::WarningVerbose(const char *format, ...) -{ - if (!m_options.Test(LLDB_LOG_OPTION_VERBOSE)) - return; - - char *arg_msg = nullptr; - va_list args; - va_start(args, format); - ::vasprintf(&arg_msg, format, args); - va_end(args); - - if (arg_msg == nullptr) - return; - - Printf("warning: %s", arg_msg); - free(arg_msg); + va_list args; + va_start(args, format); + VAPrintf(format, args); + va_end(args); } //---------------------------------------------------------------------- // Printing of warnings that are not fatal. //---------------------------------------------------------------------- -void -Log::Warning(const char *format, ...) -{ - char *arg_msg = nullptr; - va_list args; - va_start(args, format); - ::vasprintf(&arg_msg, format, args); - va_end(args); - - if (arg_msg == nullptr) - return; - - Printf("warning: %s", arg_msg); - free(arg_msg); +void Log::Warning(const char *format, ...) { + char *arg_msg = nullptr; + va_list args; + va_start(args, format); + ::vasprintf(&arg_msg, format, args); + va_end(args); + + if (arg_msg == nullptr) + return; + + Printf("warning: %s", arg_msg); + free(arg_msg); } -typedef std::map <ConstString, Log::Callbacks> CallbackMap; +typedef std::map<ConstString, Log::Callbacks> CallbackMap; typedef CallbackMap::iterator CallbackMapIter; -typedef std::map <ConstString, LogChannelSP> LogChannelMap; +typedef std::map<ConstString, LogChannelSP> LogChannelMap; typedef LogChannelMap::iterator LogChannelMapIter; // Surround our callback map with a singleton function so we don't have any // global initializers. -static CallbackMap & -GetCallbackMap () -{ - static CallbackMap g_callback_map; - return g_callback_map; -} - -static LogChannelMap & -GetChannelMap () -{ - static LogChannelMap g_channel_map; - return g_channel_map; -} - -void -Log::RegisterLogChannel (const ConstString &channel, const Log::Callbacks &log_callbacks) -{ - GetCallbackMap().insert(std::make_pair(channel, log_callbacks)); -} - -bool -Log::UnregisterLogChannel (const ConstString &channel) -{ - return GetCallbackMap().erase(channel) != 0; -} - -bool -Log::GetLogChannelCallbacks (const ConstString &channel, Log::Callbacks &log_callbacks) -{ - CallbackMap &callback_map = GetCallbackMap (); - CallbackMapIter pos = callback_map.find(channel); - if (pos != callback_map.end()) - { - log_callbacks = pos->second; - return true; +static CallbackMap &GetCallbackMap() { + static CallbackMap g_callback_map; + return g_callback_map; +} + +static LogChannelMap &GetChannelMap() { + static LogChannelMap g_channel_map; + return g_channel_map; +} + +void Log::RegisterLogChannel(const ConstString &channel, + const Log::Callbacks &log_callbacks) { + GetCallbackMap().insert(std::make_pair(channel, log_callbacks)); +} + +bool Log::UnregisterLogChannel(const ConstString &channel) { + return GetCallbackMap().erase(channel) != 0; +} + +bool Log::GetLogChannelCallbacks(const ConstString &channel, + Log::Callbacks &log_callbacks) { + CallbackMap &callback_map = GetCallbackMap(); + CallbackMapIter pos = callback_map.find(channel); + if (pos != callback_map.end()) { + log_callbacks = pos->second; + return true; + } + ::memset(&log_callbacks, 0, sizeof(log_callbacks)); + return false; +} + +bool Log::EnableLogChannel(lldb::StreamSP &log_stream_sp, uint32_t log_options, + const char *channel, const char **categories, + Stream &error_stream) { + Log::Callbacks log_callbacks; + if (Log::GetLogChannelCallbacks(ConstString(channel), log_callbacks)) { + log_callbacks.enable(log_stream_sp, log_options, categories, &error_stream); + return true; + } + + LogChannelSP log_channel_sp(LogChannel::FindPlugin(channel)); + if (log_channel_sp) { + if (log_channel_sp->Enable(log_stream_sp, log_options, &error_stream, + categories)) { + return true; + } else { + error_stream.Printf("Invalid log channel '%s'.\n", channel); + return false; } - ::memset (&log_callbacks, 0, sizeof(log_callbacks)); + } else { + error_stream.Printf("Invalid log channel '%s'.\n", channel); return false; -} - -bool -Log::EnableLogChannel(lldb::StreamSP &log_stream_sp, - uint32_t log_options, - const char *channel, - const char **categories, - Stream &error_stream) -{ - Log::Callbacks log_callbacks; - if (Log::GetLogChannelCallbacks (ConstString(channel), log_callbacks)) - { - log_callbacks.enable (log_stream_sp, log_options, categories, &error_stream); - return true; - } - - LogChannelSP log_channel_sp (LogChannel::FindPlugin (channel)); + } +} + +void Log::EnableAllLogChannels(StreamSP &log_stream_sp, uint32_t log_options, + const char **categories, Stream *feedback_strm) { + CallbackMap &callback_map = GetCallbackMap(); + CallbackMapIter pos, end = callback_map.end(); + + for (pos = callback_map.begin(); pos != end; ++pos) + pos->second.enable(log_stream_sp, log_options, categories, feedback_strm); + + LogChannelMap &channel_map = GetChannelMap(); + LogChannelMapIter channel_pos, channel_end = channel_map.end(); + for (channel_pos = channel_map.begin(); channel_pos != channel_end; + ++channel_pos) { + channel_pos->second->Enable(log_stream_sp, log_options, feedback_strm, + categories); + } +} + +void Log::AutoCompleteChannelName(const char *channel_name, + StringList &matches) { + LogChannelMap &map = GetChannelMap(); + LogChannelMapIter pos, end = map.end(); + for (pos = map.begin(); pos != end; ++pos) { + const char *pos_channel_name = pos->first.GetCString(); + if (channel_name && channel_name[0]) { + if (NameMatches(channel_name, eNameMatchStartsWith, pos_channel_name)) { + matches.AppendString(pos_channel_name); + } + } else + matches.AppendString(pos_channel_name); + } +} + +void Log::DisableAllLogChannels(Stream *feedback_strm) { + CallbackMap &callback_map = GetCallbackMap(); + CallbackMapIter pos, end = callback_map.end(); + const char *categories[] = {"all", nullptr}; + + for (pos = callback_map.begin(); pos != end; ++pos) + pos->second.disable(categories, feedback_strm); + + LogChannelMap &channel_map = GetChannelMap(); + LogChannelMapIter channel_pos, channel_end = channel_map.end(); + for (channel_pos = channel_map.begin(); channel_pos != channel_end; + ++channel_pos) + channel_pos->second->Disable(categories, feedback_strm); +} + +void Log::Initialize() { + Log::Callbacks log_callbacks = {DisableLog, EnableLog, ListLogCategories}; + Log::RegisterLogChannel(ConstString("lldb"), log_callbacks); +} + +void Log::Terminate() { DisableAllLogChannels(nullptr); } + +void Log::ListAllLogChannels(Stream *strm) { + CallbackMap &callback_map = GetCallbackMap(); + LogChannelMap &channel_map = GetChannelMap(); + + if (callback_map.empty() && channel_map.empty()) { + strm->PutCString("No logging channels are currently registered.\n"); + return; + } + + CallbackMapIter pos, end = callback_map.end(); + for (pos = callback_map.begin(); pos != end; ++pos) + pos->second.list_categories(strm); + + uint32_t idx = 0; + const char *name; + for (idx = 0; + (name = PluginManager::GetLogChannelCreateNameAtIndex(idx)) != nullptr; + ++idx) { + LogChannelSP log_channel_sp(LogChannel::FindPlugin(name)); if (log_channel_sp) - { - if (log_channel_sp->Enable (log_stream_sp, log_options, &error_stream, categories)) - { - return true; - } - else - { - error_stream.Printf ("Invalid log channel '%s'.\n", channel); - return false; - } - } - else - { - error_stream.Printf ("Invalid log channel '%s'.\n", channel); - return false; - } + log_channel_sp->ListCategories(strm); + } } -void -Log::EnableAllLogChannels(StreamSP &log_stream_sp, - uint32_t log_options, - const char **categories, - Stream *feedback_strm) -{ - CallbackMap &callback_map = GetCallbackMap (); - CallbackMapIter pos, end = callback_map.end(); - - for (pos = callback_map.begin(); pos != end; ++pos) - pos->second.enable (log_stream_sp, log_options, categories, feedback_strm); - - LogChannelMap &channel_map = GetChannelMap (); - LogChannelMapIter channel_pos, channel_end = channel_map.end(); - for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos) - { - channel_pos->second->Enable (log_stream_sp, log_options, feedback_strm, categories); - } -} - -void -Log::AutoCompleteChannelName (const char *channel_name, StringList &matches) -{ - LogChannelMap &map = GetChannelMap (); - LogChannelMapIter pos, end = map.end(); - for (pos = map.begin(); pos != end; ++pos) - { - const char *pos_channel_name = pos->first.GetCString(); - if (channel_name && channel_name[0]) - { - if (NameMatches (channel_name, eNameMatchStartsWith, pos_channel_name)) - { - matches.AppendString(pos_channel_name); - } - } - else - matches.AppendString(pos_channel_name); - } -} - -void -Log::DisableAllLogChannels (Stream *feedback_strm) -{ - CallbackMap &callback_map = GetCallbackMap (); - CallbackMapIter pos, end = callback_map.end(); - const char *categories[] = {"all", nullptr}; - - for (pos = callback_map.begin(); pos != end; ++pos) - pos->second.disable (categories, feedback_strm); - - LogChannelMap &channel_map = GetChannelMap (); - LogChannelMapIter channel_pos, channel_end = channel_map.end(); - for (channel_pos = channel_map.begin(); channel_pos != channel_end; ++channel_pos) - channel_pos->second->Disable (categories, feedback_strm); -} - -void -Log::Initialize() -{ - Log::Callbacks log_callbacks = { DisableLog, EnableLog, ListLogCategories }; - Log::RegisterLogChannel (ConstString("lldb"), log_callbacks); -} - -void -Log::Terminate () -{ - DisableAllLogChannels(nullptr); -} +bool Log::GetVerbose() const { + // FIXME: This has to be centralized between the stream and the log... + if (m_options.Test(LLDB_LOG_OPTION_VERBOSE)) + return true; -void -Log::ListAllLogChannels (Stream *strm) -{ - CallbackMap &callback_map = GetCallbackMap (); - LogChannelMap &channel_map = GetChannelMap (); - - if (callback_map.empty() && channel_map.empty()) - { - strm->PutCString ("No logging channels are currently registered.\n"); - return; - } - - CallbackMapIter pos, end = callback_map.end(); - for (pos = callback_map.begin(); pos != end; ++pos) - pos->second.list_categories (strm); - - uint32_t idx = 0; - const char *name; - for (idx = 0; (name = PluginManager::GetLogChannelCreateNameAtIndex (idx)) != nullptr; ++idx) - { - LogChannelSP log_channel_sp(LogChannel::FindPlugin (name)); - if (log_channel_sp) - log_channel_sp->ListCategories (strm); - } -} - -bool -Log::GetVerbose() const -{ - // FIXME: This has to be centralized between the stream and the log... - if (m_options.Test(LLDB_LOG_OPTION_VERBOSE)) - return true; - - // Make a copy of our stream shared pointer in case someone disables our - // log while we are logging and releases the stream - StreamSP stream_sp(m_stream_sp); - if (stream_sp) - return stream_sp->GetVerbose(); - return false; + // Make a copy of our stream shared pointer in case someone disables our + // log while we are logging and releases the stream + StreamSP stream_sp(m_stream_sp); + if (stream_sp) + return stream_sp->GetVerbose(); + return false; } //------------------------------------------------------------------ // Returns true if the debug flag bit is set in this stream. //------------------------------------------------------------------ -bool -Log::GetDebug() const -{ - // Make a copy of our stream shared pointer in case someone disables our - // log while we are logging and releases the stream - StreamSP stream_sp(m_stream_sp); - if (stream_sp) - return stream_sp->GetDebug(); - return false; -} - -LogChannelSP -LogChannel::FindPlugin (const char *plugin_name) -{ - LogChannelSP log_channel_sp; - LogChannelMap &channel_map = GetChannelMap (); - ConstString log_channel_name (plugin_name); - LogChannelMapIter pos = channel_map.find (log_channel_name); - if (pos == channel_map.end()) - { - ConstString const_plugin_name (plugin_name); - LogChannelCreateInstance create_callback = PluginManager::GetLogChannelCreateCallbackForPluginName (const_plugin_name); - if (create_callback) - { - log_channel_sp.reset(create_callback()); - if (log_channel_sp) - { - // Cache the one and only loaded instance of each log channel - // plug-in after it has been loaded once. - channel_map[log_channel_name] = log_channel_sp; - } - } - } - else - { - // We have already loaded an instance of this log channel class, - // so just return the cached instance. - log_channel_sp = pos->second; +bool Log::GetDebug() const { + // Make a copy of our stream shared pointer in case someone disables our + // log while we are logging and releases the stream + StreamSP stream_sp(m_stream_sp); + if (stream_sp) + return stream_sp->GetDebug(); + return false; +} + +LogChannelSP LogChannel::FindPlugin(const char *plugin_name) { + LogChannelSP log_channel_sp; + LogChannelMap &channel_map = GetChannelMap(); + ConstString log_channel_name(plugin_name); + LogChannelMapIter pos = channel_map.find(log_channel_name); + if (pos == channel_map.end()) { + ConstString const_plugin_name(plugin_name); + LogChannelCreateInstance create_callback = + PluginManager::GetLogChannelCreateCallbackForPluginName( + const_plugin_name); + if (create_callback) { + log_channel_sp.reset(create_callback()); + if (log_channel_sp) { + // Cache the one and only loaded instance of each log channel + // plug-in after it has been loaded once. + channel_map[log_channel_name] = log_channel_sp; + } } - return log_channel_sp; + } else { + // We have already loaded an instance of this log channel class, + // so just return the cached instance. + log_channel_sp = pos->second; + } + return log_channel_sp; } -LogChannel::LogChannel () : - m_log_ap () -{ -} +LogChannel::LogChannel() : m_log_ap() {} LogChannel::~LogChannel() = default; diff --git a/source/Core/Logging.cpp b/source/Core/Logging.cpp index 9eb4f6676a4d..4d63b60eeccd 100644 --- a/source/Core/Logging.cpp +++ b/source/Core/Logging.cpp @@ -1,4 +1,4 @@ -//===-- lldb-log.cpp --------------------------------------------*- C++ -*-===// +//===-- Logging.cpp ---------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,14 +11,14 @@ // C Includes // C++ Includes -#include <cstring> #include <atomic> +#include <cstring> // Other libraries and framework includes // Project includes -#include "lldb/Interpreter/Args.h" #include "lldb/Core/Log.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Interpreter/Args.h" using namespace lldb; using namespace lldb_private; @@ -28,254 +28,295 @@ using namespace lldb_private; // that will construct the static g_lob_sp the first time this function is // called. -static std::atomic<bool> g_log_enabled {false}; -static Log * g_log = nullptr; +static std::atomic<bool> g_log_enabled{false}; +static Log *g_log = nullptr; -static Log * -GetLog () -{ - if (!g_log_enabled) - return nullptr; - return g_log; +static Log *GetLog() { + if (!g_log_enabled) + return nullptr; + return g_log; } -uint32_t -lldb_private::GetLogMask () -{ - Log *log(GetLog ()); - if (log) - return log->GetMask().Get(); - return 0; +uint32_t lldb_private::GetLogMask() { + Log *log(GetLog()); + if (log) + return log->GetMask().Get(); + return 0; } -bool -lldb_private::IsLogVerbose () -{ - uint32_t mask = GetLogMask(); - return (mask & LIBLLDB_LOG_VERBOSE); +bool lldb_private::IsLogVerbose() { + uint32_t mask = GetLogMask(); + return (mask & LIBLLDB_LOG_VERBOSE); } -Log * -lldb_private::GetLogIfAllCategoriesSet (uint32_t mask) -{ - Log *log(GetLog ()); - if (log && mask) - { - uint32_t log_mask = log->GetMask().Get(); - if ((log_mask & mask) != mask) - return nullptr; - } - return log; +Log *lldb_private::GetLogIfAllCategoriesSet(uint32_t mask) { + Log *log(GetLog()); + if (log && mask) { + uint32_t log_mask = log->GetMask().Get(); + if ((log_mask & mask) != mask) + return nullptr; + } + return log; } -void -lldb_private::LogIfAllCategoriesSet (uint32_t mask, const char *format, ...) -{ - Log *log(GetLogIfAllCategoriesSet (mask)); - if (log) - { - va_list args; - va_start (args, format); - log->VAPrintf (format, args); - va_end (args); - } +void lldb_private::LogIfAllCategoriesSet(uint32_t mask, const char *format, + ...) { + Log *log(GetLogIfAllCategoriesSet(mask)); + if (log) { + va_list args; + va_start(args, format); + log->VAPrintf(format, args); + va_end(args); + } } -void -lldb_private::LogIfAnyCategoriesSet (uint32_t mask, const char *format, ...) -{ - Log *log(GetLogIfAnyCategoriesSet (mask)); - if (log != nullptr) - { - va_list args; - va_start (args, format); - log->VAPrintf (format, args); - va_end (args); - } +void lldb_private::LogIfAnyCategoriesSet(uint32_t mask, const char *format, + ...) { + Log *log(GetLogIfAnyCategoriesSet(mask)); + if (log != nullptr) { + va_list args; + va_start(args, format); + log->VAPrintf(format, args); + va_end(args); + } } -Log * -lldb_private::GetLogIfAnyCategoriesSet (uint32_t mask) -{ - Log *log(GetLog ()); - if (log != nullptr && mask && (mask & log->GetMask().Get())) - return log; - return nullptr; +Log *lldb_private::GetLogIfAnyCategoriesSet(uint32_t mask) { + Log *log(GetLog()); + if (log != nullptr && mask && (mask & log->GetMask().Get())) + return log; + return nullptr; } -void -lldb_private::DisableLog (const char **categories, Stream *feedback_strm) -{ - Log *log(GetLog ()); +void lldb_private::DisableLog(const char **categories, Stream *feedback_strm) { + Log *log(GetLog()); - if (log != nullptr) - { - uint32_t flag_bits = 0; - if (categories[0] != nullptr) - { - flag_bits = log->GetMask().Get(); - for (size_t i = 0; categories[i] != nullptr; ++i) - { - const char *arg = categories[i]; + if (log != nullptr) { + uint32_t flag_bits = 0; + if (categories && categories[0]) { + flag_bits = log->GetMask().Get(); + for (size_t i = 0; categories[i] != nullptr; ++i) { + const char *arg = categories[i]; - if (0 == ::strcasecmp(arg, "all")) flag_bits &= ~LIBLLDB_LOG_ALL; - else if (0 == ::strcasecmp(arg, "api")) flag_bits &= ~LIBLLDB_LOG_API; - else if (0 == ::strncasecmp(arg, "break", 5)) flag_bits &= ~LIBLLDB_LOG_BREAKPOINTS; - else if (0 == ::strcasecmp(arg, "commands")) flag_bits &= ~LIBLLDB_LOG_COMMANDS; - else if (0 == ::strcasecmp(arg, "default")) flag_bits &= ~LIBLLDB_LOG_DEFAULT; - else if (0 == ::strcasecmp(arg, "dyld")) flag_bits &= ~LIBLLDB_LOG_DYNAMIC_LOADER; - else if (0 == ::strncasecmp(arg, "event", 5)) flag_bits &= ~LIBLLDB_LOG_EVENTS; - else if (0 == ::strncasecmp(arg, "expr", 4)) flag_bits &= ~LIBLLDB_LOG_EXPRESSIONS; - else if (0 == ::strncasecmp(arg, "object", 6)) flag_bits &= ~LIBLLDB_LOG_OBJECT; - else if (0 == ::strcasecmp(arg, "process")) flag_bits &= ~LIBLLDB_LOG_PROCESS; - else if (0 == ::strcasecmp(arg, "platform")) flag_bits &= ~LIBLLDB_LOG_PLATFORM; - else if (0 == ::strcasecmp(arg, "script")) flag_bits &= ~LIBLLDB_LOG_SCRIPT; - else if (0 == ::strcasecmp(arg, "state")) flag_bits &= ~LIBLLDB_LOG_STATE; - else if (0 == ::strcasecmp(arg, "step")) flag_bits &= ~LIBLLDB_LOG_STEP; - else if (0 == ::strcasecmp(arg, "thread")) flag_bits &= ~LIBLLDB_LOG_THREAD; - else if (0 == ::strcasecmp(arg, "target")) flag_bits &= ~LIBLLDB_LOG_TARGET; - else if (0 == ::strcasecmp(arg, "verbose")) flag_bits &= ~LIBLLDB_LOG_VERBOSE; - else if (0 == ::strncasecmp(arg, "watch", 5)) flag_bits &= ~LIBLLDB_LOG_WATCHPOINTS; - else if (0 == ::strncasecmp(arg, "temp", 4)) flag_bits &= ~LIBLLDB_LOG_TEMPORARY; - else if (0 == ::strncasecmp(arg, "comm", 4)) flag_bits &= ~LIBLLDB_LOG_COMMUNICATION; - else if (0 == ::strncasecmp(arg, "conn", 4)) flag_bits &= ~LIBLLDB_LOG_CONNECTION; - else if (0 == ::strncasecmp(arg, "host", 4)) flag_bits &= ~LIBLLDB_LOG_HOST; - else if (0 == ::strncasecmp(arg, "unwind", 6)) flag_bits &= ~LIBLLDB_LOG_UNWIND; - else if (0 == ::strncasecmp(arg, "types", 5)) flag_bits &= ~LIBLLDB_LOG_TYPES; - else if (0 == ::strncasecmp(arg, "symbol", 6)) flag_bits &= ~LIBLLDB_LOG_SYMBOLS; - else if (0 == ::strcasecmp(arg, "system-runtime")) flag_bits &= ~LIBLLDB_LOG_SYSTEM_RUNTIME; - else if (0 == ::strncasecmp(arg, "module", 6)) flag_bits &= ~LIBLLDB_LOG_MODULES; - else if (0 == ::strncasecmp(arg, "mmap", 4)) flag_bits &= ~LIBLLDB_LOG_MMAP; - else if (0 == ::strcasecmp(arg, "os")) flag_bits &= ~LIBLLDB_LOG_OS; - else if (0 == ::strcasecmp(arg, "jit")) flag_bits &= ~LIBLLDB_LOG_JIT_LOADER; - else if (0 == ::strcasecmp(arg, "language")) flag_bits &= ~LIBLLDB_LOG_LANGUAGE; - else if (0 == ::strncasecmp(arg, "formatters", 10)) flag_bits &= ~LIBLLDB_LOG_DATAFORMATTERS; - else if (0 == ::strncasecmp(arg, "demangle", 8)) flag_bits &= ~LIBLLDB_LOG_DEMANGLE; - else - { - feedback_strm->Printf ("error: unrecognized log category '%s'\n", arg); - ListLogCategories (feedback_strm); - return; - } - } - } - log->GetMask().Reset (flag_bits); - if (flag_bits == 0) - { - log->SetStream(lldb::StreamSP()); - g_log_enabled = false; + if (0 == ::strcasecmp(arg, "all")) + flag_bits &= ~LIBLLDB_LOG_ALL; + else if (0 == ::strcasecmp(arg, "api")) + flag_bits &= ~LIBLLDB_LOG_API; + else if (0 == ::strncasecmp(arg, "break", 5)) + flag_bits &= ~LIBLLDB_LOG_BREAKPOINTS; + else if (0 == ::strcasecmp(arg, "commands")) + flag_bits &= ~LIBLLDB_LOG_COMMANDS; + else if (0 == ::strcasecmp(arg, "default")) + flag_bits &= ~LIBLLDB_LOG_DEFAULT; + else if (0 == ::strcasecmp(arg, "dyld")) + flag_bits &= ~LIBLLDB_LOG_DYNAMIC_LOADER; + else if (0 == ::strncasecmp(arg, "event", 5)) + flag_bits &= ~LIBLLDB_LOG_EVENTS; + else if (0 == ::strncasecmp(arg, "expr", 4)) + flag_bits &= ~LIBLLDB_LOG_EXPRESSIONS; + else if (0 == ::strncasecmp(arg, "object", 6)) + flag_bits &= ~LIBLLDB_LOG_OBJECT; + else if (0 == ::strcasecmp(arg, "process")) + flag_bits &= ~LIBLLDB_LOG_PROCESS; + else if (0 == ::strcasecmp(arg, "platform")) + flag_bits &= ~LIBLLDB_LOG_PLATFORM; + else if (0 == ::strcasecmp(arg, "script")) + flag_bits &= ~LIBLLDB_LOG_SCRIPT; + else if (0 == ::strcasecmp(arg, "state")) + flag_bits &= ~LIBLLDB_LOG_STATE; + else if (0 == ::strcasecmp(arg, "step")) + flag_bits &= ~LIBLLDB_LOG_STEP; + else if (0 == ::strcasecmp(arg, "thread")) + flag_bits &= ~LIBLLDB_LOG_THREAD; + else if (0 == ::strcasecmp(arg, "target")) + flag_bits &= ~LIBLLDB_LOG_TARGET; + else if (0 == ::strcasecmp(arg, "verbose")) + flag_bits &= ~LIBLLDB_LOG_VERBOSE; + else if (0 == ::strncasecmp(arg, "watch", 5)) + flag_bits &= ~LIBLLDB_LOG_WATCHPOINTS; + else if (0 == ::strncasecmp(arg, "temp", 4)) + flag_bits &= ~LIBLLDB_LOG_TEMPORARY; + else if (0 == ::strncasecmp(arg, "comm", 4)) + flag_bits &= ~LIBLLDB_LOG_COMMUNICATION; + else if (0 == ::strncasecmp(arg, "conn", 4)) + flag_bits &= ~LIBLLDB_LOG_CONNECTION; + else if (0 == ::strncasecmp(arg, "host", 4)) + flag_bits &= ~LIBLLDB_LOG_HOST; + else if (0 == ::strncasecmp(arg, "unwind", 6)) + flag_bits &= ~LIBLLDB_LOG_UNWIND; + else if (0 == ::strncasecmp(arg, "types", 5)) + flag_bits &= ~LIBLLDB_LOG_TYPES; + else if (0 == ::strncasecmp(arg, "symbol", 6)) + flag_bits &= ~LIBLLDB_LOG_SYMBOLS; + else if (0 == ::strcasecmp(arg, "system-runtime")) + flag_bits &= ~LIBLLDB_LOG_SYSTEM_RUNTIME; + else if (0 == ::strncasecmp(arg, "module", 6)) + flag_bits &= ~LIBLLDB_LOG_MODULES; + else if (0 == ::strncasecmp(arg, "mmap", 4)) + flag_bits &= ~LIBLLDB_LOG_MMAP; + else if (0 == ::strcasecmp(arg, "os")) + flag_bits &= ~LIBLLDB_LOG_OS; + else if (0 == ::strcasecmp(arg, "jit")) + flag_bits &= ~LIBLLDB_LOG_JIT_LOADER; + else if (0 == ::strcasecmp(arg, "language")) + flag_bits &= ~LIBLLDB_LOG_LANGUAGE; + else if (0 == ::strncasecmp(arg, "formatters", 10)) + flag_bits &= ~LIBLLDB_LOG_DATAFORMATTERS; + else if (0 == ::strncasecmp(arg, "demangle", 8)) + flag_bits &= ~LIBLLDB_LOG_DEMANGLE; + else { + feedback_strm->Printf("error: unrecognized log category '%s'\n", + arg); + ListLogCategories(feedback_strm); + return; } + } + } + log->GetMask().Reset(flag_bits); + if (flag_bits == 0) { + log->SetStream(lldb::StreamSP()); + g_log_enabled = false; } + } } -Log * -lldb_private::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **categories, Stream *feedback_strm) -{ - // Try see if there already is a log - that way we can reuse its settings. - // We could reuse the log in toto, but we don't know that the stream is the same. - uint32_t flag_bits; - if (g_log != nullptr) - flag_bits = g_log->GetMask().Get(); - else - flag_bits = 0; - - // Now make a new log with this stream if one was provided - if (log_stream_sp) - { - if (g_log != nullptr) - g_log->SetStream(log_stream_sp); - else - g_log = new Log(log_stream_sp); - } +Log *lldb_private::EnableLog(StreamSP &log_stream_sp, uint32_t log_options, + const char **categories, Stream *feedback_strm) { + // Try see if there already is a log - that way we can reuse its settings. + // We could reuse the log in toto, but we don't know that the stream is the + // same. + uint32_t flag_bits; + if (g_log != nullptr) + flag_bits = g_log->GetMask().Get(); + else + flag_bits = 0; + // Now make a new log with this stream if one was provided + if (log_stream_sp) { if (g_log != nullptr) - { - for (size_t i = 0; categories[i] != nullptr; ++i) - { - const char *arg = categories[i]; + g_log->SetStream(log_stream_sp); + else + g_log = new Log(log_stream_sp); + } - if (0 == ::strcasecmp(arg, "all")) flag_bits |= LIBLLDB_LOG_ALL; - else if (0 == ::strcasecmp(arg, "api")) flag_bits |= LIBLLDB_LOG_API; - else if (0 == ::strncasecmp(arg, "break", 5)) flag_bits |= LIBLLDB_LOG_BREAKPOINTS; - else if (0 == ::strcasecmp(arg, "commands")) flag_bits |= LIBLLDB_LOG_COMMANDS; - else if (0 == ::strncasecmp(arg, "commu", 5)) flag_bits |= LIBLLDB_LOG_COMMUNICATION; - else if (0 == ::strncasecmp(arg, "conn", 4)) flag_bits |= LIBLLDB_LOG_CONNECTION; - else if (0 == ::strcasecmp(arg, "default")) flag_bits |= LIBLLDB_LOG_DEFAULT; - else if (0 == ::strcasecmp(arg, "dyld")) flag_bits |= LIBLLDB_LOG_DYNAMIC_LOADER; - else if (0 == ::strncasecmp(arg, "event", 5)) flag_bits |= LIBLLDB_LOG_EVENTS; - else if (0 == ::strncasecmp(arg, "expr", 4)) flag_bits |= LIBLLDB_LOG_EXPRESSIONS; - else if (0 == ::strncasecmp(arg, "host", 4)) flag_bits |= LIBLLDB_LOG_HOST; - else if (0 == ::strncasecmp(arg, "mmap", 4)) flag_bits |= LIBLLDB_LOG_MMAP; - else if (0 == ::strncasecmp(arg, "module", 6)) flag_bits |= LIBLLDB_LOG_MODULES; - else if (0 == ::strncasecmp(arg, "object", 6)) flag_bits |= LIBLLDB_LOG_OBJECT; - else if (0 == ::strcasecmp(arg, "os")) flag_bits |= LIBLLDB_LOG_OS; - else if (0 == ::strcasecmp(arg, "platform")) flag_bits |= LIBLLDB_LOG_PLATFORM; - else if (0 == ::strcasecmp(arg, "process")) flag_bits |= LIBLLDB_LOG_PROCESS; - else if (0 == ::strcasecmp(arg, "script")) flag_bits |= LIBLLDB_LOG_SCRIPT; - else if (0 == ::strcasecmp(arg, "state")) flag_bits |= LIBLLDB_LOG_STATE; - else if (0 == ::strcasecmp(arg, "step")) flag_bits |= LIBLLDB_LOG_STEP; - else if (0 == ::strncasecmp(arg, "symbol", 6)) flag_bits |= LIBLLDB_LOG_SYMBOLS; - else if (0 == ::strcasecmp(arg, "system-runtime")) flag_bits |= LIBLLDB_LOG_SYSTEM_RUNTIME; - else if (0 == ::strcasecmp(arg, "target")) flag_bits |= LIBLLDB_LOG_TARGET; - else if (0 == ::strncasecmp(arg, "temp", 4)) flag_bits |= LIBLLDB_LOG_TEMPORARY; - else if (0 == ::strcasecmp(arg, "thread")) flag_bits |= LIBLLDB_LOG_THREAD; - else if (0 == ::strncasecmp(arg, "types", 5)) flag_bits |= LIBLLDB_LOG_TYPES; - else if (0 == ::strncasecmp(arg, "unwind", 6)) flag_bits |= LIBLLDB_LOG_UNWIND; - else if (0 == ::strcasecmp(arg, "verbose")) flag_bits |= LIBLLDB_LOG_VERBOSE; - else if (0 == ::strncasecmp(arg, "watch", 5)) flag_bits |= LIBLLDB_LOG_WATCHPOINTS; - else if (0 == ::strcasecmp(arg, "jit")) flag_bits |= LIBLLDB_LOG_JIT_LOADER; - else if (0 == ::strcasecmp(arg, "language")) flag_bits |= LIBLLDB_LOG_LANGUAGE; - else if (0 == ::strncasecmp(arg, "formatters", 10)) flag_bits |= LIBLLDB_LOG_DATAFORMATTERS; - else if (0 == ::strncasecmp(arg, "demangle", 8)) flag_bits |= LIBLLDB_LOG_DEMANGLE; - else - { - feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); - ListLogCategories (feedback_strm); - return g_log; - } - } + if (g_log != nullptr) { + for (size_t i = 0; categories[i] != nullptr; ++i) { + const char *arg = categories[i]; - g_log->GetMask().Reset(flag_bits); - g_log->GetOptions().Reset(log_options); + if (0 == ::strcasecmp(arg, "all")) + flag_bits |= LIBLLDB_LOG_ALL; + else if (0 == ::strcasecmp(arg, "api")) + flag_bits |= LIBLLDB_LOG_API; + else if (0 == ::strncasecmp(arg, "break", 5)) + flag_bits |= LIBLLDB_LOG_BREAKPOINTS; + else if (0 == ::strcasecmp(arg, "commands")) + flag_bits |= LIBLLDB_LOG_COMMANDS; + else if (0 == ::strncasecmp(arg, "commu", 5)) + flag_bits |= LIBLLDB_LOG_COMMUNICATION; + else if (0 == ::strncasecmp(arg, "conn", 4)) + flag_bits |= LIBLLDB_LOG_CONNECTION; + else if (0 == ::strcasecmp(arg, "default")) + flag_bits |= LIBLLDB_LOG_DEFAULT; + else if (0 == ::strcasecmp(arg, "dyld")) + flag_bits |= LIBLLDB_LOG_DYNAMIC_LOADER; + else if (0 == ::strncasecmp(arg, "event", 5)) + flag_bits |= LIBLLDB_LOG_EVENTS; + else if (0 == ::strncasecmp(arg, "expr", 4)) + flag_bits |= LIBLLDB_LOG_EXPRESSIONS; + else if (0 == ::strncasecmp(arg, "host", 4)) + flag_bits |= LIBLLDB_LOG_HOST; + else if (0 == ::strncasecmp(arg, "mmap", 4)) + flag_bits |= LIBLLDB_LOG_MMAP; + else if (0 == ::strncasecmp(arg, "module", 6)) + flag_bits |= LIBLLDB_LOG_MODULES; + else if (0 == ::strncasecmp(arg, "object", 6)) + flag_bits |= LIBLLDB_LOG_OBJECT; + else if (0 == ::strcasecmp(arg, "os")) + flag_bits |= LIBLLDB_LOG_OS; + else if (0 == ::strcasecmp(arg, "platform")) + flag_bits |= LIBLLDB_LOG_PLATFORM; + else if (0 == ::strcasecmp(arg, "process")) + flag_bits |= LIBLLDB_LOG_PROCESS; + else if (0 == ::strcasecmp(arg, "script")) + flag_bits |= LIBLLDB_LOG_SCRIPT; + else if (0 == ::strcasecmp(arg, "state")) + flag_bits |= LIBLLDB_LOG_STATE; + else if (0 == ::strcasecmp(arg, "step")) + flag_bits |= LIBLLDB_LOG_STEP; + else if (0 == ::strncasecmp(arg, "symbol", 6)) + flag_bits |= LIBLLDB_LOG_SYMBOLS; + else if (0 == ::strcasecmp(arg, "system-runtime")) + flag_bits |= LIBLLDB_LOG_SYSTEM_RUNTIME; + else if (0 == ::strcasecmp(arg, "target")) + flag_bits |= LIBLLDB_LOG_TARGET; + else if (0 == ::strncasecmp(arg, "temp", 4)) + flag_bits |= LIBLLDB_LOG_TEMPORARY; + else if (0 == ::strcasecmp(arg, "thread")) + flag_bits |= LIBLLDB_LOG_THREAD; + else if (0 == ::strncasecmp(arg, "types", 5)) + flag_bits |= LIBLLDB_LOG_TYPES; + else if (0 == ::strncasecmp(arg, "unwind", 6)) + flag_bits |= LIBLLDB_LOG_UNWIND; + else if (0 == ::strcasecmp(arg, "verbose")) + flag_bits |= LIBLLDB_LOG_VERBOSE; + else if (0 == ::strncasecmp(arg, "watch", 5)) + flag_bits |= LIBLLDB_LOG_WATCHPOINTS; + else if (0 == ::strcasecmp(arg, "jit")) + flag_bits |= LIBLLDB_LOG_JIT_LOADER; + else if (0 == ::strcasecmp(arg, "language")) + flag_bits |= LIBLLDB_LOG_LANGUAGE; + else if (0 == ::strncasecmp(arg, "formatters", 10)) + flag_bits |= LIBLLDB_LOG_DATAFORMATTERS; + else if (0 == ::strncasecmp(arg, "demangle", 8)) + flag_bits |= LIBLLDB_LOG_DEMANGLE; + else { + feedback_strm->Printf("error: unrecognized log category '%s'\n", arg); + ListLogCategories(feedback_strm); + return g_log; + } } - g_log_enabled = true; - return g_log; + + g_log->GetMask().Reset(flag_bits); + g_log->GetOptions().Reset(log_options); + } + g_log_enabled = true; + return g_log; } -void -lldb_private::ListLogCategories (Stream *strm) -{ - strm->Printf("Logging categories for 'lldb':\n" - " all - turn on all available logging categories\n" - " api - enable logging of API calls and return values\n" - " break - log breakpoints\n" - " commands - log command argument parsing\n" - " communication - log communication activities\n" - " connection - log connection details\n" - " default - enable the default set of logging categories for liblldb\n" - " demangle - log mangled names to catch demangler crashes\n" - " dyld - log shared library related activities\n" - " events - log broadcaster, listener and event queue activities\n" - " expr - log expressions\n" - " formatters - log data formatters related activities\n" - " host - log host activities\n" - " jit - log JIT events in the target\n" - " language - log language runtime events\n" - " mmap - log mmap related activities\n" - " module - log module activities such as when modules are created, destroyed, replaced, and more\n" - " object - log object construction/destruction for important objects\n" - " os - log OperatingSystem plugin related activities\n" - " platform - log platform events and activities\n" - " process - log process events and activities\n" - " script - log events about the script interpreter\n" - " state - log private and public process state changes\n" - " step - log step related activities\n" - " symbol - log symbol related issues and warnings\n" - " system-runtime - log system runtime events\n" - " target - log target events and activities\n" - " thread - log thread events and activities\n" - " types - log type system related activities\n" - " unwind - log stack unwind activities\n" - " verbose - enable verbose logging\n" - " watch - log watchpoint related activities\n"); +void lldb_private::ListLogCategories(Stream *strm) { + strm->Printf( + "Logging categories for 'lldb':\n" + " all - turn on all available logging categories\n" + " api - enable logging of API calls and return values\n" + " break - log breakpoints\n" + " commands - log command argument parsing\n" + " communication - log communication activities\n" + " connection - log connection details\n" + " default - enable the default set of logging categories for liblldb\n" + " demangle - log mangled names to catch demangler crashes\n" + " dyld - log shared library related activities\n" + " events - log broadcaster, listener and event queue activities\n" + " expr - log expressions\n" + " formatters - log data formatters related activities\n" + " host - log host activities\n" + " jit - log JIT events in the target\n" + " language - log language runtime events\n" + " mmap - log mmap related activities\n" + " module - log module activities such as when modules are created, " + "destroyed, replaced, and more\n" + " object - log object construction/destruction for important objects\n" + " os - log OperatingSystem plugin related activities\n" + " platform - log platform events and activities\n" + " process - log process events and activities\n" + " script - log events about the script interpreter\n" + " state - log private and public process state changes\n" + " step - log step related activities\n" + " symbol - log symbol related issues and warnings\n" + " system-runtime - log system runtime events\n" + " target - log target events and activities\n" + " thread - log thread events and activities\n" + " types - log type system related activities\n" + " unwind - log stack unwind activities\n" + " verbose - enable verbose logging\n" + " watch - log watchpoint related activities\n"); } diff --git a/source/Core/Mangled.cpp b/source/Core/Mangled.cpp index 543b34e337a2..c2c63b665639 100644 --- a/source/Core/Mangled.cpp +++ b/source/Core/Mangled.cpp @@ -7,32 +7,27 @@ // //===----------------------------------------------------------------------===// - // FreeBSD9-STABLE requires this to know about size_t in cxxabi.h #include <cstddef> -#if defined(_MSC_VER) +#if defined(_WIN32) #include "lldb/Host/windows/windows.h" -#include <Dbghelp.h> +#include <dbghelp.h> #pragma comment(lib, "dbghelp.lib") -#define LLDB_USE_BUILTIN_DEMANGLER -#elif defined (__FreeBSD__) -#define LLDB_USE_BUILTIN_DEMANGLER -#else -#include <cxxabi.h> #endif #ifdef LLDB_USE_BUILTIN_DEMANGLER - // Provide a fast-path demangler implemented in FastDemangle.cpp until it can // replace the existing C++ demangler with a complete implementation +#include "llvm/Demangle/Demangle.h" #include "lldb/Core/FastDemangle.h" -#include "lldb/Core/CxaDemangle.h" - +#else +#include <cxxabi.h> #endif - #include "llvm/ADT/DenseMap.h" +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" +#include "Plugins/Language/ObjC/ObjCLanguage.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Log.h" #include "lldb/Core/Logging.h" @@ -40,119 +35,114 @@ #include "lldb/Core/RegularExpression.h" #include "lldb/Core/Stream.h" #include "lldb/Core/Timer.h" -#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" -#include "Plugins/Language/ObjC/ObjCLanguage.h" #include <ctype.h> -#include <string.h> #include <stdlib.h> - +#include <string.h> using namespace lldb_private; -static inline Mangled::ManglingScheme -cstring_mangling_scheme(const char *s) -{ - if (s) - { - if (s[0] == '?') - return Mangled::eManglingSchemeMSVC; - if (s[0] == '_' && s[1] == 'Z') - return Mangled::eManglingSchemeItanium; - } - return Mangled::eManglingSchemeNone; +static inline Mangled::ManglingScheme cstring_mangling_scheme(const char *s) { + if (s) { + if (s[0] == '?') + return Mangled::eManglingSchemeMSVC; + if (s[0] == '_' && s[1] == 'Z') + return Mangled::eManglingSchemeItanium; + } + return Mangled::eManglingSchemeNone; } -static inline bool -cstring_is_mangled(const char *s) -{ - return cstring_mangling_scheme(s) != Mangled::eManglingSchemeNone; +static inline bool cstring_is_mangled(const char *s) { + return cstring_mangling_scheme(s) != Mangled::eManglingSchemeNone; } static const ConstString & -get_demangled_name_without_arguments (ConstString mangled, ConstString demangled) -{ - // This pair is <mangled name, demangled name without function arguments> - static std::pair<ConstString, ConstString> g_most_recent_mangled_to_name_sans_args; - - // Need to have the mangled & demangled names we're currently examining as statics - // so we can return a const ref to them at the end of the func if we don't have - // anything better. - static ConstString g_last_mangled; - static ConstString g_last_demangled; - - if (mangled && g_most_recent_mangled_to_name_sans_args.first == mangled) +get_demangled_name_without_arguments(ConstString mangled, + ConstString demangled) { + // This pair is <mangled name, demangled name without function arguments> + static std::pair<ConstString, ConstString> + g_most_recent_mangled_to_name_sans_args; + + // Need to have the mangled & demangled names we're currently examining as + // statics + // so we can return a const ref to them at the end of the func if we don't + // have + // anything better. + static ConstString g_last_mangled; + static ConstString g_last_demangled; + + if (mangled && g_most_recent_mangled_to_name_sans_args.first == mangled) { + return g_most_recent_mangled_to_name_sans_args.second; + } + + g_last_demangled = demangled; + g_last_mangled = mangled; + + const char *mangled_name_cstr = mangled.GetCString(); + + if (demangled && mangled_name_cstr && mangled_name_cstr[0]) { + if (mangled_name_cstr[0] == '_' && mangled_name_cstr[1] == 'Z' && + (mangled_name_cstr[2] != 'T' && // avoid virtual table, VTT structure, + // typeinfo structure, and typeinfo + // mangled_name + mangled_name_cstr[2] != 'G' && // avoid guard variables + mangled_name_cstr[2] != 'Z')) // named local entities (if we eventually + // handle eSymbolTypeData, we will want + // this back) { + CPlusPlusLanguage::MethodName cxx_method(demangled); + if (!cxx_method.GetBasename().empty()) { + std::string shortname; + if (!cxx_method.GetContext().empty()) + shortname = cxx_method.GetContext().str() + "::"; + shortname += cxx_method.GetBasename().str(); + ConstString result(shortname.c_str()); + g_most_recent_mangled_to_name_sans_args.first = mangled; + g_most_recent_mangled_to_name_sans_args.second = result; return g_most_recent_mangled_to_name_sans_args.second; + } } + } - g_last_demangled = demangled; - g_last_mangled = mangled; - - const char *mangled_name_cstr = mangled.GetCString(); - - if (demangled && mangled_name_cstr && mangled_name_cstr[0]) - { - if (mangled_name_cstr[0] == '_' && mangled_name_cstr[1] == 'Z' && - (mangled_name_cstr[2] != 'T' && // avoid virtual table, VTT structure, typeinfo structure, and typeinfo mangled_name - mangled_name_cstr[2] != 'G' && // avoid guard variables - mangled_name_cstr[2] != 'Z')) // named local entities (if we eventually handle eSymbolTypeData, we will want this back) - { - CPlusPlusLanguage::MethodName cxx_method (demangled); - if (!cxx_method.GetBasename().empty()) - { - std::string shortname; - if (!cxx_method.GetContext().empty()) - shortname = cxx_method.GetContext().str() + "::"; - shortname += cxx_method.GetBasename().str(); - ConstString result(shortname.c_str()); - g_most_recent_mangled_to_name_sans_args.first = mangled; - g_most_recent_mangled_to_name_sans_args.second = result; - return g_most_recent_mangled_to_name_sans_args.second; - } - } - } - - if (demangled) - return g_last_demangled; - return g_last_mangled; + if (demangled) + return g_last_demangled; + return g_last_mangled; } #pragma mark Mangled //---------------------------------------------------------------------- // Default constructor //---------------------------------------------------------------------- -Mangled::Mangled () : - m_mangled(), - m_demangled() -{ -} +Mangled::Mangled() : m_mangled(), m_demangled() {} //---------------------------------------------------------------------- // Constructor with an optional string and a boolean indicating if it is // the mangled version. //---------------------------------------------------------------------- -Mangled::Mangled (const ConstString &s, bool mangled) : - m_mangled(), - m_demangled() -{ - if (s) - SetValue(s, mangled); +Mangled::Mangled(const ConstString &s, bool mangled) + : m_mangled(), m_demangled() { + if (s) + SetValue(s, mangled); +} + +Mangled::Mangled(llvm::StringRef name, bool is_mangled) { + if (!name.empty()) + SetValue(ConstString(name), is_mangled); } -Mangled::Mangled (const ConstString &s) : - m_mangled(), - m_demangled() -{ - if (s) - SetValue(s); +Mangled::Mangled(const ConstString &s) : m_mangled(), m_demangled() { + if (s) + SetValue(s); +} + +Mangled::Mangled(llvm::StringRef name) { + if (!name.empty()) + SetValue(ConstString(name)); } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -Mangled::~Mangled () -{ -} +Mangled::~Mangled() {} //---------------------------------------------------------------------- // Convert to pointer operator. This allows code to check any Mangled @@ -162,9 +152,8 @@ Mangled::~Mangled () // if (mangled) // { ... //---------------------------------------------------------------------- -Mangled::operator void* () const -{ - return (m_mangled) ? const_cast<Mangled*>(this) : NULL; +Mangled::operator void *() const { + return (m_mangled) ? const_cast<Mangled *>(this) : NULL; } //---------------------------------------------------------------------- @@ -175,83 +164,58 @@ Mangled::operator void* () const // if (!file_spec) // { ... //---------------------------------------------------------------------- -bool -Mangled::operator! () const -{ - return !m_mangled; -} +bool Mangled::operator!() const { return !m_mangled; } //---------------------------------------------------------------------- // Clear the mangled and demangled values. //---------------------------------------------------------------------- -void -Mangled::Clear () -{ - m_mangled.Clear(); - m_demangled.Clear(); +void Mangled::Clear() { + m_mangled.Clear(); + m_demangled.Clear(); } - //---------------------------------------------------------------------- // Compare the string values. //---------------------------------------------------------------------- -int -Mangled::Compare (const Mangled& a, const Mangled& b) -{ - return ConstString::Compare(a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled), a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled)); +int Mangled::Compare(const Mangled &a, const Mangled &b) { + return ConstString::Compare( + a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled), + a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled)); } - - //---------------------------------------------------------------------- // Set the string value in this objects. If "mangled" is true, then // the mangled named is set with the new value in "s", else the // demangled name is set. //---------------------------------------------------------------------- -void -Mangled::SetValue (const ConstString &s, bool mangled) -{ - if (s) - { - if (mangled) - { - m_demangled.Clear(); - m_mangled = s; - } - else - { - m_demangled = s; - m_mangled.Clear(); - } - } - else - { - m_demangled.Clear(); - m_mangled.Clear(); +void Mangled::SetValue(const ConstString &s, bool mangled) { + if (s) { + if (mangled) { + m_demangled.Clear(); + m_mangled = s; + } else { + m_demangled = s; + m_mangled.Clear(); } + } else { + m_demangled.Clear(); + m_mangled.Clear(); + } } -void -Mangled::SetValue (const ConstString &name) -{ - if (name) - { - if (cstring_is_mangled(name.GetCString())) - { - m_demangled.Clear(); - m_mangled = name; - } - else - { - m_demangled = name; - m_mangled.Clear(); - } - } - else - { - m_demangled.Clear(); - m_mangled.Clear(); +void Mangled::SetValue(const ConstString &name) { + if (name) { + if (cstring_is_mangled(name.GetCString())) { + m_demangled.Clear(); + m_mangled = name; + } else { + m_demangled = name; + m_mangled.Clear(); } + } else { + m_demangled.Clear(); + m_mangled.Clear(); + } } //---------------------------------------------------------------------- @@ -261,180 +225,166 @@ Mangled::SetValue (const ConstString &name) // new string value is supplied to this object, or until the end of the // object's lifetime. //---------------------------------------------------------------------- -const ConstString& -Mangled::GetDemangledName (lldb::LanguageType language) const -{ - // Check to make sure we have a valid mangled name and that we - // haven't already decoded our mangled name. - if (m_mangled && !m_demangled) - { - // We need to generate and cache the demangled name. - Timer scoped_timer (__PRETTY_FUNCTION__, - "Mangled::GetDemangledName (m_mangled = %s)", - m_mangled.GetCString()); - - Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DEMANGLE); - - // Don't bother running anything that isn't mangled - const char *mangled_name = m_mangled.GetCString(); - ManglingScheme mangling_scheme{cstring_mangling_scheme(mangled_name)}; - if (mangling_scheme != eManglingSchemeNone && - !m_mangled.GetMangledCounterpart(m_demangled)) - { - // We didn't already mangle this name, demangle it and if all goes well - // add it to our map. - char *demangled_name = nullptr; - switch (mangling_scheme) - { - case eManglingSchemeMSVC: - { +const ConstString & +Mangled::GetDemangledName(lldb::LanguageType language) const { + // Check to make sure we have a valid mangled name and that we + // haven't already decoded our mangled name. + if (m_mangled && !m_demangled) { + // We need to generate and cache the demangled name. + Timer scoped_timer(LLVM_PRETTY_FUNCTION, + "Mangled::GetDemangledName (m_mangled = %s)", + m_mangled.GetCString()); + + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DEMANGLE); + + // Don't bother running anything that isn't mangled + const char *mangled_name = m_mangled.GetCString(); + ManglingScheme mangling_scheme{cstring_mangling_scheme(mangled_name)}; + if (mangling_scheme != eManglingSchemeNone && + !m_mangled.GetMangledCounterpart(m_demangled)) { + // We didn't already mangle this name, demangle it and if all goes well + // add it to our map. + char *demangled_name = nullptr; + switch (mangling_scheme) { + case eManglingSchemeMSVC: { #if defined(_MSC_VER) - if (log) - log->Printf("demangle msvc: %s", mangled_name); - const size_t demangled_length = 2048; - demangled_name = static_cast<char *>(::malloc(demangled_length)); - ::ZeroMemory(demangled_name, demangled_length); - DWORD result = ::UnDecorateSymbolName(mangled_name, demangled_name, demangled_length, - UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected keywords - UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc keywords - UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications - UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc specifiers - UNDNAME_NO_MS_KEYWORDS // Strip all MS extension keywords - ); - if (log) - { - if (demangled_name && demangled_name[0]) - log->Printf("demangled msvc: %s -> \"%s\"", mangled_name, demangled_name); - else - log->Printf("demangled msvc: %s -> error: 0x%" PRIx64, mangled_name, result); - } - - if (result == 0) - { - free(demangled_name); - demangled_name = nullptr; - } + if (log) + log->Printf("demangle msvc: %s", mangled_name); + const size_t demangled_length = 2048; + demangled_name = static_cast<char *>(::malloc(demangled_length)); + ::ZeroMemory(demangled_name, demangled_length); + DWORD result = ::UnDecorateSymbolName( + mangled_name, demangled_name, demangled_length, + UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected + // keywords + UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, + // etc keywords + UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications + UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc + // specifiers + UNDNAME_NO_MS_KEYWORDS // Strip all MS extension keywords + ); + if (log) { + if (demangled_name && demangled_name[0]) + log->Printf("demangled msvc: %s -> \"%s\"", mangled_name, + demangled_name); + else + log->Printf("demangled msvc: %s -> error: 0x%lu", mangled_name, + result); + } + + if (result == 0) { + free(demangled_name); + demangled_name = nullptr; + } #endif - break; - } - case eManglingSchemeItanium: - { + break; + } + case eManglingSchemeItanium: { #ifdef LLDB_USE_BUILTIN_DEMANGLER - if (log) - log->Printf("demangle itanium: %s", mangled_name); - // Try to use the fast-path demangler first for the - // performance win, falling back to the full demangler only - // when necessary - demangled_name = FastDemangle(mangled_name, m_mangled.GetLength()); - if (!demangled_name) - demangled_name = __cxa_demangle(mangled_name, NULL, NULL, NULL); + if (log) + log->Printf("demangle itanium: %s", mangled_name); + // Try to use the fast-path demangler first for the + // performance win, falling back to the full demangler only + // when necessary + demangled_name = FastDemangle(mangled_name, m_mangled.GetLength()); + if (!demangled_name) + demangled_name = + llvm::itaniumDemangle(mangled_name, NULL, NULL, NULL); #else - demangled_name = abi::__cxa_demangle(mangled_name, NULL, NULL, NULL); + demangled_name = abi::__cxa_demangle(mangled_name, NULL, NULL, NULL); #endif - if (log) - { - if (demangled_name) - log->Printf("demangled itanium: %s -> \"%s\"", mangled_name, demangled_name); - else - log->Printf("demangled itanium: %s -> error: failed to demangle", mangled_name); - } - break; - } - case eManglingSchemeNone: - break; - } - if (demangled_name) - { - m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled); - free(demangled_name); - } - } - if (!m_demangled) - { - // Set the demangled string to the empty string to indicate we - // tried to parse it once and failed. - m_demangled.SetCString(""); + if (log) { + if (demangled_name) + log->Printf("demangled itanium: %s -> \"%s\"", mangled_name, + demangled_name); + else + log->Printf("demangled itanium: %s -> error: failed to demangle", + mangled_name); } + break; + } + case eManglingSchemeNone: + break; + } + if (demangled_name) { + m_demangled.SetCStringWithMangledCounterpart(demangled_name, m_mangled); + free(demangled_name); + } } + if (!m_demangled) { + // Set the demangled string to the empty string to indicate we + // tried to parse it once and failed. + m_demangled.SetCString(""); + } + } - return m_demangled; + return m_demangled; } - ConstString -Mangled::GetDisplayDemangledName (lldb::LanguageType language) const -{ - return GetDemangledName(language); +Mangled::GetDisplayDemangledName(lldb::LanguageType language) const { + return GetDemangledName(language); } -bool -Mangled::NameMatches (const RegularExpression& regex, lldb::LanguageType language) const -{ - if (m_mangled && regex.Execute (m_mangled.AsCString())) - return true; +bool Mangled::NameMatches(const RegularExpression ®ex, + lldb::LanguageType language) const { + if (m_mangled && regex.Execute(m_mangled.AsCString())) + return true; - ConstString demangled = GetDemangledName(language); - if (demangled && regex.Execute (demangled.AsCString())) - return true; - return false; + ConstString demangled = GetDemangledName(language); + if (demangled && regex.Execute(demangled.AsCString())) + return true; + return false; } //---------------------------------------------------------------------- // Get the demangled name if there is one, else return the mangled name. //---------------------------------------------------------------------- -ConstString -Mangled::GetName (lldb::LanguageType language, Mangled::NamePreference preference) const -{ - if (preference == ePreferMangled && m_mangled) - return m_mangled; - - ConstString demangled = GetDemangledName(language); - - if (preference == ePreferDemangledWithoutArguments) - { - return get_demangled_name_without_arguments (m_mangled, demangled); - } - if (preference == ePreferDemangled) - { - // Call the accessor to make sure we get a demangled name in case - // it hasn't been demangled yet... - if (demangled) - return demangled; - return m_mangled; - } - return demangled; +ConstString Mangled::GetName(lldb::LanguageType language, + Mangled::NamePreference preference) const { + if (preference == ePreferMangled && m_mangled) + return m_mangled; + + ConstString demangled = GetDemangledName(language); + + if (preference == ePreferDemangledWithoutArguments) { + return get_demangled_name_without_arguments(m_mangled, demangled); + } + if (preference == ePreferDemangled) { + // Call the accessor to make sure we get a demangled name in case + // it hasn't been demangled yet... + if (demangled) + return demangled; + return m_mangled; + } + return demangled; } //---------------------------------------------------------------------- // Dump a Mangled object to stream "s". We don't force our // demangled name to be computed currently (we don't use the accessor). //---------------------------------------------------------------------- -void -Mangled::Dump (Stream *s) const -{ - if (m_mangled) - { - *s << ", mangled = " << m_mangled; - } - if (m_demangled) - { - const char * demangled = m_demangled.AsCString(); - s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>"); - } +void Mangled::Dump(Stream *s) const { + if (m_mangled) { + *s << ", mangled = " << m_mangled; + } + if (m_demangled) { + const char *demangled = m_demangled.AsCString(); + s->Printf(", demangled = %s", demangled[0] ? demangled : "<error>"); + } } //---------------------------------------------------------------------- // Dumps a debug version of this string with extra object and state // information to stream "s". //---------------------------------------------------------------------- -void -Mangled::DumpDebug (Stream *s) const -{ - s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void*) * 2), - static_cast<const void*>(this)); - m_mangled.DumpDebug(s); - s->Printf(", demangled = "); - m_demangled.DumpDebug(s); +void Mangled::DumpDebug(Stream *s) const { + s->Printf("%*p: Mangled mangled = ", static_cast<int>(sizeof(void *) * 2), + static_cast<const void *>(this)); + m_mangled.DumpDebug(s); + s->Printf(", demangled = "); + m_demangled.DumpDebug(s); } //---------------------------------------------------------------------- @@ -442,10 +392,8 @@ Mangled::DumpDebug (Stream *s) const // includes the size of the objects it owns, and not the strings that // it references because they are shared strings. //---------------------------------------------------------------------- -size_t -Mangled::MemorySize () const -{ - return m_mangled.MemorySize() + m_demangled.MemorySize(); +size_t Mangled::MemorySize() const { + return m_mangled.MemorySize() + m_demangled.MemorySize(); } //---------------------------------------------------------------------- @@ -456,37 +404,32 @@ Mangled::MemorySize () const // different ways of mangling names from a given language, likewise the // compilation units within those targets. //---------------------------------------------------------------------- -lldb::LanguageType -Mangled::GuessLanguage () const -{ - ConstString mangled = GetMangledName(); - if (mangled) - { - if (GetDemangledName(lldb::eLanguageTypeUnknown)) - { - const char *mangled_name = mangled.GetCString(); - if (CPlusPlusLanguage::IsCPPMangledName(mangled_name)) - return lldb::eLanguageTypeC_plus_plus; - else if (ObjCLanguage::IsPossibleObjCMethodName(mangled_name)) - return lldb::eLanguageTypeObjC; - } +lldb::LanguageType Mangled::GuessLanguage() const { + ConstString mangled = GetMangledName(); + if (mangled) { + if (GetDemangledName(lldb::eLanguageTypeUnknown)) { + const char *mangled_name = mangled.GetCString(); + if (CPlusPlusLanguage::IsCPPMangledName(mangled_name)) + return lldb::eLanguageTypeC_plus_plus; + else if (ObjCLanguage::IsPossibleObjCMethodName(mangled_name)) + return lldb::eLanguageTypeObjC; } - return lldb::eLanguageTypeUnknown; + } + return lldb::eLanguageTypeUnknown; } //---------------------------------------------------------------------- // Dump OBJ to the supplied stream S. //---------------------------------------------------------------------- -Stream& -operator << (Stream& s, const Mangled& obj) -{ - if (obj.GetMangledName()) - s << "mangled = '" << obj.GetMangledName() << "'"; - - const ConstString& demangled = obj.GetDemangledName(lldb::eLanguageTypeUnknown); - if (demangled) - s << ", demangled = '" << demangled << '\''; - else - s << ", demangled = <error>"; - return s; +Stream &operator<<(Stream &s, const Mangled &obj) { + if (obj.GetMangledName()) + s << "mangled = '" << obj.GetMangledName() << "'"; + + const ConstString &demangled = + obj.GetDemangledName(lldb::eLanguageTypeUnknown); + if (demangled) + s << ", demangled = '" << demangled << '\''; + else + s << ", demangled = <error>"; + return s; } diff --git a/source/Core/Module.cpp b/source/Core/Module.cpp index 5fe39abda183..220773b5ad40 100644 --- a/source/Core/Module.cpp +++ b/source/Core/Module.cpp @@ -12,14 +12,16 @@ // C Includes // C++ Includes // Other libraries and framework includes -#include "llvm/Support/raw_os_ostream.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/raw_os_ostream.h" // Project includes +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" +#include "Plugins/Language/ObjC/ObjCLanguage.h" #include "lldb/Core/AddressResolverFileLine.h" -#include "lldb/Core/Error.h" #include "lldb/Core/DataBuffer.h" #include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/Error.h" #include "lldb/Core/Log.h" #include "lldb/Core/ModuleList.h" #include "lldb/Core/ModuleSpec.h" @@ -28,6 +30,7 @@ #include "lldb/Core/Section.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Timer.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/Symbols.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -37,14 +40,12 @@ #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/SymbolVendor.h" +#include "lldb/Symbol/TypeMap.h" #include "lldb/Symbol/TypeSystem.h" #include "lldb/Target/Language.h" #include "lldb/Target/Process.h" #include "lldb/Target/SectionLoadList.h" #include "lldb/Target/Target.h" -#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" -#include "Plugins/Language/ObjC/ObjCLanguage.h" -#include "lldb/Symbol/TypeMap.h" #include "Plugins/ObjectFile/JIT/ObjectFileJIT.h" @@ -56,51 +57,49 @@ using namespace lldb_private; // will track all module objects that are still alive typedef std::vector<Module *> ModuleCollection; -static ModuleCollection & -GetModuleCollection() -{ - // This module collection needs to live past any module, so we could either make it a - // shared pointer in each module or just leak is. Since it is only an empty vector by - // the time all the modules have gone away, we just leak it for now. If we decide this - // is a big problem we can introduce a Finalize method that will tear everything down in - // a predictable order. - - static ModuleCollection *g_module_collection = nullptr; - if (g_module_collection == nullptr) - g_module_collection = new ModuleCollection(); - - return *g_module_collection; -} - -std::recursive_mutex & -Module::GetAllocationModuleCollectionMutex() -{ - // NOTE: The mutex below must be leaked since the global module list in - // the ModuleList class will get torn at some point, and we can't know - // if it will tear itself down before the "g_module_collection_mutex" below - // will. So we leak a Mutex object below to safeguard against that - - static std::recursive_mutex *g_module_collection_mutex = nullptr; - if (g_module_collection_mutex == nullptr) - g_module_collection_mutex = new std::recursive_mutex; // NOTE: known leak - return *g_module_collection_mutex; -} - -size_t -Module::GetNumberAllocatedModules () -{ - std::lock_guard<std::recursive_mutex> guard(GetAllocationModuleCollectionMutex()); - return GetModuleCollection().size(); -} - -Module * -Module::GetAllocatedModuleAtIndex (size_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetAllocationModuleCollectionMutex()); - ModuleCollection &modules = GetModuleCollection(); - if (idx < modules.size()) - return modules[idx]; - return nullptr; +static ModuleCollection &GetModuleCollection() { + // This module collection needs to live past any module, so we could either + // make it a + // shared pointer in each module or just leak is. Since it is only an empty + // vector by + // the time all the modules have gone away, we just leak it for now. If we + // decide this + // is a big problem we can introduce a Finalize method that will tear + // everything down in + // a predictable order. + + static ModuleCollection *g_module_collection = nullptr; + if (g_module_collection == nullptr) + g_module_collection = new ModuleCollection(); + + return *g_module_collection; +} + +std::recursive_mutex &Module::GetAllocationModuleCollectionMutex() { + // NOTE: The mutex below must be leaked since the global module list in + // the ModuleList class will get torn at some point, and we can't know + // if it will tear itself down before the "g_module_collection_mutex" below + // will. So we leak a Mutex object below to safeguard against that + + static std::recursive_mutex *g_module_collection_mutex = nullptr; + if (g_module_collection_mutex == nullptr) + g_module_collection_mutex = new std::recursive_mutex; // NOTE: known leak + return *g_module_collection_mutex; +} + +size_t Module::GetNumberAllocatedModules() { + std::lock_guard<std::recursive_mutex> guard( + GetAllocationModuleCollectionMutex()); + return GetModuleCollection().size(); +} + +Module *Module::GetAllocatedModuleAtIndex(size_t idx) { + std::lock_guard<std::recursive_mutex> guard( + GetAllocationModuleCollectionMutex()); + ModuleCollection &modules = GetModuleCollection(); + if (idx < modules.size()) + return modules[idx]; + return nullptr; } #if 0 @@ -121,7 +120,7 @@ namespace lldb { Mutex::Locker locker (Module::GetAllocationModuleCollectionMutex()); ModuleCollection &modules = GetModuleCollection(); const size_t count = modules.size(); - printf ("%s: %" PRIu64 " modules:\n", __PRETTY_FUNCTION__, (uint64_t)count); + printf ("%s: %" PRIu64 " modules:\n", LLVM_PRETTY_FUNCTION, (uint64_t)count); for (size_t i = 0; i < count; ++i) { @@ -141,1779 +140,1531 @@ namespace lldb { #endif Module::Module(const ModuleSpec &module_spec) - : m_mutex(), - m_mod_time(), - m_arch(), - m_uuid(), - m_file(), - m_platform_file(), - m_remote_install_file(), - m_symfile_spec(), - m_object_name(), - m_object_offset(), - m_object_mod_time(), - m_objfile_sp(), - m_symfile_ap(), - m_type_system_map(), - m_source_mappings(), - m_sections_ap(), - m_did_load_objfile(false), - m_did_load_symbol_vendor(false), - m_did_parse_uuid(false), - m_file_has_changed(false), - m_first_file_changed_log(false) -{ - // Scope for locker below... - { - std::lock_guard<std::recursive_mutex> guard(GetAllocationModuleCollectionMutex()); - GetModuleCollection().push_back(this); - } - - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_MODULES)); - if (log != nullptr) - log->Printf("%p Module::Module((%s) '%s%s%s%s')", static_cast<void *>(this), - module_spec.GetArchitecture().GetArchitectureName(), module_spec.GetFileSpec().GetPath().c_str(), - module_spec.GetObjectName().IsEmpty() ? "" : "(", - module_spec.GetObjectName().IsEmpty() ? "" : module_spec.GetObjectName().AsCString(""), - module_spec.GetObjectName().IsEmpty() ? "" : ")"); - - // First extract all module specifications from the file using the local - // file path. If there are no specifications, then don't fill anything in - ModuleSpecList modules_specs; - if (ObjectFile::GetModuleSpecifications(module_spec.GetFileSpec(), 0, 0, modules_specs) == 0) - return; - - // Now make sure that one of the module specifications matches what we just - // extract. We might have a module specification that specifies a file "/usr/lib/dyld" - // with UUID XXX, but we might have a local version of "/usr/lib/dyld" that has - // UUID YYY and we don't want those to match. If they don't match, just don't - // fill any ivars in so we don't accidentally grab the wrong file later since - // they don't match... - ModuleSpec matching_module_spec; - if (modules_specs.FindMatchingModuleSpec(module_spec, matching_module_spec) == 0) - return; - - if (module_spec.GetFileSpec()) - m_mod_time = module_spec.GetFileSpec().GetModificationTime(); - else if (matching_module_spec.GetFileSpec()) - m_mod_time = matching_module_spec.GetFileSpec().GetModificationTime(); - - // Copy the architecture from the actual spec if we got one back, else use the one that was specified - if (matching_module_spec.GetArchitecture().IsValid()) - m_arch = matching_module_spec.GetArchitecture(); - else if (module_spec.GetArchitecture().IsValid()) - m_arch = module_spec.GetArchitecture(); - - // Copy the file spec over and use the specified one (if there was one) so we - // don't use a path that might have gotten resolved a path in 'matching_module_spec' - if (module_spec.GetFileSpec()) - m_file = module_spec.GetFileSpec(); - else if (matching_module_spec.GetFileSpec()) - m_file = matching_module_spec.GetFileSpec(); - - // Copy the platform file spec over - if (module_spec.GetPlatformFileSpec()) - m_platform_file = module_spec.GetPlatformFileSpec(); - else if (matching_module_spec.GetPlatformFileSpec()) - m_platform_file = matching_module_spec.GetPlatformFileSpec(); - - // Copy the symbol file spec over - if (module_spec.GetSymbolFileSpec()) - m_symfile_spec = module_spec.GetSymbolFileSpec(); - else if (matching_module_spec.GetSymbolFileSpec()) - m_symfile_spec = matching_module_spec.GetSymbolFileSpec(); - - // Copy the object name over - if (matching_module_spec.GetObjectName()) - m_object_name = matching_module_spec.GetObjectName(); - else - m_object_name = module_spec.GetObjectName(); - - // Always trust the object offset (file offset) and object modification - // time (for mod time in a BSD static archive) of from the matching - // module specification - m_object_offset = matching_module_spec.GetObjectOffset(); - m_object_mod_time = matching_module_spec.GetObjectModificationTime(); -} - -Module::Module(const FileSpec &file_spec, const ArchSpec &arch, const ConstString *object_name, - lldb::offset_t object_offset, const TimeValue *object_mod_time_ptr) - : m_mutex(), - m_mod_time(file_spec.GetModificationTime()), - m_arch(arch), - m_uuid(), - m_file(file_spec), - m_platform_file(), - m_remote_install_file(), - m_symfile_spec(), - m_object_name(), - m_object_offset(object_offset), - m_object_mod_time(), - m_objfile_sp(), - m_symfile_ap(), - m_type_system_map(), - m_source_mappings(), - m_sections_ap(), - m_did_load_objfile(false), - m_did_load_symbol_vendor(false), - m_did_parse_uuid(false), - m_file_has_changed(false), - m_first_file_changed_log(false) -{ - // Scope for locker below... - { - std::lock_guard<std::recursive_mutex> guard(GetAllocationModuleCollectionMutex()); - GetModuleCollection().push_back(this); - } - - if (object_name) - m_object_name = *object_name; + : m_object_offset(0), m_file_has_changed(false), + m_first_file_changed_log(false) { + // Scope for locker below... + { + std::lock_guard<std::recursive_mutex> guard( + GetAllocationModuleCollectionMutex()); + GetModuleCollection().push_back(this); + } + + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_OBJECT | + LIBLLDB_LOG_MODULES)); + if (log != nullptr) + log->Printf("%p Module::Module((%s) '%s%s%s%s')", static_cast<void *>(this), + module_spec.GetArchitecture().GetArchitectureName(), + module_spec.GetFileSpec().GetPath().c_str(), + module_spec.GetObjectName().IsEmpty() ? "" : "(", + module_spec.GetObjectName().IsEmpty() + ? "" + : module_spec.GetObjectName().AsCString(""), + module_spec.GetObjectName().IsEmpty() ? "" : ")"); + + // First extract all module specifications from the file using the local + // file path. If there are no specifications, then don't fill anything in + ModuleSpecList modules_specs; + if (ObjectFile::GetModuleSpecifications(module_spec.GetFileSpec(), 0, 0, + modules_specs) == 0) + return; + + // Now make sure that one of the module specifications matches what we just + // extract. We might have a module specification that specifies a file + // "/usr/lib/dyld" + // with UUID XXX, but we might have a local version of "/usr/lib/dyld" that + // has + // UUID YYY and we don't want those to match. If they don't match, just don't + // fill any ivars in so we don't accidentally grab the wrong file later since + // they don't match... + ModuleSpec matching_module_spec; + if (modules_specs.FindMatchingModuleSpec(module_spec, matching_module_spec) == + 0) + return; + + if (module_spec.GetFileSpec()) + m_mod_time = FileSystem::GetModificationTime(module_spec.GetFileSpec()); + else if (matching_module_spec.GetFileSpec()) + m_mod_time = + FileSystem::GetModificationTime(matching_module_spec.GetFileSpec()); + + // Copy the architecture from the actual spec if we got one back, else use the + // one that was specified + if (matching_module_spec.GetArchitecture().IsValid()) + m_arch = matching_module_spec.GetArchitecture(); + else if (module_spec.GetArchitecture().IsValid()) + m_arch = module_spec.GetArchitecture(); + + // Copy the file spec over and use the specified one (if there was one) so we + // don't use a path that might have gotten resolved a path in + // 'matching_module_spec' + if (module_spec.GetFileSpec()) + m_file = module_spec.GetFileSpec(); + else if (matching_module_spec.GetFileSpec()) + m_file = matching_module_spec.GetFileSpec(); + + // Copy the platform file spec over + if (module_spec.GetPlatformFileSpec()) + m_platform_file = module_spec.GetPlatformFileSpec(); + else if (matching_module_spec.GetPlatformFileSpec()) + m_platform_file = matching_module_spec.GetPlatformFileSpec(); + + // Copy the symbol file spec over + if (module_spec.GetSymbolFileSpec()) + m_symfile_spec = module_spec.GetSymbolFileSpec(); + else if (matching_module_spec.GetSymbolFileSpec()) + m_symfile_spec = matching_module_spec.GetSymbolFileSpec(); + + // Copy the object name over + if (matching_module_spec.GetObjectName()) + m_object_name = matching_module_spec.GetObjectName(); + else + m_object_name = module_spec.GetObjectName(); + + // Always trust the object offset (file offset) and object modification + // time (for mod time in a BSD static archive) of from the matching + // module specification + m_object_offset = matching_module_spec.GetObjectOffset(); + m_object_mod_time = matching_module_spec.GetObjectModificationTime(); +} + +Module::Module(const FileSpec &file_spec, const ArchSpec &arch, + const ConstString *object_name, lldb::offset_t object_offset, + const llvm::sys::TimePoint<> &object_mod_time) + : m_mod_time(FileSystem::GetModificationTime(file_spec)), m_arch(arch), + m_file(file_spec), m_object_offset(object_offset), + m_object_mod_time(object_mod_time), m_file_has_changed(false), + m_first_file_changed_log(false) { + // Scope for locker below... + { + std::lock_guard<std::recursive_mutex> guard( + GetAllocationModuleCollectionMutex()); + GetModuleCollection().push_back(this); + } - if (object_mod_time_ptr) - m_object_mod_time = *object_mod_time_ptr; + if (object_name) + m_object_name = *object_name; - Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_OBJECT | LIBLLDB_LOG_MODULES)); - if (log != nullptr) - log->Printf("%p Module::Module((%s) '%s%s%s%s')", static_cast<void *>(this), m_arch.GetArchitectureName(), - m_file.GetPath().c_str(), m_object_name.IsEmpty() ? "" : "(", - m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""), m_object_name.IsEmpty() ? "" : ")"); + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_OBJECT | + LIBLLDB_LOG_MODULES)); + if (log != nullptr) + log->Printf("%p Module::Module((%s) '%s%s%s%s')", static_cast<void *>(this), + m_arch.GetArchitectureName(), m_file.GetPath().c_str(), + m_object_name.IsEmpty() ? "" : "(", + m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""), + m_object_name.IsEmpty() ? "" : ")"); } Module::Module() - : m_mutex(), - m_mod_time(), - m_arch(), - m_uuid(), - m_file(), - m_platform_file(), - m_remote_install_file(), - m_symfile_spec(), - m_object_name(), - m_object_offset(0), - m_object_mod_time(), - m_objfile_sp(), - m_symfile_ap(), - m_type_system_map(), - m_source_mappings(), - m_sections_ap(), - m_did_load_objfile(false), - m_did_load_symbol_vendor(false), - m_did_parse_uuid(false), - m_file_has_changed(false), - m_first_file_changed_log(false) -{ - std::lock_guard<std::recursive_mutex> guard(GetAllocationModuleCollectionMutex()); - GetModuleCollection().push_back(this); -} - -Module::~Module() -{ - // Lock our module down while we tear everything down to make sure - // we don't get any access to the module while it is being destroyed + : m_object_offset(0), m_file_has_changed(false), + m_first_file_changed_log(false) { + std::lock_guard<std::recursive_mutex> guard( + GetAllocationModuleCollectionMutex()); + GetModuleCollection().push_back(this); +} + +Module::~Module() { + // Lock our module down while we tear everything down to make sure + // we don't get any access to the module while it is being destroyed + std::lock_guard<std::recursive_mutex> guard(m_mutex); + // Scope for locker below... + { + std::lock_guard<std::recursive_mutex> guard( + GetAllocationModuleCollectionMutex()); + ModuleCollection &modules = GetModuleCollection(); + ModuleCollection::iterator end = modules.end(); + ModuleCollection::iterator pos = std::find(modules.begin(), end, this); + assert(pos != end); + modules.erase(pos); + } + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_OBJECT | + LIBLLDB_LOG_MODULES)); + if (log != nullptr) + log->Printf("%p Module::~Module((%s) '%s%s%s%s')", + static_cast<void *>(this), m_arch.GetArchitectureName(), + m_file.GetPath().c_str(), m_object_name.IsEmpty() ? "" : "(", + m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""), + m_object_name.IsEmpty() ? "" : ")"); + // Release any auto pointers before we start tearing down our member + // variables since the object file and symbol files might need to make + // function calls back into this module object. The ordering is important + // here because symbol files can require the module object file. So we tear + // down the symbol file first, then the object file. + m_sections_ap.reset(); + m_symfile_ap.reset(); + m_objfile_sp.reset(); +} + +ObjectFile *Module::GetMemoryObjectFile(const lldb::ProcessSP &process_sp, + lldb::addr_t header_addr, Error &error, + size_t size_to_read) { + if (m_objfile_sp) { + error.SetErrorString("object file already exists"); + } else { std::lock_guard<std::recursive_mutex> guard(m_mutex); - // Scope for locker below... - { - std::lock_guard<std::recursive_mutex> guard(GetAllocationModuleCollectionMutex()); - ModuleCollection &modules = GetModuleCollection(); - ModuleCollection::iterator end = modules.end(); - ModuleCollection::iterator pos = std::find(modules.begin(), end, this); - assert (pos != end); - modules.erase(pos); - } - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_OBJECT|LIBLLDB_LOG_MODULES)); - if (log != nullptr) - log->Printf ("%p Module::~Module((%s) '%s%s%s%s')", - static_cast<void*>(this), - m_arch.GetArchitectureName(), - m_file.GetPath().c_str(), - m_object_name.IsEmpty() ? "" : "(", - m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""), - m_object_name.IsEmpty() ? "" : ")"); - // Release any auto pointers before we start tearing down our member - // variables since the object file and symbol files might need to make - // function calls back into this module object. The ordering is important - // here because symbol files can require the module object file. So we tear - // down the symbol file first, then the object file. - m_sections_ap.reset(); - m_symfile_ap.reset(); - m_objfile_sp.reset(); -} - -ObjectFile * -Module::GetMemoryObjectFile (const lldb::ProcessSP &process_sp, lldb::addr_t header_addr, Error &error, size_t size_to_read) -{ - if (m_objfile_sp) - { - error.SetErrorString ("object file already exists"); - } - else - { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - if (process_sp) - { - m_did_load_objfile = true; - std::unique_ptr<DataBufferHeap> data_ap (new DataBufferHeap (size_to_read, 0)); - Error readmem_error; - const size_t bytes_read = process_sp->ReadMemory (header_addr, - data_ap->GetBytes(), - data_ap->GetByteSize(), - readmem_error); - if (bytes_read == size_to_read) - { - DataBufferSP data_sp(data_ap.release()); - m_objfile_sp = ObjectFile::FindPlugin(shared_from_this(), process_sp, header_addr, data_sp); - if (m_objfile_sp) - { - StreamString s; - s.Printf("0x%16.16" PRIx64, header_addr); - m_object_name.SetCString (s.GetData()); - - // Once we get the object file, update our module with the object file's - // architecture since it might differ in vendor/os if some parts were - // unknown. - m_objfile_sp->GetArchitecture (m_arch); - } - else - { - error.SetErrorString ("unable to find suitable object file plug-in"); - } - } - else - { - error.SetErrorStringWithFormat ("unable to read header from memory: %s", readmem_error.AsCString()); - } - } - else - { - error.SetErrorString ("invalid process"); + if (process_sp) { + m_did_load_objfile = true; + std::unique_ptr<DataBufferHeap> data_ap( + new DataBufferHeap(size_to_read, 0)); + Error readmem_error; + const size_t bytes_read = + process_sp->ReadMemory(header_addr, data_ap->GetBytes(), + data_ap->GetByteSize(), readmem_error); + if (bytes_read == size_to_read) { + DataBufferSP data_sp(data_ap.release()); + m_objfile_sp = ObjectFile::FindPlugin(shared_from_this(), process_sp, + header_addr, data_sp); + if (m_objfile_sp) { + StreamString s; + s.Printf("0x%16.16" PRIx64, header_addr); + m_object_name.SetString(s.GetString()); + + // Once we get the object file, update our module with the object + // file's + // architecture since it might differ in vendor/os if some parts were + // unknown. + m_objfile_sp->GetArchitecture(m_arch); + } else { + error.SetErrorString("unable to find suitable object file plug-in"); } + } else { + error.SetErrorStringWithFormat("unable to read header from memory: %s", + readmem_error.AsCString()); + } + } else { + error.SetErrorString("invalid process"); } - return m_objfile_sp.get(); + } + return m_objfile_sp.get(); } -const lldb_private::UUID& -Module::GetUUID() -{ - if (!m_did_parse_uuid.load()) - { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - if (!m_did_parse_uuid.load()) - { - ObjectFile * obj_file = GetObjectFile (); +const lldb_private::UUID &Module::GetUUID() { + if (!m_did_parse_uuid.load()) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + if (!m_did_parse_uuid.load()) { + ObjectFile *obj_file = GetObjectFile(); - if (obj_file != nullptr) - { - obj_file->GetUUID(&m_uuid); - m_did_parse_uuid = true; - } - } + if (obj_file != nullptr) { + obj_file->GetUUID(&m_uuid); + m_did_parse_uuid = true; + } } - return m_uuid; + } + return m_uuid; } -TypeSystem * -Module::GetTypeSystemForLanguage (LanguageType language) -{ - return m_type_system_map.GetTypeSystemForLanguage(language, this, true); +TypeSystem *Module::GetTypeSystemForLanguage(LanguageType language) { + return m_type_system_map.GetTypeSystemForLanguage(language, this, true); } -void -Module::ParseAllDebugSymbols() -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - size_t num_comp_units = GetNumCompileUnits(); - if (num_comp_units == 0) - return; +void Module::ParseAllDebugSymbols() { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + size_t num_comp_units = GetNumCompileUnits(); + if (num_comp_units == 0) + return; - SymbolContext sc; - sc.module_sp = shared_from_this(); - SymbolVendor *symbols = GetSymbolVendor (); + SymbolContext sc; + sc.module_sp = shared_from_this(); + SymbolVendor *symbols = GetSymbolVendor(); - for (size_t cu_idx = 0; cu_idx < num_comp_units; cu_idx++) - { - sc.comp_unit = symbols->GetCompileUnitAtIndex(cu_idx).get(); - if (sc.comp_unit) - { - sc.function = nullptr; - symbols->ParseVariablesForContext(sc); + for (size_t cu_idx = 0; cu_idx < num_comp_units; cu_idx++) { + sc.comp_unit = symbols->GetCompileUnitAtIndex(cu_idx).get(); + if (sc.comp_unit) { + sc.function = nullptr; + symbols->ParseVariablesForContext(sc); - symbols->ParseCompileUnitFunctions(sc); + symbols->ParseCompileUnitFunctions(sc); - for (size_t func_idx = 0; (sc.function = sc.comp_unit->GetFunctionAtIndex(func_idx).get()) != nullptr; ++func_idx) - { - symbols->ParseFunctionBlocks(sc); + for (size_t func_idx = 0; + (sc.function = sc.comp_unit->GetFunctionAtIndex(func_idx).get()) != + nullptr; + ++func_idx) { + symbols->ParseFunctionBlocks(sc); - // Parse the variables for this function and all its blocks - symbols->ParseVariablesForContext(sc); - } + // Parse the variables for this function and all its blocks + symbols->ParseVariablesForContext(sc); + } - // Parse all types for this compile unit - sc.function = nullptr; - symbols->ParseTypes(sc); - } + // Parse all types for this compile unit + sc.function = nullptr; + symbols->ParseTypes(sc); } + } } -void -Module::CalculateSymbolContext(SymbolContext* sc) -{ - sc->module_sp = shared_from_this(); +void Module::CalculateSymbolContext(SymbolContext *sc) { + sc->module_sp = shared_from_this(); } -ModuleSP -Module::CalculateSymbolContextModule () -{ - return shared_from_this(); -} +ModuleSP Module::CalculateSymbolContextModule() { return shared_from_this(); } -void -Module::DumpSymbolContext(Stream *s) -{ - s->Printf(", Module{%p}", static_cast<void*>(this)); +void Module::DumpSymbolContext(Stream *s) { + s->Printf(", Module{%p}", static_cast<void *>(this)); } -size_t -Module::GetNumCompileUnits() -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - Timer scoped_timer(__PRETTY_FUNCTION__, - "Module::GetNumCompileUnits (module = %p)", - static_cast<void*>(this)); - SymbolVendor *symbols = GetSymbolVendor (); - if (symbols) - return symbols->GetNumCompileUnits(); - return 0; +size_t Module::GetNumCompileUnits() { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + Timer scoped_timer(LLVM_PRETTY_FUNCTION, + "Module::GetNumCompileUnits (module = %p)", + static_cast<void *>(this)); + SymbolVendor *symbols = GetSymbolVendor(); + if (symbols) + return symbols->GetNumCompileUnits(); + return 0; } -CompUnitSP -Module::GetCompileUnitAtIndex (size_t index) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - size_t num_comp_units = GetNumCompileUnits (); - CompUnitSP cu_sp; +CompUnitSP Module::GetCompileUnitAtIndex(size_t index) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + size_t num_comp_units = GetNumCompileUnits(); + CompUnitSP cu_sp; - if (index < num_comp_units) - { - SymbolVendor *symbols = GetSymbolVendor (); - if (symbols) - cu_sp = symbols->GetCompileUnitAtIndex(index); + if (index < num_comp_units) { + SymbolVendor *symbols = GetSymbolVendor(); + if (symbols) + cu_sp = symbols->GetCompileUnitAtIndex(index); + } + return cu_sp; +} + +bool Module::ResolveFileAddress(lldb::addr_t vm_addr, Address &so_addr) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + Timer scoped_timer(LLVM_PRETTY_FUNCTION, + "Module::ResolveFileAddress (vm_addr = 0x%" PRIx64 ")", + vm_addr); + SectionList *section_list = GetSectionList(); + if (section_list) + return so_addr.ResolveAddressUsingFileSections(vm_addr, section_list); + return false; +} + +uint32_t Module::ResolveSymbolContextForAddress( + const Address &so_addr, uint32_t resolve_scope, SymbolContext &sc, + bool resolve_tail_call_address) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + uint32_t resolved_flags = 0; + + // Clear the result symbol context in case we don't find anything, but don't + // clear the target + sc.Clear(false); + + // Get the section from the section/offset address. + SectionSP section_sp(so_addr.GetSection()); + + // Make sure the section matches this module before we try and match anything + if (section_sp && section_sp->GetModule().get() == this) { + // If the section offset based address resolved itself, then this + // is the right module. + sc.module_sp = shared_from_this(); + resolved_flags |= eSymbolContextModule; + + SymbolVendor *sym_vendor = GetSymbolVendor(); + if (!sym_vendor) + return resolved_flags; + + // Resolve the compile unit, function, block, line table or line + // entry if requested. + if (resolve_scope & eSymbolContextCompUnit || + resolve_scope & eSymbolContextFunction || + resolve_scope & eSymbolContextBlock || + resolve_scope & eSymbolContextLineEntry || + resolve_scope & eSymbolContextVariable) { + resolved_flags |= + sym_vendor->ResolveSymbolContext(so_addr, resolve_scope, sc); } - return cu_sp; -} - -bool -Module::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - Timer scoped_timer(__PRETTY_FUNCTION__, "Module::ResolveFileAddress (vm_addr = 0x%" PRIx64 ")", vm_addr); - SectionList *section_list = GetSectionList(); - if (section_list) - return so_addr.ResolveAddressUsingFileSections(vm_addr, section_list); - return false; -} - -uint32_t -Module::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc, - bool resolve_tail_call_address) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - uint32_t resolved_flags = 0; - // Clear the result symbol context in case we don't find anything, but don't clear the target - sc.Clear(false); - - // Get the section from the section/offset address. - SectionSP section_sp (so_addr.GetSection()); - - // Make sure the section matches this module before we try and match anything - if (section_sp && section_sp->GetModule().get() == this) - { - // If the section offset based address resolved itself, then this - // is the right module. - sc.module_sp = shared_from_this(); - resolved_flags |= eSymbolContextModule; - - SymbolVendor* sym_vendor = GetSymbolVendor(); - if (!sym_vendor) - return resolved_flags; - - // Resolve the compile unit, function, block, line table or line - // entry if requested. - if (resolve_scope & eSymbolContextCompUnit || - resolve_scope & eSymbolContextFunction || - resolve_scope & eSymbolContextBlock || - resolve_scope & eSymbolContextLineEntry || - resolve_scope & eSymbolContextVariable ) - { - resolved_flags |= sym_vendor->ResolveSymbolContext (so_addr, resolve_scope, sc); + // Resolve the symbol if requested, but don't re-look it up if we've already + // found it. + if (resolve_scope & eSymbolContextSymbol && + !(resolved_flags & eSymbolContextSymbol)) { + Symtab *symtab = sym_vendor->GetSymtab(); + if (symtab && so_addr.IsSectionOffset()) { + Symbol *matching_symbol = nullptr; + + symtab->ForEachSymbolContainingFileAddress( + so_addr.GetFileAddress(), + [&matching_symbol](Symbol *symbol) -> bool { + if (symbol->GetType() != eSymbolTypeInvalid) { + matching_symbol = symbol; + return false; // Stop iterating + } + return true; // Keep iterating + }); + sc.symbol = matching_symbol; + if (!sc.symbol && resolve_scope & eSymbolContextFunction && + !(resolved_flags & eSymbolContextFunction)) { + bool verify_unique = false; // No need to check again since + // ResolveSymbolContext failed to find a + // symbol at this address. + if (ObjectFile *obj_file = sc.module_sp->GetObjectFile()) + sc.symbol = + obj_file->ResolveSymbolForAddress(so_addr, verify_unique); } - // Resolve the symbol if requested, but don't re-look it up if we've already found it. - if (resolve_scope & eSymbolContextSymbol && !(resolved_flags & eSymbolContextSymbol)) - { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab && so_addr.IsSectionOffset()) - { - Symbol *matching_symbol = nullptr; - - symtab->ForEachSymbolContainingFileAddress(so_addr.GetFileAddress(), - [&matching_symbol](Symbol *symbol) -> bool { - if (symbol->GetType() != eSymbolTypeInvalid) - { - matching_symbol = symbol; - return false; // Stop iterating - } - return true; // Keep iterating - }); - sc.symbol = matching_symbol; - if (!sc.symbol && - resolve_scope & eSymbolContextFunction && !(resolved_flags & eSymbolContextFunction)) - { - bool verify_unique = false; // No need to check again since ResolveSymbolContext failed to find a symbol at this address. - if (ObjectFile *obj_file = sc.module_sp->GetObjectFile()) - sc.symbol = obj_file->ResolveSymbolForAddress(so_addr, verify_unique); - } - - if (sc.symbol) - { - if (sc.symbol->IsSynthetic()) - { - // We have a synthetic symbol so lets check if the object file - // from the symbol file in the symbol vendor is different than - // the object file for the module, and if so search its symbol - // table to see if we can come up with a better symbol. For example - // dSYM files on MacOSX have an unstripped symbol table inside of - // them. - ObjectFile *symtab_objfile = symtab->GetObjectFile(); - if (symtab_objfile && symtab_objfile->IsStripped()) - { - SymbolFile *symfile = sym_vendor->GetSymbolFile(); - if (symfile) - { - ObjectFile *symfile_objfile = symfile->GetObjectFile(); - if (symfile_objfile != symtab_objfile) - { - Symtab *symfile_symtab = symfile_objfile->GetSymtab(); - if (symfile_symtab) - { - Symbol *symbol = symfile_symtab->FindSymbolContainingFileAddress(so_addr.GetFileAddress()); - if (symbol && !symbol->IsSynthetic()) - { - sc.symbol = symbol; - } - } - } - } - } + if (sc.symbol) { + if (sc.symbol->IsSynthetic()) { + // We have a synthetic symbol so lets check if the object file + // from the symbol file in the symbol vendor is different than + // the object file for the module, and if so search its symbol + // table to see if we can come up with a better symbol. For example + // dSYM files on MacOSX have an unstripped symbol table inside of + // them. + ObjectFile *symtab_objfile = symtab->GetObjectFile(); + if (symtab_objfile && symtab_objfile->IsStripped()) { + SymbolFile *symfile = sym_vendor->GetSymbolFile(); + if (symfile) { + ObjectFile *symfile_objfile = symfile->GetObjectFile(); + if (symfile_objfile != symtab_objfile) { + Symtab *symfile_symtab = symfile_objfile->GetSymtab(); + if (symfile_symtab) { + Symbol *symbol = + symfile_symtab->FindSymbolContainingFileAddress( + so_addr.GetFileAddress()); + if (symbol && !symbol->IsSynthetic()) { + sc.symbol = symbol; } - resolved_flags |= eSymbolContextSymbol; + } } + } } + } + resolved_flags |= eSymbolContextSymbol; } + } + } - // For function symbols, so_addr may be off by one. This is a convention consistent - // with FDE row indices in eh_frame sections, but requires extra logic here to permit - // symbol lookup for disassembly and unwind. - if (resolve_scope & eSymbolContextSymbol && !(resolved_flags & eSymbolContextSymbol) && - resolve_tail_call_address && so_addr.IsSectionOffset()) - { - Address previous_addr = so_addr; - previous_addr.Slide(-1); - - bool do_resolve_tail_call_address = false; // prevent recursion - const uint32_t flags = ResolveSymbolContextForAddress(previous_addr, resolve_scope, sc, - do_resolve_tail_call_address); - if (flags & eSymbolContextSymbol) - { - AddressRange addr_range; - if (sc.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range)) - { - if (addr_range.GetBaseAddress().GetSection() == so_addr.GetSection()) - { - // If the requested address is one past the address range of a function (i.e. a tail call), - // or the decremented address is the start of a function (i.e. some forms of trampoline), - // indicate that the symbol has been resolved. - if (so_addr.GetOffset() == addr_range.GetBaseAddress().GetOffset() || - so_addr.GetOffset() == addr_range.GetBaseAddress().GetOffset() + addr_range.GetByteSize()) - { - resolved_flags |= flags; - } - } - else - { - sc.symbol = nullptr; // Don't trust the symbol if the sections didn't match. - } - } + // For function symbols, so_addr may be off by one. This is a convention + // consistent + // with FDE row indices in eh_frame sections, but requires extra logic here + // to permit + // symbol lookup for disassembly and unwind. + if (resolve_scope & eSymbolContextSymbol && + !(resolved_flags & eSymbolContextSymbol) && resolve_tail_call_address && + so_addr.IsSectionOffset()) { + Address previous_addr = so_addr; + previous_addr.Slide(-1); + + bool do_resolve_tail_call_address = false; // prevent recursion + const uint32_t flags = ResolveSymbolContextForAddress( + previous_addr, resolve_scope, sc, do_resolve_tail_call_address); + if (flags & eSymbolContextSymbol) { + AddressRange addr_range; + if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, + false, addr_range)) { + if (addr_range.GetBaseAddress().GetSection() == + so_addr.GetSection()) { + // If the requested address is one past the address range of a + // function (i.e. a tail call), + // or the decremented address is the start of a function (i.e. some + // forms of trampoline), + // indicate that the symbol has been resolved. + if (so_addr.GetOffset() == + addr_range.GetBaseAddress().GetOffset() || + so_addr.GetOffset() == + addr_range.GetBaseAddress().GetOffset() + + addr_range.GetByteSize()) { + resolved_flags |= flags; } + } else { + sc.symbol = + nullptr; // Don't trust the symbol if the sections didn't match. + } } + } } - return resolved_flags; -} - -uint32_t -Module::ResolveSymbolContextForFilePath -( - const char *file_path, - uint32_t line, - bool check_inlines, - uint32_t resolve_scope, - SymbolContextList& sc_list -) -{ - FileSpec file_spec(file_path, false); - return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list); -} - -uint32_t -Module::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - Timer scoped_timer(__PRETTY_FUNCTION__, - "Module::ResolveSymbolContextForFilePath (%s:%u, check_inlines = %s, resolve_scope = 0x%8.8x)", - file_spec.GetPath().c_str(), - line, - check_inlines ? "yes" : "no", - resolve_scope); - - const uint32_t initial_count = sc_list.GetSize(); - - SymbolVendor *symbols = GetSymbolVendor (); - if (symbols) - symbols->ResolveSymbolContext (file_spec, line, check_inlines, resolve_scope, sc_list); - - return sc_list.GetSize() - initial_count; -} - -size_t -Module::FindGlobalVariables (const ConstString &name, - const CompilerDeclContext *parent_decl_ctx, - bool append, - size_t max_matches, - VariableList& variables) -{ - SymbolVendor *symbols = GetSymbolVendor (); - if (symbols) - return symbols->FindGlobalVariables(name, parent_decl_ctx, append, max_matches, variables); - return 0; -} - -size_t -Module::FindGlobalVariables (const RegularExpression& regex, - bool append, - size_t max_matches, - VariableList& variables) -{ - SymbolVendor *symbols = GetSymbolVendor (); - if (symbols) - return symbols->FindGlobalVariables(regex, append, max_matches, variables); - return 0; -} - -size_t -Module::FindCompileUnits (const FileSpec &path, - bool append, - SymbolContextList &sc_list) -{ - if (!append) - sc_list.Clear(); - - const size_t start_size = sc_list.GetSize(); - const size_t num_compile_units = GetNumCompileUnits(); - SymbolContext sc; - sc.module_sp = shared_from_this(); - const bool compare_directory = (bool)path.GetDirectory(); - for (size_t i = 0; i < num_compile_units; ++i) - { - sc.comp_unit = GetCompileUnitAtIndex(i).get(); - if (sc.comp_unit) - { - if (FileSpec::Equal (*sc.comp_unit, path, compare_directory)) - sc_list.Append(sc); - } + } + return resolved_flags; +} + +uint32_t Module::ResolveSymbolContextForFilePath(const char *file_path, + uint32_t line, + bool check_inlines, + uint32_t resolve_scope, + SymbolContextList &sc_list) { + FileSpec file_spec(file_path, false); + return ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines, + resolve_scope, sc_list); +} + +uint32_t Module::ResolveSymbolContextsForFileSpec(const FileSpec &file_spec, + uint32_t line, + bool check_inlines, + uint32_t resolve_scope, + SymbolContextList &sc_list) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + Timer scoped_timer(LLVM_PRETTY_FUNCTION, + "Module::ResolveSymbolContextForFilePath (%s:%u, " + "check_inlines = %s, resolve_scope = 0x%8.8x)", + file_spec.GetPath().c_str(), line, + check_inlines ? "yes" : "no", resolve_scope); + + const uint32_t initial_count = sc_list.GetSize(); + + SymbolVendor *symbols = GetSymbolVendor(); + if (symbols) + symbols->ResolveSymbolContext(file_spec, line, check_inlines, resolve_scope, + sc_list); + + return sc_list.GetSize() - initial_count; +} + +size_t Module::FindGlobalVariables(const ConstString &name, + const CompilerDeclContext *parent_decl_ctx, + bool append, size_t max_matches, + VariableList &variables) { + SymbolVendor *symbols = GetSymbolVendor(); + if (symbols) + return symbols->FindGlobalVariables(name, parent_decl_ctx, append, + max_matches, variables); + return 0; +} + +size_t Module::FindGlobalVariables(const RegularExpression ®ex, bool append, + size_t max_matches, + VariableList &variables) { + SymbolVendor *symbols = GetSymbolVendor(); + if (symbols) + return symbols->FindGlobalVariables(regex, append, max_matches, variables); + return 0; +} + +size_t Module::FindCompileUnits(const FileSpec &path, bool append, + SymbolContextList &sc_list) { + if (!append) + sc_list.Clear(); + + const size_t start_size = sc_list.GetSize(); + const size_t num_compile_units = GetNumCompileUnits(); + SymbolContext sc; + sc.module_sp = shared_from_this(); + const bool compare_directory = (bool)path.GetDirectory(); + for (size_t i = 0; i < num_compile_units; ++i) { + sc.comp_unit = GetCompileUnitAtIndex(i).get(); + if (sc.comp_unit) { + if (FileSpec::Equal(*sc.comp_unit, path, compare_directory)) + sc_list.Append(sc); } - return sc_list.GetSize() - start_size; -} - -Module::LookupInfo::LookupInfo(const ConstString &name, uint32_t name_type_mask, lldb::LanguageType language) : - m_name(name), - m_lookup_name(), - m_language(language), - m_name_type_mask(0), - m_match_name_after_lookup(false) -{ - const char *name_cstr = name.GetCString(); - llvm::StringRef basename; - llvm::StringRef context; - - if (name_type_mask & eFunctionNameTypeAuto) - { - if (CPlusPlusLanguage::IsCPPMangledName (name_cstr)) - m_name_type_mask = eFunctionNameTypeFull; - else if ((language == eLanguageTypeUnknown || - Language::LanguageIsObjC(language)) && - ObjCLanguage::IsPossibleObjCMethodName (name_cstr)) - m_name_type_mask = eFunctionNameTypeFull; - else if (Language::LanguageIsC(language)) - { - m_name_type_mask = eFunctionNameTypeFull; - } + } + return sc_list.GetSize() - start_size; +} + +Module::LookupInfo::LookupInfo(const ConstString &name, uint32_t name_type_mask, + lldb::LanguageType language) + : m_name(name), m_lookup_name(), m_language(language), m_name_type_mask(0), + m_match_name_after_lookup(false) { + const char *name_cstr = name.GetCString(); + llvm::StringRef basename; + llvm::StringRef context; + + if (name_type_mask & eFunctionNameTypeAuto) { + if (CPlusPlusLanguage::IsCPPMangledName(name_cstr)) + m_name_type_mask = eFunctionNameTypeFull; + else if ((language == eLanguageTypeUnknown || + Language::LanguageIsObjC(language)) && + ObjCLanguage::IsPossibleObjCMethodName(name_cstr)) + m_name_type_mask = eFunctionNameTypeFull; + else if (Language::LanguageIsC(language)) { + m_name_type_mask = eFunctionNameTypeFull; + } else { + if ((language == eLanguageTypeUnknown || + Language::LanguageIsObjC(language)) && + ObjCLanguage::IsPossibleObjCSelector(name_cstr)) + m_name_type_mask |= eFunctionNameTypeSelector; + + CPlusPlusLanguage::MethodName cpp_method(name); + basename = cpp_method.GetBasename(); + if (basename.empty()) { + if (CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, + basename)) + m_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); else - { - if ((language == eLanguageTypeUnknown || - Language::LanguageIsObjC(language)) && - ObjCLanguage::IsPossibleObjCSelector(name_cstr)) - m_name_type_mask |= eFunctionNameTypeSelector; - - CPlusPlusLanguage::MethodName cpp_method (name); - basename = cpp_method.GetBasename(); - if (basename.empty()) - { - if (CPlusPlusLanguage::ExtractContextAndIdentifier (name_cstr, context, basename)) - m_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); - else - m_name_type_mask |= eFunctionNameTypeFull; - } - else - { - m_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); - } - } + m_name_type_mask |= eFunctionNameTypeFull; + } else { + m_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); + } } - else - { - m_name_type_mask = name_type_mask; - if (name_type_mask & eFunctionNameTypeMethod || name_type_mask & eFunctionNameTypeBase) - { - // If they've asked for a CPP method or function name and it can't be that, we don't - // even need to search for CPP methods or names. - CPlusPlusLanguage::MethodName cpp_method (name); - if (cpp_method.IsValid()) - { - basename = cpp_method.GetBasename(); - - if (!cpp_method.GetQualifiers().empty()) - { - // There is a "const" or other qualifier following the end of the function parens, - // this can't be a eFunctionNameTypeBase - m_name_type_mask &= ~(eFunctionNameTypeBase); - if (m_name_type_mask == eFunctionNameTypeNone) - return; - } - } - else - { - // If the CPP method parser didn't manage to chop this up, try to fill in the base name if we can. - // If a::b::c is passed in, we need to just look up "c", and then we'll filter the result later. - CPlusPlusLanguage::ExtractContextAndIdentifier (name_cstr, context, basename); - } - } - - if (name_type_mask & eFunctionNameTypeSelector) - { - if (!ObjCLanguage::IsPossibleObjCSelector(name_cstr)) - { - m_name_type_mask &= ~(eFunctionNameTypeSelector); - if (m_name_type_mask == eFunctionNameTypeNone) - return; - } - } - - // Still try and get a basename in case someone specifies a name type mask of - // eFunctionNameTypeFull and a name like "A::func" - if (basename.empty()) - { - if (name_type_mask & eFunctionNameTypeFull) - { - CPlusPlusLanguage::MethodName cpp_method (name); - basename = cpp_method.GetBasename(); - if (basename.empty()) - CPlusPlusLanguage::ExtractContextAndIdentifier (name_cstr, context, basename); - } + } else { + m_name_type_mask = name_type_mask; + if (name_type_mask & eFunctionNameTypeMethod || + name_type_mask & eFunctionNameTypeBase) { + // If they've asked for a CPP method or function name and it can't be + // that, we don't + // even need to search for CPP methods or names. + CPlusPlusLanguage::MethodName cpp_method(name); + if (cpp_method.IsValid()) { + basename = cpp_method.GetBasename(); + + if (!cpp_method.GetQualifiers().empty()) { + // There is a "const" or other qualifier following the end of the + // function parens, + // this can't be a eFunctionNameTypeBase + m_name_type_mask &= ~(eFunctionNameTypeBase); + if (m_name_type_mask == eFunctionNameTypeNone) + return; } + } else { + // If the CPP method parser didn't manage to chop this up, try to fill + // in the base name if we can. + // If a::b::c is passed in, we need to just look up "c", and then we'll + // filter the result later. + CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, + basename); + } } - if (!basename.empty()) - { - // The name supplied was a partial C++ path like "a::count". In this case we want to do a - // lookup on the basename "count" and then make sure any matching results contain "a::count" - // so that it would match "b::a::count" and "a::count". This is why we set "match_name_after_lookup" - // to true - m_lookup_name.SetString(basename); - m_match_name_after_lookup = true; - } - else - { - // The name is already correct, just use the exact name as supplied, and we won't need - // to check if any matches contain "name" - m_lookup_name = name; - m_match_name_after_lookup = false; + if (name_type_mask & eFunctionNameTypeSelector) { + if (!ObjCLanguage::IsPossibleObjCSelector(name_cstr)) { + m_name_type_mask &= ~(eFunctionNameTypeSelector); + if (m_name_type_mask == eFunctionNameTypeNone) + return; + } } -} - -void -Module::LookupInfo::Prune(SymbolContextList &sc_list, size_t start_idx) const -{ - if (m_match_name_after_lookup && m_name) - { - SymbolContext sc; - size_t i = start_idx; - while (i < sc_list.GetSize()) - { - if (!sc_list.GetContextAtIndex(i, sc)) - break; - ConstString full_name(sc.GetFunctionName()); - if (full_name && ::strstr(full_name.GetCString(), m_name.GetCString()) == nullptr) - { - sc_list.RemoveContextAtIndex(i); - } - else - { - ++i; - } - } + // Still try and get a basename in case someone specifies a name type mask + // of + // eFunctionNameTypeFull and a name like "A::func" + if (basename.empty()) { + if (name_type_mask & eFunctionNameTypeFull) { + CPlusPlusLanguage::MethodName cpp_method(name); + basename = cpp_method.GetBasename(); + if (basename.empty()) + CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, + basename); + } } - - // If we have only full name matches we might have tried to set breakpoint on "func" - // and specified eFunctionNameTypeFull, but we might have found "a::func()", - // "a::b::func()", "c::func()", "func()" and "func". Only "func()" and "func" should - // end up matching. - if (m_name_type_mask == eFunctionNameTypeFull) - { - SymbolContext sc; - size_t i = start_idx; - while (i < sc_list.GetSize()) - { - if (!sc_list.GetContextAtIndex(i, sc)) - break; - ConstString full_name(sc.GetFunctionName()); - CPlusPlusLanguage::MethodName cpp_method(full_name); - if (cpp_method.IsValid()) - { - if (cpp_method.GetContext().empty()) - { - if (cpp_method.GetBasename().compare(m_name.GetStringRef()) != 0) - { - sc_list.RemoveContextAtIndex(i); - continue; - } - } - else - { - std::string qualified_name = cpp_method.GetScopeQualifiedName(); - if (qualified_name.compare(m_name.GetCString()) != 0) - { - sc_list.RemoveContextAtIndex(i); - continue; - } - } - } - ++i; + } + + if (!basename.empty()) { + // The name supplied was a partial C++ path like "a::count". In this case we + // want to do a + // lookup on the basename "count" and then make sure any matching results + // contain "a::count" + // so that it would match "b::a::count" and "a::count". This is why we set + // "match_name_after_lookup" + // to true + m_lookup_name.SetString(basename); + m_match_name_after_lookup = true; + } else { + // The name is already correct, just use the exact name as supplied, and we + // won't need + // to check if any matches contain "name" + m_lookup_name = name; + m_match_name_after_lookup = false; + } +} + +void Module::LookupInfo::Prune(SymbolContextList &sc_list, + size_t start_idx) const { + if (m_match_name_after_lookup && m_name) { + SymbolContext sc; + size_t i = start_idx; + while (i < sc_list.GetSize()) { + if (!sc_list.GetContextAtIndex(i, sc)) + break; + ConstString full_name(sc.GetFunctionName()); + if (full_name && + ::strstr(full_name.GetCString(), m_name.GetCString()) == nullptr) { + sc_list.RemoveContextAtIndex(i); + } else { + ++i; + } + } + } + + // If we have only full name matches we might have tried to set breakpoint on + // "func" + // and specified eFunctionNameTypeFull, but we might have found "a::func()", + // "a::b::func()", "c::func()", "func()" and "func". Only "func()" and "func" + // should + // end up matching. + if (m_name_type_mask == eFunctionNameTypeFull) { + SymbolContext sc; + size_t i = start_idx; + while (i < sc_list.GetSize()) { + if (!sc_list.GetContextAtIndex(i, sc)) + break; + ConstString full_name(sc.GetFunctionName()); + CPlusPlusLanguage::MethodName cpp_method(full_name); + if (cpp_method.IsValid()) { + if (cpp_method.GetContext().empty()) { + if (cpp_method.GetBasename().compare(m_name.GetStringRef()) != 0) { + sc_list.RemoveContextAtIndex(i); + continue; + } + } else { + std::string qualified_name = cpp_method.GetScopeQualifiedName(); + if (qualified_name.compare(m_name.GetCString()) != 0) { + sc_list.RemoveContextAtIndex(i); + continue; + } } + } + ++i; } + } } +size_t Module::FindFunctions(const ConstString &name, + const CompilerDeclContext *parent_decl_ctx, + uint32_t name_type_mask, bool include_symbols, + bool include_inlines, bool append, + SymbolContextList &sc_list) { + if (!append) + sc_list.Clear(); -size_t -Module::FindFunctions (const ConstString &name, - const CompilerDeclContext *parent_decl_ctx, - uint32_t name_type_mask, - bool include_symbols, - bool include_inlines, - bool append, - SymbolContextList& sc_list) -{ - if (!append) - sc_list.Clear(); - - const size_t old_size = sc_list.GetSize(); + const size_t old_size = sc_list.GetSize(); - // Find all the functions (not symbols, but debug information functions... - SymbolVendor *symbols = GetSymbolVendor (); - - if (name_type_mask & eFunctionNameTypeAuto) - { - LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown); + // Find all the functions (not symbols, but debug information functions... + SymbolVendor *symbols = GetSymbolVendor(); - if (symbols) - { - symbols->FindFunctions(lookup_info.GetLookupName(), - parent_decl_ctx, - lookup_info.GetNameTypeMask(), - include_inlines, - append, - sc_list); - - // Now check our symbol table for symbols that are code symbols if requested - if (include_symbols) - { - Symtab *symtab = symbols->GetSymtab(); - if (symtab) - symtab->FindFunctionSymbols(lookup_info.GetLookupName(), lookup_info.GetNameTypeMask(), sc_list); - } - } + if (name_type_mask & eFunctionNameTypeAuto) { + LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown); - const size_t new_size = sc_list.GetSize(); + if (symbols) { + symbols->FindFunctions(lookup_info.GetLookupName(), parent_decl_ctx, + lookup_info.GetNameTypeMask(), include_inlines, + append, sc_list); - if (old_size < new_size) - lookup_info.Prune (sc_list, old_size); - } - else - { - if (symbols) - { - symbols->FindFunctions(name, parent_decl_ctx, name_type_mask, include_inlines, append, sc_list); - - // Now check our symbol table for symbols that are code symbols if requested - if (include_symbols) - { - Symtab *symtab = symbols->GetSymtab(); - if (symtab) - symtab->FindFunctionSymbols(name, name_type_mask, sc_list); - } - } - } - - return sc_list.GetSize() - old_size; -} - -size_t -Module::FindFunctions (const RegularExpression& regex, - bool include_symbols, - bool include_inlines, - bool append, - SymbolContextList& sc_list) -{ - if (!append) - sc_list.Clear(); - - const size_t start_size = sc_list.GetSize(); - - SymbolVendor *symbols = GetSymbolVendor (); - if (symbols) - { - symbols->FindFunctions(regex, include_inlines, append, sc_list); - - // Now check our symbol table for symbols that are code symbols if requested - if (include_symbols) - { - Symtab *symtab = symbols->GetSymtab(); - if (symtab) - { - std::vector<uint32_t> symbol_indexes; - symtab->AppendSymbolIndexesMatchingRegExAndType (regex, eSymbolTypeAny, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes); - const size_t num_matches = symbol_indexes.size(); - if (num_matches) - { - SymbolContext sc(this); - const size_t end_functions_added_index = sc_list.GetSize(); - size_t num_functions_added_to_sc_list = end_functions_added_index - start_size; - if (num_functions_added_to_sc_list == 0) - { - // No functions were added, just symbols, so we can just append them - for (size_t i = 0; i < num_matches; ++i) - { - sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); - SymbolType sym_type = sc.symbol->GetType(); - if (sc.symbol && (sym_type == eSymbolTypeCode || - sym_type == eSymbolTypeResolver)) - sc_list.Append(sc); - } - } - else - { - typedef std::map<lldb::addr_t, uint32_t> FileAddrToIndexMap; - FileAddrToIndexMap file_addr_to_index; - for (size_t i = start_size; i < end_functions_added_index; ++i) - { - const SymbolContext &sc = sc_list[i]; - if (sc.block) - continue; - file_addr_to_index[sc.function->GetAddressRange().GetBaseAddress().GetFileAddress()] = i; - } - - FileAddrToIndexMap::const_iterator end = file_addr_to_index.end(); - // Functions were added so we need to merge symbols into any - // existing function symbol contexts - for (size_t i = start_size; i < num_matches; ++i) - { - sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); - SymbolType sym_type = sc.symbol->GetType(); - if (sc.symbol && sc.symbol->ValueIsAddress() && (sym_type == eSymbolTypeCode || sym_type == eSymbolTypeResolver)) - { - FileAddrToIndexMap::const_iterator pos = file_addr_to_index.find(sc.symbol->GetAddressRef().GetFileAddress()); - if (pos == end) - sc_list.Append(sc); - else - sc_list[pos->second].symbol = sc.symbol; - } - } - } - } - } - } + // Now check our symbol table for symbols that are code symbols if + // requested + if (include_symbols) { + Symtab *symtab = symbols->GetSymtab(); + if (symtab) + symtab->FindFunctionSymbols(lookup_info.GetLookupName(), + lookup_info.GetNameTypeMask(), sc_list); + } } - return sc_list.GetSize() - start_size; -} -void -Module::FindAddressesForLine (const lldb::TargetSP target_sp, - const FileSpec &file, uint32_t line, - Function *function, - std::vector<Address> &output_local, std::vector<Address> &output_extern) -{ - SearchFilterByModule filter(target_sp, m_file); - AddressResolverFileLine resolver(file, line, true); - resolver.ResolveAddress (filter); + const size_t new_size = sc_list.GetSize(); - for (size_t n = 0; n < resolver.GetNumberOfAddresses(); n++) - { - Address addr = resolver.GetAddressRangeAtIndex(n).GetBaseAddress(); - Function *f = addr.CalculateSymbolContextFunction(); - if (f && f == function) - output_local.push_back (addr); - else - output_extern.push_back (addr); - } -} + if (old_size < new_size) + lookup_info.Prune(sc_list, old_size); + } else { + if (symbols) { + symbols->FindFunctions(name, parent_decl_ctx, name_type_mask, + include_inlines, append, sc_list); -size_t -Module::FindTypes_Impl (const SymbolContext& sc, - const ConstString &name, - const CompilerDeclContext *parent_decl_ctx, - bool append, - size_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeMap& types) -{ - Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); - if (!sc.module_sp || sc.module_sp.get() == this) - { - SymbolVendor *symbols = GetSymbolVendor (); - if (symbols) - return symbols->FindTypes(sc, name, parent_decl_ctx, append, max_matches, searched_symbol_files, types); + // Now check our symbol table for symbols that are code symbols if + // requested + if (include_symbols) { + Symtab *symtab = symbols->GetSymtab(); + if (symtab) + symtab->FindFunctionSymbols(name, name_type_mask, sc_list); + } } - return 0; -} - -size_t -Module::FindTypesInNamespace (const SymbolContext& sc, - const ConstString &type_name, - const CompilerDeclContext *parent_decl_ctx, - size_t max_matches, - TypeList& type_list) -{ - const bool append = true; - TypeMap types_map; - llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - size_t num_types = FindTypes_Impl(sc, type_name, parent_decl_ctx, append, max_matches, searched_symbol_files, types_map); - if (num_types > 0) - sc.SortTypeList(types_map, type_list); - return num_types; -} - -lldb::TypeSP -Module::FindFirstType (const SymbolContext& sc, - const ConstString &name, - bool exact_match) -{ - TypeList type_list; - llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - const size_t num_matches = FindTypes (sc, name, exact_match, 1, searched_symbol_files, type_list); - if (num_matches) - return type_list.GetTypeAtIndex(0); - return TypeSP(); -} - -size_t -Module::FindTypes (const SymbolContext& sc, - const ConstString &name, - bool exact_match, - size_t max_matches, - llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, - TypeList& types) -{ - size_t num_matches = 0; - const char *type_name_cstr = name.GetCString(); - std::string type_scope; - std::string type_basename; - const bool append = true; - TypeClass type_class = eTypeClassAny; - TypeMap typesmap; - if (Type::GetTypeScopeAndBasename (type_name_cstr, type_scope, type_basename, type_class)) - { - // Check if "name" starts with "::" which means the qualified type starts - // from the root namespace and implies and exact match. The typenames we - // get back from clang do not start with "::" so we need to strip this off - // in order to get the qualified names to match + } + + return sc_list.GetSize() - old_size; +} + +size_t Module::FindFunctions(const RegularExpression ®ex, + bool include_symbols, bool include_inlines, + bool append, SymbolContextList &sc_list) { + if (!append) + sc_list.Clear(); + + const size_t start_size = sc_list.GetSize(); + + SymbolVendor *symbols = GetSymbolVendor(); + if (symbols) { + symbols->FindFunctions(regex, include_inlines, append, sc_list); + + // Now check our symbol table for symbols that are code symbols if requested + if (include_symbols) { + Symtab *symtab = symbols->GetSymtab(); + if (symtab) { + std::vector<uint32_t> symbol_indexes; + symtab->AppendSymbolIndexesMatchingRegExAndType( + regex, eSymbolTypeAny, Symtab::eDebugAny, Symtab::eVisibilityAny, + symbol_indexes); + const size_t num_matches = symbol_indexes.size(); + if (num_matches) { + SymbolContext sc(this); + const size_t end_functions_added_index = sc_list.GetSize(); + size_t num_functions_added_to_sc_list = + end_functions_added_index - start_size; + if (num_functions_added_to_sc_list == 0) { + // No functions were added, just symbols, so we can just append them + for (size_t i = 0; i < num_matches; ++i) { + sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); + SymbolType sym_type = sc.symbol->GetType(); + if (sc.symbol && (sym_type == eSymbolTypeCode || + sym_type == eSymbolTypeResolver)) + sc_list.Append(sc); + } + } else { + typedef std::map<lldb::addr_t, uint32_t> FileAddrToIndexMap; + FileAddrToIndexMap file_addr_to_index; + for (size_t i = start_size; i < end_functions_added_index; ++i) { + const SymbolContext &sc = sc_list[i]; + if (sc.block) + continue; + file_addr_to_index[sc.function->GetAddressRange() + .GetBaseAddress() + .GetFileAddress()] = i; + } - if (type_scope.size() >= 2 && type_scope[0] == ':' && type_scope[1] == ':') - { - type_scope.erase(0,2); - exact_match = true; - } - ConstString type_basename_const_str (type_basename.c_str()); - if (FindTypes_Impl(sc, type_basename_const_str, nullptr, append, max_matches, searched_symbol_files, typesmap)) - { - typesmap.RemoveMismatchedTypes (type_scope, type_basename, type_class, exact_match); - num_matches = typesmap.GetSize(); + FileAddrToIndexMap::const_iterator end = file_addr_to_index.end(); + // Functions were added so we need to merge symbols into any + // existing function symbol contexts + for (size_t i = start_size; i < num_matches; ++i) { + sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); + SymbolType sym_type = sc.symbol->GetType(); + if (sc.symbol && sc.symbol->ValueIsAddress() && + (sym_type == eSymbolTypeCode || + sym_type == eSymbolTypeResolver)) { + FileAddrToIndexMap::const_iterator pos = + file_addr_to_index.find( + sc.symbol->GetAddressRef().GetFileAddress()); + if (pos == end) + sc_list.Append(sc); + else + sc_list[pos->second].symbol = sc.symbol; + } + } + } } + } } + } + return sc_list.GetSize() - start_size; +} + +void Module::FindAddressesForLine(const lldb::TargetSP target_sp, + const FileSpec &file, uint32_t line, + Function *function, + std::vector<Address> &output_local, + std::vector<Address> &output_extern) { + SearchFilterByModule filter(target_sp, m_file); + AddressResolverFileLine resolver(file, line, true); + resolver.ResolveAddress(filter); + + for (size_t n = 0; n < resolver.GetNumberOfAddresses(); n++) { + Address addr = resolver.GetAddressRangeAtIndex(n).GetBaseAddress(); + Function *f = addr.CalculateSymbolContextFunction(); + if (f && f == function) + output_local.push_back(addr); else - { - // The type is not in a namespace/class scope, just search for it by basename - if (type_class != eTypeClassAny) - { - // The "type_name_cstr" will have been modified if we have a valid type class - // prefix (like "struct", "class", "union", "typedef" etc). - FindTypes_Impl(sc, ConstString(type_name_cstr), nullptr, append, max_matches, searched_symbol_files, typesmap); - typesmap.RemoveMismatchedTypes (type_class); - num_matches = typesmap.GetSize(); - } - else - { - num_matches = FindTypes_Impl(sc, name, nullptr, append, max_matches, searched_symbol_files, typesmap); - } + output_extern.push_back(addr); + } +} + +size_t Module::FindTypes_Impl( + const SymbolContext &sc, const ConstString &name, + const CompilerDeclContext *parent_decl_ctx, bool append, size_t max_matches, + llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, + TypeMap &types) { + Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION); + if (!sc.module_sp || sc.module_sp.get() == this) { + SymbolVendor *symbols = GetSymbolVendor(); + if (symbols) + return symbols->FindTypes(sc, name, parent_decl_ctx, append, max_matches, + searched_symbol_files, types); + } + return 0; +} + +size_t Module::FindTypesInNamespace(const SymbolContext &sc, + const ConstString &type_name, + const CompilerDeclContext *parent_decl_ctx, + size_t max_matches, TypeList &type_list) { + const bool append = true; + TypeMap types_map; + llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; + size_t num_types = + FindTypes_Impl(sc, type_name, parent_decl_ctx, append, max_matches, + searched_symbol_files, types_map); + if (num_types > 0) + sc.SortTypeList(types_map, type_list); + return num_types; +} + +lldb::TypeSP Module::FindFirstType(const SymbolContext &sc, + const ConstString &name, bool exact_match) { + TypeList type_list; + llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; + const size_t num_matches = + FindTypes(sc, name, exact_match, 1, searched_symbol_files, type_list); + if (num_matches) + return type_list.GetTypeAtIndex(0); + return TypeSP(); +} + +size_t Module::FindTypes( + const SymbolContext &sc, const ConstString &name, bool exact_match, + size_t max_matches, + llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, + TypeList &types) { + size_t num_matches = 0; + const char *type_name_cstr = name.GetCString(); + std::string type_scope; + std::string type_basename; + const bool append = true; + TypeClass type_class = eTypeClassAny; + TypeMap typesmap; + if (Type::GetTypeScopeAndBasename(type_name_cstr, type_scope, type_basename, + type_class)) { + // Check if "name" starts with "::" which means the qualified type starts + // from the root namespace and implies and exact match. The typenames we + // get back from clang do not start with "::" so we need to strip this off + // in order to get the qualified names to match + + if (type_scope.size() >= 2 && type_scope[0] == ':' && + type_scope[1] == ':') { + type_scope.erase(0, 2); + exact_match = true; } - if (num_matches > 0) - sc.SortTypeList(typesmap, types); - return num_matches; -} - -SymbolVendor* -Module::GetSymbolVendor (bool can_create, lldb_private::Stream *feedback_strm) -{ - if (!m_did_load_symbol_vendor.load()) - { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - if (!m_did_load_symbol_vendor.load() && can_create) - { - ObjectFile *obj_file = GetObjectFile (); - if (obj_file != nullptr) - { - Timer scoped_timer(__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); - m_symfile_ap.reset(SymbolVendor::FindPlugin(shared_from_this(), feedback_strm)); - m_did_load_symbol_vendor = true; - } - } + ConstString type_basename_const_str(type_basename.c_str()); + if (FindTypes_Impl(sc, type_basename_const_str, nullptr, append, + max_matches, searched_symbol_files, typesmap)) { + typesmap.RemoveMismatchedTypes(type_scope, type_basename, type_class, + exact_match); + num_matches = typesmap.GetSize(); } - return m_symfile_ap.get(); -} - -void -Module::SetFileSpecAndObjectName (const FileSpec &file, const ConstString &object_name) -{ - // Container objects whose paths do not specify a file directly can call - // this function to correct the file and object names. - m_file = file; - m_mod_time = file.GetModificationTime(); - m_object_name = object_name; -} - -const ArchSpec& -Module::GetArchitecture () const -{ - return m_arch; -} - -std::string -Module::GetSpecificationDescription () const -{ - std::string spec(GetFileSpec().GetPath()); - if (m_object_name) - { - spec += '('; - spec += m_object_name.GetCString(); - spec += ')'; + } else { + // The type is not in a namespace/class scope, just search for it by + // basename + if (type_class != eTypeClassAny) { + // The "type_name_cstr" will have been modified if we have a valid type + // class + // prefix (like "struct", "class", "union", "typedef" etc). + FindTypes_Impl(sc, ConstString(type_name_cstr), nullptr, append, + max_matches, searched_symbol_files, typesmap); + typesmap.RemoveMismatchedTypes(type_class); + num_matches = typesmap.GetSize(); + } else { + num_matches = FindTypes_Impl(sc, name, nullptr, append, max_matches, + searched_symbol_files, typesmap); } - return spec; + } + if (num_matches > 0) + sc.SortTypeList(typesmap, types); + return num_matches; } -void -Module::GetDescription (Stream *s, lldb::DescriptionLevel level) -{ +SymbolVendor *Module::GetSymbolVendor(bool can_create, + lldb_private::Stream *feedback_strm) { + if (!m_did_load_symbol_vendor.load()) { std::lock_guard<std::recursive_mutex> guard(m_mutex); - - if (level >= eDescriptionLevelFull) - { - if (m_arch.IsValid()) - s->Printf("(%s) ", m_arch.GetArchitectureName()); + if (!m_did_load_symbol_vendor.load() && can_create) { + ObjectFile *obj_file = GetObjectFile(); + if (obj_file != nullptr) { + Timer scoped_timer(LLVM_PRETTY_FUNCTION, LLVM_PRETTY_FUNCTION); + m_symfile_ap.reset( + SymbolVendor::FindPlugin(shared_from_this(), feedback_strm)); + m_did_load_symbol_vendor = true; + } } - - if (level == eDescriptionLevelBrief) - { - const char *filename = m_file.GetFilename().GetCString(); - if (filename) - s->PutCString (filename); - } - else - { - char path[PATH_MAX]; - if (m_file.GetPath(path, sizeof(path))) - s->PutCString(path); - } - - const char *object_name = m_object_name.GetCString(); - if (object_name) - s->Printf("(%s)", object_name); -} - -void -Module::ReportError (const char *format, ...) -{ - if (format && format[0]) - { - StreamString strm; - strm.PutCString("error: "); - GetDescription(&strm, lldb::eDescriptionLevelBrief); - strm.PutChar (' '); - va_list args; - va_start (args, format); - strm.PrintfVarArg(format, args); - va_end (args); - - const int format_len = strlen(format); - if (format_len > 0) - { - const char last_char = format[format_len-1]; - if (last_char != '\n' || last_char != '\r') - strm.EOL(); - } - Host::SystemLog (Host::eSystemLogError, "%s", strm.GetString().c_str()); + } + return m_symfile_ap.get(); +} + +void Module::SetFileSpecAndObjectName(const FileSpec &file, + const ConstString &object_name) { + // Container objects whose paths do not specify a file directly can call + // this function to correct the file and object names. + m_file = file; + m_mod_time = FileSystem::GetModificationTime(file); + m_object_name = object_name; +} + +const ArchSpec &Module::GetArchitecture() const { return m_arch; } + +std::string Module::GetSpecificationDescription() const { + std::string spec(GetFileSpec().GetPath()); + if (m_object_name) { + spec += '('; + spec += m_object_name.GetCString(); + spec += ')'; + } + return spec; +} + +void Module::GetDescription(Stream *s, lldb::DescriptionLevel level) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + + if (level >= eDescriptionLevelFull) { + if (m_arch.IsValid()) + s->Printf("(%s) ", m_arch.GetArchitectureName()); + } + + if (level == eDescriptionLevelBrief) { + const char *filename = m_file.GetFilename().GetCString(); + if (filename) + s->PutCString(filename); + } else { + char path[PATH_MAX]; + if (m_file.GetPath(path, sizeof(path))) + s->PutCString(path); + } + + const char *object_name = m_object_name.GetCString(); + if (object_name) + s->Printf("(%s)", object_name); +} + +void Module::ReportError(const char *format, ...) { + if (format && format[0]) { + StreamString strm; + strm.PutCString("error: "); + GetDescription(&strm, lldb::eDescriptionLevelBrief); + strm.PutChar(' '); + va_list args; + va_start(args, format); + strm.PrintfVarArg(format, args); + va_end(args); + + const int format_len = strlen(format); + if (format_len > 0) { + const char last_char = format[format_len - 1]; + if (last_char != '\n' || last_char != '\r') + strm.EOL(); } + Host::SystemLog(Host::eSystemLogError, "%s", strm.GetData()); + } } -bool -Module::FileHasChanged () const -{ - if (!m_file_has_changed) - m_file_has_changed = (m_file.GetModificationTime() != m_mod_time); - return m_file_has_changed; -} - -void -Module::ReportErrorIfModifyDetected (const char *format, ...) -{ - if (!m_first_file_changed_log) - { - if (FileHasChanged ()) - { - m_first_file_changed_log = true; - if (format) - { - StreamString strm; - strm.PutCString("error: the object file "); - GetDescription(&strm, lldb::eDescriptionLevelFull); - strm.PutCString (" has been modified\n"); - - va_list args; - va_start (args, format); - strm.PrintfVarArg(format, args); - va_end (args); - - const int format_len = strlen(format); - if (format_len > 0) - { - const char last_char = format[format_len-1]; - if (last_char != '\n' || last_char != '\r') - strm.EOL(); - } - strm.PutCString("The debug session should be aborted as the original debug information has been overwritten.\n"); - Host::SystemLog (Host::eSystemLogError, "%s", strm.GetString().c_str()); - } - } - } +bool Module::FileHasChanged() const { + if (!m_file_has_changed) + m_file_has_changed = + (FileSystem::GetModificationTime(m_file) != m_mod_time); + return m_file_has_changed; } -void -Module::ReportWarning (const char *format, ...) -{ - if (format && format[0]) - { +void Module::ReportErrorIfModifyDetected(const char *format, ...) { + if (!m_first_file_changed_log) { + if (FileHasChanged()) { + m_first_file_changed_log = true; + if (format) { StreamString strm; - strm.PutCString("warning: "); + strm.PutCString("error: the object file "); GetDescription(&strm, lldb::eDescriptionLevelFull); - strm.PutChar (' '); - + strm.PutCString(" has been modified\n"); + va_list args; - va_start (args, format); + va_start(args, format); strm.PrintfVarArg(format, args); - va_end (args); - + va_end(args); + const int format_len = strlen(format); - if (format_len > 0) - { - const char last_char = format[format_len-1]; - if (last_char != '\n' || last_char != '\r') - strm.EOL(); + if (format_len > 0) { + const char last_char = format[format_len - 1]; + if (last_char != '\n' || last_char != '\r') + strm.EOL(); } - Host::SystemLog (Host::eSystemLogWarning, "%s", strm.GetString().c_str()); + strm.PutCString("The debug session should be aborted as the original " + "debug information has been overwritten.\n"); + Host::SystemLog(Host::eSystemLogError, "%s", strm.GetData()); + } } -} - -void -Module::LogMessage (Log *log, const char *format, ...) -{ - if (log != nullptr) - { - StreamString log_message; - GetDescription(&log_message, lldb::eDescriptionLevelFull); - log_message.PutCString (": "); - va_list args; - va_start (args, format); - log_message.PrintfVarArg (format, args); - va_end (args); - log->PutCString(log_message.GetString().c_str()); + } +} + +void Module::ReportWarning(const char *format, ...) { + if (format && format[0]) { + StreamString strm; + strm.PutCString("warning: "); + GetDescription(&strm, lldb::eDescriptionLevelFull); + strm.PutChar(' '); + + va_list args; + va_start(args, format); + strm.PrintfVarArg(format, args); + va_end(args); + + const int format_len = strlen(format); + if (format_len > 0) { + const char last_char = format[format_len - 1]; + if (last_char != '\n' || last_char != '\r') + strm.EOL(); } -} - -void -Module::LogMessageVerboseBacktrace (Log *log, const char *format, ...) -{ - if (log != nullptr) - { - StreamString log_message; - GetDescription(&log_message, lldb::eDescriptionLevelFull); - log_message.PutCString (": "); - va_list args; - va_start (args, format); - log_message.PrintfVarArg (format, args); - va_end (args); - if (log->GetVerbose()) - { - std::string back_trace; - llvm::raw_string_ostream stream(back_trace); - llvm::sys::PrintStackTrace(stream); - log_message.PutCString(back_trace.c_str()); - } - log->PutCString(log_message.GetString().c_str()); + Host::SystemLog(Host::eSystemLogWarning, "%s", strm.GetData()); + } +} + +void Module::LogMessage(Log *log, const char *format, ...) { + if (log != nullptr) { + StreamString log_message; + GetDescription(&log_message, lldb::eDescriptionLevelFull); + log_message.PutCString(": "); + va_list args; + va_start(args, format); + log_message.PrintfVarArg(format, args); + va_end(args); + log->PutCString(log_message.GetData()); + } +} + +void Module::LogMessageVerboseBacktrace(Log *log, const char *format, ...) { + if (log != nullptr) { + StreamString log_message; + GetDescription(&log_message, lldb::eDescriptionLevelFull); + log_message.PutCString(": "); + va_list args; + va_start(args, format); + log_message.PrintfVarArg(format, args); + va_end(args); + if (log->GetVerbose()) { + std::string back_trace; + llvm::raw_string_ostream stream(back_trace); + llvm::sys::PrintStackTrace(stream); + log_message.PutCString(back_trace); } + log->PutCString(log_message.GetData()); + } } -void -Module::Dump(Stream *s) -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - //s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); - s->Indent(); - s->Printf("Module %s%s%s%s\n", - m_file.GetPath().c_str(), - m_object_name ? "(" : "", - m_object_name ? m_object_name.GetCString() : "", - m_object_name ? ")" : ""); - - s->IndentMore(); - - ObjectFile *objfile = GetObjectFile (); - if (objfile) - objfile->Dump(s); +void Module::Dump(Stream *s) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); + s->Indent(); + s->Printf("Module %s%s%s%s\n", m_file.GetPath().c_str(), + m_object_name ? "(" : "", + m_object_name ? m_object_name.GetCString() : "", + m_object_name ? ")" : ""); - SymbolVendor *symbols = GetSymbolVendor (); - if (symbols) - symbols->Dump(s); + s->IndentMore(); - s->IndentLess(); -} + ObjectFile *objfile = GetObjectFile(); + if (objfile) + objfile->Dump(s); -TypeList* -Module::GetTypeList () -{ - SymbolVendor *symbols = GetSymbolVendor (); - if (symbols) - return &symbols->GetTypeList(); - return nullptr; -} + SymbolVendor *symbols = GetSymbolVendor(); + if (symbols) + symbols->Dump(s); -const ConstString & -Module::GetObjectName() const -{ - return m_object_name; + s->IndentLess(); } -ObjectFile * -Module::GetObjectFile() -{ - if (!m_did_load_objfile.load()) - { - std::lock_guard<std::recursive_mutex> guard(m_mutex); - if (!m_did_load_objfile.load()) - { - Timer scoped_timer(__PRETTY_FUNCTION__, - "Module::GetObjectFile () module = %s", GetFileSpec().GetFilename().AsCString("")); - DataBufferSP data_sp; - lldb::offset_t data_offset = 0; - const lldb::offset_t file_size = m_file.GetByteSize(); - if (file_size > m_object_offset) - { - m_did_load_objfile = true; - m_objfile_sp = ObjectFile::FindPlugin (shared_from_this(), - &m_file, - m_object_offset, - file_size - m_object_offset, - data_sp, - data_offset); - if (m_objfile_sp) - { - // Once we get the object file, update our module with the object file's - // architecture since it might differ in vendor/os if some parts were - // unknown. But since the matching arch might already be more specific - // than the generic COFF architecture, only merge in those values that - // overwrite unspecified unknown values. - ArchSpec new_arch; - m_objfile_sp->GetArchitecture(new_arch); - m_arch.MergeFrom(new_arch); - } - else - { - ReportError ("failed to load objfile for %s", GetFileSpec().GetPath().c_str()); - } - } - } - } - return m_objfile_sp.get(); +TypeList *Module::GetTypeList() { + SymbolVendor *symbols = GetSymbolVendor(); + if (symbols) + return &symbols->GetTypeList(); + return nullptr; } -SectionList * -Module::GetSectionList() -{ - // Populate m_unified_sections_ap with sections from objfile. - if (!m_sections_ap) - { - ObjectFile *obj_file = GetObjectFile(); - if (obj_file != nullptr) - obj_file->CreateSections(*GetUnifiedSectionList()); - } - return m_sections_ap.get(); -} - -void -Module::SectionFileAddressesChanged () -{ - ObjectFile *obj_file = GetObjectFile (); - if (obj_file) - obj_file->SectionFileAddressesChanged (); - SymbolVendor* sym_vendor = GetSymbolVendor(); - if (sym_vendor != nullptr) - sym_vendor->SectionFileAddressesChanged (); -} - -SectionList * -Module::GetUnifiedSectionList() -{ - // Populate m_unified_sections_ap with sections from objfile. - if (!m_sections_ap) - m_sections_ap.reset(new SectionList()); - return m_sections_ap.get(); -} - -const Symbol * -Module::FindFirstSymbolWithNameAndType (const ConstString &name, SymbolType symbol_type) -{ - Timer scoped_timer(__PRETTY_FUNCTION__, - "Module::FindFirstSymbolWithNameAndType (name = %s, type = %i)", - name.AsCString(), - symbol_type); - SymbolVendor* sym_vendor = GetSymbolVendor(); - if (sym_vendor) - { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab) - return symtab->FindFirstSymbolWithNameAndType (name, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny); - } - return nullptr; -} -void -Module::SymbolIndicesToSymbolContextList (Symtab *symtab, std::vector<uint32_t> &symbol_indexes, SymbolContextList &sc_list) -{ - // No need to protect this call using m_mutex all other method calls are - // already thread safe. +const ConstString &Module::GetObjectName() const { return m_object_name; } - size_t num_indices = symbol_indexes.size(); - if (num_indices > 0) - { - SymbolContext sc; - CalculateSymbolContext (&sc); - for (size_t i = 0; i < num_indices; i++) - { - sc.symbol = symtab->SymbolAtIndex (symbol_indexes[i]); - if (sc.symbol) - sc_list.Append (sc); +ObjectFile *Module::GetObjectFile() { + if (!m_did_load_objfile.load()) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + if (!m_did_load_objfile.load()) { + Timer scoped_timer(LLVM_PRETTY_FUNCTION, + "Module::GetObjectFile () module = %s", + GetFileSpec().GetFilename().AsCString("")); + DataBufferSP data_sp; + lldb::offset_t data_offset = 0; + const lldb::offset_t file_size = m_file.GetByteSize(); + if (file_size > m_object_offset) { + m_did_load_objfile = true; + m_objfile_sp = ObjectFile::FindPlugin( + shared_from_this(), &m_file, m_object_offset, + file_size - m_object_offset, data_sp, data_offset); + if (m_objfile_sp) { + // Once we get the object file, update our module with the object + // file's + // architecture since it might differ in vendor/os if some parts were + // unknown. But since the matching arch might already be more + // specific + // than the generic COFF architecture, only merge in those values that + // overwrite unspecified unknown values. + ArchSpec new_arch; + m_objfile_sp->GetArchitecture(new_arch); + m_arch.MergeFrom(new_arch); + } else { + ReportError("failed to load objfile for %s", + GetFileSpec().GetPath().c_str()); } + } } + } + return m_objfile_sp.get(); } -size_t -Module::FindFunctionSymbols (const ConstString &name, - uint32_t name_type_mask, - SymbolContextList& sc_list) -{ - Timer scoped_timer(__PRETTY_FUNCTION__, - "Module::FindSymbolsFunctions (name = %s, mask = 0x%8.8x)", - name.AsCString(), - name_type_mask); - SymbolVendor* sym_vendor = GetSymbolVendor(); - if (sym_vendor) - { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab) - return symtab->FindFunctionSymbols (name, name_type_mask, sc_list); +SectionList *Module::GetSectionList() { + // Populate m_unified_sections_ap with sections from objfile. + if (!m_sections_ap) { + ObjectFile *obj_file = GetObjectFile(); + if (obj_file != nullptr) + obj_file->CreateSections(*GetUnifiedSectionList()); + } + return m_sections_ap.get(); +} + +void Module::SectionFileAddressesChanged() { + ObjectFile *obj_file = GetObjectFile(); + if (obj_file) + obj_file->SectionFileAddressesChanged(); + SymbolVendor *sym_vendor = GetSymbolVendor(); + if (sym_vendor != nullptr) + sym_vendor->SectionFileAddressesChanged(); +} + +SectionList *Module::GetUnifiedSectionList() { + // Populate m_unified_sections_ap with sections from objfile. + if (!m_sections_ap) + m_sections_ap.reset(new SectionList()); + return m_sections_ap.get(); +} + +const Symbol *Module::FindFirstSymbolWithNameAndType(const ConstString &name, + SymbolType symbol_type) { + Timer scoped_timer( + LLVM_PRETTY_FUNCTION, + "Module::FindFirstSymbolWithNameAndType (name = %s, type = %i)", + name.AsCString(), symbol_type); + SymbolVendor *sym_vendor = GetSymbolVendor(); + if (sym_vendor) { + Symtab *symtab = sym_vendor->GetSymtab(); + if (symtab) + return symtab->FindFirstSymbolWithNameAndType( + name, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny); + } + return nullptr; +} +void Module::SymbolIndicesToSymbolContextList( + Symtab *symtab, std::vector<uint32_t> &symbol_indexes, + SymbolContextList &sc_list) { + // No need to protect this call using m_mutex all other method calls are + // already thread safe. + + size_t num_indices = symbol_indexes.size(); + if (num_indices > 0) { + SymbolContext sc; + CalculateSymbolContext(&sc); + for (size_t i = 0; i < num_indices; i++) { + sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]); + if (sc.symbol) + sc_list.Append(sc); } - return 0; -} - -size_t -Module::FindSymbolsWithNameAndType (const ConstString &name, SymbolType symbol_type, SymbolContextList &sc_list) -{ - // No need to protect this call using m_mutex all other method calls are - // already thread safe. - - Timer scoped_timer(__PRETTY_FUNCTION__, - "Module::FindSymbolsWithNameAndType (name = %s, type = %i)", - name.AsCString(), - symbol_type); - const size_t initial_size = sc_list.GetSize(); - SymbolVendor* sym_vendor = GetSymbolVendor(); - if (sym_vendor) - { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab) - { - std::vector<uint32_t> symbol_indexes; - symtab->FindAllSymbolsWithNameAndType (name, symbol_type, symbol_indexes); - SymbolIndicesToSymbolContextList (symtab, symbol_indexes, sc_list); - } + } +} + +size_t Module::FindFunctionSymbols(const ConstString &name, + uint32_t name_type_mask, + SymbolContextList &sc_list) { + Timer scoped_timer(LLVM_PRETTY_FUNCTION, + "Module::FindSymbolsFunctions (name = %s, mask = 0x%8.8x)", + name.AsCString(), name_type_mask); + SymbolVendor *sym_vendor = GetSymbolVendor(); + if (sym_vendor) { + Symtab *symtab = sym_vendor->GetSymtab(); + if (symtab) + return symtab->FindFunctionSymbols(name, name_type_mask, sc_list); + } + return 0; +} + +size_t Module::FindSymbolsWithNameAndType(const ConstString &name, + SymbolType symbol_type, + SymbolContextList &sc_list) { + // No need to protect this call using m_mutex all other method calls are + // already thread safe. + + Timer scoped_timer( + LLVM_PRETTY_FUNCTION, + "Module::FindSymbolsWithNameAndType (name = %s, type = %i)", + name.AsCString(), symbol_type); + const size_t initial_size = sc_list.GetSize(); + SymbolVendor *sym_vendor = GetSymbolVendor(); + if (sym_vendor) { + Symtab *symtab = sym_vendor->GetSymtab(); + if (symtab) { + std::vector<uint32_t> symbol_indexes; + symtab->FindAllSymbolsWithNameAndType(name, symbol_type, symbol_indexes); + SymbolIndicesToSymbolContextList(symtab, symbol_indexes, sc_list); } - return sc_list.GetSize() - initial_size; -} - -size_t -Module::FindSymbolsMatchingRegExAndType (const RegularExpression ®ex, SymbolType symbol_type, SymbolContextList &sc_list) -{ - // No need to protect this call using m_mutex all other method calls are - // already thread safe. - - Timer scoped_timer(__PRETTY_FUNCTION__, - "Module::FindSymbolsMatchingRegExAndType (regex = %s, type = %i)", - regex.GetText(), - symbol_type); - const size_t initial_size = sc_list.GetSize(); - SymbolVendor* sym_vendor = GetSymbolVendor(); - if (sym_vendor) - { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab) - { - std::vector<uint32_t> symbol_indexes; - symtab->FindAllSymbolsMatchingRexExAndType (regex, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes); - SymbolIndicesToSymbolContextList (symtab, symbol_indexes, sc_list); - } + } + return sc_list.GetSize() - initial_size; +} + +size_t Module::FindSymbolsMatchingRegExAndType(const RegularExpression ®ex, + SymbolType symbol_type, + SymbolContextList &sc_list) { + // No need to protect this call using m_mutex all other method calls are + // already thread safe. + + Timer scoped_timer( + LLVM_PRETTY_FUNCTION, + "Module::FindSymbolsMatchingRegExAndType (regex = %s, type = %i)", + regex.GetText().str().c_str(), symbol_type); + const size_t initial_size = sc_list.GetSize(); + SymbolVendor *sym_vendor = GetSymbolVendor(); + if (sym_vendor) { + Symtab *symtab = sym_vendor->GetSymtab(); + if (symtab) { + std::vector<uint32_t> symbol_indexes; + symtab->FindAllSymbolsMatchingRexExAndType( + regex, symbol_type, Symtab::eDebugAny, Symtab::eVisibilityAny, + symbol_indexes); + SymbolIndicesToSymbolContextList(symtab, symbol_indexes, sc_list); } - return sc_list.GetSize() - initial_size; + } + return sc_list.GetSize() - initial_size; } -void -Module::SetSymbolFileFileSpec (const FileSpec &file) -{ - if (!file.Exists()) - return; - if (m_symfile_ap) - { - // Remove any sections in the unified section list that come from the current symbol vendor. - SectionList *section_list = GetSectionList(); - SymbolFile *symbol_file = m_symfile_ap->GetSymbolFile(); - if (section_list && symbol_file) - { - ObjectFile *obj_file = symbol_file->GetObjectFile(); - // Make sure we have an object file and that the symbol vendor's objfile isn't - // the same as the module's objfile before we remove any sections for it... - if (obj_file) - { - // Check to make sure we aren't trying to specify the file we already have - if (obj_file->GetFileSpec() == file) - { - // We are being told to add the exact same file that we already have - // we don't have to do anything. - return; - } - - // Cleare the current symtab as we are going to replace it with a new one - obj_file->ClearSymtab(); - - // The symbol file might be a directory bundle ("/tmp/a.out.dSYM") instead - // of a full path to the symbol file within the bundle - // ("/tmp/a.out.dSYM/Contents/Resources/DWARF/a.out"). So we need to check this - - if (file.IsDirectory()) - { - std::string new_path(file.GetPath()); - std::string old_path(obj_file->GetFileSpec().GetPath()); - if (old_path.find(new_path) == 0) - { - // We specified the same bundle as the symbol file that we already have - return; - } - } - - if (obj_file != m_objfile_sp.get()) - { - size_t num_sections = section_list->GetNumSections (0); - for (size_t idx = num_sections; idx > 0; --idx) - { - lldb::SectionSP section_sp (section_list->GetSectionAtIndex (idx - 1)); - if (section_sp->GetObjectFile() == obj_file) - { - section_list->DeleteSection (idx - 1); - } - } - } - } +void Module::SetSymbolFileFileSpec(const FileSpec &file) { + if (!file.Exists()) + return; + if (m_symfile_ap) { + // Remove any sections in the unified section list that come from the + // current symbol vendor. + SectionList *section_list = GetSectionList(); + SymbolFile *symbol_file = m_symfile_ap->GetSymbolFile(); + if (section_list && symbol_file) { + ObjectFile *obj_file = symbol_file->GetObjectFile(); + // Make sure we have an object file and that the symbol vendor's objfile + // isn't + // the same as the module's objfile before we remove any sections for + // it... + if (obj_file) { + // Check to make sure we aren't trying to specify the file we already + // have + if (obj_file->GetFileSpec() == file) { + // We are being told to add the exact same file that we already have + // we don't have to do anything. + return; } - // Keep all old symbol files around in case there are any lingering type references in - // any SBValue objects that might have been handed out. - m_old_symfiles.push_back(std::move(m_symfile_ap)); - } - m_symfile_spec = file; - m_symfile_ap.reset(); - m_did_load_symbol_vendor = false; -} -bool -Module::IsExecutable () -{ - if (GetObjectFile() == nullptr) - return false; - else - return GetObjectFile()->IsExecutable(); -} + // Cleare the current symtab as we are going to replace it with a new + // one + obj_file->ClearSymtab(); + + // The symbol file might be a directory bundle ("/tmp/a.out.dSYM") + // instead + // of a full path to the symbol file within the bundle + // ("/tmp/a.out.dSYM/Contents/Resources/DWARF/a.out"). So we need to + // check this + + if (file.IsDirectory()) { + std::string new_path(file.GetPath()); + std::string old_path(obj_file->GetFileSpec().GetPath()); + if (old_path.find(new_path) == 0) { + // We specified the same bundle as the symbol file that we already + // have + return; + } + } -bool -Module::IsLoadedInTarget (Target *target) -{ - ObjectFile *obj_file = GetObjectFile(); - if (obj_file) - { - SectionList *sections = GetSectionList(); - if (sections != nullptr) - { - size_t num_sections = sections->GetSize(); - for (size_t sect_idx = 0; sect_idx < num_sections; sect_idx++) - { - SectionSP section_sp = sections->GetSectionAtIndex(sect_idx); - if (section_sp->GetLoadBaseAddress(target) != LLDB_INVALID_ADDRESS) - { - return true; - } + if (obj_file != m_objfile_sp.get()) { + size_t num_sections = section_list->GetNumSections(0); + for (size_t idx = num_sections; idx > 0; --idx) { + lldb::SectionSP section_sp( + section_list->GetSectionAtIndex(idx - 1)); + if (section_sp->GetObjectFile() == obj_file) { + section_list->DeleteSection(idx - 1); } + } } + } } + // Keep all old symbol files around in case there are any lingering type + // references in + // any SBValue objects that might have been handed out. + m_old_symfiles.push_back(std::move(m_symfile_ap)); + } + m_symfile_spec = file; + m_symfile_ap.reset(); + m_did_load_symbol_vendor = false; +} + +bool Module::IsExecutable() { + if (GetObjectFile() == nullptr) return false; + else + return GetObjectFile()->IsExecutable(); +} + +bool Module::IsLoadedInTarget(Target *target) { + ObjectFile *obj_file = GetObjectFile(); + if (obj_file) { + SectionList *sections = GetSectionList(); + if (sections != nullptr) { + size_t num_sections = sections->GetSize(); + for (size_t sect_idx = 0; sect_idx < num_sections; sect_idx++) { + SectionSP section_sp = sections->GetSectionAtIndex(sect_idx); + if (section_sp->GetLoadBaseAddress(target) != LLDB_INVALID_ADDRESS) { + return true; + } + } + } + } + return false; } -bool -Module::LoadScriptingResourceInTarget (Target *target, Error& error, Stream* feedback_stream) -{ - if (!target) - { - error.SetErrorString("invalid destination Target"); - return false; - } - - LoadScriptFromSymFile should_load = target->TargetProperties::GetLoadScriptFromSymbolFile(); - - if (should_load == eLoadScriptFromSymFileFalse) - return false; - - Debugger &debugger = target->GetDebugger(); - const ScriptLanguage script_language = debugger.GetScriptLanguage(); - if (script_language != eScriptLanguageNone) - { - - PlatformSP platform_sp(target->GetPlatform()); - - if (!platform_sp) - { - error.SetErrorString("invalid Platform"); - return false; - } +bool Module::LoadScriptingResourceInTarget(Target *target, Error &error, + Stream *feedback_stream) { + if (!target) { + error.SetErrorString("invalid destination Target"); + return false; + } - FileSpecList file_specs = platform_sp->LocateExecutableScriptingResources (target, - *this, - feedback_stream); + LoadScriptFromSymFile should_load = + target->TargetProperties::GetLoadScriptFromSymbolFile(); - const uint32_t num_specs = file_specs.GetSize(); - if (num_specs) - { - ScriptInterpreter *script_interpreter = debugger.GetCommandInterpreter().GetScriptInterpreter(); - if (script_interpreter) - { - for (uint32_t i = 0; i < num_specs; ++i) - { - FileSpec scripting_fspec (file_specs.GetFileSpecAtIndex(i)); - if (scripting_fspec && scripting_fspec.Exists()) - { - if (should_load == eLoadScriptFromSymFileWarn) - { - if (feedback_stream) - feedback_stream->Printf("warning: '%s' contains a debug script. To run this script in " - "this debug session:\n\n command script import \"%s\"\n\n" - "To run all discovered debug scripts in this session:\n\n" - " settings set target.load-script-from-symbol-file true\n", - GetFileSpec().GetFileNameStrippingExtension().GetCString(), - scripting_fspec.GetPath().c_str()); - return false; - } - StreamString scripting_stream; - scripting_fspec.Dump(&scripting_stream); - const bool can_reload = true; - const bool init_lldb_globals = false; - bool did_load = script_interpreter->LoadScriptingModule(scripting_stream.GetData(), - can_reload, - init_lldb_globals, - error); - if (!did_load) - return false; - } - } - } - else - { - error.SetErrorString("invalid ScriptInterpreter"); - return false; + if (should_load == eLoadScriptFromSymFileFalse) + return false; + + Debugger &debugger = target->GetDebugger(); + const ScriptLanguage script_language = debugger.GetScriptLanguage(); + if (script_language != eScriptLanguageNone) { + + PlatformSP platform_sp(target->GetPlatform()); + + if (!platform_sp) { + error.SetErrorString("invalid Platform"); + return false; + } + + FileSpecList file_specs = platform_sp->LocateExecutableScriptingResources( + target, *this, feedback_stream); + + const uint32_t num_specs = file_specs.GetSize(); + if (num_specs) { + ScriptInterpreter *script_interpreter = + debugger.GetCommandInterpreter().GetScriptInterpreter(); + if (script_interpreter) { + for (uint32_t i = 0; i < num_specs; ++i) { + FileSpec scripting_fspec(file_specs.GetFileSpecAtIndex(i)); + if (scripting_fspec && scripting_fspec.Exists()) { + if (should_load == eLoadScriptFromSymFileWarn) { + if (feedback_stream) + feedback_stream->Printf( + "warning: '%s' contains a debug script. To run this script " + "in " + "this debug session:\n\n command script import " + "\"%s\"\n\n" + "To run all discovered debug scripts in this session:\n\n" + " settings set target.load-script-from-symbol-file " + "true\n", + GetFileSpec().GetFileNameStrippingExtension().GetCString(), + scripting_fspec.GetPath().c_str()); + return false; } + StreamString scripting_stream; + scripting_fspec.Dump(&scripting_stream); + const bool can_reload = true; + const bool init_lldb_globals = false; + bool did_load = script_interpreter->LoadScriptingModule( + scripting_stream.GetData(), can_reload, init_lldb_globals, + error); + if (!did_load) + return false; + } } + } else { + error.SetErrorString("invalid ScriptInterpreter"); + return false; + } } - return true; + } + return true; } -bool -Module::SetArchitecture (const ArchSpec &new_arch) -{ - if (!m_arch.IsValid()) - { - m_arch = new_arch; - return true; - } - return m_arch.IsCompatibleMatch(new_arch); +bool Module::SetArchitecture(const ArchSpec &new_arch) { + if (!m_arch.IsValid()) { + m_arch = new_arch; + return true; + } + return m_arch.IsCompatibleMatch(new_arch); } -bool -Module::SetLoadAddress (Target &target, lldb::addr_t value, bool value_is_offset, bool &changed) -{ - ObjectFile *object_file = GetObjectFile(); - if (object_file != nullptr) - { - changed = object_file->SetLoadAddress(target, value, value_is_offset); - return true; - } - else - { - changed = false; - } - return false; +bool Module::SetLoadAddress(Target &target, lldb::addr_t value, + bool value_is_offset, bool &changed) { + ObjectFile *object_file = GetObjectFile(); + if (object_file != nullptr) { + changed = object_file->SetLoadAddress(target, value, value_is_offset); + return true; + } else { + changed = false; + } + return false; } +bool Module::MatchesModuleSpec(const ModuleSpec &module_ref) { + const UUID &uuid = module_ref.GetUUID(); -bool -Module::MatchesModuleSpec (const ModuleSpec &module_ref) -{ - const UUID &uuid = module_ref.GetUUID(); - - if (uuid.IsValid()) - { - // If the UUID matches, then nothing more needs to match... - return (uuid == GetUUID()); - } - - const FileSpec &file_spec = module_ref.GetFileSpec(); - if (file_spec) - { - if (!FileSpec::Equal (file_spec, m_file, (bool)file_spec.GetDirectory()) && - !FileSpec::Equal (file_spec, m_platform_file, (bool)file_spec.GetDirectory())) - return false; - } + if (uuid.IsValid()) { + // If the UUID matches, then nothing more needs to match... + return (uuid == GetUUID()); + } - const FileSpec &platform_file_spec = module_ref.GetPlatformFileSpec(); - if (platform_file_spec) - { - if (!FileSpec::Equal (platform_file_spec, GetPlatformFileSpec (), (bool)platform_file_spec.GetDirectory())) - return false; - } - - const ArchSpec &arch = module_ref.GetArchitecture(); - if (arch.IsValid()) - { - if (!m_arch.IsCompatibleMatch(arch)) - return false; - } - - const ConstString &object_name = module_ref.GetObjectName(); - if (object_name) - { - if (object_name != GetObjectName()) - return false; - } - return true; + const FileSpec &file_spec = module_ref.GetFileSpec(); + if (file_spec) { + if (!FileSpec::Equal(file_spec, m_file, (bool)file_spec.GetDirectory()) && + !FileSpec::Equal(file_spec, m_platform_file, + (bool)file_spec.GetDirectory())) + return false; + } + + const FileSpec &platform_file_spec = module_ref.GetPlatformFileSpec(); + if (platform_file_spec) { + if (!FileSpec::Equal(platform_file_spec, GetPlatformFileSpec(), + (bool)platform_file_spec.GetDirectory())) + return false; + } + + const ArchSpec &arch = module_ref.GetArchitecture(); + if (arch.IsValid()) { + if (!m_arch.IsCompatibleMatch(arch)) + return false; + } + + const ConstString &object_name = module_ref.GetObjectName(); + if (object_name) { + if (object_name != GetObjectName()) + return false; + } + return true; } -bool -Module::FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - return m_source_mappings.FindFile (orig_spec, new_spec); +bool Module::FindSourceFile(const FileSpec &orig_spec, + FileSpec &new_spec) const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return m_source_mappings.FindFile(orig_spec, new_spec); } -bool -Module::RemapSourceFile (const char *path, std::string &new_path) const -{ - std::lock_guard<std::recursive_mutex> guard(m_mutex); - return m_source_mappings.RemapPath(path, new_path); +bool Module::RemapSourceFile(llvm::StringRef path, + std::string &new_path) const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return m_source_mappings.RemapPath(path, new_path); } -uint32_t -Module::GetVersion (uint32_t *versions, uint32_t num_versions) -{ - ObjectFile *obj_file = GetObjectFile(); - if (obj_file) - return obj_file->GetVersion (versions, num_versions); - - if (versions != nullptr && num_versions != 0) - { - for (uint32_t i = 0; i < num_versions; ++i) - versions[i] = LLDB_INVALID_MODULE_VERSION; - } - return 0; +uint32_t Module::GetVersion(uint32_t *versions, uint32_t num_versions) { + ObjectFile *obj_file = GetObjectFile(); + if (obj_file) + return obj_file->GetVersion(versions, num_versions); + + if (versions != nullptr && num_versions != 0) { + for (uint32_t i = 0; i < num_versions; ++i) + versions[i] = LLDB_INVALID_MODULE_VERSION; + } + return 0; } ModuleSP -Module::CreateJITModule (const lldb::ObjectFileJITDelegateSP &delegate_sp) -{ - if (delegate_sp) - { - // Must create a module and place it into a shared pointer before - // we can create an object file since it has a std::weak_ptr back - // to the module, so we need to control the creation carefully in - // this static function - ModuleSP module_sp(new Module()); - module_sp->m_objfile_sp.reset (new ObjectFileJIT (module_sp, delegate_sp)); - if (module_sp->m_objfile_sp) - { - // Once we get the object file, update our module with the object file's - // architecture since it might differ in vendor/os if some parts were - // unknown. - module_sp->m_objfile_sp->GetArchitecture (module_sp->m_arch); - } - return module_sp; +Module::CreateJITModule(const lldb::ObjectFileJITDelegateSP &delegate_sp) { + if (delegate_sp) { + // Must create a module and place it into a shared pointer before + // we can create an object file since it has a std::weak_ptr back + // to the module, so we need to control the creation carefully in + // this static function + ModuleSP module_sp(new Module()); + module_sp->m_objfile_sp.reset(new ObjectFileJIT(module_sp, delegate_sp)); + if (module_sp->m_objfile_sp) { + // Once we get the object file, update our module with the object file's + // architecture since it might differ in vendor/os if some parts were + // unknown. + module_sp->m_objfile_sp->GetArchitecture(module_sp->m_arch); } - return ModuleSP(); + return module_sp; + } + return ModuleSP(); } -bool -Module::GetIsDynamicLinkEditor() -{ - ObjectFile * obj_file = GetObjectFile (); +bool Module::GetIsDynamicLinkEditor() { + ObjectFile *obj_file = GetObjectFile(); - if (obj_file) - return obj_file->GetIsDynamicLinkEditor(); + if (obj_file) + return obj_file->GetIsDynamicLinkEditor(); - return false; + return false; } diff --git a/source/Core/ModuleChild.cpp b/source/Core/ModuleChild.cpp index 9637fc3aedda..86495742754d 100644 --- a/source/Core/ModuleChild.cpp +++ b/source/Core/ModuleChild.cpp @@ -11,36 +11,22 @@ using namespace lldb_private; -ModuleChild::ModuleChild (const lldb::ModuleSP &module_sp) : - m_module_wp (module_sp) -{ -} +ModuleChild::ModuleChild(const lldb::ModuleSP &module_sp) + : m_module_wp(module_sp) {} -ModuleChild::ModuleChild (const ModuleChild& rhs) : - m_module_wp(rhs.m_module_wp) -{ -} +ModuleChild::ModuleChild(const ModuleChild &rhs) + : m_module_wp(rhs.m_module_wp) {} -ModuleChild::~ModuleChild() -{ -} +ModuleChild::~ModuleChild() {} -const ModuleChild& -ModuleChild::operator= (const ModuleChild& rhs) -{ - if (this != &rhs) - m_module_wp = rhs.m_module_wp; - return *this; +const ModuleChild &ModuleChild::operator=(const ModuleChild &rhs) { + if (this != &rhs) + m_module_wp = rhs.m_module_wp; + return *this; } -lldb::ModuleSP -ModuleChild::GetModule () const -{ - return m_module_wp.lock(); -} +lldb::ModuleSP ModuleChild::GetModule() const { return m_module_wp.lock(); } -void -ModuleChild::SetModule (const lldb::ModuleSP &module_sp) -{ - m_module_wp = module_sp; +void ModuleChild::SetModule(const lldb::ModuleSP &module_sp) { + m_module_wp = module_sp; } diff --git a/source/Core/ModuleList.cpp b/source/Core/ModuleList.cpp index bfd53e7d1c2c..b980e15c0b37 100644 --- a/source/Core/ModuleList.cpp +++ b/source/Core/ModuleList.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/Symbols.h" #include "lldb/Symbol/ObjectFile.h" @@ -28,1131 +29,934 @@ using namespace lldb; using namespace lldb_private; -ModuleList::ModuleList() : m_modules(), m_modules_mutex(), m_notifier(nullptr) -{ +ModuleList::ModuleList() + : m_modules(), m_modules_mutex(), m_notifier(nullptr) {} + +ModuleList::ModuleList(const ModuleList &rhs) + : m_modules(), m_modules_mutex(), m_notifier(nullptr) { + std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex); + std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex); + m_modules = rhs.m_modules; +} + +ModuleList::ModuleList(ModuleList::Notifier *notifier) + : m_modules(), m_modules_mutex(), m_notifier(notifier) {} + +const ModuleList &ModuleList::operator=(const ModuleList &rhs) { + if (this != &rhs) { + // That's probably me nit-picking, but in theoretical situation: + // + // * that two threads A B and + // * two ModuleList's x y do opposite assignments ie.: + // + // in thread A: | in thread B: + // x = y; | y = x; + // + // This establishes correct(same) lock taking order and thus + // avoids priority inversion. + if (uintptr_t(this) > uintptr_t(&rhs)) { + std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex); + std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex); + m_modules = rhs.m_modules; + } else { + std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex); + std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex); + m_modules = rhs.m_modules; + } + } + return *this; } -ModuleList::ModuleList(const ModuleList &rhs) : m_modules(), m_modules_mutex(), m_notifier(nullptr) -{ - std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex); - std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex); - m_modules = rhs.m_modules; -} - -ModuleList::ModuleList(ModuleList::Notifier *notifier) : m_modules(), m_modules_mutex(), m_notifier(notifier) -{ -} +ModuleList::~ModuleList() = default; -const ModuleList& -ModuleList::operator= (const ModuleList& rhs) -{ - if (this != &rhs) - { - // That's probably me nit-picking, but in theoretical situation: - // - // * that two threads A B and - // * two ModuleList's x y do opposite assignments ie.: - // - // in thread A: | in thread B: - // x = y; | y = x; - // - // This establishes correct(same) lock taking order and thus - // avoids priority inversion. - if (uintptr_t(this) > uintptr_t(&rhs)) - { - std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex); - std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex); - m_modules = rhs.m_modules; - } - else - { - std::lock_guard<std::recursive_mutex> lhs_guard(m_modules_mutex); - std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_modules_mutex); - m_modules = rhs.m_modules; - } - } - return *this; +void ModuleList::AppendImpl(const ModuleSP &module_sp, bool use_notifier) { + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + m_modules.push_back(module_sp); + if (use_notifier && m_notifier) + m_notifier->ModuleAdded(*this, module_sp); + } } -ModuleList::~ModuleList() = default; +void ModuleList::Append(const ModuleSP &module_sp) { AppendImpl(module_sp); } -void -ModuleList::AppendImpl (const ModuleSP &module_sp, bool use_notifier) -{ - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - m_modules.push_back(module_sp); - if (use_notifier && m_notifier) - m_notifier->ModuleAdded(*this, module_sp); - } -} +void ModuleList::ReplaceEquivalent(const ModuleSP &module_sp) { + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); -void -ModuleList::Append (const ModuleSP &module_sp) -{ - AppendImpl (module_sp); -} + // First remove any equivalent modules. Equivalent modules are modules + // whose path, platform path and architecture match. + ModuleSpec equivalent_module_spec(module_sp->GetFileSpec(), + module_sp->GetArchitecture()); + equivalent_module_spec.GetPlatformFileSpec() = + module_sp->GetPlatformFileSpec(); -void -ModuleList::ReplaceEquivalent (const ModuleSP &module_sp) -{ - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - - // First remove any equivalent modules. Equivalent modules are modules - // whose path, platform path and architecture match. - ModuleSpec equivalent_module_spec (module_sp->GetFileSpec(), module_sp->GetArchitecture()); - equivalent_module_spec.GetPlatformFileSpec() = module_sp->GetPlatformFileSpec(); - - size_t idx = 0; - while (idx < m_modules.size()) - { - ModuleSP module_sp (m_modules[idx]); - if (module_sp->MatchesModuleSpec (equivalent_module_spec)) - RemoveImpl(m_modules.begin() + idx); - else - ++idx; - } - // Now add the new module to the list - Append(module_sp); + size_t idx = 0; + while (idx < m_modules.size()) { + ModuleSP module_sp(m_modules[idx]); + if (module_sp->MatchesModuleSpec(equivalent_module_spec)) + RemoveImpl(m_modules.begin() + idx); + else + ++idx; } + // Now add the new module to the list + Append(module_sp); + } } -bool -ModuleList::AppendIfNeeded (const ModuleSP &module_sp) -{ - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - if (pos->get() == module_sp.get()) - return false; // Already in the list - } - // Only push module_sp on the list if it wasn't already in there. - Append(module_sp); - return true; +bool ModuleList::AppendIfNeeded(const ModuleSP &module_sp) { + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + collection::iterator pos, end = m_modules.end(); + for (pos = m_modules.begin(); pos != end; ++pos) { + if (pos->get() == module_sp.get()) + return false; // Already in the list } - return false; + // Only push module_sp on the list if it wasn't already in there. + Append(module_sp); + return true; + } + return false; } -void -ModuleList::Append (const ModuleList& module_list) -{ - for (auto pos : module_list.m_modules) - Append(pos); +void ModuleList::Append(const ModuleList &module_list) { + for (auto pos : module_list.m_modules) + Append(pos); } -bool -ModuleList::AppendIfNeeded (const ModuleList& module_list) -{ - bool any_in = false; - for (auto pos : module_list.m_modules) - { - if (AppendIfNeeded(pos)) - any_in = true; - } - return any_in; +bool ModuleList::AppendIfNeeded(const ModuleList &module_list) { + bool any_in = false; + for (auto pos : module_list.m_modules) { + if (AppendIfNeeded(pos)) + any_in = true; + } + return any_in; } -bool -ModuleList::RemoveImpl (const ModuleSP &module_sp, bool use_notifier) -{ - if (module_sp) - { - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - if (pos->get() == module_sp.get()) - { - m_modules.erase (pos); - if (use_notifier && m_notifier) - m_notifier->ModuleRemoved(*this, module_sp); - return true; - } - } +bool ModuleList::RemoveImpl(const ModuleSP &module_sp, bool use_notifier) { + if (module_sp) { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + collection::iterator pos, end = m_modules.end(); + for (pos = m_modules.begin(); pos != end; ++pos) { + if (pos->get() == module_sp.get()) { + m_modules.erase(pos); + if (use_notifier && m_notifier) + m_notifier->ModuleRemoved(*this, module_sp); + return true; + } } - return false; + } + return false; } ModuleList::collection::iterator -ModuleList::RemoveImpl (ModuleList::collection::iterator pos, bool use_notifier) -{ - ModuleSP module_sp(*pos); - collection::iterator retval = m_modules.erase(pos); - if (use_notifier && m_notifier) - m_notifier->ModuleRemoved(*this, module_sp); - return retval; +ModuleList::RemoveImpl(ModuleList::collection::iterator pos, + bool use_notifier) { + ModuleSP module_sp(*pos); + collection::iterator retval = m_modules.erase(pos); + if (use_notifier && m_notifier) + m_notifier->ModuleRemoved(*this, module_sp); + return retval; } -bool -ModuleList::Remove (const ModuleSP &module_sp) -{ - return RemoveImpl (module_sp); +bool ModuleList::Remove(const ModuleSP &module_sp) { + return RemoveImpl(module_sp); } -bool -ModuleList::ReplaceModule (const lldb::ModuleSP &old_module_sp, const lldb::ModuleSP &new_module_sp) -{ - if (!RemoveImpl(old_module_sp, false)) - return false; - AppendImpl (new_module_sp, false); - if (m_notifier) - m_notifier->ModuleUpdated(*this, old_module_sp,new_module_sp); - return true; -} - -bool -ModuleList::RemoveIfOrphaned (const Module *module_ptr) -{ - if (module_ptr) - { - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - if (pos->get() == module_ptr) - { - if (pos->unique()) - { - pos = RemoveImpl(pos); - return true; - } - else - return false; - } - } - } +bool ModuleList::ReplaceModule(const lldb::ModuleSP &old_module_sp, + const lldb::ModuleSP &new_module_sp) { + if (!RemoveImpl(old_module_sp, false)) return false; + AppendImpl(new_module_sp, false); + if (m_notifier) + m_notifier->ModuleUpdated(*this, old_module_sp, new_module_sp); + return true; } -size_t -ModuleList::RemoveOrphans (bool mandatory) -{ - std::unique_lock<std::recursive_mutex> lock(m_modules_mutex, std::defer_lock); - - if (mandatory) - { - lock.lock(); - } - else - { - // Not mandatory, remove orphans if we can get the mutex - if (!lock.try_lock()) - return 0; - } - collection::iterator pos = m_modules.begin(); - size_t remove_count = 0; - while (pos != m_modules.end()) - { - if (pos->unique()) - { - pos = RemoveImpl(pos); - ++remove_count; - } - else - { - ++pos; - } - } - return remove_count; -} - -size_t -ModuleList::Remove (ModuleList &module_list) -{ +bool ModuleList::RemoveIfOrphaned(const Module *module_ptr) { + if (module_ptr) { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - size_t num_removed = 0; - collection::iterator pos, end = module_list.m_modules.end(); - for (pos = module_list.m_modules.begin(); pos != end; ++pos) - { - if (Remove (*pos)) - ++num_removed; + collection::iterator pos, end = m_modules.end(); + for (pos = m_modules.begin(); pos != end; ++pos) { + if (pos->get() == module_ptr) { + if (pos->unique()) { + pos = RemoveImpl(pos); + return true; + } else + return false; + } } - return num_removed; + } + return false; } +size_t ModuleList::RemoveOrphans(bool mandatory) { + std::unique_lock<std::recursive_mutex> lock(m_modules_mutex, std::defer_lock); -void -ModuleList::Clear() -{ - ClearImpl(); + if (mandatory) { + lock.lock(); + } else { + // Not mandatory, remove orphans if we can get the mutex + if (!lock.try_lock()) + return 0; + } + collection::iterator pos = m_modules.begin(); + size_t remove_count = 0; + while (pos != m_modules.end()) { + if (pos->unique()) { + pos = RemoveImpl(pos); + ++remove_count; + } else { + ++pos; + } + } + return remove_count; } -void -ModuleList::Destroy() -{ - ClearImpl(); +size_t ModuleList::Remove(ModuleList &module_list) { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + size_t num_removed = 0; + collection::iterator pos, end = module_list.m_modules.end(); + for (pos = module_list.m_modules.begin(); pos != end; ++pos) { + if (Remove(*pos)) + ++num_removed; + } + return num_removed; } -void -ModuleList::ClearImpl (bool use_notifier) -{ - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - if (use_notifier && m_notifier) - m_notifier->WillClearList(*this); - m_modules.clear(); -} +void ModuleList::Clear() { ClearImpl(); } -Module* -ModuleList::GetModulePointerAtIndex (size_t idx) const -{ - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - return GetModulePointerAtIndexUnlocked(idx); -} +void ModuleList::Destroy() { ClearImpl(); } -Module* -ModuleList::GetModulePointerAtIndexUnlocked (size_t idx) const -{ - if (idx < m_modules.size()) - return m_modules[idx].get(); - return nullptr; +void ModuleList::ClearImpl(bool use_notifier) { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + if (use_notifier && m_notifier) + m_notifier->WillClearList(*this); + m_modules.clear(); } -ModuleSP -ModuleList::GetModuleAtIndex(size_t idx) const -{ - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - return GetModuleAtIndexUnlocked(idx); +Module *ModuleList::GetModulePointerAtIndex(size_t idx) const { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + return GetModulePointerAtIndexUnlocked(idx); } -ModuleSP -ModuleList::GetModuleAtIndexUnlocked(size_t idx) const -{ - ModuleSP module_sp; - if (idx < m_modules.size()) - module_sp = m_modules[idx]; - return module_sp; +Module *ModuleList::GetModulePointerAtIndexUnlocked(size_t idx) const { + if (idx < m_modules.size()) + return m_modules[idx].get(); + return nullptr; } -size_t -ModuleList::FindFunctions (const ConstString &name, - uint32_t name_type_mask, - bool include_symbols, - bool include_inlines, - bool append, - SymbolContextList &sc_list) const -{ - if (!append) - sc_list.Clear(); - - const size_t old_size = sc_list.GetSize(); - - if (name_type_mask & eFunctionNameTypeAuto) - { - Module::LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown); - - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - (*pos)->FindFunctions(lookup_info.GetLookupName(), - nullptr, - lookup_info.GetNameTypeMask(), - include_symbols, - include_inlines, - true, - sc_list); - } - - const size_t new_size = sc_list.GetSize(); - - if (old_size < new_size) - lookup_info.Prune (sc_list, old_size); - } - else - { - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - (*pos)->FindFunctions(name, nullptr, name_type_mask, include_symbols, include_inlines, true, sc_list); - } - } - return sc_list.GetSize() - old_size; +ModuleSP ModuleList::GetModuleAtIndex(size_t idx) const { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + return GetModuleAtIndexUnlocked(idx); } -size_t -ModuleList::FindFunctionSymbols (const ConstString &name, - uint32_t name_type_mask, - SymbolContextList& sc_list) -{ - const size_t old_size = sc_list.GetSize(); - - if (name_type_mask & eFunctionNameTypeAuto) - { - Module::LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown); - - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - (*pos)->FindFunctionSymbols (lookup_info.GetLookupName(), - lookup_info.GetNameTypeMask(), - sc_list); - } +ModuleSP ModuleList::GetModuleAtIndexUnlocked(size_t idx) const { + ModuleSP module_sp; + if (idx < m_modules.size()) + module_sp = m_modules[idx]; + return module_sp; +} +size_t ModuleList::FindFunctions(const ConstString &name, + uint32_t name_type_mask, bool include_symbols, + bool include_inlines, bool append, + SymbolContextList &sc_list) const { + if (!append) + sc_list.Clear(); - const size_t new_size = sc_list.GetSize(); + const size_t old_size = sc_list.GetSize(); - if (old_size < new_size) - lookup_info.Prune (sc_list, old_size); - } - else - { - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - (*pos)->FindFunctionSymbols (name, name_type_mask, sc_list); - } - } - - return sc_list.GetSize() - old_size; -} - -size_t -ModuleList::FindFunctions(const RegularExpression &name, - bool include_symbols, - bool include_inlines, - bool append, - SymbolContextList& sc_list) -{ - const size_t old_size = sc_list.GetSize(); + if (name_type_mask & eFunctionNameTypeAuto) { + Module::LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown); std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - (*pos)->FindFunctions (name, include_symbols, include_inlines, append, sc_list); + for (pos = m_modules.begin(); pos != end; ++pos) { + (*pos)->FindFunctions(lookup_info.GetLookupName(), nullptr, + lookup_info.GetNameTypeMask(), include_symbols, + include_inlines, true, sc_list); } - return sc_list.GetSize() - old_size; -} - -size_t -ModuleList::FindCompileUnits (const FileSpec &path, - bool append, - SymbolContextList &sc_list) const -{ - if (!append) - sc_list.Clear(); + const size_t new_size = sc_list.GetSize(); + if (old_size < new_size) + lookup_info.Prune(sc_list, old_size); + } else { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - (*pos)->FindCompileUnits (path, true, sc_list); + for (pos = m_modules.begin(); pos != end; ++pos) { + (*pos)->FindFunctions(name, nullptr, name_type_mask, include_symbols, + include_inlines, true, sc_list); } - - return sc_list.GetSize(); + } + return sc_list.GetSize() - old_size; } -size_t -ModuleList::FindGlobalVariables (const ConstString &name, - bool append, - size_t max_matches, - VariableList& variable_list) const -{ - size_t initial_size = variable_list.GetSize(); - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - (*pos)->FindGlobalVariables(name, nullptr, append, max_matches, variable_list); - } - return variable_list.GetSize() - initial_size; -} +size_t ModuleList::FindFunctionSymbols(const ConstString &name, + uint32_t name_type_mask, + SymbolContextList &sc_list) { + const size_t old_size = sc_list.GetSize(); + + if (name_type_mask & eFunctionNameTypeAuto) { + Module::LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown); -size_t -ModuleList::FindGlobalVariables (const RegularExpression& regex, - bool append, - size_t max_matches, - VariableList& variable_list) const -{ - size_t initial_size = variable_list.GetSize(); std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - (*pos)->FindGlobalVariables (regex, append, max_matches, variable_list); + for (pos = m_modules.begin(); pos != end; ++pos) { + (*pos)->FindFunctionSymbols(lookup_info.GetLookupName(), + lookup_info.GetNameTypeMask(), sc_list); } - return variable_list.GetSize() - initial_size; -} -size_t -ModuleList::FindSymbolsWithNameAndType (const ConstString &name, - SymbolType symbol_type, - SymbolContextList &sc_list, - bool append) const -{ - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - if (!append) - sc_list.Clear(); - size_t initial_size = sc_list.GetSize(); - - collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - (*pos)->FindSymbolsWithNameAndType (name, symbol_type, sc_list); - return sc_list.GetSize() - initial_size; -} + const size_t new_size = sc_list.GetSize(); -size_t -ModuleList::FindSymbolsMatchingRegExAndType (const RegularExpression ®ex, - lldb::SymbolType symbol_type, - SymbolContextList &sc_list, - bool append) const -{ + if (old_size < new_size) + lookup_info.Prune(sc_list, old_size); + } else { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - if (!append) - sc_list.Clear(); - size_t initial_size = sc_list.GetSize(); - collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - (*pos)->FindSymbolsMatchingRegExAndType (regex, symbol_type, sc_list); - return sc_list.GetSize() - initial_size; + for (pos = m_modules.begin(); pos != end; ++pos) { + (*pos)->FindFunctionSymbols(name, name_type_mask, sc_list); + } + } + + return sc_list.GetSize() - old_size; +} + +size_t ModuleList::FindFunctions(const RegularExpression &name, + bool include_symbols, bool include_inlines, + bool append, SymbolContextList &sc_list) { + const size_t old_size = sc_list.GetSize(); + + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + collection::const_iterator pos, end = m_modules.end(); + for (pos = m_modules.begin(); pos != end; ++pos) { + (*pos)->FindFunctions(name, include_symbols, include_inlines, append, + sc_list); + } + + return sc_list.GetSize() - old_size; +} + +size_t ModuleList::FindCompileUnits(const FileSpec &path, bool append, + SymbolContextList &sc_list) const { + if (!append) + sc_list.Clear(); + + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + collection::const_iterator pos, end = m_modules.end(); + for (pos = m_modules.begin(); pos != end; ++pos) { + (*pos)->FindCompileUnits(path, true, sc_list); + } + + return sc_list.GetSize(); +} + +size_t ModuleList::FindGlobalVariables(const ConstString &name, bool append, + size_t max_matches, + VariableList &variable_list) const { + size_t initial_size = variable_list.GetSize(); + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + collection::const_iterator pos, end = m_modules.end(); + for (pos = m_modules.begin(); pos != end; ++pos) { + (*pos)->FindGlobalVariables(name, nullptr, append, max_matches, + variable_list); + } + return variable_list.GetSize() - initial_size; +} + +size_t ModuleList::FindGlobalVariables(const RegularExpression ®ex, + bool append, size_t max_matches, + VariableList &variable_list) const { + size_t initial_size = variable_list.GetSize(); + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + collection::const_iterator pos, end = m_modules.end(); + for (pos = m_modules.begin(); pos != end; ++pos) { + (*pos)->FindGlobalVariables(regex, append, max_matches, variable_list); + } + return variable_list.GetSize() - initial_size; +} + +size_t ModuleList::FindSymbolsWithNameAndType(const ConstString &name, + SymbolType symbol_type, + SymbolContextList &sc_list, + bool append) const { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + if (!append) + sc_list.Clear(); + size_t initial_size = sc_list.GetSize(); + + collection::const_iterator pos, end = m_modules.end(); + for (pos = m_modules.begin(); pos != end; ++pos) + (*pos)->FindSymbolsWithNameAndType(name, symbol_type, sc_list); + return sc_list.GetSize() - initial_size; +} + +size_t ModuleList::FindSymbolsMatchingRegExAndType( + const RegularExpression ®ex, lldb::SymbolType symbol_type, + SymbolContextList &sc_list, bool append) const { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + if (!append) + sc_list.Clear(); + size_t initial_size = sc_list.GetSize(); + + collection::const_iterator pos, end = m_modules.end(); + for (pos = m_modules.begin(); pos != end; ++pos) + (*pos)->FindSymbolsMatchingRegExAndType(regex, symbol_type, sc_list); + return sc_list.GetSize() - initial_size; +} + +size_t ModuleList::FindModules(const ModuleSpec &module_spec, + ModuleList &matching_module_list) const { + size_t existing_matches = matching_module_list.GetSize(); + + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + collection::const_iterator pos, end = m_modules.end(); + for (pos = m_modules.begin(); pos != end; ++pos) { + ModuleSP module_sp(*pos); + if (module_sp->MatchesModuleSpec(module_spec)) + matching_module_list.Append(module_sp); + } + return matching_module_list.GetSize() - existing_matches; } -size_t -ModuleList::FindModules (const ModuleSpec &module_spec, ModuleList& matching_module_list) const -{ - size_t existing_matches = matching_module_list.GetSize(); +ModuleSP ModuleList::FindModule(const Module *module_ptr) const { + ModuleSP module_sp; + // Scope for "locker" + { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - ModuleSP module_sp(*pos); - if (module_sp->MatchesModuleSpec (module_spec)) - matching_module_list.Append(module_sp); - } - return matching_module_list.GetSize() - existing_matches; -} -ModuleSP -ModuleList::FindModule (const Module *module_ptr) const -{ - ModuleSP module_sp; - - // Scope for "locker" - { - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::const_iterator pos, end = m_modules.end(); - - for (pos = m_modules.begin(); pos != end; ++pos) - { - if ((*pos).get() == module_ptr) - { - module_sp = (*pos); - break; - } - } + for (pos = m_modules.begin(); pos != end; ++pos) { + if ((*pos).get() == module_ptr) { + module_sp = (*pos); + break; + } } - return module_sp; + } + return module_sp; } -ModuleSP -ModuleList::FindModule (const UUID &uuid) const -{ - ModuleSP module_sp; - - if (uuid.IsValid()) - { - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::const_iterator pos, end = m_modules.end(); - - for (pos = m_modules.begin(); pos != end; ++pos) - { - if ((*pos)->GetUUID() == uuid) - { - module_sp = (*pos); - break; - } - } - } - return module_sp; -} +ModuleSP ModuleList::FindModule(const UUID &uuid) const { + ModuleSP module_sp; -size_t -ModuleList::FindTypes (const SymbolContext& sc, const ConstString &name, bool name_is_fully_qualified, size_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeList& types) const -{ + if (uuid.IsValid()) { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - - size_t total_matches = 0; collection::const_iterator pos, end = m_modules.end(); - if (sc.module_sp) - { - // The symbol context "sc" contains a module so we want to search that - // one first if it is in our list... - for (pos = m_modules.begin(); pos != end; ++pos) - { - if (sc.module_sp.get() == (*pos).get()) - { - total_matches += (*pos)->FindTypes (sc, name, name_is_fully_qualified, max_matches, searched_symbol_files, types); - - if (total_matches >= max_matches) - break; - } - } - } - - if (total_matches < max_matches) - { - SymbolContext world_sc; - for (pos = m_modules.begin(); pos != end; ++pos) - { - // Search the module if the module is not equal to the one in the symbol - // context "sc". If "sc" contains a empty module shared pointer, then - // the comparison will always be true (valid_module_ptr != nullptr). - if (sc.module_sp.get() != (*pos).get()) - total_matches += (*pos)->FindTypes (world_sc, name, name_is_fully_qualified, max_matches, searched_symbol_files, types); - - if (total_matches >= max_matches) - break; - } - } - - return total_matches; -} -bool -ModuleList::FindSourceFile (const FileSpec &orig_spec, FileSpec &new_spec) const -{ - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - if ((*pos)->FindSourceFile (orig_spec, new_spec)) - return true; + for (pos = m_modules.begin(); pos != end; ++pos) { + if ((*pos)->GetUUID() == uuid) { + module_sp = (*pos); + break; + } } - return false; -} - -void -ModuleList::FindAddressesForLine (const lldb::TargetSP target_sp, - const FileSpec &file, uint32_t line, - Function *function, - std::vector<Address> &output_local, std::vector<Address> &output_extern) -{ - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - (*pos)->FindAddressesForLine(target_sp, file, line, function, output_local, output_extern); - } -} - -ModuleSP -ModuleList::FindFirstModule (const ModuleSpec &module_spec) const -{ - ModuleSP module_sp; - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - ModuleSP module_sp(*pos); - if (module_sp->MatchesModuleSpec (module_spec)) - return module_sp; - } - return module_sp; - + } + return module_sp; } size_t -ModuleList::GetSize() const -{ - size_t size = 0; - { - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - size = m_modules.size(); - } - return size; +ModuleList::FindTypes(const SymbolContext &sc, const ConstString &name, + bool name_is_fully_qualified, size_t max_matches, + llvm::DenseSet<SymbolFile *> &searched_symbol_files, + TypeList &types) const { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + + size_t total_matches = 0; + collection::const_iterator pos, end = m_modules.end(); + if (sc.module_sp) { + // The symbol context "sc" contains a module so we want to search that + // one first if it is in our list... + for (pos = m_modules.begin(); pos != end; ++pos) { + if (sc.module_sp.get() == (*pos).get()) { + total_matches += + (*pos)->FindTypes(sc, name, name_is_fully_qualified, max_matches, + searched_symbol_files, types); + + if (total_matches >= max_matches) + break; + } + } + } + + if (total_matches < max_matches) { + SymbolContext world_sc; + for (pos = m_modules.begin(); pos != end; ++pos) { + // Search the module if the module is not equal to the one in the symbol + // context "sc". If "sc" contains a empty module shared pointer, then + // the comparison will always be true (valid_module_ptr != nullptr). + if (sc.module_sp.get() != (*pos).get()) + total_matches += + (*pos)->FindTypes(world_sc, name, name_is_fully_qualified, + max_matches, searched_symbol_files, types); + + if (total_matches >= max_matches) + break; + } + } + + return total_matches; +} + +bool ModuleList::FindSourceFile(const FileSpec &orig_spec, + FileSpec &new_spec) const { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + collection::const_iterator pos, end = m_modules.end(); + for (pos = m_modules.begin(); pos != end; ++pos) { + if ((*pos)->FindSourceFile(orig_spec, new_spec)) + return true; + } + return false; +} + +void ModuleList::FindAddressesForLine(const lldb::TargetSP target_sp, + const FileSpec &file, uint32_t line, + Function *function, + std::vector<Address> &output_local, + std::vector<Address> &output_extern) { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + collection::const_iterator pos, end = m_modules.end(); + for (pos = m_modules.begin(); pos != end; ++pos) { + (*pos)->FindAddressesForLine(target_sp, file, line, function, output_local, + output_extern); + } +} + +ModuleSP ModuleList::FindFirstModule(const ModuleSpec &module_spec) const { + ModuleSP module_sp; + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + collection::const_iterator pos, end = m_modules.end(); + for (pos = m_modules.begin(); pos != end; ++pos) { + ModuleSP module_sp(*pos); + if (module_sp->MatchesModuleSpec(module_spec)) + return module_sp; + } + return module_sp; } -void -ModuleList::Dump(Stream *s) const -{ - // s.Printf("%.*p: ", (int)sizeof(void*) * 2, this); - // s.Indent(); - // s << "ModuleList\n"; - +size_t ModuleList::GetSize() const { + size_t size = 0; + { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - (*pos)->Dump(s); - } + size = m_modules.size(); + } + return size; } -void -ModuleList::LogUUIDAndPaths (Log *log, const char *prefix_cstr) -{ - if (log != nullptr) - { - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::const_iterator pos, begin = m_modules.begin(), end = m_modules.end(); - for (pos = begin; pos != end; ++pos) - { - Module *module = pos->get(); - const FileSpec &module_file_spec = module->GetFileSpec(); - log->Printf ("%s[%u] %s (%s) \"%s\"", - prefix_cstr ? prefix_cstr : "", - (uint32_t)std::distance (begin, pos), - module->GetUUID().GetAsString().c_str(), - module->GetArchitecture().GetArchitectureName(), - module_file_spec.GetPath().c_str()); - } - } +void ModuleList::Dump(Stream *s) const { + // s.Printf("%.*p: ", (int)sizeof(void*) * 2, this); + // s.Indent(); + // s << "ModuleList\n"; + + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + collection::const_iterator pos, end = m_modules.end(); + for (pos = m_modules.begin(); pos != end; ++pos) { + (*pos)->Dump(s); + } } -bool -ModuleList::ResolveFileAddress (lldb::addr_t vm_addr, Address& so_addr) const -{ +void ModuleList::LogUUIDAndPaths(Log *log, const char *prefix_cstr) { + if (log != nullptr) { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + collection::const_iterator pos, begin = m_modules.begin(), + end = m_modules.end(); + for (pos = begin; pos != end; ++pos) { + Module *module = pos->get(); + const FileSpec &module_file_spec = module->GetFileSpec(); + log->Printf("%s[%u] %s (%s) \"%s\"", prefix_cstr ? prefix_cstr : "", + (uint32_t)std::distance(begin, pos), + module->GetUUID().GetAsString().c_str(), + module->GetArchitecture().GetArchitectureName(), + module_file_spec.GetPath().c_str()); + } + } +} + +bool ModuleList::ResolveFileAddress(lldb::addr_t vm_addr, + Address &so_addr) const { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + collection::const_iterator pos, end = m_modules.end(); + for (pos = m_modules.begin(); pos != end; ++pos) { + if ((*pos)->ResolveFileAddress(vm_addr, so_addr)) + return true; + } + + return false; +} + +uint32_t ModuleList::ResolveSymbolContextForAddress(const Address &so_addr, + uint32_t resolve_scope, + SymbolContext &sc) const { + // The address is already section offset so it has a module + uint32_t resolved_flags = 0; + ModuleSP module_sp(so_addr.GetModule()); + if (module_sp) { + resolved_flags = + module_sp->ResolveSymbolContextForAddress(so_addr, resolve_scope, sc); + } else { std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - if ((*pos)->ResolveFileAddress (vm_addr, so_addr)) - return true; - } - - return false; -} - -uint32_t -ModuleList::ResolveSymbolContextForAddress (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) const -{ - // The address is already section offset so it has a module - uint32_t resolved_flags = 0; - ModuleSP module_sp (so_addr.GetModule()); - if (module_sp) - { - resolved_flags = module_sp->ResolveSymbolContextForAddress (so_addr, - resolve_scope, - sc); - } - else - { - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - resolved_flags = (*pos)->ResolveSymbolContextForAddress (so_addr, - resolve_scope, - sc); - if (resolved_flags != 0) - break; - } + for (pos = m_modules.begin(); pos != end; ++pos) { + resolved_flags = + (*pos)->ResolveSymbolContextForAddress(so_addr, resolve_scope, sc); + if (resolved_flags != 0) + break; } + } - return resolved_flags; + return resolved_flags; } -uint32_t -ModuleList::ResolveSymbolContextForFilePath(const char *file_path, - uint32_t line, - bool check_inlines, - uint32_t resolve_scope, - SymbolContextList& sc_list) const -{ - FileSpec file_spec(file_path, false); - return ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list); +uint32_t ModuleList::ResolveSymbolContextForFilePath( + const char *file_path, uint32_t line, bool check_inlines, + uint32_t resolve_scope, SymbolContextList &sc_list) const { + FileSpec file_spec(file_path, false); + return ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines, + resolve_scope, sc_list); } -uint32_t -ModuleList::ResolveSymbolContextsForFileSpec (const FileSpec &file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) const -{ - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::const_iterator pos, end = m_modules.end(); - for (pos = m_modules.begin(); pos != end; ++pos) - { - (*pos)->ResolveSymbolContextsForFileSpec (file_spec, line, check_inlines, resolve_scope, sc_list); - } +uint32_t ModuleList::ResolveSymbolContextsForFileSpec( + const FileSpec &file_spec, uint32_t line, bool check_inlines, + uint32_t resolve_scope, SymbolContextList &sc_list) const { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + collection::const_iterator pos, end = m_modules.end(); + for (pos = m_modules.begin(); pos != end; ++pos) { + (*pos)->ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines, + resolve_scope, sc_list); + } - return sc_list.GetSize(); + return sc_list.GetSize(); } -size_t -ModuleList::GetIndexForModule (const Module *module) const -{ - if (module) - { - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - collection::const_iterator pos; - collection::const_iterator begin = m_modules.begin(); - collection::const_iterator end = m_modules.end(); - for (pos = begin; pos != end; ++pos) - { - if ((*pos).get() == module) - return std::distance (begin, pos); +size_t ModuleList::GetIndexForModule(const Module *module) const { + if (module) { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + collection::const_iterator pos; + collection::const_iterator begin = m_modules.begin(); + collection::const_iterator end = m_modules.end(); + for (pos = begin; pos != end; ++pos) { + if ((*pos).get() == module) + return std::distance(begin, pos); + } + } + return LLDB_INVALID_INDEX32; +} + +static ModuleList &GetSharedModuleList() { + static ModuleList *g_shared_module_list = nullptr; + static std::once_flag g_once_flag; + std::call_once(g_once_flag, []() { + // NOTE: Intentionally leak the module list so a program doesn't have to + // cleanup all modules and object files as it exits. This just wastes time + // doing a bunch of cleanup that isn't required. + if (g_shared_module_list == nullptr) + g_shared_module_list = new ModuleList(); // <--- Intentional leak!!! + }); + return *g_shared_module_list; +} + +bool ModuleList::ModuleIsInCache(const Module *module_ptr) { + if (module_ptr) { + ModuleList &shared_module_list = GetSharedModuleList(); + return shared_module_list.FindModule(module_ptr).get() != nullptr; + } + return false; +} + +size_t ModuleList::FindSharedModules(const ModuleSpec &module_spec, + ModuleList &matching_module_list) { + return GetSharedModuleList().FindModules(module_spec, matching_module_list); +} + +size_t ModuleList::RemoveOrphanSharedModules(bool mandatory) { + return GetSharedModuleList().RemoveOrphans(mandatory); +} + +Error ModuleList::GetSharedModule(const ModuleSpec &module_spec, + ModuleSP &module_sp, + const FileSpecList *module_search_paths_ptr, + ModuleSP *old_module_sp_ptr, + bool *did_create_ptr, bool always_create) { + ModuleList &shared_module_list = GetSharedModuleList(); + std::lock_guard<std::recursive_mutex> guard( + shared_module_list.m_modules_mutex); + char path[PATH_MAX]; + + Error error; + + module_sp.reset(); + + if (did_create_ptr) + *did_create_ptr = false; + if (old_module_sp_ptr) + old_module_sp_ptr->reset(); + + const UUID *uuid_ptr = module_spec.GetUUIDPtr(); + const FileSpec &module_file_spec = module_spec.GetFileSpec(); + const ArchSpec &arch = module_spec.GetArchitecture(); + + // Make sure no one else can try and get or create a module while this + // function is actively working on it by doing an extra lock on the + // global mutex list. + if (!always_create) { + ModuleList matching_module_list; + const size_t num_matching_modules = + shared_module_list.FindModules(module_spec, matching_module_list); + if (num_matching_modules > 0) { + for (size_t module_idx = 0; module_idx < num_matching_modules; + ++module_idx) { + module_sp = matching_module_list.GetModuleAtIndex(module_idx); + + // Make sure the file for the module hasn't been modified + if (module_sp->FileHasChanged()) { + if (old_module_sp_ptr && !*old_module_sp_ptr) + *old_module_sp_ptr = module_sp; + + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_MODULES)); + if (log != nullptr) + log->Printf("module changed: %p, removing from global module list", + static_cast<void *>(module_sp.get())); + + shared_module_list.Remove(module_sp); + module_sp.reset(); + } else { + // The module matches and the module was not modified from + // when it was last loaded. + return error; } + } } - return LLDB_INVALID_INDEX32; -} + } -static ModuleList & -GetSharedModuleList () -{ - static ModuleList *g_shared_module_list = nullptr; - static std::once_flag g_once_flag; - std::call_once(g_once_flag, [](){ - // NOTE: Intentionally leak the module list so a program doesn't have to - // cleanup all modules and object files as it exits. This just wastes time - // doing a bunch of cleanup that isn't required. - if (g_shared_module_list == nullptr) - g_shared_module_list = new ModuleList(); // <--- Intentional leak!!! - }); - return *g_shared_module_list; -} - -bool -ModuleList::ModuleIsInCache (const Module *module_ptr) -{ - if (module_ptr) - { - ModuleList &shared_module_list = GetSharedModuleList (); - return shared_module_list.FindModule(module_ptr).get() != nullptr; - } - return false; -} - -size_t -ModuleList::FindSharedModules (const ModuleSpec &module_spec, ModuleList &matching_module_list) -{ - return GetSharedModuleList ().FindModules (module_spec, matching_module_list); -} - -size_t -ModuleList::RemoveOrphanSharedModules (bool mandatory) -{ - return GetSharedModuleList ().RemoveOrphans(mandatory); -} - -Error -ModuleList::GetSharedModule(const ModuleSpec &module_spec, - ModuleSP &module_sp, - const FileSpecList *module_search_paths_ptr, - ModuleSP *old_module_sp_ptr, - bool *did_create_ptr, - bool always_create) -{ - ModuleList &shared_module_list = GetSharedModuleList (); - std::lock_guard<std::recursive_mutex> guard(shared_module_list.m_modules_mutex); - char path[PATH_MAX]; - - Error error; - - module_sp.reset(); - - if (did_create_ptr) - *did_create_ptr = false; - if (old_module_sp_ptr) - old_module_sp_ptr->reset(); - - const UUID *uuid_ptr = module_spec.GetUUIDPtr(); - const FileSpec &module_file_spec = module_spec.GetFileSpec(); - const ArchSpec &arch = module_spec.GetArchitecture(); + if (module_sp) + return error; - // Make sure no one else can try and get or create a module while this - // function is actively working on it by doing an extra lock on the - // global mutex list. - if (!always_create) - { - ModuleList matching_module_list; - const size_t num_matching_modules = shared_module_list.FindModules (module_spec, matching_module_list); - if (num_matching_modules > 0) - { - for (size_t module_idx = 0; module_idx < num_matching_modules; ++module_idx) - { - module_sp = matching_module_list.GetModuleAtIndex(module_idx); - - // Make sure the file for the module hasn't been modified - if (module_sp->FileHasChanged()) - { - if (old_module_sp_ptr && !*old_module_sp_ptr) - *old_module_sp_ptr = module_sp; - - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_MODULES)); - if (log != nullptr) - log->Printf("module changed: %p, removing from global module list", - static_cast<void*>(module_sp.get())); - - shared_module_list.Remove (module_sp); - module_sp.reset(); - } - else - { - // The module matches and the module was not modified from - // when it was last loaded. - return error; - } - } + module_sp.reset(new Module(module_spec)); + // Make sure there are a module and an object file since we can specify + // a valid file path with an architecture that might not be in that file. + // By getting the object file we can guarantee that the architecture matches + if (module_sp->GetObjectFile()) { + // If we get in here we got the correct arch, now we just need + // to verify the UUID if one was given + if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) { + module_sp.reset(); + } else { + if (module_sp->GetObjectFile() && + module_sp->GetObjectFile()->GetType() == + ObjectFile::eTypeStubLibrary) { + module_sp.reset(); + } else { + if (did_create_ptr) { + *did_create_ptr = true; } - } - if (module_sp) + shared_module_list.ReplaceEquivalent(module_sp); return error; - - module_sp.reset (new Module (module_spec)); - // Make sure there are a module and an object file since we can specify - // a valid file path with an architecture that might not be in that file. - // By getting the object file we can guarantee that the architecture matches - if (module_sp->GetObjectFile()) - { + } + } + } else { + module_sp.reset(); + } + + if (module_search_paths_ptr) { + const auto num_directories = module_search_paths_ptr->GetSize(); + for (size_t idx = 0; idx < num_directories; ++idx) { + auto search_path_spec = module_search_paths_ptr->GetFileSpecAtIndex(idx); + if (!search_path_spec.ResolvePath()) + continue; + if (!search_path_spec.Exists() || !search_path_spec.IsDirectory()) + continue; + search_path_spec.AppendPathComponent( + module_spec.GetFileSpec().GetFilename().AsCString()); + if (!search_path_spec.Exists()) + continue; + + auto resolved_module_spec(module_spec); + resolved_module_spec.GetFileSpec() = search_path_spec; + module_sp.reset(new Module(resolved_module_spec)); + if (module_sp->GetObjectFile()) { // If we get in here we got the correct arch, now we just need // to verify the UUID if one was given - if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) - { + if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) { + module_sp.reset(); + } else { + if (module_sp->GetObjectFile()->GetType() == + ObjectFile::eTypeStubLibrary) { module_sp.reset(); + } else { + if (did_create_ptr) + *did_create_ptr = true; + + shared_module_list.ReplaceEquivalent(module_sp); + return Error(); + } } - else - { - if (module_sp->GetObjectFile() && module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary) - { - module_sp.reset(); - } - else - { - if (did_create_ptr) - { - *did_create_ptr = true; - } - - shared_module_list.ReplaceEquivalent(module_sp); - return error; - } - } - } - else - { + } else { module_sp.reset(); - } - - if (module_search_paths_ptr) - { - const auto num_directories = module_search_paths_ptr->GetSize(); - for (size_t idx = 0; idx < num_directories; ++idx) - { - auto search_path_spec = module_search_paths_ptr->GetFileSpecAtIndex(idx); - if (!search_path_spec.ResolvePath()) - continue; - if (!search_path_spec.Exists() || !search_path_spec.IsDirectory()) - continue; - search_path_spec.AppendPathComponent(module_spec.GetFileSpec().GetFilename().AsCString()); - if (!search_path_spec.Exists()) - continue; - - auto resolved_module_spec(module_spec); - resolved_module_spec.GetFileSpec() = search_path_spec; - module_sp.reset (new Module (resolved_module_spec)); - if (module_sp->GetObjectFile()) - { - // If we get in here we got the correct arch, now we just need - // to verify the UUID if one was given - if (uuid_ptr && *uuid_ptr != module_sp->GetUUID()) - { - module_sp.reset(); - } - else - { - if (module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary) - { - module_sp.reset(); - } - else - { - if (did_create_ptr) - *did_create_ptr = true; - - shared_module_list.ReplaceEquivalent(module_sp); - return Error(); - } - } - } - else - { - module_sp.reset(); - } + } + } + } + + // Either the file didn't exist where at the path, or no path was given, so + // we now have to use more extreme measures to try and find the appropriate + // module. + + // Fixup the incoming path in case the path points to a valid file, yet + // the arch or UUID (if one was passed in) don't match. + ModuleSpec located_binary_modulespec = + Symbols::LocateExecutableObjectFile(module_spec); + + // Don't look for the file if it appears to be the same one we already + // checked for above... + if (located_binary_modulespec.GetFileSpec() != module_file_spec) { + if (!located_binary_modulespec.GetFileSpec().Exists()) { + located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path)); + if (path[0] == '\0') + module_file_spec.GetPath(path, sizeof(path)); + // How can this check ever be true? This branch it is false, and we + // haven't modified file_spec. + if (located_binary_modulespec.GetFileSpec().Exists()) { + std::string uuid_str; + if (uuid_ptr && uuid_ptr->IsValid()) + uuid_str = uuid_ptr->GetAsString(); + + if (arch.IsValid()) { + if (!uuid_str.empty()) + error.SetErrorStringWithFormat( + "'%s' does not contain the %s architecture and UUID %s", path, + arch.GetArchitectureName(), uuid_str.c_str()); + else + error.SetErrorStringWithFormat( + "'%s' does not contain the %s architecture.", path, + arch.GetArchitectureName()); } + } else { + error.SetErrorStringWithFormat("'%s' does not exist", path); + } + if (error.Fail()) + module_sp.reset(); + return error; } - // Either the file didn't exist where at the path, or no path was given, so - // we now have to use more extreme measures to try and find the appropriate - // module. - - // Fixup the incoming path in case the path points to a valid file, yet - // the arch or UUID (if one was passed in) don't match. - ModuleSpec located_binary_modulespec = Symbols::LocateExecutableObjectFile (module_spec); - - // Don't look for the file if it appears to be the same one we already - // checked for above... - if (located_binary_modulespec.GetFileSpec() != module_file_spec) - { - if (!located_binary_modulespec.GetFileSpec().Exists()) - { - located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path)); - if (path[0] == '\0') - module_file_spec.GetPath(path, sizeof(path)); - // How can this check ever be true? This branch it is false, and we haven't modified file_spec. - if (located_binary_modulespec.GetFileSpec().Exists()) - { - std::string uuid_str; - if (uuid_ptr && uuid_ptr->IsValid()) - uuid_str = uuid_ptr->GetAsString(); - - if (arch.IsValid()) - { - if (!uuid_str.empty()) - error.SetErrorStringWithFormat("'%s' does not contain the %s architecture and UUID %s", path, arch.GetArchitectureName(), uuid_str.c_str()); - else - error.SetErrorStringWithFormat("'%s' does not contain the %s architecture.", path, arch.GetArchitectureName()); - } - } - else - { - error.SetErrorStringWithFormat("'%s' does not exist", path); - } - if (error.Fail()) - module_sp.reset(); - return error; + // Make sure no one else can try and get or create a module while this + // function is actively working on it by doing an extra lock on the + // global mutex list. + ModuleSpec platform_module_spec(module_spec); + platform_module_spec.GetFileSpec() = + located_binary_modulespec.GetFileSpec(); + platform_module_spec.GetPlatformFileSpec() = + located_binary_modulespec.GetFileSpec(); + platform_module_spec.GetSymbolFileSpec() = + located_binary_modulespec.GetSymbolFileSpec(); + ModuleList matching_module_list; + if (shared_module_list.FindModules(platform_module_spec, + matching_module_list) > 0) { + module_sp = matching_module_list.GetModuleAtIndex(0); + + // If we didn't have a UUID in mind when looking for the object file, + // then we should make sure the modification time hasn't changed! + if (platform_module_spec.GetUUIDPtr() == nullptr) { + auto file_spec_mod_time = FileSystem::GetModificationTime( + located_binary_modulespec.GetFileSpec()); + if (file_spec_mod_time != llvm::sys::TimePoint<>()) { + if (file_spec_mod_time != module_sp->GetModificationTime()) { + if (old_module_sp_ptr) + *old_module_sp_ptr = module_sp; + shared_module_list.Remove(module_sp); + module_sp.reset(); + } } - - // Make sure no one else can try and get or create a module while this - // function is actively working on it by doing an extra lock on the - // global mutex list. - ModuleSpec platform_module_spec(module_spec); - platform_module_spec.GetFileSpec() = located_binary_modulespec.GetFileSpec(); - platform_module_spec.GetPlatformFileSpec() = located_binary_modulespec.GetFileSpec(); - platform_module_spec.GetSymbolFileSpec() = located_binary_modulespec.GetSymbolFileSpec(); - ModuleList matching_module_list; - if (shared_module_list.FindModules (platform_module_spec, matching_module_list) > 0) - { - module_sp = matching_module_list.GetModuleAtIndex(0); - - // If we didn't have a UUID in mind when looking for the object file, - // then we should make sure the modification time hasn't changed! - if (platform_module_spec.GetUUIDPtr() == nullptr) - { - TimeValue file_spec_mod_time(located_binary_modulespec.GetFileSpec().GetModificationTime()); - if (file_spec_mod_time.IsValid()) - { - if (file_spec_mod_time != module_sp->GetModificationTime()) - { - if (old_module_sp_ptr) - *old_module_sp_ptr = module_sp; - shared_module_list.Remove (module_sp); - module_sp.reset(); - } - } - } + } + } + + if (!module_sp) { + module_sp.reset(new Module(platform_module_spec)); + // Make sure there are a module and an object file since we can specify + // a valid file path with an architecture that might not be in that file. + // By getting the object file we can guarantee that the architecture + // matches + if (module_sp && module_sp->GetObjectFile()) { + if (module_sp->GetObjectFile()->GetType() == + ObjectFile::eTypeStubLibrary) { + module_sp.reset(); + } else { + if (did_create_ptr) + *did_create_ptr = true; + + shared_module_list.ReplaceEquivalent(module_sp); } - - if (!module_sp) - { - module_sp.reset (new Module (platform_module_spec)); - // Make sure there are a module and an object file since we can specify - // a valid file path with an architecture that might not be in that file. - // By getting the object file we can guarantee that the architecture matches - if (module_sp && module_sp->GetObjectFile()) - { - if (module_sp->GetObjectFile()->GetType() == ObjectFile::eTypeStubLibrary) - { - module_sp.reset(); - } - else - { - if (did_create_ptr) - *did_create_ptr = true; - - shared_module_list.ReplaceEquivalent(module_sp); - } - } - else - { - located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path)); - - if (located_binary_modulespec.GetFileSpec()) - { - if (arch.IsValid()) - error.SetErrorStringWithFormat("unable to open %s architecture in '%s'", arch.GetArchitectureName(), path); - else - error.SetErrorStringWithFormat("unable to open '%s'", path); - } - else - { - std::string uuid_str; - if (uuid_ptr && uuid_ptr->IsValid()) - uuid_str = uuid_ptr->GetAsString(); - - if (!uuid_str.empty()) - error.SetErrorStringWithFormat("cannot locate a module for UUID '%s'", uuid_str.c_str()); - else - error.SetErrorStringWithFormat("cannot locate a module"); - } - } + } else { + located_binary_modulespec.GetFileSpec().GetPath(path, sizeof(path)); + + if (located_binary_modulespec.GetFileSpec()) { + if (arch.IsValid()) + error.SetErrorStringWithFormat( + "unable to open %s architecture in '%s'", + arch.GetArchitectureName(), path); + else + error.SetErrorStringWithFormat("unable to open '%s'", path); + } else { + std::string uuid_str; + if (uuid_ptr && uuid_ptr->IsValid()) + uuid_str = uuid_ptr->GetAsString(); + + if (!uuid_str.empty()) + error.SetErrorStringWithFormat( + "cannot locate a module for UUID '%s'", uuid_str.c_str()); + else + error.SetErrorStringWithFormat("cannot locate a module"); } + } } + } - return error; + return error; } -bool -ModuleList::RemoveSharedModule (lldb::ModuleSP &module_sp) -{ - return GetSharedModuleList ().Remove (module_sp); +bool ModuleList::RemoveSharedModule(lldb::ModuleSP &module_sp) { + return GetSharedModuleList().Remove(module_sp); } -bool -ModuleList::RemoveSharedModuleIfOrphaned (const Module *module_ptr) -{ - return GetSharedModuleList ().RemoveIfOrphaned (module_ptr); +bool ModuleList::RemoveSharedModuleIfOrphaned(const Module *module_ptr) { + return GetSharedModuleList().RemoveIfOrphaned(module_ptr); } -bool -ModuleList::LoadScriptingResourcesInTarget (Target *target, - std::list<Error>& errors, - Stream *feedback_stream, - bool continue_on_error) -{ - if (!target) - return false; - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - for (auto module : m_modules) - { - Error error; - if (module) - { - if (!module->LoadScriptingResourceInTarget(target, error, feedback_stream)) - { - if (error.Fail() && error.AsCString()) - { - error.SetErrorStringWithFormat("unable to load scripting data for module %s - error reported was %s", - module->GetFileSpec().GetFileNameStrippingExtension().GetCString(), - error.AsCString()); - errors.push_back(error); - - if (!continue_on_error) - return false; - } - } +bool ModuleList::LoadScriptingResourcesInTarget(Target *target, + std::list<Error> &errors, + Stream *feedback_stream, + bool continue_on_error) { + if (!target) + return false; + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + for (auto module : m_modules) { + Error error; + if (module) { + if (!module->LoadScriptingResourceInTarget(target, error, + feedback_stream)) { + if (error.Fail() && error.AsCString()) { + error.SetErrorStringWithFormat("unable to load scripting data for " + "module %s - error reported was %s", + module->GetFileSpec() + .GetFileNameStrippingExtension() + .GetCString(), + error.AsCString()); + errors.push_back(error); + + if (!continue_on_error) + return false; } + } } - return errors.empty(); + } + return errors.empty(); } -void -ModuleList::ForEach (std::function <bool (const ModuleSP &module_sp)> const &callback) const -{ - std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); - for (const auto &module : m_modules) - { - // If the callback returns false, then stop iterating and break out - if (!callback (module)) - break; - } +void ModuleList::ForEach( + std::function<bool(const ModuleSP &module_sp)> const &callback) const { + std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); + for (const auto &module : m_modules) { + // If the callback returns false, then stop iterating and break out + if (!callback(module)) + break; + } } diff --git a/source/Core/Opcode.cpp b/source/Core/Opcode.cpp index e36727eaa313..11b913841ecb 100644 --- a/source/Core/Opcode.cpp +++ b/source/Core/Opcode.cpp @@ -24,136 +24,119 @@ using namespace lldb; using namespace lldb_private; -int -Opcode::Dump (Stream *s, uint32_t min_byte_width) -{ - int bytes_written = 0; - switch (m_type) - { - case Opcode::eTypeInvalid: - bytes_written = s->PutCString ("<invalid>"); - break; - case Opcode::eType8: - bytes_written = s->Printf ("0x%2.2x", m_data.inst8); - break; - case Opcode::eType16: - bytes_written = s->Printf ("0x%4.4x", m_data.inst16); - break; - case Opcode::eType16_2: - case Opcode::eType32: - bytes_written = s->Printf ("0x%8.8x", m_data.inst32); - break; +int Opcode::Dump(Stream *s, uint32_t min_byte_width) { + int bytes_written = 0; + switch (m_type) { + case Opcode::eTypeInvalid: + bytes_written = s->PutCString("<invalid>"); + break; + case Opcode::eType8: + bytes_written = s->Printf("0x%2.2x", m_data.inst8); + break; + case Opcode::eType16: + bytes_written = s->Printf("0x%4.4x", m_data.inst16); + break; + case Opcode::eType16_2: + case Opcode::eType32: + bytes_written = s->Printf("0x%8.8x", m_data.inst32); + break; - case Opcode::eType64: - bytes_written = s->Printf ("0x%16.16" PRIx64, m_data.inst64); - break; + case Opcode::eType64: + bytes_written = s->Printf("0x%16.16" PRIx64, m_data.inst64); + break; - case Opcode::eTypeBytes: - for (uint32_t i = 0; i < m_data.inst.length; ++i) - { - if (i > 0) - bytes_written += s->PutChar (' '); - bytes_written += s->Printf ("%2.2x", m_data.inst.bytes[i]); - } - break; + case Opcode::eTypeBytes: + for (uint32_t i = 0; i < m_data.inst.length; ++i) { + if (i > 0) + bytes_written += s->PutChar(' '); + bytes_written += s->Printf("%2.2x", m_data.inst.bytes[i]); } + break; + } - // Add spaces to make sure bytes dispay comes out even in case opcodes - // aren't all the same size - if (static_cast<uint32_t>(bytes_written) < min_byte_width) - bytes_written = s->Printf ("%*s", min_byte_width - bytes_written, ""); - return bytes_written; + // Add spaces to make sure bytes dispay comes out even in case opcodes + // aren't all the same size + if (static_cast<uint32_t>(bytes_written) < min_byte_width) + bytes_written = s->Printf("%*s", min_byte_width - bytes_written, ""); + return bytes_written; } -lldb::ByteOrder -Opcode::GetDataByteOrder () const -{ - if (m_byte_order != eByteOrderInvalid) - { - return m_byte_order; - } - switch (m_type) - { - case Opcode::eTypeInvalid: break; - case Opcode::eType8: - case Opcode::eType16: - case Opcode::eType16_2: - case Opcode::eType32: - case Opcode::eType64: return endian::InlHostByteOrder(); - case Opcode::eTypeBytes: - break; - } - return eByteOrderInvalid; +lldb::ByteOrder Opcode::GetDataByteOrder() const { + if (m_byte_order != eByteOrderInvalid) { + return m_byte_order; + } + switch (m_type) { + case Opcode::eTypeInvalid: + break; + case Opcode::eType8: + case Opcode::eType16: + case Opcode::eType16_2: + case Opcode::eType32: + case Opcode::eType64: + return endian::InlHostByteOrder(); + case Opcode::eTypeBytes: + break; + } + return eByteOrderInvalid; } -uint32_t -Opcode::GetData (DataExtractor &data) const -{ - uint32_t byte_size = GetByteSize (); - uint8_t swap_buf[8]; - const void *buf = nullptr; +uint32_t Opcode::GetData(DataExtractor &data) const { + uint32_t byte_size = GetByteSize(); + uint8_t swap_buf[8]; + const void *buf = nullptr; - if (byte_size > 0) - { - if (!GetEndianSwap()) - { - if (m_type == Opcode::eType16_2) - { - // 32 bit thumb instruction, we need to sizzle this a bit - swap_buf[0] = m_data.inst.bytes[2]; - swap_buf[1] = m_data.inst.bytes[3]; - swap_buf[2] = m_data.inst.bytes[0]; - swap_buf[3] = m_data.inst.bytes[1]; - buf = swap_buf; - } - else - { - buf = GetOpcodeDataBytes(); - } - } - else - { - switch (m_type) - { - case Opcode::eTypeInvalid: - break; - case Opcode::eType8: - buf = GetOpcodeDataBytes(); - break; - case Opcode::eType16: - *(uint16_t *)swap_buf = llvm::ByteSwap_16(m_data.inst16); - buf = swap_buf; - break; - case Opcode::eType16_2: - swap_buf[0] = m_data.inst.bytes[1]; - swap_buf[1] = m_data.inst.bytes[0]; - swap_buf[2] = m_data.inst.bytes[3]; - swap_buf[3] = m_data.inst.bytes[2]; - buf = swap_buf; - break; - case Opcode::eType32: - *(uint32_t *)swap_buf = llvm::ByteSwap_32(m_data.inst32); - buf = swap_buf; - break; - case Opcode::eType64: - *(uint32_t *)swap_buf = llvm::ByteSwap_64(m_data.inst64); - buf = swap_buf; - break; - case Opcode::eTypeBytes: - buf = GetOpcodeDataBytes(); - break; - } - } + if (byte_size > 0) { + if (!GetEndianSwap()) { + if (m_type == Opcode::eType16_2) { + // 32 bit thumb instruction, we need to sizzle this a bit + swap_buf[0] = m_data.inst.bytes[2]; + swap_buf[1] = m_data.inst.bytes[3]; + swap_buf[2] = m_data.inst.bytes[0]; + swap_buf[3] = m_data.inst.bytes[1]; + buf = swap_buf; + } else { + buf = GetOpcodeDataBytes(); + } + } else { + switch (m_type) { + case Opcode::eTypeInvalid: + break; + case Opcode::eType8: + buf = GetOpcodeDataBytes(); + break; + case Opcode::eType16: + *(uint16_t *)swap_buf = llvm::ByteSwap_16(m_data.inst16); + buf = swap_buf; + break; + case Opcode::eType16_2: + swap_buf[0] = m_data.inst.bytes[1]; + swap_buf[1] = m_data.inst.bytes[0]; + swap_buf[2] = m_data.inst.bytes[3]; + swap_buf[3] = m_data.inst.bytes[2]; + buf = swap_buf; + break; + case Opcode::eType32: + *(uint32_t *)swap_buf = llvm::ByteSwap_32(m_data.inst32); + buf = swap_buf; + break; + case Opcode::eType64: + *(uint32_t *)swap_buf = llvm::ByteSwap_64(m_data.inst64); + buf = swap_buf; + break; + case Opcode::eTypeBytes: + buf = GetOpcodeDataBytes(); + break; + } } - if (buf != nullptr) - { - DataBufferSP buffer_sp; + } + if (buf != nullptr) { + DataBufferSP buffer_sp; - buffer_sp.reset (new DataBufferHeap (buf, byte_size)); - data.SetByteOrder(GetDataByteOrder()); - data.SetData (buffer_sp); - return byte_size; - } - data.Clear(); - return 0; + buffer_sp.reset(new DataBufferHeap(buf, byte_size)); + data.SetByteOrder(GetDataByteOrder()); + data.SetData(buffer_sp); + return byte_size; + } + data.Clear(); + return 0; } diff --git a/source/Core/PluginManager.cpp b/source/Core/PluginManager.cpp index 500b08b73e9e..b7b6b9a54efe 100644 --- a/source/Core/PluginManager.cpp +++ b/source/Core/PluginManager.cpp @@ -31,3021 +31,2608 @@ using namespace lldb; using namespace lldb_private; -enum PluginAction -{ - ePluginRegisterInstance, - ePluginUnregisterInstance, - ePluginGetInstanceAtIndex +enum PluginAction { + ePluginRegisterInstance, + ePluginUnregisterInstance, + ePluginGetInstanceAtIndex }; typedef bool (*PluginInitCallback)(); typedef void (*PluginTermCallback)(); -struct PluginInfo -{ - PluginInfo() - : plugin_init_callback(nullptr), plugin_term_callback(nullptr) - { - } +struct PluginInfo { + PluginInfo() : plugin_init_callback(nullptr), plugin_term_callback(nullptr) {} - llvm::sys::DynamicLibrary library; - PluginInitCallback plugin_init_callback; - PluginTermCallback plugin_term_callback; + llvm::sys::DynamicLibrary library; + PluginInitCallback plugin_init_callback; + PluginTermCallback plugin_term_callback; }; typedef std::map<FileSpec, PluginInfo> PluginTerminateMap; -static std::recursive_mutex & -GetPluginMapMutex() -{ - static std::recursive_mutex g_plugin_map_mutex; - return g_plugin_map_mutex; -} - -static PluginTerminateMap & -GetPluginMap () -{ - static PluginTerminateMap g_plugin_map; - return g_plugin_map; -} - -static bool -PluginIsLoaded (const FileSpec &plugin_file_spec) -{ - std::lock_guard<std::recursive_mutex> guard(GetPluginMapMutex()); - PluginTerminateMap &plugin_map = GetPluginMap (); - return plugin_map.find (plugin_file_spec) != plugin_map.end(); -} - -static void -SetPluginInfo (const FileSpec &plugin_file_spec, const PluginInfo &plugin_info) -{ - std::lock_guard<std::recursive_mutex> guard(GetPluginMapMutex()); - PluginTerminateMap &plugin_map = GetPluginMap (); - assert (plugin_map.find (plugin_file_spec) == plugin_map.end()); - plugin_map[plugin_file_spec] = plugin_info; -} - -template <typename FPtrTy> -static FPtrTy -CastToFPtr (void *VPtr) -{ - return reinterpret_cast<FPtrTy>(reinterpret_cast<intptr_t>(VPtr)); -} - -static FileSpec::EnumerateDirectoryResult -LoadPluginCallback(void *baton, - FileSpec::FileType file_type, - const FileSpec &file_spec) -{ -// PluginManager *plugin_manager = (PluginManager *)baton; - Error error; - - // If we have a regular file, a symbolic link or unknown file type, try - // and process the file. We must handle unknown as sometimes the directory - // enumeration might be enumerating a file system that doesn't have correct - // file type information. - if (file_type == FileSpec::eFileTypeRegular || - file_type == FileSpec::eFileTypeSymbolicLink || - file_type == FileSpec::eFileTypeUnknown ) - { - FileSpec plugin_file_spec (file_spec); - plugin_file_spec.ResolvePath(); - - if (PluginIsLoaded (plugin_file_spec)) - return FileSpec::eEnumerateDirectoryResultNext; - else - { - PluginInfo plugin_info; - - std::string pluginLoadError; - plugin_info.library = llvm::sys::DynamicLibrary::getPermanentLibrary (plugin_file_spec.GetPath().c_str(), &pluginLoadError); - if (plugin_info.library.isValid()) - { - bool success = false; - plugin_info.plugin_init_callback = - CastToFPtr<PluginInitCallback>(plugin_info.library.getAddressOfSymbol("LLDBPluginInitialize")); - if (plugin_info.plugin_init_callback) - { - // Call the plug-in "bool LLDBPluginInitialize(void)" function - success = plugin_info.plugin_init_callback(); - } - - if (success) - { - // It is ok for the "LLDBPluginTerminate" symbol to be nullptr - plugin_info.plugin_term_callback = - CastToFPtr<PluginTermCallback>(plugin_info.library.getAddressOfSymbol("LLDBPluginTerminate")); - } - else - { - // The initialize function returned FALSE which means the plug-in might not be - // compatible, or might be too new or too old, or might not want to run on this - // machine. Set it to a default-constructed instance to invalidate it. - plugin_info = PluginInfo(); - } - - // Regardless of success or failure, cache the plug-in load - // in our plug-in info so we don't try to load it again and - // again. - SetPluginInfo (plugin_file_spec, plugin_info); - - return FileSpec::eEnumerateDirectoryResultNext; - } +static std::recursive_mutex &GetPluginMapMutex() { + static std::recursive_mutex g_plugin_map_mutex; + return g_plugin_map_mutex; +} + +static PluginTerminateMap &GetPluginMap() { + static PluginTerminateMap g_plugin_map; + return g_plugin_map; +} + +static bool PluginIsLoaded(const FileSpec &plugin_file_spec) { + std::lock_guard<std::recursive_mutex> guard(GetPluginMapMutex()); + PluginTerminateMap &plugin_map = GetPluginMap(); + return plugin_map.find(plugin_file_spec) != plugin_map.end(); +} + +static void SetPluginInfo(const FileSpec &plugin_file_spec, + const PluginInfo &plugin_info) { + std::lock_guard<std::recursive_mutex> guard(GetPluginMapMutex()); + PluginTerminateMap &plugin_map = GetPluginMap(); + assert(plugin_map.find(plugin_file_spec) == plugin_map.end()); + plugin_map[plugin_file_spec] = plugin_info; +} + +template <typename FPtrTy> static FPtrTy CastToFPtr(void *VPtr) { + return reinterpret_cast<FPtrTy>(reinterpret_cast<intptr_t>(VPtr)); +} + +static FileSpec::EnumerateDirectoryResult +LoadPluginCallback(void *baton, FileSpec::FileType file_type, + const FileSpec &file_spec) { + // PluginManager *plugin_manager = (PluginManager *)baton; + Error error; + + // If we have a regular file, a symbolic link or unknown file type, try + // and process the file. We must handle unknown as sometimes the directory + // enumeration might be enumerating a file system that doesn't have correct + // file type information. + if (file_type == FileSpec::eFileTypeRegular || + file_type == FileSpec::eFileTypeSymbolicLink || + file_type == FileSpec::eFileTypeUnknown) { + FileSpec plugin_file_spec(file_spec); + plugin_file_spec.ResolvePath(); + + if (PluginIsLoaded(plugin_file_spec)) + return FileSpec::eEnumerateDirectoryResultNext; + else { + PluginInfo plugin_info; + + std::string pluginLoadError; + plugin_info.library = llvm::sys::DynamicLibrary::getPermanentLibrary( + plugin_file_spec.GetPath().c_str(), &pluginLoadError); + if (plugin_info.library.isValid()) { + bool success = false; + plugin_info.plugin_init_callback = CastToFPtr<PluginInitCallback>( + plugin_info.library.getAddressOfSymbol("LLDBPluginInitialize")); + if (plugin_info.plugin_init_callback) { + // Call the plug-in "bool LLDBPluginInitialize(void)" function + success = plugin_info.plugin_init_callback(); } + + if (success) { + // It is ok for the "LLDBPluginTerminate" symbol to be nullptr + plugin_info.plugin_term_callback = CastToFPtr<PluginTermCallback>( + plugin_info.library.getAddressOfSymbol("LLDBPluginTerminate")); + } else { + // The initialize function returned FALSE which means the plug-in + // might not be + // compatible, or might be too new or too old, or might not want to + // run on this + // machine. Set it to a default-constructed instance to invalidate + // it. + plugin_info = PluginInfo(); + } + + // Regardless of success or failure, cache the plug-in load + // in our plug-in info so we don't try to load it again and + // again. + SetPluginInfo(plugin_file_spec, plugin_info); + + return FileSpec::eEnumerateDirectoryResultNext; + } } - - if (file_type == FileSpec::eFileTypeUnknown || - file_type == FileSpec::eFileTypeDirectory || - file_type == FileSpec::eFileTypeSymbolicLink ) - { - // Try and recurse into anything that a directory or symbolic link. - // We must also do this for unknown as sometimes the directory enumeration - // might be enumerating a file system that doesn't have correct file type - // information. - return FileSpec::eEnumerateDirectoryResultEnter; - } + } + + if (file_type == FileSpec::eFileTypeUnknown || + file_type == FileSpec::eFileTypeDirectory || + file_type == FileSpec::eFileTypeSymbolicLink) { + // Try and recurse into anything that a directory or symbolic link. + // We must also do this for unknown as sometimes the directory enumeration + // might be enumerating a file system that doesn't have correct file type + // information. + return FileSpec::eEnumerateDirectoryResultEnter; + } - return FileSpec::eEnumerateDirectoryResultNext; + return FileSpec::eEnumerateDirectoryResultNext; } -void -PluginManager::Initialize () -{ +void PluginManager::Initialize() { #if 1 - FileSpec dir_spec; - const bool find_directories = true; - const bool find_files = true; - const bool find_other = true; - char dir_path[PATH_MAX]; - if (HostInfo::GetLLDBPath(ePathTypeLLDBSystemPlugins, dir_spec)) - { - if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) - { - FileSpec::EnumerateDirectory(dir_path, - find_directories, - find_files, - find_other, - LoadPluginCallback, - nullptr); - } - } - - if (HostInfo::GetLLDBPath(ePathTypeLLDBUserPlugins, dir_spec)) - { - if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) - { - FileSpec::EnumerateDirectory(dir_path, - find_directories, - find_files, - find_other, - LoadPluginCallback, - nullptr); - } - } + FileSpec dir_spec; + const bool find_directories = true; + const bool find_files = true; + const bool find_other = true; + char dir_path[PATH_MAX]; + if (HostInfo::GetLLDBPath(ePathTypeLLDBSystemPlugins, dir_spec)) { + if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) { + FileSpec::EnumerateDirectory(dir_path, find_directories, find_files, + find_other, LoadPluginCallback, nullptr); + } + } + + if (HostInfo::GetLLDBPath(ePathTypeLLDBUserPlugins, dir_spec)) { + if (dir_spec.Exists() && dir_spec.GetPath(dir_path, sizeof(dir_path))) { + FileSpec::EnumerateDirectory(dir_path, find_directories, find_files, + find_other, LoadPluginCallback, nullptr); + } + } #endif } -void -PluginManager::Terminate () -{ - std::lock_guard<std::recursive_mutex> guard(GetPluginMapMutex()); - PluginTerminateMap &plugin_map = GetPluginMap (); - - PluginTerminateMap::const_iterator pos, end = plugin_map.end(); - for (pos = plugin_map.begin(); pos != end; ++pos) - { - // Call the plug-in "void LLDBPluginTerminate (void)" function if there - // is one (if the symbol was not nullptr). - if (pos->second.library.isValid()) - { - if (pos->second.plugin_term_callback) - pos->second.plugin_term_callback(); - } +void PluginManager::Terminate() { + std::lock_guard<std::recursive_mutex> guard(GetPluginMapMutex()); + PluginTerminateMap &plugin_map = GetPluginMap(); + + PluginTerminateMap::const_iterator pos, end = plugin_map.end(); + for (pos = plugin_map.begin(); pos != end; ++pos) { + // Call the plug-in "void LLDBPluginTerminate (void)" function if there + // is one (if the symbol was not nullptr). + if (pos->second.library.isValid()) { + if (pos->second.plugin_term_callback) + pos->second.plugin_term_callback(); } - plugin_map.clear(); + } + plugin_map.clear(); } #pragma mark ABI -struct ABIInstance -{ - ABIInstance() : - name(), - description(), - create_callback(nullptr) - { - } +struct ABIInstance { + ABIInstance() : name(), description(), create_callback(nullptr) {} - ConstString name; - std::string description; - ABICreateInstance create_callback; + ConstString name; + std::string description; + ABICreateInstance create_callback; }; typedef std::vector<ABIInstance> ABIInstances; -static std::recursive_mutex & -GetABIInstancesMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static ABIInstances & -GetABIInstances () -{ - static ABIInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin(const ConstString &name, - const char *description, - ABICreateInstance create_callback) -{ - if (create_callback) - { - ABIInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - std::lock_guard<std::recursive_mutex> guard(GetABIInstancesMutex()); - GetABIInstances ().push_back (instance); +static std::recursive_mutex &GetABIInstancesMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; +} + +static ABIInstances &GetABIInstances() { + static ABIInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin(const ConstString &name, + const char *description, + ABICreateInstance create_callback) { + if (create_callback) { + ABIInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + std::lock_guard<std::recursive_mutex> guard(GetABIInstancesMutex()); + GetABIInstances().push_back(instance); + return true; + } + return false; +} + +bool PluginManager::UnregisterPlugin(ABICreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard(GetABIInstancesMutex()); + ABIInstances &instances = GetABIInstances(); + + ABIInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); return true; + } } - return false; + } + return false; } -bool -PluginManager::UnregisterPlugin (ABICreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetABIInstancesMutex()); - ABIInstances &instances = GetABIInstances (); - - ABIInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } - } - return false; +ABICreateInstance PluginManager::GetABICreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetABIInstancesMutex()); + ABIInstances &instances = GetABIInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } ABICreateInstance -PluginManager::GetABICreateCallbackAtIndex (uint32_t idx) -{ +PluginManager::GetABICreateCallbackForPluginName(const ConstString &name) { + if (name) { std::lock_guard<std::recursive_mutex> guard(GetABIInstancesMutex()); - ABIInstances &instances = GetABIInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; -} + ABIInstances &instances = GetABIInstances(); -ABICreateInstance -PluginManager::GetABICreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetABIInstancesMutex()); - ABIInstances &instances = GetABIInstances (); - - ABIInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } + ABIInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } #pragma mark Disassembler -struct DisassemblerInstance -{ - DisassemblerInstance() : - name(), - description(), - create_callback(nullptr) - { - } +struct DisassemblerInstance { + DisassemblerInstance() : name(), description(), create_callback(nullptr) {} - ConstString name; - std::string description; - DisassemblerCreateInstance create_callback; + ConstString name; + std::string description; + DisassemblerCreateInstance create_callback; }; typedef std::vector<DisassemblerInstance> DisassemblerInstances; -static std::recursive_mutex & -GetDisassemblerMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static DisassemblerInstances & -GetDisassemblerInstances () -{ - static DisassemblerInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin(const ConstString &name, - const char *description, - DisassemblerCreateInstance create_callback) -{ - if (create_callback) - { - DisassemblerInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - std::lock_guard<std::recursive_mutex> guard(GetDisassemblerMutex()); - GetDisassemblerInstances ().push_back (instance); - return true; - } - return false; +static std::recursive_mutex &GetDisassemblerMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (DisassemblerCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetDisassemblerMutex()); - DisassemblerInstances &instances = GetDisassemblerInstances (); - - DisassemblerInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } +static DisassemblerInstances &GetDisassemblerInstances() { + static DisassemblerInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin(const ConstString &name, + const char *description, + DisassemblerCreateInstance create_callback) { + if (create_callback) { + DisassemblerInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + std::lock_guard<std::recursive_mutex> guard(GetDisassemblerMutex()); + GetDisassemblerInstances().push_back(instance); + return true; + } + return false; +} + +bool PluginManager::UnregisterPlugin( + DisassemblerCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard(GetDisassemblerMutex()); + DisassemblerInstances &instances = GetDisassemblerInstances(); + + DisassemblerInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } } - return false; + } + return false; } DisassemblerCreateInstance -PluginManager::GetDisassemblerCreateCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetDisassemblerMutex()); - DisassemblerInstances &instances = GetDisassemblerInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +PluginManager::GetDisassemblerCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetDisassemblerMutex()); + DisassemblerInstances &instances = GetDisassemblerInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } DisassemblerCreateInstance -PluginManager::GetDisassemblerCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetDisassemblerMutex()); - DisassemblerInstances &instances = GetDisassemblerInstances (); - - DisassemblerInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetDisassemblerCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetDisassemblerMutex()); + DisassemblerInstances &instances = GetDisassemblerInstances(); + + DisassemblerInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } #pragma mark DynamicLoader -struct DynamicLoaderInstance -{ - DynamicLoaderInstance() : - name(), - description(), - create_callback(nullptr), - debugger_init_callback(nullptr) - { - } +struct DynamicLoaderInstance { + DynamicLoaderInstance() + : name(), description(), create_callback(nullptr), + debugger_init_callback(nullptr) {} - ConstString name; - std::string description; - DynamicLoaderCreateInstance create_callback; - DebuggerInitializeCallback debugger_init_callback; + ConstString name; + std::string description; + DynamicLoaderCreateInstance create_callback; + DebuggerInitializeCallback debugger_init_callback; }; typedef std::vector<DynamicLoaderInstance> DynamicLoaderInstances; -static std::recursive_mutex & -GetDynamicLoaderMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static DynamicLoaderInstances & -GetDynamicLoaderInstances () -{ - static DynamicLoaderInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin(const ConstString &name, - const char *description, - DynamicLoaderCreateInstance create_callback, - DebuggerInitializeCallback debugger_init_callback) -{ - if (create_callback) - { - DynamicLoaderInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - instance.debugger_init_callback = debugger_init_callback; - std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex()); - GetDynamicLoaderInstances ().push_back (instance); - } - return false; +static std::recursive_mutex &GetDynamicLoaderMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (DynamicLoaderCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex()); - DynamicLoaderInstances &instances = GetDynamicLoaderInstances (); - - DynamicLoaderInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } +static DynamicLoaderInstances &GetDynamicLoaderInstances() { + static DynamicLoaderInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + DynamicLoaderCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback) { + if (create_callback) { + DynamicLoaderInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.debugger_init_callback = debugger_init_callback; + std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex()); + GetDynamicLoaderInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin( + DynamicLoaderCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex()); + DynamicLoaderInstances &instances = GetDynamicLoaderInstances(); + + DynamicLoaderInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } } - return false; + } + return false; } DynamicLoaderCreateInstance -PluginManager::GetDynamicLoaderCreateCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex()); - DynamicLoaderInstances &instances = GetDynamicLoaderInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +PluginManager::GetDynamicLoaderCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex()); + DynamicLoaderInstances &instances = GetDynamicLoaderInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } DynamicLoaderCreateInstance -PluginManager::GetDynamicLoaderCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex()); - DynamicLoaderInstances &instances = GetDynamicLoaderInstances (); - - DynamicLoaderInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetDynamicLoaderCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex()); + DynamicLoaderInstances &instances = GetDynamicLoaderInstances(); + + DynamicLoaderInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } #pragma mark JITLoader -struct JITLoaderInstance -{ - JITLoaderInstance() : - name(), - description(), - create_callback(nullptr), - debugger_init_callback(nullptr) - { - } +struct JITLoaderInstance { + JITLoaderInstance() + : name(), description(), create_callback(nullptr), + debugger_init_callback(nullptr) {} - ConstString name; - std::string description; - JITLoaderCreateInstance create_callback; - DebuggerInitializeCallback debugger_init_callback; + ConstString name; + std::string description; + JITLoaderCreateInstance create_callback; + DebuggerInitializeCallback debugger_init_callback; }; typedef std::vector<JITLoaderInstance> JITLoaderInstances; -static std::recursive_mutex & -GetJITLoaderMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static JITLoaderInstances & -GetJITLoaderInstances () -{ - static JITLoaderInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin(const ConstString &name, - const char *description, - JITLoaderCreateInstance create_callback, - DebuggerInitializeCallback debugger_init_callback) -{ - if (create_callback) - { - JITLoaderInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - instance.debugger_init_callback = debugger_init_callback; - std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex()); - GetJITLoaderInstances ().push_back (instance); - } - return false; +static std::recursive_mutex &GetJITLoaderMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (JITLoaderCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex()); - JITLoaderInstances &instances = GetJITLoaderInstances (); - - JITLoaderInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } - } - return false; +static JITLoaderInstances &GetJITLoaderInstances() { + static JITLoaderInstances g_instances; + return g_instances; } -JITLoaderCreateInstance -PluginManager::GetJITLoaderCreateCallbackAtIndex (uint32_t idx) -{ +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + JITLoaderCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback) { + if (create_callback) { + JITLoaderInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.debugger_init_callback = debugger_init_callback; std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex()); - JITLoaderInstances &instances = GetJITLoaderInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; + GetJITLoaderInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin(JITLoaderCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex()); + JITLoaderInstances &instances = GetJITLoaderInstances(); + + JITLoaderInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } + } + } + return false; } JITLoaderCreateInstance -PluginManager::GetJITLoaderCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex()); - JITLoaderInstances &instances = GetJITLoaderInstances (); - - JITLoaderInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetJITLoaderCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex()); + JITLoaderInstances &instances = GetJITLoaderInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; +} + +JITLoaderCreateInstance PluginManager::GetJITLoaderCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex()); + JITLoaderInstances &instances = GetJITLoaderInstances(); + + JITLoaderInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } #pragma mark EmulateInstruction -struct EmulateInstructionInstance -{ - EmulateInstructionInstance() : - name(), - description(), - create_callback(nullptr) - { - } - - ConstString name; - std::string description; - EmulateInstructionCreateInstance create_callback; +struct EmulateInstructionInstance { + EmulateInstructionInstance() + : name(), description(), create_callback(nullptr) {} + + ConstString name; + std::string description; + EmulateInstructionCreateInstance create_callback; }; typedef std::vector<EmulateInstructionInstance> EmulateInstructionInstances; -static std::recursive_mutex & -GetEmulateInstructionMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static EmulateInstructionInstances & -GetEmulateInstructionInstances () -{ - static EmulateInstructionInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin(const ConstString &name, - const char *description, - EmulateInstructionCreateInstance create_callback) -{ - if (create_callback) - { - EmulateInstructionInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - std::lock_guard<std::recursive_mutex> guard(GetEmulateInstructionMutex()); - GetEmulateInstructionInstances ().push_back (instance); - } - return false; +static std::recursive_mutex &GetEmulateInstructionMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (EmulateInstructionCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetEmulateInstructionMutex()); - EmulateInstructionInstances &instances = GetEmulateInstructionInstances (); - - EmulateInstructionInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } +static EmulateInstructionInstances &GetEmulateInstructionInstances() { + static EmulateInstructionInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + EmulateInstructionCreateInstance create_callback) { + if (create_callback) { + EmulateInstructionInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + std::lock_guard<std::recursive_mutex> guard(GetEmulateInstructionMutex()); + GetEmulateInstructionInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin( + EmulateInstructionCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard(GetEmulateInstructionMutex()); + EmulateInstructionInstances &instances = GetEmulateInstructionInstances(); + + EmulateInstructionInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } } - return false; + } + return false; } EmulateInstructionCreateInstance -PluginManager::GetEmulateInstructionCreateCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetEmulateInstructionMutex()); - EmulateInstructionInstances &instances = GetEmulateInstructionInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +PluginManager::GetEmulateInstructionCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetEmulateInstructionMutex()); + EmulateInstructionInstances &instances = GetEmulateInstructionInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } EmulateInstructionCreateInstance -PluginManager::GetEmulateInstructionCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetEmulateInstructionMutex()); - EmulateInstructionInstances &instances = GetEmulateInstructionInstances (); - - EmulateInstructionInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetEmulateInstructionCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetEmulateInstructionMutex()); + EmulateInstructionInstances &instances = GetEmulateInstructionInstances(); + + EmulateInstructionInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } #pragma mark OperatingSystem -struct OperatingSystemInstance -{ - OperatingSystemInstance () : - name (), - description (), - create_callback (nullptr), - debugger_init_callback (nullptr) - { - } - - ConstString name; - std::string description; - OperatingSystemCreateInstance create_callback; - DebuggerInitializeCallback debugger_init_callback; +struct OperatingSystemInstance { + OperatingSystemInstance() + : name(), description(), create_callback(nullptr), + debugger_init_callback(nullptr) {} + + ConstString name; + std::string description; + OperatingSystemCreateInstance create_callback; + DebuggerInitializeCallback debugger_init_callback; }; typedef std::vector<OperatingSystemInstance> OperatingSystemInstances; -static std::recursive_mutex & -GetOperatingSystemMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static OperatingSystemInstances & -GetOperatingSystemInstances () -{ - static OperatingSystemInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin(const ConstString &name, const char *description, - OperatingSystemCreateInstance create_callback, - DebuggerInitializeCallback debugger_init_callback) -{ - if (create_callback) - { - OperatingSystemInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - instance.debugger_init_callback = debugger_init_callback; - std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex()); - GetOperatingSystemInstances ().push_back (instance); - } - return false; +static std::recursive_mutex &GetOperatingSystemMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (OperatingSystemCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex()); - OperatingSystemInstances &instances = GetOperatingSystemInstances (); - - OperatingSystemInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } +static OperatingSystemInstances &GetOperatingSystemInstances() { + static OperatingSystemInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + OperatingSystemCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback) { + if (create_callback) { + OperatingSystemInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.debugger_init_callback = debugger_init_callback; + std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex()); + GetOperatingSystemInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin( + OperatingSystemCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex()); + OperatingSystemInstances &instances = GetOperatingSystemInstances(); + + OperatingSystemInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } } - return false; + } + return false; } OperatingSystemCreateInstance -PluginManager::GetOperatingSystemCreateCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex()); - OperatingSystemInstances &instances = GetOperatingSystemInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +PluginManager::GetOperatingSystemCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex()); + OperatingSystemInstances &instances = GetOperatingSystemInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } OperatingSystemCreateInstance -PluginManager::GetOperatingSystemCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex()); - OperatingSystemInstances &instances = GetOperatingSystemInstances (); - - OperatingSystemInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetOperatingSystemCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex()); + OperatingSystemInstances &instances = GetOperatingSystemInstances(); + + OperatingSystemInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } #pragma mark Language -struct LanguageInstance -{ - LanguageInstance() : - name(), - description(), - create_callback(nullptr) - { - } - - ConstString name; - std::string description; - LanguageCreateInstance create_callback; +struct LanguageInstance { + LanguageInstance() : name(), description(), create_callback(nullptr) {} + + ConstString name; + std::string description; + LanguageCreateInstance create_callback; }; typedef std::vector<LanguageInstance> LanguageInstances; -static std::recursive_mutex & -GetLanguageMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static LanguageInstances & -GetLanguageInstances () -{ - static LanguageInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin(const ConstString &name, - const char *description, - LanguageCreateInstance create_callback) -{ - if (create_callback) - { - LanguageInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - std::lock_guard<std::recursive_mutex> guard(GetLanguageMutex()); - GetLanguageInstances ().push_back (instance); - } - return false; +static std::recursive_mutex &GetLanguageMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (LanguageCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetLanguageMutex()); - LanguageInstances &instances = GetLanguageInstances (); - - LanguageInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } +static LanguageInstances &GetLanguageInstances() { + static LanguageInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin(const ConstString &name, + const char *description, + LanguageCreateInstance create_callback) { + if (create_callback) { + LanguageInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + std::lock_guard<std::recursive_mutex> guard(GetLanguageMutex()); + GetLanguageInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin(LanguageCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard(GetLanguageMutex()); + LanguageInstances &instances = GetLanguageInstances(); + + LanguageInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } } - return false; + } + return false; } LanguageCreateInstance -PluginManager::GetLanguageCreateCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetLanguageMutex()); - LanguageInstances &instances = GetLanguageInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +PluginManager::GetLanguageCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetLanguageMutex()); + LanguageInstances &instances = GetLanguageInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } LanguageCreateInstance -PluginManager::GetLanguageCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetLanguageMutex()); - LanguageInstances &instances = GetLanguageInstances (); - - LanguageInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetLanguageCreateCallbackForPluginName(const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetLanguageMutex()); + LanguageInstances &instances = GetLanguageInstances(); + + LanguageInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } #pragma mark LanguageRuntime -struct LanguageRuntimeInstance -{ - LanguageRuntimeInstance() : - name(), - description(), - create_callback(nullptr) - { - } +struct LanguageRuntimeInstance { + LanguageRuntimeInstance() : name(), description(), create_callback(nullptr) {} - ConstString name; - std::string description; - LanguageRuntimeCreateInstance create_callback; - LanguageRuntimeGetCommandObject command_callback; + ConstString name; + std::string description; + LanguageRuntimeCreateInstance create_callback; + LanguageRuntimeGetCommandObject command_callback; }; typedef std::vector<LanguageRuntimeInstance> LanguageRuntimeInstances; -static std::recursive_mutex & -GetLanguageRuntimeMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static LanguageRuntimeInstances & -GetLanguageRuntimeInstances () -{ - static LanguageRuntimeInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin(const ConstString &name, - const char *description, - LanguageRuntimeCreateInstance create_callback, - LanguageRuntimeGetCommandObject command_callback) -{ - if (create_callback) - { - LanguageRuntimeInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - instance.command_callback = command_callback; - std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex()); - GetLanguageRuntimeInstances ().push_back (instance); - } - return false; +static std::recursive_mutex &GetLanguageRuntimeMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (LanguageRuntimeCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex()); - LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances (); - - LanguageRuntimeInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } +static LanguageRuntimeInstances &GetLanguageRuntimeInstances() { + static LanguageRuntimeInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + LanguageRuntimeCreateInstance create_callback, + LanguageRuntimeGetCommandObject command_callback) { + if (create_callback) { + LanguageRuntimeInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.command_callback = command_callback; + std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex()); + GetLanguageRuntimeInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin( + LanguageRuntimeCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex()); + LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances(); + + LanguageRuntimeInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } } - return false; + } + return false; } LanguageRuntimeCreateInstance -PluginManager::GetLanguageRuntimeCreateCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex()); - LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex()); + LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } LanguageRuntimeGetCommandObject -PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex()); - LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances (); - if (idx < instances.size()) - return instances[idx].command_callback; - return nullptr; +PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex()); + LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances(); + if (idx < instances.size()) + return instances[idx].command_callback; + return nullptr; } LanguageRuntimeCreateInstance -PluginManager::GetLanguageRuntimeCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex()); - LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances (); - - LanguageRuntimeInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetLanguageRuntimeCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetLanguageRuntimeMutex()); + LanguageRuntimeInstances &instances = GetLanguageRuntimeInstances(); + + LanguageRuntimeInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } #pragma mark SystemRuntime -struct SystemRuntimeInstance -{ - SystemRuntimeInstance() : - name(), - description(), - create_callback(nullptr) - { - } +struct SystemRuntimeInstance { + SystemRuntimeInstance() : name(), description(), create_callback(nullptr) {} - ConstString name; - std::string description; - SystemRuntimeCreateInstance create_callback; + ConstString name; + std::string description; + SystemRuntimeCreateInstance create_callback; }; typedef std::vector<SystemRuntimeInstance> SystemRuntimeInstances; -static std::recursive_mutex & -GetSystemRuntimeMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static SystemRuntimeInstances & -GetSystemRuntimeInstances () -{ - static SystemRuntimeInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin(const ConstString &name, - const char *description, - SystemRuntimeCreateInstance create_callback) -{ - if (create_callback) - { - SystemRuntimeInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - std::lock_guard<std::recursive_mutex> guard(GetSystemRuntimeMutex()); - GetSystemRuntimeInstances ().push_back (instance); - } - return false; +static std::recursive_mutex &GetSystemRuntimeMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (SystemRuntimeCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetSystemRuntimeMutex()); - SystemRuntimeInstances &instances = GetSystemRuntimeInstances (); - - SystemRuntimeInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } +static SystemRuntimeInstances &GetSystemRuntimeInstances() { + static SystemRuntimeInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + SystemRuntimeCreateInstance create_callback) { + if (create_callback) { + SystemRuntimeInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + std::lock_guard<std::recursive_mutex> guard(GetSystemRuntimeMutex()); + GetSystemRuntimeInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin( + SystemRuntimeCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard(GetSystemRuntimeMutex()); + SystemRuntimeInstances &instances = GetSystemRuntimeInstances(); + + SystemRuntimeInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } } - return false; + } + return false; } SystemRuntimeCreateInstance -PluginManager::GetSystemRuntimeCreateCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetSystemRuntimeMutex()); - SystemRuntimeInstances &instances = GetSystemRuntimeInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +PluginManager::GetSystemRuntimeCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetSystemRuntimeMutex()); + SystemRuntimeInstances &instances = GetSystemRuntimeInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } SystemRuntimeCreateInstance -PluginManager::GetSystemRuntimeCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetSystemRuntimeMutex()); - SystemRuntimeInstances &instances = GetSystemRuntimeInstances (); - - SystemRuntimeInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetSystemRuntimeCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetSystemRuntimeMutex()); + SystemRuntimeInstances &instances = GetSystemRuntimeInstances(); + + SystemRuntimeInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } #pragma mark ObjectFile -struct ObjectFileInstance -{ - ObjectFileInstance() : - name(), - description(), - create_callback(nullptr), - create_memory_callback(nullptr), - get_module_specifications(nullptr), - save_core(nullptr) - { - } - - ConstString name; - std::string description; - ObjectFileCreateInstance create_callback; - ObjectFileCreateMemoryInstance create_memory_callback; - ObjectFileGetModuleSpecifications get_module_specifications; - ObjectFileSaveCore save_core; +struct ObjectFileInstance { + ObjectFileInstance() + : name(), description(), create_callback(nullptr), + create_memory_callback(nullptr), get_module_specifications(nullptr), + save_core(nullptr) {} + + ConstString name; + std::string description; + ObjectFileCreateInstance create_callback; + ObjectFileCreateMemoryInstance create_memory_callback; + ObjectFileGetModuleSpecifications get_module_specifications; + ObjectFileSaveCore save_core; }; typedef std::vector<ObjectFileInstance> ObjectFileInstances; -static std::recursive_mutex & -GetObjectFileMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static ObjectFileInstances & -GetObjectFileInstances () -{ - static ObjectFileInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin (const ConstString &name, - const char *description, - ObjectFileCreateInstance create_callback, - ObjectFileCreateMemoryInstance create_memory_callback, - ObjectFileGetModuleSpecifications get_module_specifications, - ObjectFileSaveCore save_core) -{ - if (create_callback) - { - ObjectFileInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - instance.create_memory_callback = create_memory_callback; - instance.save_core = save_core; - instance.get_module_specifications = get_module_specifications; - std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex()); - GetObjectFileInstances ().push_back (instance); - } - return false; +static std::recursive_mutex &GetObjectFileMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (ObjectFileCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex()); - ObjectFileInstances &instances = GetObjectFileInstances (); - - ObjectFileInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } +static ObjectFileInstances &GetObjectFileInstances() { + static ObjectFileInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + ObjectFileCreateInstance create_callback, + ObjectFileCreateMemoryInstance create_memory_callback, + ObjectFileGetModuleSpecifications get_module_specifications, + ObjectFileSaveCore save_core) { + if (create_callback) { + ObjectFileInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.create_memory_callback = create_memory_callback; + instance.save_core = save_core; + instance.get_module_specifications = get_module_specifications; + std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex()); + GetObjectFileInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin(ObjectFileCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex()); + ObjectFileInstances &instances = GetObjectFileInstances(); + + ObjectFileInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } } - return false; + } + return false; } ObjectFileCreateInstance -PluginManager::GetObjectFileCreateCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex()); - ObjectFileInstances &instances = GetObjectFileInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +PluginManager::GetObjectFileCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex()); + ObjectFileInstances &instances = GetObjectFileInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } ObjectFileCreateMemoryInstance -PluginManager::GetObjectFileCreateMemoryCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex()); - ObjectFileInstances &instances = GetObjectFileInstances (); - if (idx < instances.size()) - return instances[idx].create_memory_callback; - return nullptr; +PluginManager::GetObjectFileCreateMemoryCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex()); + ObjectFileInstances &instances = GetObjectFileInstances(); + if (idx < instances.size()) + return instances[idx].create_memory_callback; + return nullptr; } ObjectFileGetModuleSpecifications -PluginManager::GetObjectFileGetModuleSpecificationsCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex()); - ObjectFileInstances &instances = GetObjectFileInstances (); - if (idx < instances.size()) - return instances[idx].get_module_specifications; - return nullptr; +PluginManager::GetObjectFileGetModuleSpecificationsCallbackAtIndex( + uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex()); + ObjectFileInstances &instances = GetObjectFileInstances(); + if (idx < instances.size()) + return instances[idx].get_module_specifications; + return nullptr; } ObjectFileCreateInstance -PluginManager::GetObjectFileCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex()); - ObjectFileInstances &instances = GetObjectFileInstances (); - - ObjectFileInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } - } - return nullptr; -} +PluginManager::GetObjectFileCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex()); + ObjectFileInstances &instances = GetObjectFileInstances(); -ObjectFileCreateMemoryInstance -PluginManager::GetObjectFileCreateMemoryCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex()); - ObjectFileInstances &instances = GetObjectFileInstances (); - - ObjectFileInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_memory_callback; - } + ObjectFileInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } -Error -PluginManager::SaveCore (const lldb::ProcessSP &process_sp, const FileSpec &outfile) -{ - Error error; +ObjectFileCreateMemoryInstance +PluginManager::GetObjectFileCreateMemoryCallbackForPluginName( + const ConstString &name) { + if (name) { std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex()); - ObjectFileInstances &instances = GetObjectFileInstances (); - + ObjectFileInstances &instances = GetObjectFileInstances(); + ObjectFileInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->save_core && pos->save_core (process_sp, outfile, error)) - return error; + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_memory_callback; } - error.SetErrorString("no ObjectFile plugins were able to save a core for this process"); - return error; + } + return nullptr; +} + +Error PluginManager::SaveCore(const lldb::ProcessSP &process_sp, + const FileSpec &outfile) { + Error error; + std::lock_guard<std::recursive_mutex> guard(GetObjectFileMutex()); + ObjectFileInstances &instances = GetObjectFileInstances(); + + ObjectFileInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->save_core && pos->save_core(process_sp, outfile, error)) + return error; + } + error.SetErrorString( + "no ObjectFile plugins were able to save a core for this process"); + return error; } #pragma mark ObjectContainer -struct ObjectContainerInstance -{ - ObjectContainerInstance() : - name(), - description(), - create_callback(nullptr), - get_module_specifications(nullptr) - { - } +struct ObjectContainerInstance { + ObjectContainerInstance() + : name(), description(), create_callback(nullptr), + get_module_specifications(nullptr) {} - ConstString name; - std::string description; - ObjectContainerCreateInstance create_callback; - ObjectFileGetModuleSpecifications get_module_specifications; + ConstString name; + std::string description; + ObjectContainerCreateInstance create_callback; + ObjectFileGetModuleSpecifications get_module_specifications; }; typedef std::vector<ObjectContainerInstance> ObjectContainerInstances; -static std::recursive_mutex & -GetObjectContainerMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static ObjectContainerInstances & -GetObjectContainerInstances () -{ - static ObjectContainerInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin (const ConstString &name, - const char *description, - ObjectContainerCreateInstance create_callback, - ObjectFileGetModuleSpecifications get_module_specifications) -{ - if (create_callback) - { - ObjectContainerInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - instance.get_module_specifications = get_module_specifications; - std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex()); - GetObjectContainerInstances ().push_back (instance); - } - return false; +static std::recursive_mutex &GetObjectContainerMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (ObjectContainerCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex()); - ObjectContainerInstances &instances = GetObjectContainerInstances (); - - ObjectContainerInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } +static ObjectContainerInstances &GetObjectContainerInstances() { + static ObjectContainerInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + ObjectContainerCreateInstance create_callback, + ObjectFileGetModuleSpecifications get_module_specifications) { + if (create_callback) { + ObjectContainerInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.get_module_specifications = get_module_specifications; + std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex()); + GetObjectContainerInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin( + ObjectContainerCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex()); + ObjectContainerInstances &instances = GetObjectContainerInstances(); + + ObjectContainerInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } } - return false; + } + return false; } ObjectContainerCreateInstance -PluginManager::GetObjectContainerCreateCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex()); - ObjectContainerInstances &instances = GetObjectContainerInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +PluginManager::GetObjectContainerCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex()); + ObjectContainerInstances &instances = GetObjectContainerInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } ObjectContainerCreateInstance -PluginManager::GetObjectContainerCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex()); - ObjectContainerInstances &instances = GetObjectContainerInstances (); - - ObjectContainerInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetObjectContainerCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex()); + ObjectContainerInstances &instances = GetObjectContainerInstances(); + + ObjectContainerInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } ObjectFileGetModuleSpecifications -PluginManager::GetObjectContainerGetModuleSpecificationsCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex()); - ObjectContainerInstances &instances = GetObjectContainerInstances (); - if (idx < instances.size()) - return instances[idx].get_module_specifications; - return nullptr; +PluginManager::GetObjectContainerGetModuleSpecificationsCallbackAtIndex( + uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetObjectContainerMutex()); + ObjectContainerInstances &instances = GetObjectContainerInstances(); + if (idx < instances.size()) + return instances[idx].get_module_specifications; + return nullptr; } #pragma mark LogChannel -struct LogInstance -{ - LogInstance() : - name(), - description(), - create_callback(nullptr) - { - } +struct LogInstance { + LogInstance() : name(), description(), create_callback(nullptr) {} - ConstString name; - std::string description; - LogChannelCreateInstance create_callback; + ConstString name; + std::string description; + LogChannelCreateInstance create_callback; }; typedef std::vector<LogInstance> LogInstances; -static std::recursive_mutex & -GetLogMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static LogInstances & -GetLogInstances () -{ - static LogInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin(const ConstString &name, - const char *description, - LogChannelCreateInstance create_callback) -{ - if (create_callback) - { - LogInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - std::lock_guard<std::recursive_mutex> gard(GetLogMutex()); - GetLogInstances ().push_back (instance); - } - return false; +static std::recursive_mutex &GetLogMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (LogChannelCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> gard(GetLogMutex()); - LogInstances &instances = GetLogInstances (); - - LogInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } - } - return false; +static LogInstances &GetLogInstances() { + static LogInstances g_instances; + return g_instances; } -const char * -PluginManager::GetLogChannelCreateNameAtIndex (uint32_t idx) -{ +bool PluginManager::RegisterPlugin(const ConstString &name, + const char *description, + LogChannelCreateInstance create_callback) { + if (create_callback) { + LogInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; std::lock_guard<std::recursive_mutex> gard(GetLogMutex()); - LogInstances &instances = GetLogInstances (); - if (idx < instances.size()) - return instances[idx].name.GetCString(); - return nullptr; + GetLogInstances().push_back(instance); + } + return false; } -LogChannelCreateInstance -PluginManager::GetLogChannelCreateCallbackAtIndex (uint32_t idx) -{ +bool PluginManager::UnregisterPlugin(LogChannelCreateInstance create_callback) { + if (create_callback) { std::lock_guard<std::recursive_mutex> gard(GetLogMutex()); - LogInstances &instances = GetLogInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; + LogInstances &instances = GetLogInstances(); + + LogInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } + } + } + return false; +} + +const char *PluginManager::GetLogChannelCreateNameAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> gard(GetLogMutex()); + LogInstances &instances = GetLogInstances(); + if (idx < instances.size()) + return instances[idx].name.GetCString(); + return nullptr; } LogChannelCreateInstance -PluginManager::GetLogChannelCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> gard(GetLogMutex()); - LogInstances &instances = GetLogInstances (); - - LogInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetLogChannelCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> gard(GetLogMutex()); + LogInstances &instances = GetLogInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; +} + +LogChannelCreateInstance +PluginManager::GetLogChannelCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> gard(GetLogMutex()); + LogInstances &instances = GetLogInstances(); + + LogInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } #pragma mark Platform -struct PlatformInstance -{ - PlatformInstance() : - name(), - description(), - create_callback(nullptr), - debugger_init_callback(nullptr) - { - } - - ConstString name; - std::string description; - PlatformCreateInstance create_callback; - DebuggerInitializeCallback debugger_init_callback; +struct PlatformInstance { + PlatformInstance() + : name(), description(), create_callback(nullptr), + debugger_init_callback(nullptr) {} + + ConstString name; + std::string description; + PlatformCreateInstance create_callback; + DebuggerInitializeCallback debugger_init_callback; }; typedef std::vector<PlatformInstance> PlatformInstances; -static std::recursive_mutex & -GetPlatformInstancesMutex() -{ - static std::recursive_mutex g_platform_instances_mutex; - return g_platform_instances_mutex; -} - -static PlatformInstances & -GetPlatformInstances () -{ - static PlatformInstances g_platform_instances; - return g_platform_instances; -} - -bool -PluginManager::RegisterPlugin (const ConstString &name, - const char *description, - PlatformCreateInstance create_callback, - DebuggerInitializeCallback debugger_init_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex()); - - PlatformInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - instance.debugger_init_callback = debugger_init_callback; - GetPlatformInstances ().push_back (instance); - return true; - } - return false; +static std::recursive_mutex &GetPlatformInstancesMutex() { + static std::recursive_mutex g_platform_instances_mutex; + return g_platform_instances_mutex; } -const char * -PluginManager::GetPlatformPluginNameAtIndex (uint32_t idx) -{ +static PlatformInstances &GetPlatformInstances() { + static PlatformInstances g_platform_instances; + return g_platform_instances; +} + +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + PlatformCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback) { + if (create_callback) { std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex()); - PlatformInstances &instances = GetPlatformInstances (); - if (idx < instances.size()) - return instances[idx].name.GetCString(); - return nullptr; + + PlatformInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.debugger_init_callback = debugger_init_callback; + GetPlatformInstances().push_back(instance); + return true; + } + return false; +} + +const char *PluginManager::GetPlatformPluginNameAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex()); + PlatformInstances &instances = GetPlatformInstances(); + if (idx < instances.size()) + return instances[idx].name.GetCString(); + return nullptr; } -const char * -PluginManager::GetPlatformPluginDescriptionAtIndex (uint32_t idx) -{ +const char *PluginManager::GetPlatformPluginDescriptionAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex()); + PlatformInstances &instances = GetPlatformInstances(); + if (idx < instances.size()) + return instances[idx].description.c_str(); + return nullptr; +} + +bool PluginManager::UnregisterPlugin(PlatformCreateInstance create_callback) { + if (create_callback) { std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex()); - PlatformInstances &instances = GetPlatformInstances (); - if (idx < instances.size()) - return instances[idx].description.c_str(); - return nullptr; -} - -bool -PluginManager::UnregisterPlugin (PlatformCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex()); - PlatformInstances &instances = GetPlatformInstances (); - - PlatformInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } + PlatformInstances &instances = GetPlatformInstances(); + + PlatformInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } } - return false; + } + return false; } PlatformCreateInstance -PluginManager::GetPlatformCreateCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex()); - PlatformInstances &instances = GetPlatformInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +PluginManager::GetPlatformCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex()); + PlatformInstances &instances = GetPlatformInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } PlatformCreateInstance -PluginManager::GetPlatformCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex()); - PlatformInstances &instances = GetPlatformInstances (); - - PlatformInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetPlatformCreateCallbackForPluginName(const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex()); + PlatformInstances &instances = GetPlatformInstances(); + + PlatformInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } -size_t -PluginManager::AutoCompletePlatformName (const char *name, StringList &matches) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex()); - PlatformInstances &instances = GetPlatformInstances (); - llvm::StringRef name_sref(name); - - PlatformInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - llvm::StringRef plugin_name (pos->name.GetCString()); - if (plugin_name.startswith(name_sref)) - matches.AppendString (plugin_name.data()); - } - } +size_t PluginManager::AutoCompletePlatformName(llvm::StringRef name, + StringList &matches) { + if (name.empty()) return matches.GetSize(); + + std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex()); + PlatformInstances &instances = GetPlatformInstances(); + llvm::StringRef name_sref(name); + + PlatformInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + llvm::StringRef plugin_name(pos->name.GetCString()); + if (plugin_name.startswith(name_sref)) + matches.AppendString(plugin_name.data()); + } + return matches.GetSize(); } #pragma mark Process -struct ProcessInstance -{ - ProcessInstance() : - name(), - description(), - create_callback(nullptr), - debugger_init_callback(nullptr) - { - } - - ConstString name; - std::string description; - ProcessCreateInstance create_callback; - DebuggerInitializeCallback debugger_init_callback; +struct ProcessInstance { + ProcessInstance() + : name(), description(), create_callback(nullptr), + debugger_init_callback(nullptr) {} + + ConstString name; + std::string description; + ProcessCreateInstance create_callback; + DebuggerInitializeCallback debugger_init_callback; }; typedef std::vector<ProcessInstance> ProcessInstances; -static std::recursive_mutex & -GetProcessMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static ProcessInstances & -GetProcessInstances () -{ - static ProcessInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin (const ConstString &name, - const char *description, - ProcessCreateInstance create_callback, - DebuggerInitializeCallback debugger_init_callback) -{ - if (create_callback) - { - ProcessInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - instance.debugger_init_callback = debugger_init_callback; - std::lock_guard<std::recursive_mutex> guard(GetProcessMutex()); - GetProcessInstances ().push_back (instance); - } - return false; +static std::recursive_mutex &GetProcessMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; +} + +static ProcessInstances &GetProcessInstances() { + static ProcessInstances g_instances; + return g_instances; } -const char * -PluginManager::GetProcessPluginNameAtIndex (uint32_t idx) -{ +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + ProcessCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback) { + if (create_callback) { + ProcessInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.debugger_init_callback = debugger_init_callback; std::lock_guard<std::recursive_mutex> guard(GetProcessMutex()); - ProcessInstances &instances = GetProcessInstances (); - if (idx < instances.size()) - return instances[idx].name.GetCString(); - return nullptr; + GetProcessInstances().push_back(instance); + } + return false; +} + +const char *PluginManager::GetProcessPluginNameAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetProcessMutex()); + ProcessInstances &instances = GetProcessInstances(); + if (idx < instances.size()) + return instances[idx].name.GetCString(); + return nullptr; } -const char * -PluginManager::GetProcessPluginDescriptionAtIndex (uint32_t idx) -{ +const char *PluginManager::GetProcessPluginDescriptionAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetProcessMutex()); + ProcessInstances &instances = GetProcessInstances(); + if (idx < instances.size()) + return instances[idx].description.c_str(); + return nullptr; +} + +bool PluginManager::UnregisterPlugin(ProcessCreateInstance create_callback) { + if (create_callback) { std::lock_guard<std::recursive_mutex> guard(GetProcessMutex()); - ProcessInstances &instances = GetProcessInstances (); - if (idx < instances.size()) - return instances[idx].description.c_str(); - return nullptr; -} - -bool -PluginManager::UnregisterPlugin (ProcessCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetProcessMutex()); - ProcessInstances &instances = GetProcessInstances (); - - ProcessInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } + ProcessInstances &instances = GetProcessInstances(); + + ProcessInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } } - return false; + } + return false; } ProcessCreateInstance -PluginManager::GetProcessCreateCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetProcessMutex()); - ProcessInstances &instances = GetProcessInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +PluginManager::GetProcessCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetProcessMutex()); + ProcessInstances &instances = GetProcessInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } ProcessCreateInstance -PluginManager::GetProcessCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetProcessMutex()); - ProcessInstances &instances = GetProcessInstances (); - - ProcessInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetProcessCreateCallbackForPluginName(const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetProcessMutex()); + ProcessInstances &instances = GetProcessInstances(); + + ProcessInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } #pragma mark ScriptInterpreter -struct ScriptInterpreterInstance -{ - ScriptInterpreterInstance() - : name() - , language(lldb::eScriptLanguageNone) - , description() - , create_callback(nullptr) - { - } +struct ScriptInterpreterInstance { + ScriptInterpreterInstance() + : name(), language(lldb::eScriptLanguageNone), description(), + create_callback(nullptr) {} - ConstString name; - lldb::ScriptLanguage language; - std::string description; - ScriptInterpreterCreateInstance create_callback; + ConstString name; + lldb::ScriptLanguage language; + std::string description; + ScriptInterpreterCreateInstance create_callback; }; typedef std::vector<ScriptInterpreterInstance> ScriptInterpreterInstances; -static std::recursive_mutex & -GetScriptInterpreterMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; +static std::recursive_mutex &GetScriptInterpreterMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -static ScriptInterpreterInstances & -GetScriptInterpreterInstances() -{ - static ScriptInterpreterInstances g_instances; - return g_instances; +static ScriptInterpreterInstances &GetScriptInterpreterInstances() { + static ScriptInterpreterInstances g_instances; + return g_instances; } -bool -PluginManager::RegisterPlugin(const ConstString &name, const char *description, lldb::ScriptLanguage script_language, - ScriptInterpreterCreateInstance create_callback) -{ - if (!create_callback) - return false; - ScriptInterpreterInstance instance; - assert((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - instance.language = script_language; - std::lock_guard<std::recursive_mutex> guard(GetScriptInterpreterMutex()); - GetScriptInterpreterInstances().push_back(instance); +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + lldb::ScriptLanguage script_language, + ScriptInterpreterCreateInstance create_callback) { + if (!create_callback) + return false; + ScriptInterpreterInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.language = script_language; + std::lock_guard<std::recursive_mutex> guard(GetScriptInterpreterMutex()); + GetScriptInterpreterInstances().push_back(instance); + return false; +} + +bool PluginManager::UnregisterPlugin( + ScriptInterpreterCreateInstance create_callback) { + if (!create_callback) return false; + std::lock_guard<std::recursive_mutex> guard(GetScriptInterpreterMutex()); + ScriptInterpreterInstances &instances = GetScriptInterpreterInstances(); + + ScriptInterpreterInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback != create_callback) + continue; + + instances.erase(pos); + return true; + } + return false; } -bool -PluginManager::UnregisterPlugin(ScriptInterpreterCreateInstance create_callback) -{ - if (!create_callback) - return false; - std::lock_guard<std::recursive_mutex> guard(GetScriptInterpreterMutex()); - ScriptInterpreterInstances &instances = GetScriptInterpreterInstances(); +ScriptInterpreterCreateInstance +PluginManager::GetScriptInterpreterCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetScriptInterpreterMutex()); + ScriptInterpreterInstances &instances = GetScriptInterpreterInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; +} + +lldb::ScriptInterpreterSP PluginManager::GetScriptInterpreterForLanguage( + lldb::ScriptLanguage script_lang, CommandInterpreter &interpreter) { + std::lock_guard<std::recursive_mutex> guard(GetScriptInterpreterMutex()); + ScriptInterpreterInstances &instances = GetScriptInterpreterInstances(); + + ScriptInterpreterInstances::iterator pos, end = instances.end(); + ScriptInterpreterCreateInstance none_instance = nullptr; + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->language == lldb::eScriptLanguageNone) + none_instance = pos->create_callback; + + if (script_lang == pos->language) + return pos->create_callback(interpreter); + } + + // If we didn't find one, return the ScriptInterpreter for the null language. + assert(none_instance != nullptr); + return none_instance(interpreter); +} + +#pragma mark - +#pragma mark StructuredDataPlugin + +// ----------------------------------------------------------------------------- +// StructuredDataPlugin +// ----------------------------------------------------------------------------- + +struct StructuredDataPluginInstance { + StructuredDataPluginInstance() + : name(), description(), create_callback(nullptr), + debugger_init_callback(nullptr), filter_callback(nullptr) {} + + ConstString name; + std::string description; + StructuredDataPluginCreateInstance create_callback; + DebuggerInitializeCallback debugger_init_callback; + StructuredDataFilterLaunchInfo filter_callback; +}; + +typedef std::vector<StructuredDataPluginInstance> StructuredDataPluginInstances; - ScriptInterpreterInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++pos) - { - if (pos->create_callback != create_callback) - continue; +static std::recursive_mutex &GetStructuredDataPluginMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; +} +static StructuredDataPluginInstances &GetStructuredDataPluginInstances() { + static StructuredDataPluginInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + StructuredDataPluginCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback, + StructuredDataFilterLaunchInfo filter_callback) { + if (create_callback) { + StructuredDataPluginInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.debugger_init_callback = debugger_init_callback; + instance.filter_callback = filter_callback; + std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex()); + GetStructuredDataPluginInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin( + StructuredDataPluginCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex()); + StructuredDataPluginInstances &instances = + GetStructuredDataPluginInstances(); + + StructuredDataPluginInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { instances.erase(pos); return true; + } } - return false; + } + return false; } -ScriptInterpreterCreateInstance -PluginManager::GetScriptInterpreterCreateCallbackAtIndex(uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetScriptInterpreterMutex()); - ScriptInterpreterInstances &instances = GetScriptInterpreterInstances(); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +StructuredDataPluginCreateInstance +PluginManager::GetStructuredDataPluginCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex()); + StructuredDataPluginInstances &instances = GetStructuredDataPluginInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } -lldb::ScriptInterpreterSP -PluginManager::GetScriptInterpreterForLanguage(lldb::ScriptLanguage script_lang, CommandInterpreter &interpreter) -{ - std::lock_guard<std::recursive_mutex> guard(GetScriptInterpreterMutex()); - ScriptInterpreterInstances &instances = GetScriptInterpreterInstances(); - - ScriptInterpreterInstances::iterator pos, end = instances.end(); - ScriptInterpreterCreateInstance none_instance = nullptr; - for (pos = instances.begin(); pos != end; ++pos) - { - if (pos->language == lldb::eScriptLanguageNone) - none_instance = pos->create_callback; +StructuredDataPluginCreateInstance +PluginManager::GetStructuredDataPluginCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex()); + StructuredDataPluginInstances &instances = + GetStructuredDataPluginInstances(); - if (script_lang == pos->language) - return pos->create_callback(interpreter); + StructuredDataPluginInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } + } + return nullptr; +} - // If we didn't find one, return the ScriptInterpreter for the null language. - assert(none_instance != nullptr); - return none_instance(interpreter); +StructuredDataFilterLaunchInfo +PluginManager::GetStructuredDataFilterCallbackAtIndex( + uint32_t idx, bool &iteration_complete) { + std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex()); + StructuredDataPluginInstances &instances = GetStructuredDataPluginInstances(); + if (idx < instances.size()) { + iteration_complete = false; + return instances[idx].filter_callback; + } else { + iteration_complete = true; + } + return nullptr; } #pragma mark SymbolFile -struct SymbolFileInstance -{ - SymbolFileInstance() : - name(), - description(), - create_callback(nullptr), - debugger_init_callback(nullptr) - { - } +struct SymbolFileInstance { + SymbolFileInstance() + : name(), description(), create_callback(nullptr), + debugger_init_callback(nullptr) {} - ConstString name; - std::string description; - SymbolFileCreateInstance create_callback; - DebuggerInitializeCallback debugger_init_callback; + ConstString name; + std::string description; + SymbolFileCreateInstance create_callback; + DebuggerInitializeCallback debugger_init_callback; }; typedef std::vector<SymbolFileInstance> SymbolFileInstances; -static std::recursive_mutex & -GetSymbolFileMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static SymbolFileInstances & -GetSymbolFileInstances () -{ - static SymbolFileInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin(const ConstString &name, - const char *description, - SymbolFileCreateInstance create_callback, - DebuggerInitializeCallback debugger_init_callback) -{ - if (create_callback) - { - SymbolFileInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - instance.debugger_init_callback = debugger_init_callback; - std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex()); - GetSymbolFileInstances ().push_back (instance); - } - return false; +static std::recursive_mutex &GetSymbolFileMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (SymbolFileCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex()); - SymbolFileInstances &instances = GetSymbolFileInstances (); - - SymbolFileInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } +static SymbolFileInstances &GetSymbolFileInstances() { + static SymbolFileInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + SymbolFileCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback) { + if (create_callback) { + SymbolFileInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.debugger_init_callback = debugger_init_callback; + std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex()); + GetSymbolFileInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin(SymbolFileCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex()); + SymbolFileInstances &instances = GetSymbolFileInstances(); + + SymbolFileInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } } - return false; + } + return false; } SymbolFileCreateInstance -PluginManager::GetSymbolFileCreateCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex()); - SymbolFileInstances &instances = GetSymbolFileInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +PluginManager::GetSymbolFileCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex()); + SymbolFileInstances &instances = GetSymbolFileInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } SymbolFileCreateInstance -PluginManager::GetSymbolFileCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex()); - SymbolFileInstances &instances = GetSymbolFileInstances (); - - SymbolFileInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetSymbolFileCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex()); + SymbolFileInstances &instances = GetSymbolFileInstances(); + + SymbolFileInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } #pragma mark SymbolVendor -struct SymbolVendorInstance -{ - SymbolVendorInstance() : - name(), - description(), - create_callback(nullptr) - { - } +struct SymbolVendorInstance { + SymbolVendorInstance() : name(), description(), create_callback(nullptr) {} - ConstString name; - std::string description; - SymbolVendorCreateInstance create_callback; + ConstString name; + std::string description; + SymbolVendorCreateInstance create_callback; }; typedef std::vector<SymbolVendorInstance> SymbolVendorInstances; -static std::recursive_mutex & -GetSymbolVendorMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static SymbolVendorInstances & -GetSymbolVendorInstances () -{ - static SymbolVendorInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin(const ConstString &name, - const char *description, - SymbolVendorCreateInstance create_callback) -{ - if (create_callback) - { - SymbolVendorInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - std::lock_guard<std::recursive_mutex> guard(GetSymbolVendorMutex()); - GetSymbolVendorInstances ().push_back (instance); - } - return false; +static std::recursive_mutex &GetSymbolVendorMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (SymbolVendorCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetSymbolVendorMutex()); - SymbolVendorInstances &instances = GetSymbolVendorInstances (); - - SymbolVendorInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } +static SymbolVendorInstances &GetSymbolVendorInstances() { + static SymbolVendorInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin(const ConstString &name, + const char *description, + SymbolVendorCreateInstance create_callback) { + if (create_callback) { + SymbolVendorInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + std::lock_guard<std::recursive_mutex> guard(GetSymbolVendorMutex()); + GetSymbolVendorInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin( + SymbolVendorCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard(GetSymbolVendorMutex()); + SymbolVendorInstances &instances = GetSymbolVendorInstances(); + + SymbolVendorInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } } - return false; + } + return false; } SymbolVendorCreateInstance -PluginManager::GetSymbolVendorCreateCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetSymbolVendorMutex()); - SymbolVendorInstances &instances = GetSymbolVendorInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +PluginManager::GetSymbolVendorCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetSymbolVendorMutex()); + SymbolVendorInstances &instances = GetSymbolVendorInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } SymbolVendorCreateInstance -PluginManager::GetSymbolVendorCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetSymbolVendorMutex()); - SymbolVendorInstances &instances = GetSymbolVendorInstances (); - - SymbolVendorInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetSymbolVendorCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetSymbolVendorMutex()); + SymbolVendorInstances &instances = GetSymbolVendorInstances(); + + SymbolVendorInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } #pragma mark UnwindAssembly -struct UnwindAssemblyInstance -{ - UnwindAssemblyInstance() : - name(), - description(), - create_callback(nullptr) - { - } +struct UnwindAssemblyInstance { + UnwindAssemblyInstance() : name(), description(), create_callback(nullptr) {} - ConstString name; - std::string description; - UnwindAssemblyCreateInstance create_callback; + ConstString name; + std::string description; + UnwindAssemblyCreateInstance create_callback; }; typedef std::vector<UnwindAssemblyInstance> UnwindAssemblyInstances; -static std::recursive_mutex & -GetUnwindAssemblyMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static UnwindAssemblyInstances & -GetUnwindAssemblyInstances () -{ - static UnwindAssemblyInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin(const ConstString &name, - const char *description, - UnwindAssemblyCreateInstance create_callback) -{ - if (create_callback) - { - UnwindAssemblyInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - std::lock_guard<std::recursive_mutex> guard(GetUnwindAssemblyMutex()); - GetUnwindAssemblyInstances ().push_back (instance); - } - return false; +static std::recursive_mutex &GetUnwindAssemblyMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (UnwindAssemblyCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetUnwindAssemblyMutex()); - UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances (); - - UnwindAssemblyInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } +static UnwindAssemblyInstances &GetUnwindAssemblyInstances() { + static UnwindAssemblyInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + UnwindAssemblyCreateInstance create_callback) { + if (create_callback) { + UnwindAssemblyInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + std::lock_guard<std::recursive_mutex> guard(GetUnwindAssemblyMutex()); + GetUnwindAssemblyInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin( + UnwindAssemblyCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard(GetUnwindAssemblyMutex()); + UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances(); + + UnwindAssemblyInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } } - return false; + } + return false; } UnwindAssemblyCreateInstance -PluginManager::GetUnwindAssemblyCreateCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetUnwindAssemblyMutex()); - UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +PluginManager::GetUnwindAssemblyCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetUnwindAssemblyMutex()); + UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } UnwindAssemblyCreateInstance -PluginManager::GetUnwindAssemblyCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetUnwindAssemblyMutex()); - UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances (); - - UnwindAssemblyInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetUnwindAssemblyCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetUnwindAssemblyMutex()); + UnwindAssemblyInstances &instances = GetUnwindAssemblyInstances(); + + UnwindAssemblyInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } #pragma mark MemoryHistory -struct MemoryHistoryInstance -{ - MemoryHistoryInstance() : - name(), - description(), - create_callback(nullptr) - { - } - - ConstString name; - std::string description; - MemoryHistoryCreateInstance create_callback; +struct MemoryHistoryInstance { + MemoryHistoryInstance() : name(), description(), create_callback(nullptr) {} + + ConstString name; + std::string description; + MemoryHistoryCreateInstance create_callback; }; typedef std::vector<MemoryHistoryInstance> MemoryHistoryInstances; -static std::recursive_mutex & -GetMemoryHistoryMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static MemoryHistoryInstances & -GetMemoryHistoryInstances () -{ - static MemoryHistoryInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin(const ConstString &name, - const char *description, - MemoryHistoryCreateInstance create_callback) -{ - if (create_callback) - { - MemoryHistoryInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - std::lock_guard<std::recursive_mutex> guard(GetMemoryHistoryMutex()); - GetMemoryHistoryInstances ().push_back (instance); - } - return false; +static std::recursive_mutex &GetMemoryHistoryMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (MemoryHistoryCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetMemoryHistoryMutex()); - MemoryHistoryInstances &instances = GetMemoryHistoryInstances (); - - MemoryHistoryInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } +static MemoryHistoryInstances &GetMemoryHistoryInstances() { + static MemoryHistoryInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + MemoryHistoryCreateInstance create_callback) { + if (create_callback) { + MemoryHistoryInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + std::lock_guard<std::recursive_mutex> guard(GetMemoryHistoryMutex()); + GetMemoryHistoryInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin( + MemoryHistoryCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard(GetMemoryHistoryMutex()); + MemoryHistoryInstances &instances = GetMemoryHistoryInstances(); + + MemoryHistoryInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } } - return false; + } + return false; } MemoryHistoryCreateInstance -PluginManager::GetMemoryHistoryCreateCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetMemoryHistoryMutex()); - MemoryHistoryInstances &instances = GetMemoryHistoryInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +PluginManager::GetMemoryHistoryCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetMemoryHistoryMutex()); + MemoryHistoryInstances &instances = GetMemoryHistoryInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } MemoryHistoryCreateInstance -PluginManager::GetMemoryHistoryCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetMemoryHistoryMutex()); - MemoryHistoryInstances &instances = GetMemoryHistoryInstances (); - - MemoryHistoryInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetMemoryHistoryCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetMemoryHistoryMutex()); + MemoryHistoryInstances &instances = GetMemoryHistoryInstances(); + + MemoryHistoryInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } #pragma mark InstrumentationRuntime -struct InstrumentationRuntimeInstance -{ - InstrumentationRuntimeInstance() : - name(), - description(), - create_callback(nullptr) - { - } - - ConstString name; - std::string description; - InstrumentationRuntimeCreateInstance create_callback; - InstrumentationRuntimeGetType get_type_callback; +struct InstrumentationRuntimeInstance { + InstrumentationRuntimeInstance() + : name(), description(), create_callback(nullptr) {} + + ConstString name; + std::string description; + InstrumentationRuntimeCreateInstance create_callback; + InstrumentationRuntimeGetType get_type_callback; }; -typedef std::vector<InstrumentationRuntimeInstance> InstrumentationRuntimeInstances; - -static std::recursive_mutex & -GetInstrumentationRuntimeMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static InstrumentationRuntimeInstances & -GetInstrumentationRuntimeInstances () -{ - static InstrumentationRuntimeInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin(const ConstString &name, - const char *description, - InstrumentationRuntimeCreateInstance create_callback, - InstrumentationRuntimeGetType get_type_callback) -{ - if (create_callback) - { - InstrumentationRuntimeInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - instance.get_type_callback = get_type_callback; - std::lock_guard<std::recursive_mutex> guard(GetInstrumentationRuntimeMutex()); - GetInstrumentationRuntimeInstances ().push_back (instance); - } - return false; +typedef std::vector<InstrumentationRuntimeInstance> + InstrumentationRuntimeInstances; + +static std::recursive_mutex &GetInstrumentationRuntimeMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (InstrumentationRuntimeCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetInstrumentationRuntimeMutex()); - InstrumentationRuntimeInstances &instances = GetInstrumentationRuntimeInstances (); - - InstrumentationRuntimeInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } +static InstrumentationRuntimeInstances &GetInstrumentationRuntimeInstances() { + static InstrumentationRuntimeInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + InstrumentationRuntimeCreateInstance create_callback, + InstrumentationRuntimeGetType get_type_callback) { + if (create_callback) { + InstrumentationRuntimeInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.get_type_callback = get_type_callback; + std::lock_guard<std::recursive_mutex> guard( + GetInstrumentationRuntimeMutex()); + GetInstrumentationRuntimeInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin( + InstrumentationRuntimeCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard( + GetInstrumentationRuntimeMutex()); + InstrumentationRuntimeInstances &instances = + GetInstrumentationRuntimeInstances(); + + InstrumentationRuntimeInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } } - return false; + } + return false; } InstrumentationRuntimeGetType -PluginManager::GetInstrumentationRuntimeGetTypeCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetInstrumentationRuntimeMutex()); - InstrumentationRuntimeInstances &instances = GetInstrumentationRuntimeInstances (); - if (idx < instances.size()) - return instances[idx].get_type_callback; - return nullptr; +PluginManager::GetInstrumentationRuntimeGetTypeCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetInstrumentationRuntimeMutex()); + InstrumentationRuntimeInstances &instances = + GetInstrumentationRuntimeInstances(); + if (idx < instances.size()) + return instances[idx].get_type_callback; + return nullptr; } InstrumentationRuntimeCreateInstance -PluginManager::GetInstrumentationRuntimeCreateCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetInstrumentationRuntimeMutex()); - InstrumentationRuntimeInstances &instances = GetInstrumentationRuntimeInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +PluginManager::GetInstrumentationRuntimeCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetInstrumentationRuntimeMutex()); + InstrumentationRuntimeInstances &instances = + GetInstrumentationRuntimeInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } InstrumentationRuntimeCreateInstance -PluginManager::GetInstrumentationRuntimeCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetInstrumentationRuntimeMutex()); - InstrumentationRuntimeInstances &instances = GetInstrumentationRuntimeInstances (); - - InstrumentationRuntimeInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetInstrumentationRuntimeCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard( + GetInstrumentationRuntimeMutex()); + InstrumentationRuntimeInstances &instances = + GetInstrumentationRuntimeInstances(); + + InstrumentationRuntimeInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } #pragma mark TypeSystem -struct TypeSystemInstance -{ - TypeSystemInstance() : - name(), - description(), - create_callback(nullptr) - { - } +struct TypeSystemInstance { + TypeSystemInstance() : name(), description(), create_callback(nullptr) {} - ConstString name; - std::string description; - TypeSystemCreateInstance create_callback; - TypeSystemEnumerateSupportedLanguages enumerate_callback; + ConstString name; + std::string description; + TypeSystemCreateInstance create_callback; + TypeSystemEnumerateSupportedLanguages enumerate_callback; }; typedef std::vector<TypeSystemInstance> TypeSystemInstances; -static std::recursive_mutex & -GetTypeSystemMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static TypeSystemInstances & -GetTypeSystemInstances () -{ - static TypeSystemInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin (const ConstString &name, - const char *description, - TypeSystemCreateInstance create_callback, - TypeSystemEnumerateSupportedLanguages enumerate_supported_languages_callback) -{ - if (create_callback) - { - TypeSystemInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - instance.enumerate_callback = enumerate_supported_languages_callback; - std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex()); - GetTypeSystemInstances ().push_back (instance); - } - return false; +static std::recursive_mutex &GetTypeSystemMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (TypeSystemCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex()); - TypeSystemInstances &instances = GetTypeSystemInstances (); - - TypeSystemInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } +static TypeSystemInstances &GetTypeSystemInstances() { + static TypeSystemInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin(const ConstString &name, + const char *description, + TypeSystemCreateInstance create_callback, + TypeSystemEnumerateSupportedLanguages + enumerate_supported_languages_callback) { + if (create_callback) { + TypeSystemInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.enumerate_callback = enumerate_supported_languages_callback; + std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex()); + GetTypeSystemInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin(TypeSystemCreateInstance create_callback) { + if (create_callback) { + std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex()); + TypeSystemInstances &instances = GetTypeSystemInstances(); + + TypeSystemInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } } - return false; + } + return false; } TypeSystemCreateInstance -PluginManager::GetTypeSystemCreateCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex()); - TypeSystemInstances &instances = GetTypeSystemInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; +PluginManager::GetTypeSystemCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex()); + TypeSystemInstances &instances = GetTypeSystemInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } TypeSystemCreateInstance -PluginManager::GetTypeSystemCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex()); - TypeSystemInstances &instances = GetTypeSystemInstances (); - - TypeSystemInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetTypeSystemCreateCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex()); + TypeSystemInstances &instances = GetTypeSystemInstances(); + + TypeSystemInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } TypeSystemEnumerateSupportedLanguages -PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex()); - TypeSystemInstances &instances = GetTypeSystemInstances (); - if (idx < instances.size()) - return instances[idx].enumerate_callback; - return nullptr; +PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex( + uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex()); + TypeSystemInstances &instances = GetTypeSystemInstances(); + if (idx < instances.size()) + return instances[idx].enumerate_callback; + return nullptr; } TypeSystemEnumerateSupportedLanguages -PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex()); - TypeSystemInstances &instances = GetTypeSystemInstances (); - - TypeSystemInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->enumerate_callback; - } +PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetTypeSystemMutex()); + TypeSystemInstances &instances = GetTypeSystemInstances(); + + TypeSystemInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->enumerate_callback; } - return nullptr; + } + return nullptr; } #pragma mark REPL -struct REPLInstance -{ - REPLInstance() : - name(), - description(), - create_callback(nullptr) - { - } - - ConstString name; - std::string description; - REPLCreateInstance create_callback; - REPLEnumerateSupportedLanguages enumerate_languages_callback; +struct REPLInstance { + REPLInstance() : name(), description(), create_callback(nullptr) {} + + ConstString name; + std::string description; + REPLCreateInstance create_callback; + REPLEnumerateSupportedLanguages enumerate_languages_callback; }; typedef std::vector<REPLInstance> REPLInstances; -static std::recursive_mutex & -GetREPLMutex() -{ - static std::recursive_mutex g_instances_mutex; - return g_instances_mutex; -} - -static REPLInstances & -GetREPLInstances () -{ - static REPLInstances g_instances; - return g_instances; -} - -bool -PluginManager::RegisterPlugin (const ConstString &name, - const char *description, - REPLCreateInstance create_callback, - REPLEnumerateSupportedLanguages enumerate_languages_callback) -{ - if (create_callback) - { - REPLInstance instance; - assert ((bool)name); - instance.name = name; - if (description && description[0]) - instance.description = description; - instance.create_callback = create_callback; - instance.enumerate_languages_callback = enumerate_languages_callback; - std::lock_guard<std::recursive_mutex> guard(GetREPLMutex()); - GetREPLInstances ().push_back (instance); - } - return false; +static std::recursive_mutex &GetREPLMutex() { + static std::recursive_mutex g_instances_mutex; + return g_instances_mutex; } -bool -PluginManager::UnregisterPlugin (REPLCreateInstance create_callback) -{ - if (create_callback) - { - std::lock_guard<std::recursive_mutex> guard(GetREPLMutex()); - REPLInstances &instances = GetREPLInstances (); - - REPLInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->create_callback == create_callback) - { - instances.erase(pos); - return true; - } - } - } - return false; +static REPLInstances &GetREPLInstances() { + static REPLInstances g_instances; + return g_instances; } -REPLCreateInstance -PluginManager::GetREPLCreateCallbackAtIndex (uint32_t idx) -{ +bool PluginManager::RegisterPlugin( + const ConstString &name, const char *description, + REPLCreateInstance create_callback, + REPLEnumerateSupportedLanguages enumerate_languages_callback) { + if (create_callback) { + REPLInstance instance; + assert((bool)name); + instance.name = name; + if (description && description[0]) + instance.description = description; + instance.create_callback = create_callback; + instance.enumerate_languages_callback = enumerate_languages_callback; + std::lock_guard<std::recursive_mutex> guard(GetREPLMutex()); + GetREPLInstances().push_back(instance); + } + return false; +} + +bool PluginManager::UnregisterPlugin(REPLCreateInstance create_callback) { + if (create_callback) { std::lock_guard<std::recursive_mutex> guard(GetREPLMutex()); - REPLInstances &instances = GetREPLInstances (); - if (idx < instances.size()) - return instances[idx].create_callback; - return nullptr; + REPLInstances &instances = GetREPLInstances(); + + REPLInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->create_callback == create_callback) { + instances.erase(pos); + return true; + } + } + } + return false; +} + +REPLCreateInstance PluginManager::GetREPLCreateCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetREPLMutex()); + REPLInstances &instances = GetREPLInstances(); + if (idx < instances.size()) + return instances[idx].create_callback; + return nullptr; } REPLCreateInstance -PluginManager::GetREPLCreateCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetREPLMutex()); - REPLInstances &instances = GetREPLInstances (); - - REPLInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->create_callback; - } +PluginManager::GetREPLCreateCallbackForPluginName(const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetREPLMutex()); + REPLInstances &instances = GetREPLInstances(); + + REPLInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->create_callback; } - return nullptr; + } + return nullptr; } REPLEnumerateSupportedLanguages -PluginManager::GetREPLEnumerateSupportedLanguagesCallbackAtIndex (uint32_t idx) -{ - std::lock_guard<std::recursive_mutex> guard(GetREPLMutex()); - REPLInstances &instances = GetREPLInstances (); - if (idx < instances.size()) - return instances[idx].enumerate_languages_callback; - return nullptr; +PluginManager::GetREPLEnumerateSupportedLanguagesCallbackAtIndex(uint32_t idx) { + std::lock_guard<std::recursive_mutex> guard(GetREPLMutex()); + REPLInstances &instances = GetREPLInstances(); + if (idx < instances.size()) + return instances[idx].enumerate_languages_callback; + return nullptr; } REPLEnumerateSupportedLanguages -PluginManager::GetREPLSystemEnumerateSupportedLanguagesCallbackForPluginName (const ConstString &name) -{ - if (name) - { - std::lock_guard<std::recursive_mutex> guard(GetREPLMutex()); - REPLInstances &instances = GetREPLInstances (); - - REPLInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (name == pos->name) - return pos->enumerate_languages_callback; - } +PluginManager::GetREPLSystemEnumerateSupportedLanguagesCallbackForPluginName( + const ConstString &name) { + if (name) { + std::lock_guard<std::recursive_mutex> guard(GetREPLMutex()); + REPLInstances &instances = GetREPLInstances(); + + REPLInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (name == pos->name) + return pos->enumerate_languages_callback; } - return nullptr; + } + return nullptr; } #pragma mark PluginManager -void -PluginManager::DebuggerInitialize (Debugger &debugger) -{ - // Initialize the DynamicLoader plugins - { - std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex()); - DynamicLoaderInstances &instances = GetDynamicLoaderInstances (); - - DynamicLoaderInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->debugger_init_callback) - pos->debugger_init_callback (debugger); - } +void PluginManager::DebuggerInitialize(Debugger &debugger) { + // Initialize the DynamicLoader plugins + { + std::lock_guard<std::recursive_mutex> guard(GetDynamicLoaderMutex()); + DynamicLoaderInstances &instances = GetDynamicLoaderInstances(); + + DynamicLoaderInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->debugger_init_callback) + pos->debugger_init_callback(debugger); } + } - // Initialize the JITLoader plugins - { - std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex()); - JITLoaderInstances &instances = GetJITLoaderInstances (); - - JITLoaderInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->debugger_init_callback) - pos->debugger_init_callback (debugger); - } + // Initialize the JITLoader plugins + { + std::lock_guard<std::recursive_mutex> guard(GetJITLoaderMutex()); + JITLoaderInstances &instances = GetJITLoaderInstances(); + + JITLoaderInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->debugger_init_callback) + pos->debugger_init_callback(debugger); } + } - // Initialize the Platform plugins - { - std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex()); - PlatformInstances &instances = GetPlatformInstances (); - - PlatformInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->debugger_init_callback) - pos->debugger_init_callback (debugger); - } + // Initialize the Platform plugins + { + std::lock_guard<std::recursive_mutex> guard(GetPlatformInstancesMutex()); + PlatformInstances &instances = GetPlatformInstances(); + + PlatformInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->debugger_init_callback) + pos->debugger_init_callback(debugger); } + } - // Initialize the Process plugins - { - std::lock_guard<std::recursive_mutex> guard(GetProcessMutex()); - ProcessInstances &instances = GetProcessInstances(); - - ProcessInstances::iterator pos, end = instances.end(); - for (pos = instances.begin(); pos != end; ++ pos) - { - if (pos->debugger_init_callback) - pos->debugger_init_callback (debugger); - } + // Initialize the Process plugins + { + std::lock_guard<std::recursive_mutex> guard(GetProcessMutex()); + ProcessInstances &instances = GetProcessInstances(); + + ProcessInstances::iterator pos, end = instances.end(); + for (pos = instances.begin(); pos != end; ++pos) { + if (pos->debugger_init_callback) + pos->debugger_init_callback(debugger); } + } - // Initialize the SymbolFile plugins - { - std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex()); - for (auto& sym_file: GetSymbolFileInstances()) - { - if (sym_file.debugger_init_callback) - sym_file.debugger_init_callback (debugger); - } + // Initialize the SymbolFile plugins + { + std::lock_guard<std::recursive_mutex> guard(GetSymbolFileMutex()); + for (auto &sym_file : GetSymbolFileInstances()) { + if (sym_file.debugger_init_callback) + sym_file.debugger_init_callback(debugger); } + } - // Initialize the OperatingSystem plugins - { - std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex()); - for (auto &os : GetOperatingSystemInstances()) - { - if (os.debugger_init_callback) - os.debugger_init_callback(debugger); - } + // Initialize the OperatingSystem plugins + { + std::lock_guard<std::recursive_mutex> guard(GetOperatingSystemMutex()); + for (auto &os : GetOperatingSystemInstances()) { + if (os.debugger_init_callback) + os.debugger_init_callback(debugger); + } + } + + // Initialize the StructuredDataPlugin plugins + { + std::lock_guard<std::recursive_mutex> guard(GetStructuredDataPluginMutex()); + for (auto &plugin : GetStructuredDataPluginInstances()) { + if (plugin.debugger_init_callback) + plugin.debugger_init_callback(debugger); } + } } // This is the preferred new way to register plugin specific settings. e.g. -// This will put a plugin's settings under e.g. "plugin.<plugin_type_name>.<plugin_type_desc>.SETTINGNAME". -static lldb::OptionValuePropertiesSP -GetDebuggerPropertyForPlugins (Debugger &debugger, - const ConstString &plugin_type_name, - const ConstString &plugin_type_desc, - bool can_create) -{ - lldb::OptionValuePropertiesSP parent_properties_sp (debugger.GetValueProperties()); - if (parent_properties_sp) - { - static ConstString g_property_name("plugin"); - - OptionValuePropertiesSP plugin_properties_sp = parent_properties_sp->GetSubProperty(nullptr, g_property_name); - if (!plugin_properties_sp && can_create) - { - plugin_properties_sp.reset (new OptionValueProperties (g_property_name)); - parent_properties_sp->AppendProperty (g_property_name, - ConstString("Settings specify to plugins."), - true, - plugin_properties_sp); - } - - if (plugin_properties_sp) - { - lldb::OptionValuePropertiesSP plugin_type_properties_sp = plugin_properties_sp->GetSubProperty(nullptr, plugin_type_name); - if (!plugin_type_properties_sp && can_create) - { - plugin_type_properties_sp.reset (new OptionValueProperties (plugin_type_name)); - plugin_properties_sp->AppendProperty (plugin_type_name, - plugin_type_desc, - true, - plugin_type_properties_sp); - } - return plugin_type_properties_sp; - } +// This will put a plugin's settings under e.g. +// "plugin.<plugin_type_name>.<plugin_type_desc>.SETTINGNAME". +static lldb::OptionValuePropertiesSP GetDebuggerPropertyForPlugins( + Debugger &debugger, const ConstString &plugin_type_name, + const ConstString &plugin_type_desc, bool can_create) { + lldb::OptionValuePropertiesSP parent_properties_sp( + debugger.GetValueProperties()); + if (parent_properties_sp) { + static ConstString g_property_name("plugin"); + + OptionValuePropertiesSP plugin_properties_sp = + parent_properties_sp->GetSubProperty(nullptr, g_property_name); + if (!plugin_properties_sp && can_create) { + plugin_properties_sp.reset(new OptionValueProperties(g_property_name)); + parent_properties_sp->AppendProperty( + g_property_name, ConstString("Settings specify to plugins."), true, + plugin_properties_sp); } - return lldb::OptionValuePropertiesSP(); + + if (plugin_properties_sp) { + lldb::OptionValuePropertiesSP plugin_type_properties_sp = + plugin_properties_sp->GetSubProperty(nullptr, plugin_type_name); + if (!plugin_type_properties_sp && can_create) { + plugin_type_properties_sp.reset( + new OptionValueProperties(plugin_type_name)); + plugin_properties_sp->AppendProperty(plugin_type_name, plugin_type_desc, + true, plugin_type_properties_sp); + } + return plugin_type_properties_sp; + } + } + return lldb::OptionValuePropertiesSP(); } // This is deprecated way to register plugin specific settings. e.g. // "<plugin_type_name>.plugin.<plugin_type_desc>.SETTINGNAME" // and Platform generic settings would be under "platform.SETTINGNAME". -static lldb::OptionValuePropertiesSP -GetDebuggerPropertyForPluginsOldStyle (Debugger &debugger, - const ConstString &plugin_type_name, - const ConstString &plugin_type_desc, - bool can_create) -{ - static ConstString g_property_name("plugin"); - lldb::OptionValuePropertiesSP parent_properties_sp (debugger.GetValueProperties()); - if (parent_properties_sp) - { - OptionValuePropertiesSP plugin_properties_sp = parent_properties_sp->GetSubProperty(nullptr, plugin_type_name); - if (!plugin_properties_sp && can_create) - { - plugin_properties_sp.reset (new OptionValueProperties (plugin_type_name)); - parent_properties_sp->AppendProperty (plugin_type_name, - plugin_type_desc, - true, - plugin_properties_sp); - } - - if (plugin_properties_sp) - { - lldb::OptionValuePropertiesSP plugin_type_properties_sp = plugin_properties_sp->GetSubProperty(nullptr, g_property_name); - if (!plugin_type_properties_sp && can_create) - { - plugin_type_properties_sp.reset (new OptionValueProperties (g_property_name)); - plugin_properties_sp->AppendProperty (g_property_name, - ConstString("Settings specific to plugins"), - true, - plugin_type_properties_sp); - } - return plugin_type_properties_sp; - } - } - return lldb::OptionValuePropertiesSP(); +static lldb::OptionValuePropertiesSP GetDebuggerPropertyForPluginsOldStyle( + Debugger &debugger, const ConstString &plugin_type_name, + const ConstString &plugin_type_desc, bool can_create) { + static ConstString g_property_name("plugin"); + lldb::OptionValuePropertiesSP parent_properties_sp( + debugger.GetValueProperties()); + if (parent_properties_sp) { + OptionValuePropertiesSP plugin_properties_sp = + parent_properties_sp->GetSubProperty(nullptr, plugin_type_name); + if (!plugin_properties_sp && can_create) { + plugin_properties_sp.reset(new OptionValueProperties(plugin_type_name)); + parent_properties_sp->AppendProperty(plugin_type_name, plugin_type_desc, + true, plugin_properties_sp); + } + + if (plugin_properties_sp) { + lldb::OptionValuePropertiesSP plugin_type_properties_sp = + plugin_properties_sp->GetSubProperty(nullptr, g_property_name); + if (!plugin_type_properties_sp && can_create) { + plugin_type_properties_sp.reset( + new OptionValueProperties(g_property_name)); + plugin_properties_sp->AppendProperty( + g_property_name, ConstString("Settings specific to plugins"), true, + plugin_type_properties_sp); + } + return plugin_type_properties_sp; + } + } + return lldb::OptionValuePropertiesSP(); } namespace { typedef lldb::OptionValuePropertiesSP -GetDebuggerPropertyForPluginsPtr (Debugger&, const ConstString&, const ConstString&, bool can_create); +GetDebuggerPropertyForPluginsPtr(Debugger &, const ConstString &, + const ConstString &, bool can_create); lldb::OptionValuePropertiesSP -GetSettingForPlugin (Debugger &debugger, - const ConstString &setting_name, - const ConstString &plugin_type_name, - GetDebuggerPropertyForPluginsPtr get_debugger_property= GetDebuggerPropertyForPlugins) -{ - lldb::OptionValuePropertiesSP properties_sp; - lldb::OptionValuePropertiesSP plugin_type_properties_sp (get_debugger_property (debugger, - plugin_type_name, - ConstString(), // not creating to so we don't need the description - false)); - if (plugin_type_properties_sp) - properties_sp = plugin_type_properties_sp->GetSubProperty (nullptr, setting_name); - return properties_sp; -} - -bool -CreateSettingForPlugin (Debugger &debugger, - const ConstString &plugin_type_name, - const ConstString &plugin_type_desc, - const lldb::OptionValuePropertiesSP &properties_sp, - const ConstString &description, - bool is_global_property, - GetDebuggerPropertyForPluginsPtr get_debugger_property = GetDebuggerPropertyForPlugins) -{ - if (properties_sp) - { - lldb::OptionValuePropertiesSP plugin_type_properties_sp (get_debugger_property ( - debugger, plugin_type_name, plugin_type_desc, true)); - if (plugin_type_properties_sp) - { - plugin_type_properties_sp->AppendProperty (properties_sp->GetName(), - description, - is_global_property, - properties_sp); - return true; - } +GetSettingForPlugin(Debugger &debugger, const ConstString &setting_name, + const ConstString &plugin_type_name, + GetDebuggerPropertyForPluginsPtr get_debugger_property = + GetDebuggerPropertyForPlugins) { + lldb::OptionValuePropertiesSP properties_sp; + lldb::OptionValuePropertiesSP plugin_type_properties_sp(get_debugger_property( + debugger, plugin_type_name, + ConstString(), // not creating to so we don't need the description + false)); + if (plugin_type_properties_sp) + properties_sp = + plugin_type_properties_sp->GetSubProperty(nullptr, setting_name); + return properties_sp; +} + +bool CreateSettingForPlugin( + Debugger &debugger, const ConstString &plugin_type_name, + const ConstString &plugin_type_desc, + const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, bool is_global_property, + GetDebuggerPropertyForPluginsPtr get_debugger_property = + GetDebuggerPropertyForPlugins) { + if (properties_sp) { + lldb::OptionValuePropertiesSP plugin_type_properties_sp( + get_debugger_property(debugger, plugin_type_name, plugin_type_desc, + true)); + if (plugin_type_properties_sp) { + plugin_type_properties_sp->AppendProperty(properties_sp->GetName(), + description, is_global_property, + properties_sp); + return true; } - return false; + } + return false; } -const char* kDynamicLoaderPluginName("dynamic-loader"); -const char* kPlatformPluginName("platform"); -const char* kProcessPluginName("process"); -const char* kSymbolFilePluginName("symbol-file"); -const char* kJITLoaderPluginName("jit-loader"); +const char *kDynamicLoaderPluginName("dynamic-loader"); +const char *kPlatformPluginName("platform"); +const char *kProcessPluginName("process"); +const char *kSymbolFilePluginName("symbol-file"); +const char *kJITLoaderPluginName("jit-loader"); +const char *kStructuredDataPluginName("structured-data"); } // anonymous namespace -lldb::OptionValuePropertiesSP -PluginManager::GetSettingForDynamicLoaderPlugin (Debugger &debugger, - const ConstString &setting_name) -{ - return GetSettingForPlugin(debugger, setting_name, ConstString(kDynamicLoaderPluginName)); -} - -bool -PluginManager::CreateSettingForDynamicLoaderPlugin (Debugger &debugger, - const lldb::OptionValuePropertiesSP &properties_sp, - const ConstString &description, - bool is_global_property) -{ - return CreateSettingForPlugin(debugger, - ConstString(kDynamicLoaderPluginName), - ConstString("Settings for dynamic loader plug-ins"), - properties_sp, - description, - is_global_property); +lldb::OptionValuePropertiesSP PluginManager::GetSettingForDynamicLoaderPlugin( + Debugger &debugger, const ConstString &setting_name) { + return GetSettingForPlugin(debugger, setting_name, + ConstString(kDynamicLoaderPluginName)); +} + +bool PluginManager::CreateSettingForDynamicLoaderPlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, bool is_global_property) { + return CreateSettingForPlugin( + debugger, ConstString(kDynamicLoaderPluginName), + ConstString("Settings for dynamic loader plug-ins"), properties_sp, + description, is_global_property); } lldb::OptionValuePropertiesSP -PluginManager::GetSettingForPlatformPlugin (Debugger &debugger, const ConstString &setting_name) -{ - return GetSettingForPlugin(debugger, - setting_name, - ConstString(kPlatformPluginName), - GetDebuggerPropertyForPluginsOldStyle); -} - -bool -PluginManager::CreateSettingForPlatformPlugin (Debugger &debugger, - const lldb::OptionValuePropertiesSP &properties_sp, - const ConstString &description, - bool is_global_property) -{ - return CreateSettingForPlugin(debugger, - ConstString(kPlatformPluginName), - ConstString("Settings for platform plug-ins"), - properties_sp, - description, - is_global_property, - GetDebuggerPropertyForPluginsOldStyle); +PluginManager::GetSettingForPlatformPlugin(Debugger &debugger, + const ConstString &setting_name) { + return GetSettingForPlugin(debugger, setting_name, + ConstString(kPlatformPluginName), + GetDebuggerPropertyForPluginsOldStyle); +} + +bool PluginManager::CreateSettingForPlatformPlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, bool is_global_property) { + return CreateSettingForPlugin(debugger, ConstString(kPlatformPluginName), + ConstString("Settings for platform plug-ins"), + properties_sp, description, is_global_property, + GetDebuggerPropertyForPluginsOldStyle); } lldb::OptionValuePropertiesSP -PluginManager::GetSettingForProcessPlugin (Debugger &debugger, const ConstString &setting_name) -{ - return GetSettingForPlugin(debugger, setting_name, ConstString(kProcessPluginName)); +PluginManager::GetSettingForProcessPlugin(Debugger &debugger, + const ConstString &setting_name) { + return GetSettingForPlugin(debugger, setting_name, + ConstString(kProcessPluginName)); } -bool -PluginManager::CreateSettingForProcessPlugin (Debugger &debugger, - const lldb::OptionValuePropertiesSP &properties_sp, - const ConstString &description, - bool is_global_property) -{ - return CreateSettingForPlugin(debugger, - ConstString(kProcessPluginName), - ConstString("Settings for process plug-ins"), - properties_sp, - description, - is_global_property); +bool PluginManager::CreateSettingForProcessPlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, bool is_global_property) { + return CreateSettingForPlugin(debugger, ConstString(kProcessPluginName), + ConstString("Settings for process plug-ins"), + properties_sp, description, is_global_property); } lldb::OptionValuePropertiesSP -PluginManager::GetSettingForSymbolFilePlugin (Debugger &debugger, - const ConstString &setting_name) -{ - return GetSettingForPlugin(debugger, setting_name, ConstString(kSymbolFilePluginName)); -} - -bool -PluginManager::CreateSettingForSymbolFilePlugin (Debugger &debugger, - const lldb::OptionValuePropertiesSP &properties_sp, - const ConstString &description, - bool is_global_property) -{ - return CreateSettingForPlugin(debugger, - ConstString(kSymbolFilePluginName), - ConstString("Settings for symbol file plug-ins"), - properties_sp, - description, - is_global_property); +PluginManager::GetSettingForSymbolFilePlugin(Debugger &debugger, + const ConstString &setting_name) { + return GetSettingForPlugin(debugger, setting_name, + ConstString(kSymbolFilePluginName)); +} + +bool PluginManager::CreateSettingForSymbolFilePlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, bool is_global_property) { + return CreateSettingForPlugin( + debugger, ConstString(kSymbolFilePluginName), + ConstString("Settings for symbol file plug-ins"), properties_sp, + description, is_global_property); } lldb::OptionValuePropertiesSP -PluginManager::GetSettingForJITLoaderPlugin (Debugger &debugger, - const ConstString &setting_name) -{ - return GetSettingForPlugin(debugger, setting_name, ConstString(kJITLoaderPluginName)); -} - -bool -PluginManager::CreateSettingForJITLoaderPlugin (Debugger &debugger, - const lldb::OptionValuePropertiesSP &properties_sp, - const ConstString &description, - bool is_global_property) -{ - return CreateSettingForPlugin(debugger, - ConstString(kJITLoaderPluginName), - ConstString("Settings for JIT loader plug-ins"), - properties_sp, - description, - is_global_property); +PluginManager::GetSettingForJITLoaderPlugin(Debugger &debugger, + const ConstString &setting_name) { + return GetSettingForPlugin(debugger, setting_name, + ConstString(kJITLoaderPluginName)); +} + +bool PluginManager::CreateSettingForJITLoaderPlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, bool is_global_property) { + return CreateSettingForPlugin(debugger, ConstString(kJITLoaderPluginName), + ConstString("Settings for JIT loader plug-ins"), + properties_sp, description, is_global_property); } static const char *kOperatingSystemPluginName("os"); -lldb::OptionValuePropertiesSP -PluginManager::GetSettingForOperatingSystemPlugin(Debugger &debugger, const ConstString &setting_name) -{ - lldb::OptionValuePropertiesSP properties_sp; +lldb::OptionValuePropertiesSP PluginManager::GetSettingForOperatingSystemPlugin( + Debugger &debugger, const ConstString &setting_name) { + lldb::OptionValuePropertiesSP properties_sp; + lldb::OptionValuePropertiesSP plugin_type_properties_sp( + GetDebuggerPropertyForPlugins( + debugger, ConstString(kOperatingSystemPluginName), + ConstString(), // not creating to so we don't need the description + false)); + if (plugin_type_properties_sp) + properties_sp = + plugin_type_properties_sp->GetSubProperty(nullptr, setting_name); + return properties_sp; +} + +bool PluginManager::CreateSettingForOperatingSystemPlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, bool is_global_property) { + if (properties_sp) { lldb::OptionValuePropertiesSP plugin_type_properties_sp( - GetDebuggerPropertyForPlugins(debugger, ConstString(kOperatingSystemPluginName), - ConstString(), // not creating to so we don't need the description - false)); - if (plugin_type_properties_sp) - properties_sp = plugin_type_properties_sp->GetSubProperty(nullptr, setting_name); - return properties_sp; -} - -bool -PluginManager::CreateSettingForOperatingSystemPlugin(Debugger &debugger, - const lldb::OptionValuePropertiesSP &properties_sp, - const ConstString &description, bool is_global_property) -{ - if (properties_sp) - { - lldb::OptionValuePropertiesSP plugin_type_properties_sp( - GetDebuggerPropertyForPlugins(debugger, ConstString(kOperatingSystemPluginName), - ConstString("Settings for operating system plug-ins"), true)); - if (plugin_type_properties_sp) - { - plugin_type_properties_sp->AppendProperty(properties_sp->GetName(), description, is_global_property, - properties_sp); - return true; - } - } - return false; + GetDebuggerPropertyForPlugins( + debugger, ConstString(kOperatingSystemPluginName), + ConstString("Settings for operating system plug-ins"), true)); + if (plugin_type_properties_sp) { + plugin_type_properties_sp->AppendProperty(properties_sp->GetName(), + description, is_global_property, + properties_sp); + return true; + } + } + return false; +} + +lldb::OptionValuePropertiesSP PluginManager::GetSettingForStructuredDataPlugin( + Debugger &debugger, const ConstString &setting_name) { + return GetSettingForPlugin(debugger, setting_name, + ConstString(kStructuredDataPluginName)); +} + +bool PluginManager::CreateSettingForStructuredDataPlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + const ConstString &description, bool is_global_property) { + return CreateSettingForPlugin( + debugger, ConstString(kStructuredDataPluginName), + ConstString("Settings for structured data plug-ins"), properties_sp, + description, is_global_property); } diff --git a/source/Core/RegisterValue.cpp b/source/Core/RegisterValue.cpp index d739dd6b5902..2bc0b9dd4743 100644 --- a/source/Core/RegisterValue.cpp +++ b/source/Core/RegisterValue.cpp @@ -23,635 +23,599 @@ #include "lldb/Core/Scalar.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamString.h" -#include "lldb/Interpreter/Args.h" #include "lldb/Host/StringConvert.h" +#include "lldb/Interpreter/Args.h" using namespace lldb; using namespace lldb_private; -bool -RegisterValue::Dump (Stream *s, - const RegisterInfo *reg_info, - bool prefix_with_name, - bool prefix_with_alt_name, - Format format, - uint32_t reg_name_right_align_at) const -{ - DataExtractor data; - if (GetData (data)) - { - bool name_printed = false; - // For simplicity, alignment of the register name printing applies only - // in the most common case where: - // - // prefix_with_name^prefix_with_alt_name is true - // - StreamString format_string; - if (reg_name_right_align_at && (prefix_with_name^prefix_with_alt_name)) - format_string.Printf("%%%us", reg_name_right_align_at); - else - format_string.Printf("%%s"); - const char *fmt = format_string.GetData(); - if (prefix_with_name) - { - if (reg_info->name) - { - s->Printf (fmt, reg_info->name); - name_printed = true; - } - else if (reg_info->alt_name) - { - s->Printf (fmt, reg_info->alt_name); - prefix_with_alt_name = false; - name_printed = true; - } - } - if (prefix_with_alt_name) - { - if (name_printed) - s->PutChar ('/'); - if (reg_info->alt_name) - { - s->Printf (fmt, reg_info->alt_name); - name_printed = true; - } - else if (!name_printed) - { - // No alternate name but we were asked to display a name, so show the main name - s->Printf (fmt, reg_info->name); - name_printed = true; - } - } - if (name_printed) - s->PutCString (" = "); - - if (format == eFormatDefault) - format = reg_info->format; - - data.Dump (s, - 0, // Offset in "data" - format, // Format to use when dumping - reg_info->byte_size, // item_byte_size - 1, // item_count - UINT32_MAX, // num_per_line - LLDB_INVALID_ADDRESS, // base_addr - 0, // item_bit_size - 0); // item_bit_offset - return true; - } - return false; +bool RegisterValue::Dump(Stream *s, const RegisterInfo *reg_info, + bool prefix_with_name, bool prefix_with_alt_name, + Format format, + uint32_t reg_name_right_align_at) const { + DataExtractor data; + if (GetData(data)) { + bool name_printed = false; + // For simplicity, alignment of the register name printing applies only + // in the most common case where: + // + // prefix_with_name^prefix_with_alt_name is true + // + StreamString format_string; + if (reg_name_right_align_at && (prefix_with_name ^ prefix_with_alt_name)) + format_string.Printf("%%%us", reg_name_right_align_at); + else + format_string.Printf("%%s"); + std::string fmt = format_string.GetString(); + if (prefix_with_name) { + if (reg_info->name) { + s->Printf(fmt.c_str(), reg_info->name); + name_printed = true; + } else if (reg_info->alt_name) { + s->Printf(fmt.c_str(), reg_info->alt_name); + prefix_with_alt_name = false; + name_printed = true; + } + } + if (prefix_with_alt_name) { + if (name_printed) + s->PutChar('/'); + if (reg_info->alt_name) { + s->Printf(fmt.c_str(), reg_info->alt_name); + name_printed = true; + } else if (!name_printed) { + // No alternate name but we were asked to display a name, so show the + // main name + s->Printf(fmt.c_str(), reg_info->name); + name_printed = true; + } + } + if (name_printed) + s->PutCString(" = "); + + if (format == eFormatDefault) + format = reg_info->format; + + data.Dump(s, + 0, // Offset in "data" + format, // Format to use when dumping + reg_info->byte_size, // item_byte_size + 1, // item_count + UINT32_MAX, // num_per_line + LLDB_INVALID_ADDRESS, // base_addr + 0, // item_bit_size + 0); // item_bit_offset + return true; + } + return false; } -bool -RegisterValue::GetData (DataExtractor &data) const -{ - return data.SetData(GetBytes(), GetByteSize(), GetByteOrder()) > 0; +bool RegisterValue::GetData(DataExtractor &data) const { + return data.SetData(GetBytes(), GetByteSize(), GetByteOrder()) > 0; } -uint32_t -RegisterValue::GetAsMemoryData (const RegisterInfo *reg_info, - void *dst, - uint32_t dst_len, - lldb::ByteOrder dst_byte_order, - Error &error) const -{ - if (reg_info == nullptr) - { - error.SetErrorString ("invalid register info argument."); - return 0; - } - - // ReadRegister should have already been called on this object prior to - // calling this. - if (GetType() == eTypeInvalid) - { - // No value has been read into this object... - error.SetErrorStringWithFormat("invalid register value type for register %s", reg_info->name); - return 0; - } - - if (dst_len > kMaxRegisterByteSize) - { - error.SetErrorString ("destination is too big"); - return 0; - } - - const uint32_t src_len = reg_info->byte_size; - - // Extract the register data into a data extractor - DataExtractor reg_data; - if (!GetData(reg_data)) - { - error.SetErrorString ("invalid register value to copy into"); - return 0; - } - - // Prepare a memory buffer that contains some or all of the register value - const uint32_t bytes_copied = reg_data.CopyByteOrderedData (0, // src offset - src_len, // src length - dst, // dst buffer - dst_len, // dst length - dst_byte_order); // dst byte order - if (bytes_copied == 0) - error.SetErrorStringWithFormat("failed to copy data for register write of %s", reg_info->name); - - return bytes_copied; +uint32_t RegisterValue::GetAsMemoryData(const RegisterInfo *reg_info, void *dst, + uint32_t dst_len, + lldb::ByteOrder dst_byte_order, + Error &error) const { + if (reg_info == nullptr) { + error.SetErrorString("invalid register info argument."); + return 0; + } + + // ReadRegister should have already been called on this object prior to + // calling this. + if (GetType() == eTypeInvalid) { + // No value has been read into this object... + error.SetErrorStringWithFormat( + "invalid register value type for register %s", reg_info->name); + return 0; + } + + if (dst_len > kMaxRegisterByteSize) { + error.SetErrorString("destination is too big"); + return 0; + } + + const uint32_t src_len = reg_info->byte_size; + + // Extract the register data into a data extractor + DataExtractor reg_data; + if (!GetData(reg_data)) { + error.SetErrorString("invalid register value to copy into"); + return 0; + } + + // Prepare a memory buffer that contains some or all of the register value + const uint32_t bytes_copied = + reg_data.CopyByteOrderedData(0, // src offset + src_len, // src length + dst, // dst buffer + dst_len, // dst length + dst_byte_order); // dst byte order + if (bytes_copied == 0) + error.SetErrorStringWithFormat( + "failed to copy data for register write of %s", reg_info->name); + + return bytes_copied; } -uint32_t -RegisterValue::SetFromMemoryData (const RegisterInfo *reg_info, - const void *src, - uint32_t src_len, - lldb::ByteOrder src_byte_order, - Error &error) -{ - if (reg_info == nullptr) - { - error.SetErrorString ("invalid register info argument."); - return 0; - } - - // Moving from addr into a register - // - // Case 1: src_len == dst_len - // - // |AABBCCDD| Address contents - // |AABBCCDD| Register contents - // - // Case 2: src_len > dst_len - // - // Error! (The register should always be big enough to hold the data) - // - // Case 3: src_len < dst_len - // - // |AABB| Address contents - // |AABB0000| Register contents [on little-endian hardware] - // |0000AABB| Register contents [on big-endian hardware] - if (src_len > kMaxRegisterByteSize) - { - error.SetErrorStringWithFormat ("register buffer is too small to receive %u bytes of data.", src_len); - return 0; - } - - const uint32_t dst_len = reg_info->byte_size; - - if (src_len > dst_len) - { - error.SetErrorStringWithFormat("%u bytes is too big to store in register %s (%u bytes)", src_len, reg_info->name, dst_len); - return 0; - } +uint32_t RegisterValue::SetFromMemoryData(const RegisterInfo *reg_info, + const void *src, uint32_t src_len, + lldb::ByteOrder src_byte_order, + Error &error) { + if (reg_info == nullptr) { + error.SetErrorString("invalid register info argument."); + return 0; + } - // Use a data extractor to correctly copy and pad the bytes read into the - // register value - DataExtractor src_data (src, src_len, src_byte_order, 4); + // Moving from addr into a register + // + // Case 1: src_len == dst_len + // + // |AABBCCDD| Address contents + // |AABBCCDD| Register contents + // + // Case 2: src_len > dst_len + // + // Error! (The register should always be big enough to hold the data) + // + // Case 3: src_len < dst_len + // + // |AABB| Address contents + // |AABB0000| Register contents [on little-endian hardware] + // |0000AABB| Register contents [on big-endian hardware] + if (src_len > kMaxRegisterByteSize) { + error.SetErrorStringWithFormat( + "register buffer is too small to receive %u bytes of data.", src_len); + return 0; + } + + const uint32_t dst_len = reg_info->byte_size; + + if (src_len > dst_len) { + error.SetErrorStringWithFormat( + "%u bytes is too big to store in register %s (%u bytes)", src_len, + reg_info->name, dst_len); + return 0; + } - error = SetValueFromData(reg_info, src_data, 0, true); - if (error.Fail()) - return 0; + // Use a data extractor to correctly copy and pad the bytes read into the + // register value + DataExtractor src_data(src, src_len, src_byte_order, 4); - // If SetValueFromData succeeded, we must have copied all of src_len - return src_len; + error = SetValueFromData(reg_info, src_data, 0, true); + if (error.Fail()) + return 0; + + // If SetValueFromData succeeded, we must have copied all of src_len + return src_len; } -bool -RegisterValue::GetScalarValue (Scalar &scalar) const -{ - switch (m_type) - { - case eTypeInvalid: break; - case eTypeBytes: - { - switch (buffer.length) - { - default: break; - case 1: scalar = *(const uint8_t *)buffer.bytes; return true; - case 2: scalar = *(const uint16_t *)buffer.bytes; return true; - case 4: scalar = *(const uint32_t *)buffer.bytes; return true; - case 8: scalar = *(const uint64_t *)buffer.bytes; return true; - case 16: - case 32: - if (buffer.length % sizeof(uint64_t) == 0) - { - const auto length_in_bits = buffer.length * 8; - const auto length_in_uint64 = buffer.length / sizeof(uint64_t); - scalar = llvm::APInt(length_in_bits, llvm::ArrayRef<uint64_t>((const uint64_t *)buffer.bytes, length_in_uint64)); - return true; - } - break; - } - } - break; - case eTypeUInt8: - case eTypeUInt16: - case eTypeUInt32: - case eTypeUInt64: - case eTypeUInt128: - case eTypeFloat: - case eTypeDouble: - case eTypeLongDouble: scalar = m_scalar; return true; +bool RegisterValue::GetScalarValue(Scalar &scalar) const { + switch (m_type) { + case eTypeInvalid: + break; + case eTypeBytes: { + switch (buffer.length) { + default: + break; + case 1: + scalar = *(const uint8_t *)buffer.bytes; + return true; + case 2: + scalar = *(const uint16_t *)buffer.bytes; + return true; + case 4: + scalar = *(const uint32_t *)buffer.bytes; + return true; + case 8: + scalar = *(const uint64_t *)buffer.bytes; + return true; + case 16: + case 32: + if (buffer.length % sizeof(uint64_t) == 0) { + const auto length_in_bits = buffer.length * 8; + const auto length_in_uint64 = buffer.length / sizeof(uint64_t); + scalar = + llvm::APInt(length_in_bits, + llvm::ArrayRef<uint64_t>((const uint64_t *)buffer.bytes, + length_in_uint64)); + return true; + } + break; } - return false; + } break; + case eTypeUInt8: + case eTypeUInt16: + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: + scalar = m_scalar; + return true; + } + return false; } -void -RegisterValue::Clear() -{ - m_type = eTypeInvalid; -} +void RegisterValue::Clear() { m_type = eTypeInvalid; } -RegisterValue::Type -RegisterValue::SetType (const RegisterInfo *reg_info) -{ - // To change the type, we simply copy the data in again, using the new format - RegisterValue copy; - DataExtractor copy_data; - if (copy.CopyValue(*this) && copy.GetData(copy_data)) - SetValueFromData(reg_info, copy_data, 0, true); +RegisterValue::Type RegisterValue::SetType(const RegisterInfo *reg_info) { + // To change the type, we simply copy the data in again, using the new format + RegisterValue copy; + DataExtractor copy_data; + if (copy.CopyValue(*this) && copy.GetData(copy_data)) + SetValueFromData(reg_info, copy_data, 0, true); - return m_type; + return m_type; } -Error -RegisterValue::SetValueFromData (const RegisterInfo *reg_info, DataExtractor &src, lldb::offset_t src_offset, bool partial_data_ok) -{ - Error error; - - if (src.GetByteSize() == 0) - { - error.SetErrorString ("empty data."); - return error; - } +Error RegisterValue::SetValueFromData(const RegisterInfo *reg_info, + DataExtractor &src, + lldb::offset_t src_offset, + bool partial_data_ok) { + Error error; - if (reg_info->byte_size == 0) - { - error.SetErrorString ("invalid register info."); - return error; - } + if (src.GetByteSize() == 0) { + error.SetErrorString("empty data."); + return error; + } - uint32_t src_len = src.GetByteSize() - src_offset; - - if (!partial_data_ok && (src_len < reg_info->byte_size)) - { - error.SetErrorString ("not enough data."); - return error; - } - - // Cap the data length if there is more than enough bytes for this register - // value - if (src_len > reg_info->byte_size) - src_len = reg_info->byte_size; + if (reg_info->byte_size == 0) { + error.SetErrorString("invalid register info."); + return error; + } - // Zero out the value in case we get partial data... - memset (buffer.bytes, 0, sizeof (buffer.bytes)); + uint32_t src_len = src.GetByteSize() - src_offset; - type128 int128; + if (!partial_data_ok && (src_len < reg_info->byte_size)) { + error.SetErrorString("not enough data."); + return error; + } - m_type = eTypeInvalid; - switch (reg_info->encoding) - { - case eEncodingInvalid: - break; - case eEncodingUint: - case eEncodingSint: - if (reg_info->byte_size == 1) - SetUInt8(src.GetMaxU32(&src_offset, src_len)); - else if (reg_info->byte_size <= 2) - SetUInt16(src.GetMaxU32(&src_offset, src_len)); - else if (reg_info->byte_size <= 4) - SetUInt32(src.GetMaxU32(&src_offset, src_len)); - else if (reg_info->byte_size <= 8) - SetUInt64(src.GetMaxU64(&src_offset, src_len)); - else if (reg_info->byte_size <= 16) - { - uint64_t data1 = src.GetU64 (&src_offset); - uint64_t data2 = src.GetU64 (&src_offset); - if (src.GetByteSize() == eByteOrderBig) - { - int128.x[0] = data1; - int128.x[1] = data2; - } - else - { - int128.x[0] = data2; - int128.x[1] = data1; - } - SetUInt128 (llvm::APInt(128, 2, int128.x)); - } - break; - case eEncodingIEEE754: - if (reg_info->byte_size == sizeof(float)) - SetFloat(src.GetFloat(&src_offset)); - else if (reg_info->byte_size == sizeof(double)) - SetDouble(src.GetDouble(&src_offset)); - else if (reg_info->byte_size == sizeof(long double)) - SetLongDouble(src.GetLongDouble(&src_offset)); - break; - case eEncodingVector: - { - m_type = eTypeBytes; - buffer.length = reg_info->byte_size; - buffer.byte_order = src.GetByteOrder(); - assert (buffer.length <= kMaxRegisterByteSize); - if (buffer.length > kMaxRegisterByteSize) - buffer.length = kMaxRegisterByteSize; - if (src.CopyByteOrderedData (src_offset, // offset within "src" to start extracting data - src_len, // src length - buffer.bytes, // dst buffer - buffer.length, // dst length - buffer.byte_order) == 0)// dst byte order - { - error.SetErrorStringWithFormat("failed to copy data for register write of %s", reg_info->name); - return error; - } - } + // Cap the data length if there is more than enough bytes for this register + // value + if (src_len > reg_info->byte_size) + src_len = reg_info->byte_size; + + // Zero out the value in case we get partial data... + memset(buffer.bytes, 0, sizeof(buffer.bytes)); + + type128 int128; + + m_type = eTypeInvalid; + switch (reg_info->encoding) { + case eEncodingInvalid: + break; + case eEncodingUint: + case eEncodingSint: + if (reg_info->byte_size == 1) + SetUInt8(src.GetMaxU32(&src_offset, src_len)); + else if (reg_info->byte_size <= 2) + SetUInt16(src.GetMaxU32(&src_offset, src_len)); + else if (reg_info->byte_size <= 4) + SetUInt32(src.GetMaxU32(&src_offset, src_len)); + else if (reg_info->byte_size <= 8) + SetUInt64(src.GetMaxU64(&src_offset, src_len)); + else if (reg_info->byte_size <= 16) { + uint64_t data1 = src.GetU64(&src_offset); + uint64_t data2 = src.GetU64(&src_offset); + if (src.GetByteSize() == eByteOrderBig) { + int128.x[0] = data1; + int128.x[1] = data2; + } else { + int128.x[0] = data2; + int128.x[1] = data1; + } + SetUInt128(llvm::APInt(128, 2, int128.x)); + } + break; + case eEncodingIEEE754: + if (reg_info->byte_size == sizeof(float)) + SetFloat(src.GetFloat(&src_offset)); + else if (reg_info->byte_size == sizeof(double)) + SetDouble(src.GetDouble(&src_offset)); + else if (reg_info->byte_size == sizeof(long double)) + SetLongDouble(src.GetLongDouble(&src_offset)); + break; + case eEncodingVector: { + m_type = eTypeBytes; + buffer.length = reg_info->byte_size; + buffer.byte_order = src.GetByteOrder(); + assert(buffer.length <= kMaxRegisterByteSize); + if (buffer.length > kMaxRegisterByteSize) + buffer.length = kMaxRegisterByteSize; + if (src.CopyByteOrderedData( + src_offset, // offset within "src" to start extracting data + src_len, // src length + buffer.bytes, // dst buffer + buffer.length, // dst length + buffer.byte_order) == 0) // dst byte order + { + error.SetErrorStringWithFormat( + "failed to copy data for register write of %s", reg_info->name); + return error; } + } + } - if (m_type == eTypeInvalid) - error.SetErrorStringWithFormat("invalid register value type for register %s", reg_info->name); - return error; + if (m_type == eTypeInvalid) + error.SetErrorStringWithFormat( + "invalid register value type for register %s", reg_info->name); + return error; } -static inline void StripSpaces(llvm::StringRef &Str) -{ - while (!Str.empty() && isspace(Str[0])) - Str = Str.substr(1); - while (!Str.empty() && isspace(Str.back())) - Str = Str.substr(0, Str.size()-1); -} +// Helper function for RegisterValue::SetValueFromString() +static bool ParseVectorEncoding(const RegisterInfo *reg_info, + llvm::StringRef vector_str, + const uint32_t byte_size, + RegisterValue *reg_value) { + // Example: vector_str = "{0x2c 0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a + // 0x2a 0x3e 0x84 0x4f 0x2a 0x3e}". + vector_str = vector_str.trim(); + vector_str.consume_front("{"); + vector_str.consume_back("}"); + vector_str = vector_str.trim(); + + char Sep = ' '; + + // The first split should give us: + // ('0x2c', '0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a 0x2a 0x3e 0x84 0x4f + // 0x2a 0x3e'). + llvm::StringRef car; + llvm::StringRef cdr = vector_str; + std::tie(car, cdr) = vector_str.split(Sep); + std::vector<uint8_t> bytes; + unsigned byte = 0; + + // Using radix auto-sensing by passing 0 as the radix. + // Keep on processing the vector elements as long as the parsing succeeds and + // the vector size is < byte_size. + while (!car.getAsInteger(0, byte) && bytes.size() < byte_size) { + bytes.push_back(byte); + std::tie(car, cdr) = cdr.split(Sep); + } -static inline void LStrip(llvm::StringRef &Str, char c) -{ - if (!Str.empty() && Str.front() == c) - Str = Str.substr(1); -} + // Check for vector of exact byte_size elements. + if (bytes.size() != byte_size) + return false; -static inline void RStrip(llvm::StringRef &Str, char c) -{ - if (!Str.empty() && Str.back() == c) - Str = Str.substr(0, Str.size()-1); + reg_value->SetBytes(&(bytes.front()), byte_size, eByteOrderLittle); + return true; } -// Helper function for RegisterValue::SetValueFromCString() -static bool -ParseVectorEncoding(const RegisterInfo *reg_info, const char *vector_str, const uint32_t byte_size, RegisterValue *reg_value) -{ - // Example: vector_str = "{0x2c 0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a 0x2a 0x3e 0x84 0x4f 0x2a 0x3e}". - llvm::StringRef Str(vector_str); - StripSpaces(Str); - LStrip(Str, '{'); - RStrip(Str, '}'); - StripSpaces(Str); - - char Sep = ' '; - - // The first split should give us: - // ('0x2c', '0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a 0x2a 0x3e 0x84 0x4f 0x2a 0x3e'). - std::pair<llvm::StringRef, llvm::StringRef> Pair = Str.split(Sep); - std::vector<uint8_t> bytes; - unsigned byte = 0; - - // Using radix auto-sensing by passing 0 as the radix. - // Keep on processing the vector elements as long as the parsing succeeds and the vector size is < byte_size. - while (!Pair.first.getAsInteger(0, byte) && bytes.size() < byte_size) { - bytes.push_back(byte); - Pair = Pair.second.split(Sep); +Error RegisterValue::SetValueFromString(const RegisterInfo *reg_info, + llvm::StringRef value_str) { + Error error; + if (reg_info == nullptr) { + error.SetErrorString("Invalid register info argument."); + return error; + } + + m_type = eTypeInvalid; + if (value_str.empty()) { + error.SetErrorString("Invalid c-string value string."); + return error; + } + const uint32_t byte_size = reg_info->byte_size; + + uint64_t uval64; + int64_t ival64; + float flt_val; + double dbl_val; + long double ldbl_val; + switch (reg_info->encoding) { + case eEncodingInvalid: + error.SetErrorString("Invalid encoding."); + break; + + case eEncodingUint: + if (byte_size > sizeof(uint64_t)) { + error.SetErrorStringWithFormat( + "unsupported unsigned integer byte size: %u", byte_size); + break; + } + if (value_str.getAsInteger(0, uval64)) { + error.SetErrorStringWithFormat( + "'%s' is not a valid unsigned integer string value", + value_str.str().c_str()); + break; } - // Check for vector of exact byte_size elements. - if (bytes.size() != byte_size) - return false; + if (!Args::UInt64ValueIsValidForByteSize(uval64, byte_size)) { + error.SetErrorStringWithFormat( + "value 0x%" PRIx64 + " is too large to fit in a %u byte unsigned integer value", + uval64, byte_size); + break; + } - reg_value->SetBytes(&(bytes.front()), byte_size, eByteOrderLittle); - return true; -} + if (!SetUInt(uval64, reg_info->byte_size)) { + error.SetErrorStringWithFormat( + "unsupported unsigned integer byte size: %u", byte_size); + break; + } + // TODO: Shouldn't we be setting m_type here? + break; -Error -RegisterValue::SetValueFromCString (const RegisterInfo *reg_info, const char *value_str) -{ - Error error; - if (reg_info == nullptr) - { - error.SetErrorString ("Invalid register info argument."); - return error; + case eEncodingSint: + if (byte_size > sizeof(long long)) { + error.SetErrorStringWithFormat("unsupported signed integer byte size: %u", + byte_size); + break; } - if (value_str == nullptr || value_str[0] == '\0') - { - error.SetErrorString ("Invalid c-string value string."); - return error; + if (value_str.getAsInteger(0, ival64)) { + error.SetErrorStringWithFormat( + "'%s' is not a valid signed integer string value", + value_str.str().c_str()); + break; } - bool success = false; - const uint32_t byte_size = reg_info->byte_size; - static float flt_val; - static double dbl_val; - static long double ldbl_val; - switch (reg_info->encoding) - { - case eEncodingInvalid: - error.SetErrorString ("Invalid encoding."); - break; - - case eEncodingUint: - if (byte_size <= sizeof (uint64_t)) - { - uint64_t uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success); - if (!success) - error.SetErrorStringWithFormat ("'%s' is not a valid unsigned integer string value", value_str); - else if (!Args::UInt64ValueIsValidForByteSize (uval64, byte_size)) - error.SetErrorStringWithFormat ("value 0x%" PRIx64 " is too large to fit in a %u byte unsigned integer value", uval64, byte_size); - else - { - if (!SetUInt (uval64, reg_info->byte_size)) - error.SetErrorStringWithFormat ("unsupported unsigned integer byte size: %u", byte_size); - } - } - else - { - error.SetErrorStringWithFormat ("unsupported unsigned integer byte size: %u", byte_size); - return error; - } - break; - - case eEncodingSint: - if (byte_size <= sizeof (long long)) - { - uint64_t sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success); - if (!success) - error.SetErrorStringWithFormat ("'%s' is not a valid signed integer string value", value_str); - else if (!Args::SInt64ValueIsValidForByteSize (sval64, byte_size)) - error.SetErrorStringWithFormat ("value 0x%" PRIx64 " is too large to fit in a %u byte signed integer value", sval64, byte_size); - else - { - if (!SetUInt (sval64, reg_info->byte_size)) - error.SetErrorStringWithFormat ("unsupported signed integer byte size: %u", byte_size); - } - } - else - { - error.SetErrorStringWithFormat ("unsupported signed integer byte size: %u", byte_size); - return error; - } - break; - - case eEncodingIEEE754: - if (byte_size == sizeof (float)) - { - if (::sscanf (value_str, "%f", &flt_val) == 1) - { - m_scalar = flt_val; - m_type = eTypeFloat; - } - else - error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str); - } - else if (byte_size == sizeof (double)) - { - if (::sscanf (value_str, "%lf", &dbl_val) == 1) - { - m_scalar = dbl_val; - m_type = eTypeDouble; - } - else - error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str); - } - else if (byte_size == sizeof (long double)) - { - if (::sscanf (value_str, "%Lf", &ldbl_val) == 1) - { - m_scalar = ldbl_val; - m_type = eTypeLongDouble; - } - else - error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str); - } - else - { - error.SetErrorStringWithFormat ("unsupported float byte size: %u", byte_size); - return error; - } - break; - - case eEncodingVector: - if (!ParseVectorEncoding(reg_info, value_str, byte_size, this)) - error.SetErrorString ("unrecognized vector encoding string value."); - break; + + if (!Args::SInt64ValueIsValidForByteSize(ival64, byte_size)) { + error.SetErrorStringWithFormat( + "value 0x%" PRIx64 + " is too large to fit in a %u byte signed integer value", + ival64, byte_size); + break; } - if (error.Fail()) - m_type = eTypeInvalid; - - return error; -} -bool -RegisterValue::SignExtend (uint32_t sign_bitpos) -{ - switch (m_type) - { - case eTypeInvalid: - break; - - case eTypeUInt8: - case eTypeUInt16: - case eTypeUInt32: - case eTypeUInt64: - case eTypeUInt128: - return m_scalar.SignExtend(sign_bitpos); - case eTypeFloat: - case eTypeDouble: - case eTypeLongDouble: - case eTypeBytes: - break; + if (!SetUInt(ival64, reg_info->byte_size)) { + error.SetErrorStringWithFormat("unsupported signed integer byte size: %u", + byte_size); + break; } - return false; -} -bool -RegisterValue::CopyValue (const RegisterValue &rhs) -{ - m_type = rhs.m_type; - switch (m_type) - { - case eTypeInvalid: - return false; - case eTypeUInt8: - case eTypeUInt16: - case eTypeUInt32: - case eTypeUInt64: - case eTypeUInt128: - case eTypeFloat: - case eTypeDouble: - case eTypeLongDouble: m_scalar = rhs.m_scalar; break; - case eTypeBytes: - assert (rhs.buffer.length <= kMaxRegisterByteSize); - ::memcpy (buffer.bytes, rhs.buffer.bytes, kMaxRegisterByteSize); - buffer.length = rhs.buffer.length; - buffer.byte_order = rhs.buffer.byte_order; - break; + // TODO: Shouldn't we be setting m_type here? + break; + + case eEncodingIEEE754: { + std::string value_string = value_str; + if (byte_size == sizeof(float)) { + if (::sscanf(value_string.c_str(), "%f", &flt_val) != 1) { + error.SetErrorStringWithFormat("'%s' is not a valid float string value", + value_string.c_str()); + break; + } + m_scalar = flt_val; + m_type = eTypeFloat; + } else if (byte_size == sizeof(double)) { + if (::sscanf(value_string.c_str(), "%lf", &dbl_val) != 1) { + error.SetErrorStringWithFormat("'%s' is not a valid float string value", + value_string.c_str()); + break; + } + m_scalar = dbl_val; + m_type = eTypeDouble; + } else if (byte_size == sizeof(long double)) { + if (::sscanf(value_string.c_str(), "%Lf", &ldbl_val) != 1) { + error.SetErrorStringWithFormat("'%s' is not a valid float string value", + value_string.c_str()); + break; + } + m_scalar = ldbl_val; + m_type = eTypeLongDouble; + } else { + error.SetErrorStringWithFormat("unsupported float byte size: %u", + byte_size); + return error; } - return true; + break; + } + case eEncodingVector: + if (!ParseVectorEncoding(reg_info, value_str, byte_size, this)) + error.SetErrorString("unrecognized vector encoding string value."); + break; + } + + return error; } -uint16_t -RegisterValue::GetAsUInt16 (uint16_t fail_value, bool *success_ptr) const -{ - if (success_ptr) - *success_ptr = true; - - switch (m_type) - { - default: break; - case eTypeUInt8: - case eTypeUInt16: return m_scalar.UShort(fail_value); - case eTypeBytes: - { - switch (buffer.length) - { - default: break; - case 1: - case 2: return *(const uint16_t *)buffer.bytes; - } - } - break; +bool RegisterValue::SignExtend(uint32_t sign_bitpos) { + switch (m_type) { + case eTypeInvalid: + break; + + case eTypeUInt8: + case eTypeUInt16: + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + return m_scalar.SignExtend(sign_bitpos); + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: + case eTypeBytes: + break; + } + return false; +} + +bool RegisterValue::CopyValue(const RegisterValue &rhs) { + m_type = rhs.m_type; + switch (m_type) { + case eTypeInvalid: + return false; + case eTypeUInt8: + case eTypeUInt16: + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: + m_scalar = rhs.m_scalar; + break; + case eTypeBytes: + assert(rhs.buffer.length <= kMaxRegisterByteSize); + ::memcpy(buffer.bytes, rhs.buffer.bytes, kMaxRegisterByteSize); + buffer.length = rhs.buffer.length; + buffer.byte_order = rhs.buffer.byte_order; + break; + } + return true; +} + +uint16_t RegisterValue::GetAsUInt16(uint16_t fail_value, + bool *success_ptr) const { + if (success_ptr) + *success_ptr = true; + + switch (m_type) { + default: + break; + case eTypeUInt8: + case eTypeUInt16: + return m_scalar.UShort(fail_value); + case eTypeBytes: { + switch (buffer.length) { + default: + break; + case 1: + case 2: + return *(const uint16_t *)buffer.bytes; } - if (success_ptr) - *success_ptr = false; - return fail_value; + } break; + } + if (success_ptr) + *success_ptr = false; + return fail_value; } -uint32_t -RegisterValue::GetAsUInt32 (uint32_t fail_value, bool *success_ptr) const -{ - if (success_ptr) - *success_ptr = true; - switch (m_type) - { - default: break; - case eTypeUInt8: - case eTypeUInt16: - case eTypeUInt32: - case eTypeFloat: - case eTypeDouble: - case eTypeLongDouble: return m_scalar.UInt(fail_value); - case eTypeBytes: - { - switch (buffer.length) - { - default: break; - case 1: - case 2: - case 4: return *(const uint32_t *)buffer.bytes; - } - } - break; +uint32_t RegisterValue::GetAsUInt32(uint32_t fail_value, + bool *success_ptr) const { + if (success_ptr) + *success_ptr = true; + switch (m_type) { + default: + break; + case eTypeUInt8: + case eTypeUInt16: + case eTypeUInt32: + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: + return m_scalar.UInt(fail_value); + case eTypeBytes: { + switch (buffer.length) { + default: + break; + case 1: + case 2: + case 4: + return *(const uint32_t *)buffer.bytes; } - if (success_ptr) - *success_ptr = false; - return fail_value; + } break; + } + if (success_ptr) + *success_ptr = false; + return fail_value; } -uint64_t -RegisterValue::GetAsUInt64 (uint64_t fail_value, bool *success_ptr) const -{ +uint64_t RegisterValue::GetAsUInt64(uint64_t fail_value, + bool *success_ptr) const { if (success_ptr) *success_ptr = true; switch (m_type) { @@ -685,353 +649,312 @@ RegisterValue::GetAsUInt64 (uint64_t fail_value, bool *success_ptr) const return fail_value; } -llvm::APInt -RegisterValue::GetAsUInt128 (const llvm::APInt& fail_value, bool *success_ptr) const -{ - if (success_ptr) - *success_ptr = true; - switch (m_type) - { - default: break; - case eTypeUInt8: - case eTypeUInt16: - case eTypeUInt32: - case eTypeUInt64: - case eTypeUInt128: - case eTypeFloat: - case eTypeDouble: - case eTypeLongDouble: return m_scalar.UInt128(fail_value); - case eTypeBytes: - { - switch (buffer.length) - { - default: - break; - case 1: - case 2: - case 4: - case 8: - case 16: - return llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((const type128 *)buffer.bytes)->x); - } - } - break; +llvm::APInt RegisterValue::GetAsUInt128(const llvm::APInt &fail_value, + bool *success_ptr) const { + if (success_ptr) + *success_ptr = true; + switch (m_type) { + default: + break; + case eTypeUInt8: + case eTypeUInt16: + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: + return m_scalar.UInt128(fail_value); + case eTypeBytes: { + switch (buffer.length) { + default: + break; + case 1: + case 2: + case 4: + case 8: + case 16: + return llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, + ((const type128 *)buffer.bytes)->x); } - if (success_ptr) - *success_ptr = false; - return fail_value; + } break; + } + if (success_ptr) + *success_ptr = false; + return fail_value; } -float -RegisterValue::GetAsFloat (float fail_value, bool *success_ptr) const -{ - if (success_ptr) - *success_ptr = true; - switch (m_type) - { - default: break; - case eTypeUInt32: - case eTypeUInt64: - case eTypeUInt128: - case eTypeFloat: - case eTypeDouble: - case eTypeLongDouble: - return m_scalar.Float(fail_value); - } - if (success_ptr) - *success_ptr = false; - return fail_value; +float RegisterValue::GetAsFloat(float fail_value, bool *success_ptr) const { + if (success_ptr) + *success_ptr = true; + switch (m_type) { + default: + break; + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: + return m_scalar.Float(fail_value); + } + if (success_ptr) + *success_ptr = false; + return fail_value; } -double -RegisterValue::GetAsDouble (double fail_value, bool *success_ptr) const -{ - if (success_ptr) - *success_ptr = true; - switch (m_type) - { - default: - break; - - case eTypeUInt32: - case eTypeUInt64: - case eTypeUInt128: - case eTypeFloat: - case eTypeDouble: - case eTypeLongDouble: - return m_scalar.Double(fail_value); - } - if (success_ptr) - *success_ptr = false; - return fail_value; +double RegisterValue::GetAsDouble(double fail_value, bool *success_ptr) const { + if (success_ptr) + *success_ptr = true; + switch (m_type) { + default: + break; + + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: + return m_scalar.Double(fail_value); + } + if (success_ptr) + *success_ptr = false; + return fail_value; } -long double -RegisterValue::GetAsLongDouble (long double fail_value, bool *success_ptr) const -{ - if (success_ptr) - *success_ptr = true; - switch (m_type) - { - default: - break; - - case eTypeUInt32: - case eTypeUInt64: - case eTypeUInt128: - case eTypeFloat: - case eTypeDouble: - case eTypeLongDouble: - return m_scalar.LongDouble(); - } - if (success_ptr) - *success_ptr = false; - return fail_value; +long double RegisterValue::GetAsLongDouble(long double fail_value, + bool *success_ptr) const { + if (success_ptr) + *success_ptr = true; + switch (m_type) { + default: + break; + + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: + return m_scalar.LongDouble(); + } + if (success_ptr) + *success_ptr = false; + return fail_value; } -const void * -RegisterValue::GetBytes () const -{ - switch (m_type) - { - case eTypeInvalid: break; - case eTypeUInt8: - case eTypeUInt16: - case eTypeUInt32: - case eTypeUInt64: - case eTypeUInt128: - case eTypeFloat: - case eTypeDouble: - case eTypeLongDouble: return m_scalar.GetBytes(); - case eTypeBytes: return buffer.bytes; - } - return nullptr; +const void *RegisterValue::GetBytes() const { + switch (m_type) { + case eTypeInvalid: + break; + case eTypeUInt8: + case eTypeUInt16: + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: + return m_scalar.GetBytes(); + case eTypeBytes: + return buffer.bytes; + } + return nullptr; } -uint32_t -RegisterValue::GetByteSize () const -{ - switch (m_type) - { - case eTypeInvalid: break; - case eTypeUInt8: return 1; - case eTypeUInt16: return 2; - case eTypeUInt32: - case eTypeUInt64: - case eTypeUInt128: - case eTypeFloat: - case eTypeDouble: - case eTypeLongDouble: return m_scalar.GetByteSize(); - case eTypeBytes: return buffer.length; - } - return 0; +uint32_t RegisterValue::GetByteSize() const { + switch (m_type) { + case eTypeInvalid: + break; + case eTypeUInt8: + return 1; + case eTypeUInt16: + return 2; + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: + return m_scalar.GetByteSize(); + case eTypeBytes: + return buffer.length; + } + return 0; } -bool -RegisterValue::SetUInt (uint64_t uint, uint32_t byte_size) -{ - if (byte_size == 0) - { - SetUInt64 (uint); - } - else if (byte_size == 1) - { - SetUInt8 (uint); - } - else if (byte_size <= 2) - { - SetUInt16 (uint); - } - else if (byte_size <= 4) - { - SetUInt32 (uint); - } - else if (byte_size <= 8) - { - SetUInt64 (uint); - } - else if (byte_size <= 16) - { - SetUInt128 (llvm::APInt(128, uint)); - } - else - return false; - return true; +bool RegisterValue::SetUInt(uint64_t uint, uint32_t byte_size) { + if (byte_size == 0) { + SetUInt64(uint); + } else if (byte_size == 1) { + SetUInt8(uint); + } else if (byte_size <= 2) { + SetUInt16(uint); + } else if (byte_size <= 4) { + SetUInt32(uint); + } else if (byte_size <= 8) { + SetUInt64(uint); + } else if (byte_size <= 16) { + SetUInt128(llvm::APInt(128, uint)); + } else + return false; + return true; } -void -RegisterValue::SetBytes (const void *bytes, size_t length, lldb::ByteOrder byte_order) -{ - // If this assertion fires off we need to increase the size of - // buffer.bytes, or make it something that is allocated on - // the heap. Since the data buffer is in a union, we can't make it - // a collection class like SmallVector... - if (bytes && length > 0) - { - assert (length <= sizeof (buffer.bytes) && "Storing too many bytes in a RegisterValue."); - m_type = eTypeBytes; - buffer.length = length; - memcpy (buffer.bytes, bytes, length); - buffer.byte_order = byte_order; - } - else - { - m_type = eTypeInvalid; - buffer.length = 0; - } +void RegisterValue::SetBytes(const void *bytes, size_t length, + lldb::ByteOrder byte_order) { + // If this assertion fires off we need to increase the size of + // buffer.bytes, or make it something that is allocated on + // the heap. Since the data buffer is in a union, we can't make it + // a collection class like SmallVector... + if (bytes && length > 0) { + assert(length <= sizeof(buffer.bytes) && + "Storing too many bytes in a RegisterValue."); + m_type = eTypeBytes; + buffer.length = length; + memcpy(buffer.bytes, bytes, length); + buffer.byte_order = byte_order; + } else { + m_type = eTypeInvalid; + buffer.length = 0; + } } -bool -RegisterValue::operator == (const RegisterValue &rhs) const -{ - if (m_type == rhs.m_type) - { - switch (m_type) - { - case eTypeInvalid: return true; - case eTypeUInt8: - case eTypeUInt16: - case eTypeUInt32: - case eTypeUInt64: - case eTypeUInt128: - case eTypeFloat: - case eTypeDouble: - case eTypeLongDouble: return m_scalar == rhs.m_scalar; - case eTypeBytes: - if (buffer.length != rhs.buffer.length) - return false; - else - { - uint8_t length = buffer.length; - if (length > kMaxRegisterByteSize) - length = kMaxRegisterByteSize; - return memcmp (buffer.bytes, rhs.buffer.bytes, length) == 0; - } - break; - } +bool RegisterValue::operator==(const RegisterValue &rhs) const { + if (m_type == rhs.m_type) { + switch (m_type) { + case eTypeInvalid: + return true; + case eTypeUInt8: + case eTypeUInt16: + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: + return m_scalar == rhs.m_scalar; + case eTypeBytes: + if (buffer.length != rhs.buffer.length) + return false; + else { + uint8_t length = buffer.length; + if (length > kMaxRegisterByteSize) + length = kMaxRegisterByteSize; + return memcmp(buffer.bytes, rhs.buffer.bytes, length) == 0; + } + break; } + } + return false; +} + +bool RegisterValue::operator!=(const RegisterValue &rhs) const { + if (m_type != rhs.m_type) + return true; + switch (m_type) { + case eTypeInvalid: return false; + case eTypeUInt8: + case eTypeUInt16: + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: + return m_scalar != rhs.m_scalar; + case eTypeBytes: + if (buffer.length != rhs.buffer.length) { + return true; + } else { + uint8_t length = buffer.length; + if (length > kMaxRegisterByteSize) + length = kMaxRegisterByteSize; + return memcmp(buffer.bytes, rhs.buffer.bytes, length) != 0; + } + break; + } + return true; } -bool -RegisterValue::operator != (const RegisterValue &rhs) const -{ - if (m_type != rhs.m_type) +bool RegisterValue::ClearBit(uint32_t bit) { + switch (m_type) { + case eTypeInvalid: + break; + + case eTypeUInt8: + case eTypeUInt16: + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + if (bit < (GetByteSize() * 8)) { + return m_scalar.ClearBit(bit); + } + break; + + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: + break; + + case eTypeBytes: + if (buffer.byte_order == eByteOrderBig || + buffer.byte_order == eByteOrderLittle) { + uint32_t byte_idx; + if (buffer.byte_order == eByteOrderBig) + byte_idx = buffer.length - (bit / 8) - 1; + else + byte_idx = bit / 8; + + const uint32_t byte_bit = bit % 8; + if (byte_idx < buffer.length) { + buffer.bytes[byte_idx] &= ~(1u << byte_bit); return true; - switch (m_type) - { - case eTypeInvalid: return false; - case eTypeUInt8: - case eTypeUInt16: - case eTypeUInt32: - case eTypeUInt64: - case eTypeUInt128: - case eTypeFloat: - case eTypeDouble: - case eTypeLongDouble: return m_scalar != rhs.m_scalar; - case eTypeBytes: - if (buffer.length != rhs.buffer.length) - { - return true; - } - else - { - uint8_t length = buffer.length; - if (length > kMaxRegisterByteSize) - length = kMaxRegisterByteSize; - return memcmp (buffer.bytes, rhs.buffer.bytes, length) != 0; - } - break; + } } - return true; + break; + } + return false; } -bool -RegisterValue::ClearBit (uint32_t bit) -{ - switch (m_type) - { - case eTypeInvalid: - break; - - case eTypeUInt8: - case eTypeUInt16: - case eTypeUInt32: - case eTypeUInt64: - case eTypeUInt128: - if (bit < (GetByteSize() * 8)) - { - return m_scalar.ClearBit(bit); - } - break; - - case eTypeFloat: - case eTypeDouble: - case eTypeLongDouble: - break; - - case eTypeBytes: - if (buffer.byte_order == eByteOrderBig || buffer.byte_order == eByteOrderLittle) - { - uint32_t byte_idx; - if (buffer.byte_order == eByteOrderBig) - byte_idx = buffer.length - (bit / 8) - 1; - else - byte_idx = bit / 8; - - const uint32_t byte_bit = bit % 8; - if (byte_idx < buffer.length) - { - buffer.bytes[byte_idx] &= ~(1u << byte_bit); - return true; - } - } - break; +bool RegisterValue::SetBit(uint32_t bit) { + switch (m_type) { + case eTypeInvalid: + break; + + case eTypeUInt8: + case eTypeUInt16: + case eTypeUInt32: + case eTypeUInt64: + case eTypeUInt128: + if (bit < (GetByteSize() * 8)) { + return m_scalar.SetBit(bit); } - return false; -} + break; -bool -RegisterValue::SetBit (uint32_t bit) -{ - switch (m_type) - { - case eTypeInvalid: - break; - - case eTypeUInt8: - case eTypeUInt16: - case eTypeUInt32: - case eTypeUInt64: - case eTypeUInt128: - if (bit < (GetByteSize() * 8)) - { - return m_scalar.SetBit(bit); - } - break; - - case eTypeFloat: - case eTypeDouble: - case eTypeLongDouble: - break; - - case eTypeBytes: - if (buffer.byte_order == eByteOrderBig || buffer.byte_order == eByteOrderLittle) - { - uint32_t byte_idx; - if (buffer.byte_order == eByteOrderBig) - byte_idx = buffer.length - (bit / 8) - 1; - else - byte_idx = bit / 8; - - const uint32_t byte_bit = bit % 8; - if (byte_idx < buffer.length) - { - buffer.bytes[byte_idx] |= (1u << byte_bit); - return true; - } - } - break; + case eTypeFloat: + case eTypeDouble: + case eTypeLongDouble: + break; + + case eTypeBytes: + if (buffer.byte_order == eByteOrderBig || + buffer.byte_order == eByteOrderLittle) { + uint32_t byte_idx; + if (buffer.byte_order == eByteOrderBig) + byte_idx = buffer.length - (bit / 8) - 1; + else + byte_idx = bit / 8; + + const uint32_t byte_bit = bit % 8; + if (byte_idx < buffer.length) { + buffer.bytes[byte_idx] |= (1u << byte_bit); + return true; + } } - return false; + break; + } + return false; } diff --git a/source/Core/RegularExpression.cpp b/source/Core/RegularExpression.cpp index bdef3ced94d4..54e0231556db 100644 --- a/source/Core/RegularExpression.cpp +++ b/source/Core/RegularExpression.cpp @@ -25,46 +25,37 @@ // everywhere. //---------------------------------------------------------------------- #if defined(REG_ENHANCED) -#define DEFAULT_COMPILE_FLAGS (REG_ENHANCED|REG_EXTENDED) +#define DEFAULT_COMPILE_FLAGS (REG_ENHANCED | REG_EXTENDED) #else #define DEFAULT_COMPILE_FLAGS (REG_EXTENDED) #endif using namespace lldb_private; -RegularExpression::RegularExpression() : - m_re(), - m_comp_err (1), - m_preg() -{ - memset(&m_preg, 0, sizeof(m_preg)); +RegularExpression::RegularExpression() : m_re(), m_comp_err(1), m_preg() { + memset(&m_preg, 0, sizeof(m_preg)); } //---------------------------------------------------------------------- // Constructor that compiles "re" using "flags" and stores the // resulting compiled regular expression into this object. //---------------------------------------------------------------------- -RegularExpression::RegularExpression(const char* re) : - m_re(), - m_comp_err (1), - m_preg() -{ - memset(&m_preg,0,sizeof(m_preg)); - Compile(re); +RegularExpression::RegularExpression(llvm::StringRef str) + : m_re(), m_comp_err(1), m_preg() { + memset(&m_preg, 0, sizeof(m_preg)); + Compile(str); } -RegularExpression::RegularExpression(const RegularExpression &rhs) -{ - memset(&m_preg,0,sizeof(m_preg)); - Compile(rhs.GetText()); +RegularExpression::RegularExpression(const RegularExpression &rhs) { + memset(&m_preg, 0, sizeof(m_preg)); + Compile(rhs.GetText()); } -const RegularExpression & -RegularExpression::operator= (const RegularExpression &rhs) -{ - if (&rhs != this) - Compile (rhs.GetText()); - return *this; +const RegularExpression &RegularExpression:: +operator=(const RegularExpression &rhs) { + if (&rhs != this) + Compile(rhs.GetText()); + return *this; } //---------------------------------------------------------------------- @@ -73,10 +64,7 @@ RegularExpression::operator= (const RegularExpression &rhs) // Any previously compiled regular expression contained in this // object will be freed. //---------------------------------------------------------------------- -RegularExpression::~RegularExpression() -{ - Free(); -} +RegularExpression::~RegularExpression() { Free(); } //---------------------------------------------------------------------- // Compile a regular expression using the supplied regular @@ -90,23 +78,18 @@ RegularExpression::~RegularExpression() // True if the regular expression compiles successfully, false // otherwise. //---------------------------------------------------------------------- -bool -RegularExpression::Compile(const char* re) -{ - Free(); - - if (re && re[0]) - { - m_re = re; - m_comp_err = ::regcomp (&m_preg, re, DEFAULT_COMPILE_FLAGS); - } - else - { - // No valid regular expression - m_comp_err = 1; - } - - return m_comp_err == 0; +bool RegularExpression::Compile(llvm::StringRef str) { + Free(); + + if (!str.empty()) { + m_re = str; + m_comp_err = ::regcomp(&m_preg, m_re.c_str(), DEFAULT_COMPILE_FLAGS); + } else { + // No valid regular expression + m_comp_err = 1; + } + + return m_comp_err == 0; } //---------------------------------------------------------------------- @@ -117,145 +100,109 @@ RegularExpression::Compile(const char* re) // values that are present in "match_ptr". The regular expression // will be executed using the "execute_flags". //--------------------------------------------------------------------- -bool -RegularExpression::Execute (const char* s, Match *match) const -{ - int err = 1; - if (s != nullptr && m_comp_err == 0) - { - if (match) - { - err = ::regexec (&m_preg, - s, - match->GetSize(), - match->GetData(), - 0); - } - else - { - err = ::regexec(&m_preg, - s, - 0, - nullptr, - 0); - } - } - - if (err != 0) - { - // The regular expression didn't compile, so clear the matches - if (match) - match->Clear(); - return false; +bool RegularExpression::Execute(llvm::StringRef str, Match *match) const { + int err = 1; + if (m_comp_err == 0) { + // Argument to regexec must be null-terminated. + std::string reg_str = str; + if (match) { + err = ::regexec(&m_preg, reg_str.c_str(), match->GetSize(), + match->GetData(), 0); + } else { + err = ::regexec(&m_preg, reg_str.c_str(), 0, nullptr, 0); } - return true; -} + } -bool -RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, std::string& match_str) const -{ - llvm::StringRef match_str_ref; - if (GetMatchAtIndex(s, idx, match_str_ref)) - { - match_str = match_str_ref.str(); - return true; - } + if (err != 0) { + // The regular expression didn't compile, so clear the matches + if (match) + match->Clear(); return false; + } + return true; } -bool -RegularExpression::Match::GetMatchAtIndex (const char* s, uint32_t idx, llvm::StringRef& match_str) const -{ - if (idx < m_matches.size()) - { - if (m_matches[idx].rm_eo == -1 && m_matches[idx].rm_so == -1) - return false; +bool RegularExpression::Match::GetMatchAtIndex(llvm::StringRef s, uint32_t idx, + std::string &match_str) const { + llvm::StringRef match_str_ref; + if (GetMatchAtIndex(s, idx, match_str_ref)) { + match_str = match_str_ref.str(); + return true; + } + return false; +} - if (m_matches[idx].rm_eo == m_matches[idx].rm_so) - { - // Matched the empty string... - match_str = llvm::StringRef(); - return true; - } - else if (m_matches[idx].rm_eo > m_matches[idx].rm_so) - { - match_str = llvm::StringRef (s + m_matches[idx].rm_so, m_matches[idx].rm_eo - m_matches[idx].rm_so); - return true; - } +bool RegularExpression::Match::GetMatchAtIndex( + llvm::StringRef s, uint32_t idx, llvm::StringRef &match_str) const { + if (idx < m_matches.size()) { + if (m_matches[idx].rm_eo == -1 && m_matches[idx].rm_so == -1) + return false; + + if (m_matches[idx].rm_eo == m_matches[idx].rm_so) { + // Matched the empty string... + match_str = llvm::StringRef(); + return true; + } else if (m_matches[idx].rm_eo > m_matches[idx].rm_so) { + match_str = s.substr(m_matches[idx].rm_so, + m_matches[idx].rm_eo - m_matches[idx].rm_so); + return true; } - return false; + } + return false; } -bool -RegularExpression::Match::GetMatchSpanningIndices (const char* s, uint32_t idx1, uint32_t idx2, llvm::StringRef& match_str) const -{ - if (idx1 < m_matches.size() && idx2 < m_matches.size()) - { - if (m_matches[idx1].rm_so == m_matches[idx2].rm_eo) - { - // Matched the empty string... - match_str = llvm::StringRef(); - return true; - } - else if (m_matches[idx1].rm_so < m_matches[idx2].rm_eo) - { - match_str = llvm::StringRef (s + m_matches[idx1].rm_so, m_matches[idx2].rm_eo - m_matches[idx1].rm_so); - return true; - } +bool RegularExpression::Match::GetMatchSpanningIndices( + llvm::StringRef s, uint32_t idx1, uint32_t idx2, + llvm::StringRef &match_str) const { + if (idx1 < m_matches.size() && idx2 < m_matches.size()) { + if (m_matches[idx1].rm_so == m_matches[idx2].rm_eo) { + // Matched the empty string... + match_str = llvm::StringRef(); + return true; + } else if (m_matches[idx1].rm_so < m_matches[idx2].rm_eo) { + match_str = s.substr(m_matches[idx1].rm_so, + m_matches[idx2].rm_eo - m_matches[idx1].rm_so); + return true; } - return false; + } + return false; } //---------------------------------------------------------------------- // Returns true if the regular expression compiled and is ready // for execution. //---------------------------------------------------------------------- -bool -RegularExpression::IsValid () const -{ - return m_comp_err == 0; -} +bool RegularExpression::IsValid() const { return m_comp_err == 0; } //---------------------------------------------------------------------- // Returns the text that was used to compile the current regular // expression. //---------------------------------------------------------------------- -const char* -RegularExpression::GetText () const -{ - return (m_re.empty() ? nullptr : m_re.c_str()); -} +llvm::StringRef RegularExpression::GetText() const { return m_re; } //---------------------------------------------------------------------- // Free any contained compiled regular expressions. //---------------------------------------------------------------------- -void -RegularExpression::Free() -{ - if (m_comp_err == 0) - { - m_re.clear(); - regfree(&m_preg); - // Set a compile error since we no longer have a valid regex - m_comp_err = 1; - } +void RegularExpression::Free() { + if (m_comp_err == 0) { + m_re.clear(); + regfree(&m_preg); + // Set a compile error since we no longer have a valid regex + m_comp_err = 1; + } } -size_t -RegularExpression::GetErrorAsCString (char *err_str, size_t err_str_max_len) const -{ - if (m_comp_err == 0) - { - if (err_str && err_str_max_len) - *err_str = '\0'; - return 0; - } - - return ::regerror (m_comp_err, &m_preg, err_str, err_str_max_len); +size_t RegularExpression::GetErrorAsCString(char *err_str, + size_t err_str_max_len) const { + if (m_comp_err == 0) { + if (err_str && err_str_max_len) + *err_str = '\0'; + return 0; + } + + return ::regerror(m_comp_err, &m_preg, err_str, err_str_max_len); } -bool -RegularExpression::operator < (const RegularExpression& rhs) const -{ - return (m_re < rhs.m_re); +bool RegularExpression::operator<(const RegularExpression &rhs) const { + return (m_re < rhs.m_re); } diff --git a/source/Core/Scalar.cpp b/source/Core/Scalar.cpp index d3e9a7565046..2b99ec17b0a0 100644 --- a/source/Core/Scalar.cpp +++ b/source/Core/Scalar.cpp @@ -19,12 +19,12 @@ #include "llvm/ADT/SmallString.h" // Project includes -#include "lldb/Interpreter/Args.h" +#include "lldb/Core/DataExtractor.h" #include "lldb/Core/Error.h" #include "lldb/Core/Stream.h" -#include "lldb/Core/DataExtractor.h" #include "lldb/Host/Endian.h" #include "lldb/Host/StringConvert.h" +#include "lldb/Interpreter/Args.h" #include "Plugins/Process/Utility/InstructionUtils.h" @@ -35,63 +35,57 @@ using namespace lldb_private; // Promote to max type currently follows the ANSI C rule for type // promotion in expressions. //---------------------------------------------------------------------- -static Scalar::Type -PromoteToMaxType -( - const Scalar& lhs, // The const left hand side object - const Scalar& rhs, // The const right hand side object - Scalar& temp_value, // A modifiable temp value than can be used to hold either the promoted lhs or rhs object - const Scalar* &promoted_lhs_ptr, // Pointer to the resulting possibly promoted value of lhs (at most one of lhs/rhs will get promoted) - const Scalar* &promoted_rhs_ptr // Pointer to the resulting possibly promoted value of rhs (at most one of lhs/rhs will get promoted) -) -{ - Scalar result; - // Initialize the promoted values for both the right and left hand side values - // to be the objects themselves. If no promotion is needed (both right and left - // have the same type), then the temp_value will not get used. - promoted_lhs_ptr = &lhs; - promoted_rhs_ptr = &rhs; - // Extract the types of both the right and left hand side values - Scalar::Type lhs_type = lhs.GetType(); - Scalar::Type rhs_type = rhs.GetType(); - - if (lhs_type > rhs_type) - { - // Right hand side need to be promoted - temp_value = rhs; // Copy right hand side into the temp value - if (temp_value.Promote(lhs_type)) // Promote it - promoted_rhs_ptr = &temp_value; // Update the pointer for the promoted right hand side - } - else if (lhs_type < rhs_type) - { - // Left hand side need to be promoted - temp_value = lhs; // Copy left hand side value into the temp value - if (temp_value.Promote(rhs_type)) // Promote it - promoted_lhs_ptr = &temp_value; // Update the pointer for the promoted left hand side - } - - // Make sure our type promotion worked as expected - if (promoted_lhs_ptr->GetType() == promoted_rhs_ptr->GetType()) - return promoted_lhs_ptr->GetType(); // Return the resulting max type - - // Return the void type (zero) if we fail to promote either of the values. - return Scalar::e_void; -} - -Scalar::Scalar() : - m_type(e_void), - m_float((float)0) -{ -} - -Scalar::Scalar(const Scalar& rhs) : - m_type(rhs.m_type), - m_integer(rhs.m_integer), - m_float(rhs.m_float) -{ -} - -//Scalar::Scalar(const RegisterValue& reg) : +static Scalar::Type PromoteToMaxType( + const Scalar &lhs, // The const left hand side object + const Scalar &rhs, // The const right hand side object + Scalar &temp_value, // A modifiable temp value than can be used to hold + // either the promoted lhs or rhs object + const Scalar *&promoted_lhs_ptr, // Pointer to the resulting possibly + // promoted value of lhs (at most one of + // lhs/rhs will get promoted) + const Scalar *&promoted_rhs_ptr // Pointer to the resulting possibly + // promoted value of rhs (at most one of + // lhs/rhs will get promoted) + ) { + Scalar result; + // Initialize the promoted values for both the right and left hand side values + // to be the objects themselves. If no promotion is needed (both right and + // left + // have the same type), then the temp_value will not get used. + promoted_lhs_ptr = &lhs; + promoted_rhs_ptr = &rhs; + // Extract the types of both the right and left hand side values + Scalar::Type lhs_type = lhs.GetType(); + Scalar::Type rhs_type = rhs.GetType(); + + if (lhs_type > rhs_type) { + // Right hand side need to be promoted + temp_value = rhs; // Copy right hand side into the temp value + if (temp_value.Promote(lhs_type)) // Promote it + promoted_rhs_ptr = + &temp_value; // Update the pointer for the promoted right hand side + } else if (lhs_type < rhs_type) { + // Left hand side need to be promoted + temp_value = lhs; // Copy left hand side value into the temp value + if (temp_value.Promote(rhs_type)) // Promote it + promoted_lhs_ptr = + &temp_value; // Update the pointer for the promoted left hand side + } + + // Make sure our type promotion worked as expected + if (promoted_lhs_ptr->GetType() == promoted_rhs_ptr->GetType()) + return promoted_lhs_ptr->GetType(); // Return the resulting max type + + // Return the void type (zero) if we fail to promote either of the values. + return Scalar::e_void; +} + +Scalar::Scalar() : m_type(e_void), m_float((float)0) {} + +Scalar::Scalar(const Scalar &rhs) + : m_type(rhs.m_type), m_integer(rhs.m_integer), m_float(rhs.m_float) {} + +// Scalar::Scalar(const RegisterValue& reg) : // m_type(e_void), // m_data() //{ @@ -103,7 +97,8 @@ Scalar::Scalar(const Scalar& rhs) : // case 1: m_type = e_uint; m_data.uint = reg.value.uint8; break; // case 2: m_type = e_uint; m_data.uint = reg.value.uint16; break; // case 4: m_type = e_uint; m_data.uint = reg.value.uint32; break; -// case 8: m_type = e_ulonglong; m_data.ulonglong = reg.value.uint64; break; +// case 8: m_type = e_ulonglong; m_data.ulonglong = reg.value.uint64; +// break; // break; // } // break; @@ -114,7 +109,8 @@ Scalar::Scalar(const Scalar& rhs) : // case 1: m_type = e_sint; m_data.sint = reg.value.sint8; break; // case 2: m_type = e_sint; m_data.sint = reg.value.sint16; break; // case 4: m_type = e_sint; m_data.sint = reg.value.sint32; break; -// case 8: m_type = e_slonglong; m_data.slonglong = reg.value.sint64; break; +// case 8: m_type = e_slonglong; m_data.slonglong = reg.value.sint64; +// break; // break; // } // break; @@ -132,1385 +128,702 @@ Scalar::Scalar(const Scalar& rhs) : // } //} -bool -Scalar::GetData (DataExtractor &data, size_t limit_byte_size) const -{ - size_t byte_size = GetByteSize(); - if (byte_size > 0) - { - const uint8_t *bytes = reinterpret_cast<const uint8_t *>(GetBytes()); - - if (limit_byte_size < byte_size) - { - if (endian::InlHostByteOrder() == eByteOrderLittle) - { - // On little endian systems if we want fewer bytes from the - // current type we just specify fewer bytes since the LSByte - // is first... - byte_size = limit_byte_size; - } - else if (endian::InlHostByteOrder() == eByteOrderBig) - { - // On big endian systems if we want fewer bytes from the - // current type have to advance our initial byte pointer and - // trim down the number of bytes since the MSByte is first - bytes += byte_size - limit_byte_size; - byte_size = limit_byte_size; - } - } - - data.SetData(bytes, byte_size, endian::InlHostByteOrder()); - return true; - } - data.Clear(); - return false; -} - -const void * -Scalar::GetBytes() const -{ - const uint64_t *apint_words; - const uint8_t *bytes; - static float_t flt_val; - static double_t dbl_val; - static uint64_t swapped_words[4]; - switch (m_type) - { - case e_void: - break; - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - bytes = reinterpret_cast<const uint8_t *>(m_integer.getRawData()); - // getRawData always returns a pointer to an uint64_t. If we have a smaller type, - // we need to update the pointer on big-endian systems. - if (endian::InlHostByteOrder() == eByteOrderBig) - { - size_t byte_size = m_integer.getBitWidth() / 8; - if (byte_size < 8) - bytes += 8 - byte_size; - } - return bytes; - case e_sint128: - case e_uint128: - apint_words = m_integer.getRawData(); - // getRawData always returns a pointer to an array of two uint64_t values, - // where the least-significant word always comes first. On big-endian - // systems we need to swap the two words. - if (endian::InlHostByteOrder() == eByteOrderBig) - { - swapped_words[0] = apint_words[1]; - swapped_words[1] = apint_words[0]; - apint_words = swapped_words; - } - return reinterpret_cast<const void *>(apint_words); - case e_sint256: - case e_uint256: - apint_words = m_integer.getRawData(); - // getRawData always returns a pointer to an array of four uint64_t values, - // where the least-significant word always comes first. On big-endian - // systems we need to swap the four words. - if (endian::InlHostByteOrder() == eByteOrderBig) - { - swapped_words[0] = apint_words[3]; - swapped_words[1] = apint_words[2]; - swapped_words[2] = apint_words[1]; - swapped_words[3] = apint_words[0]; - apint_words = swapped_words; - } - return reinterpret_cast<const void *>(apint_words); - case e_float: - flt_val = m_float.convertToFloat(); - return reinterpret_cast<const void *>(&flt_val); - case e_double: - dbl_val = m_float.convertToDouble(); - return reinterpret_cast<const void *>(&dbl_val); - case e_long_double: - llvm::APInt ldbl_val = m_float.bitcastToAPInt(); - apint_words = ldbl_val.getRawData(); - // getRawData always returns a pointer to an array of two uint64_t values, - // where the least-significant word always comes first. On big-endian - // systems we need to swap the two words. - if (endian::InlHostByteOrder() == eByteOrderBig) - { - swapped_words[0] = apint_words[1]; - swapped_words[1] = apint_words[0]; - apint_words = swapped_words; - } - return reinterpret_cast<const void *>(apint_words); - } - return nullptr; -} - -size_t -Scalar::GetByteSize() const -{ - switch (m_type) - { - case e_void: - break; - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: - case e_uint256: - return (m_integer.getBitWidth() / 8); - case e_float: return sizeof(float_t); - case e_double: return sizeof(double_t); - case e_long_double: return sizeof(long_double_t); +bool Scalar::GetData(DataExtractor &data, size_t limit_byte_size) const { + size_t byte_size = GetByteSize(); + if (byte_size > 0) { + const uint8_t *bytes = reinterpret_cast<const uint8_t *>(GetBytes()); + + if (limit_byte_size < byte_size) { + if (endian::InlHostByteOrder() == eByteOrderLittle) { + // On little endian systems if we want fewer bytes from the + // current type we just specify fewer bytes since the LSByte + // is first... + byte_size = limit_byte_size; + } else if (endian::InlHostByteOrder() == eByteOrderBig) { + // On big endian systems if we want fewer bytes from the + // current type have to advance our initial byte pointer and + // trim down the number of bytes since the MSByte is first + bytes += byte_size - limit_byte_size; + byte_size = limit_byte_size; + } } - return 0; -} -bool -Scalar::IsZero() const -{ - llvm::APInt zero_int = llvm::APInt::getNullValue(m_integer.getBitWidth() / 8); - switch (m_type) - { - case e_void: - break; - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: - case e_uint256: - return llvm::APInt::isSameValue(zero_int, m_integer); - case e_float: - case e_double: - case e_long_double: - return m_float.isZero(); + data.SetData(bytes, byte_size, endian::InlHostByteOrder()); + return true; + } + data.Clear(); + return false; +} + +const void *Scalar::GetBytes() const { + const uint64_t *apint_words; + const uint8_t *bytes; + static float_t flt_val; + static double_t dbl_val; + static uint64_t swapped_words[4]; + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + bytes = reinterpret_cast<const uint8_t *>(m_integer.getRawData()); + // getRawData always returns a pointer to an uint64_t. If we have a smaller + // type, + // we need to update the pointer on big-endian systems. + if (endian::InlHostByteOrder() == eByteOrderBig) { + size_t byte_size = m_integer.getBitWidth() / 8; + if (byte_size < 8) + bytes += 8 - byte_size; } - return false; -} - -void -Scalar::GetValue (Stream *s, bool show_type) const -{ - if (show_type) - s->Printf("(%s) ", GetTypeAsCString()); - - switch (m_type) - { - case e_void: - break; - case e_sint: - case e_ulong: - case e_slonglong: - case e_sint128: - case e_sint256: - s->Printf("%s",m_integer.toString(10,true).c_str()); - break; - case e_uint: - case e_slong: - case e_ulonglong: - case e_uint128: - case e_uint256: - s->Printf("%s",m_integer.toString(16,false).c_str()); - break; - case e_float: - case e_double: - case e_long_double: - llvm::SmallString<24> string; - m_float.toString(string); - s->Printf("%s", string.c_str()); - break; + return bytes; + case e_sint128: + case e_uint128: + apint_words = m_integer.getRawData(); + // getRawData always returns a pointer to an array of two uint64_t values, + // where the least-significant word always comes first. On big-endian + // systems we need to swap the two words. + if (endian::InlHostByteOrder() == eByteOrderBig) { + swapped_words[0] = apint_words[1]; + swapped_words[1] = apint_words[0]; + apint_words = swapped_words; } -} - -const char * -Scalar::GetTypeAsCString() const -{ - switch (m_type) - { - case e_void: return "void"; - case e_sint: return "int"; - case e_uint: return "unsigned int"; - case e_slong: return "long"; - case e_ulong: return "unsigned long"; - case e_slonglong: return "long long"; - case e_ulonglong: return "unsigned long long"; - case e_sint128: return "int128_t"; - case e_uint128: return "unsigned int128_t"; - case e_sint256: return "int256_t"; - case e_uint256: return "unsigned int256_t"; - case e_float: return "float"; - case e_double: return "double"; - case e_long_double: return "long double"; + return reinterpret_cast<const void *>(apint_words); + case e_sint256: + case e_uint256: + apint_words = m_integer.getRawData(); + // getRawData always returns a pointer to an array of four uint64_t values, + // where the least-significant word always comes first. On big-endian + // systems we need to swap the four words. + if (endian::InlHostByteOrder() == eByteOrderBig) { + swapped_words[0] = apint_words[3]; + swapped_words[1] = apint_words[2]; + swapped_words[2] = apint_words[1]; + swapped_words[3] = apint_words[0]; + apint_words = swapped_words; } - return "<invalid Scalar type>"; -} - -Scalar& -Scalar::operator=(const Scalar& rhs) -{ - if (this != &rhs) - { - m_type = rhs.m_type; - m_integer = llvm::APInt(rhs.m_integer); - m_float = rhs.m_float; + return reinterpret_cast<const void *>(apint_words); + case e_float: + flt_val = m_float.convertToFloat(); + return reinterpret_cast<const void *>(&flt_val); + case e_double: + dbl_val = m_float.convertToDouble(); + return reinterpret_cast<const void *>(&dbl_val); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + apint_words = ldbl_val.getRawData(); + // getRawData always returns a pointer to an array of two uint64_t values, + // where the least-significant word always comes first. On big-endian + // systems we need to swap the two words. + if (endian::InlHostByteOrder() == eByteOrderBig) { + swapped_words[0] = apint_words[1]; + swapped_words[1] = apint_words[0]; + apint_words = swapped_words; } - return *this; -} - -Scalar& -Scalar::operator= (const int v) -{ - m_type = e_sint; - m_integer = llvm::APInt(sizeof(int) * 8, v, true); - return *this; -} - -Scalar& -Scalar::operator= (unsigned int v) -{ - m_type = e_uint; - m_integer = llvm::APInt(sizeof(int) * 8, v); - return *this; -} - -Scalar& -Scalar::operator= (long v) -{ - m_type = e_slong; - m_integer = llvm::APInt(sizeof(long) * 8, v, true); - return *this; -} - -Scalar& -Scalar::operator= (unsigned long v) -{ - m_type = e_ulong; - m_integer = llvm::APInt(sizeof(long) * 8, v); - return *this; -} - -Scalar& -Scalar::operator= (long long v) -{ - m_type = e_slonglong; - m_integer = llvm::APInt(sizeof(long) * 8, v, true); - return *this; -} - -Scalar& -Scalar::operator= (unsigned long long v) -{ - m_type = e_ulonglong; - m_integer = llvm::APInt(sizeof(long long) * 8, v); - return *this; -} - -Scalar& -Scalar::operator= (float v) -{ - m_type = e_float; - m_float = llvm::APFloat(v); - return *this; -} - -Scalar& -Scalar::operator= (double v) -{ - m_type = e_double; - m_float = llvm::APFloat(v); - return *this; -} - -Scalar& -Scalar::operator= (long double v) -{ - m_type = e_long_double; - if(m_ieee_quad) - m_float = llvm::APFloat(llvm::APFloat::IEEEquad, llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&v)->x)); + return reinterpret_cast<const void *>(apint_words); + } + return nullptr; +} + +size_t Scalar::GetByteSize() const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return (m_integer.getBitWidth() / 8); + case e_float: + return sizeof(float_t); + case e_double: + return sizeof(double_t); + case e_long_double: + return sizeof(long_double_t); + } + return 0; +} + +bool Scalar::IsZero() const { + llvm::APInt zero_int = llvm::APInt::getNullValue(m_integer.getBitWidth() / 8); + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return llvm::APInt::isSameValue(zero_int, m_integer); + case e_float: + case e_double: + case e_long_double: + return m_float.isZero(); + } + return false; +} + +void Scalar::GetValue(Stream *s, bool show_type) const { + if (show_type) + s->Printf("(%s) ", GetTypeAsCString()); + + switch (m_type) { + case e_void: + break; + case e_sint: + case e_slong: + case e_slonglong: + case e_sint128: + case e_sint256: + s->PutCString(m_integer.toString(10, true)); + break; + case e_uint: + case e_ulong: + case e_ulonglong: + case e_uint128: + case e_uint256: + s->PutCString(m_integer.toString(10, false)); + break; + case e_float: + case e_double: + case e_long_double: + llvm::SmallString<24> string; + m_float.toString(string); + s->Printf("%s", string.c_str()); + break; + } +} + +const char *Scalar::GetTypeAsCString() const { + switch (m_type) { + case e_void: + return "void"; + case e_sint: + return "int"; + case e_uint: + return "unsigned int"; + case e_slong: + return "long"; + case e_ulong: + return "unsigned long"; + case e_slonglong: + return "long long"; + case e_ulonglong: + return "unsigned long long"; + case e_sint128: + return "int128_t"; + case e_uint128: + return "unsigned int128_t"; + case e_sint256: + return "int256_t"; + case e_uint256: + return "unsigned int256_t"; + case e_float: + return "float"; + case e_double: + return "double"; + case e_long_double: + return "long double"; + } + return "<invalid Scalar type>"; +} + +Scalar &Scalar::operator=(const Scalar &rhs) { + if (this != &rhs) { + m_type = rhs.m_type; + m_integer = llvm::APInt(rhs.m_integer); + m_float = rhs.m_float; + } + return *this; +} + +Scalar &Scalar::operator=(const int v) { + m_type = e_sint; + m_integer = llvm::APInt(sizeof(int) * 8, v, true); + return *this; +} + +Scalar &Scalar::operator=(unsigned int v) { + m_type = e_uint; + m_integer = llvm::APInt(sizeof(int) * 8, v); + return *this; +} + +Scalar &Scalar::operator=(long v) { + m_type = e_slong; + m_integer = llvm::APInt(sizeof(long) * 8, v, true); + return *this; +} + +Scalar &Scalar::operator=(unsigned long v) { + m_type = e_ulong; + m_integer = llvm::APInt(sizeof(long) * 8, v); + return *this; +} + +Scalar &Scalar::operator=(long long v) { + m_type = e_slonglong; + m_integer = llvm::APInt(sizeof(long) * 8, v, true); + return *this; +} + +Scalar &Scalar::operator=(unsigned long long v) { + m_type = e_ulonglong; + m_integer = llvm::APInt(sizeof(long long) * 8, v); + return *this; +} + +Scalar &Scalar::operator=(float v) { + m_type = e_float; + m_float = llvm::APFloat(v); + return *this; +} + +Scalar &Scalar::operator=(double v) { + m_type = e_double; + m_float = llvm::APFloat(v); + return *this; +} + +Scalar &Scalar::operator=(long double v) { + m_type = e_long_double; + if (m_ieee_quad) + m_float = llvm::APFloat( + llvm::APFloat::IEEEquad(), + llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&v)->x)); + else + m_float = llvm::APFloat( + llvm::APFloat::x87DoubleExtended(), + llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&v)->x)); + return *this; +} + +Scalar &Scalar::operator=(llvm::APInt rhs) { + m_integer = llvm::APInt(rhs); + switch (m_integer.getBitWidth()) { + case 8: + case 16: + case 32: + if (m_integer.isSignedIntN(sizeof(sint_t) * 8)) + m_type = e_sint; else - m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&v)->x)); - return *this; -} - -Scalar& -Scalar::operator= (llvm::APInt rhs) -{ - m_integer = llvm::APInt(rhs); - switch(m_integer.getBitWidth()) - { - case 8: - case 16: - case 32: - if(m_integer.isSignedIntN(sizeof(sint_t) * 8)) - m_type = e_sint; - else - m_type = e_uint; - break; - case 64: - if(m_integer.isSignedIntN(sizeof(slonglong_t) * 8)) - m_type = e_slonglong; - else - m_type = e_ulonglong; - break; - case 128: - if(m_integer.isSignedIntN(BITWIDTH_INT128)) - m_type = e_sint128; - else - m_type = e_uint128; - break; - case 256: - if(m_integer.isSignedIntN(BITWIDTH_INT256)) - m_type = e_sint256; - else - m_type = e_uint256; - break; - } - return *this; + m_type = e_uint; + break; + case 64: + if (m_integer.isSignedIntN(sizeof(slonglong_t) * 8)) + m_type = e_slonglong; + else + m_type = e_ulonglong; + break; + case 128: + if (m_integer.isSignedIntN(BITWIDTH_INT128)) + m_type = e_sint128; + else + m_type = e_uint128; + break; + case 256: + if (m_integer.isSignedIntN(BITWIDTH_INT256)) + m_type = e_sint256; + else + m_type = e_uint256; + break; + } + return *this; } Scalar::~Scalar() = default; -bool -Scalar::Promote(Scalar::Type type) -{ - bool success = false; - switch (m_type) - { - case e_void: - break; +bool Scalar::Promote(Scalar::Type type) { + bool success = false; + switch (m_type) { + case e_void: + break; + case e_sint: + switch (type) { + case e_void: + break; case e_sint: - switch (type) - { - case e_void: break; - case e_sint: success = true; break; - case e_uint: - m_integer = m_integer.sextOrTrunc(sizeof(uint_t) * 8); - success = true; - break; - - case e_slong: - m_integer = m_integer.sextOrTrunc(sizeof(slong_t) * 8); - success = true; - break; - - case e_ulong: - m_integer = m_integer.sextOrTrunc(sizeof(ulong_t) * 8); - success = true; - break; - - case e_slonglong: - m_integer = m_integer.sextOrTrunc(sizeof(slonglong_t) * 8); - success = true; - break; - - case e_ulonglong: - m_integer = m_integer.sextOrTrunc(sizeof(ulonglong_t) * 8); - success = true; - break; - - case e_sint128: - case e_uint128: - m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128); - success = true; - break; - - case e_sint256: - case e_uint256: - m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256); - success = true; - break; - - case e_float: - m_float = llvm::APFloat(m_integer.bitsToFloat()); - success = true; - break; - - case e_double: - m_float = llvm::APFloat(m_integer.bitsToDouble()); - success = true; - break; - - case e_long_double: - if(m_ieee_quad) - m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); - else - m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); - success = true; - break; - } - break; - + success = true; + break; case e_uint: - switch (type) - { - case e_void: - case e_sint: break; - case e_uint: success = true; break; - case e_slong: - m_integer = m_integer.zextOrTrunc(sizeof(slong_t) * 8); - success = true; - break; - - case e_ulong: - m_integer = m_integer.zextOrTrunc(sizeof(ulong_t) * 8); - success = true; - break; - - case e_slonglong: - m_integer = m_integer.zextOrTrunc(sizeof(slonglong_t) * 8); - success = true; - break; - - case e_ulonglong: - m_integer = m_integer.zextOrTrunc(sizeof(ulonglong_t) * 8); - success = true; - break; - - case e_sint128: - case e_uint128: - m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128); - success = true; - break; - - case e_sint256: - case e_uint256: - m_integer = m_integer.zextOrTrunc(BITWIDTH_INT256); - success = true; - break; - - case e_float: - m_float = llvm::APFloat(m_integer.bitsToFloat()); - success = true; - break; - - case e_double: - m_float = llvm::APFloat(m_integer.bitsToDouble()); - success = true; - break; - - case e_long_double: - if(m_ieee_quad) - m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); - else - m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); - success = true; - break; - } - break; + m_integer = m_integer.sextOrTrunc(sizeof(uint_t) * 8); + success = true; + break; case e_slong: - switch (type) - { - case e_void: - case e_sint: - case e_uint: break; - case e_slong: success = true; break; - case e_ulong: - m_integer = m_integer.sextOrTrunc(sizeof(ulong_t) * 8); - success = true; - break; - - case e_slonglong: - m_integer = m_integer.sextOrTrunc(sizeof(slonglong_t) * 8); - success = true; - break; - - case e_ulonglong: - m_integer = m_integer.sextOrTrunc(sizeof(ulonglong_t) * 8); - success = true; - break; - - case e_sint128: - case e_uint128: - m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128); - success = true; - break; - - case e_sint256: - case e_uint256: - m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256); - success = true; - break; - - case e_float: - m_float = llvm::APFloat(m_integer.bitsToFloat()); - success = true; - break; - - case e_double: - m_float = llvm::APFloat(m_integer.bitsToDouble()); - success = true; - break; - - case e_long_double: - if(m_ieee_quad) - m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); - else - m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); - success = true; - break; - } - break; + m_integer = m_integer.sextOrTrunc(sizeof(slong_t) * 8); + success = true; + break; case e_ulong: - switch (type) - { - case e_void: - case e_sint: - case e_uint: - case e_slong: break; - case e_ulong: success = true; break; - case e_slonglong: - m_integer = m_integer.zextOrTrunc(sizeof(slonglong_t) * 8); - success = true; - break; - - case e_ulonglong: - m_integer = m_integer.zextOrTrunc(sizeof(ulonglong_t) * 8); - success = true; - break; - - case e_sint128: - case e_uint128: - m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128); - success = true; - break; - - case e_sint256: - case e_uint256: - m_integer = m_integer.zextOrTrunc(BITWIDTH_INT256); - success = true; - break; - - case e_float: - m_float = llvm::APFloat(m_integer.bitsToFloat()); - success = true; - break; - - case e_double: - m_float = llvm::APFloat(m_integer.bitsToDouble()); - success = true; - break; - - case e_long_double: - if(m_ieee_quad) - m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); - else - m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); - success = true; - break; - } - break; + m_integer = m_integer.sextOrTrunc(sizeof(ulong_t) * 8); + success = true; + break; case e_slonglong: - switch (type) - { - case e_void: - case e_sint: - case e_uint: - case e_slong: - case e_ulong: break; - case e_slonglong: success = true; break; - case e_ulonglong: - m_integer = m_integer.sextOrTrunc(sizeof(ulonglong_t) * 8); - success = true; - break; - - case e_sint128: - case e_uint128: - m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128); - success = true; - break; - - case e_sint256: - case e_uint256: - m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256); - success = true; - break; - - case e_float: - m_float = llvm::APFloat(m_integer.bitsToFloat()); - success = true; - break; - - case e_double: - m_float = llvm::APFloat(m_integer.bitsToDouble()); - success = true; - break; - - case e_long_double: - if(m_ieee_quad) - m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); - else - m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); - success = true; - break; - } - break; + m_integer = m_integer.sextOrTrunc(sizeof(slonglong_t) * 8); + success = true; + break; case e_ulonglong: - switch (type) - { - case e_void: - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: break; - case e_ulonglong: success = true; break; - case e_sint128: - case e_uint128: - m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128); - success = true; - break; - - case e_sint256: - case e_uint256: - m_integer = m_integer.zextOrTrunc(BITWIDTH_INT256); - success = true; - break; - - case e_float: - m_float = llvm::APFloat(m_integer.bitsToFloat()); - success = true; - break; - - case e_double: - m_float = llvm::APFloat(m_integer.bitsToDouble()); - success = true; - break; - - case e_long_double: - if(m_ieee_quad) - m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); - else - m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); - success = true; - break; - } - break; + m_integer = m_integer.sextOrTrunc(sizeof(ulonglong_t) * 8); + success = true; + break; case e_sint128: - switch (type) - { - case e_void: - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: break; - case e_sint128: success = true; break; - case e_uint128: - m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128); - success = true; - break; - - case e_sint256: - case e_uint256: - m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256); - success = true; - break; - - case e_float: - m_float = llvm::APFloat(m_integer.bitsToFloat()); - success = true; - break; - - case e_double: - m_float = llvm::APFloat(m_integer.bitsToDouble()); - success = true; - break; - - case e_long_double: - if(m_ieee_quad) - m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); - else - m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); - success = true; - break; - } - break; - case e_uint128: - switch (type) - { - case e_void: - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: break; - case e_uint128: success = true; break; - case e_sint256: - case e_uint256: - m_integer = m_integer.zextOrTrunc(BITWIDTH_INT256); - success = true; - break; - - case e_float: - m_float = llvm::APFloat(m_integer.bitsToFloat()); - success = true; - break; - - case e_double: - m_float = llvm::APFloat(m_integer.bitsToDouble()); - success = true; - break; - - case e_long_double: - if(m_ieee_quad) - m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); - else - m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); - success = true; - break; - } - break; + m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128); + success = true; + break; case e_sint256: - switch (type) - { - case e_void: - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: break; - case e_sint256: success = true; break; - case e_uint256: - m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256); - success = true; - break; - - case e_float: - m_float = llvm::APFloat(m_integer.bitsToFloat()); - success = true; - break; - - case e_double: - m_float = llvm::APFloat(m_integer.bitsToDouble()); - success = true; - break; - - case e_long_double: - if(m_ieee_quad) - m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); - else - m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); - success = true; - break; - } - break; - case e_uint256: - switch (type) - { - case e_void: - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: break; - case e_uint256: success = true; break; - case e_float: - m_float = llvm::APFloat(m_integer.bitsToFloat()); - success = true; - break; - - case e_double: - m_float = llvm::APFloat(m_integer.bitsToDouble()); - success = true; - break; - - case e_long_double: - if(m_ieee_quad) - m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); - else - m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); - success = true; - break; - } - break; - + m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256); + success = true; + break; + case e_float: - switch (type) - { - case e_void: - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: - case e_uint256: break; - case e_float: success = true; break; - case e_double: - m_float = llvm::APFloat((float_t)m_float.convertToFloat()); - success = true; - break; - - case e_long_double: - if(m_ieee_quad) - m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_float.bitcastToAPInt()); - else - m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_float.bitcastToAPInt()); - success = true; - break; - } - break; + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; case e_double: - switch (type) - { - case e_void: - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: - case e_uint256: - case e_float: break; - case e_double: success = true; break; - case e_long_double: - if(m_ieee_quad) - m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_float.bitcastToAPInt()); - else - m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_float.bitcastToAPInt()); - success = true; - break; - } - break; + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; case e_long_double: - switch (type) - { - case e_void: - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: - case e_uint256: - case e_float: - case e_double: break; - case e_long_double: success = true; break; - } - break; - } - - if (success) - m_type = type; - return success; -} - -const char * -Scalar::GetValueTypeAsCString (Scalar::Type type) -{ - switch (type) - { - case e_void: return "void"; - case e_sint: return "int"; - case e_uint: return "unsigned int"; - case e_slong: return "long"; - case e_ulong: return "unsigned long"; - case e_slonglong: return "long long"; - case e_ulonglong: return "unsigned long long"; - case e_float: return "float"; - case e_double: return "double"; - case e_long_double: return "long double"; - case e_sint128: return "int128_t"; - case e_uint128: return "uint128_t"; - case e_sint256: return "int256_t"; - case e_uint256: return "uint256_t"; + if (m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer); + success = true; + break; } - return "???"; -} - -Scalar::Type -Scalar::GetValueTypeForSignedIntegerWithByteSize (size_t byte_size) -{ - if (byte_size <= sizeof(sint_t)) - return e_sint; - if (byte_size <= sizeof(slong_t)) - return e_slong; - if (byte_size <= sizeof(slonglong_t)) - return e_slonglong; - return e_void; -} + break; -Scalar::Type -Scalar::GetValueTypeForUnsignedIntegerWithByteSize (size_t byte_size) -{ - if (byte_size <= sizeof(uint_t)) - return e_uint; - if (byte_size <= sizeof(ulong_t)) - return e_ulong; - if (byte_size <= sizeof(ulonglong_t)) - return e_ulonglong; - return e_void; -} - -Scalar::Type -Scalar::GetValueTypeForFloatWithByteSize (size_t byte_size) -{ - if (byte_size == sizeof(float_t)) - return e_float; - if (byte_size == sizeof(double_t)) - return e_double; - if (byte_size == sizeof(long_double_t)) - return e_long_double; - return e_void; -} - -bool -Scalar::Cast(Scalar::Type type) -{ - bool success = false; - switch (m_type) - { + case e_uint: + switch (type) { case e_void: - break; - case e_sint: + break; case e_uint: + success = true; + break; case e_slong: + m_integer = m_integer.zextOrTrunc(sizeof(slong_t) * 8); + success = true; + break; + case e_ulong: + m_integer = m_integer.zextOrTrunc(sizeof(ulong_t) * 8); + success = true; + break; + case e_slonglong: + m_integer = m_integer.zextOrTrunc(sizeof(slonglong_t) * 8); + success = true; + break; + case e_ulonglong: + m_integer = m_integer.zextOrTrunc(sizeof(ulonglong_t) * 8); + success = true; + break; + case e_sint128: case e_uint128: + m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128); + success = true; + break; + case e_sint256: case e_uint256: - switch (type) - { - case e_void: break; - case e_sint: - m_integer = m_integer.sextOrTrunc(sizeof(sint_t) * 8); - success = true; - break; - - case e_uint: - m_integer = m_integer.zextOrTrunc(sizeof(sint_t) * 8); - success = true; - break; - - case e_slong: - m_integer = m_integer.sextOrTrunc(sizeof(slong_t) * 8); - success = true; - break; - - case e_ulong: - m_integer = m_integer.zextOrTrunc(sizeof(slong_t) * 8); - success = true; - break; - - case e_slonglong: - m_integer = m_integer.sextOrTrunc(sizeof(slonglong_t) * 8); - success = true; - break; - - case e_ulonglong: - m_integer = m_integer.zextOrTrunc(sizeof(slonglong_t) * 8); - success = true; - break; - - case e_sint128: - m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128); - success = true; - break; - - case e_uint128: - m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128); - success = true; - break; - - case e_sint256: - m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256); - success = true; - break; - - case e_uint256: - m_integer = m_integer.zextOrTrunc(BITWIDTH_INT256); - success = true; - break; - - case e_float: - m_float = llvm::APFloat(m_integer.bitsToFloat()); - success = true; - break; - - case e_double: - m_float = llvm::APFloat(m_integer.bitsToDouble()); - success = true; - break; - - case e_long_double: - if(m_ieee_quad) - m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_integer); - else - m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_integer); - success = true; - break; - } - break; + m_integer = m_integer.zextOrTrunc(BITWIDTH_INT256); + success = true; + break; case e_float: - switch (type) - { - case e_void: break; - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: - case e_uint256: m_integer = m_float.bitcastToAPInt(); success = true; break; - case e_float: m_float = llvm::APFloat(m_float.convertToFloat()); success = true; break; - case e_double: m_float = llvm::APFloat(m_float.convertToFloat()); success = true; break; - case e_long_double: - if(m_ieee_quad) - m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_float.bitcastToAPInt()); - else - m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_float.bitcastToAPInt()); - success = true; - break; - } - break; + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; case e_double: - switch (type) - { - case e_void: break; - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: - case e_uint256: m_integer = m_float.bitcastToAPInt(); success = true; break; - case e_float: m_float = llvm::APFloat(m_float.convertToDouble()); success = true; break; - case e_double: m_float = llvm::APFloat(m_float.convertToDouble()); success = true; break; - case e_long_double: - if(m_ieee_quad) - m_float = llvm::APFloat(llvm::APFloat::IEEEquad, m_float.bitcastToAPInt()); - else - m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, m_float.bitcastToAPInt()); - success = true; - break; - } - break; + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; case e_long_double: - switch (type) - { - case e_void: break; - case e_sint: - m_integer = m_float.bitcastToAPInt(); - m_integer = m_integer.sextOrTrunc(sizeof(sint_t) * 8); - success = true; - break; - - case e_uint: - m_integer = m_float.bitcastToAPInt(); - m_integer = m_integer.zextOrTrunc(sizeof(sint_t) * 8); - success = true; - break; - - case e_slong: - m_integer = m_float.bitcastToAPInt(); - m_integer = m_integer.sextOrTrunc(sizeof(slong_t) * 8); - success = true; - break; - - case e_ulong: - m_integer = m_float.bitcastToAPInt(); - m_integer = m_integer.zextOrTrunc(sizeof(slong_t) * 8); - success = true; - break; - - case e_slonglong: - m_integer = m_float.bitcastToAPInt(); - m_integer = m_integer.sextOrTrunc(sizeof(slonglong_t) * 8); - success = true; - break; - - case e_ulonglong: - m_integer = m_float.bitcastToAPInt(); - m_integer = m_integer.zextOrTrunc(sizeof(slonglong_t) * 8); - success = true; - break; - - case e_sint128: - m_integer = m_float.bitcastToAPInt(); - m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128); - success = true; - break; - - case e_uint128: - m_integer = m_float.bitcastToAPInt(); - m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128); - success = true; - break; - - case e_sint256: - m_integer = m_float.bitcastToAPInt(); - m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256); - success = true; - break; - - case e_uint256: - m_integer = m_float.bitcastToAPInt(); - m_integer = m_integer.zextOrTrunc(BITWIDTH_INT256); - success = true; - break; - - case e_float: m_float = llvm::APFloat(m_float.convertToFloat()); success = true; break; - case e_double: m_float = llvm::APFloat(m_float.convertToFloat()); success = true; break; - case e_long_double: success = true; break; - } - break; - } - - if (success) - m_type = type; - return success; -} - -bool -Scalar::MakeSigned () -{ - bool success = false; - - switch (m_type) - { - case e_void: break; - case e_sint: success = true; break; - case e_uint: m_type = e_sint; success = true; break; - case e_slong: success = true; break; - case e_ulong: m_type = e_slong; success = true; break; - case e_slonglong: success = true; break; - case e_ulonglong: m_type = e_slonglong; success = true; break; - case e_sint128: success = true; break; - case e_uint128: m_type = e_sint128; success = true; break; - case e_sint256: success = true; break; - case e_uint256: m_type = e_sint256; success = true; break; - case e_float: success = true; break; - case e_double: success = true; break; - case e_long_double: success = true; break; - } - - return success; -} - -bool -Scalar::MakeUnsigned () -{ - bool success = false; - - switch (m_type) - { - case e_void: break; - case e_sint: success = true; break; - case e_uint: m_type = e_uint; success = true; break; - case e_slong: success = true; break; - case e_ulong: m_type = e_ulong; success = true; break; - case e_slonglong: success = true; break; - case e_ulonglong: m_type = e_ulonglong; success = true; break; - case e_sint128: success = true; break; - case e_uint128: m_type = e_uint128; success = true; break; - case e_sint256: success = true; break; - case e_uint256: m_type = e_uint256; success = true; break; - case e_float: success = true; break; - case e_double: success = true; break; - case e_long_double: success = true; break; + if (m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer); + success = true; + break; } + break; - return success; -} - -signed char -Scalar::SChar(char fail_value) const -{ - switch (m_type) - { - case e_void: break; + case e_slong: + switch (type) { + case e_void: case e_sint: case e_uint: + break; case e_slong: + success = true; + break; case e_ulong: + m_integer = m_integer.sextOrTrunc(sizeof(ulong_t) * 8); + success = true; + break; + case e_slonglong: + m_integer = m_integer.sextOrTrunc(sizeof(slonglong_t) * 8); + success = true; + break; + case e_ulonglong: + m_integer = m_integer.sextOrTrunc(sizeof(ulonglong_t) * 8); + success = true; + break; + case e_sint128: case e_uint128: + m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128); + success = true; + break; + case e_sint256: case e_uint256: - return (schar_t)(m_integer.sextOrTrunc(sizeof(schar_t) * 8)).getSExtValue(); + m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256); + success = true; + break; + case e_float: - return (schar_t)m_float.convertToFloat(); + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + case e_double: - return (schar_t)m_float.convertToDouble(); + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + case e_long_double: - llvm::APInt ldbl_val = m_float.bitcastToAPInt(); - return (schar_t)(ldbl_val.sextOrTrunc(sizeof(schar_t) * 8)).getSExtValue(); + if (m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer); + success = true; + break; } - return fail_value; -} + break; -unsigned char -Scalar::UChar(unsigned char fail_value) const -{ - switch (m_type) - { - case e_void: break; + case e_ulong: + switch (type) { + case e_void: case e_sint: case e_uint: case e_slong: + break; case e_ulong: + success = true; + break; case e_slonglong: + m_integer = m_integer.zextOrTrunc(sizeof(slonglong_t) * 8); + success = true; + break; + case e_ulonglong: + m_integer = m_integer.zextOrTrunc(sizeof(ulonglong_t) * 8); + success = true; + break; + case e_sint128: case e_uint128: + m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128); + success = true; + break; + case e_sint256: case e_uint256: - return (uchar_t)(m_integer.zextOrTrunc(sizeof(uchar_t) * 8)).getZExtValue(); + m_integer = m_integer.zextOrTrunc(BITWIDTH_INT256); + success = true; + break; + case e_float: - return (uchar_t)m_float.convertToFloat(); + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + case e_double: - return (uchar_t)m_float.convertToDouble(); + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + case e_long_double: - llvm::APInt ldbl_val = m_float.bitcastToAPInt(); - return (uchar_t)(ldbl_val.zextOrTrunc(sizeof(uchar_t) * 8)).getZExtValue(); + if (m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer); + success = true; + break; } - return fail_value; -} + break; -short -Scalar::SShort(short fail_value) const -{ - switch (m_type) - { - case e_void: break; + case e_slonglong: + switch (type) { + case e_void: case e_sint: case e_uint: case e_slong: case e_ulong: + break; case e_slonglong: + success = true; + break; case e_ulonglong: + m_integer = m_integer.sextOrTrunc(sizeof(ulonglong_t) * 8); + success = true; + break; + case e_sint128: case e_uint128: + m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128); + success = true; + break; + case e_sint256: case e_uint256: - return (sshort_t)(m_integer.sextOrTrunc(sizeof(sshort_t) * 8)).getSExtValue(); + m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256); + success = true; + break; + case e_float: - return (sshort_t)m_float.convertToFloat(); + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + case e_double: - return (sshort_t)m_float.convertToDouble(); + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + case e_long_double: - llvm::APInt ldbl_val = m_float.bitcastToAPInt(); - return (sshort_t)(ldbl_val.sextOrTrunc(sizeof(sshort_t) * 8)).getSExtValue(); + if (m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer); + success = true; + break; } - return fail_value; -} + break; -unsigned short -Scalar::UShort(unsigned short fail_value) const -{ - switch (m_type) - { - case e_void: break; + case e_ulonglong: + switch (type) { + case e_void: case e_sint: case e_uint: case e_slong: case e_ulong: case e_slonglong: + break; case e_ulonglong: + success = true; + break; case e_sint128: case e_uint128: + m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128); + success = true; + break; + case e_sint256: case e_uint256: - return (ushort_t)(m_integer.zextOrTrunc(sizeof(ushort_t) * 8)).getZExtValue(); + m_integer = m_integer.zextOrTrunc(BITWIDTH_INT256); + success = true; + break; + case e_float: - return (ushort_t)m_float.convertToFloat(); + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + case e_double: - return (ushort_t)m_float.convertToDouble(); + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + case e_long_double: - llvm::APInt ldbl_val = m_float.bitcastToAPInt(); - return (ushort_t)(ldbl_val.zextOrTrunc(sizeof(ushort_t) * 8)).getZExtValue(); + if (m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer); + success = true; + break; } - return fail_value; -} + break; -int -Scalar::SInt(int fail_value) const -{ - switch (m_type) - { - case e_void: break; + case e_sint128: + switch (type) { + case e_void: case e_sint: case e_uint: case e_slong: case e_ulong: case e_slonglong: case e_ulonglong: + break; case e_sint128: + success = true; + break; case e_uint128: + m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128); + success = true; + break; + case e_sint256: case e_uint256: - return (sint_t)(m_integer.sextOrTrunc(sizeof(sint_t) * 8)).getSExtValue(); + m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256); + success = true; + break; + case e_float: - return (sint_t)m_float.convertToFloat(); + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + case e_double: - return (sint_t)m_float.convertToDouble(); + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + case e_long_double: - llvm::APInt ldbl_val = m_float.bitcastToAPInt(); - return (sint_t)(ldbl_val.sextOrTrunc(sizeof(sint_t) * 8)).getSExtValue(); + if (m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer); + success = true; + break; } - return fail_value; -} + break; -unsigned int -Scalar::UInt(unsigned int fail_value) const -{ - switch (m_type) - { - case e_void: break; + case e_uint128: + switch (type) { + case e_void: case e_sint: case e_uint: case e_slong: @@ -1518,27 +831,39 @@ Scalar::UInt(unsigned int fail_value) const case e_slonglong: case e_ulonglong: case e_sint128: + break; case e_uint128: + success = true; + break; case e_sint256: case e_uint256: - return (uint_t)(m_integer.zextOrTrunc(sizeof(uint_t) * 8)).getZExtValue(); + m_integer = m_integer.zextOrTrunc(BITWIDTH_INT256); + success = true; + break; + case e_float: - return (uint_t)m_float.convertToFloat(); + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + case e_double: - return (uint_t)m_float.convertToDouble(); + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + case e_long_double: - llvm::APInt ldbl_val = m_float.bitcastToAPInt(); - return (uint_t)(ldbl_val.zextOrTrunc(sizeof(uint_t) * 8)).getZExtValue(); + if (m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer); + success = true; + break; } - return fail_value; -} + break; -long -Scalar::SLong(long fail_value) const -{ - switch (m_type) - { - case e_void: break; + case e_sint256: + switch (type) { + case e_void: case e_sint: case e_uint: case e_slong: @@ -1547,26 +872,38 @@ Scalar::SLong(long fail_value) const case e_ulonglong: case e_sint128: case e_uint128: + break; case e_sint256: + success = true; + break; case e_uint256: - return (slong_t)(m_integer.sextOrTrunc(sizeof(slong_t) * 8)).getSExtValue(); + m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256); + success = true; + break; + case e_float: - return (slong_t)m_float.convertToFloat(); + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + case e_double: - return (slong_t)m_float.convertToDouble(); + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + case e_long_double: - llvm::APInt ldbl_val = m_float.bitcastToAPInt(); - return (slong_t)(ldbl_val.sextOrTrunc(sizeof(slong_t) * 8)).getSExtValue(); + if (m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer); + success = true; + break; } - return fail_value; -} + break; -unsigned long -Scalar::ULong(unsigned long fail_value) const -{ - switch (m_type) - { - case e_void: break; + case e_uint256: + switch (type) { + case e_void: case e_sint: case e_uint: case e_slong: @@ -1576,25 +913,33 @@ Scalar::ULong(unsigned long fail_value) const case e_sint128: case e_uint128: case e_sint256: + break; case e_uint256: - return (ulong_t)(m_integer.zextOrTrunc(sizeof(ulong_t) * 8)).getZExtValue(); + success = true; + break; case e_float: - return (ulong_t)m_float.convertToFloat(); + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + case e_double: - return (ulong_t)m_float.convertToDouble(); + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + case e_long_double: - llvm::APInt ldbl_val = m_float.bitcastToAPInt(); - return (ulong_t)(ldbl_val.zextOrTrunc(sizeof(ulong_t) * 8)).getZExtValue(); + if (m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer); + success = true; + break; } - return fail_value; -} + break; -long long -Scalar::SLongLong(long long fail_value) const -{ - switch (m_type) - { - case e_void: break; + case e_float: + switch (type) { + case e_void: case e_sint: case e_uint: case e_slong: @@ -1605,24 +950,30 @@ Scalar::SLongLong(long long fail_value) const case e_uint128: case e_sint256: case e_uint256: - return (slonglong_t)(m_integer.sextOrTrunc(sizeof(slonglong_t) * 8)).getSExtValue(); + break; case e_float: - return (slonglong_t)m_float.convertToFloat(); + success = true; + break; case e_double: - return (slonglong_t)m_float.convertToDouble(); + m_float = llvm::APFloat((float_t)m_float.convertToFloat()); + success = true; + break; + case e_long_double: - llvm::APInt ldbl_val = m_float.bitcastToAPInt(); - return (slonglong_t)(ldbl_val.sextOrTrunc(sizeof(slonglong_t) * 8)).getSExtValue(); + if (m_ieee_quad) + m_float = + llvm::APFloat(llvm::APFloat::IEEEquad(), m_float.bitcastToAPInt()); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), + m_float.bitcastToAPInt()); + success = true; + break; } - return fail_value; -} + break; -unsigned long long -Scalar::ULongLong(unsigned long long fail_value) const -{ - switch (m_type) - { - case e_void: break; + case e_double: + switch (type) { + case e_void: case e_sint: case e_uint: case e_slong: @@ -1633,49 +984,26 @@ Scalar::ULongLong(unsigned long long fail_value) const case e_uint128: case e_sint256: case e_uint256: - return (ulonglong_t)(m_integer.zextOrTrunc(sizeof(ulonglong_t) * 8)).getZExtValue(); case e_float: - return (ulonglong_t)m_float.convertToFloat(); + break; case e_double: - return (ulonglong_t)m_float.convertToDouble(); + success = true; + break; case e_long_double: - llvm::APInt ldbl_val = m_float.bitcastToAPInt(); - return (ulonglong_t)(ldbl_val.zextOrTrunc(sizeof(ulonglong_t) * 8)).getZExtValue(); + if (m_ieee_quad) + m_float = + llvm::APFloat(llvm::APFloat::IEEEquad(), m_float.bitcastToAPInt()); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), + m_float.bitcastToAPInt()); + success = true; + break; } - return fail_value; -} + break; -llvm::APInt -Scalar::SInt128(llvm::APInt& fail_value) const -{ - switch (m_type) - { - case e_void: break; - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: - case e_uint256: - return m_integer; - case e_float: - case e_double: - case e_long_double: - return m_float.bitcastToAPInt(); - } - return fail_value; -} - -llvm::APInt -Scalar::UInt128(const llvm::APInt& fail_value) const -{ - switch (m_type) - { - case e_void: break; + case e_long_double: + switch (type) { + case e_void: case e_sint: case e_uint: case e_slong: @@ -1686,71 +1014,180 @@ Scalar::UInt128(const llvm::APInt& fail_value) const case e_uint128: case e_sint256: case e_uint256: - return m_integer; case e_float: case e_double: + break; case e_long_double: - return m_float.bitcastToAPInt(); + success = true; + break; } - return fail_value; + break; + } + + if (success) + m_type = type; + return success; +} + +const char *Scalar::GetValueTypeAsCString(Scalar::Type type) { + switch (type) { + case e_void: + return "void"; + case e_sint: + return "int"; + case e_uint: + return "unsigned int"; + case e_slong: + return "long"; + case e_ulong: + return "unsigned long"; + case e_slonglong: + return "long long"; + case e_ulonglong: + return "unsigned long long"; + case e_float: + return "float"; + case e_double: + return "double"; + case e_long_double: + return "long double"; + case e_sint128: + return "int128_t"; + case e_uint128: + return "uint128_t"; + case e_sint256: + return "int256_t"; + case e_uint256: + return "uint256_t"; + } + return "???"; +} + +Scalar::Type +Scalar::GetValueTypeForSignedIntegerWithByteSize(size_t byte_size) { + if (byte_size <= sizeof(sint_t)) + return e_sint; + if (byte_size <= sizeof(slong_t)) + return e_slong; + if (byte_size <= sizeof(slonglong_t)) + return e_slonglong; + return e_void; } -llvm::APInt -Scalar::SInt256(llvm::APInt& fail_value) const -{ - switch (m_type) - { - case e_void: break; +Scalar::Type +Scalar::GetValueTypeForUnsignedIntegerWithByteSize(size_t byte_size) { + if (byte_size <= sizeof(uint_t)) + return e_uint; + if (byte_size <= sizeof(ulong_t)) + return e_ulong; + if (byte_size <= sizeof(ulonglong_t)) + return e_ulonglong; + return e_void; +} + +Scalar::Type Scalar::GetValueTypeForFloatWithByteSize(size_t byte_size) { + if (byte_size == sizeof(float_t)) + return e_float; + if (byte_size == sizeof(double_t)) + return e_double; + if (byte_size == sizeof(long_double_t)) + return e_long_double; + return e_void; +} + +bool Scalar::Cast(Scalar::Type type) { + bool success = false; + switch (m_type) { + case e_void: + break; + + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + switch (type) { + case e_void: + break; case e_sint: + m_integer = m_integer.sextOrTrunc(sizeof(sint_t) * 8); + success = true; + break; + case e_uint: + m_integer = m_integer.zextOrTrunc(sizeof(sint_t) * 8); + success = true; + break; + case e_slong: + m_integer = m_integer.sextOrTrunc(sizeof(slong_t) * 8); + success = true; + break; + case e_ulong: + m_integer = m_integer.zextOrTrunc(sizeof(slong_t) * 8); + success = true; + break; + case e_slonglong: + m_integer = m_integer.sextOrTrunc(sizeof(slonglong_t) * 8); + success = true; + break; + case e_ulonglong: + m_integer = m_integer.zextOrTrunc(sizeof(slonglong_t) * 8); + success = true; + break; + case e_sint128: + m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128); + success = true; + break; + case e_uint128: + m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128); + success = true; + break; + case e_sint256: + m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256); + success = true; + break; + case e_uint256: - return m_integer; + m_integer = m_integer.zextOrTrunc(BITWIDTH_INT256); + success = true; + break; + case e_float: + m_float = llvm::APFloat(m_integer.bitsToFloat()); + success = true; + break; + case e_double: + m_float = llvm::APFloat(m_integer.bitsToDouble()); + success = true; + break; + case e_long_double: - return m_float.bitcastToAPInt(); + if (m_ieee_quad) + m_float = llvm::APFloat(llvm::APFloat::IEEEquad(), m_integer); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), m_integer); + success = true; + break; } - return fail_value; -} + break; -llvm::APInt -Scalar::UInt256(const llvm::APInt& fail_value) const -{ - switch (m_type) - { - case e_void: break; - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: - case e_uint256: - return m_integer; - case e_float: - case e_double: - case e_long_double: - return m_float.bitcastToAPInt(); - } - return fail_value; -} - -float -Scalar::Float(float fail_value) const -{ - switch (m_type) - { - case e_void: break; + case e_float: + switch (type) { + case e_void: + break; case e_sint: case e_uint: case e_slong: @@ -1761,24 +1198,33 @@ Scalar::Float(float fail_value) const case e_uint128: case e_sint256: case e_uint256: - return m_integer.bitsToFloat(); + m_integer = m_float.bitcastToAPInt(); + success = true; + break; case e_float: - return m_float.convertToFloat(); + m_float = llvm::APFloat(m_float.convertToFloat()); + success = true; + break; case e_double: - return (float_t)m_float.convertToDouble(); + m_float = llvm::APFloat(m_float.convertToFloat()); + success = true; + break; case e_long_double: - llvm::APInt ldbl_val = m_float.bitcastToAPInt(); - return ldbl_val.bitsToFloat(); + if (m_ieee_quad) + m_float = + llvm::APFloat(llvm::APFloat::IEEEquad(), m_float.bitcastToAPInt()); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), + m_float.bitcastToAPInt()); + success = true; + break; } - return fail_value; -} + break; -double -Scalar::Double(double fail_value) const -{ - switch (m_type) - { - case e_void: break; + case e_double: + switch (type) { + case e_void: + break; case e_sint: case e_uint: case e_slong: @@ -1789,92 +1235,670 @@ Scalar::Double(double fail_value) const case e_uint128: case e_sint256: case e_uint256: - return m_integer.bitsToDouble(); + m_integer = m_float.bitcastToAPInt(); + success = true; + break; case e_float: - return (double_t)m_float.convertToFloat(); + m_float = llvm::APFloat(m_float.convertToDouble()); + success = true; + break; case e_double: - return m_float.convertToDouble(); + m_float = llvm::APFloat(m_float.convertToDouble()); + success = true; + break; case e_long_double: - llvm::APInt ldbl_val = m_float.bitcastToAPInt(); - return ldbl_val.bitsToFloat(); + if (m_ieee_quad) + m_float = + llvm::APFloat(llvm::APFloat::IEEEquad(), m_float.bitcastToAPInt()); + else + m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended(), + m_float.bitcastToAPInt()); + success = true; + break; } - return fail_value; -} + break; -long double -Scalar::LongDouble(long double fail_value) const -{ - switch (m_type) - { - case e_void: break; + case e_long_double: + switch (type) { + case e_void: + break; case e_sint: + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.sextOrTrunc(sizeof(sint_t) * 8); + success = true; + break; + case e_uint: + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.zextOrTrunc(sizeof(sint_t) * 8); + success = true; + break; + case e_slong: + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.sextOrTrunc(sizeof(slong_t) * 8); + success = true; + break; + case e_ulong: + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.zextOrTrunc(sizeof(slong_t) * 8); + success = true; + break; + case e_slonglong: + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.sextOrTrunc(sizeof(slonglong_t) * 8); + success = true; + break; + case e_ulonglong: + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.zextOrTrunc(sizeof(slonglong_t) * 8); + success = true; + break; + case e_sint128: + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.sextOrTrunc(BITWIDTH_INT128); + success = true; + break; + case e_uint128: + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.zextOrTrunc(BITWIDTH_INT128); + success = true; + break; + case e_sint256: + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.sextOrTrunc(BITWIDTH_INT256); + success = true; + break; + case e_uint256: - return (long_double_t)m_integer.bitsToDouble(); + m_integer = m_float.bitcastToAPInt(); + m_integer = m_integer.zextOrTrunc(BITWIDTH_INT256); + success = true; + break; + case e_float: - return (long_double_t)m_float.convertToFloat(); + m_float = llvm::APFloat(m_float.convertToFloat()); + success = true; + break; case e_double: - return (long_double_t)m_float.convertToDouble(); + m_float = llvm::APFloat(m_float.convertToFloat()); + success = true; + break; case e_long_double: - llvm::APInt ldbl_val = m_float.bitcastToAPInt(); - return (long_double_t)ldbl_val.bitsToDouble(); - } - return fail_value; -} - -Scalar& -Scalar::operator+= (const Scalar& rhs) -{ - Scalar temp_value; - const Scalar* a; - const Scalar* b; - if ((m_type = PromoteToMaxType(*this, rhs, temp_value, a, b)) != Scalar::e_void) - { - switch (m_type) - { - case e_void: break; - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: - case e_uint256: - m_integer = a->m_integer + b->m_integer; - break; - - case e_float: - case e_double: - case e_long_double: - m_float = a->m_float + b->m_float; - break; - } + success = true; + break; } - return *this; + break; + } + + if (success) + m_type = type; + return success; } -Scalar& -Scalar::operator<<= (const Scalar& rhs) -{ - switch (m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; +bool Scalar::MakeSigned() { + bool success = false; + switch (m_type) { + case e_void: + break; + case e_sint: + success = true; + break; + case e_uint: + m_type = e_sint; + success = true; + break; + case e_slong: + success = true; + break; + case e_ulong: + m_type = e_slong; + success = true; + break; + case e_slonglong: + success = true; + break; + case e_ulonglong: + m_type = e_slonglong; + success = true; + break; + case e_sint128: + success = true; + break; + case e_uint128: + m_type = e_sint128; + success = true; + break; + case e_sint256: + success = true; + break; + case e_uint256: + m_type = e_sint256; + success = true; + break; + case e_float: + success = true; + break; + case e_double: + success = true; + break; + case e_long_double: + success = true; + break; + } + + return success; +} + +bool Scalar::MakeUnsigned() { + bool success = false; + + switch (m_type) { + case e_void: + break; + case e_sint: + success = true; + break; + case e_uint: + m_type = e_uint; + success = true; + break; + case e_slong: + success = true; + break; + case e_ulong: + m_type = e_ulong; + success = true; + break; + case e_slonglong: + success = true; + break; + case e_ulonglong: + m_type = e_ulonglong; + success = true; + break; + case e_sint128: + success = true; + break; + case e_uint128: + m_type = e_uint128; + success = true; + break; + case e_sint256: + success = true; + break; + case e_uint256: + m_type = e_uint256; + success = true; + break; + case e_float: + success = true; + break; + case e_double: + success = true; + break; + case e_long_double: + success = true; + break; + } + + return success; +} + +signed char Scalar::SChar(char fail_value) const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return (schar_t)(m_integer.sextOrTrunc(sizeof(schar_t) * 8)).getSExtValue(); + case e_float: + return (schar_t)m_float.convertToFloat(); + case e_double: + return (schar_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return (schar_t)(ldbl_val.sextOrTrunc(sizeof(schar_t) * 8)).getSExtValue(); + } + return fail_value; +} + +unsigned char Scalar::UChar(unsigned char fail_value) const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return (uchar_t)(m_integer.zextOrTrunc(sizeof(uchar_t) * 8)).getZExtValue(); + case e_float: + return (uchar_t)m_float.convertToFloat(); + case e_double: + return (uchar_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return (uchar_t)(ldbl_val.zextOrTrunc(sizeof(uchar_t) * 8)).getZExtValue(); + } + return fail_value; +} + +short Scalar::SShort(short fail_value) const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return (sshort_t)(m_integer.sextOrTrunc(sizeof(sshort_t) * 8)) + .getSExtValue(); + case e_float: + return (sshort_t)m_float.convertToFloat(); + case e_double: + return (sshort_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return (sshort_t)(ldbl_val.sextOrTrunc(sizeof(sshort_t) * 8)) + .getSExtValue(); + } + return fail_value; +} + +unsigned short Scalar::UShort(unsigned short fail_value) const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return (ushort_t)(m_integer.zextOrTrunc(sizeof(ushort_t) * 8)) + .getZExtValue(); + case e_float: + return (ushort_t)m_float.convertToFloat(); + case e_double: + return (ushort_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return (ushort_t)(ldbl_val.zextOrTrunc(sizeof(ushort_t) * 8)) + .getZExtValue(); + } + return fail_value; +} + +int Scalar::SInt(int fail_value) const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return (sint_t)(m_integer.sextOrTrunc(sizeof(sint_t) * 8)).getSExtValue(); + case e_float: + return (sint_t)m_float.convertToFloat(); + case e_double: + return (sint_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return (sint_t)(ldbl_val.sextOrTrunc(sizeof(sint_t) * 8)).getSExtValue(); + } + return fail_value; +} + +unsigned int Scalar::UInt(unsigned int fail_value) const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return (uint_t)(m_integer.zextOrTrunc(sizeof(uint_t) * 8)).getZExtValue(); + case e_float: + return (uint_t)m_float.convertToFloat(); + case e_double: + return (uint_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return (uint_t)(ldbl_val.zextOrTrunc(sizeof(uint_t) * 8)).getZExtValue(); + } + return fail_value; +} + +long Scalar::SLong(long fail_value) const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return (slong_t)(m_integer.sextOrTrunc(sizeof(slong_t) * 8)).getSExtValue(); + case e_float: + return (slong_t)m_float.convertToFloat(); + case e_double: + return (slong_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return (slong_t)(ldbl_val.sextOrTrunc(sizeof(slong_t) * 8)).getSExtValue(); + } + return fail_value; +} + +unsigned long Scalar::ULong(unsigned long fail_value) const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return (ulong_t)(m_integer.zextOrTrunc(sizeof(ulong_t) * 8)).getZExtValue(); + case e_float: + return (ulong_t)m_float.convertToFloat(); + case e_double: + return (ulong_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return (ulong_t)(ldbl_val.zextOrTrunc(sizeof(ulong_t) * 8)).getZExtValue(); + } + return fail_value; +} + +long long Scalar::SLongLong(long long fail_value) const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return (slonglong_t)(m_integer.sextOrTrunc(sizeof(slonglong_t) * 8)) + .getSExtValue(); + case e_float: + return (slonglong_t)m_float.convertToFloat(); + case e_double: + return (slonglong_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return (slonglong_t)(ldbl_val.sextOrTrunc(sizeof(slonglong_t) * 8)) + .getSExtValue(); + } + return fail_value; +} + +unsigned long long Scalar::ULongLong(unsigned long long fail_value) const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return (ulonglong_t)(m_integer.zextOrTrunc(sizeof(ulonglong_t) * 8)) + .getZExtValue(); + case e_float: + return (ulonglong_t)m_float.convertToFloat(); + case e_double: + return (ulonglong_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return (ulonglong_t)(ldbl_val.zextOrTrunc(sizeof(ulonglong_t) * 8)) + .getZExtValue(); + } + return fail_value; +} + +llvm::APInt Scalar::SInt128(llvm::APInt &fail_value) const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return m_integer; + case e_float: + case e_double: + case e_long_double: + return m_float.bitcastToAPInt(); + } + return fail_value; +} + +llvm::APInt Scalar::UInt128(const llvm::APInt &fail_value) const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return m_integer; + case e_float: + case e_double: + case e_long_double: + return m_float.bitcastToAPInt(); + } + return fail_value; +} + +llvm::APInt Scalar::SInt256(llvm::APInt &fail_value) const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return m_integer; + case e_float: + case e_double: + case e_long_double: + return m_float.bitcastToAPInt(); + } + return fail_value; +} + +llvm::APInt Scalar::UInt256(const llvm::APInt &fail_value) const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return m_integer; + case e_float: + case e_double: + case e_long_double: + return m_float.bitcastToAPInt(); + } + return fail_value; +} + +float Scalar::Float(float fail_value) const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return m_integer.bitsToFloat(); + case e_float: + return m_float.convertToFloat(); + case e_double: + return (float_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return ldbl_val.bitsToFloat(); + } + return fail_value; +} + +double Scalar::Double(double fail_value) const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return m_integer.bitsToDouble(); + case e_float: + return (double_t)m_float.convertToFloat(); + case e_double: + return m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return ldbl_val.bitsToFloat(); + } + return fail_value; +} + +long double Scalar::LongDouble(long double fail_value) const { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + return (long_double_t)m_integer.bitsToDouble(); + case e_float: + return (long_double_t)m_float.convertToFloat(); + case e_double: + return (long_double_t)m_float.convertToDouble(); + case e_long_double: + llvm::APInt ldbl_val = m_float.bitcastToAPInt(); + return (long_double_t)ldbl_val.bitsToDouble(); + } + return fail_value; +} + +Scalar &Scalar::operator+=(const Scalar &rhs) { + Scalar temp_value; + const Scalar *a; + const Scalar *b; + if ((m_type = PromoteToMaxType(*this, rhs, temp_value, a, b)) != + Scalar::e_void) { + switch (m_type) { + case e_void: + break; case e_sint: case e_uint: case e_slong: @@ -1885,92 +1909,45 @@ Scalar::operator<<= (const Scalar& rhs) case e_uint128: case e_sint256: case e_uint256: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: - case e_uint256: - m_integer = m_integer << rhs.m_integer; - break; - } - break; - } - return *this; -} + m_integer = a->m_integer + b->m_integer; + break; -bool -Scalar::ShiftRightLogical(const Scalar& rhs) -{ - switch (m_type) - { - case e_void: case e_float: case e_double: case e_long_double: - m_type = e_void; - break; - - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: - case e_uint256: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: - case e_uint256: - m_integer = m_integer.lshr(rhs.m_integer); - break; - } - break; + m_float = a->m_float + b->m_float; + break; } - return m_type != e_void; -} - -Scalar& -Scalar::operator>>= (const Scalar& rhs) -{ - switch (m_type) - { + } + return *this; +} + +Scalar &Scalar::operator<<=(const Scalar &rhs) { + switch (m_type) { + case e_void: + case e_float: + case e_double: + case e_long_double: + m_type = e_void; + break; + + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + switch (rhs.m_type) { case e_void: case e_float: case e_double: case e_long_double: - m_type = e_void; - break; - + m_type = e_void; + break; case e_sint: case e_uint: case e_slong: @@ -1981,44 +1958,40 @@ Scalar::operator>>= (const Scalar& rhs) case e_uint128: case e_sint256: case e_uint256: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: - case e_uint256: - m_integer = m_integer.ashr(rhs.m_integer); - break; - } - break; + m_integer = m_integer << rhs.m_integer; + break; } - return *this; -} - -Scalar& -Scalar::operator&= (const Scalar& rhs) -{ - switch (m_type) - { + break; + } + return *this; +} + +bool Scalar::ShiftRightLogical(const Scalar &rhs) { + switch (m_type) { + case e_void: + case e_float: + case e_double: + case e_long_double: + m_type = e_void; + break; + + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + switch (rhs.m_type) { case e_void: case e_float: case e_double: case e_long_double: - m_type = e_void; - break; - + m_type = e_void; + break; case e_sint: case e_uint: case e_slong: @@ -2029,69 +2002,40 @@ Scalar::operator&= (const Scalar& rhs) case e_uint128: case e_sint256: case e_uint256: - switch (rhs.m_type) - { - case e_void: - case e_float: - case e_double: - case e_long_double: - m_type = e_void; - break; - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: - case e_uint256: - m_integer &= rhs.m_integer; - break; - } - break; + m_integer = m_integer.lshr(rhs.m_integer); + break; } - return *this; -} - -bool -Scalar::AbsoluteValue() -{ - switch (m_type) - { + break; + } + return m_type != e_void; +} + +Scalar &Scalar::operator>>=(const Scalar &rhs) { + switch (m_type) { + case e_void: + case e_float: + case e_double: + case e_long_double: + m_type = e_void; + break; + + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + switch (rhs.m_type) { case e_void: - break; - - case e_sint: - case e_slong: - case e_slonglong: - case e_sint128: - case e_sint256: - if (m_integer.isNegative()) - m_integer = -m_integer; - return true; - - case e_uint: - case e_ulong: - case e_ulonglong: return true; - case e_uint128: - case e_uint256: case e_float: case e_double: case e_long_double: - m_float.clearSign(); - return true; - } - return false; -} - -bool -Scalar::UnaryNegate() -{ - switch (m_type) - { - case e_void: break; + m_type = e_void; + break; case e_sint: case e_uint: case e_slong: @@ -2102,20 +2046,40 @@ Scalar::UnaryNegate() case e_uint128: case e_sint256: case e_uint256: - m_integer = -m_integer; return true; + m_integer = m_integer.ashr(rhs.m_integer); + break; + } + break; + } + return *this; +} + +Scalar &Scalar::operator&=(const Scalar &rhs) { + switch (m_type) { + case e_void: + case e_float: + case e_double: + case e_long_double: + m_type = e_void; + break; + + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + switch (rhs.m_type) { + case e_void: case e_float: case e_double: case e_long_double: - m_float.changeSign(); return true; - } - return false; -} - -bool -Scalar::OnesComplement() -{ - switch (m_type) - { + m_type = e_void; + break; case e_sint: case e_uint: case e_slong: @@ -2126,696 +2090,102 @@ Scalar::OnesComplement() case e_uint128: case e_sint256: case e_uint256: - m_integer = ~m_integer; return true; - - case e_void: - case e_float: - case e_double: - case e_long_double: - break; - } - return false; -} - -const Scalar -lldb_private::operator+ (const Scalar& lhs, const Scalar& rhs) -{ - Scalar result; - Scalar temp_value; - const Scalar* a; - const Scalar* b; - if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != Scalar::e_void) - { - switch (result.m_type) - { - case Scalar::e_void: break; - case Scalar::e_sint: - case Scalar::e_uint: - case Scalar::e_slong: - case Scalar::e_ulong: - case Scalar::e_slonglong: - case Scalar::e_ulonglong: - case Scalar::e_sint128: - case Scalar::e_uint128: - case Scalar::e_sint256: - case Scalar::e_uint256: - result.m_integer = a->m_integer + b->m_integer; break; - case Scalar::e_float: - case Scalar::e_double: - case Scalar::e_long_double: - result.m_float = a->m_float + b->m_float; break; - } - } - return result; -} - -const Scalar -lldb_private::operator- (const Scalar& lhs, const Scalar& rhs) -{ - Scalar result; - Scalar temp_value; - const Scalar* a; - const Scalar* b; - if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != Scalar::e_void) - { - switch (result.m_type) - { - case Scalar::e_void: break; - case Scalar::e_sint: - case Scalar::e_uint: - case Scalar::e_slong: - case Scalar::e_ulong: - case Scalar::e_slonglong: - case Scalar::e_ulonglong: - case Scalar::e_sint128: - case Scalar::e_uint128: - case Scalar::e_sint256: - case Scalar::e_uint256: - result.m_integer = a->m_integer - b->m_integer; break; - case Scalar::e_float: - case Scalar::e_double: - case Scalar::e_long_double: - result.m_float = a->m_float - b->m_float; break; - } - } - return result; -} - -const Scalar -lldb_private::operator/ (const Scalar& lhs, const Scalar& rhs) -{ - Scalar result; - Scalar temp_value; - const Scalar* a; - const Scalar* b; - if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != Scalar::e_void) - { - switch (result.m_type) - { - case Scalar::e_void: break; - case Scalar::e_sint: - case Scalar::e_slong: - case Scalar::e_slonglong: - case Scalar::e_sint128: - case Scalar::e_sint256: - if (b->m_integer != 0) - { - result.m_integer = a->m_integer.sdiv(b->m_integer); - return result; - } - break; - case Scalar::e_uint: - case Scalar::e_ulong: - case Scalar::e_ulonglong: - case Scalar::e_uint128: - case Scalar::e_uint256: - if (b->m_integer != 0) - { - result.m_integer = a->m_integer.udiv(b->m_integer); - return result; - } - break; - case Scalar::e_float: - case Scalar::e_double: - case Scalar::e_long_double: - if (b->m_float.isZero()) - { - result.m_float = a->m_float / b->m_float; - return result; - } - break; - } - } - // For division only, the only way it should make it here is if a promotion failed, - // or if we are trying to do a divide by zero. - result.m_type = Scalar::e_void; - return result; -} - -const Scalar -lldb_private::operator* (const Scalar& lhs, const Scalar& rhs) -{ - Scalar result; - Scalar temp_value; - const Scalar* a; - const Scalar* b; - if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != Scalar::e_void) - { - switch (result.m_type) - { - case Scalar::e_void: break; - case Scalar::e_sint: - case Scalar::e_uint: - case Scalar::e_slong: - case Scalar::e_ulong: - case Scalar::e_slonglong: - case Scalar::e_ulonglong: - case Scalar::e_sint128: - case Scalar::e_uint128: - case Scalar::e_sint256: - case Scalar::e_uint256: - result.m_integer = a->m_integer * b->m_integer; break; - case Scalar::e_float: - case Scalar::e_double: - case Scalar::e_long_double: - result.m_float = a->m_float * b->m_float; break; - } + m_integer &= rhs.m_integer; + break; } - return result; -} - -const Scalar -lldb_private::operator& (const Scalar& lhs, const Scalar& rhs) -{ - Scalar result; - Scalar temp_value; - const Scalar* a; - const Scalar* b; - if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != Scalar::e_void) - { - switch (result.m_type) - { - case Scalar::e_sint: - case Scalar::e_uint: - case Scalar::e_slong: - case Scalar::e_ulong: - case Scalar::e_slonglong: - case Scalar::e_ulonglong: - case Scalar::e_sint128: - case Scalar::e_uint128: - case Scalar::e_sint256: - case Scalar::e_uint256: - result.m_integer = a->m_integer & b->m_integer; break; - case Scalar::e_void: - case Scalar::e_float: - case Scalar::e_double: - case Scalar::e_long_double: - // No bitwise AND on floats, doubles of long doubles - result.m_type = Scalar::e_void; - break; - } - } - return result; -} - -const Scalar -lldb_private::operator| (const Scalar& lhs, const Scalar& rhs) -{ - Scalar result; - Scalar temp_value; - const Scalar* a; - const Scalar* b; - if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != Scalar::e_void) - { - switch (result.m_type) - { - case Scalar::e_sint: - case Scalar::e_uint: - case Scalar::e_slong: - case Scalar::e_ulong: - case Scalar::e_slonglong: - case Scalar::e_ulonglong: - case Scalar::e_sint128: - case Scalar::e_uint128: - case Scalar::e_sint256: - case Scalar::e_uint256: - result.m_integer = a->m_integer | b->m_integer; break; - - case Scalar::e_void: - case Scalar::e_float: - case Scalar::e_double: - case Scalar::e_long_double: - // No bitwise AND on floats, doubles of long doubles - result.m_type = Scalar::e_void; - break; - } - } - return result; -} - -const Scalar -lldb_private::operator% (const Scalar& lhs, const Scalar& rhs) -{ - Scalar result; - Scalar temp_value; - const Scalar* a; - const Scalar* b; - if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != Scalar::e_void) - { - switch (result.m_type) - { - default: break; - case Scalar::e_void: break; - case Scalar::e_sint: - case Scalar::e_slong: - case Scalar::e_slonglong: - case Scalar::e_sint128: - case Scalar::e_sint256: - if (b->m_integer != 0) - { - result.m_integer = a->m_integer.srem(b->m_integer); - return result; - } - break; - case Scalar::e_uint: - case Scalar::e_ulong: - case Scalar::e_ulonglong: - case Scalar::e_uint128: - case Scalar::e_uint256: - if (b->m_integer != 0) - { - result.m_integer = a->m_integer.urem(b->m_integer); - return result; - } - break; - } - } - result.m_type = Scalar::e_void; - return result; -} - -const Scalar -lldb_private::operator^ (const Scalar& lhs, const Scalar& rhs) -{ - Scalar result; - Scalar temp_value; - const Scalar* a; - const Scalar* b; - if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != Scalar::e_void) - { - switch (result.m_type) - { - case Scalar::e_sint: - case Scalar::e_uint: - case Scalar::e_slong: - case Scalar::e_ulong: - case Scalar::e_slonglong: - case Scalar::e_ulonglong: - case Scalar::e_sint128: - case Scalar::e_uint128: - case Scalar::e_sint256: - case Scalar::e_uint256: - result.m_integer = a->m_integer ^ b->m_integer; break; - - case Scalar::e_void: - case Scalar::e_float: - case Scalar::e_double: - case Scalar::e_long_double: - // No bitwise AND on floats, doubles of long doubles - result.m_type = Scalar::e_void; - break; - } - } - return result; -} - -const Scalar -lldb_private::operator<< (const Scalar& lhs, const Scalar &rhs) -{ - Scalar result = lhs; - result <<= rhs; - return result; -} - -const Scalar -lldb_private::operator>> (const Scalar& lhs, const Scalar &rhs) -{ - Scalar result = lhs; - result >>= rhs; - return result; -} - -Error -Scalar::SetValueFromCString (const char *value_str, Encoding encoding, size_t byte_size) -{ - Error error; - if (value_str == nullptr || value_str[0] == '\0') - { - error.SetErrorString ("Invalid c-string value string."); - return error; - } - bool success = false; - switch (encoding) - { - case eEncodingInvalid: - error.SetErrorString ("Invalid encoding."); - break; - - case eEncodingUint: - if (byte_size <= sizeof (unsigned long long)) - { - uint64_t uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success); - if (!success) - error.SetErrorStringWithFormat ("'%s' is not a valid unsigned integer string value", value_str); - else if (!UIntValueIsValidForSize (uval64, byte_size)) - error.SetErrorStringWithFormat("value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value", uval64, (uint64_t)byte_size); - else - { - m_type = Scalar::GetValueTypeForUnsignedIntegerWithByteSize (byte_size); - switch (m_type) - { - case e_uint: m_integer = llvm::APInt(sizeof(uint_t) * 8, uval64, false); break; - case e_ulong: m_integer = llvm::APInt(sizeof(ulong_t) * 8, uval64, false); break; - case e_ulonglong: m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, uval64, false); break; - default: - error.SetErrorStringWithFormat("unsupported unsigned integer byte size: %" PRIu64 "", (uint64_t)byte_size); - break; - } - } - } - else - { - error.SetErrorStringWithFormat("unsupported unsigned integer byte size: %" PRIu64 "", (uint64_t)byte_size); - return error; - } - break; - - case eEncodingSint: - if (byte_size <= sizeof (long long)) - { - uint64_t sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success); - if (!success) - error.SetErrorStringWithFormat ("'%s' is not a valid signed integer string value", value_str); - else if (!SIntValueIsValidForSize (sval64, byte_size)) - error.SetErrorStringWithFormat("value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte signed integer value", sval64, (uint64_t)byte_size); - else - { - m_type = Scalar::GetValueTypeForSignedIntegerWithByteSize (byte_size); - switch (m_type) - { - case e_sint: m_integer = llvm::APInt(sizeof(sint_t) * 8, sval64, true); break; - case e_slong: m_integer = llvm::APInt(sizeof(slong_t) * 8, sval64, true); break; - case e_slonglong: m_integer = llvm::APInt(sizeof(slonglong_t) * 8, sval64, true); break; - default: - error.SetErrorStringWithFormat("unsupported signed integer byte size: %" PRIu64 "", (uint64_t)byte_size); - break; - } - } - } - else - { - error.SetErrorStringWithFormat("unsupported signed integer byte size: %" PRIu64 "", (uint64_t)byte_size); - return error; - } - break; - - case eEncodingIEEE754: - static float f_val; - static double d_val; - static long double l_val; - if (byte_size == sizeof (float)) - { - if (::sscanf (value_str, "%f", &f_val) == 1) - { - m_float = llvm::APFloat(f_val); - m_type = e_float; - } - else - error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str); - } - else if (byte_size == sizeof (double)) - { - if (::sscanf (value_str, "%lf", &d_val) == 1) - { - m_float = llvm::APFloat(d_val); - m_type = e_double; - } - else - error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str); - } - else if (byte_size == sizeof (long double)) - { - if (::sscanf (value_str, "%Lf", &l_val) == 1) - { - m_float = llvm::APFloat(llvm::APFloat::x87DoubleExtended, llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, ((type128 *)&l_val)->x)); - m_type = e_long_double; - } - else - error.SetErrorStringWithFormat ("'%s' is not a valid float string value", value_str); - } - else - { - error.SetErrorStringWithFormat("unsupported float byte size: %" PRIu64 "", (uint64_t)byte_size); - return error; - } - break; - - case eEncodingVector: - error.SetErrorString ("vector encoding unsupported."); - break; - } - if (error.Fail()) - m_type = e_void; - - return error; -} - -Error -Scalar::SetValueFromData (DataExtractor &data, lldb::Encoding encoding, size_t byte_size) -{ - Error error; - - type128 int128; - type256 int256; - switch (encoding) - { - case lldb::eEncodingInvalid: - error.SetErrorString ("invalid encoding"); - break; - case lldb::eEncodingVector: - error.SetErrorString ("vector encoding unsupported"); - break; - case lldb::eEncodingUint: - { - lldb::offset_t offset = 0; - - switch (byte_size) - { - case 1: operator=((uint8_t)data.GetU8(&offset)); break; - case 2: operator=((uint16_t)data.GetU16(&offset)); break; - case 4: operator=((uint32_t)data.GetU32(&offset)); break; - case 8: operator=((uint64_t)data.GetU64(&offset)); break; - case 16: - if (data.GetByteOrder() == eByteOrderBig) - { - int128.x[1] = (uint64_t)data.GetU64 (&offset); - int128.x[0] = (uint64_t)data.GetU64 (&offset); - } - else - { - int128.x[0] = (uint64_t)data.GetU64 (&offset); - int128.x[1] = (uint64_t)data.GetU64 (&offset); - } - operator=(llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, int128.x)); - break; - case 32: - if (data.GetByteOrder() == eByteOrderBig) - { - int256.x[3] = (uint64_t)data.GetU64 (&offset); - int256.x[2] = (uint64_t)data.GetU64 (&offset); - int256.x[1] = (uint64_t)data.GetU64 (&offset); - int256.x[0] = (uint64_t)data.GetU64 (&offset); - } - else - { - int256.x[0] = (uint64_t)data.GetU64 (&offset); - int256.x[1] = (uint64_t)data.GetU64 (&offset); - int256.x[2] = (uint64_t)data.GetU64 (&offset); - int256.x[3] = (uint64_t)data.GetU64 (&offset); - } - operator=(llvm::APInt(BITWIDTH_INT256, NUM_OF_WORDS_INT256, int256.x)); - break; - default: - error.SetErrorStringWithFormat("unsupported unsigned integer byte size: %" PRIu64 "", (uint64_t)byte_size); - break; - } - } - break; - case lldb::eEncodingSint: - { - lldb::offset_t offset = 0; - - switch (byte_size) - { - case 1: operator=((int8_t)data.GetU8(&offset)); break; - case 2: operator=((int16_t)data.GetU16(&offset)); break; - case 4: operator=((int32_t)data.GetU32(&offset)); break; - case 8: operator=((int64_t)data.GetU64(&offset)); break; - case 16: - if (data.GetByteOrder() == eByteOrderBig) - { - int128.x[1] = (uint64_t)data.GetU64 (&offset); - int128.x[0] = (uint64_t)data.GetU64 (&offset); - } - else - { - int128.x[0] = (uint64_t)data.GetU64 (&offset); - int128.x[1] = (uint64_t)data.GetU64 (&offset); - } - operator=(llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, int128.x)); - break; - case 32: - if (data.GetByteOrder() == eByteOrderBig) - { - int256.x[3] = (uint64_t)data.GetU64 (&offset); - int256.x[2] = (uint64_t)data.GetU64 (&offset); - int256.x[1] = (uint64_t)data.GetU64 (&offset); - int256.x[0] = (uint64_t)data.GetU64 (&offset); - } - else - { - int256.x[0] = (uint64_t)data.GetU64 (&offset); - int256.x[1] = (uint64_t)data.GetU64 (&offset); - int256.x[2] = (uint64_t)data.GetU64 (&offset); - int256.x[3] = (uint64_t)data.GetU64 (&offset); - } - operator=(llvm::APInt(BITWIDTH_INT256, NUM_OF_WORDS_INT256, int256.x)); - break; - default: - error.SetErrorStringWithFormat("unsupported signed integer byte size: %" PRIu64 "", (uint64_t)byte_size); - break; - } - } - break; - case lldb::eEncodingIEEE754: - { - lldb::offset_t offset = 0; - - if (byte_size == sizeof (float)) - operator=((float)data.GetFloat(&offset)); - else if (byte_size == sizeof (double)) - operator=((double)data.GetDouble(&offset)); - else if (byte_size == sizeof (long double)) - operator=((long double)data.GetLongDouble(&offset)); - else - error.SetErrorStringWithFormat("unsupported float byte size: %" PRIu64 "", (uint64_t)byte_size); - } - break; - } - - return error; -} - -bool -Scalar::SignExtend (uint32_t sign_bit_pos) -{ - const uint32_t max_bit_pos = GetByteSize() * 8; - - if (sign_bit_pos < max_bit_pos) - { - switch (m_type) - { - case Scalar::e_void: - case Scalar::e_float: - case Scalar::e_double: - case Scalar::e_long_double: - return false; - - case Scalar::e_sint: - case Scalar::e_uint: - case Scalar::e_slong: - case Scalar::e_ulong: - case Scalar::e_slonglong: - case Scalar::e_ulonglong: - case Scalar::e_sint128: - case Scalar::e_uint128: - case Scalar::e_sint256: - case Scalar::e_uint256: - if (max_bit_pos == sign_bit_pos) - return true; - else if (sign_bit_pos < (max_bit_pos-1)) - { - llvm::APInt sign_bit = llvm::APInt::getSignBit(sign_bit_pos + 1); - llvm::APInt bitwize_and = m_integer & sign_bit; - if (bitwize_and.getBoolValue()) - { - const llvm::APInt mask = ~(sign_bit) + llvm::APInt(m_integer.getBitWidth(), 1); - m_integer |= mask; - } - return true; - } - break; - } - } - return false; -} - -size_t -Scalar::GetAsMemoryData (void *dst, - size_t dst_len, - lldb::ByteOrder dst_byte_order, - Error &error) const -{ - // Get a data extractor that points to the native scalar data - DataExtractor data; - if (!GetData(data)) - { - error.SetErrorString ("invalid scalar value"); - return 0; - } - - const size_t src_len = data.GetByteSize(); - - // Prepare a memory buffer that contains some or all of the register value - const size_t bytes_copied = data.CopyByteOrderedData (0, // src offset - src_len, // src length - dst, // dst buffer - dst_len, // dst length - dst_byte_order); // dst byte order - if (bytes_copied == 0) - error.SetErrorString ("failed to copy data"); - - return bytes_copied; -} - -bool -Scalar::ExtractBitfield (uint32_t bit_size, - uint32_t bit_offset) -{ - if (bit_size == 0) - return true; + break; + } + return *this; +} + +bool Scalar::AbsoluteValue() { + switch (m_type) { + case e_void: + break; + + case e_sint: + case e_slong: + case e_slonglong: + case e_sint128: + case e_sint256: + if (m_integer.isNegative()) + m_integer = -m_integer; + return true; - switch (m_type) - { - case Scalar::e_void: - case Scalar::e_float: - case Scalar::e_double: - case Scalar::e_long_double: - break; - - case Scalar::e_sint: - case Scalar::e_slong: - case Scalar::e_slonglong: - case Scalar::e_sint128: - case Scalar::e_sint256: - m_integer = m_integer.ashr(bit_offset).sextOrTrunc(bit_size).sextOrSelf(8 * GetByteSize()); - return true; - - case Scalar::e_uint: - case Scalar::e_ulong: - case Scalar::e_ulonglong: - case Scalar::e_uint128: - case Scalar::e_uint256: - m_integer = m_integer.lshr(bit_offset).zextOrTrunc(bit_size).zextOrSelf(8 * GetByteSize()); - return true; - } - return false; -} + case e_uint: + case e_ulong: + case e_ulonglong: + return true; + case e_uint128: + case e_uint256: + case e_float: + case e_double: + case e_long_double: + m_float.clearSign(); + return true; + } + return false; +} + +bool Scalar::UnaryNegate() { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + m_integer = -m_integer; + return true; + case e_float: + case e_double: + case e_long_double: + m_float.changeSign(); + return true; + } + return false; +} + +bool Scalar::OnesComplement() { + switch (m_type) { + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + m_integer = ~m_integer; + return true; -bool -lldb_private::operator== (const Scalar& lhs, const Scalar& rhs) -{ - // If either entry is void then we can just compare the types - if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void) - return lhs.m_type == rhs.m_type; - - Scalar temp_value; - const Scalar* a; - const Scalar* b; - llvm::APFloat::cmpResult result; - switch (PromoteToMaxType(lhs, rhs, temp_value, a, b)) - { - case Scalar::e_void: break; + case e_void: + case e_float: + case e_double: + case e_long_double: + break; + } + return false; +} + +const Scalar lldb_private::operator+(const Scalar &lhs, const Scalar &rhs) { + Scalar result; + Scalar temp_value; + const Scalar *a; + const Scalar *b; + if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != + Scalar::e_void) { + switch (result.m_type) { + case Scalar::e_void: + break; case Scalar::e_sint: case Scalar::e_uint: case Scalar::e_slong: @@ -2826,31 +2196,28 @@ lldb_private::operator== (const Scalar& lhs, const Scalar& rhs) case Scalar::e_uint128: case Scalar::e_sint256: case Scalar::e_uint256: - return a->m_integer == b->m_integer; + result.m_integer = a->m_integer + b->m_integer; + break; case Scalar::e_float: case Scalar::e_double: case Scalar::e_long_double: - result = a->m_float.compare(b->m_float); - if(result == llvm::APFloat::cmpEqual) - return true; + result.m_float = a->m_float + b->m_float; + break; } - return false; -} - -bool -lldb_private::operator!= (const Scalar& lhs, const Scalar& rhs) -{ - // If either entry is void then we can just compare the types - if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void) - return lhs.m_type != rhs.m_type; - - Scalar temp_value; // A temp value that might get a copy of either promoted value - const Scalar* a; - const Scalar* b; - llvm::APFloat::cmpResult result; - switch (PromoteToMaxType(lhs, rhs, temp_value, a, b)) - { - case Scalar::e_void: break; + } + return result; +} + +const Scalar lldb_private::operator-(const Scalar &lhs, const Scalar &rhs) { + Scalar result; + Scalar temp_value; + const Scalar *a; + const Scalar *b; + if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != + Scalar::e_void) { + switch (result.m_type) { + case Scalar::e_void: + break; case Scalar::e_sint: case Scalar::e_uint: case Scalar::e_slong: @@ -2861,202 +2228,849 @@ lldb_private::operator!= (const Scalar& lhs, const Scalar& rhs) case Scalar::e_uint128: case Scalar::e_sint256: case Scalar::e_uint256: - return a->m_integer != b->m_integer; + result.m_integer = a->m_integer - b->m_integer; + break; case Scalar::e_float: case Scalar::e_double: case Scalar::e_long_double: - result = a->m_float.compare(b->m_float); - if(result != llvm::APFloat::cmpEqual) - return true; + result.m_float = a->m_float - b->m_float; + break; } - return true; -} - -bool -lldb_private::operator< (const Scalar& lhs, const Scalar& rhs) -{ - if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void) - return false; - - Scalar temp_value; - const Scalar* a; - const Scalar* b; - llvm::APFloat::cmpResult result; - switch (PromoteToMaxType(lhs, rhs, temp_value, a, b)) - { - case Scalar::e_void: break; + } + return result; +} + +const Scalar lldb_private::operator/(const Scalar &lhs, const Scalar &rhs) { + Scalar result; + Scalar temp_value; + const Scalar *a; + const Scalar *b; + if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != + Scalar::e_void) { + switch (result.m_type) { + case Scalar::e_void: + break; case Scalar::e_sint: case Scalar::e_slong: case Scalar::e_slonglong: case Scalar::e_sint128: case Scalar::e_sint256: - return a->m_integer.slt(b->m_integer); + if (b->m_integer != 0) { + result.m_integer = a->m_integer.sdiv(b->m_integer); + return result; + } + break; case Scalar::e_uint: case Scalar::e_ulong: case Scalar::e_ulonglong: case Scalar::e_uint128: case Scalar::e_uint256: - return a->m_integer.ult(b->m_integer); + if (b->m_integer != 0) { + result.m_integer = a->m_integer.udiv(b->m_integer); + return result; + } + break; case Scalar::e_float: case Scalar::e_double: case Scalar::e_long_double: - result = a->m_float.compare(b->m_float); - if(result == llvm::APFloat::cmpLessThan) - return true; + if (b->m_float.isZero()) { + result.m_float = a->m_float / b->m_float; + return result; + } + break; } - return false; -} - -bool -lldb_private::operator<= (const Scalar& lhs, const Scalar& rhs) -{ - if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void) - return false; + } + // For division only, the only way it should make it here is if a promotion + // failed, + // or if we are trying to do a divide by zero. + result.m_type = Scalar::e_void; + return result; +} + +const Scalar lldb_private::operator*(const Scalar &lhs, const Scalar &rhs) { + Scalar result; + Scalar temp_value; + const Scalar *a; + const Scalar *b; + if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != + Scalar::e_void) { + switch (result.m_type) { + case Scalar::e_void: + break; + case Scalar::e_sint: + case Scalar::e_uint: + case Scalar::e_slong: + case Scalar::e_ulong: + case Scalar::e_slonglong: + case Scalar::e_ulonglong: + case Scalar::e_sint128: + case Scalar::e_uint128: + case Scalar::e_sint256: + case Scalar::e_uint256: + result.m_integer = a->m_integer * b->m_integer; + break; + case Scalar::e_float: + case Scalar::e_double: + case Scalar::e_long_double: + result.m_float = a->m_float * b->m_float; + break; + } + } + return result; +} + +const Scalar lldb_private::operator&(const Scalar &lhs, const Scalar &rhs) { + Scalar result; + Scalar temp_value; + const Scalar *a; + const Scalar *b; + if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != + Scalar::e_void) { + switch (result.m_type) { + case Scalar::e_sint: + case Scalar::e_uint: + case Scalar::e_slong: + case Scalar::e_ulong: + case Scalar::e_slonglong: + case Scalar::e_ulonglong: + case Scalar::e_sint128: + case Scalar::e_uint128: + case Scalar::e_sint256: + case Scalar::e_uint256: + result.m_integer = a->m_integer & b->m_integer; + break; + case Scalar::e_void: + case Scalar::e_float: + case Scalar::e_double: + case Scalar::e_long_double: + // No bitwise AND on floats, doubles of long doubles + result.m_type = Scalar::e_void; + break; + } + } + return result; +} + +const Scalar lldb_private::operator|(const Scalar &lhs, const Scalar &rhs) { + Scalar result; + Scalar temp_value; + const Scalar *a; + const Scalar *b; + if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != + Scalar::e_void) { + switch (result.m_type) { + case Scalar::e_sint: + case Scalar::e_uint: + case Scalar::e_slong: + case Scalar::e_ulong: + case Scalar::e_slonglong: + case Scalar::e_ulonglong: + case Scalar::e_sint128: + case Scalar::e_uint128: + case Scalar::e_sint256: + case Scalar::e_uint256: + result.m_integer = a->m_integer | b->m_integer; + break; - Scalar temp_value; - const Scalar* a; - const Scalar* b; - llvm::APFloat::cmpResult result; - switch (PromoteToMaxType(lhs, rhs, temp_value, a, b)) - { - case Scalar::e_void: break; + case Scalar::e_void: + case Scalar::e_float: + case Scalar::e_double: + case Scalar::e_long_double: + // No bitwise AND on floats, doubles of long doubles + result.m_type = Scalar::e_void; + break; + } + } + return result; +} + +const Scalar lldb_private::operator%(const Scalar &lhs, const Scalar &rhs) { + Scalar result; + Scalar temp_value; + const Scalar *a; + const Scalar *b; + if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != + Scalar::e_void) { + switch (result.m_type) { + default: + break; + case Scalar::e_void: + break; case Scalar::e_sint: case Scalar::e_slong: case Scalar::e_slonglong: case Scalar::e_sint128: case Scalar::e_sint256: - return a->m_integer.sle(b->m_integer); + if (b->m_integer != 0) { + result.m_integer = a->m_integer.srem(b->m_integer); + return result; + } + break; + case Scalar::e_uint: + case Scalar::e_ulong: + case Scalar::e_ulonglong: + case Scalar::e_uint128: + case Scalar::e_uint256: + if (b->m_integer != 0) { + result.m_integer = a->m_integer.urem(b->m_integer); + return result; + } + break; + } + } + result.m_type = Scalar::e_void; + return result; +} + +const Scalar lldb_private::operator^(const Scalar &lhs, const Scalar &rhs) { + Scalar result; + Scalar temp_value; + const Scalar *a; + const Scalar *b; + if ((result.m_type = PromoteToMaxType(lhs, rhs, temp_value, a, b)) != + Scalar::e_void) { + switch (result.m_type) { + case Scalar::e_sint: case Scalar::e_uint: + case Scalar::e_slong: case Scalar::e_ulong: + case Scalar::e_slonglong: case Scalar::e_ulonglong: + case Scalar::e_sint128: case Scalar::e_uint128: + case Scalar::e_sint256: case Scalar::e_uint256: - return a->m_integer.ule(b->m_integer); + result.m_integer = a->m_integer ^ b->m_integer; + break; + + case Scalar::e_void: case Scalar::e_float: case Scalar::e_double: case Scalar::e_long_double: - result = a->m_float.compare(b->m_float); - if(result == llvm::APFloat::cmpLessThan || result == llvm::APFloat::cmpEqual) - return true; + // No bitwise AND on floats, doubles of long doubles + result.m_type = Scalar::e_void; + break; } - return false; + } + return result; } -bool -lldb_private::operator> (const Scalar& lhs, const Scalar& rhs) -{ - if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void) - return false; - - Scalar temp_value; - const Scalar* a; - const Scalar* b; - llvm::APFloat::cmpResult result; - switch (PromoteToMaxType(lhs, rhs, temp_value, a, b)) - { - case Scalar::e_void: break; - case Scalar::e_sint: - case Scalar::e_slong: - case Scalar::e_slonglong: - case Scalar::e_sint128: - case Scalar::e_sint256: - return a->m_integer.sgt(b->m_integer); - case Scalar::e_uint: - case Scalar::e_ulong: - case Scalar::e_ulonglong: - case Scalar::e_uint128: - case Scalar::e_uint256: - return a->m_integer.ugt(b->m_integer); - case Scalar::e_float: - case Scalar::e_double: - case Scalar::e_long_double: - result = a->m_float.compare(b->m_float); - if(result == llvm::APFloat::cmpGreaterThan) - return true; - } - return false; +const Scalar lldb_private::operator<<(const Scalar &lhs, const Scalar &rhs) { + Scalar result = lhs; + result <<= rhs; + return result; } -bool -lldb_private::operator>= (const Scalar& lhs, const Scalar& rhs) -{ - if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void) - return false; - - Scalar temp_value; - const Scalar* a; - const Scalar* b; - llvm::APFloat::cmpResult result; - switch (PromoteToMaxType(lhs, rhs, temp_value, a, b)) - { - case Scalar::e_void: break; - case Scalar::e_sint: - case Scalar::e_slong: - case Scalar::e_slonglong: - case Scalar::e_sint128: - case Scalar::e_sint256: - return a->m_integer.sge(b->m_integer); - case Scalar::e_uint: - case Scalar::e_ulong: - case Scalar::e_ulonglong: - case Scalar::e_uint128: - case Scalar::e_uint256: - return a->m_integer.uge(b->m_integer); - case Scalar::e_float: - case Scalar::e_double: - case Scalar::e_long_double: - result = a->m_float.compare(b->m_float); - if(result == llvm::APFloat::cmpGreaterThan || result == llvm::APFloat::cmpEqual) - return true; - } - return false; +const Scalar lldb_private::operator>>(const Scalar &lhs, const Scalar &rhs) { + Scalar result = lhs; + result >>= rhs; + return result; } -bool -Scalar::ClearBit (uint32_t bit) -{ - switch (m_type) - { - case e_void: - break; - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: - case e_uint256: m_integer.clearBit(bit); return true; - case e_float: - case e_double: - case e_long_double: break; +Error Scalar::SetValueFromCString(const char *value_str, Encoding encoding, + size_t byte_size) { + Error error; + if (value_str == nullptr || value_str[0] == '\0') { + error.SetErrorString("Invalid c-string value string."); + return error; + } + bool success = false; + switch (encoding) { + case eEncodingInvalid: + error.SetErrorString("Invalid encoding."); + break; + + case eEncodingUint: + if (byte_size <= sizeof(unsigned long long)) { + uint64_t uval64 = + StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success); + if (!success) + error.SetErrorStringWithFormat( + "'%s' is not a valid unsigned integer string value", value_str); + else if (!UIntValueIsValidForSize(uval64, byte_size)) + error.SetErrorStringWithFormat("value 0x%" PRIx64 + " is too large to fit in a %" PRIu64 + " byte unsigned integer value", + uval64, (uint64_t)byte_size); + else { + m_type = Scalar::GetValueTypeForUnsignedIntegerWithByteSize(byte_size); + switch (m_type) { + case e_uint: + m_integer = llvm::APInt(sizeof(uint_t) * 8, uval64, false); + break; + case e_ulong: + m_integer = llvm::APInt(sizeof(ulong_t) * 8, uval64, false); + break; + case e_ulonglong: + m_integer = llvm::APInt(sizeof(ulonglong_t) * 8, uval64, false); + break; + default: + error.SetErrorStringWithFormat( + "unsupported unsigned integer byte size: %" PRIu64 "", + (uint64_t)byte_size); + break; + } + } + } else { + error.SetErrorStringWithFormat( + "unsupported unsigned integer byte size: %" PRIu64 "", + (uint64_t)byte_size); + return error; } - return false; + break; + + case eEncodingSint: + if (byte_size <= sizeof(long long)) { + uint64_t sval64 = + StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success); + if (!success) + error.SetErrorStringWithFormat( + "'%s' is not a valid signed integer string value", value_str); + else if (!SIntValueIsValidForSize(sval64, byte_size)) + error.SetErrorStringWithFormat("value 0x%" PRIx64 + " is too large to fit in a %" PRIu64 + " byte signed integer value", + sval64, (uint64_t)byte_size); + else { + m_type = Scalar::GetValueTypeForSignedIntegerWithByteSize(byte_size); + switch (m_type) { + case e_sint: + m_integer = llvm::APInt(sizeof(sint_t) * 8, sval64, true); + break; + case e_slong: + m_integer = llvm::APInt(sizeof(slong_t) * 8, sval64, true); + break; + case e_slonglong: + m_integer = llvm::APInt(sizeof(slonglong_t) * 8, sval64, true); + break; + default: + error.SetErrorStringWithFormat( + "unsupported signed integer byte size: %" PRIu64 "", + (uint64_t)byte_size); + break; + } + } + } else { + error.SetErrorStringWithFormat( + "unsupported signed integer byte size: %" PRIu64 "", + (uint64_t)byte_size); + return error; + } + break; + + case eEncodingIEEE754: + static float f_val; + static double d_val; + static long double l_val; + if (byte_size == sizeof(float)) { + if (::sscanf(value_str, "%f", &f_val) == 1) { + m_float = llvm::APFloat(f_val); + m_type = e_float; + } else + error.SetErrorStringWithFormat("'%s' is not a valid float string value", + value_str); + } else if (byte_size == sizeof(double)) { + if (::sscanf(value_str, "%lf", &d_val) == 1) { + m_float = llvm::APFloat(d_val); + m_type = e_double; + } else + error.SetErrorStringWithFormat("'%s' is not a valid float string value", + value_str); + } else if (byte_size == sizeof(long double)) { + if (::sscanf(value_str, "%Lf", &l_val) == 1) { + m_float = + llvm::APFloat(llvm::APFloat::x87DoubleExtended(), + llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, + ((type128 *)&l_val)->x)); + m_type = e_long_double; + } else + error.SetErrorStringWithFormat("'%s' is not a valid float string value", + value_str); + } else { + error.SetErrorStringWithFormat("unsupported float byte size: %" PRIu64 "", + (uint64_t)byte_size); + return error; + } + break; + + case eEncodingVector: + error.SetErrorString("vector encoding unsupported."); + break; + } + if (error.Fail()) + m_type = e_void; + + return error; +} + +Error Scalar::SetValueFromData(DataExtractor &data, lldb::Encoding encoding, + size_t byte_size) { + Error error; + + type128 int128; + type256 int256; + switch (encoding) { + case lldb::eEncodingInvalid: + error.SetErrorString("invalid encoding"); + break; + case lldb::eEncodingVector: + error.SetErrorString("vector encoding unsupported"); + break; + case lldb::eEncodingUint: { + lldb::offset_t offset = 0; + + switch (byte_size) { + case 1: + operator=((uint8_t)data.GetU8(&offset)); + break; + case 2: + operator=((uint16_t)data.GetU16(&offset)); + break; + case 4: + operator=((uint32_t)data.GetU32(&offset)); + break; + case 8: + operator=((uint64_t)data.GetU64(&offset)); + break; + case 16: + if (data.GetByteOrder() == eByteOrderBig) { + int128.x[1] = (uint64_t)data.GetU64(&offset); + int128.x[0] = (uint64_t)data.GetU64(&offset); + } else { + int128.x[0] = (uint64_t)data.GetU64(&offset); + int128.x[1] = (uint64_t)data.GetU64(&offset); + } + operator=(llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, int128.x)); + break; + case 32: + if (data.GetByteOrder() == eByteOrderBig) { + int256.x[3] = (uint64_t)data.GetU64(&offset); + int256.x[2] = (uint64_t)data.GetU64(&offset); + int256.x[1] = (uint64_t)data.GetU64(&offset); + int256.x[0] = (uint64_t)data.GetU64(&offset); + } else { + int256.x[0] = (uint64_t)data.GetU64(&offset); + int256.x[1] = (uint64_t)data.GetU64(&offset); + int256.x[2] = (uint64_t)data.GetU64(&offset); + int256.x[3] = (uint64_t)data.GetU64(&offset); + } + operator=(llvm::APInt(BITWIDTH_INT256, NUM_OF_WORDS_INT256, int256.x)); + break; + default: + error.SetErrorStringWithFormat( + "unsupported unsigned integer byte size: %" PRIu64 "", + (uint64_t)byte_size); + break; + } + } break; + case lldb::eEncodingSint: { + lldb::offset_t offset = 0; + + switch (byte_size) { + case 1: + operator=((int8_t)data.GetU8(&offset)); + break; + case 2: + operator=((int16_t)data.GetU16(&offset)); + break; + case 4: + operator=((int32_t)data.GetU32(&offset)); + break; + case 8: + operator=((int64_t)data.GetU64(&offset)); + break; + case 16: + if (data.GetByteOrder() == eByteOrderBig) { + int128.x[1] = (uint64_t)data.GetU64(&offset); + int128.x[0] = (uint64_t)data.GetU64(&offset); + } else { + int128.x[0] = (uint64_t)data.GetU64(&offset); + int128.x[1] = (uint64_t)data.GetU64(&offset); + } + operator=(llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, int128.x)); + break; + case 32: + if (data.GetByteOrder() == eByteOrderBig) { + int256.x[3] = (uint64_t)data.GetU64(&offset); + int256.x[2] = (uint64_t)data.GetU64(&offset); + int256.x[1] = (uint64_t)data.GetU64(&offset); + int256.x[0] = (uint64_t)data.GetU64(&offset); + } else { + int256.x[0] = (uint64_t)data.GetU64(&offset); + int256.x[1] = (uint64_t)data.GetU64(&offset); + int256.x[2] = (uint64_t)data.GetU64(&offset); + int256.x[3] = (uint64_t)data.GetU64(&offset); + } + operator=(llvm::APInt(BITWIDTH_INT256, NUM_OF_WORDS_INT256, int256.x)); + break; + default: + error.SetErrorStringWithFormat( + "unsupported signed integer byte size: %" PRIu64 "", + (uint64_t)byte_size); + break; + } + } break; + case lldb::eEncodingIEEE754: { + lldb::offset_t offset = 0; + + if (byte_size == sizeof(float)) + operator=((float)data.GetFloat(&offset)); + else if (byte_size == sizeof(double)) + operator=((double)data.GetDouble(&offset)); + else if (byte_size == sizeof(long double)) + operator=((long double)data.GetLongDouble(&offset)); + else + error.SetErrorStringWithFormat("unsupported float byte size: %" PRIu64 "", + (uint64_t)byte_size); + } break; + } + + return error; } -bool -Scalar::SetBit (uint32_t bit) -{ - switch (m_type) - { - case e_void: - break; - case e_sint: - case e_uint: - case e_slong: - case e_ulong: - case e_slonglong: - case e_ulonglong: - case e_sint128: - case e_uint128: - case e_sint256: - case e_uint256: m_integer.setBit(bit); return true; - case e_float: - case e_double: - case e_long_double: break; +bool Scalar::SignExtend(uint32_t sign_bit_pos) { + const uint32_t max_bit_pos = GetByteSize() * 8; + + if (sign_bit_pos < max_bit_pos) { + switch (m_type) { + case Scalar::e_void: + case Scalar::e_float: + case Scalar::e_double: + case Scalar::e_long_double: + return false; + + case Scalar::e_sint: + case Scalar::e_uint: + case Scalar::e_slong: + case Scalar::e_ulong: + case Scalar::e_slonglong: + case Scalar::e_ulonglong: + case Scalar::e_sint128: + case Scalar::e_uint128: + case Scalar::e_sint256: + case Scalar::e_uint256: + if (max_bit_pos == sign_bit_pos) + return true; + else if (sign_bit_pos < (max_bit_pos - 1)) { + llvm::APInt sign_bit = llvm::APInt::getSignBit(sign_bit_pos + 1); + llvm::APInt bitwize_and = m_integer & sign_bit; + if (bitwize_and.getBoolValue()) { + const llvm::APInt mask = + ~(sign_bit) + llvm::APInt(m_integer.getBitWidth(), 1); + m_integer |= mask; + } + return true; + } + break; } - return false; + } + return false; } +size_t Scalar::GetAsMemoryData(void *dst, size_t dst_len, + lldb::ByteOrder dst_byte_order, + Error &error) const { + // Get a data extractor that points to the native scalar data + DataExtractor data; + if (!GetData(data)) { + error.SetErrorString("invalid scalar value"); + return 0; + } + + const size_t src_len = data.GetByteSize(); + + // Prepare a memory buffer that contains some or all of the register value + const size_t bytes_copied = + data.CopyByteOrderedData(0, // src offset + src_len, // src length + dst, // dst buffer + dst_len, // dst length + dst_byte_order); // dst byte order + if (bytes_copied == 0) + error.SetErrorString("failed to copy data"); + + return bytes_copied; +} + +bool Scalar::ExtractBitfield(uint32_t bit_size, uint32_t bit_offset) { + if (bit_size == 0) + return true; + + switch (m_type) { + case Scalar::e_void: + case Scalar::e_float: + case Scalar::e_double: + case Scalar::e_long_double: + break; + + case Scalar::e_sint: + case Scalar::e_slong: + case Scalar::e_slonglong: + case Scalar::e_sint128: + case Scalar::e_sint256: + m_integer = m_integer.ashr(bit_offset) + .sextOrTrunc(bit_size) + .sextOrSelf(8 * GetByteSize()); + return true; + + case Scalar::e_uint: + case Scalar::e_ulong: + case Scalar::e_ulonglong: + case Scalar::e_uint128: + case Scalar::e_uint256: + m_integer = m_integer.lshr(bit_offset) + .zextOrTrunc(bit_size) + .zextOrSelf(8 * GetByteSize()); + return true; + } + return false; +} + +bool lldb_private::operator==(const Scalar &lhs, const Scalar &rhs) { + // If either entry is void then we can just compare the types + if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void) + return lhs.m_type == rhs.m_type; + + Scalar temp_value; + const Scalar *a; + const Scalar *b; + llvm::APFloat::cmpResult result; + switch (PromoteToMaxType(lhs, rhs, temp_value, a, b)) { + case Scalar::e_void: + break; + case Scalar::e_sint: + case Scalar::e_uint: + case Scalar::e_slong: + case Scalar::e_ulong: + case Scalar::e_slonglong: + case Scalar::e_ulonglong: + case Scalar::e_sint128: + case Scalar::e_uint128: + case Scalar::e_sint256: + case Scalar::e_uint256: + return a->m_integer == b->m_integer; + case Scalar::e_float: + case Scalar::e_double: + case Scalar::e_long_double: + result = a->m_float.compare(b->m_float); + if (result == llvm::APFloat::cmpEqual) + return true; + } + return false; +} + +bool lldb_private::operator!=(const Scalar &lhs, const Scalar &rhs) { + // If either entry is void then we can just compare the types + if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void) + return lhs.m_type != rhs.m_type; + + Scalar + temp_value; // A temp value that might get a copy of either promoted value + const Scalar *a; + const Scalar *b; + llvm::APFloat::cmpResult result; + switch (PromoteToMaxType(lhs, rhs, temp_value, a, b)) { + case Scalar::e_void: + break; + case Scalar::e_sint: + case Scalar::e_uint: + case Scalar::e_slong: + case Scalar::e_ulong: + case Scalar::e_slonglong: + case Scalar::e_ulonglong: + case Scalar::e_sint128: + case Scalar::e_uint128: + case Scalar::e_sint256: + case Scalar::e_uint256: + return a->m_integer != b->m_integer; + case Scalar::e_float: + case Scalar::e_double: + case Scalar::e_long_double: + result = a->m_float.compare(b->m_float); + if (result != llvm::APFloat::cmpEqual) + return true; + } + return true; +} + +bool lldb_private::operator<(const Scalar &lhs, const Scalar &rhs) { + if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void) + return false; + + Scalar temp_value; + const Scalar *a; + const Scalar *b; + llvm::APFloat::cmpResult result; + switch (PromoteToMaxType(lhs, rhs, temp_value, a, b)) { + case Scalar::e_void: + break; + case Scalar::e_sint: + case Scalar::e_slong: + case Scalar::e_slonglong: + case Scalar::e_sint128: + case Scalar::e_sint256: + return a->m_integer.slt(b->m_integer); + case Scalar::e_uint: + case Scalar::e_ulong: + case Scalar::e_ulonglong: + case Scalar::e_uint128: + case Scalar::e_uint256: + return a->m_integer.ult(b->m_integer); + case Scalar::e_float: + case Scalar::e_double: + case Scalar::e_long_double: + result = a->m_float.compare(b->m_float); + if (result == llvm::APFloat::cmpLessThan) + return true; + } + return false; +} + +bool lldb_private::operator<=(const Scalar &lhs, const Scalar &rhs) { + if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void) + return false; + + Scalar temp_value; + const Scalar *a; + const Scalar *b; + llvm::APFloat::cmpResult result; + switch (PromoteToMaxType(lhs, rhs, temp_value, a, b)) { + case Scalar::e_void: + break; + case Scalar::e_sint: + case Scalar::e_slong: + case Scalar::e_slonglong: + case Scalar::e_sint128: + case Scalar::e_sint256: + return a->m_integer.sle(b->m_integer); + case Scalar::e_uint: + case Scalar::e_ulong: + case Scalar::e_ulonglong: + case Scalar::e_uint128: + case Scalar::e_uint256: + return a->m_integer.ule(b->m_integer); + case Scalar::e_float: + case Scalar::e_double: + case Scalar::e_long_double: + result = a->m_float.compare(b->m_float); + if (result == llvm::APFloat::cmpLessThan || + result == llvm::APFloat::cmpEqual) + return true; + } + return false; +} + +bool lldb_private::operator>(const Scalar &lhs, const Scalar &rhs) { + if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void) + return false; + + Scalar temp_value; + const Scalar *a; + const Scalar *b; + llvm::APFloat::cmpResult result; + switch (PromoteToMaxType(lhs, rhs, temp_value, a, b)) { + case Scalar::e_void: + break; + case Scalar::e_sint: + case Scalar::e_slong: + case Scalar::e_slonglong: + case Scalar::e_sint128: + case Scalar::e_sint256: + return a->m_integer.sgt(b->m_integer); + case Scalar::e_uint: + case Scalar::e_ulong: + case Scalar::e_ulonglong: + case Scalar::e_uint128: + case Scalar::e_uint256: + return a->m_integer.ugt(b->m_integer); + case Scalar::e_float: + case Scalar::e_double: + case Scalar::e_long_double: + result = a->m_float.compare(b->m_float); + if (result == llvm::APFloat::cmpGreaterThan) + return true; + } + return false; +} + +bool lldb_private::operator>=(const Scalar &lhs, const Scalar &rhs) { + if (lhs.m_type == Scalar::e_void || rhs.m_type == Scalar::e_void) + return false; + + Scalar temp_value; + const Scalar *a; + const Scalar *b; + llvm::APFloat::cmpResult result; + switch (PromoteToMaxType(lhs, rhs, temp_value, a, b)) { + case Scalar::e_void: + break; + case Scalar::e_sint: + case Scalar::e_slong: + case Scalar::e_slonglong: + case Scalar::e_sint128: + case Scalar::e_sint256: + return a->m_integer.sge(b->m_integer); + case Scalar::e_uint: + case Scalar::e_ulong: + case Scalar::e_ulonglong: + case Scalar::e_uint128: + case Scalar::e_uint256: + return a->m_integer.uge(b->m_integer); + case Scalar::e_float: + case Scalar::e_double: + case Scalar::e_long_double: + result = a->m_float.compare(b->m_float); + if (result == llvm::APFloat::cmpGreaterThan || + result == llvm::APFloat::cmpEqual) + return true; + } + return false; +} + +bool Scalar::ClearBit(uint32_t bit) { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + m_integer.clearBit(bit); + return true; + case e_float: + case e_double: + case e_long_double: + break; + } + return false; +} + +bool Scalar::SetBit(uint32_t bit) { + switch (m_type) { + case e_void: + break; + case e_sint: + case e_uint: + case e_slong: + case e_ulong: + case e_slonglong: + case e_ulonglong: + case e_sint128: + case e_uint128: + case e_sint256: + case e_uint256: + m_integer.setBit(bit); + return true; + case e_float: + case e_double: + case e_long_double: + break; + } + return false; +} diff --git a/source/Core/SearchFilter.cpp b/source/Core/SearchFilter.cpp index 202a40ff414d..2dfb26910ee0 100644 --- a/source/Core/SearchFilter.cpp +++ b/source/Core/SearchFilter.cpp @@ -12,89 +12,169 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Core/SearchFilter.h" #include "lldb/Core/Module.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Target/Target.h" +#include "lldb/lldb-private.h" using namespace lldb; using namespace lldb_private; -Searcher::Searcher() = default; +const char *SearchFilter::g_ty_to_name[] = {"Unconstrained", "Exception", + "Module", "Modules", + "ModulesAndCU", "Unknown"}; -Searcher::~Searcher() = default; +const char + *SearchFilter::g_option_names[SearchFilter::OptionNames::LastOptionName] = { + "ModuleList", "CUList"}; + +const char *SearchFilter::FilterTyToName(enum FilterTy type) { + if (type > LastKnownFilterType) + return g_ty_to_name[UnknownFilter]; -void -Searcher::GetDescription (Stream *s) -{ + return g_ty_to_name[type]; } -SearchFilter::SearchFilter(const TargetSP &target_sp) : - m_target_sp (target_sp) -{ +SearchFilter::FilterTy SearchFilter::NameToFilterTy(const char *name) { + for (size_t i = 0; i <= LastKnownFilterType; i++) { + if (strcmp(name, g_ty_to_name[i]) == 0) + return (FilterTy)i; + } + return UnknownFilter; } -SearchFilter::SearchFilter(const SearchFilter& rhs) = default; +Searcher::Searcher() = default; -SearchFilter& -SearchFilter::operator=(const SearchFilter& rhs) = default; +Searcher::~Searcher() = default; -SearchFilter::~SearchFilter() = default; +void Searcher::GetDescription(Stream *s) {} -bool -SearchFilter::ModulePasses (const FileSpec &spec) -{ - return true; -} +SearchFilter::SearchFilter(const TargetSP &target_sp, unsigned char filterType) + : m_target_sp(target_sp), SubclassID(filterType) {} -bool -SearchFilter::ModulePasses (const ModuleSP &module_sp) -{ - return true; -} +SearchFilter::SearchFilter(const SearchFilter &rhs) = default; -bool -SearchFilter::AddressPasses (Address &address) -{ - return true; -} +SearchFilter &SearchFilter::operator=(const SearchFilter &rhs) = default; -bool -SearchFilter::CompUnitPasses (FileSpec &fileSpec) -{ - return true; -} +SearchFilter::~SearchFilter() = default; -bool -SearchFilter::CompUnitPasses (CompileUnit &compUnit) -{ - return true; +SearchFilterSP SearchFilter::CreateFromStructuredData( + Target &target, const StructuredData::Dictionary &filter_dict, + Error &error) { + SearchFilterSP result_sp; + if (!filter_dict.IsValid()) { + error.SetErrorString("Can't deserialize from an invalid data object."); + return result_sp; + } + + std::string subclass_name; + + bool success = filter_dict.GetValueForKeyAsString( + GetSerializationSubclassKey(), subclass_name); + if (!success) { + error.SetErrorStringWithFormat("Filter data missing subclass key"); + return result_sp; + } + + FilterTy filter_type = NameToFilterTy(subclass_name.c_str()); + if (filter_type == UnknownFilter) { + error.SetErrorStringWithFormat("Unknown filter type: %s.", + subclass_name.c_str()); + return result_sp; + } + + StructuredData::Dictionary *subclass_options = nullptr; + success = filter_dict.GetValueForKeyAsDictionary( + GetSerializationSubclassOptionsKey(), subclass_options); + if (!success || !subclass_options || !subclass_options->IsValid()) { + error.SetErrorString("Filter data missing subclass options key."); + return result_sp; + } + + switch (filter_type) { + case Unconstrained: + result_sp = SearchFilterForUnconstrainedSearches::CreateFromStructuredData( + target, *subclass_options, error); + break; + case ByModule: + result_sp = SearchFilterByModule::CreateFromStructuredData( + target, *subclass_options, error); + break; + case ByModules: + result_sp = SearchFilterByModuleList::CreateFromStructuredData( + target, *subclass_options, error); + break; + case ByModulesAndCU: + result_sp = SearchFilterByModuleListAndCU::CreateFromStructuredData( + target, *subclass_options, error); + break; + case Exception: + error.SetErrorString("Can't serialize exception breakpoints yet."); + break; + default: + llvm_unreachable("Should never get an uresolvable filter type."); + } + + return result_sp; +} + +bool SearchFilter::ModulePasses(const FileSpec &spec) { return true; } + +bool SearchFilter::ModulePasses(const ModuleSP &module_sp) { return true; } + +bool SearchFilter::AddressPasses(Address &address) { return true; } + +bool SearchFilter::CompUnitPasses(FileSpec &fileSpec) { return true; } + +bool SearchFilter::CompUnitPasses(CompileUnit &compUnit) { return true; } + +uint32_t SearchFilter::GetFilterRequiredItems() { + return (lldb::SymbolContextItem)0; +} + +void SearchFilter::GetDescription(Stream *s) {} + +void SearchFilter::Dump(Stream *s) const {} + +lldb::SearchFilterSP SearchFilter::CopyForBreakpoint(Breakpoint &breakpoint) { + SearchFilterSP ret_sp = DoCopyForBreakpoint(breakpoint); + TargetSP target_sp = breakpoint.GetTargetSP(); + ret_sp->SetTarget(target_sp); + return ret_sp; } -uint32_t -SearchFilter::GetFilterRequiredItems() -{ - return (lldb::SymbolContextItem) 0; -} +//---------------------------------------------------------------------- +// Helper functions for serialization. +//---------------------------------------------------------------------- -void -SearchFilter::GetDescription (Stream *s) -{ -} +StructuredData::DictionarySP +SearchFilter::WrapOptionsDict(StructuredData::DictionarySP options_dict_sp) { + if (!options_dict_sp || !options_dict_sp->IsValid()) + return StructuredData::DictionarySP(); + + StructuredData::DictionarySP type_dict_sp(new StructuredData::Dictionary()); + type_dict_sp->AddStringItem(GetSerializationSubclassKey(), GetFilterName()); + type_dict_sp->AddItem(GetSerializationSubclassOptionsKey(), options_dict_sp); -void -SearchFilter::Dump (Stream *s) const -{ + return type_dict_sp; } -lldb::SearchFilterSP -SearchFilter::CopyForBreakpoint (Breakpoint &breakpoint) -{ - SearchFilterSP ret_sp = DoCopyForBreakpoint (breakpoint); - TargetSP target_sp = breakpoint.GetTargetSP(); - ret_sp->SetTarget(target_sp); - return ret_sp; +void SearchFilter::SerializeFileSpecList( + StructuredData::DictionarySP &options_dict_sp, OptionNames name, + FileSpecList &file_list) { + size_t num_modules = file_list.GetSize(); + + // Don't serialize empty lists. + if (num_modules == 0) + return; + + StructuredData::ArraySP module_array_sp(new StructuredData::Array()); + for (size_t i = 0; i < num_modules; i++) { + module_array_sp->AddItem(StructuredData::StringSP( + new StructuredData::String(file_list.GetFileSpecAtIndex(i).GetPath()))); + } + options_dict_sp->AddItem(GetKey(name), module_array_sp); } //---------------------------------------------------------------------- @@ -102,191 +182,178 @@ SearchFilter::CopyForBreakpoint (Breakpoint &breakpoint) // SymbolContext. //---------------------------------------------------------------------- -void -SearchFilter::Search (Searcher &searcher) -{ - SymbolContext empty_sc; +void SearchFilter::Search(Searcher &searcher) { + SymbolContext empty_sc; - if (!m_target_sp) - return; - empty_sc.target_sp = m_target_sp; + if (!m_target_sp) + return; + empty_sc.target_sp = m_target_sp; - if (searcher.GetDepth() == Searcher::eDepthTarget) - searcher.SearchCallback(*this, empty_sc, nullptr, false); - else - DoModuleIteration(empty_sc, searcher); + if (searcher.GetDepth() == Searcher::eDepthTarget) + searcher.SearchCallback(*this, empty_sc, nullptr, false); + else + DoModuleIteration(empty_sc, searcher); } -void -SearchFilter::SearchInModuleList (Searcher &searcher, ModuleList &modules) -{ - SymbolContext empty_sc; +void SearchFilter::SearchInModuleList(Searcher &searcher, ModuleList &modules) { + SymbolContext empty_sc; - if (!m_target_sp) - return; - empty_sc.target_sp = m_target_sp; + if (!m_target_sp) + return; + empty_sc.target_sp = m_target_sp; - if (searcher.GetDepth() == Searcher::eDepthTarget) - searcher.SearchCallback(*this, empty_sc, nullptr, false); - else - { - std::lock_guard<std::recursive_mutex> guard(modules.GetMutex()); - const size_t numModules = modules.GetSize(); - - for (size_t i = 0; i < numModules; i++) - { - ModuleSP module_sp(modules.GetModuleAtIndexUnlocked(i)); - if (ModulePasses(module_sp)) - { - if (DoModuleIteration(module_sp, searcher) == Searcher::eCallbackReturnStop) - return; - } - } + if (searcher.GetDepth() == Searcher::eDepthTarget) + searcher.SearchCallback(*this, empty_sc, nullptr, false); + else { + std::lock_guard<std::recursive_mutex> guard(modules.GetMutex()); + const size_t numModules = modules.GetSize(); + + for (size_t i = 0; i < numModules; i++) { + ModuleSP module_sp(modules.GetModuleAtIndexUnlocked(i)); + if (ModulePasses(module_sp)) { + if (DoModuleIteration(module_sp, searcher) == + Searcher::eCallbackReturnStop) + return; + } } + } } Searcher::CallbackReturn -SearchFilter::DoModuleIteration (const lldb::ModuleSP& module_sp, Searcher &searcher) -{ - SymbolContext matchingContext (m_target_sp, module_sp); - return DoModuleIteration(matchingContext, searcher); +SearchFilter::DoModuleIteration(const lldb::ModuleSP &module_sp, + Searcher &searcher) { + SymbolContext matchingContext(m_target_sp, module_sp); + return DoModuleIteration(matchingContext, searcher); } Searcher::CallbackReturn -SearchFilter::DoModuleIteration (const SymbolContext &context, Searcher &searcher) -{ - if (searcher.GetDepth () >= Searcher::eDepthModule) - { - if (context.module_sp) - { - if (searcher.GetDepth () == Searcher::eDepthModule) - { - SymbolContext matchingContext(context.module_sp.get()); - searcher.SearchCallback(*this, matchingContext, nullptr, false); - } - else - { - return DoCUIteration(context.module_sp, context, searcher); - } - } - else - { - const ModuleList &target_images = m_target_sp->GetImages(); - std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex()); - - size_t n_modules = target_images.GetSize(); - for (size_t i = 0; i < n_modules; i++) - { - // If this is the last level supplied, then call the callback directly, - // otherwise descend. - ModuleSP module_sp(target_images.GetModuleAtIndexUnlocked (i)); - if (!ModulePasses (module_sp)) - continue; - - if (searcher.GetDepth () == Searcher::eDepthModule) - { - SymbolContext matchingContext(m_target_sp, module_sp); - - Searcher::CallbackReturn shouldContinue = searcher.SearchCallback(*this, matchingContext, nullptr, false); - if (shouldContinue == Searcher::eCallbackReturnStop - || shouldContinue == Searcher::eCallbackReturnPop) - return shouldContinue; - } - else - { - Searcher::CallbackReturn shouldContinue = DoCUIteration(module_sp, context, searcher); - if (shouldContinue == Searcher::eCallbackReturnStop) - return shouldContinue; - else if (shouldContinue == Searcher::eCallbackReturnPop) - continue; - } - } +SearchFilter::DoModuleIteration(const SymbolContext &context, + Searcher &searcher) { + if (searcher.GetDepth() >= Searcher::eDepthModule) { + if (context.module_sp) { + if (searcher.GetDepth() == Searcher::eDepthModule) { + SymbolContext matchingContext(context.module_sp.get()); + searcher.SearchCallback(*this, matchingContext, nullptr, false); + } else { + return DoCUIteration(context.module_sp, context, searcher); + } + } else { + const ModuleList &target_images = m_target_sp->GetImages(); + std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex()); + + size_t n_modules = target_images.GetSize(); + for (size_t i = 0; i < n_modules; i++) { + // If this is the last level supplied, then call the callback directly, + // otherwise descend. + ModuleSP module_sp(target_images.GetModuleAtIndexUnlocked(i)); + if (!ModulePasses(module_sp)) + continue; + + if (searcher.GetDepth() == Searcher::eDepthModule) { + SymbolContext matchingContext(m_target_sp, module_sp); + + Searcher::CallbackReturn shouldContinue = + searcher.SearchCallback(*this, matchingContext, nullptr, false); + if (shouldContinue == Searcher::eCallbackReturnStop || + shouldContinue == Searcher::eCallbackReturnPop) + return shouldContinue; + } else { + Searcher::CallbackReturn shouldContinue = + DoCUIteration(module_sp, context, searcher); + if (shouldContinue == Searcher::eCallbackReturnStop) + return shouldContinue; + else if (shouldContinue == Searcher::eCallbackReturnPop) + continue; } + } } - return Searcher::eCallbackReturnContinue; + } + return Searcher::eCallbackReturnContinue; } Searcher::CallbackReturn -SearchFilter::DoCUIteration (const ModuleSP &module_sp, const SymbolContext &context, Searcher &searcher) -{ - Searcher::CallbackReturn shouldContinue; - if (context.comp_unit == nullptr) - { - const size_t num_comp_units = module_sp->GetNumCompileUnits(); - for (size_t i = 0; i < num_comp_units; i++) - { - CompUnitSP cu_sp (module_sp->GetCompileUnitAtIndex (i)); - if (cu_sp) - { - if (!CompUnitPasses (*(cu_sp.get()))) - continue; - - if (searcher.GetDepth () == Searcher::eDepthCompUnit) - { - SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get()); - - shouldContinue = searcher.SearchCallback(*this, matchingContext, nullptr, false); - - if (shouldContinue == Searcher::eCallbackReturnPop) - return Searcher::eCallbackReturnContinue; - else if (shouldContinue == Searcher::eCallbackReturnStop) - return shouldContinue; - } - else - { - // FIXME Descend to block. - } - } +SearchFilter::DoCUIteration(const ModuleSP &module_sp, + const SymbolContext &context, Searcher &searcher) { + Searcher::CallbackReturn shouldContinue; + if (context.comp_unit == nullptr) { + const size_t num_comp_units = module_sp->GetNumCompileUnits(); + for (size_t i = 0; i < num_comp_units; i++) { + CompUnitSP cu_sp(module_sp->GetCompileUnitAtIndex(i)); + if (cu_sp) { + if (!CompUnitPasses(*(cu_sp.get()))) + continue; + + if (searcher.GetDepth() == Searcher::eDepthCompUnit) { + SymbolContext matchingContext(m_target_sp, module_sp, cu_sp.get()); + + shouldContinue = + searcher.SearchCallback(*this, matchingContext, nullptr, false); + + if (shouldContinue == Searcher::eCallbackReturnPop) + return Searcher::eCallbackReturnContinue; + else if (shouldContinue == Searcher::eCallbackReturnStop) + return shouldContinue; + } else { + // FIXME Descend to block. } + } } - else - { - if (CompUnitPasses(*context.comp_unit)) - { - SymbolContext matchingContext (m_target_sp, module_sp, context.comp_unit); - return searcher.SearchCallback(*this, matchingContext, nullptr, false); - } + } else { + if (CompUnitPasses(*context.comp_unit)) { + SymbolContext matchingContext(m_target_sp, module_sp, context.comp_unit); + return searcher.SearchCallback(*this, matchingContext, nullptr, false); } - return Searcher::eCallbackReturnContinue; + } + return Searcher::eCallbackReturnContinue; } -Searcher::CallbackReturn -SearchFilter::DoFunctionIteration (Function *function, const SymbolContext &context, Searcher &searcher) -{ - // FIXME: Implement... - return Searcher::eCallbackReturnContinue; +Searcher::CallbackReturn SearchFilter::DoFunctionIteration( + Function *function, const SymbolContext &context, Searcher &searcher) { + // FIXME: Implement... + return Searcher::eCallbackReturnContinue; } //---------------------------------------------------------------------- // SearchFilterForUnconstrainedSearches: -// Selects a shared library matching a given file spec, consulting the targets "black list". +// Selects a shared library matching a given file spec, consulting the targets +// "black list". //---------------------------------------------------------------------- +SearchFilterSP SearchFilterForUnconstrainedSearches::CreateFromStructuredData( + Target &target, const StructuredData::Dictionary &data_dict, Error &error) { + // No options for an unconstrained search. + return SearchFilterSP( + new SearchFilterForUnconstrainedSearches(target.shared_from_this())); +} -bool -SearchFilterForUnconstrainedSearches::ModulePasses (const FileSpec &module_spec) -{ - if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches (module_spec)) - return false; - else - return true; +StructuredData::ObjectSP +SearchFilterForUnconstrainedSearches::SerializeToStructuredData() { + // The options dictionary is an empty dictionary: + StructuredData::DictionarySP result_sp(new StructuredData::Dictionary()); + return WrapOptionsDict(result_sp); } -bool -SearchFilterForUnconstrainedSearches::ModulePasses (const lldb::ModuleSP &module_sp) -{ - if (!module_sp) - return true; - else if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches (module_sp)) - return false; - else - return true; +bool SearchFilterForUnconstrainedSearches::ModulePasses( + const FileSpec &module_spec) { + if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_spec)) + return false; + else + return true; } -lldb::SearchFilterSP -SearchFilterForUnconstrainedSearches::DoCopyForBreakpoint (Breakpoint &breakpoint) -{ - SearchFilterSP ret_sp(new SearchFilterForUnconstrainedSearches(*this)); - return ret_sp; +bool SearchFilterForUnconstrainedSearches::ModulePasses( + const lldb::ModuleSP &module_sp) { + if (!module_sp) + return true; + else if (m_target_sp->ModuleIsExcludedForUnconstrainedSearches(module_sp)) + return false; + else + return true; +} + +lldb::SearchFilterSP SearchFilterForUnconstrainedSearches::DoCopyForBreakpoint( + Breakpoint &breakpoint) { + SearchFilterSP ret_sp(new SearchFilterForUnconstrainedSearches(*this)); + return ret_sp; } //---------------------------------------------------------------------- @@ -294,126 +361,136 @@ SearchFilterForUnconstrainedSearches::DoCopyForBreakpoint (Breakpoint &breakpoin // Selects a shared library matching a given file spec //---------------------------------------------------------------------- -SearchFilterByModule::SearchFilterByModule (const lldb::TargetSP &target_sp, const FileSpec &module) : - SearchFilter (target_sp), - m_module_spec (module) -{ -} +SearchFilterByModule::SearchFilterByModule(const lldb::TargetSP &target_sp, + const FileSpec &module) + : SearchFilter(target_sp, FilterTy::ByModule), m_module_spec(module) {} -SearchFilterByModule::SearchFilterByModule(const SearchFilterByModule& rhs) = default; +SearchFilterByModule::SearchFilterByModule(const SearchFilterByModule &rhs) = + default; -SearchFilterByModule& -SearchFilterByModule::operator=(const SearchFilterByModule& rhs) -{ - m_target_sp = rhs.m_target_sp; - m_module_spec = rhs.m_module_spec; - return *this; +SearchFilterByModule &SearchFilterByModule:: +operator=(const SearchFilterByModule &rhs) { + m_target_sp = rhs.m_target_sp; + m_module_spec = rhs.m_module_spec; + return *this; } SearchFilterByModule::~SearchFilterByModule() = default; -bool -SearchFilterByModule::ModulePasses (const ModuleSP &module_sp) -{ - return (module_sp && FileSpec::Equal(module_sp->GetFileSpec(), m_module_spec, false)); +bool SearchFilterByModule::ModulePasses(const ModuleSP &module_sp) { + return (module_sp && + FileSpec::Equal(module_sp->GetFileSpec(), m_module_spec, false)); } -bool -SearchFilterByModule::ModulePasses (const FileSpec &spec) -{ - // Do a full match only if "spec" has a directory - const bool full_match = (bool)spec.GetDirectory(); - return FileSpec::Equal(spec, m_module_spec, full_match); +bool SearchFilterByModule::ModulePasses(const FileSpec &spec) { + // Do a full match only if "spec" has a directory + const bool full_match = (bool)spec.GetDirectory(); + return FileSpec::Equal(spec, m_module_spec, full_match); } -bool -SearchFilterByModule::AddressPasses (Address &address) -{ - // FIXME: Not yet implemented - return true; +bool SearchFilterByModule::AddressPasses(Address &address) { + // FIXME: Not yet implemented + return true; } -bool -SearchFilterByModule::CompUnitPasses (FileSpec &fileSpec) -{ - return true; -} +bool SearchFilterByModule::CompUnitPasses(FileSpec &fileSpec) { return true; } -bool -SearchFilterByModule::CompUnitPasses (CompileUnit &compUnit) -{ - return true; +bool SearchFilterByModule::CompUnitPasses(CompileUnit &compUnit) { + return true; } -void -SearchFilterByModule::Search (Searcher &searcher) -{ - if (!m_target_sp) - return; - - if (searcher.GetDepth() == Searcher::eDepthTarget) - { - SymbolContext empty_sc; - empty_sc.target_sp = m_target_sp; - searcher.SearchCallback(*this, empty_sc, nullptr, false); - } +void SearchFilterByModule::Search(Searcher &searcher) { + if (!m_target_sp) + return; - // If the module file spec is a full path, then we can just find the one - // filespec that passes. Otherwise, we need to go through all modules and - // find the ones that match the file name. - - const ModuleList &target_modules = m_target_sp->GetImages(); - std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); - - const size_t num_modules = target_modules.GetSize (); - for (size_t i = 0; i < num_modules; i++) - { - Module* module = target_modules.GetModulePointerAtIndexUnlocked(i); - const bool full_match = (bool)m_module_spec.GetDirectory(); - if (FileSpec::Equal (m_module_spec, module->GetFileSpec(), full_match)) - { - SymbolContext matchingContext(m_target_sp, module->shared_from_this()); - Searcher::CallbackReturn shouldContinue; - - shouldContinue = DoModuleIteration(matchingContext, searcher); - if (shouldContinue == Searcher::eCallbackReturnStop) - return; - } + if (searcher.GetDepth() == Searcher::eDepthTarget) { + SymbolContext empty_sc; + empty_sc.target_sp = m_target_sp; + searcher.SearchCallback(*this, empty_sc, nullptr, false); + } + + // If the module file spec is a full path, then we can just find the one + // filespec that passes. Otherwise, we need to go through all modules and + // find the ones that match the file name. + + const ModuleList &target_modules = m_target_sp->GetImages(); + std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); + + const size_t num_modules = target_modules.GetSize(); + for (size_t i = 0; i < num_modules; i++) { + Module *module = target_modules.GetModulePointerAtIndexUnlocked(i); + const bool full_match = (bool)m_module_spec.GetDirectory(); + if (FileSpec::Equal(m_module_spec, module->GetFileSpec(), full_match)) { + SymbolContext matchingContext(m_target_sp, module->shared_from_this()); + Searcher::CallbackReturn shouldContinue; + + shouldContinue = DoModuleIteration(matchingContext, searcher); + if (shouldContinue == Searcher::eCallbackReturnStop) + return; } + } } -void -SearchFilterByModule::GetDescription (Stream *s) -{ - s->PutCString(", module = "); - if (s->GetVerbose()) - { - char buffer[2048]; - m_module_spec.GetPath(buffer, 2047); - s->PutCString(buffer); - } - else - { - s->PutCString(m_module_spec.GetFilename().AsCString("<Unknown>")); - } +void SearchFilterByModule::GetDescription(Stream *s) { + s->PutCString(", module = "); + if (s->GetVerbose()) { + char buffer[2048]; + m_module_spec.GetPath(buffer, 2047); + s->PutCString(buffer); + } else { + s->PutCString(m_module_spec.GetFilename().AsCString("<Unknown>")); + } } -uint32_t -SearchFilterByModule::GetFilterRequiredItems() -{ - return eSymbolContextModule; +uint32_t SearchFilterByModule::GetFilterRequiredItems() { + return eSymbolContextModule; } -void -SearchFilterByModule::Dump (Stream *s) const -{ -} +void SearchFilterByModule::Dump(Stream *s) const {} lldb::SearchFilterSP -SearchFilterByModule::DoCopyForBreakpoint (Breakpoint &breakpoint) -{ - SearchFilterSP ret_sp(new SearchFilterByModule(*this)); - return ret_sp; +SearchFilterByModule::DoCopyForBreakpoint(Breakpoint &breakpoint) { + SearchFilterSP ret_sp(new SearchFilterByModule(*this)); + return ret_sp; +} + +SearchFilterSP SearchFilterByModule::CreateFromStructuredData( + Target &target, const StructuredData::Dictionary &data_dict, Error &error) { + StructuredData::Array *modules_array; + bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList), + modules_array); + if (!success) { + error.SetErrorString("SFBM::CFSD: Could not find the module list key."); + return nullptr; + } + + size_t num_modules = modules_array->GetSize(); + if (num_modules > 1) { + error.SetErrorString( + "SFBM::CFSD: Only one modules allowed for SearchFilterByModule."); + return nullptr; + } + + std::string module; + success = modules_array->GetItemAtIndexAsString(0, module); + if (!success) { + error.SetErrorString("SFBM::CFSD: filter module item not a string."); + return nullptr; + } + FileSpec module_spec(module, false); + + return SearchFilterSP( + new SearchFilterByModule(target.shared_from_this(), module_spec)); +} + +StructuredData::ObjectSP SearchFilterByModule::SerializeToStructuredData() { + StructuredData::DictionarySP options_dict_sp( + new StructuredData::Dictionary()); + StructuredData::ArraySP module_array_sp(new StructuredData::Array()); + module_array_sp->AddItem(StructuredData::StringSP( + new StructuredData::String(m_module_spec.GetPath()))); + options_dict_sp->AddItem(GetKey(OptionNames::ModList), module_array_sp); + return WrapOptionsDict(options_dict_sp); } //---------------------------------------------------------------------- @@ -421,160 +498,173 @@ SearchFilterByModule::DoCopyForBreakpoint (Breakpoint &breakpoint) // Selects a shared library matching a given file spec //---------------------------------------------------------------------- -SearchFilterByModuleList::SearchFilterByModuleList (const lldb::TargetSP &target_sp, - const FileSpecList &module_list) : - SearchFilter (target_sp), - m_module_spec_list (module_list) -{ -} +SearchFilterByModuleList::SearchFilterByModuleList( + const lldb::TargetSP &target_sp, const FileSpecList &module_list) + : SearchFilter(target_sp, FilterTy::ByModules), + m_module_spec_list(module_list) {} -SearchFilterByModuleList::SearchFilterByModuleList(const SearchFilterByModuleList& rhs) = default; +SearchFilterByModuleList::SearchFilterByModuleList( + const lldb::TargetSP &target_sp, const FileSpecList &module_list, + enum FilterTy filter_ty) + : SearchFilter(target_sp, filter_ty), m_module_spec_list(module_list) {} -SearchFilterByModuleList& -SearchFilterByModuleList::operator=(const SearchFilterByModuleList& rhs) -{ - m_target_sp = rhs.m_target_sp; - m_module_spec_list = rhs.m_module_spec_list; - return *this; +SearchFilterByModuleList::SearchFilterByModuleList( + const SearchFilterByModuleList &rhs) = default; + +SearchFilterByModuleList &SearchFilterByModuleList:: +operator=(const SearchFilterByModuleList &rhs) { + m_target_sp = rhs.m_target_sp; + m_module_spec_list = rhs.m_module_spec_list; + return *this; } SearchFilterByModuleList::~SearchFilterByModuleList() = default; -bool -SearchFilterByModuleList::ModulePasses (const ModuleSP &module_sp) -{ - if (m_module_spec_list.GetSize() == 0) - return true; - - if (module_sp && - m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) != UINT32_MAX) - return true; - else - return false; -} - -bool -SearchFilterByModuleList::ModulePasses (const FileSpec &spec) -{ - if (m_module_spec_list.GetSize() == 0) - return true; - - if (m_module_spec_list.FindFileIndex(0, spec, true) != UINT32_MAX) - return true; - else - return false; -} - -bool -SearchFilterByModuleList::AddressPasses (Address &address) -{ - // FIXME: Not yet implemented +bool SearchFilterByModuleList::ModulePasses(const ModuleSP &module_sp) { + if (m_module_spec_list.GetSize() == 0) return true; -} -bool -SearchFilterByModuleList::CompUnitPasses (FileSpec &fileSpec) -{ + if (module_sp && + m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) != + UINT32_MAX) return true; + else + return false; } -bool -SearchFilterByModuleList::CompUnitPasses (CompileUnit &compUnit) -{ +bool SearchFilterByModuleList::ModulePasses(const FileSpec &spec) { + if (m_module_spec_list.GetSize() == 0) return true; -} -void -SearchFilterByModuleList::Search (Searcher &searcher) -{ - if (!m_target_sp) - return; + if (m_module_spec_list.FindFileIndex(0, spec, true) != UINT32_MAX) + return true; + else + return false; +} - if (searcher.GetDepth() == Searcher::eDepthTarget) - { - SymbolContext empty_sc; - empty_sc.target_sp = m_target_sp; - searcher.SearchCallback(*this, empty_sc, nullptr, false); - } +bool SearchFilterByModuleList::AddressPasses(Address &address) { + // FIXME: Not yet implemented + return true; +} - // If the module file spec is a full path, then we can just find the one - // filespec that passes. Otherwise, we need to go through all modules and - // find the ones that match the file name. +bool SearchFilterByModuleList::CompUnitPasses(FileSpec &fileSpec) { + return true; +} - const ModuleList &target_modules = m_target_sp->GetImages(); - std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); +bool SearchFilterByModuleList::CompUnitPasses(CompileUnit &compUnit) { + return true; +} - const size_t num_modules = target_modules.GetSize (); - for (size_t i = 0; i < num_modules; i++) - { - Module* module = target_modules.GetModulePointerAtIndexUnlocked(i); - if (m_module_spec_list.FindFileIndex(0, module->GetFileSpec(), false) != UINT32_MAX) - { - SymbolContext matchingContext(m_target_sp, module->shared_from_this()); - Searcher::CallbackReturn shouldContinue; +void SearchFilterByModuleList::Search(Searcher &searcher) { + if (!m_target_sp) + return; - shouldContinue = DoModuleIteration(matchingContext, searcher); - if (shouldContinue == Searcher::eCallbackReturnStop) - return; - } + if (searcher.GetDepth() == Searcher::eDepthTarget) { + SymbolContext empty_sc; + empty_sc.target_sp = m_target_sp; + searcher.SearchCallback(*this, empty_sc, nullptr, false); + } + + // If the module file spec is a full path, then we can just find the one + // filespec that passes. Otherwise, we need to go through all modules and + // find the ones that match the file name. + + const ModuleList &target_modules = m_target_sp->GetImages(); + std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); + + const size_t num_modules = target_modules.GetSize(); + for (size_t i = 0; i < num_modules; i++) { + Module *module = target_modules.GetModulePointerAtIndexUnlocked(i); + if (m_module_spec_list.FindFileIndex(0, module->GetFileSpec(), false) != + UINT32_MAX) { + SymbolContext matchingContext(m_target_sp, module->shared_from_this()); + Searcher::CallbackReturn shouldContinue; + + shouldContinue = DoModuleIteration(matchingContext, searcher); + if (shouldContinue == Searcher::eCallbackReturnStop) + return; } -} - -void -SearchFilterByModuleList::GetDescription (Stream *s) -{ - size_t num_modules = m_module_spec_list.GetSize(); - if (num_modules == 1) - { - s->Printf (", module = "); - if (s->GetVerbose()) - { - char buffer[2048]; - m_module_spec_list.GetFileSpecAtIndex(0).GetPath(buffer, 2047); - s->PutCString(buffer); - } - else - { - s->PutCString(m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString("<Unknown>")); - } + } +} + +void SearchFilterByModuleList::GetDescription(Stream *s) { + size_t num_modules = m_module_spec_list.GetSize(); + if (num_modules == 1) { + s->Printf(", module = "); + if (s->GetVerbose()) { + char buffer[2048]; + m_module_spec_list.GetFileSpecAtIndex(0).GetPath(buffer, 2047); + s->PutCString(buffer); + } else { + s->PutCString( + m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString( + "<Unknown>")); } - else - { - s->Printf(", modules(%" PRIu64 ") = ", (uint64_t)num_modules); - for (size_t i = 0; i < num_modules; i++) - { - if (s->GetVerbose()) - { - char buffer[2048]; - m_module_spec_list.GetFileSpecAtIndex(i).GetPath(buffer, 2047); - s->PutCString(buffer); - } - else - { - s->PutCString(m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString("<Unknown>")); - } - if (i != num_modules - 1) - s->PutCString (", "); - } + } else { + s->Printf(", modules(%" PRIu64 ") = ", (uint64_t)num_modules); + for (size_t i = 0; i < num_modules; i++) { + if (s->GetVerbose()) { + char buffer[2048]; + m_module_spec_list.GetFileSpecAtIndex(i).GetPath(buffer, 2047); + s->PutCString(buffer); + } else { + s->PutCString( + m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString( + "<Unknown>")); + } + if (i != num_modules - 1) + s->PutCString(", "); } + } } -uint32_t -SearchFilterByModuleList::GetFilterRequiredItems() -{ - return eSymbolContextModule; +uint32_t SearchFilterByModuleList::GetFilterRequiredItems() { + return eSymbolContextModule; } -void -SearchFilterByModuleList::Dump (Stream *s) const -{ -} +void SearchFilterByModuleList::Dump(Stream *s) const {} lldb::SearchFilterSP -SearchFilterByModuleList::DoCopyForBreakpoint (Breakpoint &breakpoint) -{ - SearchFilterSP ret_sp(new SearchFilterByModuleList(*this)); - return ret_sp; +SearchFilterByModuleList::DoCopyForBreakpoint(Breakpoint &breakpoint) { + SearchFilterSP ret_sp(new SearchFilterByModuleList(*this)); + return ret_sp; +} + +SearchFilterSP SearchFilterByModuleList::CreateFromStructuredData( + Target &target, const StructuredData::Dictionary &data_dict, Error &error) { + StructuredData::Array *modules_array; + bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList), + modules_array); + FileSpecList modules; + if (success) { + size_t num_modules = modules_array->GetSize(); + for (size_t i = 0; i < num_modules; i++) { + std::string module; + success = modules_array->GetItemAtIndexAsString(i, module); + if (!success) { + error.SetErrorStringWithFormat( + "SFBM::CFSD: filter module item %zu not a string.", i); + return nullptr; + } + modules.Append(FileSpec(module, false)); + } + } + + return SearchFilterSP( + new SearchFilterByModuleList(target.shared_from_this(), modules)); +} + +void SearchFilterByModuleList::SerializeUnwrapped( + StructuredData::DictionarySP &options_dict_sp) { + SerializeFileSpecList(options_dict_sp, OptionNames::ModList, + m_module_spec_list); +} + +StructuredData::ObjectSP SearchFilterByModuleList::SerializeToStructuredData() { + StructuredData::DictionarySP options_dict_sp( + new StructuredData::Dictionary()); + SerializeUnwrapped(options_dict_sp); + return WrapOptionsDict(options_dict_sp); } //---------------------------------------------------------------------- @@ -582,174 +672,196 @@ SearchFilterByModuleList::DoCopyForBreakpoint (Breakpoint &breakpoint) // Selects a shared library matching a given file spec //---------------------------------------------------------------------- -SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU (const lldb::TargetSP &target_sp, - const FileSpecList &module_list, - const FileSpecList &cu_list) : - SearchFilterByModuleList (target_sp, module_list), - m_cu_spec_list (cu_list) -{ -} +SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU( + const lldb::TargetSP &target_sp, const FileSpecList &module_list, + const FileSpecList &cu_list) + : SearchFilterByModuleList(target_sp, module_list, + FilterTy::ByModulesAndCU), + m_cu_spec_list(cu_list) {} -SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU(const SearchFilterByModuleListAndCU& rhs) = default; +SearchFilterByModuleListAndCU::SearchFilterByModuleListAndCU( + const SearchFilterByModuleListAndCU &rhs) = default; -SearchFilterByModuleListAndCU& -SearchFilterByModuleListAndCU::operator=(const SearchFilterByModuleListAndCU& rhs) -{ - if (&rhs != this) - { - m_target_sp = rhs.m_target_sp; - m_module_spec_list = rhs.m_module_spec_list; - m_cu_spec_list = rhs.m_cu_spec_list; - } - return *this; +SearchFilterByModuleListAndCU &SearchFilterByModuleListAndCU:: +operator=(const SearchFilterByModuleListAndCU &rhs) { + if (&rhs != this) { + m_target_sp = rhs.m_target_sp; + m_module_spec_list = rhs.m_module_spec_list; + m_cu_spec_list = rhs.m_cu_spec_list; + } + return *this; } SearchFilterByModuleListAndCU::~SearchFilterByModuleListAndCU() = default; -bool -SearchFilterByModuleListAndCU::AddressPasses (Address &address) -{ - return true; +lldb::SearchFilterSP SearchFilterByModuleListAndCU::CreateFromStructuredData( + Target &target, const StructuredData::Dictionary &data_dict, Error &error) { + StructuredData::Array *modules_array = nullptr; + SearchFilterSP result_sp; + bool success = data_dict.GetValueForKeyAsArray(GetKey(OptionNames::ModList), + modules_array); + FileSpecList modules; + if (success) { + size_t num_modules = modules_array->GetSize(); + for (size_t i = 0; i < num_modules; i++) { + std::string module; + success = modules_array->GetItemAtIndexAsString(i, module); + if (!success) { + error.SetErrorStringWithFormat( + "SFBM::CFSD: filter module item %zu not a string.", i); + return result_sp; + } + modules.Append(FileSpec(module, false)); + } + } + + StructuredData::Array *cus_array = nullptr; + success = + data_dict.GetValueForKeyAsArray(GetKey(OptionNames::CUList), cus_array); + if (!success) { + error.SetErrorString("SFBM::CFSD: Could not find the CU list key."); + return result_sp; + } + + size_t num_cus = cus_array->GetSize(); + FileSpecList cus; + for (size_t i = 0; i < num_cus; i++) { + std::string cu; + success = cus_array->GetItemAtIndexAsString(i, cu); + if (!success) { + error.SetErrorStringWithFormat( + "SFBM::CFSD: filter cu item %zu not a string.", i); + return nullptr; + } + cus.Append(FileSpec(cu, false)); + } + + return SearchFilterSP(new SearchFilterByModuleListAndCU( + target.shared_from_this(), modules, cus)); } -bool -SearchFilterByModuleListAndCU::CompUnitPasses (FileSpec &fileSpec) -{ - return m_cu_spec_list.FindFileIndex(0, fileSpec, false) != UINT32_MAX; +StructuredData::ObjectSP +SearchFilterByModuleListAndCU::SerializeToStructuredData() { + StructuredData::DictionarySP options_dict_sp( + new StructuredData::Dictionary()); + SearchFilterByModuleList::SerializeUnwrapped(options_dict_sp); + SerializeFileSpecList(options_dict_sp, OptionNames::CUList, m_cu_spec_list); + return WrapOptionsDict(options_dict_sp); } -bool -SearchFilterByModuleListAndCU::CompUnitPasses (CompileUnit &compUnit) -{ - bool in_cu_list = m_cu_spec_list.FindFileIndex(0, compUnit, false) != UINT32_MAX; - if (in_cu_list) - { - ModuleSP module_sp(compUnit.GetModule()); - if (module_sp) - { - bool module_passes = SearchFilterByModuleList::ModulePasses(module_sp); - return module_passes; - } - else - return true; - } - else - return false; +bool SearchFilterByModuleListAndCU::AddressPasses(Address &address) { + return true; } -void -SearchFilterByModuleListAndCU::Search (Searcher &searcher) -{ - if (!m_target_sp) - return; +bool SearchFilterByModuleListAndCU::CompUnitPasses(FileSpec &fileSpec) { + return m_cu_spec_list.FindFileIndex(0, fileSpec, false) != UINT32_MAX; +} - if (searcher.GetDepth() == Searcher::eDepthTarget) - { - SymbolContext empty_sc; - empty_sc.target_sp = m_target_sp; - searcher.SearchCallback(*this, empty_sc, nullptr, false); - } +bool SearchFilterByModuleListAndCU::CompUnitPasses(CompileUnit &compUnit) { + bool in_cu_list = + m_cu_spec_list.FindFileIndex(0, compUnit, false) != UINT32_MAX; + if (in_cu_list) { + ModuleSP module_sp(compUnit.GetModule()); + if (module_sp) { + bool module_passes = SearchFilterByModuleList::ModulePasses(module_sp); + return module_passes; + } else + return true; + } else + return false; +} - // If the module file spec is a full path, then we can just find the one - // filespec that passes. Otherwise, we need to go through all modules and - // find the ones that match the file name. - - ModuleList matching_modules; - const ModuleList &target_images = m_target_sp->GetImages(); - std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex()); - - const size_t num_modules = target_images.GetSize (); - bool no_modules_in_filter = m_module_spec_list.GetSize() == 0; - for (size_t i = 0; i < num_modules; i++) - { - lldb::ModuleSP module_sp = target_images.GetModuleAtIndexUnlocked(i); - if (no_modules_in_filter || - m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) != UINT32_MAX) - { - SymbolContext matchingContext(m_target_sp, module_sp); - Searcher::CallbackReturn shouldContinue; - - if (searcher.GetDepth() == Searcher::eDepthModule) - { - shouldContinue = DoModuleIteration(matchingContext, searcher); - if (shouldContinue == Searcher::eCallbackReturnStop) - return; - } - else - { - const size_t num_cu = module_sp->GetNumCompileUnits(); - for (size_t cu_idx = 0; cu_idx < num_cu; cu_idx++) - { - CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(cu_idx); - matchingContext.comp_unit = cu_sp.get(); - if (matchingContext.comp_unit) - { - if (m_cu_spec_list.FindFileIndex(0, *matchingContext.comp_unit, false) != UINT32_MAX) - { - shouldContinue = DoCUIteration(module_sp, matchingContext, searcher); - if (shouldContinue == Searcher::eCallbackReturnStop) - return; - } - } - } +void SearchFilterByModuleListAndCU::Search(Searcher &searcher) { + if (!m_target_sp) + return; + + if (searcher.GetDepth() == Searcher::eDepthTarget) { + SymbolContext empty_sc; + empty_sc.target_sp = m_target_sp; + searcher.SearchCallback(*this, empty_sc, nullptr, false); + } + + // If the module file spec is a full path, then we can just find the one + // filespec that passes. Otherwise, we need to go through all modules and + // find the ones that match the file name. + + ModuleList matching_modules; + const ModuleList &target_images = m_target_sp->GetImages(); + std::lock_guard<std::recursive_mutex> guard(target_images.GetMutex()); + + const size_t num_modules = target_images.GetSize(); + bool no_modules_in_filter = m_module_spec_list.GetSize() == 0; + for (size_t i = 0; i < num_modules; i++) { + lldb::ModuleSP module_sp = target_images.GetModuleAtIndexUnlocked(i); + if (no_modules_in_filter || + m_module_spec_list.FindFileIndex(0, module_sp->GetFileSpec(), false) != + UINT32_MAX) { + SymbolContext matchingContext(m_target_sp, module_sp); + Searcher::CallbackReturn shouldContinue; + + if (searcher.GetDepth() == Searcher::eDepthModule) { + shouldContinue = DoModuleIteration(matchingContext, searcher); + if (shouldContinue == Searcher::eCallbackReturnStop) + return; + } else { + const size_t num_cu = module_sp->GetNumCompileUnits(); + for (size_t cu_idx = 0; cu_idx < num_cu; cu_idx++) { + CompUnitSP cu_sp = module_sp->GetCompileUnitAtIndex(cu_idx); + matchingContext.comp_unit = cu_sp.get(); + if (matchingContext.comp_unit) { + if (m_cu_spec_list.FindFileIndex(0, *matchingContext.comp_unit, + false) != UINT32_MAX) { + shouldContinue = + DoCUIteration(module_sp, matchingContext, searcher); + if (shouldContinue == Searcher::eCallbackReturnStop) + return; } + } } + } } -} - -void -SearchFilterByModuleListAndCU::GetDescription (Stream *s) -{ - size_t num_modules = m_module_spec_list.GetSize(); - if (num_modules == 1) - { - s->Printf (", module = "); - if (s->GetVerbose()) - { - char buffer[2048]; - m_module_spec_list.GetFileSpecAtIndex(0).GetPath(buffer, 2047); - s->PutCString(buffer); - } - else - { - s->PutCString(m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString("<Unknown>")); - } + } +} + +void SearchFilterByModuleListAndCU::GetDescription(Stream *s) { + size_t num_modules = m_module_spec_list.GetSize(); + if (num_modules == 1) { + s->Printf(", module = "); + if (s->GetVerbose()) { + char buffer[2048]; + m_module_spec_list.GetFileSpecAtIndex(0).GetPath(buffer, 2047); + s->PutCString(buffer); + } else { + s->PutCString( + m_module_spec_list.GetFileSpecAtIndex(0).GetFilename().AsCString( + "<Unknown>")); } - else if (num_modules > 0) - { - s->Printf (", modules(%" PRIu64 ") = ", static_cast<uint64_t>(num_modules)); - for (size_t i = 0; i < num_modules; i++) - { - if (s->GetVerbose()) - { - char buffer[2048]; - m_module_spec_list.GetFileSpecAtIndex(i).GetPath(buffer, 2047); - s->PutCString(buffer); - } - else - { - s->PutCString(m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString("<Unknown>")); - } - if (i != num_modules - 1) - s->PutCString (", "); - } + } else if (num_modules > 0) { + s->Printf(", modules(%" PRIu64 ") = ", static_cast<uint64_t>(num_modules)); + for (size_t i = 0; i < num_modules; i++) { + if (s->GetVerbose()) { + char buffer[2048]; + m_module_spec_list.GetFileSpecAtIndex(i).GetPath(buffer, 2047); + s->PutCString(buffer); + } else { + s->PutCString( + m_module_spec_list.GetFileSpecAtIndex(i).GetFilename().AsCString( + "<Unknown>")); + } + if (i != num_modules - 1) + s->PutCString(", "); } + } } -uint32_t -SearchFilterByModuleListAndCU::GetFilterRequiredItems() -{ - return eSymbolContextModule | eSymbolContextCompUnit; +uint32_t SearchFilterByModuleListAndCU::GetFilterRequiredItems() { + return eSymbolContextModule | eSymbolContextCompUnit; } -void -SearchFilterByModuleListAndCU::Dump (Stream *s) const -{ -} +void SearchFilterByModuleListAndCU::Dump(Stream *s) const {} lldb::SearchFilterSP -SearchFilterByModuleListAndCU::DoCopyForBreakpoint (Breakpoint &breakpoint) -{ - SearchFilterSP ret_sp(new SearchFilterByModuleListAndCU(*this)); - return ret_sp; +SearchFilterByModuleListAndCU::DoCopyForBreakpoint(Breakpoint &breakpoint) { + SearchFilterSP ret_sp(new SearchFilterByModuleListAndCU(*this)); + return ret_sp; } diff --git a/source/Core/Section.cpp b/source/Core/Section.cpp index 9622cb78970c..95bcdada5377 100644 --- a/source/Core/Section.cpp +++ b/source/Core/Section.cpp @@ -17,600 +17,491 @@ using namespace lldb; using namespace lldb_private; -Section::Section(const ModuleSP &module_sp, ObjectFile *obj_file, user_id_t sect_id, const ConstString &name, - SectionType sect_type, addr_t file_addr, addr_t byte_size, lldb::offset_t file_offset, - lldb::offset_t file_size, uint32_t log2align, uint32_t flags, uint32_t target_byte_size /*=1*/) - : ModuleChild(module_sp), - UserID(sect_id), - Flags(flags), - m_obj_file(obj_file), - m_type(sect_type), - m_parent_wp(), - m_name(name), - m_file_addr(file_addr), - m_byte_size(byte_size), - m_file_offset(file_offset), - m_file_size(file_size), - m_log2align(log2align), - m_children(), - m_fake(false), - m_encrypted(false), - m_thread_specific(false), - m_readable(false), - m_writable(false), - m_executable(false), - m_target_byte_size(target_byte_size) -{ -// printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s\n", -// this, module_sp.get(), sect_id, file_addr, file_addr + byte_size, file_offset, file_offset + file_size, flags, name.GetCString()); -} - -Section::Section(const lldb::SectionSP &parent_section_sp, const ModuleSP &module_sp, ObjectFile *obj_file, - user_id_t sect_id, const ConstString &name, SectionType sect_type, addr_t file_addr, addr_t byte_size, - lldb::offset_t file_offset, lldb::offset_t file_size, uint32_t log2align, uint32_t flags, +Section::Section(const ModuleSP &module_sp, ObjectFile *obj_file, + user_id_t sect_id, const ConstString &name, + SectionType sect_type, addr_t file_addr, addr_t byte_size, + lldb::offset_t file_offset, lldb::offset_t file_size, + uint32_t log2align, uint32_t flags, uint32_t target_byte_size /*=1*/) - : ModuleChild(module_sp), - UserID(sect_id), - Flags(flags), - m_obj_file(obj_file), - m_type(sect_type), - m_parent_wp(), - m_name(name), - m_file_addr(file_addr), - m_byte_size(byte_size), - m_file_offset(file_offset), - m_file_size(file_size), - m_log2align(log2align), - m_children(), - m_fake(false), - m_encrypted(false), - m_thread_specific(false), - m_readable(false), - m_writable(false), - m_executable(false), - m_target_byte_size(target_byte_size) -{ -// printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s.%s\n", -// this, module_sp.get(), sect_id, file_addr, file_addr + byte_size, file_offset, file_offset + file_size, flags, parent_section_sp->GetName().GetCString(), name.GetCString()); - if (parent_section_sp) - m_parent_wp = parent_section_sp; -} - -Section::~Section() -{ -// printf ("Section::~Section(%p)\n", this); -} - -addr_t -Section::GetFileAddress () const -{ - SectionSP parent_sp (GetParent ()); - if (parent_sp) - { - // This section has a parent which means m_file_addr is an offset into - // the parent section, so the file address for this section is the file - // address of the parent plus the offset - return parent_sp->GetFileAddress() + m_file_addr; - } + : ModuleChild(module_sp), UserID(sect_id), Flags(flags), + m_obj_file(obj_file), m_type(sect_type), m_parent_wp(), m_name(name), + m_file_addr(file_addr), m_byte_size(byte_size), + m_file_offset(file_offset), m_file_size(file_size), + m_log2align(log2align), m_children(), m_fake(false), m_encrypted(false), + m_thread_specific(false), m_readable(false), m_writable(false), + m_executable(false), m_target_byte_size(target_byte_size) { + // printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", + // addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " + // - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s\n", + // this, module_sp.get(), sect_id, file_addr, file_addr + + // byte_size, file_offset, file_offset + file_size, flags, + // name.GetCString()); +} + +Section::Section(const lldb::SectionSP &parent_section_sp, + const ModuleSP &module_sp, ObjectFile *obj_file, + user_id_t sect_id, const ConstString &name, + SectionType sect_type, addr_t file_addr, addr_t byte_size, + lldb::offset_t file_offset, lldb::offset_t file_size, + uint32_t log2align, uint32_t flags, + uint32_t target_byte_size /*=1*/) + : ModuleChild(module_sp), UserID(sect_id), Flags(flags), + m_obj_file(obj_file), m_type(sect_type), m_parent_wp(), m_name(name), + m_file_addr(file_addr), m_byte_size(byte_size), + m_file_offset(file_offset), m_file_size(file_size), + m_log2align(log2align), m_children(), m_fake(false), m_encrypted(false), + m_thread_specific(false), m_readable(false), m_writable(false), + m_executable(false), m_target_byte_size(target_byte_size) { + // printf ("Section::Section(%p): module=%p, sect_id = 0x%16.16" PRIx64 ", + // addr=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), file [0x%16.16" PRIx64 " + // - 0x%16.16" PRIx64 "), flags = 0x%8.8x, name = %s.%s\n", + // this, module_sp.get(), sect_id, file_addr, file_addr + + // byte_size, file_offset, file_offset + file_size, flags, + // parent_section_sp->GetName().GetCString(), name.GetCString()); + if (parent_section_sp) + m_parent_wp = parent_section_sp; +} + +Section::~Section() { + // printf ("Section::~Section(%p)\n", this); +} + +addr_t Section::GetFileAddress() const { + SectionSP parent_sp(GetParent()); + if (parent_sp) { + // This section has a parent which means m_file_addr is an offset into + // the parent section, so the file address for this section is the file + // address of the parent plus the offset + return parent_sp->GetFileAddress() + m_file_addr; + } + // This section has no parent, so m_file_addr is the file base address + return m_file_addr; +} + +bool Section::SetFileAddress(lldb::addr_t file_addr) { + SectionSP parent_sp(GetParent()); + if (parent_sp) { + if (m_file_addr >= file_addr) + return parent_sp->SetFileAddress(m_file_addr - file_addr); + return false; + } else { // This section has no parent, so m_file_addr is the file base address - return m_file_addr; -} - -bool -Section::SetFileAddress (lldb::addr_t file_addr) -{ - SectionSP parent_sp (GetParent ()); - if (parent_sp) - { - if (m_file_addr >= file_addr) - return parent_sp->SetFileAddress (m_file_addr - file_addr); - return false; - } - else - { - // This section has no parent, so m_file_addr is the file base address - m_file_addr = file_addr; - return true; - } + m_file_addr = file_addr; + return true; + } } -lldb::addr_t -Section::GetOffset () const -{ - // This section has a parent which means m_file_addr is an offset. - SectionSP parent_sp (GetParent ()); - if (parent_sp) - return m_file_addr; - - // This section has no parent, so there is no offset to be had - return 0; -} +lldb::addr_t Section::GetOffset() const { + // This section has a parent which means m_file_addr is an offset. + SectionSP parent_sp(GetParent()); + if (parent_sp) + return m_file_addr; -addr_t -Section::GetLoadBaseAddress (Target *target) const -{ - addr_t load_base_addr = LLDB_INVALID_ADDRESS; - SectionSP parent_sp (GetParent ()); - if (parent_sp) - { - load_base_addr = parent_sp->GetLoadBaseAddress (target); - if (load_base_addr != LLDB_INVALID_ADDRESS) - load_base_addr += GetOffset(); - } - if (load_base_addr == LLDB_INVALID_ADDRESS) - { - load_base_addr = target->GetSectionLoadList().GetSectionLoadAddress (const_cast<Section *>(this)->shared_from_this()); + // This section has no parent, so there is no offset to be had + return 0; +} + +addr_t Section::GetLoadBaseAddress(Target *target) const { + addr_t load_base_addr = LLDB_INVALID_ADDRESS; + SectionSP parent_sp(GetParent()); + if (parent_sp) { + load_base_addr = parent_sp->GetLoadBaseAddress(target); + if (load_base_addr != LLDB_INVALID_ADDRESS) + load_base_addr += GetOffset(); + } + if (load_base_addr == LLDB_INVALID_ADDRESS) { + load_base_addr = target->GetSectionLoadList().GetSectionLoadAddress( + const_cast<Section *>(this)->shared_from_this()); + } + return load_base_addr; +} + +bool Section::ResolveContainedAddress(addr_t offset, Address &so_addr) const { + const size_t num_children = m_children.GetSize(); + if (num_children > 0) { + for (size_t i = 0; i < num_children; i++) { + Section *child_section = m_children.GetSectionAtIndex(i).get(); + + addr_t child_offset = child_section->GetOffset(); + if (child_offset <= offset && + offset - child_offset < child_section->GetByteSize()) + return child_section->ResolveContainedAddress(offset - child_offset, + so_addr); } - return load_base_addr; -} - -bool -Section::ResolveContainedAddress (addr_t offset, Address &so_addr) const -{ - const size_t num_children = m_children.GetSize(); - if (num_children > 0) - { - for (size_t i=0; i<num_children; i++) - { - Section* child_section = m_children.GetSectionAtIndex (i).get(); - - addr_t child_offset = child_section->GetOffset(); - if (child_offset <= offset && offset - child_offset < child_section->GetByteSize()) - return child_section->ResolveContainedAddress (offset - child_offset, so_addr); - } - } - so_addr.SetOffset(offset); - so_addr.SetSection(const_cast<Section *>(this)->shared_from_this()); - + } + so_addr.SetOffset(offset); + so_addr.SetSection(const_cast<Section *>(this)->shared_from_this()); + #ifdef LLDB_CONFIGURATION_DEBUG - // For debug builds, ensure that there are no orphaned (i.e., moduleless) sections. - assert(GetModule().get()); + // For debug builds, ensure that there are no orphaned (i.e., moduleless) + // sections. + assert(GetModule().get()); #endif - return true; + return true; } -bool -Section::ContainsFileAddress (addr_t vm_addr) const -{ - const addr_t file_addr = GetFileAddress(); - if (file_addr != LLDB_INVALID_ADDRESS) - { - if (file_addr <= vm_addr) - { - const addr_t offset = (vm_addr - file_addr) * m_target_byte_size; - return offset < GetByteSize(); - } +bool Section::ContainsFileAddress(addr_t vm_addr) const { + const addr_t file_addr = GetFileAddress(); + if (file_addr != LLDB_INVALID_ADDRESS) { + if (file_addr <= vm_addr) { + const addr_t offset = (vm_addr - file_addr) * m_target_byte_size; + return offset < GetByteSize(); } - return false; + } + return false; } -int -Section::Compare (const Section& a, const Section& b) -{ - if (&a == &b) - return 0; - - const ModuleSP a_module_sp = a.GetModule(); - const ModuleSP b_module_sp = b.GetModule(); - if (a_module_sp == b_module_sp) - { - user_id_t a_sect_uid = a.GetID(); - user_id_t b_sect_uid = b.GetID(); - if (a_sect_uid < b_sect_uid) - return -1; - if (a_sect_uid > b_sect_uid) - return 1; - return 0; - } - else - { - // The modules are different, just compare the module pointers - if (a_module_sp.get() < b_module_sp.get()) - return -1; - else - return 1; // We already know the modules aren't equal - } -} - - -void -Section::Dump (Stream *s, Target *target, uint32_t depth) const -{ -// s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); - s->Indent(); - s->Printf("0x%8.8" PRIx64 " %-16s ", GetID(), GetSectionTypeAsCString (m_type)); - bool resolved = true; - addr_t addr = LLDB_INVALID_ADDRESS; +int Section::Compare(const Section &a, const Section &b) { + if (&a == &b) + return 0; - if (GetByteSize() == 0) - s->Printf("%39s", ""); + const ModuleSP a_module_sp = a.GetModule(); + const ModuleSP b_module_sp = b.GetModule(); + if (a_module_sp == b_module_sp) { + user_id_t a_sect_uid = a.GetID(); + user_id_t b_sect_uid = b.GetID(); + if (a_sect_uid < b_sect_uid) + return -1; + if (a_sect_uid > b_sect_uid) + return 1; + return 0; + } else { + // The modules are different, just compare the module pointers + if (a_module_sp.get() < b_module_sp.get()) + return -1; else - { - if (target) - addr = GetLoadBaseAddress (target); - - if (addr == LLDB_INVALID_ADDRESS) - { - if (target) - resolved = false; - addr = GetFileAddress(); - } - - VMRange range(addr, addr + m_byte_size); - range.Dump (s, 0); + return 1; // We already know the modules aren't equal + } +} + +void Section::Dump(Stream *s, Target *target, uint32_t depth) const { + // s->Printf("%.*p: ", (int)sizeof(void*) * 2, this); + s->Indent(); + s->Printf("0x%8.8" PRIx64 " %-16s ", GetID(), + GetSectionTypeAsCString(m_type)); + bool resolved = true; + addr_t addr = LLDB_INVALID_ADDRESS; + + if (GetByteSize() == 0) + s->Printf("%39s", ""); + else { + if (target) + addr = GetLoadBaseAddress(target); + + if (addr == LLDB_INVALID_ADDRESS) { + if (target) + resolved = false; + addr = GetFileAddress(); } - s->Printf("%c %c%c%c 0x%8.8" PRIx64 " 0x%8.8" PRIx64 " 0x%8.8x ", resolved ? ' ' : '*', m_readable ? 'r' : '-', - m_writable ? 'w' : '-', m_executable ? 'x' : '-', m_file_offset, m_file_size, Get()); + VMRange range(addr, addr + m_byte_size); + range.Dump(s, 0); + } + + s->Printf("%c %c%c%c 0x%8.8" PRIx64 " 0x%8.8" PRIx64 " 0x%8.8x ", + resolved ? ' ' : '*', m_readable ? 'r' : '-', + m_writable ? 'w' : '-', m_executable ? 'x' : '-', m_file_offset, + m_file_size, Get()); - DumpName (s); + DumpName(s); - s->EOL(); + s->EOL(); - if (depth > 0) - m_children.Dump(s, target, false, depth - 1); + if (depth > 0) + m_children.Dump(s, target, false, depth - 1); } -void -Section::DumpName (Stream *s) const -{ - SectionSP parent_sp (GetParent ()); - if (parent_sp) - { - parent_sp->DumpName (s); - s->PutChar('.'); - } - else - { - // The top most section prints the module basename - const char * name = NULL; - ModuleSP module_sp (GetModule()); - const FileSpec &file_spec = m_obj_file->GetFileSpec(); - - if (m_obj_file) - name = file_spec.GetFilename().AsCString(); - if ((!name || !name[0]) && module_sp) - name = module_sp->GetFileSpec().GetFilename().AsCString(); - if (name && name[0]) - s->Printf("%s.", name); - } - m_name.Dump(s); +void Section::DumpName(Stream *s) const { + SectionSP parent_sp(GetParent()); + if (parent_sp) { + parent_sp->DumpName(s); + s->PutChar('.'); + } else { + // The top most section prints the module basename + const char *name = NULL; + ModuleSP module_sp(GetModule()); + const FileSpec &file_spec = m_obj_file->GetFileSpec(); + + if (m_obj_file) + name = file_spec.GetFilename().AsCString(); + if ((!name || !name[0]) && module_sp) + name = module_sp->GetFileSpec().GetFilename().AsCString(); + if (name && name[0]) + s->Printf("%s.", name); + } + m_name.Dump(s); } -bool -Section::IsDescendant (const Section *section) -{ - if (this == section) - return true; - SectionSP parent_sp (GetParent ()); - if (parent_sp) - return parent_sp->IsDescendant (section); - return false; +bool Section::IsDescendant(const Section *section) { + if (this == section) + return true; + SectionSP parent_sp(GetParent()); + if (parent_sp) + return parent_sp->IsDescendant(section); + return false; } -bool -Section::Slide (addr_t slide_amount, bool slide_children) -{ - if (m_file_addr != LLDB_INVALID_ADDRESS) - { - if (slide_amount == 0) - return true; +bool Section::Slide(addr_t slide_amount, bool slide_children) { + if (m_file_addr != LLDB_INVALID_ADDRESS) { + if (slide_amount == 0) + return true; - m_file_addr += slide_amount; + m_file_addr += slide_amount; - if (slide_children) - m_children.Slide (slide_amount, slide_children); + if (slide_children) + m_children.Slide(slide_amount, slide_children); - return true; - } - return false; + return true; + } + return false; } //------------------------------------------------------------------ /// Get the permissions as OR'ed bits from lldb::Permissions //------------------------------------------------------------------ -uint32_t -Section::GetPermissions() const -{ - uint32_t permissions = 0; - if (m_readable) - permissions |= ePermissionsReadable; - if (m_writable) - permissions |= ePermissionsWritable; - if (m_executable) - permissions |= ePermissionsExecutable; - return permissions; +uint32_t Section::GetPermissions() const { + uint32_t permissions = 0; + if (m_readable) + permissions |= ePermissionsReadable; + if (m_writable) + permissions |= ePermissionsWritable; + if (m_executable) + permissions |= ePermissionsExecutable; + return permissions; } //------------------------------------------------------------------ /// Set the permissions using bits OR'ed from lldb::Permissions //------------------------------------------------------------------ -void -Section::SetPermissions(uint32_t permissions) -{ - m_readable = (permissions & ePermissionsReadable) != 0; - m_writable = (permissions & ePermissionsWritable) != 0; - m_executable = (permissions & ePermissionsExecutable) != 0; +void Section::SetPermissions(uint32_t permissions) { + m_readable = (permissions & ePermissionsReadable) != 0; + m_writable = (permissions & ePermissionsWritable) != 0; + m_executable = (permissions & ePermissionsExecutable) != 0; } -lldb::offset_t -Section::GetSectionData (void *dst, lldb::offset_t dst_len, lldb::offset_t offset) -{ - if (m_obj_file) - return m_obj_file->ReadSectionData (this, - offset, - dst, - dst_len); - return 0; +lldb::offset_t Section::GetSectionData(void *dst, lldb::offset_t dst_len, + lldb::offset_t offset) { + if (m_obj_file) + return m_obj_file->ReadSectionData(this, offset, dst, dst_len); + return 0; } -lldb::offset_t -Section::GetSectionData (DataExtractor& section_data) const -{ - if (m_obj_file) - return m_obj_file->ReadSectionData (this, section_data); - return 0; +lldb::offset_t Section::GetSectionData(DataExtractor §ion_data) const { + if (m_obj_file) + return m_obj_file->ReadSectionData(this, section_data); + return 0; } #pragma mark SectionList -SectionList::SectionList () : - m_sections() -{ -} - +SectionList::SectionList() : m_sections() {} -SectionList::~SectionList () -{ -} +SectionList::~SectionList() {} -SectionList & -SectionList::operator = (const SectionList& rhs) -{ - if (this != &rhs) - m_sections = rhs.m_sections; - return *this; +SectionList &SectionList::operator=(const SectionList &rhs) { + if (this != &rhs) + m_sections = rhs.m_sections; + return *this; } -size_t -SectionList::AddSection (const lldb::SectionSP& section_sp) -{ - if (section_sp) - { - size_t section_index = m_sections.size(); - m_sections.push_back(section_sp); - return section_index; - } +size_t SectionList::AddSection(const lldb::SectionSP §ion_sp) { + if (section_sp) { + size_t section_index = m_sections.size(); + m_sections.push_back(section_sp); + return section_index; + } - return std::numeric_limits<size_t>::max (); + return std::numeric_limits<size_t>::max(); } // Warning, this can be slow as it's removing items from a std::vector. -bool -SectionList::DeleteSection (size_t idx) -{ - if (idx < m_sections.size()) - { - m_sections.erase (m_sections.begin() + idx); - return true; - } - return false; -} - -size_t -SectionList::FindSectionIndex (const Section* sect) -{ - iterator sect_iter; - iterator begin = m_sections.begin(); - iterator end = m_sections.end(); - for (sect_iter = begin; sect_iter != end; ++sect_iter) - { - if (sect_iter->get() == sect) - { - // The secton was already in this section list - return std::distance (begin, sect_iter); - } - } - return UINT32_MAX; -} - -size_t -SectionList::AddUniqueSection (const lldb::SectionSP& sect_sp) -{ - size_t sect_idx = FindSectionIndex (sect_sp.get()); - if (sect_idx == UINT32_MAX) - { - sect_idx = AddSection (sect_sp); - } - return sect_idx; -} - -bool -SectionList::ReplaceSection (user_id_t sect_id, const lldb::SectionSP& sect_sp, uint32_t depth) -{ - iterator sect_iter, end = m_sections.end(); - for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter) - { - if ((*sect_iter)->GetID() == sect_id) - { - *sect_iter = sect_sp; - return true; - } - else if (depth > 0) - { - if ((*sect_iter)->GetChildren().ReplaceSection(sect_id, sect_sp, depth - 1)) - return true; - } +bool SectionList::DeleteSection(size_t idx) { + if (idx < m_sections.size()) { + m_sections.erase(m_sections.begin() + idx); + return true; + } + return false; +} + +size_t SectionList::FindSectionIndex(const Section *sect) { + iterator sect_iter; + iterator begin = m_sections.begin(); + iterator end = m_sections.end(); + for (sect_iter = begin; sect_iter != end; ++sect_iter) { + if (sect_iter->get() == sect) { + // The secton was already in this section list + return std::distance(begin, sect_iter); } - return false; -} - -size_t -SectionList::GetNumSections (uint32_t depth) const -{ - size_t count = m_sections.size(); - if (depth > 0) - { - const_iterator sect_iter, end = m_sections.end(); - for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter) - { - count += (*sect_iter)->GetChildren().GetNumSections(depth - 1); - } + } + return UINT32_MAX; +} + +size_t SectionList::AddUniqueSection(const lldb::SectionSP §_sp) { + size_t sect_idx = FindSectionIndex(sect_sp.get()); + if (sect_idx == UINT32_MAX) { + sect_idx = AddSection(sect_sp); + } + return sect_idx; +} + +bool SectionList::ReplaceSection(user_id_t sect_id, + const lldb::SectionSP §_sp, + uint32_t depth) { + iterator sect_iter, end = m_sections.end(); + for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter) { + if ((*sect_iter)->GetID() == sect_id) { + *sect_iter = sect_sp; + return true; + } else if (depth > 0) { + if ((*sect_iter) + ->GetChildren() + .ReplaceSection(sect_id, sect_sp, depth - 1)) + return true; } - return count; + } + return false; } -SectionSP -SectionList::GetSectionAtIndex (size_t idx) const -{ - SectionSP sect_sp; - if (idx < m_sections.size()) - sect_sp = m_sections[idx]; - return sect_sp; -} - -SectionSP -SectionList::FindSectionByName (const ConstString §ion_dstr) const -{ - SectionSP sect_sp; - // Check if we have a valid section string - if (section_dstr && !m_sections.empty()) - { - const_iterator sect_iter; - const_iterator end = m_sections.end(); - for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter) - { - Section *child_section = sect_iter->get(); - if (child_section) - { - if (child_section->GetName() == section_dstr) - { - sect_sp = *sect_iter; - } - else - { - sect_sp = child_section->GetChildren().FindSectionByName(section_dstr); - } - } - } +size_t SectionList::GetNumSections(uint32_t depth) const { + size_t count = m_sections.size(); + if (depth > 0) { + const_iterator sect_iter, end = m_sections.end(); + for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter) { + count += (*sect_iter)->GetChildren().GetNumSections(depth - 1); } - return sect_sp; + } + return count; } -SectionSP -SectionList::FindSectionByID (user_id_t sect_id) const -{ - SectionSP sect_sp; - if (sect_id) - { - const_iterator sect_iter; - const_iterator end = m_sections.end(); - for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter) - { - if ((*sect_iter)->GetID() == sect_id) - { - sect_sp = *sect_iter; - break; - } - else - { - sect_sp = (*sect_iter)->GetChildren().FindSectionByID (sect_id); - } - } - } - return sect_sp; +SectionSP SectionList::GetSectionAtIndex(size_t idx) const { + SectionSP sect_sp; + if (idx < m_sections.size()) + sect_sp = m_sections[idx]; + return sect_sp; } - SectionSP -SectionList::FindSectionByType (SectionType sect_type, bool check_children, size_t start_idx) const -{ - SectionSP sect_sp; - size_t num_sections = m_sections.size(); - for (size_t idx = start_idx; idx < num_sections; ++idx) - { - if (m_sections[idx]->GetType() == sect_type) - { - sect_sp = m_sections[idx]; - break; - } - else if (check_children) - { - sect_sp = m_sections[idx]->GetChildren().FindSectionByType (sect_type, check_children, 0); - if (sect_sp) - break; +SectionList::FindSectionByName(const ConstString §ion_dstr) const { + SectionSP sect_sp; + // Check if we have a valid section string + if (section_dstr && !m_sections.empty()) { + const_iterator sect_iter; + const_iterator end = m_sections.end(); + for (sect_iter = m_sections.begin(); + sect_iter != end && sect_sp.get() == NULL; ++sect_iter) { + Section *child_section = sect_iter->get(); + if (child_section) { + if (child_section->GetName() == section_dstr) { + sect_sp = *sect_iter; + } else { + sect_sp = + child_section->GetChildren().FindSectionByName(section_dstr); } + } } - return sect_sp; + } + return sect_sp; } -SectionSP -SectionList::FindSectionContainingFileAddress (addr_t vm_addr, uint32_t depth) const -{ - SectionSP sect_sp; +SectionSP SectionList::FindSectionByID(user_id_t sect_id) const { + SectionSP sect_sp; + if (sect_id) { const_iterator sect_iter; const_iterator end = m_sections.end(); - for (sect_iter = m_sections.begin(); sect_iter != end && sect_sp.get() == NULL; ++sect_iter) - { - Section *sect = sect_iter->get(); - if (sect->ContainsFileAddress (vm_addr)) - { - // The file address is in this section. We need to make sure one of our child - // sections doesn't contain this address as well as obeying the depth limit - // that was passed in. - if (depth > 0) - sect_sp = sect->GetChildren().FindSectionContainingFileAddress(vm_addr, depth - 1); - - if (sect_sp.get() == NULL && !sect->IsFake()) - sect_sp = *sect_iter; - } + for (sect_iter = m_sections.begin(); + sect_iter != end && sect_sp.get() == NULL; ++sect_iter) { + if ((*sect_iter)->GetID() == sect_id) { + sect_sp = *sect_iter; + break; + } else { + sect_sp = (*sect_iter)->GetChildren().FindSectionByID(sect_id); + } } - return sect_sp; -} - -bool -SectionList::ContainsSection(user_id_t sect_id) const -{ - return FindSectionByID (sect_id).get() != NULL; -} - -void -SectionList::Dump (Stream *s, Target *target, bool show_header, uint32_t depth) const -{ - bool target_has_loaded_sections = target && !target->GetSectionLoadList().IsEmpty(); - if (show_header && !m_sections.empty()) - { - s->Indent(); - s->Printf("SectID Type %s Address Perm File Off. File Size Flags " - " Section Name\n", - target_has_loaded_sections ? "Load" : "File"); - s->Indent(); - s->PutCString("---------- ---------------- --------------------------------------- ---- ---------- ---------- " - "---------- ----------------------------\n"); + } + return sect_sp; +} + +SectionSP SectionList::FindSectionByType(SectionType sect_type, + bool check_children, + size_t start_idx) const { + SectionSP sect_sp; + size_t num_sections = m_sections.size(); + for (size_t idx = start_idx; idx < num_sections; ++idx) { + if (m_sections[idx]->GetType() == sect_type) { + sect_sp = m_sections[idx]; + break; + } else if (check_children) { + sect_sp = m_sections[idx]->GetChildren().FindSectionByType( + sect_type, check_children, 0); + if (sect_sp) + break; } - - - const_iterator sect_iter; - const_iterator end = m_sections.end(); - for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter) - { - (*sect_iter)->Dump(s, target_has_loaded_sections ? target : NULL, depth); + } + return sect_sp; +} + +SectionSP SectionList::FindSectionContainingFileAddress(addr_t vm_addr, + uint32_t depth) const { + SectionSP sect_sp; + const_iterator sect_iter; + const_iterator end = m_sections.end(); + for (sect_iter = m_sections.begin(); + sect_iter != end && sect_sp.get() == NULL; ++sect_iter) { + Section *sect = sect_iter->get(); + if (sect->ContainsFileAddress(vm_addr)) { + // The file address is in this section. We need to make sure one of our + // child + // sections doesn't contain this address as well as obeying the depth + // limit + // that was passed in. + if (depth > 0) + sect_sp = sect->GetChildren().FindSectionContainingFileAddress( + vm_addr, depth - 1); + + if (sect_sp.get() == NULL && !sect->IsFake()) + sect_sp = *sect_iter; } + } + return sect_sp; +} - if (show_header && !m_sections.empty()) - s->IndentLess(); - +bool SectionList::ContainsSection(user_id_t sect_id) const { + return FindSectionByID(sect_id).get() != NULL; } -size_t -SectionList::Slide (addr_t slide_amount, bool slide_children) -{ - size_t count = 0; - const_iterator pos, end = m_sections.end(); - for (pos = m_sections.begin(); pos != end; ++pos) - { - if ((*pos)->Slide(slide_amount, slide_children)) - ++count; - } - return count; +void SectionList::Dump(Stream *s, Target *target, bool show_header, + uint32_t depth) const { + bool target_has_loaded_sections = + target && !target->GetSectionLoadList().IsEmpty(); + if (show_header && !m_sections.empty()) { + s->Indent(); + s->Printf("SectID Type %s Address " + " Perm File Off. File Size Flags " + " Section Name\n", + target_has_loaded_sections ? "Load" : "File"); + s->Indent(); + s->PutCString("---------- ---------------- " + "--------------------------------------- ---- ---------- " + "---------- " + "---------- ----------------------------\n"); + } + + const_iterator sect_iter; + const_iterator end = m_sections.end(); + for (sect_iter = m_sections.begin(); sect_iter != end; ++sect_iter) { + (*sect_iter)->Dump(s, target_has_loaded_sections ? target : NULL, depth); + } + + if (show_header && !m_sections.empty()) + s->IndentLess(); +} + +size_t SectionList::Slide(addr_t slide_amount, bool slide_children) { + size_t count = 0; + const_iterator pos, end = m_sections.end(); + for (pos = m_sections.begin(); pos != end; ++pos) { + if ((*pos)->Slide(slide_amount, slide_children)) + ++count; + } + return count; } diff --git a/source/Core/SourceManager.cpp b/source/Core/SourceManager.cpp index a69e75fe244a..603fe5711498 100644 --- a/source/Core/SourceManager.cpp +++ b/source/Core/SourceManager.cpp @@ -18,682 +18,680 @@ #include "lldb/Core/Module.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/Stream.h" +#include "lldb/Host/FileSystem.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/Target.h" +#include "lldb/Utility/AnsiTerminal.h" using namespace lldb; using namespace lldb_private; - -static inline bool is_newline_char(char ch) -{ - return ch == '\n' || ch == '\r'; -} - +static inline bool is_newline_char(char ch) { return ch == '\n' || ch == '\r'; } //---------------------------------------------------------------------- // SourceManager constructor //---------------------------------------------------------------------- -SourceManager::SourceManager(const TargetSP &target_sp) : - m_last_file_sp (), - m_last_line (0), - m_last_count (0), - m_default_set(false), - m_target_wp (target_sp), - m_debugger_wp(target_sp->GetDebugger().shared_from_this()) -{ -} +SourceManager::SourceManager(const TargetSP &target_sp) + : m_last_file_sp(), m_last_line(0), m_last_count(0), m_default_set(false), + m_target_wp(target_sp), + m_debugger_wp(target_sp->GetDebugger().shared_from_this()) {} -SourceManager::SourceManager(const DebuggerSP &debugger_sp) : - m_last_file_sp (), - m_last_line (0), - m_last_count (0), - m_default_set(false), - m_target_wp (), - m_debugger_wp (debugger_sp) -{ -} +SourceManager::SourceManager(const DebuggerSP &debugger_sp) + : m_last_file_sp(), m_last_line(0), m_last_count(0), m_default_set(false), + m_target_wp(), m_debugger_wp(debugger_sp) {} //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -SourceManager::~SourceManager() -{ -} +SourceManager::~SourceManager() {} + +SourceManager::FileSP SourceManager::GetFile(const FileSpec &file_spec) { + bool same_as_previous = + m_last_file_sp && m_last_file_sp->FileSpecMatches(file_spec); + + DebuggerSP debugger_sp(m_debugger_wp.lock()); + FileSP file_sp; + if (same_as_previous) + file_sp = m_last_file_sp; + else if (debugger_sp) + file_sp = debugger_sp->GetSourceFileCache().FindSourceFile(file_spec); + + TargetSP target_sp(m_target_wp.lock()); + + // It the target source path map has been updated, get this file again so we + // can successfully remap the source file + if (target_sp && file_sp && + file_sp->GetSourceMapModificationID() != + target_sp->GetSourcePathMap().GetModificationID()) + file_sp.reset(); + + // Update the file contents if needed if we found a file + if (file_sp) + file_sp->UpdateIfNeeded(); + + // If file_sp is no good or it points to a non-existent file, reset it. + if (!file_sp || !file_sp->GetFileSpec().Exists()) { + if (target_sp) + file_sp.reset(new File(file_spec, target_sp.get())); + else + file_sp.reset(new File(file_spec, debugger_sp)); -SourceManager::FileSP -SourceManager::GetFile (const FileSpec &file_spec) -{ - bool same_as_previous = m_last_file_sp && m_last_file_sp->FileSpecMatches (file_spec); - - DebuggerSP debugger_sp (m_debugger_wp.lock()); - FileSP file_sp; - if (same_as_previous) - file_sp = m_last_file_sp; - else if (debugger_sp) - file_sp = debugger_sp->GetSourceFileCache().FindSourceFile (file_spec); - - TargetSP target_sp (m_target_wp.lock()); - - // It the target source path map has been updated, get this file again so we - // can successfully remap the source file - if (target_sp && file_sp && file_sp->GetSourceMapModificationID() != target_sp->GetSourcePathMap().GetModificationID()) - file_sp.reset(); - - // Update the file contents if needed if we found a file - if (file_sp) - file_sp->UpdateIfNeeded(); - - // If file_sp is no good or it points to a non-existent file, reset it. - if (!file_sp || !file_sp->GetFileSpec().Exists()) - { - file_sp.reset (new File (file_spec, target_sp.get())); - - if (debugger_sp) - debugger_sp->GetSourceFileCache().AddSourceFile(file_sp); - } - return file_sp; + if (debugger_sp) + debugger_sp->GetSourceFileCache().AddSourceFile(file_sp); + } + return file_sp; } -size_t -SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile (uint32_t start_line, - uint32_t count, - uint32_t curr_line, - const char* current_line_cstr, - Stream *s, - const SymbolContextList *bp_locs) -{ - if (count == 0) - return 0; - size_t return_value = 0; - if (start_line == 0) - { - if (m_last_line != 0 && m_last_line != UINT32_MAX) - start_line = m_last_line + m_last_count; - else - start_line = 1; - } +static bool should_show_stop_column_with_ansi(DebuggerSP debugger_sp) { + // We don't use ANSI stop column formatting if we can't lookup values from + // the debugger. + if (!debugger_sp) + return false; - if (!m_default_set) - { - FileSpec tmp_spec; - uint32_t tmp_line; - GetDefaultFileAndLine(tmp_spec, tmp_line); - } + // We don't use ANSI stop column formatting if the debugger doesn't think + // it should be using color. + if (!debugger_sp->GetUseColor()) + return false; - m_last_line = start_line; - m_last_count = count; - - if (m_last_file_sp.get()) - { - const uint32_t end_line = start_line + count - 1; - for (uint32_t line = start_line; line <= end_line; ++line) - { - if (!m_last_file_sp->LineIsValid (line)) - { - m_last_line = UINT32_MAX; - break; - } + // We only use ANSI stop column formatting if we're either supposed to show + // ANSI where available (which we know we have when we get to this point), or + // if we're only supposed to use ANSI. + const auto value = debugger_sp->GetStopShowColumn(); + return ((value == eStopShowColumnAnsiOrCaret) || + (value == eStopShowColumnAnsi)); +} - char prefix[32] = ""; - if (bp_locs) - { - uint32_t bp_count = bp_locs->NumLineEntriesWithLine (line); - - if (bp_count > 0) - ::snprintf (prefix, sizeof (prefix), "[%u] ", bp_count); - else - ::snprintf (prefix, sizeof (prefix), " "); - } +static bool should_show_stop_column_with_caret(DebuggerSP debugger_sp) { + // We don't use text-based stop column formatting if we can't lookup values + // from the debugger. + if (!debugger_sp) + return false; - return_value += s->Printf("%s%2.2s %-4u\t", - prefix, - line == curr_line ? current_line_cstr : "", - line); - size_t this_line_size = m_last_file_sp->DisplaySourceLines (line, 0, 0, s); - if (this_line_size == 0) - { - m_last_line = UINT32_MAX; - break; - } - else - return_value += this_line_size; - } - } - return return_value; + // If we're asked to show the first available of ANSI or caret, then + // we do show the caret when ANSI is not available. + const auto value = debugger_sp->GetStopShowColumn(); + if ((value == eStopShowColumnAnsiOrCaret) && !debugger_sp->GetUseColor()) + return true; + + // The only other time we use caret is if we're explicitly asked to show + // caret. + return value == eStopShowColumnCaret; } -size_t -SourceManager::DisplaySourceLinesWithLineNumbers -( - const FileSpec &file_spec, - uint32_t line, - uint32_t context_before, - uint32_t context_after, - const char* current_line_cstr, - Stream *s, - const SymbolContextList *bp_locs -) -{ - FileSP file_sp (GetFile (file_spec)); - - uint32_t start_line; - uint32_t count = context_before + context_after + 1; - if (line > context_before) - start_line = line - context_before; +size_t SourceManager::DisplaySourceLinesWithLineNumbersUsingLastFile( + uint32_t start_line, uint32_t count, uint32_t curr_line, uint32_t column, + const char *current_line_cstr, Stream *s, + const SymbolContextList *bp_locs) { + if (count == 0) + return 0; + size_t return_value = 0; + if (start_line == 0) { + if (m_last_line != 0 && m_last_line != UINT32_MAX) + start_line = m_last_line + m_last_count; else - start_line = 1; - - if (m_last_file_sp.get() != file_sp.get()) - { - if (line == 0) - m_last_line = 0; - m_last_file_sp = file_sp; + start_line = 1; + } + + if (!m_default_set) { + FileSpec tmp_spec; + uint32_t tmp_line; + GetDefaultFileAndLine(tmp_spec, tmp_line); + } + + m_last_line = start_line; + m_last_count = count; + + if (m_last_file_sp.get()) { + const uint32_t end_line = start_line + count - 1; + for (uint32_t line = start_line; line <= end_line; ++line) { + if (!m_last_file_sp->LineIsValid(line)) { + m_last_line = UINT32_MAX; + break; + } + + char prefix[32] = ""; + if (bp_locs) { + uint32_t bp_count = bp_locs->NumLineEntriesWithLine(line); + + if (bp_count > 0) + ::snprintf(prefix, sizeof(prefix), "[%u] ", bp_count); + else + ::snprintf(prefix, sizeof(prefix), " "); + } + + return_value += + s->Printf("%s%2.2s %-4u\t", prefix, + line == curr_line ? current_line_cstr : "", line); + size_t this_line_size = m_last_file_sp->DisplaySourceLines( + line, line == curr_line ? column : 0, 0, 0, s); + if (column != 0 && line == curr_line && + should_show_stop_column_with_caret(m_debugger_wp.lock())) { + // Display caret cursor. + std::string src_line; + m_last_file_sp->GetLine(line, src_line); + return_value += s->Printf(" \t"); + // Insert a space for every non-tab character in the source line. + for (size_t i = 0; i + 1 < column && i < src_line.length(); ++i) + return_value += s->PutChar(src_line[i] == '\t' ? '\t' : ' '); + // Now add the caret. + return_value += s->Printf("^\n"); + } + if (this_line_size == 0) { + m_last_line = UINT32_MAX; + break; + } else + return_value += this_line_size; } - return DisplaySourceLinesWithLineNumbersUsingLastFile (start_line, count, line, current_line_cstr, s, bp_locs); + } + return return_value; } -size_t -SourceManager::DisplayMoreWithLineNumbers (Stream *s, - uint32_t count, - bool reverse, - const SymbolContextList *bp_locs) -{ - // If we get called before anybody has set a default file and line, then try to figure it out here. - const bool have_default_file_line = m_last_file_sp && m_last_line > 0; - if (!m_default_set) - { - FileSpec tmp_spec; - uint32_t tmp_line; - GetDefaultFileAndLine(tmp_spec, tmp_line); - } - - if (m_last_file_sp) - { - if (m_last_line == UINT32_MAX) - return 0; - - if (reverse && m_last_line == 1) - return 0; - - if (count > 0) - m_last_count = count; - else if (m_last_count == 0) - m_last_count = 10; - - if (m_last_line > 0) - { - if (reverse) - { - // If this is the first time we've done a reverse, then back up one more time so we end - // up showing the chunk before the last one we've shown: - if (m_last_line > m_last_count) - m_last_line -= m_last_count; - else - m_last_line = 1; - } - else if (have_default_file_line) - m_last_line += m_last_count; - } +size_t SourceManager::DisplaySourceLinesWithLineNumbers( + const FileSpec &file_spec, uint32_t line, uint32_t column, + uint32_t context_before, uint32_t context_after, + const char *current_line_cstr, Stream *s, + const SymbolContextList *bp_locs) { + FileSP file_sp(GetFile(file_spec)); + + uint32_t start_line; + uint32_t count = context_before + context_after + 1; + if (line > context_before) + start_line = line - context_before; + else + start_line = 1; + + if (m_last_file_sp.get() != file_sp.get()) { + if (line == 0) + m_last_line = 0; + m_last_file_sp = file_sp; + } + return DisplaySourceLinesWithLineNumbersUsingLastFile( + start_line, count, line, column, current_line_cstr, s, bp_locs); +} + +size_t SourceManager::DisplayMoreWithLineNumbers( + Stream *s, uint32_t count, bool reverse, const SymbolContextList *bp_locs) { + // If we get called before anybody has set a default file and line, then try + // to figure it out here. + const bool have_default_file_line = m_last_file_sp && m_last_line > 0; + if (!m_default_set) { + FileSpec tmp_spec; + uint32_t tmp_line; + GetDefaultFileAndLine(tmp_spec, tmp_line); + } + + if (m_last_file_sp) { + if (m_last_line == UINT32_MAX) + return 0; + + if (reverse && m_last_line == 1) + return 0; + + if (count > 0) + m_last_count = count; + else if (m_last_count == 0) + m_last_count = 10; + + if (m_last_line > 0) { + if (reverse) { + // If this is the first time we've done a reverse, then back up one more + // time so we end + // up showing the chunk before the last one we've shown: + if (m_last_line > m_last_count) + m_last_line -= m_last_count; else - m_last_line = 1; - - return DisplaySourceLinesWithLineNumbersUsingLastFile (m_last_line, m_last_count, UINT32_MAX, "", s, bp_locs); - } - return 0; + m_last_line = 1; + } else if (have_default_file_line) + m_last_line += m_last_count; + } else + m_last_line = 1; + + const uint32_t column = 0; + return DisplaySourceLinesWithLineNumbersUsingLastFile( + m_last_line, m_last_count, UINT32_MAX, column, "", s, bp_locs); + } + return 0; } -bool -SourceManager::SetDefaultFileAndLine (const FileSpec &file_spec, uint32_t line) -{ - FileSP old_file_sp = m_last_file_sp; - m_last_file_sp = GetFile (file_spec); - - m_default_set = true; - if (m_last_file_sp) - { - m_last_line = line; - return true; - } - else - { - m_last_file_sp = old_file_sp; - return false; - } +bool SourceManager::SetDefaultFileAndLine(const FileSpec &file_spec, + uint32_t line) { + FileSP old_file_sp = m_last_file_sp; + m_last_file_sp = GetFile(file_spec); + + m_default_set = true; + if (m_last_file_sp) { + m_last_line = line; + return true; + } else { + m_last_file_sp = old_file_sp; + return false; + } } -bool -SourceManager::GetDefaultFileAndLine (FileSpec &file_spec, uint32_t &line) -{ - if (m_last_file_sp) - { - file_spec = m_last_file_sp->GetFileSpec(); - line = m_last_line; - return true; - } - else if (!m_default_set) - { - TargetSP target_sp (m_target_wp.lock()); - - if (target_sp) - { - // If nobody has set the default file and line then try here. If there's no executable, then we - // will try again later when there is one. Otherwise, if we can't find it we won't look again, - // somebody will have to set it (for instance when we stop somewhere...) - Module *executable_ptr = target_sp->GetExecutableModulePointer(); - if (executable_ptr) - { - SymbolContextList sc_list; - ConstString main_name("main"); - bool symbols_okay = false; // Force it to be a debug symbol. - bool inlines_okay = true; - bool append = false; - size_t num_matches = executable_ptr->FindFunctions (main_name, - NULL, - lldb::eFunctionNameTypeBase, - inlines_okay, - symbols_okay, - append, - sc_list); - for (size_t idx = 0; idx < num_matches; idx++) - { - SymbolContext sc; - sc_list.GetContextAtIndex(idx, sc); - if (sc.function) - { - lldb_private::LineEntry line_entry; - if (sc.function->GetAddressRange().GetBaseAddress().CalculateSymbolContextLineEntry (line_entry)) - { - SetDefaultFileAndLine (line_entry.file, - line_entry.line); - file_spec = m_last_file_sp->GetFileSpec(); - line = m_last_line; - return true; - } - } - } +bool SourceManager::GetDefaultFileAndLine(FileSpec &file_spec, uint32_t &line) { + if (m_last_file_sp) { + file_spec = m_last_file_sp->GetFileSpec(); + line = m_last_line; + return true; + } else if (!m_default_set) { + TargetSP target_sp(m_target_wp.lock()); + + if (target_sp) { + // If nobody has set the default file and line then try here. If there's + // no executable, then we + // will try again later when there is one. Otherwise, if we can't find it + // we won't look again, + // somebody will have to set it (for instance when we stop somewhere...) + Module *executable_ptr = target_sp->GetExecutableModulePointer(); + if (executable_ptr) { + SymbolContextList sc_list; + ConstString main_name("main"); + bool symbols_okay = false; // Force it to be a debug symbol. + bool inlines_okay = true; + bool append = false; + size_t num_matches = executable_ptr->FindFunctions( + main_name, NULL, lldb::eFunctionNameTypeBase, inlines_okay, + symbols_okay, append, sc_list); + for (size_t idx = 0; idx < num_matches; idx++) { + SymbolContext sc; + sc_list.GetContextAtIndex(idx, sc); + if (sc.function) { + lldb_private::LineEntry line_entry; + if (sc.function->GetAddressRange() + .GetBaseAddress() + .CalculateSymbolContextLineEntry(line_entry)) { + SetDefaultFileAndLine(line_entry.file, line_entry.line); + file_spec = m_last_file_sp->GetFileSpec(); + line = m_last_line; + return true; } + } } + } } - return false; + } + return false; } -void -SourceManager::FindLinesMatchingRegex (FileSpec &file_spec, - RegularExpression& regex, - uint32_t start_line, - uint32_t end_line, - std::vector<uint32_t> &match_lines) -{ - match_lines.clear(); - FileSP file_sp = GetFile (file_spec); - if (!file_sp) - return; - return file_sp->FindLinesMatchingRegex (regex, start_line, end_line, match_lines); +void SourceManager::FindLinesMatchingRegex(FileSpec &file_spec, + RegularExpression ®ex, + uint32_t start_line, + uint32_t end_line, + std::vector<uint32_t> &match_lines) { + match_lines.clear(); + FileSP file_sp = GetFile(file_spec); + if (!file_sp) + return; + return file_sp->FindLinesMatchingRegex(regex, start_line, end_line, + match_lines); } -SourceManager::File::File(const FileSpec &file_spec, Target *target) : - m_file_spec_orig (file_spec), - m_file_spec(file_spec), - m_mod_time (file_spec.GetModificationTime()), - m_source_map_mod_id (0), - m_data_sp(), - m_offsets() -{ - if (!m_mod_time.IsValid()) - { - if (target) - { - m_source_map_mod_id = target->GetSourcePathMap().GetModificationID(); - - if (!file_spec.GetDirectory() && file_spec.GetFilename()) - { - // If this is just a file name, lets see if we can find it in the target: - bool check_inlines = false; - SymbolContextList sc_list; - size_t num_matches = target->GetImages().ResolveSymbolContextForFilePath (file_spec.GetFilename().AsCString(), - 0, - check_inlines, - lldb::eSymbolContextModule | lldb::eSymbolContextCompUnit, - sc_list); - bool got_multiple = false; - if (num_matches != 0) - { - if (num_matches > 1) - { - SymbolContext sc; - FileSpec *test_cu_spec = NULL; - - for (unsigned i = 0; i < num_matches; i++) - { - sc_list.GetContextAtIndex(i, sc); - if (sc.comp_unit) - { - if (test_cu_spec) - { - if (test_cu_spec != static_cast<FileSpec *> (sc.comp_unit)) - got_multiple = true; - break; - } - else - test_cu_spec = sc.comp_unit; - } - } - } - if (!got_multiple) - { - SymbolContext sc; - sc_list.GetContextAtIndex (0, sc); - m_file_spec = sc.comp_unit; - m_mod_time = m_file_spec.GetModificationTime(); - } - } - } - // Try remapping if m_file_spec does not correspond to an existing file. - if (!m_file_spec.Exists()) - { - FileSpec new_file_spec; - // Check target specific source remappings first, then fall back to - // modules objects can have individual path remappings that were detected - // when the debug info for a module was found. - // then - if (target->GetSourcePathMap().FindFile (m_file_spec, new_file_spec) || - target->GetImages().FindSourceFile (m_file_spec, new_file_spec)) - { - m_file_spec = new_file_spec; - m_mod_time = m_file_spec.GetModificationTime(); - } +SourceManager::File::File(const FileSpec &file_spec, + lldb::DebuggerSP debugger_sp) + : m_file_spec_orig(file_spec), m_file_spec(file_spec), + m_mod_time(FileSystem::GetModificationTime(file_spec)), + m_debugger_wp(debugger_sp) { + CommonInitializer(file_spec, nullptr); +} + +SourceManager::File::File(const FileSpec &file_spec, Target *target) + : m_file_spec_orig(file_spec), m_file_spec(file_spec), + m_mod_time(FileSystem::GetModificationTime(file_spec)), + m_debugger_wp(target ? target->GetDebugger().shared_from_this() + : DebuggerSP()) { + CommonInitializer(file_spec, target); +} + +void SourceManager::File::CommonInitializer(const FileSpec &file_spec, + Target *target) { + if (m_mod_time == llvm::sys::TimePoint<>()) { + if (target) { + m_source_map_mod_id = target->GetSourcePathMap().GetModificationID(); + + if (!file_spec.GetDirectory() && file_spec.GetFilename()) { + // If this is just a file name, lets see if we can find it in the + // target: + bool check_inlines = false; + SymbolContextList sc_list; + size_t num_matches = + target->GetImages().ResolveSymbolContextForFilePath( + file_spec.GetFilename().AsCString(), 0, check_inlines, + lldb::eSymbolContextModule | lldb::eSymbolContextCompUnit, + sc_list); + bool got_multiple = false; + if (num_matches != 0) { + if (num_matches > 1) { + SymbolContext sc; + FileSpec *test_cu_spec = NULL; + + for (unsigned i = 0; i < num_matches; i++) { + sc_list.GetContextAtIndex(i, sc); + if (sc.comp_unit) { + if (test_cu_spec) { + if (test_cu_spec != static_cast<FileSpec *>(sc.comp_unit)) + got_multiple = true; + break; + } else + test_cu_spec = sc.comp_unit; + } } + } + if (!got_multiple) { + SymbolContext sc; + sc_list.GetContextAtIndex(0, sc); + m_file_spec = sc.comp_unit; + m_mod_time = FileSystem::GetModificationTime(m_file_spec); + } + } + } + // Try remapping if m_file_spec does not correspond to an existing file. + if (!m_file_spec.Exists()) { + FileSpec new_file_spec; + // Check target specific source remappings first, then fall back to + // modules objects can have individual path remappings that were + // detected + // when the debug info for a module was found. + // then + if (target->GetSourcePathMap().FindFile(m_file_spec, new_file_spec) || + target->GetImages().FindSourceFile(m_file_spec, new_file_spec)) { + m_file_spec = new_file_spec; + m_mod_time = FileSystem::GetModificationTime(m_file_spec); } + } } - - if (m_mod_time.IsValid()) - m_data_sp = m_file_spec.ReadFileContents (); -} + } -SourceManager::File::~File() -{ + if (m_mod_time != llvm::sys::TimePoint<>()) + m_data_sp = m_file_spec.ReadFileContents(); } -uint32_t -SourceManager::File::GetLineOffset (uint32_t line) -{ - if (line == 0) - return UINT32_MAX; +uint32_t SourceManager::File::GetLineOffset(uint32_t line) { + if (line == 0) + return UINT32_MAX; - if (line == 1) - return 0; + if (line == 1) + return 0; - if (CalculateLineOffsets (line)) - { - if (line < m_offsets.size()) - return m_offsets[line - 1]; // yes we want "line - 1" in the index - } - return UINT32_MAX; + if (CalculateLineOffsets(line)) { + if (line < m_offsets.size()) + return m_offsets[line - 1]; // yes we want "line - 1" in the index + } + return UINT32_MAX; } -uint32_t -SourceManager::File::GetNumLines () -{ - CalculateLineOffsets(); - return m_offsets.size(); +uint32_t SourceManager::File::GetNumLines() { + CalculateLineOffsets(); + return m_offsets.size(); } -const char * -SourceManager::File::PeekLineData (uint32_t line) -{ - if (!LineIsValid(line)) - return NULL; - - size_t line_offset = GetLineOffset (line); - if (line_offset < m_data_sp->GetByteSize()) - return (const char *)m_data_sp->GetBytes() + line_offset; +const char *SourceManager::File::PeekLineData(uint32_t line) { + if (!LineIsValid(line)) return NULL; + + size_t line_offset = GetLineOffset(line); + if (line_offset < m_data_sp->GetByteSize()) + return (const char *)m_data_sp->GetBytes() + line_offset; + return NULL; } -uint32_t -SourceManager::File::GetLineLength (uint32_t line, bool include_newline_chars) -{ - if (!LineIsValid(line)) - return false; - - size_t start_offset = GetLineOffset (line); - size_t end_offset = GetLineOffset (line + 1); - if (end_offset == UINT32_MAX) - end_offset = m_data_sp->GetByteSize(); - - if (end_offset > start_offset) - { - uint32_t length = end_offset - start_offset; - if (include_newline_chars == false) - { - const char *line_start = (const char *)m_data_sp->GetBytes() + start_offset; - while (length > 0) - { - const char last_char = line_start[length-1]; - if ((last_char == '\r') || (last_char == '\n')) - --length; - else - break; - } - } - return length; +uint32_t SourceManager::File::GetLineLength(uint32_t line, + bool include_newline_chars) { + if (!LineIsValid(line)) + return false; + + size_t start_offset = GetLineOffset(line); + size_t end_offset = GetLineOffset(line + 1); + if (end_offset == UINT32_MAX) + end_offset = m_data_sp->GetByteSize(); + + if (end_offset > start_offset) { + uint32_t length = end_offset - start_offset; + if (include_newline_chars == false) { + const char *line_start = + (const char *)m_data_sp->GetBytes() + start_offset; + while (length > 0) { + const char last_char = line_start[length - 1]; + if ((last_char == '\r') || (last_char == '\n')) + --length; + else + break; + } } - return 0; + return length; + } + return 0; } -bool -SourceManager::File::LineIsValid (uint32_t line) -{ - if (line == 0) - return false; - - if (CalculateLineOffsets (line)) - return line < m_offsets.size(); +bool SourceManager::File::LineIsValid(uint32_t line) { + if (line == 0) return false; + + if (CalculateLineOffsets(line)) + return line < m_offsets.size(); + return false; } -void -SourceManager::File::UpdateIfNeeded () -{ - // TODO: use host API to sign up for file modifications to anything in our - // source cache and only update when we determine a file has been updated. - // For now we check each time we want to display info for the file. - TimeValue curr_mod_time (m_file_spec.GetModificationTime()); - - if (curr_mod_time.IsValid() && m_mod_time != curr_mod_time) - { - m_mod_time = curr_mod_time; - m_data_sp = m_file_spec.ReadFileContents (); - m_offsets.clear(); - } +void SourceManager::File::UpdateIfNeeded() { + // TODO: use host API to sign up for file modifications to anything in our + // source cache and only update when we determine a file has been updated. + // For now we check each time we want to display info for the file. + auto curr_mod_time = FileSystem::GetModificationTime(m_file_spec); + + if (curr_mod_time != llvm::sys::TimePoint<>() && + m_mod_time != curr_mod_time) { + m_mod_time = curr_mod_time; + m_data_sp = m_file_spec.ReadFileContents(); + m_offsets.clear(); + } } -size_t -SourceManager::File::DisplaySourceLines (uint32_t line, uint32_t context_before, uint32_t context_after, Stream *s) -{ - // Sanity check m_data_sp before proceeding. - if (!m_data_sp) - return 0; - - const uint32_t start_line = line <= context_before ? 1 : line - context_before; - const uint32_t start_line_offset = GetLineOffset (start_line); - if (start_line_offset != UINT32_MAX) - { - const uint32_t end_line = line + context_after; - uint32_t end_line_offset = GetLineOffset (end_line + 1); - if (end_line_offset == UINT32_MAX) - end_line_offset = m_data_sp->GetByteSize(); - - assert (start_line_offset <= end_line_offset); - size_t bytes_written = 0; - if (start_line_offset < end_line_offset) - { - size_t count = end_line_offset - start_line_offset; - const uint8_t *cstr = m_data_sp->GetBytes() + start_line_offset; - bytes_written = s->Write(cstr, count); - if (!is_newline_char(cstr[count-1])) - bytes_written += s->EOL(); +size_t SourceManager::File::DisplaySourceLines(uint32_t line, uint32_t column, + uint32_t context_before, + uint32_t context_after, + Stream *s) { + // Nothing to write if there's no stream. + if (!s) + return 0; + + // Sanity check m_data_sp before proceeding. + if (!m_data_sp) + return 0; + + const uint32_t start_line = + line <= context_before ? 1 : line - context_before; + const uint32_t start_line_offset = GetLineOffset(start_line); + if (start_line_offset != UINT32_MAX) { + const uint32_t end_line = line + context_after; + uint32_t end_line_offset = GetLineOffset(end_line + 1); + if (end_line_offset == UINT32_MAX) + end_line_offset = m_data_sp->GetByteSize(); + + assert(start_line_offset <= end_line_offset); + size_t bytes_written = 0; + if (start_line_offset < end_line_offset) { + size_t count = end_line_offset - start_line_offset; + const uint8_t *cstr = m_data_sp->GetBytes() + start_line_offset; + + bool displayed_line = false; + + if (column && (column < count)) { + auto debugger_sp = m_debugger_wp.lock(); + if (should_show_stop_column_with_ansi(debugger_sp) && debugger_sp) { + // Check if we have any ANSI codes with which to mark this column. + // If not, no need to do this work. + auto ansi_prefix_entry = debugger_sp->GetStopShowColumnAnsiPrefix(); + auto ansi_suffix_entry = debugger_sp->GetStopShowColumnAnsiSuffix(); + + // We only bother breaking up the line to format the marked column if + // there is any marking specified on both sides of the marked column. + // In ANSI-terminal-sequence land, there must be a post if there is a + // pre format, and vice versa. + if (ansi_prefix_entry && ansi_suffix_entry) { + // Mark the current column with the desired escape sequence for + // formatting the column (e.g. underline, inverse, etc.) + + // First print the part before the column to mark. + bytes_written = s->Write(cstr, column - 1); + + // Write the pre escape sequence. + const SymbolContext *sc = nullptr; + const ExecutionContext *exe_ctx = nullptr; + const Address addr = LLDB_INVALID_ADDRESS; + ValueObject *valobj = nullptr; + const bool function_changed = false; + const bool initial_function = false; + + FormatEntity::Format(*ansi_prefix_entry, *s, sc, exe_ctx, &addr, + valobj, function_changed, initial_function); + + // Write the marked column. + bytes_written += s->Write(cstr + column - 1, 1); + + // Write the post escape sequence. + FormatEntity::Format(*ansi_suffix_entry, *s, sc, exe_ctx, &addr, + valobj, function_changed, initial_function); + + // And finish up with the rest of the line. + bytes_written += s->Write(cstr + column, count - column); + + // Keep track of the fact that we just wrote the line. + displayed_line = true; + } } - return bytes_written; + } + + // If we didn't end up displaying the line with ANSI codes for whatever + // reason, display it now sans codes. + if (!displayed_line) + bytes_written = s->Write(cstr, count); + + // Ensure we get an end of line character one way or another. + if (!is_newline_char(cstr[count - 1])) + bytes_written += s->EOL(); } - return 0; + return bytes_written; + } + return 0; } -void -SourceManager::File::FindLinesMatchingRegex (RegularExpression& regex, uint32_t start_line, uint32_t end_line, std::vector<uint32_t> &match_lines) -{ - match_lines.clear(); - - if (!LineIsValid(start_line) || (end_line != UINT32_MAX && !LineIsValid(end_line))) - return; - if (start_line > end_line) - return; - - for (uint32_t line_no = start_line; line_no < end_line; line_no++) - { - std::string buffer; - if (!GetLine (line_no, buffer)) - break; - if (regex.Execute(buffer.c_str())) - { - match_lines.push_back(line_no); - } +void SourceManager::File::FindLinesMatchingRegex( + RegularExpression ®ex, uint32_t start_line, uint32_t end_line, + std::vector<uint32_t> &match_lines) { + match_lines.clear(); + + if (!LineIsValid(start_line) || + (end_line != UINT32_MAX && !LineIsValid(end_line))) + return; + if (start_line > end_line) + return; + + for (uint32_t line_no = start_line; line_no < end_line; line_no++) { + std::string buffer; + if (!GetLine(line_no, buffer)) + break; + if (regex.Execute(buffer)) { + match_lines.push_back(line_no); } + } } -bool -SourceManager::File::FileSpecMatches (const FileSpec &file_spec) -{ - return FileSpec::Equal (m_file_spec, file_spec, false); +bool SourceManager::File::FileSpecMatches(const FileSpec &file_spec) { + return FileSpec::Equal(m_file_spec, file_spec, false); } -bool -lldb_private::operator== (const SourceManager::File &lhs, const SourceManager::File &rhs) -{ - if (lhs.m_file_spec == rhs.m_file_spec) - { - if (lhs.m_mod_time.IsValid()) - { - if (rhs.m_mod_time.IsValid()) - return lhs.m_mod_time == rhs.m_mod_time; - else - return false; - } - else if (rhs.m_mod_time.IsValid()) - return false; - else - return true; - } - else - return false; +bool lldb_private::operator==(const SourceManager::File &lhs, + const SourceManager::File &rhs) { + if (lhs.m_file_spec != rhs.m_file_spec) + return false; + return lhs.m_mod_time == rhs.m_mod_time; } -bool -SourceManager::File::CalculateLineOffsets (uint32_t line) -{ - line = UINT32_MAX; // TODO: take this line out when we support partial indexing - if (line == UINT32_MAX) - { - // Already done? - if (!m_offsets.empty() && m_offsets[0] == UINT32_MAX) - return true; - - if (m_offsets.empty()) - { - if (m_data_sp.get() == NULL) - return false; - - const char *start = (char *)m_data_sp->GetBytes(); - if (start) - { - const char *end = start + m_data_sp->GetByteSize(); - - // Calculate all line offsets from scratch - - // Push a 1 at index zero to indicate the file has been completely indexed. - m_offsets.push_back(UINT32_MAX); - const char *s; - for (s = start; s < end; ++s) - { - char curr_ch = *s; - if (is_newline_char (curr_ch)) - { - if (s + 1 < end) - { - char next_ch = s[1]; - if (is_newline_char (next_ch)) - { - if (curr_ch != next_ch) - ++s; - } - } - m_offsets.push_back(s + 1 - start); - } - } - if (!m_offsets.empty()) - { - if (m_offsets.back() < end - start) - m_offsets.push_back(end - start); - } - return true; +bool SourceManager::File::CalculateLineOffsets(uint32_t line) { + line = + UINT32_MAX; // TODO: take this line out when we support partial indexing + if (line == UINT32_MAX) { + // Already done? + if (!m_offsets.empty() && m_offsets[0] == UINT32_MAX) + return true; + + if (m_offsets.empty()) { + if (m_data_sp.get() == NULL) + return false; + + const char *start = (char *)m_data_sp->GetBytes(); + if (start) { + const char *end = start + m_data_sp->GetByteSize(); + + // Calculate all line offsets from scratch + + // Push a 1 at index zero to indicate the file has been completely + // indexed. + m_offsets.push_back(UINT32_MAX); + const char *s; + for (s = start; s < end; ++s) { + char curr_ch = *s; + if (is_newline_char(curr_ch)) { + if (s + 1 < end) { + char next_ch = s[1]; + if (is_newline_char(next_ch)) { + if (curr_ch != next_ch) + ++s; + } } + m_offsets.push_back(s + 1 - start); + } } - else - { - // Some lines have been populated, start where we last left off - assert("Not implemented yet" && false); + if (!m_offsets.empty()) { + if (m_offsets.back() < size_t(end - start)) + m_offsets.push_back(end - start); } - - } - else - { - // Calculate all line offsets up to "line" - assert("Not implemented yet" && false); + return true; + } + } else { + // Some lines have been populated, start where we last left off + assert("Not implemented yet" && false); } - return false; + + } else { + // Calculate all line offsets up to "line" + assert("Not implemented yet" && false); + } + return false; } -bool -SourceManager::File::GetLine (uint32_t line_no, std::string &buffer) -{ - if (!LineIsValid(line_no)) - return false; +bool SourceManager::File::GetLine(uint32_t line_no, std::string &buffer) { + if (!LineIsValid(line_no)) + return false; - size_t start_offset = GetLineOffset (line_no); - size_t end_offset = GetLineOffset (line_no + 1); - if (end_offset == UINT32_MAX) - { - end_offset = m_data_sp->GetByteSize(); - } - buffer.assign((char *) m_data_sp->GetBytes() + start_offset, end_offset - start_offset); - - return true; -} + size_t start_offset = GetLineOffset(line_no); + size_t end_offset = GetLineOffset(line_no + 1); + if (end_offset == UINT32_MAX) { + end_offset = m_data_sp->GetByteSize(); + } + buffer.assign((char *)m_data_sp->GetBytes() + start_offset, + end_offset - start_offset); -void -SourceManager::SourceFileCache::AddSourceFile (const FileSP &file_sp) -{ - FileSpec file_spec; - FileCache::iterator pos = m_file_cache.find(file_spec); - if (pos == m_file_cache.end()) - m_file_cache[file_spec] = file_sp; - else - { - if (file_sp != pos->second) - m_file_cache[file_spec] = file_sp; - } + return true; } -SourceManager::FileSP -SourceManager::SourceFileCache::FindSourceFile (const FileSpec &file_spec) const -{ - FileSP file_sp; - FileCache::const_iterator pos = m_file_cache.find(file_spec); - if (pos != m_file_cache.end()) - file_sp = pos->second; - return file_sp; +void SourceManager::SourceFileCache::AddSourceFile(const FileSP &file_sp) { + FileSpec file_spec; + FileCache::iterator pos = m_file_cache.find(file_spec); + if (pos == m_file_cache.end()) + m_file_cache[file_spec] = file_sp; + else { + if (file_sp != pos->second) + m_file_cache[file_spec] = file_sp; + } } +SourceManager::FileSP SourceManager::SourceFileCache::FindSourceFile( + const FileSpec &file_spec) const { + FileSP file_sp; + FileCache::const_iterator pos = m_file_cache.find(file_spec); + if (pos != m_file_cache.end()) + file_sp = pos->second; + return file_sp; +} diff --git a/source/Core/State.cpp b/source/Core/State.cpp index 7d9ccda532a2..80497dd77b87 100644 --- a/source/Core/State.cpp +++ b/source/Core/State.cpp @@ -17,99 +17,103 @@ using namespace lldb; using namespace lldb_private; -const char * -lldb_private::StateAsCString (StateType state) -{ - switch (state) - { - case eStateInvalid: return "invalid"; - case eStateUnloaded: return "unloaded"; - case eStateConnected: return "connected"; - case eStateAttaching: return "attaching"; - case eStateLaunching: return "launching"; - case eStateStopped: return "stopped"; - case eStateRunning: return "running"; - case eStateStepping: return "stepping"; - case eStateCrashed: return "crashed"; - case eStateDetached: return "detached"; - case eStateExited: return "exited"; - case eStateSuspended: return "suspended"; - } - static char unknown_state_string[64]; - snprintf(unknown_state_string, sizeof (unknown_state_string), "StateType = %i", state); - return unknown_state_string; +const char *lldb_private::StateAsCString(StateType state) { + switch (state) { + case eStateInvalid: + return "invalid"; + case eStateUnloaded: + return "unloaded"; + case eStateConnected: + return "connected"; + case eStateAttaching: + return "attaching"; + case eStateLaunching: + return "launching"; + case eStateStopped: + return "stopped"; + case eStateRunning: + return "running"; + case eStateStepping: + return "stepping"; + case eStateCrashed: + return "crashed"; + case eStateDetached: + return "detached"; + case eStateExited: + return "exited"; + case eStateSuspended: + return "suspended"; + } + static char unknown_state_string[64]; + snprintf(unknown_state_string, sizeof(unknown_state_string), "StateType = %i", + state); + return unknown_state_string; } -const char * -lldb_private::GetPermissionsAsCString (uint32_t permissions) -{ - switch (permissions) - { - case 0: return "---"; - case ePermissionsWritable: return "-w-"; - case ePermissionsReadable: return "r--"; - case ePermissionsExecutable: return "--x"; - case ePermissionsReadable | - ePermissionsWritable: return "rw-"; - case ePermissionsReadable | - ePermissionsExecutable: return "r-x"; - case ePermissionsWritable | - ePermissionsExecutable: return "-wx"; - case ePermissionsReadable | - ePermissionsWritable | - ePermissionsExecutable: return "rwx"; - default: - break; - } - return "???"; +const char *lldb_private::GetPermissionsAsCString(uint32_t permissions) { + switch (permissions) { + case 0: + return "---"; + case ePermissionsWritable: + return "-w-"; + case ePermissionsReadable: + return "r--"; + case ePermissionsExecutable: + return "--x"; + case ePermissionsReadable | ePermissionsWritable: + return "rw-"; + case ePermissionsReadable | ePermissionsExecutable: + return "r-x"; + case ePermissionsWritable | ePermissionsExecutable: + return "-wx"; + case ePermissionsReadable | ePermissionsWritable | ePermissionsExecutable: + return "rwx"; + default: + break; + } + return "???"; } -bool -lldb_private::StateIsRunningState (StateType state) -{ - switch (state) - { - case eStateAttaching: - case eStateLaunching: - case eStateRunning: - case eStateStepping: - return true; +bool lldb_private::StateIsRunningState(StateType state) { + switch (state) { + case eStateAttaching: + case eStateLaunching: + case eStateRunning: + case eStateStepping: + return true; - case eStateConnected: - case eStateDetached: - case eStateInvalid: - case eStateUnloaded: - case eStateStopped: - case eStateCrashed: - case eStateExited: - case eStateSuspended: - break; - } - return false; + case eStateConnected: + case eStateDetached: + case eStateInvalid: + case eStateUnloaded: + case eStateStopped: + case eStateCrashed: + case eStateExited: + case eStateSuspended: + break; + } + return false; } -bool -lldb_private::StateIsStoppedState (StateType state, bool must_exist) -{ - switch (state) - { - case eStateInvalid: - case eStateConnected: - case eStateAttaching: - case eStateLaunching: - case eStateRunning: - case eStateStepping: - case eStateDetached: - break; +bool lldb_private::StateIsStoppedState(StateType state, bool must_exist) { + switch (state) { + case eStateInvalid: + case eStateConnected: + case eStateAttaching: + case eStateLaunching: + case eStateRunning: + case eStateStepping: + case eStateDetached: + break; - case eStateUnloaded: - case eStateExited: - return !must_exist; + case eStateUnloaded: + case eStateExited: + return !must_exist; - case eStateStopped: - case eStateCrashed: - case eStateSuspended: - return true; - } - return false; + case eStateStopped: + case eStateCrashed: + case eStateSuspended: + return true; + } + return false; } diff --git a/source/Core/Stream.cpp b/source/Core/Stream.cpp index 15876d558ec5..2f9c650ee5b0 100644 --- a/source/Core/Stream.cpp +++ b/source/Core/Stream.cpp @@ -9,778 +9,622 @@ #include "lldb/Core/Stream.h" #include "lldb/Host/Endian.h" +#include "lldb/Host/PosixApi.h" #include <stddef.h> #include <stdio.h> -#include <string.h> #include <stdlib.h> +#include <string.h> #include <inttypes.h> using namespace lldb; using namespace lldb_private; -Stream::Stream (uint32_t flags, uint32_t addr_size, ByteOrder byte_order) : - m_flags (flags), - m_addr_size (addr_size), - m_byte_order (byte_order), - m_indent_level(0) -{ -} +Stream::Stream(uint32_t flags, uint32_t addr_size, ByteOrder byte_order) + : m_flags(flags), m_addr_size(addr_size), m_byte_order(byte_order), + m_indent_level(0) {} -Stream::Stream () : - m_flags (0), - m_addr_size (4), - m_byte_order (endian::InlHostByteOrder()), - m_indent_level(0) -{ -} +Stream::Stream() + : m_flags(0), m_addr_size(4), m_byte_order(endian::InlHostByteOrder()), + m_indent_level(0) {} //------------------------------------------------------------------ // Destructor //------------------------------------------------------------------ -Stream::~Stream () -{ -} +Stream::~Stream() {} -ByteOrder -Stream::SetByteOrder (ByteOrder byte_order) -{ - ByteOrder old_byte_order = m_byte_order; - m_byte_order = byte_order; - return old_byte_order; +ByteOrder Stream::SetByteOrder(ByteOrder byte_order) { + ByteOrder old_byte_order = m_byte_order; + m_byte_order = byte_order; + return old_byte_order; } //------------------------------------------------------------------ // Put an offset "uval" out to the stream using the printf format // in "format". //------------------------------------------------------------------ -void -Stream::Offset (uint32_t uval, const char *format) -{ - Printf (format, uval); -} +void Stream::Offset(uint32_t uval, const char *format) { Printf(format, uval); } //------------------------------------------------------------------ // Put an SLEB128 "uval" out to the stream using the printf format // in "format". //------------------------------------------------------------------ -size_t -Stream::PutSLEB128 (int64_t sval) -{ - size_t bytes_written = 0; - if (m_flags.Test(eBinary)) - { - bool more = true; - while (more) - { - uint8_t byte = sval & 0x7fu; - sval >>= 7; - /* sign bit of byte is 2nd high order bit (0x40) */ - if ((sval == 0 && !(byte & 0x40)) || - (sval == -1 && (byte & 0x40)) ) - more = false; - else - // more bytes to come - byte |= 0x80u; - bytes_written += Write(&byte, 1); - } - } - else - { - bytes_written = Printf ("0x%" PRIi64, sval); +size_t Stream::PutSLEB128(int64_t sval) { + size_t bytes_written = 0; + if (m_flags.Test(eBinary)) { + bool more = true; + while (more) { + uint8_t byte = sval & 0x7fu; + sval >>= 7; + /* sign bit of byte is 2nd high order bit (0x40) */ + if ((sval == 0 && !(byte & 0x40)) || (sval == -1 && (byte & 0x40))) + more = false; + else + // more bytes to come + byte |= 0x80u; + bytes_written += Write(&byte, 1); } + } else { + bytes_written = Printf("0x%" PRIi64, sval); + } - return bytes_written; - + return bytes_written; } //------------------------------------------------------------------ // Put an ULEB128 "uval" out to the stream using the printf format // in "format". //------------------------------------------------------------------ -size_t -Stream::PutULEB128 (uint64_t uval) -{ - size_t bytes_written = 0; - if (m_flags.Test(eBinary)) - { - do - { - - uint8_t byte = uval & 0x7fu; - uval >>= 7; - if (uval != 0) - { - // more bytes to come - byte |= 0x80u; - } - bytes_written += Write(&byte, 1); - } while (uval != 0); - } - else - { - bytes_written = Printf ("0x%" PRIx64, uval); - } - return bytes_written; +size_t Stream::PutULEB128(uint64_t uval) { + size_t bytes_written = 0; + if (m_flags.Test(eBinary)) { + do { + + uint8_t byte = uval & 0x7fu; + uval >>= 7; + if (uval != 0) { + // more bytes to come + byte |= 0x80u; + } + bytes_written += Write(&byte, 1); + } while (uval != 0); + } else { + bytes_written = Printf("0x%" PRIx64, uval); + } + return bytes_written; } //------------------------------------------------------------------ // Print a raw NULL terminated C string to the stream. //------------------------------------------------------------------ -size_t -Stream::PutCString (const char *cstr) -{ - size_t cstr_len = strlen(cstr); - // when in binary mode, emit the NULL terminator - if (m_flags.Test(eBinary)) - ++cstr_len; - return Write (cstr, cstr_len); +size_t Stream::PutCString(llvm::StringRef str) { + size_t bytes_written = 0; + bytes_written = Write(str.data(), str.size()); + + // when in binary mode, emit the NULL terminator + if (m_flags.Test(eBinary)) + bytes_written += PutChar('\0'); + return bytes_written; } //------------------------------------------------------------------ // Print a double quoted NULL terminated C string to the stream // using the printf format in "format". //------------------------------------------------------------------ -void -Stream::QuotedCString (const char *cstr, const char *format) -{ - Printf (format, cstr); +void Stream::QuotedCString(const char *cstr, const char *format) { + Printf(format, cstr); } //------------------------------------------------------------------ // Put an address "addr" out to the stream with optional prefix // and suffix strings. //------------------------------------------------------------------ -void -Stream::Address (uint64_t addr, uint32_t addr_size, const char *prefix, const char *suffix) -{ - if (prefix == NULL) - prefix = ""; - if (suffix == NULL) - suffix = ""; -// int addr_width = m_addr_size << 1; -// Printf ("%s0x%0*" PRIx64 "%s", prefix, addr_width, addr, suffix); - Printf ("%s0x%0*" PRIx64 "%s", prefix, addr_size * 2, (uint64_t)addr, suffix); +void Stream::Address(uint64_t addr, uint32_t addr_size, const char *prefix, + const char *suffix) { + if (prefix == NULL) + prefix = ""; + if (suffix == NULL) + suffix = ""; + // int addr_width = m_addr_size << 1; + // Printf ("%s0x%0*" PRIx64 "%s", prefix, addr_width, addr, suffix); + Printf("%s0x%0*" PRIx64 "%s", prefix, addr_size * 2, (uint64_t)addr, suffix); } //------------------------------------------------------------------ // Put an address range out to the stream with optional prefix // and suffix strings. //------------------------------------------------------------------ -void -Stream::AddressRange(uint64_t lo_addr, uint64_t hi_addr, uint32_t addr_size, const char *prefix, const char *suffix) -{ - if (prefix && prefix[0]) - PutCString (prefix); - Address (lo_addr, addr_size, "["); - Address (hi_addr, addr_size, "-", ")"); - if (suffix && suffix[0]) - PutCString (suffix); -} - - -size_t -Stream::PutChar (char ch) -{ - return Write (&ch, 1); +void Stream::AddressRange(uint64_t lo_addr, uint64_t hi_addr, + uint32_t addr_size, const char *prefix, + const char *suffix) { + if (prefix && prefix[0]) + PutCString(prefix); + Address(lo_addr, addr_size, "["); + Address(hi_addr, addr_size, "-", ")"); + if (suffix && suffix[0]) + PutCString(suffix); } +size_t Stream::PutChar(char ch) { return Write(&ch, 1); } //------------------------------------------------------------------ // Print some formatted output to the stream. //------------------------------------------------------------------ -size_t -Stream::Printf (const char *format, ...) -{ - va_list args; - va_start (args, format); - size_t result = PrintfVarArg(format, args); - va_end (args); - return result; +size_t Stream::Printf(const char *format, ...) { + va_list args; + va_start(args, format); + size_t result = PrintfVarArg(format, args); + va_end(args); + return result; } //------------------------------------------------------------------ // Print some formatted output to the stream. //------------------------------------------------------------------ -size_t -Stream::PrintfVarArg (const char *format, va_list args) -{ - char str[1024]; - va_list args_copy; - - va_copy (args_copy, args); - - size_t bytes_written = 0; - // Try and format our string into a fixed buffer first and see if it fits - size_t length = ::vsnprintf (str, sizeof(str), format, args); - if (length < sizeof(str)) - { - // Include the NULL termination byte for binary output - if (m_flags.Test(eBinary)) - length += 1; - // The formatted string fit into our stack based buffer, so we can just - // append that to our packet - bytes_written = Write (str, length); - } - else - { - // Our stack buffer wasn't big enough to contain the entire formatted - // string, so lets let vasprintf create the string for us! - char *str_ptr = NULL; - length = ::vasprintf (&str_ptr, format, args_copy); - if (str_ptr) - { - // Include the NULL termination byte for binary output - if (m_flags.Test(eBinary)) - length += 1; - bytes_written = Write (str_ptr, length); - ::free (str_ptr); - } +size_t Stream::PrintfVarArg(const char *format, va_list args) { + char str[1024]; + va_list args_copy; + + va_copy(args_copy, args); + + size_t bytes_written = 0; + // Try and format our string into a fixed buffer first and see if it fits + size_t length = ::vsnprintf(str, sizeof(str), format, args); + if (length < sizeof(str)) { + // Include the NULL termination byte for binary output + if (m_flags.Test(eBinary)) + length += 1; + // The formatted string fit into our stack based buffer, so we can just + // append that to our packet + bytes_written = Write(str, length); + } else { + // Our stack buffer wasn't big enough to contain the entire formatted + // string, so lets let vasprintf create the string for us! + char *str_ptr = NULL; + length = ::vasprintf(&str_ptr, format, args_copy); + if (str_ptr) { + // Include the NULL termination byte for binary output + if (m_flags.Test(eBinary)) + length += 1; + bytes_written = Write(str_ptr, length); + ::free(str_ptr); } - va_end (args_copy); - return bytes_written; + } + va_end(args_copy); + return bytes_written; } //------------------------------------------------------------------ // Print and End of Line character to the stream //------------------------------------------------------------------ -size_t -Stream::EOL() -{ - return PutChar ('\n'); -} +size_t Stream::EOL() { return PutChar('\n'); } //------------------------------------------------------------------ // Indent the current line using the current indentation level and // print an optional string following the indentation spaces. //------------------------------------------------------------------ -size_t -Stream::Indent(const char *s) -{ - return Printf ("%*.*s%s", m_indent_level, m_indent_level, "", s ? s : ""); +size_t Stream::Indent(const char *s) { + return Printf("%*.*s%s", m_indent_level, m_indent_level, "", s ? s : ""); +} + +size_t Stream::Indent(llvm::StringRef str) { + return Printf("%*.*s%s", m_indent_level, m_indent_level, "", str.str().c_str()); } //------------------------------------------------------------------ // Stream a character "ch" out to this stream. //------------------------------------------------------------------ -Stream& -Stream::operator<< (char ch) -{ - PutChar (ch); - return *this; +Stream &Stream::operator<<(char ch) { + PutChar(ch); + return *this; } //------------------------------------------------------------------ // Stream the NULL terminated C string out to this stream. //------------------------------------------------------------------ -Stream& -Stream::operator<< (const char *s) -{ - Printf ("%s", s); - return *this; +Stream &Stream::operator<<(const char *s) { + Printf("%s", s); + return *this; +} + +Stream &Stream::operator<<(llvm::StringRef str) { + Write(str.data(), str.size()); + return *this; } //------------------------------------------------------------------ // Stream the pointer value out to this stream. //------------------------------------------------------------------ -Stream& -Stream::operator<< (const void *p) -{ - Printf ("0x%.*tx", (int)sizeof(const void*) * 2, (ptrdiff_t)p); - return *this; +Stream &Stream::operator<<(const void *p) { + Printf("0x%.*tx", (int)sizeof(const void *) * 2, (ptrdiff_t)p); + return *this; } //------------------------------------------------------------------ // Stream a uint8_t "uval" out to this stream. //------------------------------------------------------------------ -Stream& -Stream::operator<< (uint8_t uval) -{ - PutHex8(uval); - return *this; +Stream &Stream::operator<<(uint8_t uval) { + PutHex8(uval); + return *this; } //------------------------------------------------------------------ // Stream a uint16_t "uval" out to this stream. //------------------------------------------------------------------ -Stream& -Stream::operator<< (uint16_t uval) -{ - PutHex16(uval, m_byte_order); - return *this; +Stream &Stream::operator<<(uint16_t uval) { + PutHex16(uval, m_byte_order); + return *this; } //------------------------------------------------------------------ // Stream a uint32_t "uval" out to this stream. //------------------------------------------------------------------ -Stream& -Stream::operator<< (uint32_t uval) -{ - PutHex32(uval, m_byte_order); - return *this; +Stream &Stream::operator<<(uint32_t uval) { + PutHex32(uval, m_byte_order); + return *this; } //------------------------------------------------------------------ // Stream a uint64_t "uval" out to this stream. //------------------------------------------------------------------ -Stream& -Stream::operator<< (uint64_t uval) -{ - PutHex64(uval, m_byte_order); - return *this; +Stream &Stream::operator<<(uint64_t uval) { + PutHex64(uval, m_byte_order); + return *this; } //------------------------------------------------------------------ // Stream a int8_t "sval" out to this stream. //------------------------------------------------------------------ -Stream& -Stream::operator<< (int8_t sval) -{ - Printf ("%i", (int)sval); - return *this; +Stream &Stream::operator<<(int8_t sval) { + Printf("%i", (int)sval); + return *this; } //------------------------------------------------------------------ // Stream a int16_t "sval" out to this stream. //------------------------------------------------------------------ -Stream& -Stream::operator<< (int16_t sval) -{ - Printf ("%i", (int)sval); - return *this; +Stream &Stream::operator<<(int16_t sval) { + Printf("%i", (int)sval); + return *this; } //------------------------------------------------------------------ // Stream a int32_t "sval" out to this stream. //------------------------------------------------------------------ -Stream& -Stream::operator<< (int32_t sval) -{ - Printf ("%i", (int)sval); - return *this; +Stream &Stream::operator<<(int32_t sval) { + Printf("%i", (int)sval); + return *this; } //------------------------------------------------------------------ // Stream a int64_t "sval" out to this stream. //------------------------------------------------------------------ -Stream& -Stream::operator<< (int64_t sval) -{ - Printf ("%" PRIi64, sval); - return *this; +Stream &Stream::operator<<(int64_t sval) { + Printf("%" PRIi64, sval); + return *this; } //------------------------------------------------------------------ // Get the current indentation level //------------------------------------------------------------------ -int -Stream::GetIndentLevel() const -{ - return m_indent_level; -} +int Stream::GetIndentLevel() const { return m_indent_level; } //------------------------------------------------------------------ // Set the current indentation level //------------------------------------------------------------------ -void -Stream::SetIndentLevel(int indent_level) -{ - m_indent_level = indent_level; -} +void Stream::SetIndentLevel(int indent_level) { m_indent_level = indent_level; } //------------------------------------------------------------------ // Increment the current indentation level //------------------------------------------------------------------ -void -Stream::IndentMore(int amount) -{ - m_indent_level += amount; -} +void Stream::IndentMore(int amount) { m_indent_level += amount; } //------------------------------------------------------------------ // Decrement the current indentation level //------------------------------------------------------------------ -void -Stream::IndentLess (int amount) -{ - if (m_indent_level >= amount) - m_indent_level -= amount; - else - m_indent_level = 0; +void Stream::IndentLess(int amount) { + if (m_indent_level >= amount) + m_indent_level -= amount; + else + m_indent_level = 0; } //------------------------------------------------------------------ // Get the address size in bytes //------------------------------------------------------------------ -uint32_t -Stream::GetAddressByteSize() const -{ - return m_addr_size; -} +uint32_t Stream::GetAddressByteSize() const { return m_addr_size; } //------------------------------------------------------------------ // Set the address size in bytes //------------------------------------------------------------------ -void -Stream::SetAddressByteSize(uint32_t addr_size) -{ - m_addr_size = addr_size; -} +void Stream::SetAddressByteSize(uint32_t addr_size) { m_addr_size = addr_size; } //------------------------------------------------------------------ // Returns true if the verbose flag bit is set in this stream. //------------------------------------------------------------------ -bool -Stream::GetVerbose() const -{ - return m_flags.Test(eVerbose); -} +bool Stream::GetVerbose() const { return m_flags.Test(eVerbose); } //------------------------------------------------------------------ // Returns true if the debug flag bit is set in this stream. //------------------------------------------------------------------ -bool -Stream::GetDebug() const -{ - return m_flags.Test(eDebug); -} +bool Stream::GetDebug() const { return m_flags.Test(eDebug); } //------------------------------------------------------------------ // The flags get accessor //------------------------------------------------------------------ -Flags& -Stream::GetFlags() -{ - return m_flags; -} +Flags &Stream::GetFlags() { return m_flags; } //------------------------------------------------------------------ // The flags const get accessor //------------------------------------------------------------------ -const Flags& -Stream::GetFlags() const -{ - return m_flags; -} +const Flags &Stream::GetFlags() const { return m_flags; } //------------------------------------------------------------------ // The byte order get accessor //------------------------------------------------------------------ -lldb::ByteOrder -Stream::GetByteOrder() const -{ - return m_byte_order; -} - -size_t -Stream::PrintfAsRawHex8 (const char *format, ...) -{ - va_list args; - va_list args_copy; - va_start (args, format); - va_copy (args_copy,args); // Copy this so we - - char str[1024]; - size_t bytes_written = 0; - // Try and format our string into a fixed buffer first and see if it fits - size_t length = ::vsnprintf (str, sizeof(str), format, args); - if (length < sizeof(str)) - { - // The formatted string fit into our stack based buffer, so we can just - // append that to our packet - for (size_t i=0; i<length; ++i) - bytes_written += _PutHex8 (str[i], false); - } - else - { - // Our stack buffer wasn't big enough to contain the entire formatted - // string, so lets let vasprintf create the string for us! - char *str_ptr = NULL; - length = ::vasprintf (&str_ptr, format, args_copy); - if (str_ptr) - { - for (size_t i=0; i<length; ++i) - bytes_written += _PutHex8 (str_ptr[i], false); - ::free (str_ptr); - } - } - va_end (args); - va_end (args_copy); - - return bytes_written; -} - -size_t -Stream::PutNHex8 (size_t n, uint8_t uvalue) -{ - size_t bytes_written = 0; - for (size_t i=0; i<n; ++i) - bytes_written += _PutHex8 (uvalue, m_flags.Test(eAddPrefix)); - return bytes_written; -} - -size_t -Stream::_PutHex8 (uint8_t uvalue, bool add_prefix) -{ - size_t bytes_written = 0; - if (m_flags.Test(eBinary)) - { - bytes_written = Write (&uvalue, 1); - } - else - { - if (add_prefix) - PutCString("0x"); - - static char g_hex_to_ascii_hex_char[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - char nibble_chars[2]; - nibble_chars[0] = g_hex_to_ascii_hex_char[(uvalue >> 4) & 0xf]; - nibble_chars[1] = g_hex_to_ascii_hex_char[(uvalue >> 0) & 0xf]; - bytes_written = Write (nibble_chars, sizeof(nibble_chars)); - } - return bytes_written; -} - -size_t -Stream::PutHex8 (uint8_t uvalue) -{ - return _PutHex8 (uvalue, m_flags.Test(eAddPrefix)); -} - -size_t -Stream::PutHex16 (uint16_t uvalue, ByteOrder byte_order) -{ - if (byte_order == eByteOrderInvalid) - byte_order = m_byte_order; - - bool add_prefix = m_flags.Test(eAddPrefix); - size_t bytes_written = 0; - if (byte_order == eByteOrderLittle) - { - for (size_t byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false) - bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix); +lldb::ByteOrder Stream::GetByteOrder() const { return m_byte_order; } + +size_t Stream::PrintfAsRawHex8(const char *format, ...) { + va_list args; + va_list args_copy; + va_start(args, format); + va_copy(args_copy, args); // Copy this so we + + char str[1024]; + size_t bytes_written = 0; + // Try and format our string into a fixed buffer first and see if it fits + size_t length = ::vsnprintf(str, sizeof(str), format, args); + if (length < sizeof(str)) { + // The formatted string fit into our stack based buffer, so we can just + // append that to our packet + for (size_t i = 0; i < length; ++i) + bytes_written += _PutHex8(str[i], false); + } else { + // Our stack buffer wasn't big enough to contain the entire formatted + // string, so lets let vasprintf create the string for us! + char *str_ptr = NULL; + length = ::vasprintf(&str_ptr, format, args_copy); + if (str_ptr) { + for (size_t i = 0; i < length; ++i) + bytes_written += _PutHex8(str_ptr[i], false); + ::free(str_ptr); } - else - { - for (size_t byte = sizeof(uvalue)-1; byte < sizeof(uvalue); --byte, add_prefix = false) - bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix); - } - return bytes_written; -} - -size_t -Stream::PutHex32(uint32_t uvalue, ByteOrder byte_order) -{ - if (byte_order == eByteOrderInvalid) - byte_order = m_byte_order; + } + va_end(args); + va_end(args_copy); + + return bytes_written; +} + +size_t Stream::PutNHex8(size_t n, uint8_t uvalue) { + size_t bytes_written = 0; + for (size_t i = 0; i < n; ++i) + bytes_written += _PutHex8(uvalue, m_flags.Test(eAddPrefix)); + return bytes_written; +} + +size_t Stream::_PutHex8(uint8_t uvalue, bool add_prefix) { + size_t bytes_written = 0; + if (m_flags.Test(eBinary)) { + bytes_written = Write(&uvalue, 1); + } else { + if (add_prefix) + PutCString("0x"); + + static char g_hex_to_ascii_hex_char[16] = {'0', '1', '2', '3', '4', '5', + '6', '7', '8', '9', 'a', 'b', + 'c', 'd', 'e', 'f'}; + char nibble_chars[2]; + nibble_chars[0] = g_hex_to_ascii_hex_char[(uvalue >> 4) & 0xf]; + nibble_chars[1] = g_hex_to_ascii_hex_char[(uvalue >> 0) & 0xf]; + bytes_written = Write(nibble_chars, sizeof(nibble_chars)); + } + return bytes_written; +} + +size_t Stream::PutHex8(uint8_t uvalue) { + return _PutHex8(uvalue, m_flags.Test(eAddPrefix)); +} - bool add_prefix = m_flags.Test(eAddPrefix); - size_t bytes_written = 0; - if (byte_order == eByteOrderLittle) - { - for (size_t byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false) - bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix); - } - else - { - for (size_t byte = sizeof(uvalue)-1; byte < sizeof(uvalue); --byte, add_prefix = false) - bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix); - } - return bytes_written; -} - -size_t -Stream::PutHex64(uint64_t uvalue, ByteOrder byte_order) -{ - if (byte_order == eByteOrderInvalid) - byte_order = m_byte_order; - - bool add_prefix = m_flags.Test(eAddPrefix); - size_t bytes_written = 0; - if (byte_order == eByteOrderLittle) - { - for (size_t byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false) - bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix); - } - else - { - for (size_t byte = sizeof(uvalue)-1; byte < sizeof(uvalue); --byte, add_prefix = false) - bytes_written += _PutHex8 ((uint8_t)(uvalue >> (byte * 8)), add_prefix); - } - return bytes_written; -} - -size_t -Stream::PutMaxHex64 -( - uint64_t uvalue, - size_t byte_size, - lldb::ByteOrder byte_order -) -{ - switch (byte_size) - { - case 1: return PutHex8 ((uint8_t)uvalue); - case 2: return PutHex16 ((uint16_t)uvalue); - case 4: return PutHex32 ((uint32_t)uvalue); - case 8: return PutHex64 (uvalue); - } - return 0; -} - -size_t -Stream::PutPointer (void *ptr) -{ - return PutRawBytes (&ptr, sizeof(ptr), endian::InlHostByteOrder(), endian::InlHostByteOrder()); -} - -size_t -Stream::PutFloat(float f, ByteOrder byte_order) -{ - if (byte_order == eByteOrderInvalid) - byte_order = m_byte_order; - - return PutRawBytes (&f, sizeof(f), endian::InlHostByteOrder(), byte_order); -} - -size_t -Stream::PutDouble(double d, ByteOrder byte_order) -{ - if (byte_order == eByteOrderInvalid) - byte_order = m_byte_order; - - return PutRawBytes (&d, sizeof(d), endian::InlHostByteOrder(), byte_order); -} - -size_t -Stream::PutLongDouble(long double ld, ByteOrder byte_order) -{ - if (byte_order == eByteOrderInvalid) - byte_order = m_byte_order; - - return PutRawBytes (&ld, sizeof(ld), endian::InlHostByteOrder(), byte_order); -} - -size_t -Stream::PutRawBytes (const void *s, size_t src_len, ByteOrder src_byte_order, ByteOrder dst_byte_order) -{ - if (src_byte_order == eByteOrderInvalid) - src_byte_order = m_byte_order; - - if (dst_byte_order == eByteOrderInvalid) - dst_byte_order = m_byte_order; - - size_t bytes_written = 0; - const uint8_t *src = (const uint8_t *)s; - bool binary_was_set = m_flags.Test (eBinary); - if (!binary_was_set) - m_flags.Set (eBinary); - if (src_byte_order == dst_byte_order) - { - for (size_t i = 0; i < src_len; ++i) - bytes_written += _PutHex8 (src[i], false); - } - else - { - for (size_t i = src_len-1; i < src_len; --i) - bytes_written += _PutHex8 (src[i], false); - } - if (!binary_was_set) - m_flags.Clear (eBinary); - - return bytes_written; -} - -size_t -Stream::PutBytesAsRawHex8 (const void *s, size_t src_len, ByteOrder src_byte_order, ByteOrder dst_byte_order) -{ - if (src_byte_order == eByteOrderInvalid) - src_byte_order = m_byte_order; - - if (dst_byte_order == eByteOrderInvalid) - dst_byte_order = m_byte_order; - - size_t bytes_written = 0; - const uint8_t *src = (const uint8_t *)s; - bool binary_is_set = m_flags.Test(eBinary); +size_t Stream::PutHex16(uint16_t uvalue, ByteOrder byte_order) { + if (byte_order == eByteOrderInvalid) + byte_order = m_byte_order; + + bool add_prefix = m_flags.Test(eAddPrefix); + size_t bytes_written = 0; + if (byte_order == eByteOrderLittle) { + for (size_t byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false) + bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), add_prefix); + } else { + for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); + --byte, add_prefix = false) + bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), add_prefix); + } + return bytes_written; +} + +size_t Stream::PutHex32(uint32_t uvalue, ByteOrder byte_order) { + if (byte_order == eByteOrderInvalid) + byte_order = m_byte_order; + + bool add_prefix = m_flags.Test(eAddPrefix); + size_t bytes_written = 0; + if (byte_order == eByteOrderLittle) { + for (size_t byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false) + bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), add_prefix); + } else { + for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); + --byte, add_prefix = false) + bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), add_prefix); + } + return bytes_written; +} + +size_t Stream::PutHex64(uint64_t uvalue, ByteOrder byte_order) { + if (byte_order == eByteOrderInvalid) + byte_order = m_byte_order; + + bool add_prefix = m_flags.Test(eAddPrefix); + size_t bytes_written = 0; + if (byte_order == eByteOrderLittle) { + for (size_t byte = 0; byte < sizeof(uvalue); ++byte, add_prefix = false) + bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), add_prefix); + } else { + for (size_t byte = sizeof(uvalue) - 1; byte < sizeof(uvalue); + --byte, add_prefix = false) + bytes_written += _PutHex8((uint8_t)(uvalue >> (byte * 8)), add_prefix); + } + return bytes_written; +} + +size_t Stream::PutMaxHex64(uint64_t uvalue, size_t byte_size, + lldb::ByteOrder byte_order) { + switch (byte_size) { + case 1: + return PutHex8((uint8_t)uvalue); + case 2: + return PutHex16((uint16_t)uvalue); + case 4: + return PutHex32((uint32_t)uvalue); + case 8: + return PutHex64(uvalue); + } + return 0; +} + +size_t Stream::PutPointer(void *ptr) { + return PutRawBytes(&ptr, sizeof(ptr), endian::InlHostByteOrder(), + endian::InlHostByteOrder()); +} + +size_t Stream::PutFloat(float f, ByteOrder byte_order) { + if (byte_order == eByteOrderInvalid) + byte_order = m_byte_order; + + return PutRawBytes(&f, sizeof(f), endian::InlHostByteOrder(), byte_order); +} + +size_t Stream::PutDouble(double d, ByteOrder byte_order) { + if (byte_order == eByteOrderInvalid) + byte_order = m_byte_order; + + return PutRawBytes(&d, sizeof(d), endian::InlHostByteOrder(), byte_order); +} + +size_t Stream::PutLongDouble(long double ld, ByteOrder byte_order) { + if (byte_order == eByteOrderInvalid) + byte_order = m_byte_order; + + return PutRawBytes(&ld, sizeof(ld), endian::InlHostByteOrder(), byte_order); +} + +size_t Stream::PutRawBytes(const void *s, size_t src_len, + ByteOrder src_byte_order, ByteOrder dst_byte_order) { + if (src_byte_order == eByteOrderInvalid) + src_byte_order = m_byte_order; + + if (dst_byte_order == eByteOrderInvalid) + dst_byte_order = m_byte_order; + + size_t bytes_written = 0; + const uint8_t *src = (const uint8_t *)s; + bool binary_was_set = m_flags.Test(eBinary); + if (!binary_was_set) + m_flags.Set(eBinary); + if (src_byte_order == dst_byte_order) { + for (size_t i = 0; i < src_len; ++i) + bytes_written += _PutHex8(src[i], false); + } else { + for (size_t i = src_len - 1; i < src_len; --i) + bytes_written += _PutHex8(src[i], false); + } + if (!binary_was_set) m_flags.Clear(eBinary); - if (src_byte_order == dst_byte_order) - { - for (size_t i = 0; i < src_len; ++i) - bytes_written += _PutHex8 (src[i], false); - } - else - { - for (size_t i = src_len-1; i < src_len; --i) - bytes_written += _PutHex8 (src[i], false); - } - if (binary_is_set) - m_flags.Set(eBinary); - return bytes_written; + return bytes_written; +} + +size_t Stream::PutBytesAsRawHex8(const void *s, size_t src_len, + ByteOrder src_byte_order, + ByteOrder dst_byte_order) { + if (src_byte_order == eByteOrderInvalid) + src_byte_order = m_byte_order; + + if (dst_byte_order == eByteOrderInvalid) + dst_byte_order = m_byte_order; + + size_t bytes_written = 0; + const uint8_t *src = (const uint8_t *)s; + bool binary_is_set = m_flags.Test(eBinary); + m_flags.Clear(eBinary); + if (src_byte_order == dst_byte_order) { + for (size_t i = 0; i < src_len; ++i) + bytes_written += _PutHex8(src[i], false); + } else { + for (size_t i = src_len - 1; i < src_len; --i) + bytes_written += _PutHex8(src[i], false); + } + if (binary_is_set) + m_flags.Set(eBinary); + + return bytes_written; +} + +size_t Stream::PutCStringAsRawHex8(const char *s) { + size_t bytes_written = 0; + bool binary_is_set = m_flags.Test(eBinary); + m_flags.Clear(eBinary); + do { + bytes_written += _PutHex8(*s, false); + ++s; + } while (*s); + if (binary_is_set) + m_flags.Set(eBinary); + return bytes_written; +} + +void Stream::UnitTest(Stream *s) { + s->PutHex8(0x12); + + s->PutChar(' '); + s->PutHex16(0x3456, endian::InlHostByteOrder()); + s->PutChar(' '); + s->PutHex16(0x3456, eByteOrderBig); + s->PutChar(' '); + s->PutHex16(0x3456, eByteOrderLittle); + + s->PutChar(' '); + s->PutHex32(0x789abcde, endian::InlHostByteOrder()); + s->PutChar(' '); + s->PutHex32(0x789abcde, eByteOrderBig); + s->PutChar(' '); + s->PutHex32(0x789abcde, eByteOrderLittle); + + s->PutChar(' '); + s->PutHex64(0x1122334455667788ull, endian::InlHostByteOrder()); + s->PutChar(' '); + s->PutHex64(0x1122334455667788ull, eByteOrderBig); + s->PutChar(' '); + s->PutHex64(0x1122334455667788ull, eByteOrderLittle); + + const char *hola = "Hello World!!!"; + s->PutChar(' '); + s->PutCString(hola); + + s->PutChar(' '); + s->Write(hola, 5); + + s->PutChar(' '); + s->PutCStringAsRawHex8(hola); + + s->PutChar(' '); + s->PutCStringAsRawHex8("01234"); + + s->PutChar(' '); + s->Printf("pid=%i", 12733); + + s->PutChar(' '); + s->PrintfAsRawHex8("pid=%i", 12733); + s->PutChar('\n'); } - -size_t -Stream::PutCStringAsRawHex8 (const char *s) -{ - size_t bytes_written = 0; - bool binary_is_set = m_flags.Test(eBinary); - m_flags.Clear(eBinary); - do - { - bytes_written += _PutHex8 (*s, false); - ++s; - } while (*s); - if (binary_is_set) - m_flags.Set(eBinary); - return bytes_written; -} - -void -Stream::UnitTest(Stream *s) -{ - s->PutHex8(0x12); - - s->PutChar(' '); - s->PutHex16(0x3456, endian::InlHostByteOrder()); - s->PutChar(' '); - s->PutHex16(0x3456, eByteOrderBig); - s->PutChar(' '); - s->PutHex16(0x3456, eByteOrderLittle); - - s->PutChar(' '); - s->PutHex32(0x789abcde, endian::InlHostByteOrder()); - s->PutChar(' '); - s->PutHex32(0x789abcde, eByteOrderBig); - s->PutChar(' '); - s->PutHex32(0x789abcde, eByteOrderLittle); - - s->PutChar(' '); - s->PutHex64(0x1122334455667788ull, endian::InlHostByteOrder()); - s->PutChar(' '); - s->PutHex64(0x1122334455667788ull, eByteOrderBig); - s->PutChar(' '); - s->PutHex64(0x1122334455667788ull, eByteOrderLittle); - - const char *hola = "Hello World!!!"; - s->PutChar(' '); - s->PutCString (hola); - - s->PutChar(' '); - s->Write (hola, 5); - - s->PutChar(' '); - s->PutCStringAsRawHex8 (hola); - - s->PutChar(' '); - s->PutCStringAsRawHex8 ("01234"); - - s->PutChar(' '); - s->Printf ("pid=%i", 12733); - - s->PutChar(' '); - s->PrintfAsRawHex8 ("pid=%i", 12733); - s->PutChar('\n'); -} - diff --git a/source/Core/StreamAsynchronousIO.cpp b/source/Core/StreamAsynchronousIO.cpp index 6f8fcce932e7..1f7e634dfe33 100644 --- a/source/Core/StreamAsynchronousIO.cpp +++ b/source/Core/StreamAsynchronousIO.cpp @@ -1,4 +1,4 @@ -//===-- StreamBroadcast.cpp -------------------------------------*- C++ -*-===// +//===-- StreamAsynchronousIO.cpp --------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -9,40 +9,29 @@ #include "lldb/Core/StreamAsynchronousIO.h" -#include "lldb/lldb-private.h" #include "lldb/Core/Debugger.h" +#include "lldb/lldb-private.h" using namespace lldb; using namespace lldb_private; +StreamAsynchronousIO::StreamAsynchronousIO(Debugger &debugger, bool for_stdout) + : Stream(0, 4, eByteOrderBig), m_debugger(debugger), m_data(), + m_for_stdout(for_stdout) {} -StreamAsynchronousIO::StreamAsynchronousIO (Debugger &debugger, bool for_stdout) : - Stream (0, 4, eByteOrderBig), - m_debugger (debugger), - m_data (), - m_for_stdout (for_stdout) -{ -} - -StreamAsynchronousIO::~StreamAsynchronousIO () -{ - // Flush when we destroy to make sure we display the data - Flush(); +StreamAsynchronousIO::~StreamAsynchronousIO() { + // Flush when we destroy to make sure we display the data + Flush(); } -void -StreamAsynchronousIO::Flush () -{ - if (!m_data.empty()) - { - m_debugger.PrintAsync (m_data.data(), m_data.size(), m_for_stdout); - m_data = std::string(); - } +void StreamAsynchronousIO::Flush() { + if (!m_data.empty()) { + m_debugger.PrintAsync(m_data.data(), m_data.size(), m_for_stdout); + m_data = std::string(); + } } -size_t -StreamAsynchronousIO::Write (const void *s, size_t length) -{ - m_data.append ((const char *)s, length); - return length; +size_t StreamAsynchronousIO::Write(const void *s, size_t length) { + m_data.append((const char *)s, length); + return length; } diff --git a/source/Core/StreamCallback.cpp b/source/Core/StreamCallback.cpp index 9f0adee2a159..de784101e969 100644 --- a/source/Core/StreamCallback.cpp +++ b/source/Core/StreamCallback.cpp @@ -9,51 +9,42 @@ #include <stdio.h> -#include "lldb/lldb-private.h" #include "lldb/Core/Broadcaster.h" #include "lldb/Core/Event.h" #include "lldb/Core/StreamCallback.h" #include "lldb/Host/Host.h" +#include "lldb/lldb-private.h" using namespace lldb; using namespace lldb_private; StreamCallback::StreamCallback(lldb::LogOutputCallback callback, void *baton) - : Stream(0, 4, eByteOrderBig), m_callback(callback), m_baton(baton), m_accumulated_data(), m_collection_mutex() -{ -} - -StreamCallback::~StreamCallback () -{ -} - -StreamString & -StreamCallback::FindStreamForThread(lldb::tid_t cur_tid) -{ - std::lock_guard<std::mutex> guard(m_collection_mutex); - collection::iterator iter = m_accumulated_data.find (cur_tid); - if (iter == m_accumulated_data.end()) - { - std::pair<collection::iterator, bool> ret; - ret = m_accumulated_data.insert(std::pair<lldb::tid_t,StreamString>(cur_tid, StreamString())); - iter = ret.first; - } - return (*iter).second; + : Stream(0, 4, eByteOrderBig), m_callback(callback), m_baton(baton), + m_accumulated_data(), m_collection_mutex() {} + +StreamCallback::~StreamCallback() {} + +StreamString &StreamCallback::FindStreamForThread(lldb::tid_t cur_tid) { + std::lock_guard<std::mutex> guard(m_collection_mutex); + collection::iterator iter = m_accumulated_data.find(cur_tid); + if (iter == m_accumulated_data.end()) { + std::pair<collection::iterator, bool> ret; + ret = m_accumulated_data.insert( + std::pair<lldb::tid_t, StreamString>(cur_tid, StreamString())); + iter = ret.first; + } + return (*iter).second; } -void -StreamCallback::Flush () -{ - lldb::tid_t cur_tid = Host::GetCurrentThreadID(); - StreamString &out_stream = FindStreamForThread(cur_tid); - m_callback (out_stream.GetData(), m_baton); - out_stream.Clear(); +void StreamCallback::Flush() { + lldb::tid_t cur_tid = Host::GetCurrentThreadID(); + StreamString &out_stream = FindStreamForThread(cur_tid); + m_callback(out_stream.GetData(), m_baton); + out_stream.Clear(); } -size_t -StreamCallback::Write (const void *s, size_t length) -{ - lldb::tid_t cur_tid = Host::GetCurrentThreadID(); - FindStreamForThread(cur_tid).Write (s, length); - return length; +size_t StreamCallback::Write(const void *s, size_t length) { + lldb::tid_t cur_tid = Host::GetCurrentThreadID(); + FindStreamForThread(cur_tid).Write(s, length); + return length; } diff --git a/source/Core/StreamFile.cpp b/source/Core/StreamFile.cpp index 8c9700c6dcba..f8c7fb9a84dc 100644 --- a/source/Core/StreamFile.cpp +++ b/source/Core/StreamFile.cpp @@ -16,65 +16,37 @@ // Project includes #include "lldb/Core/Error.h" - using namespace lldb; using namespace lldb_private; //---------------------------------------------------------------------- // StreamFile constructor //---------------------------------------------------------------------- -StreamFile::StreamFile () : - Stream (), - m_file () -{ -} +StreamFile::StreamFile() : Stream(), m_file() {} -StreamFile::StreamFile (uint32_t flags, uint32_t addr_size, ByteOrder byte_order) : - Stream (flags, addr_size, byte_order), - m_file () -{ -} +StreamFile::StreamFile(uint32_t flags, uint32_t addr_size, ByteOrder byte_order) + : Stream(flags, addr_size, byte_order), m_file() {} -StreamFile::StreamFile (int fd, bool transfer_ownership) : - Stream (), - m_file (fd, transfer_ownership) -{ -} +StreamFile::StreamFile(int fd, bool transfer_ownership) + : Stream(), m_file(fd, transfer_ownership) {} -StreamFile::StreamFile (FILE *fh, bool transfer_ownership) : - Stream (), - m_file (fh, transfer_ownership) -{ -} +StreamFile::StreamFile(FILE *fh, bool transfer_ownership) + : Stream(), m_file(fh, transfer_ownership) {} -StreamFile::StreamFile (const char *path) : - Stream (), - m_file (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionCloseOnExec, - lldb::eFilePermissionsFileDefault) -{ -} +StreamFile::StreamFile(const char *path) + : Stream(), + m_file(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate | + File::eOpenOptionCloseOnExec, + lldb::eFilePermissionsFileDefault) {} -StreamFile::StreamFile (const char *path, - uint32_t options, - uint32_t permissions) : - Stream(), - m_file(path, options, permissions) -{ -} +StreamFile::StreamFile(const char *path, uint32_t options, uint32_t permissions) + : Stream(), m_file(path, options, permissions) {} -StreamFile::~StreamFile() -{ -} +StreamFile::~StreamFile() {} -void -StreamFile::Flush () -{ - m_file.Flush(); -} +void StreamFile::Flush() { m_file.Flush(); } -size_t -StreamFile::Write (const void *s, size_t length) -{ - m_file.Write (s, length); - return length; +size_t StreamFile::Write(const void *s, size_t length) { + m_file.Write(s, length); + return length; } diff --git a/source/Core/StreamGDBRemote.cpp b/source/Core/StreamGDBRemote.cpp index 46cb99ce98a5..a371d1316c7c 100644 --- a/source/Core/StreamGDBRemote.cpp +++ b/source/Core/StreamGDBRemote.cpp @@ -13,42 +13,30 @@ using namespace lldb; using namespace lldb_private; -StreamGDBRemote::StreamGDBRemote () : -StreamString () -{ +StreamGDBRemote::StreamGDBRemote() : StreamString() {} + +StreamGDBRemote::StreamGDBRemote(uint32_t flags, uint32_t addr_size, + ByteOrder byte_order) + : StreamString(flags, addr_size, byte_order) {} + +StreamGDBRemote::~StreamGDBRemote() {} + +int StreamGDBRemote::PutEscapedBytes(const void *s, size_t src_len) { + int bytes_written = 0; + const uint8_t *src = (const uint8_t *)s; + bool binary_is_set = m_flags.Test(eBinary); + m_flags.Clear(eBinary); + while (src_len) { + uint8_t byte = *src; + src++; + src_len--; + if (byte == 0x23 || byte == 0x24 || byte == 0x7d || byte == 0x2a) { + bytes_written += PutChar(0x7d); + byte ^= 0x20; + } + bytes_written += PutChar(byte); + }; + if (binary_is_set) + m_flags.Set(eBinary); + return bytes_written; } - -StreamGDBRemote::StreamGDBRemote(uint32_t flags, uint32_t addr_size, ByteOrder byte_order) : -StreamString (flags, addr_size, byte_order) -{ -} - -StreamGDBRemote::~StreamGDBRemote() -{ -} - - -int -StreamGDBRemote::PutEscapedBytes (const void* s, - size_t src_len) -{ - int bytes_written = 0; - const uint8_t *src = (const uint8_t *)s; - bool binary_is_set = m_flags.Test(eBinary); - m_flags.Clear(eBinary); - while (src_len) - { - uint8_t byte = *src; - src++; src_len--; - if (byte == 0x23 || byte == 0x24 || byte == 0x7d || byte == 0x2a) - { - bytes_written += PutChar(0x7d); - byte ^= 0x20; - } - bytes_written += PutChar(byte); - }; - if (binary_is_set) - m_flags.Set(eBinary); - return bytes_written; -} - diff --git a/source/Core/StreamString.cpp b/source/Core/StreamString.cpp index 36e086b0b433..461648815f18 100644 --- a/source/Core/StreamString.cpp +++ b/source/Core/StreamString.cpp @@ -13,104 +13,53 @@ using namespace lldb; using namespace lldb_private; -StreamString::StreamString () : - Stream (0, 4, eByteOrderBig) -{ -} +StreamString::StreamString() : Stream(0, 4, eByteOrderBig) {} -StreamString::StreamString(uint32_t flags, uint32_t addr_size, ByteOrder byte_order) : - Stream (flags, addr_size, byte_order), - m_packet () -{ -} +StreamString::StreamString(uint32_t flags, uint32_t addr_size, + ByteOrder byte_order) + : Stream(flags, addr_size, byte_order), m_packet() {} -StreamString::~StreamString() -{ -} +StreamString::~StreamString() {} -void -StreamString::Flush () -{ - // Nothing to do when flushing a buffer based stream... +void StreamString::Flush() { + // Nothing to do when flushing a buffer based stream... } -size_t -StreamString::Write (const void *s, size_t length) -{ - m_packet.append (reinterpret_cast<const char *>(s), length); - return length; +size_t StreamString::Write(const void *s, size_t length) { + m_packet.append(reinterpret_cast<const char *>(s), length); + return length; } -void -StreamString::Clear() -{ - m_packet.clear(); -} +void StreamString::Clear() { m_packet.clear(); } -bool -StreamString::Empty() const -{ - return GetSize() == 0; -} +bool StreamString::Empty() const { return GetSize() == 0; } -const char * -StreamString::GetData () const -{ - return m_packet.c_str(); -} +size_t StreamString::GetSize() const { return m_packet.size(); } -size_t -StreamString::GetSize () const -{ - return m_packet.size(); -} - -size_t -StreamString::GetSizeOfLastLine () const -{ - const size_t length = m_packet.size(); - size_t last_line_begin_pos = m_packet.find_last_of("\r\n"); - if (last_line_begin_pos == std::string::npos) - { - return length; - } - else - { - ++last_line_begin_pos; - return length - last_line_begin_pos; - } -} - -std::string & -StreamString::GetString() -{ - return m_packet; -} - -const std::string & -StreamString::GetString() const -{ - return m_packet; +size_t StreamString::GetSizeOfLastLine() const { + const size_t length = m_packet.size(); + size_t last_line_begin_pos = m_packet.find_last_of("\r\n"); + if (last_line_begin_pos == std::string::npos) { + return length; + } else { + ++last_line_begin_pos; + return length - last_line_begin_pos; + } } -void -StreamString::FillLastLineToColumn (uint32_t column, char fill_char) -{ - const size_t length = m_packet.size(); - size_t last_line_begin_pos = m_packet.find_last_of("\r\n"); - if (last_line_begin_pos == std::string::npos) - { - last_line_begin_pos = 0; - } - else - { - ++last_line_begin_pos; - } - - const size_t line_columns = length - last_line_begin_pos; - if (column > line_columns) - { - m_packet.append(column - line_columns, fill_char); - } +llvm::StringRef StreamString::GetString() const { return m_packet; } + +void StreamString::FillLastLineToColumn(uint32_t column, char fill_char) { + const size_t length = m_packet.size(); + size_t last_line_begin_pos = m_packet.find_last_of("\r\n"); + if (last_line_begin_pos == std::string::npos) { + last_line_begin_pos = 0; + } else { + ++last_line_begin_pos; + } + + const size_t line_columns = length - last_line_begin_pos; + if (column > line_columns) { + m_packet.append(column - line_columns, fill_char); + } } - diff --git a/source/Core/StringList.cpp b/source/Core/StringList.cpp index 98a079007fba..d2c4ac6775aa 100644 --- a/source/Core/StringList.cpp +++ b/source/Core/StringList.cpp @@ -9,369 +9,263 @@ #include "lldb/Core/StringList.h" +#include "lldb/Core/Log.h" #include "lldb/Core/StreamString.h" #include "lldb/Host/FileSpec.h" -#include "lldb/Core/Log.h" #include <string> using namespace lldb_private; -StringList::StringList () : - m_strings () -{ -} +StringList::StringList() : m_strings() {} -StringList::StringList (const char *str) : - m_strings () -{ - if (str) - m_strings.push_back (str); +StringList::StringList(const char *str) : m_strings() { + if (str) + m_strings.push_back(str); } -StringList::StringList (const char **strv, int strc) : - m_strings () -{ - for (int i = 0; i < strc; ++i) - { - if (strv[i]) - m_strings.push_back (strv[i]); - } +StringList::StringList(const char **strv, int strc) : m_strings() { + for (int i = 0; i < strc; ++i) { + if (strv[i]) + m_strings.push_back(strv[i]); + } } -StringList::~StringList () -{ -} +StringList::~StringList() {} -void -StringList::AppendString (const char *str) -{ - if (str) - m_strings.push_back (str); +void StringList::AppendString(const char *str) { + if (str) + m_strings.push_back(str); } -void -StringList::AppendString (const std::string &s) -{ - m_strings.push_back (s); -} +void StringList::AppendString(const std::string &s) { m_strings.push_back(s); } -void -StringList::AppendString (std::string &&s) -{ - m_strings.push_back (s); -} +void StringList::AppendString(std::string &&s) { m_strings.push_back(s); } -void -StringList::AppendString (const char *str, size_t str_len) -{ - if (str) - m_strings.push_back (std::string (str, str_len)); +void StringList::AppendString(const char *str, size_t str_len) { + if (str) + m_strings.push_back(std::string(str, str_len)); } -void -StringList::AppendString(llvm::StringRef str) -{ - m_strings.push_back(str.str()); +void StringList::AppendString(llvm::StringRef str) { + m_strings.push_back(str.str()); } -void -StringList::AppendList (const char **strv, int strc) -{ - for (int i = 0; i < strc; ++i) - { - if (strv[i]) - m_strings.push_back (strv[i]); - } +void StringList::AppendList(const char **strv, int strc) { + for (int i = 0; i < strc; ++i) { + if (strv[i]) + m_strings.push_back(strv[i]); + } } -void -StringList::AppendList (StringList strings) -{ - size_t len = strings.GetSize(); +void StringList::AppendList(StringList strings) { + size_t len = strings.GetSize(); - for (size_t i = 0; i < len; ++i) - m_strings.push_back (strings.GetStringAtIndex(i)); + for (size_t i = 0; i < len; ++i) + m_strings.push_back(strings.GetStringAtIndex(i)); } -bool -StringList::ReadFileLines (FileSpec &input_file) -{ - return input_file.ReadFileLines (m_strings); +bool StringList::ReadFileLines(FileSpec &input_file) { + return input_file.ReadFileLines(m_strings); } -size_t -StringList::GetSize () const -{ - return m_strings.size(); +size_t StringList::GetSize() const { return m_strings.size(); } + +size_t StringList::GetMaxStringLength() const { + size_t max_length = 0; + for (const auto &s : m_strings) { + const size_t len = s.size(); + if (max_length < len) + max_length = len; + } + return max_length; } -size_t -StringList::GetMaxStringLength () const -{ - size_t max_length = 0; - for (const auto &s : m_strings) - { - const size_t len = s.size(); - if (max_length < len) - max_length = len; - } - return max_length; +const char *StringList::GetStringAtIndex(size_t idx) const { + if (idx < m_strings.size()) + return m_strings[idx].c_str(); + return NULL; } +void StringList::Join(const char *separator, Stream &strm) { + size_t size = GetSize(); -const char * -StringList::GetStringAtIndex (size_t idx) const -{ - if (idx < m_strings.size()) - return m_strings[idx].c_str(); - return NULL; -} + if (size == 0) + return; -void -StringList::Join (const char *separator, Stream &strm) -{ - size_t size = GetSize(); - - if (size == 0) - return; - - for (uint32_t i = 0; i < size; ++i) - { - if (i > 0) - strm.PutCString(separator); - strm.PutCString(GetStringAtIndex(i)); - } + for (uint32_t i = 0; i < size; ++i) { + if (i > 0) + strm.PutCString(separator); + strm.PutCString(GetStringAtIndex(i)); + } } -void -StringList::Clear () -{ - m_strings.clear(); -} +void StringList::Clear() { m_strings.clear(); } -void -StringList::LongestCommonPrefix (std::string &common_prefix) -{ - const size_t num_strings = m_strings.size(); +void StringList::LongestCommonPrefix(std::string &common_prefix) { + common_prefix.clear(); + if (m_strings.empty()) + return; - if (num_strings == 0) - { - common_prefix.clear(); - } - else - { - common_prefix = m_strings.front(); - - for (size_t idx = 1; idx < num_strings; ++idx) - { - std::string &curr_string = m_strings[idx]; - size_t new_size = curr_string.size(); - - // First trim common_prefix if it is longer than the current element: - if (common_prefix.size() > new_size) - common_prefix.erase (new_size); - - // Then trim it at the first disparity: - for (size_t i = 0; i < common_prefix.size(); i++) - { - if (curr_string[i] != common_prefix[i]) - { - common_prefix.erase(i); - break; - } - } - - // If we've emptied the common prefix, we're done. - if (common_prefix.empty()) - break; - } + auto args = llvm::makeArrayRef(m_strings); + llvm::StringRef prefix = args.front(); + for (auto arg : args.drop_front()) { + size_t count = 0; + for (count = 0; count < std::min(prefix.size(), arg.size()); ++count) { + if (prefix[count] != arg[count]) + break; } + prefix = prefix.take_front(count); + } + common_prefix = prefix; } -void -StringList::InsertStringAtIndex (size_t idx, const char *str) -{ - if (str) - { - if (idx < m_strings.size()) - m_strings.insert (m_strings.begin() + idx, str); - else - m_strings.push_back (str); - } -} - -void -StringList::InsertStringAtIndex (size_t idx, const std::string &str) -{ +void StringList::InsertStringAtIndex(size_t idx, const char *str) { + if (str) { if (idx < m_strings.size()) - m_strings.insert (m_strings.begin() + idx, str); + m_strings.insert(m_strings.begin() + idx, str); else - m_strings.push_back (str); + m_strings.push_back(str); + } } -void -StringList::InsertStringAtIndex (size_t idx, std::string &&str) -{ - if (idx < m_strings.size()) - m_strings.insert (m_strings.begin() + idx, str); - else - m_strings.push_back (str); +void StringList::InsertStringAtIndex(size_t idx, const std::string &str) { + if (idx < m_strings.size()) + m_strings.insert(m_strings.begin() + idx, str); + else + m_strings.push_back(str); } -void -StringList::DeleteStringAtIndex (size_t idx) -{ - if (idx < m_strings.size()) - m_strings.erase (m_strings.begin() + idx); +void StringList::InsertStringAtIndex(size_t idx, std::string &&str) { + if (idx < m_strings.size()) + m_strings.insert(m_strings.begin() + idx, str); + else + m_strings.push_back(str); } -size_t -StringList::SplitIntoLines (const std::string &lines) -{ - return SplitIntoLines (lines.c_str(), lines.size()); +void StringList::DeleteStringAtIndex(size_t idx) { + if (idx < m_strings.size()) + m_strings.erase(m_strings.begin() + idx); } -size_t -StringList::SplitIntoLines (const char *lines, size_t len) -{ - const size_t orig_size = m_strings.size(); - - if (len == 0) - return 0; - - const char *k_newline_chars = "\r\n"; - const char *p = lines; - const char *end = lines + len; - while (p < end) - { - size_t count = strcspn (p, k_newline_chars); - if (count == 0) - { - if (p[count] == '\r' || p[count] == '\n') - m_strings.push_back(std::string()); - else - break; - } - else - { - if (p + count > end) - count = end - p; - m_strings.push_back(std::string(p, count)); - } - if (p[count] == '\r' && p[count+1] == '\n') - count++; // Skip an extra newline char for the DOS newline - count++; // Skip the newline character - p += count; - } - return m_strings.size() - orig_size; +size_t StringList::SplitIntoLines(const std::string &lines) { + return SplitIntoLines(lines.c_str(), lines.size()); } -void -StringList::RemoveBlankLines () -{ - if (GetSize() == 0) - return; - - size_t idx = 0; - while (idx < m_strings.size()) - { - if (m_strings[idx].empty()) - DeleteStringAtIndex(idx); - else - idx++; +size_t StringList::SplitIntoLines(const char *lines, size_t len) { + const size_t orig_size = m_strings.size(); + + if (len == 0) + return 0; + + const char *k_newline_chars = "\r\n"; + const char *p = lines; + const char *end = lines + len; + while (p < end) { + size_t count = strcspn(p, k_newline_chars); + if (count == 0) { + if (p[count] == '\r' || p[count] == '\n') + m_strings.push_back(std::string()); + else + break; + } else { + if (p + count > end) + count = end - p; + m_strings.push_back(std::string(p, count)); } + if (p[count] == '\r' && p[count + 1] == '\n') + count++; // Skip an extra newline char for the DOS newline + count++; // Skip the newline character + p += count; + } + return m_strings.size() - orig_size; +} + +void StringList::RemoveBlankLines() { + if (GetSize() == 0) + return; + + size_t idx = 0; + while (idx < m_strings.size()) { + if (m_strings[idx].empty()) + DeleteStringAtIndex(idx); + else + idx++; + } } -std::string -StringList::CopyList(const char* item_preamble, const char* items_sep) const -{ - StreamString strm; - for (size_t i = 0; i < GetSize(); i++) - { - if (i && items_sep && items_sep[0]) - strm << items_sep; - if (item_preamble) - strm << item_preamble; - strm << GetStringAtIndex(i); - } - return std::string(strm.GetData()); +std::string StringList::CopyList(const char *item_preamble, + const char *items_sep) const { + StreamString strm; + for (size_t i = 0; i < GetSize(); i++) { + if (i && items_sep && items_sep[0]) + strm << items_sep; + if (item_preamble) + strm << item_preamble; + strm << GetStringAtIndex(i); + } + return strm.GetString(); } -StringList& -StringList::operator << (const char* str) -{ - AppendString(str); - return *this; +StringList &StringList::operator<<(const char *str) { + AppendString(str); + return *this; } -StringList& -StringList::operator << (const std::string& str) -{ - AppendString(str); - return *this; +StringList &StringList::operator<<(const std::string &str) { + AppendString(str); + return *this; } -StringList& -StringList::operator << (StringList strings) -{ - AppendList(strings); - return *this; +StringList &StringList::operator<<(StringList strings) { + AppendList(strings); + return *this; } -StringList& -StringList::operator = (const std::vector<std::string> &rhs) -{ - Clear(); - for (const auto &s : rhs) - m_strings.push_back(s); +StringList &StringList::operator=(const std::vector<std::string> &rhs) { + Clear(); + for (const auto &s : rhs) + m_strings.push_back(s); - return *this; + return *this; } -size_t -StringList::AutoComplete (const char *s, StringList &matches, size_t &exact_idx) const -{ - matches.Clear(); - exact_idx = SIZE_MAX; - if (s && s[0]) - { - const size_t s_len = strlen (s); - const size_t num_strings = m_strings.size(); - - for (size_t i=0; i<num_strings; ++i) - { - if (m_strings[i].find(s) == 0) - { - if (exact_idx == SIZE_MAX && m_strings[i].size() == s_len) - exact_idx = matches.GetSize(); - matches.AppendString (m_strings[i]); - } - } - } - else - { - // No string, so it matches everything - matches = *this; - } +size_t StringList::AutoComplete(llvm::StringRef s, StringList &matches, + size_t &exact_idx) const { + matches.Clear(); + exact_idx = SIZE_MAX; + if (s.empty()) { + // No string, so it matches everything + matches = *this; return matches.GetSize(); -} + } -void -StringList::LogDump(Log *log, const char *name) -{ - if (!log) - return; - - StreamString strm; - if (name) - strm.Printf("Begin %s:\n", name); - for (const auto &s : m_strings) { - strm.Indent(); - strm.Printf("%s\n", s.c_str()); + const size_t s_len = s.size(); + const size_t num_strings = m_strings.size(); + + for (size_t i = 0; i < num_strings; ++i) { + if (m_strings[i].find(s) == 0) { + if (exact_idx == SIZE_MAX && m_strings[i].size() == s_len) + exact_idx = matches.GetSize(); + matches.AppendString(m_strings[i]); } - if (name) - strm.Printf("End %s.\n", name); + } + return matches.GetSize(); +} + +void StringList::LogDump(Log *log, const char *name) { + if (!log) + return; + + StreamString strm; + if (name) + strm.Printf("Begin %s:\n", name); + for (const auto &s : m_strings) { + strm.Indent(); + strm.Printf("%s\n", s.c_str()); + } + if (name) + strm.Printf("End %s.\n", name); - log->Debug("%s", strm.GetData()); + log->Debug("%s", strm.GetData()); } diff --git a/source/Core/StructuredData.cpp b/source/Core/StructuredData.cpp index efc104f1f3e8..1e190f52314e 100644 --- a/source/Core/StructuredData.cpp +++ b/source/Core/StructuredData.cpp @@ -1,4 +1,4 @@ -//===---------------------StructuredData.cpp ---------------------*- C++ -*-===// +//===---------------------StructuredData.cpp ---------------------*- C++-*-===// // // The LLVM Compiler Infrastructure // @@ -10,296 +10,298 @@ #include "lldb/Core/StructuredData.h" #include <errno.h> -#include <stdlib.h> #include <inttypes.h> +#include <stdlib.h> +#include "lldb/Core/DataBuffer.h" +#include "lldb/Core/Error.h" #include "lldb/Core/StreamString.h" +#include "lldb/Host/File.h" +#include "lldb/Host/FileSpec.h" #include "lldb/Host/StringConvert.h" #include "lldb/Utility/JSON.h" using namespace lldb_private; - //---------------------------------------------------------------------- // Functions that use a JSONParser to parse JSON into StructuredData //---------------------------------------------------------------------- -static StructuredData::ObjectSP ParseJSONValue (JSONParser &json_parser); -static StructuredData::ObjectSP ParseJSONObject (JSONParser &json_parser); -static StructuredData::ObjectSP ParseJSONArray (JSONParser &json_parser); - -static StructuredData::ObjectSP -ParseJSONObject (JSONParser &json_parser) -{ - // The "JSONParser::Token::ObjectStart" token should have already been consumed - // by the time this function is called - std::unique_ptr<StructuredData::Dictionary> dict_up(new StructuredData::Dictionary()); - - std::string value; - std::string key; - while (1) - { - JSONParser::Token token = json_parser.GetToken(value); - - if (token == JSONParser::Token::String) - { - key.swap(value); - token = json_parser.GetToken(value); - if (token == JSONParser::Token::Colon) - { - StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser); - if (value_sp) - dict_up->AddItem(key, value_sp); - else - break; - } - } - else if (token == JSONParser::Token::ObjectEnd) - { - return StructuredData::ObjectSP(dict_up.release()); - } - else if (token == JSONParser::Token::Comma) - { - continue; - } - else - { - break; - } - } - return StructuredData::ObjectSP(); +static StructuredData::ObjectSP ParseJSONValue(JSONParser &json_parser); +static StructuredData::ObjectSP ParseJSONObject(JSONParser &json_parser); +static StructuredData::ObjectSP ParseJSONArray(JSONParser &json_parser); + +StructuredData::ObjectSP +StructuredData::ParseJSONFromFile(const FileSpec &input_spec, Error &error) { + StructuredData::ObjectSP return_sp; + if (!input_spec.Exists()) { + error.SetErrorStringWithFormat("input file %s does not exist.", + input_spec.GetPath().c_str()); + return return_sp; + } + + File input_file(nullptr, File::OpenOptions::eOpenOptionRead, + lldb::eFilePermissionsUserRead); + std::string input_path = input_spec.GetPath(); + error = + input_file.Open(input_path.c_str(), File::OpenOptions::eOpenOptionRead, + lldb::eFilePermissionsUserRead); + + if (!error.Success()) { + error.SetErrorStringWithFormat("could not open input file: %s - %s.", + input_spec.GetPath().c_str(), + error.AsCString()); + return return_sp; + } + + lldb::DataBufferSP input_data; + size_t num_bytes = std::numeric_limits<size_t>::max(); + off_t offset = 0; + error = input_file.Read(num_bytes, offset, true, input_data); + if (!error.Success()) { + error.SetErrorStringWithFormat("could not read input file: %s - %s.", + input_spec.GetPath().c_str(), + error.AsCString()); + return return_sp; + } + JSONParser json_parser((char *)input_data->GetBytes()); + return_sp = ParseJSONValue(json_parser); + return return_sp; } -static StructuredData::ObjectSP -ParseJSONArray (JSONParser &json_parser) -{ - // The "JSONParser::Token::ObjectStart" token should have already been consumed - // by the time this function is called - std::unique_ptr<StructuredData::Array> array_up(new StructuredData::Array()); - - std::string value; - std::string key; - while (1) - { +static StructuredData::ObjectSP ParseJSONObject(JSONParser &json_parser) { + // The "JSONParser::Token::ObjectStart" token should have already been + // consumed + // by the time this function is called + std::unique_ptr<StructuredData::Dictionary> dict_up( + new StructuredData::Dictionary()); + + std::string value; + std::string key; + while (1) { + JSONParser::Token token = json_parser.GetToken(value); + + if (token == JSONParser::Token::String) { + key.swap(value); + token = json_parser.GetToken(value); + if (token == JSONParser::Token::Colon) { StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser); if (value_sp) - array_up->AddItem(value_sp); - else - break; - - JSONParser::Token token = json_parser.GetToken(value); - if (token == JSONParser::Token::Comma) - { - continue; - } - else if (token == JSONParser::Token::ArrayEnd) - { - return StructuredData::ObjectSP(array_up.release()); - } + dict_up->AddItem(key, value_sp); else - { - break; - } + break; + } + } else if (token == JSONParser::Token::ObjectEnd) { + return StructuredData::ObjectSP(dict_up.release()); + } else if (token == JSONParser::Token::Comma) { + continue; + } else { + break; } - return StructuredData::ObjectSP(); + } + return StructuredData::ObjectSP(); } -static StructuredData::ObjectSP -ParseJSONValue (JSONParser &json_parser) -{ - std::string value; - const JSONParser::Token token = json_parser.GetToken(value); - switch (token) - { - case JSONParser::Token::ObjectStart: - return ParseJSONObject(json_parser); - - case JSONParser::Token::ArrayStart: - return ParseJSONArray(json_parser); - - case JSONParser::Token::Integer: - { - bool success = false; - uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success); - if (success) - return StructuredData::ObjectSP(new StructuredData::Integer(uval)); - } - break; - - case JSONParser::Token::Float: - { - bool success = false; - double val = StringConvert::ToDouble(value.c_str(), 0.0, &success); - if (success) - return StructuredData::ObjectSP(new StructuredData::Float(val)); - } - break; - - case JSONParser::Token::String: - return StructuredData::ObjectSP(new StructuredData::String(value)); - - case JSONParser::Token::True: - case JSONParser::Token::False: - return StructuredData::ObjectSP(new StructuredData::Boolean(token == JSONParser::Token::True)); - - case JSONParser::Token::Null: - return StructuredData::ObjectSP(new StructuredData::Null()); - - default: - break; +static StructuredData::ObjectSP ParseJSONArray(JSONParser &json_parser) { + // The "JSONParser::Token::ObjectStart" token should have already been + // consumed + // by the time this function is called + std::unique_ptr<StructuredData::Array> array_up(new StructuredData::Array()); + + std::string value; + std::string key; + while (1) { + StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser); + if (value_sp) + array_up->AddItem(value_sp); + else + break; + + JSONParser::Token token = json_parser.GetToken(value); + if (token == JSONParser::Token::Comma) { + continue; + } else if (token == JSONParser::Token::ArrayEnd) { + return StructuredData::ObjectSP(array_up.release()); + } else { + break; } - return StructuredData::ObjectSP(); + } + return StructuredData::ObjectSP(); +} +static StructuredData::ObjectSP ParseJSONValue(JSONParser &json_parser) { + std::string value; + const JSONParser::Token token = json_parser.GetToken(value); + switch (token) { + case JSONParser::Token::ObjectStart: + return ParseJSONObject(json_parser); + + case JSONParser::Token::ArrayStart: + return ParseJSONArray(json_parser); + + case JSONParser::Token::Integer: { + bool success = false; + uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success); + if (success) + return StructuredData::ObjectSP(new StructuredData::Integer(uval)); + } break; + + case JSONParser::Token::Float: { + bool success = false; + double val = StringConvert::ToDouble(value.c_str(), 0.0, &success); + if (success) + return StructuredData::ObjectSP(new StructuredData::Float(val)); + } break; + + case JSONParser::Token::String: + return StructuredData::ObjectSP(new StructuredData::String(value)); + + case JSONParser::Token::True: + case JSONParser::Token::False: + return StructuredData::ObjectSP( + new StructuredData::Boolean(token == JSONParser::Token::True)); + + case JSONParser::Token::Null: + return StructuredData::ObjectSP(new StructuredData::Null()); + + default: + break; + } + return StructuredData::ObjectSP(); } -StructuredData::ObjectSP -StructuredData::ParseJSON (std::string json_text) -{ - JSONParser json_parser(json_text.c_str()); - StructuredData::ObjectSP object_sp = ParseJSONValue(json_parser); - return object_sp; +StructuredData::ObjectSP StructuredData::ParseJSON(std::string json_text) { + JSONParser json_parser(json_text.c_str()); + StructuredData::ObjectSP object_sp = ParseJSONValue(json_parser); + return object_sp; } StructuredData::ObjectSP -StructuredData::Object::GetObjectForDotSeparatedPath (llvm::StringRef path) -{ - if (this->GetType() == Type::eTypeDictionary) - { - std::pair<llvm::StringRef, llvm::StringRef> match = path.split('.'); - std::string key = match.first.str(); - ObjectSP value = this->GetAsDictionary()->GetValueForKey (key.c_str()); - if (value.get()) - { - // Do we have additional words to descend? If not, return the - // value we're at right now. - if (match.second.empty()) - { - return value; - } - else - { - return value->GetObjectForDotSeparatedPath (match.second); - } - } - return ObjectSP(); +StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) { + if (this->GetType() == Type::eTypeDictionary) { + std::pair<llvm::StringRef, llvm::StringRef> match = path.split('.'); + std::string key = match.first.str(); + ObjectSP value = this->GetAsDictionary()->GetValueForKey(key); + if (value.get()) { + // Do we have additional words to descend? If not, return the + // value we're at right now. + if (match.second.empty()) { + return value; + } else { + return value->GetObjectForDotSeparatedPath(match.second); + } } + return ObjectSP(); + } - if (this->GetType() == Type::eTypeArray) - { - std::pair<llvm::StringRef, llvm::StringRef> match = path.split('['); - if (match.second.size() == 0) - { - return this->shared_from_this(); - } - errno = 0; - uint64_t val = strtoul (match.second.str().c_str(), NULL, 10); - if (errno == 0) - { - return this->GetAsArray()->GetItemAtIndex(val); - } - return ObjectSP(); + if (this->GetType() == Type::eTypeArray) { + std::pair<llvm::StringRef, llvm::StringRef> match = path.split('['); + if (match.second.size() == 0) { + return this->shared_from_this(); + } + errno = 0; + uint64_t val = strtoul(match.second.str().c_str(), NULL, 10); + if (errno == 0) { + return this->GetAsArray()->GetItemAtIndex(val); } + return ObjectSP(); + } - return this->shared_from_this(); + return this->shared_from_this(); } -void -StructuredData::Object::DumpToStdout() const -{ - StreamString stream; - Dump(stream); - printf("%s\n", stream.GetString().c_str()); +void StructuredData::Object::DumpToStdout(bool pretty_print) const { + StreamString stream; + Dump(stream, pretty_print); + printf("%s\n", stream.GetData()); } -void -StructuredData::Array::Dump(Stream &s) const -{ - bool first = true; - s << "[\n"; +void StructuredData::Array::Dump(Stream &s, bool pretty_print) const { + bool first = true; + s << "["; + if (pretty_print) { + s << "\n"; s.IndentMore(); - for (const auto &item_sp : m_items) - { - if (first) - first = false; - else - s << ",\n"; - - s.Indent(); - item_sp->Dump(s); + } + for (const auto &item_sp : m_items) { + if (first) { + first = false; + } else { + s << ","; + if (pretty_print) + s << "\n"; } + + if (pretty_print) + s.Indent(); + item_sp->Dump(s, pretty_print); + } + if (pretty_print) { s.IndentLess(); s.EOL(); s.Indent(); - s << "]"; + } + s << "]"; } -void -StructuredData::Integer::Dump (Stream &s) const -{ - s.Printf ("%" PRIu64, m_value); +void StructuredData::Integer::Dump(Stream &s, bool pretty_print) const { + s.Printf("%" PRIu64, m_value); } - -void -StructuredData::Float::Dump (Stream &s) const -{ - s.Printf ("%lg", m_value); +void StructuredData::Float::Dump(Stream &s, bool pretty_print) const { + s.Printf("%lg", m_value); } -void -StructuredData::Boolean::Dump (Stream &s) const -{ - if (m_value == true) - s.PutCString ("true"); - else - s.PutCString ("false"); +void StructuredData::Boolean::Dump(Stream &s, bool pretty_print) const { + if (m_value == true) + s.PutCString("true"); + else + s.PutCString("false"); } - -void -StructuredData::String::Dump (Stream &s) const -{ - std::string quoted; - const size_t strsize = m_value.size(); - for (size_t i = 0; i < strsize ; ++i) - { - char ch = m_value[i]; - if (ch == '"') - quoted.push_back ('\\'); - quoted.push_back (ch); - } - s.Printf ("\"%s\"", quoted.c_str()); +void StructuredData::String::Dump(Stream &s, bool pretty_print) const { + std::string quoted; + const size_t strsize = m_value.size(); + for (size_t i = 0; i < strsize; ++i) { + char ch = m_value[i]; + if (ch == '"' || ch == '\\') + quoted.push_back('\\'); + quoted.push_back(ch); + } + s.Printf("\"%s\"", quoted.c_str()); } -void -StructuredData::Dictionary::Dump (Stream &s) const -{ - bool first = true; - s << "{\n"; +void StructuredData::Dictionary::Dump(Stream &s, bool pretty_print) const { + bool first = true; + s << "{"; + if (pretty_print) { + s << "\n"; s.IndentMore(); - for (const auto &pair : m_dict) - { - if (first) - first = false; - else - s << ",\n"; - s.Indent(); - s << "\"" << pair.first.AsCString() << "\" : "; - pair.second->Dump(s); + } + for (const auto &pair : m_dict) { + if (first) + first = false; + else { + s << ","; + if (pretty_print) + s << "\n"; } + if (pretty_print) + s.Indent(); + s << "\"" << pair.first.AsCString() << "\" : "; + pair.second->Dump(s, pretty_print); + } + if (pretty_print) { s.IndentLess(); s.EOL(); s.Indent(); - s << "}"; + } + s << "}"; } -void -StructuredData::Null::Dump (Stream &s) const -{ - s << "null"; +void StructuredData::Null::Dump(Stream &s, bool pretty_print) const { + s << "null"; } -void -StructuredData::Generic::Dump(Stream &s) const -{ - s << "0x" << m_object; +void StructuredData::Generic::Dump(Stream &s, bool pretty_print) const { + s << "0x" << m_object; } diff --git a/source/Core/Timer.cpp b/source/Core/Timer.cpp index f4cd33fc3cb5..ca1a2b749ec3 100644 --- a/source/Core/Timer.cpp +++ b/source/Core/Timer.cpp @@ -22,245 +22,133 @@ using namespace lldb_private; #define TIMER_INDENT_AMOUNT 2 -namespace -{ - typedef std::map<const char*, uint64_t> TimerCategoryMap; - - struct TimerStack - { - TimerStack() : - m_depth(0) - {} - - uint32_t m_depth; - std::vector<Timer*> m_stack; - }; +namespace { +typedef std::map<const char *, std::chrono::nanoseconds> TimerCategoryMap; +typedef std::vector<Timer *> TimerStack; } // end of anonymous namespace std::atomic<bool> Timer::g_quiet(true); std::atomic<unsigned> Timer::g_display_depth(0); -static std::mutex & -GetFileMutex() -{ - static std::mutex *g_file_mutex_ptr = nullptr; - static std::once_flag g_once_flag; - std::call_once(g_once_flag, []() { - // leaked on purpose to ensure this mutex works after main thread has run - // global C++ destructor chain - g_file_mutex_ptr = new std::mutex(); - }); - return *g_file_mutex_ptr; +static std::mutex &GetFileMutex() { + static std::mutex *g_file_mutex_ptr = new std::mutex(); + return *g_file_mutex_ptr; } -static std::mutex & -GetCategoryMutex() -{ - static std::mutex g_category_mutex; - return g_category_mutex; +static std::mutex &GetCategoryMutex() { + static std::mutex g_category_mutex; + return g_category_mutex; } -static TimerCategoryMap & -GetCategoryMap() -{ - static TimerCategoryMap g_category_map; - return g_category_map; +static TimerCategoryMap &GetCategoryMap() { + static TimerCategoryMap g_category_map; + return g_category_map; } -static void -ThreadSpecificCleanup(void *p) -{ - delete static_cast<TimerStack *>(p); +static void ThreadSpecificCleanup(void *p) { + delete static_cast<TimerStack *>(p); } -static TimerStack * -GetTimerStackForCurrentThread () -{ - static lldb::thread_key_t g_key = Host::ThreadLocalStorageCreate(ThreadSpecificCleanup); - - void *timer_stack = Host::ThreadLocalStorageGet(g_key); - if (timer_stack == NULL) - { - Host::ThreadLocalStorageSet(g_key, new TimerStack); - timer_stack = Host::ThreadLocalStorageGet(g_key); - } - return (TimerStack *)timer_stack; -} +static TimerStack *GetTimerStackForCurrentThread() { + static lldb::thread_key_t g_key = + Host::ThreadLocalStorageCreate(ThreadSpecificCleanup); -void -Timer::SetQuiet (bool value) -{ - g_quiet = value; + void *timer_stack = Host::ThreadLocalStorageGet(g_key); + if (timer_stack == NULL) { + Host::ThreadLocalStorageSet(g_key, new TimerStack); + timer_stack = Host::ThreadLocalStorageGet(g_key); + } + return (TimerStack *)timer_stack; } -Timer::Timer (const char *category, const char *format, ...) : - m_category (category), - m_total_start (), - m_timer_start (), - m_total_ticks (0), - m_timer_ticks (0) -{ - TimerStack *stack = GetTimerStackForCurrentThread (); - if (!stack) - return; +void Timer::SetQuiet(bool value) { g_quiet = value; } - if (stack->m_depth++ < g_display_depth) - { - if (g_quiet == false) - { - std::lock_guard<std::mutex> lock(GetFileMutex()); - - // Indent - ::fprintf(stdout, "%*s", stack->m_depth * TIMER_INDENT_AMOUNT, ""); - // Print formatted string - va_list args; - va_start (args, format); - ::vfprintf(stdout, format, args); - va_end (args); - - // Newline - ::fprintf(stdout, "\n"); - } - TimeValue start_time(TimeValue::Now()); - m_total_start = start_time; - m_timer_start = start_time; - - if (!stack->m_stack.empty()) - stack->m_stack.back()->ChildStarted (start_time); - stack->m_stack.push_back(this); - } -} - -Timer::~Timer() -{ - TimerStack *stack = GetTimerStackForCurrentThread (); - if (!stack) - return; - - if (m_total_start.IsValid()) - { - TimeValue stop_time = TimeValue::Now(); - if (m_total_start.IsValid()) - { - m_total_ticks += (stop_time - m_total_start); - m_total_start.Clear(); - } - if (m_timer_start.IsValid()) - { - m_timer_ticks += (stop_time - m_timer_start); - m_timer_start.Clear(); - } - - assert (stack->m_stack.back() == this); - stack->m_stack.pop_back(); - if (stack->m_stack.empty() == false) - stack->m_stack.back()->ChildStopped(stop_time); - - const uint64_t total_nsec_uint = GetTotalElapsedNanoSeconds(); - const uint64_t timer_nsec_uint = GetTimerElapsedNanoSeconds(); - const double total_nsec = total_nsec_uint; - const double timer_nsec = timer_nsec_uint; - - if (g_quiet == false) - { - std::lock_guard<std::mutex> lock(GetFileMutex()); - ::fprintf(stdout, "%*s%.9f sec (%.9f sec)\n", (stack->m_depth - 1) * TIMER_INDENT_AMOUNT, "", - total_nsec / 1000000000.0, timer_nsec / 1000000000.0); - } - - // Keep total results for each category so we can dump results. - std::lock_guard<std::mutex> guard(GetCategoryMutex()); - TimerCategoryMap &category_map = GetCategoryMap(); - category_map[m_category] += timer_nsec_uint; - } - if (stack->m_depth > 0) - --stack->m_depth; -} +Timer::Timer(const char *category, const char *format, ...) + : m_category(category), m_total_start(std::chrono::steady_clock::now()) { + TimerStack *stack = GetTimerStackForCurrentThread(); + if (!stack) + return; -uint64_t -Timer::GetTotalElapsedNanoSeconds() -{ - uint64_t total_ticks = m_total_ticks; + stack->push_back(this); + if (g_quiet && stack->size() <= g_display_depth) { + std::lock_guard<std::mutex> lock(GetFileMutex()); - // If we are currently running, we need to add the current - // elapsed time of the running timer... - if (m_total_start.IsValid()) - total_ticks += (TimeValue::Now() - m_total_start); + // Indent + ::fprintf(stdout, "%*s", int(stack->size() - 1) * TIMER_INDENT_AMOUNT, ""); + // Print formatted string + va_list args; + va_start(args, format); + ::vfprintf(stdout, format, args); + va_end(args); - return total_ticks; + // Newline + ::fprintf(stdout, "\n"); + } } -uint64_t -Timer::GetTimerElapsedNanoSeconds() -{ - uint64_t timer_ticks = m_timer_ticks; +Timer::~Timer() { + using namespace std::chrono; - // If we are currently running, we need to add the current - // elapsed time of the running timer... - if (m_timer_start.IsValid()) - timer_ticks += (TimeValue::Now() - m_timer_start); + TimerStack *stack = GetTimerStackForCurrentThread(); + if (!stack) + return; - return timer_ticks; -} + auto stop_time = steady_clock::now(); + auto total_dur = stop_time - m_total_start; + auto timer_dur = total_dur - m_child_duration; -void -Timer::ChildStarted (const TimeValue& start_time) -{ - if (m_timer_start.IsValid()) - { - m_timer_ticks += (start_time - m_timer_start); - m_timer_start.Clear(); - } -} + if (g_quiet && stack->size() <= g_display_depth) { + std::lock_guard<std::mutex> lock(GetFileMutex()); + ::fprintf(stdout, "%*s%.9f sec (%.9f sec)\n", + int(stack->size() - 1) * TIMER_INDENT_AMOUNT, "", + duration<double>(total_dur).count(), + duration<double>(timer_dur).count()); + } -void -Timer::ChildStopped (const TimeValue& stop_time) -{ - if (!m_timer_start.IsValid()) - m_timer_start = stop_time; -} + assert(stack->back() == this); + stack->pop_back(); + if (!stack->empty()) + stack->back()->ChildDuration(total_dur); -void -Timer::SetDisplayDepth (uint32_t depth) -{ - g_display_depth = depth; + // Keep total results for each category so we can dump results. + { + std::lock_guard<std::mutex> guard(GetCategoryMutex()); + TimerCategoryMap &category_map = GetCategoryMap(); + category_map[m_category] += timer_dur; + } } +void Timer::SetDisplayDepth(uint32_t depth) { g_display_depth = depth; } /* binary function predicate: * - returns whether a person is less than another person */ static bool -CategoryMapIteratorSortCriterion (const TimerCategoryMap::const_iterator& lhs, const TimerCategoryMap::const_iterator& rhs) -{ - return lhs->second > rhs->second; -} - - -void -Timer::ResetCategoryTimes () -{ - std::lock_guard<std::mutex> guard(GetCategoryMutex()); - TimerCategoryMap &category_map = GetCategoryMap(); - category_map.clear(); -} - -void -Timer::DumpCategoryTimes (Stream *s) -{ - std::lock_guard<std::mutex> guard(GetCategoryMutex()); - TimerCategoryMap &category_map = GetCategoryMap(); - std::vector<TimerCategoryMap::const_iterator> sorted_iterators; - TimerCategoryMap::const_iterator pos, end = category_map.end(); - for (pos = category_map.begin(); pos != end; ++pos) - { - sorted_iterators.push_back (pos); - } - std::sort (sorted_iterators.begin(), sorted_iterators.end(), CategoryMapIteratorSortCriterion); - - const size_t count = sorted_iterators.size(); - for (size_t i=0; i<count; ++i) - { - const double timer_nsec = sorted_iterators[i]->second; - s->Printf("%.9f sec for %s\n", timer_nsec / 1000000000.0, sorted_iterators[i]->first); - } +CategoryMapIteratorSortCriterion(const TimerCategoryMap::const_iterator &lhs, + const TimerCategoryMap::const_iterator &rhs) { + return lhs->second > rhs->second; +} + +void Timer::ResetCategoryTimes() { + std::lock_guard<std::mutex> guard(GetCategoryMutex()); + TimerCategoryMap &category_map = GetCategoryMap(); + category_map.clear(); +} + +void Timer::DumpCategoryTimes(Stream *s) { + std::lock_guard<std::mutex> guard(GetCategoryMutex()); + TimerCategoryMap &category_map = GetCategoryMap(); + std::vector<TimerCategoryMap::const_iterator> sorted_iterators; + TimerCategoryMap::const_iterator pos, end = category_map.end(); + for (pos = category_map.begin(); pos != end; ++pos) { + sorted_iterators.push_back(pos); + } + std::sort(sorted_iterators.begin(), sorted_iterators.end(), + CategoryMapIteratorSortCriterion); + + const size_t count = sorted_iterators.size(); + for (size_t i = 0; i < count; ++i) { + const auto timer = sorted_iterators[i]->second; + s->Printf("%.9f sec for %s\n", std::chrono::duration<double>(timer).count(), + sorted_iterators[i]->first); + } } diff --git a/source/Core/UUID.cpp b/source/Core/UUID.cpp index 88290d137943..a08a748821de 100644 --- a/source/Core/UUID.cpp +++ b/source/Core/UUID.cpp @@ -9,9 +9,9 @@ #include "lldb/Core/UUID.h" // C Includes -#include <string.h> -#include <stdio.h> #include <ctype.h> +#include <stdio.h> +#include <string.h> // C++ Includes #include <string> @@ -22,261 +22,203 @@ namespace lldb_private { -UUID::UUID() : m_num_uuid_bytes(16) -{ - ::memset (m_uuid, 0, sizeof(m_uuid)); -} +UUID::UUID() : m_num_uuid_bytes(16) { ::memset(m_uuid, 0, sizeof(m_uuid)); } -UUID::UUID(const UUID& rhs) -{ - m_num_uuid_bytes = rhs.m_num_uuid_bytes; - ::memcpy (m_uuid, rhs.m_uuid, sizeof (m_uuid)); +UUID::UUID(const UUID &rhs) { + m_num_uuid_bytes = rhs.m_num_uuid_bytes; + ::memcpy(m_uuid, rhs.m_uuid, sizeof(m_uuid)); } -UUID::UUID (const void *uuid_bytes, uint32_t num_uuid_bytes) -{ - SetBytes (uuid_bytes, num_uuid_bytes); +UUID::UUID(const void *uuid_bytes, uint32_t num_uuid_bytes) { + SetBytes(uuid_bytes, num_uuid_bytes); } -const UUID& -UUID::operator=(const UUID& rhs) -{ - if (this != &rhs) - { - m_num_uuid_bytes = rhs.m_num_uuid_bytes; - ::memcpy (m_uuid, rhs.m_uuid, sizeof (m_uuid)); +const UUID &UUID::operator=(const UUID &rhs) { + if (this != &rhs) { + m_num_uuid_bytes = rhs.m_num_uuid_bytes; + ::memcpy(m_uuid, rhs.m_uuid, sizeof(m_uuid)); + } + return *this; +} + +UUID::~UUID() {} + +void UUID::Clear() { + m_num_uuid_bytes = 16; + ::memset(m_uuid, 0, sizeof(m_uuid)); +} + +const void *UUID::GetBytes() const { return m_uuid; } + +std::string UUID::GetAsString(const char *separator) const { + std::string result; + char buf[256]; + if (!separator) + separator = "-"; + const uint8_t *u = (const uint8_t *)GetBytes(); + if (sizeof(buf) > + (size_t)snprintf(buf, sizeof(buf), "%2.2X%2.2X%2.2X%2.2X%s%2.2X%2.2X%s%2." + "2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%2.2X%" + "2.2X%2.2X%2.2X", + u[0], u[1], u[2], u[3], separator, u[4], u[5], separator, + u[6], u[7], separator, u[8], u[9], separator, u[10], + u[11], u[12], u[13], u[14], u[15])) { + result.append(buf); + if (m_num_uuid_bytes == 20) { + if (sizeof(buf) > (size_t)snprintf(buf, sizeof(buf), + "%s%2.2X%2.2X%2.2X%2.2X", separator, + u[16], u[17], u[18], u[19])) + result.append(buf); } - return *this; -} - -UUID::~UUID() -{ -} - -void -UUID::Clear() -{ - m_num_uuid_bytes = 16; - ::memset (m_uuid, 0, sizeof(m_uuid)); -} - -const void * -UUID::GetBytes() const -{ - return m_uuid; -} - -std::string -UUID::GetAsString (const char *separator) const -{ - std::string result; - char buf[256]; - if (!separator) - separator = "-"; - const uint8_t *u = (const uint8_t *)GetBytes(); - if (sizeof (buf) > (size_t)snprintf (buf, - sizeof (buf), - "%2.2X%2.2X%2.2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%s%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X", - u[0],u[1],u[2],u[3],separator, - u[4],u[5],separator, - u[6],u[7],separator, - u[8],u[9],separator, - u[10],u[11],u[12],u[13],u[14],u[15])) - { - result.append (buf); - if (m_num_uuid_bytes == 20) - { - if (sizeof (buf) > (size_t)snprintf (buf, sizeof (buf), "%s%2.2X%2.2X%2.2X%2.2X", separator,u[16],u[17],u[18],u[19])) - result.append (buf); - } + } + return result; +} + +void UUID::Dump(Stream *s) const { + const uint8_t *u = (const uint8_t *)GetBytes(); + s->Printf("%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%" + "2.2X%2.2X%2.2X%2.2X", + u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7], u[8], u[9], u[10], + u[11], u[12], u[13], u[14], u[15]); + if (m_num_uuid_bytes == 20) { + s->Printf("-%2.2X%2.2X%2.2X%2.2X", u[16], u[17], u[18], u[19]); + } +} + +bool UUID::SetBytes(const void *uuid_bytes, uint32_t num_uuid_bytes) { + if (uuid_bytes) { + switch (num_uuid_bytes) { + case 20: + m_num_uuid_bytes = 20; + break; + case 16: + m_num_uuid_bytes = 16; + m_uuid[16] = m_uuid[17] = m_uuid[18] = m_uuid[19] = 0; + break; + default: + // Unsupported UUID byte size + m_num_uuid_bytes = 0; + break; } - return result; -} -void -UUID::Dump (Stream *s) const -{ - const uint8_t *u = (const uint8_t *)GetBytes(); - s->Printf ("%2.2X%2.2X%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X-%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X", - u[0],u[1],u[2],u[3],u[4],u[5],u[6],u[7],u[8],u[9],u[10],u[11],u[12],u[13],u[14],u[15]); - if (m_num_uuid_bytes == 20) - { - s->Printf ("-%2.2X%2.2X%2.2X%2.2X", u[16],u[17],u[18],u[19]); + if (m_num_uuid_bytes > 0) { + ::memcpy(m_uuid, uuid_bytes, m_num_uuid_bytes); + return true; } -} - -bool -UUID::SetBytes (const void *uuid_bytes, uint32_t num_uuid_bytes) -{ - if (uuid_bytes) - { - switch (num_uuid_bytes) - { - case 20: - m_num_uuid_bytes = 20; - break; - case 16: - m_num_uuid_bytes = 16; - m_uuid[16] = m_uuid[17] = m_uuid[18] = m_uuid[19] = 0; - break; - default: - // Unsupported UUID byte size - m_num_uuid_bytes = 0; - break; - } - - if (m_num_uuid_bytes > 0) - { - ::memcpy (m_uuid, uuid_bytes, m_num_uuid_bytes); - return true; - } + } + ::memset(m_uuid, 0, sizeof(m_uuid)); + return false; +} + +size_t UUID::GetByteSize() { return m_num_uuid_bytes; } + +bool UUID::IsValid() const { + return m_uuid[0] || m_uuid[1] || m_uuid[2] || m_uuid[3] || m_uuid[4] || + m_uuid[5] || m_uuid[6] || m_uuid[7] || m_uuid[8] || m_uuid[9] || + m_uuid[10] || m_uuid[11] || m_uuid[12] || m_uuid[13] || m_uuid[14] || + m_uuid[15] || m_uuid[16] || m_uuid[17] || m_uuid[18] || m_uuid[19]; +} + +static inline int xdigit_to_int(char ch) { + ch = tolower(ch); + if (ch >= 'a' && ch <= 'f') + return 10 + ch - 'a'; + return ch - '0'; +} + +llvm::StringRef UUID::DecodeUUIDBytesFromString(llvm::StringRef p, + ValueType &uuid_bytes, + uint32_t &bytes_decoded, + uint32_t num_uuid_bytes) { + ::memset(uuid_bytes, 0, sizeof(uuid_bytes)); + size_t uuid_byte_idx = 0; + while (!p.empty()) { + if (isxdigit(p[0]) && isxdigit(p[1])) { + int hi_nibble = xdigit_to_int(p[0]); + int lo_nibble = xdigit_to_int(p[1]); + // Translate the two hex nibble characters into a byte + uuid_bytes[uuid_byte_idx] = (hi_nibble << 4) + lo_nibble; + + // Skip both hex digits + p = p.drop_front(2); + + // Increment the byte that we are decoding within the UUID value + // and break out if we are done + if (++uuid_byte_idx == num_uuid_bytes) + break; + } else if (p.front() == '-') { + // Skip dashes + p = p.drop_front(); + } else { + // UUID values can only consist of hex characters and '-' chars + break; } - ::memset (m_uuid, 0, sizeof(m_uuid)); - return false; -} + } -size_t -UUID::GetByteSize() -{ - return m_num_uuid_bytes; + // Clear trailing bytes to 0. + for (uint32_t i = uuid_byte_idx; i < sizeof(ValueType); i++) + uuid_bytes[i] = 0; + bytes_decoded = uuid_byte_idx; + return p; } +size_t UUID::SetFromCString(const char *cstr, uint32_t num_uuid_bytes) { + if (cstr == NULL) + return 0; -bool -UUID::IsValid () const -{ - return m_uuid[0] || - m_uuid[1] || - m_uuid[2] || - m_uuid[3] || - m_uuid[4] || - m_uuid[5] || - m_uuid[6] || - m_uuid[7] || - m_uuid[8] || - m_uuid[9] || - m_uuid[10] || - m_uuid[11] || - m_uuid[12] || - m_uuid[13] || - m_uuid[14] || - m_uuid[15] || - m_uuid[16] || - m_uuid[17] || - m_uuid[18] || - m_uuid[19]; -} + llvm::StringRef orig(cstr); + llvm::StringRef p = orig; -static inline int -xdigit_to_int (char ch) -{ - ch = tolower(ch); - if (ch >= 'a' && ch <= 'f') - return 10 + ch - 'a'; - return ch - '0'; -} + // Skip leading whitespace characters + p = p.ltrim(); -size_t -UUID::DecodeUUIDBytesFromCString (const char *p, ValueType &uuid_bytes, const char **end, uint32_t num_uuid_bytes) -{ - size_t uuid_byte_idx = 0; - if (p) - { - while (*p) - { - if (isxdigit(p[0]) && isxdigit(p[1])) - { - int hi_nibble = xdigit_to_int(p[0]); - int lo_nibble = xdigit_to_int(p[1]); - // Translate the two hex nibble characters into a byte - uuid_bytes[uuid_byte_idx] = (hi_nibble << 4) + lo_nibble; - - // Skip both hex digits - p += 2; - - // Increment the byte that we are decoding within the UUID value - // and break out if we are done - if (++uuid_byte_idx == num_uuid_bytes) - break; - } - else if (*p == '-') - { - // Skip dashes - p++; - } - else - { - // UUID values can only consist of hex characters and '-' chars - break; - } - } - } - if (end) - *end = p; - // Clear trailing bytes to 0. - for (uint32_t i = uuid_byte_idx; i < sizeof(ValueType); i++) - uuid_bytes[i] = 0; - return uuid_byte_idx; -} -size_t -UUID::SetFromCString (const char *cstr, uint32_t num_uuid_bytes) -{ - if (cstr == NULL) - return 0; - - const char *p = cstr; - - // Skip leading whitespace characters - while (isspace(*p)) - ++p; - - const size_t uuid_byte_idx = UUID::DecodeUUIDBytesFromCString (p, m_uuid, &p, num_uuid_bytes); - - // If we successfully decoded a UUID, return the amount of characters that - // were consumed - if (uuid_byte_idx == num_uuid_bytes) - { - m_num_uuid_bytes = num_uuid_bytes; - return p - cstr; - } + uint32_t bytes_decoded = 0; + llvm::StringRef rest = + UUID::DecodeUUIDBytesFromString(p, m_uuid, bytes_decoded, num_uuid_bytes); - // Else return zero to indicate we were not able to parse a UUID value - return 0; -} + // If we successfully decoded a UUID, return the amount of characters that + // were consumed + if (bytes_decoded == num_uuid_bytes) { + m_num_uuid_bytes = num_uuid_bytes; + return orig.size() - rest.size(); + } + // Else return zero to indicate we were not able to parse a UUID value + return 0; +} } -bool -lldb_private::operator == (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs) -{ - return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) == 0; +bool lldb_private::operator==(const lldb_private::UUID &lhs, + const lldb_private::UUID &rhs) { + return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), + sizeof(lldb_private::UUID::ValueType)) == 0; } -bool -lldb_private::operator != (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs) -{ - return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) != 0; +bool lldb_private::operator!=(const lldb_private::UUID &lhs, + const lldb_private::UUID &rhs) { + return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), + sizeof(lldb_private::UUID::ValueType)) != 0; } -bool -lldb_private::operator < (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs) -{ - return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) < 0; +bool lldb_private::operator<(const lldb_private::UUID &lhs, + const lldb_private::UUID &rhs) { + return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), + sizeof(lldb_private::UUID::ValueType)) < 0; } -bool -lldb_private::operator <= (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs) -{ - return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) <= 0; +bool lldb_private::operator<=(const lldb_private::UUID &lhs, + const lldb_private::UUID &rhs) { + return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), + sizeof(lldb_private::UUID::ValueType)) <= 0; } -bool -lldb_private::operator > (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs) -{ - return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) > 0; +bool lldb_private::operator>(const lldb_private::UUID &lhs, + const lldb_private::UUID &rhs) { + return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), + sizeof(lldb_private::UUID::ValueType)) > 0; } -bool -lldb_private::operator >= (const lldb_private::UUID &lhs, const lldb_private::UUID &rhs) -{ - return ::memcmp (lhs.GetBytes(), rhs.GetBytes(), sizeof (lldb_private::UUID::ValueType)) >= 0; +bool lldb_private::operator>=(const lldb_private::UUID &lhs, + const lldb_private::UUID &rhs) { + return ::memcmp(lhs.GetBytes(), rhs.GetBytes(), + sizeof(lldb_private::UUID::ValueType)) >= 0; } diff --git a/source/Core/UserID.cpp b/source/Core/UserID.cpp index f3d6e5b22185..5446154c1d27 100644 --- a/source/Core/UserID.cpp +++ b/source/Core/UserID.cpp @@ -15,9 +15,7 @@ using namespace lldb; using namespace lldb_private; -Stream& -lldb_private::operator << (Stream& strm, const UserID& uid) -{ - strm.Printf("{0x%8.8" PRIx64 "}", uid.GetID()); - return strm; +Stream &lldb_private::operator<<(Stream &strm, const UserID &uid) { + strm.Printf("{0x%8.8" PRIx64 "}", uid.GetID()); + return strm; } diff --git a/source/Core/UserSettingsController.cpp b/source/Core/UserSettingsController.cpp index 6313fa1eb13a..92c3c8440d15 100644 --- a/source/Core/UserSettingsController.cpp +++ b/source/Core/UserSettingsController.cpp @@ -1,4 +1,5 @@ -//====-- UserSettingsController.cpp ------------------------------*- C++ -*-===// +//====-- UserSettingsController.cpp ------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -7,14 +8,14 @@ // //===----------------------------------------------------------------------===// -#include <string.h> #include <algorithm> +#include <string.h> -#include "lldb/Core/UserSettingsController.h" #include "lldb/Core/Error.h" #include "lldb/Core/RegularExpression.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamString.h" +#include "lldb/Core/UserSettingsController.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/OptionValueProperties.h" #include "lldb/Interpreter/OptionValueString.h" @@ -22,113 +23,81 @@ using namespace lldb; using namespace lldb_private; - lldb::OptionValueSP -Properties::GetPropertyValue (const ExecutionContext *exe_ctx, - const char *path, - bool will_modify, - Error &error) const -{ - OptionValuePropertiesSP properties_sp (GetValueProperties ()); - if (properties_sp) - return properties_sp->GetSubValue(exe_ctx, path, will_modify, error); - return lldb::OptionValueSP(); +Properties::GetPropertyValue(const ExecutionContext *exe_ctx, llvm::StringRef path, + bool will_modify, Error &error) const { + OptionValuePropertiesSP properties_sp(GetValueProperties()); + if (properties_sp) + return properties_sp->GetSubValue(exe_ctx, path, will_modify, error); + return lldb::OptionValueSP(); } -Error -Properties::SetPropertyValue (const ExecutionContext *exe_ctx, - VarSetOperationType op, - const char *path, - const char *value) -{ - OptionValuePropertiesSP properties_sp (GetValueProperties ()); - if (properties_sp) - return properties_sp->SetSubValue(exe_ctx, op, path, value); - Error error; - error.SetErrorString ("no properties"); - return error; +Error Properties::SetPropertyValue(const ExecutionContext *exe_ctx, + VarSetOperationType op, llvm::StringRef path, + llvm::StringRef value) { + OptionValuePropertiesSP properties_sp(GetValueProperties()); + if (properties_sp) + return properties_sp->SetSubValue(exe_ctx, op, path, value); + Error error; + error.SetErrorString("no properties"); + return error; } -void -Properties::DumpAllPropertyValues (const ExecutionContext *exe_ctx, Stream &strm, uint32_t dump_mask) -{ - OptionValuePropertiesSP properties_sp (GetValueProperties ()); - if (properties_sp) - return properties_sp->DumpValue (exe_ctx, strm, dump_mask); +void Properties::DumpAllPropertyValues(const ExecutionContext *exe_ctx, + Stream &strm, uint32_t dump_mask) { + OptionValuePropertiesSP properties_sp(GetValueProperties()); + if (properties_sp) + return properties_sp->DumpValue(exe_ctx, strm, dump_mask); } -void -Properties::DumpAllDescriptions (CommandInterpreter &interpreter, - Stream &strm) const -{ - strm.PutCString("Top level variables:\n\n"); +void Properties::DumpAllDescriptions(CommandInterpreter &interpreter, + Stream &strm) const { + strm.PutCString("Top level variables:\n\n"); - OptionValuePropertiesSP properties_sp (GetValueProperties ()); - if (properties_sp) - return properties_sp->DumpAllDescriptions (interpreter, strm); + OptionValuePropertiesSP properties_sp(GetValueProperties()); + if (properties_sp) + return properties_sp->DumpAllDescriptions(interpreter, strm); } - - -Error -Properties::DumpPropertyValue (const ExecutionContext *exe_ctx, Stream &strm, const char *property_path, uint32_t dump_mask) -{ - OptionValuePropertiesSP properties_sp (GetValueProperties ()); - if (properties_sp) - { - return properties_sp->DumpPropertyValue (exe_ctx, - strm, - property_path, - dump_mask); - } - Error error; - error.SetErrorString("empty property list"); - return error; +Error Properties::DumpPropertyValue(const ExecutionContext *exe_ctx, + Stream &strm, llvm::StringRef property_path, + uint32_t dump_mask) { + OptionValuePropertiesSP properties_sp(GetValueProperties()); + if (properties_sp) { + return properties_sp->DumpPropertyValue(exe_ctx, strm, property_path, + dump_mask); + } + Error error; + error.SetErrorString("empty property list"); + return error; } size_t -Properties::Apropos (const char *keyword, std::vector<const Property *> &matching_properties) const -{ - OptionValuePropertiesSP properties_sp (GetValueProperties ()); - if (properties_sp) - { - properties_sp->Apropos (keyword, matching_properties); - } - return matching_properties.size(); +Properties::Apropos(llvm::StringRef keyword, + std::vector<const Property *> &matching_properties) const { + OptionValuePropertiesSP properties_sp(GetValueProperties()); + if (properties_sp) { + properties_sp->Apropos(keyword, matching_properties); + } + return matching_properties.size(); } - lldb::OptionValuePropertiesSP -Properties::GetSubProperty (const ExecutionContext *exe_ctx, - const ConstString &name) -{ - OptionValuePropertiesSP properties_sp (GetValueProperties ()); - if (properties_sp) - return properties_sp->GetSubProperty (exe_ctx, name); - return lldb::OptionValuePropertiesSP(); +Properties::GetSubProperty(const ExecutionContext *exe_ctx, + const ConstString &name) { + OptionValuePropertiesSP properties_sp(GetValueProperties()); + if (properties_sp) + return properties_sp->GetSubProperty(exe_ctx, name); + return lldb::OptionValuePropertiesSP(); } -const char * -Properties::GetExperimentalSettingsName() -{ - return "experimental"; -} +const char *Properties::GetExperimentalSettingsName() { return "experimental"; } -bool -Properties::IsSettingExperimental(const char *setting) -{ - if (setting == nullptr) - return false; - - const char *experimental = GetExperimentalSettingsName(); - const char *dot_pos = strchr(setting, '.'); - if (dot_pos == nullptr) - return strcmp(experimental, setting) == 0; - else - { - size_t first_elem_len = dot_pos - setting; - return strncmp(experimental, setting, first_elem_len) == 0; - } +bool Properties::IsSettingExperimental(llvm::StringRef setting) { + if (setting.empty()) + return false; + llvm::StringRef experimental = GetExperimentalSettingsName(); + size_t dot_pos = setting.find_first_of('.'); + return setting.take_front(dot_pos) == experimental; } - diff --git a/source/Core/VMRange.cpp b/source/Core/VMRange.cpp index 902489e1ff38..8d21f4b1273c 100644 --- a/source/Core/VMRange.cpp +++ b/source/Core/VMRange.cpp @@ -16,97 +16,82 @@ using namespace lldb; using namespace lldb_private; -bool -VMRange::ContainsValue(const VMRange::collection& coll, lldb::addr_t value) -{ - ValueInRangeUnaryPredicate in_range_predicate(value); - VMRange::const_iterator pos; - VMRange::const_iterator end = coll.end(); - pos = std::find_if( coll.begin(), end, in_range_predicate ); - if (pos != end) - return true; - return false; +bool VMRange::ContainsValue(const VMRange::collection &coll, + lldb::addr_t value) { + ValueInRangeUnaryPredicate in_range_predicate(value); + VMRange::const_iterator pos; + VMRange::const_iterator end = coll.end(); + pos = std::find_if(coll.begin(), end, in_range_predicate); + if (pos != end) + return true; + return false; } -bool -VMRange::ContainsRange(const VMRange::collection& coll, const VMRange& range) -{ - RangeInRangeUnaryPredicate in_range_predicate(range); - VMRange::const_iterator pos; - VMRange::const_iterator end = coll.end(); - pos = std::find_if( coll.begin(), end, in_range_predicate ); - if (pos != end) - return true; - return false; +bool VMRange::ContainsRange(const VMRange::collection &coll, + const VMRange &range) { + RangeInRangeUnaryPredicate in_range_predicate(range); + VMRange::const_iterator pos; + VMRange::const_iterator end = coll.end(); + pos = std::find_if(coll.begin(), end, in_range_predicate); + if (pos != end) + return true; + return false; } -size_t -VMRange::FindRangeIndexThatContainsValue (const VMRange::collection& coll, lldb::addr_t value) -{ - ValueInRangeUnaryPredicate in_range_predicate(value); - VMRange::const_iterator begin = coll.begin(); - VMRange::const_iterator end = coll.end(); - VMRange::const_iterator pos = std::find_if (begin, end, in_range_predicate); - if (pos != end) - return std::distance (begin, pos); - return UINT32_MAX; +size_t VMRange::FindRangeIndexThatContainsValue(const VMRange::collection &coll, + lldb::addr_t value) { + ValueInRangeUnaryPredicate in_range_predicate(value); + VMRange::const_iterator begin = coll.begin(); + VMRange::const_iterator end = coll.end(); + VMRange::const_iterator pos = std::find_if(begin, end, in_range_predicate); + if (pos != end) + return std::distance(begin, pos); + return UINT32_MAX; } -void -VMRange::Dump(Stream *s, lldb::addr_t offset, uint32_t addr_width) const -{ - s->AddressRange(offset + GetBaseAddress(), offset + GetEndAddress(), addr_width); +void VMRange::Dump(Stream *s, lldb::addr_t offset, uint32_t addr_width) const { + s->AddressRange(offset + GetBaseAddress(), offset + GetEndAddress(), + addr_width); } -bool -lldb_private::operator== (const VMRange& lhs, const VMRange& rhs) -{ - return lhs.GetBaseAddress() == rhs.GetBaseAddress() && lhs.GetEndAddress() == rhs.GetEndAddress(); +bool lldb_private::operator==(const VMRange &lhs, const VMRange &rhs) { + return lhs.GetBaseAddress() == rhs.GetBaseAddress() && + lhs.GetEndAddress() == rhs.GetEndAddress(); } -bool -lldb_private::operator!= (const VMRange& lhs, const VMRange& rhs) -{ - return lhs.GetBaseAddress() != rhs.GetBaseAddress() || lhs.GetEndAddress() != rhs.GetEndAddress(); +bool lldb_private::operator!=(const VMRange &lhs, const VMRange &rhs) { + return lhs.GetBaseAddress() != rhs.GetBaseAddress() || + lhs.GetEndAddress() != rhs.GetEndAddress(); } -bool -lldb_private::operator< (const VMRange& lhs, const VMRange& rhs) -{ - if (lhs.GetBaseAddress() < rhs.GetBaseAddress()) - return true; - else if (lhs.GetBaseAddress() > rhs.GetBaseAddress()) - return false; - return lhs.GetEndAddress() < rhs.GetEndAddress(); +bool lldb_private::operator<(const VMRange &lhs, const VMRange &rhs) { + if (lhs.GetBaseAddress() < rhs.GetBaseAddress()) + return true; + else if (lhs.GetBaseAddress() > rhs.GetBaseAddress()) + return false; + return lhs.GetEndAddress() < rhs.GetEndAddress(); } -bool -lldb_private::operator<= (const VMRange& lhs, const VMRange& rhs) -{ - if (lhs.GetBaseAddress() < rhs.GetBaseAddress()) - return true; - else if (lhs.GetBaseAddress() > rhs.GetBaseAddress()) - return false; - return lhs.GetEndAddress() <= rhs.GetEndAddress(); +bool lldb_private::operator<=(const VMRange &lhs, const VMRange &rhs) { + if (lhs.GetBaseAddress() < rhs.GetBaseAddress()) + return true; + else if (lhs.GetBaseAddress() > rhs.GetBaseAddress()) + return false; + return lhs.GetEndAddress() <= rhs.GetEndAddress(); } -bool -lldb_private::operator> (const VMRange& lhs, const VMRange& rhs) -{ - if (lhs.GetBaseAddress() > rhs.GetBaseAddress()) - return true; - else if (lhs.GetBaseAddress() < rhs.GetBaseAddress()) - return false; - return lhs.GetEndAddress() > rhs.GetEndAddress(); +bool lldb_private::operator>(const VMRange &lhs, const VMRange &rhs) { + if (lhs.GetBaseAddress() > rhs.GetBaseAddress()) + return true; + else if (lhs.GetBaseAddress() < rhs.GetBaseAddress()) + return false; + return lhs.GetEndAddress() > rhs.GetEndAddress(); } -bool -lldb_private::operator>= (const VMRange& lhs, const VMRange& rhs) -{ - if (lhs.GetBaseAddress() > rhs.GetBaseAddress()) - return true; - else if (lhs.GetBaseAddress() < rhs.GetBaseAddress()) - return false; - return lhs.GetEndAddress() >= rhs.GetEndAddress(); +bool lldb_private::operator>=(const VMRange &lhs, const VMRange &rhs) { + if (lhs.GetBaseAddress() > rhs.GetBaseAddress()) + return true; + else if (lhs.GetBaseAddress() < rhs.GetBaseAddress()) + return false; + return lhs.GetEndAddress() >= rhs.GetEndAddress(); } - diff --git a/source/Core/Value.cpp b/source/Core/Value.cpp index eb250eb77e46..a480c3cf375a 100644 --- a/source/Core/Value.cpp +++ b/source/Core/Value.cpp @@ -13,13 +13,13 @@ // C++ Includes // Other libraries and framework includes // Project includes -#include "lldb/Core/DataExtractor.h" #include "lldb/Core/DataBufferHeap.h" +#include "lldb/Core/DataExtractor.h" #include "lldb/Core/Module.h" #include "lldb/Core/State.h" #include "lldb/Core/Stream.h" -#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Type.h" @@ -32,828 +32,675 @@ using namespace lldb; using namespace lldb_private; -Value::Value() : - m_value (), - m_vector (), - m_compiler_type (), - m_context (NULL), - m_value_type (eValueTypeScalar), - m_context_type (eContextTypeInvalid), - m_data_buffer () -{ -} +Value::Value() + : m_value(), m_vector(), m_compiler_type(), m_context(NULL), + m_value_type(eValueTypeScalar), m_context_type(eContextTypeInvalid), + m_data_buffer() {} + +Value::Value(const Scalar &scalar) + : m_value(scalar), m_vector(), m_compiler_type(), m_context(NULL), + m_value_type(eValueTypeScalar), m_context_type(eContextTypeInvalid), + m_data_buffer() {} + +Value::Value(const void *bytes, int len) + : m_value(), m_vector(), m_compiler_type(), m_context(NULL), + m_value_type(eValueTypeHostAddress), m_context_type(eContextTypeInvalid), + m_data_buffer() { + SetBytes(bytes, len); +} + +Value::Value(const Value &v) + : m_value(v.m_value), m_vector(v.m_vector), + m_compiler_type(v.m_compiler_type), m_context(v.m_context), + m_value_type(v.m_value_type), m_context_type(v.m_context_type), + m_data_buffer() { + const uintptr_t rhs_value = + (uintptr_t)v.m_value.ULongLong(LLDB_INVALID_ADDRESS); + if ((rhs_value != 0) && + (rhs_value == (uintptr_t)v.m_data_buffer.GetBytes())) { + m_data_buffer.CopyData(v.m_data_buffer.GetBytes(), + v.m_data_buffer.GetByteSize()); -Value::Value(const Scalar& scalar) : - m_value (scalar), - m_vector (), - m_compiler_type (), - m_context (NULL), - m_value_type (eValueTypeScalar), - m_context_type (eContextTypeInvalid), - m_data_buffer () -{ -} - - -Value::Value(const void *bytes, int len) : - m_value (), - m_vector (), - m_compiler_type (), - m_context (NULL), - m_value_type (eValueTypeHostAddress), - m_context_type (eContextTypeInvalid), - m_data_buffer () -{ - SetBytes(bytes, len); -} - -Value::Value(const Value &v) : - m_value (v.m_value), - m_vector (v.m_vector), - m_compiler_type (v.m_compiler_type), - m_context (v.m_context), - m_value_type (v.m_value_type), - m_context_type (v.m_context_type), - m_data_buffer () -{ - const uintptr_t rhs_value = (uintptr_t)v.m_value.ULongLong(LLDB_INVALID_ADDRESS); - if ((rhs_value != 0) && (rhs_value == (uintptr_t)v.m_data_buffer.GetBytes())) - { - m_data_buffer.CopyData(v.m_data_buffer.GetBytes(), - v.m_data_buffer.GetByteSize()); - - m_value = (uintptr_t)m_data_buffer.GetBytes(); + m_value = (uintptr_t)m_data_buffer.GetBytes(); + } +} + +Value &Value::operator=(const Value &rhs) { + if (this != &rhs) { + m_value = rhs.m_value; + m_vector = rhs.m_vector; + m_compiler_type = rhs.m_compiler_type; + m_context = rhs.m_context; + m_value_type = rhs.m_value_type; + m_context_type = rhs.m_context_type; + const uintptr_t rhs_value = + (uintptr_t)rhs.m_value.ULongLong(LLDB_INVALID_ADDRESS); + if ((rhs_value != 0) && + (rhs_value == (uintptr_t)rhs.m_data_buffer.GetBytes())) { + m_data_buffer.CopyData(rhs.m_data_buffer.GetBytes(), + rhs.m_data_buffer.GetByteSize()); + + m_value = (uintptr_t)m_data_buffer.GetBytes(); } -} - -Value & -Value::operator=(const Value &rhs) -{ - if (this != &rhs) - { - m_value = rhs.m_value; - m_vector = rhs.m_vector; - m_compiler_type = rhs.m_compiler_type; - m_context = rhs.m_context; - m_value_type = rhs.m_value_type; - m_context_type = rhs.m_context_type; - const uintptr_t rhs_value = (uintptr_t)rhs.m_value.ULongLong(LLDB_INVALID_ADDRESS); - if ((rhs_value != 0) && (rhs_value == (uintptr_t)rhs.m_data_buffer.GetBytes())) - { - m_data_buffer.CopyData(rhs.m_data_buffer.GetBytes(), - rhs.m_data_buffer.GetByteSize()); - - m_value = (uintptr_t)m_data_buffer.GetBytes(); - } + } + return *this; +} + +void Value::SetBytes(const void *bytes, int len) { + m_value_type = eValueTypeHostAddress; + m_data_buffer.CopyData(bytes, len); + m_value = (uintptr_t)m_data_buffer.GetBytes(); +} + +void Value::AppendBytes(const void *bytes, int len) { + m_value_type = eValueTypeHostAddress; + m_data_buffer.AppendData(bytes, len); + m_value = (uintptr_t)m_data_buffer.GetBytes(); +} + +void Value::Dump(Stream *strm) { + m_value.GetValue(strm, true); + strm->Printf(", value_type = %s, context = %p, context_type = %s", + Value::GetValueTypeAsCString(m_value_type), m_context, + Value::GetContextTypeAsCString(m_context_type)); +} + +Value::ValueType Value::GetValueType() const { return m_value_type; } + +AddressType Value::GetValueAddressType() const { + switch (m_value_type) { + default: + case eValueTypeScalar: + break; + case eValueTypeLoadAddress: + return eAddressTypeLoad; + case eValueTypeFileAddress: + return eAddressTypeFile; + case eValueTypeHostAddress: + return eAddressTypeHost; + } + return eAddressTypeInvalid; +} + +RegisterInfo *Value::GetRegisterInfo() const { + if (m_context_type == eContextTypeRegisterInfo) + return static_cast<RegisterInfo *>(m_context); + return NULL; +} + +Type *Value::GetType() { + if (m_context_type == eContextTypeLLDBType) + return static_cast<Type *>(m_context); + return NULL; +} + +size_t Value::AppendDataToHostBuffer(const Value &rhs) { + size_t curr_size = m_data_buffer.GetByteSize(); + Error error; + switch (rhs.GetValueType()) { + case eValueTypeScalar: { + const size_t scalar_size = rhs.m_value.GetByteSize(); + if (scalar_size > 0) { + const size_t new_size = curr_size + scalar_size; + if (ResizeData(new_size) == new_size) { + rhs.m_value.GetAsMemoryData(m_data_buffer.GetBytes() + curr_size, + scalar_size, endian::InlHostByteOrder(), + error); + return scalar_size; + } } - return *this; -} - -void -Value::SetBytes (const void *bytes, int len) -{ - m_value_type = eValueTypeHostAddress; - m_data_buffer.CopyData(bytes, len); - m_value = (uintptr_t)m_data_buffer.GetBytes(); -} - -void -Value::AppendBytes (const void *bytes, int len) -{ - m_value_type = eValueTypeHostAddress; - m_data_buffer.AppendData (bytes, len); - m_value = (uintptr_t)m_data_buffer.GetBytes(); -} - -void -Value::Dump (Stream* strm) -{ - m_value.GetValue (strm, true); - strm->Printf(", value_type = %s, context = %p, context_type = %s", - Value::GetValueTypeAsCString(m_value_type), - m_context, - Value::GetContextTypeAsCString(m_context_type)); -} - -Value::ValueType -Value::GetValueType() const -{ - return m_value_type; -} - -AddressType -Value::GetValueAddressType () const -{ - switch (m_value_type) - { - default: - case eValueTypeScalar: - break; - case eValueTypeLoadAddress: return eAddressTypeLoad; - case eValueTypeFileAddress: return eAddressTypeFile; - case eValueTypeHostAddress: return eAddressTypeHost; + } break; + case eValueTypeVector: { + const size_t vector_size = rhs.m_vector.length; + if (vector_size > 0) { + const size_t new_size = curr_size + vector_size; + if (ResizeData(new_size) == new_size) { + ::memcpy(m_data_buffer.GetBytes() + curr_size, rhs.m_vector.bytes, + vector_size); + return vector_size; + } + } + } break; + case eValueTypeFileAddress: + case eValueTypeLoadAddress: + case eValueTypeHostAddress: { + const uint8_t *src = rhs.GetBuffer().GetBytes(); + const size_t src_len = rhs.GetBuffer().GetByteSize(); + if (src && src_len > 0) { + const size_t new_size = curr_size + src_len; + if (ResizeData(new_size) == new_size) { + ::memcpy(m_data_buffer.GetBytes() + curr_size, src, src_len); + return src_len; + } } - return eAddressTypeInvalid; + } break; + } + return 0; } -RegisterInfo * -Value::GetRegisterInfo() const -{ - if (m_context_type == eContextTypeRegisterInfo) - return static_cast<RegisterInfo *> (m_context); - return NULL; +size_t Value::ResizeData(size_t len) { + m_value_type = eValueTypeHostAddress; + m_data_buffer.SetByteSize(len); + m_value = (uintptr_t)m_data_buffer.GetBytes(); + return m_data_buffer.GetByteSize(); } -Type * -Value::GetType() -{ - if (m_context_type == eContextTypeLLDBType) - return static_cast<Type *> (m_context); - return NULL; -} +bool Value::ValueOf(ExecutionContext *exe_ctx) { + switch (m_context_type) { + case eContextTypeInvalid: + case eContextTypeRegisterInfo: // RegisterInfo * + case eContextTypeLLDBType: // Type * + break; -size_t -Value::AppendDataToHostBuffer (const Value &rhs) -{ - size_t curr_size = m_data_buffer.GetByteSize(); - Error error; - switch (rhs.GetValueType()) - { - case eValueTypeScalar: - { - const size_t scalar_size = rhs.m_value.GetByteSize(); - if (scalar_size > 0) - { - const size_t new_size = curr_size + scalar_size; - if (ResizeData(new_size) == new_size) - { - rhs.m_value.GetAsMemoryData (m_data_buffer.GetBytes() + curr_size, - scalar_size, - endian::InlHostByteOrder(), - error); - return scalar_size; - } - } - } - break; - case eValueTypeVector: - { - const size_t vector_size = rhs.m_vector.length; - if (vector_size > 0) - { - const size_t new_size = curr_size + vector_size; - if (ResizeData(new_size) == new_size) - { - ::memcpy (m_data_buffer.GetBytes() + curr_size, - rhs.m_vector.bytes, - vector_size); - return vector_size; - } - } - } - break; - case eValueTypeFileAddress: - case eValueTypeLoadAddress: - case eValueTypeHostAddress: - { - const uint8_t *src = rhs.GetBuffer().GetBytes(); - const size_t src_len = rhs.GetBuffer().GetByteSize(); - if (src && src_len > 0) - { - const size_t new_size = curr_size + src_len; - if (ResizeData(new_size) == new_size) - { - ::memcpy (m_data_buffer.GetBytes() + curr_size, src, src_len); - return src_len; - } - } - } - break; - } - return 0; + case eContextTypeVariable: // Variable * + ResolveValue(exe_ctx); + return true; + } + return false; } -size_t -Value::ResizeData(size_t len) -{ - m_value_type = eValueTypeHostAddress; - m_data_buffer.SetByteSize(len); - m_value = (uintptr_t)m_data_buffer.GetBytes(); - return m_data_buffer.GetByteSize(); -} +uint64_t Value::GetValueByteSize(Error *error_ptr, ExecutionContext *exe_ctx) { + uint64_t byte_size = 0; -bool -Value::ValueOf(ExecutionContext *exe_ctx) -{ - switch (m_context_type) - { - case eContextTypeInvalid: - case eContextTypeRegisterInfo: // RegisterInfo * - case eContextTypeLLDBType: // Type * - break; + switch (m_context_type) { + case eContextTypeRegisterInfo: // RegisterInfo * + if (GetRegisterInfo()) + byte_size = GetRegisterInfo()->byte_size; + break; - case eContextTypeVariable: // Variable * - ResolveValue(exe_ctx); - return true; + case eContextTypeInvalid: + case eContextTypeLLDBType: // Type * + case eContextTypeVariable: // Variable * + { + const CompilerType &ast_type = GetCompilerType(); + if (ast_type.IsValid()) + byte_size = ast_type.GetByteSize( + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); + } break; + } + + if (error_ptr) { + if (byte_size == 0) { + if (error_ptr->Success()) + error_ptr->SetErrorString("Unable to determine byte size."); + } else { + error_ptr->Clear(); } - return false; + } + return byte_size; } -uint64_t -Value::GetValueByteSize (Error *error_ptr, ExecutionContext *exe_ctx) -{ - uint64_t byte_size = 0; - - switch (m_context_type) - { - case eContextTypeRegisterInfo: // RegisterInfo * - if (GetRegisterInfo()) - byte_size = GetRegisterInfo()->byte_size; - break; - +const CompilerType &Value::GetCompilerType() { + if (!m_compiler_type.IsValid()) { + switch (m_context_type) { case eContextTypeInvalid: - case eContextTypeLLDBType: // Type * - case eContextTypeVariable: // Variable * - { - const CompilerType &ast_type = GetCompilerType(); - if (ast_type.IsValid()) - byte_size = ast_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); - } - break; - } + break; - if (error_ptr) - { - if (byte_size == 0) - { - if (error_ptr->Success()) - error_ptr->SetErrorString("Unable to determine byte size."); - } - else - { - error_ptr->Clear(); - } - } - return byte_size; -} - -const CompilerType & -Value::GetCompilerType () -{ - if (!m_compiler_type.IsValid()) - { - switch (m_context_type) - { - case eContextTypeInvalid: - break; - - case eContextTypeRegisterInfo: - break; // TODO: Eventually convert into a compiler type? - - case eContextTypeLLDBType: - { - Type *lldb_type = GetType(); - if (lldb_type) - m_compiler_type = lldb_type->GetForwardCompilerType (); - } - break; - - case eContextTypeVariable: - { - Variable *variable = GetVariable(); - if (variable) - { - Type *variable_type = variable->GetType(); - if (variable_type) - m_compiler_type = variable_type->GetForwardCompilerType (); - } - } - break; - } + case eContextTypeRegisterInfo: + break; // TODO: Eventually convert into a compiler type? + + case eContextTypeLLDBType: { + Type *lldb_type = GetType(); + if (lldb_type) + m_compiler_type = lldb_type->GetForwardCompilerType(); + } break; + + case eContextTypeVariable: { + Variable *variable = GetVariable(); + if (variable) { + Type *variable_type = variable->GetType(); + if (variable_type) + m_compiler_type = variable_type->GetForwardCompilerType(); + } + } break; } + } - return m_compiler_type; + return m_compiler_type; } -void -Value::SetCompilerType (const CompilerType &compiler_type) -{ - m_compiler_type = compiler_type; +void Value::SetCompilerType(const CompilerType &compiler_type) { + m_compiler_type = compiler_type; } -lldb::Format -Value::GetValueDefaultFormat () -{ - switch (m_context_type) - { - case eContextTypeRegisterInfo: - if (GetRegisterInfo()) - return GetRegisterInfo()->format; - break; - - case eContextTypeInvalid: - case eContextTypeLLDBType: - case eContextTypeVariable: - { - const CompilerType &ast_type = GetCompilerType(); - if (ast_type.IsValid()) - return ast_type.GetFormat(); - } - break; +lldb::Format Value::GetValueDefaultFormat() { + switch (m_context_type) { + case eContextTypeRegisterInfo: + if (GetRegisterInfo()) + return GetRegisterInfo()->format; + break; + case eContextTypeInvalid: + case eContextTypeLLDBType: + case eContextTypeVariable: { + const CompilerType &ast_type = GetCompilerType(); + if (ast_type.IsValid()) + return ast_type.GetFormat(); + } break; + } + + // Return a good default in case we can't figure anything out + return eFormatHex; +} + +bool Value::GetData(DataExtractor &data) { + switch (m_value_type) { + default: + break; + + case eValueTypeScalar: + if (m_value.GetData(data)) + return true; + break; + + case eValueTypeLoadAddress: + case eValueTypeFileAddress: + case eValueTypeHostAddress: + if (m_data_buffer.GetByteSize()) { + data.SetData(m_data_buffer.GetBytes(), m_data_buffer.GetByteSize(), + data.GetByteOrder()); + return true; } + break; + } - // Return a good default in case we can't figure anything out - return eFormatHex; + return false; } -bool -Value::GetData (DataExtractor &data) -{ - switch (m_value_type) - { - default: - break; - - case eValueTypeScalar: - if (m_value.GetData (data)) - return true; - break; +Error Value::GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, + uint32_t data_offset, Module *module) { + data.Clear(); - case eValueTypeLoadAddress: - case eValueTypeFileAddress: - case eValueTypeHostAddress: - if (m_data_buffer.GetByteSize()) - { - data.SetData(m_data_buffer.GetBytes(), m_data_buffer.GetByteSize(), data.GetByteOrder()); - return true; - } - break; - } + Error error; + lldb::addr_t address = LLDB_INVALID_ADDRESS; + AddressType address_type = eAddressTypeFile; + Address file_so_addr; + const CompilerType &ast_type = GetCompilerType(); + switch (m_value_type) { + case eValueTypeVector: + if (ast_type.IsValid()) + data.SetAddressByteSize(ast_type.GetPointerByteSize()); + else + data.SetAddressByteSize(sizeof(void *)); + data.SetData(m_vector.bytes, m_vector.length, m_vector.byte_order); + break; + + case eValueTypeScalar: { + data.SetByteOrder(endian::InlHostByteOrder()); + if (ast_type.IsValid()) + data.SetAddressByteSize(ast_type.GetPointerByteSize()); + else + data.SetAddressByteSize(sizeof(void *)); - return false; + uint32_t limit_byte_size = UINT32_MAX; -} + if (ast_type.IsValid()) { + limit_byte_size = ast_type.GetByteSize( + exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); + } -Error -Value::GetValueAsData (ExecutionContext *exe_ctx, - DataExtractor &data, - uint32_t data_offset, - Module *module) -{ - data.Clear(); - - Error error; - lldb::addr_t address = LLDB_INVALID_ADDRESS; - AddressType address_type = eAddressTypeFile; - Address file_so_addr; - const CompilerType &ast_type = GetCompilerType(); - switch (m_value_type) - { - case eValueTypeVector: - if (ast_type.IsValid()) - data.SetAddressByteSize (ast_type.GetPointerByteSize()); - else - data.SetAddressByteSize(sizeof(void *)); - data.SetData(m_vector.bytes, m_vector.length, m_vector.byte_order); - break; + if (limit_byte_size <= m_value.GetByteSize()) { + if (m_value.GetData(data, limit_byte_size)) + return error; // Success; + } - case eValueTypeScalar: - { - data.SetByteOrder (endian::InlHostByteOrder()); - if (ast_type.IsValid()) - data.SetAddressByteSize (ast_type.GetPointerByteSize()); - else - data.SetAddressByteSize(sizeof(void *)); - - uint32_t limit_byte_size = UINT32_MAX; - - if (ast_type.IsValid()) - { - limit_byte_size = ast_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); - } - - if (limit_byte_size <= m_value.GetByteSize()) - { - if (m_value.GetData (data, limit_byte_size)) - return error; // Success; - } - - error.SetErrorStringWithFormat("extracting data from value failed"); - break; - } - case eValueTypeLoadAddress: - if (exe_ctx == NULL) - { - error.SetErrorString ("can't read load address (no execution context)"); + error.SetErrorStringWithFormat("extracting data from value failed"); + break; + } + case eValueTypeLoadAddress: + if (exe_ctx == NULL) { + error.SetErrorString("can't read load address (no execution context)"); + } else { + Process *process = exe_ctx->GetProcessPtr(); + if (process == NULL || !process->IsAlive()) { + Target *target = exe_ctx->GetTargetPtr(); + if (target) { + // Allow expressions to run and evaluate things when the target + // has memory sections loaded. This allows you to use "target modules + // load" + // to load your executable and any shared libraries, then execute + // commands where you can look at types in data sections. + const SectionLoadList &target_sections = target->GetSectionLoadList(); + if (!target_sections.IsEmpty()) { + address = m_value.ULongLong(LLDB_INVALID_ADDRESS); + if (target_sections.ResolveLoadAddress(address, file_so_addr)) { + address_type = eAddressTypeLoad; + data.SetByteOrder(target->GetArchitecture().GetByteOrder()); + data.SetAddressByteSize( + target->GetArchitecture().GetAddressByteSize()); + } else + address = LLDB_INVALID_ADDRESS; + } + // else + // { + // ModuleSP exe_module_sp + // (target->GetExecutableModule()); + // if (exe_module_sp) + // { + // address = + // m_value.ULongLong(LLDB_INVALID_ADDRESS); + // if (address != LLDB_INVALID_ADDRESS) + // { + // if + // (exe_module_sp->ResolveFileAddress(address, + // file_so_addr)) + // { + // data.SetByteOrder(target->GetArchitecture().GetByteOrder()); + // data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); + // address_type = eAddressTypeFile; + // } + // else + // { + // address = LLDB_INVALID_ADDRESS; + // } + // } + // } + // } + } else { + error.SetErrorString("can't read load address (invalid process)"); } - else - { - Process *process = exe_ctx->GetProcessPtr(); - if (process == NULL || !process->IsAlive()) - { - Target *target = exe_ctx->GetTargetPtr(); - if (target) - { - // Allow expressions to run and evaluate things when the target - // has memory sections loaded. This allows you to use "target modules load" - // to load your executable and any shared libraries, then execute - // commands where you can look at types in data sections. - const SectionLoadList &target_sections = target->GetSectionLoadList(); - if (!target_sections.IsEmpty()) - { - address = m_value.ULongLong(LLDB_INVALID_ADDRESS); - if (target_sections.ResolveLoadAddress(address, file_so_addr)) - { - address_type = eAddressTypeLoad; - data.SetByteOrder(target->GetArchitecture().GetByteOrder()); - data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); - } - else - address = LLDB_INVALID_ADDRESS; - } -// else -// { -// ModuleSP exe_module_sp (target->GetExecutableModule()); -// if (exe_module_sp) -// { -// address = m_value.ULongLong(LLDB_INVALID_ADDRESS); -// if (address != LLDB_INVALID_ADDRESS) -// { -// if (exe_module_sp->ResolveFileAddress(address, file_so_addr)) -// { -// data.SetByteOrder(target->GetArchitecture().GetByteOrder()); -// data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); -// address_type = eAddressTypeFile; -// } -// else -// { -// address = LLDB_INVALID_ADDRESS; -// } -// } -// } -// } - } - else - { - error.SetErrorString ("can't read load address (invalid process)"); - } - } - else - { - address = m_value.ULongLong(LLDB_INVALID_ADDRESS); - address_type = eAddressTypeLoad; - data.SetByteOrder(process->GetTarget().GetArchitecture().GetByteOrder()); - data.SetAddressByteSize(process->GetTarget().GetArchitecture().GetAddressByteSize()); - } + } else { + address = m_value.ULongLong(LLDB_INVALID_ADDRESS); + address_type = eAddressTypeLoad; + data.SetByteOrder( + process->GetTarget().GetArchitecture().GetByteOrder()); + data.SetAddressByteSize( + process->GetTarget().GetArchitecture().GetAddressByteSize()); + } + } + break; + + case eValueTypeFileAddress: + if (exe_ctx == NULL) { + error.SetErrorString("can't read file address (no execution context)"); + } else if (exe_ctx->GetTargetPtr() == NULL) { + error.SetErrorString("can't read file address (invalid target)"); + } else { + address = m_value.ULongLong(LLDB_INVALID_ADDRESS); + if (address == LLDB_INVALID_ADDRESS) { + error.SetErrorString("invalid file address"); + } else { + if (module == NULL) { + // The only thing we can currently lock down to a module so that + // we can resolve a file address, is a variable. + Variable *variable = GetVariable(); + if (variable) { + SymbolContext var_sc; + variable->CalculateSymbolContext(&var_sc); + module = var_sc.module_sp.get(); + } } - break; - case eValueTypeFileAddress: - if (exe_ctx == NULL) - { - error.SetErrorString ("can't read file address (no execution context)"); - } - else if (exe_ctx->GetTargetPtr() == NULL) - { - error.SetErrorString ("can't read file address (invalid target)"); - } - else - { - address = m_value.ULongLong(LLDB_INVALID_ADDRESS); - if (address == LLDB_INVALID_ADDRESS) - { - error.SetErrorString ("invalid file address"); + if (module) { + bool resolved = false; + ObjectFile *objfile = module->GetObjectFile(); + if (objfile) { + Address so_addr(address, objfile->GetSectionList()); + addr_t load_address = + so_addr.GetLoadAddress(exe_ctx->GetTargetPtr()); + bool process_launched_and_stopped = + exe_ctx->GetProcessPtr() + ? StateIsStoppedState(exe_ctx->GetProcessPtr()->GetState(), + true /* must_exist */) + : false; + // Don't use the load address if the process has exited. + if (load_address != LLDB_INVALID_ADDRESS && + process_launched_and_stopped) { + resolved = true; + address = load_address; + address_type = eAddressTypeLoad; + data.SetByteOrder( + exe_ctx->GetTargetRef().GetArchitecture().GetByteOrder()); + data.SetAddressByteSize(exe_ctx->GetTargetRef() + .GetArchitecture() + .GetAddressByteSize()); + } else { + if (so_addr.IsSectionOffset()) { + resolved = true; + file_so_addr = so_addr; + data.SetByteOrder(objfile->GetByteOrder()); + data.SetAddressByteSize(objfile->GetAddressByteSize()); + } } - else - { - if (module == NULL) - { - // The only thing we can currently lock down to a module so that - // we can resolve a file address, is a variable. - Variable *variable = GetVariable(); - if (variable) - { - SymbolContext var_sc; - variable->CalculateSymbolContext(&var_sc); - module = var_sc.module_sp.get(); - } - } - - if (module) - { - bool resolved = false; - ObjectFile *objfile = module->GetObjectFile(); - if (objfile) - { - Address so_addr(address, objfile->GetSectionList()); - addr_t load_address = so_addr.GetLoadAddress (exe_ctx->GetTargetPtr()); - bool process_launched_and_stopped = exe_ctx->GetProcessPtr() - ? StateIsStoppedState(exe_ctx->GetProcessPtr()->GetState(), true /* must_exist */) - : false; - // Don't use the load address if the process has exited. - if (load_address != LLDB_INVALID_ADDRESS && process_launched_and_stopped) - { - resolved = true; - address = load_address; - address_type = eAddressTypeLoad; - data.SetByteOrder(exe_ctx->GetTargetRef().GetArchitecture().GetByteOrder()); - data.SetAddressByteSize(exe_ctx->GetTargetRef().GetArchitecture().GetAddressByteSize()); - } - else - { - if (so_addr.IsSectionOffset()) - { - resolved = true; - file_so_addr = so_addr; - data.SetByteOrder(objfile->GetByteOrder()); - data.SetAddressByteSize(objfile->GetAddressByteSize()); - } - } - } - if (!resolved) - { - Variable *variable = GetVariable(); - - if (module) - { - if (variable) - error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " for variable '%s' in %s", - address, - variable->GetName().AsCString(""), - module->GetFileSpec().GetPath().c_str()); - else - error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " in %s", - address, - module->GetFileSpec().GetPath().c_str()); - } - else - { - if (variable) - error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " for variable '%s'", - address, - variable->GetName().AsCString("")); - else - error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64, address); - } - } - } - else - { - // Can't convert a file address to anything valid without more - // context (which Module it came from) - error.SetErrorString ("can't read memory from file address without more context"); - } + } + if (!resolved) { + Variable *variable = GetVariable(); + + if (module) { + if (variable) + error.SetErrorStringWithFormat( + "unable to resolve the module for file address 0x%" PRIx64 + " for variable '%s' in %s", + address, variable->GetName().AsCString(""), + module->GetFileSpec().GetPath().c_str()); + else + error.SetErrorStringWithFormat( + "unable to resolve the module for file address 0x%" PRIx64 + " in %s", + address, module->GetFileSpec().GetPath().c_str()); + } else { + if (variable) + error.SetErrorStringWithFormat( + "unable to resolve the module for file address 0x%" PRIx64 + " for variable '%s'", + address, variable->GetName().AsCString("")); + else + error.SetErrorStringWithFormat( + "unable to resolve the module for file address 0x%" PRIx64, + address); } + } + } else { + // Can't convert a file address to anything valid without more + // context (which Module it came from) + error.SetErrorString( + "can't read memory from file address without more context"); } + } + } + break; + + case eValueTypeHostAddress: + address = m_value.ULongLong(LLDB_INVALID_ADDRESS); + address_type = eAddressTypeHost; + if (exe_ctx) { + Target *target = exe_ctx->GetTargetPtr(); + if (target) { + data.SetByteOrder(target->GetArchitecture().GetByteOrder()); + data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); break; - - case eValueTypeHostAddress: - address = m_value.ULongLong(LLDB_INVALID_ADDRESS); - address_type = eAddressTypeHost; - if (exe_ctx) - { - Target *target = exe_ctx->GetTargetPtr(); - if (target) - { - data.SetByteOrder(target->GetArchitecture().GetByteOrder()); - data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); - break; - } - } - // fallback to host settings - data.SetByteOrder(endian::InlHostByteOrder()); - data.SetAddressByteSize(sizeof(void *)); - break; + } } + // fallback to host settings + data.SetByteOrder(endian::InlHostByteOrder()); + data.SetAddressByteSize(sizeof(void *)); + break; + } + + // Bail if we encountered any errors + if (error.Fail()) + return error; - // Bail if we encountered any errors - if (error.Fail()) - return error; + if (address == LLDB_INVALID_ADDRESS) { + error.SetErrorStringWithFormat("invalid %s address", + address_type == eAddressTypeHost ? "host" + : "load"); + return error; + } - if (address == LLDB_INVALID_ADDRESS) - { - error.SetErrorStringWithFormat ("invalid %s address", address_type == eAddressTypeHost ? "host" : "load"); - return error; - } + // If we got here, we need to read the value from memory + size_t byte_size = GetValueByteSize(&error, exe_ctx); - // If we got here, we need to read the value from memory - size_t byte_size = GetValueByteSize (&error, exe_ctx); + // Bail if we encountered any errors getting the byte size + if (error.Fail()) + return error; - // Bail if we encountered any errors getting the byte size - if (error.Fail()) + // Make sure we have enough room within "data", and if we don't make + // something large enough that does + if (!data.ValidOffsetForDataOfSize(data_offset, byte_size)) { + DataBufferSP data_sp(new DataBufferHeap(data_offset + byte_size, '\0')); + data.SetData(data_sp); + } + + uint8_t *dst = const_cast<uint8_t *>(data.PeekData(data_offset, byte_size)); + if (dst != NULL) { + if (address_type == eAddressTypeHost) { + // The address is an address in this process, so just copy it. + if (address == 0) { + error.SetErrorStringWithFormat( + "trying to read from host address of 0."); return error; - - // Make sure we have enough room within "data", and if we don't make - // something large enough that does - if (!data.ValidOffsetForDataOfSize (data_offset, byte_size)) - { - DataBufferSP data_sp(new DataBufferHeap (data_offset + byte_size, '\0')); - data.SetData(data_sp); - } - - uint8_t* dst = const_cast<uint8_t*>(data.PeekData (data_offset, byte_size)); - if (dst != NULL) - { - if (address_type == eAddressTypeHost) - { - // The address is an address in this process, so just copy it. - if (address == 0) - { - error.SetErrorStringWithFormat("trying to read from host address of 0."); - return error; - } - memcpy (dst, (uint8_t*)NULL + address, byte_size); - } - else if ((address_type == eAddressTypeLoad) || (address_type == eAddressTypeFile)) - { - if (file_so_addr.IsValid()) - { - // We have a file address that we were able to translate into a - // section offset address so we might be able to read this from - // the object files if we don't have a live process. Lets always - // try and read from the process if we have one though since we - // want to read the actual value by setting "prefer_file_cache" - // to false. - const bool prefer_file_cache = false; - if (exe_ctx->GetTargetRef().ReadMemory(file_so_addr, prefer_file_cache, dst, byte_size, error) != byte_size) - { - error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed", (uint64_t)address); - } - } - else - { - // The execution context might have a NULL process, but it - // might have a valid process in the exe_ctx->target, so use - // the ExecutionContext::GetProcess accessor to ensure we - // get the process if there is one. - Process *process = exe_ctx->GetProcessPtr(); - - if (process) - { - const size_t bytes_read = process->ReadMemory(address, dst, byte_size, error); - if (bytes_read != byte_size) - error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed (%u of %u bytes read)", - (uint64_t)address, - (uint32_t)bytes_read, - (uint32_t)byte_size); - } - else - { - error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed (invalid process)", (uint64_t)address); - } - } + } + memcpy(dst, (uint8_t *)NULL + address, byte_size); + } else if ((address_type == eAddressTypeLoad) || + (address_type == eAddressTypeFile)) { + if (file_so_addr.IsValid()) { + // We have a file address that we were able to translate into a + // section offset address so we might be able to read this from + // the object files if we don't have a live process. Lets always + // try and read from the process if we have one though since we + // want to read the actual value by setting "prefer_file_cache" + // to false. + const bool prefer_file_cache = false; + if (exe_ctx->GetTargetRef().ReadMemory(file_so_addr, prefer_file_cache, + dst, byte_size, + error) != byte_size) { + error.SetErrorStringWithFormat( + "read memory from 0x%" PRIx64 " failed", (uint64_t)address); } - else - { - error.SetErrorStringWithFormat ("unsupported AddressType value (%i)", address_type); + } else { + // The execution context might have a NULL process, but it + // might have a valid process in the exe_ctx->target, so use + // the ExecutionContext::GetProcess accessor to ensure we + // get the process if there is one. + Process *process = exe_ctx->GetProcessPtr(); + + if (process) { + const size_t bytes_read = + process->ReadMemory(address, dst, byte_size, error); + if (bytes_read != byte_size) + error.SetErrorStringWithFormat( + "read memory from 0x%" PRIx64 " failed (%u of %u bytes read)", + (uint64_t)address, (uint32_t)bytes_read, (uint32_t)byte_size); + } else { + error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 + " failed (invalid process)", + (uint64_t)address); } + } + } else { + error.SetErrorStringWithFormat("unsupported AddressType value (%i)", + address_type); } - else - { - error.SetErrorStringWithFormat ("out of memory"); - } + } else { + error.SetErrorStringWithFormat("out of memory"); + } - return error; + return error; } -Scalar & -Value::ResolveValue(ExecutionContext *exe_ctx) -{ - const CompilerType &compiler_type = GetCompilerType(); - if (compiler_type.IsValid()) +Scalar &Value::ResolveValue(ExecutionContext *exe_ctx) { + const CompilerType &compiler_type = GetCompilerType(); + if (compiler_type.IsValid()) { + switch (m_value_type) { + case eValueTypeScalar: // raw scalar value + break; + + default: + case eValueTypeFileAddress: + case eValueTypeLoadAddress: // load address value + case eValueTypeHostAddress: // host address value (for memory in the process + // that is using liblldb) { - switch (m_value_type) - { - case eValueTypeScalar: // raw scalar value - break; - - default: - case eValueTypeFileAddress: - case eValueTypeLoadAddress: // load address value - case eValueTypeHostAddress: // host address value (for memory in the process that is using liblldb) - { - DataExtractor data; - lldb::addr_t addr = m_value.ULongLong(LLDB_INVALID_ADDRESS); - Error error (GetValueAsData (exe_ctx, data, 0, NULL)); - if (error.Success()) - { - Scalar scalar; - if (compiler_type.GetValueAsScalar (data, 0, data.GetByteSize(), scalar)) - { - m_value = scalar; - m_value_type = eValueTypeScalar; - } - else - { - if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) - { - m_value.Clear(); - m_value_type = eValueTypeScalar; - } - } - } - else - { - if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) - { - m_value.Clear(); - m_value_type = eValueTypeScalar; - } - } - } - break; + DataExtractor data; + lldb::addr_t addr = m_value.ULongLong(LLDB_INVALID_ADDRESS); + Error error(GetValueAsData(exe_ctx, data, 0, NULL)); + if (error.Success()) { + Scalar scalar; + if (compiler_type.GetValueAsScalar(data, 0, data.GetByteSize(), + scalar)) { + m_value = scalar; + m_value_type = eValueTypeScalar; + } else { + if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) { + m_value.Clear(); + m_value_type = eValueTypeScalar; + } } + } else { + if ((uintptr_t)addr != (uintptr_t)m_data_buffer.GetBytes()) { + m_value.Clear(); + m_value_type = eValueTypeScalar; + } + } + } break; } - return m_value; -} - -Variable * -Value::GetVariable() -{ - if (m_context_type == eContextTypeVariable) - return static_cast<Variable *> (m_context); + } + return m_value; +} + +Variable *Value::GetVariable() { + if (m_context_type == eContextTypeVariable) + return static_cast<Variable *>(m_context); + return NULL; +} + +void Value::Clear() { + m_value.Clear(); + m_vector.Clear(); + m_compiler_type.Clear(); + m_value_type = eValueTypeScalar; + m_context = NULL; + m_context_type = eContextTypeInvalid; + m_data_buffer.Clear(); +} + +const char *Value::GetValueTypeAsCString(ValueType value_type) { + switch (value_type) { + case eValueTypeScalar: + return "scalar"; + case eValueTypeVector: + return "vector"; + case eValueTypeFileAddress: + return "file address"; + case eValueTypeLoadAddress: + return "load address"; + case eValueTypeHostAddress: + return "host address"; + }; + return "???"; +} + +const char *Value::GetContextTypeAsCString(ContextType context_type) { + switch (context_type) { + case eContextTypeInvalid: + return "invalid"; + case eContextTypeRegisterInfo: + return "RegisterInfo *"; + case eContextTypeLLDBType: + return "Type *"; + case eContextTypeVariable: + return "Variable *"; + }; + return "???"; +} + +ValueList::ValueList(const ValueList &rhs) { m_values = rhs.m_values; } + +const ValueList &ValueList::operator=(const ValueList &rhs) { + m_values = rhs.m_values; + return *this; +} + +void ValueList::PushValue(const Value &value) { m_values.push_back(value); } + +size_t ValueList::GetSize() { return m_values.size(); } + +Value *ValueList::GetValueAtIndex(size_t idx) { + if (idx < GetSize()) { + return &(m_values[idx]); + } else return NULL; } -void -Value::Clear() -{ - m_value.Clear(); - m_vector.Clear(); - m_compiler_type.Clear(); - m_value_type = eValueTypeScalar; - m_context = NULL; - m_context_type = eContextTypeInvalid; - m_data_buffer.Clear(); -} - - -const char * -Value::GetValueTypeAsCString (ValueType value_type) -{ - switch (value_type) - { - case eValueTypeScalar: return "scalar"; - case eValueTypeVector: return "vector"; - case eValueTypeFileAddress: return "file address"; - case eValueTypeLoadAddress: return "load address"; - case eValueTypeHostAddress: return "host address"; - }; - return "???"; -} - -const char * -Value::GetContextTypeAsCString (ContextType context_type) -{ - switch (context_type) - { - case eContextTypeInvalid: return "invalid"; - case eContextTypeRegisterInfo: return "RegisterInfo *"; - case eContextTypeLLDBType: return "Type *"; - case eContextTypeVariable: return "Variable *"; - }; - return "???"; -} - -ValueList::ValueList (const ValueList &rhs) -{ - m_values = rhs.m_values; -} - -const ValueList & -ValueList::operator= (const ValueList &rhs) -{ - m_values = rhs.m_values; - return *this; -} - -void -ValueList::PushValue (const Value &value) -{ - m_values.push_back (value); -} - -size_t -ValueList::GetSize() -{ - return m_values.size(); -} - -Value * -ValueList::GetValueAtIndex (size_t idx) -{ - if (idx < GetSize()) - { - return &(m_values[idx]); - } - else - return NULL; -} - -void -ValueList::Clear () -{ - m_values.clear(); -} - +void ValueList::Clear() { m_values.clear(); } diff --git a/source/Core/ValueObject.cpp b/source/Core/ValueObject.cpp index 3e0a31833ef6..fc2312d60d57 100644 --- a/source/Core/ValueObject.cpp +++ b/source/Core/ValueObject.cpp @@ -41,9 +41,9 @@ #include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/Type.h" #include "lldb/Target/ExecutionContext.h" @@ -65,2032 +65,1684 @@ static user_id_t g_value_obj_uid = 0; //---------------------------------------------------------------------- // ValueObject constructor //---------------------------------------------------------------------- -ValueObject::ValueObject (ValueObject &parent) : - UserID (++g_value_obj_uid), // Unique identifier for every value object - m_parent (&parent), - m_root (NULL), - m_update_point (parent.GetUpdatePoint ()), - m_name (), - m_data (), - m_value (), - m_error (), - m_value_str (), - m_old_value_str (), - m_location_str (), - m_summary_str (), - m_object_desc_str (), - m_validation_result(), - m_manager(parent.GetManager()), - m_children (), - m_synthetic_children (), - m_dynamic_value (NULL), - m_synthetic_value(NULL), - m_deref_valobj(NULL), - m_format (eFormatDefault), - m_last_format (eFormatDefault), - m_last_format_mgr_revision(0), - m_type_summary_sp(), - m_type_format_sp(), - m_synthetic_children_sp(), - m_type_validator_sp(), - m_user_id_of_forced_summary(), - m_address_type_of_ptr_or_ref_children(eAddressTypeInvalid), - m_value_checksum(), - m_preferred_display_language(lldb::eLanguageTypeUnknown), - m_language_flags(0), - m_value_is_valid (false), - m_value_did_change (false), - m_children_count_valid (false), - m_old_value_valid (false), - m_is_deref_of_parent (false), - m_is_array_item_for_pointer(false), - m_is_bitfield_for_scalar(false), - m_is_child_at_offset(false), - m_is_getting_summary(false), - m_did_calculate_complete_objc_class_type(false), - m_is_synthetic_children_generated(parent.m_is_synthetic_children_generated) -{ - m_manager->ManageObject(this); +ValueObject::ValueObject(ValueObject &parent) + : UserID(++g_value_obj_uid), // Unique identifier for every value object + m_parent(&parent), m_root(NULL), m_update_point(parent.GetUpdatePoint()), + m_name(), m_data(), m_value(), m_error(), m_value_str(), + m_old_value_str(), m_location_str(), m_summary_str(), m_object_desc_str(), + m_validation_result(), m_manager(parent.GetManager()), m_children(), + m_synthetic_children(), m_dynamic_value(NULL), m_synthetic_value(NULL), + m_deref_valobj(NULL), m_format(eFormatDefault), + m_last_format(eFormatDefault), m_last_format_mgr_revision(0), + m_type_summary_sp(), m_type_format_sp(), m_synthetic_children_sp(), + m_type_validator_sp(), m_user_id_of_forced_summary(), + m_address_type_of_ptr_or_ref_children(eAddressTypeInvalid), + m_value_checksum(), + m_preferred_display_language(lldb::eLanguageTypeUnknown), + m_language_flags(0), m_value_is_valid(false), m_value_did_change(false), + m_children_count_valid(false), m_old_value_valid(false), + m_is_deref_of_parent(false), m_is_array_item_for_pointer(false), + m_is_bitfield_for_scalar(false), m_is_child_at_offset(false), + m_is_getting_summary(false), + m_did_calculate_complete_objc_class_type(false), + m_is_synthetic_children_generated( + parent.m_is_synthetic_children_generated) { + m_manager->ManageObject(this); } //---------------------------------------------------------------------- // ValueObject constructor //---------------------------------------------------------------------- -ValueObject::ValueObject (ExecutionContextScope *exe_scope, - AddressType child_ptr_or_ref_addr_type) : - UserID (++g_value_obj_uid), // Unique identifier for every value object - m_parent (NULL), - m_root (NULL), - m_update_point (exe_scope), - m_name (), - m_data (), - m_value (), - m_error (), - m_value_str (), - m_old_value_str (), - m_location_str (), - m_summary_str (), - m_object_desc_str (), - m_validation_result(), - m_manager(), - m_children (), - m_synthetic_children (), - m_dynamic_value (NULL), - m_synthetic_value(NULL), - m_deref_valobj(NULL), - m_format (eFormatDefault), - m_last_format (eFormatDefault), - m_last_format_mgr_revision(0), - m_type_summary_sp(), - m_type_format_sp(), - m_synthetic_children_sp(), - m_type_validator_sp(), - m_user_id_of_forced_summary(), - m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type), - m_value_checksum(), - m_preferred_display_language(lldb::eLanguageTypeUnknown), - m_language_flags(0), - m_value_is_valid (false), - m_value_did_change (false), - m_children_count_valid (false), - m_old_value_valid (false), - m_is_deref_of_parent (false), - m_is_array_item_for_pointer(false), - m_is_bitfield_for_scalar(false), - m_is_child_at_offset(false), - m_is_getting_summary(false), - m_did_calculate_complete_objc_class_type(false), - m_is_synthetic_children_generated(false) -{ - m_manager = new ValueObjectManager(); - m_manager->ManageObject (this); +ValueObject::ValueObject(ExecutionContextScope *exe_scope, + AddressType child_ptr_or_ref_addr_type) + : UserID(++g_value_obj_uid), // Unique identifier for every value object + m_parent(NULL), m_root(NULL), m_update_point(exe_scope), m_name(), + m_data(), m_value(), m_error(), m_value_str(), m_old_value_str(), + m_location_str(), m_summary_str(), m_object_desc_str(), + m_validation_result(), m_manager(), m_children(), m_synthetic_children(), + m_dynamic_value(NULL), m_synthetic_value(NULL), m_deref_valobj(NULL), + m_format(eFormatDefault), m_last_format(eFormatDefault), + m_last_format_mgr_revision(0), m_type_summary_sp(), m_type_format_sp(), + m_synthetic_children_sp(), m_type_validator_sp(), + m_user_id_of_forced_summary(), + m_address_type_of_ptr_or_ref_children(child_ptr_or_ref_addr_type), + m_value_checksum(), + m_preferred_display_language(lldb::eLanguageTypeUnknown), + m_language_flags(0), m_value_is_valid(false), m_value_did_change(false), + m_children_count_valid(false), m_old_value_valid(false), + m_is_deref_of_parent(false), m_is_array_item_for_pointer(false), + m_is_bitfield_for_scalar(false), m_is_child_at_offset(false), + m_is_getting_summary(false), + m_did_calculate_complete_objc_class_type(false), + m_is_synthetic_children_generated(false) { + m_manager = new ValueObjectManager(); + m_manager->ManageObject(this); } //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -ValueObject::~ValueObject () -{ -} +ValueObject::~ValueObject() {} + +bool ValueObject::UpdateValueIfNeeded(bool update_format) { + + bool did_change_formats = false; + + if (update_format) + did_change_formats = UpdateFormatsIfNeeded(); + + // If this is a constant value, then our success is predicated on whether + // we have an error or not + if (GetIsConstant()) { + // if you are constant, things might still have changed behind your back + // (e.g. you are a frozen object and things have changed deeper than you + // cared to freeze-dry yourself) + // in this case, your value has not changed, but "computed" entries might + // have, so you might now have + // a different summary, or a different object description. clear these so we + // will recompute them + if (update_format && !did_change_formats) + ClearUserVisibleData(eClearUserVisibleDataItemsSummary | + eClearUserVisibleDataItemsDescription); + return m_error.Success(); + } -bool -ValueObject::UpdateValueIfNeeded (bool update_format) -{ - - bool did_change_formats = false; - - if (update_format) - did_change_formats = UpdateFormatsIfNeeded(); - - // If this is a constant value, then our success is predicated on whether - // we have an error or not - if (GetIsConstant()) - { - // if you are constant, things might still have changed behind your back - // (e.g. you are a frozen object and things have changed deeper than you cared to freeze-dry yourself) - // in this case, your value has not changed, but "computed" entries might have, so you might now have - // a different summary, or a different object description. clear these so we will recompute them - if (update_format && !did_change_formats) - ClearUserVisibleData(eClearUserVisibleDataItemsSummary | eClearUserVisibleDataItemsDescription); - return m_error.Success(); + bool first_update = IsChecksumEmpty(); + + if (NeedsUpdating()) { + m_update_point.SetUpdated(); + + // Save the old value using swap to avoid a string copy which + // also will clear our m_value_str + if (m_value_str.empty()) { + m_old_value_valid = false; + } else { + m_old_value_valid = true; + m_old_value_str.swap(m_value_str); + ClearUserVisibleData(eClearUserVisibleDataItemsValue); } - bool first_update = IsChecksumEmpty(); - - if (NeedsUpdating()) - { - m_update_point.SetUpdated(); - - // Save the old value using swap to avoid a string copy which - // also will clear our m_value_str - if (m_value_str.empty()) - { - m_old_value_valid = false; - } - else - { - m_old_value_valid = true; - m_old_value_str.swap (m_value_str); - ClearUserVisibleData(eClearUserVisibleDataItemsValue); - } + ClearUserVisibleData(); - ClearUserVisibleData(); - - if (IsInScope()) - { - const bool value_was_valid = GetValueIsValid(); - SetValueDidChange (false); - - m_error.Clear(); - - // Call the pure virtual function to update the value - - bool need_compare_checksums = false; - llvm::SmallVector<uint8_t, 16> old_checksum; - - if (!first_update && CanProvideValue()) - { - need_compare_checksums = true; - old_checksum.resize(m_value_checksum.size()); - std::copy(m_value_checksum.begin(), m_value_checksum.end(), old_checksum.begin()); - } - - bool success = UpdateValue (); - - SetValueIsValid (success); - - if (success) - { - const uint64_t max_checksum_size = 128; - m_data.Checksum(m_value_checksum, - max_checksum_size); - } - else - { - need_compare_checksums = false; - m_value_checksum.clear(); - } - - assert (!need_compare_checksums || (!old_checksum.empty() && !m_value_checksum.empty())); - - if (first_update) - SetValueDidChange (false); - else if (!m_value_did_change && success == false) - { - // The value wasn't gotten successfully, so we mark this - // as changed if the value used to be valid and now isn't - SetValueDidChange (value_was_valid); - } - else if (need_compare_checksums) - { - SetValueDidChange(memcmp(&old_checksum[0], &m_value_checksum[0], m_value_checksum.size())); - } - - } - else - { - m_error.SetErrorString("out of scope"); - } + if (IsInScope()) { + const bool value_was_valid = GetValueIsValid(); + SetValueDidChange(false); + + m_error.Clear(); + + // Call the pure virtual function to update the value + + bool need_compare_checksums = false; + llvm::SmallVector<uint8_t, 16> old_checksum; + + if (!first_update && CanProvideValue()) { + need_compare_checksums = true; + old_checksum.resize(m_value_checksum.size()); + std::copy(m_value_checksum.begin(), m_value_checksum.end(), + old_checksum.begin()); + } + + bool success = UpdateValue(); + + SetValueIsValid(success); + + if (success) { + const uint64_t max_checksum_size = 128; + m_data.Checksum(m_value_checksum, max_checksum_size); + } else { + need_compare_checksums = false; + m_value_checksum.clear(); + } + + assert(!need_compare_checksums || + (!old_checksum.empty() && !m_value_checksum.empty())); + + if (first_update) + SetValueDidChange(false); + else if (!m_value_did_change && success == false) { + // The value wasn't gotten successfully, so we mark this + // as changed if the value used to be valid and now isn't + SetValueDidChange(value_was_valid); + } else if (need_compare_checksums) { + SetValueDidChange(memcmp(&old_checksum[0], &m_value_checksum[0], + m_value_checksum.size())); + } + + } else { + m_error.SetErrorString("out of scope"); } - return m_error.Success(); + } + return m_error.Success(); } -bool -ValueObject::UpdateFormatsIfNeeded() -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_DATAFORMATTERS)); - if (log) - log->Printf("[%s %p] checking for FormatManager revisions. ValueObject rev: %d - Global rev: %d", - GetName().GetCString(), static_cast<void*>(this), - m_last_format_mgr_revision, - DataVisualization::GetCurrentRevision()); +bool ValueObject::UpdateFormatsIfNeeded() { + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); + if (log) + log->Printf("[%s %p] checking for FormatManager revisions. ValueObject " + "rev: %d - Global rev: %d", + GetName().GetCString(), static_cast<void *>(this), + m_last_format_mgr_revision, + DataVisualization::GetCurrentRevision()); - bool any_change = false; + bool any_change = false; - if ( (m_last_format_mgr_revision != DataVisualization::GetCurrentRevision())) - { - m_last_format_mgr_revision = DataVisualization::GetCurrentRevision(); - any_change = true; - - SetValueFormat(DataVisualization::GetFormat (*this, eNoDynamicValues)); - SetSummaryFormat(DataVisualization::GetSummaryFormat (*this, GetDynamicValueType())); + if ((m_last_format_mgr_revision != DataVisualization::GetCurrentRevision())) { + m_last_format_mgr_revision = DataVisualization::GetCurrentRevision(); + any_change = true; + + SetValueFormat(DataVisualization::GetFormat(*this, eNoDynamicValues)); + SetSummaryFormat( + DataVisualization::GetSummaryFormat(*this, GetDynamicValueType())); #ifndef LLDB_DISABLE_PYTHON - SetSyntheticChildren(DataVisualization::GetSyntheticChildren (*this, GetDynamicValueType())); + SetSyntheticChildren( + DataVisualization::GetSyntheticChildren(*this, GetDynamicValueType())); #endif - SetValidator(DataVisualization::GetValidator(*this, GetDynamicValueType())); - } + SetValidator(DataVisualization::GetValidator(*this, GetDynamicValueType())); + } - return any_change; + return any_change; } -void -ValueObject::SetNeedsUpdate () -{ - m_update_point.SetNeedsUpdate(); - // We have to clear the value string here so ConstResult children will notice if their values are - // changed by hand (i.e. with SetValueAsCString). - ClearUserVisibleData(eClearUserVisibleDataItemsValue); +void ValueObject::SetNeedsUpdate() { + m_update_point.SetNeedsUpdate(); + // We have to clear the value string here so ConstResult children will notice + // if their values are + // changed by hand (i.e. with SetValueAsCString). + ClearUserVisibleData(eClearUserVisibleDataItemsValue); } -void -ValueObject::ClearDynamicTypeInformation () -{ - m_children_count_valid = false; - m_did_calculate_complete_objc_class_type = false; - m_last_format_mgr_revision = 0; - m_override_type = CompilerType(); - SetValueFormat(lldb::TypeFormatImplSP()); - SetSummaryFormat(lldb::TypeSummaryImplSP()); - SetSyntheticChildren(lldb::SyntheticChildrenSP()); +void ValueObject::ClearDynamicTypeInformation() { + m_children_count_valid = false; + m_did_calculate_complete_objc_class_type = false; + m_last_format_mgr_revision = 0; + m_override_type = CompilerType(); + SetValueFormat(lldb::TypeFormatImplSP()); + SetSummaryFormat(lldb::TypeSummaryImplSP()); + SetSyntheticChildren(lldb::SyntheticChildrenSP()); } -CompilerType -ValueObject::MaybeCalculateCompleteType () -{ - CompilerType compiler_type(GetCompilerTypeImpl()); - - if (m_did_calculate_complete_objc_class_type) - { - if (m_override_type.IsValid()) - return m_override_type; - else - return compiler_type; - } - - CompilerType class_type; - bool is_pointer_type = false; - - if (ClangASTContext::IsObjCObjectPointerType(compiler_type, &class_type)) - { - is_pointer_type = true; - } - else if (ClangASTContext::IsObjCObjectOrInterfaceType(compiler_type)) - { - class_type = compiler_type; - } +CompilerType ValueObject::MaybeCalculateCompleteType() { + CompilerType compiler_type(GetCompilerTypeImpl()); + + if (m_did_calculate_complete_objc_class_type) { + if (m_override_type.IsValid()) + return m_override_type; else - { - return compiler_type; - } - - m_did_calculate_complete_objc_class_type = true; - - if (class_type) - { - ConstString class_name (class_type.GetConstTypeName()); - - if (class_name) - { - ProcessSP process_sp(GetUpdatePoint().GetExecutionContextRef().GetProcessSP()); - - if (process_sp) - { - ObjCLanguageRuntime *objc_language_runtime(process_sp->GetObjCLanguageRuntime()); - - if (objc_language_runtime) - { - TypeSP complete_objc_class_type_sp = objc_language_runtime->LookupInCompleteClassCache(class_name); - - if (complete_objc_class_type_sp) - { - CompilerType complete_class(complete_objc_class_type_sp->GetFullCompilerType ()); - - if (complete_class.GetCompleteType()) - { - if (is_pointer_type) - { - m_override_type = complete_class.GetPointerType(); - } - else - { - m_override_type = complete_class; - } - - if (m_override_type.IsValid()) - return m_override_type; - } - } - } - } - } - } + return compiler_type; + } + + CompilerType class_type; + bool is_pointer_type = false; + + if (ClangASTContext::IsObjCObjectPointerType(compiler_type, &class_type)) { + is_pointer_type = true; + } else if (ClangASTContext::IsObjCObjectOrInterfaceType(compiler_type)) { + class_type = compiler_type; + } else { return compiler_type; -} + } -CompilerType -ValueObject::GetCompilerType () -{ - return MaybeCalculateCompleteType(); -} + m_did_calculate_complete_objc_class_type = true; -TypeImpl -ValueObject::GetTypeImpl () -{ - return TypeImpl(GetCompilerType()); -} + if (class_type) { + ConstString class_name(class_type.GetConstTypeName()); -DataExtractor & -ValueObject::GetDataExtractor () -{ - UpdateValueIfNeeded(false); - return m_data; -} + if (class_name) { + ProcessSP process_sp( + GetUpdatePoint().GetExecutionContextRef().GetProcessSP()); -const Error & -ValueObject::GetError() -{ - UpdateValueIfNeeded(false); - return m_error; -} + if (process_sp) { + ObjCLanguageRuntime *objc_language_runtime( + process_sp->GetObjCLanguageRuntime()); -const ConstString & -ValueObject::GetName() const -{ - return m_name; -} + if (objc_language_runtime) { + TypeSP complete_objc_class_type_sp = + objc_language_runtime->LookupInCompleteClassCache(class_name); -const char * -ValueObject::GetLocationAsCString () -{ - return GetLocationAsCStringImpl(m_value, - m_data); -} + if (complete_objc_class_type_sp) { + CompilerType complete_class( + complete_objc_class_type_sp->GetFullCompilerType()); -const char * -ValueObject::GetLocationAsCStringImpl (const Value& value, - const DataExtractor& data) -{ - if (UpdateValueIfNeeded(false)) - { - if (m_location_str.empty()) - { - StreamString sstr; - - Value::ValueType value_type = value.GetValueType(); - - switch (value_type) - { - case Value::eValueTypeScalar: - case Value::eValueTypeVector: - if (value.GetContextType() == Value::eContextTypeRegisterInfo) - { - RegisterInfo *reg_info = value.GetRegisterInfo(); - if (reg_info) - { - if (reg_info->name) - m_location_str = reg_info->name; - else if (reg_info->alt_name) - m_location_str = reg_info->alt_name; - if (m_location_str.empty()) - m_location_str = (reg_info->encoding == lldb::eEncodingVector) ? "vector" : "scalar"; - } - } - if (m_location_str.empty()) - m_location_str = (value_type == Value::eValueTypeVector) ? "vector" : "scalar"; - break; - - case Value::eValueTypeLoadAddress: - case Value::eValueTypeFileAddress: - case Value::eValueTypeHostAddress: - { - uint32_t addr_nibble_size = data.GetAddressByteSize() * 2; - sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size, value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS)); - m_location_str.swap(sstr.GetString()); - } - break; + if (complete_class.GetCompleteType()) { + if (is_pointer_type) { + m_override_type = complete_class.GetPointerType(); + } else { + m_override_type = complete_class; + } + + if (m_override_type.IsValid()) + return m_override_type; } + } } + } } - return m_location_str.c_str(); + } + return compiler_type; } -Value & -ValueObject::GetValue() -{ - return m_value; +CompilerType ValueObject::GetCompilerType() { + return MaybeCalculateCompleteType(); } -const Value & -ValueObject::GetValue() const -{ - return m_value; -} +TypeImpl ValueObject::GetTypeImpl() { return TypeImpl(GetCompilerType()); } -bool -ValueObject::ResolveValue (Scalar &scalar) -{ - if (UpdateValueIfNeeded(false)) // make sure that you are up to date before returning anything - { - ExecutionContext exe_ctx (GetExecutionContextRef()); - Value tmp_value(m_value); - scalar = tmp_value.ResolveValue(&exe_ctx); - if (scalar.IsValid()) - { - const uint32_t bitfield_bit_size = GetBitfieldBitSize(); - if (bitfield_bit_size) - return scalar.ExtractBitfield (bitfield_bit_size, GetBitfieldBitOffset()); - return true; - } - } - return false; +DataExtractor &ValueObject::GetDataExtractor() { + UpdateValueIfNeeded(false); + return m_data; } -bool -ValueObject::IsLogicalTrue (Error& error) -{ - if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) - { - LazyBool is_logical_true = language->IsLogicalTrue(*this, error); - switch (is_logical_true) - { - case eLazyBoolYes: - case eLazyBoolNo: - return (is_logical_true == true); - case eLazyBoolCalculate: - break; - } - } - - Scalar scalar_value; - - if (!ResolveValue (scalar_value)) - { - error.SetErrorString("failed to get a scalar result"); - return false; - } - - bool ret; - if (scalar_value.ULongLong(1) == 0) - ret = false; - else - ret = true; - error.Clear(); - return ret; +const Error &ValueObject::GetError() { + UpdateValueIfNeeded(false); + return m_error; } -bool -ValueObject::GetValueIsValid () const -{ - return m_value_is_valid; +const ConstString &ValueObject::GetName() const { return m_name; } + +const char *ValueObject::GetLocationAsCString() { + return GetLocationAsCStringImpl(m_value, m_data); } +const char *ValueObject::GetLocationAsCStringImpl(const Value &value, + const DataExtractor &data) { + if (UpdateValueIfNeeded(false)) { + if (m_location_str.empty()) { + StreamString sstr; -void -ValueObject::SetValueIsValid (bool b) -{ - m_value_is_valid = b; -} + Value::ValueType value_type = value.GetValueType(); + + switch (value_type) { + case Value::eValueTypeScalar: + case Value::eValueTypeVector: + if (value.GetContextType() == Value::eContextTypeRegisterInfo) { + RegisterInfo *reg_info = value.GetRegisterInfo(); + if (reg_info) { + if (reg_info->name) + m_location_str = reg_info->name; + else if (reg_info->alt_name) + m_location_str = reg_info->alt_name; + if (m_location_str.empty()) + m_location_str = (reg_info->encoding == lldb::eEncodingVector) + ? "vector" + : "scalar"; + } + } + if (m_location_str.empty()) + m_location_str = + (value_type == Value::eValueTypeVector) ? "vector" : "scalar"; + break; + + case Value::eValueTypeLoadAddress: + case Value::eValueTypeFileAddress: + case Value::eValueTypeHostAddress: { + uint32_t addr_nibble_size = data.GetAddressByteSize() * 2; + sstr.Printf("0x%*.*llx", addr_nibble_size, addr_nibble_size, + value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS)); + m_location_str = sstr.GetString(); + } break; + } + } + } + return m_location_str.c_str(); +} + +Value &ValueObject::GetValue() { return m_value; } + +const Value &ValueObject::GetValue() const { return m_value; } + +bool ValueObject::ResolveValue(Scalar &scalar) { + if (UpdateValueIfNeeded( + false)) // make sure that you are up to date before returning anything + { + ExecutionContext exe_ctx(GetExecutionContextRef()); + Value tmp_value(m_value); + scalar = tmp_value.ResolveValue(&exe_ctx); + if (scalar.IsValid()) { + const uint32_t bitfield_bit_size = GetBitfieldBitSize(); + if (bitfield_bit_size) + return scalar.ExtractBitfield(bitfield_bit_size, + GetBitfieldBitOffset()); + return true; + } + } + return false; +} + +bool ValueObject::IsLogicalTrue(Error &error) { + if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) { + LazyBool is_logical_true = language->IsLogicalTrue(*this, error); + switch (is_logical_true) { + case eLazyBoolYes: + case eLazyBoolNo: + return (is_logical_true == true); + case eLazyBoolCalculate: + break; + } + } + + Scalar scalar_value; + + if (!ResolveValue(scalar_value)) { + error.SetErrorString("failed to get a scalar result"); + return false; + } -bool -ValueObject::GetValueDidChange () -{ - return m_value_did_change; + bool ret; + if (scalar_value.ULongLong(1) == 0) + ret = false; + else + ret = true; + error.Clear(); + return ret; } -void -ValueObject::SetValueDidChange (bool value_changed) -{ - m_value_did_change = value_changed; +bool ValueObject::GetValueIsValid() const { return m_value_is_valid; } + +void ValueObject::SetValueIsValid(bool b) { m_value_is_valid = b; } + +bool ValueObject::GetValueDidChange() { return m_value_did_change; } + +void ValueObject::SetValueDidChange(bool value_changed) { + m_value_did_change = value_changed; } -ValueObjectSP -ValueObject::GetChildAtIndex (size_t idx, bool can_create) -{ - ValueObjectSP child_sp; - // We may need to update our value if we are dynamic - if (IsPossibleDynamicType ()) - UpdateValueIfNeeded(false); - if (idx < GetNumChildren()) - { - // Check if we have already made the child value object? - if (can_create && !m_children.HasChildAtIndex(idx)) - { - // No we haven't created the child at this index, so lets have our - // subclass do it and cache the result for quick future access. - m_children.SetChildAtIndex(idx,CreateChildAtIndex (idx, false, 0)); - } - - ValueObject* child = m_children.GetChildAtIndex(idx); - if (child != NULL) - return child->GetSP(); +ValueObjectSP ValueObject::GetChildAtIndex(size_t idx, bool can_create) { + ValueObjectSP child_sp; + // We may need to update our value if we are dynamic + if (IsPossibleDynamicType()) + UpdateValueIfNeeded(false); + if (idx < GetNumChildren()) { + // Check if we have already made the child value object? + if (can_create && !m_children.HasChildAtIndex(idx)) { + // No we haven't created the child at this index, so lets have our + // subclass do it and cache the result for quick future access. + m_children.SetChildAtIndex(idx, CreateChildAtIndex(idx, false, 0)); } - return child_sp; + + ValueObject *child = m_children.GetChildAtIndex(idx); + if (child != NULL) + return child->GetSP(); + } + return child_sp; } ValueObjectSP -ValueObject::GetChildAtIndexPath (const std::initializer_list<size_t>& idxs, - size_t* index_of_error) -{ - return GetChildAtIndexPath( std::vector<size_t>(idxs), - index_of_error ); +ValueObject::GetChildAtIndexPath(const std::initializer_list<size_t> &idxs, + size_t *index_of_error) { + return GetChildAtIndexPath(std::vector<size_t>(idxs), index_of_error); } -ValueObjectSP -ValueObject::GetChildAtIndexPath (const std::initializer_list< std::pair<size_t, bool> >& idxs, - size_t* index_of_error) -{ - return GetChildAtIndexPath( std::vector<std::pair<size_t,bool>>(idxs), - index_of_error ); +ValueObjectSP ValueObject::GetChildAtIndexPath( + const std::initializer_list<std::pair<size_t, bool>> &idxs, + size_t *index_of_error) { + return GetChildAtIndexPath(std::vector<std::pair<size_t, bool>>(idxs), + index_of_error); } lldb::ValueObjectSP -ValueObject::GetChildAtIndexPath (const std::vector<size_t> &idxs, - size_t* index_of_error) -{ - if (idxs.size() == 0) - return GetSP(); - ValueObjectSP root(GetSP()); - for (size_t idx : idxs) - { - root = root->GetChildAtIndex(idx, true); - if (!root) - { - if (index_of_error) - *index_of_error = idx; - return root; - } +ValueObject::GetChildAtIndexPath(const std::vector<size_t> &idxs, + size_t *index_of_error) { + if (idxs.size() == 0) + return GetSP(); + ValueObjectSP root(GetSP()); + for (size_t idx : idxs) { + root = root->GetChildAtIndex(idx, true); + if (!root) { + if (index_of_error) + *index_of_error = idx; + return root; } - return root; + } + return root; } -lldb::ValueObjectSP -ValueObject::GetChildAtIndexPath (const std::vector< std::pair<size_t, bool> > &idxs, - size_t* index_of_error) -{ - if (idxs.size() == 0) - return GetSP(); - ValueObjectSP root(GetSP()); - for (std::pair<size_t, bool> idx : idxs) - { - root = root->GetChildAtIndex(idx.first, idx.second); - if (!root) - { - if (index_of_error) - *index_of_error = idx.first; - return root; - } +lldb::ValueObjectSP ValueObject::GetChildAtIndexPath( + const std::vector<std::pair<size_t, bool>> &idxs, size_t *index_of_error) { + if (idxs.size() == 0) + return GetSP(); + ValueObjectSP root(GetSP()); + for (std::pair<size_t, bool> idx : idxs) { + root = root->GetChildAtIndex(idx.first, idx.second); + if (!root) { + if (index_of_error) + *index_of_error = idx.first; + return root; } - return root; + } + return root; } lldb::ValueObjectSP -ValueObject::GetChildAtNamePath (const std::initializer_list<ConstString> &names, - ConstString* name_of_error) -{ - return GetChildAtNamePath( std::vector<ConstString>(names), - name_of_error ); +ValueObject::GetChildAtNamePath(const std::initializer_list<ConstString> &names, + ConstString *name_of_error) { + return GetChildAtNamePath(std::vector<ConstString>(names), name_of_error); } -lldb::ValueObjectSP -ValueObject::GetChildAtNamePath (const std::initializer_list< std::pair<ConstString, bool> > &names, - ConstString* name_of_error) -{ - return GetChildAtNamePath( std::vector<std::pair<ConstString,bool>>(names), - name_of_error ); +lldb::ValueObjectSP ValueObject::GetChildAtNamePath( + const std::initializer_list<std::pair<ConstString, bool>> &names, + ConstString *name_of_error) { + return GetChildAtNamePath(std::vector<std::pair<ConstString, bool>>(names), + name_of_error); } lldb::ValueObjectSP -ValueObject::GetChildAtNamePath (const std::vector<ConstString> &names, - ConstString* name_of_error) -{ - if (names.size() == 0) - return GetSP(); - ValueObjectSP root(GetSP()); - for (ConstString name : names) - { - root = root->GetChildMemberWithName(name, true); - if (!root) - { - if (name_of_error) - *name_of_error = name; - return root; - } +ValueObject::GetChildAtNamePath(const std::vector<ConstString> &names, + ConstString *name_of_error) { + if (names.size() == 0) + return GetSP(); + ValueObjectSP root(GetSP()); + for (ConstString name : names) { + root = root->GetChildMemberWithName(name, true); + if (!root) { + if (name_of_error) + *name_of_error = name; + return root; + } + } + return root; +} + +lldb::ValueObjectSP ValueObject::GetChildAtNamePath( + const std::vector<std::pair<ConstString, bool>> &names, + ConstString *name_of_error) { + if (names.size() == 0) + return GetSP(); + ValueObjectSP root(GetSP()); + for (std::pair<ConstString, bool> name : names) { + root = root->GetChildMemberWithName(name.first, name.second); + if (!root) { + if (name_of_error) + *name_of_error = name.first; + return root; } - return root; + } + return root; } -lldb::ValueObjectSP -ValueObject::GetChildAtNamePath (const std::vector< std::pair<ConstString, bool> > &names, - ConstString* name_of_error) -{ - if (names.size() == 0) - return GetSP(); - ValueObjectSP root(GetSP()); - for (std::pair<ConstString, bool> name : names) - { - root = root->GetChildMemberWithName(name.first, name.second); - if (!root) - { - if (name_of_error) - *name_of_error = name.first; - return root; - } - } - return root; +size_t ValueObject::GetIndexOfChildWithName(const ConstString &name) { + bool omit_empty_base_classes = true; + return GetCompilerType().GetIndexOfChildWithName(name.GetCString(), + omit_empty_base_classes); } -size_t -ValueObject::GetIndexOfChildWithName (const ConstString &name) -{ - bool omit_empty_base_classes = true; - return GetCompilerType().GetIndexOfChildWithName (name.GetCString(), omit_empty_base_classes); +ValueObjectSP ValueObject::GetChildMemberWithName(const ConstString &name, + bool can_create) { + // when getting a child by name, it could be buried inside some base + // classes (which really aren't part of the expression path), so we + // need a vector of indexes that can get us down to the correct child + ValueObjectSP child_sp; + + // We may need to update our value if we are dynamic + if (IsPossibleDynamicType()) + UpdateValueIfNeeded(false); + + std::vector<uint32_t> child_indexes; + bool omit_empty_base_classes = true; + const size_t num_child_indexes = + GetCompilerType().GetIndexOfChildMemberWithName( + name.GetCString(), omit_empty_base_classes, child_indexes); + if (num_child_indexes > 0) { + std::vector<uint32_t>::const_iterator pos = child_indexes.begin(); + std::vector<uint32_t>::const_iterator end = child_indexes.end(); + + child_sp = GetChildAtIndex(*pos, can_create); + for (++pos; pos != end; ++pos) { + if (child_sp) { + ValueObjectSP new_child_sp(child_sp->GetChildAtIndex(*pos, can_create)); + child_sp = new_child_sp; + } else { + child_sp.reset(); + } + } + } + return child_sp; +} + +size_t ValueObject::GetNumChildren(uint32_t max) { + UpdateValueIfNeeded(); + + if (max < UINT32_MAX) { + if (m_children_count_valid) { + size_t children_count = m_children.GetChildrenCount(); + return children_count <= max ? children_count : max; + } else + return CalculateNumChildren(max); + } + + if (!m_children_count_valid) { + SetNumChildren(CalculateNumChildren()); + } + return m_children.GetChildrenCount(); +} + +bool ValueObject::MightHaveChildren() { + bool has_children = false; + const uint32_t type_info = GetTypeInfo(); + if (type_info) { + if (type_info & (eTypeHasChildren | eTypeIsPointer | eTypeIsReference)) + has_children = true; + } else { + has_children = GetNumChildren() > 0; + } + return has_children; } -ValueObjectSP -ValueObject::GetChildMemberWithName (const ConstString &name, bool can_create) -{ - // when getting a child by name, it could be buried inside some base - // classes (which really aren't part of the expression path), so we - // need a vector of indexes that can get us down to the correct child - ValueObjectSP child_sp; - - // We may need to update our value if we are dynamic - if (IsPossibleDynamicType ()) - UpdateValueIfNeeded(false); - - std::vector<uint32_t> child_indexes; - bool omit_empty_base_classes = true; - const size_t num_child_indexes = GetCompilerType().GetIndexOfChildMemberWithName (name.GetCString(), - omit_empty_base_classes, - child_indexes); - if (num_child_indexes > 0) - { - std::vector<uint32_t>::const_iterator pos = child_indexes.begin (); - std::vector<uint32_t>::const_iterator end = child_indexes.end (); +// Should only be called by ValueObject::GetNumChildren() +void ValueObject::SetNumChildren(size_t num_children) { + m_children_count_valid = true; + m_children.SetChildrenCount(num_children); +} + +void ValueObject::SetName(const ConstString &name) { m_name = name; } + +ValueObject *ValueObject::CreateChildAtIndex(size_t idx, + bool synthetic_array_member, + int32_t synthetic_index) { + ValueObject *valobj = NULL; + + bool omit_empty_base_classes = true; + bool ignore_array_bounds = synthetic_array_member; + std::string child_name_str; + uint32_t child_byte_size = 0; + int32_t child_byte_offset = 0; + uint32_t child_bitfield_bit_size = 0; + uint32_t child_bitfield_bit_offset = 0; + bool child_is_base_class = false; + bool child_is_deref_of_parent = false; + uint64_t language_flags = 0; + + const bool transparent_pointers = synthetic_array_member == false; + CompilerType child_compiler_type; + + ExecutionContext exe_ctx(GetExecutionContextRef()); + + child_compiler_type = GetCompilerType().GetChildCompilerTypeAtIndex( + &exe_ctx, idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset, + child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, + child_is_deref_of_parent, this, language_flags); + if (child_compiler_type) { + if (synthetic_index) + child_byte_offset += child_byte_size * synthetic_index; + + ConstString child_name; + if (!child_name_str.empty()) + child_name.SetCString(child_name_str.c_str()); + + valobj = new ValueObjectChild( + *this, child_compiler_type, child_name, child_byte_size, + child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, + child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid, + language_flags); + // if (valobj) + // valobj->SetAddressTypeOfChildren(eAddressTypeInvalid); + } + + return valobj; +} + +bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr, + std::string &destination, + lldb::LanguageType lang) { + return GetSummaryAsCString(summary_ptr, destination, + TypeSummaryOptions().SetLanguage(lang)); +} + +bool ValueObject::GetSummaryAsCString(TypeSummaryImpl *summary_ptr, + std::string &destination, + const TypeSummaryOptions &options) { + destination.clear(); + + // ideally we would like to bail out if passing NULL, but if we do so + // we end up not providing the summary for function pointers anymore + if (/*summary_ptr == NULL ||*/ m_is_getting_summary) + return false; - child_sp = GetChildAtIndex(*pos, can_create); - for (++pos; pos != end; ++pos) - { - if (child_sp) - { - ValueObjectSP new_child_sp(child_sp->GetChildAtIndex (*pos, can_create)); - child_sp = new_child_sp; - } - else - { - child_sp.reset(); - } + m_is_getting_summary = true; + + TypeSummaryOptions actual_options(options); + + if (actual_options.GetLanguage() == lldb::eLanguageTypeUnknown) + actual_options.SetLanguage(GetPreferredDisplayLanguage()); + + // this is a hot path in code and we prefer to avoid setting this string all + // too often also clearing out other + // information that we might care to see in a crash log. might be useful in + // very specific situations though. + /*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s. + Summary provider's description is %s", + GetTypeName().GetCString(), + GetName().GetCString(), + summary_ptr->GetDescription().c_str());*/ + + if (UpdateValueIfNeeded(false) && summary_ptr) { + if (HasSyntheticValue()) + m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on + // the synthetic children being + // up-to-date (e.g. ${svar%#}) + summary_ptr->FormatObject(this, destination, actual_options); + } + m_is_getting_summary = false; + return !destination.empty(); +} + +const char *ValueObject::GetSummaryAsCString(lldb::LanguageType lang) { + if (UpdateValueIfNeeded(true) && m_summary_str.empty()) { + TypeSummaryOptions summary_options; + summary_options.SetLanguage(lang); + GetSummaryAsCString(GetSummaryFormat().get(), m_summary_str, + summary_options); + } + if (m_summary_str.empty()) + return NULL; + return m_summary_str.c_str(); +} - } - } - return child_sp; +bool ValueObject::GetSummaryAsCString(std::string &destination, + const TypeSummaryOptions &options) { + return GetSummaryAsCString(GetSummaryFormat().get(), destination, options); } +bool ValueObject::IsCStringContainer(bool check_pointer) { + CompilerType pointee_or_element_compiler_type; + const Flags type_flags(GetTypeInfo(&pointee_or_element_compiler_type)); + bool is_char_arr_ptr(type_flags.AnySet(eTypeIsArray | eTypeIsPointer) && + pointee_or_element_compiler_type.IsCharType()); + if (!is_char_arr_ptr) + return false; + if (!check_pointer) + return true; + if (type_flags.Test(eTypeIsArray)) + return true; + addr_t cstr_address = LLDB_INVALID_ADDRESS; + AddressType cstr_address_type = eAddressTypeInvalid; + cstr_address = GetAddressOf(true, &cstr_address_type); + return (cstr_address != LLDB_INVALID_ADDRESS); +} + +size_t ValueObject::GetPointeeData(DataExtractor &data, uint32_t item_idx, + uint32_t item_count) { + CompilerType pointee_or_element_compiler_type; + const uint32_t type_info = GetTypeInfo(&pointee_or_element_compiler_type); + const bool is_pointer_type = type_info & eTypeIsPointer; + const bool is_array_type = type_info & eTypeIsArray; + if (!(is_pointer_type || is_array_type)) + return 0; -size_t -ValueObject::GetNumChildren (uint32_t max) -{ - UpdateValueIfNeeded(); + if (item_count == 0) + return 0; - if (max < UINT32_MAX) - { - if (m_children_count_valid) - { - size_t children_count = m_children.GetChildrenCount(); - return children_count <= max ? children_count : max; - } - else - return CalculateNumChildren(max); - } + ExecutionContext exe_ctx(GetExecutionContextRef()); - if (!m_children_count_valid) - { - SetNumChildren (CalculateNumChildren()); - } - return m_children.GetChildrenCount(); -} + const uint64_t item_type_size = pointee_or_element_compiler_type.GetByteSize( + exe_ctx.GetBestExecutionContextScope()); + const uint64_t bytes = item_count * item_type_size; + const uint64_t offset = item_idx * item_type_size; -bool -ValueObject::MightHaveChildren() -{ - bool has_children = false; - const uint32_t type_info = GetTypeInfo(); - if (type_info) - { - if (type_info & (eTypeHasChildren | - eTypeIsPointer | - eTypeIsReference)) - has_children = true; - } - else - { - has_children = GetNumChildren () > 0; + if (item_idx == 0 && item_count == 1) // simply a deref + { + if (is_pointer_type) { + Error error; + ValueObjectSP pointee_sp = Dereference(error); + if (error.Fail() || pointee_sp.get() == NULL) + return 0; + return pointee_sp->GetData(data, error); + } else { + ValueObjectSP child_sp = GetChildAtIndex(0, true); + if (child_sp.get() == NULL) + return 0; + Error error; + return child_sp->GetData(data, error); } - return has_children; -} + return true; + } else /* (items > 1) */ + { + Error error; + lldb_private::DataBufferHeap *heap_buf_ptr = NULL; + lldb::DataBufferSP data_sp(heap_buf_ptr = + new lldb_private::DataBufferHeap()); + + AddressType addr_type; + lldb::addr_t addr = is_pointer_type ? GetPointerValue(&addr_type) + : GetAddressOf(true, &addr_type); + + switch (addr_type) { + case eAddressTypeFile: { + ModuleSP module_sp(GetModule()); + if (module_sp) { + addr = addr + offset; + Address so_addr; + module_sp->ResolveFileAddress(addr, so_addr); + ExecutionContext exe_ctx(GetExecutionContextRef()); + Target *target = exe_ctx.GetTargetPtr(); + if (target) { + heap_buf_ptr->SetByteSize(bytes); + size_t bytes_read = target->ReadMemory( + so_addr, false, heap_buf_ptr->GetBytes(), bytes, error); + if (error.Success()) { + data.SetData(data_sp); + return bytes_read; + } + } + } + } break; + case eAddressTypeLoad: { + ExecutionContext exe_ctx(GetExecutionContextRef()); + Process *process = exe_ctx.GetProcessPtr(); + if (process) { + heap_buf_ptr->SetByteSize(bytes); + size_t bytes_read = process->ReadMemory( + addr + offset, heap_buf_ptr->GetBytes(), bytes, error); + if (error.Success() || bytes_read > 0) { + data.SetData(data_sp); + return bytes_read; + } + } + } break; + case eAddressTypeHost: { + const uint64_t max_bytes = + GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope()); + if (max_bytes > offset) { + size_t bytes_read = std::min<uint64_t>(max_bytes - offset, bytes); + addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + if (addr == 0 || addr == LLDB_INVALID_ADDRESS) + break; + heap_buf_ptr->CopyData((uint8_t *)(addr + offset), bytes_read); + data.SetData(data_sp); + return bytes_read; + } + } break; + case eAddressTypeInvalid: + break; + } + } + return 0; +} + +uint64_t ValueObject::GetData(DataExtractor &data, Error &error) { + UpdateValueIfNeeded(false); + ExecutionContext exe_ctx(GetExecutionContextRef()); + error = m_value.GetValueAsData(&exe_ctx, data, 0, GetModule().get()); + if (error.Fail()) { + if (m_data.GetByteSize()) { + data = m_data; + error.Clear(); + return data.GetByteSize(); + } else { + return 0; + } + } + data.SetAddressByteSize(m_data.GetAddressByteSize()); + data.SetByteOrder(m_data.GetByteOrder()); + return data.GetByteSize(); +} + +bool ValueObject::SetData(DataExtractor &data, Error &error) { + error.Clear(); + // Make sure our value is up to date first so that our location and location + // type is valid. + if (!UpdateValueIfNeeded(false)) { + error.SetErrorString("unable to read value"); + return false; + } -// Should only be called by ValueObject::GetNumChildren() -void -ValueObject::SetNumChildren (size_t num_children) -{ - m_children_count_valid = true; - m_children.SetChildrenCount(num_children); -} + uint64_t count = 0; + const Encoding encoding = GetCompilerType().GetEncoding(count); -void -ValueObject::SetName (const ConstString &name) -{ - m_name = name; -} + const size_t byte_size = GetByteSize(); -ValueObject * -ValueObject::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index) -{ - ValueObject *valobj = NULL; - - bool omit_empty_base_classes = true; - bool ignore_array_bounds = synthetic_array_member; - std::string child_name_str; - uint32_t child_byte_size = 0; - int32_t child_byte_offset = 0; - uint32_t child_bitfield_bit_size = 0; - uint32_t child_bitfield_bit_offset = 0; - bool child_is_base_class = false; - bool child_is_deref_of_parent = false; - uint64_t language_flags = 0; + Value::ValueType value_type = m_value.GetValueType(); - const bool transparent_pointers = synthetic_array_member == false; - CompilerType child_compiler_type; - - ExecutionContext exe_ctx (GetExecutionContextRef()); - - child_compiler_type = GetCompilerType().GetChildCompilerTypeAtIndex(&exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name_str, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent, - this, - language_flags); - if (child_compiler_type) - { - if (synthetic_index) - child_byte_offset += child_byte_size * synthetic_index; - - ConstString child_name; - if (!child_name_str.empty()) - child_name.SetCString (child_name_str.c_str()); - - valobj = new ValueObjectChild (*this, - child_compiler_type, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent, - eAddressTypeInvalid, - language_flags); - //if (valobj) - // valobj->SetAddressTypeOfChildren(eAddressTypeInvalid); - } - - return valobj; -} + switch (value_type) { + case Value::eValueTypeScalar: { + Error set_error = + m_value.GetScalar().SetValueFromData(data, encoding, byte_size); -bool -ValueObject::GetSummaryAsCString (TypeSummaryImpl* summary_ptr, - std::string& destination, - lldb::LanguageType lang) -{ - return GetSummaryAsCString(summary_ptr, destination, TypeSummaryOptions().SetLanguage(lang)); -} - -bool -ValueObject::GetSummaryAsCString (TypeSummaryImpl* summary_ptr, - std::string& destination, - const TypeSummaryOptions& options) -{ - destination.clear(); - - // ideally we would like to bail out if passing NULL, but if we do so - // we end up not providing the summary for function pointers anymore - if (/*summary_ptr == NULL ||*/ m_is_getting_summary) - return false; - - m_is_getting_summary = true; - - TypeSummaryOptions actual_options(options); - - if (actual_options.GetLanguage() == lldb::eLanguageTypeUnknown) - actual_options.SetLanguage(GetPreferredDisplayLanguage()); - - // this is a hot path in code and we prefer to avoid setting this string all too often also clearing out other - // information that we might care to see in a crash log. might be useful in very specific situations though. - /*Host::SetCrashDescriptionWithFormat("Trying to fetch a summary for %s %s. Summary provider's description is %s", - GetTypeName().GetCString(), - GetName().GetCString(), - summary_ptr->GetDescription().c_str());*/ - - if (UpdateValueIfNeeded (false) && summary_ptr) - { - if (HasSyntheticValue()) - m_synthetic_value->UpdateValueIfNeeded(); // the summary might depend on the synthetic children being up-to-date (e.g. ${svar%#}) - summary_ptr->FormatObject(this, destination, actual_options); + if (!set_error.Success()) { + error.SetErrorStringWithFormat("unable to set scalar value: %s", + set_error.AsCString()); + return false; } - m_is_getting_summary = false; - return !destination.empty(); -} + } break; + case Value::eValueTypeLoadAddress: { + // If it is a load address, then the scalar value is the storage location + // of the data, and we have to shove this value down to that load location. + ExecutionContext exe_ctx(GetExecutionContextRef()); + Process *process = exe_ctx.GetProcessPtr(); + if (process) { + addr_t target_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + size_t bytes_written = process->WriteMemory( + target_addr, data.GetDataStart(), byte_size, error); + if (!error.Success()) + return false; + if (bytes_written != byte_size) { + error.SetErrorString("unable to write value to memory"); + return false; + } + } + } break; + case Value::eValueTypeHostAddress: { + // If it is a host address, then we stuff the scalar as a DataBuffer into + // the Value's data. + DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0)); + m_data.SetData(buffer_sp, 0); + data.CopyByteOrderedData(0, byte_size, + const_cast<uint8_t *>(m_data.GetDataStart()), + byte_size, m_data.GetByteOrder()); + m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); + } break; + case Value::eValueTypeFileAddress: + case Value::eValueTypeVector: + break; + } + + // If we have reached this point, then we have successfully changed the value. + SetNeedsUpdate(); + return true; +} + +static bool CopyStringDataToBufferSP(const StreamString &source, + lldb::DataBufferSP &destination) { + destination.reset(new DataBufferHeap(source.GetSize() + 1, 0)); + memcpy(destination->GetBytes(), source.GetString().data(), source.GetSize()); + return true; +} + +std::pair<size_t, bool> +ValueObject::ReadPointedString(lldb::DataBufferSP &buffer_sp, Error &error, + uint32_t max_length, bool honor_array, + Format item_format) { + bool was_capped = false; + StreamString s; + ExecutionContext exe_ctx(GetExecutionContextRef()); + Target *target = exe_ctx.GetTargetPtr(); + + if (!target) { + s << "<no target to read from>"; + error.SetErrorString("no target to read from"); + CopyStringDataToBufferSP(s, buffer_sp); + return {0, was_capped}; + } -const char * -ValueObject::GetSummaryAsCString (lldb::LanguageType lang) -{ - if (UpdateValueIfNeeded(true) && m_summary_str.empty()) - { - TypeSummaryOptions summary_options; - summary_options.SetLanguage(lang); - GetSummaryAsCString(GetSummaryFormat().get(), - m_summary_str, - summary_options); - } - if (m_summary_str.empty()) - return NULL; - return m_summary_str.c_str(); -} + if (max_length == 0) + max_length = target->GetMaximumSizeOfStringSummary(); -bool -ValueObject::GetSummaryAsCString (std::string& destination, - const TypeSummaryOptions& options) -{ - return GetSummaryAsCString(GetSummaryFormat().get(), - destination, - options); -} + size_t bytes_read = 0; + size_t total_bytes_read = 0; -bool -ValueObject::IsCStringContainer(bool check_pointer) -{ - CompilerType pointee_or_element_compiler_type; - const Flags type_flags (GetTypeInfo (&pointee_or_element_compiler_type)); - bool is_char_arr_ptr (type_flags.AnySet (eTypeIsArray | eTypeIsPointer) && - pointee_or_element_compiler_type.IsCharType ()); - if (!is_char_arr_ptr) - return false; - if (!check_pointer) - return true; - if (type_flags.Test(eTypeIsArray)) - return true; + CompilerType compiler_type = GetCompilerType(); + CompilerType elem_or_pointee_compiler_type; + const Flags type_flags(GetTypeInfo(&elem_or_pointee_compiler_type)); + if (type_flags.AnySet(eTypeIsArray | eTypeIsPointer) && + elem_or_pointee_compiler_type.IsCharType()) { addr_t cstr_address = LLDB_INVALID_ADDRESS; AddressType cstr_address_type = eAddressTypeInvalid; - cstr_address = GetAddressOf (true, &cstr_address_type); - return (cstr_address != LLDB_INVALID_ADDRESS); -} -size_t -ValueObject::GetPointeeData (DataExtractor& data, - uint32_t item_idx, - uint32_t item_count) -{ - CompilerType pointee_or_element_compiler_type; - const uint32_t type_info = GetTypeInfo (&pointee_or_element_compiler_type); - const bool is_pointer_type = type_info & eTypeIsPointer; - const bool is_array_type = type_info & eTypeIsArray; - if (!(is_pointer_type || is_array_type)) - return 0; - - if (item_count == 0) - return 0; - - ExecutionContext exe_ctx (GetExecutionContextRef()); - - const uint64_t item_type_size = pointee_or_element_compiler_type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); - const uint64_t bytes = item_count * item_type_size; - const uint64_t offset = item_idx * item_type_size; - - if (item_idx == 0 && item_count == 1) // simply a deref - { - if (is_pointer_type) - { - Error error; - ValueObjectSP pointee_sp = Dereference(error); - if (error.Fail() || pointee_sp.get() == NULL) - return 0; - return pointee_sp->GetData(data, error); - } - else - { - ValueObjectSP child_sp = GetChildAtIndex(0, true); - if (child_sp.get() == NULL) - return 0; - Error error; - return child_sp->GetData(data, error); - } - return true; - } - else /* (items > 1) */ - { - Error error; - lldb_private::DataBufferHeap* heap_buf_ptr = NULL; - lldb::DataBufferSP data_sp(heap_buf_ptr = new lldb_private::DataBufferHeap()); - - AddressType addr_type; - lldb::addr_t addr = is_pointer_type ? GetPointerValue(&addr_type) : GetAddressOf(true, &addr_type); - - switch (addr_type) - { - case eAddressTypeFile: - { - ModuleSP module_sp (GetModule()); - if (module_sp) - { - addr = addr + offset; - Address so_addr; - module_sp->ResolveFileAddress(addr, so_addr); - ExecutionContext exe_ctx (GetExecutionContextRef()); - Target* target = exe_ctx.GetTargetPtr(); - if (target) - { - heap_buf_ptr->SetByteSize(bytes); - size_t bytes_read = target->ReadMemory(so_addr, false, heap_buf_ptr->GetBytes(), bytes, error); - if (error.Success()) - { - data.SetData(data_sp); - return bytes_read; - } - } - } - } - break; - case eAddressTypeLoad: - { - ExecutionContext exe_ctx (GetExecutionContextRef()); - Process *process = exe_ctx.GetProcessPtr(); - if (process) - { - heap_buf_ptr->SetByteSize(bytes); - size_t bytes_read = process->ReadMemory(addr + offset, heap_buf_ptr->GetBytes(), bytes, error); - if (error.Success() || bytes_read > 0) - { - data.SetData(data_sp); - return bytes_read; - } - } - } - break; - case eAddressTypeHost: - { - const uint64_t max_bytes = GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope()); - if (max_bytes > offset) - { - size_t bytes_read = std::min<uint64_t>(max_bytes - offset, bytes); - addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - if (addr == 0 || addr == LLDB_INVALID_ADDRESS) - break; - heap_buf_ptr->CopyData((uint8_t*)(addr + offset), bytes_read); - data.SetData(data_sp); - return bytes_read; - } - } - break; - case eAddressTypeInvalid: - break; - } - } - return 0; -} + size_t cstr_len = 0; + bool capped_data = false; + const bool is_array = type_flags.Test(eTypeIsArray); + if (is_array) { + // We have an array + uint64_t array_size = 0; + if (compiler_type.IsArrayType(NULL, &array_size, NULL)) { + cstr_len = array_size; + if (cstr_len > max_length) { + capped_data = true; + cstr_len = max_length; + } + } + cstr_address = GetAddressOf(true, &cstr_address_type); + } else { + // We have a pointer + cstr_address = GetPointerValue(&cstr_address_type); + } + + if (cstr_address == 0 || cstr_address == LLDB_INVALID_ADDRESS) { + if (cstr_address_type == eAddressTypeHost && is_array) { + const char *cstr = GetDataExtractor().PeekCStr(0); + if (cstr == nullptr) { + s << "<invalid address>"; + error.SetErrorString("invalid address"); + CopyStringDataToBufferSP(s, buffer_sp); + return {0, was_capped}; + } + buffer_sp.reset(new DataBufferHeap(cstr_len, 0)); + memcpy(buffer_sp->GetBytes(), cstr, cstr_len); + return {cstr_len, was_capped}; + } else { + s << "<invalid address>"; + error.SetErrorString("invalid address"); + CopyStringDataToBufferSP(s, buffer_sp); + return {0, was_capped}; + } + } + + Address cstr_so_addr(cstr_address); + DataExtractor data; + if (cstr_len > 0 && honor_array) { + // I am using GetPointeeData() here to abstract the fact that some + // ValueObjects are actually frozen pointers in the host + // but the pointed-to data lives in the debuggee, and GetPointeeData() + // automatically takes care of this + GetPointeeData(data, 0, cstr_len); + + if ((bytes_read = data.GetByteSize()) > 0) { + total_bytes_read = bytes_read; + for (size_t offset = 0; offset < bytes_read; offset++) + s.Printf("%c", *data.PeekData(offset, 1)); + if (capped_data) + was_capped = true; + } + } else { + cstr_len = max_length; + const size_t k_max_buf_size = 64; + + size_t offset = 0; + + int cstr_len_displayed = -1; + bool capped_cstr = false; + // I am using GetPointeeData() here to abstract the fact that some + // ValueObjects are actually frozen pointers in the host + // but the pointed-to data lives in the debuggee, and GetPointeeData() + // automatically takes care of this + while ((bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0) { + total_bytes_read += bytes_read; + const char *cstr = data.PeekCStr(0); + size_t len = strnlen(cstr, k_max_buf_size); + if (cstr_len_displayed < 0) + cstr_len_displayed = len; + + if (len == 0) + break; + cstr_len_displayed += len; + if (len > bytes_read) + len = bytes_read; + if (len > cstr_len) + len = cstr_len; + + for (size_t offset = 0; offset < bytes_read; offset++) + s.Printf("%c", *data.PeekData(offset, 1)); + + if (len < k_max_buf_size) + break; + + if (len >= cstr_len) { + capped_cstr = true; + break; + } + + cstr_len -= len; + offset += len; + } + + if (cstr_len_displayed >= 0) { + if (capped_cstr) + was_capped = true; + } + } + } else { + error.SetErrorString("not a string object"); + s << "<not a string object>"; + } + CopyStringDataToBufferSP(s, buffer_sp); + return {total_bytes_read, was_capped}; +} + +std::pair<TypeValidatorResult, std::string> ValueObject::GetValidationStatus() { + if (!UpdateValueIfNeeded(true)) + return {TypeValidatorResult::Success, + ""}; // not the validator's job to discuss update problems + + if (m_validation_result.hasValue()) + return m_validation_result.getValue(); + + if (!m_type_validator_sp) + return {TypeValidatorResult::Success, ""}; // no validator no failure + + auto outcome = m_type_validator_sp->FormatObject(this); + + return (m_validation_result = {outcome.m_result, outcome.m_message}) + .getValue(); +} + +const char *ValueObject::GetObjectDescription() { + + if (!UpdateValueIfNeeded(true)) + return NULL; -uint64_t -ValueObject::GetData (DataExtractor& data, Error &error) -{ - UpdateValueIfNeeded(false); - ExecutionContext exe_ctx (GetExecutionContextRef()); - error = m_value.GetValueAsData(&exe_ctx, data, 0, GetModule().get()); - if (error.Fail()) - { - if (m_data.GetByteSize()) - { - data = m_data; - error.Clear(); - return data.GetByteSize(); - } - else - { - return 0; - } - } - data.SetAddressByteSize(m_data.GetAddressByteSize()); - data.SetByteOrder(m_data.GetByteOrder()); - return data.GetByteSize(); -} + if (!m_object_desc_str.empty()) + return m_object_desc_str.c_str(); -bool -ValueObject::SetData (DataExtractor &data, Error &error) -{ - error.Clear(); - // Make sure our value is up to date first so that our location and location - // type is valid. - if (!UpdateValueIfNeeded(false)) - { - error.SetErrorString("unable to read value"); - return false; - } - - uint64_t count = 0; - const Encoding encoding = GetCompilerType().GetEncoding(count); - - const size_t byte_size = GetByteSize(); - - Value::ValueType value_type = m_value.GetValueType(); - - switch (value_type) - { - case Value::eValueTypeScalar: - { - Error set_error = m_value.GetScalar().SetValueFromData(data, encoding, byte_size); - - if (!set_error.Success()) - { - error.SetErrorStringWithFormat("unable to set scalar value: %s", set_error.AsCString()); - return false; - } - } - break; - case Value::eValueTypeLoadAddress: - { - // If it is a load address, then the scalar value is the storage location - // of the data, and we have to shove this value down to that load location. - ExecutionContext exe_ctx (GetExecutionContextRef()); - Process *process = exe_ctx.GetProcessPtr(); - if (process) - { - addr_t target_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - size_t bytes_written = process->WriteMemory(target_addr, - data.GetDataStart(), - byte_size, - error); - if (!error.Success()) - return false; - if (bytes_written != byte_size) - { - error.SetErrorString("unable to write value to memory"); - return false; - } - } - } - break; - case Value::eValueTypeHostAddress: - { - // If it is a host address, then we stuff the scalar as a DataBuffer into the Value's data. - DataBufferSP buffer_sp (new DataBufferHeap(byte_size, 0)); - m_data.SetData(buffer_sp, 0); - data.CopyByteOrderedData (0, - byte_size, - const_cast<uint8_t *>(m_data.GetDataStart()), - byte_size, - m_data.GetByteOrder()); - m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); - } - break; - case Value::eValueTypeFileAddress: - case Value::eValueTypeVector: - break; - } - - // If we have reached this point, then we have successfully changed the value. - SetNeedsUpdate(); - return true; -} + ExecutionContext exe_ctx(GetExecutionContextRef()); + Process *process = exe_ctx.GetProcessPtr(); + if (process == NULL) + return NULL; -static bool -CopyStringDataToBufferSP(const StreamString& source, - lldb::DataBufferSP& destination) -{ - destination.reset(new DataBufferHeap(source.GetSize()+1,0)); - memcpy(destination->GetBytes(), source.GetString().c_str(), source.GetSize()); - return true; -} + StreamString s; -std::pair<size_t,bool> -ValueObject::ReadPointedString (lldb::DataBufferSP& buffer_sp, - Error& error, - uint32_t max_length, - bool honor_array, - Format item_format) -{ - bool was_capped = false; - StreamString s; - ExecutionContext exe_ctx (GetExecutionContextRef()); - Target* target = exe_ctx.GetTargetPtr(); - - if (!target) - { - s << "<no target to read from>"; - error.SetErrorString("no target to read from"); - CopyStringDataToBufferSP(s, buffer_sp); - return {0,was_capped}; - } - - if (max_length == 0) - max_length = target->GetMaximumSizeOfStringSummary(); - - size_t bytes_read = 0; - size_t total_bytes_read = 0; - + LanguageType language = GetObjectRuntimeLanguage(); + LanguageRuntime *runtime = process->GetLanguageRuntime(language); + + if (runtime == NULL) { + // Aw, hell, if the things a pointer, or even just an integer, let's try + // ObjC anyway... CompilerType compiler_type = GetCompilerType(); - CompilerType elem_or_pointee_compiler_type; - const Flags type_flags (GetTypeInfo (&elem_or_pointee_compiler_type)); - if (type_flags.AnySet (eTypeIsArray | eTypeIsPointer) && - elem_or_pointee_compiler_type.IsCharType ()) - { - addr_t cstr_address = LLDB_INVALID_ADDRESS; - AddressType cstr_address_type = eAddressTypeInvalid; - - size_t cstr_len = 0; - bool capped_data = false; - if (type_flags.Test (eTypeIsArray)) - { - // We have an array - uint64_t array_size = 0; - if (compiler_type.IsArrayType(NULL, &array_size, NULL)) - { - cstr_len = array_size; - if (cstr_len > max_length) - { - capped_data = true; - cstr_len = max_length; - } - } - cstr_address = GetAddressOf (true, &cstr_address_type); - } - else - { - // We have a pointer - cstr_address = GetPointerValue (&cstr_address_type); - } - - if (cstr_address == 0 || cstr_address == LLDB_INVALID_ADDRESS) - { - s << "<invalid address>"; - error.SetErrorString("invalid address"); - CopyStringDataToBufferSP(s, buffer_sp); - return {0,was_capped}; - } - - Address cstr_so_addr (cstr_address); - DataExtractor data; - if (cstr_len > 0 && honor_array) - { - // I am using GetPointeeData() here to abstract the fact that some ValueObjects are actually frozen pointers in the host - // but the pointed-to data lives in the debuggee, and GetPointeeData() automatically takes care of this - GetPointeeData(data, 0, cstr_len); - - if ((bytes_read = data.GetByteSize()) > 0) - { - total_bytes_read = bytes_read; - for (size_t offset = 0; offset < bytes_read; offset++) - s.Printf("%c", *data.PeekData(offset, 1)); - if (capped_data) - was_capped = true; - } - } - else - { - cstr_len = max_length; - const size_t k_max_buf_size = 64; - - size_t offset = 0; - - int cstr_len_displayed = -1; - bool capped_cstr = false; - // I am using GetPointeeData() here to abstract the fact that some ValueObjects are actually frozen pointers in the host - // but the pointed-to data lives in the debuggee, and GetPointeeData() automatically takes care of this - while ((bytes_read = GetPointeeData(data, offset, k_max_buf_size)) > 0) - { - total_bytes_read += bytes_read; - const char *cstr = data.PeekCStr(0); - size_t len = strnlen (cstr, k_max_buf_size); - if (cstr_len_displayed < 0) - cstr_len_displayed = len; - - if (len == 0) - break; - cstr_len_displayed += len; - if (len > bytes_read) - len = bytes_read; - if (len > cstr_len) - len = cstr_len; - - for (size_t offset = 0; offset < bytes_read; offset++) - s.Printf("%c", *data.PeekData(offset, 1)); - - if (len < k_max_buf_size) - break; - - if (len >= cstr_len) - { - capped_cstr = true; - break; - } - - cstr_len -= len; - offset += len; - } - - if (cstr_len_displayed >= 0) - { - if (capped_cstr) - was_capped = true; - } - } + if (compiler_type) { + bool is_signed; + if (compiler_type.IsIntegerType(is_signed) || + compiler_type.IsPointerType()) { + runtime = process->GetLanguageRuntime(eLanguageTypeObjC); + } } - else - { - error.SetErrorString("not a string object"); - s << "<not a string object>"; - } - CopyStringDataToBufferSP(s, buffer_sp); - return {total_bytes_read,was_capped}; + } + + if (runtime && runtime->GetObjectDescription(s, *this)) { + m_object_desc_str.append(s.GetString()); + } + + if (m_object_desc_str.empty()) + return NULL; + else + return m_object_desc_str.c_str(); } -std::pair<TypeValidatorResult, std::string> -ValueObject::GetValidationStatus () -{ - if (!UpdateValueIfNeeded(true)) - return {TypeValidatorResult::Success,""}; // not the validator's job to discuss update problems - - if (m_validation_result.hasValue()) - return m_validation_result.getValue(); - - if (!m_type_validator_sp) - return {TypeValidatorResult::Success,""}; // no validator no failure - - auto outcome = m_type_validator_sp->FormatObject(this); - - return (m_validation_result = {outcome.m_result,outcome.m_message}).getValue(); +bool ValueObject::GetValueAsCString(const lldb_private::TypeFormatImpl &format, + std::string &destination) { + if (UpdateValueIfNeeded(false)) + return format.FormatObject(this, destination); + else + return false; } -const char * -ValueObject::GetObjectDescription () -{ - - if (!UpdateValueIfNeeded (true)) - return NULL; +bool ValueObject::GetValueAsCString(lldb::Format format, + std::string &destination) { + return GetValueAsCString(TypeFormatImpl_Format(format), destination); +} + +const char *ValueObject::GetValueAsCString() { + if (UpdateValueIfNeeded(true)) { + lldb::TypeFormatImplSP format_sp; + lldb::Format my_format = GetFormat(); + if (my_format == lldb::eFormatDefault) { + if (m_type_format_sp) + format_sp = m_type_format_sp; + else { + if (m_is_bitfield_for_scalar) + my_format = eFormatUnsigned; + else { + if (m_value.GetContextType() == Value::eContextTypeRegisterInfo) { + const RegisterInfo *reg_info = m_value.GetRegisterInfo(); + if (reg_info) + my_format = reg_info->format; + } else { + my_format = GetValue().GetCompilerType().GetFormat(); + } + } + } + } + if (my_format != m_last_format || m_value_str.empty()) { + m_last_format = my_format; + if (!format_sp) + format_sp.reset(new TypeFormatImpl_Format(my_format)); + if (GetValueAsCString(*format_sp.get(), m_value_str)) { + if (!m_value_did_change && m_old_value_valid) { + // The value was gotten successfully, so we consider the + // value as changed if the value string differs + SetValueDidChange(m_old_value_str != m_value_str); + } + } + } + } + if (m_value_str.empty()) + return NULL; + return m_value_str.c_str(); +} - if (!m_object_desc_str.empty()) - return m_object_desc_str.c_str(); +// if > 8bytes, 0 is returned. this method should mostly be used +// to read address values out of pointers +uint64_t ValueObject::GetValueAsUnsigned(uint64_t fail_value, bool *success) { + // If our byte size is zero this is an aggregate type that has children + if (CanProvideValue()) { + Scalar scalar; + if (ResolveValue(scalar)) { + if (success) + *success = true; + return scalar.ULongLong(fail_value); + } + // fallthrough, otherwise... + } + + if (success) + *success = false; + return fail_value; +} + +int64_t ValueObject::GetValueAsSigned(int64_t fail_value, bool *success) { + // If our byte size is zero this is an aggregate type that has children + if (CanProvideValue()) { + Scalar scalar; + if (ResolveValue(scalar)) { + if (success) + *success = true; + return scalar.SLongLong(fail_value); + } + // fallthrough, otherwise... + } + + if (success) + *success = false; + return fail_value; +} + +// if any more "special cases" are added to +// ValueObject::DumpPrintableRepresentation() please keep +// this call up to date by returning true for your new special cases. We will +// eventually move +// to checking this call result before trying to display special cases +bool ValueObject::HasSpecialPrintableRepresentation( + ValueObjectRepresentationStyle val_obj_display, Format custom_format) { + Flags flags(GetTypeInfo()); + if (flags.AnySet(eTypeIsArray | eTypeIsPointer) && + val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) { + if (IsCStringContainer(true) && + (custom_format == eFormatCString || custom_format == eFormatCharArray || + custom_format == eFormatChar || custom_format == eFormatVectorOfChar)) + return true; + + if (flags.Test(eTypeIsArray)) { + if ((custom_format == eFormatBytes) || + (custom_format == eFormatBytesWithASCII)) + return true; - ExecutionContext exe_ctx (GetExecutionContextRef()); - Process *process = exe_ctx.GetProcessPtr(); - if (process == NULL) - return NULL; - - StreamString s; - - LanguageType language = GetObjectRuntimeLanguage(); - LanguageRuntime *runtime = process->GetLanguageRuntime(language); - - if (runtime == NULL) - { - // Aw, hell, if the things a pointer, or even just an integer, let's try ObjC anyway... - CompilerType compiler_type = GetCompilerType(); - if (compiler_type) - { - bool is_signed; - if (compiler_type.IsIntegerType (is_signed) || compiler_type.IsPointerType ()) - { - runtime = process->GetLanguageRuntime(eLanguageTypeObjC); - } - } - } - - if (runtime && runtime->GetObjectDescription(s, *this)) - { - m_object_desc_str.append (s.GetData()); + if ((custom_format == eFormatVectorOfChar) || + (custom_format == eFormatVectorOfFloat32) || + (custom_format == eFormatVectorOfFloat64) || + (custom_format == eFormatVectorOfSInt16) || + (custom_format == eFormatVectorOfSInt32) || + (custom_format == eFormatVectorOfSInt64) || + (custom_format == eFormatVectorOfSInt8) || + (custom_format == eFormatVectorOfUInt128) || + (custom_format == eFormatVectorOfUInt16) || + (custom_format == eFormatVectorOfUInt32) || + (custom_format == eFormatVectorOfUInt64) || + (custom_format == eFormatVectorOfUInt8)) + return true; } - - if (m_object_desc_str.empty()) - return NULL; - else - return m_object_desc_str.c_str(); + } + return false; } -bool -ValueObject::GetValueAsCString (const lldb_private::TypeFormatImpl& format, - std::string& destination) -{ - if (UpdateValueIfNeeded(false)) - return format.FormatObject(this,destination); - else - return false; -} +bool ValueObject::DumpPrintableRepresentation( + Stream &s, ValueObjectRepresentationStyle val_obj_display, + Format custom_format, PrintableRepresentationSpecialCases special, + bool do_dump_error) { -bool -ValueObject::GetValueAsCString (lldb::Format format, - std::string& destination) -{ - return GetValueAsCString(TypeFormatImpl_Format(format),destination); -} + Flags flags(GetTypeInfo()); -const char * -ValueObject::GetValueAsCString () -{ - if (UpdateValueIfNeeded(true)) - { - lldb::TypeFormatImplSP format_sp; - lldb::Format my_format = GetFormat(); - if (my_format == lldb::eFormatDefault) - { - if (m_type_format_sp) - format_sp = m_type_format_sp; - else - { - if (m_is_bitfield_for_scalar) - my_format = eFormatUnsigned; - else - { - if (m_value.GetContextType() == Value::eContextTypeRegisterInfo) - { - const RegisterInfo *reg_info = m_value.GetRegisterInfo(); - if (reg_info) - my_format = reg_info->format; - } - else - { - my_format = GetValue().GetCompilerType().GetFormat(); - } - } - } - } - if (my_format != m_last_format || m_value_str.empty()) - { - m_last_format = my_format; - if (!format_sp) - format_sp.reset(new TypeFormatImpl_Format(my_format)); - if (GetValueAsCString(*format_sp.get(), m_value_str)) - { - if (!m_value_did_change && m_old_value_valid) - { - // The value was gotten successfully, so we consider the - // value as changed if the value string differs - SetValueDidChange (m_old_value_str != m_value_str); - } - } - } - } - if (m_value_str.empty()) - return NULL; - return m_value_str.c_str(); -} + bool allow_special = + (special == ValueObject::PrintableRepresentationSpecialCases::eAllow); + const bool only_special = false; -// if > 8bytes, 0 is returned. this method should mostly be used -// to read address values out of pointers -uint64_t -ValueObject::GetValueAsUnsigned (uint64_t fail_value, bool *success) -{ - // If our byte size is zero this is an aggregate type that has children - if (CanProvideValue()) - { - Scalar scalar; - if (ResolveValue (scalar)) - { - if (success) - *success = true; - return scalar.ULongLong(fail_value); - } - // fallthrough, otherwise... - } + if (allow_special) { + if (flags.AnySet(eTypeIsArray | eTypeIsPointer) && + val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) { + // when being asked to get a printable display an array or pointer type + // directly, + // try to "do the right thing" - if (success) - *success = false; - return fail_value; -} + if (IsCStringContainer(true) && + (custom_format == eFormatCString || + custom_format == eFormatCharArray || custom_format == eFormatChar || + custom_format == + eFormatVectorOfChar)) // print char[] & char* directly + { + Error error; + lldb::DataBufferSP buffer_sp; + std::pair<size_t, bool> read_string = ReadPointedString( + buffer_sp, error, 0, (custom_format == eFormatVectorOfChar) || + (custom_format == eFormatCharArray)); + lldb_private::formatters::StringPrinter:: + ReadBufferAndDumpToStreamOptions options(*this); + options.SetData(DataExtractor( + buffer_sp, lldb::eByteOrderInvalid, + 8)); // none of this matters for a string - pass some defaults + options.SetStream(&s); + options.SetPrefixToken(0); + options.SetQuote('"'); + options.SetSourceSize(buffer_sp->GetByteSize()); + options.SetIsTruncated(read_string.second); + formatters::StringPrinter::ReadBufferAndDumpToStream< + lldb_private::formatters::StringPrinter::StringElementType::ASCII>( + options); + return !error.Fail(); + } + + if (custom_format == eFormatEnum) + return false; -int64_t -ValueObject::GetValueAsSigned (int64_t fail_value, bool *success) -{ - // If our byte size is zero this is an aggregate type that has children - if (CanProvideValue()) - { - Scalar scalar; - if (ResolveValue (scalar)) - { - if (success) - *success = true; - return scalar.SLongLong(fail_value); - } - // fallthrough, otherwise... - } - - if (success) - *success = false; - return fail_value; -} + // this only works for arrays, because I have no way to know when + // the pointed memory ends, and no special \0 end of data marker + if (flags.Test(eTypeIsArray)) { + if ((custom_format == eFormatBytes) || + (custom_format == eFormatBytesWithASCII)) { + const size_t count = GetNumChildren(); -// if any more "special cases" are added to ValueObject::DumpPrintableRepresentation() please keep -// this call up to date by returning true for your new special cases. We will eventually move -// to checking this call result before trying to display special cases -bool -ValueObject::HasSpecialPrintableRepresentation(ValueObjectRepresentationStyle val_obj_display, - Format custom_format) -{ - Flags flags(GetTypeInfo()); - if (flags.AnySet(eTypeIsArray | eTypeIsPointer) - && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) - { - if (IsCStringContainer(true) && - (custom_format == eFormatCString || - custom_format == eFormatCharArray || - custom_format == eFormatChar || - custom_format == eFormatVectorOfChar)) - return true; - - if (flags.Test(eTypeIsArray)) - { - if ((custom_format == eFormatBytes) || - (custom_format == eFormatBytesWithASCII)) - return true; - - if ((custom_format == eFormatVectorOfChar) || - (custom_format == eFormatVectorOfFloat32) || - (custom_format == eFormatVectorOfFloat64) || - (custom_format == eFormatVectorOfSInt16) || - (custom_format == eFormatVectorOfSInt32) || - (custom_format == eFormatVectorOfSInt64) || - (custom_format == eFormatVectorOfSInt8) || - (custom_format == eFormatVectorOfUInt128) || - (custom_format == eFormatVectorOfUInt16) || - (custom_format == eFormatVectorOfUInt32) || - (custom_format == eFormatVectorOfUInt64) || - (custom_format == eFormatVectorOfUInt8)) - return true; - } - } - return false; -} + s << '['; + for (size_t low = 0; low < count; low++) { -bool -ValueObject::DumpPrintableRepresentation(Stream& s, - ValueObjectRepresentationStyle val_obj_display, - Format custom_format, - PrintableRepresentationSpecialCases special, - bool do_dump_error) -{ - - Flags flags(GetTypeInfo()); - - bool allow_special = ((special & ePrintableRepresentationSpecialCasesAllow) == ePrintableRepresentationSpecialCasesAllow); - bool only_special = ((special & ePrintableRepresentationSpecialCasesOnly) == ePrintableRepresentationSpecialCasesOnly); - - if (allow_special) - { - if (flags.AnySet(eTypeIsArray | eTypeIsPointer) - && val_obj_display == ValueObject::eValueObjectRepresentationStyleValue) - { - // when being asked to get a printable display an array or pointer type directly, - // try to "do the right thing" - - if (IsCStringContainer(true) && - (custom_format == eFormatCString || - custom_format == eFormatCharArray || - custom_format == eFormatChar || - custom_format == eFormatVectorOfChar)) // print char[] & char* directly - { - Error error; - lldb::DataBufferSP buffer_sp; - std::pair<size_t, bool> read_string = ReadPointedString(buffer_sp, - error, - 0, - (custom_format == eFormatVectorOfChar) || - (custom_format == eFormatCharArray)); - lldb_private::formatters::StringPrinter::ReadBufferAndDumpToStreamOptions options(*this); - options.SetData(DataExtractor(buffer_sp, lldb::eByteOrderInvalid, 8)); // none of this matters for a string - pass some defaults - options.SetStream(&s); - options.SetPrefixToken(0); - options.SetQuote('"'); - options.SetSourceSize(buffer_sp->GetByteSize()); - options.SetIsTruncated(read_string.second); - formatters::StringPrinter::ReadBufferAndDumpToStream<lldb_private::formatters::StringPrinter::StringElementType::ASCII>(options); - return !error.Fail(); + if (low) + s << ','; + + ValueObjectSP child = GetChildAtIndex(low, true); + if (!child.get()) { + s << "<invalid child>"; + continue; } - - if (custom_format == eFormatEnum) - return false; - - // this only works for arrays, because I have no way to know when - // the pointed memory ends, and no special \0 end of data marker - if (flags.Test(eTypeIsArray)) - { - if ((custom_format == eFormatBytes) || - (custom_format == eFormatBytesWithASCII)) - { - const size_t count = GetNumChildren(); - - s << '['; - for (size_t low = 0; low < count; low++) - { - - if (low) - s << ','; - - ValueObjectSP child = GetChildAtIndex(low,true); - if (!child.get()) - { - s << "<invalid child>"; - continue; - } - child->DumpPrintableRepresentation(s, ValueObject::eValueObjectRepresentationStyleValue, custom_format); - } - - s << ']'; - - return true; - } - - if ((custom_format == eFormatVectorOfChar) || - (custom_format == eFormatVectorOfFloat32) || - (custom_format == eFormatVectorOfFloat64) || - (custom_format == eFormatVectorOfSInt16) || - (custom_format == eFormatVectorOfSInt32) || - (custom_format == eFormatVectorOfSInt64) || - (custom_format == eFormatVectorOfSInt8) || - (custom_format == eFormatVectorOfUInt128) || - (custom_format == eFormatVectorOfUInt16) || - (custom_format == eFormatVectorOfUInt32) || - (custom_format == eFormatVectorOfUInt64) || - (custom_format == eFormatVectorOfUInt8)) // arrays of bytes, bytes with ASCII or any vector format should be printed directly - { - const size_t count = GetNumChildren(); - - Format format = FormatManager::GetSingleItemFormat(custom_format); - - s << '['; - for (size_t low = 0; low < count; low++) - { - - if (low) - s << ','; - - ValueObjectSP child = GetChildAtIndex(low,true); - if (!child.get()) - { - s << "<invalid child>"; - continue; - } - child->DumpPrintableRepresentation(s, ValueObject::eValueObjectRepresentationStyleValue, format); - } - - s << ']'; - - return true; - } + child->DumpPrintableRepresentation( + s, ValueObject::eValueObjectRepresentationStyleValue, + custom_format); + } + + s << ']'; + + return true; + } + + if ((custom_format == eFormatVectorOfChar) || + (custom_format == eFormatVectorOfFloat32) || + (custom_format == eFormatVectorOfFloat64) || + (custom_format == eFormatVectorOfSInt16) || + (custom_format == eFormatVectorOfSInt32) || + (custom_format == eFormatVectorOfSInt64) || + (custom_format == eFormatVectorOfSInt8) || + (custom_format == eFormatVectorOfUInt128) || + (custom_format == eFormatVectorOfUInt16) || + (custom_format == eFormatVectorOfUInt32) || + (custom_format == eFormatVectorOfUInt64) || + (custom_format == eFormatVectorOfUInt8)) // arrays of bytes, bytes + // with ASCII or any vector + // format should be printed + // directly + { + const size_t count = GetNumChildren(); + + Format format = FormatManager::GetSingleItemFormat(custom_format); + + s << '['; + for (size_t low = 0; low < count; low++) { + + if (low) + s << ','; + + ValueObjectSP child = GetChildAtIndex(low, true); + if (!child.get()) { + s << "<invalid child>"; + continue; } - - if ((custom_format == eFormatBoolean) || - (custom_format == eFormatBinary) || - (custom_format == eFormatChar) || - (custom_format == eFormatCharPrintable) || - (custom_format == eFormatComplexFloat) || - (custom_format == eFormatDecimal) || - (custom_format == eFormatHex) || - (custom_format == eFormatHexUppercase) || - (custom_format == eFormatFloat) || - (custom_format == eFormatOctal) || - (custom_format == eFormatOSType) || - (custom_format == eFormatUnicode16) || - (custom_format == eFormatUnicode32) || - (custom_format == eFormatUnsigned) || - (custom_format == eFormatPointer) || - (custom_format == eFormatComplexInteger) || - (custom_format == eFormatComplex) || - (custom_format == eFormatDefault)) // use the [] operator - return false; - } - } - - if (only_special) + child->DumpPrintableRepresentation( + s, ValueObject::eValueObjectRepresentationStyleValue, format); + } + + s << ']'; + + return true; + } + } + + if ((custom_format == eFormatBoolean) || + (custom_format == eFormatBinary) || (custom_format == eFormatChar) || + (custom_format == eFormatCharPrintable) || + (custom_format == eFormatComplexFloat) || + (custom_format == eFormatDecimal) || (custom_format == eFormatHex) || + (custom_format == eFormatHexUppercase) || + (custom_format == eFormatFloat) || (custom_format == eFormatOctal) || + (custom_format == eFormatOSType) || + (custom_format == eFormatUnicode16) || + (custom_format == eFormatUnicode32) || + (custom_format == eFormatUnsigned) || + (custom_format == eFormatPointer) || + (custom_format == eFormatComplexInteger) || + (custom_format == eFormatComplex) || + (custom_format == eFormatDefault)) // use the [] operator return false; - - bool var_success = false; - - { - const char *cstr = NULL; - - // this is a local stream that we are using to ensure that the data pointed to by cstr survives - // long enough for us to copy it to its destination - it is necessary to have this temporary storage - // area for cases where our desired output is not backed by some other longer-term storage - StreamString strm; - - if (custom_format != eFormatInvalid) - SetFormat(custom_format); - - switch(val_obj_display) - { - case eValueObjectRepresentationStyleValue: - cstr = GetValueAsCString(); - break; - - case eValueObjectRepresentationStyleSummary: - cstr = GetSummaryAsCString(); - break; - - case eValueObjectRepresentationStyleLanguageSpecific: - cstr = GetObjectDescription(); - break; - - case eValueObjectRepresentationStyleLocation: - cstr = GetLocationAsCString(); - break; - - case eValueObjectRepresentationStyleChildrenCount: - strm.Printf("%" PRIu64 "", (uint64_t)GetNumChildren()); - cstr = strm.GetString().c_str(); - break; - - case eValueObjectRepresentationStyleType: - cstr = GetTypeName().AsCString(); - break; - - case eValueObjectRepresentationStyleName: - cstr = GetName().AsCString(); - break; - - case eValueObjectRepresentationStyleExpressionPath: - GetExpressionPath(strm, false); - cstr = strm.GetString().c_str(); - break; - } - - if (!cstr) - { - if (val_obj_display == eValueObjectRepresentationStyleValue) - cstr = GetSummaryAsCString(); - else if (val_obj_display == eValueObjectRepresentationStyleSummary) - { - if (!CanProvideValue()) - { - strm.Printf("%s @ %s", GetTypeName().AsCString(), GetLocationAsCString()); - cstr = strm.GetString().c_str(); - } - else - cstr = GetValueAsCString(); - } - } - - if (cstr) - s.PutCString(cstr); - else - { - if (m_error.Fail()) - { - if (do_dump_error) - s.Printf("<%s>", m_error.AsCString()); - else - return false; - } - else if (val_obj_display == eValueObjectRepresentationStyleSummary) - s.PutCString("<no summary available>"); - else if (val_obj_display == eValueObjectRepresentationStyleValue) - s.PutCString("<no value available>"); - else if (val_obj_display == eValueObjectRepresentationStyleLanguageSpecific) - s.PutCString("<not a valid Objective-C object>"); // edit this if we have other runtimes that support a description - else - s.PutCString("<no printable representation>"); - } - - // we should only return false here if we could not do *anything* - // even if we have an error message as output, that's a success - // from our callers' perspective, so return true - var_success = true; - - if (custom_format != eFormatInvalid) - SetFormat(eFormatDefault); } - - return var_success; -} + } -addr_t -ValueObject::GetAddressOf (bool scalar_is_load_address, AddressType *address_type) -{ - // Can't take address of a bitfield - if (IsBitfield()) - return LLDB_INVALID_ADDRESS; - - if (!UpdateValueIfNeeded(false)) - return LLDB_INVALID_ADDRESS; - - switch (m_value.GetValueType()) - { - case Value::eValueTypeScalar: - case Value::eValueTypeVector: - if (scalar_is_load_address) - { - if(address_type) - *address_type = eAddressTypeLoad; - return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - } - break; + if (only_special) + return false; - case Value::eValueTypeLoadAddress: - case Value::eValueTypeFileAddress: - { - if(address_type) - *address_type = m_value.GetValueAddressType (); - return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - } - break; - case Value::eValueTypeHostAddress: - { - if(address_type) - *address_type = m_value.GetValueAddressType (); - return LLDB_INVALID_ADDRESS; - } - break; - } - if (address_type) - *address_type = eAddressTypeInvalid; + bool var_success = false; + + { + llvm::StringRef str; + + // this is a local stream that we are using to ensure that the data pointed + // to by cstr survives long enough for us to copy it to its destination - it + // is necessary to have this temporary storage area for cases where our + // desired output is not backed by some other longer-term storage + StreamString strm; + + if (custom_format != eFormatInvalid) + SetFormat(custom_format); + + switch (val_obj_display) { + case eValueObjectRepresentationStyleValue: + str = GetValueAsCString(); + break; + + case eValueObjectRepresentationStyleSummary: + str = GetSummaryAsCString(); + break; + + case eValueObjectRepresentationStyleLanguageSpecific: + str = GetObjectDescription(); + break; + + case eValueObjectRepresentationStyleLocation: + str = GetLocationAsCString(); + break; + + case eValueObjectRepresentationStyleChildrenCount: + strm.Printf("%" PRIu64 "", (uint64_t)GetNumChildren()); + str = strm.GetString(); + break; + + case eValueObjectRepresentationStyleType: + str = GetTypeName().GetStringRef(); + break; + + case eValueObjectRepresentationStyleName: + str = GetName().GetStringRef(); + break; + + case eValueObjectRepresentationStyleExpressionPath: + GetExpressionPath(strm, false); + str = strm.GetString(); + break; + } + + if (str.empty()) { + if (val_obj_display == eValueObjectRepresentationStyleValue) + str = GetSummaryAsCString(); + else if (val_obj_display == eValueObjectRepresentationStyleSummary) { + if (!CanProvideValue()) { + strm.Printf("%s @ %s", GetTypeName().AsCString(), + GetLocationAsCString()); + str = strm.GetString(); + } else + str = GetValueAsCString(); + } + } + + if (!str.empty()) + s << str; + else { + if (m_error.Fail()) { + if (do_dump_error) + s.Printf("<%s>", m_error.AsCString()); + else + return false; + } else if (val_obj_display == eValueObjectRepresentationStyleSummary) + s.PutCString("<no summary available>"); + else if (val_obj_display == eValueObjectRepresentationStyleValue) + s.PutCString("<no value available>"); + else if (val_obj_display == + eValueObjectRepresentationStyleLanguageSpecific) + s.PutCString("<not a valid Objective-C object>"); // edit this if we + // have other runtimes + // that support a + // description + else + s.PutCString("<no printable representation>"); + } + + // we should only return false here if we could not do *anything* + // even if we have an error message as output, that's a success + // from our callers' perspective, so return true + var_success = true; + + if (custom_format != eFormatInvalid) + SetFormat(eFormatDefault); + } + + return var_success; +} + +addr_t ValueObject::GetAddressOf(bool scalar_is_load_address, + AddressType *address_type) { + // Can't take address of a bitfield + if (IsBitfield()) return LLDB_INVALID_ADDRESS; -} -addr_t -ValueObject::GetPointerValue (AddressType *address_type) -{ - addr_t address = LLDB_INVALID_ADDRESS; - if(address_type) - *address_type = eAddressTypeInvalid; - - if (!UpdateValueIfNeeded(false)) - return address; - - switch (m_value.GetValueType()) - { - case Value::eValueTypeScalar: - case Value::eValueTypeVector: - address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - break; + if (!UpdateValueIfNeeded(false)) + return LLDB_INVALID_ADDRESS; - case Value::eValueTypeHostAddress: - case Value::eValueTypeLoadAddress: - case Value::eValueTypeFileAddress: - { - lldb::offset_t data_offset = 0; - address = m_data.GetPointer(&data_offset); - } - break; + switch (m_value.GetValueType()) { + case Value::eValueTypeScalar: + case Value::eValueTypeVector: + if (scalar_is_load_address) { + if (address_type) + *address_type = eAddressTypeLoad; + return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); } + break; + case Value::eValueTypeLoadAddress: + case Value::eValueTypeFileAddress: { if (address_type) - *address_type = GetAddressTypeOfChildren(); + *address_type = m_value.GetValueAddressType(); + return m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + } break; + case Value::eValueTypeHostAddress: { + if (address_type) + *address_type = m_value.GetValueAddressType(); + return LLDB_INVALID_ADDRESS; + } break; + } + if (address_type) + *address_type = eAddressTypeInvalid; + return LLDB_INVALID_ADDRESS; +} +addr_t ValueObject::GetPointerValue(AddressType *address_type) { + addr_t address = LLDB_INVALID_ADDRESS; + if (address_type) + *address_type = eAddressTypeInvalid; + + if (!UpdateValueIfNeeded(false)) return address; -} -bool -ValueObject::SetValueFromCString (const char *value_str, Error& error) -{ - error.Clear(); - // Make sure our value is up to date first so that our location and location - // type is valid. - if (!UpdateValueIfNeeded(false)) - { - error.SetErrorString("unable to read value"); - return false; - } + switch (m_value.GetValueType()) { + case Value::eValueTypeScalar: + case Value::eValueTypeVector: + address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + break; - uint64_t count = 0; - const Encoding encoding = GetCompilerType().GetEncoding (count); + case Value::eValueTypeHostAddress: + case Value::eValueTypeLoadAddress: + case Value::eValueTypeFileAddress: { + lldb::offset_t data_offset = 0; + address = m_data.GetPointer(&data_offset); + } break; + } - const size_t byte_size = GetByteSize(); + if (address_type) + *address_type = GetAddressTypeOfChildren(); - Value::ValueType value_type = m_value.GetValueType(); - - if (value_type == Value::eValueTypeScalar) - { - // If the value is already a scalar, then let the scalar change itself: - m_value.GetScalar().SetValueFromCString (value_str, encoding, byte_size); - } - else if (byte_size <= 16) - { - // If the value fits in a scalar, then make a new scalar and again let the - // scalar code do the conversion, then figure out where to put the new value. - Scalar new_scalar; - error = new_scalar.SetValueFromCString (value_str, encoding, byte_size); - if (error.Success()) - { - switch (value_type) - { - case Value::eValueTypeLoadAddress: - { - // If it is a load address, then the scalar value is the storage location - // of the data, and we have to shove this value down to that load location. - ExecutionContext exe_ctx (GetExecutionContextRef()); - Process *process = exe_ctx.GetProcessPtr(); - if (process) - { - addr_t target_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - size_t bytes_written = process->WriteScalarToMemory (target_addr, - new_scalar, - byte_size, - error); - if (!error.Success()) - return false; - if (bytes_written != byte_size) - { - error.SetErrorString("unable to write value to memory"); - return false; - } - } - } - break; - case Value::eValueTypeHostAddress: - { - // If it is a host address, then we stuff the scalar as a DataBuffer into the Value's data. - DataExtractor new_data; - new_data.SetByteOrder (m_data.GetByteOrder()); - - DataBufferSP buffer_sp (new DataBufferHeap(byte_size, 0)); - m_data.SetData(buffer_sp, 0); - bool success = new_scalar.GetData(new_data); - if (success) - { - new_data.CopyByteOrderedData (0, - byte_size, - const_cast<uint8_t *>(m_data.GetDataStart()), - byte_size, - m_data.GetByteOrder()); - } - m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); - - } - break; - case Value::eValueTypeFileAddress: - case Value::eValueTypeScalar: - case Value::eValueTypeVector: - break; - } - } - else - { - return false; - } - } - else - { - // We don't support setting things bigger than a scalar at present. - error.SetErrorString("unable to write aggregate data type"); - return false; - } - - // If we have reached this point, then we have successfully changed the value. - SetNeedsUpdate(); - return true; + return address; } -bool -ValueObject::GetDeclaration (Declaration &decl) -{ - decl.Clear(); +bool ValueObject::SetValueFromCString(const char *value_str, Error &error) { + error.Clear(); + // Make sure our value is up to date first so that our location and location + // type is valid. + if (!UpdateValueIfNeeded(false)) { + error.SetErrorString("unable to read value"); return false; -} + } + + uint64_t count = 0; + const Encoding encoding = GetCompilerType().GetEncoding(count); + + const size_t byte_size = GetByteSize(); + + Value::ValueType value_type = m_value.GetValueType(); + + if (value_type == Value::eValueTypeScalar) { + // If the value is already a scalar, then let the scalar change itself: + m_value.GetScalar().SetValueFromCString(value_str, encoding, byte_size); + } else if (byte_size <= 16) { + // If the value fits in a scalar, then make a new scalar and again let the + // scalar code do the conversion, then figure out where to put the new + // value. + Scalar new_scalar; + error = new_scalar.SetValueFromCString(value_str, encoding, byte_size); + if (error.Success()) { + switch (value_type) { + case Value::eValueTypeLoadAddress: { + // If it is a load address, then the scalar value is the storage + // location + // of the data, and we have to shove this value down to that load + // location. + ExecutionContext exe_ctx(GetExecutionContextRef()); + Process *process = exe_ctx.GetProcessPtr(); + if (process) { + addr_t target_addr = + m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + size_t bytes_written = process->WriteScalarToMemory( + target_addr, new_scalar, byte_size, error); + if (!error.Success()) + return false; + if (bytes_written != byte_size) { + error.SetErrorString("unable to write value to memory"); + return false; + } + } + } break; + case Value::eValueTypeHostAddress: { + // If it is a host address, then we stuff the scalar as a DataBuffer + // into the Value's data. + DataExtractor new_data; + new_data.SetByteOrder(m_data.GetByteOrder()); + + DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0)); + m_data.SetData(buffer_sp, 0); + bool success = new_scalar.GetData(new_data); + if (success) { + new_data.CopyByteOrderedData( + 0, byte_size, const_cast<uint8_t *>(m_data.GetDataStart()), + byte_size, m_data.GetByteOrder()); + } + m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); + + } break; + case Value::eValueTypeFileAddress: + case Value::eValueTypeScalar: + case Value::eValueTypeVector: + break; + } + } else { + return false; + } + } else { + // We don't support setting things bigger than a scalar at present. + error.SetErrorString("unable to write aggregate data type"); + return false; + } -ConstString -ValueObject::GetTypeName() -{ - return GetCompilerType().GetConstTypeName(); + // If we have reached this point, then we have successfully changed the value. + SetNeedsUpdate(); + return true; } -ConstString -ValueObject::GetDisplayTypeName() -{ - return GetTypeName(); +bool ValueObject::GetDeclaration(Declaration &decl) { + decl.Clear(); + return false; } -ConstString -ValueObject::GetQualifiedTypeName() -{ - return GetCompilerType().GetConstQualifiedTypeName(); +ConstString ValueObject::GetTypeName() { + return GetCompilerType().GetConstTypeName(); } +ConstString ValueObject::GetDisplayTypeName() { return GetTypeName(); } -LanguageType -ValueObject::GetObjectRuntimeLanguage () -{ - return GetCompilerType().GetMinimumLanguage (); +ConstString ValueObject::GetQualifiedTypeName() { + return GetCompilerType().GetConstQualifiedTypeName(); } -void -ValueObject::AddSyntheticChild (const ConstString &key, ValueObject *valobj) -{ - m_synthetic_children[key] = valobj; +LanguageType ValueObject::GetObjectRuntimeLanguage() { + return GetCompilerType().GetMinimumLanguage(); } -ValueObjectSP -ValueObject::GetSyntheticChild (const ConstString &key) const -{ - ValueObjectSP synthetic_child_sp; - std::map<ConstString, ValueObject *>::const_iterator pos = m_synthetic_children.find (key); - if (pos != m_synthetic_children.end()) - synthetic_child_sp = pos->second->GetSP(); - return synthetic_child_sp; +void ValueObject::AddSyntheticChild(const ConstString &key, + ValueObject *valobj) { + m_synthetic_children[key] = valobj; } -uint32_t -ValueObject::GetTypeInfo (CompilerType *pointee_or_element_compiler_type) -{ - return GetCompilerType().GetTypeInfo (pointee_or_element_compiler_type); +ValueObjectSP ValueObject::GetSyntheticChild(const ConstString &key) const { + ValueObjectSP synthetic_child_sp; + std::map<ConstString, ValueObject *>::const_iterator pos = + m_synthetic_children.find(key); + if (pos != m_synthetic_children.end()) + synthetic_child_sp = pos->second->GetSP(); + return synthetic_child_sp; } -bool -ValueObject::IsPointerType () -{ - return GetCompilerType().IsPointerType(); +uint32_t +ValueObject::GetTypeInfo(CompilerType *pointee_or_element_compiler_type) { + return GetCompilerType().GetTypeInfo(pointee_or_element_compiler_type); } -bool -ValueObject::IsArrayType () -{ - return GetCompilerType().IsArrayType (NULL, NULL, NULL); -} +bool ValueObject::IsPointerType() { return GetCompilerType().IsPointerType(); } -bool -ValueObject::IsScalarType () -{ - return GetCompilerType().IsScalarType (); +bool ValueObject::IsArrayType() { + return GetCompilerType().IsArrayType(NULL, NULL, NULL); } -bool -ValueObject::IsIntegerType (bool &is_signed) -{ - return GetCompilerType().IsIntegerType (is_signed); +bool ValueObject::IsScalarType() { return GetCompilerType().IsScalarType(); } + +bool ValueObject::IsIntegerType(bool &is_signed) { + return GetCompilerType().IsIntegerType(is_signed); } -bool -ValueObject::IsPointerOrReferenceType () -{ - return GetCompilerType().IsPointerOrReferenceType (); +bool ValueObject::IsPointerOrReferenceType() { + return GetCompilerType().IsPointerOrReferenceType(); } -bool -ValueObject::IsPossibleDynamicType () -{ - ExecutionContext exe_ctx (GetExecutionContextRef()); - Process *process = exe_ctx.GetProcessPtr(); - if (process) - return process->IsPossibleDynamicValue(*this); - else - return GetCompilerType().IsPossibleDynamicType (NULL, true, true); +bool ValueObject::IsPossibleDynamicType() { + ExecutionContext exe_ctx(GetExecutionContextRef()); + Process *process = exe_ctx.GetProcessPtr(); + if (process) + return process->IsPossibleDynamicValue(*this); + else + return GetCompilerType().IsPossibleDynamicType(NULL, true, true); } -bool -ValueObject::IsRuntimeSupportValue () -{ - Process *process(GetProcessSP().get()); - if (process) - { - LanguageRuntime *runtime = process->GetLanguageRuntime(GetObjectRuntimeLanguage()); - if (!runtime) - runtime = process->GetObjCLanguageRuntime(); - if (runtime) - return runtime->IsRuntimeSupportValue(*this); - } - return false; +bool ValueObject::IsRuntimeSupportValue() { + Process *process(GetProcessSP().get()); + if (process) { + LanguageRuntime *runtime = + process->GetLanguageRuntime(GetObjectRuntimeLanguage()); + if (!runtime) + runtime = process->GetObjCLanguageRuntime(); + if (runtime) + return runtime->IsRuntimeSupportValue(*this); + } + return false; } -bool -ValueObject::IsNilReference () -{ - if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) - { - return language->IsNilReference(*this); - } - return false; +bool ValueObject::IsNilReference() { + if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) { + return language->IsNilReference(*this); + } + return false; } -bool -ValueObject::IsUninitializedReference () -{ - if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) - { - return language->IsUninitializedReference(*this); - } - return false; +bool ValueObject::IsUninitializedReference() { + if (Language *language = Language::FindPlugin(GetObjectRuntimeLanguage())) { + return language->IsUninitializedReference(*this); + } + return false; } // This allows you to create an array member using and index @@ -2104,2243 +1756,1694 @@ ValueObject::IsUninitializedReference () // The size of the "item_array" is 1, but many times in practice // there are more items in "item_array". -ValueObjectSP -ValueObject::GetSyntheticArrayMember (size_t index, bool can_create) -{ - ValueObjectSP synthetic_child_sp; - if (IsPointerType () || IsArrayType()) - { - char index_str[64]; - snprintf(index_str, sizeof(index_str), "[%" PRIu64 "]", (uint64_t)index); - ConstString index_const_str(index_str); - // Check if we have already created a synthetic array member in this - // valid object. If we have we will re-use it. - synthetic_child_sp = GetSyntheticChild (index_const_str); - if (!synthetic_child_sp) - { - ValueObject *synthetic_child; - // We haven't made a synthetic array member for INDEX yet, so - // lets make one and cache it for any future reference. - synthetic_child = CreateChildAtIndex(0, true, index); - - // Cache the value if we got one back... - if (synthetic_child) - { - AddSyntheticChild(index_const_str, synthetic_child); - synthetic_child_sp = synthetic_child->GetSP(); - synthetic_child_sp->SetName(ConstString(index_str)); - synthetic_child_sp->m_is_array_item_for_pointer = true; - } - } - } - return synthetic_child_sp; -} - -ValueObjectSP -ValueObject::GetSyntheticBitFieldChild (uint32_t from, uint32_t to, bool can_create) -{ - ValueObjectSP synthetic_child_sp; - if (IsScalarType ()) - { - char index_str[64]; - snprintf(index_str, sizeof(index_str), "[%i-%i]", from, to); - ConstString index_const_str(index_str); - // Check if we have already created a synthetic array member in this - // valid object. If we have we will re-use it. - synthetic_child_sp = GetSyntheticChild (index_const_str); - if (!synthetic_child_sp) - { - uint32_t bit_field_size = to - from + 1; - uint32_t bit_field_offset = from; - if (GetDataExtractor().GetByteOrder() == eByteOrderBig) - bit_field_offset = GetByteSize() * 8 - bit_field_size - bit_field_offset; - // We haven't made a synthetic array member for INDEX yet, so - // lets make one and cache it for any future reference. - ValueObjectChild *synthetic_child = new ValueObjectChild (*this, - GetCompilerType(), - index_const_str, - GetByteSize(), - 0, - bit_field_size, - bit_field_offset, - false, - false, - eAddressTypeInvalid, - 0); - - // Cache the value if we got one back... - if (synthetic_child) - { - AddSyntheticChild(index_const_str, synthetic_child); - synthetic_child_sp = synthetic_child->GetSP(); - synthetic_child_sp->SetName(ConstString(index_str)); - synthetic_child_sp->m_is_bitfield_for_scalar = true; - } - } - } - return synthetic_child_sp; -} - -ValueObjectSP -ValueObject::GetSyntheticChildAtOffset(uint32_t offset, - const CompilerType& type, - bool can_create, - ConstString name_const_str) -{ - - ValueObjectSP synthetic_child_sp; - - if (name_const_str.IsEmpty()) - { - char name_str[64]; - snprintf(name_str, sizeof(name_str), "@%i", offset); - name_const_str.SetCString(name_str); - } - +ValueObjectSP ValueObject::GetSyntheticArrayMember(size_t index, + bool can_create) { + ValueObjectSP synthetic_child_sp; + if (IsPointerType() || IsArrayType()) { + char index_str[64]; + snprintf(index_str, sizeof(index_str), "[%" PRIu64 "]", (uint64_t)index); + ConstString index_const_str(index_str); // Check if we have already created a synthetic array member in this // valid object. If we have we will re-use it. - synthetic_child_sp = GetSyntheticChild (name_const_str); - - if (synthetic_child_sp.get()) - return synthetic_child_sp; - - if (!can_create) - return ValueObjectSP(); - - ExecutionContext exe_ctx (GetExecutionContextRef()); - - ValueObjectChild *synthetic_child = new ValueObjectChild(*this, - type, - name_const_str, - type.GetByteSize(exe_ctx.GetBestExecutionContextScope()), - offset, - 0, - 0, - false, - false, - eAddressTypeInvalid, - 0); - if (synthetic_child) - { - AddSyntheticChild(name_const_str, synthetic_child); + synthetic_child_sp = GetSyntheticChild(index_const_str); + if (!synthetic_child_sp) { + ValueObject *synthetic_child; + // We haven't made a synthetic array member for INDEX yet, so + // lets make one and cache it for any future reference. + synthetic_child = CreateChildAtIndex(0, true, index); + + // Cache the value if we got one back... + if (synthetic_child) { + AddSyntheticChild(index_const_str, synthetic_child); synthetic_child_sp = synthetic_child->GetSP(); - synthetic_child_sp->SetName(name_const_str); - synthetic_child_sp->m_is_child_at_offset = true; + synthetic_child_sp->SetName(ConstString(index_str)); + synthetic_child_sp->m_is_array_item_for_pointer = true; + } } - return synthetic_child_sp; + } + return synthetic_child_sp; } -ValueObjectSP -ValueObject::GetSyntheticBase (uint32_t offset, - const CompilerType& type, - bool can_create, - ConstString name_const_str) -{ - ValueObjectSP synthetic_child_sp; - - if (name_const_str.IsEmpty()) - { - char name_str[128]; - snprintf(name_str, sizeof(name_str), "base%s@%i", type.GetTypeName().AsCString("<unknown>"), offset); - name_const_str.SetCString(name_str); - } - +ValueObjectSP ValueObject::GetSyntheticBitFieldChild(uint32_t from, uint32_t to, + bool can_create) { + ValueObjectSP synthetic_child_sp; + if (IsScalarType()) { + char index_str[64]; + snprintf(index_str, sizeof(index_str), "[%i-%i]", from, to); + ConstString index_const_str(index_str); // Check if we have already created a synthetic array member in this // valid object. If we have we will re-use it. - synthetic_child_sp = GetSyntheticChild (name_const_str); - - if (synthetic_child_sp.get()) - return synthetic_child_sp; - - if (!can_create) - return ValueObjectSP(); - - const bool is_base_class = true; - - ExecutionContext exe_ctx (GetExecutionContextRef()); - - ValueObjectChild *synthetic_child = new ValueObjectChild(*this, - type, - name_const_str, - type.GetByteSize(exe_ctx.GetBestExecutionContextScope()), - offset, - 0, - 0, - is_base_class, - false, - eAddressTypeInvalid, - 0); - if (synthetic_child) - { - AddSyntheticChild(name_const_str, synthetic_child); + synthetic_child_sp = GetSyntheticChild(index_const_str); + if (!synthetic_child_sp) { + uint32_t bit_field_size = to - from + 1; + uint32_t bit_field_offset = from; + if (GetDataExtractor().GetByteOrder() == eByteOrderBig) + bit_field_offset = + GetByteSize() * 8 - bit_field_size - bit_field_offset; + // We haven't made a synthetic array member for INDEX yet, so + // lets make one and cache it for any future reference. + ValueObjectChild *synthetic_child = new ValueObjectChild( + *this, GetCompilerType(), index_const_str, GetByteSize(), 0, + bit_field_size, bit_field_offset, false, false, eAddressTypeInvalid, + 0); + + // Cache the value if we got one back... + if (synthetic_child) { + AddSyntheticChild(index_const_str, synthetic_child); synthetic_child_sp = synthetic_child->GetSP(); - synthetic_child_sp->SetName(name_const_str); + synthetic_child_sp->SetName(ConstString(index_str)); + synthetic_child_sp->m_is_bitfield_for_scalar = true; + } } - return synthetic_child_sp; + } + return synthetic_child_sp; } +ValueObjectSP ValueObject::GetSyntheticChildAtOffset( + uint32_t offset, const CompilerType &type, bool can_create, + ConstString name_const_str) { + + ValueObjectSP synthetic_child_sp; + + if (name_const_str.IsEmpty()) { + char name_str[64]; + snprintf(name_str, sizeof(name_str), "@%i", offset); + name_const_str.SetCString(name_str); + } + + // Check if we have already created a synthetic array member in this + // valid object. If we have we will re-use it. + synthetic_child_sp = GetSyntheticChild(name_const_str); + + if (synthetic_child_sp.get()) + return synthetic_child_sp; + + if (!can_create) + return ValueObjectSP(); + + ExecutionContext exe_ctx(GetExecutionContextRef()); + + ValueObjectChild *synthetic_child = new ValueObjectChild( + *this, type, name_const_str, + type.GetByteSize(exe_ctx.GetBestExecutionContextScope()), offset, 0, 0, + false, false, eAddressTypeInvalid, 0); + if (synthetic_child) { + AddSyntheticChild(name_const_str, synthetic_child); + synthetic_child_sp = synthetic_child->GetSP(); + synthetic_child_sp->SetName(name_const_str); + synthetic_child_sp->m_is_child_at_offset = true; + } + return synthetic_child_sp; +} + +ValueObjectSP ValueObject::GetSyntheticBase(uint32_t offset, + const CompilerType &type, + bool can_create, + ConstString name_const_str) { + ValueObjectSP synthetic_child_sp; + + if (name_const_str.IsEmpty()) { + char name_str[128]; + snprintf(name_str, sizeof(name_str), "base%s@%i", + type.GetTypeName().AsCString("<unknown>"), offset); + name_const_str.SetCString(name_str); + } + + // Check if we have already created a synthetic array member in this + // valid object. If we have we will re-use it. + synthetic_child_sp = GetSyntheticChild(name_const_str); + + if (synthetic_child_sp.get()) + return synthetic_child_sp; + + if (!can_create) + return ValueObjectSP(); + + const bool is_base_class = true; + + ExecutionContext exe_ctx(GetExecutionContextRef()); + + ValueObjectChild *synthetic_child = new ValueObjectChild( + *this, type, name_const_str, + type.GetByteSize(exe_ctx.GetBestExecutionContextScope()), offset, 0, 0, + is_base_class, false, eAddressTypeInvalid, 0); + if (synthetic_child) { + AddSyntheticChild(name_const_str, synthetic_child); + synthetic_child_sp = synthetic_child->GetSP(); + synthetic_child_sp->SetName(name_const_str); + } + return synthetic_child_sp; +} // your expression path needs to have a leading . or -> // (unless it somehow "looks like" an array, in which case it has // a leading [ symbol). while the [ is meaningful and should be shown // to the user, . and -> are just parser design, but by no means // added information for the user.. strip them off -static const char* -SkipLeadingExpressionPathSeparators(const char* expression) -{ - if (!expression || !expression[0]) - return expression; - if (expression[0] == '.') - return expression+1; - if (expression[0] == '-' && expression[1] == '>') - return expression+2; +static const char *SkipLeadingExpressionPathSeparators(const char *expression) { + if (!expression || !expression[0]) return expression; + if (expression[0] == '.') + return expression + 1; + if (expression[0] == '-' && expression[1] == '>') + return expression + 2; + return expression; } ValueObjectSP -ValueObject::GetSyntheticExpressionPathChild(const char* expression, bool can_create) -{ - ValueObjectSP synthetic_child_sp; - ConstString name_const_string(expression); - // Check if we have already created a synthetic array member in this - // valid object. If we have we will re-use it. - synthetic_child_sp = GetSyntheticChild (name_const_string); - if (!synthetic_child_sp) - { - // We haven't made a synthetic array member for expression yet, so - // lets make one and cache it for any future reference. - synthetic_child_sp = GetValueForExpressionPath(expression, - NULL, NULL, NULL, - GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal(GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None)); - - // Cache the value if we got one back... - if (synthetic_child_sp.get()) - { - // FIXME: this causes a "real" child to end up with its name changed to the contents of expression - AddSyntheticChild(name_const_string, synthetic_child_sp.get()); - synthetic_child_sp->SetName(ConstString(SkipLeadingExpressionPathSeparators(expression))); - } +ValueObject::GetSyntheticExpressionPathChild(const char *expression, + bool can_create) { + ValueObjectSP synthetic_child_sp; + ConstString name_const_string(expression); + // Check if we have already created a synthetic array member in this + // valid object. If we have we will re-use it. + synthetic_child_sp = GetSyntheticChild(name_const_string); + if (!synthetic_child_sp) { + // We haven't made a synthetic array member for expression yet, so + // lets make one and cache it for any future reference. + synthetic_child_sp = GetValueForExpressionPath( + expression, NULL, NULL, + GetValueForExpressionPathOptions().SetSyntheticChildrenTraversal( + GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: + None)); + + // Cache the value if we got one back... + if (synthetic_child_sp.get()) { + // FIXME: this causes a "real" child to end up with its name changed to + // the contents of expression + AddSyntheticChild(name_const_string, synthetic_child_sp.get()); + synthetic_child_sp->SetName( + ConstString(SkipLeadingExpressionPathSeparators(expression))); + } + } + return synthetic_child_sp; +} + +void ValueObject::CalculateSyntheticValue(bool use_synthetic) { + if (use_synthetic == false) + return; + + TargetSP target_sp(GetTargetSP()); + if (target_sp && target_sp->GetEnableSyntheticValue() == false) { + m_synthetic_value = NULL; + return; + } + + lldb::SyntheticChildrenSP current_synth_sp(m_synthetic_children_sp); + + if (!UpdateFormatsIfNeeded() && m_synthetic_value) + return; + + if (m_synthetic_children_sp.get() == NULL) + return; + + if (current_synth_sp == m_synthetic_children_sp && m_synthetic_value) + return; + + m_synthetic_value = new ValueObjectSynthetic(*this, m_synthetic_children_sp); +} + +void ValueObject::CalculateDynamicValue(DynamicValueType use_dynamic) { + if (use_dynamic == eNoDynamicValues) + return; + + if (!m_dynamic_value && !IsDynamic()) { + ExecutionContext exe_ctx(GetExecutionContextRef()); + Process *process = exe_ctx.GetProcessPtr(); + if (process && process->IsPossibleDynamicValue(*this)) { + ClearDynamicTypeInformation(); + m_dynamic_value = new ValueObjectDynamicValue(*this, use_dynamic); } - return synthetic_child_sp; + } } -void -ValueObject::CalculateSyntheticValue (bool use_synthetic) -{ - if (use_synthetic == false) - return; - - TargetSP target_sp(GetTargetSP()); - if (target_sp && target_sp->GetEnableSyntheticValue() == false) - { - m_synthetic_value = NULL; - return; - } - - lldb::SyntheticChildrenSP current_synth_sp(m_synthetic_children_sp); - - if (!UpdateFormatsIfNeeded() && m_synthetic_value) - return; - - if (m_synthetic_children_sp.get() == NULL) - return; - - if (current_synth_sp == m_synthetic_children_sp && m_synthetic_value) - return; - - m_synthetic_value = new ValueObjectSynthetic(*this, m_synthetic_children_sp); -} +ValueObjectSP ValueObject::GetDynamicValue(DynamicValueType use_dynamic) { + if (use_dynamic == eNoDynamicValues) + return ValueObjectSP(); -void -ValueObject::CalculateDynamicValue (DynamicValueType use_dynamic) -{ - if (use_dynamic == eNoDynamicValues) - return; - - if (!m_dynamic_value && !IsDynamic()) - { - ExecutionContext exe_ctx (GetExecutionContextRef()); - Process *process = exe_ctx.GetProcessPtr(); - if (process && process->IsPossibleDynamicValue(*this)) - { - ClearDynamicTypeInformation (); - m_dynamic_value = new ValueObjectDynamicValue (*this, use_dynamic); - } - } + if (!IsDynamic() && m_dynamic_value == NULL) { + CalculateDynamicValue(use_dynamic); + } + if (m_dynamic_value) + return m_dynamic_value->GetSP(); + else + return ValueObjectSP(); } -ValueObjectSP -ValueObject::GetDynamicValue (DynamicValueType use_dynamic) -{ - if (use_dynamic == eNoDynamicValues) - return ValueObjectSP(); - - if (!IsDynamic() && m_dynamic_value == NULL) - { - CalculateDynamicValue(use_dynamic); - } - if (m_dynamic_value) - return m_dynamic_value->GetSP(); - else - return ValueObjectSP(); -} +ValueObjectSP ValueObject::GetStaticValue() { return GetSP(); } -ValueObjectSP -ValueObject::GetStaticValue() -{ - return GetSP(); -} +lldb::ValueObjectSP ValueObject::GetNonSyntheticValue() { return GetSP(); } -lldb::ValueObjectSP -ValueObject::GetNonSyntheticValue () -{ - return GetSP(); -} +ValueObjectSP ValueObject::GetSyntheticValue(bool use_synthetic) { + if (use_synthetic == false) + return ValueObjectSP(); -ValueObjectSP -ValueObject::GetSyntheticValue (bool use_synthetic) -{ - if (use_synthetic == false) - return ValueObjectSP(); + CalculateSyntheticValue(use_synthetic); - CalculateSyntheticValue(use_synthetic); - - if (m_synthetic_value) - return m_synthetic_value->GetSP(); - else - return ValueObjectSP(); + if (m_synthetic_value) + return m_synthetic_value->GetSP(); + else + return ValueObjectSP(); } -bool -ValueObject::HasSyntheticValue() -{ - UpdateFormatsIfNeeded(); - - if (m_synthetic_children_sp.get() == NULL) - return false; - - CalculateSyntheticValue(true); - - if (m_synthetic_value) - return true; - else - return false; -} +bool ValueObject::HasSyntheticValue() { + UpdateFormatsIfNeeded(); -bool -ValueObject::GetBaseClassPath (Stream &s) -{ - if (IsBaseClass()) - { - bool parent_had_base_class = GetParent() && GetParent()->GetBaseClassPath (s); - CompilerType compiler_type = GetCompilerType(); - std::string cxx_class_name; - bool this_had_base_class = ClangASTContext::GetCXXClassName (compiler_type, cxx_class_name); - if (this_had_base_class) - { - if (parent_had_base_class) - s.PutCString("::"); - s.PutCString(cxx_class_name.c_str()); - } - return parent_had_base_class || this_had_base_class; - } + if (m_synthetic_children_sp.get() == NULL) return false; -} + CalculateSyntheticValue(true); -ValueObject * -ValueObject::GetNonBaseClassParent() -{ - if (GetParent()) - { - if (GetParent()->IsBaseClass()) - return GetParent()->GetNonBaseClassParent(); - else - return GetParent(); - } - return NULL; + if (m_synthetic_value) + return true; + else + return false; } +bool ValueObject::GetBaseClassPath(Stream &s) { + if (IsBaseClass()) { + bool parent_had_base_class = + GetParent() && GetParent()->GetBaseClassPath(s); + CompilerType compiler_type = GetCompilerType(); + std::string cxx_class_name; + bool this_had_base_class = + ClangASTContext::GetCXXClassName(compiler_type, cxx_class_name); + if (this_had_base_class) { + if (parent_had_base_class) + s.PutCString("::"); + s.PutCString(cxx_class_name); + } + return parent_had_base_class || this_had_base_class; + } + return false; +} + +ValueObject *ValueObject::GetNonBaseClassParent() { + if (GetParent()) { + if (GetParent()->IsBaseClass()) + return GetParent()->GetNonBaseClassParent(); + else + return GetParent(); + } + return NULL; +} -bool -ValueObject::IsBaseClass (uint32_t& depth) -{ - if (!IsBaseClass()) - { - depth = 0; - return false; - } - if (GetParent()) - { - GetParent()->IsBaseClass(depth); - depth = depth + 1; - return true; - } - // TODO: a base of no parent? weird.. - depth = 1; +bool ValueObject::IsBaseClass(uint32_t &depth) { + if (!IsBaseClass()) { + depth = 0; + return false; + } + if (GetParent()) { + GetParent()->IsBaseClass(depth); + depth = depth + 1; return true; -} + } + // TODO: a base of no parent? weird.. + depth = 1; + return true; +} + +void ValueObject::GetExpressionPath(Stream &s, bool qualify_cxx_base_classes, + GetExpressionPathFormat epformat) { + // synthetic children do not actually "exist" as part of the hierarchy, and + // sometimes they are consed up in ways + // that don't make sense from an underlying language/API standpoint. So, use a + // special code path here to return + // something that can hopefully be used in expression + if (m_is_synthetic_children_generated) { + UpdateValueIfNeeded(); -void -ValueObject::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat epformat) -{ - // synthetic children do not actually "exist" as part of the hierarchy, and sometimes they are consed up in ways - // that don't make sense from an underlying language/API standpoint. So, use a special code path here to return - // something that can hopefully be used in expression - if (m_is_synthetic_children_generated) - { - UpdateValueIfNeeded(); - - if (m_value.GetValueType() == Value::eValueTypeLoadAddress) - { - if (IsPointerOrReferenceType()) - { - s.Printf("((%s)0x%" PRIx64 ")", - GetTypeName().AsCString("void"), - GetValueAsUnsigned(0)); - return; + if (m_value.GetValueType() == Value::eValueTypeLoadAddress) { + if (IsPointerOrReferenceType()) { + s.Printf("((%s)0x%" PRIx64 ")", GetTypeName().AsCString("void"), + GetValueAsUnsigned(0)); + return; + } else { + uint64_t load_addr = + m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + if (load_addr != LLDB_INVALID_ADDRESS) { + s.Printf("(*( (%s *)0x%" PRIx64 "))", GetTypeName().AsCString("void"), + load_addr); + return; + } + } + } + + if (CanProvideValue()) { + s.Printf("((%s)%s)", GetTypeName().AsCString("void"), + GetValueAsCString()); + return; + } + + return; + } + + const bool is_deref_of_parent = IsDereferenceOfParent(); + + if (is_deref_of_parent && + epformat == eGetExpressionPathFormatDereferencePointers) { + // this is the original format of GetExpressionPath() producing code like + // *(a_ptr).memberName, which is entirely + // fine, until you put this into + // StackFrame::GetValueForVariableExpressionPath() which prefers to see + // a_ptr->memberName. + // the eHonorPointers mode is meant to produce strings in this latter format + s.PutCString("*("); + } + + ValueObject *parent = GetParent(); + + if (parent) + parent->GetExpressionPath(s, qualify_cxx_base_classes, epformat); + + // if we are a deref_of_parent just because we are synthetic array + // members made up to allow ptr[%d] syntax to work in variable + // printing, then add our name ([%d]) to the expression path + if (m_is_array_item_for_pointer && + epformat == eGetExpressionPathFormatHonorPointers) + s.PutCString(m_name.AsCString()); + + if (!IsBaseClass()) { + if (!is_deref_of_parent) { + ValueObject *non_base_class_parent = GetNonBaseClassParent(); + if (non_base_class_parent && + !non_base_class_parent->GetName().IsEmpty()) { + CompilerType non_base_class_parent_compiler_type = + non_base_class_parent->GetCompilerType(); + if (non_base_class_parent_compiler_type) { + if (parent && parent->IsDereferenceOfParent() && + epformat == eGetExpressionPathFormatHonorPointers) { + s.PutCString("->"); + } else { + const uint32_t non_base_class_parent_type_info = + non_base_class_parent_compiler_type.GetTypeInfo(); + + if (non_base_class_parent_type_info & eTypeIsPointer) { + s.PutCString("->"); + } else if ((non_base_class_parent_type_info & eTypeHasChildren) && + !(non_base_class_parent_type_info & eTypeIsArray)) { + s.PutChar('.'); } - else - { - uint64_t load_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - if (load_addr != LLDB_INVALID_ADDRESS) - { - s.Printf("(*( (%s *)0x%" PRIx64 "))", - GetTypeName().AsCString("void"), - load_addr); - return; - } + } + } + } + + const char *name = GetName().GetCString(); + if (name) { + if (qualify_cxx_base_classes) { + if (GetBaseClassPath(s)) + s.PutCString("::"); + } + s.PutCString(name); + } + } + } + + if (is_deref_of_parent && + epformat == eGetExpressionPathFormatDereferencePointers) { + s.PutChar(')'); + } +} + +ValueObjectSP ValueObject::GetValueForExpressionPath( + llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop, + ExpressionPathEndResultType *final_value_type, + const GetValueForExpressionPathOptions &options, + ExpressionPathAftermath *final_task_on_target) { + + ExpressionPathScanEndReason dummy_reason_to_stop = + ValueObject::eExpressionPathScanEndReasonUnknown; + ExpressionPathEndResultType dummy_final_value_type = + ValueObject::eExpressionPathEndResultTypeInvalid; + ExpressionPathAftermath dummy_final_task_on_target = + ValueObject::eExpressionPathAftermathNothing; + + ValueObjectSP ret_val = GetValueForExpressionPath_Impl( + expression, reason_to_stop ? reason_to_stop : &dummy_reason_to_stop, + final_value_type ? final_value_type : &dummy_final_value_type, options, + final_task_on_target ? final_task_on_target + : &dummy_final_task_on_target); + + if (!final_task_on_target || + *final_task_on_target == ValueObject::eExpressionPathAftermathNothing) + return ret_val; + + if (ret_val.get() && + ((final_value_type ? *final_value_type : dummy_final_value_type) == + eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress + // of plain objects + { + if ((final_task_on_target ? *final_task_on_target + : dummy_final_task_on_target) == + ValueObject::eExpressionPathAftermathDereference) { + Error error; + ValueObjectSP final_value = ret_val->Dereference(error); + if (error.Fail() || !final_value.get()) { + if (reason_to_stop) + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonDereferencingFailed; + if (final_value_type) + *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid; + return ValueObjectSP(); + } else { + if (final_task_on_target) + *final_task_on_target = ValueObject::eExpressionPathAftermathNothing; + return final_value; + } + } + if (*final_task_on_target == + ValueObject::eExpressionPathAftermathTakeAddress) { + Error error; + ValueObjectSP final_value = ret_val->AddressOf(error); + if (error.Fail() || !final_value.get()) { + if (reason_to_stop) + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonTakingAddressFailed; + if (final_value_type) + *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid; + return ValueObjectSP(); + } else { + if (final_task_on_target) + *final_task_on_target = ValueObject::eExpressionPathAftermathNothing; + return final_value; + } + } + } + return ret_val; // final_task_on_target will still have its original value, so + // you know I did not do it +} + +ValueObjectSP ValueObject::GetValueForExpressionPath_Impl( + llvm::StringRef expression, ExpressionPathScanEndReason *reason_to_stop, + ExpressionPathEndResultType *final_result, + const GetValueForExpressionPathOptions &options, + ExpressionPathAftermath *what_next) { + ValueObjectSP root = GetSP(); + + if (!root) + return nullptr; + + llvm::StringRef remainder = expression; + + while (true) { + llvm::StringRef temp_expression = remainder; + + CompilerType root_compiler_type = root->GetCompilerType(); + CompilerType pointee_compiler_type; + Flags pointee_compiler_type_info; + + Flags root_compiler_type_info( + root_compiler_type.GetTypeInfo(&pointee_compiler_type)); + if (pointee_compiler_type) + pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo()); + + if (temp_expression.empty()) { + *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; + return root; + } + + switch (temp_expression.front()) { + case '-': { + temp_expression = temp_expression.drop_front(); + if (options.m_check_dot_vs_arrow_syntax && + root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to + // use -> on a + // non-pointer and I + // must catch the error + { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return ValueObjectSP(); + } + if (root_compiler_type_info.Test(eTypeIsObjC) && // if yo are trying to + // extract an ObjC IVar + // when this is forbidden + root_compiler_type_info.Test(eTypeIsPointer) && + options.m_no_fragile_ivar) { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return ValueObjectSP(); + } + if (!temp_expression.startswith(">")) { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return ValueObjectSP(); + } + } + LLVM_FALLTHROUGH; + case '.': // or fallthrough from -> + { + if (options.m_check_dot_vs_arrow_syntax && + temp_expression.front() == '.' && + root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to + // use . on a pointer + // and I must catch the + // error + { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } + temp_expression = temp_expression.drop_front(); // skip . or > + + size_t next_sep_pos = temp_expression.find_first_of("-.[", 1); + ConstString child_name; + if (next_sep_pos == llvm::StringRef::npos) // if no other separator just + // expand this last layer + { + child_name.SetString(temp_expression); + ValueObjectSP child_valobj_sp = + root->GetChildMemberWithName(child_name, true); + + if (child_valobj_sp.get()) // we know we are done, so just return + { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonEndOfString; + *final_result = ValueObject::eExpressionPathEndResultTypePlain; + return child_valobj_sp; + } else { + switch (options.m_synthetic_children_traversal) { + case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: + None: + break; + case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: + FromSynthetic: + if (root->IsSynthetic()) { + child_valobj_sp = root->GetNonSyntheticValue(); + if (child_valobj_sp.get()) + child_valobj_sp = + child_valobj_sp->GetChildMemberWithName(child_name, true); } - } - - if (CanProvideValue()) - { - s.Printf("((%s)%s)", - GetTypeName().AsCString("void"), - GetValueAsCString()); - return; - } - - return; - } - - const bool is_deref_of_parent = IsDereferenceOfParent (); - - if (is_deref_of_parent && epformat == eGetExpressionPathFormatDereferencePointers) - { - // this is the original format of GetExpressionPath() producing code like *(a_ptr).memberName, which is entirely - // fine, until you put this into StackFrame::GetValueForVariableExpressionPath() which prefers to see a_ptr->memberName. - // the eHonorPointers mode is meant to produce strings in this latter format - s.PutCString("*("); - } - - ValueObject* parent = GetParent(); - - if (parent) - parent->GetExpressionPath (s, qualify_cxx_base_classes, epformat); - - // if we are a deref_of_parent just because we are synthetic array - // members made up to allow ptr[%d] syntax to work in variable - // printing, then add our name ([%d]) to the expression path - if (m_is_array_item_for_pointer && epformat == eGetExpressionPathFormatHonorPointers) - s.PutCString(m_name.AsCString()); - - if (!IsBaseClass()) - { - if (!is_deref_of_parent) - { - ValueObject *non_base_class_parent = GetNonBaseClassParent(); - if (non_base_class_parent && !non_base_class_parent->GetName().IsEmpty()) - { - CompilerType non_base_class_parent_compiler_type = non_base_class_parent->GetCompilerType(); - if (non_base_class_parent_compiler_type) - { - if (parent && parent->IsDereferenceOfParent() && epformat == eGetExpressionPathFormatHonorPointers) - { - s.PutCString("->"); - } - else - { - const uint32_t non_base_class_parent_type_info = non_base_class_parent_compiler_type.GetTypeInfo(); - - if (non_base_class_parent_type_info & eTypeIsPointer) - { - s.PutCString("->"); - } - else if ((non_base_class_parent_type_info & eTypeHasChildren) && - !(non_base_class_parent_type_info & eTypeIsArray)) - { - s.PutChar('.'); - } - } - } + break; + case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: + ToSynthetic: + if (!root->IsSynthetic()) { + child_valobj_sp = root->GetSyntheticValue(); + if (child_valobj_sp.get()) + child_valobj_sp = + child_valobj_sp->GetChildMemberWithName(child_name, true); } - - const char *name = GetName().GetCString(); - if (name) - { - if (qualify_cxx_base_classes) - { - if (GetBaseClassPath (s)) - s.PutCString("::"); - } - s.PutCString(name); + break; + case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: + Both: + if (root->IsSynthetic()) { + child_valobj_sp = root->GetNonSyntheticValue(); + if (child_valobj_sp.get()) + child_valobj_sp = + child_valobj_sp->GetChildMemberWithName(child_name, true); + } else { + child_valobj_sp = root->GetSyntheticValue(); + if (child_valobj_sp.get()) + child_valobj_sp = + child_valobj_sp->GetChildMemberWithName(child_name, true); } - } - } - - if (is_deref_of_parent && epformat == eGetExpressionPathFormatDereferencePointers) - { - s.PutChar(')'); - } -} - -ValueObjectSP -ValueObject::GetValueForExpressionPath(const char* expression, - const char** first_unparsed, - ExpressionPathScanEndReason* reason_to_stop, - ExpressionPathEndResultType* final_value_type, - const GetValueForExpressionPathOptions& options, - ExpressionPathAftermath* final_task_on_target) -{ - - const char* dummy_first_unparsed; - ExpressionPathScanEndReason dummy_reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnknown; - ExpressionPathEndResultType dummy_final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid; - ExpressionPathAftermath dummy_final_task_on_target = ValueObject::eExpressionPathAftermathNothing; - - ValueObjectSP ret_val = GetValueForExpressionPath_Impl(expression, - first_unparsed ? first_unparsed : &dummy_first_unparsed, - reason_to_stop ? reason_to_stop : &dummy_reason_to_stop, - final_value_type ? final_value_type : &dummy_final_value_type, - options, - final_task_on_target ? final_task_on_target : &dummy_final_task_on_target); - - if (!final_task_on_target || *final_task_on_target == ValueObject::eExpressionPathAftermathNothing) - return ret_val; - - if (ret_val.get() && ((final_value_type ? *final_value_type : dummy_final_value_type) == eExpressionPathEndResultTypePlain)) // I can only deref and takeaddress of plain objects - { - if ( (final_task_on_target ? *final_task_on_target : dummy_final_task_on_target) == ValueObject::eExpressionPathAftermathDereference) - { - Error error; - ValueObjectSP final_value = ret_val->Dereference(error); - if (error.Fail() || !final_value.get()) - { - if (reason_to_stop) - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed; - if (final_value_type) - *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); + break; + } + } + + // if we are here and options.m_no_synthetic_children is true, + // child_valobj_sp is going to be a NULL SP, + // so we hit the "else" branch, and return an error + if (child_valobj_sp.get()) // if it worked, just return + { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonEndOfString; + *final_result = ValueObject::eExpressionPathEndResultTypePlain; + return child_valobj_sp; + } else { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } + } else // other layers do expand + { + llvm::StringRef next_separator = temp_expression.substr(next_sep_pos); + + child_name.SetString(temp_expression.slice(0, next_sep_pos)); + + ValueObjectSP child_valobj_sp = + root->GetChildMemberWithName(child_name, true); + if (child_valobj_sp.get()) // store the new root and move on + { + root = child_valobj_sp; + remainder = next_separator; + *final_result = ValueObject::eExpressionPathEndResultTypePlain; + continue; + } else { + switch (options.m_synthetic_children_traversal) { + case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: + None: + break; + case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: + FromSynthetic: + if (root->IsSynthetic()) { + child_valobj_sp = root->GetNonSyntheticValue(); + if (child_valobj_sp.get()) + child_valobj_sp = + child_valobj_sp->GetChildMemberWithName(child_name, true); } - else - { - if (final_task_on_target) - *final_task_on_target = ValueObject::eExpressionPathAftermathNothing; - return final_value; + break; + case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: + ToSynthetic: + if (!root->IsSynthetic()) { + child_valobj_sp = root->GetSyntheticValue(); + if (child_valobj_sp.get()) + child_valobj_sp = + child_valobj_sp->GetChildMemberWithName(child_name, true); } - } - if (*final_task_on_target == ValueObject::eExpressionPathAftermathTakeAddress) - { + break; + case GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: + Both: + if (root->IsSynthetic()) { + child_valobj_sp = root->GetNonSyntheticValue(); + if (child_valobj_sp.get()) + child_valobj_sp = + child_valobj_sp->GetChildMemberWithName(child_name, true); + } else { + child_valobj_sp = root->GetSyntheticValue(); + if (child_valobj_sp.get()) + child_valobj_sp = + child_valobj_sp->GetChildMemberWithName(child_name, true); + } + break; + } + } + + // if we are here and options.m_no_synthetic_children is true, + // child_valobj_sp is going to be a NULL SP, + // so we hit the "else" branch, and return an error + if (child_valobj_sp.get()) // if it worked, move on + { + root = child_valobj_sp; + remainder = next_separator; + *final_result = ValueObject::eExpressionPathEndResultTypePlain; + continue; + } else { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } + } + break; + } + case '[': { + if (!root_compiler_type_info.Test(eTypeIsArray) && + !root_compiler_type_info.Test(eTypeIsPointer) && + !root_compiler_type_info.Test( + eTypeIsVector)) // if this is not a T[] nor a T* + { + if (!root_compiler_type_info.Test( + eTypeIsScalar)) // if this is not even a scalar... + { + if (options.m_synthetic_children_traversal == + GetValueForExpressionPathOptions::SyntheticChildrenTraversal:: + None) // ...only chance left is synthetic + { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return ValueObjectSP(); + } + } else if (!options.m_allow_bitfields_syntax) // if this is a scalar, + // check that we can + // expand bitfields + { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return ValueObjectSP(); + } + } + if (temp_expression[1] == + ']') // if this is an unbounded range it only works for arrays + { + if (!root_compiler_type_info.Test(eTypeIsArray)) { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } else // even if something follows, we cannot expand unbounded ranges, + // just let the caller do it + { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet; + *final_result = + ValueObject::eExpressionPathEndResultTypeUnboundedRange; + return root; + } + } + + size_t close_bracket_position = temp_expression.find(']', 1); + if (close_bracket_position == + llvm::StringRef::npos) // if there is no ], this is a syntax error + { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } + + llvm::StringRef bracket_expr = + temp_expression.slice(1, close_bracket_position); + + // If this was an empty expression it would have been caught by the if + // above. + assert(!bracket_expr.empty()); + + if (!bracket_expr.contains('-')) { + // if no separator, this is of the form [N]. Note that this cannot + // be an unbounded range of the form [], because that case was handled + // above with an unconditional return. + unsigned long index = 0; + if (bracket_expr.getAsInteger(0, index)) { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } + + // from here on we do have a valid index + if (root_compiler_type_info.Test(eTypeIsArray)) { + ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index, true); + if (!child_valobj_sp) + child_valobj_sp = root->GetSyntheticArrayMember(index, true); + if (!child_valobj_sp) + if (root->HasSyntheticValue() && + root->GetSyntheticValue()->GetNumChildren() > index) + child_valobj_sp = + root->GetSyntheticValue()->GetChildAtIndex(index, true); + if (child_valobj_sp) { + root = child_valobj_sp; + remainder = + temp_expression.substr(close_bracket_position + 1); // skip ] + *final_result = ValueObject::eExpressionPathEndResultTypePlain; + continue; + } else { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } + } else if (root_compiler_type_info.Test(eTypeIsPointer)) { + if (*what_next == + ValueObject:: + eExpressionPathAftermathDereference && // if this is a + // ptr-to-scalar, I + // am accessing it + // by index and I + // would have + // deref'ed anyway, + // then do it now + // and use this as + // a bitfield + pointee_compiler_type_info.Test(eTypeIsScalar)) { Error error; - ValueObjectSP final_value = ret_val->AddressOf(error); - if (error.Fail() || !final_value.get()) - { - if (reason_to_stop) - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonTakingAddressFailed; - if (final_value_type) - *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); + root = root->Dereference(error); + if (error.Fail() || !root) { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonDereferencingFailed; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } else { + *what_next = eExpressionPathAftermathNothing; + continue; } - else - { - if (final_task_on_target) - *final_task_on_target = ValueObject::eExpressionPathAftermathNothing; - return final_value; + } else { + if (root->GetCompilerType().GetMinimumLanguage() == + eLanguageTypeObjC && + pointee_compiler_type_info.AllClear(eTypeIsPointer) && + root->HasSyntheticValue() && + (options.m_synthetic_children_traversal == + GetValueForExpressionPathOptions:: + SyntheticChildrenTraversal::ToSynthetic || + options.m_synthetic_children_traversal == + GetValueForExpressionPathOptions:: + SyntheticChildrenTraversal::Both)) { + root = root->GetSyntheticValue()->GetChildAtIndex(index, true); + } else + root = root->GetSyntheticArrayMember(index, true); + if (!root) { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } else { + remainder = + temp_expression.substr(close_bracket_position + 1); // skip ] + *final_result = ValueObject::eExpressionPathEndResultTypePlain; + continue; } - } - } - return ret_val; // final_task_on_target will still have its original value, so you know I did not do it + } + } else if (root_compiler_type_info.Test(eTypeIsScalar)) { + root = root->GetSyntheticBitFieldChild(index, index, true); + if (!root) { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } else // we do not know how to expand members of bitfields, so we + // just return and let the caller do any further processing + { + *reason_to_stop = ValueObject:: + eExpressionPathScanEndReasonBitfieldRangeOperatorMet; + *final_result = ValueObject::eExpressionPathEndResultTypeBitfield; + return root; + } + } else if (root_compiler_type_info.Test(eTypeIsVector)) { + root = root->GetChildAtIndex(index, true); + if (!root) { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return ValueObjectSP(); + } else { + remainder = + temp_expression.substr(close_bracket_position + 1); // skip ] + *final_result = ValueObject::eExpressionPathEndResultTypePlain; + continue; + } + } else if (options.m_synthetic_children_traversal == + GetValueForExpressionPathOptions:: + SyntheticChildrenTraversal::ToSynthetic || + options.m_synthetic_children_traversal == + GetValueForExpressionPathOptions:: + SyntheticChildrenTraversal::Both) { + if (root->HasSyntheticValue()) + root = root->GetSyntheticValue(); + else if (!root->IsSynthetic()) { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } + // if we are here, then root itself is a synthetic VO.. should be good + // to go + + if (!root) { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } + root = root->GetChildAtIndex(index, true); + if (!root) { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } else { + remainder = + temp_expression.substr(close_bracket_position + 1); // skip ] + *final_result = ValueObject::eExpressionPathEndResultTypePlain; + continue; + } + } else { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } + } else { + // we have a low and a high index + llvm::StringRef sleft, sright; + unsigned long low_index, high_index; + std::tie(sleft, sright) = bracket_expr.split('-'); + if (sleft.getAsInteger(0, low_index) || + sright.getAsInteger(0, high_index)) { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } + + if (low_index > high_index) // swap indices if required + std::swap(low_index, high_index); + + if (root_compiler_type_info.Test( + eTypeIsScalar)) // expansion only works for scalars + { + root = root->GetSyntheticBitFieldChild(low_index, high_index, true); + if (!root) { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonNoSuchChild; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } else { + *reason_to_stop = ValueObject:: + eExpressionPathScanEndReasonBitfieldRangeOperatorMet; + *final_result = ValueObject::eExpressionPathEndResultTypeBitfield; + return root; + } + } else if (root_compiler_type_info.Test( + eTypeIsPointer) && // if this is a ptr-to-scalar, I am + // accessing it by index and I would + // have deref'ed anyway, then do it + // now and use this as a bitfield + *what_next == + ValueObject::eExpressionPathAftermathDereference && + pointee_compiler_type_info.Test(eTypeIsScalar)) { + Error error; + root = root->Dereference(error); + if (error.Fail() || !root) { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonDereferencingFailed; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } else { + *what_next = ValueObject::eExpressionPathAftermathNothing; + continue; + } + } else { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet; + *final_result = ValueObject::eExpressionPathEndResultTypeBoundedRange; + return root; + } + } + break; + } + default: // some non-separator is in the way + { + *reason_to_stop = + ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; + *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; + return nullptr; + } + } + } +} + +void ValueObject::LogValueObject(Log *log) { + if (log) + return LogValueObject(log, DumpValueObjectOptions(*this)); +} + +void ValueObject::LogValueObject(Log *log, + const DumpValueObjectOptions &options) { + if (log) { + StreamString s; + Dump(s, options); + if (s.GetSize()) + log->PutCString(s.GetData()); + } } -int -ValueObject::GetValuesForExpressionPath(const char* expression, - ValueObjectListSP& list, - const char** first_unparsed, - ExpressionPathScanEndReason* reason_to_stop, - ExpressionPathEndResultType* final_value_type, - const GetValueForExpressionPathOptions& options, - ExpressionPathAftermath* final_task_on_target) -{ - const char* dummy_first_unparsed; - ExpressionPathScanEndReason dummy_reason_to_stop; - ExpressionPathEndResultType dummy_final_value_type; - ExpressionPathAftermath dummy_final_task_on_target = ValueObject::eExpressionPathAftermathNothing; - - ValueObjectSP ret_val = GetValueForExpressionPath_Impl(expression, - first_unparsed ? first_unparsed : &dummy_first_unparsed, - reason_to_stop ? reason_to_stop : &dummy_reason_to_stop, - final_value_type ? final_value_type : &dummy_final_value_type, - options, - final_task_on_target ? final_task_on_target : &dummy_final_task_on_target); - - if (!ret_val.get()) // if there are errors, I add nothing to the list - return 0; - - if ( (reason_to_stop ? *reason_to_stop : dummy_reason_to_stop) != eExpressionPathScanEndReasonArrayRangeOperatorMet) - { - // I need not expand a range, just post-process the final value and return - if (!final_task_on_target || *final_task_on_target == ValueObject::eExpressionPathAftermathNothing) - { - list->Append(ret_val); - return 1; - } - if (ret_val.get() && (final_value_type ? *final_value_type : dummy_final_value_type) == eExpressionPathEndResultTypePlain) // I can only deref and takeaddress of plain objects - { - if (*final_task_on_target == ValueObject::eExpressionPathAftermathDereference) - { - Error error; - ValueObjectSP final_value = ret_val->Dereference(error); - if (error.Fail() || !final_value.get()) - { - if (reason_to_stop) - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed; - if (final_value_type) - *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid; - return 0; - } - else - { - *final_task_on_target = ValueObject::eExpressionPathAftermathNothing; - list->Append(final_value); - return 1; - } - } - if (*final_task_on_target == ValueObject::eExpressionPathAftermathTakeAddress) - { - Error error; - ValueObjectSP final_value = ret_val->AddressOf(error); - if (error.Fail() || !final_value.get()) - { - if (reason_to_stop) - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonTakingAddressFailed; - if (final_value_type) - *final_value_type = ValueObject::eExpressionPathEndResultTypeInvalid; - return 0; - } - else - { - *final_task_on_target = ValueObject::eExpressionPathAftermathNothing; - list->Append(final_value); - return 1; - } - } - } - } - else - { - return ExpandArraySliceExpression(first_unparsed ? *first_unparsed : dummy_first_unparsed, - first_unparsed ? first_unparsed : &dummy_first_unparsed, - ret_val, - list, - reason_to_stop ? reason_to_stop : &dummy_reason_to_stop, - final_value_type ? final_value_type : &dummy_final_value_type, - options, - final_task_on_target ? final_task_on_target : &dummy_final_task_on_target); - } - // in any non-covered case, just do the obviously right thing - list->Append(ret_val); - return 1; -} +void ValueObject::Dump(Stream &s) { Dump(s, DumpValueObjectOptions(*this)); } -ValueObjectSP -ValueObject::GetValueForExpressionPath_Impl(const char* expression_cstr, - const char** first_unparsed, - ExpressionPathScanEndReason* reason_to_stop, - ExpressionPathEndResultType* final_result, - const GetValueForExpressionPathOptions& options, - ExpressionPathAftermath* what_next) -{ - ValueObjectSP root = GetSP(); - - if (!root.get()) - return ValueObjectSP(); - - *first_unparsed = expression_cstr; - - while (true) - { - - const char* expression_cstr = *first_unparsed; // hide the top level expression_cstr - - CompilerType root_compiler_type = root->GetCompilerType(); - CompilerType pointee_compiler_type; - Flags pointee_compiler_type_info; - - Flags root_compiler_type_info(root_compiler_type.GetTypeInfo(&pointee_compiler_type)); - if (pointee_compiler_type) - pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo()); - - if (!expression_cstr || *expression_cstr == '\0') - { - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; - return root; - } - - switch (*expression_cstr) - { - case '-': - { - if (options.m_check_dot_vs_arrow_syntax && - root_compiler_type_info.Test(eTypeIsPointer) ) // if you are trying to use -> on a non-pointer and I must catch the error - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrowInsteadOfDot; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - if (root_compiler_type_info.Test(eTypeIsObjC) && // if yo are trying to extract an ObjC IVar when this is forbidden - root_compiler_type_info.Test(eTypeIsPointer) && - options.m_no_fragile_ivar) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonFragileIVarNotAllowed; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - if (expression_cstr[1] != '>') - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - expression_cstr++; // skip the - - } - LLVM_FALLTHROUGH; - case '.': // or fallthrough from -> - { - if (options.m_check_dot_vs_arrow_syntax && *expression_cstr == '.' && - root_compiler_type_info.Test(eTypeIsPointer)) // if you are trying to use . on a pointer and I must catch the error - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDotInsteadOfArrow; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - expression_cstr++; // skip . - const char *next_separator = strpbrk(expression_cstr+1,"-.["); - ConstString child_name; - if (!next_separator) // if no other separator just expand this last layer - { - child_name.SetCString (expression_cstr); - ValueObjectSP child_valobj_sp = root->GetChildMemberWithName(child_name, true); - - if (child_valobj_sp.get()) // we know we are done, so just return - { - *first_unparsed = ""; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; - *final_result = ValueObject::eExpressionPathEndResultTypePlain; - return child_valobj_sp; - } - else - { - switch (options.m_synthetic_children_traversal) - { - case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None: - break; - case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::FromSynthetic: - if (root->IsSynthetic()) - { - child_valobj_sp = root->GetNonSyntheticValue(); - if (child_valobj_sp.get()) - child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true); - } - break; - case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::ToSynthetic: - if (!root->IsSynthetic()) - { - child_valobj_sp = root->GetSyntheticValue(); - if (child_valobj_sp.get()) - child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true); - } - break; - case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::Both: - if (root->IsSynthetic()) - { - child_valobj_sp = root->GetNonSyntheticValue(); - if (child_valobj_sp.get()) - child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true); - } - else - { - child_valobj_sp = root->GetSyntheticValue(); - if (child_valobj_sp.get()) - child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true); - } - break; - } - } - - // if we are here and options.m_no_synthetic_children is true, child_valobj_sp is going to be a NULL SP, - // so we hit the "else" branch, and return an error - if(child_valobj_sp.get()) // if it worked, just return - { - *first_unparsed = ""; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; - *final_result = ValueObject::eExpressionPathEndResultTypePlain; - return child_valobj_sp; - } - else - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - } - else // other layers do expand - { - child_name.SetCStringWithLength(expression_cstr, next_separator - expression_cstr); - ValueObjectSP child_valobj_sp = root->GetChildMemberWithName(child_name, true); - if (child_valobj_sp.get()) // store the new root and move on - { - root = child_valobj_sp; - *first_unparsed = next_separator; - *final_result = ValueObject::eExpressionPathEndResultTypePlain; - continue; - } - else - { - switch (options.m_synthetic_children_traversal) - { - case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None: - break; - case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::FromSynthetic: - if (root->IsSynthetic()) - { - child_valobj_sp = root->GetNonSyntheticValue(); - if (child_valobj_sp.get()) - child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true); - } - break; - case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::ToSynthetic: - if (!root->IsSynthetic()) - { - child_valobj_sp = root->GetSyntheticValue(); - if (child_valobj_sp.get()) - child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true); - } - break; - case GetValueForExpressionPathOptions::SyntheticChildrenTraversal::Both: - if (root->IsSynthetic()) - { - child_valobj_sp = root->GetNonSyntheticValue(); - if (child_valobj_sp.get()) - child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true); - } - else - { - child_valobj_sp = root->GetSyntheticValue(); - if (child_valobj_sp.get()) - child_valobj_sp = child_valobj_sp->GetChildMemberWithName(child_name, true); - } - break; - } - } - - // if we are here and options.m_no_synthetic_children is true, child_valobj_sp is going to be a NULL SP, - // so we hit the "else" branch, and return an error - if(child_valobj_sp.get()) // if it worked, move on - { - root = child_valobj_sp; - *first_unparsed = next_separator; - *final_result = ValueObject::eExpressionPathEndResultTypePlain; - continue; - } - else - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - } - break; - } - case '[': - { - if (!root_compiler_type_info.Test(eTypeIsArray) && !root_compiler_type_info.Test(eTypeIsPointer) && !root_compiler_type_info.Test(eTypeIsVector)) // if this is not a T[] nor a T* - { - if (!root_compiler_type_info.Test(eTypeIsScalar)) // if this is not even a scalar... - { - if (options.m_synthetic_children_traversal == GetValueForExpressionPathOptions::SyntheticChildrenTraversal::None) // ...only chance left is synthetic - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - } - else if (!options.m_allow_bitfields_syntax) // if this is a scalar, check that we can expand bitfields - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - } - if (*(expression_cstr+1) == ']') // if this is an unbounded range it only works for arrays - { - if (!root_compiler_type_info.Test(eTypeIsArray)) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - else // even if something follows, we cannot expand unbounded ranges, just let the caller do it - { - *first_unparsed = expression_cstr+2; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet; - *final_result = ValueObject::eExpressionPathEndResultTypeUnboundedRange; - return root; - } - } - const char *separator_position = ::strchr(expression_cstr+1,'-'); - const char *close_bracket_position = ::strchr(expression_cstr+1,']'); - if (!close_bracket_position) // if there is no ], this is a syntax error - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - if (!separator_position || separator_position > close_bracket_position) // if no separator, this is either [] or [N] - { - char *end = NULL; - unsigned long index = ::strtoul (expression_cstr+1, &end, 0); - if (!end || end != close_bracket_position) // if something weird is in our way return an error - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays - { - if (root_compiler_type_info.Test(eTypeIsArray)) - { - *first_unparsed = expression_cstr+2; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet; - *final_result = ValueObject::eExpressionPathEndResultTypeUnboundedRange; - return root; - } - else - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - } - // from here on we do have a valid index - if (root_compiler_type_info.Test(eTypeIsArray)) - { - ValueObjectSP child_valobj_sp = root->GetChildAtIndex(index, true); - if (!child_valobj_sp) - child_valobj_sp = root->GetSyntheticArrayMember(index, true); - if (!child_valobj_sp) - if (root->HasSyntheticValue() && root->GetSyntheticValue()->GetNumChildren() > index) - child_valobj_sp = root->GetSyntheticValue()->GetChildAtIndex(index, true); - if (child_valobj_sp) - { - root = child_valobj_sp; - *first_unparsed = end+1; // skip ] - *final_result = ValueObject::eExpressionPathEndResultTypePlain; - continue; - } - else - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - } - else if (root_compiler_type_info.Test(eTypeIsPointer)) - { - if (*what_next == ValueObject::eExpressionPathAftermathDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield - pointee_compiler_type_info.Test(eTypeIsScalar)) - { - Error error; - root = root->Dereference(error); - if (error.Fail() || !root.get()) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - else - { - *what_next = eExpressionPathAftermathNothing; - continue; - } - } - else - { - if (root->GetCompilerType().GetMinimumLanguage() == eLanguageTypeObjC - && pointee_compiler_type_info.AllClear(eTypeIsPointer) - && root->HasSyntheticValue() - && (options.m_synthetic_children_traversal == GetValueForExpressionPathOptions::SyntheticChildrenTraversal::ToSynthetic || - options.m_synthetic_children_traversal == GetValueForExpressionPathOptions::SyntheticChildrenTraversal::Both)) - { - root = root->GetSyntheticValue()->GetChildAtIndex(index, true); - } - else - root = root->GetSyntheticArrayMember(index, true); - if (!root.get()) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - else - { - *first_unparsed = end+1; // skip ] - *final_result = ValueObject::eExpressionPathEndResultTypePlain; - continue; - } - } - } - else if (root_compiler_type_info.Test(eTypeIsScalar)) - { - root = root->GetSyntheticBitFieldChild(index, index, true); - if (!root.get()) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - else // we do not know how to expand members of bitfields, so we just return and let the caller do any further processing - { - *first_unparsed = end+1; // skip ] - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonBitfieldRangeOperatorMet; - *final_result = ValueObject::eExpressionPathEndResultTypeBitfield; - return root; - } - } - else if (root_compiler_type_info.Test(eTypeIsVector)) - { - root = root->GetChildAtIndex(index, true); - if (!root.get()) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - else - { - *first_unparsed = end+1; // skip ] - *final_result = ValueObject::eExpressionPathEndResultTypePlain; - continue; - } - } - else if (options.m_synthetic_children_traversal == GetValueForExpressionPathOptions::SyntheticChildrenTraversal::ToSynthetic || - options.m_synthetic_children_traversal == GetValueForExpressionPathOptions::SyntheticChildrenTraversal::Both) - { - if (root->HasSyntheticValue()) - root = root->GetSyntheticValue(); - else if (!root->IsSynthetic()) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - // if we are here, then root itself is a synthetic VO.. should be good to go - - if (!root.get()) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonSyntheticValueMissing; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - root = root->GetChildAtIndex(index, true); - if (!root.get()) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - else - { - *first_unparsed = end+1; // skip ] - *final_result = ValueObject::eExpressionPathEndResultTypePlain; - continue; - } - } - else - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - } - else // we have a low and a high index - { - char *end = NULL; - unsigned long index_lower = ::strtoul (expression_cstr+1, &end, 0); - if (!end || end != separator_position) // if something weird is in our way return an error - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - unsigned long index_higher = ::strtoul (separator_position+1, &end, 0); - if (!end || end != close_bracket_position) // if something weird is in our way return an error - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - if (index_lower > index_higher) // swap indices if required - { - unsigned long temp = index_lower; - index_lower = index_higher; - index_higher = temp; - } - if (root_compiler_type_info.Test(eTypeIsScalar)) // expansion only works for scalars - { - root = root->GetSyntheticBitFieldChild(index_lower, index_higher, true); - if (!root.get()) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - else - { - *first_unparsed = end+1; // skip ] - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonBitfieldRangeOperatorMet; - *final_result = ValueObject::eExpressionPathEndResultTypeBitfield; - return root; - } - } - else if (root_compiler_type_info.Test(eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield - *what_next == ValueObject::eExpressionPathAftermathDereference && - pointee_compiler_type_info.Test(eTypeIsScalar)) - { - Error error; - root = root->Dereference(error); - if (error.Fail() || !root.get()) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - } - else - { - *what_next = ValueObject::eExpressionPathAftermathNothing; - continue; - } - } - else - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonArrayRangeOperatorMet; - *final_result = ValueObject::eExpressionPathEndResultTypeBoundedRange; - return root; - } - } - break; - } - default: // some non-separator is in the way - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return ValueObjectSP(); - break; - } - } - } +void ValueObject::Dump(Stream &s, const DumpValueObjectOptions &options) { + ValueObjectPrinter printer(this, &s, options); + printer.PrintValueObject(); } -int -ValueObject::ExpandArraySliceExpression(const char* expression_cstr, - const char** first_unparsed, - ValueObjectSP root, - ValueObjectListSP& list, - ExpressionPathScanEndReason* reason_to_stop, - ExpressionPathEndResultType* final_result, - const GetValueForExpressionPathOptions& options, - ExpressionPathAftermath* what_next) -{ - if (!root.get()) - return 0; - - *first_unparsed = expression_cstr; - - while (true) - { - - const char* expression_cstr = *first_unparsed; // hide the top level expression_cstr - - CompilerType root_compiler_type = root->GetCompilerType(); - CompilerType pointee_compiler_type; - Flags pointee_compiler_type_info; - Flags root_compiler_type_info(root_compiler_type.GetTypeInfo(&pointee_compiler_type)); - if (pointee_compiler_type) - pointee_compiler_type_info.Reset(pointee_compiler_type.GetTypeInfo()); - - if (!expression_cstr || *expression_cstr == '\0') - { - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEndOfString; - list->Append(root); - return 1; - } - - switch (*expression_cstr) - { - case '[': - { - if (!root_compiler_type_info.Test(eTypeIsArray) && !root_compiler_type_info.Test(eTypeIsPointer)) // if this is not a T[] nor a T* - { - if (!root_compiler_type_info.Test(eTypeIsScalar)) // if this is not even a scalar, this syntax is just plain wrong! - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorInvalid; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return 0; - } - else if (!options.m_allow_bitfields_syntax) // if this is a scalar, check that we can expand bitfields - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorNotAllowed; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return 0; - } - } - if (*(expression_cstr+1) == ']') // if this is an unbounded range it only works for arrays - { - if (!root_compiler_type_info.Test(eTypeIsArray)) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return 0; - } - else // expand this into list - { - const size_t max_index = root->GetNumChildren() - 1; - for (size_t index = 0; index < max_index; index++) - { - ValueObjectSP child = - root->GetChildAtIndex(index, true); - list->Append(child); - } - *first_unparsed = expression_cstr+2; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded; - *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList; - return max_index; // tell me number of items I added to the VOList - } - } - const char *separator_position = ::strchr(expression_cstr+1,'-'); - const char *close_bracket_position = ::strchr(expression_cstr+1,']'); - if (!close_bracket_position) // if there is no ], this is a syntax error - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return 0; - } - if (!separator_position || separator_position > close_bracket_position) // if no separator, this is either [] or [N] - { - char *end = NULL; - unsigned long index = ::strtoul (expression_cstr+1, &end, 0); - if (!end || end != close_bracket_position) // if something weird is in our way return an error - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return 0; - } - if (end - expression_cstr == 1) // if this is [], only return a valid value for arrays - { - if (root_compiler_type_info.Test(eTypeIsArray)) - { - const size_t max_index = root->GetNumChildren() - 1; - for (size_t index = 0; index < max_index; index++) - { - ValueObjectSP child = - root->GetChildAtIndex(index, true); - list->Append(child); - } - *first_unparsed = expression_cstr+2; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded; - *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList; - return max_index; // tell me number of items I added to the VOList - } - else - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonEmptyRangeNotAllowed; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return 0; - } - } - // from here on we do have a valid index - if (root_compiler_type_info.Test(eTypeIsArray)) - { - root = root->GetChildAtIndex(index, true); - if (!root.get()) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return 0; - } - else - { - list->Append(root); - *first_unparsed = end+1; // skip ] - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded; - *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList; - return 1; - } - } - else if (root_compiler_type_info.Test(eTypeIsPointer)) - { - if (*what_next == ValueObject::eExpressionPathAftermathDereference && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield - pointee_compiler_type_info.Test(eTypeIsScalar)) - { - Error error; - root = root->Dereference(error); - if (error.Fail() || !root.get()) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return 0; - } - else - { - *what_next = eExpressionPathAftermathNothing; - continue; - } - } - else - { - root = root->GetSyntheticArrayMember(index, true); - if (!root.get()) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return 0; - } - else - { - list->Append(root); - *first_unparsed = end+1; // skip ] - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded; - *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList; - return 1; - } - } - } - else /*if (ClangASTContext::IsScalarType(root_compiler_type))*/ - { - root = root->GetSyntheticBitFieldChild(index, index, true); - if (!root.get()) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return 0; - } - else // we do not know how to expand members of bitfields, so we just return and let the caller do any further processing - { - list->Append(root); - *first_unparsed = end+1; // skip ] - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded; - *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList; - return 1; - } - } - } - else // we have a low and a high index - { - char *end = NULL; - unsigned long index_lower = ::strtoul (expression_cstr+1, &end, 0); - if (!end || end != separator_position) // if something weird is in our way return an error - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return 0; - } - unsigned long index_higher = ::strtoul (separator_position+1, &end, 0); - if (!end || end != close_bracket_position) // if something weird is in our way return an error - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return 0; - } - if (index_lower > index_higher) // swap indices if required - { - unsigned long temp = index_lower; - index_lower = index_higher; - index_higher = temp; - } - if (root_compiler_type_info.Test(eTypeIsScalar)) // expansion only works for scalars - { - root = root->GetSyntheticBitFieldChild(index_lower, index_higher, true); - if (!root.get()) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonNoSuchChild; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return 0; - } - else - { - list->Append(root); - *first_unparsed = end+1; // skip ] - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded; - *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList; - return 1; - } - } - else if (root_compiler_type_info.Test(eTypeIsPointer) && // if this is a ptr-to-scalar, I am accessing it by index and I would have deref'ed anyway, then do it now and use this as a bitfield - *what_next == ValueObject::eExpressionPathAftermathDereference && - pointee_compiler_type_info.Test(eTypeIsScalar)) - { - Error error; - root = root->Dereference(error); - if (error.Fail() || !root.get()) - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonDereferencingFailed; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return 0; - } - else - { - *what_next = ValueObject::eExpressionPathAftermathNothing; - continue; - } - } - else - { - for (unsigned long index = index_lower; - index <= index_higher; index++) - { - ValueObjectSP child = - root->GetChildAtIndex(index, true); - list->Append(child); - } - *first_unparsed = end+1; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonRangeOperatorExpanded; - *final_result = ValueObject::eExpressionPathEndResultTypeValueObjectList; - return index_higher-index_lower+1; // tell me number of items I added to the VOList - } - } - break; - } - default: // some non-[ separator, or something entirely wrong, is in the way - { - *first_unparsed = expression_cstr; - *reason_to_stop = ValueObject::eExpressionPathScanEndReasonUnexpectedSymbol; - *final_result = ValueObject::eExpressionPathEndResultTypeInvalid; - return 0; - break; - } - } - } -} +ValueObjectSP ValueObject::CreateConstantValue(const ConstString &name) { + ValueObjectSP valobj_sp; -void -ValueObject::LogValueObject (Log *log) -{ - if (log) - return LogValueObject (log, DumpValueObjectOptions(*this)); -} + if (UpdateValueIfNeeded(false) && m_error.Success()) { + ExecutionContext exe_ctx(GetExecutionContextRef()); -void -ValueObject::LogValueObject (Log *log, const DumpValueObjectOptions& options) -{ - if (log) - { - StreamString s; - Dump (s, options); - if (s.GetSize()) - log->PutCString(s.GetData()); - } -} + DataExtractor data; + data.SetByteOrder(m_data.GetByteOrder()); + data.SetAddressByteSize(m_data.GetAddressByteSize()); -void -ValueObject::Dump (Stream &s) -{ - Dump (s, DumpValueObjectOptions(*this)); -} + if (IsBitfield()) { + Value v(Scalar(GetValueAsUnsigned(UINT64_MAX))); + m_error = v.GetValueAsData(&exe_ctx, data, 0, GetModule().get()); + } else + m_error = m_value.GetValueAsData(&exe_ctx, data, 0, GetModule().get()); -void -ValueObject::Dump (Stream &s, - const DumpValueObjectOptions& options) -{ - ValueObjectPrinter printer(this,&s,options); - printer.PrintValueObject(); -} + valobj_sp = ValueObjectConstResult::Create( + exe_ctx.GetBestExecutionContextScope(), GetCompilerType(), name, data, + GetAddressOf()); + } -ValueObjectSP -ValueObject::CreateConstantValue (const ConstString &name) -{ - ValueObjectSP valobj_sp; - - if (UpdateValueIfNeeded(false) && m_error.Success()) - { - ExecutionContext exe_ctx (GetExecutionContextRef()); - - DataExtractor data; - data.SetByteOrder (m_data.GetByteOrder()); - data.SetAddressByteSize(m_data.GetAddressByteSize()); - - if (IsBitfield()) - { - Value v(Scalar(GetValueAsUnsigned(UINT64_MAX))); - m_error = v.GetValueAsData (&exe_ctx, data, 0, GetModule().get()); - } - else - m_error = m_value.GetValueAsData (&exe_ctx, data, 0, GetModule().get()); - - valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), - GetCompilerType(), - name, - data, - GetAddressOf()); - } - - if (!valobj_sp) - { - ExecutionContext exe_ctx (GetExecutionContextRef()); - valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), m_error); - } - return valobj_sp; + if (!valobj_sp) { + ExecutionContext exe_ctx(GetExecutionContextRef()); + valobj_sp = ValueObjectConstResult::Create( + exe_ctx.GetBestExecutionContextScope(), m_error); + } + return valobj_sp; } -ValueObjectSP -ValueObject::GetQualifiedRepresentationIfAvailable (lldb::DynamicValueType dynValue, - bool synthValue) -{ - ValueObjectSP result_sp(GetSP()); - - switch (dynValue) - { - case lldb::eDynamicCanRunTarget: - case lldb::eDynamicDontRunTarget: - { - if (!result_sp->IsDynamic()) - { - if (result_sp->GetDynamicValue(dynValue)) - result_sp = result_sp->GetDynamicValue(dynValue); - } - } - break; - case lldb::eNoDynamicValues: - { - if (result_sp->IsDynamic()) - { - if (result_sp->GetStaticValue()) - result_sp = result_sp->GetStaticValue(); - } - } - break; +ValueObjectSP ValueObject::GetQualifiedRepresentationIfAvailable( + lldb::DynamicValueType dynValue, bool synthValue) { + ValueObjectSP result_sp(GetSP()); + + switch (dynValue) { + case lldb::eDynamicCanRunTarget: + case lldb::eDynamicDontRunTarget: { + if (!result_sp->IsDynamic()) { + if (result_sp->GetDynamicValue(dynValue)) + result_sp = result_sp->GetDynamicValue(dynValue); } - - if (synthValue) - { - if (!result_sp->IsSynthetic()) - { - if (result_sp->GetSyntheticValue()) - result_sp = result_sp->GetSyntheticValue(); - } + } break; + case lldb::eNoDynamicValues: { + if (result_sp->IsDynamic()) { + if (result_sp->GetStaticValue()) + result_sp = result_sp->GetStaticValue(); } - else - { - if (result_sp->IsSynthetic()) - { - if (result_sp->GetNonSyntheticValue()) - result_sp = result_sp->GetNonSyntheticValue(); - } - } - - return result_sp; -} + } break; + } -lldb::addr_t -ValueObject::GetCPPVTableAddress (AddressType &address_type) -{ - CompilerType pointee_type; - CompilerType this_type(GetCompilerType()); - uint32_t type_info = this_type.GetTypeInfo(&pointee_type); - if (type_info) - { - bool ptr_or_ref = false; - if (type_info & (eTypeIsPointer | eTypeIsReference)) - { - ptr_or_ref = true; - type_info = pointee_type.GetTypeInfo(); - } - - const uint32_t cpp_class = eTypeIsClass | eTypeIsCPlusPlus; - if ((type_info & cpp_class) == cpp_class) - { - if (ptr_or_ref) - { - address_type = GetAddressTypeOfChildren(); - return GetValueAsUnsigned(LLDB_INVALID_ADDRESS); - } - else - return GetAddressOf (false, &address_type); - } + if (synthValue) { + if (!result_sp->IsSynthetic()) { + if (result_sp->GetSyntheticValue()) + result_sp = result_sp->GetSyntheticValue(); + } + } else { + if (result_sp->IsSynthetic()) { + if (result_sp->GetNonSyntheticValue()) + result_sp = result_sp->GetNonSyntheticValue(); } + } - address_type = eAddressTypeInvalid; - return LLDB_INVALID_ADDRESS; + return result_sp; } -ValueObjectSP -ValueObject::Dereference (Error &error) -{ - if (m_deref_valobj) - return m_deref_valobj->GetSP(); - - const bool is_pointer_or_reference_type = IsPointerOrReferenceType(); - if (is_pointer_or_reference_type) - { - bool omit_empty_base_classes = true; - bool ignore_array_bounds = false; - - std::string child_name_str; - uint32_t child_byte_size = 0; - int32_t child_byte_offset = 0; - uint32_t child_bitfield_bit_size = 0; - uint32_t child_bitfield_bit_offset = 0; - bool child_is_base_class = false; - bool child_is_deref_of_parent = false; - const bool transparent_pointers = false; - CompilerType compiler_type = GetCompilerType(); - CompilerType child_compiler_type; - uint64_t language_flags; - - ExecutionContext exe_ctx (GetExecutionContextRef()); - - child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex (&exe_ctx, - 0, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name_str, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent, - this, - language_flags); - if (child_compiler_type && child_byte_size) - { - ConstString child_name; - if (!child_name_str.empty()) - child_name.SetCString (child_name_str.c_str()); - - m_deref_valobj = new ValueObjectChild (*this, - child_compiler_type, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent, - eAddressTypeInvalid, - language_flags); - } +lldb::addr_t ValueObject::GetCPPVTableAddress(AddressType &address_type) { + CompilerType pointee_type; + CompilerType this_type(GetCompilerType()); + uint32_t type_info = this_type.GetTypeInfo(&pointee_type); + if (type_info) { + bool ptr_or_ref = false; + if (type_info & (eTypeIsPointer | eTypeIsReference)) { + ptr_or_ref = true; + type_info = pointee_type.GetTypeInfo(); } - if (m_deref_valobj) - { - error.Clear(); - return m_deref_valobj->GetSP(); + const uint32_t cpp_class = eTypeIsClass | eTypeIsCPlusPlus; + if ((type_info & cpp_class) == cpp_class) { + if (ptr_or_ref) { + address_type = GetAddressTypeOfChildren(); + return GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + } else + return GetAddressOf(false, &address_type); } - else - { - StreamString strm; - GetExpressionPath(strm, true); + } - if (is_pointer_or_reference_type) - error.SetErrorStringWithFormat("dereference failed: (%s) %s", GetTypeName().AsCString("<invalid type>"), strm.GetString().c_str()); - else - error.SetErrorStringWithFormat("not a pointer or reference type: (%s) %s", GetTypeName().AsCString("<invalid type>"), strm.GetString().c_str()); - return ValueObjectSP(); - } + address_type = eAddressTypeInvalid; + return LLDB_INVALID_ADDRESS; } -ValueObjectSP -ValueObject::AddressOf (Error &error) -{ - if (m_addr_of_valobj_sp) - return m_addr_of_valobj_sp; - - AddressType address_type = eAddressTypeInvalid; - const bool scalar_is_load_address = false; - addr_t addr = GetAddressOf (scalar_is_load_address, &address_type); - error.Clear(); - if (addr != LLDB_INVALID_ADDRESS && address_type != eAddressTypeHost) - { - switch (address_type) - { - case eAddressTypeInvalid: - { - StreamString expr_path_strm; - GetExpressionPath(expr_path_strm, true); - error.SetErrorStringWithFormat("'%s' is not in memory", expr_path_strm.GetString().c_str()); - } - break; - - case eAddressTypeFile: - case eAddressTypeLoad: - { - CompilerType compiler_type = GetCompilerType(); - if (compiler_type) - { - std::string name (1, '&'); - name.append (m_name.AsCString("")); - ExecutionContext exe_ctx (GetExecutionContextRef()); - m_addr_of_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), - compiler_type.GetPointerType(), - ConstString (name.c_str()), - addr, - eAddressTypeInvalid, - m_data.GetAddressByteSize()); - } - } - break; - default: - break; - } - } - else - { - StreamString expr_path_strm; - GetExpressionPath(expr_path_strm, true); - error.SetErrorStringWithFormat("'%s' doesn't have a valid address", expr_path_strm.GetString().c_str()); - } - - return m_addr_of_valobj_sp; -} +ValueObjectSP ValueObject::Dereference(Error &error) { + if (m_deref_valobj) + return m_deref_valobj->GetSP(); -ValueObjectSP -ValueObject::Cast (const CompilerType &compiler_type) -{ - return ValueObjectCast::Create (*this, GetName(), compiler_type); -} + const bool is_pointer_or_reference_type = IsPointerOrReferenceType(); + if (is_pointer_or_reference_type) { + bool omit_empty_base_classes = true; + bool ignore_array_bounds = false; -ValueObjectSP -ValueObject::CastPointerType (const char *name, CompilerType &compiler_type) -{ - ValueObjectSP valobj_sp; - AddressType address_type; - addr_t ptr_value = GetPointerValue (&address_type); - - if (ptr_value != LLDB_INVALID_ADDRESS) - { - Address ptr_addr (ptr_value); - ExecutionContext exe_ctx (GetExecutionContextRef()); - valobj_sp = ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(), - name, - ptr_addr, - compiler_type); - } - return valobj_sp; -} + std::string child_name_str; + uint32_t child_byte_size = 0; + int32_t child_byte_offset = 0; + uint32_t child_bitfield_bit_size = 0; + uint32_t child_bitfield_bit_offset = 0; + bool child_is_base_class = false; + bool child_is_deref_of_parent = false; + const bool transparent_pointers = false; + CompilerType compiler_type = GetCompilerType(); + CompilerType child_compiler_type; + uint64_t language_flags; -ValueObjectSP -ValueObject::CastPointerType (const char *name, TypeSP &type_sp) -{ - ValueObjectSP valobj_sp; - AddressType address_type; - addr_t ptr_value = GetPointerValue (&address_type); - - if (ptr_value != LLDB_INVALID_ADDRESS) - { - Address ptr_addr (ptr_value); - ExecutionContext exe_ctx (GetExecutionContextRef()); - valobj_sp = ValueObjectMemory::Create (exe_ctx.GetBestExecutionContextScope(), - name, - ptr_addr, - type_sp); - } - return valobj_sp; -} + ExecutionContext exe_ctx(GetExecutionContextRef()); -ValueObject::EvaluationPoint::EvaluationPoint () : - m_mod_id(), - m_exe_ctx_ref(), - m_needs_update (true) -{ -} + child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex( + &exe_ctx, 0, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset, + child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, + child_is_deref_of_parent, this, language_flags); + if (child_compiler_type && child_byte_size) { + ConstString child_name; + if (!child_name_str.empty()) + child_name.SetCString(child_name_str.c_str()); -ValueObject::EvaluationPoint::EvaluationPoint (ExecutionContextScope *exe_scope, bool use_selected): - m_mod_id(), - m_exe_ctx_ref(), - m_needs_update (true) -{ - ExecutionContext exe_ctx(exe_scope); - TargetSP target_sp (exe_ctx.GetTargetSP()); - if (target_sp) - { - m_exe_ctx_ref.SetTargetSP (target_sp); - ProcessSP process_sp (exe_ctx.GetProcessSP()); - if (!process_sp) - process_sp = target_sp->GetProcessSP(); - - if (process_sp) - { - m_mod_id = process_sp->GetModID(); - m_exe_ctx_ref.SetProcessSP (process_sp); - - ThreadSP thread_sp (exe_ctx.GetThreadSP()); - - if (!thread_sp) - { - if (use_selected) - thread_sp = process_sp->GetThreadList().GetSelectedThread(); - } - - if (thread_sp) - { - m_exe_ctx_ref.SetThreadSP(thread_sp); - - StackFrameSP frame_sp (exe_ctx.GetFrameSP()); - if (!frame_sp) - { - if (use_selected) - frame_sp = thread_sp->GetSelectedFrame(); - } - if (frame_sp) - m_exe_ctx_ref.SetFrameSP(frame_sp); - } - } + m_deref_valobj = new ValueObjectChild( + *this, child_compiler_type, child_name, child_byte_size, + child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, + child_is_base_class, child_is_deref_of_parent, eAddressTypeInvalid, + language_flags); } -} + } -ValueObject::EvaluationPoint::EvaluationPoint (const ValueObject::EvaluationPoint &rhs) : - m_mod_id(), - m_exe_ctx_ref(rhs.m_exe_ctx_ref), - m_needs_update (true) -{ -} + if (m_deref_valobj) { + error.Clear(); + return m_deref_valobj->GetSP(); + } else { + StreamString strm; + GetExpressionPath(strm, true); -ValueObject::EvaluationPoint::~EvaluationPoint () -{ + if (is_pointer_or_reference_type) + error.SetErrorStringWithFormat("dereference failed: (%s) %s", + GetTypeName().AsCString("<invalid type>"), + strm.GetData()); + else + error.SetErrorStringWithFormat("not a pointer or reference type: (%s) %s", + GetTypeName().AsCString("<invalid type>"), + strm.GetData()); + return ValueObjectSP(); + } } -// This function checks the EvaluationPoint against the current process state. If the current -// state matches the evaluation point, or the evaluation point is already invalid, then we return -// false, meaning "no change". If the current state is different, we update our state, and return -// true meaning "yes, change". If we did see a change, we also set m_needs_update to true, so +ValueObjectSP ValueObject::AddressOf(Error &error) { + if (m_addr_of_valobj_sp) + return m_addr_of_valobj_sp; + + AddressType address_type = eAddressTypeInvalid; + const bool scalar_is_load_address = false; + addr_t addr = GetAddressOf(scalar_is_load_address, &address_type); + error.Clear(); + if (addr != LLDB_INVALID_ADDRESS && address_type != eAddressTypeHost) { + switch (address_type) { + case eAddressTypeInvalid: { + StreamString expr_path_strm; + GetExpressionPath(expr_path_strm, true); + error.SetErrorStringWithFormat("'%s' is not in memory", + expr_path_strm.GetData()); + } break; + + case eAddressTypeFile: + case eAddressTypeLoad: { + CompilerType compiler_type = GetCompilerType(); + if (compiler_type) { + std::string name(1, '&'); + name.append(m_name.AsCString("")); + ExecutionContext exe_ctx(GetExecutionContextRef()); + m_addr_of_valobj_sp = ValueObjectConstResult::Create( + exe_ctx.GetBestExecutionContextScope(), + compiler_type.GetPointerType(), ConstString(name.c_str()), addr, + eAddressTypeInvalid, m_data.GetAddressByteSize()); + } + } break; + default: + break; + } + } else { + StreamString expr_path_strm; + GetExpressionPath(expr_path_strm, true); + error.SetErrorStringWithFormat("'%s' doesn't have a valid address", + expr_path_strm.GetData()); + } + + return m_addr_of_valobj_sp; +} + +ValueObjectSP ValueObject::Cast(const CompilerType &compiler_type) { + return ValueObjectCast::Create(*this, GetName(), compiler_type); +} + +ValueObjectSP ValueObject::CastPointerType(const char *name, + CompilerType &compiler_type) { + ValueObjectSP valobj_sp; + AddressType address_type; + addr_t ptr_value = GetPointerValue(&address_type); + + if (ptr_value != LLDB_INVALID_ADDRESS) { + Address ptr_addr(ptr_value); + ExecutionContext exe_ctx(GetExecutionContextRef()); + valobj_sp = ValueObjectMemory::Create( + exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, compiler_type); + } + return valobj_sp; +} + +ValueObjectSP ValueObject::CastPointerType(const char *name, TypeSP &type_sp) { + ValueObjectSP valobj_sp; + AddressType address_type; + addr_t ptr_value = GetPointerValue(&address_type); + + if (ptr_value != LLDB_INVALID_ADDRESS) { + Address ptr_addr(ptr_value); + ExecutionContext exe_ctx(GetExecutionContextRef()); + valobj_sp = ValueObjectMemory::Create( + exe_ctx.GetBestExecutionContextScope(), name, ptr_addr, type_sp); + } + return valobj_sp; +} + +ValueObject::EvaluationPoint::EvaluationPoint() + : m_mod_id(), m_exe_ctx_ref(), m_needs_update(true) {} + +ValueObject::EvaluationPoint::EvaluationPoint(ExecutionContextScope *exe_scope, + bool use_selected) + : m_mod_id(), m_exe_ctx_ref(), m_needs_update(true) { + ExecutionContext exe_ctx(exe_scope); + TargetSP target_sp(exe_ctx.GetTargetSP()); + if (target_sp) { + m_exe_ctx_ref.SetTargetSP(target_sp); + ProcessSP process_sp(exe_ctx.GetProcessSP()); + if (!process_sp) + process_sp = target_sp->GetProcessSP(); + + if (process_sp) { + m_mod_id = process_sp->GetModID(); + m_exe_ctx_ref.SetProcessSP(process_sp); + + ThreadSP thread_sp(exe_ctx.GetThreadSP()); + + if (!thread_sp) { + if (use_selected) + thread_sp = process_sp->GetThreadList().GetSelectedThread(); + } + + if (thread_sp) { + m_exe_ctx_ref.SetThreadSP(thread_sp); + + StackFrameSP frame_sp(exe_ctx.GetFrameSP()); + if (!frame_sp) { + if (use_selected) + frame_sp = thread_sp->GetSelectedFrame(); + } + if (frame_sp) + m_exe_ctx_ref.SetFrameSP(frame_sp); + } + } + } +} + +ValueObject::EvaluationPoint::EvaluationPoint( + const ValueObject::EvaluationPoint &rhs) + : m_mod_id(), m_exe_ctx_ref(rhs.m_exe_ctx_ref), m_needs_update(true) {} + +ValueObject::EvaluationPoint::~EvaluationPoint() {} + +// This function checks the EvaluationPoint against the current process state. +// If the current +// state matches the evaluation point, or the evaluation point is already +// invalid, then we return +// false, meaning "no change". If the current state is different, we update our +// state, and return +// true meaning "yes, change". If we did see a change, we also set +// m_needs_update to true, so // future calls to NeedsUpdate will return true. // exe_scope will be set to the current execution context scope. -bool -ValueObject::EvaluationPoint::SyncWithProcessState(bool accept_invalid_exe_ctx) -{ - // Start with the target, if it is NULL, then we're obviously not going to get any further: - const bool thread_and_frame_only_if_stopped = true; - ExecutionContext exe_ctx(m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped)); - - if (exe_ctx.GetTargetPtr() == NULL) - return false; - - // If we don't have a process nothing can change. - Process *process = exe_ctx.GetProcessPtr(); - if (process == NULL) - return false; - - // If our stop id is the current stop ID, nothing has changed: - ProcessModID current_mod_id = process->GetModID(); - - // If the current stop id is 0, either we haven't run yet, or the process state has been cleared. - // In either case, we aren't going to be able to sync with the process state. - if (current_mod_id.GetStopID() == 0) - return false; - - bool changed = false; - const bool was_valid = m_mod_id.IsValid(); - if (was_valid) - { - if (m_mod_id == current_mod_id) - { - // Everything is already up to date in this object, no need to - // update the execution context scope. - changed = false; - } - else - { - m_mod_id = current_mod_id; - m_needs_update = true; - changed = true; - } - } - - // Now re-look up the thread and frame in case the underlying objects have gone away & been recreated. - // That way we'll be sure to return a valid exe_scope. - // If we used to have a thread or a frame but can't find it anymore, then mark ourselves as invalid. - - if (!accept_invalid_exe_ctx) - { - if (m_exe_ctx_ref.HasThreadRef()) - { - ThreadSP thread_sp (m_exe_ctx_ref.GetThreadSP()); - if (thread_sp) - { - if (m_exe_ctx_ref.HasFrameRef()) - { - StackFrameSP frame_sp (m_exe_ctx_ref.GetFrameSP()); - if (!frame_sp) - { - // We used to have a frame, but now it is gone - SetInvalid(); - changed = was_valid; - } - } - } - else - { - // We used to have a thread, but now it is gone - SetInvalid(); - changed = was_valid; - } - } - } +bool ValueObject::EvaluationPoint::SyncWithProcessState( + bool accept_invalid_exe_ctx) { + // Start with the target, if it is NULL, then we're obviously not going to get + // any further: + const bool thread_and_frame_only_if_stopped = true; + ExecutionContext exe_ctx( + m_exe_ctx_ref.Lock(thread_and_frame_only_if_stopped)); - return changed; -} + if (exe_ctx.GetTargetPtr() == NULL) + return false; -void -ValueObject::EvaluationPoint::SetUpdated () -{ - ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP()); - if (process_sp) - m_mod_id = process_sp->GetModID(); - m_needs_update = false; -} - - - -void -ValueObject::ClearUserVisibleData(uint32_t clear_mask) -{ - if ((clear_mask & eClearUserVisibleDataItemsValue) == eClearUserVisibleDataItemsValue) - m_value_str.clear(); - - if ((clear_mask & eClearUserVisibleDataItemsLocation) == eClearUserVisibleDataItemsLocation) - m_location_str.clear(); - - if ((clear_mask & eClearUserVisibleDataItemsSummary) == eClearUserVisibleDataItemsSummary) - m_summary_str.clear(); - - if ((clear_mask & eClearUserVisibleDataItemsDescription) == eClearUserVisibleDataItemsDescription) - m_object_desc_str.clear(); - - if ((clear_mask & eClearUserVisibleDataItemsSyntheticChildren) == eClearUserVisibleDataItemsSyntheticChildren) - { - if (m_synthetic_value) - m_synthetic_value = NULL; - } - - if ((clear_mask & eClearUserVisibleDataItemsValidator) == eClearUserVisibleDataItemsValidator) - m_validation_result.reset(); -} + // If we don't have a process nothing can change. + Process *process = exe_ctx.GetProcessPtr(); + if (process == NULL) + return false; -SymbolContextScope * -ValueObject::GetSymbolContextScope() -{ - if (m_parent) - { - if (!m_parent->IsPointerOrReferenceType()) - return m_parent->GetSymbolContextScope(); - } - return NULL; -} + // If our stop id is the current stop ID, nothing has changed: + ProcessModID current_mod_id = process->GetModID(); -lldb::ValueObjectSP -ValueObject::CreateValueObjectFromExpression (const char* name, - const char* expression, - const ExecutionContext& exe_ctx) -{ - return CreateValueObjectFromExpression(name, expression, exe_ctx, EvaluateExpressionOptions()); -} + // If the current stop id is 0, either we haven't run yet, or the process + // state has been cleared. + // In either case, we aren't going to be able to sync with the process state. + if (current_mod_id.GetStopID() == 0) + return false; + bool changed = false; + const bool was_valid = m_mod_id.IsValid(); + if (was_valid) { + if (m_mod_id == current_mod_id) { + // Everything is already up to date in this object, no need to + // update the execution context scope. + changed = false; + } else { + m_mod_id = current_mod_id; + m_needs_update = true; + changed = true; + } + } + + // Now re-look up the thread and frame in case the underlying objects have + // gone away & been recreated. + // That way we'll be sure to return a valid exe_scope. + // If we used to have a thread or a frame but can't find it anymore, then mark + // ourselves as invalid. + + if (!accept_invalid_exe_ctx) { + if (m_exe_ctx_ref.HasThreadRef()) { + ThreadSP thread_sp(m_exe_ctx_ref.GetThreadSP()); + if (thread_sp) { + if (m_exe_ctx_ref.HasFrameRef()) { + StackFrameSP frame_sp(m_exe_ctx_ref.GetFrameSP()); + if (!frame_sp) { + // We used to have a frame, but now it is gone + SetInvalid(); + changed = was_valid; + } + } + } else { + // We used to have a thread, but now it is gone + SetInvalid(); + changed = was_valid; + } + } + } + + return changed; +} + +void ValueObject::EvaluationPoint::SetUpdated() { + ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP()); + if (process_sp) + m_mod_id = process_sp->GetModID(); + m_needs_update = false; +} + +void ValueObject::ClearUserVisibleData(uint32_t clear_mask) { + if ((clear_mask & eClearUserVisibleDataItemsValue) == + eClearUserVisibleDataItemsValue) + m_value_str.clear(); + + if ((clear_mask & eClearUserVisibleDataItemsLocation) == + eClearUserVisibleDataItemsLocation) + m_location_str.clear(); + + if ((clear_mask & eClearUserVisibleDataItemsSummary) == + eClearUserVisibleDataItemsSummary) + m_summary_str.clear(); + + if ((clear_mask & eClearUserVisibleDataItemsDescription) == + eClearUserVisibleDataItemsDescription) + m_object_desc_str.clear(); + + if ((clear_mask & eClearUserVisibleDataItemsSyntheticChildren) == + eClearUserVisibleDataItemsSyntheticChildren) { + if (m_synthetic_value) + m_synthetic_value = NULL; + } -lldb::ValueObjectSP -ValueObject::CreateValueObjectFromExpression (const char* name, - const char* expression, - const ExecutionContext& exe_ctx, - const EvaluateExpressionOptions& options) -{ - lldb::ValueObjectSP retval_sp; - lldb::TargetSP target_sp(exe_ctx.GetTargetSP()); - if (!target_sp) - return retval_sp; - if (!expression || !*expression) - return retval_sp; - target_sp->EvaluateExpression (expression, - exe_ctx.GetFrameSP().get(), - retval_sp, - options); - if (retval_sp && name && *name) - retval_sp->SetName(ConstString(name)); - return retval_sp; + if ((clear_mask & eClearUserVisibleDataItemsValidator) == + eClearUserVisibleDataItemsValidator) + m_validation_result.reset(); } -lldb::ValueObjectSP -ValueObject::CreateValueObjectFromAddress (const char* name, - uint64_t address, - const ExecutionContext& exe_ctx, - CompilerType type) -{ - if (type) - { - CompilerType pointer_type(type.GetPointerType()); - if (pointer_type) - { - lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&address,sizeof(lldb::addr_t))); - lldb::ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), - pointer_type, - ConstString(name), - buffer, - exe_ctx.GetByteOrder(), - exe_ctx.GetAddressByteSize())); - if (ptr_result_valobj_sp) - { - ptr_result_valobj_sp->GetValue().SetValueType(Value::eValueTypeLoadAddress); - Error err; - ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(err); - if (ptr_result_valobj_sp && name && *name) - ptr_result_valobj_sp->SetName(ConstString(name)); - } - return ptr_result_valobj_sp; - } - } - return lldb::ValueObjectSP(); +SymbolContextScope *ValueObject::GetSymbolContextScope() { + if (m_parent) { + if (!m_parent->IsPointerOrReferenceType()) + return m_parent->GetSymbolContextScope(); + } + return NULL; } lldb::ValueObjectSP -ValueObject::CreateValueObjectFromData (const char* name, - const DataExtractor& data, - const ExecutionContext& exe_ctx, - CompilerType type) -{ - lldb::ValueObjectSP new_value_sp; - new_value_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), - type, - ConstString(name), - data, - LLDB_INVALID_ADDRESS); - new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad); - if (new_value_sp && name && *name) - new_value_sp->SetName(ConstString(name)); - return new_value_sp; +ValueObject::CreateValueObjectFromExpression(llvm::StringRef name, + llvm::StringRef expression, + const ExecutionContext &exe_ctx) { + return CreateValueObjectFromExpression(name, expression, exe_ctx, + EvaluateExpressionOptions()); +} + +lldb::ValueObjectSP ValueObject::CreateValueObjectFromExpression( + llvm::StringRef name, llvm::StringRef expression, + const ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options) { + lldb::ValueObjectSP retval_sp; + lldb::TargetSP target_sp(exe_ctx.GetTargetSP()); + if (!target_sp) + return retval_sp; + if (expression.empty()) + return retval_sp; + target_sp->EvaluateExpression(expression, exe_ctx.GetFrameSP().get(), + retval_sp, options); + if (retval_sp && !name.empty()) + retval_sp->SetName(ConstString(name)); + return retval_sp; +} + +lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress( + llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx, + CompilerType type) { + if (type) { + CompilerType pointer_type(type.GetPointerType()); + if (pointer_type) { + lldb::DataBufferSP buffer( + new lldb_private::DataBufferHeap(&address, sizeof(lldb::addr_t))); + lldb::ValueObjectSP ptr_result_valobj_sp(ValueObjectConstResult::Create( + exe_ctx.GetBestExecutionContextScope(), pointer_type, + ConstString(name), buffer, exe_ctx.GetByteOrder(), + exe_ctx.GetAddressByteSize())); + if (ptr_result_valobj_sp) { + ptr_result_valobj_sp->GetValue().SetValueType( + Value::eValueTypeLoadAddress); + Error err; + ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(err); + if (ptr_result_valobj_sp && !name.empty()) + ptr_result_valobj_sp->SetName(ConstString(name)); + } + return ptr_result_valobj_sp; + } + } + return lldb::ValueObjectSP(); +} + +lldb::ValueObjectSP ValueObject::CreateValueObjectFromData( + llvm::StringRef name, const DataExtractor &data, + const ExecutionContext &exe_ctx, CompilerType type) { + lldb::ValueObjectSP new_value_sp; + new_value_sp = ValueObjectConstResult::Create( + exe_ctx.GetBestExecutionContextScope(), type, ConstString(name), data, + LLDB_INVALID_ADDRESS); + new_value_sp->SetAddressTypeOfChildren(eAddressTypeLoad); + if (new_value_sp && !name.empty()) + new_value_sp->SetName(ConstString(name)); + return new_value_sp; +} + +ModuleSP ValueObject::GetModule() { + ValueObject *root(GetRoot()); + if (root != this) + return root->GetModule(); + return lldb::ModuleSP(); +} + +ValueObject *ValueObject::GetRoot() { + if (m_root) + return m_root; + return (m_root = FollowParentChain([](ValueObject *vo) -> bool { + return (vo->m_parent != nullptr); + })); } -ModuleSP -ValueObject::GetModule () -{ - ValueObject* root(GetRoot()); +ValueObject * +ValueObject::FollowParentChain(std::function<bool(ValueObject *)> f) { + ValueObject *vo = this; + while (vo) { + if (f(vo) == false) + break; + vo = vo->m_parent; + } + return vo; +} + +AddressType ValueObject::GetAddressTypeOfChildren() { + if (m_address_type_of_ptr_or_ref_children == eAddressTypeInvalid) { + ValueObject *root(GetRoot()); if (root != this) - return root->GetModule(); - return lldb::ModuleSP(); + return root->GetAddressTypeOfChildren(); + } + return m_address_type_of_ptr_or_ref_children; } -ValueObject* -ValueObject::GetRoot () -{ - if (m_root) - return m_root; - return (m_root = FollowParentChain( [] (ValueObject* vo) -> bool { - return (vo->m_parent != nullptr); - })); +lldb::DynamicValueType ValueObject::GetDynamicValueType() { + ValueObject *with_dv_info = this; + while (with_dv_info) { + if (with_dv_info->HasDynamicValueTypeInfo()) + return with_dv_info->GetDynamicValueTypeImpl(); + with_dv_info = with_dv_info->m_parent; + } + return lldb::eNoDynamicValues; } -ValueObject* -ValueObject::FollowParentChain (std::function<bool(ValueObject*)> f) -{ - ValueObject* vo = this; - while (vo) - { - if (f(vo) == false) - break; - vo = vo->m_parent; - } - return vo; +lldb::Format ValueObject::GetFormat() const { + const ValueObject *with_fmt_info = this; + while (with_fmt_info) { + if (with_fmt_info->m_format != lldb::eFormatDefault) + return with_fmt_info->m_format; + with_fmt_info = with_fmt_info->m_parent; + } + return m_format; } -AddressType -ValueObject::GetAddressTypeOfChildren() -{ - if (m_address_type_of_ptr_or_ref_children == eAddressTypeInvalid) - { - ValueObject* root(GetRoot()); - if (root != this) - return root->GetAddressTypeOfChildren(); +lldb::LanguageType ValueObject::GetPreferredDisplayLanguage() { + lldb::LanguageType type = m_preferred_display_language; + if (m_preferred_display_language == lldb::eLanguageTypeUnknown) { + if (GetRoot()) { + if (GetRoot() == this) { + if (StackFrameSP frame_sp = GetFrameSP()) { + const SymbolContext &sc( + frame_sp->GetSymbolContext(eSymbolContextCompUnit)); + if (CompileUnit *cu = sc.comp_unit) + type = cu->GetLanguage(); + } + } else { + type = GetRoot()->GetPreferredDisplayLanguage(); + } } - return m_address_type_of_ptr_or_ref_children; + } + return (m_preferred_display_language = type); // only compute it once } -lldb::DynamicValueType -ValueObject::GetDynamicValueType () -{ - ValueObject* with_dv_info = this; - while (with_dv_info) - { - if (with_dv_info->HasDynamicValueTypeInfo()) - return with_dv_info->GetDynamicValueTypeImpl(); - with_dv_info = with_dv_info->m_parent; - } - return lldb::eNoDynamicValues; +void ValueObject::SetPreferredDisplayLanguage(lldb::LanguageType lt) { + m_preferred_display_language = lt; } -lldb::Format -ValueObject::GetFormat () const -{ - const ValueObject* with_fmt_info = this; - while (with_fmt_info) - { - if (with_fmt_info->m_format != lldb::eFormatDefault) - return with_fmt_info->m_format; - with_fmt_info = with_fmt_info->m_parent; - } - return m_format; +void ValueObject::SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType lt) { + if (m_preferred_display_language == lldb::eLanguageTypeUnknown) + SetPreferredDisplayLanguage(lt); } -lldb::LanguageType -ValueObject::GetPreferredDisplayLanguage () -{ - lldb::LanguageType type = m_preferred_display_language; - if (m_preferred_display_language == lldb::eLanguageTypeUnknown) - { - if (GetRoot()) - { - if (GetRoot() == this) - { - if (StackFrameSP frame_sp = GetFrameSP()) - { - const SymbolContext& sc(frame_sp->GetSymbolContext(eSymbolContextCompUnit)); - if (CompileUnit* cu = sc.comp_unit) - type = cu->GetLanguage(); - } - } - else - { - type = GetRoot()->GetPreferredDisplayLanguage(); - } - } - } - return (m_preferred_display_language = type); // only compute it once +bool ValueObject::CanProvideValue() { + // we need to support invalid types as providers of values because some + // bare-board + // debugging scenarios have no notion of types, but still manage to have raw + // numeric + // values for things like registers. sigh. + const CompilerType &type(GetCompilerType()); + return (false == type.IsValid()) || + (0 != (type.GetTypeInfo() & eTypeHasValue)); } -void -ValueObject::SetPreferredDisplayLanguage (lldb::LanguageType lt) -{ - m_preferred_display_language = lt; -} +bool ValueObject::IsChecksumEmpty() { return m_value_checksum.empty(); } -void -ValueObject::SetPreferredDisplayLanguageIfNeeded (lldb::LanguageType lt) -{ - if (m_preferred_display_language == lldb::eLanguageTypeUnknown) - SetPreferredDisplayLanguage(lt); -} +ValueObjectSP ValueObject::Persist() { + if (!UpdateValueIfNeeded()) + return nullptr; -bool -ValueObject::CanProvideValue () -{ - // we need to support invalid types as providers of values because some bare-board - // debugging scenarios have no notion of types, but still manage to have raw numeric - // values for things like registers. sigh. - const CompilerType &type(GetCompilerType()); - return (false == type.IsValid()) || (0 != (type.GetTypeInfo() & eTypeHasValue)); -} + TargetSP target_sp(GetTargetSP()); + if (!target_sp) + return nullptr; + + PersistentExpressionState *persistent_state = + target_sp->GetPersistentExpressionStateForLanguage( + GetPreferredDisplayLanguage()); + + if (!persistent_state) + return nullptr; -bool -ValueObject::IsChecksumEmpty () -{ - return m_value_checksum.empty(); + ConstString name(persistent_state->GetNextPersistentVariableName()); + + ValueObjectSP const_result_sp = + ValueObjectConstResult::Create(target_sp.get(), GetValue(), name); + + ExpressionVariableSP clang_var_sp = + persistent_state->CreatePersistentVariable(const_result_sp); + clang_var_sp->m_live_sp = clang_var_sp->m_frozen_sp; + clang_var_sp->m_flags |= ExpressionVariable::EVIsProgramReference; + + return clang_var_sp->GetValueObject(); } -ValueObjectSP -ValueObject::Persist () -{ - if (!UpdateValueIfNeeded()) - return nullptr; - - TargetSP target_sp(GetTargetSP()); - if (!target_sp) - return nullptr; - - PersistentExpressionState *persistent_state = target_sp->GetPersistentExpressionStateForLanguage(GetPreferredDisplayLanguage()); - - if (!persistent_state) - return nullptr; - - ConstString name(persistent_state->GetNextPersistentVariableName()); - - ValueObjectSP const_result_sp = ValueObjectConstResult::Create (target_sp.get(), GetValue(), name); - - ExpressionVariableSP clang_var_sp = persistent_state->CreatePersistentVariable(const_result_sp); - clang_var_sp->m_live_sp = clang_var_sp->m_frozen_sp; - clang_var_sp->m_flags |= ExpressionVariable::EVIsProgramReference; - - return clang_var_sp->GetValueObject(); +bool ValueObject::IsSyntheticChildrenGenerated() { + return m_is_synthetic_children_generated; } -bool -ValueObject::IsSyntheticChildrenGenerated () -{ - return m_is_synthetic_children_generated; +void ValueObject::SetSyntheticChildrenGenerated(bool b) { + m_is_synthetic_children_generated = b; } -void -ValueObject::SetSyntheticChildrenGenerated (bool b) -{ - m_is_synthetic_children_generated = b; +uint64_t ValueObject::GetLanguageFlags() { return m_language_flags; } + +void ValueObject::SetLanguageFlags(uint64_t flags) { m_language_flags = flags; } + +ValueObjectManager::ValueObjectManager(lldb::ValueObjectSP in_valobj_sp, + lldb::DynamicValueType use_dynamic, + bool use_synthetic) : m_root_valobj_sp(), + m_user_valobj_sp(), m_use_dynamic(use_dynamic), m_stop_id(UINT32_MAX), + m_use_synthetic(use_synthetic) { + if (!in_valobj_sp) + return; + // If the user passes in a value object that is dynamic or synthetic, then + // water it down to the static type. + m_root_valobj_sp = in_valobj_sp->GetQualifiedRepresentationIfAvailable(lldb::eNoDynamicValues, false); } -uint64_t -ValueObject::GetLanguageFlags () -{ - return m_language_flags; +bool ValueObjectManager::IsValid() const { + if (!m_root_valobj_sp) + return false; + lldb::TargetSP target_sp = GetTargetSP(); + if (target_sp) + return target_sp->IsValid(); + return false; } -void -ValueObject::SetLanguageFlags (uint64_t flags) -{ - m_language_flags = flags; +lldb::ValueObjectSP ValueObjectManager::GetSP() { + lldb::ProcessSP process_sp = GetProcessSP(); + if (!process_sp) + return lldb::ValueObjectSP(); + + const uint32_t current_stop_id = process_sp->GetLastNaturalStopID(); + if (current_stop_id == m_stop_id) + return m_user_valobj_sp; + + m_stop_id = current_stop_id; + + if (!m_root_valobj_sp) { + m_user_valobj_sp.reset(); + return m_root_valobj_sp; + } + + m_user_valobj_sp = m_root_valobj_sp; + + if (m_use_dynamic != lldb::eNoDynamicValues) { + lldb::ValueObjectSP dynamic_sp = m_user_valobj_sp->GetDynamicValue(m_use_dynamic); + if (dynamic_sp) + m_user_valobj_sp = dynamic_sp; + } + + if (m_use_synthetic) { + lldb::ValueObjectSP synthetic_sp = m_user_valobj_sp->GetSyntheticValue(m_use_synthetic); + if (synthetic_sp) + m_user_valobj_sp = synthetic_sp; + } + + return m_user_valobj_sp; +} + +void ValueObjectManager::SetUseDynamic(lldb::DynamicValueType use_dynamic) { + if (use_dynamic != m_use_dynamic) { + m_use_dynamic = use_dynamic; + m_user_valobj_sp.reset(); + m_stop_id = UINT32_MAX; + } +} + +void ValueObjectManager::SetUseSynthetic(bool use_synthetic) { + if (m_use_synthetic != use_synthetic) { + m_use_synthetic = use_synthetic; + m_user_valobj_sp.reset(); + m_stop_id = UINT32_MAX; + } +} + +lldb::TargetSP ValueObjectManager::GetTargetSP() const { + if (!m_root_valobj_sp) + return m_root_valobj_sp->GetTargetSP(); + return lldb::TargetSP(); +} + +lldb::ProcessSP ValueObjectManager::GetProcessSP() const { + if (m_root_valobj_sp) + return m_root_valobj_sp->GetProcessSP(); + return lldb::ProcessSP(); +} + +lldb::ThreadSP ValueObjectManager::GetThreadSP() const { + if (m_root_valobj_sp) + return m_root_valobj_sp->GetThreadSP(); + return lldb::ThreadSP(); +} + +lldb::StackFrameSP ValueObjectManager::GetFrameSP() const { + if (m_root_valobj_sp) + return m_root_valobj_sp->GetFrameSP(); + return lldb::StackFrameSP(); } + diff --git a/source/Core/ValueObjectCast.cpp b/source/Core/ValueObjectCast.cpp index 1c5838b820e1..300aeae3b33a 100644 --- a/source/Core/ValueObjectCast.cpp +++ b/source/Core/ValueObjectCast.cpp @@ -1,4 +1,4 @@ -//===-- ValueObjectDynamicValue.cpp ---------------------------------*- C++ -*-===// +//===-- ValueObjectCast.cpp -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - #include "lldb/Core/ValueObjectCast.h" // C Includes @@ -16,9 +15,9 @@ // Project includes #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" -#include "lldb/Core/ValueObjectList.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectList.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ObjectFile.h" @@ -34,97 +33,72 @@ using namespace lldb_private; -lldb::ValueObjectSP -ValueObjectCast::Create (ValueObject &parent, - const ConstString &name, - const CompilerType &cast_type) -{ - ValueObjectCast *cast_valobj_ptr = new ValueObjectCast (parent, name, cast_type); - return cast_valobj_ptr->GetSP(); +lldb::ValueObjectSP ValueObjectCast::Create(ValueObject &parent, + const ConstString &name, + const CompilerType &cast_type) { + ValueObjectCast *cast_valobj_ptr = + new ValueObjectCast(parent, name, cast_type); + return cast_valobj_ptr->GetSP(); } -ValueObjectCast::ValueObjectCast -( - ValueObject &parent, - const ConstString &name, - const CompilerType &cast_type -) : - ValueObject(parent), - m_cast_type (cast_type) -{ - SetName (name); - //m_value.SetContext (Value::eContextTypeClangType, cast_type.GetOpaqueQualType()); - m_value.SetCompilerType (cast_type); +ValueObjectCast::ValueObjectCast(ValueObject &parent, const ConstString &name, + const CompilerType &cast_type) + : ValueObject(parent), m_cast_type(cast_type) { + SetName(name); + // m_value.SetContext (Value::eContextTypeClangType, + // cast_type.GetOpaqueQualType()); + m_value.SetCompilerType(cast_type); } -ValueObjectCast::~ValueObjectCast() -{ -} +ValueObjectCast::~ValueObjectCast() {} -CompilerType -ValueObjectCast::GetCompilerTypeImpl () -{ - return m_cast_type; -} +CompilerType ValueObjectCast::GetCompilerTypeImpl() { return m_cast_type; } -size_t -ValueObjectCast::CalculateNumChildren(uint32_t max) -{ - auto children_count = GetCompilerType().GetNumChildren (true); - return children_count <= max ? children_count : max; +size_t ValueObjectCast::CalculateNumChildren(uint32_t max) { + auto children_count = GetCompilerType().GetNumChildren(true); + return children_count <= max ? children_count : max; } -uint64_t -ValueObjectCast::GetByteSize() -{ - ExecutionContext exe_ctx (GetExecutionContextRef()); - return m_value.GetValueByteSize(nullptr, &exe_ctx); +uint64_t ValueObjectCast::GetByteSize() { + ExecutionContext exe_ctx(GetExecutionContextRef()); + return m_value.GetValueByteSize(nullptr, &exe_ctx); } -lldb::ValueType -ValueObjectCast::GetValueType() const -{ - // Let our parent answer global, local, argument, etc... - return m_parent->GetValueType(); +lldb::ValueType ValueObjectCast::GetValueType() const { + // Let our parent answer global, local, argument, etc... + return m_parent->GetValueType(); } -bool -ValueObjectCast::UpdateValue () -{ - SetValueIsValid (false); - m_error.Clear(); - - if (m_parent->UpdateValueIfNeeded(false)) - { - Value old_value(m_value); - m_update_point.SetUpdated(); - m_value = m_parent->GetValue(); - CompilerType compiler_type (GetCompilerType()); - //m_value.SetContext (Value::eContextTypeClangType, compiler_type); - m_value.SetCompilerType (compiler_type); - SetAddressTypeOfChildren(m_parent->GetAddressTypeOfChildren()); - if (!CanProvideValue()) - { - // this value object represents an aggregate type whose - // children have values, but this object does not. So we - // say we are changed if our location has changed. - SetValueDidChange (m_value.GetValueType() != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar()); - } - ExecutionContext exe_ctx (GetExecutionContextRef()); - m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); - SetValueDidChange (m_parent->GetValueDidChange()); - return true; +bool ValueObjectCast::UpdateValue() { + SetValueIsValid(false); + m_error.Clear(); + + if (m_parent->UpdateValueIfNeeded(false)) { + Value old_value(m_value); + m_update_point.SetUpdated(); + m_value = m_parent->GetValue(); + CompilerType compiler_type(GetCompilerType()); + // m_value.SetContext (Value::eContextTypeClangType, compiler_type); + m_value.SetCompilerType(compiler_type); + SetAddressTypeOfChildren(m_parent->GetAddressTypeOfChildren()); + if (!CanProvideValue()) { + // this value object represents an aggregate type whose + // children have values, but this object does not. So we + // say we are changed if our location has changed. + SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() || + m_value.GetScalar() != old_value.GetScalar()); } - - // The dynamic value failed to get an error, pass the error along - if (m_error.Success() && m_parent->GetError().Fail()) - m_error = m_parent->GetError(); - SetValueIsValid (false); - return false; -} + ExecutionContext exe_ctx(GetExecutionContextRef()); + m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + SetValueDidChange(m_parent->GetValueDidChange()); + return true; + } -bool -ValueObjectCast::IsInScope () -{ - return m_parent->IsInScope(); + // The dynamic value failed to get an error, pass the error along + if (m_error.Success() && m_parent->GetError().Fail()) + m_error = m_parent->GetError(); + SetValueIsValid(false); + return false; } + +bool ValueObjectCast::IsInScope() { return m_parent->IsInScope(); } diff --git a/source/Core/ValueObjectChild.cpp b/source/Core/ValueObjectChild.cpp index 6ecc749b8953..9b2bdd1e468c 100644 --- a/source/Core/ValueObjectChild.cpp +++ b/source/Core/ValueObjectChild.cpp @@ -24,254 +24,205 @@ using namespace lldb_private; -ValueObjectChild::ValueObjectChild -( - ValueObject &parent, - const CompilerType &compiler_type, - const ConstString &name, - uint64_t byte_size, - int32_t byte_offset, - uint32_t bitfield_bit_size, - uint32_t bitfield_bit_offset, - bool is_base_class, - bool is_deref_of_parent, - AddressType child_ptr_or_ref_addr_type, - uint64_t language_flags -) : - ValueObject (parent), - m_compiler_type (compiler_type), - m_byte_size (byte_size), - m_byte_offset (byte_offset), - m_bitfield_bit_size (bitfield_bit_size), - m_bitfield_bit_offset (bitfield_bit_offset), - m_is_base_class (is_base_class), - m_is_deref_of_parent (is_deref_of_parent), - m_can_update_with_invalid_exe_ctx() -{ - m_name = name; - SetAddressTypeOfChildren(child_ptr_or_ref_addr_type); - SetLanguageFlags(language_flags); +ValueObjectChild::ValueObjectChild( + ValueObject &parent, const CompilerType &compiler_type, + const ConstString &name, uint64_t byte_size, int32_t byte_offset, + uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, + bool is_base_class, bool is_deref_of_parent, + AddressType child_ptr_or_ref_addr_type, uint64_t language_flags) + : ValueObject(parent), m_compiler_type(compiler_type), + m_byte_size(byte_size), m_byte_offset(byte_offset), + m_bitfield_bit_size(bitfield_bit_size), + m_bitfield_bit_offset(bitfield_bit_offset), + m_is_base_class(is_base_class), m_is_deref_of_parent(is_deref_of_parent), + m_can_update_with_invalid_exe_ctx() { + m_name = name; + SetAddressTypeOfChildren(child_ptr_or_ref_addr_type); + SetLanguageFlags(language_flags); } -ValueObjectChild::~ValueObjectChild() -{ -} +ValueObjectChild::~ValueObjectChild() {} -lldb::ValueType -ValueObjectChild::GetValueType() const -{ - return m_parent->GetValueType(); +lldb::ValueType ValueObjectChild::GetValueType() const { + return m_parent->GetValueType(); } -size_t -ValueObjectChild::CalculateNumChildren(uint32_t max) -{ - auto children_count = GetCompilerType().GetNumChildren (true); - return children_count <= max ? children_count : max; +size_t ValueObjectChild::CalculateNumChildren(uint32_t max) { + auto children_count = GetCompilerType().GetNumChildren(true); + return children_count <= max ? children_count : max; } -static void -AdjustForBitfieldness(ConstString& name, - uint8_t bitfield_bit_size) -{ - if (name && bitfield_bit_size) - { - const char *compiler_type_name = name.AsCString(); - if (compiler_type_name) - { - std::vector<char> bitfield_type_name (strlen(compiler_type_name) + 32, 0); - ::snprintf (&bitfield_type_name.front(), bitfield_type_name.size(), "%s:%u", compiler_type_name, bitfield_bit_size); - name.SetCString(&bitfield_type_name.front()); - } +static void AdjustForBitfieldness(ConstString &name, + uint8_t bitfield_bit_size) { + if (name && bitfield_bit_size) { + const char *compiler_type_name = name.AsCString(); + if (compiler_type_name) { + std::vector<char> bitfield_type_name(strlen(compiler_type_name) + 32, 0); + ::snprintf(&bitfield_type_name.front(), bitfield_type_name.size(), + "%s:%u", compiler_type_name, bitfield_bit_size); + name.SetCString(&bitfield_type_name.front()); } + } } -ConstString -ValueObjectChild::GetTypeName() -{ - if (m_type_name.IsEmpty()) - { - m_type_name = GetCompilerType().GetConstTypeName (); - AdjustForBitfieldness(m_type_name, m_bitfield_bit_size); - } - return m_type_name; +ConstString ValueObjectChild::GetTypeName() { + if (m_type_name.IsEmpty()) { + m_type_name = GetCompilerType().GetConstTypeName(); + AdjustForBitfieldness(m_type_name, m_bitfield_bit_size); + } + return m_type_name; } -ConstString -ValueObjectChild::GetQualifiedTypeName() -{ - ConstString qualified_name = GetCompilerType().GetConstTypeName(); - AdjustForBitfieldness(qualified_name, m_bitfield_bit_size); - return qualified_name; +ConstString ValueObjectChild::GetQualifiedTypeName() { + ConstString qualified_name = GetCompilerType().GetConstTypeName(); + AdjustForBitfieldness(qualified_name, m_bitfield_bit_size); + return qualified_name; } -ConstString -ValueObjectChild::GetDisplayTypeName() -{ - ConstString display_name = GetCompilerType().GetDisplayTypeName(); - AdjustForBitfieldness(display_name, m_bitfield_bit_size); - return display_name; +ConstString ValueObjectChild::GetDisplayTypeName() { + ConstString display_name = GetCompilerType().GetDisplayTypeName(); + AdjustForBitfieldness(display_name, m_bitfield_bit_size); + return display_name; } -LazyBool -ValueObjectChild::CanUpdateWithInvalidExecutionContext () -{ - if (m_can_update_with_invalid_exe_ctx.hasValue()) - return m_can_update_with_invalid_exe_ctx.getValue(); - if (m_parent) - { - ValueObject *opinionated_parent = m_parent->FollowParentChain([] (ValueObject* valobj) -> bool { - return (valobj->CanUpdateWithInvalidExecutionContext() == eLazyBoolCalculate); +LazyBool ValueObjectChild::CanUpdateWithInvalidExecutionContext() { + if (m_can_update_with_invalid_exe_ctx.hasValue()) + return m_can_update_with_invalid_exe_ctx.getValue(); + if (m_parent) { + ValueObject *opinionated_parent = + m_parent->FollowParentChain([](ValueObject *valobj) -> bool { + return (valobj->CanUpdateWithInvalidExecutionContext() == + eLazyBoolCalculate); }); - if (opinionated_parent) - return (m_can_update_with_invalid_exe_ctx = opinionated_parent->CanUpdateWithInvalidExecutionContext()).getValue(); - } - return (m_can_update_with_invalid_exe_ctx = this->ValueObject::CanUpdateWithInvalidExecutionContext()).getValue(); + if (opinionated_parent) + return (m_can_update_with_invalid_exe_ctx = + opinionated_parent->CanUpdateWithInvalidExecutionContext()) + .getValue(); + } + return (m_can_update_with_invalid_exe_ctx = + this->ValueObject::CanUpdateWithInvalidExecutionContext()) + .getValue(); } -bool -ValueObjectChild::UpdateValue () -{ - m_error.Clear(); - SetValueIsValid (false); - ValueObject* parent = m_parent; - if (parent) - { - if (parent->UpdateValueIfNeeded(false)) - { - m_value.SetCompilerType(GetCompilerType()); - - CompilerType parent_type(parent->GetCompilerType()); - // Copy the parent scalar value and the scalar value type - m_value.GetScalar() = parent->GetValue().GetScalar(); - Value::ValueType value_type = parent->GetValue().GetValueType(); - m_value.SetValueType (value_type); - - Flags parent_type_flags(parent_type.GetTypeInfo()); - const bool is_instance_ptr_base = ((m_is_base_class == true) && (parent_type_flags.AnySet(lldb::eTypeInstanceIsPointer))); - - if (parent->GetCompilerType().ShouldTreatScalarValueAsAddress()) - { - lldb::addr_t addr = parent->GetPointerValue (); - m_value.GetScalar() = addr; - - if (addr == LLDB_INVALID_ADDRESS) - { - m_error.SetErrorString ("parent address is invalid."); - } - else if (addr == 0) - { - m_error.SetErrorString ("parent is NULL"); - } - else - { - m_value.GetScalar() += m_byte_offset; - AddressType addr_type = parent->GetAddressTypeOfChildren(); - - switch (addr_type) - { - case eAddressTypeFile: - { - lldb::ProcessSP process_sp (GetProcessSP()); - if (process_sp && process_sp->IsAlive() == true) - m_value.SetValueType (Value::eValueTypeLoadAddress); - else - m_value.SetValueType(Value::eValueTypeFileAddress); - } - break; - case eAddressTypeLoad: - m_value.SetValueType (is_instance_ptr_base ? Value::eValueTypeScalar: Value::eValueTypeLoadAddress); - break; - case eAddressTypeHost: - m_value.SetValueType(Value::eValueTypeHostAddress); - break; - case eAddressTypeInvalid: - // TODO: does this make sense? - m_value.SetValueType(Value::eValueTypeScalar); - break; - } - } - } +bool ValueObjectChild::UpdateValue() { + m_error.Clear(); + SetValueIsValid(false); + ValueObject *parent = m_parent; + if (parent) { + if (parent->UpdateValueIfNeeded(false)) { + m_value.SetCompilerType(GetCompilerType()); + + CompilerType parent_type(parent->GetCompilerType()); + // Copy the parent scalar value and the scalar value type + m_value.GetScalar() = parent->GetValue().GetScalar(); + Value::ValueType value_type = parent->GetValue().GetValueType(); + m_value.SetValueType(value_type); + + Flags parent_type_flags(parent_type.GetTypeInfo()); + const bool is_instance_ptr_base = + ((m_is_base_class == true) && + (parent_type_flags.AnySet(lldb::eTypeInstanceIsPointer))); + + if (parent->GetCompilerType().ShouldTreatScalarValueAsAddress()) { + lldb::addr_t addr = parent->GetPointerValue(); + m_value.GetScalar() = addr; + + if (addr == LLDB_INVALID_ADDRESS) { + m_error.SetErrorString("parent address is invalid."); + } else if (addr == 0) { + m_error.SetErrorString("parent is NULL"); + } else { + m_value.GetScalar() += m_byte_offset; + AddressType addr_type = parent->GetAddressTypeOfChildren(); + + switch (addr_type) { + case eAddressTypeFile: { + lldb::ProcessSP process_sp(GetProcessSP()); + if (process_sp && process_sp->IsAlive() == true) + m_value.SetValueType(Value::eValueTypeLoadAddress); else - { - switch (value_type) - { - case Value::eValueTypeLoadAddress: - case Value::eValueTypeFileAddress: - case Value::eValueTypeHostAddress: - { - lldb::addr_t addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - if (addr == LLDB_INVALID_ADDRESS) - { - m_error.SetErrorString ("parent address is invalid."); - } - else if (addr == 0) - { - m_error.SetErrorString ("parent is NULL"); - } - else - { - // Set this object's scalar value to the address of its - // value by adding its byte offset to the parent address - m_value.GetScalar() += GetByteOffset(); - } - } - break; - - case Value::eValueTypeScalar: - // try to extract the child value from the parent's scalar value - { - Scalar scalar(m_value.GetScalar()); - if (m_bitfield_bit_size) - scalar.ExtractBitfield(m_bitfield_bit_size, m_bitfield_bit_offset); - else - scalar.ExtractBitfield(8*m_byte_size, 8*m_byte_offset); - m_value.GetScalar() = scalar; - } - break; - default: - m_error.SetErrorString ("parent has invalid value."); - break; - } - } - - if (m_error.Success()) - { - const bool thread_and_frame_only_if_stopped = true; - ExecutionContext exe_ctx (GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped)); - if (GetCompilerType().GetTypeInfo() & lldb::eTypeHasValue) - { - if (!is_instance_ptr_base) - m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); - else - m_error = m_parent->GetValue().GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); - } - else - { - m_error.Clear(); // No value so nothing to read... - } - } - + m_value.SetValueType(Value::eValueTypeFileAddress); + } break; + case eAddressTypeLoad: + m_value.SetValueType(is_instance_ptr_base + ? Value::eValueTypeScalar + : Value::eValueTypeLoadAddress); + break; + case eAddressTypeHost: + m_value.SetValueType(Value::eValueTypeHostAddress); + break; + case eAddressTypeInvalid: + // TODO: does this make sense? + m_value.SetValueType(Value::eValueTypeScalar); + break; + } } - else - { - m_error.SetErrorStringWithFormat("parent failed to evaluate: %s", parent->GetError().AsCString()); + } else { + switch (value_type) { + case Value::eValueTypeLoadAddress: + case Value::eValueTypeFileAddress: + case Value::eValueTypeHostAddress: { + lldb::addr_t addr = + m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + if (addr == LLDB_INVALID_ADDRESS) { + m_error.SetErrorString("parent address is invalid."); + } else if (addr == 0) { + m_error.SetErrorString("parent is NULL"); + } else { + // Set this object's scalar value to the address of its + // value by adding its byte offset to the parent address + m_value.GetScalar() += GetByteOffset(); + } + } break; + + case Value::eValueTypeScalar: + // try to extract the child value from the parent's scalar value + { + Scalar scalar(m_value.GetScalar()); + if (m_bitfield_bit_size) + scalar.ExtractBitfield(m_bitfield_bit_size, + m_bitfield_bit_offset); + else + scalar.ExtractBitfield(8 * m_byte_size, 8 * m_byte_offset); + m_value.GetScalar() = scalar; + } + break; + default: + m_error.SetErrorString("parent has invalid value."); + break; } + } + + if (m_error.Success()) { + const bool thread_and_frame_only_if_stopped = true; + ExecutionContext exe_ctx( + GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped)); + if (GetCompilerType().GetTypeInfo() & lldb::eTypeHasValue) { + if (!is_instance_ptr_base) + m_error = + m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + else + m_error = m_parent->GetValue().GetValueAsData(&exe_ctx, m_data, 0, + GetModule().get()); + } else { + m_error.Clear(); // No value so nothing to read... + } + } + + } else { + m_error.SetErrorStringWithFormat("parent failed to evaluate: %s", + parent->GetError().AsCString()); } - else - { - m_error.SetErrorString("ValueObjectChild has a NULL parent ValueObject."); - } - - return m_error.Success(); -} + } else { + m_error.SetErrorString("ValueObjectChild has a NULL parent ValueObject."); + } + return m_error.Success(); +} -bool -ValueObjectChild::IsInScope () -{ - ValueObject* root(GetRoot()); - if (root) - return root->IsInScope (); - return false; +bool ValueObjectChild::IsInScope() { + ValueObject *root(GetRoot()); + if (root) + return root->IsInScope(); + return false; } diff --git a/source/Core/ValueObjectConstResult.cpp b/source/Core/ValueObjectConstResult.cpp index 441cee540f7c..f78574ef7ee3 100644 --- a/source/Core/ValueObjectConstResult.cpp +++ b/source/Core/ValueObjectConstResult.cpp @@ -9,10 +9,10 @@ #include "lldb/Core/ValueObjectConstResult.h" -#include "lldb/Core/ValueObjectChild.h" -#include "lldb/Core/ValueObjectConstResultChild.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Module.h" +#include "lldb/Core/ValueObjectChild.h" +#include "lldb/Core/ValueObjectConstResultChild.h" #include "lldb/Core/ValueObjectDynamicValue.h" #include "lldb/Core/ValueObjectList.h" @@ -29,356 +29,270 @@ using namespace lldb; using namespace lldb_private; -ValueObjectSP -ValueObjectConstResult::Create (ExecutionContextScope *exe_scope, - ByteOrder byte_order, - uint32_t addr_byte_size, - lldb::addr_t address) -{ - return (new ValueObjectConstResult (exe_scope, - byte_order, - addr_byte_size, - address))->GetSP(); +ValueObjectSP ValueObjectConstResult::Create(ExecutionContextScope *exe_scope, + ByteOrder byte_order, + uint32_t addr_byte_size, + lldb::addr_t address) { + return (new ValueObjectConstResult(exe_scope, byte_order, addr_byte_size, + address)) + ->GetSP(); } -ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope, - ByteOrder byte_order, - uint32_t addr_byte_size, - lldb::addr_t address) : - ValueObject (exe_scope), - m_type_name (), - m_byte_size (0), - m_impl(this, address) -{ - SetIsConstant (); - SetValueIsValid(true); - m_data.SetByteOrder(byte_order); - m_data.SetAddressByteSize(addr_byte_size); - SetAddressTypeOfChildren(eAddressTypeLoad); +ValueObjectConstResult::ValueObjectConstResult(ExecutionContextScope *exe_scope, + ByteOrder byte_order, + uint32_t addr_byte_size, + lldb::addr_t address) + : ValueObject(exe_scope), m_type_name(), m_byte_size(0), + m_impl(this, address) { + SetIsConstant(); + SetValueIsValid(true); + m_data.SetByteOrder(byte_order); + m_data.SetAddressByteSize(addr_byte_size); + SetAddressTypeOfChildren(eAddressTypeLoad); } -ValueObjectSP -ValueObjectConstResult::Create -( - ExecutionContextScope *exe_scope, - const CompilerType &compiler_type, - const ConstString &name, - const DataExtractor &data, - lldb::addr_t address -) -{ - return (new ValueObjectConstResult (exe_scope, - compiler_type, - name, - data, - address))->GetSP(); +ValueObjectSP ValueObjectConstResult::Create(ExecutionContextScope *exe_scope, + const CompilerType &compiler_type, + const ConstString &name, + const DataExtractor &data, + lldb::addr_t address) { + return (new ValueObjectConstResult(exe_scope, compiler_type, name, data, + address)) + ->GetSP(); } -ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope, - const CompilerType &compiler_type, - const ConstString &name, - const DataExtractor &data, - lldb::addr_t address) : - ValueObject (exe_scope), - m_type_name (), - m_byte_size (0), - m_impl(this, address) -{ - m_data = data; - - if (!m_data.GetSharedDataBuffer()) - { - DataBufferSP shared_data_buffer(new DataBufferHeap(data.GetDataStart(), data.GetByteSize())); - m_data.SetData(shared_data_buffer); - } - - m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); - m_value.SetValueType(Value::eValueTypeHostAddress); - m_value.SetCompilerType(compiler_type); - m_name = name; - SetIsConstant (); - SetValueIsValid(true); - SetAddressTypeOfChildren(eAddressTypeLoad); +ValueObjectConstResult::ValueObjectConstResult( + ExecutionContextScope *exe_scope, const CompilerType &compiler_type, + const ConstString &name, const DataExtractor &data, lldb::addr_t address) + : ValueObject(exe_scope), m_type_name(), m_byte_size(0), + m_impl(this, address) { + m_data = data; + + if (!m_data.GetSharedDataBuffer()) { + DataBufferSP shared_data_buffer( + new DataBufferHeap(data.GetDataStart(), data.GetByteSize())); + m_data.SetData(shared_data_buffer); + } + + m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); + m_value.SetValueType(Value::eValueTypeHostAddress); + m_value.SetCompilerType(compiler_type); + m_name = name; + SetIsConstant(); + SetValueIsValid(true); + SetAddressTypeOfChildren(eAddressTypeLoad); } -ValueObjectSP -ValueObjectConstResult::Create (ExecutionContextScope *exe_scope, - const CompilerType &compiler_type, - const ConstString &name, - const lldb::DataBufferSP &data_sp, - lldb::ByteOrder data_byte_order, - uint32_t data_addr_size, - lldb::addr_t address) -{ - return (new ValueObjectConstResult (exe_scope, - compiler_type, - name, - data_sp, - data_byte_order, - data_addr_size, - address))->GetSP(); +ValueObjectSP ValueObjectConstResult::Create(ExecutionContextScope *exe_scope, + const CompilerType &compiler_type, + const ConstString &name, + const lldb::DataBufferSP &data_sp, + lldb::ByteOrder data_byte_order, + uint32_t data_addr_size, + lldb::addr_t address) { + return (new ValueObjectConstResult(exe_scope, compiler_type, name, data_sp, + data_byte_order, data_addr_size, address)) + ->GetSP(); } -ValueObjectSP -ValueObjectConstResult::Create (ExecutionContextScope *exe_scope, - Value &value, - const ConstString &name, - Module *module) -{ - return (new ValueObjectConstResult (exe_scope, value, name, module))->GetSP(); +ValueObjectSP ValueObjectConstResult::Create(ExecutionContextScope *exe_scope, + Value &value, + const ConstString &name, + Module *module) { + return (new ValueObjectConstResult(exe_scope, value, name, module))->GetSP(); } -ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope, - const CompilerType &compiler_type, - const ConstString &name, - const lldb::DataBufferSP &data_sp, - lldb::ByteOrder data_byte_order, - uint32_t data_addr_size, - lldb::addr_t address) : - ValueObject (exe_scope), - m_type_name (), - m_byte_size (0), - m_impl(this, address) -{ - m_data.SetByteOrder(data_byte_order); - m_data.SetAddressByteSize(data_addr_size); - m_data.SetData(data_sp); - m_value.GetScalar() = (uintptr_t)data_sp->GetBytes(); - m_value.SetValueType(Value::eValueTypeHostAddress); - //m_value.SetContext(Value::eContextTypeClangType, compiler_type); - m_value.SetCompilerType (compiler_type); - m_name = name; - SetIsConstant (); - SetValueIsValid(true); - SetAddressTypeOfChildren(eAddressTypeLoad); +ValueObjectConstResult::ValueObjectConstResult( + ExecutionContextScope *exe_scope, const CompilerType &compiler_type, + const ConstString &name, const lldb::DataBufferSP &data_sp, + lldb::ByteOrder data_byte_order, uint32_t data_addr_size, + lldb::addr_t address) + : ValueObject(exe_scope), m_type_name(), m_byte_size(0), + m_impl(this, address) { + m_data.SetByteOrder(data_byte_order); + m_data.SetAddressByteSize(data_addr_size); + m_data.SetData(data_sp); + m_value.GetScalar() = (uintptr_t)data_sp->GetBytes(); + m_value.SetValueType(Value::eValueTypeHostAddress); + // m_value.SetContext(Value::eContextTypeClangType, compiler_type); + m_value.SetCompilerType(compiler_type); + m_name = name; + SetIsConstant(); + SetValueIsValid(true); + SetAddressTypeOfChildren(eAddressTypeLoad); } -ValueObjectSP -ValueObjectConstResult::Create (ExecutionContextScope *exe_scope, - const CompilerType &compiler_type, - const ConstString &name, - lldb::addr_t address, - AddressType address_type, - uint32_t addr_byte_size) -{ - return (new ValueObjectConstResult (exe_scope, - compiler_type, - name, - address, - address_type, - addr_byte_size))->GetSP(); +ValueObjectSP ValueObjectConstResult::Create(ExecutionContextScope *exe_scope, + const CompilerType &compiler_type, + const ConstString &name, + lldb::addr_t address, + AddressType address_type, + uint32_t addr_byte_size) { + return (new ValueObjectConstResult(exe_scope, compiler_type, name, address, + address_type, addr_byte_size)) + ->GetSP(); } -ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope, - const CompilerType &compiler_type, - const ConstString &name, - lldb::addr_t address, - AddressType address_type, - uint32_t addr_byte_size) : - ValueObject (exe_scope), - m_type_name (), - m_byte_size (0), - m_impl(this, address) -{ - m_value.GetScalar() = address; - m_data.SetAddressByteSize(addr_byte_size); - m_value.GetScalar().GetData (m_data, addr_byte_size); - //m_value.SetValueType(Value::eValueTypeHostAddress); - switch (address_type) - { - case eAddressTypeInvalid: m_value.SetValueType(Value::eValueTypeScalar); break; - case eAddressTypeFile: m_value.SetValueType(Value::eValueTypeFileAddress); break; - case eAddressTypeLoad: m_value.SetValueType(Value::eValueTypeLoadAddress); break; - case eAddressTypeHost: m_value.SetValueType(Value::eValueTypeHostAddress); break; - } -// m_value.SetContext(Value::eContextTypeClangType, compiler_type); - m_value.SetCompilerType (compiler_type); - m_name = name; - SetIsConstant (); - SetValueIsValid(true); - SetAddressTypeOfChildren(eAddressTypeLoad); +ValueObjectConstResult::ValueObjectConstResult( + ExecutionContextScope *exe_scope, const CompilerType &compiler_type, + const ConstString &name, lldb::addr_t address, AddressType address_type, + uint32_t addr_byte_size) + : ValueObject(exe_scope), m_type_name(), m_byte_size(0), + m_impl(this, address) { + m_value.GetScalar() = address; + m_data.SetAddressByteSize(addr_byte_size); + m_value.GetScalar().GetData(m_data, addr_byte_size); + // m_value.SetValueType(Value::eValueTypeHostAddress); + switch (address_type) { + case eAddressTypeInvalid: + m_value.SetValueType(Value::eValueTypeScalar); + break; + case eAddressTypeFile: + m_value.SetValueType(Value::eValueTypeFileAddress); + break; + case eAddressTypeLoad: + m_value.SetValueType(Value::eValueTypeLoadAddress); + break; + case eAddressTypeHost: + m_value.SetValueType(Value::eValueTypeHostAddress); + break; + } + // m_value.SetContext(Value::eContextTypeClangType, compiler_type); + m_value.SetCompilerType(compiler_type); + m_name = name; + SetIsConstant(); + SetValueIsValid(true); + SetAddressTypeOfChildren(eAddressTypeLoad); } -ValueObjectSP -ValueObjectConstResult::Create -( - ExecutionContextScope *exe_scope, - const Error& error -) -{ - return (new ValueObjectConstResult (exe_scope, - error))->GetSP(); +ValueObjectSP ValueObjectConstResult::Create(ExecutionContextScope *exe_scope, + const Error &error) { + return (new ValueObjectConstResult(exe_scope, error))->GetSP(); } -ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope, - const Error& error) : - ValueObject (exe_scope), - m_type_name (), - m_byte_size (0), - m_impl(this) -{ - m_error = error; - SetIsConstant (); +ValueObjectConstResult::ValueObjectConstResult(ExecutionContextScope *exe_scope, + const Error &error) + : ValueObject(exe_scope), m_type_name(), m_byte_size(0), m_impl(this) { + m_error = error; + SetIsConstant(); } -ValueObjectConstResult::ValueObjectConstResult (ExecutionContextScope *exe_scope, - const Value &value, - const ConstString &name, - Module *module) : - ValueObject (exe_scope), - m_type_name (), - m_byte_size (0), - m_impl(this) -{ - m_value = value; - m_name = name; - ExecutionContext exe_ctx; - exe_scope->CalculateExecutionContext(exe_ctx); - m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, module); +ValueObjectConstResult::ValueObjectConstResult(ExecutionContextScope *exe_scope, + const Value &value, + const ConstString &name, + Module *module) + : ValueObject(exe_scope), m_type_name(), m_byte_size(0), m_impl(this) { + m_value = value; + m_name = name; + ExecutionContext exe_ctx; + exe_scope->CalculateExecutionContext(exe_ctx); + m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, module); } -ValueObjectConstResult::~ValueObjectConstResult() -{ -} +ValueObjectConstResult::~ValueObjectConstResult() {} -CompilerType -ValueObjectConstResult::GetCompilerTypeImpl() -{ - return m_value.GetCompilerType(); +CompilerType ValueObjectConstResult::GetCompilerTypeImpl() { + return m_value.GetCompilerType(); } -lldb::ValueType -ValueObjectConstResult::GetValueType() const -{ - return eValueTypeConstResult; +lldb::ValueType ValueObjectConstResult::GetValueType() const { + return eValueTypeConstResult; } -uint64_t -ValueObjectConstResult::GetByteSize() -{ - ExecutionContext exe_ctx(GetExecutionContextRef()); +uint64_t ValueObjectConstResult::GetByteSize() { + ExecutionContext exe_ctx(GetExecutionContextRef()); - if (m_byte_size == 0) - SetByteSize(GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope())); - return m_byte_size; + if (m_byte_size == 0) + SetByteSize( + GetCompilerType().GetByteSize(exe_ctx.GetBestExecutionContextScope())); + return m_byte_size; } -void -ValueObjectConstResult::SetByteSize (size_t size) -{ - m_byte_size = size; -} +void ValueObjectConstResult::SetByteSize(size_t size) { m_byte_size = size; } -size_t -ValueObjectConstResult::CalculateNumChildren(uint32_t max) -{ - auto children_count = GetCompilerType().GetNumChildren (true); - return children_count <= max ? children_count : max; +size_t ValueObjectConstResult::CalculateNumChildren(uint32_t max) { + auto children_count = GetCompilerType().GetNumChildren(true); + return children_count <= max ? children_count : max; } -ConstString -ValueObjectConstResult::GetTypeName() -{ - if (m_type_name.IsEmpty()) - m_type_name = GetCompilerType().GetConstTypeName (); - return m_type_name; +ConstString ValueObjectConstResult::GetTypeName() { + if (m_type_name.IsEmpty()) + m_type_name = GetCompilerType().GetConstTypeName(); + return m_type_name; } -ConstString -ValueObjectConstResult::GetDisplayTypeName() -{ - return GetCompilerType().GetDisplayTypeName(); +ConstString ValueObjectConstResult::GetDisplayTypeName() { + return GetCompilerType().GetDisplayTypeName(); } -bool -ValueObjectConstResult::UpdateValue () -{ - // Const value is always valid - SetValueIsValid (true); - return true; +bool ValueObjectConstResult::UpdateValue() { + // Const value is always valid + SetValueIsValid(true); + return true; } - -bool -ValueObjectConstResult::IsInScope () -{ - // A const result value is always in scope since it serializes all - // information needed to contain the constant value. - return true; +bool ValueObjectConstResult::IsInScope() { + // A const result value is always in scope since it serializes all + // information needed to contain the constant value. + return true; } -lldb::ValueObjectSP -ValueObjectConstResult::Dereference (Error &error) -{ - return m_impl.Dereference(error); +lldb::ValueObjectSP ValueObjectConstResult::Dereference(Error &error) { + return m_impl.Dereference(error); } -lldb::ValueObjectSP -ValueObjectConstResult::GetSyntheticChildAtOffset(uint32_t offset, - const CompilerType& type, - bool can_create, - ConstString name_const_str) -{ - return m_impl.GetSyntheticChildAtOffset(offset, type, can_create, name_const_str); +lldb::ValueObjectSP ValueObjectConstResult::GetSyntheticChildAtOffset( + uint32_t offset, const CompilerType &type, bool can_create, + ConstString name_const_str) { + return m_impl.GetSyntheticChildAtOffset(offset, type, can_create, + name_const_str); } -lldb::ValueObjectSP -ValueObjectConstResult::AddressOf (Error &error) -{ - return m_impl.AddressOf(error); +lldb::ValueObjectSP ValueObjectConstResult::AddressOf(Error &error) { + return m_impl.AddressOf(error); } -lldb::addr_t -ValueObjectConstResult::GetAddressOf (bool scalar_is_load_address, - AddressType *address_type) -{ - return m_impl.GetAddressOf(scalar_is_load_address, address_type); +lldb::addr_t ValueObjectConstResult::GetAddressOf(bool scalar_is_load_address, + AddressType *address_type) { + return m_impl.GetAddressOf(scalar_is_load_address, address_type); } -ValueObject * -ValueObjectConstResult::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index) -{ - return m_impl.CreateChildAtIndex(idx, synthetic_array_member, synthetic_index); +ValueObject *ValueObjectConstResult::CreateChildAtIndex( + size_t idx, bool synthetic_array_member, int32_t synthetic_index) { + return m_impl.CreateChildAtIndex(idx, synthetic_array_member, + synthetic_index); } -size_t -ValueObjectConstResult::GetPointeeData (DataExtractor& data, - uint32_t item_idx, - uint32_t item_count) -{ - return m_impl.GetPointeeData(data, item_idx, item_count); +size_t ValueObjectConstResult::GetPointeeData(DataExtractor &data, + uint32_t item_idx, + uint32_t item_count) { + return m_impl.GetPointeeData(data, item_idx, item_count); } lldb::ValueObjectSP -ValueObjectConstResult::GetDynamicValue (lldb::DynamicValueType use_dynamic) -{ - // Always recalculate dynamic values for const results as the memory that - // they might point to might have changed at any time. - if (use_dynamic != eNoDynamicValues) - { - if (!IsDynamic()) - { - ExecutionContext exe_ctx (GetExecutionContextRef()); - Process *process = exe_ctx.GetProcessPtr(); - if (process && process->IsPossibleDynamicValue(*this)) - m_dynamic_value = new ValueObjectDynamicValue (*this, use_dynamic); - } - if (m_dynamic_value) - return m_dynamic_value->GetSP(); +ValueObjectConstResult::GetDynamicValue(lldb::DynamicValueType use_dynamic) { + // Always recalculate dynamic values for const results as the memory that + // they might point to might have changed at any time. + if (use_dynamic != eNoDynamicValues) { + if (!IsDynamic()) { + ExecutionContext exe_ctx(GetExecutionContextRef()); + Process *process = exe_ctx.GetProcessPtr(); + if (process && process->IsPossibleDynamicValue(*this)) + m_dynamic_value = new ValueObjectDynamicValue(*this, use_dynamic); } - return ValueObjectSP(); + if (m_dynamic_value) + return m_dynamic_value->GetSP(); + } + return ValueObjectSP(); } lldb::ValueObjectSP -ValueObjectConstResult::Cast (const CompilerType &compiler_type) -{ - return m_impl.Cast(compiler_type); +ValueObjectConstResult::Cast(const CompilerType &compiler_type) { + return m_impl.Cast(compiler_type); } -lldb::LanguageType -ValueObjectConstResult::GetPreferredDisplayLanguage () -{ - if (m_preferred_display_language != lldb::eLanguageTypeUnknown) - return m_preferred_display_language; - return GetCompilerTypeImpl().GetMinimumLanguage(); +lldb::LanguageType ValueObjectConstResult::GetPreferredDisplayLanguage() { + if (m_preferred_display_language != lldb::eLanguageTypeUnknown) + return m_preferred_display_language; + return GetCompilerTypeImpl().GetMinimumLanguage(); } diff --git a/source/Core/ValueObjectConstResultCast.cpp b/source/Core/ValueObjectConstResultCast.cpp index 1611503c4bf1..32451468c183 100644 --- a/source/Core/ValueObjectConstResultCast.cpp +++ b/source/Core/ValueObjectConstResultCast.cpp @@ -17,60 +17,42 @@ using namespace lldb_private; ValueObjectConstResultCast::ValueObjectConstResultCast( - ValueObject &parent, - const ConstString &name, - const CompilerType &cast_type, - lldb::addr_t live_address) : - ValueObjectCast (parent, name, cast_type), - m_impl(this, live_address) -{ - m_name = name; + ValueObject &parent, const ConstString &name, const CompilerType &cast_type, + lldb::addr_t live_address) + : ValueObjectCast(parent, name, cast_type), m_impl(this, live_address) { + m_name = name; } -ValueObjectConstResultCast::~ValueObjectConstResultCast() -{ -} +ValueObjectConstResultCast::~ValueObjectConstResultCast() {} -lldb::ValueObjectSP -ValueObjectConstResultCast::Dereference (Error &error) -{ - return m_impl.Dereference(error); +lldb::ValueObjectSP ValueObjectConstResultCast::Dereference(Error &error) { + return m_impl.Dereference(error); } -lldb::ValueObjectSP -ValueObjectConstResultCast::GetSyntheticChildAtOffset(uint32_t offset, - const CompilerType& type, - bool can_create, - ConstString name_const_str) -{ - return m_impl.GetSyntheticChildAtOffset(offset, type, can_create, name_const_str); +lldb::ValueObjectSP ValueObjectConstResultCast::GetSyntheticChildAtOffset( + uint32_t offset, const CompilerType &type, bool can_create, + ConstString name_const_str) { + return m_impl.GetSyntheticChildAtOffset(offset, type, can_create, + name_const_str); } -lldb::ValueObjectSP -ValueObjectConstResultCast::AddressOf (Error &error) -{ - return m_impl.AddressOf(error); +lldb::ValueObjectSP ValueObjectConstResultCast::AddressOf(Error &error) { + return m_impl.AddressOf(error); } -ValueObject * -ValueObjectConstResultCast::CreateChildAtIndex (size_t idx, - bool synthetic_array_member, - int32_t synthetic_index) -{ - return m_impl.CreateChildAtIndex( - idx, synthetic_array_member, synthetic_index); +ValueObject *ValueObjectConstResultCast::CreateChildAtIndex( + size_t idx, bool synthetic_array_member, int32_t synthetic_index) { + return m_impl.CreateChildAtIndex(idx, synthetic_array_member, + synthetic_index); } -size_t -ValueObjectConstResultCast::GetPointeeData (DataExtractor& data, - uint32_t item_idx, - uint32_t item_count) -{ - return m_impl.GetPointeeData(data, item_idx, item_count); +size_t ValueObjectConstResultCast::GetPointeeData(DataExtractor &data, + uint32_t item_idx, + uint32_t item_count) { + return m_impl.GetPointeeData(data, item_idx, item_count); } lldb::ValueObjectSP -ValueObjectConstResultCast::Cast (const CompilerType &compiler_type) -{ - return m_impl.Cast(compiler_type); +ValueObjectConstResultCast::Cast(const CompilerType &compiler_type) { + return m_impl.Cast(compiler_type); } diff --git a/source/Core/ValueObjectConstResultChild.cpp b/source/Core/ValueObjectConstResultChild.cpp index e3afa36351a8..c4c9c63c765d 100644 --- a/source/Core/ValueObjectConstResultChild.cpp +++ b/source/Core/ValueObjectConstResultChild.cpp @@ -1,4 +1,5 @@ -//===-- ValueObjectConstResultChild.cpp ------------------------------*- C++ -*-===// +//===-- ValueObjectConstResultChild.cpp ------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -16,80 +17,49 @@ using namespace lldb_private; -ValueObjectConstResultChild::ValueObjectConstResultChild -( - ValueObject &parent, - const CompilerType &compiler_type, - const ConstString &name, - uint32_t byte_size, - int32_t byte_offset, - uint32_t bitfield_bit_size, - uint32_t bitfield_bit_offset, - bool is_base_class, - bool is_deref_of_parent, - lldb::addr_t live_address, - uint64_t language_flags -) : - ValueObjectChild (parent, - compiler_type, - name, - byte_size, - byte_offset, - bitfield_bit_size, - bitfield_bit_offset, - is_base_class, - is_deref_of_parent, - eAddressTypeLoad, - language_flags), - m_impl(this, live_address) -{ - m_name = name; +ValueObjectConstResultChild::ValueObjectConstResultChild( + ValueObject &parent, const CompilerType &compiler_type, + const ConstString &name, uint32_t byte_size, int32_t byte_offset, + uint32_t bitfield_bit_size, uint32_t bitfield_bit_offset, + bool is_base_class, bool is_deref_of_parent, lldb::addr_t live_address, + uint64_t language_flags) + : ValueObjectChild(parent, compiler_type, name, byte_size, byte_offset, + bitfield_bit_size, bitfield_bit_offset, is_base_class, + is_deref_of_parent, eAddressTypeLoad, language_flags), + m_impl(this, live_address) { + m_name = name; } -ValueObjectConstResultChild::~ValueObjectConstResultChild() -{ -} +ValueObjectConstResultChild::~ValueObjectConstResultChild() {} -lldb::ValueObjectSP -ValueObjectConstResultChild::Dereference (Error &error) -{ - return m_impl.Dereference(error); +lldb::ValueObjectSP ValueObjectConstResultChild::Dereference(Error &error) { + return m_impl.Dereference(error); } -lldb::ValueObjectSP -ValueObjectConstResultChild::GetSyntheticChildAtOffset(uint32_t offset, - const CompilerType& type, - bool can_create, - ConstString name_const_str) -{ - return m_impl.GetSyntheticChildAtOffset(offset, - type, - can_create, - name_const_str); +lldb::ValueObjectSP ValueObjectConstResultChild::GetSyntheticChildAtOffset( + uint32_t offset, const CompilerType &type, bool can_create, + ConstString name_const_str) { + return m_impl.GetSyntheticChildAtOffset(offset, type, can_create, + name_const_str); } -lldb::ValueObjectSP -ValueObjectConstResultChild::AddressOf (Error &error) -{ - return m_impl.AddressOf(error); +lldb::ValueObjectSP ValueObjectConstResultChild::AddressOf(Error &error) { + return m_impl.AddressOf(error); } -ValueObject * -ValueObjectConstResultChild::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index) -{ - return m_impl.CreateChildAtIndex(idx, synthetic_array_member, synthetic_index); +ValueObject *ValueObjectConstResultChild::CreateChildAtIndex( + size_t idx, bool synthetic_array_member, int32_t synthetic_index) { + return m_impl.CreateChildAtIndex(idx, synthetic_array_member, + synthetic_index); } -size_t -ValueObjectConstResultChild::GetPointeeData (DataExtractor& data, - uint32_t item_idx, - uint32_t item_count) -{ - return m_impl.GetPointeeData(data, item_idx, item_count); +size_t ValueObjectConstResultChild::GetPointeeData(DataExtractor &data, + uint32_t item_idx, + uint32_t item_count) { + return m_impl.GetPointeeData(data, item_idx, item_count); } lldb::ValueObjectSP -ValueObjectConstResultChild::Cast (const CompilerType &compiler_type) -{ - return m_impl.Cast(compiler_type); +ValueObjectConstResultChild::Cast(const CompilerType &compiler_type) { + return m_impl.Cast(compiler_type); } diff --git a/source/Core/ValueObjectConstResultImpl.cpp b/source/Core/ValueObjectConstResultImpl.cpp index 6db7f184da8f..0e4f73f13b52 100644 --- a/source/Core/ValueObjectConstResultImpl.cpp +++ b/source/Core/ValueObjectConstResultImpl.cpp @@ -1,4 +1,5 @@ -//===-- ValueObjectConstResultImpl.cpp ---------------------------*- C++ -*-===// +//===-- ValueObjectConstResultImpl.cpp ---------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -9,14 +10,14 @@ #include "lldb/Core/ValueObjectConstResultImpl.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Module.h" #include "lldb/Core/ValueObjectChild.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectConstResultCast.h" #include "lldb/Core/ValueObjectConstResultChild.h" -#include "lldb/Core/ValueObjectMemory.h" -#include "lldb/Core/DataExtractor.h" -#include "lldb/Core/Module.h" #include "lldb/Core/ValueObjectList.h" +#include "lldb/Core/ValueObjectMemory.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ObjectFile.h" @@ -31,176 +32,143 @@ using namespace lldb; using namespace lldb_private; -ValueObjectConstResultImpl::ValueObjectConstResultImpl (ValueObject* valobj, - lldb::addr_t live_address) : - m_impl_backend(valobj), - m_live_address(live_address), - m_live_address_type(eAddressTypeLoad), - m_load_addr_backend(), - m_address_of_backend() -{ -} +ValueObjectConstResultImpl::ValueObjectConstResultImpl( + ValueObject *valobj, lldb::addr_t live_address) + : m_impl_backend(valobj), m_live_address(live_address), + m_live_address_type(eAddressTypeLoad), m_load_addr_backend(), + m_address_of_backend() {} -lldb::ValueObjectSP -ValueObjectConstResultImpl::Dereference (Error &error) -{ - if (m_impl_backend == NULL) - return lldb::ValueObjectSP(); - - return m_impl_backend->ValueObject::Dereference(error); +lldb::ValueObjectSP ValueObjectConstResultImpl::Dereference(Error &error) { + if (m_impl_backend == NULL) + return lldb::ValueObjectSP(); + + return m_impl_backend->ValueObject::Dereference(error); } -ValueObject * -ValueObjectConstResultImpl::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index) -{ - if (m_impl_backend == NULL) - return NULL; - - m_impl_backend->UpdateValueIfNeeded(false); - - ValueObjectConstResultChild *valobj = NULL; - - bool omit_empty_base_classes = true; - bool ignore_array_bounds = synthetic_array_member; - std::string child_name_str; - uint32_t child_byte_size = 0; - int32_t child_byte_offset = 0; - uint32_t child_bitfield_bit_size = 0; - uint32_t child_bitfield_bit_offset = 0; - bool child_is_base_class = false; - bool child_is_deref_of_parent = false; - uint64_t language_flags; - - const bool transparent_pointers = synthetic_array_member == false; - CompilerType compiler_type = m_impl_backend->GetCompilerType(); - CompilerType child_compiler_type; - - ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef()); - - child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex (&exe_ctx, - idx, - transparent_pointers, - omit_empty_base_classes, - ignore_array_bounds, - child_name_str, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent, - m_impl_backend, - language_flags); - if (child_compiler_type && child_byte_size) - { - if (synthetic_index) - child_byte_offset += child_byte_size * synthetic_index; - - ConstString child_name; - if (!child_name_str.empty()) - child_name.SetCString (child_name_str.c_str()); - - valobj = new ValueObjectConstResultChild (*m_impl_backend, - child_compiler_type, - child_name, - child_byte_size, - child_byte_offset, - child_bitfield_bit_size, - child_bitfield_bit_offset, - child_is_base_class, - child_is_deref_of_parent, - m_live_address == LLDB_INVALID_ADDRESS ? m_live_address : m_live_address+child_byte_offset, - language_flags); - } - - return valobj; +ValueObject *ValueObjectConstResultImpl::CreateChildAtIndex( + size_t idx, bool synthetic_array_member, int32_t synthetic_index) { + if (m_impl_backend == NULL) + return NULL; + + m_impl_backend->UpdateValueIfNeeded(false); + + ValueObjectConstResultChild *valobj = NULL; + + bool omit_empty_base_classes = true; + bool ignore_array_bounds = synthetic_array_member; + std::string child_name_str; + uint32_t child_byte_size = 0; + int32_t child_byte_offset = 0; + uint32_t child_bitfield_bit_size = 0; + uint32_t child_bitfield_bit_offset = 0; + bool child_is_base_class = false; + bool child_is_deref_of_parent = false; + uint64_t language_flags; + + const bool transparent_pointers = synthetic_array_member == false; + CompilerType compiler_type = m_impl_backend->GetCompilerType(); + CompilerType child_compiler_type; + + ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef()); + + child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex( + &exe_ctx, idx, transparent_pointers, omit_empty_base_classes, + ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset, + child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, + child_is_deref_of_parent, m_impl_backend, language_flags); + if (child_compiler_type && child_byte_size) { + if (synthetic_index) + child_byte_offset += child_byte_size * synthetic_index; + + ConstString child_name; + if (!child_name_str.empty()) + child_name.SetCString(child_name_str.c_str()); + + valobj = new ValueObjectConstResultChild( + *m_impl_backend, child_compiler_type, child_name, child_byte_size, + child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset, + child_is_base_class, child_is_deref_of_parent, + m_live_address == LLDB_INVALID_ADDRESS + ? m_live_address + : m_live_address + child_byte_offset, + language_flags); + } + + return valobj; } -lldb::ValueObjectSP -ValueObjectConstResultImpl::GetSyntheticChildAtOffset (uint32_t offset, - const CompilerType& type, - bool can_create, - ConstString name_const_str) -{ - if (m_impl_backend == NULL) - return lldb::ValueObjectSP(); - - return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(offset, - type, - can_create, - name_const_str); +lldb::ValueObjectSP ValueObjectConstResultImpl::GetSyntheticChildAtOffset( + uint32_t offset, const CompilerType &type, bool can_create, + ConstString name_const_str) { + if (m_impl_backend == NULL) + return lldb::ValueObjectSP(); + + return m_impl_backend->ValueObject::GetSyntheticChildAtOffset( + offset, type, can_create, name_const_str); } -lldb::ValueObjectSP -ValueObjectConstResultImpl::AddressOf (Error &error) -{ - if (m_address_of_backend.get() != NULL) - return m_address_of_backend; - - if (m_impl_backend == NULL) - return lldb::ValueObjectSP(); - if (m_live_address != LLDB_INVALID_ADDRESS) - { - CompilerType compiler_type(m_impl_backend->GetCompilerType()); - - lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(&m_live_address,sizeof(lldb::addr_t))); - - std::string new_name("&"); - new_name.append(m_impl_backend->GetName().AsCString("")); - ExecutionContext exe_ctx (m_impl_backend->GetExecutionContextRef()); - m_address_of_backend = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), - compiler_type.GetPointerType(), - ConstString(new_name.c_str()), - buffer, - endian::InlHostByteOrder(), - exe_ctx.GetAddressByteSize()); - - m_address_of_backend->GetValue().SetValueType(Value::eValueTypeScalar); - m_address_of_backend->GetValue().GetScalar() = m_live_address; - - return m_address_of_backend; - } - else - return m_impl_backend->ValueObject::AddressOf(error); +lldb::ValueObjectSP ValueObjectConstResultImpl::AddressOf(Error &error) { + if (m_address_of_backend.get() != NULL) + return m_address_of_backend; + + if (m_impl_backend == NULL) + return lldb::ValueObjectSP(); + if (m_live_address != LLDB_INVALID_ADDRESS) { + CompilerType compiler_type(m_impl_backend->GetCompilerType()); + + lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap( + &m_live_address, sizeof(lldb::addr_t))); + + std::string new_name("&"); + new_name.append(m_impl_backend->GetName().AsCString("")); + ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef()); + m_address_of_backend = ValueObjectConstResult::Create( + exe_ctx.GetBestExecutionContextScope(), compiler_type.GetPointerType(), + ConstString(new_name.c_str()), buffer, endian::InlHostByteOrder(), + exe_ctx.GetAddressByteSize()); + + m_address_of_backend->GetValue().SetValueType(Value::eValueTypeScalar); + m_address_of_backend->GetValue().GetScalar() = m_live_address; + + return m_address_of_backend; + } else + return m_impl_backend->ValueObject::AddressOf(error); } lldb::ValueObjectSP -ValueObjectConstResultImpl::Cast (const CompilerType &compiler_type) -{ - if (m_impl_backend == NULL) - return lldb::ValueObjectSP(); - - ValueObjectConstResultCast *result_cast = new ValueObjectConstResultCast( - *m_impl_backend, m_impl_backend->GetName(), compiler_type, m_live_address); - return result_cast->GetSP(); +ValueObjectConstResultImpl::Cast(const CompilerType &compiler_type) { + if (m_impl_backend == NULL) + return lldb::ValueObjectSP(); + + ValueObjectConstResultCast *result_cast = + new ValueObjectConstResultCast(*m_impl_backend, m_impl_backend->GetName(), + compiler_type, m_live_address); + return result_cast->GetSP(); } lldb::addr_t -ValueObjectConstResultImpl::GetAddressOf (bool scalar_is_load_address, - AddressType *address_type) -{ - - if (m_impl_backend == NULL) - return 0; - - if (m_live_address == LLDB_INVALID_ADDRESS) - { - return m_impl_backend->ValueObject::GetAddressOf (scalar_is_load_address, - address_type); - } - - if (address_type) - *address_type = m_live_address_type; - - return m_live_address; +ValueObjectConstResultImpl::GetAddressOf(bool scalar_is_load_address, + AddressType *address_type) { + + if (m_impl_backend == NULL) + return 0; + + if (m_live_address == LLDB_INVALID_ADDRESS) { + return m_impl_backend->ValueObject::GetAddressOf(scalar_is_load_address, + address_type); + } + + if (address_type) + *address_type = m_live_address_type; + + return m_live_address; } -size_t -ValueObjectConstResultImpl::GetPointeeData (DataExtractor& data, - uint32_t item_idx, - uint32_t item_count) -{ - if (m_impl_backend == NULL) - return 0; - return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, item_count); +size_t ValueObjectConstResultImpl::GetPointeeData(DataExtractor &data, + uint32_t item_idx, + uint32_t item_count) { + if (m_impl_backend == NULL) + return 0; + return m_impl_backend->ValueObject::GetPointeeData(data, item_idx, + item_count); } diff --git a/source/Core/ValueObjectDynamicValue.cpp b/source/Core/ValueObjectDynamicValue.cpp index 65deba096d82..1fb32d4e86a3 100644 --- a/source/Core/ValueObjectDynamicValue.cpp +++ b/source/Core/ValueObjectDynamicValue.cpp @@ -1,4 +1,5 @@ -//===-- ValueObjectDynamicValue.cpp ---------------------------------*- C++ -*-===// +//===-- ValueObjectDynamicValue.cpp ---------------------------------*- C++ +//-*-===// // // The LLVM Compiler Infrastructure // @@ -7,7 +8,6 @@ // //===----------------------------------------------------------------------===// - #include "lldb/Core/ValueObjectDynamicValue.h" // C Includes @@ -16,9 +16,9 @@ // Project includes #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" -#include "lldb/Core/ValueObjectList.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectList.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ObjectFile.h" @@ -35,427 +35,365 @@ using namespace lldb_private; -ValueObjectDynamicValue::ValueObjectDynamicValue (ValueObject &parent, lldb::DynamicValueType use_dynamic) : - ValueObject(parent), - m_address (), - m_dynamic_type_info(), - m_use_dynamic (use_dynamic) -{ - SetName (parent.GetName()); +ValueObjectDynamicValue::ValueObjectDynamicValue( + ValueObject &parent, lldb::DynamicValueType use_dynamic) + : ValueObject(parent), m_address(), m_dynamic_type_info(), + m_use_dynamic(use_dynamic) { + SetName(parent.GetName()); } -ValueObjectDynamicValue::~ValueObjectDynamicValue() -{ - m_owning_valobj_sp.reset(); +ValueObjectDynamicValue::~ValueObjectDynamicValue() { + m_owning_valobj_sp.reset(); } -CompilerType -ValueObjectDynamicValue::GetCompilerTypeImpl () -{ - const bool success = UpdateValueIfNeeded(false); - if (success) - { - if (m_dynamic_type_info.HasType()) - return m_value.GetCompilerType(); - else - return m_parent->GetCompilerType(); - } - return m_parent->GetCompilerType(); +CompilerType ValueObjectDynamicValue::GetCompilerTypeImpl() { + const bool success = UpdateValueIfNeeded(false); + if (success) { + if (m_dynamic_type_info.HasType()) + return m_value.GetCompilerType(); + else + return m_parent->GetCompilerType(); + } + return m_parent->GetCompilerType(); } -ConstString -ValueObjectDynamicValue::GetTypeName() -{ - const bool success = UpdateValueIfNeeded(false); - if (success) - { - if (m_dynamic_type_info.HasName()) - return m_dynamic_type_info.GetName(); - } - return m_parent->GetTypeName(); +ConstString ValueObjectDynamicValue::GetTypeName() { + const bool success = UpdateValueIfNeeded(false); + if (success) { + if (m_dynamic_type_info.HasName()) + return m_dynamic_type_info.GetName(); + } + return m_parent->GetTypeName(); } -TypeImpl -ValueObjectDynamicValue::GetTypeImpl () -{ - const bool success = UpdateValueIfNeeded(false); - if (success && m_type_impl.IsValid()) - { - return m_type_impl; - } - return m_parent->GetTypeImpl(); +TypeImpl ValueObjectDynamicValue::GetTypeImpl() { + const bool success = UpdateValueIfNeeded(false); + if (success && m_type_impl.IsValid()) { + return m_type_impl; + } + return m_parent->GetTypeImpl(); } -ConstString -ValueObjectDynamicValue::GetQualifiedTypeName() -{ - const bool success = UpdateValueIfNeeded(false); - if (success) - { - if (m_dynamic_type_info.HasName()) - return m_dynamic_type_info.GetName(); - } - return m_parent->GetQualifiedTypeName(); +ConstString ValueObjectDynamicValue::GetQualifiedTypeName() { + const bool success = UpdateValueIfNeeded(false); + if (success) { + if (m_dynamic_type_info.HasName()) + return m_dynamic_type_info.GetName(); + } + return m_parent->GetQualifiedTypeName(); } -ConstString -ValueObjectDynamicValue::GetDisplayTypeName() -{ - const bool success = UpdateValueIfNeeded(false); - if (success) - { - if (m_dynamic_type_info.HasType()) - return GetCompilerType().GetDisplayTypeName(); - if (m_dynamic_type_info.HasName()) - return m_dynamic_type_info.GetName(); - } - return m_parent->GetDisplayTypeName(); +ConstString ValueObjectDynamicValue::GetDisplayTypeName() { + const bool success = UpdateValueIfNeeded(false); + if (success) { + if (m_dynamic_type_info.HasType()) + return GetCompilerType().GetDisplayTypeName(); + if (m_dynamic_type_info.HasName()) + return m_dynamic_type_info.GetName(); + } + return m_parent->GetDisplayTypeName(); } -size_t -ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) -{ - const bool success = UpdateValueIfNeeded(false); - if (success && m_dynamic_type_info.HasType()) - { - auto children_count = GetCompilerType().GetNumChildren (true); - return children_count <= max ? children_count : max; - } - else - return m_parent->GetNumChildren(max); +size_t ValueObjectDynamicValue::CalculateNumChildren(uint32_t max) { + const bool success = UpdateValueIfNeeded(false); + if (success && m_dynamic_type_info.HasType()) { + auto children_count = GetCompilerType().GetNumChildren(true); + return children_count <= max ? children_count : max; + } else + return m_parent->GetNumChildren(max); } -uint64_t -ValueObjectDynamicValue::GetByteSize() -{ - const bool success = UpdateValueIfNeeded(false); - if (success && m_dynamic_type_info.HasType()) - { - ExecutionContext exe_ctx (GetExecutionContextRef()); - return m_value.GetValueByteSize(nullptr, &exe_ctx); - } - else - return m_parent->GetByteSize(); +uint64_t ValueObjectDynamicValue::GetByteSize() { + const bool success = UpdateValueIfNeeded(false); + if (success && m_dynamic_type_info.HasType()) { + ExecutionContext exe_ctx(GetExecutionContextRef()); + return m_value.GetValueByteSize(nullptr, &exe_ctx); + } else + return m_parent->GetByteSize(); } -lldb::ValueType -ValueObjectDynamicValue::GetValueType() const -{ - return m_parent->GetValueType(); +lldb::ValueType ValueObjectDynamicValue::GetValueType() const { + return m_parent->GetValueType(); } -bool -ValueObjectDynamicValue::UpdateValue () -{ - SetValueIsValid (false); - m_error.Clear(); - - if (!m_parent->UpdateValueIfNeeded(false)) - { - // The dynamic value failed to get an error, pass the error along - if (m_error.Success() && m_parent->GetError().Fail()) - m_error = m_parent->GetError(); - return false; - } +bool ValueObjectDynamicValue::UpdateValue() { + SetValueIsValid(false); + m_error.Clear(); - // Setting our type_sp to NULL will route everything back through our - // parent which is equivalent to not using dynamic values. - if (m_use_dynamic == lldb::eNoDynamicValues) - { - m_dynamic_type_info.Clear(); - return true; - } + if (!m_parent->UpdateValueIfNeeded(false)) { + // The dynamic value failed to get an error, pass the error along + if (m_error.Success() && m_parent->GetError().Fail()) + m_error = m_parent->GetError(); + return false; + } + + // Setting our type_sp to NULL will route everything back through our + // parent which is equivalent to not using dynamic values. + if (m_use_dynamic == lldb::eNoDynamicValues) { + m_dynamic_type_info.Clear(); + return true; + } + + ExecutionContext exe_ctx(GetExecutionContextRef()); + Target *target = exe_ctx.GetTargetPtr(); + if (target) { + m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); + m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); + } + + // First make sure our Type and/or Address haven't changed: + Process *process = exe_ctx.GetProcessPtr(); + if (!process) + return false; - ExecutionContext exe_ctx (GetExecutionContextRef()); - Target *target = exe_ctx.GetTargetPtr(); - if (target) - { - m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); - m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); - } + TypeAndOrName class_type_or_name; + Address dynamic_address; + bool found_dynamic_type = false; + Value::ValueType value_type; - // First make sure our Type and/or Address haven't changed: - Process *process = exe_ctx.GetProcessPtr(); - if (!process) - return false; - - TypeAndOrName class_type_or_name; - Address dynamic_address; - bool found_dynamic_type = false; - Value::ValueType value_type; - - LanguageRuntime *runtime = nullptr; - - lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage(); - if (known_type != lldb::eLanguageTypeUnknown && known_type != lldb::eLanguageTypeC) - { - runtime = process->GetLanguageRuntime (known_type); - if (runtime) - found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address, value_type); - } - else - { - runtime = process->GetLanguageRuntime (lldb::eLanguageTypeC_plus_plus); - if (runtime) - found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address, value_type); - - if (!found_dynamic_type) - { - runtime = process->GetLanguageRuntime (lldb::eLanguageTypeObjC); - if (runtime) - found_dynamic_type = runtime->GetDynamicTypeAndAddress (*m_parent, m_use_dynamic, class_type_or_name, dynamic_address, value_type); - } - } + LanguageRuntime *runtime = nullptr; - // Getting the dynamic value may have run the program a bit, and so marked us as needing updating, but we really - // don't... - - m_update_point.SetUpdated(); - - if (runtime && found_dynamic_type) - { - if (class_type_or_name.HasType()) - { - m_type_impl = TypeImpl(m_parent->GetCompilerType(), - runtime->FixUpDynamicType(class_type_or_name, *m_parent).GetCompilerType()); - } - else - { - m_type_impl.Clear(); - } + lldb::LanguageType known_type = m_parent->GetObjectRuntimeLanguage(); + if (known_type != lldb::eLanguageTypeUnknown && + known_type != lldb::eLanguageTypeC) { + runtime = process->GetLanguageRuntime(known_type); + if (runtime) + found_dynamic_type = runtime->GetDynamicTypeAndAddress( + *m_parent, m_use_dynamic, class_type_or_name, dynamic_address, + value_type); + } else { + runtime = process->GetLanguageRuntime(lldb::eLanguageTypeC_plus_plus); + if (runtime) + found_dynamic_type = runtime->GetDynamicTypeAndAddress( + *m_parent, m_use_dynamic, class_type_or_name, dynamic_address, + value_type); + + if (!found_dynamic_type) { + runtime = process->GetLanguageRuntime(lldb::eLanguageTypeObjC); + if (runtime) + found_dynamic_type = runtime->GetDynamicTypeAndAddress( + *m_parent, m_use_dynamic, class_type_or_name, dynamic_address, + value_type); } - else - { - m_type_impl.Clear(); + } + + // Getting the dynamic value may have run the program a bit, and so marked us + // as needing updating, but we really + // don't... + + m_update_point.SetUpdated(); + + if (runtime && found_dynamic_type) { + if (class_type_or_name.HasType()) { + m_type_impl = + TypeImpl(m_parent->GetCompilerType(), + runtime->FixUpDynamicType(class_type_or_name, *m_parent) + .GetCompilerType()); + } else { + m_type_impl.Clear(); } - - // If we don't have a dynamic type, then make ourselves just a echo of our parent. - // Or we could return false, and make ourselves an echo of our parent? - if (!found_dynamic_type) - { - if (m_dynamic_type_info) - SetValueDidChange(true); - ClearDynamicTypeInformation(); - m_dynamic_type_info.Clear(); - m_value = m_parent->GetValue(); - m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); - return m_error.Success(); + } else { + m_type_impl.Clear(); + } + + // If we don't have a dynamic type, then make ourselves just a echo of our + // parent. + // Or we could return false, and make ourselves an echo of our parent? + if (!found_dynamic_type) { + if (m_dynamic_type_info) + SetValueDidChange(true); + ClearDynamicTypeInformation(); + m_dynamic_type_info.Clear(); + m_value = m_parent->GetValue(); + m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + return m_error.Success(); + } + + Value old_value(m_value); + + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); + + bool has_changed_type = false; + + if (!m_dynamic_type_info) { + m_dynamic_type_info = class_type_or_name; + has_changed_type = true; + } else if (class_type_or_name != m_dynamic_type_info) { + // We are another type, we need to tear down our children... + m_dynamic_type_info = class_type_or_name; + SetValueDidChange(true); + has_changed_type = true; + } + + if (has_changed_type) + ClearDynamicTypeInformation(); + + if (!m_address.IsValid() || m_address != dynamic_address) { + if (m_address.IsValid()) + SetValueDidChange(true); + + // We've moved, so we should be fine... + m_address = dynamic_address; + lldb::TargetSP target_sp(GetTargetSP()); + lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); + m_value.GetScalar() = load_address; + } + + if (runtime) + m_dynamic_type_info = + runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent); + + // m_value.SetContext (Value::eContextTypeClangType, corrected_type); + m_value.SetCompilerType(m_dynamic_type_info.GetCompilerType()); + + m_value.SetValueType(value_type); + + if (has_changed_type && log) + log->Printf("[%s %p] has a new dynamic type %s", GetName().GetCString(), + static_cast<void *>(this), GetTypeName().GetCString()); + + if (m_address.IsValid() && m_dynamic_type_info) { + // The variable value is in the Scalar value inside the m_value. + // We can point our m_data right to it. + m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + if (m_error.Success()) { + if (!CanProvideValue()) { + // this value object represents an aggregate type whose + // children have values, but this object does not. So we + // say we are changed if our location has changed. + SetValueDidChange(m_value.GetValueType() != old_value.GetValueType() || + m_value.GetScalar() != old_value.GetScalar()); + } + + SetValueIsValid(true); + return true; } + } - Value old_value(m_value); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_TYPES)); - - bool has_changed_type = false; - - if (!m_dynamic_type_info) - { - m_dynamic_type_info = class_type_or_name; - has_changed_type = true; - } - else if (class_type_or_name != m_dynamic_type_info) - { - // We are another type, we need to tear down our children... - m_dynamic_type_info = class_type_or_name; - SetValueDidChange (true); - has_changed_type = true; - } + // We get here if we've failed above... + SetValueIsValid(false); + return false; +} - if (has_changed_type) - ClearDynamicTypeInformation (); +bool ValueObjectDynamicValue::IsInScope() { return m_parent->IsInScope(); } - if (!m_address.IsValid() || m_address != dynamic_address) - { - if (m_address.IsValid()) - SetValueDidChange (true); +bool ValueObjectDynamicValue::SetValueFromCString(const char *value_str, + Error &error) { + if (!UpdateValueIfNeeded(false)) { + error.SetErrorString("unable to read value"); + return false; + } - // We've moved, so we should be fine... - m_address = dynamic_address; - lldb::TargetSP target_sp (GetTargetSP()); - lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); - m_value.GetScalar() = load_address; - } + uint64_t my_value = GetValueAsUnsigned(UINT64_MAX); + uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX); - if (runtime) - m_dynamic_type_info = runtime->FixUpDynamicType(m_dynamic_type_info, *m_parent); - - //m_value.SetContext (Value::eContextTypeClangType, corrected_type); - m_value.SetCompilerType (m_dynamic_type_info.GetCompilerType()); - - m_value.SetValueType(value_type); - - if (has_changed_type && log) - log->Printf("[%s %p] has a new dynamic type %s", GetName().GetCString(), - static_cast<void*>(this), GetTypeName().GetCString()); - - if (m_address.IsValid() && m_dynamic_type_info) - { - // The variable value is in the Scalar value inside the m_value. - // We can point our m_data right to it. - m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); - if (m_error.Success()) - { - if (!CanProvideValue()) - { - // this value object represents an aggregate type whose - // children have values, but this object does not. So we - // say we are changed if our location has changed. - SetValueDidChange (m_value.GetValueType() != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar()); - } - - SetValueIsValid (true); - return true; - } + if (my_value == UINT64_MAX || parent_value == UINT64_MAX) { + error.SetErrorString("unable to read value"); + return false; + } + + // if we are at an offset from our parent, in order to set ourselves correctly + // we would need + // to change the new value so that it refers to the correct dynamic type. we + // choose not to deal + // with that - if anything more than a value overwrite is required, you should + // be using the + // expression parser instead of the value editing facility + if (my_value != parent_value) { + // but NULL'ing out a value should always be allowed + if (strcmp(value_str, "0")) { + error.SetErrorString( + "unable to modify dynamic value, use 'expression' command"); + return false; } + } - // We get here if we've failed above... - SetValueIsValid (false); - return false; + bool ret_val = m_parent->SetValueFromCString(value_str, error); + SetNeedsUpdate(); + return ret_val; } +bool ValueObjectDynamicValue::SetData(DataExtractor &data, Error &error) { + if (!UpdateValueIfNeeded(false)) { + error.SetErrorString("unable to read value"); + return false; + } + uint64_t my_value = GetValueAsUnsigned(UINT64_MAX); + uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX); -bool -ValueObjectDynamicValue::IsInScope () -{ - return m_parent->IsInScope(); -} - -bool -ValueObjectDynamicValue::SetValueFromCString (const char *value_str, Error& error) -{ - if (!UpdateValueIfNeeded(false)) - { - error.SetErrorString("unable to read value"); - return false; - } - - uint64_t my_value = GetValueAsUnsigned(UINT64_MAX); - uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX); - - if (my_value == UINT64_MAX || parent_value == UINT64_MAX) - { - error.SetErrorString("unable to read value"); - return false; - } - - // if we are at an offset from our parent, in order to set ourselves correctly we would need - // to change the new value so that it refers to the correct dynamic type. we choose not to deal - // with that - if anything more than a value overwrite is required, you should be using the - // expression parser instead of the value editing facility - if (my_value != parent_value) - { - // but NULL'ing out a value should always be allowed - if (strcmp(value_str,"0")) - { - error.SetErrorString("unable to modify dynamic value, use 'expression' command"); - return false; - } + if (my_value == UINT64_MAX || parent_value == UINT64_MAX) { + error.SetErrorString("unable to read value"); + return false; + } + + // if we are at an offset from our parent, in order to set ourselves correctly + // we would need + // to change the new value so that it refers to the correct dynamic type. we + // choose not to deal + // with that - if anything more than a value overwrite is required, you should + // be using the + // expression parser instead of the value editing facility + if (my_value != parent_value) { + // but NULL'ing out a value should always be allowed + lldb::offset_t offset = 0; + + if (data.GetPointer(&offset) != 0) { + error.SetErrorString( + "unable to modify dynamic value, use 'expression' command"); + return false; } - - bool ret_val = m_parent->SetValueFromCString(value_str,error); - SetNeedsUpdate(); - return ret_val; -} + } -bool -ValueObjectDynamicValue::SetData (DataExtractor &data, Error &error) -{ - if (!UpdateValueIfNeeded(false)) - { - error.SetErrorString("unable to read value"); - return false; - } - - uint64_t my_value = GetValueAsUnsigned(UINT64_MAX); - uint64_t parent_value = m_parent->GetValueAsUnsigned(UINT64_MAX); - - if (my_value == UINT64_MAX || parent_value == UINT64_MAX) - { - error.SetErrorString("unable to read value"); - return false; - } - - // if we are at an offset from our parent, in order to set ourselves correctly we would need - // to change the new value so that it refers to the correct dynamic type. we choose not to deal - // with that - if anything more than a value overwrite is required, you should be using the - // expression parser instead of the value editing facility - if (my_value != parent_value) - { - // but NULL'ing out a value should always be allowed - lldb::offset_t offset = 0; - - if (data.GetPointer(&offset) != 0) - { - error.SetErrorString("unable to modify dynamic value, use 'expression' command"); - return false; - } - } - - bool ret_val = m_parent->SetData(data, error); - SetNeedsUpdate(); - return ret_val; + bool ret_val = m_parent->SetData(data, error); + SetNeedsUpdate(); + return ret_val; } -void -ValueObjectDynamicValue::SetPreferredDisplayLanguage (lldb::LanguageType lang) -{ - this->ValueObject::SetPreferredDisplayLanguage(lang); - if (m_parent) - m_parent->SetPreferredDisplayLanguage(lang); +void ValueObjectDynamicValue::SetPreferredDisplayLanguage( + lldb::LanguageType lang) { + this->ValueObject::SetPreferredDisplayLanguage(lang); + if (m_parent) + m_parent->SetPreferredDisplayLanguage(lang); } -lldb::LanguageType -ValueObjectDynamicValue::GetPreferredDisplayLanguage () -{ - if (m_preferred_display_language == lldb::eLanguageTypeUnknown) - { - if (m_parent) - return m_parent->GetPreferredDisplayLanguage(); - return lldb::eLanguageTypeUnknown; - } - else - return m_preferred_display_language; +lldb::LanguageType ValueObjectDynamicValue::GetPreferredDisplayLanguage() { + if (m_preferred_display_language == lldb::eLanguageTypeUnknown) { + if (m_parent) + return m_parent->GetPreferredDisplayLanguage(); + return lldb::eLanguageTypeUnknown; + } else + return m_preferred_display_language; } -bool -ValueObjectDynamicValue::IsSyntheticChildrenGenerated () -{ - if (m_parent) - return m_parent->IsSyntheticChildrenGenerated(); - return false; +bool ValueObjectDynamicValue::IsSyntheticChildrenGenerated() { + if (m_parent) + return m_parent->IsSyntheticChildrenGenerated(); + return false; } -void -ValueObjectDynamicValue::SetSyntheticChildrenGenerated (bool b) -{ - if (m_parent) - m_parent->SetSyntheticChildrenGenerated(b); - this->ValueObject::SetSyntheticChildrenGenerated(b); +void ValueObjectDynamicValue::SetSyntheticChildrenGenerated(bool b) { + if (m_parent) + m_parent->SetSyntheticChildrenGenerated(b); + this->ValueObject::SetSyntheticChildrenGenerated(b); } -bool -ValueObjectDynamicValue::GetDeclaration (Declaration &decl) -{ - if (m_parent) - return m_parent->GetDeclaration(decl); +bool ValueObjectDynamicValue::GetDeclaration(Declaration &decl) { + if (m_parent) + return m_parent->GetDeclaration(decl); - return ValueObject::GetDeclaration(decl); + return ValueObject::GetDeclaration(decl); } -uint64_t -ValueObjectDynamicValue::GetLanguageFlags () -{ - if (m_parent) - return m_parent->GetLanguageFlags(); - return this->ValueObject::GetLanguageFlags(); +uint64_t ValueObjectDynamicValue::GetLanguageFlags() { + if (m_parent) + return m_parent->GetLanguageFlags(); + return this->ValueObject::GetLanguageFlags(); } -void -ValueObjectDynamicValue::SetLanguageFlags (uint64_t flags) -{ - if (m_parent) - m_parent->SetLanguageFlags(flags); - else - this->ValueObject::SetLanguageFlags(flags); +void ValueObjectDynamicValue::SetLanguageFlags(uint64_t flags) { + if (m_parent) + m_parent->SetLanguageFlags(flags); + else + this->ValueObject::SetLanguageFlags(flags); } diff --git a/source/Core/ValueObjectList.cpp b/source/Core/ValueObjectList.cpp index 180d4a0eaf12..7eae49744413 100644 --- a/source/Core/ValueObjectList.cpp +++ b/source/Core/ValueObjectList.cpp @@ -22,145 +22,101 @@ using namespace lldb; using namespace lldb_private; -ValueObjectList::ValueObjectList () : - m_value_objects() -{ -} +ValueObjectList::ValueObjectList() : m_value_objects() {} -ValueObjectList::ValueObjectList (const ValueObjectList &rhs) : - m_value_objects(rhs.m_value_objects) -{ -} +ValueObjectList::ValueObjectList(const ValueObjectList &rhs) + : m_value_objects(rhs.m_value_objects) {} +ValueObjectList::~ValueObjectList() {} -ValueObjectList::~ValueObjectList () -{ +const ValueObjectList &ValueObjectList::operator=(const ValueObjectList &rhs) { + if (this != &rhs) + m_value_objects = rhs.m_value_objects; + return *this; } -const ValueObjectList & -ValueObjectList::operator = (const ValueObjectList &rhs) -{ - if (this != &rhs) - m_value_objects = rhs.m_value_objects; - return *this; +void ValueObjectList::Append(const ValueObjectSP &val_obj_sp) { + m_value_objects.push_back(val_obj_sp); } -void -ValueObjectList::Append (const ValueObjectSP &val_obj_sp) -{ - m_value_objects.push_back(val_obj_sp); +void ValueObjectList::Append(const ValueObjectList &valobj_list) { + std::copy(valobj_list.m_value_objects.begin(), // source begin + valobj_list.m_value_objects.end(), // source end + back_inserter(m_value_objects)); // destination } -void -ValueObjectList::Append (const ValueObjectList &valobj_list) -{ - std::copy(valobj_list.m_value_objects.begin(), // source begin - valobj_list.m_value_objects.end(), // source end - back_inserter(m_value_objects)); // destination - -} +size_t ValueObjectList::GetSize() const { return m_value_objects.size(); } +void ValueObjectList::Resize(size_t size) { m_value_objects.resize(size); } -size_t -ValueObjectList::GetSize() const -{ - return m_value_objects.size(); +lldb::ValueObjectSP ValueObjectList::GetValueObjectAtIndex(size_t idx) { + lldb::ValueObjectSP valobj_sp; + if (idx < m_value_objects.size()) + valobj_sp = m_value_objects[idx]; + return valobj_sp; } -void -ValueObjectList::Resize (size_t size) -{ - m_value_objects.resize (size); +lldb::ValueObjectSP ValueObjectList::RemoveValueObjectAtIndex(size_t idx) { + lldb::ValueObjectSP valobj_sp; + if (idx < m_value_objects.size()) { + valobj_sp = m_value_objects[idx]; + m_value_objects.erase(m_value_objects.begin() + idx); + } + return valobj_sp; } -lldb::ValueObjectSP -ValueObjectList::GetValueObjectAtIndex (size_t idx) -{ - lldb::ValueObjectSP valobj_sp; - if (idx < m_value_objects.size()) - valobj_sp = m_value_objects[idx]; - return valobj_sp; +void ValueObjectList::SetValueObjectAtIndex(size_t idx, + const ValueObjectSP &valobj_sp) { + if (idx >= m_value_objects.size()) + m_value_objects.resize(idx + 1); + m_value_objects[idx] = valobj_sp; } -lldb::ValueObjectSP -ValueObjectList::RemoveValueObjectAtIndex (size_t idx) -{ - lldb::ValueObjectSP valobj_sp; - if (idx < m_value_objects.size()) - { - valobj_sp = m_value_objects[idx]; - m_value_objects.erase (m_value_objects.begin() + idx); +ValueObjectSP ValueObjectList::FindValueObjectByValueName(const char *name) { + ConstString name_const_str(name); + ValueObjectSP val_obj_sp; + collection::iterator pos, end = m_value_objects.end(); + for (pos = m_value_objects.begin(); pos != end; ++pos) { + ValueObject *valobj = (*pos).get(); + if (valobj && valobj->GetName() == name_const_str) { + val_obj_sp = *pos; + break; } - return valobj_sp; + } + return val_obj_sp; } -void -ValueObjectList::SetValueObjectAtIndex (size_t idx, const ValueObjectSP &valobj_sp) -{ - if (idx >= m_value_objects.size()) - m_value_objects.resize (idx + 1); - m_value_objects[idx] = valobj_sp; -} - -ValueObjectSP -ValueObjectList::FindValueObjectByValueName (const char *name) -{ - ConstString name_const_str(name); - ValueObjectSP val_obj_sp; - collection::iterator pos, end = m_value_objects.end(); - for (pos = m_value_objects.begin(); pos != end; ++pos) - { - ValueObject *valobj = (*pos).get(); - if (valobj && valobj->GetName() == name_const_str) - { - val_obj_sp = *pos; - break; - } +ValueObjectSP ValueObjectList::FindValueObjectByUID(lldb::user_id_t uid) { + ValueObjectSP valobj_sp; + collection::iterator pos, end = m_value_objects.end(); + + for (pos = m_value_objects.begin(); pos != end; ++pos) { + // Watch out for NULL objects in our list as the list + // might get resized to a specific size and lazily filled in + ValueObject *valobj = (*pos).get(); + if (valobj && valobj->GetID() == uid) { + valobj_sp = *pos; + break; } - return val_obj_sp; + } + return valobj_sp; } ValueObjectSP -ValueObjectList::FindValueObjectByUID (lldb::user_id_t uid) -{ - ValueObjectSP valobj_sp; - collection::iterator pos, end = m_value_objects.end(); - - for (pos = m_value_objects.begin(); pos != end; ++pos) - { - // Watch out for NULL objects in our list as the list - // might get resized to a specific size and lazily filled in - ValueObject *valobj = (*pos).get(); - if (valobj && valobj->GetID() == uid) - { - valobj_sp = *pos; - break; - } - } - return valobj_sp; -} - - -ValueObjectSP -ValueObjectList::FindValueObjectByPointer (ValueObject *find_valobj) -{ - ValueObjectSP valobj_sp; - collection::iterator pos, end = m_value_objects.end(); - - for (pos = m_value_objects.begin(); pos != end; ++pos) - { - ValueObject *valobj = (*pos).get(); - if (valobj && valobj == find_valobj) - { - valobj_sp = *pos; - break; - } +ValueObjectList::FindValueObjectByPointer(ValueObject *find_valobj) { + ValueObjectSP valobj_sp; + collection::iterator pos, end = m_value_objects.end(); + + for (pos = m_value_objects.begin(); pos != end; ++pos) { + ValueObject *valobj = (*pos).get(); + if (valobj && valobj == find_valobj) { + valobj_sp = *pos; + break; } - return valobj_sp; + } + return valobj_sp; } -void -ValueObjectList::Swap (ValueObjectList &value_object_list) -{ - m_value_objects.swap (value_object_list.m_value_objects); +void ValueObjectList::Swap(ValueObjectList &value_object_list) { + m_value_objects.swap(value_object_list.m_value_objects); } diff --git a/source/Core/ValueObjectMemory.cpp b/source/Core/ValueObjectMemory.cpp index b989710c95d5..86747b84522b 100644 --- a/source/Core/ValueObjectMemory.cpp +++ b/source/Core/ValueObjectMemory.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - #include "lldb/Core/ValueObjectMemory.h" // C Includes @@ -15,9 +14,9 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/Module.h" -#include "lldb/Core/ValueObjectList.h" #include "lldb/Core/Value.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectList.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolContext.h" @@ -33,256 +32,201 @@ using namespace lldb; using namespace lldb_private; -ValueObjectSP -ValueObjectMemory::Create (ExecutionContextScope *exe_scope, - const char *name, - const Address &address, - lldb::TypeSP &type_sp) -{ - return (new ValueObjectMemory (exe_scope, name, address, type_sp))->GetSP(); +ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope, + llvm::StringRef name, + const Address &address, + lldb::TypeSP &type_sp) { + return (new ValueObjectMemory(exe_scope, name, address, type_sp))->GetSP(); } -ValueObjectSP -ValueObjectMemory::Create (ExecutionContextScope *exe_scope, - const char *name, - const Address &address, - const CompilerType &ast_type) -{ - return (new ValueObjectMemory (exe_scope, name, address, ast_type))->GetSP(); +ValueObjectSP ValueObjectMemory::Create(ExecutionContextScope *exe_scope, + llvm::StringRef name, + const Address &address, + const CompilerType &ast_type) { + return (new ValueObjectMemory(exe_scope, name, address, ast_type))->GetSP(); } -ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope, - const char *name, - const Address &address, - lldb::TypeSP &type_sp) : - ValueObject(exe_scope), - m_address (address), - m_type_sp(type_sp), - m_compiler_type() -{ - // Do not attempt to construct one of these objects with no variable! - assert (m_type_sp.get() != NULL); - SetName (ConstString(name)); - m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); - TargetSP target_sp (GetTargetSP()); - lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); - if (load_address != LLDB_INVALID_ADDRESS) - { - m_value.SetValueType(Value::eValueTypeLoadAddress); - m_value.GetScalar() = load_address; - } - else - { - lldb::addr_t file_address = m_address.GetFileAddress(); - if (file_address != LLDB_INVALID_ADDRESS) - { - m_value.SetValueType(Value::eValueTypeFileAddress); - m_value.GetScalar() = file_address; - } - else - { - m_value.GetScalar() = m_address.GetOffset(); - m_value.SetValueType (Value::eValueTypeScalar); - } +ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope, + llvm::StringRef name, + const Address &address, + lldb::TypeSP &type_sp) + : ValueObject(exe_scope), m_address(address), m_type_sp(type_sp), + m_compiler_type() { + // Do not attempt to construct one of these objects with no variable! + assert(m_type_sp.get() != NULL); + SetName(ConstString(name)); + m_value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); + TargetSP target_sp(GetTargetSP()); + lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); + if (load_address != LLDB_INVALID_ADDRESS) { + m_value.SetValueType(Value::eValueTypeLoadAddress); + m_value.GetScalar() = load_address; + } else { + lldb::addr_t file_address = m_address.GetFileAddress(); + if (file_address != LLDB_INVALID_ADDRESS) { + m_value.SetValueType(Value::eValueTypeFileAddress); + m_value.GetScalar() = file_address; + } else { + m_value.GetScalar() = m_address.GetOffset(); + m_value.SetValueType(Value::eValueTypeScalar); } + } } -ValueObjectMemory::ValueObjectMemory (ExecutionContextScope *exe_scope, - const char *name, - const Address &address, - const CompilerType &ast_type) : - ValueObject(exe_scope), - m_address (address), - m_type_sp(), - m_compiler_type(ast_type) -{ - // Do not attempt to construct one of these objects with no variable! - assert (m_compiler_type.GetTypeSystem()); - assert (m_compiler_type.GetOpaqueQualType()); - - TargetSP target_sp (GetTargetSP()); - - SetName (ConstString(name)); -// m_value.SetContext(Value::eContextTypeClangType, m_compiler_type.GetOpaqueQualType()); - m_value.SetCompilerType(m_compiler_type); - lldb::addr_t load_address = m_address.GetLoadAddress (target_sp.get()); - if (load_address != LLDB_INVALID_ADDRESS) - { - m_value.SetValueType(Value::eValueTypeLoadAddress); - m_value.GetScalar() = load_address; - } - else - { - lldb::addr_t file_address = m_address.GetFileAddress(); - if (file_address != LLDB_INVALID_ADDRESS) - { - m_value.SetValueType(Value::eValueTypeFileAddress); - m_value.GetScalar() = file_address; - } - else - { - m_value.GetScalar() = m_address.GetOffset(); - m_value.SetValueType (Value::eValueTypeScalar); - } +ValueObjectMemory::ValueObjectMemory(ExecutionContextScope *exe_scope, + llvm::StringRef name, + const Address &address, + const CompilerType &ast_type) + : ValueObject(exe_scope), m_address(address), m_type_sp(), + m_compiler_type(ast_type) { + // Do not attempt to construct one of these objects with no variable! + assert(m_compiler_type.GetTypeSystem()); + assert(m_compiler_type.GetOpaqueQualType()); + + TargetSP target_sp(GetTargetSP()); + + SetName(ConstString(name)); + // m_value.SetContext(Value::eContextTypeClangType, + // m_compiler_type.GetOpaqueQualType()); + m_value.SetCompilerType(m_compiler_type); + lldb::addr_t load_address = m_address.GetLoadAddress(target_sp.get()); + if (load_address != LLDB_INVALID_ADDRESS) { + m_value.SetValueType(Value::eValueTypeLoadAddress); + m_value.GetScalar() = load_address; + } else { + lldb::addr_t file_address = m_address.GetFileAddress(); + if (file_address != LLDB_INVALID_ADDRESS) { + m_value.SetValueType(Value::eValueTypeFileAddress); + m_value.GetScalar() = file_address; + } else { + m_value.GetScalar() = m_address.GetOffset(); + m_value.SetValueType(Value::eValueTypeScalar); } + } } -ValueObjectMemory::~ValueObjectMemory() -{ -} +ValueObjectMemory::~ValueObjectMemory() {} -CompilerType -ValueObjectMemory::GetCompilerTypeImpl () -{ - if (m_type_sp) - return m_type_sp->GetForwardCompilerType (); - return m_compiler_type; +CompilerType ValueObjectMemory::GetCompilerTypeImpl() { + if (m_type_sp) + return m_type_sp->GetForwardCompilerType(); + return m_compiler_type; } -ConstString -ValueObjectMemory::GetTypeName() -{ - if (m_type_sp) - return m_type_sp->GetName(); - return m_compiler_type.GetConstTypeName(); +ConstString ValueObjectMemory::GetTypeName() { + if (m_type_sp) + return m_type_sp->GetName(); + return m_compiler_type.GetConstTypeName(); } -ConstString -ValueObjectMemory::GetDisplayTypeName() -{ - if (m_type_sp) - return m_type_sp->GetForwardCompilerType ().GetDisplayTypeName(); - return m_compiler_type.GetDisplayTypeName(); +ConstString ValueObjectMemory::GetDisplayTypeName() { + if (m_type_sp) + return m_type_sp->GetForwardCompilerType().GetDisplayTypeName(); + return m_compiler_type.GetDisplayTypeName(); } -size_t -ValueObjectMemory::CalculateNumChildren(uint32_t max) -{ - if (m_type_sp) - { - auto child_count = m_type_sp->GetNumChildren(true); - return child_count <= max ? child_count : max; - } - - const bool omit_empty_base_classes = true; - auto child_count = m_compiler_type.GetNumChildren (omit_empty_base_classes); +size_t ValueObjectMemory::CalculateNumChildren(uint32_t max) { + if (m_type_sp) { + auto child_count = m_type_sp->GetNumChildren(true); return child_count <= max ? child_count : max; -} + } -uint64_t -ValueObjectMemory::GetByteSize() -{ - if (m_type_sp) - return m_type_sp->GetByteSize(); - return m_compiler_type.GetByteSize (nullptr); + const bool omit_empty_base_classes = true; + auto child_count = m_compiler_type.GetNumChildren(omit_empty_base_classes); + return child_count <= max ? child_count : max; } -lldb::ValueType -ValueObjectMemory::GetValueType() const -{ - // RETHINK: Should this be inherited from somewhere? - return lldb::eValueTypeVariableGlobal; +uint64_t ValueObjectMemory::GetByteSize() { + if (m_type_sp) + return m_type_sp->GetByteSize(); + return m_compiler_type.GetByteSize(nullptr); } -bool -ValueObjectMemory::UpdateValue () -{ - SetValueIsValid (false); - m_error.Clear(); - - ExecutionContext exe_ctx (GetExecutionContextRef()); - - Target *target = exe_ctx.GetTargetPtr(); - if (target) - { - m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); - m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); - } +lldb::ValueType ValueObjectMemory::GetValueType() const { + // RETHINK: Should this be inherited from somewhere? + return lldb::eValueTypeVariableGlobal; +} - Value old_value(m_value); - if (m_address.IsValid()) - { - Value::ValueType value_type = m_value.GetValueType(); - - switch (value_type) - { - default: - assert(!"Unhandled expression result value kind..."); - break; - - case Value::eValueTypeScalar: - // The variable value is in the Scalar value inside the m_value. - // We can point our m_data right to it. - m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); - break; - - case Value::eValueTypeFileAddress: - case Value::eValueTypeLoadAddress: - case Value::eValueTypeHostAddress: - // The DWARF expression result was an address in the inferior - // process. If this variable is an aggregate type, we just need - // the address as the main value as all child variable objects - // will rely upon this location and add an offset and then read - // their own values as needed. If this variable is a simple - // type, we read all data for it into m_data. - // Make sure this type has a value before we try and read it - - // If we have a file address, convert it to a load address if we can. - if (value_type == Value::eValueTypeFileAddress && exe_ctx.GetProcessPtr()) - { - lldb::addr_t load_addr = m_address.GetLoadAddress(target); - if (load_addr != LLDB_INVALID_ADDRESS) - { - m_value.SetValueType(Value::eValueTypeLoadAddress); - m_value.GetScalar() = load_addr; - } - } - - if (!CanProvideValue()) - { - // this value object represents an aggregate type whose - // children have values, but this object does not. So we - // say we are changed if our location has changed. - SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar()); - } - else - { - // Copy the Value and set the context to use our Variable - // so it can extract read its value into m_data appropriately - Value value(m_value); - if (m_type_sp) - value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); - else - { - //value.SetContext(Value::eContextTypeClangType, m_compiler_type.GetOpaqueQualType()); - value.SetCompilerType(m_compiler_type); - } - - m_error = value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); - } - break; +bool ValueObjectMemory::UpdateValue() { + SetValueIsValid(false); + m_error.Clear(); + + ExecutionContext exe_ctx(GetExecutionContextRef()); + + Target *target = exe_ctx.GetTargetPtr(); + if (target) { + m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); + m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); + } + + Value old_value(m_value); + if (m_address.IsValid()) { + Value::ValueType value_type = m_value.GetValueType(); + + switch (value_type) { + default: + assert(!"Unhandled expression result value kind..."); + break; + + case Value::eValueTypeScalar: + // The variable value is in the Scalar value inside the m_value. + // We can point our m_data right to it. + m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + break; + + case Value::eValueTypeFileAddress: + case Value::eValueTypeLoadAddress: + case Value::eValueTypeHostAddress: + // The DWARF expression result was an address in the inferior + // process. If this variable is an aggregate type, we just need + // the address as the main value as all child variable objects + // will rely upon this location and add an offset and then read + // their own values as needed. If this variable is a simple + // type, we read all data for it into m_data. + // Make sure this type has a value before we try and read it + + // If we have a file address, convert it to a load address if we can. + if (value_type == Value::eValueTypeFileAddress && + exe_ctx.GetProcessPtr()) { + lldb::addr_t load_addr = m_address.GetLoadAddress(target); + if (load_addr != LLDB_INVALID_ADDRESS) { + m_value.SetValueType(Value::eValueTypeLoadAddress); + m_value.GetScalar() = load_addr; + } + } + + if (!CanProvideValue()) { + // this value object represents an aggregate type whose + // children have values, but this object does not. So we + // say we are changed if our location has changed. + SetValueDidChange(value_type != old_value.GetValueType() || + m_value.GetScalar() != old_value.GetScalar()); + } else { + // Copy the Value and set the context to use our Variable + // so it can extract read its value into m_data appropriately + Value value(m_value); + if (m_type_sp) + value.SetContext(Value::eContextTypeLLDBType, m_type_sp.get()); + else { + // value.SetContext(Value::eContextTypeClangType, + // m_compiler_type.GetOpaqueQualType()); + value.SetCompilerType(m_compiler_type); } - SetValueIsValid (m_error.Success()); + m_error = value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + } + break; } - return m_error.Success(); -} - - -bool -ValueObjectMemory::IsInScope () -{ - // FIXME: Maybe try to read the memory address, and if that works, then - // we are in scope? - return true; + SetValueIsValid(m_error.Success()); + } + return m_error.Success(); } - -lldb::ModuleSP -ValueObjectMemory::GetModule() -{ - return m_address.GetModule(); +bool ValueObjectMemory::IsInScope() { + // FIXME: Maybe try to read the memory address, and if that works, then + // we are in scope? + return true; } - +lldb::ModuleSP ValueObjectMemory::GetModule() { return m_address.GetModule(); } diff --git a/source/Core/ValueObjectRegister.cpp b/source/Core/ValueObjectRegister.cpp index c7845cd03207..80e00e4007c4 100644 --- a/source/Core/ValueObjectRegister.cpp +++ b/source/Core/ValueObjectRegister.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - #include "lldb/Core/ValueObjectRegister.h" // C Includes @@ -15,8 +14,8 @@ // Other libraries and framework includes // Project includes #include "lldb/Core/Module.h" -#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" @@ -29,416 +28,322 @@ using namespace lldb_private; #pragma mark ValueObjectRegisterContext -ValueObjectRegisterContext::ValueObjectRegisterContext (ValueObject &parent, RegisterContextSP ®_ctx) : - ValueObject (parent), - m_reg_ctx_sp (reg_ctx) -{ - assert (reg_ctx); - m_name.SetCString("Registers"); - SetValueIsValid (true); +ValueObjectRegisterContext::ValueObjectRegisterContext( + ValueObject &parent, RegisterContextSP ®_ctx) + : ValueObject(parent), m_reg_ctx_sp(reg_ctx) { + assert(reg_ctx); + m_name.SetCString("Registers"); + SetValueIsValid(true); } -ValueObjectRegisterContext::~ValueObjectRegisterContext() -{ -} +ValueObjectRegisterContext::~ValueObjectRegisterContext() {} -CompilerType -ValueObjectRegisterContext::GetCompilerTypeImpl () -{ - return CompilerType(); +CompilerType ValueObjectRegisterContext::GetCompilerTypeImpl() { + return CompilerType(); } -ConstString -ValueObjectRegisterContext::GetTypeName() -{ - return ConstString(); -} +ConstString ValueObjectRegisterContext::GetTypeName() { return ConstString(); } -ConstString -ValueObjectRegisterContext::GetDisplayTypeName() -{ - return ConstString(); +ConstString ValueObjectRegisterContext::GetDisplayTypeName() { + return ConstString(); } -ConstString -ValueObjectRegisterContext::GetQualifiedTypeName() -{ - return ConstString(); +ConstString ValueObjectRegisterContext::GetQualifiedTypeName() { + return ConstString(); } -size_t -ValueObjectRegisterContext::CalculateNumChildren(uint32_t max) -{ - auto reg_set_count = m_reg_ctx_sp->GetRegisterSetCount(); - return reg_set_count <= max ? reg_set_count : max; +size_t ValueObjectRegisterContext::CalculateNumChildren(uint32_t max) { + auto reg_set_count = m_reg_ctx_sp->GetRegisterSetCount(); + return reg_set_count <= max ? reg_set_count : max; } -uint64_t -ValueObjectRegisterContext::GetByteSize() -{ - return 0; -} +uint64_t ValueObjectRegisterContext::GetByteSize() { return 0; } -bool -ValueObjectRegisterContext::UpdateValue () -{ - m_error.Clear(); - ExecutionContext exe_ctx(GetExecutionContextRef()); - StackFrame *frame = exe_ctx.GetFramePtr(); - if (frame) - m_reg_ctx_sp = frame->GetRegisterContext(); - else - m_reg_ctx_sp.reset(); +bool ValueObjectRegisterContext::UpdateValue() { + m_error.Clear(); + ExecutionContext exe_ctx(GetExecutionContextRef()); + StackFrame *frame = exe_ctx.GetFramePtr(); + if (frame) + m_reg_ctx_sp = frame->GetRegisterContext(); + else + m_reg_ctx_sp.reset(); - if (m_reg_ctx_sp.get() == NULL) - { - SetValueIsValid (false); - m_error.SetErrorToGenericError(); - } - else - SetValueIsValid (true); - - return m_error.Success(); -} + if (m_reg_ctx_sp.get() == NULL) { + SetValueIsValid(false); + m_error.SetErrorToGenericError(); + } else + SetValueIsValid(true); -ValueObject * -ValueObjectRegisterContext::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index) -{ - ValueObject *new_valobj = NULL; - - const size_t num_children = GetNumChildren(); - if (idx < num_children) - { - ExecutionContext exe_ctx(GetExecutionContextRef()); - new_valobj = new ValueObjectRegisterSet(exe_ctx.GetBestExecutionContextScope(), m_reg_ctx_sp, idx); - } - - return new_valobj; + return m_error.Success(); } +ValueObject *ValueObjectRegisterContext::CreateChildAtIndex( + size_t idx, bool synthetic_array_member, int32_t synthetic_index) { + ValueObject *new_valobj = NULL; + + const size_t num_children = GetNumChildren(); + if (idx < num_children) { + ExecutionContext exe_ctx(GetExecutionContextRef()); + new_valobj = new ValueObjectRegisterSet( + exe_ctx.GetBestExecutionContextScope(), m_reg_ctx_sp, idx); + } + + return new_valobj; +} #pragma mark - #pragma mark ValueObjectRegisterSet ValueObjectSP -ValueObjectRegisterSet::Create (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx_sp, uint32_t set_idx) -{ - return (new ValueObjectRegisterSet (exe_scope, reg_ctx_sp, set_idx))->GetSP(); +ValueObjectRegisterSet::Create(ExecutionContextScope *exe_scope, + lldb::RegisterContextSP ®_ctx_sp, + uint32_t set_idx) { + return (new ValueObjectRegisterSet(exe_scope, reg_ctx_sp, set_idx))->GetSP(); } - -ValueObjectRegisterSet::ValueObjectRegisterSet (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx, uint32_t reg_set_idx) : - ValueObject (exe_scope), - m_reg_ctx_sp (reg_ctx), - m_reg_set (NULL), - m_reg_set_idx (reg_set_idx) -{ - assert (reg_ctx); - m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx); - if (m_reg_set) - { - m_name.SetCString (m_reg_set->name); - } +ValueObjectRegisterSet::ValueObjectRegisterSet(ExecutionContextScope *exe_scope, + lldb::RegisterContextSP ®_ctx, + uint32_t reg_set_idx) + : ValueObject(exe_scope), m_reg_ctx_sp(reg_ctx), m_reg_set(NULL), + m_reg_set_idx(reg_set_idx) { + assert(reg_ctx); + m_reg_set = reg_ctx->GetRegisterSet(m_reg_set_idx); + if (m_reg_set) { + m_name.SetCString(m_reg_set->name); + } } -ValueObjectRegisterSet::~ValueObjectRegisterSet() -{ -} +ValueObjectRegisterSet::~ValueObjectRegisterSet() {} -CompilerType -ValueObjectRegisterSet::GetCompilerTypeImpl () -{ - return CompilerType(); +CompilerType ValueObjectRegisterSet::GetCompilerTypeImpl() { + return CompilerType(); } -ConstString -ValueObjectRegisterSet::GetTypeName() -{ - return ConstString(); -} +ConstString ValueObjectRegisterSet::GetTypeName() { return ConstString(); } -ConstString -ValueObjectRegisterSet::GetQualifiedTypeName() -{ - return ConstString(); +ConstString ValueObjectRegisterSet::GetQualifiedTypeName() { + return ConstString(); } -size_t -ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) -{ - const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx); - if (reg_set) - { - auto reg_count = reg_set->num_registers; - return reg_count <= max ? reg_count : max; - } - return 0; +size_t ValueObjectRegisterSet::CalculateNumChildren(uint32_t max) { + const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx); + if (reg_set) { + auto reg_count = reg_set->num_registers; + return reg_count <= max ? reg_count : max; + } + return 0; } -uint64_t -ValueObjectRegisterSet::GetByteSize() -{ - return 0; -} +uint64_t ValueObjectRegisterSet::GetByteSize() { return 0; } -bool -ValueObjectRegisterSet::UpdateValue () -{ - m_error.Clear(); - SetValueDidChange (false); - ExecutionContext exe_ctx(GetExecutionContextRef()); - StackFrame *frame = exe_ctx.GetFramePtr(); - if (frame == NULL) +bool ValueObjectRegisterSet::UpdateValue() { + m_error.Clear(); + SetValueDidChange(false); + ExecutionContext exe_ctx(GetExecutionContextRef()); + StackFrame *frame = exe_ctx.GetFramePtr(); + if (frame == NULL) + m_reg_ctx_sp.reset(); + else { + m_reg_ctx_sp = frame->GetRegisterContext(); + if (m_reg_ctx_sp) { + const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet(m_reg_set_idx); + if (reg_set == NULL) m_reg_ctx_sp.reset(); - else - { - m_reg_ctx_sp = frame->GetRegisterContext (); - if (m_reg_ctx_sp) - { - const RegisterSet *reg_set = m_reg_ctx_sp->GetRegisterSet (m_reg_set_idx); - if (reg_set == NULL) - m_reg_ctx_sp.reset(); - else if (m_reg_set != reg_set) - { - SetValueDidChange (true); - m_name.SetCString(reg_set->name); - } - } - } - if (m_reg_ctx_sp) - { - SetValueIsValid (true); - } - else - { - SetValueIsValid (false); - m_error.SetErrorToGenericError (); - m_children.Clear(); - } - return m_error.Success(); -} - - -ValueObject * -ValueObjectRegisterSet::CreateChildAtIndex (size_t idx, bool synthetic_array_member, int32_t synthetic_index) -{ - ValueObject *valobj = NULL; - if (m_reg_ctx_sp && m_reg_set) - { - const size_t num_children = GetNumChildren(); - if (idx < num_children) - valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, m_reg_set->registers[idx]); + else if (m_reg_set != reg_set) { + SetValueDidChange(true); + m_name.SetCString(reg_set->name); + } } - return valobj; + } + if (m_reg_ctx_sp) { + SetValueIsValid(true); + } else { + SetValueIsValid(false); + m_error.SetErrorToGenericError(); + m_children.Clear(); + } + return m_error.Success(); +} + +ValueObject *ValueObjectRegisterSet::CreateChildAtIndex( + size_t idx, bool synthetic_array_member, int32_t synthetic_index) { + ValueObject *valobj = NULL; + if (m_reg_ctx_sp && m_reg_set) { + const size_t num_children = GetNumChildren(); + if (idx < num_children) + valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, + m_reg_set->registers[idx]); + } + return valobj; } lldb::ValueObjectSP -ValueObjectRegisterSet::GetChildMemberWithName (const ConstString &name, bool can_create) -{ - ValueObject *valobj = NULL; - if (m_reg_ctx_sp && m_reg_set) - { - const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName (name.AsCString()); - if (reg_info != NULL) - valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info->kinds[eRegisterKindLLDB]); - } - if (valobj) - return valobj->GetSP(); - else - return ValueObjectSP(); +ValueObjectRegisterSet::GetChildMemberWithName(const ConstString &name, + bool can_create) { + ValueObject *valobj = NULL; + if (m_reg_ctx_sp && m_reg_set) { + const RegisterInfo *reg_info = + m_reg_ctx_sp->GetRegisterInfoByName(name.AsCString()); + if (reg_info != NULL) + valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, + reg_info->kinds[eRegisterKindLLDB]); + } + if (valobj) + return valobj->GetSP(); + else + return ValueObjectSP(); } size_t -ValueObjectRegisterSet::GetIndexOfChildWithName (const ConstString &name) -{ - if (m_reg_ctx_sp && m_reg_set) - { - const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName (name.AsCString()); - if (reg_info != NULL) - return reg_info->kinds[eRegisterKindLLDB]; - } - return UINT32_MAX; +ValueObjectRegisterSet::GetIndexOfChildWithName(const ConstString &name) { + if (m_reg_ctx_sp && m_reg_set) { + const RegisterInfo *reg_info = + m_reg_ctx_sp->GetRegisterInfoByName(name.AsCString()); + if (reg_info != NULL) + return reg_info->kinds[eRegisterKindLLDB]; + } + return UINT32_MAX; } #pragma mark - #pragma mark ValueObjectRegister -void -ValueObjectRegister::ConstructObject (uint32_t reg_num) -{ - const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoAtIndex (reg_num); - if (reg_info) - { - m_reg_info = *reg_info; - if (reg_info->name) - m_name.SetCString(reg_info->name); - else if (reg_info->alt_name) - m_name.SetCString(reg_info->alt_name); - } -} - -ValueObjectRegister::ValueObjectRegister (ValueObject &parent, lldb::RegisterContextSP ®_ctx_sp, uint32_t reg_num) : - ValueObject (parent), - m_reg_ctx_sp (reg_ctx_sp), - m_reg_info (), - m_reg_value (), - m_type_name (), - m_compiler_type () -{ - assert (reg_ctx_sp.get()); - ConstructObject(reg_num); -} - -ValueObjectSP -ValueObjectRegister::Create (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx_sp, uint32_t reg_num) -{ - return (new ValueObjectRegister (exe_scope, reg_ctx_sp, reg_num))->GetSP(); -} - -ValueObjectRegister::ValueObjectRegister (ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx, uint32_t reg_num) : - ValueObject (exe_scope), - m_reg_ctx_sp (reg_ctx), - m_reg_info (), - m_reg_value (), - m_type_name (), - m_compiler_type () -{ - assert (reg_ctx); - ConstructObject(reg_num); -} - -ValueObjectRegister::~ValueObjectRegister() -{ +void ValueObjectRegister::ConstructObject(uint32_t reg_num) { + const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoAtIndex(reg_num); + if (reg_info) { + m_reg_info = *reg_info; + if (reg_info->name) + m_name.SetCString(reg_info->name); + else if (reg_info->alt_name) + m_name.SetCString(reg_info->alt_name); + } } -CompilerType -ValueObjectRegister::GetCompilerTypeImpl () -{ - if (!m_compiler_type.IsValid()) - { - ExecutionContext exe_ctx (GetExecutionContextRef()); - Target *target = exe_ctx.GetTargetPtr(); - if (target) - { - Module *exe_module = target->GetExecutableModulePointer(); - if (exe_module) - { - TypeSystem *type_system = exe_module->GetTypeSystemForLanguage (eLanguageTypeC); - if (type_system) - m_compiler_type = type_system->GetBuiltinTypeForEncodingAndBitSize (m_reg_info.encoding, - m_reg_info.byte_size * 8); - } - } - } - return m_compiler_type; +ValueObjectRegister::ValueObjectRegister(ValueObject &parent, + lldb::RegisterContextSP ®_ctx_sp, + uint32_t reg_num) + : ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(), + m_reg_value(), m_type_name(), m_compiler_type() { + assert(reg_ctx_sp.get()); + ConstructObject(reg_num); } -ConstString -ValueObjectRegister::GetTypeName() -{ - if (m_type_name.IsEmpty()) - m_type_name = GetCompilerType().GetConstTypeName (); - return m_type_name; +ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope, + lldb::RegisterContextSP ®_ctx_sp, + uint32_t reg_num) { + return (new ValueObjectRegister(exe_scope, reg_ctx_sp, reg_num))->GetSP(); } -size_t -ValueObjectRegister::CalculateNumChildren(uint32_t max) -{ - auto children_count = GetCompilerType().GetNumChildren (true); - return children_count <= max ? children_count : max; +ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope, + lldb::RegisterContextSP ®_ctx, + uint32_t reg_num) + : ValueObject(exe_scope), m_reg_ctx_sp(reg_ctx), m_reg_info(), + m_reg_value(), m_type_name(), m_compiler_type() { + assert(reg_ctx); + ConstructObject(reg_num); } -uint64_t -ValueObjectRegister::GetByteSize() -{ - return m_reg_info.byte_size; -} +ValueObjectRegister::~ValueObjectRegister() {} -bool -ValueObjectRegister::UpdateValue () -{ - m_error.Clear(); +CompilerType ValueObjectRegister::GetCompilerTypeImpl() { + if (!m_compiler_type.IsValid()) { ExecutionContext exe_ctx(GetExecutionContextRef()); - StackFrame *frame = exe_ctx.GetFramePtr(); - if (frame == NULL) - { - m_reg_ctx_sp.reset(); - m_reg_value.Clear(); + Target *target = exe_ctx.GetTargetPtr(); + if (target) { + Module *exe_module = target->GetExecutableModulePointer(); + if (exe_module) { + TypeSystem *type_system = + exe_module->GetTypeSystemForLanguage(eLanguageTypeC); + if (type_system) + m_compiler_type = type_system->GetBuiltinTypeForEncodingAndBitSize( + m_reg_info.encoding, m_reg_info.byte_size * 8); + } } - - - if (m_reg_ctx_sp) - { - if (m_reg_ctx_sp->ReadRegister (&m_reg_info, m_reg_value)) - { - if (m_reg_value.GetData (m_data)) - { - Process *process = exe_ctx.GetProcessPtr(); - if (process) - m_data.SetAddressByteSize(process->GetAddressByteSize()); - m_value.SetContext(Value::eContextTypeRegisterInfo, (void *)&m_reg_info); - m_value.SetValueType(Value::eValueTypeHostAddress); - m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); - SetValueIsValid (true); - return true; - } - } + } + return m_compiler_type; +} + +ConstString ValueObjectRegister::GetTypeName() { + if (m_type_name.IsEmpty()) + m_type_name = GetCompilerType().GetConstTypeName(); + return m_type_name; +} + +size_t ValueObjectRegister::CalculateNumChildren(uint32_t max) { + auto children_count = GetCompilerType().GetNumChildren(true); + return children_count <= max ? children_count : max; +} + +uint64_t ValueObjectRegister::GetByteSize() { return m_reg_info.byte_size; } + +bool ValueObjectRegister::UpdateValue() { + m_error.Clear(); + ExecutionContext exe_ctx(GetExecutionContextRef()); + StackFrame *frame = exe_ctx.GetFramePtr(); + if (frame == NULL) { + m_reg_ctx_sp.reset(); + m_reg_value.Clear(); + } + + if (m_reg_ctx_sp) { + RegisterValue m_old_reg_value(m_reg_value); + if (m_reg_ctx_sp->ReadRegister(&m_reg_info, m_reg_value)) { + if (m_reg_value.GetData(m_data)) { + Process *process = exe_ctx.GetProcessPtr(); + if (process) + m_data.SetAddressByteSize(process->GetAddressByteSize()); + m_value.SetContext(Value::eContextTypeRegisterInfo, + (void *)&m_reg_info); + m_value.SetValueType(Value::eValueTypeHostAddress); + m_value.GetScalar() = (uintptr_t)m_data.GetDataStart(); + SetValueIsValid(true); + SetValueDidChange(!(m_old_reg_value == m_reg_value)); + return true; + } } - - SetValueIsValid (false); - m_error.SetErrorToGenericError (); + } + + SetValueIsValid(false); + m_error.SetErrorToGenericError(); + return false; +} + +bool ValueObjectRegister::SetValueFromCString(const char *value_str, + Error &error) { + // The new value will be in the m_data. Copy that into our register value. + error = + m_reg_value.SetValueFromString(&m_reg_info, llvm::StringRef(value_str)); + if (error.Success()) { + if (m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) { + SetNeedsUpdate(); + return true; + } else + return false; + } else return false; } -bool -ValueObjectRegister::SetValueFromCString (const char *value_str, Error& error) -{ - // The new value will be in the m_data. Copy that into our register value. - error = m_reg_value.SetValueFromCString (&m_reg_info, value_str); - if (error.Success()) - { - if (m_reg_ctx_sp->WriteRegister (&m_reg_info, m_reg_value)) - { - SetNeedsUpdate(); - return true; - } - else - return false; - } - else - return false; -} - -bool -ValueObjectRegister::SetData (DataExtractor &data, Error &error) -{ - error = m_reg_value.SetValueFromData(&m_reg_info, data, 0, false); - if (error.Success()) - { - if (m_reg_ctx_sp->WriteRegister (&m_reg_info, m_reg_value)) - { - SetNeedsUpdate(); - return true; - } - else - return false; - } - else - return false; -} - -bool -ValueObjectRegister::ResolveValue (Scalar &scalar) -{ - if (UpdateValueIfNeeded(false)) // make sure that you are up to date before returning anything - return m_reg_value.GetScalarValue(scalar); +bool ValueObjectRegister::SetData(DataExtractor &data, Error &error) { + error = m_reg_value.SetValueFromData(&m_reg_info, data, 0, false); + if (error.Success()) { + if (m_reg_ctx_sp->WriteRegister(&m_reg_info, m_reg_value)) { + SetNeedsUpdate(); + return true; + } else + return false; + } else return false; } -void -ValueObjectRegister::GetExpressionPath (Stream &s, bool qualify_cxx_base_classes, GetExpressionPathFormat epformat) -{ - s.Printf("$%s", m_reg_info.name); +bool ValueObjectRegister::ResolveValue(Scalar &scalar) { + if (UpdateValueIfNeeded( + false)) // make sure that you are up to date before returning anything + return m_reg_value.GetScalarValue(scalar); + return false; } - +void ValueObjectRegister::GetExpressionPath(Stream &s, + bool qualify_cxx_base_classes, + GetExpressionPathFormat epformat) { + s.Printf("$%s", m_reg_info.name); +} diff --git a/source/Core/ValueObjectSyntheticFilter.cpp b/source/Core/ValueObjectSyntheticFilter.cpp index f2f233711b9c..592f1ea56bdf 100644 --- a/source/Core/ValueObjectSyntheticFilter.cpp +++ b/source/Core/ValueObjectSyntheticFilter.cpp @@ -19,441 +19,361 @@ using namespace lldb_private; -class DummySyntheticFrontEnd : public SyntheticChildrenFrontEnd -{ +class DummySyntheticFrontEnd : public SyntheticChildrenFrontEnd { public: - DummySyntheticFrontEnd(ValueObject &backend) : - SyntheticChildrenFrontEnd(backend) - {} - - size_t - CalculateNumChildren() override - { - return m_backend.GetNumChildren(); - } - - lldb::ValueObjectSP - GetChildAtIndex(size_t idx) override - { - return m_backend.GetChildAtIndex(idx, true); - } + DummySyntheticFrontEnd(ValueObject &backend) + : SyntheticChildrenFrontEnd(backend) {} - size_t - GetIndexOfChildWithName(const ConstString &name) override - { - return m_backend.GetIndexOfChildWithName(name); - } - - bool - MightHaveChildren() override - { - return true; - } - - bool - Update() override - { - return false; - } + size_t CalculateNumChildren() override { return m_backend.GetNumChildren(); } + + lldb::ValueObjectSP GetChildAtIndex(size_t idx) override { + return m_backend.GetChildAtIndex(idx, true); + } + + size_t GetIndexOfChildWithName(const ConstString &name) override { + return m_backend.GetIndexOfChildWithName(name); + } + + bool MightHaveChildren() override { return true; } + + bool Update() override { return false; } }; -ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter) : - ValueObject(parent), - m_synth_sp(filter), - m_children_byindex(), - m_name_toindex(), - m_synthetic_children_count(UINT32_MAX), - m_synthetic_children_cache(), - m_parent_type_name(parent.GetTypeName()), - m_might_have_children(eLazyBoolCalculate), - m_provides_value(eLazyBoolCalculate) -{ - SetName(parent.GetName()); - CopyValueData(m_parent); - CreateSynthFilter(); +ValueObjectSynthetic::ValueObjectSynthetic(ValueObject &parent, + lldb::SyntheticChildrenSP filter) + : ValueObject(parent), m_synth_sp(filter), m_children_byindex(), + m_name_toindex(), m_synthetic_children_count(UINT32_MAX), + m_synthetic_children_cache(), m_parent_type_name(parent.GetTypeName()), + m_might_have_children(eLazyBoolCalculate), + m_provides_value(eLazyBoolCalculate) { + SetName(parent.GetName()); + CopyValueData(m_parent); + CreateSynthFilter(); } ValueObjectSynthetic::~ValueObjectSynthetic() = default; -CompilerType -ValueObjectSynthetic::GetCompilerTypeImpl () -{ - return m_parent->GetCompilerType(); +CompilerType ValueObjectSynthetic::GetCompilerTypeImpl() { + return m_parent->GetCompilerType(); } -ConstString -ValueObjectSynthetic::GetTypeName() -{ - return m_parent->GetTypeName(); +ConstString ValueObjectSynthetic::GetTypeName() { + return m_parent->GetTypeName(); } -ConstString -ValueObjectSynthetic::GetQualifiedTypeName() -{ - return m_parent->GetQualifiedTypeName(); +ConstString ValueObjectSynthetic::GetQualifiedTypeName() { + return m_parent->GetQualifiedTypeName(); } -ConstString -ValueObjectSynthetic::GetDisplayTypeName() -{ - if (ConstString synth_name = m_synth_filter_ap->GetSyntheticTypeName()) - return synth_name; +ConstString ValueObjectSynthetic::GetDisplayTypeName() { + if (ConstString synth_name = m_synth_filter_ap->GetSyntheticTypeName()) + return synth_name; - return m_parent->GetDisplayTypeName(); + return m_parent->GetDisplayTypeName(); } -size_t -ValueObjectSynthetic::CalculateNumChildren(uint32_t max) -{ - Log* log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS); - - UpdateValueIfNeeded(); - if (m_synthetic_children_count < UINT32_MAX) - return m_synthetic_children_count <= max ? m_synthetic_children_count : max; - - if (max < UINT32_MAX) - { - size_t num_children = m_synth_filter_ap->CalculateNumChildren(max); - if (log) - log->Printf("[ValueObjectSynthetic::CalculateNumChildren] for VO of name %s and type %s, the filter returned %zu child values", - GetName().AsCString(), - GetTypeName().AsCString(), - num_children); - return num_children; - } - else - { - size_t num_children = (m_synthetic_children_count = m_synth_filter_ap->CalculateNumChildren(max)); - if (log) - log->Printf("[ValueObjectSynthetic::CalculateNumChildren] for VO of name %s and type %s, the filter returned %zu child values", - GetName().AsCString(), - GetTypeName().AsCString(), - num_children); - return num_children; - } +size_t ValueObjectSynthetic::CalculateNumChildren(uint32_t max) { + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS); + + UpdateValueIfNeeded(); + if (m_synthetic_children_count < UINT32_MAX) + return m_synthetic_children_count <= max ? m_synthetic_children_count : max; + + if (max < UINT32_MAX) { + size_t num_children = m_synth_filter_ap->CalculateNumChildren(max); + if (log) + log->Printf("[ValueObjectSynthetic::CalculateNumChildren] for VO of name " + "%s and type %s, the filter returned %zu child values", + GetName().AsCString(), GetTypeName().AsCString(), + num_children); + return num_children; + } else { + size_t num_children = (m_synthetic_children_count = + m_synth_filter_ap->CalculateNumChildren(max)); + if (log) + log->Printf("[ValueObjectSynthetic::CalculateNumChildren] for VO of name " + "%s and type %s, the filter returned %zu child values", + GetName().AsCString(), GetTypeName().AsCString(), + num_children); + return num_children; + } } lldb::ValueObjectSP -ValueObjectSynthetic::GetDynamicValue (lldb::DynamicValueType valueType) -{ - if (!m_parent) - return lldb::ValueObjectSP(); - if (IsDynamic() && GetDynamicValueType() == valueType) - return GetSP(); - return m_parent->GetDynamicValue(valueType); +ValueObjectSynthetic::GetDynamicValue(lldb::DynamicValueType valueType) { + if (!m_parent) + return lldb::ValueObjectSP(); + if (IsDynamic() && GetDynamicValueType() == valueType) + return GetSP(); + return m_parent->GetDynamicValue(valueType); } -bool -ValueObjectSynthetic::MightHaveChildren() -{ - if (m_might_have_children == eLazyBoolCalculate) - m_might_have_children = (m_synth_filter_ap->MightHaveChildren() ? eLazyBoolYes : eLazyBoolNo); - return (m_might_have_children == eLazyBoolNo ? false : true); +bool ValueObjectSynthetic::MightHaveChildren() { + if (m_might_have_children == eLazyBoolCalculate) + m_might_have_children = + (m_synth_filter_ap->MightHaveChildren() ? eLazyBoolYes : eLazyBoolNo); + return (m_might_have_children == eLazyBoolNo ? false : true); } -uint64_t -ValueObjectSynthetic::GetByteSize() -{ - return m_parent->GetByteSize(); -} +uint64_t ValueObjectSynthetic::GetByteSize() { return m_parent->GetByteSize(); } -lldb::ValueType -ValueObjectSynthetic::GetValueType() const -{ - return m_parent->GetValueType(); +lldb::ValueType ValueObjectSynthetic::GetValueType() const { + return m_parent->GetValueType(); } -void -ValueObjectSynthetic::CreateSynthFilter () -{ - m_synth_filter_ap = (m_synth_sp->GetFrontEnd(*m_parent)); - if (!m_synth_filter_ap.get()) - m_synth_filter_ap.reset(new DummySyntheticFrontEnd(*m_parent)); +void ValueObjectSynthetic::CreateSynthFilter() { + m_synth_filter_ap = (m_synth_sp->GetFrontEnd(*m_parent)); + if (!m_synth_filter_ap.get()) + m_synth_filter_ap.reset(new DummySyntheticFrontEnd(*m_parent)); } -bool -ValueObjectSynthetic::UpdateValue () -{ - Log* log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS); - - SetValueIsValid (false); - m_error.Clear(); - - if (!m_parent->UpdateValueIfNeeded(false)) - { - // our parent could not update.. as we are meaningless without a parent, just stop - if (m_parent->GetError().Fail()) - m_error = m_parent->GetError(); - return false; - } - - // regenerate the synthetic filter if our typename changes - // <rdar://problem/12424824> - ConstString new_parent_type_name = m_parent->GetTypeName(); - if (new_parent_type_name != m_parent_type_name) - { - if (log) - log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, type changed from %s to %s, recomputing synthetic filter", - GetName().AsCString(), - m_parent_type_name.AsCString(), - new_parent_type_name.AsCString()); - m_parent_type_name = new_parent_type_name; - CreateSynthFilter(); - } +bool ValueObjectSynthetic::UpdateValue() { + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS); - // let our backend do its update - if (m_synth_filter_ap->Update() == false) - { - if (log) - log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic filter said caches are stale - clearing", GetName().AsCString()); - // filter said that cached values are stale - m_children_byindex.Clear(); - m_name_toindex.Clear(); - // usually, an object's value can change but this does not alter its children count - // for a synthetic VO that might indeed happen, so we need to tell the upper echelons - // that they need to come back to us asking for children - m_children_count_valid = false; - m_synthetic_children_cache.Clear(); - m_synthetic_children_count = UINT32_MAX; - m_might_have_children = eLazyBoolCalculate; - } - else - { - if (log) - log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic filter said caches are still valid", GetName().AsCString()); - } - - m_provides_value = eLazyBoolCalculate; - - lldb::ValueObjectSP synth_val(m_synth_filter_ap->GetSyntheticValue()); - - if (synth_val && synth_val->CanProvideValue()) - { - if (log) - log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic filter said it can provide a value", GetName().AsCString()); - - m_provides_value = eLazyBoolYes; - CopyValueData(synth_val.get()); - } - else - { - if (log) - log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic filter said it will not provide a value", GetName().AsCString()); + SetValueIsValid(false); + m_error.Clear(); - m_provides_value = eLazyBoolNo; - CopyValueData(m_parent); - } - - SetValueIsValid(true); - return true; -} + if (!m_parent->UpdateValueIfNeeded(false)) { + // our parent could not update.. as we are meaningless without a parent, + // just stop + if (m_parent->GetError().Fail()) + m_error = m_parent->GetError(); + return false; + } -lldb::ValueObjectSP -ValueObjectSynthetic::GetChildAtIndex (size_t idx, bool can_create) -{ - Log* log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS); - + // regenerate the synthetic filter if our typename changes + // <rdar://problem/12424824> + ConstString new_parent_type_name = m_parent->GetTypeName(); + if (new_parent_type_name != m_parent_type_name) { if (log) - log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, retrieving child at index %zu", - GetName().AsCString(), - idx); - - UpdateValueIfNeeded(); - - ValueObject *valobj; - if (m_children_byindex.GetValueForKey(idx, valobj) == false) - { - if (can_create && m_synth_filter_ap.get() != nullptr) - { - if (log) - log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index %zu not cached and will be created", - GetName().AsCString(), - idx); - - lldb::ValueObjectSP synth_guy = m_synth_filter_ap->GetChildAtIndex (idx); - - if (log) - log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index %zu created as %p (is synthetic: %s)", - GetName().AsCString(), - idx, - synth_guy.get(), - synth_guy.get() ? (synth_guy->IsSyntheticChildrenGenerated() ? "yes" : "no") : "no"); - - if (!synth_guy) - return synth_guy; - - if (synth_guy->IsSyntheticChildrenGenerated()) - m_synthetic_children_cache.AppendObject(synth_guy); - m_children_byindex.SetValueForKey(idx, synth_guy.get()); - synth_guy->SetPreferredDisplayLanguageIfNeeded(GetPreferredDisplayLanguage()); - return synth_guy; - } - else - { - if (log) - log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index %zu not cached and cannot be created (can_create = %s, synth_filter = %p)", - GetName().AsCString(), - idx, - can_create ? "yes" : "no", - m_synth_filter_ap.get()); - - return lldb::ValueObjectSP(); - } - } - else - { - if (log) - log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index %zu cached as %p", - GetName().AsCString(), - idx, - valobj); - - return valobj->GetSP(); - } -} + log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, type changed " + "from %s to %s, recomputing synthetic filter", + GetName().AsCString(), m_parent_type_name.AsCString(), + new_parent_type_name.AsCString()); + m_parent_type_name = new_parent_type_name; + CreateSynthFilter(); + } -lldb::ValueObjectSP -ValueObjectSynthetic::GetChildMemberWithName (const ConstString &name, bool can_create) -{ - UpdateValueIfNeeded(); + // let our backend do its update + if (m_synth_filter_ap->Update() == false) { + if (log) + log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic " + "filter said caches are stale - clearing", + GetName().AsCString()); + // filter said that cached values are stale + m_children_byindex.Clear(); + m_name_toindex.Clear(); + // usually, an object's value can change but this does not alter its + // children count + // for a synthetic VO that might indeed happen, so we need to tell the upper + // echelons + // that they need to come back to us asking for children + m_children_count_valid = false; + m_synthetic_children_cache.Clear(); + m_synthetic_children_count = UINT32_MAX; + m_might_have_children = eLazyBoolCalculate; + } else { + if (log) + log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic " + "filter said caches are still valid", + GetName().AsCString()); + } - uint32_t index = GetIndexOfChildWithName(name); - - if (index == UINT32_MAX) - return lldb::ValueObjectSP(); - - return GetChildAtIndex(index, can_create); + m_provides_value = eLazyBoolCalculate; + + lldb::ValueObjectSP synth_val(m_synth_filter_ap->GetSyntheticValue()); + + if (synth_val && synth_val->CanProvideValue()) { + if (log) + log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic " + "filter said it can provide a value", + GetName().AsCString()); + + m_provides_value = eLazyBoolYes; + CopyValueData(synth_val.get()); + } else { + if (log) + log->Printf("[ValueObjectSynthetic::UpdateValue] name=%s, synthetic " + "filter said it will not provide a value", + GetName().AsCString()); + + m_provides_value = eLazyBoolNo; + CopyValueData(m_parent); + } + + SetValueIsValid(true); + return true; } -size_t -ValueObjectSynthetic::GetIndexOfChildWithName (const ConstString &name) -{ - UpdateValueIfNeeded(); - - uint32_t found_index = UINT32_MAX; - bool did_find = m_name_toindex.GetValueForKey(name.GetCString(), found_index); - - if (!did_find && m_synth_filter_ap.get() != nullptr) - { - uint32_t index = m_synth_filter_ap->GetIndexOfChildWithName (name); - if (index == UINT32_MAX) - return index; - m_name_toindex.SetValueForKey(name.GetCString(), index); - return index; +lldb::ValueObjectSP ValueObjectSynthetic::GetChildAtIndex(size_t idx, + bool can_create) { + Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS); + + if (log) + log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, retrieving " + "child at index %zu", + GetName().AsCString(), idx); + + UpdateValueIfNeeded(); + + ValueObject *valobj; + if (m_children_byindex.GetValueForKey(idx, valobj) == false) { + if (can_create && m_synth_filter_ap.get() != nullptr) { + if (log) + log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at " + "index %zu not cached and will be created", + GetName().AsCString(), idx); + + lldb::ValueObjectSP synth_guy = m_synth_filter_ap->GetChildAtIndex(idx); + + if (log) + log->Printf( + "[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at index " + "%zu created as %p (is " + "synthetic: %s)", + GetName().AsCString(), idx, static_cast<void *>(synth_guy.get()), + synth_guy.get() + ? (synth_guy->IsSyntheticChildrenGenerated() ? "yes" : "no") + : "no"); + + if (!synth_guy) + return synth_guy; + + if (synth_guy->IsSyntheticChildrenGenerated()) + m_synthetic_children_cache.AppendObject(synth_guy); + m_children_byindex.SetValueForKey(idx, synth_guy.get()); + synth_guy->SetPreferredDisplayLanguageIfNeeded( + GetPreferredDisplayLanguage()); + return synth_guy; + } else { + if (log) + log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at " + "index %zu not cached and cannot " + "be created (can_create = %s, synth_filter = %p)", + GetName().AsCString(), idx, can_create ? "yes" : "no", + static_cast<void *>(m_synth_filter_ap.get())); + + return lldb::ValueObjectSP(); } - else if (!did_find && m_synth_filter_ap.get() == nullptr) - return UINT32_MAX; - else /*if (iter != m_name_toindex.end())*/ - return found_index; -} + } else { + if (log) + log->Printf("[ValueObjectSynthetic::GetChildAtIndex] name=%s, child at " + "index %zu cached as %p", + GetName().AsCString(), idx, static_cast<void *>(valobj)); -bool -ValueObjectSynthetic::IsInScope () -{ - return m_parent->IsInScope(); + return valobj->GetSP(); + } } lldb::ValueObjectSP -ValueObjectSynthetic::GetNonSyntheticValue () -{ - return m_parent->GetSP(); +ValueObjectSynthetic::GetChildMemberWithName(const ConstString &name, + bool can_create) { + UpdateValueIfNeeded(); + + uint32_t index = GetIndexOfChildWithName(name); + + if (index == UINT32_MAX) + return lldb::ValueObjectSP(); + + return GetChildAtIndex(index, can_create); +} + +size_t ValueObjectSynthetic::GetIndexOfChildWithName(const ConstString &name) { + UpdateValueIfNeeded(); + + uint32_t found_index = UINT32_MAX; + bool did_find = m_name_toindex.GetValueForKey(name.GetCString(), found_index); + + if (!did_find && m_synth_filter_ap.get() != nullptr) { + uint32_t index = m_synth_filter_ap->GetIndexOfChildWithName(name); + if (index == UINT32_MAX) + return index; + m_name_toindex.SetValueForKey(name.GetCString(), index); + return index; + } else if (!did_find && m_synth_filter_ap.get() == nullptr) + return UINT32_MAX; + else /*if (iter != m_name_toindex.end())*/ + return found_index; } -void -ValueObjectSynthetic::CopyValueData (ValueObject *source) -{ - m_value = (source->UpdateValueIfNeeded(), source->GetValue()); - ExecutionContext exe_ctx (GetExecutionContextRef()); - m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); +bool ValueObjectSynthetic::IsInScope() { return m_parent->IsInScope(); } + +lldb::ValueObjectSP ValueObjectSynthetic::GetNonSyntheticValue() { + return m_parent->GetSP(); } -bool -ValueObjectSynthetic::CanProvideValue () -{ - if (!UpdateValueIfNeeded()) - return false; - if (m_provides_value == eLazyBoolYes) - return true; - return m_parent->CanProvideValue(); +void ValueObjectSynthetic::CopyValueData(ValueObject *source) { + m_value = (source->UpdateValueIfNeeded(), source->GetValue()); + ExecutionContext exe_ctx(GetExecutionContextRef()); + m_error = m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); } -bool -ValueObjectSynthetic::SetValueFromCString (const char *value_str, Error& error) -{ - return m_parent->SetValueFromCString(value_str, error); +bool ValueObjectSynthetic::CanProvideValue() { + if (!UpdateValueIfNeeded()) + return false; + if (m_provides_value == eLazyBoolYes) + return true; + return m_parent->CanProvideValue(); } -void -ValueObjectSynthetic::SetFormat (lldb::Format format) -{ - if (m_parent) - { - m_parent->ClearUserVisibleData(eClearUserVisibleDataItemsAll); - m_parent->SetFormat(format); - } - this->ValueObject::SetFormat(format); - this->ClearUserVisibleData(eClearUserVisibleDataItemsAll); +bool ValueObjectSynthetic::SetValueFromCString(const char *value_str, + Error &error) { + return m_parent->SetValueFromCString(value_str, error); } -void -ValueObjectSynthetic::SetPreferredDisplayLanguage (lldb::LanguageType lang) -{ - this->ValueObject::SetPreferredDisplayLanguage(lang); - if (m_parent) - m_parent->SetPreferredDisplayLanguage(lang); +void ValueObjectSynthetic::SetFormat(lldb::Format format) { + if (m_parent) { + m_parent->ClearUserVisibleData(eClearUserVisibleDataItemsAll); + m_parent->SetFormat(format); + } + this->ValueObject::SetFormat(format); + this->ClearUserVisibleData(eClearUserVisibleDataItemsAll); } -lldb::LanguageType -ValueObjectSynthetic::GetPreferredDisplayLanguage () -{ - if (m_preferred_display_language == lldb::eLanguageTypeUnknown) - { - if (m_parent) - return m_parent->GetPreferredDisplayLanguage(); - return lldb::eLanguageTypeUnknown; - } - else - return m_preferred_display_language; +void ValueObjectSynthetic::SetPreferredDisplayLanguage( + lldb::LanguageType lang) { + this->ValueObject::SetPreferredDisplayLanguage(lang); + if (m_parent) + m_parent->SetPreferredDisplayLanguage(lang); } -bool -ValueObjectSynthetic::IsSyntheticChildrenGenerated () -{ +lldb::LanguageType ValueObjectSynthetic::GetPreferredDisplayLanguage() { + if (m_preferred_display_language == lldb::eLanguageTypeUnknown) { if (m_parent) - return m_parent->IsSyntheticChildrenGenerated(); - return false; + return m_parent->GetPreferredDisplayLanguage(); + return lldb::eLanguageTypeUnknown; + } else + return m_preferred_display_language; } -void -ValueObjectSynthetic::SetSyntheticChildrenGenerated (bool b) -{ - if (m_parent) - m_parent->SetSyntheticChildrenGenerated(b); - this->ValueObject::SetSyntheticChildrenGenerated(b); +bool ValueObjectSynthetic::IsSyntheticChildrenGenerated() { + if (m_parent) + return m_parent->IsSyntheticChildrenGenerated(); + return false; } -bool -ValueObjectSynthetic::GetDeclaration (Declaration &decl) -{ - if (m_parent) - return m_parent->GetDeclaration(decl); +void ValueObjectSynthetic::SetSyntheticChildrenGenerated(bool b) { + if (m_parent) + m_parent->SetSyntheticChildrenGenerated(b); + this->ValueObject::SetSyntheticChildrenGenerated(b); +} + +bool ValueObjectSynthetic::GetDeclaration(Declaration &decl) { + if (m_parent) + return m_parent->GetDeclaration(decl); - return ValueObject::GetDeclaration(decl); + return ValueObject::GetDeclaration(decl); } -uint64_t -ValueObjectSynthetic::GetLanguageFlags () -{ - if (m_parent) - return m_parent->GetLanguageFlags(); - return this->ValueObject::GetLanguageFlags(); +uint64_t ValueObjectSynthetic::GetLanguageFlags() { + if (m_parent) + return m_parent->GetLanguageFlags(); + return this->ValueObject::GetLanguageFlags(); } -void -ValueObjectSynthetic::SetLanguageFlags (uint64_t flags) -{ - if (m_parent) - m_parent->SetLanguageFlags(flags); - else - this->ValueObject::SetLanguageFlags(flags); +void ValueObjectSynthetic::SetLanguageFlags(uint64_t flags) { + if (m_parent) + m_parent->SetLanguageFlags(flags); + else + this->ValueObject::SetLanguageFlags(flags); } diff --git a/source/Core/ValueObjectVariable.cpp b/source/Core/ValueObjectVariable.cpp index a29d858d169f..f8eedc30e709 100644 --- a/source/Core/ValueObjectVariable.cpp +++ b/source/Core/ValueObjectVariable.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// - #include "lldb/Core/ValueObjectVariable.h" // C Includes @@ -16,8 +15,8 @@ // Project includes #include "lldb/Core/Module.h" #include "lldb/Core/RegisterValue.h" -#include "lldb/Core/ValueObjectList.h" #include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectList.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" @@ -32,422 +31,357 @@ #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" - using namespace lldb_private; lldb::ValueObjectSP -ValueObjectVariable::Create (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp) -{ - return (new ValueObjectVariable (exe_scope, var_sp))->GetSP(); +ValueObjectVariable::Create(ExecutionContextScope *exe_scope, + const lldb::VariableSP &var_sp) { + return (new ValueObjectVariable(exe_scope, var_sp))->GetSP(); } -ValueObjectVariable::ValueObjectVariable (ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp) : - ValueObject(exe_scope), - m_variable_sp(var_sp) -{ - // Do not attempt to construct one of these objects with no variable! - assert (m_variable_sp.get() != NULL); - m_name = var_sp->GetName(); +ValueObjectVariable::ValueObjectVariable(ExecutionContextScope *exe_scope, + const lldb::VariableSP &var_sp) + : ValueObject(exe_scope), m_variable_sp(var_sp) { + // Do not attempt to construct one of these objects with no variable! + assert(m_variable_sp.get() != NULL); + m_name = var_sp->GetName(); } -ValueObjectVariable::~ValueObjectVariable() -{ -} +ValueObjectVariable::~ValueObjectVariable() {} -CompilerType -ValueObjectVariable::GetCompilerTypeImpl () -{ - Type *var_type = m_variable_sp->GetType(); - if (var_type) - return var_type->GetForwardCompilerType (); - return CompilerType(); +CompilerType ValueObjectVariable::GetCompilerTypeImpl() { + Type *var_type = m_variable_sp->GetType(); + if (var_type) + return var_type->GetForwardCompilerType(); + return CompilerType(); } -ConstString -ValueObjectVariable::GetTypeName() -{ - Type * var_type = m_variable_sp->GetType(); - if (var_type) - return var_type->GetName(); - return ConstString(); +ConstString ValueObjectVariable::GetTypeName() { + Type *var_type = m_variable_sp->GetType(); + if (var_type) + return var_type->GetName(); + return ConstString(); } -ConstString -ValueObjectVariable::GetDisplayTypeName() -{ - Type * var_type = m_variable_sp->GetType(); - if (var_type) - return var_type->GetForwardCompilerType ().GetDisplayTypeName(); - return ConstString(); +ConstString ValueObjectVariable::GetDisplayTypeName() { + Type *var_type = m_variable_sp->GetType(); + if (var_type) + return var_type->GetForwardCompilerType().GetDisplayTypeName(); + return ConstString(); } -ConstString -ValueObjectVariable::GetQualifiedTypeName() -{ - Type * var_type = m_variable_sp->GetType(); - if (var_type) - return var_type->GetQualifiedName(); - return ConstString(); +ConstString ValueObjectVariable::GetQualifiedTypeName() { + Type *var_type = m_variable_sp->GetType(); + if (var_type) + return var_type->GetQualifiedName(); + return ConstString(); } -size_t -ValueObjectVariable::CalculateNumChildren(uint32_t max) -{ - CompilerType type(GetCompilerType()); - - if (!type.IsValid()) - return 0; - - const bool omit_empty_base_classes = true; - auto child_count = type.GetNumChildren(omit_empty_base_classes); - return child_count <= max ? child_count : max; +size_t ValueObjectVariable::CalculateNumChildren(uint32_t max) { + CompilerType type(GetCompilerType()); + + if (!type.IsValid()) + return 0; + + const bool omit_empty_base_classes = true; + auto child_count = type.GetNumChildren(omit_empty_base_classes); + return child_count <= max ? child_count : max; } -uint64_t -ValueObjectVariable::GetByteSize() -{ - ExecutionContext exe_ctx(GetExecutionContextRef()); - - CompilerType type(GetCompilerType()); - - if (!type.IsValid()) - return 0; - - return type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); +uint64_t ValueObjectVariable::GetByteSize() { + ExecutionContext exe_ctx(GetExecutionContextRef()); + + CompilerType type(GetCompilerType()); + + if (!type.IsValid()) + return 0; + + return type.GetByteSize(exe_ctx.GetBestExecutionContextScope()); } -lldb::ValueType -ValueObjectVariable::GetValueType() const -{ - if (m_variable_sp) - return m_variable_sp->GetScope(); - return lldb::eValueTypeInvalid; +lldb::ValueType ValueObjectVariable::GetValueType() const { + if (m_variable_sp) + return m_variable_sp->GetScope(); + return lldb::eValueTypeInvalid; } -bool -ValueObjectVariable::UpdateValue () -{ - SetValueIsValid (false); - m_error.Clear(); - - Variable *variable = m_variable_sp.get(); - DWARFExpression &expr = variable->LocationExpression(); - - if (variable->GetLocationIsConstantValueData()) - { - // expr doesn't contain DWARF bytes, it contains the constant variable - // value bytes themselves... - if (expr.GetExpressionData(m_data)) - m_value.SetContext(Value::eContextTypeVariable, variable); - else - m_error.SetErrorString ("empty constant data"); - // constant bytes can't be edited - sorry - m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL); - } - else - { - lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS; - ExecutionContext exe_ctx (GetExecutionContextRef()); - - Target *target = exe_ctx.GetTargetPtr(); - if (target) - { - m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); - m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); - } +bool ValueObjectVariable::UpdateValue() { + SetValueIsValid(false); + m_error.Clear(); - if (expr.IsLocationList()) - { - SymbolContext sc; - variable->CalculateSymbolContext (&sc); - if (sc.function) - loclist_base_load_addr = sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress (target); - } - Value old_value(m_value); - if (expr.Evaluate (&exe_ctx, - nullptr, - nullptr, - nullptr, - loclist_base_load_addr, - nullptr, - nullptr, - m_value, - &m_error)) - { - m_resolved_value = m_value; - m_value.SetContext(Value::eContextTypeVariable, variable); - - CompilerType compiler_type = GetCompilerType(); - if (compiler_type.IsValid()) - m_value.SetCompilerType(compiler_type); - - Value::ValueType value_type = m_value.GetValueType(); - - Process *process = exe_ctx.GetProcessPtr(); - const bool process_is_alive = process && process->IsAlive(); - const uint32_t type_info = compiler_type.GetTypeInfo(); - const bool is_pointer_or_ref = (type_info & (lldb::eTypeIsPointer | lldb::eTypeIsReference)) != 0; - - switch (value_type) - { - case Value::eValueTypeFileAddress: - // If this type is a pointer, then its children will be considered load addresses - // if the pointer or reference is dereferenced, but only if the process is alive. - // - // There could be global variables like in the following code: - // struct LinkedListNode { Foo* foo; LinkedListNode* next; }; - // Foo g_foo1; - // Foo g_foo2; - // LinkedListNode g_second_node = { &g_foo2, NULL }; - // LinkedListNode g_first_node = { &g_foo1, &g_second_node }; - // - // When we aren't running, we should be able to look at these variables using - // the "target variable" command. Children of the "g_first_node" always will - // be of the same address type as the parent. But children of the "next" member of - // LinkedListNode will become load addresses if we have a live process, or remain - // what a file address if it what a file address. - if (process_is_alive && is_pointer_or_ref) - SetAddressTypeOfChildren(eAddressTypeLoad); - else - SetAddressTypeOfChildren(eAddressTypeFile); - break; - case Value::eValueTypeHostAddress: - // Same as above for load addresses, except children of pointer or refs are always - // load addresses. Host addresses are used to store freeze dried variables. If this - // type is a struct, the entire struct contents will be copied into the heap of the - // LLDB process, but we do not currrently follow any pointers. - if (is_pointer_or_ref) - SetAddressTypeOfChildren(eAddressTypeLoad); - else - SetAddressTypeOfChildren(eAddressTypeHost); - break; - case Value::eValueTypeLoadAddress: - case Value::eValueTypeScalar: - case Value::eValueTypeVector: - SetAddressTypeOfChildren(eAddressTypeLoad); - break; - } + Variable *variable = m_variable_sp.get(); + DWARFExpression &expr = variable->LocationExpression(); - switch (value_type) - { - case Value::eValueTypeVector: - // fall through - case Value::eValueTypeScalar: - // The variable value is in the Scalar value inside the m_value. - // We can point our m_data right to it. - m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get()); - break; - - case Value::eValueTypeFileAddress: - case Value::eValueTypeLoadAddress: - case Value::eValueTypeHostAddress: - // The DWARF expression result was an address in the inferior - // process. If this variable is an aggregate type, we just need - // the address as the main value as all child variable objects - // will rely upon this location and add an offset and then read - // their own values as needed. If this variable is a simple - // type, we read all data for it into m_data. - // Make sure this type has a value before we try and read it - - // If we have a file address, convert it to a load address if we can. - if (value_type == Value::eValueTypeFileAddress && process_is_alive) - { - lldb::addr_t file_addr = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); - if (file_addr != LLDB_INVALID_ADDRESS) - { - SymbolContext var_sc; - variable->CalculateSymbolContext(&var_sc); - if (var_sc.module_sp) - { - ObjectFile *objfile = var_sc.module_sp->GetObjectFile(); - if (objfile) - { - Address so_addr(file_addr, objfile->GetSectionList()); - lldb::addr_t load_addr = so_addr.GetLoadAddress (target); - if (load_addr != LLDB_INVALID_ADDRESS) - { - m_value.SetValueType(Value::eValueTypeLoadAddress); - m_value.GetScalar() = load_addr; - } - } - } - } - } + if (variable->GetLocationIsConstantValueData()) { + // expr doesn't contain DWARF bytes, it contains the constant variable + // value bytes themselves... + if (expr.GetExpressionData(m_data)) + m_value.SetContext(Value::eContextTypeVariable, variable); + else + m_error.SetErrorString("empty constant data"); + // constant bytes can't be edited - sorry + m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL); + } else { + lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS; + ExecutionContext exe_ctx(GetExecutionContextRef()); - if (!CanProvideValue()) - { - // this value object represents an aggregate type whose - // children have values, but this object does not. So we - // say we are changed if our location has changed. - SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar()); - } - else - { - // Copy the Value and set the context to use our Variable - // so it can extract read its value into m_data appropriately - Value value(m_value); - value.SetContext(Value::eContextTypeVariable, variable); - m_error = value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); - - SetValueDidChange (value_type != old_value.GetValueType() || m_value.GetScalar() != old_value.GetScalar()); + Target *target = exe_ctx.GetTargetPtr(); + if (target) { + m_data.SetByteOrder(target->GetArchitecture().GetByteOrder()); + m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); + } + + if (expr.IsLocationList()) { + SymbolContext sc; + variable->CalculateSymbolContext(&sc); + if (sc.function) + loclist_base_load_addr = + sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress( + target); + } + Value old_value(m_value); + if (expr.Evaluate(&exe_ctx, nullptr, nullptr, nullptr, + loclist_base_load_addr, nullptr, nullptr, m_value, + &m_error)) { + m_resolved_value = m_value; + m_value.SetContext(Value::eContextTypeVariable, variable); + + CompilerType compiler_type = GetCompilerType(); + if (compiler_type.IsValid()) + m_value.SetCompilerType(compiler_type); + + Value::ValueType value_type = m_value.GetValueType(); + + Process *process = exe_ctx.GetProcessPtr(); + const bool process_is_alive = process && process->IsAlive(); + const uint32_t type_info = compiler_type.GetTypeInfo(); + const bool is_pointer_or_ref = + (type_info & (lldb::eTypeIsPointer | lldb::eTypeIsReference)) != 0; + + switch (value_type) { + case Value::eValueTypeFileAddress: + // If this type is a pointer, then its children will be considered load + // addresses + // if the pointer or reference is dereferenced, but only if the process + // is alive. + // + // There could be global variables like in the following code: + // struct LinkedListNode { Foo* foo; LinkedListNode* next; }; + // Foo g_foo1; + // Foo g_foo2; + // LinkedListNode g_second_node = { &g_foo2, NULL }; + // LinkedListNode g_first_node = { &g_foo1, &g_second_node }; + // + // When we aren't running, we should be able to look at these variables + // using + // the "target variable" command. Children of the "g_first_node" always + // will + // be of the same address type as the parent. But children of the "next" + // member of + // LinkedListNode will become load addresses if we have a live process, + // or remain + // what a file address if it what a file address. + if (process_is_alive && is_pointer_or_ref) + SetAddressTypeOfChildren(eAddressTypeLoad); + else + SetAddressTypeOfChildren(eAddressTypeFile); + break; + case Value::eValueTypeHostAddress: + // Same as above for load addresses, except children of pointer or refs + // are always + // load addresses. Host addresses are used to store freeze dried + // variables. If this + // type is a struct, the entire struct contents will be copied into the + // heap of the + // LLDB process, but we do not currrently follow any pointers. + if (is_pointer_or_ref) + SetAddressTypeOfChildren(eAddressTypeLoad); + else + SetAddressTypeOfChildren(eAddressTypeHost); + break; + case Value::eValueTypeLoadAddress: + case Value::eValueTypeScalar: + case Value::eValueTypeVector: + SetAddressTypeOfChildren(eAddressTypeLoad); + break; + } + + switch (value_type) { + case Value::eValueTypeVector: + // fall through + case Value::eValueTypeScalar: + // The variable value is in the Scalar value inside the m_value. + // We can point our m_data right to it. + m_error = + m_value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + break; + + case Value::eValueTypeFileAddress: + case Value::eValueTypeLoadAddress: + case Value::eValueTypeHostAddress: + // The DWARF expression result was an address in the inferior + // process. If this variable is an aggregate type, we just need + // the address as the main value as all child variable objects + // will rely upon this location and add an offset and then read + // their own values as needed. If this variable is a simple + // type, we read all data for it into m_data. + // Make sure this type has a value before we try and read it + + // If we have a file address, convert it to a load address if we can. + if (value_type == Value::eValueTypeFileAddress && process_is_alive) { + lldb::addr_t file_addr = + m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); + if (file_addr != LLDB_INVALID_ADDRESS) { + SymbolContext var_sc; + variable->CalculateSymbolContext(&var_sc); + if (var_sc.module_sp) { + ObjectFile *objfile = var_sc.module_sp->GetObjectFile(); + if (objfile) { + Address so_addr(file_addr, objfile->GetSectionList()); + lldb::addr_t load_addr = so_addr.GetLoadAddress(target); + if (load_addr != LLDB_INVALID_ADDRESS) { + m_value.SetValueType(Value::eValueTypeLoadAddress); + m_value.GetScalar() = load_addr; } - break; + } } - - SetValueIsValid (m_error.Success()); + } } - else - { - // could not find location, won't allow editing - m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL); + + if (!CanProvideValue()) { + // this value object represents an aggregate type whose + // children have values, but this object does not. So we + // say we are changed if our location has changed. + SetValueDidChange(value_type != old_value.GetValueType() || + m_value.GetScalar() != old_value.GetScalar()); + } else { + // Copy the Value and set the context to use our Variable + // so it can extract read its value into m_data appropriately + Value value(m_value); + value.SetContext(Value::eContextTypeVariable, variable); + m_error = + value.GetValueAsData(&exe_ctx, m_data, 0, GetModule().get()); + + SetValueDidChange(value_type != old_value.GetValueType() || + m_value.GetScalar() != old_value.GetScalar()); } + break; + } + + SetValueIsValid(m_error.Success()); + } else { + // could not find location, won't allow editing + m_resolved_value.SetContext(Value::eContextTypeInvalid, NULL); } - return m_error.Success(); + } + return m_error.Success(); } - - -bool -ValueObjectVariable::IsInScope () -{ - const ExecutionContextRef &exe_ctx_ref = GetExecutionContextRef(); - if (exe_ctx_ref.HasFrameRef()) - { - ExecutionContext exe_ctx (exe_ctx_ref); - StackFrame *frame = exe_ctx.GetFramePtr(); - if (frame) - { - return m_variable_sp->IsInScope (frame); - } - else - { - // This ValueObject had a frame at one time, but now we - // can't locate it, so return false since we probably aren't - // in scope. - return false; - } +bool ValueObjectVariable::IsInScope() { + const ExecutionContextRef &exe_ctx_ref = GetExecutionContextRef(); + if (exe_ctx_ref.HasFrameRef()) { + ExecutionContext exe_ctx(exe_ctx_ref); + StackFrame *frame = exe_ctx.GetFramePtr(); + if (frame) { + return m_variable_sp->IsInScope(frame); + } else { + // This ValueObject had a frame at one time, but now we + // can't locate it, so return false since we probably aren't + // in scope. + return false; } - // We have a variable that wasn't tied to a frame, which - // means it is a global and is always in scope. - return true; - + } + // We have a variable that wasn't tied to a frame, which + // means it is a global and is always in scope. + return true; } -lldb::ModuleSP -ValueObjectVariable::GetModule() -{ - if (m_variable_sp) - { - SymbolContextScope *sc_scope = m_variable_sp->GetSymbolContextScope(); - if (sc_scope) - { - return sc_scope->CalculateSymbolContextModule(); - } +lldb::ModuleSP ValueObjectVariable::GetModule() { + if (m_variable_sp) { + SymbolContextScope *sc_scope = m_variable_sp->GetSymbolContextScope(); + if (sc_scope) { + return sc_scope->CalculateSymbolContextModule(); } - return lldb::ModuleSP(); + } + return lldb::ModuleSP(); } -SymbolContextScope * -ValueObjectVariable::GetSymbolContextScope() -{ - if (m_variable_sp) - return m_variable_sp->GetSymbolContextScope(); - return NULL; +SymbolContextScope *ValueObjectVariable::GetSymbolContextScope() { + if (m_variable_sp) + return m_variable_sp->GetSymbolContextScope(); + return NULL; } -bool -ValueObjectVariable::GetDeclaration (Declaration &decl) -{ - if (m_variable_sp) - { - decl = m_variable_sp->GetDeclaration(); - return true; - } - return false; +bool ValueObjectVariable::GetDeclaration(Declaration &decl) { + if (m_variable_sp) { + decl = m_variable_sp->GetDeclaration(); + return true; + } + return false; } -const char * -ValueObjectVariable::GetLocationAsCString () -{ - if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo) - return GetLocationAsCStringImpl(m_resolved_value, - m_data); - else - return ValueObject::GetLocationAsCString(); +const char *ValueObjectVariable::GetLocationAsCString() { + if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo) + return GetLocationAsCStringImpl(m_resolved_value, m_data); + else + return ValueObject::GetLocationAsCString(); } -bool -ValueObjectVariable::SetValueFromCString (const char *value_str, Error& error) -{ - if (!UpdateValueIfNeeded()) - { - error.SetErrorString("unable to update value before writing"); - return false; +bool ValueObjectVariable::SetValueFromCString(const char *value_str, + Error &error) { + if (!UpdateValueIfNeeded()) { + error.SetErrorString("unable to update value before writing"); + return false; + } + + if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo) { + RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo(); + ExecutionContext exe_ctx(GetExecutionContextRef()); + RegisterContext *reg_ctx = exe_ctx.GetRegisterContext(); + RegisterValue reg_value; + if (!reg_info || !reg_ctx) { + error.SetErrorString("unable to retrieve register info"); + return false; } - - if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo) - { - RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo(); - ExecutionContext exe_ctx(GetExecutionContextRef()); - RegisterContext *reg_ctx = exe_ctx.GetRegisterContext(); - RegisterValue reg_value; - if (!reg_info || !reg_ctx) - { - error.SetErrorString("unable to retrieve register info"); - return false; - } - error = reg_value.SetValueFromCString(reg_info, value_str); - if (error.Fail()) - return false; - if (reg_ctx->WriteRegister (reg_info, reg_value)) - { - SetNeedsUpdate(); - return true; - } - else - { - error.SetErrorString("unable to write back to register"); - return false; - } + error = reg_value.SetValueFromString(reg_info, llvm::StringRef(value_str)); + if (error.Fail()) + return false; + if (reg_ctx->WriteRegister(reg_info, reg_value)) { + SetNeedsUpdate(); + return true; + } else { + error.SetErrorString("unable to write back to register"); + return false; } - else - return ValueObject::SetValueFromCString(value_str, error); + } else + return ValueObject::SetValueFromCString(value_str, error); } -bool -ValueObjectVariable::SetData (DataExtractor &data, Error &error) -{ - if (!UpdateValueIfNeeded()) - { - error.SetErrorString("unable to update value before writing"); - return false; +bool ValueObjectVariable::SetData(DataExtractor &data, Error &error) { + if (!UpdateValueIfNeeded()) { + error.SetErrorString("unable to update value before writing"); + return false; + } + + if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo) { + RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo(); + ExecutionContext exe_ctx(GetExecutionContextRef()); + RegisterContext *reg_ctx = exe_ctx.GetRegisterContext(); + RegisterValue reg_value; + if (!reg_info || !reg_ctx) { + error.SetErrorString("unable to retrieve register info"); + return false; } - - if (m_resolved_value.GetContextType() == Value::eContextTypeRegisterInfo) - { - RegisterInfo *reg_info = m_resolved_value.GetRegisterInfo(); - ExecutionContext exe_ctx(GetExecutionContextRef()); - RegisterContext *reg_ctx = exe_ctx.GetRegisterContext(); - RegisterValue reg_value; - if (!reg_info || !reg_ctx) - { - error.SetErrorString("unable to retrieve register info"); - return false; - } - error = reg_value.SetValueFromData(reg_info, data, 0, true); - if (error.Fail()) - return false; - if (reg_ctx->WriteRegister (reg_info, reg_value)) - { - SetNeedsUpdate(); - return true; - } - else - { - error.SetErrorString("unable to write back to register"); - return false; - } + error = reg_value.SetValueFromData(reg_info, data, 0, true); + if (error.Fail()) + return false; + if (reg_ctx->WriteRegister(reg_info, reg_value)) { + SetNeedsUpdate(); + return true; + } else { + error.SetErrorString("unable to write back to register"); + return false; } - else - return ValueObject::SetData(data, error); + } else + return ValueObject::SetData(data, error); } |