/* Chrysalide - Outil d'analyse de fichiers binaires
 * vmpa.c - adressages virtuels ou physiques
 *
 * Copyright (C) 2014 Cyrille Bagard
 *
 *  This file is part of Chrysalide.
 *
 *  OpenIDA 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.
 *
 *  OpenIDA 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 "vmpa.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include "../common/io.h"
/* ---------------------- DEFINITION D'UNE POSITION EN MEMOIRE ---------------------- */
/* Transforme une position physique en chaîne de caractères. */
static char *_phys_t_to_string(phys_t, MemoryDataSize, char [VMPA_MAX_LEN], size_t *);
/* ---------------------------------------------------------------------------------- */
/*                        DEFINITION D'UNE POSITION EN MEMOIRE                        */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
*                                                                             *
*  Paramètres  : addr = élément à initialiser. [OUT]                          *
*                phy  = position dans la mémoire physique.                    *
*                virt = adresse dans la mémoire virtuelle.                    *
*                                                                             *
*  Description : Initialise une localisation dans l'espace mémoire/physique.  *
*                                                                             *
*  Retour      : Adressage alloué en mémoire.                                 *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void init_vmpa(vmpa2t *addr, phys_t phy, virt_t virt)
{
    addr->physical = phy;
    addr->virtual = virt;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : phy  = position dans la mémoire physique.                    *
*                virt = adresse dans la mémoire virtuelle.                    *
*                                                                             *
*  Description : Crée une localisation dans l'adressage mémoire.              *
*                                                                             *
*  Retour      : Adressage alloué en mémoire.                                 *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
vmpa2t *make_vmpa(phys_t phy, virt_t virt)
{
    vmpa2t *result;                         /* Structure à retourner       */
    result = (vmpa2t *)calloc(1, sizeof(vmpa2t));
    init_vmpa(result, phy, virt);
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : dest = structure de destination pour la copie.               *
*                src  = structure de source pour la copie.                    *
*                                                                             *
*  Description : Copie la définition d'un adressage dans un autre.            *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void copy_vmpa(vmpa2t *dest, const vmpa2t *src)
{
    dest->physical = src->physical;
    dest->virtual = src->virtual;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : a = première définition à analyser.                          *
*                b = seconde définition à analyser.                           *
*                                                                             *
*  Description : Compare entre elles deux adresses physiques.                 *
*                                                                             *
*  Retour      : Bilan de la comparaison : -1, 0 ou 1.                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
int cmp_vmpa_by_phy(const vmpa2t *a, const vmpa2t *b)
{
    int result;                             /* Bilan à retourner           */
    if (a->physical != VMPA_NO_PHYSICAL && b->physical != VMPA_NO_PHYSICAL)
    {
        if (a->physical < b->physical) result = -1;
        else if (a->physical > b->physical) result = 1;
        else result = 0;
    }
    else
    {
        if (a->physical == VMPA_NO_PHYSICAL && b->physical == VMPA_NO_PHYSICAL) result = 0;
        else if (a->physical == VMPA_NO_PHYSICAL) result = -1;
        else result = 1;
    }
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : a = première définition à analyser.                          *
*                b = seconde définition à analyser.                           *
*                                                                             *
*  Description : Compare entre elles deux adresses virtuelles.                *
*                                                                             *
*  Retour      : Bilan de la comparaison : -1, 0 ou 1.                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
int cmp_vmpa_by_virt(const vmpa2t *a, const vmpa2t *b)
{
    int result;                             /* Bilan à retourner           */
    if (a->virtual != VMPA_NO_VIRTUAL && b->virtual != VMPA_NO_VIRTUAL)
    {
        if (a->virtual < b->virtual) result = -1;
        else if (a->virtual > b->virtual) result = 1;
        else result = 0;
    }
    else
    {
        if (a->virtual == VMPA_NO_VIRTUAL && b->virtual == VMPA_NO_VIRTUAL) result = 0;
        else if (a->virtual == VMPA_NO_VIRTUAL) result = -1;
        else result = 1;
    }
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : a = première définition à analyser.                          *
*                b = seconde définition à analyser.                           *
*                                                                             *
*  Description : Compare deux localisations selon leurs parties définies.     *
*                                                                             *
*  Retour      : Bilan de la comparaison : -1, 0 ou 1 (-1 par défaut).        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
int cmp_vmpa(const vmpa2t *a, const vmpa2t *b)
{
    int result;                             /* Bilan à retourner           */
    bool half;                              /* Comparaison débutée         */
    result = -1;
    half = false;
    if (a->physical != VMPA_NO_PHYSICAL && b->physical != VMPA_NO_PHYSICAL)
    {
        result = cmp_vmpa_by_phy(a, b);
        half = true;
    }
    if (a->virtual != VMPA_NO_VIRTUAL && b->virtual != VMPA_NO_VIRTUAL
        && (!half || (half && result == 0)))
    {
        result = cmp_vmpa_by_virt(a, b);
    }
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : addr = élément à modifier.                                   *
*                qty  = quantité d'unités de décallage.                       *
*                                                                             *
*  Description : Décalle une position d'une certaine quantité.                *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void advance_vmpa(vmpa2t *addr, phys_t qty)
{
    if (addr->physical != VMPA_NO_PHYSICAL)
        addr->physical += qty;
    if (addr->virtual != VMPA_NO_VIRTUAL)
        addr->virtual += qty;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : addr = élément à modifier.                                   *
*                qty  = quantité d'unités de décallage.                       *
*                                                                             *
*  Description : Décalle une position d'une certaine quantité.                *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void deminish_vmpa(vmpa2t *addr, phys_t qty)
{
    /* On choisit de ne pas vérifier les débordements */
    if (addr->physical != VMPA_NO_PHYSICAL)
        addr->physical -= qty;
    if (addr->virtual != VMPA_NO_VIRTUAL)
        addr->virtual -= qty;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : a = première élément à venir consulter.                      *
*                b = second élément à traiter en parallèle.                   *
*                                                                             *
*  Description : Calcule au mieux la distance entre deux coordonnées.         *
*                                                                             *
*  Retour      : Distance absolue entre deux localisations.                   *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
phys_t compute_vmpa_diff(const vmpa2t *a, const vmpa2t *b)
{
    phys_t result;                          /* Valeur à retourner          */
    result = VMPA_NO_PHYSICAL;
    if (a->physical != VMPA_NO_PHYSICAL && b->physical != VMPA_NO_PHYSICAL)
        result = (b->physical > a->physical ? b->physical - a->physical : a->physical - b->physical);
    else if (a->virtual != VMPA_NO_VIRTUAL && b->virtual != VMPA_NO_VIRTUAL)
        result = (phys_t)(b->virtual > a->virtual ? b->virtual - a->virtual : a->virtual - b->virtual);
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : addr  = élément à venir lire. [OUT]                          *
*                fd    = flux ouvert en lecture pour l'importation.           *
*                flags = éventuelles options d'envoi supplémentaires.         *
*                                                                             *
*  Description : Lit la définition d'une adresse depuis un flux réseau.       *
*                                                                             *
*  Retour      : Bilan de l'opération.                                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
bool recv_vmpa(vmpa2t *addr, int fd, int flags)
{
    virt_t val64;                           /* Valeur sur 64 bits          */
    bool status;                            /* Bilan d'une réception       */
    status = safe_recv(fd, &val64, sizeof(uint64_t), MSG_WAITALL | flags);
    if (!status) return false;
    addr->physical = be64toh(val64);
    status = safe_recv(fd, &val64, sizeof(uint64_t), MSG_WAITALL | flags);
    if (!status) return false;
    addr->virtual = be64toh(val64);
    return true;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : addr  = élément à venir écrire.                              *
*                fd    = flux ouvert en écriture pour l'exportation.          *
*                flags = éventuelles options d'envoi supplémentaires.         *
*                                                                             *
*  Description : Ecrit la définition d'une adresse dans un flux réseau.       *
*                                                                             *
*  Retour      : Bilan de l'opération.                                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
bool send_vmpa(const vmpa2t *addr, int fd, int flags)
{
    bool status;                            /* Bilan d'une émission        */
    status = safe_send(fd, (uint64_t []) { htobe64(addr->physical) }, sizeof(uint64_t), MSG_MORE | flags);
    if (!status) return false;
    status = safe_send(fd, (uint64_t []) { htobe64(addr->virtual) }, sizeof(uint64_t), flags);
    if (!status) return false;
    return true;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : phys   = position physique à traiter.                        *
*                msize  = taille de cette adresse, réelle ou désirée.         *
*                buffer = tampon de sortie utilisé à constituer. [OUT]        *
*                length = transmission de la taille du résultat ou NULL. [OUT]*
*                                                                             *
*  Description : Transforme une position physique en chaîne de caractères.    *
*                                                                             *
*  Retour      : Chaîne de caractères constituée.                             *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
static char *_phys_t_to_string(phys_t phys, MemoryDataSize msize, char buffer[VMPA_MAX_LEN], size_t *length)
{
    size_t ret;                             /* Retour de l'impression      */
	if (phys == VMPA_NO_PHYSICAL)
		ret = snprintf(buffer, VMPA_MAX_LEN, _("(none)"));
	else
        switch (msize)
        {
            case MDS_8_BITS:
                ret = snprintf(buffer, VMPA_MAX_LEN,"0x%02" PRIx64, phys);
                break;
            case MDS_16_BITS:
                ret = snprintf(buffer, VMPA_MAX_LEN, "0x%04" PRIx64, phys);
                break;
            case MDS_32_BITS:
                ret = snprintf(buffer, VMPA_MAX_LEN, "0x%08" PRIx64, phys);
                break;
            case MDS_64_BITS:
                ret = snprintf(buffer, VMPA_MAX_LEN, "0x%016" PRIx64, phys);
                break;
            default:
                ret = snprintf(buffer, VMPA_MAX_LEN, "0x%" PRIx64, phys);
                break;
        }
    if (length != NULL)
        *length = ret;
    return buffer;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : addr   = adresse virtuelle ou physique à traiter.            *
*                msize  = taille de cette adresse, réelle ou désirée.         *
*                buffer = tampon de sortie utilisé à constituer. [OUT]        *
*                length = transmission de la taille du résultat ou NULL. [OUT]*
*                                                                             *
*  Description : Transforme une adresse physique en chaîne de caractères.     *
*                                                                             *
*  Retour      : Chaîne de caractères constituée.                             *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
char *vmpa2_phys_to_string(const vmpa2t *addr, MemoryDataSize msize, char buffer[VMPA_MAX_LEN], size_t *length)
{
    return _phys_t_to_string(addr->physical, msize, buffer, length);
}
/******************************************************************************
*                                                                             *
*  Paramètres  : addr   = adresse virtuelle ou physique à traiter.            *
*                msize  = taille de cette adresse, réelle ou désirée.         *
*                buffer = tampon de sortie utilisé à constituer. [OUT]        *
*                length = transmission de la taille du résultat ou NULL. [OUT]*
*                                                                             *
*  Description : Transforme une adresse virtuelle en chaîne de caractères.    *
*                                                                             *
*  Retour      : Chaîne de caractères constituée.                             *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
char *vmpa2_virt_to_string(const vmpa2t *addr, MemoryDataSize msize, char buffer[VMPA_MAX_LEN], size_t *length)
{
    size_t ret;                             /* Retour de l'impression      */
	if (addr->virtual == VMPA_NO_VIRTUAL)
		ret = snprintf(buffer, VMPA_MAX_LEN, _("(none)"));
	else
		switch (msize)
		{
            case MDS_8_BITS:
				ret = snprintf(buffer, VMPA_MAX_LEN,"0x%02" PRIx64, addr->virtual);
				break;
            case MDS_16_BITS:
				ret = snprintf(buffer, VMPA_MAX_LEN, "0x%04" PRIx64, addr->virtual);
				break;
            case MDS_32_BITS:
				ret = snprintf(buffer, VMPA_MAX_LEN, "0x%08" PRIx64, addr->virtual);
				break;
            case MDS_64_BITS:
				ret = snprintf(buffer, VMPA_MAX_LEN, "0x%016" PRIx64, addr->virtual);
				break;
            default:
				ret = snprintf(buffer, VMPA_MAX_LEN, "0x%" PRIx64, addr->virtual);
				break;
		}
    if (length != NULL)
        *length = ret;
    return buffer;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : buffer = chaîne de caractères à consulter.                   *
*                                                                             *
*  Description : Transforme une chaîne de caractères en position physique.    *
*                                                                             *
*  Retour      : Adresse obtenue.                                             *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
vmpa2t *string_to_vmpa_phy(const char *buffer)
{
    phys_t physical;                        /* Position à retrouver        */
    physical = strtoull(buffer, NULL, 16);
    return make_vmpa(physical, VMPA_NO_VIRTUAL);
}
/******************************************************************************
*                                                                             *
*  Paramètres  : buffer = chaîne de caractères à consulter.                   *
*                                                                             *
*  Description : Transforme une chaîne de caractères en adresse virtuelle.    *
*                                                                             *
*  Retour      : Adresse obtenue.                                             *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
vmpa2t *string_to_vmpa_virt(const char *buffer)
{
    virt_t virtual;                         /* Adresse à retrouver         */
    virtual = strtoull(buffer, NULL, 16);
    return make_vmpa(VMPA_NO_PHYSICAL, virtual);
}
/******************************************************************************
*                                                                             *
*  Paramètres  : addr   = localisation dont la définition est à consulter.    *
*                values = tableau d'éléments à compléter. [OUT]               *
*                count  = nombre de descriptions renseignées. [OUT]           *
*                                                                             *
*  Description : Décrit les colonnes utiles à un chargement de données.       *
*                                                                             *
*  Retour      : Bilan de l'opération.                                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
bool setup_load_for_vmpa(const vmpa2t *addr, bound_value **values, size_t *count)
{
    bound_value *value;                     /* Valeur à éditer / définir   */
    (*count) += 2;
    *values = (bound_value *)realloc(*values, (*count) * sizeof(bound_value));
    value = &(*values)[*count - 2];
    value->name = "phys";
    value->type = SQLITE_NATIVE;
    value = &(*values)[*count - 1];
    value->name = "virt";
    value->type = SQLITE_NATIVE;
    return true;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : addr   = localisation dont la définition est à définir.      *
*                values = tableau d'éléments à consulter.                     *
*                count  = nombre de descriptions renseignées.                 *
*                                                                             *
*  Description : Charge les valeurs utiles pour une localisation.             *
*                                                                             *
*  Retour      : Bilan de l'opération.                                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
bool load_vmpa(vmpa2t *addr, const bound_value *values, size_t count)
{
    const bound_value *value;               /* Valeur à intégrer           */
    value = find_bound_value(values, count, "phys");
    if (value == NULL) return false;
    switch (value->type)
    {
        case SQLITE_INT64:
            addr->physical = value->integer64;
            break;
        case SQLITE_NULL:
            addr->physical = VMPA_NO_PHYSICAL;
            break;
        default:
            return false;
            break;
    }
    value = find_bound_value(values, count, "virt");
    if (value == NULL) return false;
    switch (value->type)
    {
        case SQLITE_INT64:
            addr->virtual = value->integer64;
            break;
        case SQLITE_NULL:
            addr->virtual = VMPA_NO_VIRTUAL;
            break;
        default:
            return false;
            break;
    }
    return true;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : addr   = adresse virtuelle ou physique à traiter.            *
*                values = couples de champs et de valeurs à lier. [OUT]       *
*                count  = nombre de ces couples. [OUT]                        *
*                                                                             *
*  Description : Constitue les champs destinés à une insertion / modification.*
*                                                                             *
*  Retour      : Bilan de l'opération : succès ou non.                        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
bool prepare_vmpa_db_statement(const vmpa2t *addr, bound_value **values, size_t *count)
{
    bound_value *value;                     /* Valeur à éditer / définir   */
    *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value));
    value = &(*values)[*count - 1];
    value->name = "phys";
    if (addr->physical != VMPA_NO_PHYSICAL)
    {
        value->type = SQLITE_INT64;
        value->integer64 = addr->physical;
    }
    else
    {
        value->type = SQLITE_NULL;
    }
    *values = (bound_value *)realloc(*values, ++(*count) * sizeof(bound_value));
    value = &(*values)[*count - 1];
    value->name = "virt";
    if (addr->virtual != VMPA_NO_VIRTUAL)
    {
        value->type = SQLITE_INT64;
        value->integer64 = addr->virtual;
    }
    else
    {
        value->type = SQLITE_NULL;
    }
    return true;
}
/* ---------------------------------------------------------------------------------- */
/*                          AIDES FONCTIONNELLES AUXILIAIRES                          */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
*                                                                             *
*  Paramètres  : label  = désignation humaine d'unn symbole de base.          *
*                offset = décalage déterminé à faie apparaître au besoin.     *
*                                                                             *
*  Description : Construit une désignation de symbole avec décalage.          *
*                                                                             *
*  Retour      : Chaîne de caractères constituée à libérer après usage.       *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
char *make_symbol_offset(const char *label, phys_t offset)
{
    char *result;                           /* Construction à retourner    */
    size_t length;                          /* Taille de désignation créée */
    if (offset == 0)
        result = strdup(label);
    else
    {
        length = strlen(label) + 1 + VMPA_MAX_LEN + 1;
        result = (char *)calloc(length, sizeof(char));
        snprintf(result, length, "%s+0x%llx", label, (unsigned long long)offset);
    }
    return result;
}
/* ---------------------------------------------------------------------------------- */
/*                          DEFINITION D'UNE ZONE EN MEMOIRE                          */
/* ---------------------------------------------------------------------------------- */
/******************************************************************************
*                                                                             *
*  Paramètres  : range  = plage à initialiser. [OUT]                          *
*                addr   = position de départ dans la mémoire.                 *
*                length = taille de la plage à constituer.                    *
*                                                                             *
*  Description : Initialise une plage dans l'espace mémoire/physique.         *
*                                                                             *
*  Retour      : Place définie en mémoire.                                    *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void init_mrange(mrange_t *range, const vmpa2t *addr, phys_t length)
{
    copy_vmpa(&range->addr, addr);
    range->length = length;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : dest = structure de destination pour la copie.               *
*                src  = structure de source pour la copie.                    *
*                                                                             *
*  Description : Copie la définition d'une plage mémoire dans une autre.      *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void copy_mrange(mrange_t *dest, const mrange_t *src)
{
    copy_vmpa(&dest->addr, &src->addr);
    dest->length = src->length;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : a = première définition à analyser.                          *
*                b = seconde définition à analyser.                           *
*                                                                             *
*  Description : Compare deux couvertures mémoire selon leurs propriétés.     *
*                                                                             *
*  Retour      : Bilan de la comparaison : -1, 0 ou 1 (-1 par défaut).        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
int cmp_mrange(const mrange_t *a, const mrange_t *b)
{
    int result;                             /* Bilan à retourner           */
    result = cmp_vmpa(&a->addr, &b->addr);
    if (result == 0)
    {
        if (a->length < b->length)
            result = -1;
        else if (a->length > b->length)
            result = 1;
        else
            result = 0;
    }
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : a = première définition à analyser.                          *
*                b = seconde définition à analyser.                           *
*                                                                             *
*  Description : Compare une couverture mémoire avec une localisation simple. *
*                                                                             *
*  Retour      : Bilan de la comparaison : -1, 0 ou 1 (-1 par défaut).        *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
int cmp_mrange_with_vmpa(const mrange_t *a, const vmpa2t *b)
{
    int result;                             /* Bilan à retourner           */
    phys_t diff;                            /* Espace entre deux adresses  */
    result = cmp_vmpa(b, &a->addr);
    if (result >= 0)
    {
        diff = compute_vmpa_diff(&a->addr, b);
        /**
         * On prend en compte le cas très particulier des couvertures vides.
         *
         * C'est typiquement le cas avec les espaces de symboles pendant la
         * phase de désassemblage, après laquelle ces espaces deviennent bornés.
         *
         */
        if (diff == 0 && a->length == 0)
            result = 0;
        /**
         * Sinon on regarde simplement si l'adresse est contenue.
         */
        else if (diff < a->length)
            result = 0;
        else
            result = 1;
    }
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : range = zone mémoire à consulter.                            *
*                sub   = éventuelle sous-région à valider.                    *
*                                                                             *
*  Description : Indique si une zone en contient une autre ou non.            *
*                                                                             *
*  Retour      : Bilan de la consultation.                                    *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
bool mrange_contains_mrange(const mrange_t *range, const mrange_t *sub)
{
    bool result;                            /* Bilan à retourner           */
    phys_t start;                           /* Point de départ             */
    result = mrange_contains_addr(range, get_mrange_addr(sub));
    if (result)
    {
        start = compute_vmpa_diff(get_mrange_addr(range), get_mrange_addr(sub));
        result = (start + get_mrange_length(sub) <= get_mrange_length(range));
    }
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : range = zone mémoire à consulter.                            *
*                addr  = localisation mémoire à analyser.                     *
*                                                                             *
*  Description : Indique si une localisation est incluse dans une zone ou non.*
*                                                                             *
*  Retour      : Bilan de la consultation.                                    *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
bool mrange_contains_addr(const mrange_t *range, const vmpa2t *addr)
{
    bool result;                            /* Bilan à retourner           */
    int ret;                                /* Bilan d'une comparaison     */
    phys_t diff;                            /* Espace entre deux adresses  */
    ret = cmp_vmpa(&range->addr, addr);
    if (ret < 0)
    {
        diff = compute_vmpa_diff(&range->addr, addr);
        if (diff != VMPA_NO_PHYSICAL)
            result = (diff < range->length);
        else
            result = false;
    }
    else if (ret == 0)
        result = true;
    else
        result = false;
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : range = zone mémoire à consulter.                            *
*                addr  = localisation mémoire à analyser.                     *
*                                                                             *
*  Description : Indique si une localisation est incluse dans une zone ou non.*
*                                                                             *
*  Retour      : Bilan de la consultation.                                    *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
bool mrange_contains_addr_inclusive(const mrange_t *range, const vmpa2t *addr)
{
    bool result;                            /* Bilan à retourner           */
    int ret;                                /* Bilan d'une comparaison     */
    phys_t diff;                            /* Espace entre deux adresses  */
    ret = cmp_vmpa(&range->addr, addr);
    if (ret <= -1)
    {
        diff = compute_vmpa_diff(&range->addr, addr);
        if (diff != VMPA_NO_PHYSICAL)
            result = (diff <= range->length);
        else
            result = false;
    }
    else if (ret == 0)
        result = true;
    else
        result = false;
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : range = zone mémoire à consulter.                            *
*                other = autre zone mémoire à manipuler.                      *
*                                                                             *
*  Description : Détermine si deux zones mémoire se chevauchent ou non.       *
*                                                                             *
*  Retour      : Bilan de la consultation.                                    *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
bool mrange_intersects_mrange(const mrange_t *range, const mrange_t *other)
{
    bool result;                            /* Bilan à retourner           */
    vmpa2t end;                             /* Fin d'une zone mémoire      */
    result = false;
    result |= mrange_contains_addr(range, &other->addr);
    result |= mrange_contains_addr(other, &range->addr);
    if (get_mrange_length(other) > 0)
    {
        compute_mrange_end_addr(other, &end);
        deminish_vmpa(&end, 1);
        result |= mrange_contains_addr(range, &end);
    }
    if (get_mrange_length(range) > 0)
    {
        compute_mrange_end_addr(range, &end);
        deminish_vmpa(&end, 1);
        result |= mrange_contains_addr(other, &end);
    }
    return result;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : range = zone mémoire à consulter.                            *
*                addr  = localisation mémoire à déterminer.                   *
*                                                                             *
*  Description : Calcule la position extérieure finale d'une couverture.      *
*                                                                             *
*  Retour      : -                                                            *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
void compute_mrange_end_addr(const mrange_t *range, vmpa2t *addr)
{
    copy_vmpa(addr, &range->addr);
    advance_vmpa(addr, range->length);
}
/******************************************************************************
*                                                                             *
*  Paramètres  : rane   = emplacement virtuel ou physique à traiter.          *
*                msize  = taille de cette adresse, réelle ou désirée.         *
*                start  = indique si le début ou la fin est à imprimer.       *
*                buffer = tampon de sortie utilisé à constituer. [OUT]        *
*                length = transmission de la taille du résultat ou NULL. [OUT]*
*                                                                             *
*  Description : Transforme un emplacement physique en chaîne de caractères.  *
*                                                                             *
*  Retour      : Chaîne de caractères constituée.                             *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
char *mrange_phys_to_string(const mrange_t *range, MemoryDataSize msize, bool start, char buffer[VMPA_MAX_LEN], size_t *length)
{
    vmpa2t tmp;
    if (start)
        vmpa2_phys_to_string(&range->addr, msize, buffer, length);
    else
    {
        copy_vmpa(&tmp, &range->addr);
        advance_vmpa(&tmp, range->length);
        vmpa2_phys_to_string(&tmp, msize, buffer, length);
    }
    return buffer;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : rane   = emplacement virtuel ou physique à traiter.          *
*                msize  = taille de cette adresse, réelle ou désirée.         *
*                start  = indique si le début ou la fin est à imprimer.       *
*                buffer = tampon de sortie utilisé à constituer. [OUT]        *
*                length = transmission de la taille du résultat ou NULL. [OUT]*
*                                                                             *
*  Description : Transforme un emplacement virtuel en chaîne de caractères.   *
*                                                                             *
*  Retour      : Chaîne de caractères constituée.                             *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
char *mrange_virt_to_string(const mrange_t *range, MemoryDataSize msize, bool start, char buffer[VMPA_MAX_LEN], size_t *length)
{
    vmpa2t tmp;
    if (start)
        vmpa2_virt_to_string(&range->addr, msize, buffer, length);
    else
    {
        copy_vmpa(&tmp, &range->addr);
        advance_vmpa(&tmp, range->length);
        vmpa2_virt_to_string(&tmp, msize, buffer, length);
    }
    return buffer;
}
/******************************************************************************
*                                                                             *
*  Paramètres  : rane   = emplacement virtuel ou physique à traiter.          *
*                msize  = taille de cette adresse, réelle ou désirée.         *
*                buffer = tampon de sortie utilisé à constituer. [OUT]        *
*                length = transmission de la taille du résultat ou NULL. [OUT]*
*                                                                             *
*  Description : Transforme une taille d'emplacement en chaîne de caractères. *
*                                                                             *
*  Retour      : Chaîne de caractères constituée.                             *
*                                                                             *
*  Remarques   : -                                                            *
*                                                                             *
******************************************************************************/
char *mrange_length_to_string(const mrange_t *range, MemoryDataSize msize, char buffer[VMPA_MAX_LEN], size_t *length)
{
    return _phys_t_to_string(range->length, msize, buffer, length);
}