/* Chrysalide - Outil d'analyse de fichiers binaires
* helpers.c - assistanat dans la manipulation des paquets GDB
*
* Copyright (C) 2018 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 Chrysalide. If not, see .
*/
#include "helpers.h"
#include
#include
#include "gdb-int.h"
#include "utils.h"
/******************************************************************************
* *
* Paramètres : debugger = débogueur à consulter. *
* addr = emplacement en mémoire à venir consulter. *
* out = zone d'impression en hexadécimal. [OUT] *
* *
* Description : Traduit une adresse en chaîne hexadécimale pour GDB. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
bool translate_virt_to_hex(const GGdbDebugger *debugger, virt_t addr, char *out)
{
bool result; /* Bilan d'opération à renvoyer*/
uint8_t conv8; /* Valeur adaptée sur 8 bits */
uint16_t conv16; /* Valeur adaptée sur 16 bits */
uint32_t conv32; /* Valeur adaptée sur 32 bits */
uint64_t conv64; /* Valeur adaptée sur 64 bits */
char hexval[17]; /* Valeur sous forme hexa */
bool got_msn; /* Obtention d'un quartet ? */
size_t i; /* Boucle de parcours */
/* Conversion */
switch (debugger->msize)
{
case MDS_8_BITS:
conv8 = addr;
result = u8_to_hex(&conv8, hexval);
break;
case MDS_16_BITS:
conv16 = addr;
conv16 = to_u16(&conv16, SRE_BIG);
result = u16_to_hex(&conv16, hexval);
break;
case MDS_32_BITS:
conv32 = addr;
conv32 = to_u32(&conv32, SRE_BIG);
result = u32_to_hex(&conv32, hexval);
break;
case MDS_64_BITS:
conv64 = addr;
conv64 = to_u64(&conv64, SRE_BIG);
result = u64_to_hex(&conv64, hexval);
break;
default:
result = false;
break;
}
/* On saute les zéros préliminaires... */
if (result)
{
got_msn = false;
for (i = 0; i < 17; i++)
{
if (!got_msn)
{
if (hexval[i] == '0')
continue;
else
got_msn = true;
}
*out = hexval[i];
out++;
}
*out = '\0';
}
return result;
}
/* -------------------------- 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);
}