summaryrefslogtreecommitdiff
path: root/plugins/elf
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2020-02-08 00:21:49 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2020-02-08 00:21:49 (GMT)
commitbacf50f92fb497b201925b010cae78bf44584072 (patch)
tree1c7194ad080d6f3bb5746d78ce2aee0f8011c606 /plugins/elf
parent063383ee06a472515ddd39a071c449a7e34f5c6b (diff)
Counted Elf symbols using the DT_GNU_HASH dynamic item.
Diffstat (limited to 'plugins/elf')
-rw-r--r--plugins/elf/elf_def.h2
-rw-r--r--plugins/elf/symbols.c120
2 files changed, 108 insertions, 14 deletions
diff --git a/plugins/elf/elf_def.h b/plugins/elf/elf_def.h
index 355fa2f..915eb15 100644
--- a/plugins/elf/elf_def.h
+++ b/plugins/elf/elf_def.h
@@ -518,6 +518,8 @@ typedef union _elf_dyn
#define DT_PREINIT_ARRAYSZ 33 /* Taille de DT_PREINIT_ARRAY */
#define DT_NUM 34 /* Nombre utilisé */
+#define DT_GNU_HASH 0x6ffffef5 /* Table d'empreintes version GNU */
+
/* ---------------------------- SYMBOLES DE BINAIRES ELF ---------------------------- */
diff --git a/plugins/elf/symbols.c b/plugins/elf/symbols.c
index d90f4a5..26876bd 100644
--- a/plugins/elf/symbols.c
+++ b/plugins/elf/symbols.c
@@ -781,6 +781,13 @@ static bool count_elf_global_symbols(GElfFormat *format, GExeFormat *exec, uint3
elf_dyn hash; /* Table de type DT_HASH */
bool found; /* Détection validée */
vmpa2t addr; /* Position de départ brute */
+ uint32_t n_buckets; /* Quantité de bacs en place */
+ uint32_t sym_offset; /* Indice du premier symbole */
+ uint32_t bloom_size; /* Taille du filtre Bloom */
+ uint32_t last_symbol; /* Indice de dernier symbole */
+ uint32_t i; /* Boucle de parcours */
+ uint32_t start; /* Indice de départ d'un bac */
+ uint32_t value; /* Valeur d'un maillon */
result = false;
@@ -790,22 +797,107 @@ static bool count_elf_global_symbols(GElfFormat *format, GExeFormat *exec, uint3
* - http://www.gabriel.urdhr.fr/2015/09/28/elf-file-format/#symbol-tables
* - http://www.sco.com/developers/gabi/latest/ch5.dynamic.html#hash
*
+ * Le fonctionnement global des chaînes est décrit ici :
+ *
+ * - https://flapenguin.me/2017/04/24/elf-lookup-dt-hash/
+ *
+ * Celui des chaînes GNU fait l'objet de l'article suivant :
+ *
+ * - https://flapenguin.me/2017/05/10/elf-lookup-dt-gnu-hash/
+ *
*/
+ /* Méthode DT_HASH */
+
found = find_elf_dynamic_item_by_type(format, DT_HASH, &hash);
- if (!found) goto cegs_exit;
- exec = G_EXE_FORMAT(format);
+ if (found)
+ {
+ result = g_exe_format_translate_address_into_vmpa(exec, ELF_DYN(format, hash, d_un.d_ptr), &addr);
+ if (!result) goto exit;
+
+ advance_vmpa(&addr, sizeof(uint32_t));
+
+ result = g_binary_content_read_u32(G_BIN_FORMAT(format)->content, &addr, format->endian, count);
+ if (!result) goto exit;
+
+ goto exit;
+
+ }
- result = g_exe_format_translate_address_into_vmpa(exec, ELF_DYN(format, hash, d_un.d_ptr), &addr);
- if (!result) goto cegs_exit;
+ /* Méthode DT_GNU_HASH */
- advance_vmpa(&addr, 4);
+ found = find_elf_dynamic_item_by_type(format, DT_GNU_HASH, &hash);
- result = g_binary_content_read_u32(G_BIN_FORMAT(format)->content, &addr, format->endian, count);
- if (!result) goto cegs_exit;
+ if (found)
+ {
+ result = g_exe_format_translate_address_into_vmpa(exec, ELF_DYN(format, hash, d_un.d_ptr), &addr);
+ if (!result) goto exit;
+
+ result = g_binary_content_read_u32(G_BIN_FORMAT(format)->content, &addr, format->endian, &n_buckets);
+ if (!result) goto exit;
+
+ result = g_binary_content_read_u32(G_BIN_FORMAT(format)->content, &addr, format->endian, &sym_offset);
+ if (!result) goto exit;
+
+ result = g_binary_content_read_u32(G_BIN_FORMAT(format)->content, &addr, format->endian, &bloom_size);
+ if (!result) goto exit;
+
+ /* Saut de bloom_shift */
+ advance_vmpa(&addr, sizeof(uint32_t));
+
+ /* Saut de bloom[bloom_size] */
+ if (format->is_32b)
+ advance_vmpa(&addr, bloom_size * sizeof(uint32_t));
+ else
+ advance_vmpa(&addr, bloom_size * sizeof(uint64_t));
+
+ /* Localisation de la chaîne comportant le plus grand index */
+
+ last_symbol = 0;
+
+ for (i = 0; i < n_buckets; i++)
+ {
+ result = g_binary_content_read_u32(G_BIN_FORMAT(format)->content, &addr, format->endian, &start);
+ if (!result) goto exit;
+
+ if (last_symbol < start)
+ last_symbol = start;
+
+ }
+
+ if (last_symbol < sym_offset)
+ {
+ *count = sym_offset;
+ result = true;
+ }
+
+ else
+ {
+ /* Parcours de la chaîne au plus haut potentiel */
+
+ advance_vmpa(&addr, (last_symbol - sym_offset) * sizeof(uint32_t));
+
+ while (true)
+ {
+ result = g_binary_content_read_u32(G_BIN_FORMAT(format)->content, &addr, format->endian, &value);
+ if (!result) goto exit;
+
+ last_symbol++;
+
+ if (value & 0x1)
+ break;
+
+ }
+
+ *count = last_symbol;
+ result = true;
+
+ }
+
+ }
- cegs_exit:
+ exit:
return result;
@@ -851,23 +943,23 @@ static bool load_elf_global_symbols(GElfFormat *format, wgroup_id_t gid, GtkStat
/* Récupération du début des chaînes de description */
result = find_elf_dynamic_item_by_type(format, DT_STRTAB, &strtab);
- if (!result) goto lees_exit;
+ if (!result) goto exit;
result = g_exe_format_translate_address_into_offset(exec, ELF_DYN(format, strtab, d_un.d_ptr), &str_start);
- if (!result) goto lees_exit;
+ if (!result) goto exit;
/* Récupération du début des définitions de symboles */
result = find_elf_dynamic_item_by_type(format, DT_SYMTAB, &symtab);
- if (!result) goto lees_exit;
+ if (!result) goto exit;
result = g_exe_format_translate_address_into_offset(exec, ELF_DYN(format, symtab, d_un.d_ptr), &sym_start);
- if (!result) goto lees_exit;
+ if (!result) goto exit;
/* Détermination du nombre d'éléments */
result = count_elf_global_symbols(format, exec, &count);
- if (!result) goto lees_exit;
+ if (!result) goto exit;
/* Chargement des symboles */
@@ -882,7 +974,7 @@ static bool load_elf_global_symbols(GElfFormat *format, wgroup_id_t gid, GtkStat
gtk_status_stack_remove_activity(status, msg);
- lees_exit:
+ exit:
return result;