summaryrefslogtreecommitdiff
path: root/src/format/java/pool.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2009-01-25 21:27:14 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2009-01-25 21:27:14 (GMT)
commit21493170bb188ad9548820c830c3e8d7055e3f46 (patch)
treefdc4d03b0aaa5e7ed8a0b8b151926f654cece321 /src/format/java/pool.c
parent8f1e49332cd81760c98166be9df79a7136f5ca57 (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-xsrc/format/java/pool.c354
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;
+
+}