diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2009-01-25 21:27:14 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2009-01-25 21:27:14 (GMT) |
commit | 21493170bb188ad9548820c830c3e8d7055e3f46 (patch) | |
tree | fdc4d03b0aaa5e7ed8a0b8b151926f654cece321 /src/format/java/pool.c | |
parent | 8f1e49332cd81760c98166be9df79a7136f5ca57 (diff) |
Supported the Java Class file format.
git-svn-id: svn://svn.gna.org/svn/chrysalide/trunk@46 abbe820e-26c8-41b2-8c08-b7b2b41f8b0a
Diffstat (limited to 'src/format/java/pool.c')
-rwxr-xr-x | src/format/java/pool.c | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/src/format/java/pool.c b/src/format/java/pool.c new file mode 100755 index 0000000..f735819 --- /dev/null +++ b/src/format/java/pool.c @@ -0,0 +1,354 @@ + +/* OpenIDA - Outil d'analyse de fichiers binaires + * pool.c - lecture du réservoir de constantes + * + * 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 <http://www.gnu.org/licenses/>. + */ + + +#include "pool.h" + + +#include <malloc.h> +#include <math.h> +#include <string.h> + +#include "java-int.h" +#include "../../common/endianness.h" + + + +/* Charge les propriétés d'une constante du réservoir. */ +bool load_java_pool_entry(java_format *, constant_pool_entry *, off_t *); + + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* pos = point de lecture à faire évoluer. [OUT] * +* * +* Description : Charge le réservoir de constantes d'un binaire Java. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_java_pool(java_format *format, off_t *pos) +{ + bool result; /* Bilan à remonter */ + uint16_t count; /* Nombre d'éléments présents */ + uint16_t i; /* Boucle de parcours */ + + result = read_u16(&count, EXE_FORMAT(format)->content, pos, + EXE_FORMAT(format)->length, SRE_BIG); + + format->pool_len = count - 1; + format->pool = (constant_pool_entry *)calloc(count - 1, sizeof(constant_pool_entry)); + + for (i = 1; i < count && result; i++) + { + result = load_java_pool_entry(format, &format->pool[i - 1], pos); + + if (format->pool[i - 1].tag == CONSTANT_LONG + || format->pool[i - 1].tag == CONSTANT_DOUBLE) + { + i++; + + /* On n'est jamais trop prudent */ + if (i < count) + format->pool[i - 1].tag = CONSTANT_EMPTY; + + } + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à vider. * +* * +* Description : Décharge le réservoir de constantes d'un binaire Java. * +* * +* Retour : - * +* * +* Remarques : - * +* * +******************************************************************************/ + +void unload_java_pool(java_format *format) +{ + uint16_t i; /* Boucle de parcours */ + + for (i = 0; i < format->pool_len; i++) + switch (format->pool[i].tag) + { + case CONSTANT_EMPTY: + case CONSTANT_CLASS: + case CONSTANT_FIELD_REF: + case CONSTANT_METHOD_REF: + case CONSTANT_INTERFACE_METHOD_REF: + case CONSTANT_STRING: + case CONSTANT_INTEGER: + case CONSTANT_FLOAT: + case CONSTANT_LONG: + case CONSTANT_DOUBLE: + case CONSTANT_NAME_AND_TYPE: + break; + + case CONSTANT_UTF8: + free(format->pool[i].info.utf8.bytes); + break; + + } + + free(format->pool); + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* entry = élément à spécifier. [OUT] * +* pos = point de lecture à faire évoluer. [OUT] * +* * +* Description : Charge les propriétés d'une constante du réservoir. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool load_java_pool_entry(java_format *format, constant_pool_entry *entry, off_t *pos) +{ + bool result; /* Bilan à retourner */ + uint8_t tag; /* Type de l'élément */ + uint32_t low_bytes; /* Octets de poids faible */ + uint32_t high_bytes; /* Octets de poids fort */ + uint64_t bits; /* Nombre lu sur 64 bits */ + int sign; /* Signe du nombre lu */ + int exponent; /* Exposant du nombre lu */ + uint64_t mantissa32; /* Mantisse du nombre lu 32b */ + uint64_t mantissa64; /* Mantisse du nombre lu 64b */ + uint16_t length; /* Taille d'une chaîne */ + + result = read_u8(&tag, EXE_FORMAT(format)->content, pos, + EXE_FORMAT(format)->length, SRE_BIG); + + entry->tag = tag; + + switch (entry->tag) + { + case CONSTANT_CLASS: + result = read_u16(&entry->info.class.name_index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + break; + + case CONSTANT_FIELD_REF: + case CONSTANT_METHOD_REF: + case CONSTANT_INTERFACE_METHOD_REF: + + result = read_u16(&entry->info.ref.class_index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + result &= read_u16(&entry->info.ref.name_and_type_index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + break; + + case CONSTANT_STRING: + result = read_u16(&entry->info.string.string_index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + break; + + case CONSTANT_INTEGER: + result = read_u32(&entry->info.int_val.val, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + break; + + case CONSTANT_FLOAT: + + result = read_u32(&low_bytes, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + if (result) + { + if (low_bytes == 0x7f800000) + entry->info.float_val.val = INFINITY; + + else if (low_bytes == 0xff800000) + entry->info.float_val.val = /* -1* */INFINITY; + + else if ((low_bytes >= 0x7f800001 && low_bytes <= 0x7fffffff) + || (low_bytes >= 0xff800001 && low_bytes <= 0xffffffff)) + entry->info.float_val.val = NAN; + + else if (low_bytes == 0x00000000 || low_bytes == 0x80000000) + entry->info.float_val.val = 0; + + else + { + sign = (low_bytes & 0x80000000) ? -1 : 1; + exponent = (low_bytes >> 23) & 0xff; + mantissa32 = (exponent == 0 ? + (low_bytes & 0x7fffff) << 1 : + (low_bytes & 0x7fffff) | 0x800000); + + entry->info.float_val.val = pow(2, (exponent - 150)); + entry->info.float_val.val *= mantissa32; + entry->info.float_val.val *= sign; + + } + + } + + break; + + case CONSTANT_LONG: + + result = read_u32(&high_bytes, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + result &= read_u32(&low_bytes, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + if (result) + { + entry->info.double_val.val = (uint64_t)high_bytes << 32; + entry->info.double_val.val += low_bytes; + } + + break; + + case CONSTANT_DOUBLE: + + result = read_u32(&high_bytes, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + result &= read_u32(&low_bytes, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + if (result) + { + bits = (uint64_t)high_bytes << 32 | (uint64_t)low_bytes; + + if (bits == 0x7ff0000000000000ll) + entry->info.double_val.val = INFINITY; + + else if (bits == 0xfff0000000000000ll) + entry->info.double_val.val = /* -1* */INFINITY; + + else if ((bits >= 0x7ff0000000000001ll && bits <= 0x7fffffffffffffffll) + || (bits >= 0xfff0000000000001ll && bits <= 0xffffffffffffffffll)) + entry->info.double_val.val = NAN; + + else if (bits == 0x0000000000000000ll || bits == 0x8000000000000000ll) + entry->info.double_val.val = 0; + + else + { + sign = ((bits >> 63) == 0) ? 1 : -1; + exponent = (bits >> 52) & 0x7ffl; + mantissa64 = (exponent == 0 ? + (bits & 0xfffffffffffffll) << 1 : + (bits & 0xfffffffffffffll) | 0x10000000000000ll); + + entry->info.double_val.val = pow(2, (exponent - 1075)); + entry->info.double_val.val *= mantissa64; + entry->info.double_val.val *= sign; + + } + + } + + break; + + case CONSTANT_NAME_AND_TYPE: + + result = read_u16(&entry->info.name_type.name_index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + result &= read_u16(&entry->info.name_type.descriptor_index, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + break; + + case CONSTANT_UTF8: + + result = read_u16(&length, EXE_FORMAT(format)->content, + pos, EXE_FORMAT(format)->length, SRE_BIG); + + if (result) + { + entry->info.utf8.bytes = (char *)calloc(length + 1, sizeof(char)); + memcpy(entry->info.utf8.bytes, &EXE_FORMAT(format)->content[*pos], length); + *pos += length; + } + + break; + + default: + result = false; + break; + + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : format = description de l'exécutable à compléter. * +* index = indice de l'élément dont la valeur est à recupérer. * +* str = adresse où placer la chaîne de caractères trouvée. * +* * +* Description : Recherche une chaîne de caractères dans le réservoir. * +* * +* Retour : true si l'opération s'est bien déroulée, false sinon. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool get_java_pool_ut8_string(java_format *format, uint16_t index, const char **str) +{ + bool result; /* Bilan à renvoyer */ + constant_pool_entry *entry; /* Entrée du réservoir visée */ + + result = (index <= format->pool_len); + + if (result) + { + entry = &format->pool[index - 1]; + + result = (entry->tag == CONSTANT_UTF8); + + if (result) + (*str) = entry->info.utf8.bytes; + + } + + return result; + +} |