/* Chrysalide - Outil d'analyse de fichiers binaires
 * debugger.c - gestion des différents débogueurs
 *
 * Copyright (C) 2010-2012 Cyrille Bagard
 *
 *  This file is part of Chrysalide.
 *
 *  OpenIDA is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  OpenIDA is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
 */


#include "debugger.h"

#include "debugger-int.h"
#include "jdwp/debugger.h"
#include "remgdb/gdb.h"
#include "../glibext/chrysamarshal.h"
#include "../plugins/pglist.h"



/* Initialise la classe de base des débogueurs. */
static void g_binary_debugger_class_init(GBinaryDebuggerClass *);

/* Initialise une instance de base d'un débogueur. */
static void g_binary_debugger_init(GBinaryDebugger *);



/* Indique le type définit pour une ligne de représentation. */
G_DEFINE_TYPE(GBinaryDebugger, g_binary_debugger, G_TYPE_OBJECT);



/******************************************************************************
*                                                                             *
*  Paramètres  : klass = classe à initialiser.                                *
*                                                                             *
*  Description : Initialise la classe de base des débogueurs.                 *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static void g_binary_debugger_class_init(GBinaryDebuggerClass *klass)
{
    g_signal_new("debugger-stopped",
                 G_TYPE_BINARY_DEBUGGER,
                 G_SIGNAL_RUN_LAST,
                 G_STRUCT_OFFSET(GBinaryDebuggerClass, debugger_stopped),
                 NULL, NULL,
                 g_cclosure_user_marshal_VOID__UINT64_UINT64,
                 G_TYPE_NONE, 2, G_TYPE_UINT64, G_TYPE_UINT64);

    g_signal_new("halted",
                 G_TYPE_BINARY_DEBUGGER,
                 G_SIGNAL_RUN_LAST,
                 G_STRUCT_OFFSET(GBinaryDebuggerClass, debugger_halted),
                 NULL, NULL,
                 g_cclosure_user_marshal_VOID__INT_UINT64_INT,
                 G_TYPE_NONE, 3, G_TYPE_INT, G_TYPE_UINT64, G_TYPE_INT);

}


/******************************************************************************
*                                                                             *
*  Paramètres  : debugger = instance à initialiser.                           *
*                                                                             *
*  Description : Initialise une instance de base d'un débogueur.              *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

static void g_binary_debugger_init(GBinaryDebugger *debugger)
{

}


/******************************************************************************
*                                                                             *
*  Paramètres  : type   = type de débigueur choisi pour l'opération.          *
*                binary = binaire devant être débogué.                        *
*                                                                             *
*  Description : Crée un nouveau débogueur.                                   *
*                                                                             *
*  Retour      : Composant GObject mis en place ou NULL.                      *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

GBinaryDebugger *g_new_binary_debugger(DebuggerType type, GLoadedBinary *binary)
{
    GBinaryDebugger *result;

    switch (type)
    {
        case DGT_JDWP:
            result = g_java_debugger_new(binary, NULL);
            break;

        case DGT_REMOTE_GDB:
            result = g_gdb_debugger_new(binary, NULL);
            break;

        default:
            result = NULL;
            break;

    }

    if (result != NULL)
        result->binary = binary;

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : debugger = débogueur à manipuler ici.                        *
*                                                                             *
*  Description : Démarre une procédure de débogage.                           *
*                                                                             *
*  Retour      : Bilan de l'opération.                                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

bool g_binary_debugger_attach(GBinaryDebugger *debugger)
{
    bool result;                            /* Bilan à retourner           */
    GPluginModule **pglist;                 /* Liste de greffons           */
    size_t pgcount;                         /* Taille de cette liste       */
    size_t i;                               /* Boucle de parcours          */

    if (debugger->attach == NULL) result = true;
    else result = debugger->attach(debugger);

    pgcount = 0;
    pglist = NULL;//get_all_plugins_for_action(PGA_DEBUGGER_ATTACH, &pgcount);

    if (pgcount > 0)
    {
        /*
        for (i = 0; i < pgcount; i++)
            g_plugin_module_handle_debugger(pglist[i], debugger, PGA_DEBUGGER_ATTACH);
        */

        free(pglist);

    }

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : debugger = débogueur à manipuler ici.                        *
*                                                                             *
*  Description : Démarre une procédure de débogage.                           *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void g_binary_debugger_run(GBinaryDebugger *debugger)
{
    debugger->run(debugger);

}


/******************************************************************************
*                                                                             *
*  Paramètres  : debugger = débogueur à manipuler ici.                        *
*                                                                             *
*  Description : Reprend une procédure de débogage.                           *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void g_binary_debugger_resume(GBinaryDebugger *debugger)
{
    debugger->resume(debugger);

}


/******************************************************************************
*                                                                             *
*  Paramètres  : debugger = débogueur à manipuler ici.                        *
*                                                                             *
*  Description : Tue une procédure de débogage.                               *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

void g_binary_debugger_kill(GBinaryDebugger *debugger)
{
    debugger->kill(debugger);

}


/******************************************************************************
*                                                                             *
*  Paramètres  : debugger = instance du module de débogage chargé.            *
*                names    = désignations de tous les threads ou NULL. [OUT]   *
*                count    = nombre de threads actifs. [OUT]                   *
*                                                                             *
*  Description : Fournit les identifiants de tous les threads actifs.         *
*                                                                             *
*  Retour      : Liste des threads décomptés.                                 *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

pid_t *g_binary_debugger_list_all_threads(GBinaryDebugger *debugger, char ***names, size_t *count)
{
    pid_t *result;                          /* Liste à retourner           */

    if (debugger->all_threads != NULL)
        result = debugger->all_threads(debugger, names, count);
    else
        result = NULL;

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : debugger = instance du module de débogage chargé.            *
*                thread   = thread concerné par l'analyse.                    *
*                count    = nombre de frames en place. [OUT]                  *
*                                                                             *
*  Description : Fournit la liste des frames courantes d'un thread donné.     *
*                                                                             *
*  Retour      : Liste des frames trouvées.                                   *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

dbg_frame_t *g_binary_debugger_get_frames_stack(GBinaryDebugger *debugger, pid_t thread, size_t *count)
{
    dbg_frame_t *result;                    /* Liste à retourner           */

    if (debugger->frames_stack != NULL)
        result = debugger->frames_stack(debugger, thread, count);
    else
    {
        *count = 0;
        result = NULL;
    }

    return result;

}


/******************************************************************************
*                                                                             *
*  Paramètres  : debugger = débogueur à manipuler ici.                        *
*                count    = nombre de transmissions effetuées.                *
*                                                                             *
*  Description : Fournit la valeur des registres de l'architecture.           *
*                                                                             *
*  Retour      : Tableau de valeurs transmises à libérer de la mémoire / NULL.*
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/

register_value *g_binary_debugger_get_registers(GBinaryDebugger *debugger, size_t *count)
{
    return debugger->get_reg_values(debugger, count);

}