aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins')
-rw-r--r--source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp30
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp141
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h17
-rw-r--r--source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp2
-rw-r--r--source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp64
-rw-r--r--source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp5
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp44
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.h5
-rw-r--r--source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp35
-rw-r--r--source/Plugins/OperatingSystem/Python/OperatingSystemPython.h1
-rw-r--r--source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp18
-rw-r--r--source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h7
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.cpp5
-rw-r--r--source/Plugins/Platform/POSIX/PlatformPOSIX.h5
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp44
-rw-r--r--source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h9
-rw-r--r--source/Plugins/Process/FreeBSD/FreeBSDThread.cpp69
-rw-r--r--source/Plugins/Process/FreeBSD/FreeBSDThread.h39
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp145
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessFreeBSD.h21
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.cpp102
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.h24
-rw-r--r--source/Plugins/Process/POSIX/POSIXThread.cpp4
-rw-r--r--source/Plugins/Process/POSIX/ProcessPOSIX.cpp16
-rw-r--r--source/Plugins/Process/POSIX/ProcessPOSIX.h8
-rw-r--r--source/Plugins/Process/Utility/HistoryThread.cpp2
-rw-r--r--source/Plugins/Process/Utility/HistoryThread.h10
-rw-r--r--source/Plugins/Process/Utility/InferiorCallPOSIX.cpp31
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.cpp164
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.h22
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.cpp54
-rw-r--r--source/Plugins/Process/Utility/UnwindLLDB.h20
-rw-r--r--source/Plugins/Process/elf-core/ProcessElfCore.cpp46
-rw-r--r--source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp12
-rw-r--r--source/Plugins/Process/elf-core/ThreadElfCore.cpp70
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp256
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h43
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp411
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h54
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp641
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h145
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp12
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp332
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.h16
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp13
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFFormValue.h2
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp120
-rw-r--r--source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp4
48 files changed, 2206 insertions, 1134 deletions
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
index 61c3c64d4fc3..e9b8a9f573a3 100644
--- a/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
@@ -35,6 +35,7 @@
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/StackFrame.h"
@@ -127,6 +128,7 @@ public:
bool got_op = false;
DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC();
const ArchSpec &arch = llvm_disasm.GetArchitecture();
+ const lldb::ByteOrder byte_order = data.GetByteOrder();
const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize();
const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize();
@@ -135,26 +137,26 @@ public:
// Fixed size instructions, just read that amount of data.
if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size))
return false;
-
+
switch (min_op_byte_size)
{
case 1:
- m_opcode.SetOpcode8 (data.GetU8 (&data_offset));
+ m_opcode.SetOpcode8 (data.GetU8 (&data_offset), byte_order);
got_op = true;
break;
case 2:
- m_opcode.SetOpcode16 (data.GetU16 (&data_offset));
+ m_opcode.SetOpcode16 (data.GetU16 (&data_offset), byte_order);
got_op = true;
break;
case 4:
- m_opcode.SetOpcode32 (data.GetU32 (&data_offset));
+ m_opcode.SetOpcode32 (data.GetU32 (&data_offset), byte_order);
got_op = true;
break;
case 8:
- m_opcode.SetOpcode64 (data.GetU64 (&data_offset));
+ m_opcode.SetOpcode64 (data.GetU64 (&data_offset), byte_order);
got_op = true;
break;
@@ -177,20 +179,20 @@ public:
uint32_t thumb_opcode = data.GetU16(&data_offset);
if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
{
- m_opcode.SetOpcode16 (thumb_opcode);
+ m_opcode.SetOpcode16 (thumb_opcode, byte_order);
m_is_valid = true;
}
else
{
thumb_opcode <<= 16;
thumb_opcode |= data.GetU16(&data_offset);
- m_opcode.SetOpcode16_2 (thumb_opcode);
+ m_opcode.SetOpcode16_2 (thumb_opcode, byte_order);
m_is_valid = true;
}
}
else
{
- m_opcode.SetOpcode32 (data.GetU32(&data_offset));
+ m_opcode.SetOpcode32 (data.GetU32(&data_offset), byte_order);
m_is_valid = true;
}
}
@@ -303,12 +305,13 @@ public:
inst_size = m_opcode.GetByteSize();
StreamString mnemonic_strm;
lldb::offset_t offset = 0;
+ lldb::ByteOrder byte_order = data.GetByteOrder();
switch (inst_size)
{
case 1:
{
const uint8_t uval8 = data.GetU8 (&offset);
- m_opcode.SetOpcode8 (uval8);
+ m_opcode.SetOpcode8 (uval8, byte_order);
m_opcode_name.assign (".byte");
mnemonic_strm.Printf("0x%2.2x", uval8);
}
@@ -316,7 +319,7 @@ public:
case 2:
{
const uint16_t uval16 = data.GetU16(&offset);
- m_opcode.SetOpcode16(uval16);
+ m_opcode.SetOpcode16(uval16, byte_order);
m_opcode_name.assign (".short");
mnemonic_strm.Printf("0x%4.4x", uval16);
}
@@ -324,7 +327,7 @@ public:
case 4:
{
const uint32_t uval32 = data.GetU32(&offset);
- m_opcode.SetOpcode32(uval32);
+ m_opcode.SetOpcode32(uval32, byte_order);
m_opcode_name.assign (".long");
mnemonic_strm.Printf("0x%8.8x", uval32);
}
@@ -332,7 +335,7 @@ public:
case 8:
{
const uint64_t uval64 = data.GetU64(&offset);
- m_opcode.SetOpcode64(uval64);
+ m_opcode.SetOpcode64(uval64, byte_order);
m_opcode_name.assign (".quad");
mnemonic_strm.Printf("0x%16.16" PRIx64, uval64);
}
@@ -432,7 +435,8 @@ DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, uns
m_subtarget_info_ap.reset(curr_target->createMCSubtargetInfo(triple, "",
features_str));
- m_asm_info_ap.reset(curr_target->createMCAsmInfo(*curr_target->createMCRegInfo(triple), triple));
+ std::unique_ptr<llvm::MCRegisterInfo> reg_info(curr_target->createMCRegInfo(triple));
+ m_asm_info_ap.reset(curr_target->createMCAsmInfo(*reg_info, triple));
if (m_instr_info_ap.get() == NULL || m_reg_info_ap.get() == NULL || m_subtarget_info_ap.get() == NULL || m_asm_info_ap.get() == NULL)
{
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
index 4284558c4409..286b1ef62d9a 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp
@@ -150,46 +150,6 @@ DynamicLoaderPOSIXDYLD::DidLaunch()
}
}
-ModuleSP
-DynamicLoaderPOSIXDYLD::GetTargetExecutable()
-{
- Target &target = m_process->GetTarget();
- ModuleSP executable = target.GetExecutableModule();
-
- if (executable.get())
- {
- 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.get() && module_sp->GetUUID().IsValid() && executable->GetUUID().IsValid())
- {
- if (module_sp->GetUUID() != executable->GetUUID())
- executable.reset();
- }
- else if (executable->FileHasChanged())
- {
- executable.reset();
- }
-
- if (!executable.get())
- {
- 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;
-}
-
Error
DynamicLoaderPOSIXDYLD::ExecutePluginCommand(Args &command, Stream *strm)
{
@@ -211,48 +171,17 @@ DynamicLoaderPOSIXDYLD::CanLoadImage()
void
DynamicLoaderPOSIXDYLD::UpdateLoadedSections(ModuleSP module, addr_t link_map_addr, addr_t base_addr)
{
- SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();
- const SectionList *sections = GetSectionListFromModule(module);
-
- assert(sections && "SectionList missing from loaded module.");
-
m_loaded_modules[module] = link_map_addr;
- const size_t num_sections = sections->GetSize();
-
- for (unsigned i = 0; i < num_sections; ++i)
- {
- SectionSP section_sp (sections->GetSectionAtIndex(i));
- lldb::addr_t new_load_addr = section_sp->GetFileAddress() + base_addr;
- lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section_sp);
-
- // If the file address of the section is zero then this is not an
- // allocatable/loadable section (property of ELF sh_addr). Skip it.
- if (new_load_addr == base_addr)
- continue;
-
- if (old_load_addr == LLDB_INVALID_ADDRESS ||
- old_load_addr != new_load_addr)
- load_list.SetSectionLoadAddress(section_sp, new_load_addr);
- }
+ UpdateLoadedSectionsCommon(module, base_addr);
}
void
DynamicLoaderPOSIXDYLD::UnloadSections(const ModuleSP module)
{
- SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();
- const SectionList *sections = GetSectionListFromModule(module);
-
- assert(sections && "SectionList missing from unloaded module.");
-
m_loaded_modules.erase(module);
- const size_t num_sections = sections->GetSize();
- for (size_t i = 0; i < num_sections; ++i)
- {
- SectionSP section_sp (sections->GetSectionAtIndex(i));
- load_list.SetSectionUnloaded(section_sp);
- }
+ UnloadSectionsCommon(module);
}
void
@@ -470,26 +399,6 @@ DynamicLoaderPOSIXDYLD::LoadAllCurrentModules()
m_process->GetTarget().ModulesDidLoad(module_list);
}
-ModuleSP
-DynamicLoaderPOSIXDYLD::LoadModuleAtAddress(const FileSpec &file, addr_t link_map_addr, addr_t base_addr)
-{
- 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);
- }
- else if ((module_sp = target.GetSharedModule(module_spec)))
- {
- UpdateLoadedSections(module_sp, link_map_addr, base_addr);
- }
-
- return module_sp;
-}
-
addr_t
DynamicLoaderPOSIXDYLD::ComputeLoadOffset()
{
@@ -533,41 +442,6 @@ DynamicLoaderPOSIXDYLD::GetEntryPoint()
return m_entry_point;
}
-const SectionList *
-DynamicLoaderPOSIXDYLD::GetSectionListFromModule(const ModuleSP module) const
-{
- SectionList *sections = nullptr;
- if (module.get())
- {
- ObjectFile *obj_file = module->GetObjectFile();
- if (obj_file)
- {
- sections = obj_file->GetSectionList();
- }
- }
- return sections;
-}
-
-static int ReadInt(Process *process, addr_t addr)
-{
- Error error;
- int value = (int)process->ReadUnsignedIntegerFromMemory(addr, sizeof(uint32_t), 0, error);
- if (error.Fail())
- return -1;
- else
- return value;
-}
-
-static addr_t ReadPointer(Process *process, addr_t addr)
-{
- Error error;
- addr_t value = process->ReadPointerFromMemory(addr, error);
- if (error.Fail())
- return LLDB_INVALID_ADDRESS;
- else
- return value;
-}
-
lldb::addr_t
DynamicLoaderPOSIXDYLD::GetThreadLocalData (const lldb::ModuleSP module, const lldb::ThreadSP thread)
{
@@ -589,26 +463,27 @@ DynamicLoaderPOSIXDYLD::GetThreadLocalData (const lldb::ModuleSP module, const l
return LLDB_INVALID_ADDRESS;
// Find the module's modid.
- int modid = ReadInt (m_process, link_map + metadata.modid_offset);
+ int modid_size = 4; // FIXME(spucci): This isn't right for big-endian 64-bit
+ int64_t modid = ReadUnsignedIntWithSizeInBytes (link_map + metadata.modid_offset, modid_size);
if (modid == -1)
return LLDB_INVALID_ADDRESS;
// Lookup the DTV stucture for this thread.
addr_t dtv_ptr = tp + metadata.dtv_offset;
- addr_t dtv = ReadPointer (m_process, dtv_ptr);
+ addr_t dtv = ReadPointer (dtv_ptr);
if (dtv == LLDB_INVALID_ADDRESS)
return LLDB_INVALID_ADDRESS;
// Find the TLS block for this module.
addr_t dtv_slot = dtv + metadata.dtv_slot_size*modid;
- addr_t tls_block = ReadPointer (m_process, dtv_slot + metadata.tls_offset);
+ addr_t tls_block = ReadPointer (dtv_slot + metadata.tls_offset);
Module *mod = module.get();
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
if (log)
log->Printf("DynamicLoaderPOSIXDYLD::Performed TLS lookup: "
- "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 ", modid=%i, tls_block=0x%" PRIx64 "\n",
- mod->GetObjectName().AsCString(""), link_map, tp, modid, tls_block);
+ "module=%s, link_map=0x%" PRIx64 ", tp=0x%" PRIx64 ", modid=%" PRId64 ", tls_block=0x%" PRIx64 "\n",
+ mod->GetObjectName().AsCString(""), link_map, tp, (int64_t)modid, tls_block);
return tls_block;
}
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
index 7997b34195a4..9ced5da8a015 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h
@@ -126,7 +126,7 @@ protected:
/// @param link_map_addr The virtual address of the link map for the @p module.
///
/// @param base_addr The virtual base address @p module is loaded at.
- void
+ virtual void
UpdateLoadedSections(lldb::ModuleSP module,
lldb::addr_t link_map_addr,
lldb::addr_t base_addr);
@@ -134,14 +134,9 @@ protected:
/// Removes the loaded sections from the target in @p module.
///
/// @param module The module to traverse.
- void
+ virtual void
UnloadSections(const lldb::ModuleSP module);
- /// Locates or creates a module given by @p file and updates/loads the
- /// resulting module at the virtual base address @p base_addr.
- lldb::ModuleSP
- LoadModuleAtAddress(const lldb_private::FileSpec &file, lldb::addr_t link_map_addr, lldb::addr_t base_addr);
-
/// Resolves the entry point for the current inferior process and sets a
/// breakpoint at that address.
void
@@ -173,16 +168,8 @@ protected:
lldb::addr_t
GetEntryPoint();
- /// Checks to see if the target module has changed, updates the target
- /// accordingly and returns the target executable module.
- lldb::ModuleSP
- GetTargetExecutable();
-
private:
DISALLOW_COPY_AND_ASSIGN(DynamicLoaderPOSIXDYLD);
-
- const lldb_private::SectionList *
- GetSectionListFromModule(const lldb::ModuleSP module) const;
};
#endif // liblldb_DynamicLoaderPOSIXDYLD_H_
diff --git a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
index 274ba328ad1f..86cf45013a4d 100644
--- a/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
+++ b/source/Plugins/DynamicLoader/Static/DynamicLoaderStatic.cpp
@@ -134,7 +134,7 @@ DynamicLoaderStatic::LoadAllImagesAtFileAddresses ()
SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx));
if (section_sp)
{
- if (m_process->GetTarget().GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress()))
+ if (m_process->GetTarget().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress()))
changed = true;
}
}
diff --git a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
index db03f4536188..f1cb41d5a913 100644
--- a/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
+++ b/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp
@@ -289,37 +289,65 @@ EmulateInstructionARM::GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num, Reg
uint32_t
EmulateInstructionARM::GetFramePointerRegisterNumber () const
{
- if (m_opcode_mode == eModeThumb)
+ bool is_apple = false;
+ if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
+ is_apple = true;
+ switch (m_arch.GetTriple().getOS())
{
- switch (m_arch.GetTriple().getOS())
- {
case llvm::Triple::Darwin:
case llvm::Triple::MacOSX:
case llvm::Triple::IOS:
- return 7;
+ is_apple = true;
+ break;
default:
break;
- }
}
- return 11;
+
+ /* On Apple iOS et al, the frame pointer register is always r7.
+ * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
+ */
+
+ uint32_t fp_regnum = 11;
+
+ if (is_apple)
+ fp_regnum = 7;
+
+ if (m_opcode_mode == eModeThumb)
+ fp_regnum = 7;
+
+ return fp_regnum;
}
uint32_t
EmulateInstructionARM::GetFramePointerDWARFRegisterNumber () const
{
- if (m_opcode_mode == eModeThumb)
+ bool is_apple = false;
+ if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple)
+ is_apple = true;
+ switch (m_arch.GetTriple().getOS())
{
- switch (m_arch.GetTriple().getOS())
- {
case llvm::Triple::Darwin:
case llvm::Triple::MacOSX:
case llvm::Triple::IOS:
- return dwarf_r7;
+ is_apple = true;
+ break;
default:
break;
- }
}
- return dwarf_r11;
+
+ /* On Apple iOS et al, the frame pointer register is always r7.
+ * Typically on other ARM systems, thumb code uses r7; arm code uses r11.
+ */
+
+ uint32_t fp_regnum = dwarf_r11;
+
+ if (is_apple)
+ fp_regnum = dwarf_r7;
+
+ if (m_opcode_mode == eModeThumb)
+ fp_regnum = dwarf_r7;
+
+ return fp_regnum;
}
// Push Multiple Registers stores multiple registers to the stack, storing to
@@ -12889,18 +12917,18 @@ EmulateInstructionARM::ReadInstruction ()
{
if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
{
- m_opcode.SetOpcode16 (thumb_opcode);
+ m_opcode.SetOpcode16 (thumb_opcode, GetByteOrder());
}
else
{
- m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success));
+ m_opcode.SetOpcode32 ((thumb_opcode << 16) | MemARead(read_inst_context, pc + 2, 2, 0, &success), GetByteOrder());
}
}
}
else
{
m_opcode_mode = eModeARM;
- m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success));
+ m_opcode.SetOpcode32 (MemARead(read_inst_context, pc, 4, 0, &success), GetByteOrder());
}
}
}
@@ -13510,15 +13538,15 @@ EmulateInstructionARM::TestEmulation (Stream *out_stream, ArchSpec &arch, Option
if (arch.GetTriple().getArch() == llvm::Triple::arm)
{
m_opcode_mode = eModeARM;
- m_opcode.SetOpcode32 (test_opcode);
+ m_opcode.SetOpcode32 (test_opcode, GetByteOrder());
}
else if (arch.GetTriple().getArch() == llvm::Triple::thumb)
{
m_opcode_mode = eModeThumb;
if (test_opcode < 0x10000)
- m_opcode.SetOpcode16 (test_opcode);
+ m_opcode.SetOpcode16 (test_opcode, GetByteOrder());
else
- m_opcode.SetOpcode32 (test_opcode);
+ m_opcode.SetOpcode32 (test_opcode, GetByteOrder());
}
else
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index f3c2d63729ae..9781dcb093ac 100644
--- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -23,6 +23,7 @@
#include "lldb/Symbol/TypeList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StopInfo.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
@@ -402,7 +403,9 @@ ItaniumABILanguageRuntime::CreateExceptionBreakpoint (bool catch_bp,
FileSpecList filter_modules;
BreakpointResolverSP exception_resolver_sp = CreateExceptionResolver (NULL, catch_bp, throw_bp, for_expressions);
SearchFilterSP filter_sp (CreateExceptionSearchFilter ());
- return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal, false);
+ const bool hardware = false;
+ const bool resolve_indirect_functions = false;
+ return target.CreateBreakpoint (filter_sp, exception_resolver_sp, is_internal, hardware, resolve_indirect_functions);
}
void
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 7bdacfe14cde..02db05b3c6b2 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -24,6 +24,7 @@
#include "lldb/Core/Stream.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Host/Host.h"
@@ -462,6 +463,49 @@ ObjectFileELF::IsExecutable() const
return m_header.e_entry != 0;
}
+bool
+ObjectFileELF::SetLoadAddress (Target &target,
+ lldb::addr_t value,
+ bool value_is_offset)
+{
+ bool changed = false;
+ ModuleSP module_sp = GetModule();
+ if (module_sp)
+ {
+ size_t num_loaded_sections = 0;
+ SectionList *section_list = GetSectionList ();
+ if (section_list)
+ {
+ if (value_is_offset)
+ {
+ const size_t num_sections = section_list->GetSize();
+ size_t sect_idx = 0;
+
+ for (sect_idx = 0; sect_idx < num_sections; ++sect_idx)
+ {
+ // Iterate through the object file sections to find all
+ // of the sections that have SHF_ALLOC in their flag bits.
+ SectionSP section_sp (section_list->GetSectionAtIndex (sect_idx));
+ // if (section_sp && !section_sp->IsThreadSpecific())
+ if (section_sp && section_sp->Test(SHF_ALLOC))
+ {
+ if (target.GetSectionLoadList().SetSectionLoadAddress (section_sp, section_sp->GetFileAddress() + value))
+ ++num_loaded_sections;
+ }
+ }
+ changed = num_loaded_sections > 0;
+ return num_loaded_sections > 0;
+ }
+ else
+ {
+ // Not sure how to slide an ELF file given the base address
+ // of the ELF file in memory
+ }
+ }
+ }
+ return changed;
+}
+
ByteOrder
ObjectFileELF::GetByteOrder() const
{
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
index a2ab9b8f3703..9b7c073d902d 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.h
@@ -118,6 +118,11 @@ public:
virtual bool
ParseHeader();
+ virtual bool
+ SetLoadAddress (lldb_private::Target &target,
+ lldb::addr_t value,
+ bool value_is_offset);
+
virtual lldb::ByteOrder
GetByteOrder() const;
diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
index 37b324197350..7ca337e797da 100644
--- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
+++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.cpp
@@ -190,6 +190,13 @@ OperatingSystemPython::UpdateThreadList (ThreadList &old_thread_list,
auto lock = m_interpreter->AcquireInterpreterLock(); // to make sure threads_list stays alive
PythonList threads_list(m_interpreter->OSPlugin_ThreadsInfo(m_python_object_sp));
+
+ const uint32_t num_cores = core_thread_list.GetSize(false);
+
+ // Make a map so we can keep track of which cores were used from the
+ // core_thread list. Any real threads/cores that weren't used should
+ // later be put back into the "new_thread_list".
+ std::vector<bool> core_used_map(num_cores, false);
if (threads_list)
{
if (log)
@@ -207,18 +214,26 @@ OperatingSystemPython::UpdateThreadList (ThreadList &old_thread_list,
PythonDictionary thread_dict(threads_list.GetItemAtIndex(i));
if (thread_dict)
{
- ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_dict, core_thread_list, old_thread_list, NULL));
+ ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_dict, core_thread_list, old_thread_list, core_used_map, NULL));
if (thread_sp)
new_thread_list.AddThread(thread_sp);
}
}
}
}
-
- // No new threads added from the thread info array gotten from python, just
- // display the core threads.
- if (new_thread_list.GetSize(false) == 0)
- new_thread_list = core_thread_list;
+
+ // Any real core threads that didn't end up backing a memory thread should
+ // still be in the main thread list, and they should be inserted at the beginning
+ // of the list
+ uint32_t insert_idx = 0;
+ for (uint32_t core_idx = 0; core_idx < num_cores; ++core_idx)
+ {
+ if (core_used_map[core_idx] == false)
+ {
+ new_thread_list.InsertThread (core_thread_list.GetThreadAtIndex(core_idx, false), insert_idx);
+ ++insert_idx;
+ }
+ }
return new_thread_list.GetSize(false) > 0;
}
@@ -227,6 +242,7 @@ ThreadSP
OperatingSystemPython::CreateThreadFromThreadInfo (PythonDictionary &thread_dict,
ThreadList &core_thread_list,
ThreadList &old_thread_list,
+ std::vector<bool> &core_used_map,
bool *did_create_ptr)
{
ThreadSP thread_sp;
@@ -282,6 +298,10 @@ OperatingSystemPython::CreateThreadFromThreadInfo (PythonDictionary &thread_dict
ThreadSP core_thread_sp (core_thread_list.GetThreadAtIndex(core_number, false));
if (core_thread_sp)
{
+ // Keep track of which cores were set as the backing thread for memory threads...
+ if (core_number < core_used_map.size())
+ core_used_map[core_number] = true;
+
ThreadSP backing_core_thread_sp (core_thread_sp->GetBackingThread());
if (backing_core_thread_sp)
{
@@ -398,12 +418,13 @@ OperatingSystemPython::CreateThread (lldb::tid_t tid, addr_t context)
auto lock = m_interpreter->AcquireInterpreterLock(); // to make sure thread_info_dict stays alive
PythonDictionary thread_info_dict (m_interpreter->OSPlugin_CreateThread(m_python_object_sp, tid, context));
+ std::vector<bool> core_used_map;
if (thread_info_dict)
{
ThreadList core_threads(m_process);
ThreadList &thread_list = m_process->GetThreadList();
bool did_create = false;
- ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_info_dict, core_threads, thread_list, &did_create));
+ ThreadSP thread_sp (CreateThreadFromThreadInfo (thread_info_dict, core_threads, thread_list, core_used_map, &did_create));
if (did_create)
thread_list.AddThread(thread_sp);
return thread_sp;
diff --git a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
index 077039e50d56..3b7dd264dc62 100644
--- a/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
+++ b/source/Plugins/OperatingSystem/Python/OperatingSystemPython.h
@@ -93,6 +93,7 @@ protected:
CreateThreadFromThreadInfo (lldb_private::PythonDictionary &thread_dict,
lldb_private::ThreadList &core_thread_list,
lldb_private::ThreadList &old_thread_list,
+ std::vector<bool> &core_used_map,
bool *did_create_ptr);
DynamicRegisterInfo *
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
index da29c16ac3ab..7eca67ac7f57 100644
--- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
+++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
@@ -142,7 +142,8 @@ PlatformFreeBSD::Terminate ()
/// Default Constructor
//------------------------------------------------------------------
PlatformFreeBSD::PlatformFreeBSD (bool is_host) :
-Platform(is_host)
+Platform(is_host),
+m_remote_platform_sp()
{
}
@@ -312,6 +313,7 @@ PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite
case ArchSpec::eCore_x86_32_i386:
case ArchSpec::eCore_x86_64_x86_64:
+ case ArchSpec::eCore_x86_64_x86_64h:
{
static const uint8_t g_i386_opcode[] = { 0xCC };
trap_opcode = g_i386_opcode;
@@ -571,14 +573,14 @@ PlatformFreeBSD::GetGroupName (uint32_t gid)
// From PlatformMacOSX only
Error
-PlatformFreeBSD::GetFile (const FileSpec &platform_file,
- const UUID *uuid_ptr,
- FileSpec &local_file)
+PlatformFreeBSD::GetFileWithUUID (const FileSpec &platform_file,
+ const UUID *uuid_ptr,
+ FileSpec &local_file)
{
if (IsRemote())
{
if (m_remote_platform_sp)
- return m_remote_platform_sp->GetFile (platform_file, uuid_ptr, local_file);
+ return m_remote_platform_sp->GetFileWithUUID (platform_file, uuid_ptr, local_file);
}
// Default to the local case
@@ -673,3 +675,9 @@ PlatformFreeBSD::GetStatus (Stream &strm)
Platform::GetStatus(strm);
}
+
+void
+PlatformFreeBSD::CalculateTrapHandlerSymbolNames ()
+{
+ m_trap_handlers.push_back (ConstString ("_sigtramp"));
+}
diff --git a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
index 11d1cd609779..0682eacc5a43 100644
--- a/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
+++ b/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.h
@@ -144,8 +144,8 @@ public:
// Only on PlatformMacOSX:
virtual lldb_private::Error
- GetFile (const lldb_private::FileSpec &platform_file,
- const lldb_private::UUID* uuid, lldb_private::FileSpec &local_file);
+ GetFileWithUUID (const lldb_private::FileSpec &platform_file,
+ const lldb_private::UUID* uuid, lldb_private::FileSpec &local_file);
lldb_private::Error
GetSharedModule (const lldb_private::ModuleSpec &module_spec,
@@ -160,6 +160,9 @@ public:
virtual void
GetStatus (lldb_private::Stream &strm);
+ virtual void
+ CalculateTrapHandlerSymbolNames ();
+
protected:
lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote freebsd OS
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
index b5f92dcc3dcd..bb07d999c4c2 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.cpp
@@ -589,3 +589,8 @@ PlatformPOSIX::SetRemoteWorkingDirectory(const lldb_private::ConstString &path)
return Platform::SetRemoteWorkingDirectory(path);
}
+void
+PlatformPOSIX::CalculateTrapHandlerSymbolNames ()
+{
+ m_trap_handlers.push_back (ConstString ("_sigtramp"));
+}
diff --git a/source/Plugins/Platform/POSIX/PlatformPOSIX.h b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
index 336e0f90fcad..130c84bdface 100644
--- a/source/Plugins/Platform/POSIX/PlatformPOSIX.h
+++ b/source/Plugins/Platform/POSIX/PlatformPOSIX.h
@@ -111,8 +111,11 @@ public:
uint64_t &low,
uint64_t &high);
+ virtual void
+ CalculateTrapHandlerSymbolNames ();
+
protected:
- std::auto_ptr<lldb_private::OptionGroupOptions> m_options;
+ std::unique_ptr<lldb_private::OptionGroupOptions> m_options;
lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote POSIX-compliant OS
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
index 248abaf6fea7..ce5645ea74fe 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.cpp
@@ -119,9 +119,9 @@ PlatformRemoteGDBServer::ResolveExecutable (const FileSpec &exe_file,
}
Error
-PlatformRemoteGDBServer::GetFile (const FileSpec &platform_file,
- const UUID *uuid_ptr,
- FileSpec &local_file)
+PlatformRemoteGDBServer::GetFileWithUUID (const FileSpec &platform_file,
+ const UUID *uuid_ptr,
+ FileSpec &local_file)
{
// Default to the local case
local_file = platform_file;
@@ -418,7 +418,21 @@ PlatformRemoteGDBServer::DebugProcess (lldb_private::ProcessLaunchInfo &launch_i
if (IsConnected())
{
lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
- uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid);
+ ArchSpec remote_arch = GetRemoteSystemArchitecture();
+ llvm::Triple &remote_triple = remote_arch.GetTriple();
+ uint16_t port = 0;
+ if (remote_triple.getVendor() == llvm::Triple::Apple && remote_triple.getOS() == llvm::Triple::IOS)
+ {
+ // When remote debugging to iOS, we use a USB mux that always talks
+ // to localhost, so we will need the remote debugserver to accept connections
+ // only from localhost, no matter what our current hostname is
+ port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, "localhost");
+ }
+ else
+ {
+ // All other hosts should use their actual hostname
+ port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, NULL);
+ }
if (port == 0)
{
@@ -492,7 +506,21 @@ PlatformRemoteGDBServer::Attach (lldb_private::ProcessAttachInfo &attach_info,
if (IsConnected())
{
lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
- uint16_t port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid);
+ ArchSpec remote_arch = GetRemoteSystemArchitecture();
+ llvm::Triple &remote_triple = remote_arch.GetTriple();
+ uint16_t port = 0;
+ if (remote_triple.getVendor() == llvm::Triple::Apple && remote_triple.getOS() == llvm::Triple::IOS)
+ {
+ // When remote debugging to iOS, we use a USB mux that always talks
+ // to localhost, so we will need the remote debugserver to accept connections
+ // only from localhost, no matter what our current hostname is
+ port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, "localhost");
+ }
+ else
+ {
+ // All other hosts should use their actual hostname
+ port = m_gdb_client.LaunchGDBserverAndGetPort(debugserver_pid, NULL);
+ }
if (port == 0)
{
@@ -673,3 +701,9 @@ PlatformRemoteGDBServer::RunShellCommand (const char *command, // Shou
{
return m_gdb_client.RunShellCommand (command, working_dir, status_ptr, signo_ptr, command_output, timeout_sec);
}
+
+void
+PlatformRemoteGDBServer::CalculateTrapHandlerSymbolNames ()
+{
+ m_trap_handlers.push_back (ConstString ("_sigtramp"));
+}
diff --git a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
index 808fb5ed61cc..e236e97c8bb3 100644
--- a/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
+++ b/source/Plugins/Platform/gdb-server/PlatformRemoteGDBServer.h
@@ -73,9 +73,9 @@ public:
GetDescription ();
virtual lldb_private::Error
- GetFile (const lldb_private::FileSpec &platform_file,
- const lldb_private::UUID *uuid_ptr,
- lldb_private::FileSpec &local_file);
+ GetFileWithUUID (const lldb_private::FileSpec &platform_file,
+ const lldb_private::UUID *uuid_ptr,
+ lldb_private::FileSpec &local_file);
virtual bool
GetProcessInfo (lldb::pid_t pid,
@@ -209,6 +209,9 @@ public:
std::string *command_output, // Pass NULL if you don't want the command output
uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish
+ virtual void
+ CalculateTrapHandlerSymbolNames ();
+
protected:
GDBRemoteCommunicationClient m_gdb_client;
std::string m_platform_description; // After we connect we can get a more complete description of what we are connected to
diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
new file mode 100644
index 000000000000..493f36ca8b48
--- /dev/null
+++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
@@ -0,0 +1,69 @@
+//===-- FreeBSDThread.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/State.h"
+
+// Project includes
+#include "FreeBSDThread.h"
+#include "ProcessFreeBSD.h"
+#include "ProcessPOSIXLog.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//------------------------------------------------------------------------------
+// Constructors and destructors.
+
+FreeBSDThread::FreeBSDThread(Process &process, lldb::tid_t tid)
+ : POSIXThread(process, tid)
+{
+}
+
+FreeBSDThread::~FreeBSDThread()
+{
+}
+
+//------------------------------------------------------------------------------
+// ProcessInterface protocol.
+
+void
+FreeBSDThread::WillResume(lldb::StateType resume_state)
+{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log)
+ log->Printf("tid %lu resume_state = %s", GetID(),
+ lldb_private::StateAsCString(resume_state));
+ ProcessSP process_sp(GetProcess());
+ ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(process_sp.get());
+ int signo = GetResumeSignal();
+ bool signo_valid = process->GetUnixSignals().SignalIsValid(signo);
+
+ switch (resume_state)
+ {
+ case eStateSuspended:
+ case eStateStopped:
+ process->m_suspend_tids.push_back(GetID());
+ break;
+ case eStateRunning:
+ process->m_run_tids.push_back(GetID());
+ if (signo_valid)
+ process->m_resume_signo = signo;
+ break;
+ case eStateStepping:
+ process->m_step_tids.push_back(GetID());
+ if (signo_valid)
+ process->m_resume_signo = signo;
+ break;
+ default:
+ break;
+ }
+}
diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.h b/source/Plugins/Process/FreeBSD/FreeBSDThread.h
new file mode 100644
index 000000000000..8741075cb60b
--- /dev/null
+++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.h
@@ -0,0 +1,39 @@
+//===-- FreeBSDThread.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_FreeBSDThread_H_
+#define liblldb_FreeBSDThread_H_
+
+// Other libraries and framework includes
+#include "POSIXThread.h"
+
+//------------------------------------------------------------------------------
+// @class FreeBSDThread
+// @brief Abstraction of a FreeBSD thread.
+class FreeBSDThread
+ : public POSIXThread
+{
+public:
+
+ //------------------------------------------------------------------
+ // Constructors and destructors
+ //------------------------------------------------------------------
+ FreeBSDThread(lldb_private::Process &process, lldb::tid_t tid);
+
+ virtual ~FreeBSDThread();
+
+ //--------------------------------------------------------------------------
+ // FreeBSDThread internal API.
+
+ // POSIXThread override
+ virtual void
+ WillResume(lldb::StateType resume_state);
+};
+
+#endif // #ifndef liblldb_FreeBSDThread_H_
diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
index 952ec95f5873..083f08ebba84 100644
--- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
@@ -23,7 +23,7 @@
#include "ProcessPOSIXLog.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
#include "ProcessMonitor.h"
-#include "POSIXThread.h"
+#include "FreeBSDThread.h"
using namespace lldb;
using namespace lldb_private;
@@ -140,29 +140,136 @@ ProcessFreeBSD::DoDetach(bool keep_stopped)
return error;
}
+Error
+ProcessFreeBSD::DoResume()
+{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
+ // FreeBSD's ptrace() uses 0 to indicate "no signal is to be sent."
+ int resume_signal = 0;
+
+ SetPrivateState(eStateRunning);
+
+ Mutex::Locker lock(m_thread_list.GetMutex());
+ bool do_step = false;
+
+ for (tid_collection::const_iterator t_pos = m_run_tids.begin(), t_end = m_run_tids.end(); t_pos != t_end; ++t_pos)
+ {
+ m_monitor->ThreadSuspend(*t_pos, false);
+ }
+ for (tid_collection::const_iterator t_pos = m_step_tids.begin(), t_end = m_step_tids.end(); t_pos != t_end; ++t_pos)
+ {
+ m_monitor->ThreadSuspend(*t_pos, false);
+ do_step = true;
+ }
+ for (tid_collection::const_iterator t_pos = m_suspend_tids.begin(), t_end = m_suspend_tids.end(); t_pos != t_end; ++t_pos)
+ {
+ m_monitor->ThreadSuspend(*t_pos, true);
+ // XXX Cannot PT_CONTINUE properly with suspended threads.
+ do_step = true;
+ }
+
+ if (log)
+ log->Printf("process %lu resuming (%s)", GetID(), do_step ? "step" : "continue");
+ if (do_step)
+ m_monitor->SingleStep(GetID(), resume_signal);
+ else
+ m_monitor->Resume(GetID(), resume_signal);
+
+ return Error();
+}
+
bool
ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessFreeBSD::%s() (pid = %" PRIu64 ")", __FUNCTION__, GetID());
-
- bool has_updated = false;
- const lldb::pid_t pid = GetID();
- // Update the process thread list with this new thread.
- // FIXME: We should be using tid, not pid.
- assert(m_monitor);
- ThreadSP thread_sp (old_thread_list.FindThreadByID (pid, false));
- if (!thread_sp) {
- ProcessSP me = this->shared_from_this();
- thread_sp.reset(new POSIXThread(*me, pid));
- has_updated = true;
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+ if (log)
+ log->Printf("ProcessFreeBSD::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID());
+
+ std::vector<lldb::pid_t> tds;
+ if (!GetMonitor().GetCurrentThreadIDs(tds))
+ {
+ return false;
}
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessFreeBSD::%s() updated tid = %" PRIu64, __FUNCTION__, pid);
+ ThreadList old_thread_list_copy(old_thread_list);
+ for (size_t i = 0; i < tds.size(); ++i)
+ {
+ tid_t tid = tds[i];
+ ThreadSP thread_sp (old_thread_list_copy.RemoveThreadByID(tid, false));
+ if (!thread_sp)
+ {
+ thread_sp.reset(new FreeBSDThread(*this, tid));
+ if (log)
+ log->Printf("ProcessFreeBSD::%s new tid = %" PRIu64, __FUNCTION__, tid);
+ }
+ else
+ {
+ if (log)
+ log->Printf("ProcessFreeBSD::%s existing tid = %" PRIu64, __FUNCTION__, tid);
+ }
+ new_thread_list.AddThread(thread_sp);
+ }
+ for (size_t i = 0; i < old_thread_list_copy.GetSize(false); ++i)
+ {
+ ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false));
+ if (old_thread_sp)
+ {
+ if (log)
+ log->Printf("ProcessFreeBSD::%s remove tid", __FUNCTION__);
+ }
+ }
- new_thread_list.AddThread(thread_sp);
+ return true;
+}
- return has_updated; // the list has been updated
+Error
+ProcessFreeBSD::WillResume()
+{
+ m_suspend_tids.clear();
+ m_run_tids.clear();
+ m_step_tids.clear();
+ return ProcessPOSIX::WillResume();
}
+
+void
+ProcessFreeBSD::SendMessage(const ProcessMessage &message)
+{
+ Mutex::Locker lock(m_message_mutex);
+
+ switch (message.GetKind())
+ {
+ case ProcessMessage::eInvalidMessage:
+ return;
+
+ case ProcessMessage::eAttachMessage:
+ SetPrivateState(eStateStopped);
+ return;
+
+ case ProcessMessage::eLimboMessage:
+ case ProcessMessage::eExitMessage:
+ m_exit_status = message.GetExitStatus();
+ SetExitStatus(m_exit_status, NULL);
+ break;
+
+ case ProcessMessage::eSignalMessage:
+ case ProcessMessage::eSignalDeliveredMessage:
+ case ProcessMessage::eBreakpointMessage:
+ case ProcessMessage::eTraceMessage:
+ case ProcessMessage::eWatchpointMessage:
+ case ProcessMessage::eCrashMessage:
+ SetPrivateState(eStateStopped);
+ break;
+
+ case ProcessMessage::eNewThreadMessage:
+ assert(0 && "eNewThreadMessage unexpected on FreeBSD");
+ break;
+
+ case ProcessMessage::eExecMessage:
+ SetPrivateState(eStateStopped);
+ break;
+ }
+
+ m_message_queue.push(message);
+}
+
diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
index fb549745b80c..d6ae3462c73b 100644
--- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
+++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
@@ -60,6 +60,15 @@ public:
virtual bool
UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list);
+ virtual lldb_private::Error
+ DoResume();
+
+ virtual lldb_private::Error
+ WillResume();
+
+ virtual void
+ SendMessage(const ProcessMessage &message);
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -80,6 +89,16 @@ public:
EnablePluginLogging(lldb_private::Stream *strm,
lldb_private::Args &command);
+protected:
+ friend class FreeBSDThread;
+
+ typedef std::vector<lldb::tid_t> tid_collection;
+ tid_collection m_suspend_tids;
+ tid_collection m_run_tids;
+ tid_collection m_step_tids;
+
+ int m_resume_signo;
+
};
-#endif // liblldb_MacOSXProcess_H_
+#endif // liblldb_ProcessFreeBSD_H_
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index ac5357916501..3b260538b190 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -560,6 +560,31 @@ LwpInfoOperation::Execute(ProcessMonitor *monitor)
}
//------------------------------------------------------------------------------
+/// @class ThreadSuspendOperation
+/// @brief Implements ProcessMonitor::ThreadSuspend.
+class ThreadSuspendOperation : public Operation
+{
+public:
+ ThreadSuspendOperation(lldb::tid_t tid, bool suspend, bool &result)
+ : m_tid(tid), m_suspend(suspend), m_result(result) { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ lldb::tid_t m_tid;
+ bool m_suspend;
+ bool &m_result;
+} ;
+
+void
+ThreadSuspendOperation::Execute(ProcessMonitor *monitor)
+{
+ m_result = !PTRACE(m_suspend ? PT_SUSPEND : PT_RESUME, m_tid, NULL, 0);
+}
+
+
+
+//------------------------------------------------------------------------------
/// @class EventMessageOperation
/// @brief Implements ProcessMonitor::GetEventMessage.
class EventMessageOperation : public Operation
@@ -871,7 +896,8 @@ ProcessMonitor::Launch(LaunchArgs *args)
eDupStdoutFailed,
eDupStderrFailed,
eChdirFailed,
- eExecFailed
+ eExecFailed,
+ eSetGidFailed
};
// Child process.
@@ -882,7 +908,8 @@ ProcessMonitor::Launch(LaunchArgs *args)
exit(ePtraceFailed);
// Do not inherit setgid powers.
- setgid(getgid());
+ if (setgid(getgid()) != 0)
+ exit(eSetGidFailed);
// Let us have our own process group.
setpgid(0, 0);
@@ -947,6 +974,9 @@ ProcessMonitor::Launch(LaunchArgs *args)
case eExecFailed:
args->m_error.SetErrorString("Child exec failed.");
break;
+ case eSetGidFailed:
+ args->m_error.SetErrorString("Child setgid failed.");
+ break;
default:
args->m_error.SetErrorString("Child returned unknown exit status.");
break;
@@ -1041,6 +1071,29 @@ FINISH:
return args->m_error.Success();
}
+size_t
+ProcessMonitor::GetCurrentThreadIDs(std::vector<lldb::tid_t>&thread_ids)
+{
+ lwpid_t *tids;
+ int tdcnt;
+
+ thread_ids.clear();
+
+ tdcnt = PTRACE(PT_GETNUMLWPS, m_pid, NULL, 0);
+ if (tdcnt <= 0)
+ return 0;
+ tids = (lwpid_t *)malloc(tdcnt * sizeof(*tids));
+ if (tids == NULL)
+ return 0;
+ if (PTRACE(PT_GETLWPLIST, m_pid, (void *)tids, tdcnt) < 0) {
+ free(tids);
+ return 0;
+ }
+ thread_ids = std::vector<lldb::tid_t>(tids, tids + tdcnt);
+ free(tids);
+ return thread_ids.size();
+}
+
bool
ProcessMonitor::MonitorCallback(void *callback_baton,
lldb::pid_t pid,
@@ -1073,11 +1126,11 @@ ProcessMonitor::MonitorCallback(void *callback_baton,
switch (plwp.pl_siginfo.si_signo)
{
case SIGTRAP:
- message = MonitorSIGTRAP(monitor, &plwp.pl_siginfo, pid);
+ message = MonitorSIGTRAP(monitor, &plwp.pl_siginfo, plwp.pl_lwpid);
break;
default:
- message = MonitorSignal(monitor, &plwp.pl_siginfo, pid);
+ message = MonitorSignal(monitor, &plwp.pl_siginfo, plwp.pl_lwpid);
break;
}
@@ -1090,7 +1143,7 @@ ProcessMonitor::MonitorCallback(void *callback_baton,
ProcessMessage
ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor,
- const siginfo_t *info, lldb::pid_t pid)
+ const siginfo_t *info, lldb::tid_t tid)
{
ProcessMessage message;
@@ -1111,26 +1164,26 @@ ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor,
// state of "limbo" until we are explicitly commanded to detach,
// destroy, resume, etc.
unsigned long data = 0;
- if (!monitor->GetEventMessage(pid, &data))
+ if (!monitor->GetEventMessage(tid, &data))
data = -1;
if (log)
- log->Printf ("ProcessMonitor::%s() received exit? event, data = %lx, pid = %" PRIu64, __FUNCTION__, data, pid);
- message = ProcessMessage::Limbo(pid, (data >> 8));
+ log->Printf ("ProcessMonitor::%s() received exit? event, data = %lx, tid = %" PRIu64, __FUNCTION__, data, tid);
+ message = ProcessMessage::Limbo(tid, (data >> 8));
break;
}
case 0:
case TRAP_TRACE:
if (log)
- log->Printf ("ProcessMonitor::%s() received trace event, pid = %" PRIu64, __FUNCTION__, pid);
- message = ProcessMessage::Trace(pid);
+ log->Printf ("ProcessMonitor::%s() received trace event, tid = %" PRIu64, __FUNCTION__, tid);
+ message = ProcessMessage::Trace(tid);
break;
case SI_KERNEL:
case TRAP_BRKPT:
if (log)
- log->Printf ("ProcessMonitor::%s() received breakpoint event, pid = %" PRIu64, __FUNCTION__, pid);
- message = ProcessMessage::Break(pid);
+ log->Printf ("ProcessMonitor::%s() received breakpoint event, tid = %" PRIu64, __FUNCTION__, tid);
+ message = ProcessMessage::Break(tid);
break;
}
@@ -1139,7 +1192,7 @@ ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor,
ProcessMessage
ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
- const siginfo_t *info, lldb::pid_t pid)
+ const siginfo_t *info, lldb::tid_t tid)
{
ProcessMessage message;
int signo = info->si_signo;
@@ -1163,9 +1216,9 @@ ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
"SI_USER",
info->si_pid);
if (info->si_pid == getpid())
- return ProcessMessage::SignalDelivered(pid, signo);
+ return ProcessMessage::SignalDelivered(tid, signo);
else
- return ProcessMessage::Signal(pid, signo);
+ return ProcessMessage::Signal(tid, signo);
}
if (log)
@@ -1174,30 +1227,30 @@ ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
if (signo == SIGSEGV) {
lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
ProcessMessage::CrashReason reason = GetCrashReasonForSIGSEGV(info);
- return ProcessMessage::Crash(pid, reason, signo, fault_addr);
+ return ProcessMessage::Crash(tid, reason, signo, fault_addr);
}
if (signo == SIGILL) {
lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
ProcessMessage::CrashReason reason = GetCrashReasonForSIGILL(info);
- return ProcessMessage::Crash(pid, reason, signo, fault_addr);
+ return ProcessMessage::Crash(tid, reason, signo, fault_addr);
}
if (signo == SIGFPE) {
lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
ProcessMessage::CrashReason reason = GetCrashReasonForSIGFPE(info);
- return ProcessMessage::Crash(pid, reason, signo, fault_addr);
+ return ProcessMessage::Crash(tid, reason, signo, fault_addr);
}
if (signo == SIGBUS) {
lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
ProcessMessage::CrashReason reason = GetCrashReasonForSIGBUS(info);
- return ProcessMessage::Crash(pid, reason, signo, fault_addr);
+ return ProcessMessage::Crash(tid, reason, signo, fault_addr);
}
// Everything else is "normal" and does not require any special action on
// our part.
- return ProcessMessage::Signal(pid, signo);
+ return ProcessMessage::Signal(tid, signo);
}
ProcessMessage::CrashReason
@@ -1508,6 +1561,15 @@ ProcessMonitor::GetLwpInfo(lldb::tid_t tid, void *lwpinfo, int &ptrace_err)
}
bool
+ProcessMonitor::ThreadSuspend(lldb::tid_t tid, bool suspend)
+{
+ bool result;
+ ThreadSuspendOperation op(tid, suspend, result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
ProcessMonitor::GetEventMessage(lldb::tid_t tid, unsigned long *message)
{
bool result;
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
index 44219c4eb9e3..84bbac16e5e5 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
@@ -104,8 +104,6 @@ public:
/// dependent) offset.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
- /// FIXME: The FreeBSD implementation of this function should use tid in order
- /// to enable support for debugging threaded programs.
bool
ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
unsigned size, lldb_private::RegisterValue &value);
@@ -114,49 +112,35 @@ public:
/// (architecture dependent) offset.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
- /// FIXME: The FreeBSD implementation of this function should use tid in order
- /// to enable support for debugging threaded programs.
bool
WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
const lldb_private::RegisterValue &value);
/// Reads all general purpose registers into the specified buffer.
- /// FIXME: The FreeBSD implementation of this function should use tid in order
- /// to enable support for debugging threaded programs.
bool
ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size);
/// Reads all floating point registers into the specified buffer.
- /// FIXME: The FreeBSD implementation of this function should use tid in order
- /// to enable support for debugging threaded programs.
bool
ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);
/// Reads the specified register set into the specified buffer.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
- /// FIXME: The FreeBSD implementation of this function should use tid in order
- /// to enable support for debugging threaded programs.
bool
ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
/// Writes all general purpose registers into the specified buffer.
- /// FIXME: The FreeBSD implementation of this function should use tid in order
- /// to enable support for debugging threaded programs.
bool
WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size);
/// Writes all floating point registers into the specified buffer.
- /// FIXME: The FreeBSD implementation of this function should use tid in order
- /// to enable support for debugging threaded programs.
bool
WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size);
/// Writes the specified register set into the specified buffer.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
- /// FIXME: The FreeBSD implementation of this function should use tid in order
- /// to enable support for debugging threaded programs.
bool
WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
@@ -164,11 +148,19 @@ public:
bool
ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value);
+ /// Returns current thread IDs in process
+ size_t
+ GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids);
+
/// Writes a ptrace_lwpinfo structure corresponding to the given thread ID
/// to the memory region pointed to by @p lwpinfo.
bool
GetLwpInfo(lldb::tid_t tid, void *lwpinfo, int &error_no);
+ /// Suspends or unsuspends a thread prior to process resume or step.
+ bool
+ ThreadSuspend(lldb::tid_t tid, bool suspend);
+
/// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
/// corresponding to the given thread IDto the memory pointed to by @p
/// message.
diff --git a/source/Plugins/Process/POSIX/POSIXThread.cpp b/source/Plugins/Process/POSIX/POSIXThread.cpp
index 16399748c544..8d4c71ff269a 100644
--- a/source/Plugins/Process/POSIX/POSIXThread.cpp
+++ b/source/Plugins/Process/POSIX/POSIXThread.cpp
@@ -83,6 +83,7 @@ POSIXThread::GetMonitor()
return process.GetMonitor();
}
+// Overridden by FreeBSDThread; this is used only on Linux.
void
POSIXThread::RefreshStateAfterStop()
{
@@ -150,8 +151,6 @@ POSIXThread::GetRegisterContext()
{
case ArchSpec::eCore_mips64:
{
- RegisterInfoInterface *reg_interface = NULL;
-
switch (target_arch.GetTriple().getOS())
{
case llvm::Triple::FreeBSD:
@@ -257,6 +256,7 @@ POSIXThread::GetUnwinder()
return m_unwinder_ap.get();
}
+// Overridden by FreeBSDThread; this is used only on Linux.
void
POSIXThread::WillResume(lldb::StateType resume_state)
{
diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
index 70ad3a66d9ef..62394623c59d 100644
--- a/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
+++ b/source/Plugins/Process/POSIX/ProcessPOSIX.cpp
@@ -200,7 +200,7 @@ ProcessPOSIX::GetFilePath(
Error
ProcessPOSIX::DoLaunch (Module *module,
- const ProcessLaunchInfo &launch_info)
+ ProcessLaunchInfo &launch_info)
{
Error error;
assert(m_monitor == NULL);
@@ -632,20 +632,6 @@ ProcessPOSIX::DoDeallocateMemory(lldb::addr_t addr)
return error;
}
-addr_t
-ProcessPOSIX::ResolveIndirectFunction(const Address *address, Error &error)
-{
- addr_t function_addr = LLDB_INVALID_ADDRESS;
- if (address == NULL) {
- error.SetErrorStringWithFormat("unable to determine direct function call for NULL address");
- } else if (!InferiorCall(this, address, function_addr)) {
- function_addr = LLDB_INVALID_ADDRESS;
- error.SetErrorStringWithFormat("unable to determine direct function call for indirect function %s",
- address->CalculateSymbolContextSymbol()->GetName().AsCString());
- }
- return function_addr;
-}
-
size_t
ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
{
diff --git a/source/Plugins/Process/POSIX/ProcessPOSIX.h b/source/Plugins/Process/POSIX/ProcessPOSIX.h
index 790041be321a..7f705d33fe68 100644
--- a/source/Plugins/Process/POSIX/ProcessPOSIX.h
+++ b/source/Plugins/Process/POSIX/ProcessPOSIX.h
@@ -58,7 +58,7 @@ public:
virtual lldb_private::Error
DoLaunch (lldb_private::Module *exe_module,
- const lldb_private::ProcessLaunchInfo &launch_info);
+ lldb_private::ProcessLaunchInfo &launch_info);
virtual void
DidLaunch();
@@ -104,9 +104,6 @@ public:
virtual lldb_private::Error
DoDeallocateMemory(lldb::addr_t ptr);
- virtual lldb::addr_t
- ResolveIndirectFunction(const lldb_private::Address *address, lldb_private::Error &error);
-
virtual size_t
GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite* bp_site);
@@ -148,7 +145,8 @@ public:
// ProcessPOSIX internal API.
/// Registers the given message with this process.
- void SendMessage(const ProcessMessage &message);
+ virtual void
+ SendMessage(const ProcessMessage &message);
ProcessMonitor &
GetMonitor() { assert(m_monitor); return *m_monitor; }
diff --git a/source/Plugins/Process/Utility/HistoryThread.cpp b/source/Plugins/Process/Utility/HistoryThread.cpp
index 521136295fd5..d045bc7e10d7 100644
--- a/source/Plugins/Process/Utility/HistoryThread.cpp
+++ b/source/Plugins/Process/Utility/HistoryThread.cpp
@@ -25,7 +25,7 @@ HistoryThread::HistoryThread (lldb_private::Process &process,
std::vector<lldb::addr_t> pcs,
uint32_t stop_id,
bool stop_id_is_valid) :
- Thread (process, LLDB_INVALID_THREAD_ID),
+ Thread (process, tid),
m_framelist_mutex(),
m_framelist(),
m_pcs (pcs),
diff --git a/source/Plugins/Process/Utility/HistoryThread.h b/source/Plugins/Process/Utility/HistoryThread.h
index 01fdd1608706..f9a431d8340b 100644
--- a/source/Plugins/Process/Utility/HistoryThread.h
+++ b/source/Plugins/Process/Utility/HistoryThread.h
@@ -22,6 +22,16 @@
namespace lldb_private {
+//----------------------------------------------------------------------
+/// @class HistoryThread HistoryThread.h "HistoryThread.h"
+/// @brief A thread object representing a backtrace from a previous point in the process execution
+///
+/// This subclass of Thread is used to provide a backtrace from earlier in
+/// process execution. It is given a backtrace list of pc addresses and
+/// optionally a stop_id of when those pc addresses were collected, and it will
+/// create stack frames for them.
+//----------------------------------------------------------------------
+
class HistoryThread : public lldb_private::Thread
{
public:
diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index 6d1b04f7f1a7..1d5d19fad25f 100644
--- a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -34,9 +34,16 @@
using namespace lldb;
using namespace lldb_private;
-bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
- addr_t addr, addr_t length, unsigned prot,
- unsigned flags, addr_t fd, addr_t offset) {
+bool
+lldb_private::InferiorCallMmap (Process *process,
+ addr_t &allocated_addr,
+ addr_t addr,
+ addr_t length,
+ unsigned prot,
+ unsigned flags,
+ addr_t fd,
+ addr_t offset)
+{
Thread *thread = process->GetThreadList().GetSelectedThread().get();
if (thread == NULL)
return false;
@@ -139,8 +146,11 @@ bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
return false;
}
-bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
- addr_t length) {
+bool
+lldb_private::InferiorCallMunmap (Process *process,
+ addr_t addr,
+ addr_t length)
+{
Thread *thread = process->GetThreadList().GetSelectedThread().get();
if (thread == NULL)
return false;
@@ -209,7 +219,14 @@ bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
return false;
}
-bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t &returned_func) {
+// FIXME: This has nothing to do with Posix, it is just a convenience function that calls a
+// function of the form "void * (*)(void)". We should find a better place to put this.
+
+bool
+lldb_private::InferiorCall (Process *process,
+ const Address *address,
+ addr_t &returned_func)
+{
Thread *thread = process->GetThreadList().GetSelectedThread().get();
if (thread == NULL || address == NULL)
return false;
@@ -233,7 +250,7 @@ bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t
lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
if (call_plan_sp)
{
- StreamFile error_strm;
+ StreamString error_strm;
// This plan is a utility plan, so set it to discard itself when done.
call_plan_sp->SetIsMasterPlan (true);
call_plan_sp->SetOkayToDiscard(true);
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index c19aec3a02c7..f87db5810740 100644
--- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -21,15 +21,17 @@
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
-#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Target/ABI.h"
+#include "lldb/Target/DynamicLoader.h"
#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
+#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
-#include "lldb/Target/DynamicLoader.h"
#include "RegisterContextLLDB.h"
@@ -75,13 +77,44 @@ RegisterContextLLDB::RegisterContextLLDB
// This same code exists over in the GetFullUnwindPlanForFrame() but it may not have been executed yet
if (IsFrameZero()
- || next_frame->m_frame_type == eSigtrampFrame
+ || next_frame->m_frame_type == eTrapHandlerFrame
|| next_frame->m_frame_type == eDebuggerFrame)
{
m_all_registers_available = true;
}
}
+bool
+RegisterContextLLDB::IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp, int &valid_pc_offset)
+{
+ if (!unwind_plan_sp)
+ return false;
+
+ // check if m_current_pc is valid
+ if (unwind_plan_sp->PlanValidAtAddress(m_current_pc))
+ {
+ // yes - current offset can be used as is
+ valid_pc_offset = m_current_offset;
+ return true;
+ }
+
+ // if m_current_offset <= 0, we've got nothing else to try
+ if (m_current_offset <= 0)
+ return false;
+
+ // check pc - 1 to see if it's valid
+ Address pc_minus_one (m_current_pc);
+ pc_minus_one.SetOffset(m_current_pc.GetOffset() - 1);
+ if (unwind_plan_sp->PlanValidAtAddress(pc_minus_one))
+ {
+ // *valid_pc_offset = m_current_offset - 1;
+ valid_pc_offset = m_current_pc.GetOffset() - 1;
+ return true;
+ }
+
+ return false;
+}
+
// Initialize a RegisterContextLLDB which is the first frame of a stack -- the zeroth frame or currently
// executing frame.
@@ -95,6 +128,7 @@ RegisterContextLLDB::InitializeZerothFrame()
if (reg_ctx_sp.get() == NULL)
{
m_frame_type = eNotAValidFrame;
+ UnwindLogMsg ("frame does not have a register context");
return;
}
@@ -103,6 +137,7 @@ RegisterContextLLDB::InitializeZerothFrame()
if (current_pc == LLDB_INVALID_ADDRESS)
{
m_frame_type = eNotAValidFrame;
+ UnwindLogMsg ("frame does not have a pc");
return;
}
@@ -117,7 +152,7 @@ RegisterContextLLDB::InitializeZerothFrame()
current_pc = abi->FixCodeAddress(current_pc);
// Initialize m_current_pc, an Address object, based on current_pc, an addr_t.
- process->GetTarget().GetSectionLoadList().ResolveLoadAddress (current_pc, m_current_pc);
+ m_current_pc.SetLoadAddress (current_pc, &process->GetTarget());
// If we don't have a Module for some reason, we're not going to find symbol/function information - just
// stick in some reasonable defaults and hope we can unwind past this frame.
@@ -137,11 +172,9 @@ RegisterContextLLDB::InitializeZerothFrame()
AddressRange addr_range;
m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range);
- static ConstString g_sigtramp_name ("_sigtramp");
- if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == g_sigtramp_name) ||
- (m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == g_sigtramp_name))
+ if (IsTrapHandlerSymbol (process, m_sym_ctx))
{
- m_frame_type = eSigtrampFrame;
+ m_frame_type = eTrapHandlerFrame;
}
else
{
@@ -197,6 +230,7 @@ RegisterContextLLDB::InitializeZerothFrame()
if (!active_row.get())
{
+ UnwindLogMsg ("could not find an unwindplan row for this frame's pc");
m_frame_type = eNotAValidFrame;
return;
}
@@ -205,6 +239,7 @@ RegisterContextLLDB::InitializeZerothFrame()
addr_t cfa_regval = LLDB_INVALID_ADDRESS;
if (!ReadGPRValue (row_register_kind, active_row->GetCFARegister(), cfa_regval))
{
+ UnwindLogMsg ("could not read CFA register for this frame.");
m_frame_type = eNotAValidFrame;
return;
}
@@ -229,17 +264,20 @@ RegisterContextLLDB::InitializeNonZerothFrame()
if (IsFrameZero ())
{
m_frame_type = eNotAValidFrame;
+ UnwindLogMsg ("non-zeroth frame tests positive for IsFrameZero -- that shouldn't happen.");
return;
}
if (!GetNextFrame().get() || !GetNextFrame()->IsValid())
{
m_frame_type = eNotAValidFrame;
+ UnwindLogMsg ("Could not get next frame, marking this frame as invalid.");
return;
}
if (!m_thread.GetRegisterContext())
{
m_frame_type = eNotAValidFrame;
+ UnwindLogMsg ("Could not get register context for this thread, marking this frame as invalid.");
return;
}
@@ -265,6 +303,7 @@ RegisterContextLLDB::InitializeNonZerothFrame()
if (pc == 0)
{
m_frame_type = eNotAValidFrame;
+ UnwindLogMsg ("this frame has a pc of 0x0");
return;
}
@@ -276,7 +315,7 @@ RegisterContextLLDB::InitializeNonZerothFrame()
if (abi)
pc = abi->FixCodeAddress(pc);
- process->GetTarget().GetSectionLoadList().ResolveLoadAddress (pc, m_current_pc);
+ m_current_pc.SetLoadAddress (pc, &process->GetTarget());
// If we don't have a Module for some reason, we're not going to find symbol/function information - just
// stick in some reasonable defaults and hope we can unwind past this frame.
@@ -304,6 +343,7 @@ RegisterContextLLDB::InitializeNonZerothFrame()
{
// anywhere other than the second frame, a non-executable pc means we're off in the weeds -- stop now.
m_frame_type = eNotAValidFrame;
+ UnwindLogMsg ("pc is in a non-executable section of memory and this isn't the 2nd frame in the stack walk.");
return;
}
}
@@ -352,6 +392,7 @@ RegisterContextLLDB::InitializeNonZerothFrame()
&& (permissions & ePermissionsReadable) == 0)
{
m_frame_type = eNotAValidFrame;
+ UnwindLogMsg ("the CFA points to a region of memory that is not readable");
return;
}
}
@@ -366,10 +407,15 @@ RegisterContextLLDB::InitializeNonZerothFrame()
return;
}
m_frame_type = eNotAValidFrame;
+ UnwindLogMsg ("could not find any symbol for this pc, or a default unwind plan, to continue unwind.");
return;
}
bool resolve_tail_call_address = true; // m_current_pc can be one past the address range of the function...
+ // This will handle the case where the saved pc does not point to
+ // a function/symbol because it is beyond the bounds of the correct
+ // function and there's no symbol there. ResolveSymbolContextForAddress
+ // will fail to find a symbol, back up the pc by 1 and re-search.
uint32_t resolved_scope = pc_module_sp->ResolveSymbolContextForAddress (m_current_pc,
eSymbolContextFunction | eSymbolContextSymbol,
m_sym_ctx, resolve_tail_call_address);
@@ -392,18 +438,35 @@ RegisterContextLLDB::InitializeNonZerothFrame()
if (m_sym_ctx_valid == false)
decr_pc_and_recompute_addr_range = true;
- // Or if we're in the middle of the stack (and not "above" an asynchronous event like sigtramp), and
- // our "current" pc is the start of a function or our "current" pc is one past the end of a function...
+ // Or if we're in the middle of the stack (and not "above" an asynchronous event like sigtramp),
+ // and our "current" pc is the start of a function...
if (m_sym_ctx_valid
- && GetNextFrame()->m_frame_type != eSigtrampFrame
+ && GetNextFrame()->m_frame_type != eTrapHandlerFrame
&& GetNextFrame()->m_frame_type != eDebuggerFrame
&& addr_range.GetBaseAddress().IsValid()
- && addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection())
+ && addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection()
+ && addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset())
{
- if (addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset() ||
- addr_range.GetBaseAddress().GetOffset() + addr_range.GetByteSize() == m_current_pc.GetOffset())
+ decr_pc_and_recompute_addr_range = true;
+ }
+
+ // We need to back up the pc by 1 byte and re-search for the Symbol to handle the case where the "saved pc"
+ // value is pointing to the next function, e.g. if a function ends with a CALL instruction.
+ // FIXME this may need to be an architectural-dependent behavior; if so we'll need to add a member function
+ // to the ABI plugin and consult that.
+ if (decr_pc_and_recompute_addr_range)
+ {
+ Address temporary_pc(m_current_pc);
+ temporary_pc.SetOffset(m_current_pc.GetOffset() - 1);
+ m_sym_ctx.Clear(false);
+ m_sym_ctx_valid = false;
+ if ((pc_module_sp->ResolveSymbolContextForAddress (temporary_pc, eSymbolContextFunction| eSymbolContextSymbol, m_sym_ctx) & eSymbolContextSymbol) == eSymbolContextSymbol)
+ {
+ m_sym_ctx_valid = true;
+ }
+ if (!m_sym_ctx.GetAddressRange (eSymbolContextFunction | eSymbolContextSymbol, 0, false, addr_range))
{
- decr_pc_and_recompute_addr_range = true;
+ m_sym_ctx_valid = false;
}
}
@@ -428,11 +491,9 @@ RegisterContextLLDB::InitializeNonZerothFrame()
m_current_offset_backed_up_one = -1;
}
- static ConstString sigtramp_name ("_sigtramp");
- if ((m_sym_ctx.function && m_sym_ctx.function->GetMangled().GetMangledName() == sigtramp_name)
- || (m_sym_ctx.symbol && m_sym_ctx.symbol->GetMangled().GetMangledName() == sigtramp_name))
+ if (IsTrapHandlerSymbol (process, m_sym_ctx))
{
- m_frame_type = eSigtrampFrame;
+ m_frame_type = eTrapHandlerFrame;
}
else
{
@@ -467,9 +528,10 @@ RegisterContextLLDB::InitializeNonZerothFrame()
else
{
m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
- if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc))
+ int valid_offset = -1;
+ if (IsUnwindPlanValidForCurrentPC(m_full_unwind_plan_sp, valid_offset))
{
- active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
+ active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (valid_offset);
row_register_kind = m_full_unwind_plan_sp->GetRegisterKind ();
if (active_row.get() && log)
{
@@ -483,6 +545,7 @@ RegisterContextLLDB::InitializeNonZerothFrame()
if (!active_row.get())
{
m_frame_type = eNotAValidFrame;
+ UnwindLogMsg ("could not find unwind row for this pc");
return;
}
@@ -551,7 +614,7 @@ RegisterContextLLDB::IsFrameZero () const
//
// On entry to this method,
//
-// 1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct,
+// 1. m_frame_type should already be set to eTrapHandlerFrame/eDebuggerFrame if either of those are correct,
// 2. m_sym_ctx should already be filled in, and
// 3. m_current_pc should have the current pc value for this frame
// 4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown
@@ -573,7 +636,7 @@ RegisterContextLLDB::GetFastUnwindPlanForFrame ()
return unwind_plan_sp;
// If we're in _sigtramp(), unwinding past this frame requires special knowledge.
- if (m_frame_type == eSigtrampFrame || m_frame_type == eDebuggerFrame)
+ if (m_frame_type == eTrapHandlerFrame || m_frame_type == eDebuggerFrame)
return unwind_plan_sp;
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanFastUnwind (m_thread);
@@ -602,7 +665,7 @@ RegisterContextLLDB::GetFastUnwindPlanForFrame ()
// On entry to this method,
//
-// 1. m_frame_type should already be set to eSigtrampFrame/eDebuggerFrame if either of those are correct,
+// 1. m_frame_type should already be set to eTrapHandlerFrame/eDebuggerFrame if either of those are correct,
// 2. m_sym_ctx should already be filled in, and
// 3. m_current_pc should have the current pc value for this frame
// 4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown
@@ -627,7 +690,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
bool behaves_like_zeroth_frame = false;
if (IsFrameZero ()
- || GetNextFrame()->m_frame_type == eSigtrampFrame
+ || GetNextFrame()->m_frame_type == eTrapHandlerFrame
|| GetNextFrame()->m_frame_type == eDebuggerFrame)
{
behaves_like_zeroth_frame = true;
@@ -648,7 +711,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
uint32_t permissions;
addr_t current_pc_addr = m_current_pc.GetLoadAddress (exe_ctx.GetTargetPtr());
if (current_pc_addr == 0
- || (process->GetLoadAddressPermissions(current_pc_addr, permissions)
+ || (process->GetLoadAddressPermissions (current_pc_addr, permissions)
&& (permissions & ePermissionsExecutable) == 0))
{
unwind_plan_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric));
@@ -697,7 +760,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
// is properly encoded in the eh_frame section, so prefer that if available.
// On other platforms we may need to provide a platform-specific UnwindPlan which encodes the details of
// how to unwind out of sigtramp.
- if (m_frame_type == eSigtrampFrame)
+ if (m_frame_type == eTrapHandlerFrame)
{
m_fast_unwind_plan_sp.reset();
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
@@ -735,7 +798,8 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
// Typically this is unwind info from an eh_frame section intended for exception handling; only valid at call sites
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
- if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
+ int valid_offset = -1;
+ if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset))
{
UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
return unwind_plan_sp;
@@ -744,7 +808,7 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
// We'd prefer to use an UnwindPlan intended for call sites when we're at a call site but if we've
// struck out on that, fall back to using the non-call-site assembly inspection UnwindPlan if possible.
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread);
- if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
+ if (IsUnwindPlanValidForCurrentPC(unwind_plan_sp, valid_offset))
{
UnwindLogMsgVerbose ("frame uses %s for full UnwindPlan", unwind_plan_sp->GetSourceName().GetCString());
return unwind_plan_sp;
@@ -915,6 +979,12 @@ RegisterContextLLDB::IsValid () const
return m_frame_type != eNotAValidFrame;
}
+bool
+RegisterContextLLDB::IsTrapHandlerFrame () const
+{
+ return m_frame_type == eTrapHandlerFrame;
+}
+
// A skip frame is a bogus frame on the stack -- but one where we're likely to find a real frame farther
// up the stack if we keep looking. It's always the second frame in an unwind (i.e. the first frame after
// frame zero) where unwinding can be the trickiest. Ideally we'll mark up this frame in some way so the
@@ -927,6 +997,35 @@ RegisterContextLLDB::IsSkipFrame () const
return m_frame_type == eSkipFrame;
}
+bool
+RegisterContextLLDB::IsTrapHandlerSymbol (lldb_private::Process *process, const lldb_private::SymbolContext &m_sym_ctx) const
+{
+ PlatformSP platform_sp (process->GetTarget().GetPlatform());
+ if (platform_sp)
+ {
+ const std::vector<ConstString> trap_handler_names (platform_sp->GetTrapHandlerSymbolNames());
+ for (ConstString name : trap_handler_names)
+ {
+ if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) ||
+ (m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == name))
+ {
+ return true;
+ }
+ }
+ }
+ const std::vector<ConstString> user_specified_trap_handler_names (m_parent_unwind.GetUserSpecifiedTrapHandlerFunctionNames());
+ for (ConstString name : user_specified_trap_handler_names)
+ {
+ if ((m_sym_ctx.function && m_sym_ctx.function->GetName() == name) ||
+ (m_sym_ctx.symbol && m_sym_ctx.symbol->GetName() == name))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
// Answer the question: Where did THIS frame save the CALLER frame ("previous" frame)'s register value?
enum UnwindLLDB::RegisterSearchResult
@@ -1161,7 +1260,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
regloc.type = UnwindLLDB::RegisterLocation::eRegisterValueInferred;
regloc.location.inferred_value = m_cfa + offset;
m_registers[lldb_regnum] = regloc;
- UnwindLogMsg ("supplying caller's register %d, value is CFA plus offset", lldb_regnum);
+ UnwindLogMsg ("supplying caller's register %d, value is CFA plus offset %d", lldb_regnum, offset);
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
@@ -1171,7 +1270,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, lldb_privat
regloc.type = UnwindLLDB::RegisterLocation::eRegisterSavedAtMemoryLocation;
regloc.location.target_memory_location = m_cfa + offset;
m_registers[lldb_regnum] = regloc;
- UnwindLogMsg ("supplying caller's register %d from the stack, saved at CFA plus offset", lldb_regnum);
+ UnwindLogMsg ("supplying caller's register %d from the stack, saved at CFA plus offset %d", lldb_regnum, offset);
return UnwindLLDB::RegisterSearchResult::eRegisterFound;
}
@@ -1550,3 +1649,4 @@ RegisterContextLLDB::UnwindLogMsgVerbose (const char *fmt, ...)
}
}
+
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.h b/source/Plugins/Process/Utility/RegisterContextLLDB.h
index dc6d8c61fa4a..bf9dd9a29319 100644
--- a/source/Plugins/Process/Utility/RegisterContextLLDB.h
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.h
@@ -73,6 +73,9 @@ public:
IsValid () const;
bool
+ IsTrapHandlerFrame () const;
+
+ bool
GetCFA (lldb::addr_t& cfa);
bool
@@ -86,7 +89,7 @@ private:
enum FrameType
{
eNormalFrame,
- eSigtrampFrame,
+ eTrapHandlerFrame,
eDebuggerFrame, // a debugger inferior function call frame; we get caller's registers from debugger
eSkipFrame, // The unwind resulted in a bogus frame but may get back on track so we don't want to give up yet
eNotAValidFrame // this frame is invalid for some reason - most likely it is past the top (end) of the stack
@@ -120,6 +123,19 @@ private:
bool
IsSkipFrame () const;
+
+ //------------------------------------------------------------------
+ /// Determines if a SymbolContext is a trap handler or not
+ ///
+ /// Given a SymbolContext, determines if this is a trap handler function
+ /// aka asynchronous signal handler.
+ ///
+ /// @return
+ /// Returns true if the SymbolContext is a trap handler.
+ //------------------------------------------------------------------
+ bool
+ IsTrapHandlerSymbol (lldb_private::Process *process, const lldb_private::SymbolContext &m_sym_ctx) const;
+
// Provide a location for where THIS function saved the CALLER's register value
// Or a frame "below" this one saved it, i.e. a function called by this one, preserved a register that this
// function didn't modify/use.
@@ -164,6 +180,10 @@ private:
void
UnwindLogMsgVerbose (const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));
+ bool
+ IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp, int &valid_pc_offset);
+
+
lldb_private::Thread& m_thread;
///
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.cpp b/source/Plugins/Process/Utility/UnwindLLDB.cpp
index 552ae501bd21..a3a7002ea099 100644
--- a/source/Plugins/Process/Utility/UnwindLLDB.cpp
+++ b/source/Plugins/Process/Utility/UnwindLLDB.cpp
@@ -26,8 +26,21 @@ using namespace lldb_private;
UnwindLLDB::UnwindLLDB (Thread &thread) :
Unwind (thread),
m_frames(),
- m_unwind_complete(false)
+ m_unwind_complete(false),
+ m_user_supplied_trap_handler_functions()
{
+ ProcessSP process_sp(thread.GetProcess());
+ if (process_sp)
+ {
+ Args args;
+ process_sp->GetTarget().GetUserSpecifiedTrapHandlerNames (args);
+ size_t count = args.GetArgumentCount();
+ for (size_t i = 0; i < count; i++)
+ {
+ const char *func_name = args.GetArgumentAtIndex(i);
+ m_user_supplied_trap_handler_functions.push_back (ConstString (func_name));
+ }
+ }
}
uint32_t
@@ -95,7 +108,13 @@ UnwindLLDB::AddFirstFrame ()
first_cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp;
m_frames.push_back (first_cursor_sp);
return true;
+
unwind_done:
+ Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
+ if (log)
+ {
+ log->Printf ("th%d Unwind of this thread is complete.", m_thread.GetIndexID());
+ }
m_unwind_complete = true;
return false;
}
@@ -138,7 +157,12 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
}
if (reg_ctx_sp.get() == NULL)
+ {
+ if (log)
+ log->Printf ("%*sFrame %d did not get a RegisterContext, stopping.",
+ cur_idx < 100 ? cur_idx : 100, "", cur_idx);
goto unwind_done;
+ }
if (!reg_ctx_sp->IsValid())
{
@@ -160,12 +184,18 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
}
if (abi && !abi->CallFrameAddressIsValid(cursor_sp->cfa))
{
- if (log)
+ // On Mac OS X, the _sigtramp asynchronous signal trampoline frame may not have
+ // its (constructed) CFA aligned correctly -- don't do the abi alignment check for
+ // these.
+ if (reg_ctx_sp->IsTrapHandlerFrame() == false)
{
- log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk",
- cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+ if (log)
+ {
+ log->Printf("%*sFrame %d did not get a valid CFA for this frame, stopping stack walk",
+ cur_idx < 100 ? cur_idx : 100, "", cur_idx);
+ }
+ goto unwind_done;
}
- goto unwind_done;
}
if (!reg_ctx_sp->ReadPC (cursor_sp->start_pc))
{
@@ -185,12 +215,26 @@ UnwindLLDB::AddOneMoreFrame (ABI *abi)
}
goto unwind_done;
}
+ if (!m_frames.empty())
+ {
+ // Infinite loop where the current cursor is the same as the previous one...
+ if (m_frames.back()->start_pc == cursor_sp->start_pc && m_frames.back()->cfa == cursor_sp->cfa)
+ {
+ if (log)
+ log->Printf ("th%d pc of this frame is the same as the previous frame and CFAs for both frames are identical -- stopping unwind", m_thread.GetIndexID());
+ goto unwind_done;
+ }
+ }
cursor_sp->reg_ctx_lldb_sp = reg_ctx_sp;
m_frames.push_back (cursor_sp);
return true;
unwind_done:
+ if (log)
+ {
+ log->Printf ("th%d Unwind of this thread is complete.", m_thread.GetIndexID());
+ }
m_unwind_complete = true;
return false;
}
diff --git a/source/Plugins/Process/Utility/UnwindLLDB.h b/source/Plugins/Process/Utility/UnwindLLDB.h
index 5725654a6869..eb5400389df3 100644
--- a/source/Plugins/Process/Utility/UnwindLLDB.h
+++ b/source/Plugins/Process/Utility/UnwindLLDB.h
@@ -13,6 +13,7 @@
#include <vector>
#include "lldb/lldb-public.h"
+#include "lldb/Core/ConstString.h"
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/RegisterContext.h"
@@ -90,6 +91,24 @@ protected:
SearchForSavedLocationForRegister (uint32_t lldb_regnum, lldb_private::UnwindLLDB::RegisterLocation &regloc, uint32_t starting_frame_num, bool pc_register);
+ //------------------------------------------------------------------
+ /// Provide the list of user-specified trap handler functions
+ ///
+ /// The Platform is one source of trap handler function names; that
+ /// may be augmented via a setting. The setting needs to be converted
+ /// into an array of ConstStrings before it can be used - we only want
+ /// to do that once per thread so it's here in the UnwindLLDB object.
+ ///
+ /// @return
+ /// Vector of ConstStrings of trap handler function names. May be
+ /// empty.
+ //------------------------------------------------------------------
+ const std::vector<ConstString> &
+ GetUserSpecifiedTrapHandlerFunctionNames ()
+ {
+ return m_user_supplied_trap_handler_functions;
+ }
+
private:
struct Cursor
@@ -110,6 +129,7 @@ private:
// number of frames, etc. Otherwise we've only gone as far as directly asked, and m_frames.size()
// is how far we've currently gone.
+ std::vector<ConstString> m_user_supplied_trap_handler_functions;
bool AddOneMoreFrame (ABI *abi);
bool AddFirstFrame ();
diff --git a/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 93641ede1bc7..7ea5c89e7df4 100644
--- a/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -131,7 +131,8 @@ ProcessElfCore::AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader *head
VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
if (last_entry &&
last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
- last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase())
+ last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() &&
+ last_entry->GetByteSize() == last_entry->data.GetByteSize())
{
last_entry->SetRangeEnd (range_entry.GetRangeEnd());
last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd());
@@ -294,9 +295,13 @@ ProcessElfCore::DoReadMemory (lldb::addr_t addr, void *buf, size_t size, Error &
size_t zero_fill_size = 0; // Padding
lldb::addr_t bytes_left = 0; // Number of bytes available in the core file from the given address
- if (file_end > offset)
- bytes_left = file_end - offset;
+ // Figure out how many on-disk bytes remain in this segment
+ // starting at the given offset
+ if (file_end > file_start + offset)
+ bytes_left = file_end - (file_start + offset);
+ // Figure out how many bytes we need to zero-fill if we are
+ // reading more bytes than available in the on-disk segment
if (bytes_to_read > bytes_left)
{
zero_fill_size = bytes_to_read - bytes_left;
@@ -365,12 +370,12 @@ enum {
// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.
static void
-ParseFreeBSDPrStatus(ThreadData *thread_data, DataExtractor &data,
+ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data,
ArchSpec &arch)
{
lldb::offset_t offset = 0;
- bool have_padding = (arch.GetMachine() == llvm::Triple::mips64 ||
- arch.GetMachine() == llvm::Triple::x86_64);
+ bool lp64 = (arch.GetMachine() == llvm::Triple::mips64 ||
+ arch.GetMachine() == llvm::Triple::x86_64);
int pr_version = data.GetU32(&offset);
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
@@ -380,23 +385,26 @@ ParseFreeBSDPrStatus(ThreadData *thread_data, DataExtractor &data,
log->Printf("FreeBSD PRSTATUS unexpected version %d", pr_version);
}
- if (have_padding)
- offset += 4;
- offset += 28; // pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate
- thread_data->signo = data.GetU32(&offset); // pr_cursig
+ // Skip padding, pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate
+ if (lp64)
+ offset += 32;
+ else
+ offset += 16;
+
+ thread_data.signo = data.GetU32(&offset); // pr_cursig
offset += 4; // pr_pid
- if (have_padding)
+ if (lp64)
offset += 4;
size_t len = data.GetByteSize() - offset;
- thread_data->gpregset = DataExtractor(data, offset, len);
+ thread_data.gpregset = DataExtractor(data, offset, len);
}
static void
-ParseFreeBSDThrMisc(ThreadData *thread_data, DataExtractor &data)
+ParseFreeBSDThrMisc(ThreadData &thread_data, DataExtractor &data)
{
lldb::offset_t offset = 0;
- thread_data->name = data.GetCStr(&offset, 20);
+ thread_data.name = data.GetCStr(&offset, 20);
}
/// Parse Thread context from PT_NOTE segment and store it in the thread list
@@ -418,13 +426,13 @@ ParseFreeBSDThrMisc(ThreadData *thread_data, DataExtractor &data)
/// For case (b) there may be either one NT_PRPSINFO per thread, or a single
/// one that applies to all threads (depending on the platform type).
void
-ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *segment_header,
+ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *segment_header,
DataExtractor segment_data)
{
assert(segment_header && segment_header->p_type == llvm::ELF::PT_NOTE);
lldb::offset_t offset = 0;
- ThreadData *thread_data = new ThreadData();
+ std::unique_ptr<ThreadData> thread_data(new ThreadData);
bool have_prstatus = false;
bool have_prpsinfo = false;
@@ -447,7 +455,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
assert(thread_data->gpregset.GetByteSize() > 0);
// Add the new thread to thread list
m_thread_data.push_back(*thread_data);
- thread_data = new ThreadData();
+ *thread_data = ThreadData();
have_prstatus = false;
have_prpsinfo = false;
}
@@ -464,7 +472,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
{
case NT_FREEBSD_PRSTATUS:
have_prstatus = true;
- ParseFreeBSDPrStatus(thread_data, note_data, arch);
+ ParseFreeBSDPrStatus(*thread_data, note_data, arch);
break;
case NT_FREEBSD_FPREGSET:
thread_data->fpregset = note_data;
@@ -473,7 +481,7 @@ ProcessElfCore::ParseThreadContextsFromNoteSegment(const elf::ELFProgramHeader *
have_prpsinfo = true;
break;
case NT_FREEBSD_THRMISC:
- ParseFreeBSDThrMisc(thread_data, note_data);
+ ParseFreeBSDThrMisc(*thread_data, note_data);
break;
case NT_FREEBSD_PROCSTAT_AUXV:
// FIXME: FreeBSD sticks an int at the beginning of the note
diff --git a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
index 610506c20a0b..3e09c7bc2032 100644
--- a/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
+++ b/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_x86_64.cpp
@@ -63,8 +63,16 @@ RegisterContextCorePOSIX_x86_64::WriteFPR()
bool
RegisterContextCorePOSIX_x86_64::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
{
- value = *(uint64_t *)(m_gpregset + reg_info->byte_offset);
- return true;
+ switch (reg_info->byte_size)
+ {
+ case 4:
+ value = *(uint32_t *)(m_gpregset + reg_info->byte_offset);
+ return true;
+ case 8:
+ value = *(uint64_t *)(m_gpregset + reg_info->byte_offset);
+ return true;
+ }
+ return false;
}
bool
diff --git a/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
index 3bda86dc0f73..cadcf53ca543 100644
--- a/source/Plugins/Process/elf-core/ThreadElfCore.cpp
+++ b/source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -17,6 +17,7 @@
#include "ThreadElfCore.h"
#include "ProcessElfCore.h"
#include "RegisterContextLinux_x86_64.h"
+#include "RegisterContextFreeBSD_i386.h"
#include "RegisterContextFreeBSD_mips64.h"
#include "RegisterContextFreeBSD_x86_64.h"
#include "RegisterContextPOSIXCore_mips64.h"
@@ -85,45 +86,66 @@ ThreadElfCore::CreateRegisterContextForFrame (StackFrame *frame)
ProcessElfCore *process = static_cast<ProcessElfCore *>(GetProcess().get());
ArchSpec arch = process->GetArchitecture();
- switch (arch.GetMachine())
+ RegisterInfoInterface *reg_interface = NULL;
+
+ switch (arch.GetTriple().getOS())
{
- case llvm::Triple::mips64:
- switch (arch.GetTriple().getOS())
+ case llvm::Triple::FreeBSD:
+ {
+ switch (arch.GetMachine())
{
- case llvm::Triple::FreeBSD:
- m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64 (*this, new RegisterContextFreeBSD_mips64(arch), m_gpregset_data, m_fpregset_data));
+ case llvm::Triple::mips64:
+ reg_interface = new RegisterContextFreeBSD_mips64(arch);
+ break;
+ case llvm::Triple::x86:
+ reg_interface = new RegisterContextFreeBSD_i386(arch);
+ break;
+ case llvm::Triple::x86_64:
+ reg_interface = new RegisterContextFreeBSD_x86_64(arch);
break;
default:
- if (log)
- log->Printf ("elf-core::%s:: OS(%d) not supported",
- __FUNCTION__, arch.GetTriple().getOS());
- assert (false && "OS not supported");
break;
}
break;
- case llvm::Triple::x86_64:
- switch (arch.GetTriple().getOS())
+ }
+
+ case llvm::Triple::Linux:
+ {
+ switch (arch.GetMachine())
{
- case llvm::Triple::FreeBSD:
- m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, new RegisterContextFreeBSD_x86_64(arch), m_gpregset_data, m_fpregset_data));
- break;
- case llvm::Triple::Linux:
- m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, new RegisterContextLinux_x86_64(arch), m_gpregset_data, m_fpregset_data));
+ case llvm::Triple::x86_64:
+ reg_interface = new RegisterContextLinux_x86_64(arch);
break;
default:
- if (log)
- log->Printf ("elf-core::%s:: OS(%d) not supported",
- __FUNCTION__, arch.GetTriple().getOS());
- assert (false && "OS not supported");
break;
}
break;
+ }
+
+ default:
+ break;
+ }
+
+ if (!reg_interface) {
+ if (log)
+ log->Printf ("elf-core::%s:: Architecture(%d) or OS(%d) not supported",
+ __FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
+ assert (false && "Architecture or OS not supported");
+ }
+
+ switch (arch.GetMachine())
+ {
+ case llvm::Triple::mips64:
+ m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
+ break;
+ case llvm::Triple::x86:
+ case llvm::Triple::x86_64:
+ m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
+ break;
default:
- if (log)
- log->Printf ("elf-core::%s:: Architecture(%d) not supported",
- __FUNCTION__, arch.GetMachine());
- assert (false && "Architecture not supported");
+ break;
}
+
reg_ctx_sp = m_thread_reg_ctx_sp;
}
else if (m_unwinder_ap.get())
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index f67e1b5d49c3..1ec75a4bc7af 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -13,9 +13,11 @@
// C Includes
#include <limits.h>
#include <string.h>
+#include <sys/stat.h>
// C++ Includes
// Other libraries and framework includes
+#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
@@ -143,7 +145,9 @@ GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
m_private_is_running (false),
m_history (512),
m_send_acks (true),
- m_is_platform (is_platform)
+ m_is_platform (is_platform),
+ m_listen_thread (LLDB_INVALID_HOST_THREAD),
+ m_listen_url ()
{
}
@@ -195,14 +199,14 @@ GDBRemoteCommunication::SendNack ()
return bytes_written;
}
-size_t
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length)
{
Mutex::Locker locker(m_sequence_mutex);
return SendPacketNoLock (payload, payload_length);
}
-size_t
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length)
{
if (IsConnected())
@@ -235,32 +239,32 @@ GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_le
if (bytes_written == packet.GetSize())
{
if (GetSendAcks ())
- {
- if (GetAck () != '+')
- {
- if (log)
- log->Printf("get ack failed...");
- return 0;
- }
- }
+ return GetAck ();
+ else
+ return PacketResult::Success;
}
else
{
if (log)
log->Printf ("error: failed to send packet: %.*s", (int)packet.GetSize(), packet.GetData());
}
- return bytes_written;
}
- return 0;
+ return PacketResult::ErrorSendFailed;
}
-char
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunication::GetAck ()
{
StringExtractorGDBRemote packet;
- if (WaitForPacketWithTimeoutMicroSecondsNoLock (packet, GetPacketTimeoutInMicroSeconds ()) == 1)
- return packet.GetChar();
- return 0;
+ PacketResult result = WaitForPacketWithTimeoutMicroSecondsNoLock (packet, GetPacketTimeoutInMicroSeconds ());
+ if (result == PacketResult::Success)
+ {
+ if (packet.GetResponseType() == StringExtractorGDBRemote::ResponseType::eAck)
+ return PacketResult::Success;
+ else
+ return PacketResult::ErrorSendAck;
+ }
+ return result;
}
bool
@@ -280,7 +284,7 @@ GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
}
-size_t
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &packet, uint32_t timeout_usec)
{
uint8_t buffer[8192];
@@ -290,9 +294,10 @@ GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtrac
// Check for a packet from our cache first without trying any reading...
if (CheckForPacket (NULL, 0, packet))
- return packet.GetStringRef().size();
+ return PacketResult::Success;
bool timed_out = false;
+ bool disconnected = false;
while (IsConnected() && !timed_out)
{
lldb::ConnectionStatus status = eConnectionStatusNoConnection;
@@ -309,7 +314,7 @@ GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtrac
if (bytes_read > 0)
{
if (CheckForPacket (buffer, bytes_read, packet))
- return packet.GetStringRef().size();
+ return PacketResult::Success;
}
else
{
@@ -326,13 +331,19 @@ GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtrac
case eConnectionStatusNoConnection:
case eConnectionStatusLostConnection:
case eConnectionStatusError:
+ disconnected = true;
Disconnect();
break;
}
}
}
- packet.Clear ();
- return 0;
+ packet.Clear ();
+ if (disconnected)
+ return PacketResult::ErrorDisconnected;
+ if (timed_out)
+ return PacketResult::ErrorReplyTimeout;
+ else
+ return PacketResult::ErrorReplyFailed;
}
bool
@@ -538,18 +549,65 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri
}
Error
-GDBRemoteCommunication::StartDebugserverProcess (const char *debugserver_url,
- const char *unix_socket_name, // For handshaking
- lldb_private::ProcessLaunchInfo &launch_info)
+GDBRemoteCommunication::StartListenThread (const char *hostname, uint16_t port)
{
Error error;
+ if (IS_VALID_LLDB_HOST_THREAD(m_listen_thread))
+ {
+ error.SetErrorString("listen thread already running");
+ }
+ else
+ {
+ char listen_url[512];
+ if (hostname && hostname[0])
+ snprintf(listen_url, sizeof(listen_url), "listen://%s:%i", hostname, port);
+ else
+ snprintf(listen_url, sizeof(listen_url), "listen://%i", port);
+ m_listen_url = listen_url;
+ SetConnection(new ConnectionFileDescriptor());
+ m_listen_thread = Host::ThreadCreate (listen_url, GDBRemoteCommunication::ListenThread, this, &error);
+ }
+ return error;
+}
+
+bool
+GDBRemoteCommunication::JoinListenThread ()
+{
+ if (IS_VALID_LLDB_HOST_THREAD(m_listen_thread))
+ {
+ Host::ThreadJoin(m_listen_thread, NULL, NULL);
+ m_listen_thread = LLDB_INVALID_HOST_THREAD;
+ }
+ return true;
+}
+
+lldb::thread_result_t
+GDBRemoteCommunication::ListenThread (lldb::thread_arg_t arg)
+{
+ GDBRemoteCommunication *comm = (GDBRemoteCommunication *)arg;
+ Error error;
+ ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)comm->GetConnection ();
+
+ if (connection)
+ {
+ // Do the listen on another thread so we can continue on...
+ if (connection->Connect(comm->m_listen_url.c_str(), &error) != eConnectionStatusSuccess)
+ comm->SetConnection(NULL);
+ }
+ return NULL;
+}
+
+Error
+GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,
+ uint16_t in_port,
+ lldb_private::ProcessLaunchInfo &launch_info,
+ uint16_t &out_port)
+{
+ out_port = in_port;
+ Error error;
// If we locate debugserver, keep that located version around
static FileSpec g_debugserver_file_spec;
- // This function will fill in the launch information for the debugserver
- // instance that gets launched.
- launch_info.Clear();
-
char debugserver_path[PATH_MAX];
FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
@@ -591,19 +649,88 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *debugserver_url,
// Start args with "debugserver /file/path -r --"
debugserver_args.AppendArgument(debugserver_path);
- debugserver_args.AppendArgument(debugserver_url);
+
+ // If a host and port is supplied then use it
+ char host_and_port[128];
+ if (hostname)
+ {
+ snprintf (host_and_port, sizeof(host_and_port), "%s:%u", hostname, in_port);
+ debugserver_args.AppendArgument(host_and_port);
+ }
+ else
+ {
+ host_and_port[0] = '\0';
+ }
+
// use native registers, not the GDB registers
debugserver_args.AppendArgument("--native-regs");
// make debugserver run in its own session so signals generated by
// special terminal key sequences (^C) don't affect debugserver
debugserver_args.AppendArgument("--setsid");
-
- if (unix_socket_name && unix_socket_name[0])
+
+ char named_pipe_path[PATH_MAX];
+ named_pipe_path[0] = '\0';
+
+ bool listen = false;
+ if (host_and_port[0])
{
- debugserver_args.AppendArgument("--unix-socket");
- debugserver_args.AppendArgument(unix_socket_name);
+ // Create a temporary file to get the stdout/stderr and redirect the
+ // output of the command into this file. We will later read this file
+ // if all goes well and fill the data into "command_output_ptr"
+
+ if (in_port == 0)
+ {
+ // Binding to port zero, we need to figure out what port it ends up
+ // using using a named pipe...
+ FileSpec tmpdir_file_spec;
+ if (Host::GetLLDBPath (ePathTypeLLDBTempSystemDir, tmpdir_file_spec))
+ {
+ tmpdir_file_spec.GetFilename().SetCString("debugserver-named-pipe.XXXXXX");
+ strncpy(named_pipe_path, tmpdir_file_spec.GetPath().c_str(), sizeof(named_pipe_path));
+ }
+ else
+ {
+ strncpy(named_pipe_path, "/tmp/debugserver-named-pipe.XXXXXX", sizeof(named_pipe_path));
+ }
+
+ if (::mktemp (named_pipe_path))
+ {
+#if defined(_MSC_VER)
+ if ( false )
+#else
+ if (::mkfifo(named_pipe_path, 0600) == 0)
+#endif
+ {
+ debugserver_args.AppendArgument("--named-pipe");
+ debugserver_args.AppendArgument(named_pipe_path);
+ }
+ }
+ }
+ else
+ {
+ listen = true;
+ }
+ }
+ else
+ {
+ // No host and port given, so lets listen on our end and make the debugserver
+ // connect to us..
+ error = StartListenThread ("localhost", 0);
+ if (error.Fail())
+ return error;
+
+ ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection ();
+ out_port = connection->GetBoundPort(3);
+ assert (out_port != 0);
+ char port_cstr[32];
+ snprintf(port_cstr, sizeof(port_cstr), "localhost:%i", out_port);
+ // Send the host and port down that debugserver and specify an option
+ // so that it connects back to the port we are listening to in this process
+ debugserver_args.AppendArgument("--reverse-connect");
+ debugserver_args.AppendArgument(port_cstr);
}
+
const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
if (env_debugserver_log_file)
{
@@ -617,46 +744,41 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *debugserver_url,
::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
debugserver_args.AppendArgument(arg_cstr);
}
- // debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt");
- // debugserver_args.AppendArgument("--log-flags=0x802e0e");
- // We currently send down all arguments, attach pids, or attach
- // process names in dedicated GDB server packets, so we don't need
- // to pass them as arguments. This is currently because of all the
- // things we need to setup prior to launching: the environment,
- // current working dir, file actions, etc.
-#if 0
- // Now append the program arguments
- if (inferior_argv)
+ // Close STDIN, STDOUT and STDERR. We might need to redirect them
+ // to "/dev/null" if we run into any problems.
+ launch_info.AppendCloseFileAction (STDIN_FILENO);
+ launch_info.AppendCloseFileAction (STDOUT_FILENO);
+ launch_info.AppendCloseFileAction (STDERR_FILENO);
+
+ error = Host::LaunchProcess(launch_info);
+
+ if (named_pipe_path[0])
{
- // Terminate the debugserver args so we can now append the inferior args
- debugserver_args.AppendArgument("--");
-
- for (int i = 0; inferior_argv[i] != NULL; ++i)
- debugserver_args.AppendArgument (inferior_argv[i]);
+ File name_pipe_file;
+ error = name_pipe_file.Open(named_pipe_path, File::eOpenOptionRead);
+ if (error.Success())
+ {
+ char port_cstr[256];
+ port_cstr[0] = '\0';
+ size_t num_bytes = sizeof(port_cstr);
+ error = name_pipe_file.Read(port_cstr, num_bytes);
+ assert (error.Success());
+ assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0');
+ out_port = Args::StringToUInt32(port_cstr, 0);
+ name_pipe_file.Close();
+ }
+ Host::Unlink(named_pipe_path);
}
- else if (attach_pid != LLDB_INVALID_PROCESS_ID)
+ else if (listen)
{
- ::snprintf (arg_cstr, sizeof(arg_cstr), "--attach=%u", attach_pid);
- debugserver_args.AppendArgument (arg_cstr);
+
}
- else if (attach_name && attach_name[0])
+ else
{
- if (wait_for_launch)
- debugserver_args.AppendArgument ("--waitfor");
- else
- debugserver_args.AppendArgument ("--attach");
- debugserver_args.AppendArgument (attach_name);
+ // Make sure we actually connect with the debugserver...
+ JoinListenThread();
}
-#endif
-
- // Close STDIN, STDOUT and STDERR. We might need to redirect them
- // to "/dev/null" if we run into any problems.
-// launch_info.AppendCloseFileAction (STDIN_FILENO);
-// launch_info.AppendCloseFileAction (STDOUT_FILENO);
-// launch_info.AppendCloseFileAction (STDERR_FILENO);
-
- error = Host::LaunchProcess(launch_info);
}
else
{
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index a1077957c6a6..d8361113ddc8 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -35,6 +35,19 @@ public:
{
eBroadcastBitRunPacketSent = kLoUserBroadcastBit
};
+
+ enum class PacketResult
+ {
+ Success = 0, // Success
+ ErrorSendFailed, // Error sending the packet
+ ErrorSendAck, // Didn't get an ack back after sending a packet
+ ErrorReplyFailed, // Error getting the reply
+ ErrorReplyTimeout, // Timed out waiting for reply
+ ErrorReplyInvalid, // Got a reply but it wasn't valid for the packet that was sent
+ ErrorReplyAck, // Sending reply ack failed
+ ErrorDisconnected, // We were disconnected
+ ErrorNoSequenceLock // We couldn't get the sequence lock for a multi-packet request
+ };
//------------------------------------------------------------------
// Constructors and Destructors
//------------------------------------------------------------------
@@ -45,7 +58,7 @@ public:
virtual
~GDBRemoteCommunication();
- char
+ PacketResult
GetAck ();
size_t
@@ -109,9 +122,10 @@ public:
// supplied connection URL.
//------------------------------------------------------------------
lldb_private::Error
- StartDebugserverProcess (const char *connect_url,
- const char *unix_socket_name,
- lldb_private::ProcessLaunchInfo &launch_info);
+ StartDebugserverProcess (const char *hostname,
+ uint16_t in_port, // If set to zero, then out_port will contain the bound port on exit
+ lldb_private::ProcessLaunchInfo &launch_info,
+ uint16_t &out_port);
void
DumpHistory(lldb_private::Stream &strm);
@@ -223,15 +237,15 @@ protected:
mutable bool m_dumped_to_log;
};
- size_t
+ PacketResult
SendPacket (const char *payload,
size_t payload_length);
- size_t
+ PacketResult
SendPacketNoLock (const char *payload,
size_t payload_length);
- size_t
+ PacketResult
WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &response,
uint32_t timeout_usec);
@@ -242,7 +256,7 @@ protected:
// Classes that inherit from GDBRemoteCommunication can see and modify these
//------------------------------------------------------------------
uint32_t m_packet_timeout;
-#ifdef LLDB_CONFIGURATION_DEBUG
+#ifdef ENABLE_MUTEX_ERROR_CHECKING
lldb_private::TrackingMutex m_sequence_mutex;
#else
lldb_private::Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time
@@ -256,9 +270,22 @@ protected:
// a single process
+ lldb_private::Error
+ StartListenThread (const char *hostname = "localhost",
+ uint16_t port = 0);
+
+ bool
+ JoinListenThread ();
+ static lldb::thread_result_t
+ ListenThread (lldb::thread_arg_t arg);
private:
+
+ lldb::thread_t m_listen_thread;
+ std::string m_listen_url;
+
+
//------------------------------------------------------------------
// For GDBRemoteCommunication only
//------------------------------------------------------------------
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 2690992eeed3..aa60ec1b4a27 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -66,6 +66,9 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_prepare_for_reg_writing_reply (eLazyBoolCalculate),
m_supports_p (eLazyBoolCalculate),
m_supports_QSaveRegisterState (eLazyBoolCalculate),
+ m_supports_qXfer_libraries_read (eLazyBoolCalculate),
+ m_supports_qXfer_libraries_svr4_read (eLazyBoolCalculate),
+ m_supports_augmented_libraries_svr4_read (eLazyBoolCalculate),
m_supports_qProcessInfoPID (true),
m_supports_qfProcessInfo (true),
m_supports_qUserName (true),
@@ -84,6 +87,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_async_mutex (Mutex::eMutexTypeRecursive),
m_async_packet_predicate (false),
m_async_packet (),
+ m_async_result (PacketResult::Success),
m_async_response (),
m_async_signal (-1),
m_thread_id_to_used_usec_map (),
@@ -95,7 +99,8 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) :
m_os_build (),
m_os_kernel (),
m_hostname (),
- m_default_packet_timeout (0)
+ m_default_packet_timeout (0),
+ m_max_packet_size (0)
{
}
@@ -117,6 +122,14 @@ GDBRemoteCommunicationClient::HandshakeWithServer (Error *error_ptr)
// fail to send the handshake ack, there is no reason to continue...
if (SendAck())
{
+ // Wait for any responses that might have been queued up in the remote
+ // GDB server and flush them all
+ StringExtractorGDBRemote response;
+ PacketResult packet_result = PacketResult::Success;
+ const uint32_t timeout_usec = 10 * 1000; // Wait for 10 ms for a response
+ while (packet_result == PacketResult::Success)
+ packet_result = WaitForPacketWithTimeoutMicroSecondsNoLock (response, timeout_usec);
+
// The return value from QueryNoAckModeSupported() is true if the packet
// was sent and _any_ response (including UNIMPLEMENTED) was received),
// or false if no response was received. This quickly tells us if we have
@@ -140,6 +153,46 @@ GDBRemoteCommunicationClient::HandshakeWithServer (Error *error_ptr)
}
bool
+GDBRemoteCommunicationClient::GetAugmentedLibrariesSVR4ReadSupported ()
+{
+ if (m_supports_augmented_libraries_svr4_read == eLazyBoolCalculate)
+ {
+ GetRemoteQSupported();
+ }
+ return (m_supports_augmented_libraries_svr4_read == eLazyBoolYes);
+}
+
+bool
+GDBRemoteCommunicationClient::GetQXferLibrariesSVR4ReadSupported ()
+{
+ if (m_supports_qXfer_libraries_svr4_read == eLazyBoolCalculate)
+ {
+ GetRemoteQSupported();
+ }
+ return (m_supports_qXfer_libraries_svr4_read == eLazyBoolYes);
+}
+
+bool
+GDBRemoteCommunicationClient::GetQXferLibrariesReadSupported ()
+{
+ if (m_supports_qXfer_libraries_read == eLazyBoolCalculate)
+ {
+ GetRemoteQSupported();
+ }
+ return (m_supports_qXfer_libraries_read == eLazyBoolYes);
+}
+
+uint64_t
+GDBRemoteCommunicationClient::GetRemoteMaxPacketSize()
+{
+ if (m_max_packet_size == 0)
+ {
+ GetRemoteQSupported();
+ }
+ return m_max_packet_size;
+}
+
+bool
GDBRemoteCommunicationClient::QueryNoAckModeSupported ()
{
if (m_supports_not_sending_acks == eLazyBoolCalculate)
@@ -148,7 +201,7 @@ GDBRemoteCommunicationClient::QueryNoAckModeSupported ()
m_supports_not_sending_acks = eLazyBoolNo;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false))
+ if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
{
@@ -169,7 +222,7 @@ GDBRemoteCommunicationClient::GetListThreadsInStopReplySupported ()
m_supports_threads_in_stop_reply = eLazyBoolNo;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response, false))
+ if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
m_supports_threads_in_stop_reply = eLazyBoolYes;
@@ -185,7 +238,7 @@ GDBRemoteCommunicationClient::GetVAttachOrWaitSupported ()
m_attach_or_wait_reply = eLazyBoolNo;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response, false))
+ if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
m_attach_or_wait_reply = eLazyBoolYes;
@@ -205,7 +258,7 @@ GDBRemoteCommunicationClient::GetSyncThreadStateSupported ()
m_prepare_for_reg_writing_reply = eLazyBoolNo;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response, false))
+ if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
m_prepare_for_reg_writing_reply = eLazyBoolYes;
@@ -236,6 +289,9 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings()
m_supports_memory_region_info = eLazyBoolCalculate;
m_prepare_for_reg_writing_reply = eLazyBoolCalculate;
m_attach_or_wait_reply = eLazyBoolCalculate;
+ m_supports_qXfer_libraries_read = eLazyBoolCalculate;
+ m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
+ m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
m_supports_qProcessInfoPID = true;
m_supports_qfProcessInfo = true;
@@ -251,8 +307,50 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings()
m_supports_QEnvironmentHexEncoded = true;
m_host_arch.Clear();
m_process_arch.Clear();
+
+ m_max_packet_size = 0;
}
+void
+GDBRemoteCommunicationClient::GetRemoteQSupported ()
+{
+ // Clear out any capabilities we expect to see in the qSupported response
+ m_supports_qXfer_libraries_svr4_read = eLazyBoolNo;
+ m_supports_qXfer_libraries_read = eLazyBoolNo;
+ m_supports_augmented_libraries_svr4_read = eLazyBoolNo;
+ m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if not, we assume no limit
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("qSupported",
+ response,
+ /*send_async=*/false) == PacketResult::Success)
+ {
+ const char *response_cstr = response.GetStringRef().c_str();
+ if (::strstr (response_cstr, "qXfer:libraries-svr4:read+"))
+ m_supports_qXfer_libraries_svr4_read = eLazyBoolYes;
+ if (::strstr (response_cstr, "augmented-libraries-svr4-read"))
+ {
+ m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; // implied
+ m_supports_augmented_libraries_svr4_read = eLazyBoolYes;
+ }
+ if (::strstr (response_cstr, "qXfer:libraries:read+"))
+ m_supports_qXfer_libraries_read = eLazyBoolYes;
+
+ const char *packet_size_str = ::strstr (response_cstr, "PacketSize=");
+ if (packet_size_str)
+ {
+ StringExtractorGDBRemote packet_response(packet_size_str + strlen("PacketSize="));
+ m_max_packet_size = packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX);
+ if (m_max_packet_size == 0)
+ {
+ m_max_packet_size = UINT64_MAX; // Must have been a garbled response
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf ("Garbled PacketSize spec in qSupported response");
+ }
+ }
+ }
+}
bool
GDBRemoteCommunicationClient::GetThreadSuffixSupported ()
@@ -261,7 +359,7 @@ GDBRemoteCommunicationClient::GetThreadSuffixSupported ()
{
StringExtractorGDBRemote response;
m_supports_thread_suffix = eLazyBoolNo;
- if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response, false))
+ if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
m_supports_thread_suffix = eLazyBoolYes;
@@ -281,7 +379,7 @@ GDBRemoteCommunicationClient::GetVContSupported (char flavor)
m_supports_vCont_C = eLazyBoolNo;
m_supports_vCont_s = eLazyBoolNo;
m_supports_vCont_S = eLazyBoolNo;
- if (SendPacketAndWaitForResponse("vCont?", response, false))
+ if (SendPacketAndWaitForResponse("vCont?", response, false) == PacketResult::Success)
{
const char *response_cstr = response.GetStringRef().c_str();
if (::strstr (response_cstr, ";c"))
@@ -345,7 +443,7 @@ GDBRemoteCommunicationClient::GetpPacketSupported (lldb::tid_t tid)
else
snprintf(packet, sizeof(packet), "p0");
- if (SendPacketAndWaitForResponse(packet, response, false))
+ if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success)
{
if (response.IsNormalResponse())
m_supports_p = eLazyBoolYes;
@@ -354,7 +452,63 @@ GDBRemoteCommunicationClient::GetpPacketSupported (lldb::tid_t tid)
return m_supports_p;
}
-size_t
+GDBRemoteCommunicationClient::PacketResult
+GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses
+(
+ const char *payload_prefix,
+ std::string &response_string
+)
+{
+ Mutex::Locker locker;
+ if (!GetSequenceMutex(locker,
+ "ProcessGDBRemote::SendPacketsAndConcatenateResponses() failed due to not getting the sequence mutex"))
+ {
+ Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS));
+ if (log)
+ log->Printf("error: failed to get packet sequence mutex, not sending packets with prefix '%s'",
+ payload_prefix);
+ return PacketResult::ErrorNoSequenceLock;
+ }
+
+ response_string = "";
+ std::string payload_prefix_str(payload_prefix);
+ unsigned int response_size = 0x1000;
+ if (response_size > GetRemoteMaxPacketSize()) { // May send qSupported packet
+ response_size = GetRemoteMaxPacketSize();
+ }
+
+ for (unsigned int offset = 0; true; offset += response_size)
+ {
+ StringExtractorGDBRemote this_response;
+ // Construct payload
+ char sizeDescriptor[128];
+ snprintf(sizeDescriptor, sizeof(sizeDescriptor), "%x,%x", offset, response_size);
+ PacketResult result = SendPacketAndWaitForResponse((payload_prefix_str + sizeDescriptor).c_str(),
+ this_response,
+ /*send_async=*/false);
+ if (result != PacketResult::Success)
+ return result;
+
+ const std::string &this_string = this_response.GetStringRef();
+
+ // Check for m or l as first character; l seems to mean this is the last chunk
+ char first_char = *this_string.c_str();
+ if (first_char != 'm' && first_char != 'l')
+ {
+ return PacketResult::ErrorReplyInvalid;
+ }
+ // Skip past m or l
+ const char *s = this_string.c_str() + 1;
+
+ // Concatenate the result so far
+ response_string += s;
+ if (first_char == 'l')
+ // We're done
+ return PacketResult::Success;
+ }
+}
+
+GDBRemoteCommunicationClient::PacketResult
GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
(
const char *payload,
@@ -368,7 +522,18 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
send_async);
}
-size_t
+GDBRemoteCommunicationClient::PacketResult
+GDBRemoteCommunicationClient::SendPacketAndWaitForResponseNoLock (const char *payload,
+ size_t payload_length,
+ StringExtractorGDBRemote &response)
+{
+ PacketResult packet_result = SendPacketNoLock (payload, payload_length);
+ if (packet_result == PacketResult::Success)
+ packet_result = WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ());
+ return packet_result;
+}
+
+GDBRemoteCommunicationClient::PacketResult
GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
(
const char *payload,
@@ -377,18 +542,13 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
bool send_async
)
{
+ PacketResult packet_result = PacketResult::ErrorSendFailed;
Mutex::Locker locker;
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
size_t response_len = 0;
if (GetSequenceMutex (locker))
{
- if (SendPacketNoLock (payload, payload_length))
- response_len = WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ());
- else
- {
- if (log)
- log->Printf("error: failed to send '%*s'", (int) payload_length, payload);
- }
+ packet_result = SendPacketAndWaitForResponseNoLock (payload, payload_length, response);
}
else
{
@@ -424,6 +584,7 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
// Swap the response buffer to avoid malloc and string copy
response.GetStringRef().swap (m_async_response.GetStringRef());
response_len = response.GetStringRef().size();
+ packet_result = m_async_result;
}
else
{
@@ -456,13 +617,7 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
if (log)
log->Printf ("async: got lock without sending interrupt");
// Send the packet normally since we got the lock
- if (SendPacketNoLock (payload, payload_length))
- response_len = WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ());
- else
- {
- if (log)
- log->Printf("error: failed to send '%*s'", (int) payload_length, payload);
- }
+ packet_result = SendPacketAndWaitForResponseNoLock (payload, payload_length, response);
}
}
else
@@ -483,12 +638,7 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
log->Printf("error: failed to get packet sequence mutex, not sending packet '%*s'", (int) payload_length, payload);
}
}
- if (response_len == 0)
- {
- if (log)
- log->Printf("error: failed to get response for '%*s'", (int) payload_length, payload);
- }
- return response_len;
+ return packet_result;
}
static const char *end_delimiter = "--end--;";
@@ -615,7 +765,7 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
{
if (log)
log->Printf ("GDBRemoteCommunicationClient::%s () sending continue packet: %s", __FUNCTION__, continue_packet.c_str());
- if (SendPacketNoLock(continue_packet.c_str(), continue_packet.size()) == 0)
+ if (SendPacketNoLock(continue_packet.c_str(), continue_packet.size()) != PacketResult::Success)
state = eStateInvalid;
m_private_is_running.SetValue (true, eBroadcastAlways);
@@ -626,7 +776,7 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
if (log)
log->Printf ("GDBRemoteCommunicationClient::%s () WaitForPacket(%s)", __FUNCTION__, continue_packet.c_str());
- if (WaitForPacketWithTimeoutMicroSecondsNoLock(response, UINT32_MAX))
+ if (WaitForPacketWithTimeoutMicroSecondsNoLock(response, UINT32_MAX) == PacketResult::Success)
{
if (response.Empty())
state = eStateInvalid;
@@ -683,7 +833,7 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
// packet to make sure it doesn't get in the way
StringExtractorGDBRemote extra_stop_reply_packet;
uint32_t timeout_usec = 1000;
- if (WaitForPacketWithTimeoutMicroSecondsNoLock (extra_stop_reply_packet, timeout_usec))
+ if (WaitForPacketWithTimeoutMicroSecondsNoLock (extra_stop_reply_packet, timeout_usec) == PacketResult::Success)
{
switch (extra_stop_reply_packet.GetChar())
{
@@ -747,11 +897,12 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
Log * packet_log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
// We are supposed to send an asynchronous packet while
- // we are running.
+ // we are running.
m_async_response.Clear();
if (m_async_packet.empty())
{
- if (packet_log)
+ m_async_result = PacketResult::ErrorSendFailed;
+ if (packet_log)
packet_log->Printf ("async: error: empty async packet");
}
@@ -760,10 +911,10 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
if (packet_log)
packet_log->Printf ("async: sending packet");
- SendPacketAndWaitForResponse (&m_async_packet[0],
- m_async_packet.size(),
- m_async_response,
- false);
+ m_async_result = SendPacketAndWaitForResponse (&m_async_packet[0],
+ m_async_packet.size(),
+ m_async_response,
+ false);
}
// Let the other thread that was trying to send the async
// packet know that the packet has been sent and response is
@@ -973,7 +1124,7 @@ lldb::pid_t
GDBRemoteCommunicationClient::GetCurrentProcessID ()
{
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, false))
+ if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, false) == PacketResult::Success)
{
if (response.GetChar() == 'Q')
if (response.GetChar() == 'C')
@@ -987,7 +1138,7 @@ GDBRemoteCommunicationClient::GetLaunchSuccess (std::string &error_str)
{
error_str.clear();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qLaunchSuccess", strlen("qLaunchSuccess"), response, false))
+ if (SendPacketAndWaitForResponse("qLaunchSuccess", strlen("qLaunchSuccess"), response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
return true;
@@ -1050,7 +1201,7 @@ GDBRemoteCommunicationClient::SendArgumentsPacket (const ProcessLaunchInfo &laun
}
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
return 0;
@@ -1097,7 +1248,7 @@ GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_valu
{
packet.PutCString("QEnvironmentHexEncoded:");
packet.PutBytesAsRawHex8 (name_equal_value, strlen(name_equal_value));
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
return 0;
@@ -1113,7 +1264,7 @@ GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_valu
else if (m_supports_QEnvironment)
{
packet.Printf("QEnvironment:%s", name_equal_value);
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
return 0;
@@ -1136,7 +1287,7 @@ GDBRemoteCommunicationClient::SendLaunchArchPacket (char const *arch)
StreamString packet;
packet.Printf("QLaunchArch:%s", arch);
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
return 0;
@@ -1236,7 +1387,7 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force)
{
m_qHostInfo_is_valid = eLazyBoolNo;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse ("qHostInfo", response, false))
+ if (SendPacketAndWaitForResponse ("qHostInfo", response, false) == PacketResult::Success)
{
if (response.IsNormalResponse())
{
@@ -1248,6 +1399,7 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force)
std::string os_name;
std::string vendor_name;
std::string triple;
+ std::string distribution_id;
uint32_t pointer_byte_size = 0;
StringExtractor extractor;
ByteOrder byte_order = eByteOrderInvalid;
@@ -1281,6 +1433,13 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force)
extractor.GetHexByteString (triple);
++num_keys_decoded;
}
+ else if (name.compare ("distribution_id") == 0)
+ {
+ extractor.GetStringRef ().swap (value);
+ extractor.SetFilePos (0);
+ extractor.GetHexByteString (distribution_id);
+ ++num_keys_decoded;
+ }
else if (name.compare("os_build") == 0)
{
extractor.GetStringRef().swap(value);
@@ -1455,7 +1614,9 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force)
{
assert (byte_order == m_host_arch.GetByteOrder());
}
- }
+ }
+ if (!distribution_id.empty ())
+ m_host_arch.SetDistributionId (distribution_id.c_str ());
}
}
}
@@ -1474,7 +1635,7 @@ GDBRemoteCommunicationClient::SendAttach
char packet[64];
const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%" PRIx64, pid);
assert (packet_len < (int)sizeof(packet));
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
{
if (response.IsErrorResponse())
return response.GetError();
@@ -1514,7 +1675,7 @@ GDBRemoteCommunicationClient::AllocateMemory (size_t size, uint32_t permissions)
permissions & lldb::ePermissionsExecutable ? "x" : "");
assert (packet_len < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
{
if (!response.IsErrorResponse())
return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
@@ -1537,7 +1698,7 @@ GDBRemoteCommunicationClient::DeallocateMemory (addr_t addr)
const int packet_len = ::snprintf(packet, sizeof(packet), "_m%" PRIx64, (uint64_t)addr);
assert (packet_len < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
return true;
@@ -1563,7 +1724,7 @@ GDBRemoteCommunicationClient::Detach (bool keep_stopped)
const int packet_len = ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:");
assert (packet_len < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
{
m_supports_detach_stay_stopped = eLazyBoolYes;
}
@@ -1580,15 +1741,15 @@ GDBRemoteCommunicationClient::Detach (bool keep_stopped)
}
else
{
- size_t num_sent = SendPacket ("D1", 2);
- if (num_sent == 0)
+ PacketResult packet_result = SendPacket ("D1", 2);
+ if (packet_result != PacketResult::Success)
error.SetErrorString ("Sending extended disconnect packet failed.");
}
}
else
{
- size_t num_sent = SendPacket ("D", 1);
- if (num_sent == 0)
+ PacketResult packet_result = SendPacket ("D", 1);
+ if (packet_result != PacketResult::Success)
error.SetErrorString ("Sending disconnect packet failed.");
}
return error;
@@ -1608,7 +1769,7 @@ GDBRemoteCommunicationClient::GetMemoryRegionInfo (lldb::addr_t addr,
const int packet_len = ::snprintf(packet, sizeof(packet), "qMemoryRegionInfo:%" PRIx64, (uint64_t)addr);
assert (packet_len < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
{
std::string name;
std::string value;
@@ -1711,7 +1872,7 @@ GDBRemoteCommunicationClient::GetWatchpointSupportInfo (uint32_t &num)
const int packet_len = ::snprintf(packet, sizeof(packet), "qWatchpointSupportInfo:");
assert (packet_len < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
{
m_supports_watchpoint_support_info = eLazyBoolYes;
std::string name;
@@ -1773,7 +1934,7 @@ GDBRemoteCommunicationClient::SetSTDIN (char const *path)
packet.PutBytesAsRawHex8(path, strlen(path));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
return 0;
@@ -1795,7 +1956,7 @@ GDBRemoteCommunicationClient::SetSTDOUT (char const *path)
packet.PutBytesAsRawHex8(path, strlen(path));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
return 0;
@@ -1817,7 +1978,7 @@ GDBRemoteCommunicationClient::SetSTDERR (char const *path)
packet.PutBytesAsRawHex8(path, strlen(path));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
return 0;
@@ -1833,7 +1994,7 @@ bool
GDBRemoteCommunicationClient::GetWorkingDir (std::string &cwd)
{
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse ("qGetWorkingDir", response, false))
+ if (SendPacketAndWaitForResponse ("qGetWorkingDir", response, false) == PacketResult::Success)
{
if (response.IsUnsupportedResponse())
return false;
@@ -1855,7 +2016,7 @@ GDBRemoteCommunicationClient::SetWorkingDir (char const *path)
packet.PutBytesAsRawHex8(path, strlen(path));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
return 0;
@@ -1874,7 +2035,7 @@ GDBRemoteCommunicationClient::SetDisableASLR (bool enable)
const int packet_len = ::snprintf (packet, sizeof (packet), "QSetDisableASLR:%i", enable ? 1 : 0);
assert (packet_len < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
return 0;
@@ -1893,6 +2054,11 @@ GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemot
std::string name;
std::string value;
StringExtractor extractor;
+
+ uint32_t cpu = LLDB_INVALID_CPUTYPE;
+ uint32_t sub = 0;
+ std::string vendor;
+ std::string os_type;
while (response.GetNameColonValue(name, value))
{
@@ -1938,6 +2104,32 @@ GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemot
extractor.GetHexByteString (value);
process_info.GetExecutableFile().SetFile (value.c_str(), false);
}
+ else if (name.compare("cputype") == 0)
+ {
+ cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16);
+ }
+ else if (name.compare("cpusubtype") == 0)
+ {
+ sub = Args::StringToUInt32 (value.c_str(), 0, 16);
+ }
+ else if (name.compare("vendor") == 0)
+ {
+ vendor = value;
+ }
+ else if (name.compare("ostype") == 0)
+ {
+ os_type = value;
+ }
+ }
+
+ if (cpu != LLDB_INVALID_CPUTYPE && !vendor.empty() && !os_type.empty())
+ {
+ if (vendor == "apple")
+ {
+ process_info.GetArchitecture().SetArchitecture (eArchTypeMachO, cpu, sub);
+ process_info.GetArchitecture().GetTriple().setVendorName (llvm::StringRef (vendor));
+ process_info.GetArchitecture().GetTriple().setOSName (llvm::StringRef (os_type));
+ }
}
if (process_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
@@ -1957,7 +2149,7 @@ GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInstanceIn
const int packet_len = ::snprintf (packet, sizeof (packet), "qProcessInfoPID:%" PRIu64, pid);
assert (packet_len < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
{
return DecodeProcessInfoResponse (response, process_info);
}
@@ -1981,7 +2173,7 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo ()
GetHostInfo ();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse ("qProcessInfo", response, false))
+ if (SendPacketAndWaitForResponse ("qProcessInfo", response, false) == PacketResult::Success)
{
if (response.IsNormalResponse())
{
@@ -2141,7 +2333,7 @@ GDBRemoteCommunicationClient::FindProcesses (const ProcessInstanceInfoMatch &mat
}
}
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false))
+ if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
{
do
{
@@ -2151,7 +2343,7 @@ GDBRemoteCommunicationClient::FindProcesses (const ProcessInstanceInfoMatch &mat
process_infos.Append(process_info);
response.GetStringRef().clear();
response.SetFilePos(0);
- } while (SendPacketAndWaitForResponse ("qsProcessInfo", strlen ("qsProcessInfo"), response, false));
+ } while (SendPacketAndWaitForResponse ("qsProcessInfo", strlen ("qsProcessInfo"), response, false) == PacketResult::Success);
}
else
{
@@ -2172,7 +2364,7 @@ GDBRemoteCommunicationClient::GetUserName (uint32_t uid, std::string &name)
const int packet_len = ::snprintf (packet, sizeof (packet), "qUserName:%i", uid);
assert (packet_len < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
{
if (response.IsNormalResponse())
{
@@ -2202,7 +2394,7 @@ GDBRemoteCommunicationClient::GetGroupName (uint32_t gid, std::string &name)
const int packet_len = ::snprintf (packet, sizeof (packet), "qGroupName:%i", gid);
assert (packet_len < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
{
if (response.IsNormalResponse())
{
@@ -2296,32 +2488,36 @@ GDBRemoteCommunicationClient::SendSpeedTestPacket (uint32_t send_size, uint32_t
}
StringExtractorGDBRemote response;
- return SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) > 0;
- return false;
+ return SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success;
}
uint16_t
-GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid)
+GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const char *remote_accept_hostname)
{
pid = LLDB_INVALID_PROCESS_ID;
StringExtractorGDBRemote response;
StreamString stream;
stream.PutCString("qLaunchGDBServer;");
std::string hostname;
- if (Host::GetHostname (hostname))
- {
- // Make the GDB server we launch only accept connections from this host
- stream.Printf("host:%s;", hostname.c_str());
- }
+ if (remote_accept_hostname && remote_accept_hostname[0])
+ hostname = remote_accept_hostname;
else
{
- // Make the GDB server we launch accept connections from any host since we can't figure out the hostname
- stream.Printf("host:*;");
+ if (Host::GetHostname (hostname))
+ {
+ // Make the GDB server we launch only accept connections from this host
+ stream.Printf("host:%s;", hostname.c_str());
+ }
+ else
+ {
+ // Make the GDB server we launch accept connections from any host since we can't figure out the hostname
+ stream.Printf("host:*;");
+ }
}
const char *packet = stream.GetData();
int packet_len = stream.GetSize();
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
std::string name;
std::string value;
@@ -2347,7 +2543,7 @@ GDBRemoteCommunicationClient::KillSpawnedProcess (lldb::pid_t pid)
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
return true;
@@ -2369,7 +2565,7 @@ GDBRemoteCommunicationClient::SetCurrentThread (uint64_t tid)
packet_len = ::snprintf (packet, sizeof(packet), "Hg%" PRIx64, tid);
assert (packet_len + 1 < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
{
@@ -2395,7 +2591,7 @@ GDBRemoteCommunicationClient::SetCurrentThreadForRun (uint64_t tid)
assert (packet_len + 1 < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
{
@@ -2409,7 +2605,7 @@ GDBRemoteCommunicationClient::SetCurrentThreadForRun (uint64_t tid)
bool
GDBRemoteCommunicationClient::GetStopReply (StringExtractorGDBRemote &response)
{
- if (SendPacketAndWaitForResponse("?", 1, response, false))
+ if (SendPacketAndWaitForResponse("?", 1, response, false) == PacketResult::Success)
return response.IsNormalResponse();
return false;
}
@@ -2422,7 +2618,7 @@ GDBRemoteCommunicationClient::GetThreadStopInfo (lldb::tid_t tid, StringExtracto
char packet[256];
int packet_len = ::snprintf(packet, sizeof(packet), "qThreadStopInfo%" PRIx64, tid);
assert (packet_len < (int)sizeof(packet));
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
if (response.IsUnsupportedResponse())
m_supports_qThreadStopInfo = false;
@@ -2463,7 +2659,7 @@ GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type,
assert (packet_len + 1 < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, true))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, true) == PacketResult::Success)
{
if (response.IsOKResponse())
return 0;
@@ -2497,9 +2693,10 @@ GDBRemoteCommunicationClient::GetCurrentThreadIDs (std::vector<lldb::tid_t> &thr
sequence_mutex_unavailable = false;
StringExtractorGDBRemote response;
- for (SendPacketNoLock ("qfThreadInfo", strlen("qfThreadInfo")) && WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ());
- response.IsNormalResponse();
- SendPacketNoLock ("qsThreadInfo", strlen("qsThreadInfo")) && WaitForPacketWithTimeoutMicroSecondsNoLock (response, GetPacketTimeoutInMicroSeconds ()))
+ PacketResult packet_result;
+ for (packet_result = SendPacketAndWaitForResponseNoLock ("qfThreadInfo", strlen("qfThreadInfo"), response);
+ packet_result == PacketResult::Success && response.IsNormalResponse();
+ packet_result = SendPacketAndWaitForResponseNoLock ("qsThreadInfo", strlen("qsThreadInfo"), response))
{
char ch = response.GetChar();
if (ch == 'l')
@@ -2539,7 +2736,7 @@ GDBRemoteCommunicationClient::GetShlibInfoAddr()
if (!IsRunning())
{
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qShlibInfoAddr", ::strlen ("qShlibInfoAddr"), response, false))
+ if (SendPacketAndWaitForResponse("qShlibInfoAddr", ::strlen ("qShlibInfoAddr"), response, false) == PacketResult::Success)
{
if (response.IsNormalResponse())
return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
@@ -2569,7 +2766,7 @@ GDBRemoteCommunicationClient::RunShellCommand (const char *command, //
const char *packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
if (response.GetChar() != 'F')
return Error("malformed reply");
@@ -2608,7 +2805,7 @@ GDBRemoteCommunicationClient::MakeDirectory (const char *path,
const char *packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
return Error(response.GetHexMaxU32(false, UINT32_MAX), eErrorTypePOSIX);
}
@@ -2628,7 +2825,7 @@ GDBRemoteCommunicationClient::SetFilePermissions (const char *path,
const char *packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
return Error(response.GetHexMaxU32(false, UINT32_MAX), eErrorTypePOSIX);
}
@@ -2679,7 +2876,7 @@ GDBRemoteCommunicationClient::OpenFile (const lldb_private::FileSpec& file_spec,
const char* packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
return ParseHostIOPacketResponse (response, UINT64_MAX, error);
}
@@ -2695,7 +2892,7 @@ GDBRemoteCommunicationClient::CloseFile (lldb::user_id_t fd,
const char* packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
return ParseHostIOPacketResponse (response, -1, error) == 0;
}
@@ -2713,7 +2910,7 @@ GDBRemoteCommunicationClient::GetFileSize (const lldb_private::FileSpec& file_sp
const char* packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
if (response.GetChar() != 'F')
return UINT64_MAX;
@@ -2733,7 +2930,7 @@ GDBRemoteCommunicationClient::GetFilePermissions(const char *path, uint32_t &fil
const char* packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
if (response.GetChar() != 'F')
{
@@ -2780,7 +2977,7 @@ GDBRemoteCommunicationClient::ReadFile (lldb::user_id_t fd,
const char* packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
if (response.GetChar() != 'F')
return 0;
@@ -2819,7 +3016,7 @@ GDBRemoteCommunicationClient::WriteFile (lldb::user_id_t fd,
const char* packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
if (response.GetChar() != 'F')
{
@@ -2861,7 +3058,7 @@ GDBRemoteCommunicationClient::CreateSymlink (const char *src, const char *dst)
const char* packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
if (response.GetChar() == 'F')
{
@@ -2902,7 +3099,7 @@ GDBRemoteCommunicationClient::Unlink (const char *path)
const char* packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
if (response.GetChar() == 'F')
{
@@ -2942,7 +3139,7 @@ GDBRemoteCommunicationClient::GetFileExists (const lldb_private::FileSpec& file_
const char* packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
if (response.GetChar() != 'F')
return false;
@@ -2966,7 +3163,7 @@ GDBRemoteCommunicationClient::CalculateMD5 (const lldb_private::FileSpec& file_s
const char* packet = stream.GetData();
int packet_len = stream.GetSize();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
{
if (response.GetChar() != 'F')
return false;
@@ -2998,7 +3195,7 @@ GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid, uint32_t reg, String
else
packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg);
assert (packet_len < ((int)sizeof(packet) - 1));
- return SendPacketAndWaitForResponse(packet, response, false);
+ return SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success;
}
}
return false;
@@ -3024,7 +3221,7 @@ GDBRemoteCommunicationClient::ReadAllRegisters (lldb::tid_t tid, StringExtractor
else
packet_len = ::snprintf (packet, sizeof(packet), "g");
assert (packet_len < ((int)sizeof(packet) - 1));
- return SendPacketAndWaitForResponse(packet, response, false);
+ return SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success;
}
}
return false;
@@ -3051,7 +3248,7 @@ GDBRemoteCommunicationClient::SaveRegisterState (lldb::tid_t tid, uint32_t &save
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false))
+ if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success)
{
if (response.IsUnsupportedResponse())
{
@@ -3094,7 +3291,7 @@ GDBRemoteCommunicationClient::RestoreRegisterState (lldb::tid_t tid, uint32_t sa
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, response, false))
+ if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
{
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index 564afbb2911c..a1e982b3ec4e 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -47,17 +47,38 @@ public:
bool
HandshakeWithServer (lldb_private::Error *error_ptr);
- size_t
+ PacketResult
SendPacketAndWaitForResponse (const char *send_payload,
StringExtractorGDBRemote &response,
bool send_async);
- size_t
+ PacketResult
SendPacketAndWaitForResponse (const char *send_payload,
size_t send_length,
StringExtractorGDBRemote &response,
bool send_async);
+ // For packets which specify a range of output to be returned,
+ // return all of the output via a series of request packets of the form
+ // <prefix>0,<size>
+ // <prefix><size>,<size>
+ // <prefix><size>*2,<size>
+ // <prefix><size>*3,<size>
+ // ...
+ // until a "$l..." packet is received, indicating the end.
+ // (size is in hex; this format is used by a standard gdbserver to
+ // return the given portion of the output specified by <prefix>;
+ // for example, "qXfer:libraries-svr4:read::fff,1000" means
+ // "return a chunk of the xml description file for shared
+ // library load addresses, where the chunk starts at offset 0xfff
+ // and continues for 0x1000 bytes").
+ // Concatenate the resulting server response packets together and
+ // return in response_string. If any packet fails, the return value
+ // indicates that failure and the returned string value is undefined.
+ PacketResult
+ SendPacketsAndConcatenateResponses (const char *send_payload_prefix,
+ std::string &response_string);
+
lldb::StateType
SendContinuePacketAndWaitForResponse (ProcessGDBRemote *process,
const char *packet_payload,
@@ -94,7 +115,7 @@ public:
GetLaunchSuccess (std::string &error_str);
uint16_t
- LaunchGDBserverAndGetPort (lldb::pid_t &pid);
+ LaunchGDBserverAndGetPort (lldb::pid_t &pid, const char *remote_accept_hostname);
bool
KillSpawnedProcess (lldb::pid_t pid);
@@ -248,6 +269,9 @@ public:
const lldb_private::ArchSpec &
GetProcessArchitecture ();
+ void
+ GetRemoteQSupported();
+
bool
GetVContSupported (char flavor);
@@ -359,6 +383,18 @@ public:
bool
SetCurrentThreadForRun (uint64_t tid);
+ bool
+ GetQXferLibrariesReadSupported ();
+
+ bool
+ GetQXferLibrariesSVR4ReadSupported ();
+
+ uint64_t
+ GetRemoteMaxPacketSize();
+
+ bool
+ GetAugmentedLibrariesSVR4ReadSupported ();
+
lldb_private::LazyBool
SupportsAllocDeallocMemory () // const
{
@@ -458,6 +494,11 @@ public:
protected:
+ PacketResult
+ SendPacketAndWaitForResponseNoLock (const char *payload,
+ size_t payload_length,
+ StringExtractorGDBRemote &response);
+
bool
GetCurrentProcessInfo ();
@@ -484,7 +525,10 @@ protected:
lldb_private::LazyBool m_prepare_for_reg_writing_reply;
lldb_private::LazyBool m_supports_p;
lldb_private::LazyBool m_supports_QSaveRegisterState;
-
+ lldb_private::LazyBool m_supports_qXfer_libraries_read;
+ lldb_private::LazyBool m_supports_qXfer_libraries_svr4_read;
+ lldb_private::LazyBool m_supports_augmented_libraries_svr4_read;
+
bool
m_supports_qProcessInfoPID:1,
m_supports_qfProcessInfo:1,
@@ -511,6 +555,7 @@ protected:
lldb_private::Mutex m_async_mutex;
lldb_private::Predicate<bool> m_async_packet_predicate;
std::string m_async_packet;
+ PacketResult m_async_result;
StringExtractorGDBRemote m_async_response;
int m_async_signal; // We were asked to deliver a signal to the inferior process.
bool m_interrupt_sent;
@@ -526,6 +571,7 @@ protected:
std::string m_os_kernel;
std::string m_hostname;
uint32_t m_default_packet_timeout;
+ uint64_t m_max_packet_size; // as returned by qSupported
bool
DecodeProcessInfoResponse (StringExtractorGDBRemote &response,
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 7cc3a05304d4..df95542d2c0f 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -25,6 +25,7 @@
#include "lldb/Host/File.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/TimeValue.h"
+#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
// Project includes
@@ -40,6 +41,7 @@ using namespace lldb_private;
//----------------------------------------------------------------------
GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform),
+ m_platform_sp (Platform::GetDefaultPlatform ()),
m_async_thread (LLDB_INVALID_HOST_THREAD),
m_process_launch_info (),
m_process_launch_error (),
@@ -52,6 +54,23 @@ GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) :
{
}
+GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform,
+ const lldb::PlatformSP& platform_sp) :
+ GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform),
+ m_platform_sp (platform_sp),
+ m_async_thread (LLDB_INVALID_HOST_THREAD),
+ m_process_launch_info (),
+ m_process_launch_error (),
+ m_spawned_pids (),
+ m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),
+ m_proc_infos (),
+ m_proc_infos_index (0),
+ m_port_map (),
+ m_port_offset(0)
+{
+ assert(platform_sp);
+}
+
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
@@ -90,154 +109,249 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
bool &quit)
{
StringExtractorGDBRemote packet;
- if (WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec))
+ PacketResult packet_result = WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec);
+ if (packet_result == PacketResult::Success)
{
const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
switch (packet_type)
{
- case StringExtractorGDBRemote::eServerPacketType_nack:
- case StringExtractorGDBRemote::eServerPacketType_ack:
- break;
-
- case StringExtractorGDBRemote::eServerPacketType_invalid:
- error.SetErrorString("invalid packet");
- quit = true;
- break;
-
- case StringExtractorGDBRemote::eServerPacketType_interrupt:
- error.SetErrorString("interrupt received");
- interrupt = true;
- break;
+ case StringExtractorGDBRemote::eServerPacketType_nack:
+ case StringExtractorGDBRemote::eServerPacketType_ack:
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_invalid:
+ error.SetErrorString("invalid packet");
+ quit = true;
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_interrupt:
+ error.SetErrorString("interrupt received");
+ interrupt = true;
+ break;
+
+ default:
+ case StringExtractorGDBRemote::eServerPacketType_unimplemented:
+ packet_result = SendUnimplementedResponse (packet.GetStringRef().c_str());
+ break;
- case StringExtractorGDBRemote::eServerPacketType_unimplemented:
- return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0;
+ case StringExtractorGDBRemote::eServerPacketType_A:
+ packet_result = Handle_A (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_A:
- return Handle_A (packet);
+ case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
+ packet_result = Handle_qfProcessInfo (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo:
- return Handle_qfProcessInfo (packet);
+ case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
+ packet_result = Handle_qsProcessInfo (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo:
- return Handle_qsProcessInfo (packet);
+ case StringExtractorGDBRemote::eServerPacketType_qC:
+ packet_result = Handle_qC (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_qC:
- return Handle_qC (packet);
+ case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
+ packet_result = Handle_qHostInfo (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_qHostInfo:
- return Handle_qHostInfo (packet);
+ case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
+ packet_result = Handle_qLaunchGDBServer (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer:
- return Handle_qLaunchGDBServer (packet);
+ case StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess:
+ packet_result = Handle_qKillSpawnedProcess (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess:
- return Handle_qKillSpawnedProcess (packet);
+ case StringExtractorGDBRemote::eServerPacketType_k:
+ packet_result = Handle_k (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
- return Handle_qLaunchSuccess (packet);
+ case StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess:
+ packet_result = Handle_qLaunchSuccess (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_qGroupName:
- return Handle_qGroupName (packet);
+ case StringExtractorGDBRemote::eServerPacketType_qGroupName:
+ packet_result = Handle_qGroupName (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
+ packet_result = Handle_qProcessInfoPID (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_qSpeedTest:
+ packet_result = Handle_qSpeedTest (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_qUserName:
+ packet_result = Handle_qUserName (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir:
+ packet_result = Handle_qGetWorkingDir(packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_QEnvironment:
+ packet_result = Handle_QEnvironment (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_QLaunchArch:
+ packet_result = Handle_QLaunchArch (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR:
+ packet_result = Handle_QSetDisableASLR (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
+ packet_result = Handle_QSetSTDIN (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT:
+ packet_result = Handle_QSetSTDOUT (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR:
+ packet_result = Handle_QSetSTDERR (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir:
+ packet_result = Handle_QSetWorkingDir (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
+ packet_result = Handle_QStartNoAckMode (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir:
+ packet_result = Handle_qPlatform_mkdir (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod:
+ packet_result = Handle_qPlatform_chmod (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_qPlatform_shell:
+ packet_result = Handle_qPlatform_shell (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID:
- return Handle_qProcessInfoPID (packet);
+ case StringExtractorGDBRemote::eServerPacketType_vFile_open:
+ packet_result = Handle_vFile_Open (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_qSpeedTest:
- return Handle_qSpeedTest (packet);
-
- case StringExtractorGDBRemote::eServerPacketType_qUserName:
- return Handle_qUserName (packet);
-
- case StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir:
- return Handle_qGetWorkingDir(packet);
-
- case StringExtractorGDBRemote::eServerPacketType_QEnvironment:
- return Handle_QEnvironment (packet);
+ case StringExtractorGDBRemote::eServerPacketType_vFile_close:
+ packet_result = Handle_vFile_Close (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_QLaunchArch:
- return Handle_QLaunchArch (packet);
+ case StringExtractorGDBRemote::eServerPacketType_vFile_pread:
+ packet_result = Handle_vFile_pRead (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR:
- return Handle_QSetDisableASLR (packet);
+ case StringExtractorGDBRemote::eServerPacketType_vFile_pwrite:
+ packet_result = Handle_vFile_pWrite (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_QSetSTDIN:
- return Handle_QSetSTDIN (packet);
+ case StringExtractorGDBRemote::eServerPacketType_vFile_size:
+ packet_result = Handle_vFile_Size (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT:
- return Handle_QSetSTDOUT (packet);
+ case StringExtractorGDBRemote::eServerPacketType_vFile_mode:
+ packet_result = Handle_vFile_Mode (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_QSetSTDERR:
- return Handle_QSetSTDERR (packet);
+ case StringExtractorGDBRemote::eServerPacketType_vFile_exists:
+ packet_result = Handle_vFile_Exists (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir:
- return Handle_QSetWorkingDir (packet);
+ case StringExtractorGDBRemote::eServerPacketType_vFile_stat:
+ packet_result = Handle_vFile_Stat (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode:
- return Handle_QStartNoAckMode (packet);
+ case StringExtractorGDBRemote::eServerPacketType_vFile_md5:
+ packet_result = Handle_vFile_MD5 (packet);
+ break;
- case StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir:
- return Handle_qPlatform_mkdir (packet);
-
- case StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod:
- return Handle_qPlatform_chmod (packet);
-
- case StringExtractorGDBRemote::eServerPacketType_qPlatform_shell:
- return Handle_qPlatform_shell (packet);
-
- case StringExtractorGDBRemote::eServerPacketType_vFile_open:
- return Handle_vFile_Open (packet);
-
- case StringExtractorGDBRemote::eServerPacketType_vFile_close:
- return Handle_vFile_Close (packet);
+ case StringExtractorGDBRemote::eServerPacketType_vFile_symlink:
+ packet_result = Handle_vFile_symlink (packet);
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_vFile_unlink:
+ packet_result = Handle_vFile_unlink (packet);
+ break;
+ }
+ }
+ else
+ {
+ if (!IsConnected())
+ {
+ error.SetErrorString("lost connection");
+ quit = true;
+ }
+ else
+ {
+ error.SetErrorString("timeout");
+ }
+ }
+ return packet_result == PacketResult::Success;
+}
- case StringExtractorGDBRemote::eServerPacketType_vFile_pread:
- return Handle_vFile_pRead (packet);
+lldb_private::Error
+GDBRemoteCommunicationServer::SetLaunchArguments (const char *const args[], int argc)
+{
+ if ((argc < 1) || !args || !args[0] || !args[0][0])
+ return lldb_private::Error ("%s: no process command line specified to launch", __FUNCTION__);
- case StringExtractorGDBRemote::eServerPacketType_vFile_pwrite:
- return Handle_vFile_pWrite (packet);
+ m_process_launch_info.SetArguments (const_cast<const char**> (args), true);
+ return lldb_private::Error ();
+}
- case StringExtractorGDBRemote::eServerPacketType_vFile_size:
- return Handle_vFile_Size (packet);
+lldb_private::Error
+GDBRemoteCommunicationServer::SetLaunchFlags (unsigned int launch_flags)
+{
+ m_process_launch_info.GetFlags ().Set (launch_flags);
+ return lldb_private::Error ();
+}
- case StringExtractorGDBRemote::eServerPacketType_vFile_mode:
- return Handle_vFile_Mode (packet);
+lldb_private::Error
+GDBRemoteCommunicationServer::LaunchProcess ()
+{
+ if (!m_process_launch_info.GetArguments ().GetArgumentCount ())
+ return lldb_private::Error ("%s: no process command line specified to launch", __FUNCTION__);
- case StringExtractorGDBRemote::eServerPacketType_vFile_exists:
- return Handle_vFile_Exists (packet);
+ // specify the process monitor if not already set. This should
+ // generally be what happens since we need to reap started
+ // processes.
+ if (!m_process_launch_info.GetMonitorProcessCallback ())
+ m_process_launch_info.SetMonitorProcessCallback(ReapDebuggedProcess, this, false);
- case StringExtractorGDBRemote::eServerPacketType_vFile_stat:
- return Handle_vFile_Stat (packet);
+ lldb_private::Error error = m_platform_sp->LaunchProcess (m_process_launch_info);
+ if (!error.Success ())
+ {
+ fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0));
+ return error;
+ }
- case StringExtractorGDBRemote::eServerPacketType_vFile_md5:
- return Handle_vFile_MD5 (packet);
+ printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID());
- case StringExtractorGDBRemote::eServerPacketType_vFile_symlink:
- return Handle_vFile_symlink (packet);
-
- case StringExtractorGDBRemote::eServerPacketType_vFile_unlink:
- return Handle_vFile_unlink (packet);
- }
- return true;
- }
- else
+ // add to list of spawned processes. On an lldb-gdbserver, we
+ // would expect there to be only one.
+ lldb::pid_t pid;
+ if ( (pid = m_process_launch_info.GetProcessID()) != LLDB_INVALID_PROCESS_ID )
{
- if (!IsConnected())
- error.SetErrorString("lost connection");
- else
- error.SetErrorString("timeout");
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ m_spawned_pids.insert(pid);
}
- return false;
+ return error;
}
-size_t
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
{
// TODO: Log the packet we aren't handling...
return SendPacketNoLock ("", 0);
}
-size_t
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
{
char packet[16];
@@ -247,7 +361,7 @@ GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
}
-size_t
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::SendOKResponse ()
{
return SendPacketNoLock ("OK", 2);
@@ -256,10 +370,10 @@ GDBRemoteCommunicationServer::SendOKResponse ()
bool
GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr)
{
- return GetAck();
+ return GetAck() == PacketResult::Success;
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet)
{
StreamString response;
@@ -272,6 +386,14 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
+ const char* distribution_id = host_arch.GetDistributionId ().AsCString ();
+ if (distribution_id)
+ {
+ response.PutCString("distribution_id:");
+ response.PutCStringAsRawHex8(distribution_id);
+ response.PutCString(";");
+ }
+
uint32_t cpu = host_arch.GetMachOCPUType();
uint32_t sub = host_arch.GetMachOCPUSubType();
if (cpu != LLDB_INVALID_CPUTYPE)
@@ -351,7 +473,7 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet
}
#endif // #if defined(__APPLE__)
- return SendPacketNoLock (response.GetData(), response.GetSize()) > 0;
+ return SendPacketNoLock (response.GetData(), response.GetSize());
}
static void
@@ -377,7 +499,7 @@ CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &r
}
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
{
// Packet format: "qProcessInfoPID:%i" where %i is the pid
@@ -396,7 +518,7 @@ GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &
return SendErrorResponse (1);
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
{
m_proc_infos_index = 0;
@@ -497,7 +619,7 @@ GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &pa
return SendErrorResponse (3);
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
{
if (m_proc_infos_index < m_proc_infos.GetSize())
@@ -510,7 +632,7 @@ GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &pa
return SendErrorResponse (4);
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet)
{
// Packet format: "qUserName:%i" where %i is the uid
@@ -530,7 +652,7 @@ GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet)
{
// Packet format: "qGroupName:%i" where %i is the gid
@@ -549,7 +671,7 @@ GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packe
return SendErrorResponse (6);
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen ("qSpeedTest:"));
@@ -641,7 +763,7 @@ AcceptPortFromInferior (void *arg)
// return false;
//}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
{
// The 'A' packet is the most over designed packet ever here with
@@ -708,8 +830,11 @@ GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
if (success)
{
+ // FIXME: remove linux restriction once eLaunchFlagDebug is supported
+#if !defined (__linux__)
m_process_launch_info.GetFlags().Set (eLaunchFlagDebug);
- m_process_launch_error = Host::LaunchProcess (m_process_launch_info);
+#endif
+ m_process_launch_error = LaunchProcess ();
if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
{
return SendOKResponse ();
@@ -718,7 +843,7 @@ GDBRemoteCommunicationServer::Handle_A (StringExtractorGDBRemote &packet)
return SendErrorResponse (8);
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qC (StringExtractorGDBRemote &packet)
{
lldb::pid_t pid = m_process_launch_info.GetProcessID();
@@ -762,11 +887,30 @@ GDBRemoteCommunicationServer::ReapDebugserverProcess (void *callback_baton,
}
bool
+GDBRemoteCommunicationServer::DebuggedProcessReaped (lldb::pid_t pid)
+{
+ // reap a process that we were debugging (but not debugserver)
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ return m_spawned_pids.erase(pid) > 0;
+}
+
+bool
+GDBRemoteCommunicationServer::ReapDebuggedProcess (void *callback_baton,
+ lldb::pid_t pid,
+ bool exited,
+ int signal, // Zero for no signal
+ int status) // Exit value of process if signal is zero
+{
+ GDBRemoteCommunicationServer *server = (GDBRemoteCommunicationServer *)callback_baton;
+ server->DebuggedProcessReaped (pid);
+ return true;
+}
+
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
{
#ifdef _WIN32
- // No unix sockets on windows
- return false;
+ return SendErrorResponse(9);
#else
// Spawn a local debugserver as a platform so we can then attach or launch
// a process...
@@ -775,7 +919,6 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
{
// Sleep and wait a bit for debugserver to start to listen...
ConnectionFileDescriptor file_conn;
- char connect_url[PATH_MAX];
Error error;
std::string hostname;
// TODO: /tmp/ should not be hardcoded. User might want to override /tmp
@@ -796,45 +939,23 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
// Spawn a new thread to accept the port that gets bound after
// binding to port 0 (zero).
- lldb::thread_t accept_thread = LLDB_INVALID_HOST_THREAD;
- const char *unix_socket_name = NULL;
- char unix_socket_name_buf[PATH_MAX] = "/tmp/XXXXXXXXX";
-
- if (port == 0)
- {
- if (::mkstemp (unix_socket_name_buf) == 0)
- {
- unix_socket_name = unix_socket_name_buf;
- ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name);
- accept_thread = Host::ThreadCreate (unix_socket_name,
- AcceptPortFromInferior,
- connect_url,
- &error);
- }
- else
- {
- error.SetErrorStringWithFormat("failed to make temporary path for a unix socket: %s", strerror(errno));
- }
- }
if (error.Success())
{
// Spawn a debugserver and try to get the port it listens to.
ProcessLaunchInfo debugserver_launch_info;
- StreamString host_and_port;
if (hostname.empty())
hostname = "localhost";
- host_and_port.Printf("%s:%u", hostname.c_str(), port);
- const char *host_and_port_cstr = host_and_port.GetString().c_str();
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
- log->Printf("Launching debugserver with: %s...\n", host_and_port_cstr);
+ log->Printf("Launching debugserver with: %s:%u...\n", hostname.c_str(), port);
debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false);
- error = StartDebugserverProcess (host_and_port_cstr,
- unix_socket_name,
- debugserver_launch_info);
+ error = StartDebugserverProcess (hostname.empty() ? NULL : hostname.c_str(),
+ port,
+ debugserver_launch_info,
+ port);
lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID();
@@ -854,45 +975,17 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
if (error.Success())
{
- bool success = false;
+ char response[256];
+ const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
+ assert (response_len < sizeof(response));
+ PacketResult packet_result = SendPacketNoLock (response, response_len);
- if (IS_VALID_LLDB_HOST_THREAD(accept_thread))
- {
- thread_result_t accept_thread_result = NULL;
- if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error))
- {
- if (accept_thread_result)
- {
- port = (intptr_t)accept_thread_result;
- char response[256];
- const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
- assert (response_len < sizeof(response));
- //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
- success = SendPacketNoLock (response, response_len) > 0;
- }
- }
- }
- else
- {
- char response[256];
- const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
- assert (response_len < sizeof(response));
- //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID();
- success = SendPacketNoLock (response, response_len) > 0;
-
- }
- Host::Unlink (unix_socket_name);
-
- if (!success)
+ if (packet_result != PacketResult::Success)
{
if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
::kill (debugserver_pid, SIGINT);
}
- return success;
- }
- else if (accept_thread)
- {
- Host::Unlink (unix_socket_name);
+ return packet_result;
}
}
}
@@ -901,59 +994,124 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote
}
bool
-GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
+GDBRemoteCommunicationServer::KillSpawnedProcess (lldb::pid_t pid)
{
- // Spawn a local debugserver as a platform so we can then attach or launch
- // a process...
-
- if (m_is_platform)
+ // make sure we know about this process
{
- packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return false;
+ }
- lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
+ // first try a SIGTERM (standard kill)
+ Host::Kill (pid, SIGTERM);
- // Scope for locker
+ // check if that worked
+ for (size_t i=0; i<10; ++i)
+ {
{
Mutex::Locker locker (m_spawned_pids_mutex);
if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return SendErrorResponse (10);
+ {
+ // it is now killed
+ return true;
+ }
}
- Host::Kill (pid, SIGTERM);
+ usleep (10000);
+ }
+
+ // check one more time after the final usleep
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+
+ // the launched process still lives. Now try killling it again,
+ // this time with an unblockable signal.
+ Host::Kill (pid, SIGKILL);
- for (size_t i=0; i<10; ++i)
+ for (size_t i=0; i<10; ++i)
+ {
{
- // Scope for locker
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
{
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return SendOKResponse();
+ // it is now killed
+ return true;
}
- usleep (10000);
}
+ usleep (10000);
+ }
+
+ // check one more time after the final usleep
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
+
+ // no luck - the process still lives
+ return false;
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
+{
+ packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
+
+ lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
- // Scope for locker
+ // verify that we know anything about this pid.
+ // Scope for locker
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
{
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return SendOKResponse();
+ // not a pid we know about
+ return SendErrorResponse (10);
}
- Host::Kill (pid, SIGKILL);
+ }
+
+ // go ahead and attempt to kill the spawned process
+ if (KillSpawnedProcess (pid))
+ return SendOKResponse ();
+ else
+ return SendErrorResponse (11);
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServer::Handle_k (StringExtractorGDBRemote &packet)
+{
+ // ignore for now if we're lldb_platform
+ if (m_is_platform)
+ return SendUnimplementedResponse (packet.GetStringRef().c_str());
- for (size_t i=0; i<10; ++i)
+ // shutdown all spawned processes
+ std::set<lldb::pid_t> spawned_pids_copy;
+
+ // copy pids
+ {
+ Mutex::Locker locker (m_spawned_pids_mutex);
+ spawned_pids_copy.insert (m_spawned_pids.begin (), m_spawned_pids.end ());
+ }
+
+ // nuke the spawned processes
+ for (auto it = spawned_pids_copy.begin (); it != spawned_pids_copy.end (); ++it)
+ {
+ lldb::pid_t spawned_pid = *it;
+ if (!KillSpawnedProcess (spawned_pid))
{
- // Scope for locker
- {
- Mutex::Locker locker (m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return SendOKResponse();
- }
- usleep (10000);
+ fprintf (stderr, "%s: failed to kill spawned pid %" PRIu64 ", ignoring.\n", __FUNCTION__, spawned_pid);
}
}
- return SendErrorResponse (11);
+
+ // TODO figure out how to shut down gracefully at this point
+ return SendOKResponse ();
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
{
if (m_process_launch_error.Success())
@@ -964,7 +1122,7 @@ GDBRemoteCommunicationServer::Handle_qLaunchSuccess (StringExtractorGDBRemote &p
return SendPacketNoLock (response.GetData(), response.GetSize());
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen ("QEnvironment:"));
@@ -977,7 +1135,7 @@ GDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &pa
return SendErrorResponse (12);
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_QLaunchArch (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen ("QLaunchArch:"));
@@ -992,7 +1150,7 @@ GDBRemoteCommunicationServer::Handle_QLaunchArch (StringExtractorGDBRemote &pack
return SendErrorResponse(13);
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen ("QSetDisableASLR:"));
@@ -1003,7 +1161,7 @@ GDBRemoteCommunicationServer::Handle_QSetDisableASLR (StringExtractorGDBRemote &
return SendOKResponse ();
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen ("QSetWorkingDir:"));
@@ -1027,7 +1185,7 @@ GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &p
return SendOKResponse ();
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)
{
StreamString response;
@@ -1043,8 +1201,7 @@ GDBRemoteCommunicationServer::Handle_qGetWorkingDir (StringExtractorGDBRemote &p
else
{
response.PutBytesAsRawHex8(cwd, strlen(cwd));
- SendPacketNoLock(response.GetData(), response.GetSize());
- return true;
+ return SendPacketNoLock(response.GetData(), response.GetSize());
}
}
else
@@ -1053,8 +1210,7 @@ GDBRemoteCommunicationServer::Handle_qGetWorkingDir (StringExtractorGDBRemote &p
if (working_dir && working_dir[0])
{
response.PutBytesAsRawHex8(working_dir, strlen(working_dir));
- SendPacketNoLock(response.GetData(), response.GetSize());
- return true;
+ return SendPacketNoLock(response.GetData(), response.GetSize());
}
else
{
@@ -1063,7 +1219,7 @@ GDBRemoteCommunicationServer::Handle_qGetWorkingDir (StringExtractorGDBRemote &p
}
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen ("QSetSTDIN:"));
@@ -1080,7 +1236,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet
return SendErrorResponse (15);
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen ("QSetSTDOUT:"));
@@ -1097,7 +1253,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packe
return SendErrorResponse (16);
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen ("QSetSTDERR:"));
@@ -1114,16 +1270,16 @@ GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packe
return SendErrorResponse (17);
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
{
// Send response first before changing m_send_acks to we ack this packet
- SendOKResponse ();
+ PacketResult packet_result = SendOKResponse ();
m_send_acks = false;
- return true;
+ return packet_result;
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen("qPlatform_mkdir:"));
@@ -1141,7 +1297,7 @@ GDBRemoteCommunicationServer::Handle_qPlatform_mkdir (StringExtractorGDBRemote &
return SendErrorResponse(20);
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qPlatform_chmod (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen("qPlatform_chmod:"));
@@ -1160,7 +1316,7 @@ GDBRemoteCommunicationServer::Handle_qPlatform_chmod (StringExtractorGDBRemote &
return SendErrorResponse(19);
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen("vFile:open:"));
@@ -1176,7 +1332,6 @@ GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packe
mode_t mode = packet.GetHexMaxU32(false, 0600);
Error error;
int fd = ::open (path.c_str(), flags, mode);
- printf ("open('%s', flags=0x%x, mode=%o) fd = %i (%s)\n", path.c_str(), flags, mode, fd, fd == -1 ? strerror(errno) : "<success>");
const int save_errno = fd == -1 ? errno : 0;
StreamString response;
response.PutChar('F');
@@ -1190,7 +1345,7 @@ GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packe
return SendErrorResponse(18);
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen("vFile:close:"));
@@ -1215,7 +1370,7 @@ GDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &pack
return SendPacketNoLock(response.GetData(), response.GetSize());
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_vFile_pRead (StringExtractorGDBRemote &packet)
{
#ifdef _WIN32
@@ -1257,7 +1412,7 @@ GDBRemoteCommunicationServer::Handle_vFile_pRead (StringExtractorGDBRemote &pack
#endif
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &packet)
{
#ifdef _WIN32
@@ -1294,7 +1449,7 @@ GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &pac
#endif
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen("vFile:size:"));
@@ -1316,7 +1471,7 @@ GDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packe
return SendErrorResponse(22);
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen("vFile:mode:"));
@@ -1335,7 +1490,7 @@ GDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packe
return SendErrorResponse(23);
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen("vFile:exists:"));
@@ -1356,7 +1511,7 @@ GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &pac
return SendErrorResponse(24);
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_vFile_symlink (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen("vFile:symlink:"));
@@ -1370,7 +1525,7 @@ GDBRemoteCommunicationServer::Handle_vFile_symlink (StringExtractorGDBRemote &pa
return SendPacketNoLock(response.GetData(), response.GetSize());
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_vFile_unlink (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen("vFile:unlink:"));
@@ -1382,7 +1537,7 @@ GDBRemoteCommunicationServer::Handle_vFile_unlink (StringExtractorGDBRemote &pac
return SendPacketNoLock(response.GetData(), response.GetSize());
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_qPlatform_shell (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen("qPlatform_shell:"));
@@ -1424,13 +1579,13 @@ GDBRemoteCommunicationServer::Handle_qPlatform_shell (StringExtractorGDBRemote &
return SendErrorResponse(24);
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_vFile_Stat (StringExtractorGDBRemote &packet)
{
return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_Stat() unimplemented");
}
-bool
+GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet)
{
packet.SetFilePos(::strlen("vFile:MD5:"));
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index 721ea5012b33..913c6b673cfb 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -37,6 +37,9 @@ public:
//------------------------------------------------------------------
GDBRemoteCommunicationServer(bool is_platform);
+ GDBRemoteCommunicationServer(bool is_platform,
+ const lldb::PlatformSP& platform_sp);
+
virtual
~GDBRemoteCommunicationServer();
@@ -138,7 +141,55 @@ public:
m_port_offset = port_offset;
}
+ //------------------------------------------------------------------
+ /// Specify the program to launch and its arguments.
+ ///
+ /// The LaunchProcess () command can be executed to do the lauching.
+ ///
+ /// @param[in] args
+ /// The command line to launch.
+ ///
+ /// @param[in] argc
+ /// The number of elements in the args array of cstring pointers.
+ ///
+ /// @return
+ /// An Error object indicating the success or failure of making
+ /// the setting.
+ //------------------------------------------------------------------
+ lldb_private::Error
+ SetLaunchArguments (const char *const args[], int argc);
+
+ //------------------------------------------------------------------
+ /// Specify the launch flags for the process.
+ ///
+ /// The LaunchProcess () command can be executed to do the lauching.
+ ///
+ /// @param[in] launch_flags
+ /// The launch flags to use when launching this process.
+ ///
+ /// @return
+ /// An Error object indicating the success or failure of making
+ /// the setting.
+ //------------------------------------------------------------------
+ lldb_private::Error
+ SetLaunchFlags (unsigned int launch_flags);
+
+ //------------------------------------------------------------------
+ /// Launch a process with the current launch settings.
+ ///
+ /// This method supports running an lldb-gdbserver or similar
+ /// server in a situation where the startup code has been provided
+ /// with all the information for a child process to be launched.
+ ///
+ /// @return
+ /// An Error object indicating the success or failure of the
+ /// launch.
+ //------------------------------------------------------------------
+ lldb_private::Error
+ LaunchProcess ();
+
protected:
+ lldb::PlatformSP m_platform_sp;
lldb::thread_t m_async_thread;
lldb_private::ProcessLaunchInfo m_process_launch_info;
lldb_private::Error m_process_launch_error;
@@ -148,120 +199,123 @@ protected:
uint32_t m_proc_infos_index;
PortMap m_port_map;
uint16_t m_port_offset;
-
- size_t
+
+ PacketResult
SendUnimplementedResponse (const char *packet);
- size_t
+ PacketResult
SendErrorResponse (uint8_t error);
- size_t
+ PacketResult
SendOKResponse ();
- bool
+ PacketResult
Handle_A (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_qLaunchSuccess (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_qHostInfo (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
+ Handle_k (StringExtractorGDBRemote &packet);
+
+ PacketResult
Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_qPlatform_chmod (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_qProcessInfoPID (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_qfProcessInfo (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_qsProcessInfo (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_qC (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_qUserName (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_qGroupName (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_qSpeedTest (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_QEnvironment (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_QLaunchArch (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_QSetDisableASLR (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_QSetWorkingDir (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_qGetWorkingDir (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_QStartNoAckMode (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_QSetSTDIN (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_QSetSTDOUT (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_QSetSTDERR (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_vFile_Open (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_vFile_Close (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_vFile_pRead (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_vFile_pWrite (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_vFile_Size (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_vFile_Mode (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_vFile_Exists (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_vFile_symlink (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_vFile_unlink (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_vFile_Stat (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_vFile_MD5 (StringExtractorGDBRemote &packet);
- bool
+ PacketResult
Handle_qPlatform_shell (StringExtractorGDBRemote &packet);
private:
@@ -275,6 +329,19 @@ private:
int signal,
int status);
+ bool
+ DebuggedProcessReaped (lldb::pid_t pid);
+
+ static bool
+ ReapDebuggedProcess (void *callback_baton,
+ lldb::pid_t pid,
+ bool exited,
+ int signal,
+ int status);
+
+ bool
+ KillSpawnedProcess (lldb::pid_t pid);
+
//------------------------------------------------------------------
// For GDBRemoteCommunicationServer only
//------------------------------------------------------------------
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index c291df786d10..73b9b3e8267e 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -275,7 +275,7 @@ GDBRemoteRegisterContext::SetPrimordialRegister(const lldb_private::RegisterInfo
if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
packet.GetString().size(),
response,
- false))
+ false) == GDBRemoteCommunication::PacketResult::Success)
{
if (response.IsOKResponse())
return true;
@@ -298,7 +298,7 @@ GDBRemoteRegisterContext::SyncThreadState(Process *process)
if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
packet.GetString().size(),
response,
- false))
+ false) == GDBRemoteCommunication::PacketResult::Success)
{
if (response.IsOKResponse())
InvalidateAllRegisters();
@@ -363,7 +363,7 @@ GDBRemoteRegisterContext::WriteRegisterBytes (const lldb_private::RegisterInfo *
if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
packet.GetString().size(),
response,
- false))
+ false) == GDBRemoteCommunication::PacketResult::Success)
{
SetAllRegisterValid (false);
if (response.IsOKResponse())
@@ -519,7 +519,7 @@ GDBRemoteRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
packet_len = ::snprintf (packet, sizeof(packet), "g");
assert (packet_len < ((int)sizeof(packet) - 1));
- if (gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false) == GDBRemoteCommunication::PacketResult::Success)
{
if (response.IsErrorResponse())
return false;
@@ -591,7 +591,7 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
if (gdb_comm.SendPacketAndWaitForResponse (G_packet,
G_packet_len,
response,
- false))
+ false) == GDBRemoteCommunication::PacketResult::Success)
{
if (response.IsOKResponse())
return true;
@@ -660,7 +660,7 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
packet.GetString().size(),
response,
- false))
+ false) == GDBRemoteCommunication::PacketResult::Success)
{
if (response.IsOKResponse())
++num_restored;
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 7f1fbefc1b7e..e1989eb1dd14 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -34,7 +34,6 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/ConnectionFileDescriptor.h"
#include "lldb/Host/FileSpec.h"
-#include "lldb/Core/InputReader.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
@@ -95,7 +94,7 @@ using namespace lldb_private;
namespace {
-
+
static PropertyDefinition
g_properties[] =
{
@@ -187,7 +186,7 @@ get_random_port ()
if (!rand_initialized)
{
time_t seed = time(NULL);
-
+
rand_initialized = true;
srand(seed);
}
@@ -386,7 +385,7 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
const int packet_len = ::snprintf (packet, sizeof(packet), "qRegisterInfo%x", reg_num);
assert (packet_len < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false))
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false) == GDBRemoteCommunication::PacketResult::Success)
{
response_type = response.GetResponseType();
if (response_type == StringExtractorGDBRemote::eResponse)
@@ -537,6 +536,10 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
}
+ else
+ {
+ break; // ensure exit before reg_num is incremented
+ }
}
else
{
@@ -645,13 +648,20 @@ ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
// We have a valid process
SetID (pid);
GetThreadList();
- if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, m_last_stop_packet, false))
+ if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, m_last_stop_packet, false) == GDBRemoteCommunication::PacketResult::Success)
{
- if (!m_target.GetArchitecture().IsValid()) { // Make sure we have an architecture
- m_target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
+ if (!m_target.GetArchitecture().IsValid())
+ {
+ if (m_gdb_comm.GetProcessArchitecture().IsValid())
+ {
+ m_target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
+ }
+ else
+ {
+ m_target.SetArchitecture(m_gdb_comm.GetHostArchitecture());
+ }
}
-
const StateType state = SetThreadStopInfo (m_last_stop_packet);
if (state == eStateStopped)
{
@@ -690,7 +700,7 @@ ProcessGDBRemote::WillLaunchOrAttach ()
// Process Control
//----------------------------------------------------------------------
Error
-ProcessGDBRemote::DoLaunch (Module *exe_module, const ProcessLaunchInfo &launch_info)
+ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
{
Error error;
@@ -728,23 +738,10 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, const ProcessLaunchInfo &launch_
ObjectFile * object_file = exe_module->GetObjectFile();
if (object_file)
{
- char host_port[128];
- snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
- char connect_url[128];
- snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
-
// Make sure we aren't already connected?
if (!m_gdb_comm.IsConnected())
{
- error = StartDebugserverProcess (host_port, launch_info);
- if (error.Fail())
- {
- if (log)
- log->Printf("failed to start debugserver process: %s", error.AsCString());
- return error;
- }
-
- error = ConnectToDebugserver (connect_url);
+ error = LaunchAndConnectToDebugserver (launch_info);
}
if (error.Success())
@@ -848,10 +845,18 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, const ProcessLaunchInfo &launch_
return error;
}
- if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, m_last_stop_packet, false))
+ if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, m_last_stop_packet, false) == GDBRemoteCommunication::PacketResult::Success)
{
- if (!m_target.GetArchitecture().IsValid()) { // Make sure we have an architecture
- m_target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
+ if (!m_target.GetArchitecture().IsValid())
+ {
+ if (m_gdb_comm.GetProcessArchitecture().IsValid())
+ {
+ m_target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
+ }
+ else
+ {
+ m_target.SetArchitecture(m_gdb_comm.GetHostArchitecture());
+ }
}
SetPrivateState (SetThreadStopInfo (m_last_stop_packet));
@@ -886,31 +891,35 @@ Error
ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
{
Error error;
- // Sleep and wait a bit for debugserver to start to listen...
- std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
- if (conn_ap.get())
+ // Only connect if we have a valid connect URL
+
+ if (connect_url && connect_url[0])
{
- const uint32_t max_retry_count = 50;
- uint32_t retry_count = 0;
- while (!m_gdb_comm.IsConnected())
+ std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
+ if (conn_ap.get())
{
- if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess)
+ const uint32_t max_retry_count = 50;
+ uint32_t retry_count = 0;
+ while (!m_gdb_comm.IsConnected())
{
- m_gdb_comm.SetConnection (conn_ap.release());
- break;
- }
- else if (error.WasInterrupted())
- {
- // If we were interrupted, don't keep retrying.
- break;
- }
-
- retry_count++;
-
- if (retry_count >= max_retry_count)
- break;
+ if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess)
+ {
+ m_gdb_comm.SetConnection (conn_ap.release());
+ break;
+ }
+ else if (error.WasInterrupted())
+ {
+ // If we were interrupted, don't keep retrying.
+ break;
+ }
+
+ retry_count++;
+
+ if (retry_count >= max_retry_count)
+ break;
- usleep (100000);
+ usleep (100000);
+ }
}
}
@@ -1040,12 +1049,7 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const Process
// Make sure we aren't already connected?
if (!m_gdb_comm.IsConnected())
{
- char host_port[128];
- snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
- char connect_url[128];
- snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
-
- error = StartDebugserverProcess (host_port, attach_info);
+ error = LaunchAndConnectToDebugserver (attach_info);
if (error.Fail())
{
@@ -1055,10 +1059,6 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const Process
SetExitStatus (-1, error_string);
}
- else
- {
- error = ConnectToDebugserver (connect_url);
- }
}
if (error.Success())
@@ -1072,29 +1072,8 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const Process
return error;
}
-size_t
-ProcessGDBRemote::AttachInputReaderCallback
-(
- void *baton,
- InputReader *reader,
- lldb::InputReaderAction notification,
- const char *bytes,
- size_t bytes_len
-)
-{
- if (notification == eInputReaderGotToken)
- {
- ProcessGDBRemote *gdb_process = (ProcessGDBRemote *)baton;
- if (gdb_process->m_waiting_for_attach)
- gdb_process->m_waiting_for_attach = false;
- reader->SetIsDone(true);
- return 1;
- }
- return 0;
-}
-
Error
-ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait_for_launch, const ProcessAttachInfo &attach_info)
+ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const ProcessAttachInfo &attach_info)
{
Error error;
// Clear out and clean up from any current state
@@ -1105,12 +1084,8 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait
// Make sure we aren't already connected?
if (!m_gdb_comm.IsConnected())
{
- char host_port[128];
- snprintf (host_port, sizeof(host_port), "localhost:%u", get_random_port ());
- char connect_url[128];
- snprintf (connect_url, sizeof(connect_url), "connect://%s", host_port);
+ error = LaunchAndConnectToDebugserver (attach_info);
- error = StartDebugserverProcess (host_port, attach_info);
if (error.Fail())
{
const char *error_string = error.AsCString();
@@ -1119,17 +1094,13 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, bool wait
SetExitStatus (-1, error_string);
}
- else
- {
- error = ConnectToDebugserver (connect_url);
- }
}
if (error.Success())
{
StreamString packet;
- if (wait_for_launch)
+ if (attach_info.GetWaitForLaunch())
{
if (!m_gdb_comm.GetVAttachOrWaitSupported())
{
@@ -1199,7 +1170,11 @@ ProcessGDBRemote::DoResume ()
bool continue_packet_error = false;
if (m_gdb_comm.HasAnyVContSupport ())
{
- if (m_continue_c_tids.size() == num_threads)
+ if (m_continue_c_tids.size() == num_threads ||
+ (m_continue_c_tids.empty() &&
+ m_continue_C_tids.empty() &&
+ m_continue_s_tids.empty() &&
+ m_continue_S_tids.empty()))
{
// All threads are continuing, just send a "c" packet
continue_packet.PutCString ("c");
@@ -2026,7 +2001,7 @@ ProcessGDBRemote::DoDestroy ()
bool send_async = true;
const uint32_t old_packet_timeout = m_gdb_comm.SetPacketTimeout (3);
- if (m_gdb_comm.SendPacketAndWaitForResponse("k", 1, response, send_async))
+ if (m_gdb_comm.SendPacketAndWaitForResponse("k", 1, response, send_async) == GDBRemoteCommunication::PacketResult::Success)
{
char packet_cmd = response.GetChar(0);
@@ -2128,7 +2103,7 @@ ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &erro
const int packet_len = ::snprintf (packet, sizeof(packet), "m%" PRIx64 ",%" PRIx64, (uint64_t)addr, (uint64_t)size);
assert (packet_len + 1 < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true))
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true) == GDBRemoteCommunication::PacketResult::Success)
{
if (response.IsNormalResponse())
{
@@ -2164,7 +2139,7 @@ ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Erro
packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size);
packet.PutBytesAsRawHex8(buf, size, lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder());
StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, true))
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, true) == GDBRemoteCommunication::PacketResult::Success)
{
if (response.IsOKResponse())
{
@@ -2546,14 +2521,7 @@ ProcessGDBRemote::DoSignal (int signo)
}
Error
-ProcessGDBRemote::StartDebugserverProcess (const char *debugserver_url)
-{
- ProcessLaunchInfo launch_info;
- return StartDebugserverProcess(debugserver_url, launch_info);
-}
-
-Error
-ProcessGDBRemote::StartDebugserverProcess (const char *debugserver_url, const ProcessInfo &process_info) // The connection string to use in the spawned debugserver ("localhost:1234" or "/dev/tty...")
+ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info)
{
Error error;
if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID)
@@ -2562,141 +2530,55 @@ ProcessGDBRemote::StartDebugserverProcess (const char *debugserver_url, const Pr
static FileSpec g_debugserver_file_spec;
ProcessLaunchInfo debugserver_launch_info;
- char debugserver_path[PATH_MAX];
- FileSpec &debugserver_file_spec = debugserver_launch_info.GetExecutableFile();
-
- // Always check to see if we have an environment override for the path
- // to the debugserver to use and use it if we do.
- const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
- if (env_debugserver_path)
- debugserver_file_spec.SetFile (env_debugserver_path, false);
- else
- debugserver_file_spec = g_debugserver_file_spec;
- bool debugserver_exists = debugserver_file_spec.Exists();
- if (!debugserver_exists)
- {
- // The debugserver binary is in the LLDB.framework/Resources
- // directory.
- if (Host::GetLLDBPath (ePathTypeSupportExecutableDir, debugserver_file_spec))
- {
- debugserver_file_spec.GetFilename().SetCString(DEBUGSERVER_BASENAME);
- debugserver_exists = debugserver_file_spec.Exists();
- if (debugserver_exists)
- {
- g_debugserver_file_spec = debugserver_file_spec;
- }
- else
- {
- g_debugserver_file_spec.Clear();
- debugserver_file_spec.Clear();
- }
- }
- }
-
- if (debugserver_exists)
- {
- debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));
-
- m_stdio_communication.Clear();
-
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
-
- Args &debugserver_args = debugserver_launch_info.GetArguments();
- char arg_cstr[PATH_MAX];
+ debugserver_launch_info.SetMonitorProcessCallback (MonitorDebugserverProcess, this, false);
+ debugserver_launch_info.SetUserID(process_info.GetUserID());
- // Start args with "debugserver /file/path -r --"
- debugserver_args.AppendArgument(debugserver_path);
- debugserver_args.AppendArgument(debugserver_url);
- // use native registers, not the GDB registers
- debugserver_args.AppendArgument("--native-regs");
- // make debugserver run in its own session so signals generated by
- // special terminal key sequences (^C) don't affect debugserver
- debugserver_args.AppendArgument("--setsid");
-
- const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
- if (env_debugserver_log_file)
- {
- ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file);
- debugserver_args.AppendArgument(arg_cstr);
- }
-
- const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
- if (env_debugserver_log_flags)
- {
- ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
- debugserver_args.AppendArgument(arg_cstr);
- }
-// debugserver_args.AppendArgument("--log-file=/tmp/debugserver.txt");
-// debugserver_args.AppendArgument("--log-flags=0x802e0e");
-
- // We currently send down all arguments, attach pids, or attach
- // process names in dedicated GDB server packets, so we don't need
- // to pass them as arguments. This is currently because of all the
- // things we need to setup prior to launching: the environment,
- // current working dir, file actions, etc.
-#if 0
- // Now append the program arguments
- if (inferior_argv)
- {
- // Terminate the debugserver args so we can now append the inferior args
- debugserver_args.AppendArgument("--");
-
- for (int i = 0; inferior_argv[i] != NULL; ++i)
- debugserver_args.AppendArgument (inferior_argv[i]);
- }
- else if (attach_pid != LLDB_INVALID_PROCESS_ID)
- {
- ::snprintf (arg_cstr, sizeof(arg_cstr), "--attach=%u", attach_pid);
- debugserver_args.AppendArgument (arg_cstr);
- }
- else if (attach_name && attach_name[0])
- {
- if (wait_for_launch)
- debugserver_args.AppendArgument ("--waitfor");
- else
- debugserver_args.AppendArgument ("--attach");
- debugserver_args.AppendArgument (attach_name);
- }
+#if defined (__APPLE__) && defined (__arm__)
+ // On iOS, still do a local connection using a random port
+ const char *hostname = "localhost";
+ uint16_t port = get_random_port ();
+#else
+ // Set hostname being NULL to do the reverse connect where debugserver
+ // will bind to port zero and it will communicate back to us the port
+ // that we will connect to
+ const char *hostname = NULL;
+ uint16_t port = 0;
#endif
-
- ProcessLaunchInfo::FileAction file_action;
-
- // Close STDIN, STDOUT and STDERR. We might need to redirect them
- // to "/dev/null" if we run into any problems.
- file_action.Close (STDIN_FILENO);
- debugserver_launch_info.AppendFileAction (file_action);
- file_action.Close (STDOUT_FILENO);
- debugserver_launch_info.AppendFileAction (file_action);
- file_action.Close (STDERR_FILENO);
- debugserver_launch_info.AppendFileAction (file_action);
-
- if (log)
- {
- StreamString strm;
- debugserver_args.Dump (&strm);
- log->Printf("%s arguments:\n%s", debugserver_args.GetArgumentAtIndex(0), strm.GetData());
- }
- debugserver_launch_info.SetMonitorProcessCallback (MonitorDebugserverProcess, this, false);
- debugserver_launch_info.SetUserID(process_info.GetUserID());
+ error = m_gdb_comm.StartDebugserverProcess (hostname,
+ port,
+ debugserver_launch_info,
+ port);
- error = Host::LaunchProcess(debugserver_launch_info);
+ if (error.Success ())
+ m_debugserver_pid = debugserver_launch_info.GetProcessID();
+ else
+ m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
- if (error.Success ())
- m_debugserver_pid = debugserver_launch_info.GetProcessID();
- else
- m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
+ if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ StartAsyncThread ();
+
+ if (error.Fail())
+ {
+ Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- if (error.Fail() || log)
- error.PutToLog(log, "Host::LaunchProcess (launch_info) => pid=%" PRIu64 ", path='%s'", m_debugserver_pid, debugserver_path);
+ if (log)
+ log->Printf("failed to start debugserver process: %s", error.AsCString());
+ return error;
+ }
+
+ if (m_gdb_comm.IsConnected())
+ {
+ // Finish the connection process by doing the handshake without connecting (send NULL URL)
+ ConnectToDebugserver (NULL);
}
else
{
- error.SetErrorStringWithFormat ("unable to locate " DEBUGSERVER_BASENAME);
+ StreamString connect_url;
+ connect_url.Printf("connect://%s:%u", hostname, port);
+ error = ConnectToDebugserver (connect_url.GetString().c_str());
}
- if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
- StartAsyncThread ();
}
return error;
}
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 35244074bab7..9331775bb896 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -21,7 +21,6 @@
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Error.h"
-#include "lldb/Core/InputReader.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/StringList.h"
#include "lldb/Core/ThreadSafeValue.h"
@@ -86,7 +85,7 @@ public:
virtual lldb_private::Error
DoLaunch (lldb_private::Module *exe_module,
- const lldb_private::ProcessLaunchInfo &launch_info);
+ lldb_private::ProcessLaunchInfo &launch_info);
virtual void
DidLaunch ();
@@ -111,7 +110,6 @@ public:
virtual lldb_private::Error
DoAttachToProcessWithName (const char *process_name,
- bool wait_for_launch,
const lldb_private::ProcessAttachInfo &attach_info);
virtual void
@@ -284,10 +282,7 @@ protected:
lldb_private::ThreadList &new_thread_list);
lldb_private::Error
- StartDebugserverProcess (const char *debugserver_url);
-
- lldb_private::Error
- StartDebugserverProcess (const char *debugserver_url, const lldb_private::ProcessInfo &process_info);
+ LaunchAndConnectToDebugserver (const lldb_private::ProcessInfo &process_info);
void
KillDebugserverProcess ();
@@ -382,13 +377,6 @@ protected:
GetDispatchQueueNameForThread (lldb::addr_t thread_dispatch_qaddr,
std::string &dispatch_queue_name);
- static size_t
- AttachInputReaderCallback (void *baton,
- lldb_private::InputReader *reader,
- lldb::InputReaderAction notification,
- const char *bytes,
- size_t bytes_len);
-
lldb_private::DynamicLoader *
GetDynamicLoader ();
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 4e475c80bdab..fb524deda813 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -19,6 +19,7 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StopInfo.h"
+#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Unwind.h"
@@ -74,10 +75,10 @@ ThreadGDBRemote::GetQueueName ()
ProcessSP process_sp (GetProcess());
if (process_sp)
{
- PlatformSP platform_sp (process_sp->GetTarget().GetPlatform());
- if (platform_sp)
+ SystemRuntime *runtime = process_sp->GetSystemRuntime ();
+ if (runtime)
{
- m_dispatch_queue_name = platform_sp->GetQueueNameForThreadQAddress (process_sp.get(), m_thread_dispatch_qaddr);
+ m_dispatch_queue_name = runtime->GetQueueNameFromThreadQAddress (m_thread_dispatch_qaddr);
}
if (m_dispatch_queue_name.length() > 0)
{
@@ -96,10 +97,10 @@ ThreadGDBRemote::GetQueueID ()
ProcessSP process_sp (GetProcess());
if (process_sp)
{
- PlatformSP platform_sp (process_sp->GetTarget().GetPlatform());
- if (platform_sp)
+ SystemRuntime *runtime = process_sp->GetSystemRuntime ();
+ if (runtime)
{
- return platform_sp->GetQueueIDForThreadQAddress (process_sp.get(), m_thread_dispatch_qaddr);
+ return runtime->GetQueueIDFromThreadQAddress (m_thread_dispatch_qaddr);
}
}
}
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
index fce995e4ff2e..d6c580c7ab1b 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
+++ b/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h
@@ -53,7 +53,7 @@ public:
bool ExtractValue(const lldb_private::DWARFDataExtractor& data,
lldb::offset_t* offset_ptr,
const DWARFCompileUnit* cu);
- bool IsInlinedCStr() const { return (m_value.data != NULL) && m_value.data == (uint8_t*)m_value.value.cstr; }
+ bool IsInlinedCStr() const { return (m_value.data != NULL) && m_value.data == (const uint8_t*)m_value.value.cstr; }
const uint8_t* BlockData() const;
uint64_t Reference(const DWARFCompileUnit* cu) const;
uint64_t Reference (dw_offset_t offset) const;
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 09b50531b8a9..ef03cac540c6 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1644,6 +1644,13 @@ struct BitfieldInfo
{
}
+ void
+ Clear()
+ {
+ bit_size = LLDB_INVALID_ADDRESS;
+ bit_offset = LLDB_INVALID_ADDRESS;
+ }
+
bool IsValid ()
{
return (bit_size != LLDB_INVALID_ADDRESS) &&
@@ -1915,12 +1922,14 @@ SymbolFileDWARF::ParseChildMembers
accessibility = default_accessibility;
member_accessibilities.push_back(accessibility);
- BitfieldInfo this_field_info;
-
- this_field_info.bit_size = bit_size;
-
- if (member_byte_offset != UINT32_MAX || bit_size != 0)
+ uint64_t field_bit_offset = (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8));
+ if (bit_size > 0)
{
+
+ BitfieldInfo this_field_info;
+ this_field_info.bit_offset = field_bit_offset;
+ this_field_info.bit_size = bit_size;
+
/////////////////////////////////////////////////////////////
// How to locate a field given the DWARF debug information
//
@@ -1937,10 +1946,9 @@ SymbolFileDWARF::ParseChildMembers
// AT_bit_size indicates the size of the field in bits.
/////////////////////////////////////////////////////////////
- this_field_info.bit_offset = 0;
-
- this_field_info.bit_offset += (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8));
-
+ if (byte_size == 0)
+ byte_size = member_type->GetByteSize();
+
if (GetObjectFile()->GetByteOrder() == eByteOrderLittle)
{
this_field_info.bit_offset += byte_size * 8;
@@ -1950,30 +1958,30 @@ SymbolFileDWARF::ParseChildMembers
{
this_field_info.bit_offset += bit_offset;
}
- }
+
+ // Update the field bit offset we will report for layout
+ field_bit_offset = this_field_info.bit_offset;
- // If the member to be emitted did not start on a character boundary and there is
- // empty space between the last field and this one, then we need to emit an
- // anonymous member filling up the space up to its start. There are three cases
- // here:
- //
- // 1 If the previous member ended on a character boundary, then we can emit an
- // anonymous member starting at the most recent character boundary.
- //
- // 2 If the previous member did not end on a character boundary and the distance
- // from the end of the previous member to the current member is less than a
- // word width, then we can emit an anonymous member starting right after the
- // previous member and right before this member.
- //
- // 3 If the previous member did not end on a character boundary and the distance
- // from the end of the previous member to the current member is greater than
- // or equal a word width, then we act as in Case 1.
-
- const uint64_t character_width = 8;
- const uint64_t word_width = 32;
-
- if (this_field_info.IsValid())
- {
+ // If the member to be emitted did not start on a character boundary and there is
+ // empty space between the last field and this one, then we need to emit an
+ // anonymous member filling up the space up to its start. There are three cases
+ // here:
+ //
+ // 1 If the previous member ended on a character boundary, then we can emit an
+ // anonymous member starting at the most recent character boundary.
+ //
+ // 2 If the previous member did not end on a character boundary and the distance
+ // from the end of the previous member to the current member is less than a
+ // word width, then we can emit an anonymous member starting right after the
+ // previous member and right before this member.
+ //
+ // 3 If the previous member did not end on a character boundary and the distance
+ // from the end of the previous member to the current member is greater than
+ // or equal a word width, then we act as in Case 1.
+
+ const uint64_t character_width = 8;
+ const uint64_t word_width = 32;
+
// Objective-C has invalid DW_AT_bit_offset values in older versions
// of clang, so we have to be careful and only insert unnammed bitfields
// if we have a new enough clang.
@@ -2019,6 +2027,11 @@ SymbolFileDWARF::ParseChildMembers
layout_info.field_offsets.insert(std::make_pair(unnamed_bitfield_decl, anon_field_info.bit_offset));
}
}
+ last_field_info = this_field_info;
+ }
+ else
+ {
+ last_field_info.Clear();
}
ClangASTType member_clang_type = member_type->GetClangLayoutType();
@@ -2062,11 +2075,8 @@ SymbolFileDWARF::ParseChildMembers
GetClangASTContext().SetMetadataAsUserID (field_decl, MakeUserID(die->GetOffset()));
- if (this_field_info.IsValid())
- {
- layout_info.field_offsets.insert(std::make_pair(field_decl, this_field_info.bit_offset));
- last_field_info = this_field_info;
- }
+ layout_info.field_offsets.insert(std::make_pair(field_decl, field_bit_offset));
+
}
else
{
@@ -2546,6 +2556,37 @@ SymbolFileDWARF::ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type)
if (!base_classes.empty())
{
+ // Make sure all base classes refer to complete types and not
+ // forward declarations. If we don't do this, clang will crash
+ // with an assertion in the call to clang_type.SetBaseClassesForClassType()
+ bool base_class_error = false;
+ for (auto &base_class : base_classes)
+ {
+ clang::TypeSourceInfo *type_source_info = base_class->getTypeSourceInfo();
+ if (type_source_info)
+ {
+ ClangASTType base_class_type (GetClangASTContext().getASTContext(), type_source_info->getType());
+ if (base_class_type.GetCompleteType() == false)
+ {
+ if (!base_class_error)
+ {
+ GetObjectFile()->GetModule()->ReportError ("DWARF DIE at 0x%8.8x for class '%s' has a base class '%s' that is a forward declaration, not a complete definition.\nPlease file a bug against the compiler and include the preprocessed output for %s",
+ die->GetOffset(),
+ die->GetName(this, dwarf_cu),
+ base_class_type.GetTypeName().GetCString(),
+ sc.comp_unit ? sc.comp_unit->GetPath().c_str() : "the source file");
+ }
+ // We have no choice other than to pretend that the base class
+ // is complete. If we don't do this, clang will crash when we
+ // call setBases() inside of "clang_type.SetBaseClassesForClassType()"
+ // below. Since we provide layout assistance, all ivars in this
+ // class and other classe will be fine, this is the best we can do
+ // short of crashing.
+ base_class_type.StartTagDeclarationDefinition ();
+ base_class_type.CompleteTagDeclarationDefinition ();
+ }
+ }
+ }
clang_type.SetBaseClassesForClassType (&base_classes.front(),
base_classes.size());
@@ -6222,6 +6263,11 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
case DW_TAG_subprogram:
case DW_TAG_member:
case DW_TAG_APPLE_property:
+ case DW_TAG_class_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_enumeration_type:
+ case DW_TAG_typedef:
+ case DW_TAG_union_type:
child_die = NULL;
is_forward_declaration = false;
break;
diff --git a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
index 6500aabdcea3..a9f8f36e610e 100644
--- a/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
+++ b/source/Plugins/SymbolVendor/ELF/SymbolVendorELF.cpp
@@ -9,12 +9,8 @@
#include "SymbolVendorELF.h"
-//#include <libxml/parser.h>
-// #include <libxml/tree.h>
#include <string.h>
-// #include <AvailabilityMacros.h>
-
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"