Initial checkin of lldb code from internal Apple repo.


git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@105619 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp b/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp
new file mode 100644
index 0000000..db2d561
--- /dev/null
+++ b/source/Plugins/Disassembler/llvm/DisassemblerLLVM.cpp
@@ -0,0 +1,468 @@
+//===-- DisassemblerLLVM.cpp ------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DisassemblerLLVM.h"
+
+#include "llvm-c/EnhancedDisassembly.h"
+
+#include "lldb/Core/Address.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Symbol/SymbolContext.h"
+
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+
+#include <memory>
+#include <string>
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+static
+int DataExtractorByteReader(uint8_t *byte, uint64_t address, void *arg)
+{
+    DataExtractor &extractor = *((DataExtractor *)arg);
+
+    if (extractor.ValidOffset(address))
+    {
+        *byte = *(extractor.GetDataStart() + address);
+        return 0;
+    }
+    else
+    {
+        return -1;
+    }
+}
+
+namespace {
+    struct RegisterReaderArg {
+        const lldb::addr_t instructionPointer;
+        const EDDisassemblerRef disassembler;
+
+        RegisterReaderArg(lldb::addr_t ip,
+                          EDDisassemblerRef dis) :
+            instructionPointer(ip),
+            disassembler(dis)
+        {
+        }
+    };
+}
+
+static int IPRegisterReader(uint64_t *value, unsigned regID, void* arg)
+{
+    uint64_t instructionPointer = ((RegisterReaderArg*)arg)->instructionPointer;
+    EDDisassemblerRef disassembler = ((RegisterReaderArg*)arg)->disassembler;
+
+    if(EDRegisterIsProgramCounter(disassembler, regID)) {
+        *value = instructionPointer;
+        return 0;
+    }
+
+    return -1;
+}
+
+DisassemblerLLVM::Instruction::Instruction(EDDisassemblerRef disassembler) :
+    Disassembler::Instruction (),
+    m_disassembler (disassembler)
+{
+}
+
+DisassemblerLLVM::Instruction::~Instruction()
+{
+}
+
+static void
+PadString(Stream *s, const std::string &str, size_t width)
+{
+    int diff = width - str.length();
+
+    if (diff > 0)
+        s->Printf("%s%*.*s", str.c_str(), diff, diff, "");
+    else
+        s->Printf("%s ", str.c_str());
+}
+
+void
+DisassemblerLLVM::Instruction::Dump
+(
+    Stream *s,
+    lldb::addr_t base_address,
+    DataExtractor *bytes,
+    uint32_t bytes_offset,
+    const lldb_private::ExecutionContext exe_ctx,
+    bool raw
+)
+{
+    const size_t opcodeColumnWidth = 7;
+    const size_t operandColumnWidth = 25;
+
+    // If we have an address, print it out
+    if (base_address != LLDB_INVALID_ADDRESS)
+        s->Printf("0x%llx:  ", base_address);
+
+    // If we are supposed to show bytes, "bytes" will be non-NULL.
+    if (bytes)
+    {
+        uint32_t bytes_dumped = bytes->Dump(s, bytes_offset, eFormatBytes, 1, EDInstByteSize(m_inst), UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0) - bytes_offset;
+        // Allow for 8 bytes of opcodes normally
+        const uint32_t default_num_opcode_bytes = 9;
+        if (bytes_dumped * 3 < (default_num_opcode_bytes*3))
+        {
+            uint32_t indent_level = (default_num_opcode_bytes*3) - (bytes_dumped * 3);
+            s->Printf("%*.*s", indent_level, indent_level, "");
+        }
+    }
+
+    int numTokens = EDNumTokens(m_inst);
+
+    int currentOpIndex = -1;
+
+    RegisterReaderArg rra(base_address + EDInstByteSize(m_inst), m_disassembler);
+
+    lldb_private::Process *process = exe_ctx.process;
+
+    bool printTokenized = false;
+
+    if (numTokens != -1)
+    {
+        printTokenized = true;
+
+        // Handle the opcode column.
+
+        StreamString opcode;
+
+        int tokenIndex = 0;
+
+        EDTokenRef token;
+        const char *tokenStr;
+
+        if (EDGetToken(&token, m_inst, tokenIndex))
+            printTokenized = false;
+
+        if (!printTokenized || !EDTokenIsOpcode(token))
+            printTokenized = false;
+
+        if (!printTokenized || EDGetTokenString(&tokenStr, token))
+            printTokenized = false;
+
+        // Put the token string into our opcode string
+        opcode.PutCString(tokenStr);
+
+        // If anything follows, it probably starts with some whitespace.  Skip it.
+
+        tokenIndex++;
+
+        if (printTokenized && tokenIndex < numTokens)
+        {
+            if(!printTokenized || EDGetToken(&token, m_inst, tokenIndex))
+                printTokenized = false;
+
+            if(!printTokenized || !EDTokenIsWhitespace(token))
+                printTokenized = false;
+        }
+
+        tokenIndex++;
+
+        // Handle the operands and the comment.
+
+        StreamString operands;
+        StreamString comment;
+
+        if (printTokenized)
+        {
+            bool show_token;
+
+            for (; tokenIndex < numTokens; ++tokenIndex)
+            {
+                if (EDGetToken(&token, m_inst, tokenIndex))
+                    return;
+
+                if (raw)
+                {
+                    show_token = true;
+                }
+                else
+                {
+                    int operandIndex = EDOperandIndexForToken(token);
+
+                    if (operandIndex >= 0)
+                    {
+                        if (operandIndex != currentOpIndex)
+                        {
+                            show_token = true;
+
+                            currentOpIndex = operandIndex;
+                            EDOperandRef operand;
+
+                            if (!EDGetOperand(&operand, m_inst, currentOpIndex))
+                            {
+                                if (EDOperandIsMemory(operand))
+                                {
+                                    uint64_t operand_value;
+
+                                    if (!EDEvaluateOperand(&operand_value, operand, IPRegisterReader, &rra))
+                                    {
+                                        if (EDInstIsBranch(m_inst))
+                                        {
+                                            operands.Printf("0x%llx ", operand_value);
+                                            show_token = false;
+                                        }
+                                        else
+                                        {
+                                            // Put the address value into the comment
+                                            comment.Printf("0x%llx ", operand_value);
+                                        }
+
+                                        lldb_private::Address so_addr;
+                                        if (process)
+                                        {
+                                            if (process->ResolveLoadAddress(operand_value, so_addr))
+                                            {
+                                                so_addr.Dump(&comment, process, Address::DumpStyleResolvedDescription, Address::DumpStyleSectionNameOffset);
+                                            }
+                                        }
+                                    } // EDEvaluateOperand
+                                } // EDOperandIsMemory
+                            } // EDGetOperand
+                        } // operandIndex != currentOpIndex
+                    } // operandIndex >= 0
+                } // else(raw)
+
+                if (show_token)
+                {
+                    if(EDGetTokenString(&tokenStr, token))
+                    {
+                        printTokenized = false;
+                        break;
+                    }
+
+                    operands.PutCString(tokenStr);
+                }
+            } // for (tokenIndex)
+
+            if (printTokenized)
+            {
+                if (operands.GetString().empty())
+                {
+                    s->PutCString(opcode.GetString().c_str());
+                }
+                else
+                {
+                    PadString(s, opcode.GetString(), opcodeColumnWidth);
+
+                    if (comment.GetString().empty())
+                    {
+                        s->PutCString(operands.GetString().c_str());
+                    }
+                    else
+                    {
+                        PadString(s, operands.GetString(), operandColumnWidth);
+
+                        s->PutCString("; ");
+                        s->PutCString(comment.GetString().c_str());
+                    } // else (comment.GetString().empty())
+                } // else (operands.GetString().empty())
+            } // printTokenized
+        } // for (tokenIndex)
+    } // numTokens != -1
+
+    if (!printTokenized)
+    {
+        const char *str;
+
+        if (EDGetInstString(&str, m_inst))
+            return;
+        else
+            s->PutCString(str);
+    }
+}
+
+bool
+DisassemblerLLVM::Instruction::DoesBranch() const
+{
+    return EDInstIsBranch(m_inst);
+}
+
+size_t
+DisassemblerLLVM::Instruction::GetByteSize() const
+{
+    return EDInstByteSize(m_inst);
+}
+
+size_t
+DisassemblerLLVM::Instruction::Extract(const DataExtractor &data, uint32_t data_offset)
+{
+    if (EDCreateInsts(&m_inst, 1, m_disassembler, DataExtractorByteReader, data_offset, (void*)(&data)))
+        return EDInstByteSize(m_inst);
+    else
+        return 0;
+}
+
+static inline const char *
+TripleForCPU(cpu_type_t cpuType)
+{
+    switch (cpuType)
+    {
+    default:
+        return NULL;
+    case CPU_TYPE_X86:
+        return "i386-unknown-unknown";
+    case CPU_TYPE_X86_64:
+        return "x86_64-unknown-unknown";
+    }
+}
+
+static inline EDAssemblySyntax_t
+SyntaxForCPU(cpu_type_t cpuType)
+{
+    switch (cpuType)
+    {
+    default:
+        return (EDAssemblySyntax_t)0;   // default
+    case CPU_TYPE_X86:
+    case CPU_TYPE_X86_64:
+        return kEDAssemblySyntaxX86ATT;
+    }
+}
+
+Disassembler *
+DisassemblerLLVM::CreateInstance(const ArchSpec &arch)
+{
+    cpu_type_t cpuType = arch.GetCPUType();
+
+    if (TripleForCPU(cpuType))
+        return new DisassemblerLLVM(arch);
+    else
+        return NULL;
+}
+
+DisassemblerLLVM::DisassemblerLLVM(const ArchSpec &arch) :
+    Disassembler(arch)
+{
+    cpu_type_t cpuType = arch.GetCPUType();
+
+    const char *triple = TripleForCPU(cpuType);
+    assert(triple && "Unhandled CPU type!");
+
+    EDAssemblySyntax_t syntax = SyntaxForCPU(cpuType);
+
+    assert(!EDGetDisassembler(&m_disassembler, triple, syntax) && "No disassembler created!");
+}
+
+DisassemblerLLVM::~DisassemblerLLVM()
+{
+}
+
+size_t
+DisassemblerLLVM::ParseInstructions
+(
+    const DataExtractor& data,
+    uint32_t data_offset,
+    uint32_t num_instructions,
+    lldb::addr_t base_addr
+)
+{
+    size_t total_inst_byte_size = 0;
+
+    m_instruction_list.Clear();
+
+    while (data.ValidOffset(data_offset) && num_instructions)
+    {
+        Instruction::shared_ptr inst_sp (new Instruction(m_disassembler));
+
+        size_t inst_byte_size = inst_sp->Extract(data, data_offset);
+
+        if (inst_byte_size == 0)
+            break;
+
+        m_instruction_list.AppendInstruction(inst_sp);
+
+        total_inst_byte_size += inst_byte_size;
+        data_offset += inst_byte_size;
+        num_instructions--;
+    }
+
+    return total_inst_byte_size;
+}
+
+void
+DisassemblerLLVM::Initialize()
+{
+    PluginManager::RegisterPlugin (GetPluginNameStatic(),
+                                   GetPluginDescriptionStatic(),
+                                   CreateInstance);
+}
+
+void
+DisassemblerLLVM::Terminate()
+{
+    PluginManager::UnregisterPlugin (CreateInstance);
+}
+
+
+const char *
+DisassemblerLLVM::GetPluginNameStatic()
+{
+    return "disassembler.llvm";
+}
+
+const char *
+DisassemblerLLVM::GetPluginDescriptionStatic()
+{
+    return "Disassembler that uses LLVM opcode tables to disassemble i386 and x86_64.";
+}
+
+//------------------------------------------------------------------
+// PluginInterface protocol
+//------------------------------------------------------------------
+const char *
+DisassemblerLLVM::GetPluginName()
+{
+    return "DisassemblerLLVM";
+}
+
+const char *
+DisassemblerLLVM::GetShortPluginName()
+{
+    return GetPluginNameStatic();
+}
+
+uint32_t
+DisassemblerLLVM::GetPluginVersion()
+{
+    return 1;
+}
+
+void
+DisassemblerLLVM::GetPluginCommandHelp (const char *command, Stream *strm)
+{
+}
+
+Error
+DisassemblerLLVM::ExecutePluginCommand (Args &command, Stream *strm)
+{
+    Error error;
+    error.SetErrorString("No plug-in command are currently supported.");
+    return error;
+}
+
+Log *
+DisassemblerLLVM::EnablePluginLogging (Stream *strm, Args &command)
+{
+    return NULL;
+}
+