#define grub_elfXX_load_phdrs grub_elf32_load_phdrs
#define ElfXX_Phdr Elf32_Phdr
#define ElfXX_Ehdr Elf32_Ehdr
+#define ElfXX_Shdr Elf32_Shdr
+#define ElfXX_Word Elf32_Word
+#define ElfXX_Shnum Elf32_Shnum
#define grub_uintXX_t grub_uint32_t
#define grub_swap_bytes_addrXX grub_swap_bytes32
#define grub_swap_bytes_offXX grub_swap_bytes32
#define grub_swap_bytes_XwordXX grub_swap_bytes32
#define grub_elfXX_check_endianess_and_bswap_ehdr grub_elf32_check_endianess_and_bswap_ehdr
+#define grub_elfXX_get_shnum grub_elf32_get_shnum
#include "elfXX.c"
#undef grub_elfXX_load_phdrs
#undef ElfXX_Phdr
#undef ElfXX_Ehdr
+#undef ElfXX_Shdr
+#undef ElfXX_Word
+#undef ElfXX_Shnum
#undef grub_uintXX_t
#undef grub_swap_bytes_addrXX
#undef grub_swap_bytes_offXX
#undef grub_swap_bytes_XwordXX
#undef grub_elfXX_check_endianess_and_bswap_ehdr
+#undef grub_elfXX_get_shnum
\f
/* 64-bit */
#define grub_elfXX_load_phdrs grub_elf64_load_phdrs
#define ElfXX_Phdr Elf64_Phdr
#define ElfXX_Ehdr Elf64_Ehdr
+#define ElfXX_Shdr Elf64_Shdr
+#define ElfXX_Word Elf64_Word
+#define ElfXX_Shnum Elf64_Shnum
#define grub_uintXX_t grub_uint64_t
#define grub_swap_bytes_addrXX grub_swap_bytes64
#define grub_swap_bytes_offXX grub_swap_bytes64
#define grub_swap_bytes_XwordXX grub_swap_bytes64
#define grub_elfXX_check_endianess_and_bswap_ehdr grub_elf64_check_endianess_and_bswap_ehdr
+#define grub_elfXX_get_shnum grub_elf64_get_shnum
#include "elfXX.c"
return 0;
}
+
+grub_err_t
+grub_elfXX_get_shnum (ElfXX_Ehdr *e, ElfXX_Shnum *shnum)
+{
+ ElfXX_Shdr *s;
+
+ if (shnum == NULL)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("NULL pointer passed for shnum"));
+
+ /* Set *shnum to 0 so that shnum doesn't return junk on error */
+ *shnum = 0;
+
+ if (e == NULL)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("NULL pointer passed for elf header"));
+
+ *shnum = e->e_shnum;
+ if (*shnum == SHN_UNDEF)
+ {
+ if (e->e_shoff == 0)
+ return grub_error (GRUB_ERR_BAD_NUMBER, N_("invalid section header table offset in e_shoff"));
+
+ s = (ElfXX_Shdr *) ((grub_uint8_t *) e + e->e_shoff);
+ *shnum = s->sh_size;
+ if (*shnum < SHN_LORESERVE)
+ return grub_error (GRUB_ERR_BAD_NUMBER, N_("invalid number of section header table entries in sh_size: %" PRIuGRUB_UINT64_T), (grub_uint64_t) *shnum);
+ }
+ else
+ {
+ if (*shnum >= SHN_LORESERVE)
+ return grub_error (GRUB_ERR_BAD_NUMBER, N_("invalid number of section header table entries in e_shnum: %" PRIuGRUB_UINT64_T), (grub_uint64_t) *shnum);
+ }
+
+ return GRUB_ERR_NONE;
+}
static inline grub_err_t
read_headers (grub_file_t file, const char *filename, Elf_Ehdr *e, Elf_Shdr **shdr)
{
- if (grub_file_seek (file, 0) == (grub_off_t) -1)
+ Elf_Shnum shnum;
+ grub_err_t err;
+
+ if (grub_file_seek (file, 0) == (grub_off_t) -1)
return grub_errno;
if (grub_file_read (file, (char *) e, sizeof (*e)) != sizeof (*e))
if (e->e_ident[EI_CLASS] != SUFFIX (ELFCLASS))
return grub_error (GRUB_ERR_BAD_OS, N_("invalid arch-dependent ELF magic"));
- *shdr = grub_calloc (e->e_shnum, e->e_shentsize);
+ err = grub_elf_get_shnum (e, &shnum);
+ if (err != GRUB_ERR_NONE)
+ return err;
+
+ *shdr = grub_calloc (shnum, e->e_shentsize);
if (! *shdr)
return grub_errno;
if (grub_file_seek (file, e->e_shoff) == (grub_off_t) -1)
return grub_errno;
- if (grub_file_read (file, *shdr, (grub_uint32_t) e->e_shnum * e->e_shentsize)
- != (grub_ssize_t) ((grub_uint32_t) e->e_shnum * e->e_shentsize))
+ if (grub_file_read (file, *shdr, shnum * e->e_shentsize)
+ != ((grub_ssize_t) shnum * e->e_shentsize))
{
if (grub_errno)
return grub_errno;
{
Elf_Ehdr e;
Elf_Shdr *s, *shdr = NULL;
+ Elf_Shnum shnum;
grub_addr_t curload, module;
grub_err_t err;
grub_size_t chunk_size = 0;
if (err)
goto out;
- for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * e.e_shentsize);
+ err = grub_elf_get_shnum (&e, &shnum);
+ if (err != GRUB_ERR_NONE)
+ goto out;
+
+ for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * e.e_shentsize);
s = (Elf_Shdr *) ((grub_uint8_t *) s + e.e_shentsize))
{
if (s->sh_size == 0)
chunk_src = get_virtual_current_address (ch);
}
- for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * e.e_shentsize);
+ for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * e.e_shentsize);
s = (Elf_Shdr *) ((grub_uint8_t *) s + e.e_shentsize))
{
if (s->sh_size == 0)
if (! err)
err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA
| FREEBSD_MODINFOMD_SHDR,
- shdr, e.e_shnum * e.e_shentsize);
+ shdr, shnum * e.e_shentsize);
out:
grub_free (shdr);
{
Elf_Ehdr e;
Elf_Shdr *s, *shdr = NULL;
+ Elf_Shnum shnum;
grub_addr_t curload, module;
grub_err_t err;
grub_size_t chunk_size = 0;
if (err)
goto out;
- for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * e.e_shentsize);
+ err = grub_elf_get_shnum (&e, &shnum);
+ if (err != GRUB_ERR_NONE)
+ goto out;
+
+ for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * e.e_shentsize);
s = (Elf_Shdr *) ((grub_uint8_t *) s + e.e_shentsize))
{
if (s->sh_size == 0)
if (chunk_size < sizeof (e))
chunk_size = sizeof (e);
chunk_size += (grub_uint32_t) e.e_phnum * e.e_phentsize;
- chunk_size += (grub_uint32_t) e.e_shnum * e.e_shentsize;
+ chunk_size += (grub_size_t) shnum * e.e_shentsize;
{
grub_relocator_chunk_t ch;
chunk_src = get_virtual_current_address (ch);
}
- for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * e.e_shentsize);
+ for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * e.e_shentsize);
s = (Elf_Shdr *) ((grub_uint8_t *) s + e.e_shentsize))
{
if (s->sh_size == 0)
curload = module + sizeof (e);
load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end, e.e_shoff,
- (grub_uint32_t) e.e_shnum * e.e_shentsize);
+ (grub_size_t) shnum * e.e_shentsize);
e.e_shoff = curload - module;
- curload += (grub_uint32_t) e.e_shnum * e.e_shentsize;
+ curload += (grub_addr_t) shnum * e.e_shentsize;
load (file, argv[0], (grub_uint8_t *) chunk_src + curload - *kern_end, e.e_phoff,
(grub_uint32_t) e.e_phnum * e.e_phentsize);
grub_err_t err;
Elf_Ehdr e;
Elf_Shdr *s, *shdr = NULL;
+ Elf_Shnum shnum;
unsigned symoff, stroff, symsize, strsize;
grub_freebsd_addr_t symstart, symend, symentsize, dynamic;
Elf_Sym *sym;
if (err)
goto out;
+ err = grub_elf_get_shnum (&e, &shnum);
+ if (err != GRUB_ERR_NONE)
+ goto out;
+
err = grub_bsd_add_meta (FREEBSD_MODINFO_METADATA |
FREEBSD_MODINFOMD_ELFHDR, &e,
sizeof (e));
if (err)
goto out;
- for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * e.e_shentsize);
+ for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * e.e_shentsize);
s = (Elf_Shdr *) ((grub_uint8_t *) s + e.e_shentsize))
if (s->sh_type == SHT_SYMTAB)
break;
- if (s >= (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * e.e_shentsize))
+ if (s >= (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * e.e_shentsize))
{
err = grub_error (GRUB_ERR_BAD_OS, N_("no symbol table"));
goto out;
grub_err_t err;
Elf_Ehdr e;
Elf_Shdr *s, *symsh, *strsh, *shdr = NULL;
+ Elf_Shnum shnum;
unsigned symsize, strsize;
void *sym_chunk;
grub_uint8_t *curload;
return grub_errno;
}
- for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * e.e_shentsize);
+ err = grub_elf_get_shnum (&e, &shnum);
+ if (err != GRUB_ERR_NONE)
+ {
+ grub_free (shdr);
+ return err;
+ }
+
+ for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * e.e_shentsize);
s = (Elf_Shdr *) ((grub_uint8_t *) s + e.e_shentsize))
if (s->sh_type == SHT_SYMTAB)
break;
- if (s >= (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * e.e_shentsize))
+ if (s >= (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * e.e_shentsize))
{
grub_free (shdr);
return GRUB_ERR_NONE;
chunk_size = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t))
+ ALIGN_UP (strsize, sizeof (grub_freebsd_addr_t))
- + sizeof (e) + (grub_uint32_t) e.e_shnum * e.e_shentsize;
+ + sizeof (e) + shnum * e.e_shentsize;
symtarget = ALIGN_UP (*kern_end, sizeof (grub_freebsd_addr_t));
{
curload += sizeof (e);
- for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * e.e_shentsize);
+ for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * e.e_shentsize);
s = (Elf_Shdr *) ((grub_uint8_t *) s + e.e_shentsize))
{
Elf_Shdr *s2;
s2 = (Elf_Shdr *) curload;
grub_memcpy (curload, s, e.e_shentsize);
if (s == symsh)
- s2->sh_offset = sizeof (e) + (grub_uint32_t) e.e_shnum * e.e_shentsize;
+ s2->sh_offset = sizeof (e) + shnum * e.e_shentsize;
else if (s == strsh)
s2->sh_offset = ALIGN_UP (symsize, sizeof (grub_freebsd_addr_t))
- + sizeof (e) + (grub_uint32_t) e.e_shnum * e.e_shentsize;
+ + sizeof (e) + shnum * e.e_shentsize;
else
s2->sh_offset = 0;
s2->sh_addr = s2->sh_offset;
grub_err_t err;
Elf_Ehdr e;
Elf_Shdr *s, *shdr = NULL;
+ Elf_Shnum shnum;
err = read_headers (file, filename, &e, &shdr);
if (err)
return err;
}
- for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * e.e_shentsize);
+ err = grub_elf_get_shnum (&e, &shnum);
+ if (err != GRUB_ERR_NONE)
+ {
+ grub_free (shdr);
+ return err;
+ }
+
+ for (s = shdr; s < (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * e.e_shentsize);
s = (Elf_Shdr *) ((grub_uint8_t *) s + e.e_shentsize))
if (s->sh_type == SHT_SYMTAB)
break;
- if (s >= (Elf_Shdr *) ((grub_uint8_t *) shdr + e.e_shnum * e.e_shentsize))
+ if (s >= (Elf_Shdr *) ((grub_uint8_t *) shdr + shnum * e.e_shentsize))
{
grub_free (shdr);
return GRUB_ERR_NONE;
*/
#if defined(MULTIBOOT_LOAD_ELF32)
-# define XX 32
-# define E_MACHINE MULTIBOOT_ELF32_MACHINE
-# define ELFCLASSXX ELFCLASS32
-# define Elf_Ehdr Elf32_Ehdr
-# define Elf_Phdr Elf32_Phdr
-# define Elf_Shdr Elf32_Shdr
+# define XX 32
+# define E_MACHINE MULTIBOOT_ELF32_MACHINE
+# define ELFCLASSXX ELFCLASS32
+# define Elf_Ehdr Elf32_Ehdr
+# define Elf_Phdr Elf32_Phdr
+# define Elf_Shdr Elf32_Shdr
+# define Elf_Shnum Elf32_Shnum
+# define grub_multiboot_elf_get_shnum grub_elf32_get_shnum
#elif defined(MULTIBOOT_LOAD_ELF64)
-# define XX 64
-# define E_MACHINE MULTIBOOT_ELF64_MACHINE
-# define ELFCLASSXX ELFCLASS64
-# define Elf_Ehdr Elf64_Ehdr
-# define Elf_Phdr Elf64_Phdr
-# define Elf_Shdr Elf64_Shdr
+# define XX 64
+# define E_MACHINE MULTIBOOT_ELF64_MACHINE
+# define ELFCLASSXX ELFCLASS64
+# define Elf_Ehdr Elf64_Ehdr
+# define Elf_Phdr Elf64_Phdr
+# define Elf_Shdr Elf64_Shdr
+# define Elf_Shnum Elf64_Shnum
+# define grub_multiboot_elf_get_shnum grub_elf64_get_shnum
#else
#error "I'm confused"
#endif
grub_err_t err;
grub_relocator_chunk_t ch;
grub_uint32_t load_offset = 0, load_size;
- int i;
+ Elf_Shnum shnum;
+ unsigned int i;
void *source = NULL;
if (ehdr->e_ident[EI_MAG0] != ELFMAG0
if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
return grub_error (GRUB_ERR_UNKNOWN_OS, N_("this ELF file is not of the right type"));
+ err = grub_multiboot_elf_get_shnum (ehdr, &shnum);
+ if (err != GRUB_ERR_NONE)
+ return err;
+
/* FIXME: Should we support program headers at strange locations? */
if (ehdr->e_phoff + (grub_uint32_t) ehdr->e_phnum * ehdr->e_phentsize > MULTIBOOT_SEARCH)
return grub_error (GRUB_ERR_BAD_OS, "program header at a too high offset");
#error Please complete this
#endif
- if (ehdr->e_shnum)
+ if (shnum)
{
grub_uint8_t *shdr, *shdrptr;
- shdr = grub_calloc (ehdr->e_shnum, ehdr->e_shentsize);
+ shdr = grub_calloc (shnum, ehdr->e_shentsize);
if (!shdr)
return grub_errno;
return grub_errno;
}
- if (grub_file_read (mld->file, shdr, (grub_uint32_t) ehdr->e_shnum * ehdr->e_shentsize)
- != (grub_ssize_t) ehdr->e_shnum * ehdr->e_shentsize)
+ if (grub_file_read (mld->file, shdr, shnum * ehdr->e_shentsize)
+ != (grub_ssize_t) shnum * ehdr->e_shentsize)
{
if (!grub_errno)
grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
return grub_errno;
}
- for (shdrptr = shdr, i = 0; i < ehdr->e_shnum;
+ for (shdrptr = shdr, i = 0; i < shnum;
shdrptr += ehdr->e_shentsize, i++)
{
Elf_Shdr *sh = (Elf_Shdr *) shdrptr;
}
sh->sh_addr = target;
}
- GRUB_MULTIBOOT (add_elfsyms) (ehdr->e_shnum, ehdr->e_shentsize,
+ GRUB_MULTIBOOT (add_elfsyms) (shnum, ehdr->e_shentsize,
ehdr->e_shstrndx, shdr);
}
#undef Elf_Ehdr
#undef Elf_Phdr
#undef Elf_Shdr
+#undef Elf_Shnum
+#undef grub_multiboot_elf_get_shnum
/* Standard ELF types. */
#include <grub/types.h>
+#include <grub/err.h>
/* Type for a 16-bit quantity. */
typedef grub_uint16_t Elf32_Half;
typedef Elf32_Half Elf32_Versym;
typedef Elf64_Half Elf64_Versym;
+/* Type for number of section header table entries */
+typedef Elf32_Word Elf32_Shnum;
+typedef Elf64_Xword Elf64_Shnum;
/* The ELF file header. This appears at the start of every ELF file. */
#define R_RISCV_SET32 56
#define R_RISCV_32_PCREL 57
+extern grub_err_t grub_elf32_get_shnum (Elf32_Ehdr *e, Elf32_Shnum *shnum);
+
+extern grub_err_t grub_elf64_get_shnum (Elf64_Ehdr *e, Elf64_Shnum *shnum);
+
#ifdef GRUB_TARGET_WORDSIZE
#if GRUB_TARGET_WORDSIZE == 32
typedef Elf32_Sym Elf_Sym;
typedef Elf32_Word Elf_Word;
typedef Elf32_Xword Elf_Xword;
+typedef Elf32_Shnum Elf_Shnum;
#define ELF_ST_BIND(val) ELF32_ST_BIND(val)
#define ELF_ST_TYPE(val) ELF32_ST_TYPE(val)
#define ELF_R_TYPE(val) ELF32_R_TYPE(val)
#define ELF_R_INFO(sym, type) ELF32_R_INFO(sym, type)
+#define grub_elf_get_shnum grub_elf32_get_shnum
+
#elif GRUB_TARGET_WORDSIZE == 64
typedef Elf64_Addr Elf_Addr;
typedef Elf64_Sym Elf_Sym;
typedef Elf64_Word Elf_Word;
typedef Elf64_Xword Elf_Xword;
+typedef Elf64_Shnum Elf_Shnum;
#define ELF_ST_BIND(val) ELF64_ST_BIND (val)
#define ELF_ST_TYPE(val) ELF64_ST_TYPE (val)
#define ELF_R_TYPE(val) ELF64_R_TYPE(val)
#define ELF_R_INFO(sym, type) ELF64_R_INFO(sym, type)
+#define grub_elf_get_shnum grub_elf64_get_shnum
+
#endif /* GRUB_TARGET_WORDSIZE == 64 */
#endif