//===-- CommandObjectImage.cpp ----------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "CommandObjectImage.h"

// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Debugger.h"
#include "lldb/Core/FileSpec.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/RegularExpression.h"
#include "lldb/Core/Stream.h"
#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/CommandCompletions.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"

using namespace lldb;
using namespace lldb_private;

//----------------------------------------------------------------------
// Static Helper functions
//----------------------------------------------------------------------
static void
DumpModuleArchitecture (Stream &strm, Module *module, uint32_t width)
{
    if (module)
    {
        if (width)
            strm.Printf("%-*s", width, module->GetArchitecture().AsCString());
        else
            strm.PutCString(module->GetArchitecture().AsCString());
    }
}

static void
DumpModuleUUID (Stream &strm, Module *module)
{
    module->GetUUID().Dump (&strm);
}

static uint32_t
DumpCompileUnitLineTable
(
    CommandInterpreter &interpreter,
    Stream &strm,
    Module *module,
    const FileSpec &file_spec,
    bool load_addresses
)
{
    uint32_t num_matches = 0;
    if (module)
    {
        SymbolContextList sc_list;
        num_matches = module->ResolveSymbolContextsForFileSpec (file_spec,
                                                                0,
                                                                false,
                                                                eSymbolContextCompUnit,
                                                                sc_list);
        
        for (uint32_t i=0; i<num_matches; ++i)
        {
            SymbolContext sc;
            if (sc_list.GetContextAtIndex(i, sc))
            {
                if (i > 0)
                    strm << "\n\n";

                strm << "Line table for " << *dynamic_cast<FileSpec*> (sc.comp_unit) << " in `"
                     << module->GetFileSpec().GetFilename() << "\n";
                LineTable *line_table = sc.comp_unit->GetLineTable();
                if (line_table)
                    line_table->GetDescription (&strm, 
                                                interpreter.GetDebugger().GetExecutionContext().process, 
                                                lldb::eDescriptionLevelBrief);
                else
                    strm << "No line table";
            }
        }
    }
    return num_matches;
}

static void
DumpFullpath (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
{
    if (file_spec_ptr)
    {
        if (width > 0)
        {
            char fullpath[PATH_MAX];
            if (file_spec_ptr->GetPath(fullpath, sizeof(fullpath)))
            {
                strm.Printf("%-*s", width, fullpath);
                return;
            }
        }
        else
        {
            file_spec_ptr->Dump(&strm);
            return;
        }
    }
    // Keep the width spacing correct if things go wrong...
    if (width > 0)
        strm.Printf("%-*s", width, "");
}

static void
DumpDirectory (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
{
    if (file_spec_ptr)
    {
        if (width > 0)
            strm.Printf("%-*s", width, file_spec_ptr->GetDirectory().AsCString(""));
        else
            file_spec_ptr->GetDirectory().Dump(&strm);
        return;
    }
    // Keep the width spacing correct if things go wrong...
    if (width > 0)
        strm.Printf("%-*s", width, "");
}

static void
DumpBasename (Stream &strm, const FileSpec *file_spec_ptr, uint32_t width)
{
    if (file_spec_ptr)
    {
        if (width > 0)
            strm.Printf("%-*s", width, file_spec_ptr->GetFilename().AsCString(""));
        else
            file_spec_ptr->GetFilename().Dump(&strm);
        return;
    }
    // Keep the width spacing correct if things go wrong...
    if (width > 0)
        strm.Printf("%-*s", width, "");
}


static void
DumpModuleSymtab (CommandInterpreter &interpreter, Stream &strm, Module *module)
{
    if (module)
    {
        ObjectFile *objfile = module->GetObjectFile ();
        if (objfile)
        {
            Symtab *symtab = objfile->GetSymtab();
            if (symtab)
                symtab->Dump(&strm, interpreter.GetDebugger().GetExecutionContext().process);
        }
    }
}

static void
DumpModuleSections (CommandInterpreter &interpreter, Stream &strm, Module *module)
{
    if (module)
    {
        ObjectFile *objfile = module->GetObjectFile ();
        if (objfile)
        {
            SectionList *section_list = objfile->GetSectionList();
            if (section_list)
                section_list->Dump(&strm, interpreter.GetDebugger().GetExecutionContext().process, true);
        }
    }
}

static bool
DumpModuleSymbolVendor (Stream &strm, Module *module)
{
    if (module)
    {
        SymbolVendor *symbol_vendor = module->GetSymbolVendor(true);
        if (symbol_vendor)
        {
            symbol_vendor->Dump(&strm);
            return true;
        }
    }
    return false;
}

static bool
LookupAddressInModule (CommandInterpreter &interpreter, Stream &strm, Module *module, uint32_t resolve_mask, lldb::addr_t raw_addr, lldb::addr_t offset)
{
    if (module)
    {
        lldb::addr_t addr = raw_addr - offset;
        Address so_addr;
        SymbolContext sc;
        Process *process = interpreter.GetDebugger().GetExecutionContext().process;
        if (process && process->IsAlive())
        {
            if (!process->ResolveLoadAddress (addr, so_addr))
                return false;
            else if (so_addr.GetModule() != module)
                return false;
        }
        else
        {
            if (!module->ResolveFileAddress (addr, so_addr))
                return false;
        }

        // If an offset was given, print out the address we ended up looking up
        if (offset)
            strm.Printf("0x%llx: ", addr);

        ExecutionContextScope *exe_scope = interpreter.GetDebugger().GetExecutionContext().GetBestExecutionContextScope();
        strm.IndentMore();
        strm.Indent ("    Address: ");
        so_addr.Dump (&strm, exe_scope, Address::DumpStyleSectionNameOffset);
        strm.EOL();
        strm.Indent ("    Summary: ");
        so_addr.Dump (&strm, exe_scope, Address::DumpStyleResolvedDescription);
        strm.EOL();
        if (so_addr.Dump (&strm, exe_scope, Address::DumpStyleDetailedSymbolContext))
            strm.EOL();
        strm.IndentLess();
        return true;
    }

    return false;
}

static uint32_t
LookupSymbolInModule (CommandInterpreter &interpreter, Stream &strm, Module *module, const char *name, bool name_is_regex)
{
    if (module)
    {
        SymbolContext sc;

        ObjectFile *objfile = module->GetObjectFile ();
        if (objfile)
        {
            Symtab *symtab = objfile->GetSymtab();
            if (symtab)
            {
                uint32_t i;
                std::vector<uint32_t> match_indexes;
                ConstString symbol_name (name);
                uint32_t num_matches = 0;
                if (name_is_regex)
                {
                    RegularExpression name_regexp(name);
                    num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType (name_regexp, eSymbolTypeAny,
                                                                                   match_indexes);
                }
                else
                {
                    num_matches = symtab->AppendSymbolIndexesWithName (symbol_name, match_indexes);
                }


                if (num_matches > 0)
                {
                    strm.Indent ();
                    strm.Printf("%u symbols match %s'%s' in ", num_matches,
                                name_is_regex ? "the regular expression " : "", name);
                    DumpFullpath (strm, &module->GetFileSpec(), 0);
                    strm.PutCString(":\n");
                    strm.IndentMore ();
                    Symtab::DumpSymbolHeader (&strm);
                    for (i=0; i < num_matches; ++i)
                    {
                        Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]);
                        strm.Indent ();
                        symbol->Dump (&strm, interpreter.GetDebugger().GetExecutionContext().process, i);
                    }
                    strm.IndentLess ();
                    return num_matches;
                }
            }
        }
    }
    return 0;
}


static void
DumpSymbolContextList (CommandInterpreter &interpreter, Stream &strm, SymbolContextList &sc_list, bool prepend_addr)
{
    strm.IndentMore ();
    uint32_t i;
    const uint32_t num_matches = sc_list.GetSize();

    for (i=0; i<num_matches; ++i)
    {
        SymbolContext sc;
        if (sc_list.GetContextAtIndex(i, sc))
        {
            strm.Indent();
            if (prepend_addr)
            {
                if (sc.line_entry.range.GetBaseAddress().IsValid())
                {
                    lldb::addr_t vm_addr =
                                      sc.line_entry.range.GetBaseAddress().GetLoadAddress(interpreter.GetDebugger().GetExecutionContext().process);
                    int addr_size = sizeof (addr_t);
                    Process *process = interpreter.GetDebugger().GetExecutionContext().process;
                    if (process)
                        addr_size = process->GetAddressByteSize();
                    if (vm_addr != LLDB_INVALID_ADDRESS)
                        strm.Address (vm_addr, addr_size);
                    else
                        sc.line_entry.range.GetBaseAddress().Dump (&strm, NULL, Address::DumpStyleSectionNameOffset);

                    strm.PutCString(" in ");
                }
            }
            sc.DumpStopContext(&strm, interpreter.GetDebugger().GetExecutionContext().process, sc.line_entry.range.GetBaseAddress());
        }
    }
    strm.IndentLess ();
}

static uint32_t
LookupFunctionInModule (CommandInterpreter &interpreter, Stream &strm, Module *module, const char *name, bool name_is_regex)
{
    if (module && name && name[0])
    {
        SymbolContextList sc_list;

        SymbolVendor *symbol_vendor = module->GetSymbolVendor();
        if (symbol_vendor)
        {
            uint32_t num_matches = 0;
            if (name_is_regex)
            {
                RegularExpression function_name_regex (name);
                num_matches = symbol_vendor->FindFunctions(function_name_regex, true, sc_list);

            }
            else
            {
                ConstString function_name(name);
                num_matches = symbol_vendor->FindFunctions(function_name, eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeMethod | eFunctionNameTypeSelector, true, sc_list);
            }

            if (num_matches)
            {
                strm.Indent ();
                strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : "");
                DumpFullpath (strm, &module->GetFileSpec(), 0);
                strm.PutCString(":\n");
                DumpSymbolContextList (interpreter, strm, sc_list, true);
            }
            return num_matches;
        }
    }
    return 0;
}

static uint32_t
LookupFileAndLineInModule (CommandInterpreter &interpreter, Stream &strm, Module *module, const FileSpec &file_spec, uint32_t line, bool check_inlines)
{
    if (module && file_spec)
    {
        SymbolContextList sc_list;
        const uint32_t num_matches = module->ResolveSymbolContextsForFileSpec(file_spec, line, check_inlines,
                                                                             eSymbolContextEverything, sc_list);
        if (num_matches > 0)
        {
            strm.Indent ();
            strm.Printf("%u match%s found in ", num_matches, num_matches > 1 ? "es" : "");
            strm << file_spec;
            if (line > 0)
                strm.Printf (":%u", line);
            strm << " in ";
            DumpFullpath (strm, &module->GetFileSpec(), 0);
            strm.PutCString(":\n");
            DumpSymbolContextList (interpreter, strm, sc_list, true);
            return num_matches;
        }
    }
    return 0;

}


//----------------------------------------------------------------------
// Image symbol table dumping command
//----------------------------------------------------------------------

class CommandObjectImageDumpModuleList : public CommandObject
{
public:

    CommandObjectImageDumpModuleList (const char *name,
                                      const char *help,
                                      const char *syntax) :
        CommandObject (name, help, syntax)
    {
    }

    virtual
    ~CommandObjectImageDumpModuleList ()
    {
    }

    virtual int
    HandleArgumentCompletion (CommandInterpreter &interpreter,
                              Args &input,
                              int &cursor_index,
                              int &cursor_char_position,
                              OptionElementVector &opt_element_vector,
                              int match_start_point,
                              int max_return_elements,
                              bool &word_complete,
                              StringList &matches)
    {
        // Arguments are the standard module completer.
        std::string completion_str (input.GetArgumentAtIndex(cursor_index));
        completion_str.erase (cursor_char_position);

        CommandCompletions::InvokeCommonCompletionCallbacks (interpreter,
                                                             CommandCompletions::eModuleCompletion,
                                                             completion_str.c_str(),
                                                             match_start_point,
                                                             max_return_elements,
                                                             NULL,
                                                             word_complete,
                                                             matches);
        return matches.GetSize();
    }
};

class CommandObjectImageDumpSourceFileList : public CommandObject
{
public:

    CommandObjectImageDumpSourceFileList (const char *name,
                                          const char *help,
                                          const char *syntax) :
        CommandObject (name, help, syntax)
    {
    }

    virtual
    ~CommandObjectImageDumpSourceFileList ()
    {
    }

    virtual int
    HandleArgumentCompletion (CommandInterpreter &interpreter,
                              Args &input,
                              int &cursor_index,
                              int &cursor_char_position,
                              OptionElementVector &opt_element_vector,
                              int match_start_point,
                              int max_return_elements,
                              bool &word_complete,
                              StringList &matches)
    {
        // Arguments are the standard source file completer.
        std::string completion_str (input.GetArgumentAtIndex(cursor_index));
        completion_str.erase (cursor_char_position);

        CommandCompletions::InvokeCommonCompletionCallbacks (interpreter, 
                                                             CommandCompletions::eSourceFileCompletion,
                                                             completion_str.c_str(),
                                                             match_start_point,
                                                             max_return_elements,
                                                             NULL,
                                                             word_complete,
                                                             matches);
        return matches.GetSize();
    }
};


class CommandObjectImageDumpSymtab : public CommandObjectImageDumpModuleList
{
public:
    CommandObjectImageDumpSymtab () :
        CommandObjectImageDumpModuleList ("image dump symtab",
                         "Dump the symbol table from one or more executable images.",
                         "image dump symtab [<file1> ...]")
    {
    }

    virtual
    ~CommandObjectImageDumpSymtab ()
    {
    }

    virtual bool
    Execute (CommandInterpreter &interpreter,
             Args& command,
             CommandReturnObject &result)
    {
        Target *target = interpreter.GetDebugger().GetCurrentTarget().get();
        if (target == NULL)
        {
            result.AppendError ("invalid target, set executable file using 'file' command");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }
        else
        {
            uint32_t num_dumped = 0;

            uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
            result.GetOutputStream().SetAddressByteSize(addr_byte_size);
            result.GetErrorStream().SetAddressByteSize(addr_byte_size);

            if (command.GetArgumentCount() == 0)
            {
                // Dump all sections for all modules images
                const uint32_t num_modules = target->GetImages().GetSize();
                if (num_modules > 0)
                {
                    result.GetOutputStream().Printf("Dumping symbol table for %u modules.\n", num_modules);
                    for (uint32_t image_idx = 0;  image_idx<num_modules; ++image_idx)
                    {
                        num_dumped++;
                        DumpModuleSymtab (interpreter, result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx));
                    }
                }
                else
                {
                    result.AppendError ("the target has no associated executable images");
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
            else
            {
                // Dump specified images (by basename or fullpath)
                const char *arg_cstr;
                for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
                {
                    FileSpec image_file(arg_cstr);
                    ModuleList matching_modules;
                    size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);

                    // Not found in our module list for our target, check the main
                    // shared module list in case it is a extra file used somewhere
                    // else
                    if (num_matching_modules == 0)
                        num_matching_modules = ModuleList::FindSharedModules (image_file, 
                                                                              target->GetArchitecture(), 
                                                                              NULL, 
                                                                              NULL, 
                                                                              matching_modules);
                    
                    if (num_matching_modules > 0)
                    {
                        for (size_t i=0; i<num_matching_modules; ++i)
                        {
                            Module *image_module = matching_modules.GetModulePointerAtIndex(i);
                            if (image_module)
                            {
                                num_dumped++;
                                DumpModuleSymtab (interpreter, result.GetOutputStream(), image_module);
                            }
                        }
                    }
                    else
                        result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
                }
            }

            if (num_dumped > 0)
                result.SetStatus (eReturnStatusSuccessFinishResult);
            else
            {
                result.AppendError ("no matching executable images found");
                result.SetStatus (eReturnStatusFailed);
            }
        }
        return result.Succeeded();
    }

};

//----------------------------------------------------------------------
// Image section dumping command
//----------------------------------------------------------------------
class CommandObjectImageDumpSections : public CommandObjectImageDumpModuleList
{
public:
    CommandObjectImageDumpSections () :
        CommandObjectImageDumpModuleList ("image dump sections",
                                          "Dump the sections from one or more executable images.",
                                          "image dump sections [<file1> ...]")
    {
    }

    virtual
    ~CommandObjectImageDumpSections ()
    {
    }

    virtual bool
    Execute (CommandInterpreter &interpreter,
             Args& command,
             CommandReturnObject &result)
    {
        Target *target = interpreter.GetDebugger().GetCurrentTarget().get();
        if (target == NULL)
        {
            result.AppendError ("invalid target, set executable file using 'file' command");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }
        else
        {
            uint32_t num_dumped = 0;

            uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
            result.GetOutputStream().SetAddressByteSize(addr_byte_size);
            result.GetErrorStream().SetAddressByteSize(addr_byte_size);

            if (command.GetArgumentCount() == 0)
            {
                // Dump all sections for all modules images
                const uint32_t num_modules = target->GetImages().GetSize();
                if (num_modules > 0)
                {
                    result.GetOutputStream().Printf("Dumping sections for %u modules.\n", num_modules);
                    for (uint32_t image_idx = 0;  image_idx<num_modules; ++image_idx)
                    {
                        num_dumped++;
                        DumpModuleSections (interpreter, result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx));
                    }
                }
                else
                {
                    result.AppendError ("the target has no associated executable images");
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
            else
            {
                // Dump specified images (by basename or fullpath)
                const char *arg_cstr;
                for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
                {
                    FileSpec image_file(arg_cstr);
                    ModuleList matching_modules;
                    size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);

                    // Not found in our module list for our target, check the main
                    // shared module list in case it is a extra file used somewhere
                    // else
                    if (num_matching_modules == 0)
                        num_matching_modules = ModuleList::FindSharedModules (image_file, 
                                                                              target->GetArchitecture(), 
                                                                              NULL, 
                                                                              NULL, 
                                                                              matching_modules);
                    
                    if (num_matching_modules > 0)
                    {
                        for (size_t i=0; i<num_matching_modules; ++i)
                        {
                            Module * image_module = matching_modules.GetModulePointerAtIndex(i);
                            if (image_module)
                            {
                                num_dumped++;
                                DumpModuleSections (interpreter, result.GetOutputStream(), image_module);
                            }
                        }
                    }
                    else
                        result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
                }
            }

            if (num_dumped > 0)
                result.SetStatus (eReturnStatusSuccessFinishResult);
            else
            {
                result.AppendError ("no matching executable images found");
                result.SetStatus (eReturnStatusFailed);
            }
        }
        return result.Succeeded();
    }
};

//----------------------------------------------------------------------
// Image debug symbol dumping command
//----------------------------------------------------------------------
class CommandObjectImageDumpSymfile : public CommandObjectImageDumpModuleList
{
public:
    CommandObjectImageDumpSymfile () :
        CommandObjectImageDumpModuleList ("image dump symfile",
                         "Dump the debug symbol file for one or more executable images.",
                         "image dump symfile [<file1> ...]")
    {
    }

    virtual
    ~CommandObjectImageDumpSymfile ()
    {
    }

    virtual bool
    Execute (CommandInterpreter &interpreter,
             Args& command,
             CommandReturnObject &result)
    {
        Target *target = interpreter.GetDebugger().GetCurrentTarget().get();
        if (target == NULL)
        {
            result.AppendError ("invalid target, set executable file using 'file' command");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }
        else
        {
            uint32_t num_dumped = 0;

            uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
            result.GetOutputStream().SetAddressByteSize(addr_byte_size);
            result.GetErrorStream().SetAddressByteSize(addr_byte_size);

            if (command.GetArgumentCount() == 0)
            {
                // Dump all sections for all modules images
                const uint32_t num_modules = target->GetImages().GetSize();
                if (num_modules > 0)
                {
                    result.GetOutputStream().Printf("Dumping debug symbols for %u modules.\n", num_modules);
                    for (uint32_t image_idx = 0;  image_idx<num_modules; ++image_idx)
                    {
                        if (DumpModuleSymbolVendor (result.GetOutputStream(), target->GetImages().GetModulePointerAtIndex(image_idx)))
                            num_dumped++;
                    }
                }
                else
                {
                    result.AppendError ("the target has no associated executable images");
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
            else
            {
                // Dump specified images (by basename or fullpath)
                const char *arg_cstr;
                for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
                {
                    FileSpec image_file(arg_cstr);
                    ModuleList matching_modules;
                    size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);

                    // Not found in our module list for our target, check the main
                    // shared module list in case it is a extra file used somewhere
                    // else
                    if (num_matching_modules == 0)
                        num_matching_modules = ModuleList::FindSharedModules (image_file, 
                                                                              target->GetArchitecture(), 
                                                                              NULL, 
                                                                              NULL, 
                                                                              matching_modules);
                    
                    if (num_matching_modules > 0)
                    {
                        for (size_t i=0; i<num_matching_modules; ++i)
                        {
                            Module * image_module = matching_modules.GetModulePointerAtIndex(i);
                            if (image_module)
                            {
                                if (DumpModuleSymbolVendor (result.GetOutputStream(), image_module))
                                    num_dumped++;
                            }
                        }
                    }
                    else
                        result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
                }
            }

            if (num_dumped > 0)
                result.SetStatus (eReturnStatusSuccessFinishResult);
            else
            {
                result.AppendError ("no matching executable images found");
                result.SetStatus (eReturnStatusFailed);
            }
        }
        return result.Succeeded();
    }
};

//----------------------------------------------------------------------
// Image debug symbol dumping command
//----------------------------------------------------------------------
class CommandObjectImageDumpLineTable : public CommandObjectImageDumpSourceFileList
{
public:
    CommandObjectImageDumpLineTable () :
        CommandObjectImageDumpSourceFileList ("image dump line-table",
                         "Dump the debug symbol file for one or more executable images.",
                         "image dump line-table <file1> [<file2> ...]")
    {
    }

    virtual
    ~CommandObjectImageDumpLineTable ()
    {
    }

    virtual bool
    Execute (CommandInterpreter &interpreter,
             Args& command,
             CommandReturnObject &result)
    {
        Target *target = interpreter.GetDebugger().GetCurrentTarget().get();
        if (target == NULL)
        {
            result.AppendError ("invalid target, set executable file using 'file' command");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }
        else
        {
            ExecutionContext exe_ctx(interpreter.GetDebugger().GetExecutionContext());
            uint32_t total_num_dumped = 0;

            uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
            result.GetOutputStream().SetAddressByteSize(addr_byte_size);
            result.GetErrorStream().SetAddressByteSize(addr_byte_size);

            if (command.GetArgumentCount() == 0)
            {
                result.AppendErrorWithFormat ("\nSyntax: %s\n", m_cmd_syntax.c_str());
                result.SetStatus (eReturnStatusFailed);
            }
            else
            {
                // Dump specified images (by basename or fullpath)
                const char *arg_cstr;
                for (int arg_idx = 0; (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != NULL; ++arg_idx)
                {
                    FileSpec file_spec(arg_cstr);
                    const uint32_t num_modules = target->GetImages().GetSize();
                    if (num_modules > 0)
                    {
                        uint32_t num_dumped = 0;
                        for (uint32_t i = 0; i<num_modules; ++i)
                        {
                            if (DumpCompileUnitLineTable (interpreter,
                                                          result.GetOutputStream(),
                                                          target->GetImages().GetModulePointerAtIndex(i),
                                                          file_spec,
                                                          exe_ctx.process != NULL && exe_ctx.process->IsAlive()))
                                num_dumped++;
                        }
                        if (num_dumped == 0)
                            result.AppendWarningWithFormat ("No source filenames matched '%s'.\n", arg_cstr);
                        else
                            total_num_dumped += num_dumped;
                    }
                }
            }

            if (total_num_dumped > 0)
                result.SetStatus (eReturnStatusSuccessFinishResult);
            else
            {
                result.AppendError ("no source filenames matched any command arguments");
                result.SetStatus (eReturnStatusFailed);
            }
        }
        return result.Succeeded();
    }
};

//----------------------------------------------------------------------
// Dump multi-word command
//----------------------------------------------------------------------
class CommandObjectImageDump : public CommandObjectMultiword
{
public:

    //------------------------------------------------------------------
    // Constructors and Destructors
    //------------------------------------------------------------------
    CommandObjectImageDump(CommandInterpreter &interpreter) :
        CommandObjectMultiword ("image dump",
                                "Dumps information in one or more executable images; 'line-table' expects a source file name",
                                "image dump [symtab|sections|symfile|line-table] [<file1> <file2> ...]")
    {
        LoadSubCommand (interpreter, "symtab",      CommandObjectSP (new CommandObjectImageDumpSymtab ()));
        LoadSubCommand (interpreter, "sections",    CommandObjectSP (new CommandObjectImageDumpSections ()));
        LoadSubCommand (interpreter, "symfile",     CommandObjectSP (new CommandObjectImageDumpSymfile ()));
        LoadSubCommand (interpreter, "line-table",  CommandObjectSP (new CommandObjectImageDumpLineTable ()));
    }

    virtual
    ~CommandObjectImageDump()
    {
    }
};

//----------------------------------------------------------------------
// List images with associated information
//----------------------------------------------------------------------
class CommandObjectImageList : public CommandObject
{
public:

    class CommandOptions : public Options
    {
    public:

        CommandOptions () :
            Options(),
            m_format_array()
        {
        }

        virtual
        ~CommandOptions ()
        {
        }

        virtual Error
        SetOptionValue (int option_idx, const char *option_arg)
        {
            char short_option = (char) m_getopt_table[option_idx].val;
            uint32_t width = 0;
            if (option_arg)
                width = strtoul (option_arg, NULL, 0);
            m_format_array.push_back(std::make_pair(short_option, width));
            Error error;
            return error;
        }

        void
        ResetOptionValues ()
        {
            Options::ResetOptionValues();
            m_format_array.clear();
        }

        const lldb::OptionDefinition*
        GetDefinitions ()
        {
            return g_option_table;
        }

        // Options table: Required for subclasses of Options.

        static lldb::OptionDefinition g_option_table[];

        // Instance variables to hold the values for command options.
        typedef std::vector< std::pair<char, uint32_t> > FormatWidthCollection;
        FormatWidthCollection m_format_array;
    };

    CommandObjectImageList () :
        CommandObject (
                "image list",
                "List current executable and dependent shared library images.",
                "image list [<cmd-options>]")
    {
    }

    virtual
    ~CommandObjectImageList ()
    {
    }

    virtual
    Options *
    GetOptions ()
    {
        return &m_options;
    }

    virtual bool
    Execute (CommandInterpreter &interpreter,
             Args& command,
             CommandReturnObject &result)
    {
        Target *target = interpreter.GetDebugger().GetCurrentTarget().get();
        if (target == NULL)
        {
            result.AppendError ("invalid target, set executable file using 'file' command");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }
        else
        {
            uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
            result.GetOutputStream().SetAddressByteSize(addr_byte_size);
            result.GetErrorStream().SetAddressByteSize(addr_byte_size);
            // Dump all sections for all modules images
            const uint32_t num_modules = target->GetImages().GetSize();
            if (num_modules > 0)
            {
                Stream &strm = result.GetOutputStream();

                for (uint32_t image_idx = 0; image_idx<num_modules; ++image_idx)
                {
                    Module *module = target->GetImages().GetModulePointerAtIndex(image_idx);
                    strm.Printf("[%3u] ", image_idx);

                    if (m_options.m_format_array.empty())
                    {
                        DumpFullpath(strm, &module->GetFileSpec(), 0);
                    }
                    else
                    {
                        const size_t num_entries = m_options.m_format_array.size();
                        for (size_t i=0; i<num_entries; ++i)
                        {
                            if (i > 0)
                                strm.PutChar(' ');
                            char format_char = m_options.m_format_array[i].first;
                            uint32_t width = m_options.m_format_array[i].second;
                            switch (format_char)
                            {
                            case 'a':
                                DumpModuleArchitecture (strm, module, width);
                                break;

                            case 'f':
                                DumpFullpath (strm, &module->GetFileSpec(), width);
                                break;

                            case 'd':
                                DumpDirectory (strm, &module->GetFileSpec(), width);
                                break;

                            case 'b':
                                DumpBasename (strm, &module->GetFileSpec(), width);
                                break;

                            case 's':
                            case 'S':
                                {
                                    SymbolVendor *symbol_vendor = module->GetSymbolVendor();
                                    if (symbol_vendor)
                                    {
                                        SymbolFile *symbol_file = symbol_vendor->GetSymbolFile();
                                        if (symbol_file)
                                        {
                                            if (format_char == 'S')
                                                DumpBasename(strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
                                            else
                                                DumpFullpath (strm, &symbol_file->GetObjectFile()->GetFileSpec(), width);
                                            break;
                                        }
                                    }
                                    strm.Printf("%.*s", width, "<NONE>");
                                }
                                break;

                            case 'u':
                                DumpModuleUUID(strm, module);
                                break;

                            default:
                                break;
                            }
                        }
                    }
                    strm.EOL();
                }
                result.SetStatus (eReturnStatusSuccessFinishResult);
            }
            else
            {
                result.AppendError ("the target has no associated executable images");
                result.SetStatus (eReturnStatusFailed);
                return false;
            }
        }
        return result.Succeeded();
    }
protected:

    CommandOptions m_options;
};

lldb::OptionDefinition
CommandObjectImageList::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_1, false, "arch",       'a', optional_argument, NULL, 0, "<width>",   "Display the architecture when listing images."},
{ LLDB_OPT_SET_1, false, "uuid",       'u', no_argument,       NULL, 0, NULL,        "Display the UUID when listing images."},
{ LLDB_OPT_SET_1, false, "fullpath",   'f', optional_argument, NULL, 0, "<width>",   "Display the fullpath to the image object file."},
{ LLDB_OPT_SET_1, false, "directory",  'd', optional_argument, NULL, 0, "<width>",   "Display the directory with optional width for the image object file."},
{ LLDB_OPT_SET_1, false, "basename",   'b', optional_argument, NULL, 0, "<width>",   "Display the basename with optional width for the image object file."},
{ LLDB_OPT_SET_1, false, "symfile",    's', optional_argument, NULL, 0, "<width>",   "Display the fullpath to the image symbol file with optional width."},
{ LLDB_OPT_SET_1, false, "symfile-basename", 'S', optional_argument, NULL, 0, "<width>",   "Display the basename to the image symbol file with optional width."},
{ 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
};



//----------------------------------------------------------------------
// Lookup information in images
//----------------------------------------------------------------------
class CommandObjectImageLookup : public CommandObject
{
public:

    enum
    {
        eLookupTypeInvalid = -1,
        eLookupTypeAddress = 0,
        eLookupTypeSymbol,
        eLookupTypeFileLine,    // Line is optional
        eLookupTypeFunction,
        kNumLookupTypes
    };

    class CommandOptions : public Options
    {
    public:

        CommandOptions () :
            Options()
        {
            ResetOptionValues();
        }

        virtual
        ~CommandOptions ()
        {
        }

        virtual Error
        SetOptionValue (int option_idx, const char *option_arg)
        {
            Error error;

            char short_option = (char) m_getopt_table[option_idx].val;

            switch (short_option)
            {
            case 'a':
                m_type = eLookupTypeAddress;
                m_addr = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS);
                if (m_addr == LLDB_INVALID_ADDRESS)
                    error.SetErrorStringWithFormat ("Invalid address string '%s'.\n", option_arg);
                break;

            case 'o':
                m_offset = Args::StringToUInt64(option_arg, LLDB_INVALID_ADDRESS);
                if (m_offset == LLDB_INVALID_ADDRESS)
                    error.SetErrorStringWithFormat ("Invalid offset string '%s'.\n", option_arg);
                break;

            case 's':
                m_str = option_arg;
                m_type = eLookupTypeSymbol;
                break;

            case 'f':
                m_file.SetFile (option_arg);
                m_type = eLookupTypeFileLine;
                break;

            case 'i':
                m_check_inlines = false;
                break;

            case 'l':
                m_line_number = Args::StringToUInt32(option_arg, UINT32_MAX);
                if (m_line_number == UINT32_MAX)
                    error.SetErrorStringWithFormat ("Invalid line number string '%s'.\n", option_arg);
                else if (m_line_number == 0)
                    error.SetErrorString ("Zero is an invalid line number.");
                m_type = eLookupTypeFileLine;
                break;

            case 'n':
                m_str = option_arg;
                m_type = eLookupTypeFunction;
                break;

            case 'r':
                m_use_regex = true;
                break;
            }

            return error;
        }

        void
        ResetOptionValues ()
        {
            Options::ResetOptionValues();
            m_type = eLookupTypeInvalid;
            m_str.clear();
            m_file.Clear();
            m_addr = LLDB_INVALID_ADDRESS;
            m_offset = 0;
            m_line_number = 0;
            m_use_regex = false;
            m_check_inlines = true;
        }

        const lldb::OptionDefinition*
        GetDefinitions ()
        {
            return g_option_table;
        }

        // Options table: Required for subclasses of Options.

        static lldb::OptionDefinition g_option_table[];
        int             m_type;         // Should be a eLookupTypeXXX enum after parsing options
        std::string     m_str;          // Holds name lookup
        FileSpec        m_file;         // Files for file lookups
        lldb::addr_t    m_addr;         // Holds the address to lookup
        lldb::addr_t    m_offset;       // Subtract this offset from m_addr before doing lookups.
        uint32_t        m_line_number;  // Line number for file+line lookups
        bool            m_use_regex;    // Name lookups in m_str are regular expressions.
        bool            m_check_inlines;// Check for inline entries when looking up by file/line.
    };

    CommandObjectImageLookup () :
        CommandObject (
                "image lookup",
                "Look up information within executable and dependent shared library images.",
                "image lookup [<cmd-options>] [<file1>...]")
    {
    }

    virtual
    ~CommandObjectImageLookup ()
    {
    }

    virtual
    Options *
    GetOptions ()
    {
        return &m_options;
    }


    bool
    LookupInModule (CommandInterpreter &interpreter, Module *module, CommandReturnObject &result, bool &syntax_error)
    {
        switch (m_options.m_type)
        {
        case eLookupTypeAddress:
            if (m_options.m_addr != LLDB_INVALID_ADDRESS)
            {
                if (LookupAddressInModule (interpreter, result.GetOutputStream(), module, eSymbolContextEverything, m_options.m_addr, m_options.m_offset))
                {
                    result.SetStatus(eReturnStatusSuccessFinishResult);
                    return true;
                }
            }
            break;

        case eLookupTypeSymbol:
            if (!m_options.m_str.empty())
            {
                if (LookupSymbolInModule (interpreter, result.GetOutputStream(), module, m_options.m_str.c_str(), m_options.m_use_regex))
                {
                    result.SetStatus(eReturnStatusSuccessFinishResult);
                    return true;
                }
            }
            break;

        case eLookupTypeFileLine:
            if (m_options.m_file)
            {

                if (LookupFileAndLineInModule (interpreter,
                                               result.GetOutputStream(),
                                               module,
                                               m_options.m_file,
                                               m_options.m_line_number,
                                               m_options.m_check_inlines))
                {
                    result.SetStatus(eReturnStatusSuccessFinishResult);
                    return true;
                }
            }
            break;

        case eLookupTypeFunction:
            if (!m_options.m_str.empty())
            {
                if (LookupFunctionInModule (interpreter,
                                            result.GetOutputStream(),
                                            module,
                                            m_options.m_str.c_str(),
                                            m_options.m_use_regex))
                {
                    result.SetStatus(eReturnStatusSuccessFinishResult);
                    return true;
                }
            }
            break;

        default:
            m_options.GenerateOptionUsage (result.GetErrorStream(), this);
            syntax_error = true;
            break;
        }

        result.SetStatus (eReturnStatusFailed);
        return false;
    }

    virtual bool
    Execute (CommandInterpreter &interpreter,
             Args& command,
             CommandReturnObject &result)
    {
        Target *target = interpreter.GetDebugger().GetCurrentTarget().get();
        if (target == NULL)
        {
            result.AppendError ("invalid target, set executable file using 'file' command");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }
        else
        {
            bool syntax_error = false;
            uint32_t i;
            uint32_t num_successful_lookups = 0;
            uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize();
            result.GetOutputStream().SetAddressByteSize(addr_byte_size);
            result.GetErrorStream().SetAddressByteSize(addr_byte_size);
            // Dump all sections for all modules images

            if (command.GetArgumentCount() == 0)
            {
                // Dump all sections for all modules images
                const uint32_t num_modules = target->GetImages().GetSize();
                if (num_modules > 0)
                {
                    for (i = 0; i<num_modules && syntax_error == false; ++i)
                    {
                        if (LookupInModule (interpreter, target->GetImages().GetModulePointerAtIndex(i), result, syntax_error))
                        {
                            result.GetOutputStream().EOL();
                            num_successful_lookups++;
                        }
                    }
                }
                else
                {
                    result.AppendError ("the target has no associated executable images");
                    result.SetStatus (eReturnStatusFailed);
                    return false;
                }
            }
            else
            {
                // Dump specified images (by basename or fullpath)
                const char *arg_cstr;
                for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != NULL && syntax_error == false; ++i)
                {
                    FileSpec image_file(arg_cstr);
                    ModuleList matching_modules;
                    size_t num_matching_modules = target->GetImages().FindModules(&image_file, NULL, NULL, NULL, matching_modules);

                    // Not found in our module list for our target, check the main
                    // shared module list in case it is a extra file used somewhere
                    // else
                    if (num_matching_modules == 0)
                        num_matching_modules = ModuleList::FindSharedModules (image_file, 
                                                                              target->GetArchitecture(), 
                                                                              NULL, 
                                                                              NULL, 
                                                                              matching_modules);
                    
                    if (num_matching_modules > 0)
                    {
                        for (size_t i=0; i<num_matching_modules; ++i)
                        {
                            Module * image_module = matching_modules.GetModulePointerAtIndex(i);
                            if (image_module)
                            {
                                if (LookupInModule (interpreter, image_module, result, syntax_error))
                                {
                                    result.GetOutputStream().EOL();
                                    num_successful_lookups++;
                                }
                            }
                        }
                    }
                    else
                        result.AppendWarningWithFormat("Unable to find an image that matches '%s'.\n", arg_cstr);
                }
            }

            if (num_successful_lookups > 0)
                result.SetStatus (eReturnStatusSuccessFinishResult);
            else
                result.SetStatus (eReturnStatusFailed);
        }
        return result.Succeeded();
    }
protected:

    CommandOptions m_options;
};

lldb::OptionDefinition
CommandObjectImageLookup::CommandOptions::g_option_table[] =
{
{ LLDB_OPT_SET_1, true,  "address",    'a', required_argument, NULL, 0, "<addr>",    "Lookup an address in one or more executable images."},
{ LLDB_OPT_SET_1, false, "offset",     'o', required_argument, NULL, 0, "<offset>",  "When looking up an address subtract <offset> from any addresses before doing the lookup."},
{ LLDB_OPT_SET_2, true,  "symbol",     's', required_argument, NULL, 0, "<name>",    "Lookup a symbol by name in the symbol tables in one or more executable images."},
{ LLDB_OPT_SET_2, false, "regex",      'r', no_argument,       NULL, 0, NULL,        "The <name> argument for name lookups are regular expressions."},
{ LLDB_OPT_SET_3, true,  "file",       'f', required_argument, NULL, 0, "<file>",    "Lookup a file by fullpath or basename in one or more executable images."},
{ LLDB_OPT_SET_3, false, "line",       'l', required_argument, NULL, 0, "<line>",    "Lookup a line number in a file (must be used in conjunction with --file)."},
{ LLDB_OPT_SET_3, false, "no-inlines", 'i', no_argument,       NULL, 0, NULL,        "Check inline line entries (must be used in conjunction with --file)."},
{ LLDB_OPT_SET_4, true,  "function",   'n', required_argument, NULL, 0, "<name>",    "Lookup a function by name in the debug symbols in one or more executable images."},
{ 0, false, NULL,           0, 0,                 NULL, 0, NULL, NULL }
};





//----------------------------------------------------------------------
// CommandObjectImage constructor
//----------------------------------------------------------------------
CommandObjectImage::CommandObjectImage(CommandInterpreter &interpreter) :
    CommandObjectMultiword ("image",
                            "Access information for one or more executable images.",
                            "image [dump|list] ...")
{
    LoadSubCommand (interpreter, "dump",    CommandObjectSP (new CommandObjectImageDump (interpreter)));
    LoadSubCommand (interpreter, "list",    CommandObjectSP (new CommandObjectImageList ()));
    LoadSubCommand (interpreter, "lookup",  CommandObjectSP (new CommandObjectImageLookup ()));
}

//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
CommandObjectImage::~CommandObjectImage()
{
}

