/* Chrysalide - Outil d'analyse de fichiers binaires
 * helpers.c - assistanat dans la manipulation des paquets GDB
 *
 * Copyright (C) 2010-2017 Cyrille Bagard
 *
 *  This file is part of Chrysalide.
 *
 *  Chrysalide 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.
 *
 *  Chrysalide 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 .
 */
#include "helpers.h"
#include 
#include 
/* -------------------------- PAQUETS DES REPONSES D'ARRET -------------------------- */
/******************************************************************************
*                                                                             *
*  Paramètres  : packet = paquet de deonnées à interpréter.                   *
*                sig    = identifiant du signal source. [OUT]                 *
*                addr   = adresse de l'instruction courante. [OUT]            *
*                thread = identifiant du thread concerné. [OUT]               *
*                endian = boutisme de la plateforme ciblée.                   *
*                                                                             *
*  Description : Récupère les informations liées à un arrêt suite à signal.   *
*                                                                             *
*  Retour      : Bilan de l'opération.                                        *
*                                                                             *
*  Remarques   : Les données sont la forme :                                  *
*                T0505:00000000;04:a08de6bf;08:505878b7;thread:50dc;          *
*                                                                             *
******************************************************************************/
bool get_stop_reply_sig_info(const GGdbPacket *packet, int *sig, vmpa_t *addr, pid_t *thread, SourceEndian endian)
{
    const char *data;                       /* Données brutes du paquet    */
    size_t length;                          /* Quantité de ces données     */
    uint8_t index;                          /* Indice de 8 bits quelconque */
    size_t pos;                             /* Tête de lecture courante    */
    regex_t preg;                           /* Expression régulière        */
    int ret;                                /* Bilan d'un appel            */
    regmatch_t pmatch[3];                   /* Zones remarquées            */
    size_t key_len;                         /* Taille de l'indicatif       */
    *addr = 0ull;
    g_gdb_packet_get_data(packet, &data, &length, NULL);
    pos = 1;
    /* Lecture du numéro du signal */
    if (!strtou8(&index, data, &pos, length, SRE_LITTLE))
        return false;
    *sig = index;
    /* Reste des informations */
    ret = regcomp(&preg, "([^:]+):([^;]+);", REG_EXTENDED | REG_ICASE);
    if (ret != 0) return false;
    for (ret = regexec(&preg, &data[pos], 3, pmatch, 0);
         ret != REG_NOMATCH;
         ret = regexec(&preg, &data[pos], 3, pmatch, 0))
    {
        key_len = pmatch[1].rm_eo - pmatch[1].rm_so;
        /* Indication sur le thread */
        if (key_len == strlen("thread")
            && strncmp(&data[pos + pmatch[1].rm_so], "thread", key_len) == 0)
        {
            /* TODO printf("Thread found !\n"); */
        }
        /* Valeur de registre ? */
        else if (key_len == 2)
        {
            if (!strtou8(&index, data, (size_t []) { pos + pmatch[1].rm_so }, length, SRE_LITTLE))
                return false;
            if (index != 8 /* FIXME */)
                goto next_field;
            if (!strtou32(addr, data, (size_t []) { pos + pmatch[2].rm_so }, length, SRE_LITTLE/* FIXME */))
                return false;
        }
    next_field:
        pos += pmatch[0].rm_eo;
    }
    regfree(&preg);
    return (*addr != 0ull);
}