summaryrefslogtreecommitdiffstats
path: root/src/readelf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/readelf.c')
-rw-r--r--src/readelf.c287
1 files changed, 91 insertions, 196 deletions
diff --git a/src/readelf.c b/src/readelf.c
index 9fbc24d6..135abe36 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -2320,194 +2320,6 @@ handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
}
-static void
-print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
- uint_fast32_t maxlength, Elf32_Word nbucket,
- uint_fast32_t nsyms, uint32_t *lengths)
-{
- uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1, sizeof (uint32_t));
-
- for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
- ++counts[lengths[cnt]];
-
- GElf_Shdr glink;
- printf (ngettext ("\
-\nHistogram for bucket list length in section [%2u] '%s' (total of %d bucket):\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
- "\
-\nHistogram for bucket list length in section [%2u] '%s' (total of %d buckets):\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
- nbucket),
- (unsigned int) elf_ndxscn (scn),
- elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
- (int) nbucket,
- gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
- shdr->sh_addr,
- shdr->sh_offset,
- (unsigned int) shdr->sh_link,
- elf_strptr (ebl->elf, shstrndx,
- gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
- &glink)->sh_name));
-
- if (nbucket > 0)
- {
- uint64_t success = 0;
-
- fputs_unlocked (gettext ("\
- Length Number % of total Coverage\n"), stdout);
- printf (gettext (" 0 %6" PRIu32 " %5.1f%%\n"),
- counts[0], (counts[0] * 100.0) / nbucket);
-
- uint64_t nzero_counts = 0;
- for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
- {
- nzero_counts += counts[cnt] * cnt;
- printf (gettext ("\
-%7d %6" PRIu32 " %5.1f%% %5.1f%%\n"),
- (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
- (nzero_counts * 100.0) / nsyms);
- }
-
- Elf32_Word acc = 0;
- for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
- {
- acc += cnt;
- success += counts[cnt] * acc;
- }
-
- printf (gettext ("\
- Average number of tests: successful lookup: %f\n\
- unsuccessful lookup: %f\n"),
- (double) success / (double) nzero_counts,
- (double) nzero_counts / (double) nbucket);
- }
-
- free (counts);
-}
-
-
-/* This function handles the traditional System V-style hash table format. */
-static void
-handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
-{
- Elf_Data *data = elf_getdata (scn, NULL);
- if (data == NULL)
- {
- error (0, 0, gettext ("cannot get data for section %d: %s"),
- (int) elf_ndxscn (scn), elf_errmsg (-1));
- return;
- }
-
- Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
- Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
- Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
- Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
-
- uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
-
- uint_fast32_t maxlength = 0;
- uint_fast32_t nsyms = 0;
- for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
- {
- Elf32_Word inner = bucket[cnt];
- while (inner > 0 && inner < nchain)
- {
- ++nsyms;
- if (maxlength < ++lengths[cnt])
- ++maxlength;
-
- inner = chain[inner];
- }
- }
-
- print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
- lengths);
-
- free (lengths);
-}
-
-
-/* This function handles the incorrect, System V-style hash table
- format some 64-bit architectures use. */
-static void
-handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
-{
- Elf_Data *data = elf_getdata (scn, NULL);
- if (data == NULL)
- {
- error (0, 0, gettext ("cannot get data for section %d: %s"),
- (int) elf_ndxscn (scn), elf_errmsg (-1));
- return;
- }
-
- Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
- Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
- Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
- Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
-
- uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
-
- uint_fast32_t maxlength = 0;
- uint_fast32_t nsyms = 0;
- for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
- {
- Elf64_Xword inner = bucket[cnt];
- while (inner > 0 && inner < nchain)
- {
- ++nsyms;
- if (maxlength < ++lengths[cnt])
- ++maxlength;
-
- inner = chain[inner];
- }
- }
-
- print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
- lengths);
-
- free (lengths);
-}
-
-
-/* This function handles the GNU-style hash table format. */
-static void
-handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
-{
- Elf_Data *data = elf_getdata (scn, NULL);
- if (data == NULL)
- {
- error (0, 0, gettext ("cannot get data for section %d: %s"),
- (int) elf_ndxscn (scn), elf_errmsg (-1));
- return;
- }
-
- Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
- Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
- Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
- Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + 2 * nbucket];
-
- uint32_t *lengths = (uint32_t *) xcalloc (nbucket, sizeof (uint32_t));
-
- uint_fast32_t maxlength = 0;
- uint_fast32_t nsyms = 0;
- for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
- if (bucket[2 * cnt + 1] != 0)
- {
- Elf32_Word inner = bucket[2 * cnt + 1] - symbias;
- do
- {
- ++nsyms;
- if (maxlength < ++lengths[cnt])
- ++maxlength;
- }
- while ((chain[inner++] & 1) == 0);
- }
-
- print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
- lengths);
-
- free (lengths);
-}
-
-
/* Find the symbol table(s). For this we have to search through the
section table. */
static void
@@ -2526,17 +2338,100 @@ handle_hash (Ebl *ebl)
GElf_Shdr shdr_mem;
GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
- if (shdr != NULL)
+ if (shdr != NULL && shdr->sh_type == SHT_HASH)
{
- if (shdr->sh_type == SHT_HASH)
+ Elf_Data *data = elf_getdata (scn, NULL);
+ if (data == NULL)
{
- if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
- handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
- else
- handle_sysv_hash (ebl, scn, shdr, shstrndx);
+ error (0, 0, gettext ("cannot get data for section %d: %s"),
+ (int) elf_ndxscn (scn), elf_errmsg (-1));
+ continue;
}
- else if (shdr->sh_type == SHT_GNU_HASH)
- handle_gnu_hash (ebl, scn, shdr, shstrndx);
+
+ Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
+ Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
+ Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
+ Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
+
+ GElf_Shdr glink;
+ printf (ngettext ("\
+\nHistogram for bucket list length in section [%2u] '%s' (total of %d bucket):\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
+ "\
+\nHistogram for bucket list length in section [%2u] '%s' (total of %d buckets):\n Addr: %#0*" PRIx64 " Offset: %#08" PRIx64 " Link to section: [%2u] '%s'\n",
+ nbucket),
+ (unsigned int) elf_ndxscn (scn),
+ elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
+ (int) nbucket,
+ gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
+ shdr->sh_addr,
+ shdr->sh_offset,
+ (unsigned int) shdr->sh_link,
+ elf_strptr (ebl->elf, shstrndx,
+ gelf_getshdr (elf_getscn (ebl->elf,
+ shdr->sh_link),
+ &glink)->sh_name));
+
+ uint32_t *lengths = (uint32_t *) xcalloc (nbucket,
+ sizeof (uint32_t));
+
+ Elf32_Word maxlength = 0;
+ Elf32_Word nsyms = 0;
+ for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
+ if (bucket[cnt] != 0)
+ {
+ Elf32_Word inner = bucket[cnt];
+ while (inner > 0 && inner < nchain)
+ {
+ ++nsyms;
+ if (maxlength < ++lengths[cnt])
+ ++maxlength;
+
+ inner = chain[inner];
+ }
+ }
+
+ uint32_t *counts = (uint32_t *) xcalloc (maxlength + 1,
+ sizeof (uint32_t));
+
+ for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
+ ++counts[lengths[cnt]];
+
+ if (nbucket > 0)
+ {
+ uint64_t success = 0;
+
+ fputs_unlocked (gettext ("\
+ Length Number % of total Coverage\n"), stdout);
+ printf (gettext (" 0 %6" PRIu32 " %5.1f%%\n"),
+ counts[0], (counts[0] * 100.0) / nbucket);
+
+ uint64_t nzero_counts = 0;
+ for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
+ {
+ nzero_counts += counts[cnt] * cnt;
+ printf (gettext ("\
+%7d %6" PRIu32 " %5.1f%% %5.1f%%\n"),
+ (int) cnt,
+ counts[cnt], (counts[cnt] * 100.0) / nbucket,
+ (nzero_counts * 100.0) / nsyms);
+ }
+
+ Elf32_Word acc = 0;
+ for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
+ {
+ acc += cnt;
+ success += counts[cnt] * acc;
+ }
+
+ printf (gettext ("\
+ Average number of tests: successful lookup: %f\n\
+ unsuccessful lookup: %f\n"),
+ (double) success / (double) nzero_counts,
+ (double) nzero_counts / (double) nbucket);
+ }
+
+ free (counts);
+ free (lengths);
}
}
}