diff options
Diffstat (limited to 'src/debug/gdbrsp')
-rw-r--r-- | src/debug/gdbrsp/Makefile.am | 29 | ||||
-rw-r--r-- | src/debug/gdbrsp/aops.h | 57 | ||||
-rw-r--r-- | src/debug/gdbrsp/gdb-int.h | 116 | ||||
-rw-r--r-- | src/debug/gdbrsp/gdb.c | 1524 | ||||
-rw-r--r-- | src/debug/gdbrsp/gdb.h | 61 | ||||
-rw-r--r-- | src/debug/gdbrsp/helpers.c | 224 | ||||
-rw-r--r-- | src/debug/gdbrsp/helpers.h | 62 | ||||
-rw-r--r-- | src/debug/gdbrsp/helpers_arm.c | 252 | ||||
-rw-r--r-- | src/debug/gdbrsp/helpers_arm.h | 37 | ||||
-rw-r--r-- | src/debug/gdbrsp/helpers_arm64.c | 97 | ||||
-rw-r--r-- | src/debug/gdbrsp/helpers_arm64.h | 40 | ||||
-rw-r--r-- | src/debug/gdbrsp/packet.c | 389 | ||||
-rw-r--r-- | src/debug/gdbrsp/packet.h | 82 | ||||
-rw-r--r-- | src/debug/gdbrsp/stream-int.h | 89 | ||||
-rw-r--r-- | src/debug/gdbrsp/stream.c | 696 | ||||
-rw-r--r-- | src/debug/gdbrsp/stream.h | 68 | ||||
-rw-r--r-- | src/debug/gdbrsp/support.c | 598 | ||||
-rw-r--r-- | src/debug/gdbrsp/support.h | 73 | ||||
-rw-r--r-- | src/debug/gdbrsp/target.c | 950 | ||||
-rw-r--r-- | src/debug/gdbrsp/target.h | 72 | ||||
-rw-r--r-- | src/debug/gdbrsp/tcp.c | 280 | ||||
-rw-r--r-- | src/debug/gdbrsp/tcp.h | 57 | ||||
-rw-r--r-- | src/debug/gdbrsp/utils.c | 354 | ||||
-rw-r--r-- | src/debug/gdbrsp/utils.h | 58 |
24 files changed, 0 insertions, 6265 deletions
diff --git a/src/debug/gdbrsp/Makefile.am b/src/debug/gdbrsp/Makefile.am deleted file mode 100644 index 5ee8df6..0000000 --- a/src/debug/gdbrsp/Makefile.am +++ /dev/null @@ -1,29 +0,0 @@ - -noinst_LTLIBRARIES = libdebuggdbrsp.la - -libdebuggdbrsp_la_SOURCES = \ - aops.h \ - gdb-int.h \ - gdb.h gdb.c \ - helpers.h helpers.c \ - helpers_arm.h helpers_arm.c \ - helpers_arm64.h helpers_arm64.c \ - packet.h packet.c \ - stream-int.h \ - stream.h stream.c \ - support.h support.c \ - target.h target.c \ - tcp.h tcp.c \ - utils.h utils.c - -libdebuggdbrsp_la_CFLAGS = $(AM_CFLAGS) - - -devdir = $(includedir)/chrysalide/$(subdir:src/%=%) - -dev_HEADERS = $(libdebuggdbrsp_la_SOURCES:%c=) - - -AM_CPPFLAGS = $(LIBGTK_CFLAGS) $(LIBXML_CFLAGS) - -AM_CFLAGS = $(DEBUG_CFLAGS) $(WARNING_FLAGS) $(COMPLIANCE_FLAGS) diff --git a/src/debug/gdbrsp/aops.h b/src/debug/gdbrsp/aops.h deleted file mode 100644 index 1599615..0000000 --- a/src/debug/gdbrsp/aops.h +++ /dev/null @@ -1,57 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * aops.h - prototypes pour les compléments utiles à GDB pour l'architecture ARM - * - * Copyright (C) 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _DEBUG_GDBRSP_AOPS_H -#define _DEBUG_GDBRSP_AOPS_H - - -#include "gdb.h" - - - -/* Détermine le point d'exécution courant. */ -typedef bool (* get_pc_fc) (GGdbDebugger *, virt_t *); - -/* Remonte la pile d'appels jusqu'au point courant. */ -typedef bool (* compute_call_stack_fc) (const GGdbDebugger *, virt_t **, size_t *); - -/* Complète la commande manipulant des points d'arrêt. */ -typedef const char * (* get_bp_kind_fc) (const GGdbDebugger *, virt_t); - -/* Construit une instruction provoquant un arrêt d'exécution. */ -typedef const uint8_t * (* get_bp_data_fc) (const GGdbDebugger *, virt_t, size_t *); - - -/* Procédures spécifiques pour une architecture */ -typedef struct _gdb_arch_ops -{ - get_pc_fc get_pc; /* Obtention du point d'exéc. */ - compute_call_stack_fc compute_cstack; /* Calcule la pile d'appels */ - get_bp_kind_fc get_bp_kind; /* Fournit le type d'un point */ - get_bp_data_fc get_bp_data; /* Code d'un point d'arrêt */ - -} gdb_arch_ops; - - - -#endif /* _DEBUG_GDBRSP_AOPS_H */ diff --git a/src/debug/gdbrsp/gdb-int.h b/src/debug/gdbrsp/gdb-int.h deleted file mode 100644 index 11b4753..0000000 --- a/src/debug/gdbrsp/gdb-int.h +++ /dev/null @@ -1,116 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gdb.h - prototypes pour le débogage à l'aide de gdb. - * - * Copyright (C) 2009-2012 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 <http://www.gnu.org/licenses/>. - */ - - -#ifndef _DEBUG_GDBRSP_GDB_INT_H -#define _DEBUG_GDBRSP_GDB_INT_H - - -#include "aops.h" -#include "gdb.h" -#include "stream.h" -#include "support.h" -#include "target.h" -#include "../break-int.h" -#include "../debugger-int.h" - - - - - - - - - - -/* Définition d'un point d'arrêt appliqué */ -typedef struct _gdb_breakpoint -{ - raw_breakpoint raw; /* A laisser en premier */ - - bool is_z; /* Usage de commande dédiée ? */ - - union - { - const char *kind; /* Précision de taille */ - - struct - { - uint8_t memory[16]; /* Données d'origine remplacées*/ - size_t len; /* Quantité de ces données */ - }; - - }; - -} gdb_breakpoint; - - - - - - - - - - - - - - -/* Débogueur utilisant un serveur GDB (instance) */ -struct _GGdbDebugger -{ - GBinaryDebugger parent; /* A laisser en premier */ - - SourceEndian endian; /* Boutisme du format */ - MemoryDataSize msize; /* Taille des adresses */ - - const gdb_arch_ops *ops; /* Opérations spécifiques */ - - GGdbStream *stream; /* Flux de communication */ - GGdbSupport *support; /* Configuration à adopter */ - GGdbTarget *target; /* Architecture ciblée par GDB */ - -}; - - -/* Débogueur utilisant un serveur GDB (classe) */ -struct _GGdbDebuggerClass -{ - GBinaryDebuggerClass parent; /* A laisser en premier */ - -}; - - - -/* ------------------------ ACCUEIL D'EVENEMENTS ASYNCHRONES ------------------------ */ - - -/* Réagit à la réception d'un signal par le programme étudié. */ -void g_gdb_debugger_receive_signal_reply(GGdbDebugger *, int); - -/* Réagit à la sortie d'exécution d'un programme étudié. */ -void g_gdb_debugger_receive_exit_reply(GGdbDebugger *, int, pid_t); - - - -#endif /* _DEBUG_GDBRSP_GDB_INT_H */ diff --git a/src/debug/gdbrsp/gdb.c b/src/debug/gdbrsp/gdb.c deleted file mode 100644 index 1d0ffe5..0000000 --- a/src/debug/gdbrsp/gdb.c +++ /dev/null @@ -1,1524 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gdb.c - débogage à l'aide de gdb. - * - * Copyright (C) 2009-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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "gdb.h" - - - -#include <assert.h> -#include <malloc.h> -#include <stdarg.h> -#include <stdio.h> -#include <string.h> - - -#include "gdb-int.h" -#include "helpers.h" -#include "helpers_arm.h" -#include "helpers_arm64.h" -#include "tcp.h" -#include "utils.h" -#include "../../common/cpp.h" -#include "../../format/format.h" - - - - - - - - -/* Initialise la classe du débogueur utilisant gdb. */ -static void g_gdb_debugger_class_init(GGdbDebuggerClass *); - -/* Procède à l'initialisation du débogueur utilisant gdb. */ -static void g_gdb_debugger_init(GGdbDebugger *); - -/* Supprime toutes les références externes. */ -static void g_gdb_debugger_dispose(GGdbDebugger *); - -/* Procède à la libération totale de la mémoire. */ -static void g_gdb_debugger_finalize(GGdbDebugger *); - - -/* Met en marche le débogueur utilisant un serveur GDB. */ -static bool g_gdb_debugger_run(GGdbDebugger *); - -/* Remet en marche le débogueur utilisant un serveur GDB. */ -//static bool g_gdb_debugger_resume(GGdbDebugger *); - -/* Tue le débogueur utilisant un serveur GDB. */ -static bool g_gdb_debugger_kill(GGdbDebugger *); - - - - - - -/* --------------------------- ENTREES / SORTIES BASIQUES --------------------------- */ - - -/* Lit une valeur quelconque à une adresse arbitraire. */ -static bool g_gdb_debugger_read_memory(GGdbDebugger *, virt_t, size_t, ...); - -/* Ecrit une valeur quelconque à une adresse arbitraire. */ -static bool g_gdb_debugger_write_memory(GGdbDebugger *, virt_t, size_t, ...); - -/* Liste l'ensemble des registres appartenant à un groupe. */ -static char **g_gdb_debugger_get_register_names(const GGdbDebugger *, const char *, size_t *); - -/* Indique la taille associée à un registre donné. */ -static unsigned int g_gdb_debugger_get_register_size(const GGdbDebugger *, const char *); - -/* Effectue la lecture d'un registre donné. */ -static bool g_gdb_debugger_read_register(GGdbDebugger *, const char *, size_t, ...); - -/* Effectue l'écriture d'un registre donné. */ -static bool g_gdb_debugger_write_register(GGdbDebugger *, const char *, size_t, ...); - - - -/* ------------------------- MANIPULATION DE L'ETAT COURANT ------------------------- */ - - -/* Détermine le point d'exécution courant. */ -static bool g_gdb_debugger_get_current_pc(GGdbDebugger *, virt_t *); - -/* Remonte la pile d'appels jusqu'au point courant. */ -static bool g_gdb_debugger_compute_call_stack(GGdbDebugger *, virt_t **, size_t *); - - - -/* --------------------------- GESTION DES POINTS D'ARRET --------------------------- */ - - -/* Ajoute un point d'arrêt basique en mémoire. */ -static gdb_breakpoint *g_gdb_debugger_enable_memory_breakpoint(GGdbDebugger *, virt_t); - -/* Retire un point d'arrêt basique en mémoire. */ -static bool g_gdb_debugger_disable_memory_breakpoint(GGdbDebugger *, gdb_breakpoint *); - - - -/* -------------------------- CONTROLE DU FLOT D'EXECUTION -------------------------- */ - - -/* Redémarre le processus de débogage lié à un serveur GDB. */ -static bool g_gdb_debugger_restart(GGdbDebugger *); - -/* Remet en marche le débogueur utilisant un serveur GDB. */ -static bool g_gdb_debugger_resume(GGdbDebugger *); - - - - - - - - - - - - -/* Détermine l'identifiant du thread principal courant. */ -static char *g_gdb_debugger_get_active_thread(GGdbDebugger *); - - - - - - -/* ------------------------ ACCUEIL D'EVENEMENTS ASYNCHRONES ------------------------ */ - - - - - - - - -/* Indique le type défini par la GLib pour le débogueur gdb. */ -G_DEFINE_TYPE(GGdbDebugger, g_gdb_debugger, G_TYPE_BINARY_DEBUGGER); - - -/****************************************************************************** -* * -* Paramètres : klass = classe de débogueur à initialiser. * -* * -* Description : Initialise la classe du débogueur utilisant gdb. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_debugger_class_init(GGdbDebuggerClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - GBinaryDebuggerClass *parent; /* Version en classe parente */ - - object = G_OBJECT_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_gdb_debugger_dispose; - object->finalize = (GObjectFinalizeFunc)g_gdb_debugger_finalize; - - parent = G_BINARY_DEBUGGER_CLASS(klass); - - parent->read_mem = (read_mem_any_fc)g_gdb_debugger_read_memory; - parent->write_mem = (write_mem_any_fc)g_gdb_debugger_write_memory; - parent->get_reg_names = (get_reg_names_fc)g_gdb_debugger_get_register_names; - parent->get_reg_size = (get_reg_size_fc)g_gdb_debugger_get_register_size; - parent->read_reg = (read_write_reg_any_fc)g_gdb_debugger_read_register; - parent->write_reg = (read_write_reg_any_fc)g_gdb_debugger_write_register; - - parent->get_current_pc = (get_current_pc_fc)g_gdb_debugger_get_current_pc; - parent->get_call_stack = (get_call_stack_fc)g_gdb_debugger_compute_call_stack; - - parent->enable_bp = (enable_mem_bp_fc)g_gdb_debugger_enable_memory_breakpoint; - parent->disable_bp = (disable_mem_bp_fc)g_gdb_debugger_disable_memory_breakpoint; - - parent->restart = (restart_debugger_fc)g_gdb_debugger_restart; - parent->resume = (resume_debugger_fc)g_gdb_debugger_resume; - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = instance de débogueur à préparer. * -* * -* Description : Procède à l'initialisation du débogueur utilisant gdb. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_debugger_init(GGdbDebugger *debugger) -{ - GBinaryDebugger *parent; /* Instance parente */ - - parent = G_BINARY_DEBUGGER(debugger); - - parent->run = (basic_debugger_fc)g_gdb_debugger_run; - //parent->resume = (resume_debugger_fc)g_gdb_debugger_resume; - parent->kill = (basic_debugger_fc)g_gdb_debugger_kill; - - //parent->get_reg_values = (get_register_values_fc)get_register_values_using_gdb_debugger; - - //debugger->cond = g_cond_new(); - //debugger->mutex = g_mutex_new(); - - - // FIXME - //debugger->compute_cstack = compute_call_stack_for_arm64; - //debugger->fill_mem_bp = fill_memory_breakpoint_cmd_for_arm64; - - - - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_debugger_dispose(GGdbDebugger *debugger) -{ - if (debugger->stream != NULL) - g_object_unref(G_OBJECT(debugger->stream)); - - if (debugger->support != NULL) - g_object_unref(G_OBJECT(debugger->support)); - - if (debugger->target != NULL) - g_object_unref(G_OBJECT(debugger->target)); - - G_OBJECT_CLASS(g_gdb_debugger_parent_class)->dispose(G_OBJECT(debugger)); - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_debugger_finalize(GGdbDebugger *debugger) -{ - G_OBJECT_CLASS(g_gdb_debugger_parent_class)->finalize(G_OBJECT(debugger)); - -} - - -/****************************************************************************** -* * -* Paramètres : binary = binaire représenter à déboguer. * -* server = nom ou adresse du serveur à contacter. * -* port = port de connexion. * -* * -* Description : Crée un débogueur utilisant un serveur GDB distant. * -* * -* Retour : Instance de débogueur mise en place ou NULL. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GBinaryDebugger *g_gdb_debugger_new(GLoadedBinary *binary, const char *server, unsigned short port) -{ - GGdbDebugger *result; /* Débogueur à retourner */ - GExeFormat *format; /* Format du binaire chargé */ - const char *arch; /* Architecture d'exécution */ - GArchProcessor *proc; /* Processeur lié au binaire */ - char service[sizeof(XSTR(UINT16_MAX)) + 1]; /* Conversion requise */ - - result = g_object_new(G_TYPE_GDB_DEBUGGER, NULL); - - G_BINARY_DEBUGGER(result)->binary = binary; - g_object_ref(G_OBJECT(binary)); - - /* Propriétés de la cible */ - - format = g_loaded_binary_get_format(binary); - - result->endian = g_binary_format_get_endianness(G_BIN_FORMAT(format)); - - arch = g_exe_format_get_target_machine(format); - - if (strcmp(arch, "armv7") == 0) - result->ops = get_arm_operations(); - else - result->ops = NULL; - - g_object_unref(G_OBJECT(format)); - - if (result->ops == NULL) - goto ggdn_error; - - proc = g_loaded_binary_get_processor(binary); - - result->msize = g_arch_processor_get_memory_size(proc); - - g_object_unref(G_OBJECT(proc)); - - /* Mise en place des modules auxialiaires */ - - snprintf(service, sizeof(service), "%hu", port); - - result->stream = g_gdb_tcp_client_new(server, service, result); - if (result->stream == NULL) goto ggdn_error; - - result->support = g_gdb_support_new(result->stream); - - result->target = g_gdb_target_new(result->stream); - if (result->target == NULL) goto ggdn_error; - - return G_BINARY_DEBUGGER(result); - - ggdn_error: - - g_object_unref(G_OBJECT(result)); - - return NULL; - -} - - - - - - - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à lancer. * -* * -* Description : Met en marche le débogueur utilisant un serveur GDB. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_debugger_run(GGdbDebugger *debugger) -{ - - - - GGdbPacket *packet; - - bool test; - - const char *data; - size_t len; - - - int sig; - vmpa_t addr; - pid_t thread; - - - debugger->stream = g_gdb_tcp_client_new("127.0.0.1", "6666", NULL); - if (debugger->stream == NULL) return false; - - - printf("Connection done !\n"); - - - - packet = g_gdb_stream_get_free_packet(debugger->stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, "?"); - - - test = g_gdb_stream_send_packet(debugger->stream, packet); - - - - printf(" >> Paquet '%s' bien envoyé ? %s\n", "?", test ? "oui" : "non"); - - - - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - - packet = g_gdb_stream_recv_packet(debugger->stream); - - g_gdb_packet_get_data(packet, &data, &len, NULL); - - printf(" << Réception de '%s'\n", data); - - - - - - get_stop_reply_sig_info(packet, &sig, &addr, &thread, SRE_LITTLE); - - g_signal_emit_by_name(debugger, "halted", sig, addr, thread); - - - - return true; - -} - - - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à relancer. * -* * -* Description : Tue le débogueur utilisant un serveur GDB. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_debugger_kill(GGdbDebugger *debugger) -{ - - -#if 0 - int ret; /* Bilan de l'appel système */ - - ret = kill(debugger->child, SIGKILL); - if (ret != 0) perror("kill"); - - debugger->child = 0; - - g_mutex_lock(debugger->mutex); - debugger->run_again = TRUE; - g_cond_signal(debugger->cond); - g_mutex_unlock(debugger->mutex); -#endif - return true; - -} - - - - - - - - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à consulter. * -* * -* Description : Détermine l'identifiant du thread principal courant. * -* * -* Retour : Identifiant du thread actif principal ou NULL en cas d'échec.* -* * -* Remarques : - * -* * -******************************************************************************/ - -static char *g_gdb_debugger_get_active_thread(GGdbDebugger *debugger) -{ - char *result; /* Identifiant à renvoyer */ - GGdbPacket *packet; /* Paquet de communication */ - bool status; /* Bilan d'une communication */ - const char *data; /* Données reçues à analyser */ - const char *start; /* Début d'identification */ - const char *end; /* Fin d'identification */ - - result = NULL; - - /* Envoi de la requête */ - - packet = g_gdb_stream_get_free_packet(debugger->stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, "?"); - - status = g_gdb_stream_send_packet(debugger->stream, packet); - - if (!status) - goto ggdgat_exit; - - /* Réception de la réponse */ - - packet = g_gdb_stream_recv_packet(debugger->stream); - - g_gdb_packet_get_data(packet, &data, NULL, NULL); - - start = strstr(data, "thread:"); - if (start == NULL) goto ggdgat_exit; - - start += sizeof("thread:") - 1 /* '\0' */; - - end = strstr(start, ";"); - if (end == NULL) goto ggdgat_exit; - - result = strndup(start, end - start); - - ggdgat_exit: - - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - - return result; - -} - - - - - - - - - - - - - - - - - - - - -/* ---------------------------------------------------------------------------------- */ -/* ENTREES / SORTIES BASIQUES */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à consulter. * -* addr = emplacement en mémoire à venir consulter. * -* size = taille des données mises en jeu. * -* ... = emplacement de la valeur lue à conserver. [OUT] * -* * -* Description : Lit une valeur quelconque à une adresse arbitraire. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_debugger_read_memory(GGdbDebugger *debugger, virt_t addr, size_t size, ...) -{ - bool result; /* Bilan d'opération à renvoyer*/ - char cmd[1 + VMPA_MAX_LEN + 3]; /* Commande à émettre */ - GGdbPacket *packet; /* Paquet de communication */ - const char *data; /* Données reçues à analyser */ - size_t len; /* Quantité de données reçues */ - va_list ap; /* Liste variable d'arguments */ - uint8_t *val8; /* Valeur sur 8 bits */ - uint16_t *val16; /* Valeur sur 16 bits */ - uint16_t conv16; /* Valeur adaptée sur 16 bits */ - uint32_t *val32; /* Valeur sur 32 bits */ - uint32_t conv32; /* Valeur adaptée sur 32 bits */ - uint64_t *val64; /* Valeur sur 64 bits */ - uint64_t conv64; /* Valeur adaptée sur 64 bits */ - - /* Envoi de la requête */ - - cmd[0] = 'm'; - - result = translate_virt_to_hex(debugger, addr, &cmd[1]); - - switch (size) - { - case 8: - strcat(cmd, ",1"); - break; - - case 16: - strcat(cmd, ",2"); - break; - - case 32: - strcat(cmd, ",4"); - break; - - case 64: - strcat(cmd, ",8"); - break; - - default: - assert(false); - result = false; - goto ggdrm_exit; - break; - - } - - packet = g_gdb_stream_get_free_packet(debugger->stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, cmd); - - result = g_gdb_stream_send_packet(debugger->stream, packet); - - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - - if (!result) - goto ggdrm_exit; - - /* Réception de la réponse */ - - packet = g_gdb_stream_recv_packet(debugger->stream); - - g_gdb_packet_get_data(packet, &data, &len, NULL); - - if (is_error_code(data, len)) - { - result = false; - goto ggdrm_error; - } - - va_start(ap, size); - - switch (size) - { - case 8: - val8 = va_arg(ap, uint8_t *); - result = hex_to_u8(data, val8); - break; - - case 16: - val16 = va_arg(ap, uint16_t *); - result = hex_to_u16(data, &conv16); - *val16 = from_u16(&conv16, debugger->endian); - break; - - case 32: - val32 = va_arg(ap, uint32_t *); - result = hex_to_u32(data, &conv32); - *val32 = from_u32(&conv32, debugger->endian); - break; - - case 64: - val64 = va_arg(ap, uint64_t *); - result = hex_to_u64(data, &conv64); - *val64 = from_u64(&conv64, debugger->endian); - break; - - default: - assert(false); - result = false; - break; - - } - - va_end(ap); - - ggdrm_error: - - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - - ggdrm_exit: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à manipuler. * -* addr = emplacement en mémoire à venir consulter. * -* size = taille des données mises en jeu. * -* ... = emplacement de la valeur lue à conserver. [OUT] * -* * -* Description : Lit une valeur quelconque à une adresse arbitraire. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_debugger_write_memory(GGdbDebugger *debugger, virt_t addr, size_t size, ...) -{ - bool result; /* Bilan d'opération à renvoyer*/ - char cmd[1 + 3 * VMPA_MAX_LEN + 3]; /* Commande à émettre */ - va_list ap; /* Liste variable d'arguments */ - const uint8_t *val8; /* Valeur sur 8 bits */ - const uint16_t *val16; /* Valeur sur 16 bits */ - uint16_t conv16; /* Valeur adaptée sur 16 bits */ - const uint32_t *val32; /* Valeur sur 32 bits */ - uint32_t conv32; /* Valeur adaptée sur 32 bits */ - const uint64_t *val64; /* Valeur sur 64 bits */ - uint64_t conv64; /* Valeur adaptée sur 64 bits */ - char hexval[17]; /* Valeur sous forme hexa */ - GGdbPacket *packet; /* Paquet de communication */ - const char *data; /* Données reçues à analyser */ - size_t len; /* Quantité de données reçues */ - - /* Envoi de la requête */ - - cmd[0] = 'M'; - - result = translate_virt_to_hex(debugger, addr, &cmd[1]); - - va_start(ap, size); - - switch (size) - { - case 8: - val8 = va_arg(ap, uint8_t *); - result = u8_to_hex(val8, hexval); - - strcat(cmd, ",1:"); - strcat(cmd, hexval); - break; - - case 16: - val16 = va_arg(ap, uint16_t *); - conv16 = to_u16(val16, debugger->endian); - result = u16_to_hex(&conv16, hexval); - - strcat(cmd, ",2:"); - strcat(cmd, hexval); - break; - - case 32: - val32 = va_arg(ap, uint32_t *); - conv32 = to_u32(val32, debugger->endian); - result = u32_to_hex(&conv32, hexval); - - strcat(cmd, ",4:"); - strcat(cmd, hexval); - break; - - case 64: - val64 = va_arg(ap, uint64_t *); - conv64 = to_u64(val64, debugger->endian); - result = u16_to_hex(&conv64, hexval); - - strcat(cmd, ",8:"); - strcat(cmd, hexval); - break; - - default: - assert(false); - result = false; - break; - - } - - if (!result) - goto ggdwm_exit; - - packet = g_gdb_stream_get_free_packet(debugger->stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, cmd); - - result = g_gdb_stream_send_packet(debugger->stream, packet); - - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - - if (!result) - goto ggdwm_exit; - - /* Réception de la réponse */ - - packet = g_gdb_stream_recv_packet(debugger->stream); - - g_gdb_packet_get_data(packet, &data, &len, NULL); - - if (len == 3 && data[0] == 'E') - { - result = false; - goto ggdrm_error; - } - - ggdrm_error: - - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - - ggdwm_exit: - - va_end(ap); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à consulter. * -* group = éventuel groupe de registres ciblé ou NULL. * -* count = nombre d'éléments dans la liste de noms. [OUT] * -* * -* Description : Liste l'ensemble des registres appartenant à un groupe. * -* * -* Retour : Liste de noms à libérer de la mémoire après utilisation. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static char **g_gdb_debugger_get_register_names(const GGdbDebugger *debugger, const char *group, size_t *count) -{ - return g_gdb_target_get_register_names(debugger->target, group, count); - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à consulter. * -* name = désignation du registre visé. * -* * -* Description : Indique la taille associée à un registre donné. * -* * -* Retour : Taille en bits, ou 0 si le registre n'a pas été trouvé. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static unsigned int g_gdb_debugger_get_register_size(const GGdbDebugger *debugger, const char *name) -{ - return g_gdb_target_get_register_size(debugger->target, name); - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à consulter. * -* reg = désignation humaine du register à consulter. * -* size = taille des données mises en jeu. * -* ... = emplacement de la valeur lue à conserver. [OUT] * -* * -* Description : Effectue la lecture d'un registre donné. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_debugger_read_register(GGdbDebugger *debugger, const char *reg, size_t size, ...) -{ - bool result; /* Bilan d'opération à renvoyer*/ - va_list ap; /* Liste variable d'arguments */ - uint8_t *val8; /* Valeur sur 8 bits */ - uint16_t *val16; /* Valeur sur 16 bits */ - uint32_t *val32; /* Valeur sur 32 bits */ - uint64_t *val64; /* Valeur sur 64 bits */ - - va_start(ap, size); - - switch (size) - { - case 8: - val8 = va_arg(ap, uint8_t *); - result = g_gdb_target_read_register(debugger->target, debugger->stream, debugger->endian, - reg, 8, val8); - break; - - case 16: - val16 = va_arg(ap, uint16_t *); - result = g_gdb_target_read_register(debugger->target, debugger->stream, debugger->endian, - reg, 16, val16); - break; - - case 32: - val32 = va_arg(ap, uint32_t *); - result = g_gdb_target_read_register(debugger->target, debugger->stream, debugger->endian, - reg, 32, val32); - break; - - case 64: - val64 = va_arg(ap, uint64_t *); - result = g_gdb_target_read_register(debugger->target, debugger->stream, debugger->endian, - reg, 64, val64); - break; - - default: - assert(false); - result = false; - break; - - } - - va_end(ap); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à manipuler. * -* reg = désignation humaine du register à consulter. * -* size = taille des données mises en jeu. * -* ... = emplacement de la valeur à écrire. * -* * -* Description : Effectue l'écriture d'un registre donné. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_debugger_write_register(GGdbDebugger *debugger, const char *reg, size_t size, ...) -{ - bool result; /* Bilan d'opération à renvoyer*/ - va_list ap; /* Liste variable d'arguments */ - const uint8_t *val8; /* Valeur sur 8 bits */ - const uint16_t *val16; /* Valeur sur 16 bits */ - const uint32_t *val32; /* Valeur sur 32 bits */ - const uint64_t *val64; /* Valeur sur 64 bits */ - - va_start(ap, size); - - switch (size) - { - case 8: - val8 = va_arg(ap, const uint8_t *); - result = g_gdb_target_write_register(debugger->target, debugger->stream, debugger->endian, - reg, 8, val8); - break; - - case 16: - val16 = va_arg(ap, const uint16_t *); - result = g_gdb_target_write_register(debugger->target, debugger->stream, debugger->endian, - reg, 16, val16); - break; - - case 32: - val32 = va_arg(ap, const uint32_t *); - result = g_gdb_target_write_register(debugger->target, debugger->stream, debugger->endian, - reg, 32, val32); - break; - - case 64: - val64 = va_arg(ap, const uint64_t *); - result = g_gdb_target_write_register(debugger->target, debugger->stream, debugger->endian, - reg, 64, val64); - break; - - default: - assert(false); - result = false; - break; - - } - - va_end(ap); - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* MANIPULATION DE L'ETAT COURANT */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à consulter. * -* pc = adresse de l'instruction courante. [OUT] * -* * -* Description : Détermine le point d'exécution courant. * -* * -* Retour : Bilan de la récupération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_debugger_get_current_pc(GGdbDebugger *debugger, virt_t *pc) -{ - bool result; /* Bilan à retourner */ - - result = debugger->ops->get_pc(debugger, pc); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à consulter. * -* callstack = pile d'appels reconstituée. [OUT] * -* size = taille de cette pile. [OUT] * -* * -* Description : Remonte la pile d'appels jusqu'au point courant. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_debugger_compute_call_stack(GGdbDebugger *debugger, virt_t **callstack, size_t *size) -{ - bool result; /* Bilan global à retourner */ - - if (debugger->ops->compute_cstack != NULL) - result = debugger->ops->compute_cstack(debugger, callstack, size); - - else - result = false; - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* GESTION DES POINTS D'ARRET */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à manipuler ici. * -* addr = emplacement du point mémoire à traiter. * -* * -* Description : Ajoute un point d'arrêt basique en mémoire. * -* * -* Retour : Structure de suivi mise en place pour l'occasion, voire NULL.* -* * -* Remarques : - * -* * -******************************************************************************/ - -static gdb_breakpoint *g_gdb_debugger_enable_memory_breakpoint(GGdbDebugger *debugger, virt_t addr) -{ - gdb_breakpoint *result; /* Nouveau suivi à retourner */ - char cmd[3 + VMPA_MAX_LEN + 3]; /* Commande à émettre */ - bool status; /* Bilan d'une opération */ - const char *kind; /* Taille spécifique du point */ - GGdbPacket *packet; /* Paquet de communication */ - const char *data; /* Données reçues à analyser */ - size_t len; /* Quantité de données reçues */ - GBinaryDebugger *dbg; /* Autre version du débogueur */ - const uint8_t *bp; /* Données du point d'arrêt */ - size_t bp_len; /* Quantité de ces données */ - uint8_t memory[16]; /* Sauvegarde de la mémoire */ - - result = NULL; - - /* Si l'utilisation de la commande dédiée est possible */ - if (1) //////// TODO - { - /* Envoi de la requête */ - - strcpy(cmd, "Z0,"); - - status = translate_virt_to_hex(debugger, addr, &cmd[3]); - - if (!status) - goto ggdemb_exit; - - kind = debugger->ops->get_bp_kind(debugger, addr); - - if (kind == NULL) - goto ggdemb_exit; - - strcat(cmd, kind); - - packet = g_gdb_stream_get_free_packet(debugger->stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, cmd); - - status = g_gdb_stream_send_packet(debugger->stream, packet); - - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - - if (!status) - goto ggdemb_exit; - - /* Réception de la réponse */ - - packet = g_gdb_stream_recv_packet(debugger->stream); - - g_gdb_packet_get_data(packet, &data, &len, NULL); - - if (is_error_code(data, len)) - { - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - goto ggdemb_fallback; - } - - if (strcmp(data, "OK") != 0) - { - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - goto ggdemb_fallback; - } - - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - - /* Constitution d'un dossier de suivi */ - - result = (gdb_breakpoint *)malloc(sizeof(gdb_breakpoint)); - - result->is_z = true; - - result->kind = kind; - - } - - else - { - - ggdemb_fallback: - - dbg = G_BINARY_DEBUGGER(debugger); - - /* Détermination du point d'arrêt */ - - bp = debugger->ops->get_bp_data(debugger, addr, &bp_len); - - assert(bp_len <= 16); - - /* Sauvegarde de la mémoire courante */ - - status = g_binary_debugger_read_memory_data(dbg, addr, memory, bp_len); - - if (!status) goto ggdemb_exit; - - /* Application du point d'arrêt */ - - status = g_binary_debugger_write_memory_data(dbg, addr, bp, bp_len); - - if (!status) goto ggdemb_exit; - - /* Constitution d'un dossier de suivi */ - - result = (gdb_breakpoint *)malloc(sizeof(gdb_breakpoint)); - - result->is_z = false; - - memcpy(result->memory, memory, bp_len); - result->len = bp_len; - - } - - init_raw_breakpoint((raw_breakpoint *)result, addr); - - ggdemb_exit: - - return result; -} - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à manipuler ici. * -* bp = point d'arrêt à traiter. * -* * -* Description : Retire un point d'arrêt basique de la mémoire ciblée. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_debugger_disable_memory_breakpoint(GGdbDebugger *debugger, gdb_breakpoint *bp) -{ - bool result; /* Bilan à retourner */ - char cmd[3 + VMPA_MAX_LEN + 3]; /* Commande à émettre */ - bool status; /* Bilan d'une opération */ - GGdbPacket *packet; /* Paquet de communication */ - const char *data; /* Données reçues à analyser */ - size_t len; /* Quantité de données reçues */ - GBinaryDebugger *dbg; /* Autre version du débogueur */ - - result = false; - - /* Si l'utilisation de la commande dédiée est requise */ - if (bp->is_z) - { - /* Envoi de la requête */ - - strcpy(cmd, "z0,"); - - status = translate_virt_to_hex(debugger, bp->raw.addr, &cmd[3]); - - if (!status) - goto ggddmb_exit; - - strcat(cmd, bp->kind); - - packet = g_gdb_stream_get_free_packet(debugger->stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, cmd); - - status = g_gdb_stream_send_packet(debugger->stream, packet); - - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - - if (!status) - goto ggddmb_exit; - - /* Réception de la réponse */ - - packet = g_gdb_stream_recv_packet(debugger->stream); - - g_gdb_packet_get_data(packet, &data, &len, NULL); - - if (is_error_code(data, len)) - { - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - goto ggddmb_exit; - } - - if (strcmp(data, "OK") != 0) - { - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - goto ggddmb_exit; - } - - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - - result = true; - - } - - else - { - dbg = G_BINARY_DEBUGGER(debugger); - - result = g_binary_debugger_write_memory_data(dbg, bp->raw.addr, bp->memory, bp->len); - - } - - ggddmb_exit: - - return result; - -} - - - -/* ---------------------------------------------------------------------------------- */ -/* CONTROLE DU FLOT D'EXECUTION */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à redémarrer. * -* * -* Description : Redémarre le processus de débogage lié à un serveur GDB. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_debugger_restart(GGdbDebugger *debugger) -{ - bool result; /* Bilan à retourner */ - GGdbPacket *packet; /* Paquet de communication */ - return true; - /* Envoi de la requête */ - - packet = g_gdb_stream_get_free_packet(debugger->stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, "R00"); - - result = g_gdb_stream_send_packet(debugger->stream, packet); - - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à relancer. * -* * -* Description : Remet en marche le débogueur utilisant un serveur GDB. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_debugger_resume(GGdbDebugger *debugger) -{ - bool result; /* Bilan à retourner */ - //char *id; /* Identifiant de thread */ - GGdbPacket *packet; /* Paquet de communication */ - //const char *data; /* Données reçues à analyser */ - - static bool _twice = false; - - - if (!_twice && 0) - { - - packet = g_gdb_stream_get_free_packet(debugger->stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, "$QPassSignals:e;10;14;17;1a;1b;1c;21;24;25;2c;4c;"); - - result = g_gdb_stream_send_packet(debugger->stream, packet); - - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - - if (!result) - goto ggdhmb_exit; - - } - - - - - - - /* Envoi de la requête */ - - /* - id = g_gdb_debugger_get_active_thread(debugger); - if (id == NULL) return false; - - printf("ID : %s\n", id); - */ - - /* - id = g_gdb_support_get_id(debugger->support); - if (id == NULL) return false; - - printf("ID : %s\n", id); - */ - - packet = g_gdb_stream_get_free_packet(debugger->stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, "vCont;c:-1"); - //g_gdb_packet_append(packet, "vCont;c:p256f.-1"); - - - /* - if (_twice) - { - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, "vCont;c:p"); - g_gdb_packet_append(packet, id); - g_gdb_packet_append(packet, "."); - g_gdb_packet_append(packet, id); - } - else - { - _twice = true; - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, "vCont;c:p"); - g_gdb_packet_append(packet, id); - g_gdb_packet_append(packet, ".-1"); - } - */ - - - - - - result = g_gdb_stream_send_packet(debugger->stream, packet); - - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - - if (!result) - goto ggdhmb_exit; - - /* Réception de la réponse */ - /* - packet = g_gdb_stream_recv_packet(debugger->stream); - - g_gdb_packet_get_data(packet, &data, NULL, NULL); - - printf("Ack cont...\n"); - - //result = (strcmp(data, "OK") == 0); - - g_gdb_stream_mark_packet_as_free(debugger->stream, packet); - */ - ggdhmb_exit: - - _twice = true; - - return result; - -} - - - - - - - - - - - - - - -/* ---------------------------------------------------------------------------------- */ -/* ACCUEIL D'EVENEMENTS ASYNCHRONES */ -/* ---------------------------------------------------------------------------------- */ - - -/****************************************************************************** -* * -* Paramètres : debugger = instance liée à un débogueur GDB à manipuler. * -* signum = indentifiant du signal concerné. * -* * -* Description : Réagit à la réception d'un signal par le programme étudié. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_gdb_debugger_receive_signal_reply(GGdbDebugger *debugger, int signum) -{ - virt_t pc; /* Position courante du CPU */ - bool status; /* Bilan d'une opération */ - GBinaryDebugger *base; /* Version basique du débogueur*/ - - base = G_BINARY_DEBUGGER(debugger); - - status = g_binary_debugger_get_current_pc(base, &pc); - - if (!status) - pc = VMPA_NO_VIRTUAL; - - on_binary_debugger_stopped(base, pc); - - g_signal_emit_by_name(debugger, "signaled", signum); - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = instance liée à un débogueur GDB à manipuler. * -* status = indication d'état à la sortie. * -* pid = éventuel identifiant de processus concerné ou -1. * -* * -* Description : Réagit à la sortie d'exécution d'un programme étudié. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_gdb_debugger_receive_exit_reply(GGdbDebugger *debugger, int status, pid_t pid) -{ - GBinaryDebugger *base; /* Version basique du débogueur*/ - - base = G_BINARY_DEBUGGER(debugger); - - on_binary_debugger_finished(base, pid); - - g_signal_emit_by_name(debugger, "exited", status, pid); - -} diff --git a/src/debug/gdbrsp/gdb.h b/src/debug/gdbrsp/gdb.h deleted file mode 100644 index a338f98..0000000 --- a/src/debug/gdbrsp/gdb.h +++ /dev/null @@ -1,61 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * gdb.h - prototypes pour le débogage à l'aide de gdb. - * - * Copyright (C) 2009-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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _DEBUG_GDBRSP_GDB_H -#define _DEBUG_GDBRSP_GDB_H - - -#include <glib-object.h> - - -#include "../debugger.h" - - - -#define G_TYPE_GDB_DEBUGGER (g_gdb_debugger_get_type()) -#define G_GDB_DEBUGGER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_GDB_DEBUGGER, GGdbDebugger)) -#define G_IS_GDB_DEBUGGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_GDB_DEBUGGER)) -#define G_GDB_DEBUGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GDB_DEBUGGER, GGdbDebuggerClass)) -#define G_IS_GDB_DEBUGGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GDB_DEBUGGER)) -#define G_GDB_DEBUGGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_DEBUGGER, GGdbDebuggerClass)) - - -/* Débogueur utilisant un serveur GDB (instance) */ -typedef struct _GGdbDebugger GGdbDebugger; - -/* Débogueur utilisant un serveur GDB (classe) */ -typedef struct _GGdbDebuggerClass GGdbDebuggerClass; - - -/* Indique le type défini par la GLib pour le débogueur gdb. */ -GType g_gdb_debugger_get_type(void); - -/* Crée un débogueur utilisant un serveur GDB distant. */ -GBinaryDebugger *g_gdb_debugger_new(GLoadedBinary *, const char *, unsigned short); - - -void test_gdb(void); - - - -#endif /* _DEBUG_GDBRSP_GDB_H */ diff --git a/src/debug/gdbrsp/helpers.c b/src/debug/gdbrsp/helpers.c deleted file mode 100644 index 1bdf6f7..0000000 --- a/src/debug/gdbrsp/helpers.c +++ /dev/null @@ -1,224 +0,0 @@ - -/* 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "helpers.h" - - -#include <regex.h> -#include <string.h> - - -#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); - -} - - - diff --git a/src/debug/gdbrsp/helpers.h b/src/debug/gdbrsp/helpers.h deleted file mode 100644 index 0492ea3..0000000 --- a/src/debug/gdbrsp/helpers.h +++ /dev/null @@ -1,62 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * helpers.h - prototypes pour un 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _DEBUG_GDBRSP_HELPERS_H -#define _DEBUG_GDBRSP_HELPERS_H - - -#include "gdb.h" -#include "packet.h" - - - -/* Traduit une adresse en chaîne hexadécimale pour GDB. */ -bool translate_virt_to_hex(const GGdbDebugger *, virt_t, char *); - - - - - - -/* -------------------------- PAQUETS DES REPONSES D'ARRET -------------------------- */ - - -/* Récupère les informations liées à un arrêt suite à signal. */ -bool get_stop_reply_sig_info(const GGdbPacket *, int *, vmpa_t *, pid_t *, SourceEndian); - - - -/* ---------------------------------------------------------------------------------- */ -/* PAQUETS DES REPONSES D'ARRET */ -/* ---------------------------------------------------------------------------------- */ - - - - - - - - - - -#endif /* _DEBUG_GDBRSP_HELPERS_H */ diff --git a/src/debug/gdbrsp/helpers_arm.c b/src/debug/gdbrsp/helpers_arm.c deleted file mode 100644 index 4b486d4..0000000 --- a/src/debug/gdbrsp/helpers_arm.c +++ /dev/null @@ -1,252 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * helpers_arm.c - compléments utiles à GDB pour l'architecture ARM - * - * Copyright (C) 2016 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 <http://www.gnu.org/licenses/>. - */ - - -#include "helpers_arm.h" - - -#include <malloc.h> -#include <string.h> - - -#include "gdb-int.h" - - - -/* Détermine le point d'exécution courant. */ -static bool get_arm_pc(GGdbDebugger *, virt_t *); - -/* Remonte la pile d'appels jusqu'au point courant. */ -static bool compute_call_stack_for_arm(const GGdbDebugger *, virt_t **, size_t *); - -/* Complète la commande manipulant des points d'arrêt. */ -static const char *get_breakpoint_kind_for_arm(const GGdbDebugger *, virt_t); - -/* Construit une instruction provoquant un arrêt d'exécution. */ -static const uint8_t *get_arm_breakpoint_data(const GGdbDebugger *, virt_t, size_t *); - - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Fournit les fonctions adaptées aux opérations pour ARM. * -* * -* Retour : Opérations spécifiques adaptées à ARM. * -* * -* Remarques : - * -* * -******************************************************************************/ - -const gdb_arch_ops *get_arm_operations(void) -{ - static const gdb_arch_ops arm_ops = { - - .get_pc = get_arm_pc, - .compute_cstack = compute_call_stack_for_arm, - .get_bp_kind = get_breakpoint_kind_for_arm, - .get_bp_data = get_arm_breakpoint_data - - }; - - return &arm_ops; - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à consulter. * -* pc = adresse de l'instruction courante. [OUT] * -* * -* Description : Détermine le point d'exécution courant. * -* * -* Retour : Bilan de la récupération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool get_arm_pc(GGdbDebugger *debugger, virt_t *pc) -{ - bool result; /* Bilan à retourner */ - uint32_t value; - - result = g_binary_debugger_read_register_u32(G_BINARY_DEBUGGER(debugger), "pc", &value); - - if (result) - *pc = value; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à consulter. * -* callstack = pile d'appels reconstituée. [OUT] * -* size = taille de cette pile. [OUT] * -* * -* Description : Remonte la pile d'appels jusqu'au point courant. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool compute_call_stack_for_arm(const GGdbDebugger *debugger, virt_t **callstack, size_t *size) -{ - bool result; /* Bilan global à retourner */ - GBinaryDebugger *base; /* Version basique d'instance */ - uint32_t lr; /* Retour de fonction */ - uint32_t fp; /* Pointeur de cadre à suivre */ - - base = G_BINARY_DEBUGGER(debugger); - - result = g_binary_debugger_read_register_u32(base, "lr", &lr); - - if (result && lr != 0) - { - *callstack = (virt_t *)realloc(*callstack, ++(*size) * sizeof(virt_t)); - - (*callstack)[*size - 1] = lr; - - } - - result &= g_binary_debugger_read_register_u32(base, "r11", &fp); - - while (result && fp != 0) - { - /** - * fp[-0] : pc sauvegardé - * fp[-1] : lr sauvegardé - * fp[-2] : sp précédent - * fp[-3] : fp précédent - */ - - result = g_binary_debugger_read_memory_u32(base, fp - 2 * sizeof(uint32_t), &lr); - if (!result) break; - - if (lr != 0) - { - *callstack = (virt_t *)realloc(*callstack, ++(*size) * sizeof(virt_t)); - - (*callstack)[*size - 1] = lr; - - } - - result = g_binary_debugger_read_memory_u32(base, fp - 4 * sizeof(uint32_t), &fp); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à manipuler ici. * -* virt = emplacement du point mémoire à traiter. * -* * -* Description : Complète la commande manipulant des points d'arrêt. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static const char *get_breakpoint_kind_for_arm(const GGdbDebugger *debugger, virt_t virt) -{ - const char *result; /* Indication à retourner */ - GArchProcessor *proc; /* Processeur lié au binaire */ - vmpa2t addr; /* Format d'adresse complet */ - GArchInstruction *instr; /* Instruction ciblée */ - const char *encoding; /* Encodage de l'instruction */ - - proc = g_loaded_binary_get_processor(G_BINARY_DEBUGGER(debugger)->binary); - - init_vmpa(&addr, VMPA_NO_PHYSICAL, virt); - instr = g_arch_processor_find_instr_by_address(proc, &addr); - - if (instr == NULL) - result = NULL; - - else - { - encoding = g_arch_instruction_get_encoding(instr); - - if (strcmp(encoding, "Thumb/16") == 0) - result = ",2"; - - if (strcmp(encoding, "Thumb/32") == 0) - result = ",3"; - - if (strcmp(encoding, "ARM") == 0) - result = ",4"; - - else - result = NULL; - - g_object_unref(G_OBJECT(instr)); - - } - - g_object_unref(G_OBJECT(proc)); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à manipuler ici. * -* addr = emplacement du point mémoire à traiter. * -* len = quantité de mémoire à remplacer. [OUT] * -* * -* Description : Construit une instruction provoquant un arrêt d'exécution. * -* * -* Retour : Définition du point d'arrêt à placer à l'adresse donnée. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static const uint8_t *get_arm_breakpoint_data(const GGdbDebugger *debugger, virt_t addr, size_t *len) -{ - const uint8_t *result; /* Données à placer en mémoire */ - - /* Version point d'arrêt */ - static const uint32_t bkpt_code[] = { 0xe1200070 }; - - *len = sizeof(bkpt_code);; - - result = (const uint8_t *)bkpt_code; - - return result; - -} diff --git a/src/debug/gdbrsp/helpers_arm.h b/src/debug/gdbrsp/helpers_arm.h deleted file mode 100644 index ec82b27..0000000 --- a/src/debug/gdbrsp/helpers_arm.h +++ /dev/null @@ -1,37 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * helpers_arm.h - prototypes pour les compléments utiles à GDB pour l'architecture ARM - * - * Copyright (C) 2016 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 <http://www.gnu.org/licenses/>. - */ - - -#ifndef _DEBUG_GDBRSP_HELPERS_ARM_H -#define _DEBUG_GDBRSP_HELPERS_ARM_H - - -#include "aops.h" - - - -/* Fournit les fonctions adaptées aux opérations pour ARM. */ -const gdb_arch_ops *get_arm_operations(void); - - - -#endif /* _DEBUG_GDBRSP_HELPERS_ARM_H */ diff --git a/src/debug/gdbrsp/helpers_arm64.c b/src/debug/gdbrsp/helpers_arm64.c deleted file mode 100644 index 810c8b3..0000000 --- a/src/debug/gdbrsp/helpers_arm64.c +++ /dev/null @@ -1,97 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * helpers_arm64.c - compléments utiles à GDB pour l'architecture AArch64 - * - * Copyright (C) 2016 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 <http://www.gnu.org/licenses/>. - */ - - -#include "helpers_arm64.h" - - -#include <malloc.h> - - -#include "gdb-int.h" - - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à consulter. * -* callstack = pile d'appels reconstituée. [OUT] * -* size = taille de cette pile. [OUT] * -* * -* Description : Remonte la pile d'appels jusqu'au point courant. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool compute_call_stack_for_arm64(GGdbDebugger *debugger, virt_t **callstack, size_t *size) -{ - bool result; /* Bilan global à retourner */ - GBinaryDebugger *base; /* Version basique d'instance */ - uint64_t fp; /* Pointeur de cadre à suivre */ - uint64_t previous; /* Appel de fonction précédent */ - - base = G_BINARY_DEBUGGER(debugger); - - result = g_binary_debugger_read_register_u64(base, "x29", &fp); - - while (result && fp != 0) - { - result = g_binary_debugger_read_memory_u64(base, fp + sizeof(uint64_t), &previous); - if (!result) break; - - *callstack = (virt_t *)realloc(*callstack, ++(*size) * sizeof(virt_t)); - - (*callstack)[*size - 1] = previous; - - result = g_binary_debugger_read_memory_u64(base, fp, &fp); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : debugger = débogueur à manipuler ici. * -* addr = emplacement du point mémoire à traiter. * -* cmd = commande en cours de constitution. [OUT] * -* * -* Description : Complète la commande manipulant des points d'arrêt. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool fill_memory_breakpoint_cmd_for_arm64(GGdbDebugger *debugger, virt_t addr, char *cmd) -{ - strcat(cmd, ",4"); - - return true; - -} diff --git a/src/debug/gdbrsp/helpers_arm64.h b/src/debug/gdbrsp/helpers_arm64.h deleted file mode 100644 index 5e89deb..0000000 --- a/src/debug/gdbrsp/helpers_arm64.h +++ /dev/null @@ -1,40 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * helpers_arm64.h - prototypes pour les compléments utiles à GDB pour l'architecture AArch64 - * - * Copyright (C) 2016 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 <http://www.gnu.org/licenses/>. - */ - - -#ifndef _DEBUG_GDBRSP_HELPERS_ARM64_H -#define _DEBUG_GDBRSP_HELPERS_ARM64_H - - -#include "gdb.h" - - - -/* Remonte la pile d'appels jusqu'au point courant. */ -bool compute_call_stack_for_arm64(GGdbDebugger *, virt_t **, size_t *); - -/* Complète la commande manipulant des points d'arrêt. */ -bool fill_memory_breakpoint_cmd_for_arm64(GGdbDebugger *, virt_t, char *); - - - -#endif /* _DEBUG_GDBRSP_HELPERS_ARM64_H */ diff --git a/src/debug/gdbrsp/packet.c b/src/debug/gdbrsp/packet.c deleted file mode 100644 index 806c6b0..0000000 --- a/src/debug/gdbrsp/packet.c +++ /dev/null @@ -1,389 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * packet.c - manipulation des paquets de données GDB. - * - * Copyright (C) 2009-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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "packet.h" - - -#include <malloc.h> -#include <string.h> - - -#include "../../common/dllist.h" - - - -/* Répresentation d'un paquet GDB (instance) */ -struct _GGdbPacket -{ - GObject parent; /* A laisser en premier */ - - DL_LIST_ITEM(link); /* Lien vers les autres */ - - char *buffer; /* Données à traiter */ - size_t len; /* Quantité de ces données */ - size_t allocated; /* Taille du tampon */ - - uint8_t checksum; /* Empreinte de contrôle */ - -}; - - -/* Répresentation d'un paquet GDB (classe) */ -struct _GGdbPacketClass -{ - GObjectClass parent; /* A laisser en premier */ - -}; - - -/* Initialise la classe des représentations des paquets GDB. */ -static void g_gdb_packet_class_init(GGdbPacketClass *); - -/* Initialise une instance de représentation de paquet GDB. */ -static void g_gdb_packet_init(GGdbPacket *); - - - -/* Indique le type défini pour une répresentation de paquet GDB. */ -G_DEFINE_TYPE(GGdbPacket, g_gdb_packet, G_TYPE_OBJECT); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des représentations des paquets GDB. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_packet_class_init(GGdbPacketClass *klass) -{ - -} - - -/****************************************************************************** -* * -* Paramètres : packet = instance à initialiser. * -* * -* Description : Initialise une instance de représentation de paquet GDB. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_packet_init(GGdbPacket *packet) -{ - DL_LIST_ITEM_INIT(&packet->link); - -} - - -/****************************************************************************** -* * -* Paramètres : - * -* * -* Description : Crée une représentation de paquet GDB. * -* * -* Retour : Adresse de la structure mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GGdbPacket *g_gdb_packet_new(void) -{ - GGdbPacket *result; /* Structure à retourner */ - - result = g_object_new(G_TYPE_GDB_PACKET, NULL); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : packet = paquet à préparer pour une émission. * -* * -* Description : Prépare un paquet pour un envoi prochain. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_gdb_packet_start_new_command(GGdbPacket *packet) -{ - if (packet->allocated == 0) - { - packet->allocated = 1; - packet->buffer = (char *)calloc(packet->allocated, sizeof(char)); - } - - packet->buffer[0] = '\0'; - packet->len = 0; - -} - - -/****************************************************************************** -* * -* Paramètres : packet = paquet à préparer pour une émission. * -* string = chaîne à inclure dans le paquet. * -* * -* Description : Complète un paquet pour un envoi prochain. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_gdb_packet_append(GGdbPacket *packet, const char *string) -{ - size_t len; /* Taille de la chaîne donnée */ - - len = strlen(string); - - /* Si la place n'est pas assez grande */ - if ((packet->len + len + 1) > packet->allocated) - { - packet->buffer = (char *)realloc(packet->buffer, (packet->len + len + 1) * sizeof(char)); - packet->allocated = packet->len + len + 1; - } - - - memcpy(packet->buffer + packet->len, string, len + 1); - //strcat(packet->buffer, string); - - packet->len += len; - -} - - -/****************************************************************************** -* * -* Paramètres : packet = paquet à analyser. * -* * -* Description : Détermine l'empreinte des données d'un paquet GDB. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_gdb_packet_compute_checksum(GGdbPacket *packet) -{ - int sum; /* Valeur cumulée des données */ - size_t i; /* Boucle de parcours */ - - sum = 0; - - for (i = 0; i < packet->len; i++) - sum += packet->buffer[i]; - - packet->checksum = sum % 256; - -} - - -/****************************************************************************** -* * -* Paramètres : packet = paquet à analyser. * -* checksum = contrôle d'intégrité à retrouver. * -* * -* Description : Contrôle l'intégrité des données d'un paquet GDB. * -* * -* Retour : Bilan de la vérification. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_gdb_packet_verify_checksum(GGdbPacket *packet, uint8_t checksum) -{ - g_gdb_packet_compute_checksum(packet); - - return checksum == packet->checksum; - -} - - -/****************************************************************************** -* * -* Paramètres : packet = paquet à décoder et/ou décompresser. * -* * -* Description : Décode et/ou décompresse un paquet GDB. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_gdb_packet_decode(GGdbPacket *packet) -{ - bool result; /* Bilan à retourner */ - char *buffer; /* Données transcrites */ - size_t allocated; /* Quantité de données gérées */ - size_t i; /* Boucle de parcours */ - size_t k; /* Point d'insertion */ - size_t repeat; /* Nombre de répétitions */ - - result = true; - - allocated = packet->len + 1; - buffer = (char *)calloc(allocated, sizeof(char)); - - for (i = 0, k = 0; i < packet->len && result; i++) - switch (packet->buffer[i]) - { - case '#': - case '$': - result = false; - break; - - case '*': - - if (++i == packet->len || k == 0) - { - result = false; - break; - } - - repeat = packet->buffer[i] - ' ' + 3; - - allocated += repeat; - buffer = (char *)realloc(buffer, allocated * sizeof(char)); - - memset(&buffer[k], buffer[k - 1], repeat); - k += repeat; - - break; - - case '}': - - if (++i == packet->len) - { - result = false; - break; - } - - buffer[k++] = packet->buffer[i] ^ 0x20; - - break; - - default: - buffer[k++] = packet->buffer[i]; - break; - - } - - if (packet->buffer != NULL) - free(packet->buffer); - - buffer[k] = '\0'; - - packet->buffer = buffer; - packet->len = k; - packet->allocated = allocated; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : packet = paquet à analyser. * -* data = données contenues dans le paquet. [OUT] * -* len = quantité de ces données ou NULL. [OUT] * -* checksum = contrôle d'intégrité des données ou NULL. [OUT] * -* * -* Description : Fournit le contenu du paquet. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_gdb_packet_get_data(const GGdbPacket *packet, const char **data, size_t *len, uint8_t *checksum) -{ - *data = packet->buffer; - - if (len != NULL) - *len = packet->len; - - if (checksum != NULL) - *checksum = packet->checksum; - -} - - -/****************************************************************************** -* * -* Paramètres : list = liste de paquets à compléter. * -* item = paquet à ajouter à la liste. * -* * -* Description : Ajoute un paquet à une liste de paquets. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_gdb_packet_push(GGdbPacket **list, GGdbPacket *item) -{ - dl_list_push(item, list, GGdbPacket, link); - -} - - -/****************************************************************************** -* * -* Paramètres : list = liste de paquets à consulter. * -* * -* Description : Retire et fournit le premier élément d'une liste de paquets. * -* * -* Retour : Elément dépilé de la liste de paquets. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GGdbPacket *g_gdb_packet_pop(GGdbPacket **list) -{ - return dl_list_pop(list, GGdbPacket, link); - -} diff --git a/src/debug/gdbrsp/packet.h b/src/debug/gdbrsp/packet.h deleted file mode 100644 index 7f362bd..0000000 --- a/src/debug/gdbrsp/packet.h +++ /dev/null @@ -1,82 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * packet.h - prototypes pour la manipulation des paquets de données GDB. - * - * Copyright (C) 2009-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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _DEBUG_GDBRSP_PACKET_H -#define _DEBUG_GDBRSP_PACKET_H - - -#include <glib-object.h> -#include <stdbool.h> -#include <stdint.h> - - - -#define G_TYPE_GDB_PACKET g_gdb_packet_get_type() -#define G_GDB_PACKET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_gdb_packet_get_type(), GGdbPacket)) -#define G_IS_GDB_PACKET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_gdb_packet_get_type())) -#define G_GDB_PACKET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GDB_PACKET, GGdbPacketClass)) -#define G_IS_GDB_PACKET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GDB_PACKET)) -#define G_GDB_PACKET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_PACKET, GGdbPacketClass)) - - -/* Répresentation d'un paquet GDB (instance) */ -typedef struct _GGdbPacket GGdbPacket; - -/* Répresentation d'un paquet GDB (classe) */ -typedef struct _GGdbPacketClass GGdbPacketClass; - - - -/* Indique le type défini pour une répresentation de paquet GDB. */ -GType g_gdb_packet_get_type(void); - -/* Crée une représentation de paquet GDB. */ -GGdbPacket *g_gdb_packet_new(void); - -/* Prépare un paquet pour un envoi prochain. */ -void g_gdb_packet_start_new_command(GGdbPacket *); - -/* Complète un paquet pour un envoi prochain. */ -void g_gdb_packet_append(GGdbPacket *, const char *); - -/* Détermine l'empreinte des données d'un paquet GDB. */ -void g_gdb_packet_compute_checksum(GGdbPacket *); - -/* Contrôle l'intégrité des données d'un paquet GDB. */ -bool g_gdb_packet_verify_checksum(GGdbPacket *, uint8_t); - -/* Décode et/ou décompresse un paquet GDB. */ -bool g_gdb_packet_decode(GGdbPacket *); - -/* Fournit le contenu du paquet. */ -void g_gdb_packet_get_data(const GGdbPacket *, const char **, size_t *, uint8_t *); - -/* Ajoute un paquet à une liste de paquets. */ -void g_gdb_packet_push(GGdbPacket **, GGdbPacket *); - -/* Retire et fournit le premier élément d'une liste de paquets. */ -GGdbPacket *g_gdb_packet_pop(GGdbPacket **); - - - -#endif /* _DEBUG_GDBRSP_PACKET_H */ diff --git a/src/debug/gdbrsp/stream-int.h b/src/debug/gdbrsp/stream-int.h deleted file mode 100644 index ab26dc2..0000000 --- a/src/debug/gdbrsp/stream-int.h +++ /dev/null @@ -1,89 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * stream-int.h - prototypes internes pour la gestion des connexions aux serveurs GDB. - * - * Copyright (C) 2009-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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _DEBUG_GDBRSP_STREAM_INT_H -#define _DEBUG_GDBRSP_STREAM_INT_H - - -#include "gdb.h" -#include "stream.h" - - - -/* Envoie des données à un serveur GDB. */ -typedef bool (* send_gdb_data_fc) (GGdbStream *, const char *, size_t); - -/* Réceptionne un octet de donnée d'un serveur GDB. */ -typedef bool (* recv_gdb_byte_fc) (GGdbStream *, char *); - - -/* Flux de communication avec un serveur GDB (instance) */ -struct _GGdbStream -{ - GObject parent; /* A laisser en premier */ - - int fd; /* Flux ouvert en L./E. */ - - GGdbDebugger *owner; /* Propriétaire du flux */ - - send_gdb_data_fc send_data; /* Envoi d'un paquet GDB */ - recv_gdb_byte_fc recv_byte; /* Réception d'un paquet GDB */ - - GThread *listening; /* Thread pour les réceptions */ - - GGdbPacket *free_packets; /* Liste des disponibles */ - GMutex free_mutex; /* Accès à la liste */ - - GGdbPacket *recv_packets; /* Liste des paquets reçus */ - GCond recv_cond; /* Attente de disponibilité */ - GMutex recv_mutex; /* Accès à la liste */ - - GGdbPacket *status_packets; /* Liste des paquets d'état */ - GCond status_cond; /* Attente de disponibilité */ - GMutex status_mutex; /* Accès à la liste */ - - - - - bool skip_ack; - - bool want_status; - - -}; - - -/* Flux de communication avec un serveur GDB (classe) */ -struct _GGdbStreamClass -{ - GObjectClass parent; /* A laisser en premier */ - -}; - - -/* Lance l'écoute d'un flux de communication avec GDB. */ -bool g_gdb_stream_listen(GGdbStream *); - - - -#endif /* _DEBUG_GDBRSP_STREAM_INT_H */ diff --git a/src/debug/gdbrsp/stream.c b/src/debug/gdbrsp/stream.c deleted file mode 100644 index f86f630..0000000 --- a/src/debug/gdbrsp/stream.c +++ /dev/null @@ -1,696 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * stream.c - gestion des connexions aux serveurs GDB. - * - * Copyright (C) 2009-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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "stream.h" - - -#include <assert.h> -#include <stdio.h> -#include <stdlib.h> -#include <strings.h> -#include <glib/gthread.h> -#include <sys/select.h> - - -#include "gdb-int.h" -#include "stream-int.h" -#include "utils.h" -#include "../../common/dllist.h" -#include "../../core/logs.h" - - - -/* Initialise la classe des flux de communication avec GDB. */ -static void g_gdb_stream_class_init(GGdbStreamClass *); - -/* Initialise une instance de flux de communication avec GDB. */ -static void g_gdb_stream_init(GGdbStream *); - -/* Supprime toutes les références externes. */ -static void g_gdb_stream_dispose(GGdbStream *); - -/* Procède à la libération totale de la mémoire. */ -static void g_gdb_stream_finalize(GGdbStream *); - -/* Envoie un acquittement pour la dernière réception. */ -static bool gdb_stream_ack(GGdbStream *); - -/* Ecoute une connexion à un serveur GDB. */ -static void *gdb_stream_thread(GGdbStream *); - -/* Reste en alerte quant au changement de statut de l'exécution. */ -static void *gdb_stream_status_thread(GGdbStream *); - -/* Réceptionne un paquet d'un serveur GDB. */ -static bool g_gdb_stream_read_packet(GGdbStream *, GGdbPacket *); - - - -/* Indique le type défini pour un flux de communication avec un serveur GDB. */ -G_DEFINE_TYPE(GGdbStream, g_gdb_stream, G_TYPE_OBJECT); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des flux de communication avec GDB. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_stream_class_init(GGdbStreamClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - - object = G_OBJECT_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_gdb_stream_dispose; - object->finalize = (GObjectFinalizeFunc)g_gdb_stream_finalize; - -} - - -/****************************************************************************** -* * -* Paramètres : stream = instance à initialiser. * -* * -* Description : Initialise une instance de flux de communication avec GDB. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_stream_init(GGdbStream *stream) -{ - g_mutex_init(&stream->free_mutex); - - g_cond_init(&stream->recv_cond); - g_mutex_init(&stream->recv_mutex); - - g_cond_init(&stream->status_cond); - g_mutex_init(&stream->status_mutex); - - stream->skip_ack = false; - - stream->want_status = false; - -} - - -/****************************************************************************** -* * -* Paramètres : stream = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_stream_dispose(GGdbStream *stream) -{ - g_object_unref(G_OBJECT(stream->owner)); - - - /* TODO... */ - - - G_OBJECT_CLASS(g_gdb_stream_parent_class)->dispose(G_OBJECT(stream)); - -} - - -/****************************************************************************** -* * -* Paramètres : stream = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_stream_finalize(GGdbStream *stream) -{ - - /* TODO */ - - - G_OBJECT_CLASS(g_gdb_stream_parent_class)->finalize(G_OBJECT(stream)); - -} - - -/****************************************************************************** -* * -* Paramètres : stream = instance à modifier. * -* * -* Description : Ne participe plus aux acquitements de paquets. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_gdb_stream_do_not_ack(GGdbStream *stream) -{ - stream->skip_ack = true; - -} - - - -/****************************************************************************** -* * -* Paramètres : stream = instance à réellement lancer. * -* * -* Description : Lance l'écoute d'un flux de communication avec GDB. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_gdb_stream_listen(GGdbStream *stream) -{ - bool result; /* Bilan final à retourner */ - - result = true; - - if (!g_thread_new("chrysalide_gdb_stream", (GThreadFunc)gdb_stream_thread, stream)) - result = false; - - if (!g_thread_new("chrysalide_gdb_status", (GThreadFunc)gdb_stream_status_thread, stream)) - result = false; - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : stream = encadrement associée à l'opération. * -* * -* Description : Envoie un acquittement pour la dernière réception. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool gdb_stream_ack(GGdbStream *stream) -{ - /// - //return true; - - bool result; /* Bilan à retourner */ - GGdbPacket *packet; /* Paquet à envoyer */ - - packet = g_gdb_stream_get_free_packet(stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, "+"); - - result = g_gdb_stream_send_packet(stream, packet); - - g_gdb_stream_mark_packet_as_free(stream, packet); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : stream = encadrement associée à l'opération. * -* * -* Description : Ecoute une connexion à un serveur GDB. * -* * -* Retour : ??? * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void *gdb_stream_thread(GGdbStream *stream) -{ - fd_set rfds; /* Liste des flux à surveiller */ - int ret; /* Bilan d'un appel */ - GGdbPacket *packet; /* Nouveau paquet reçu */ - - - const char *data; /* Données reçues à analyser */ - size_t len; /* Quantité de ces données */ - - - - while (1) - { - FD_ZERO(&rfds); - FD_SET(stream->fd, &rfds); - - ret = select(stream->fd + 1, &rfds, NULL, NULL, NULL); - - switch (ret) - { - case -1: - perror("select()"); - break; - - case 0: - break; - - default: - - packet = g_gdb_stream_get_free_packet(stream); - - g_gdb_packet_start_new_command(packet); - - if (g_gdb_stream_read_packet(stream, packet)) - { - /* Acquittement ? */ - if (!stream->skip_ack) - { - if (!gdb_stream_ack(stream)) goto bad_recv; - } - - - /* On conserve le résultat ? */ - - - g_gdb_packet_get_data(packet, &data, &len, NULL); - - - //printf("---------------------------\n"); - //printf(">> want status ? %d\n", stream->want_status); - //printf(">> got '%s'\n", data); - - - if (len >= 1) - { - if (stream->want_status) - stream->want_status = false; - - else if (index("STWX", data[0]) != NULL) - { - g_mutex_lock(&stream->status_mutex); - g_gdb_packet_push(&stream->status_packets, packet); - g_mutex_unlock(&stream->status_mutex); - - g_cond_signal(&stream->status_cond); - - break; - } - - // else message inconnu -> log_message() ! - - } - - - - - g_mutex_lock(&stream->recv_mutex); - g_gdb_packet_push(&stream->recv_packets, packet); - g_mutex_unlock(&stream->recv_mutex); - - g_cond_signal(&stream->recv_cond); - - } - - else - g_gdb_stream_mark_packet_as_free(stream, packet); - - break; - - bad_recv: - - printf("bad things happend...\n"); - - g_gdb_stream_mark_packet_as_free(stream, packet); - - break; - - } - - } - - - printf("Oh noes....\n"); - - - return NULL; - -} - - -/****************************************************************************** -* * -* Paramètres : stream = encadrement associée à l'opération. * -* * -* Description : Reste en alerte quant au changement de statut de l'exécution.* -* * -* Retour : ??? * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void *gdb_stream_status_thread(GGdbStream *stream) -{ - GGdbPacket *packet; /* Nouveau paquet reçu */ - const char *data; /* Données reçues à analyser */ - size_t len; /* Quantité de ces données */ - bool malformed; /* Echec d'interprétation */ - uint8_t byte; /* Valeur quelconque sur 8 bits*/ - bool ret; /* Bilan d'un appel */ - - while (1) - { - /* Réception d'un nouveau paquet de statut */ - - g_mutex_lock(&stream->status_mutex); - - if (dl_list_empty(stream->status_packets)) - g_cond_wait(&stream->status_cond, &stream->status_mutex); - - packet = g_gdb_packet_pop(&stream->status_packets); - - g_mutex_unlock(&stream->status_mutex); - - /* Traitement du paquet reçu */ - - g_gdb_packet_get_data(packet, &data, &len, NULL); - - malformed = false; - - switch (data[0]) - { - case 'S': - - ret = read_fixed_byte(data + 1, len - 1, &byte); - - if (!ret) - { - malformed = true; - goto gsst_processed; - } - - g_gdb_debugger_receive_signal_reply(stream->owner, byte); - break; - - case 'T': - assert(false); // TODO - break; - - case 'W': - - ret = read_fixed_byte(data + 1, len - 1, &byte); - - if (!ret) - { - malformed = true; - goto gsst_processed; - } - - - // TODO : ";process:pid" - - - printf("Program exited (status=%hhu)\n", byte); - - - g_gdb_debugger_receive_exit_reply(stream->owner, byte, -1); - - - // log_message en cas de mauvais format... - - - break; - - - default: - assert(false); - break; - - } - - gsst_processed: - - if (malformed && true/* TODO : config->show_... */) - log_variadic_message(LMT_WARNING, "Malformed GDB status reply: '%s'", data); - - g_gdb_stream_mark_packet_as_free(stream, packet); - - } - - return NULL; - -} - - -/****************************************************************************** -* * -* Paramètres : stream = flux de communication avec GDB à consulter. * -* * -* Description : Fournit un paquet prêt à emploi. * -* * -* Retour : Paquet prêt à emploi. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GGdbPacket *g_gdb_stream_get_free_packet(GGdbStream *stream) -{ - GGdbPacket *result; /* Paquet à retourner */ - - g_mutex_lock(&stream->free_mutex); - - if (dl_list_empty(stream->free_packets)) - result = g_gdb_packet_new(); - - else - result = g_gdb_packet_pop(&stream->free_packets); - - g_mutex_unlock(&stream->free_mutex); - - // ??? - //g_gdb_packet_start_new_command(result); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : stream = flux de communication avec GDB à mettre à jour. * -* packet = paquet à considérer comme disponible. * -* * -* Description : Place un paquet en attente d'une future utilisation. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -void g_gdb_stream_mark_packet_as_free(GGdbStream *stream, GGdbPacket *packet) -{ - //// Utile ? - g_gdb_packet_start_new_command(packet); - - - g_mutex_lock(&stream->free_mutex); - - g_gdb_packet_push(&stream->free_packets, packet); - - g_mutex_unlock(&stream->free_mutex); - -} - - -/****************************************************************************** -* * -* Paramètres : stream = flux ouvert en lecture à utiliser. * -* packet = données à recevoir. * -* * -* Description : Réceptionne un paquet d'un serveur GDB. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_stream_read_packet(GGdbStream *stream, GGdbPacket *packet) -{ - bool result; /* Bilan à renvoyer */ - char tmp[3]; /* Tampon de réception */ - uint8_t checksum; /* Contrôle d'intégrité */ - - do - { - result = stream->recv_byte(stream, tmp); - if (tmp[0] != '+') break; - } - while (0); - - if (tmp[0] != '$') return false; - - tmp[1] = '\0'; - - while ((result = stream->recv_byte(stream, tmp))) - { - //printf(" .. '%c'\n", tmp[0]); - - if (tmp[0] == '#') break; - else g_gdb_packet_append(packet, tmp); - } - - if (result) - { - result = stream->recv_byte(stream, &tmp[0]); - result &= stream->recv_byte(stream, &tmp[1]); - - tmp[2] = 0; - checksum = strtol(tmp, NULL, 16); - - } - - if (result) - result = g_gdb_packet_verify_checksum(packet, checksum); - - if (result) - result = g_gdb_packet_decode(packet); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : stream = flux ouvert en écriture à mettre à jour. * -* packet = données à transmettre. * -* * -* Description : Envoie un paquet à un serveur GDB. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ -#include <string.h> -bool g_gdb_stream_send_packet(GGdbStream *stream, GGdbPacket *packet) -{ - bool result; /* Bilan à renvoyer */ - const char *data; /* Données à envoyer */ - size_t len; /* Quantité de ces données */ - uint8_t checksum; /* Contrôle d'intégrité */ - char tmp[3]; /* Impression du checksum */ - - g_gdb_packet_get_data(packet, &data, &len, NULL); - -#if 1 - /* Ack ? */ - if (len == 1 && data[0] == '+') - result = stream->send_data(stream, "+", 1); - - else -#endif - { - - result = stream->send_data(stream, "$", 1); - //result = stream->send_data(stream, "+$", 2); - - g_gdb_packet_compute_checksum(packet); - g_gdb_packet_get_data(packet, &data, &len, &checksum); - - - if (len == 1 && data[0] == '?') - stream->want_status = true; - - /* - if (memcmp(data, "vCont;c", strlen("vCont;c")) == 0) - stream->want_status = true; - */ - - - - result &= stream->send_data(stream, data, len); - - result = stream->send_data(stream, "#", 1); - - snprintf(tmp, 3, "%02hhx", checksum); - result &= stream->send_data(stream, tmp, 2); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : stream = flux de communication avec GDB à consulter. * -* * -* Description : Fournit un paquet reçu d'un serveur GDB. * -* * -* Retour : Paquet GDB. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GGdbPacket *g_gdb_stream_recv_packet(GGdbStream *stream) -{ - GGdbPacket *result; /* Paquet à retourner */ - - g_mutex_lock(&stream->recv_mutex); - - if (dl_list_empty(stream->recv_packets)) - g_cond_wait(&stream->recv_cond, &stream->recv_mutex); - - result = g_gdb_packet_pop(&stream->recv_packets); - - g_mutex_unlock(&stream->recv_mutex); - - return result; - -} diff --git a/src/debug/gdbrsp/stream.h b/src/debug/gdbrsp/stream.h deleted file mode 100644 index a64485a..0000000 --- a/src/debug/gdbrsp/stream.h +++ /dev/null @@ -1,68 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * stream.h - prototypes pour la gestion des connexions aux serveurs GDB. - * - * Copyright (C) 2009-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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _DEBUG_GDBRSP_STREAM_H -#define _DEBUG_GDBRSP_STREAM_H - - -#include "packet.h" - - - -#define G_TYPE_GDB_STREAM g_gdb_stream_get_type() -#define G_GDB_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_gdb_stream_get_type(), GGdbStream)) -#define G_IS_GDB_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_gdb_stream_get_type())) -#define G_GDB_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GDB_STREAM, GGdbStreamClass)) -#define G_IS_GDB_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GDB_STREAM)) -#define G_GDB_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_STREAM, GGdbStreamClass)) - - -/* Flux de communication avec un serveur GDB (instance) */ -typedef struct _GGdbStream GGdbStream; - -/* Flux de communication avec un serveur GDB (classe) */ -typedef struct _GGdbStreamClass GGdbStreamClass; - - - -/* Indique le type défini pour un flux de communication avec un serveur GDB. */ -GType g_gdb_stream_get_type(void); - -/* Ne participe plus aux acquitements de paquets. */ -void g_gdb_stream_do_not_ack(GGdbStream *); - -/* Fournit un paquet prêt à emploi. */ -GGdbPacket *g_gdb_stream_get_free_packet(GGdbStream *); - -/* Place un paquet en attente d'une future utilisation. */ -void g_gdb_stream_mark_packet_as_free(GGdbStream *, GGdbPacket *); - -/* Envoie un paquet à un serveur GDB. */ -bool g_gdb_stream_send_packet(GGdbStream *, GGdbPacket *); - -/* Fournit un paquet reçu d'un serveur GDB. */ -GGdbPacket *g_gdb_stream_recv_packet(GGdbStream *); - - - -#endif /* _DEBUG_GDBRSP_STREAM_H */ diff --git a/src/debug/gdbrsp/support.c b/src/debug/gdbrsp/support.c deleted file mode 100644 index 3d27c06..0000000 --- a/src/debug/gdbrsp/support.c +++ /dev/null @@ -1,598 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * support.c - conformité dans l'interfaçage client/serveur - * - * Copyright (C) 2016 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 <http://www.gnu.org/licenses/>. - */ - - -#include "support.h" - - -#include <stdlib.h> -#include <string.h> - - - -/* Indications quant à l'interfaçage client/serveur GDB (instance) */ -struct _GGdbSupport -{ - GObject parent; /* A laisser en premier */ - - unsigned long packet_size; /* Taille maximale d'un paquet */ - - bool os_data; - - - bool extended_mode; /* Mode étendu présent & actif */ - - - char *id; - -}; - -/* Indications quant à l'interfaçage client/serveur GDB (classe) */ -struct _GGdbSupportClass -{ - GObjectClass parent; /* A laisser en premier */ - -}; - - -/* Initialise la classe des détails d'interfaçage GDB. */ -static void g_gdb_support_class_init(GGdbSupportClass *); - -/* Procède à l'initialisation des détails d'interfaçage GDB. */ -static void g_gdb_support_init(GGdbSupport *); - -/* Supprime toutes les références externes. */ -static void g_gdb_support_dispose(GGdbSupport *); - -/* Procède à la libération totale de la mémoire. */ -static void g_gdb_support_finalize(GGdbSupport *); - -/* Lit une valeur booléenne à partir des détails du serveur. */ -static bool g_gdb_support_read_bool(GGdbSupport *, const char *, const char *, bool *); - -/* Lit une valeur longue à partir des détails du serveur. */ -static bool g_gdb_support_read_ulong(GGdbSupport *, const char *, const char *, unsigned long *); - - - -/* Indique le type défini par la GLib pour les détails d'interfaçage GDB. */ -G_DEFINE_TYPE(GGdbSupport, g_gdb_support, G_TYPE_OBJECT); - - -/****************************************************************************** -* * -* Paramètres : klass = classe de débogueur à initialiser. * -* * -* Description : Initialise la classe des détails d'interfaçage GDB. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_support_class_init(GGdbSupportClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - - object = G_OBJECT_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_gdb_support_dispose; - object->finalize = (GObjectFinalizeFunc)g_gdb_support_finalize; - -} - - -/****************************************************************************** -* * -* Paramètres : support = instance de débogueur à préparer. * -* * -* Description : Procède à l'initialisation des détails d'interfaçage GDB. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_support_init(GGdbSupport *support) -{ - -} - - -/****************************************************************************** -* * -* Paramètres : support = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_support_dispose(GGdbSupport *support) -{ - G_OBJECT_CLASS(g_gdb_support_parent_class)->dispose(G_OBJECT(support)); - -} - - -/****************************************************************************** -* * -* Paramètres : support = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_support_finalize(GGdbSupport *support) -{ - G_OBJECT_CLASS(g_gdb_support_parent_class)->finalize(G_OBJECT(support)); - -} - - - - - - - - - - - - - - -#include <string.h> - -static char *build_id(GGdbStream *stream) -{ - char *result; /* Identifiant à renvoyer */ - GGdbPacket *packet; /* Paquet de communication */ - bool status; /* Bilan d'une communication */ - const char *data; /* Données reçues à analyser */ - const char *start; /* Début d'identification */ - const char *end; /* Fin d'identification */ - - result = NULL; - - /* Envoi de la requête */ - - packet = g_gdb_stream_get_free_packet(stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, "?"); - - status = g_gdb_stream_send_packet(stream, packet); - - if (!status) - goto ggdgat_exit; - - /* Réception de la réponse */ - - packet = g_gdb_stream_recv_packet(stream); - - g_gdb_packet_get_data(packet, &data, NULL, NULL); - - start = strstr(data, "thread:"); - if (start == NULL) goto ggdgat_exit; - - start += sizeof("thread:") - 1 /* '\0' */; - - end = strstr(start, ";"); - if (end == NULL) goto ggdgat_exit; - - result = strndup(start, end - start); - - ggdgat_exit: - - g_gdb_stream_mark_packet_as_free(stream, packet); - - return result; - -} - - - - - - - -/****************************************************************************** -* * -* Paramètres : stream = flux de communication ouvert avec le débogueur. * -* * -* Description : Crée une définition des détails d'interfaçage GDB. * -* * -* Retour : Instance de détails mise en place ou NULL. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GGdbSupport *g_gdb_support_new(GGdbStream *stream) -{ - GGdbSupport *result; /* Débogueur à retourner */ - GGdbPacket *packet; /* Paquet de communication GDB */ - - - //goto end; - - //goto skip; - - packet = g_gdb_stream_get_free_packet(stream); - - g_gdb_packet_start_new_command(packet); - //g_gdb_packet_append(packet, "qSupported:multiprocess+;xmlRegisters"); - g_gdb_packet_append(packet, "qSupported"); - - g_gdb_packet_append(packet, "qSupported:multiprocess+;swbreak+;hwbreak+;qRelocInsn+;fork-events+;vfork-events+;exec-events+;vContSupported+;QThreadEvents+;no-resumed+"); - - - bool test; - - const char *data; /* Données reçues à analyser */ - size_t len; - - test = g_gdb_stream_send_packet(stream, packet); - - - - printf(" >> Paquet '%s' bien envoyé ? %s\n", "qSupported", test ? "oui" : "non"); - - - - g_gdb_stream_mark_packet_as_free(stream, packet); - - packet = g_gdb_stream_recv_packet(stream); - - g_gdb_packet_get_data(packet, &data, &len, NULL); - - printf(" << Réception de '%s'\n", data); - - - - - result = g_object_new(G_TYPE_GDB_SUPPORT, NULL); - - - - /* Découpage des éléments de réponse */ - - char *answer; /* Réponse modifiable */ - char *save; /* Sauvegarde de position */ - char *token; /* Elément de réponse cerné */ - - answer = strdup(data); - - for (token = strtok_r(answer, ";", &save); - token != NULL; - token = strtok_r(NULL, ";", &save)) - { - - - printf("TOKEN :: %s\n", token); - - if (g_gdb_support_read_ulong(result, token, "PacketSize", &result->packet_size)) - continue; - - if (g_gdb_support_read_bool(result, token, "qXfer:osdata:read", &result->os_data)) - { - printf(" -->> %d\n", result->os_data); - continue; - } - - - - - } - - free(answer); - - - - /** - * Première chose : plus d'acquitement ! - * - * Dans les faits, c'est impossible à gérer en asynchrone. Par exemple : - * - * C> vCont;c - * C> g Txx... <S - * - * Si le client envoie une commande en même temps que le serveur envoie - * quelque chose, le serveur attend dans tous les cas un acquitement. - * Donc il va consommer les données envoyées par le client jusqu'à y - * trouver ce qu'il cherche. - */ - - /* Envoi de la requête */ - - packet = g_gdb_stream_get_free_packet(stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, "QStartNoAckMode"); - - test = g_gdb_stream_send_packet(stream, packet); - - g_gdb_stream_mark_packet_as_free(stream, packet); - - if (!test) - goto ggsn_error; - - /* Réception de la réponse */ - - packet = g_gdb_stream_recv_packet(stream); - - g_gdb_packet_get_data(packet, &data, NULL, NULL); - - if (strcmp(data, "OK") != 0) - goto ggsn_error; - - g_gdb_stream_mark_packet_as_free(stream, packet); - - /* Désactivation des acquitements */ - - g_gdb_stream_do_not_ack(stream); - - /** - * Passage en mode étendu. C'est obligatoire pour pouvoir redémarrer un - * programme débogué. - */ - - /* Envoi de la requête */ - - packet = g_gdb_stream_get_free_packet(stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, "!"); - - test = g_gdb_stream_send_packet(stream, packet); - - g_gdb_stream_mark_packet_as_free(stream, packet); - - if (!test) - goto ggsn_error; - - /* Réception de la réponse */ - - packet = g_gdb_stream_recv_packet(stream); - - g_gdb_packet_get_data(packet, &data, NULL, NULL); - - result->extended_mode = (strcmp(data, "OK") == 0); - - g_gdb_stream_mark_packet_as_free(stream, packet); - - - - - result->id = build_id(stream); - - - -#if 0 - //end: - -#define CMD "?" - - - packet = g_gdb_stream_get_free_packet(stream); - - g_gdb_packet_start_new_command(packet); - //g_gdb_packet_append(packet, "qSupported:multiprocess+;xmlRegisters"); - g_gdb_packet_append(packet, CMD); - - - test = g_gdb_stream_send_packet(stream, packet); - - - - printf(" >> Paquet '%s' bien envoyé ? %s\n", CMD, test ? "oui" : "non"); - - - - g_gdb_stream_mark_packet_as_free(stream, packet); - - packet = g_gdb_stream_recv_packet(stream); - - g_gdb_packet_get_data(packet, &data, &len, NULL); - - printf(" << [pkt = %p ] Réception de '%s' (len=%d)\n", packet, data, (int)len); - - -#endif - - - - // qfThreadInfo - - -#undef CMD - - //#define CMD "qXfer:threads:read::0,1fff" - //#define CMD "qXfer:btrace:read:all:0,1fff" - //#define CMD "g" - //#define CMD "m400000,8" -#define CMD "qsThreadInfo" - - packet = g_gdb_stream_get_free_packet(stream); - - g_gdb_packet_start_new_command(packet); - //g_gdb_packet_append(packet, "qSupported:multiprocess+;xmlRegisters"); - g_gdb_packet_append(packet, CMD); - - - test = g_gdb_stream_send_packet(stream, packet); - - - - printf(" >> Paquet '%s' bien envoyé ? %s\n", CMD, test ? "oui" : "non"); - - - - g_gdb_stream_mark_packet_as_free(stream, packet); - - packet = g_gdb_stream_recv_packet(stream); - - g_gdb_packet_get_data(packet, &data, &len, NULL); - - printf(" << [pkt = %p ] Réception de '%s' (len=%d)\n", packet, data, (int)len); - - - - - - - - - - - - return result; - - ggsn_error: - - - - return NULL; - -} - - -/****************************************************************************** -* * -* Paramètres : support = ensemble de détails à préciser. * -* raw = données brutes à parcourir. * -* name = désignation de la valeur recherchée. * -* value = emplacement de la valeur à inscrire. * -* * -* Description : Lit une valeur booléenne à partir des détails du serveur. * -* * -* Retour : true en cas d'affectation, false dans tous les autres cas. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_support_read_bool(GGdbSupport *support, const char *raw, const char *name, bool *value) -{ - bool result; /* Bilan à retourner */ - size_t rlen; /* Taille de l'ensemble */ - size_t nlen; /* Taille du nom */ - - rlen = strlen(raw); - nlen = strlen(name); - - if ((nlen + 1) != rlen) - return false; - - if (strncmp(raw, name, nlen) != 0) - return false; - - switch (raw[nlen]) - { - case '+': - *value = true; - result = true; - break; - - case '-': - case '?': - *value = false; - result = true; - break; - - default: - result = false; - break; - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : support = ensemble de détails à préciser. * -* raw = données brutes à parcourir. * -* name = désignation de la valeur recherchée. * -* value = emplacement de la valeur à inscrire. * -* * -* Description : Lit une valeur longue à partir des détails du serveur. * -* * -* Retour : true en cas d'affectation, false dans tous les autres cas. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_support_read_ulong(GGdbSupport *support, const char *raw, const char *name, unsigned long *value) -{ - size_t rlen; /* Taille de l'ensemble */ - size_t nlen; /* Taille du nom */ - unsigned long v; /* Valeur récupérée à assigner */ - - rlen = strlen(raw); - nlen = strlen(name); - - if (strncmp(raw, name, nlen) != 0) - return false; - - if (raw[nlen] != '=') - return false; - - v = strtoul(raw + nlen + 1, NULL, 16); - - if (v == ULONG_MAX/* && errno == ERANGE*/) - return false; - - *value = v; - - return true; - -} - - - - - - -char *g_gdb_support_get_id(const GGdbSupport *support) -{ - return support->id; - -} - - - - - diff --git a/src/debug/gdbrsp/support.h b/src/debug/gdbrsp/support.h deleted file mode 100644 index 2f6259c..0000000 --- a/src/debug/gdbrsp/support.h +++ /dev/null @@ -1,73 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * support.h - prototypes pour la conformité dans l'interfaçage client/serveur - * - * Copyright (C) 2016 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 <http://www.gnu.org/licenses/>. - */ - - -#ifndef _DEBUG_GDBRSP_SUPPORT_H -#define _DEBUG_GDBRSP_SUPPORT_H - - -#include <glib-object.h> -#include <stdbool.h> - - -#include "stream.h" - - - -#define G_TYPE_GDB_SUPPORT (g_gdb_support_get_type()) -#define G_GDB_SUPPORT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_GDB_SUPPORT, GGdbSupport)) -#define G_IS_GDB_SUPPORT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_GDB_SUPPORT)) -#define G_GDB_SUPPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GDB_SUPPORT, GGdbSupportClass)) -#define G_IS_GDB_SUPPORT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GDB_SUPPORT)) -#define G_GDB_SUPPORT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_SUPPORT, GGdbSupportClass)) - - -/* Indications quant à l'interfaçage client/serveur GDB (instance) */ -typedef struct _GGdbSupport GGdbSupport; - -/* Indications quant à l'interfaçage client/serveur GDB (classe) */ -typedef struct _GGdbSupportClass GGdbSupportClass; - - -/* Indique le type défini par la GLib pour les détails d'interfaçage GDB. */ -GType g_gdb_support_get_type(void); - -/* Crée une définition des détails d'interfaçage GDB. */ -GGdbSupport *g_gdb_support_new(GGdbStream *); - - - - - - - -char *g_gdb_support_get_id(const GGdbSupport *support); - - - - - - - - - -#endif /* _DEBUG_GDBRSP_SUPPORT_H */ diff --git a/src/debug/gdbrsp/target.c b/src/debug/gdbrsp/target.c deleted file mode 100644 index cf28a49..0000000 --- a/src/debug/gdbrsp/target.c +++ /dev/null @@ -1,950 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * target.c - gestion des éléments propres à l'architecture reconnue par GDB - * - * Copyright (C) 2016 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 <http://www.gnu.org/licenses/>. - */ - - -#include "target.h" - - -#include <assert.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - - -#include "utils.h" -#include "../../common/cpp.h" -#include "../../common/extstr.h" -#include "../../common/xml.h" - - - -/* Définitions de registres */ - -typedef struct _arch_register_t -{ - char *name; /* Nom de registre */ - unsigned int size; /* Taille en bits */ - -} arch_register_t; - -typedef struct _target_cpu_t -{ - char *label; /* Désignation de l'ensemble */ - - arch_register_t *regs; /* Définition des registres */ - unsigned int count; /* Quantité de ces définitions */ - -} target_cpu_t; - - -/* Indications quant à l'interfaçage client/serveur GDB (instance) */ -struct _GGdbTarget -{ - GObject parent; /* A laisser en premier */ - - target_cpu_t **defs; /* Liste de définitions */ - size_t count; /* Taille de cette même liste */ - - bool read_single_register; /* Lecture spécifique permise ?*/ - bool write_single_register; /* Ecriture spécifique valide ?*/ - -}; - -/* Indications quant à l'interfaçage client/serveur GDB (classe) */ -struct _GGdbTargetClass -{ - GObjectClass parent; /* A laisser en premier */ - -}; - - -/* Initialise la classe des détails d'interfaçage GDB. */ -static void g_gdb_target_class_init(GGdbTargetClass *); - -/* Procède à l'initialisation des détails d'interfaçage GDB. */ -static void g_gdb_target_init(GGdbTarget *); - -/* Supprime toutes les références externes. */ -static void g_gdb_target_dispose(GGdbTarget *); - -/* Procède à la libération totale de la mémoire. */ -static void g_gdb_target_finalize(GGdbTarget *); - -/* Charge la définition d'un groupe de registres. */ -static bool g_gdb_target_load_register_definition(GGdbTarget *, GGdbStream *, const char *); - -/* Recherche l'indice correspondant à un registre donné. */ -static bool g_gdb_target_find_register_index(const GGdbTarget *, const char *, unsigned int *); - -/* Recherche la position correspondant à un registre donné. */ -static bool g_gdb_target_find_register_offset(const GGdbTarget *, unsigned int, size_t *); - - - -/* Indique le type défini par la GLib pour les détails d'interfaçage GDB. */ -G_DEFINE_TYPE(GGdbTarget, g_gdb_target, G_TYPE_OBJECT); - - -/****************************************************************************** -* * -* Paramètres : klass = classe de débogueur à initialiser. * -* * -* Description : Initialise la classe des détails d'interfaçage GDB. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_target_class_init(GGdbTargetClass *klass) -{ - GObjectClass *object; /* Autre version de la classe */ - - object = G_OBJECT_CLASS(klass); - - object->dispose = (GObjectFinalizeFunc/* ! */)g_gdb_target_dispose; - object->finalize = (GObjectFinalizeFunc)g_gdb_target_finalize; - -} - - -/****************************************************************************** -* * -* Paramètres : target = instance de débogueur à préparer. * -* * -* Description : Procède à l'initialisation des détails d'interfaçage GDB. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_target_init(GGdbTarget *target) -{ - target->defs = NULL; - target->count = 0; - - target->read_single_register = true; - target->write_single_register = true; - -} - - -/****************************************************************************** -* * -* Paramètres : target = instance d'objet GLib à traiter. * -* * -* Description : Supprime toutes les références externes. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_target_dispose(GGdbTarget *target) -{ - G_OBJECT_CLASS(g_gdb_target_parent_class)->dispose(G_OBJECT(target)); - -} - - -/****************************************************************************** -* * -* Paramètres : target = instance d'objet GLib à traiter. * -* * -* Description : Procède à la libération totale de la mémoire. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_target_finalize(GGdbTarget *target) -{ - G_OBJECT_CLASS(g_gdb_target_parent_class)->finalize(G_OBJECT(target)); - -} - - -/****************************************************************************** -* * -* Paramètres : stream = flux de communication ouvert avec le débogueur. * -* * -* Description : Crée une définition des détails d'interfaçage GDB. * -* * -* Retour : Instance de détails mise en place ou NULL. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GGdbTarget *g_gdb_target_new(GGdbStream *stream) -{ - GGdbTarget *result; /* Débogueur à retourner */ - GGdbPacket *packet; /* Paquet de communication GDB */ - bool status; /* Bilan d'une communication */ - - const char *data; /* Données reçues du serveur */ - size_t len; /* Quantité de ces données */ - char *xmldata; /* Données modifiables */ - xmlDocPtr xdoc; /* Document XML récupéré */ - xmlXPathContextPtr context; /* Contexte d'analyse associé */ - xmlXPathObjectPtr xobject; /* Cible d'une recherche */ - unsigned int i; /* Boucle de parcours */ - char *access; /* Chemin d'accès à un élément */ - char *xmlref; /* Référence de définitions */ - - - - - result = NULL; - - - //goto end; - - //goto skip; - - - packet = g_gdb_stream_get_free_packet(stream); - - g_gdb_packet_start_new_command(packet); - //g_gdb_packet_append(packet, "qTargeted:multiprocess+;xmlRegisters"); - g_gdb_packet_append(packet, "qXfer:features:read:target.xml:0,3fff"); - - //g_gdb_packet_append(packet, "qTargeted:multiprocess+;swbreak+;hwbreak+;qRelocInsn+;fork-events+;vfork-events+;exec-events+;vContTargeted+;QThreadEvents+;no-resumed+"); - - - - status = g_gdb_stream_send_packet(stream, packet); - if (!status) goto ggtn_failed; - - - - - g_gdb_stream_mark_packet_as_free(stream, packet); - - packet = g_gdb_stream_recv_packet(stream); - - g_gdb_packet_get_data(packet, &data, &len, NULL); - - printf(" << Réception de '%s'\n", data); - - /* Marqueur de fin placé au début ?! */ - if (data[0] != 'l') - goto ggtn_failed; - - xmldata = strdup(data + 1); - - /** - * On cherche à éviter la déconvenue suivante avec la libxml2 : - * - * noname.xml:12: namespace error : Namespace prefix xi on include is not defined - * <xi:include href="aarch64-core.xml"/> - */ - - xmldata = strrpl(xmldata, "xi:include", "include"); - - if (!load_xml_from_memory(xmldata, len - 1, &xdoc, &context)) - goto ggtn_failed; - - - result = g_object_new(G_TYPE_GDB_TARGET, NULL); - - - xobject = get_node_xpath_object(context, "/target/include"); - - for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++) - { - asprintf(&access, "/target/include[position()=%u]", i + 1); - - xmlref = get_node_prop_value(context, access, "href"); - - free(access); - - if (xmlref != NULL) - { - printf("REF>> %s\n", xmlref); - /*static bool */g_gdb_target_load_register_definition(result, stream, xmlref); - - free(xmlref); - - } - - } - - if(xobject != NULL) - xmlXPathFreeObject(xobject); - - close_xml_file(xdoc, context); - - free(xmldata); - - - - - - - - - - - //result = g_object_new(G_TYPE_GDB_TARGET, NULL); - - - ggtn_failed: - - g_gdb_stream_mark_packet_as_free(stream, packet); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : target = ensemble d'informations liées à l'architecture. * -* stream = flux de communication ouvert avec le débogueur. * -* name = désignation des définitions de registres à charger. * -* * -* Description : Charge la définition d'un groupe de registres. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_target_load_register_definition(GGdbTarget *target, GGdbStream *stream, const char *name) -{ - bool result; /* Bilan à retourner */ - GGdbPacket *packet; /* Paquet de communication GDB */ - bool status; /* Bilan d'une communication */ - const char *data; /* Données reçues du serveur */ - size_t len; /* Quantité de ces données */ - xmlDocPtr xdoc; /* Document XML récupéré */ - xmlXPathContextPtr context; /* Contexte d'analyse associé */ - xmlXPathObjectPtr xobject; /* Cible d'une recherche */ - target_cpu_t *def; /* Nouvelle définition à lire */ - unsigned int i; /* Boucle de parcours */ - char *access; /* Chemin d'accès à un élément */ - char *type; /* Espèce de définition */ - - result = false; - - /* Envoi de la requête */ - - packet = g_gdb_stream_get_free_packet(stream); - - g_gdb_packet_start_new_command(packet); - - g_gdb_packet_append(packet, "qXfer:features:read:"); - g_gdb_packet_append(packet, name); - g_gdb_packet_append(packet, ":0,3fff"); - - status = g_gdb_stream_send_packet(stream, packet); - if (!status) goto ggtlrd_failed; - - g_gdb_stream_mark_packet_as_free(stream, packet); - - /* Réception de la réponse */ - - packet = g_gdb_stream_recv_packet(stream); - - g_gdb_packet_get_data(packet, &data, &len, NULL); - - //printf(">>>> '%s'\n", data); - - /* Marqueur de fin placé au début ?! */ - if (data[0] != 'l') - goto ggtlrd_failed; - - if (!load_xml_from_memory(data + 1, len - 1, &xdoc, &context)) - goto ggtlrd_failed; - - /* Chargement des définitions */ - - xobject = get_node_xpath_object(context, "/feature/*"); - - def = (target_cpu_t *)calloc(1, sizeof(target_cpu_t)); - - def->count = XPATH_OBJ_NODES_COUNT(xobject); - def->regs = (arch_register_t *)calloc(def->count, sizeof(arch_register_t)); - - for (i = 0; i < XPATH_OBJ_NODES_COUNT(xobject); i++) - { - asprintf(&access, "/feature/*[position()=%u]", i + 1); - - type = get_node_name(context, access); - - if (strcmp(type, "reg") == 0) - { - def->regs[i].name = get_node_prop_value(context, access, "name"); - def->regs[i].size = atoi(get_node_prop_value(context, access, "bitsize")); - - //printf("load reg '%s' (%u)\n", def->regs[i].name, def->regs[i].size); - - } - - free(type); - - free(access); - - } - - if(xobject != NULL) - xmlXPathFreeObject(xobject); - - close_xml_file(xdoc, context); - - /* Intégration finale */ - - target->defs = (target_cpu_t **)realloc(target->defs, ++target->count * sizeof(target_cpu_t *)); - - target->defs[target->count - 1] = def; - - ggtlrd_failed: - - g_gdb_stream_mark_packet_as_free(stream, packet); - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : target = ensemble d'informations liées à l'architecture. * -* group = éventuel groupe de registres ciblé ou NULL. * -* count = nombre d'éléments dans la liste de noms. [OUT] * -* * -* Description : Liste l'ensemble des registres appartenant à un groupe. * -* * -* Retour : Liste de noms à libérer de la mémoire après utilisation. * -* * -* Remarques : - * -* * -******************************************************************************/ - -char **g_gdb_target_get_register_names(const GGdbTarget *target, const char *group, size_t *count) -{ - char **result; /* Désignations à retourner */ - unsigned int i; /* Boucle de parcours #1 */ - const target_cpu_t *rgrp; /* Groupe de registres */ - unsigned int j; /* Boucle de parcours #2 */ - - result = NULL; - - for (i = 0; i < target->count && result == NULL; i++) - { - rgrp = target->defs[i]; - - if (group != NULL) - { - if (strcmp(rgrp->label, group) != 0) - continue; - } - - *count = rgrp->count; - - result = (char **)calloc(*count, sizeof(char *)); - - for (j = 0; j < *count; j++) - result[j] = strdup(rgrp->regs[j].name); - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : target = ensemble d'informations liées à l'architecture. * -* name = désignation du registre visé. * -* * -* Description : Indique la taille associée à un registre donné. * -* * -* Retour : Taille en bits, ou 0 si le registre n'a pas été trouvé. * -* * -* Remarques : - * -* * -******************************************************************************/ - -unsigned int g_gdb_target_get_register_size(const GGdbTarget *target, const char *name) -{ - unsigned int result; /* Taille en bits à retourner */ - unsigned int i; /* Boucle de parcours #1 */ - const target_cpu_t *rgrp; /* Groupe de registres */ - unsigned int j; /* Boucle de parcours #2 */ - - result = 0; - - for (i = 0; i < target->count && result == 0; i++) - { - rgrp = target->defs[i]; - - for (j = 0; j < rgrp->count; j++) - if (strcmp(rgrp->regs[j].name, name) == 0) - result = rgrp->regs[j].size; - - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : target = ensemble d'informations liées à l'architecture. * -* reg = désignation humaine du register à consulter. * -* index = indice correspondant au registre pour GDB. [OUT] * -* * -* Description : Recherche l'indice correspondant à un registre donné. * -* * -* Retour : Bilan de l'opération : trouvaille ou échec ? * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_target_find_register_index(const GGdbTarget *target, const char *reg, unsigned int *index) -{ - bool result; /* Bilan à retourner */ - unsigned int i; /* Boucle de parcours #1 */ - unsigned int j; /* Boucle de parcours #2 */ - - result = false; - - *index = 0; - - for (i = 0; i < target->count && !result; i++) - for (j = 0; j < target->defs[i]->count && !result; j++) - { - if (strcmp(target->defs[i]->regs[j].name, reg) == 0) - result = true; - else - (*index)++; - } - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : target = ensemble d'informations liées à l'architecture. * -* index = indice correspondant au registre pour GDB. * -* offset = position de valeur du registre dans du texte. [OUT] * -* * -* Description : Recherche la position correspondant à un registre donné. * -* * -* Retour : Bilan de l'opération : trouvaille ou échec ? * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_target_find_register_offset(const GGdbTarget *target, unsigned int index, size_t *offset) -{ - unsigned int i; /* Boucle de parcours #1 */ - unsigned int j; /* Boucle de parcours #2 */ - - *offset = 0; - - for (i = 0; i < target->count && index > 0; i++) - for (j = 0; j < target->defs[i]->count && index > 0; j++) - { - assert(target->defs[i]->regs[j].size % 4 == 0); - - *offset += target->defs[i]->regs[j].size / 4; - - index--; - - } - - return (index == 0); - -} - - -/****************************************************************************** -* * -* Paramètres : target = ensemble d'informations liées à l'architecture. * -* stream = flux de communication ouvert avec le débogueur. * -* endian = boutisme de la cible. * -* reg = désignation humaine du register à consulter. * -* size = taille des données mises en jeu. * -* ... = emplacement de la valeur lue à conserver. [OUT] * -* * -* Description : Effectue la lecture d'un registre donné. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_gdb_target_read_register(GGdbTarget *target, GGdbStream *stream, SourceEndian endian, const char *reg, size_t size, ...) -{ - bool result; /* Bilan à retourner */ - unsigned int index; /* Indice du registre ciblé */ - GGdbPacket *packet; /* Paquet de communication */ - char cmd[sizeof(XSTR(UINT_MAX)) + 1]; /* Elément de requête */ - const char *data; /* Données reçues à analyser */ - size_t len; /* Quantité de ces données */ - const char *raw; /* Début de zone à relire */ - size_t offset; /* Position dans la masse */ - va_list ap; /* Liste variable d'arguments */ - uint8_t *val8; /* Valeur sur 8 bits */ - uint16_t *val16; /* Valeur sur 16 bits */ - uint16_t conv16; /* Valeur adaptée sur 16 bits */ - uint32_t *val32; /* Valeur sur 32 bits */ - uint32_t conv32; /* Valeur adaptée sur 32 bits */ - uint64_t *val64; /* Valeur sur 64 bits */ - uint64_t conv64; /* Valeur adaptée sur 64 bits */ - - result = g_gdb_target_find_register_index(target, reg, &index); - if (!result) goto ggtrr_error; - - /** - * Essai avec la méthode précise. - */ - - if (!target->read_single_register) - goto read_all_register_fallback; - - packet = g_gdb_stream_get_free_packet(stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, "p"); - - snprintf(cmd, sizeof(cmd), "%x", index); - g_gdb_packet_append(packet, cmd); - - result = g_gdb_stream_send_packet(stream, packet); - - g_gdb_stream_mark_packet_as_free(stream, packet); - - if (!result) - goto ggtrr_error; - - /* Réception de la réponse */ - - packet = g_gdb_stream_recv_packet(stream); - - g_gdb_packet_get_data(packet, &data, &len, NULL); - - if (len != 0 && !is_error_code(data, len)) - raw = data; - - else - { - target->read_single_register = false; - - g_gdb_stream_mark_packet_as_free(stream, packet); - - read_all_register_fallback: - - /** - * Utilisation de la méthode de masse au besoin... - */ - - packet = g_gdb_stream_get_free_packet(stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, "g"); - - result = g_gdb_stream_send_packet(stream, packet); - - g_gdb_stream_mark_packet_as_free(stream, packet); - - if (!result) - goto ggtrr_error; - - /* Réception de la réponse */ - - packet = g_gdb_stream_recv_packet(stream); - - g_gdb_packet_get_data(packet, &data, &len, NULL); - - result = g_gdb_target_find_register_offset(target, index, &offset); - - if (!result || offset > len) - goto ggtrr_exit; - - raw = data + offset; - len -= offset; - - } - - /* Lecture finale de la valeur recherchée */ - - va_start(ap, size); - - switch (size) - { - case 8: - val8 = va_arg(ap, uint8_t *); - result = hex_to_u8(raw, val8); - break; - - case 16: - val16 = va_arg(ap, uint16_t *); - result = hex_to_u16(raw, &conv16); - *val16 = from_u16(&conv16, endian); - break; - - case 32: - val32 = va_arg(ap, uint32_t *); - result = hex_to_u32(raw, &conv32); - *val32 = from_u32(&conv32, endian); - break; - - case 64: - val64 = va_arg(ap, uint64_t *); - result = hex_to_u64(raw, &conv64); - *val64 = from_u64(&conv64, endian); - break; - - default: - assert(false); - result = false; - break; - - } - - va_end(ap); - - ggtrr_exit: - - g_gdb_stream_mark_packet_as_free(stream, packet); - - ggtrr_error: - - return result; - -} - - -/****************************************************************************** -* * -* Paramètres : target = ensemble d'informations liées à l'architecture. * -* stream = flux de communication ouvert avec le débogueur. * -* endian = boutisme de la cible. * -* reg = désignation humaine du register à consulter. * -* size = taille des données mises en jeu. * -* ... = emplacement de la valeur à écrire. * -* * -* Description : Effectue l'écriture d'un registre donné. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -bool g_gdb_target_write_register(GGdbTarget *target, GGdbStream *stream, SourceEndian endian, const char *reg, size_t size, ...) -{ - bool result; /* Bilan d'opération à renvoyer*/ - va_list ap; /* Liste variable d'arguments */ - const uint8_t *val8; /* Valeur sur 8 bits */ - const uint16_t *val16; /* Valeur sur 16 bits */ - uint16_t conv16; /* Valeur adaptée sur 16 bits */ - const uint32_t *val32; /* Valeur sur 32 bits */ - uint32_t conv32; /* Valeur adaptée sur 32 bits */ - const uint64_t *val64; /* Valeur sur 64 bits */ - uint64_t conv64; /* Valeur adaptée sur 64 bits */ - char hexval[17]; /* Valeur sous forme hexa */ - unsigned int index; /* Indice du registre ciblé */ - GGdbPacket *packet; /* Paquet de communication */ - char cmd[sizeof(XSTR(UINT_MAX)) + 1]; /* Elément de requête */ - const char *data; /* Données reçues à analyser */ - size_t len; /* Quantité de ces données */ - char *new; /* Nouvelles valeurs générales */ - size_t offset; /* Position dans la masse */ - - /* Tronc commun : récupération de la valeur */ - - va_start(ap, size); - - switch (size) - { - case 8: - val8 = va_arg(ap, uint8_t *); - result = u8_to_hex(val8, hexval); - break; - - case 16: - val16 = va_arg(ap, uint16_t *); - conv16 = to_u16(val16, endian); - result = u16_to_hex(&conv16, hexval); - break; - - case 32: - val32 = va_arg(ap, uint32_t *); - conv32 = to_u32(val32, endian); - result = u32_to_hex(&conv32, hexval); - break; - - case 64: - val64 = va_arg(ap, uint64_t *); - conv64 = to_u64(val64, endian); - result = u16_to_hex(&conv64, hexval); - break; - - default: - assert(false); - result = false; - break; - - } - - va_end(ap); - - if (!result) - goto ggtwr_error; - - /* Préparation de la suite */ - - result = g_gdb_target_find_register_index(target, reg, &index); - if (!result) goto ggtwr_error; - - /** - * Essai avec la méthode précise. - */ - - if (!target->write_single_register) - goto write_all_register_fallback; - - packet = g_gdb_stream_get_free_packet(stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, "P"); - - snprintf(cmd, sizeof(cmd), "%x", index); - g_gdb_packet_append(packet, cmd); - - g_gdb_packet_append(packet, "="); - - g_gdb_packet_append(packet, hexval); - - result = g_gdb_stream_send_packet(stream, packet); - - g_gdb_stream_mark_packet_as_free(stream, packet); - - if (!result) - goto ggtwr_error; - - /* Réception de la réponse */ - - packet = g_gdb_stream_recv_packet(stream); - - g_gdb_packet_get_data(packet, &data, &len, NULL); - - if (is_error_code(data, len) || strcmp(data, "OK") != 0) - { - target->write_single_register = false; - - g_gdb_stream_mark_packet_as_free(stream, packet); - - write_all_register_fallback: - - /** - * Utilisation de la méthode de masse au besoin... - */ - - /* Lecture de l'ensemble des registres */ - - packet = g_gdb_stream_get_free_packet(stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, "g"); - - result = g_gdb_stream_send_packet(stream, packet); - - g_gdb_stream_mark_packet_as_free(stream, packet); - - if (!result) - goto ggtwr_error; - - /* Réception de la réponse et mise à jour */ - - packet = g_gdb_stream_recv_packet(stream); - - g_gdb_packet_get_data(packet, &data, &len, NULL); - - result = g_gdb_target_find_register_offset(target, index, &offset); - - if (!result || offset > len) - goto ggtwr_exit; - - new = (char *)malloc(len); - - memcpy(new, data, len); - memcpy(new + offset, hexval, strlen(hexval)); - - g_gdb_stream_mark_packet_as_free(stream, packet); - - /* Ecrasement de tous les registres */ - - packet = g_gdb_stream_get_free_packet(stream); - - g_gdb_packet_start_new_command(packet); - g_gdb_packet_append(packet, "G"); - - g_gdb_packet_append(packet, new); - free(new); - - result = g_gdb_stream_send_packet(stream, packet); - - g_gdb_stream_mark_packet_as_free(stream, packet); - - if (!result) - goto ggtwr_error; - - /* Réception de la réponse */ - - packet = g_gdb_stream_recv_packet(stream); - - g_gdb_packet_get_data(packet, &data, &len, NULL); - - result = (!is_error_code(data, len) && strcmp(data, "OK") == 0); - - } - - ggtwr_exit: - - g_gdb_stream_mark_packet_as_free(stream, packet); - - ggtwr_error: - - return result; - -} diff --git a/src/debug/gdbrsp/target.h b/src/debug/gdbrsp/target.h deleted file mode 100644 index bbdbec1..0000000 --- a/src/debug/gdbrsp/target.h +++ /dev/null @@ -1,72 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * target.h - prototypes pour la gestion des éléments propres à l'architecture reconnue par GDB - * - * Copyright (C) 2016 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 <http://www.gnu.org/licenses/>. - */ - - -#ifndef _DEBUG_GDBRSP_TARGET_H -#define _DEBUG_GDBRSP_TARGET_H - - -#include <glib-object.h> -#include <stdbool.h> - - -#include "stream.h" -#include "../../common/endianness.h" - - - -#define G_TYPE_GDB_TARGET (g_gdb_target_get_type()) -#define G_GDB_TARGET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), G_TYPE_GDB_TARGET, GGdbTarget)) -#define G_IS_GDB_TARGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), G_TYPE_GDB_TARGET)) -#define G_GDB_TARGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GDB_TARGET, GGdbTargetClass)) -#define G_IS_GDB_TARGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GDB_TARGET)) -#define G_GDB_TARGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_TARGET, GGdbTargetClass)) - - -/* Indications quant à l'interfaçage client/serveur GDB (instance) */ -typedef struct _GGdbTarget GGdbTarget; - -/* Indications quant à l'interfaçage client/serveur GDB (classe) */ -typedef struct _GGdbTargetClass GGdbTargetClass; - - -/* Indique le type défini par la GLib pour les détails d'interfaçage GDB. */ -GType g_gdb_target_get_type(void); - -/* Crée une définition des détails d'interfaçage GDB. */ -GGdbTarget *g_gdb_target_new(GGdbStream *); - -/* Liste l'ensemble des registres appartenant à un groupe. */ -char **g_gdb_target_get_register_names(const GGdbTarget *, const char *, size_t *); - -/* Indique la taille associée à un registre donné. */ -unsigned int g_gdb_target_get_register_size(const GGdbTarget *, const char *); - -/* Effectue la lecture d'un registre donné. */ -bool g_gdb_target_read_register(GGdbTarget *, GGdbStream *, SourceEndian, const char *, size_t, ...); - -/* Effectue l'écriture d'un registre donné. */ -bool g_gdb_target_write_register(GGdbTarget *, GGdbStream *, SourceEndian, const char *, size_t, ...); - - - -#endif /* _DEBUG_GDBRSP_TARGET_H */ diff --git a/src/debug/gdbrsp/tcp.c b/src/debug/gdbrsp/tcp.c deleted file mode 100644 index 8458dc6..0000000 --- a/src/debug/gdbrsp/tcp.c +++ /dev/null @@ -1,280 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * tcp.c - gestion des connexions TCP aux serveurs GDB. - * - * Copyright (C) 2009-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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. - */ - - -#include "tcp.h" - - -#include <netdb.h> -#include <stdio.h> -#include <string.h> -#include <unistd.h> -#include <sys/socket.h> -#include <sys/types.h> - - -#include "stream-int.h" - - -#include "../../common/net.h" - - -/* Flux de communication TCP avec un serveur GDB (instance) */ -struct _GGdbTcpClient -{ - GGdbStream parent; /* A laisser en premier */ - -}; - - -/* Flux de communication TCP avec un serveur GDB (classe) */ -struct _GGdbTcpClientClass -{ - GGdbStreamClass parent; /* A laisser en premier */ - -}; - - -/* Initialise la classe des flux de communication TCP avec GDB. */ -static void g_gdb_tcp_client_class_init(GGdbTcpClientClass *); - -/* Initialise une instance de flux de communication avec GDB. */ -static void g_gdb_tcp_client_init(GGdbTcpClient *); - -/* Ouvre une connexion TCP à un serveur GDB. */ -//static int connect_via_tcp(const char *, const char *); - -/* Envoie des données à un serveur GDB. */ -static bool g_gdb_tcp_client_send_data(GGdbTcpClient *, const char *, size_t); - -/* Réceptionne un octet de donnée d'un serveur GDB. */ -static bool g_gdb_tcp_client_recv_byte(GGdbTcpClient *, char *); - - - -/* Indique le type défini pour un flux de communication TCP avec un serveur GDB. */ -G_DEFINE_TYPE(GGdbTcpClient, g_gdb_tcp_client, G_TYPE_GDB_STREAM); - - -/****************************************************************************** -* * -* Paramètres : klass = classe à initialiser. * -* * -* Description : Initialise la classe des flux de communication TCP avec GDB. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_tcp_client_class_init(GGdbTcpClientClass *klass) -{ - -} - - -/****************************************************************************** -* * -* Paramètres : client = instance à initialiser. * -* * -* Description : Initialise une instance de flux de communication avec GDB. * -* * -* Retour : - * -* * -* Remarques : - * -* * -******************************************************************************/ - -static void g_gdb_tcp_client_init(GGdbTcpClient *client) -{ - GGdbStream *stream; /* Version parente */ - - stream = G_GDB_STREAM(client); - - stream->send_data = (send_gdb_data_fc)g_gdb_tcp_client_send_data; - stream->recv_byte = (recv_gdb_byte_fc)g_gdb_tcp_client_recv_byte; - -} - - -/****************************************************************************** -* * -* Paramètres : server = nom ou adresse du serveur à contacter. * -* port = port de connexion. * -* * -* Description : Ouvre une connexion TCP à un serveur GDB. * -* * -* Retour : Flux ouvert en lecture/écriture ou -1 en cas d'échec. * -* * -* Remarques : - * -* * -******************************************************************************/ -#if 0 -static int connect_via_tcp(const char *server, const char *port) -{ - int result; /* Bilan à retourner */ - struct addrinfo hints; /* Type de connexion souhaitée */ - struct addrinfo *infos; /* Informations disponibles */ - int ret; /* Bilan d'un appel */ - struct addrinfo *iter; /* Boucle de parcours */ - struct sockaddr_in addr; /* Infos de connexion distante */ - - memset(&hints, 0, sizeof(struct addrinfo)); - - hints.ai_family = AF_UNSPEC; /* IPv4 ou IPv6 */ - hints.ai_socktype = SOCK_STREAM; - hints.ai_flags = 0; - hints.ai_protocol = 0; /* N'importe quel protocole */ - - ret = getaddrinfo(server, port, &hints, &infos); - if (ret != 0) - { - fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret)); - return -1; - } - - for (iter = infos; iter != NULL; iter = iter->ai_next) - { - result = socket(iter->ai_family, iter->ai_socktype, iter->ai_protocol); - if (result == -1) continue; - - ret = connect(result, iter->ai_addr, iter->ai_addrlen); - if (ret == 0) break; - - perror("connect"); - close(result); - - } - - freeaddrinfo(infos); - - if (iter == NULL) return -1; - - ret = getpeername(result, (struct sockaddr *)&addr, (socklen_t []){ sizeof(struct sockaddr_in) }); - if (ret == -1) - { - perror("getpeername"); - close(result); - return -1; - } - - printf("Connecté à %s:%hd\n", server, ntohs(addr.sin_port)); - - return result; - -} -#endif - -/****************************************************************************** -* * -* Paramètres : server = nom ou adresse du serveur à contacter. * -* port = port de connexion. * -* owner = débogueur tributaire du canal de communication. * -* * -* Description : Crée une nouvelle connexion TCP à un serveur GDB. * -* * -* Retour : Adresse de la structure mise en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -GGdbStream *g_gdb_tcp_client_new(const char *server, const char *port, GGdbDebugger *owner) -{ - GGdbTcpClient *result; /* Structure à retourner */ - int sock; /* Flux ouvert à construire */ - - sock = connect_via_tcp(server, port, NULL); - if (sock == -1) return NULL; - - result = g_object_new(G_TYPE_GDB_TCP_CLIENT, NULL); - - G_GDB_STREAM(result)->fd = sock; - - G_GDB_STREAM(result)->owner = owner; - g_object_ref(G_OBJECT(owner)); - - if (!g_gdb_stream_listen(G_GDB_STREAM(result))) - goto ggtcn_error; - - return G_GDB_STREAM(result); - - ggtcn_error: - - return NULL; - -} - - -/****************************************************************************** -* * -* Paramètres : client = flux ouvert en écriture à utiliser. * -* data = données à envoyer. * -* len = quantité de ces données. * -* * -* Description : Envoie des données à un serveur GDB. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_tcp_client_send_data(GGdbTcpClient *client, const char *data, size_t len) -{ - ssize_t sent; /* Quantité de données envoyée */ - - sent = send(G_GDB_STREAM(client)->fd, data, len, 0); - - //printf(" sent '%s'\n", data); - //printf(" sent ? %d vs %d\n", (int)sent, (int)len); - - return (sent == len); - -} - - -/****************************************************************************** -* * -* Paramètres : client = flux ouvert en lecture à utiliser. * -* data = donnée à recevoir. * -* * -* Description : Réceptionne un octet de donnée d'un serveur GDB. * -* * -* Retour : Bilan de l'opération. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static bool g_gdb_tcp_client_recv_byte(GGdbTcpClient *client, char *data) -{ - ssize_t got; /* Quantité de données reçue */ - - got = recv(G_GDB_STREAM(client)->fd, data, 1, 0); - - //printf(" got ? %d vs %d -> %c (0x%02hhx\n", (int)got, (int)1, *data, *data); - - return (got == 1); - -} diff --git a/src/debug/gdbrsp/tcp.h b/src/debug/gdbrsp/tcp.h deleted file mode 100644 index 3472fd2..0000000 --- a/src/debug/gdbrsp/tcp.h +++ /dev/null @@ -1,57 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * tcp.h - prototypes pour la gestion des connexions TCP aux serveurs GDB. - * - * Copyright (C) 2009-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 Chrysalide. If not, see <http://www.gnu.org/licenses/>. - */ - - -#ifndef _DEBUG_GDBRSP_TCP_H -#define _DEBUG_GDBRSP_TCP_H - - -#include "gdb.h" -#include "stream.h" - - - -#define G_TYPE_GDB_TCP_CLIENT g_gdb_tcp_client_get_type() -#define G_GDB_TCP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), g_gdb_tcp_client_get_type(), GGdbTcpClient)) -#define G_IS_GDB_TCP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), g_gdb_tcp_client_get_type())) -#define G_GDB_TCP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), G_TYPE_GDB_TCP_CLIENT, GGdbTcpClientClass)) -#define G_IS_GDB_TCP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), G_TYPE_GDB_TCP_CLIENT)) -#define G_GDB_TCP_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), G_TYPE_GDB_TCP_CLIENT, GGdbTcpClientClass)) - - -/* Flux de communication TCP avec un serveur GDB (instance) */ -typedef struct _GGdbTcpClient GGdbTcpClient; - -/* Flux de communication TCP avec un serveur GDB (classe) */ -typedef struct _GGdbTcpClientClass GGdbTcpClientClass; - - - -/* Indique le type défini pour un flux de communication TCP avec un serveur GDB. */ -GType g_gdb_tcp_client_get_type(void); - -/* Crée une nouvelle connexion TCP à un serveur GDB. */ -GGdbStream *g_gdb_tcp_client_new(const char *, const char *, GGdbDebugger *); - - - -#endif /* _DEBUG_GDBRSP_TCP_H */ diff --git a/src/debug/gdbrsp/utils.c b/src/debug/gdbrsp/utils.c deleted file mode 100644 index 1088e51..0000000 --- a/src/debug/gdbrsp/utils.c +++ /dev/null @@ -1,354 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * utils.h - fonctions qui simplifient la vie dans les interactions avec un serveur GDB - * - * Copyright (C) 2016 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 <http://www.gnu.org/licenses/>. - */ - - -#include "utils.h" - - -#include <assert.h> -#include <ctype.h> -#include <stdarg.h> -#include <stdbool.h> -#include <sys/param.h> -#include <sys/types.h> - - - -/****************************************************************************** -* * -* 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; - -} diff --git a/src/debug/gdbrsp/utils.h b/src/debug/gdbrsp/utils.h deleted file mode 100644 index 833fe69..0000000 --- a/src/debug/gdbrsp/utils.h +++ /dev/null @@ -1,58 +0,0 @@ - -/* Chrysalide - Outil d'analyse de fichiers binaires - * utils.h - prototypes pour les fonctions qui simplifient la vie dans les interactions avec un serveur GDB - * - * Copyright (C) 2016 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 <http://www.gnu.org/licenses/>. - */ - - -#ifndef _DEBUG_GDBRSP_UTILS_H -#define _DEBUG_GDBRSP_UTILS_H - - -#include <stdbool.h> -#include <stdint.h> -#include <sys/types.h> - - - -/* Indique si les données correspondent à un code d'erreur. */ -bool is_error_code(const char *, size_t); - -/* Relit une valeur sur 8 bits et deux lettres. */ -bool read_fixed_byte(const char *, size_t, uint8_t *); - -/* Traduit en valeur sur XX bits une forme textuelle. */ -bool hex_to_any_u(const char *, size_t, ...); - -#define hex_to_u8(h, v) hex_to_any_u(h, 1, v) -#define hex_to_u16(h, v) hex_to_any_u(h, 2, v) -#define hex_to_u32(h, v) hex_to_any_u(h, 4, v) -#define hex_to_u64(h, v) hex_to_any_u(h, 8, v) - -/* Traduit une valeur sur XX bits en forme textuelle. */ -bool any_u_to_hex(size_t, char [17], ...); - -#define u8_to_hex(v, h) any_u_to_hex(1, h, v) -#define u16_to_hex(v, h) any_u_to_hex(2, h, v) -#define u32_to_hex(v, h) any_u_to_hex(4, h, v) -#define u64_to_hex(v, h) any_u_to_hex(8, h, v) - - - -#endif /* _DEBUG_GDBRSP_UTILS_H */ |