//===-- 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().target, 
                                                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().target);
        }
    }
}

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().target, 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,
    bool verbose
)
{
    if (module)
    {
        lldb::addr_t addr = raw_addr - offset;
        Address so_addr;
        SymbolContext sc;
        Target *target = interpreter.GetDebugger().GetExecutionContext().target;
        if (target && !target->GetSectionLoadList().IsEmpty())
        {
            if (!target->GetSectionLoadList().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();
        // Print out detailed address information when verbose is enabled
        if (verbose)
        {
            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().target, 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().target);
                    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(), true, true, false);
        }
    }
    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
LookupTypeInModule 
(
    CommandInterpreter &interpreter, 
    Stream &strm, 
    Module *module, 
    const char *name_cstr, 
    bool name_is_regex
)
{
    if (module && name_cstr && name_cstr[0])
    {
        SymbolContextList sc_list;

        SymbolVendor *symbol_vendor = module->GetSymbolVendor();
        if (symbol_vendor)
        {
            TypeList type_list;
            uint32_t num_matches = 0;
            SymbolContext sc;
//            if (name_is_regex)
//            {
//                RegularExpression name_regex (name_cstr);
//                num_matches = symbol_vendor->FindFunctions(sc, name_regex, true, UINT32_MAX, type_list);
//            }
//            else
//            {
                ConstString name(name_cstr);
                num_matches = symbol_vendor->FindTypes(sc, name, true, UINT32_MAX, type_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");
                const uint32_t num_types = type_list.GetSize();
                for (uint32_t i=0; i<num_types; ++i)
                {
                    TypeSP type_sp (type_list.GetTypeAtIndex(i));
                    if (type_sp)
                    {
                        // Resolve the clang type so that any forward references
                        // to types that haven't yet been parsed will get parsed.
                        type_sp->GetClangType ();
                        type_sp->GetDescription (&strm, eDescriptionLevelFull, true);
                    }
                    strm.EOL();
                }
            }
            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 (CommandInterpreter &interpreter,
                                      const char *name,
                                      const char *help,
                                      const char *syntax) :
        CommandObject (interpreter, name, help, syntax)
    {
    }

    virtual
    ~CommandObjectImageDumpModuleList ()
    {
    }

    virtual int
    HandleArgumentCompletion (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 (m_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 (CommandInterpreter &interpreter,
                                          const char *name,
                                          const char *help,
                                          const char *syntax) :
        CommandObject (interpreter, name, help, syntax)
    {
    }

    virtual
    ~CommandObjectImageDumpSourceFileList ()
    {
    }

    virtual int
    HandleArgumentCompletion (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 (m_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 (CommandInterpreter &interpreter) :
        CommandObjectImageDumpModuleList (interpreter,
                                          "image dump symtab",
                                          "Dump the symbol table from one or more executable images.",
                                          "image dump symtab [<file1> ...]")
    {
    }

    virtual
    ~CommandObjectImageDumpSymtab ()
    {
    }

    virtual bool
    Execute (Args& command,
             CommandReturnObject &result)
    {
        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().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 (m_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 (m_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 (CommandInterpreter &interpreter) :
        CommandObjectImageDumpModuleList (interpreter,
                                          "image dump sections",
                                          "Dump the sections from one or more executable images.",
                                          "image dump sections [<file1> ...]")
    {
    }

    virtual
    ~CommandObjectImageDumpSections ()
    {
    }

    virtual bool
    Execute (Args& command,
             CommandReturnObject &result)
    {
        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().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 (m_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 (m_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 (CommandInterpreter &interpreter) :
        CommandObjectImageDumpModuleList (interpreter,
                                          "image dump symfile",
                                          "Dump the debug symbol file for one or more executable images.",
                                          "image dump symfile [<file1> ...]")
    {
    }

    virtual
    ~CommandObjectImageDumpSymfile ()
    {
    }

    virtual bool
    Execute (Args& command,
             CommandReturnObject &result)
    {
        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().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 (CommandInterpreter &interpreter) :
        CommandObjectImageDumpSourceFileList (interpreter,
                                              "image dump line-table",
                                              "Dump the debug symbol file for one or more executable images.",
                                              "image dump line-table <source-file1> [<source-file2> ...]")
    {
    }

    virtual
    ~CommandObjectImageDumpLineTable ()
    {
    }

    virtual bool
    Execute (Args& command,
             CommandReturnObject &result)
    {
        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().get();
        if (target == NULL)
        {
            result.AppendError ("invalid target, set executable file using 'file' command");
            result.SetStatus (eReturnStatusFailed);
            return false;
        }
        else
        {
            ExecutionContext exe_ctx(m_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 (m_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 (interpreter, 
                                "image dump",
                                "A set of commands for dumping information about one or more executable images; 'line-table' expects a source file name",
                                "image dump [symtab|sections|symfile|line-table] [<file1> <file2> ...]")
    {
        LoadSubCommand ("symtab",      CommandObjectSP (new CommandObjectImageDumpSymtab (interpreter)));
        LoadSubCommand ("sections",    CommandObjectSP (new CommandObjectImageDumpSections (interpreter)));
        LoadSubCommand ("symfile",     CommandObjectSP (new CommandObjectImageDumpSymfile (interpreter)));
        LoadSubCommand ("line-table",  CommandObjectSP (new CommandObjectImageDumpLineTable (interpreter)));
    }

    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 (CommandInterpreter &interpreter) :
        CommandObject (interpreter,
                       "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 (Args& command,
             CommandReturnObject &result)
    {
        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().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,
        eLookupTypeType,
        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 't':
                m_str = option_arg;
                m_type = eLookupTypeType;
                break;

            case 'v':
                m_verbose = 1;
                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;
            m_verbose = false;
        }

        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.
        bool            m_verbose;      // Enable verbose lookup info

    };

    CommandObjectImageLookup (CommandInterpreter &interpreter) :
        CommandObject (interpreter,
                       "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 (m_interpreter, 
                                           result.GetOutputStream(), 
                                           module, 
                                           eSymbolContextEverything, 
                                           m_options.m_addr, 
                                           m_options.m_offset,
                                           m_options.m_verbose))
                {
                    result.SetStatus(eReturnStatusSuccessFinishResult);
                    return true;
                }
            }
            break;

        case eLookupTypeSymbol:
            if (!m_options.m_str.empty())
            {
                if (LookupSymbolInModule (m_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 (m_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 (m_interpreter,
                                            result.GetOutputStream(),
                                            module,
                                            m_options.m_str.c_str(),
                                            m_options.m_use_regex))
                {
                    result.SetStatus(eReturnStatusSuccessFinishResult);
                    return true;
                }
            }
            break;

        case eLookupTypeType:
            if (!m_options.m_str.empty())
            {
                if (LookupTypeInModule (m_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 (m_interpreter, result.GetErrorStream(), this);
            syntax_error = true;
            break;
        }

        result.SetStatus (eReturnStatusFailed);
        return false;
    }

    virtual bool
    Execute (Args& command,
             CommandReturnObject &result)
    {
        Target *target = m_interpreter.GetDebugger().GetSelectedTarget().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 (m_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 j=0; j<num_matching_modules; ++j)
                        {
                            Module * image_module = matching_modules.GetModulePointerAtIndex(j);
                            if (image_module)
                            {
                                if (LookupInModule (m_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."},
{ LLDB_OPT_SET_5,   true,  "type",       't', required_argument, NULL, 0, "<name>",    "Lookup a type by name in the debug symbols in one or more executable images."},
{ LLDB_OPT_SET_ALL, false, "verbose",    'v', no_argument,       NULL, 0, NULL,        "Enable verbose lookup information."},
{ 0, false, NULL,           0, 0,                 NULL, 0, NULL, NULL }
};





//----------------------------------------------------------------------
// CommandObjectImage constructor
//----------------------------------------------------------------------
CommandObjectImage::CommandObjectImage(CommandInterpreter &interpreter) :
    CommandObjectMultiword (interpreter,
                            "image",
                            "A set of commands for accessing information for one or more executable images.",
                            "image <sub-command> ...")
{
    LoadSubCommand ("dump",    CommandObjectSP (new CommandObjectImageDump (interpreter)));
    LoadSubCommand ("list",    CommandObjectSP (new CommandObjectImageList (interpreter)));
    LoadSubCommand ("lookup",  CommandObjectSP (new CommandObjectImageLookup (interpreter)));
}

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

