diff options
Diffstat (limited to 'src/debug/gdbrsp/target.c')
-rw-r--r-- | src/debug/gdbrsp/target.c | 950 |
1 files changed, 0 insertions, 950 deletions
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; - -} |