#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */
-#define GET_ELF_SYMBOLS(file, section) \
- (is_32bit_elf ? get_32bit_elf_symbols (file, section) \
- : get_64bit_elf_symbols (file, section))
+#define GET_ELF_SYMBOLS(file, section, sym_count) \
+ (is_32bit_elf ? get_32bit_elf_symbols (file, section, sym_count) \
+ : get_64bit_elf_symbols (file, section, sym_count))
#define VALID_DYNAMIC_NAME(offset) ((dynamic_strings != NULL) && (offset < dynamic_strings_length))
/* GET_DYNAMIC_NAME asssumes that VALID_DYNAMIC_NAME has
}
static Elf_Internal_Sym *
-get_32bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
+get_32bit_elf_symbols (FILE * file,
+ Elf_Internal_Shdr * section,
+ unsigned long * num_syms_return)
{
- unsigned long number;
+ unsigned long number = 0;
Elf32_External_Sym * esyms = NULL;
- Elf_External_Sym_Shndx * shndx;
+ Elf_External_Sym_Shndx * shndx = NULL;
Elf_Internal_Sym * isyms = NULL;
Elf_Internal_Sym * psym;
unsigned int j;
if (section->sh_entsize == 0)
{
error (_("sh_entsize is zero\n"));
- return NULL;
+ goto exit_point;
}
number = section->sh_size / section->sh_entsize;
if (number * sizeof (Elf32_External_Sym) > section->sh_size + 1)
{
error (_("Invalid sh_entsize\n"));
- return NULL;
+ goto exit_point;
}
esyms = (Elf32_External_Sym *) get_data (NULL, file, section->sh_offset, 1,
section->sh_size, _("symbols"));
if (esyms == NULL)
- return NULL;
+ goto exit_point;
shndx = NULL;
if (symtab_shndx_hdr != NULL
}
exit_point:
- if (shndx)
+ if (shndx != NULL)
free (shndx);
- if (esyms)
+ if (esyms != NULL)
free (esyms);
+ if (num_syms_return != NULL)
+ * num_syms_return = isyms == NULL ? 0 : number;
+
return isyms;
}
static Elf_Internal_Sym *
-get_64bit_elf_symbols (FILE * file, Elf_Internal_Shdr * section)
+get_64bit_elf_symbols (FILE * file,
+ Elf_Internal_Shdr * section,
+ unsigned long * num_syms_return)
{
- unsigned long number;
- Elf64_External_Sym * esyms;
- Elf_External_Sym_Shndx * shndx;
- Elf_Internal_Sym * isyms;
+ unsigned long number = 0;
+ Elf64_External_Sym * esyms = NULL;
+ Elf_External_Sym_Shndx * shndx = NULL;
+ Elf_Internal_Sym * isyms = NULL;
Elf_Internal_Sym * psym;
unsigned int j;
if (section->sh_entsize == 0)
{
error (_("sh_entsize is zero\n"));
- return NULL;
+ goto exit_point;
}
number = section->sh_size / section->sh_entsize;
if (number * sizeof (Elf64_External_Sym) > section->sh_size + 1)
{
error (_("Invalid sh_entsize\n"));
- return NULL;
+ goto exit_point;
}
esyms = (Elf64_External_Sym *) get_data (NULL, file, section->sh_offset, 1,
section->sh_size, _("symbols"));
if (!esyms)
- return NULL;
+ goto exit_point;
- shndx = NULL;
if (symtab_shndx_hdr != NULL
&& (symtab_shndx_hdr->sh_link
== (unsigned long) (section - section_headers)))
symtab_shndx_hdr->sh_offset,
1, symtab_shndx_hdr->sh_size,
_("symtab shndx"));
- if (!shndx)
- {
- free (esyms);
- return NULL;
- }
+ if (shndx == NULL)
+ goto exit_point;
}
isyms = (Elf_Internal_Sym *) cmalloc (number, sizeof (Elf_Internal_Sym));
if (isyms == NULL)
{
error (_("Out of memory\n"));
- if (shndx)
- free (shndx);
- free (esyms);
- return NULL;
+ goto exit_point;
}
- for (j = 0, psym = isyms;
- j < number;
- j++, psym++)
+ for (j = 0, psym = isyms; j < number; j++, psym++)
{
psym->st_name = BYTE_GET (esyms[j].st_name);
psym->st_info = BYTE_GET (esyms[j].st_info);
psym->st_other = BYTE_GET (esyms[j].st_other);
psym->st_shndx = BYTE_GET (esyms[j].st_shndx);
+
if (psym->st_shndx == (SHN_XINDEX & 0xffff) && shndx != NULL)
psym->st_shndx
= byte_get ((unsigned char *) &shndx[j], sizeof (shndx[j]));
else if (psym->st_shndx >= (SHN_LORESERVE & 0xffff))
psym->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff);
+
psym->st_value = BYTE_GET (esyms[j].st_value);
psym->st_size = BYTE_GET (esyms[j].st_size);
}
- if (shndx)
+ exit_point:
+ if (shndx != NULL)
free (shndx);
- free (esyms);
+ if (esyms != NULL)
+ free (esyms);
+
+ if (num_syms_return != NULL)
+ * num_syms_return = isyms == NULL ? 0 : number;
return isyms;
}
}
CHECK_ENTSIZE (section, i, Sym);
- num_dynamic_syms = section->sh_size / section->sh_entsize;
- dynamic_symbols = GET_ELF_SYMBOLS (file, section);
+ dynamic_symbols = GET_ELF_SYMBOLS (file, section, & num_dynamic_syms);
}
else if (section->sh_type == SHT_STRTAB
&& streq (name, ".dynstr"))
Elf_Internal_Shdr * symtab_sec;
Elf_Internal_Shdr * strtab_sec;
Elf_Internal_Sym * symtab;
+ unsigned long num_syms;
char * strtab;
size_t strtab_size;
symtab_sec = NULL;
strtab_sec = NULL;
symtab = NULL;
+ num_syms = 0;
strtab = NULL;
strtab_size = 0;
for (i = 0, section = section_headers, group = section_groups;
symtab_sec = sec;
if (symtab)
free (symtab);
- symtab = GET_ELF_SYMBOLS (file, symtab_sec);
+ symtab = GET_ELF_SYMBOLS (file, symtab_sec, & num_syms);
}
if (symtab == NULL)
continue;
}
+ if (section->sh_info >= num_syms)
+ {
+ error (_("Bad sh_info in group section `%s'\n"), name);
+ continue;
+ }
+
sym = symtab + section->sh_info;
if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
&& symsec->sh_type != SHT_DYNSYM)
continue;
- nsyms = symsec->sh_size / symsec->sh_entsize;
- symtab = GET_ELF_SYMBOLS (file, symsec);
+ symtab = GET_ELF_SYMBOLS (file, symsec, & nsyms);
if (symtab == NULL)
continue;
if (sec->sh_type == SHT_SYMTAB
&& sec->sh_link < elf_header.e_shnum)
{
- aux.nsyms = sec->sh_size / sec->sh_entsize;
- aux.symtab = GET_ELF_SYMBOLS (file, sec);
+ aux.symtab = GET_ELF_SYMBOLS (file, sec, & aux.nsyms);
strsec = section_headers + sec->sh_link;
assert (aux.strtab == NULL);
if (sec->sh_type == SHT_SYMTAB
&& sec->sh_link < elf_header.e_shnum)
{
- aux.nsyms = sec->sh_size / sec->sh_entsize;
- aux.symtab = GET_ELF_SYMBOLS (file, sec);
+ aux.symtab = GET_ELF_SYMBOLS (file, sec, & aux.nsyms);
strsec = section_headers + sec->sh_link;
assert (aux.strtab == NULL);
{
if (sec->sh_type == SHT_SYMTAB && sec->sh_link < elf_header.e_shnum)
{
- aux.nsyms = sec->sh_size / sec->sh_entsize;
- aux.symtab = GET_ELF_SYMBOLS (file, sec);
+ aux.symtab = GET_ELF_SYMBOLS (file, sec, & aux.nsyms);
strsec = section_headers + sec->sh_link;
assert (aux.strtab == NULL);
else
section.sh_entsize = sizeof (Elf64_External_Sym);
- num_dynamic_syms = section.sh_size / section.sh_entsize;
+ dynamic_symbols = GET_ELF_SYMBOLS (file, §ion, & num_dynamic_syms);
if (num_dynamic_syms < 1)
{
error (_("Unable to determine the number of symbols to load\n"));
continue;
}
-
- dynamic_symbols = GET_ELF_SYMBOLS (file, §ion);
}
}
char * strtab;
Elf_Internal_Sym * symbols;
Elf_Internal_Shdr * string_sec;
+ unsigned long num_syms;
long off;
if (section->sh_link >= elf_header.e_shnum)
found = 1;
- symbols = GET_ELF_SYMBOLS (file, link_section);
+ symbols = GET_ELF_SYMBOLS (file, link_section, & num_syms);
if (symbols == NULL)
break;
data[cnt + j] & VERSYM_HIDDEN ? 'h' : ' ');
/* If this index value is greater than the size of the symbols
- array, break to avoid an out-of-bounds read, */
- if ((unsigned long)(cnt + j) >=
- ((unsigned long)link_section->sh_size /
- (unsigned long)link_section->sh_entsize))
+ array, break to avoid an out-of-bounds read. */
+ if ((unsigned long)(cnt + j) >= num_syms)
{
warn (_("invalid index into symbol array\n"));
break;
unsigned long int strtab_size = 0;
Elf_Internal_Sym * symtab;
Elf_Internal_Sym * psym;
+ unsigned long num_syms;
if ((section->sh_type != SHT_SYMTAB
&& section->sh_type != SHT_DYNSYM)
else
printf (_(" Num: Value Size Type Bind Vis Ndx Name\n"));
- symtab = GET_ELF_SYMBOLS (file, section);
+ symtab = GET_ELF_SYMBOLS (file, section, & num_syms);
if (symtab == NULL)
continue;
strtab_size = strtab != NULL ? string_sec->sh_size : 0;
}
- for (si = 0, psym = symtab;
- si < section->sh_size / section->sh_entsize;
- si++, psym++)
+ for (si = 0, psym = symtab; si < num_syms; si++, psym++)
{
printf ("%6d: ", si);
print_vma (psym->st_value, LONG_HEX);
Elf_Internal_Rela * rp;
Elf_Internal_Shdr * symsec;
Elf_Internal_Sym * symtab;
+ unsigned long num_syms;
Elf_Internal_Sym * sym;
if ((relsec->sh_type != SHT_RELA && relsec->sh_type != SHT_REL)
is_rela = FALSE;
symsec = section_headers + relsec->sh_link;
- symtab = GET_ELF_SYMBOLS ((FILE *) file, symsec);
+ symtab = GET_ELF_SYMBOLS ((FILE *) file, symsec, & num_syms);
for (rp = relocs; rp < relocs + num_relocs; ++rp)
{
unsigned int reloc_type;
unsigned int reloc_size;
unsigned char * rloc;
+ unsigned long sym_index;
reloc_type = get_reloc_type (rp->r_info);
continue;
}
- sym = symtab + get_reloc_symindex (rp->r_info);
+ sym_index = (unsigned long) get_reloc_symindex (rp->r_info);
+ if (sym_index >= num_syms)
+ {
+ warn (_("skipping invalid relocation symbol index 0x%lx in section %s\n"),
+ sym_index, SECTION_NAME (section));
+ continue;
+ }
+ sym = symtab + sym_index;
/* If the reloc has a symbol associated with it,
make sure that it is of an appropriate type.