/* Chrysalide - Outil d'analyse de fichiers binaires * packet.c - définition des paquets destiné au protocole JDWP * * Copyright (C) 2010-2017 Cyrille Bagard * * This file is part of Chrysalide. * * Chrysalide is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * Chrysalide is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Foobar. If not, see . */ #include "packet.h" #include "misc/header.h" #include "../packet-int.h" #include "../../arch/archbase.h" #include "../../common/endianness.h" /* Répresentation d'un paquet de débogage JDWP (instance) */ struct _GJdwpPacket { GDebugPacket parent; /* A laisser en premier */ jdwp_header header; /* En-tête du paquet JDWP */ bin_t hblob[sizeof(jdwp_header)]; /* Contenu encodé en B.E. */ jdwp_payload payload; /* Charge utile du paquet */ bin_t pblob[sizeof(jdwp_payload)]; /* Contenu encodé en B.E. */ bool got; /* Précise le type de charge */ }; /* Répresentation d'un paquet de débogage JDWP (classe) */ struct _GJdwpPacketClass { GDebugPacketClass parent; /* A laisser en premier */ jdwp_cmd_vm_id_sizes_reply sizes; /* Réf. des tailles dynamiques */ }; /* Initialise la classe des paquets de débogage JDWP. */ static void g_jdwp_packet_class_init(GJdwpPacketClass *); /* Initialise une instance de paquet de débogage JDWP. */ static void g_jdwp_packet_init(GJdwpPacket *); /* Précise les zones mémoires correspondant au contenu. */ static void g_jdwp_packet_vectorize(GJdwpPacket *, struct iovec [UIO_MAXIOV], int *); /* Indique le type défini pour un paquet de débogage JDWP. */ G_DEFINE_TYPE(GJdwpPacket, g_jdwp_packet, G_TYPE_DEBUG_PACKET); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe des paquets de débogage JDWP. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_jdwp_packet_class_init(GJdwpPacketClass *klass) { } /****************************************************************************** * * * Paramètres : packet = instance à initialiser. * * * * Description : Initialise une instance de paquet de débogage JDWP. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_jdwp_packet_init(GJdwpPacket *packet) { GDebugPacket *dpkt; /* Version parente */ dpkt = G_DEBUG_PACKET(packet); dpkt->vectorize = (debug_vectorize_fc)g_jdwp_packet_vectorize; } /****************************************************************************** * * * Paramètres : packet = instance à utiliser comme intermédiaire. * * sizes = références pour la valeur des tailles dynamiques. * * * * Description : Enregistre les différentes tailles dynamiques. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_jdwp_packet_set_sizes(GJdwpPacket *packet, const jdwp_cmd_vm_id_sizes_reply *sizes) { G_JDWP_PACKET_GET_CLASS(packet)->sizes = *sizes; } /****************************************************************************** * * * Paramètres : packet = instance à convertir. * * iov = table de vecteurs. [OUT] * * iovcnt = quantité de champs renseignés. [OUT] * * * * Description : Précise les zones mémoires correspondant au contenu. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_jdwp_packet_vectorize(GJdwpPacket *packet, struct iovec iov[UIO_MAXIOV], int *iovcnt) { uint32_t length; /* Quantité de données */ bool empty; /* Présence d'une charge utile */ read_u32(&length, packet->hblob, (off_t []) { 0 }, sizeof(jdwp_header), SRE_BIG); iov[0].iov_base = packet->hblob; iov[0].iov_len = sizeof(jdwp_header); empty = (length == sizeof(jdwp_header)); if (!empty) { iov[1].iov_base = packet->pblob; iov[1].iov_len = length - sizeof(jdwp_header); } *iovcnt = (empty ? 1 : 2); } /****************************************************************************** * * * Paramètres : packet = instance à consulter. * * * * Description : Fournit l'adresse des données de l'en-tête d'un paquet JDWP. * * * * Retour : Adresse des données de l'en-tête (à priori de requête). * * * * Remarques : - * * * ******************************************************************************/ jdwp_header *g_jdwp_packet_get_header(GJdwpPacket *packet) { return &packet->header; } /****************************************************************************** * * * Paramètres : packet = instance à consulter. * * * * Description : Fournit l'adresse des données de l'en-tête d'un paquet JDWP. * * * * Retour : Adresse des données de l'en-tête (à priori de requête). * * * * Remarques : - * * * ******************************************************************************/ bin_t *g_jdwp_packet_get_hblob(GJdwpPacket *packet) { return packet->hblob; } /****************************************************************************** * * * Paramètres : packet = instance à mettre à jour. * * * * Description : Recompose l'en-tête d'un paquet à partir de données brutes. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool g_jdwp_packet_parse_header(GJdwpPacket *packet) { return get_jdwp_header(packet->hblob, &packet->header); } /****************************************************************************** * * * Paramètres : packet = paquet à mettre à jour. * * set = jeu de commandes de la requête. * * command = commande proprement dite. * * * * Description : Définit l'en-tête du paquet pour une requête au format JDWP. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_jdwp_packet_set_request_header(GJdwpPacket *packet, uint8_t set, uint8_t command) { set_jdwp_request_header(&packet->header, packet->hblob, 0, set, command); packet->got = false; } /****************************************************************************** * * * Paramètres : packet = paquet à mettre à jour. * * lastid = jeton du paquet à l'origine du besoin de réponse. * * error = éventuelle indication d'erreur. * * * * Description : Définit l'en-tête du paquet pour une réponse au format JDWP. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_jdwp_packet_set_reply_header(GJdwpPacket *packet, uint32_t lastid, uint16_t error) { set_jdwp_reply_header(&packet->header, packet->hblob, 0, lastid, error); packet->got = false; } /****************************************************************************** * * * Paramètres : packet = instance à consulter. * * payload = modèle de charge à copier. * * * * Description : Fournit l'adresse des charges utiles d'un paquet JDWP. * * * * Retour : Adresse des données d'une charge utile. * * * * Remarques : - * * * ******************************************************************************/ void g_jdwp_packet_set_payload(GJdwpPacket *packet, const jdwp_payload *payload) { off_t len; /* Quantité max puis effective */ len = sizeof(jdwp_payload); set_jdwp_payload(payload, packet->header.set, packet->header.command, &G_JDWP_PACKET_GET_CLASS(packet)->sizes, packet->pblob, &len); packet->header.length += len; update_jdwp_header_length(&packet->header, packet->hblob); packet->got = false; } /****************************************************************************** * * * Paramètres : packet = instance à consulter. * * * * Description : Fournit l'adresse des charges utiles d'un paquet JDWP. * * * * Retour : Adresse des données d'une charge utile. * * * * Remarques : - * * * ******************************************************************************/ jdwp_payload *g_jdwp_packet_get_payload(GJdwpPacket *packet) { return &packet->payload; } /****************************************************************************** * * * Paramètres : packet = instance à consulter. * * * * Description : Fournit l'adresse des charges utiles d'un paquet JDWP. * * * * Retour : Adresse des données d'une charge utile. * * * * Remarques : - * * * ******************************************************************************/ bin_t *g_jdwp_packet_get_pblob(GJdwpPacket *packet) { return packet->pblob; } /****************************************************************************** * * * Paramètres : packet = instance à mettre à jour. * * set = jeu de commandes concerné. * * cmd = identifiant d'une commande donnée. * * * * Description : Recompose une charge utile à partir de ses données brutes. * * * * Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ bool g_jdwp_packet_parse_payload(GJdwpPacket *packet, uint8_t set, uint8_t cmd) { bool result; /* Bilan à retourner */ result = get_jdwp_payload(packet->pblob, packet->header.length - sizeof(jdwp_header)/* FIXME */, set, cmd, &G_JDWP_PACKET_GET_CLASS(packet)->sizes, &packet->payload); if (result) { packet->header.set = set; packet->header.command = cmd; } packet->got = true; return result; } /****************************************************************************** * * * Paramètres : packet = instance à mettre à jour. * * * * Description : Libère la mémoire occupée par une charge utile de paquet. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_jdwp_packet_free_payload(GJdwpPacket *packet) { if (packet->header.set == JDWP_CST_NONE || packet->header.command == JDWP_CMD_NONE) return; free_jdwp_payload(&packet->payload, packet->got, packet->header.set, packet->header.command); } /****************************************************************************** * * * Paramètres : reply = instance de paquet à analyser. * * packet = instance de paquet de référence. * * * * Description : Détermine si un paquet est une réponse à un premier paquet. * * * * Retour : true si le paquet correspond à la réponse attendue. * * * * Remarques : - * * * ******************************************************************************/ bool g_jdwp_packet_is_reply(const GJdwpPacket *reply, const GJdwpPacket *packet) { return (reply->header.id == packet->header.id && reply->header.flags & JDWP_FLAGS_REPLY); }