/* OpenIDA - Outil d'analyse de fichiers binaires
* demangler.c - décodage des noms d'éléments
*
* Copyright (C) 2008 Cyrille Bagard
*
* This file is part of OpenIDA.
*
* 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 "demangler.h"
#include
#include "demangler-int.h"
#include "itanium.h"
#include "java.h"
/* Prépare de quoi effectuer un décodage. */
typedef GDemanglingContext * (* create_context_fc) (void);
/* Procède au décodage d'une chaîne de caractères. */
typedef bool (* demangle_type_fc) (GDemanglingContext *, const char *);
/* Appels liés à un décodeur */
typedef struct _demangling_properties
{
create_context_fc create_context; /* Création de contextes */
demangle_type_fc demangle_routine; /* Décodage d'une routine */
demangle_type_fc demangle_type; /* Décodage d'un type */
} demangling_properties;
/* Liste des décodeurs */
static demangling_properties demanglers[DGT_COUNT] = {
[DGT_ITANIUM] = {
.create_context = (create_context_fc)g_itanium_dcontext_new,
.demangle_routine = (demangle_type_fc)demangle_itanium_routine,
.demangle_type = (demangle_type_fc)NULL
},
[DGT_JAVA] = {
.create_context = (create_context_fc)g_java_dcontext_new,
.demangle_routine = (demangle_type_fc)NULL,
.demangle_type = (demangle_type_fc)demangle_java_type
}
};
/******************************************************************************
* *
* Paramètres : type = identifiant du décodeur visé. *
* *
* Description : Fournit la référence correspondant à un décodeur donné. *
* *
* Retour : Adresse du décodeur trouvé ou NULL. *
* *
* Remarques : - *
* *
******************************************************************************/
name_demangler *get_demangler_by_type(DemanglerType type)
{
name_demangler *result; /* Adresse à retourner */
result = NULL;//demanglers[0];
return result;
}
/******************************************************************************
* *
* Paramètres : demangler = décodeur à utiliser. *
* name = chaîne de caractères à décoder. *
* *
* Description : Tente de décoder une chaîne de caractères donnée. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
GBinRoutine *try_to_demangle_routine(name_demangler *demangler, const char *name)
{
GBinRoutine *result; /* Construction à remonter */
result = NULL;
/*
if (demangler->can_be_demangled(demangler, name))
result = demangler->demangle_routine(demangler, name);
*/
return result;
}
/******************************************************************************
* *
* Paramètres : type = type de décodeur à utiliser. *
* desc = chaîne de caractères à décoder. *
* *
* Description : Tente de décoder une chaîne de caractères donnée. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
GBinRoutine *demangle_routine(DemanglerType type, const char *desc)
{
GBinRoutine *result; /* Construction à remonter */
GDemanglingContext *context; /* Contexte pour le décodage */
result = NULL;
/*
if (demangler->can_be_demangled(demangler, name))
result = demangler->demangle_routine(demangler, name);
*/
context = demanglers[type].create_context();
if (demanglers[type].demangle_routine(context, desc))
{
result = g_demangling_context_get_decoded_routine(context);
g_object_ref(result);
}
g_object_unref(context);
return result;
}
/******************************************************************************
* *
* Paramètres : type = type de décodeur à utiliser. *
* desc = chaîne de caractères à décoder. *
* *
* Description : Tente de décoder une chaîne de caractères donnée. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
GOpenidaType *demangle_type(DemanglerType type, const char *desc)
{
GOpenidaType *result; /* Construction à remonter */
GDemanglingContext *context; /* Contexte pour le décodage */
result = NULL;
/*
if (demangler->can_be_demangled(demangler, name))
result = demangler->demangle_routine(demangler, name);
*/
context = demanglers[type].create_context();
if (demanglers[type].demangle_type(context, desc))
{
result = g_demangling_context_get_decoded_type(context);
g_object_ref(result);
}
g_object_unref(context);
return result;
}
/******************************************************************************
* *
* Paramètres : - *
* *
* Description : Procède au test de décodages de chaînes de caractères. *
* *
* Retour : Bilan de l'opération. *
* *
* Remarques : - *
* *
******************************************************************************/
#ifdef DEBUG
void test_itanium_demangling(void)
{
GBinRoutine *routine;
char *human;
char stop;
#define TEST_ITANIUM_MANGLING(name, ref) \
do \
{ \
printf(" >> %s\n", name); \
routine = demangle_routine(DGT_ITANIUM, name); \
if (routine == NULL) \
{ \
printf("Error with %s\n", name); \
stop = true; \
} \
else \
{ \
human = g_binary_routine_to_string(routine); \
printf(" >> %s\n", human); \
stop = (strcmp(ref, human) != 0); \
printf(" >> ok ? %s\n", (!stop ? "oui" : "non")); \
if (stop) printf(" >> expected '%s'\n", ref); \
free(human); \
} \
if (stop) goto end_of_test; \
else printf("\n"); \
} \
while (0)
/**
* Tests de :
* http://www.codesourcery.com/public/cxx-abi/abi-examples.html#mangling
*/
TEST_ITANIUM_MANGLING("_Z1fv", "??? f(void)");
TEST_ITANIUM_MANGLING("_Z1fi", "??? f(int)");
TEST_ITANIUM_MANGLING("_Z3foo3bar", "??? foo(bar)");
TEST_ITANIUM_MANGLING("_Zrm1XS_", "??? %(X, X)");
TEST_ITANIUM_MANGLING("_ZplR1XS0_", "??? +(X &, X &)");
TEST_ITANIUM_MANGLING("_ZlsRK1XS1_", "??? <<(const X &, const X &)");
TEST_ITANIUM_MANGLING("_Z1fIiEvi", "void f(int)");
TEST_ITANIUM_MANGLING("_Z5firstI3DuoEvS0_", "void first(Duo)");
TEST_ITANIUM_MANGLING("_Z5firstI3DuoEvT_", "void first(Duo)");
TEST_ITANIUM_MANGLING("_Z3fooIiPFidEiEvv", "void foo(void)");
TEST_ITANIUM_MANGLING("_ZN6System5Sound4beepEv", "??? System::Sound::beep(void)");
TEST_ITANIUM_MANGLING("_Z1fI1XE vPV N1AIT_E1TE", "void f(volatile A::T *)");
//// TODO :: TEST_ITANIUM_MANGLING("_ZngILi42EE v N1A I XplT_Li2EE E 1TE", "");
TEST_ITANIUM_MANGLING("_Z4makeI7FactoryiE T_IT0_E v", "Factory make(void)");
TEST_ITANIUM_MANGLING("_ZlsRSoRKSs", "??? <<(std::ostream &, const std::string &)");
//TEST_ITANIUM_MANGLING("", "");
end_of_test:
;
}
#endif