/* Chrysalide - Outil d'analyse de fichiers binaires
* utils.h - fonctions qui simplifient la vie dans les interactions avec un serveur 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 "utils.h"
#include
#include
#include
#include
#include
#include
/******************************************************************************
* *
* Paramètres : data = données à inspecter. *
* len = quantité de ces données. *
* *
* Description : Indique si les données correspondent à un code d'erreur. *
* *
* Retour : Bilan de l'analyse. *
* *
* Remarques : - *
* *
******************************************************************************/
bool is_error_code(const char *data, size_t len)
{
bool result; /* Bilan à retourner */
result = (len == 3);
if (result)
result = (data[0] == 'E' && isdigit(data[1]) && isdigit(data[2]));
return result;
}
/******************************************************************************
* *
* Paramètres : data = données à analyser. *
* size = taille de ces données. *
* byte = statut de sortie d'un programme. [OUT] *
* *
* Description : Relit une valeur sur 8 bits et deux lettres. *
* *
* Retour : Bilan de la lecture. *
* *
* Remarques : - *
* *
******************************************************************************/
bool read_fixed_byte(const char *data, size_t len, uint8_t *byte)
{
bool result; /* Bilan à retourner */
const char *iter; /* Boucle de parcours #1 */
size_t i; /* Boucle de parcours #2 */
uint8_t nibble; /* Valeur affichée */
result = true;
len = MIN(2, len);
for (i = 0, iter = data; i < len; i++, iter++)
{
switch (*iter)
{
case '0' ... '9':
nibble = *iter - '0';
break;
case 'a' ... 'f':
nibble = *iter - 'a' + 10;
break;
case 'A' ... 'F':
nibble = *iter - 'A' + 10;
break;
default:
result = false;
break;
}
if (!result)
break;
if (i == 0)
*byte = (nibble << 4);
else
*byte |= nibble;
}
if (result)
result = (i == 2);
return result;
}
/******************************************************************************
* *
* Paramètres : hex = tampon d'origine assez grand. *
* size = taille de la valeur à considérer pour les travaux. *
* value = valeur sur XX bits à transcrire. [OUT] *
* *
* Description : Traduit en valeur sur XX bits une forme textuelle. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
bool hex_to_any_u(const char *hex, size_t size, ...)
{
bool result; /* Bilan à retourner */
va_list ap; /* Gestion de l'inconnue */
uint8_t *value8; /* Valeur sur 8 bits */
uint16_t *value16; /* Valeur sur 16 bits */
uint32_t *value32; /* Valeur sur 32 bits */
uint64_t *value64; /* Valeur sur 64 bits */
uint8_t *iter; /* Boucle de parcours #1 */
size_t i; /* Boucle de parcours #2 */
char nibble; /* Valeur à afficher */
result = false;
/* Récupération de la destination */
va_start(ap, size);
switch (size)
{
case 1:
value8 = va_arg(ap, uint8_t *);
iter = value8;
break;
case 2:
value16 = va_arg(ap, uint16_t *);
iter = (uint8_t *)value16;
break;
case 4:
value32 = va_arg(ap, uint32_t *);
iter = (uint8_t *)value32;
break;
case 8:
value64 = va_arg(ap, uint64_t *);
iter = (uint8_t *)value64;
break;
default:
goto done;
break;
}
/* Lecture de la valeur */
for (i = 0; i < size; i++, iter++)
{
*iter = 0;
nibble = hex[i * 2];
switch (nibble)
{
case '0' ... '9':
*iter = (nibble - '0') << 4;
break;
case 'a' ... 'f':
*iter = (nibble - 'a' + 0xa) << 4;
break;
case 'A' ... 'F':
*iter = (nibble - 'A' + 0xa) << 4;
break;
default:
goto done;
break;
}
nibble = hex[i * 2 + 1];
switch (nibble)
{
case '0' ... '9':
*iter |= (nibble - '0');
break;
case 'a' ... 'f':
*iter |= (nibble - 'a' + 0xa);
break;
case 'A' ... 'F':
*iter |= (nibble - 'A' + 0xa);
break;
default:
goto done;
break;
}
}
result = (i == size);
done:
va_end(ap);
return result;
}
/******************************************************************************
* *
* Paramètres : size = taille de la valeur à considérer pour les travaux. *
* hex = tampon de destination assez grand. *
* value = valeur sur XX bits à transcrire. [OUT] *
* *
* Description : Traduit une valeur sur XX bits en forme textuelle. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
bool any_u_to_hex(size_t size, char hex[17], ...)
{
bool result; /* Bilan à retourner */
va_list ap; /* Gestion de l'inconnue */
uint8_t *value8; /* Valeur sur 8 bits */
uint16_t *value16; /* Valeur sur 16 bits */
uint32_t *value32; /* Valeur sur 32 bits */
uint64_t *value64; /* Valeur sur 64 bits */
size_t i; /* Boucle de parcours #1 */
const uint8_t *iter; /* Boucle de parcours #2 */
uint8_t nibble; /* Valeur à retenir */
result = true;
/* Récupération de la destination */
va_start(ap, hex);
switch (size)
{
case 1:
value8 = va_arg(ap, uint8_t *);
iter = (const uint8_t *)value8;
break;
case 2:
value16 = va_arg(ap, uint16_t *);
iter = (const uint8_t *)value16;
break;
case 4:
value32 = va_arg(ap, uint32_t *);
iter = (const uint8_t *)value32;
break;
case 8:
value64 = va_arg(ap, uint64_t *);
iter = (const uint8_t *)value64;
break;
default:
result = false;
goto done;
break;
}
/* Lecture de la valeur */
for (i = 0; i < size; i++, iter++)
{
nibble = (*iter & 0xf0) >> 4;
switch (nibble)
{
case 0x0 ... 0x9:
hex[i * 2] = '0' + nibble;
break;
case 0xa ... 0xf:
hex[i * 2] = 'A' + nibble - 0xa;
break;
}
nibble = (*iter & 0x0f);
switch (nibble)
{
case 0x0 ... 0x9:
hex[i * 2 + 1] = '0' + nibble;
break;
case 0xa ... 0xf:
hex[i * 2 + 1] = 'A' + nibble - 0xa;
break;
}
}
hex[size * 2] = '\0';
done:
va_end(ap);
return result;
}