/* Compare relevant content of two ELF files.
- Copyright (C) 2005, 2006, 2007, 2008, 2009 Red Hat, Inc.
+ Copyright (C) 2005-2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2005.
goto out;
}
+ size_t shnum1;
+ size_t shnum2;
+ if (unlikely (elf_getshdrnum (elf1, &shnum1) != 0))
+ error (2, 0, gettext ("cannot get section count of '%s': %s"),
+ fname1, elf_errmsg (-1));
+ if (unlikely (elf_getshdrnum (elf2, &shnum2) != 0))
+ error (2, 0, gettext ("cannot get section count of '%s': %s"),
+ fname2, elf_errmsg (-1));
+ if (unlikely (shnum1 != shnum2))
+ {
+ if (! quiet)
+ error (0, 0, gettext ("%s %s diff: section count"), fname1, fname2);
+ result = 1;
+ goto out;
+ }
+
+ size_t phnum1;
+ size_t phnum2;
+ if (unlikely (elf_getphdrnum (elf1, &phnum1) != 0))
+ error (2, 0, gettext ("cannot get program header count of '%s': %s"),
+ fname1, elf_errmsg (-1));
+ if (unlikely (elf_getphdrnum (elf2, &phnum2) != 0))
+ error (2, 0, gettext ("cannot get program header count of '%s': %s"),
+ fname2, elf_errmsg (-1));
+ if (unlikely (phnum1 != phnum2))
+ {
+ if (! quiet)
+ error (0, 0, gettext ("%s %s diff: program header count"),
+ fname1, fname2);
+ result = 1;
+ goto out;
+ }
+
/* Iterate over all sections. We expect the sections in the two
files to match exactly. */
Elf_Scn *scn1 = NULL;
ehdr_region.next = &phdr_region;
phdr_region.from = ehdr1->e_phoff;
- phdr_region.to = ehdr1->e_phoff + ehdr1->e_phnum * ehdr1->e_phentsize;
+ phdr_region.to = ehdr1->e_phoff + phnum1 * ehdr1->e_phentsize;
phdr_region.next = regions;
regions = &ehdr_region;
}
/* Compare the program header tables. */
- for (int ndx = 0; ndx < ehdr1->e_phnum; ++ndx)
+ for (unsigned int ndx = 0; ndx < phnum1; ++ndx)
{
GElf_Phdr phdr1_mem;
GElf_Phdr *phdr1 = gelf_getphdr (elf1, ndx, &phdr1_mem);
/* Pedantic checking of ELF files compliance with gABI/psABI spec.
- Copyright (C) 2001,2002,2003,2004,2005,2006,2007,2008,2009 Red Hat, Inc.
+ Copyright (C) 2001-2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2001.
(sizeof (valid_e_machine) / sizeof (valid_e_machine[0]))
-/* Number of sections. */
+/* Numbers of sections and program headers. */
static unsigned int shnum;
+static unsigned int phnum;
static void
ERROR (gettext ("invalid section header index\n"));
}
+ phnum = ehdr->e_phnum;
+ if (ehdr->e_phnum == PN_XNUM)
+ {
+ /* Get the header of the zeroth section. The sh_info field
+ might contain the phnum count. */
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
+ if (shdr != NULL)
+ {
+ /* The error will be reported later. */
+ if (shdr->sh_info < PN_XNUM)
+ ERROR (gettext ("\
+invalid number of program header table entries\n"));
+ else
+ phnum = shdr->sh_info;
+ }
+ }
+
/* Check the e_flags field. */
if (!ebl_machine_flag_check (ebl, ehdr->e_flags))
ERROR (gettext ("invalid machine flags: %s\n"),
if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf32_Phdr))
ERROR (gettext ("invalid program header size: %hd\n"),
ehdr->e_phentsize);
- else if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > size)
+ else if (ehdr->e_phoff + phnum * ehdr->e_phentsize > size)
ERROR (gettext ("invalid program header position or size\n"));
if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf32_Shdr))
ERROR (gettext ("invalid section header size: %hd\n"),
ehdr->e_shentsize);
- else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size)
+ else if (ehdr->e_shoff + shnum * ehdr->e_shentsize > size)
ERROR (gettext ("invalid section header position or size\n"));
}
else if (gelf_getclass (ebl->elf) == ELFCLASS64)
if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf64_Phdr))
ERROR (gettext ("invalid program header size: %hd\n"),
ehdr->e_phentsize);
- else if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > size)
+ else if (ehdr->e_phoff + phnum * ehdr->e_phentsize > size)
ERROR (gettext ("invalid program header position or size\n"));
if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf64_Shdr))
{
GElf_Phdr phdr_mem;
GElf_Phdr *phdr = NULL;
- int pcnt;
+ unsigned int pcnt;
- for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
+ for (pcnt = 0; pcnt < phnum; ++pcnt)
{
phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
if (phdr != NULL && phdr->p_type == PT_TLS)
break;
}
- if (pcnt == ehdr->e_phnum)
+ if (pcnt == phnum)
{
if (no_pt_tls++ == 0)
ERROR (gettext ("\
/* Check that address and size match the dynamic section.
We locate the dynamic section via the program header
entry. */
- for (int pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
+ for (unsigned int pcnt = 0; pcnt < phnum; ++pcnt)
{
GElf_Phdr phdr_mem;
GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
the loaded segments are and b) which are read-only. This will
also allow us to determine whether the same reloc section is
modifying loaded and not loaded segments. */
- for (int i = 0; i < ehdr->e_phnum; ++i)
+ for (unsigned int i = 0; i < phnum; ++i)
{
GElf_Phdr phdr_mem;
GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
case DT_VERNEED:
case DT_VERSYM:
check_addr:
- for (n = 0; n < ehdr->e_phnum; ++n)
+ for (n = 0; n < phnum; ++n)
{
GElf_Phdr phdr_mem;
GElf_Phdr *phdr = gelf_getphdr (ebl->elf, n, &phdr_mem);
&& phdr->p_vaddr + phdr->p_memsz > dyn->d_un.d_ptr)
break;
}
- if (unlikely (n >= ehdr->e_phnum))
+ if (unlikely (n >= phnum))
{
char buf[50];
ERROR (gettext ("\
static int
-unknown_dependency_p (Elf *elf, GElf_Ehdr *ehdr, const char *fname)
+unknown_dependency_p (Elf *elf, const char *fname)
{
GElf_Phdr phdr_mem;
GElf_Phdr *phdr = NULL;
- int i;
- for (i = 0; i < ehdr->e_phnum; ++i)
+ unsigned int i;
+ for (i = 0; i < phnum; ++i)
if ((phdr = gelf_getphdr (elf, i, &phdr_mem)) != NULL
&& phdr->p_type == PT_DYNAMIC)
break;
- if (i == ehdr->e_phnum)
+ if (i == phnum)
return 1;
assert (phdr != NULL);
Elf_Scn *scn = gelf_offscn (elf, phdr->p_offset);
static unsigned int nverneed;
static void
-check_verneed (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
+check_verneed (Ebl *ebl, GElf_Shdr *shdr, int idx)
{
if (++nverneed == 2)
ERROR (gettext ("more than one version reference section present\n"));
}
/* Check that there is a DT_NEEDED entry for the referenced library. */
- if (unknown_dependency_p (ebl->elf, ehdr, libname))
+ if (unknown_dependency_p (ebl->elf, libname))
ERROR (gettext ("\
section [%2d] '%s': entry %d references unknown dependency\n"),
idx, section_name (ebl, idx), cnt);
ERROR (gettext ("zeroth section has nonzero address\n"));
if (shdr->sh_offset != 0)
ERROR (gettext ("zeroth section has nonzero offset\n"));
- if (shdr->sh_info != 0)
- ERROR (gettext ("zeroth section has nonzero info field\n"));
if (shdr->sh_addralign != 0)
ERROR (gettext ("zeroth section has nonzero align value\n"));
if (shdr->sh_entsize != 0)
if (shdr->sh_link != 0 && ehdr->e_shstrndx != SHN_XINDEX)
ERROR (gettext ("\
zeroth section has nonzero link value while ELF header does not signal overflow in shstrndx\n"));
+
+ if (shdr->sh_info != 0 && ehdr->e_phnum != PN_XNUM)
+ ERROR (gettext ("\
+zeroth section has nonzero link value while ELF header does not signal overflow in phnum\n"));
}
- int *segment_flags = xcalloc (ehdr->e_phnum, sizeof segment_flags[0]);
+ int *segment_flags = xcalloc (phnum, sizeof segment_flags[0]);
bool dot_interp_section = false;
{
/* Make sure the section is contained in a loaded segment
and that the initialization part matches NOBITS sections. */
- int pcnt;
+ unsigned int pcnt;
GElf_Phdr phdr_mem;
GElf_Phdr *phdr;
- for (pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
+ for (pcnt = 0; pcnt < phnum; ++pcnt)
if ((phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem)) != NULL
&& ((phdr->p_type == PT_LOAD
&& (shdr->sh_flags & SHF_TLS) == 0)
break;
}
- if (pcnt == ehdr->e_phnum)
+ if (pcnt == phnum)
ERROR (gettext ("\
section [%2zu] '%s': alloc flag set but section not in any loaded segment\n"),
cnt, section_name (ebl, cnt));
break;
case SHT_GNU_verneed:
- check_verneed (ebl, ehdr, shdr, cnt);
+ check_verneed (ebl, shdr, cnt);
break;
case SHT_GNU_verdef:
ERROR (gettext ("INTERP program header entry but no .interp section\n"));
if (!is_debuginfo)
- for (int pcnt = 0; pcnt < ehdr->e_phnum; ++pcnt)
+ for (unsigned int pcnt = 0; pcnt < phnum; ++pcnt)
{
GElf_Phdr phdr_mem;
GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
int num_pt_tls = 0;
int num_pt_relro = 0;
- for (int cnt = 0; cnt < ehdr->e_phnum; ++cnt)
+ for (unsigned int cnt = 0; cnt < phnum; ++cnt)
{
GElf_Phdr phdr_mem;
GElf_Phdr *phdr;
else
{
/* Check that the region is in a writable segment. */
- int inner;
- for (inner = 0; inner < ehdr->e_phnum; ++inner)
+ unsigned int inner;
+ for (inner = 0; inner < phnum; ++inner)
{
GElf_Phdr phdr2_mem;
GElf_Phdr *phdr2;
}
}
- if (inner >= ehdr->e_phnum)
+ if (inner >= phnum)
ERROR (gettext ("\
%s segment not contained in a loaded segment\n"), "GNU_RELRO");
}
else if (phdr->p_type == PT_PHDR)
{
/* Check that the region is in a writable segment. */
- int inner;
- for (inner = 0; inner < ehdr->e_phnum; ++inner)
+ unsigned int inner;
+ for (inner = 0; inner < phnum; ++inner)
{
GElf_Phdr phdr2_mem;
GElf_Phdr *phdr2;
break;
}
- if (inner >= ehdr->e_phnum)
+ if (inner >= phnum)
ERROR (gettext ("\
%s segment not contained in a loaded segment\n"), "PHDR");