diff --git a/elf/dl-load.c b/elf/dl-load.c
index 4312369..807cba6 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -792,6 +792,17 @@ lose (int code, int fd, const char *name, char *realname, struct link_map *l,
   _dl_signal_error (code, name, NULL, msg);
 }
 
+#define DYNARRAY_STRUCT        loadcmd_list
+#define DYNARRAY_ELEMENT       struct loadcmd
+#define DYNARRAY_PREFIX        loadcmd_list_
+#define DYNARRAY_INITIAL_SIZE  8
+#include <malloc/dynarray-skeleton.c>
+
+#define DYNARRAY_STRUCT        phdr_list
+#define DYNARRAY_ELEMENT       ElfW(Phdr)
+#define DYNARRAY_PREFIX        phdr_list_
+#define DYNARRAY_INITIAL_SIZE  16
+#include <malloc/dynarray-skeleton.c>
 
 /* Map in the shared object NAME, actually located in REALNAME, and already
    opened on FD.  */
@@ -809,6 +820,8 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
   const ElfW(Ehdr) *header;
   const ElfW(Phdr) *phdr;
   const ElfW(Phdr) *ph;
+  struct loadcmd_list loadcmds;
+  struct phdr_list phdrlist;
   size_t maplength;
   int type;
   /* Initialize to keep the compiler happy.  */
@@ -817,6 +830,9 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
   struct r_debug *r = _dl_debug_initialize (0, nsid);
   bool make_consistent = false;
 
+  loadcmd_list_init (&loadcmds);
+  phdr_list_init (&phdrlist);
+
   /* Get file information.  */
   struct r_file_id id;
   if (__glibc_unlikely (!_dl_get_file_id (fd, &id)))
@@ -827,6 +843,8 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
     call_lose:
       lose (errval, fd, name, realname, l, errstring,
 	    make_consistent ? r : NULL, nsid);
+      phdr_list_free (&phdrlist);
+      loadcmd_list_free (&loadcmds);
     }
 
   /* Look again to see if the real name matched another already loaded.  */
@@ -960,7 +978,13 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
     phdr = (void *) (fbp->buf + header->e_phoff);
   else
     {
-      phdr = alloca (maplength);
+      if (!phdr_list_resize (&phdrlist, header->e_phnum))
+	{
+	  errstring = N_("cannot allocate memory for program header");
+	  goto call_lose_errno;
+	}
+      phdr = phdr_list_begin (&phdrlist);
+
       __lseek (fd, header->e_phoff, SEEK_SET);
       if ((size_t) __libc_read (fd, (void *) phdr, maplength) != maplength)
 	{
@@ -976,7 +1000,11 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
 
   {
     /* Scan the program header table, collecting its load commands.  */
-    struct loadcmd loadcmds[l->l_phnum];
+    if (!loadcmd_list_resize (&loadcmds, l->l_phnum))
+      {
+	errstring = N_("cannot allocate memory for program header");
+	goto call_lose_errno;
+      }
     size_t nloadcmds = 0;
     bool has_holes = false;
 
@@ -1021,7 +1049,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
 	      goto call_lose;
 	    }
 
-	  struct loadcmd *c = &loadcmds[nloadcmds++];
+	  struct loadcmd *c = loadcmd_list_at (&loadcmds, nloadcmds++);
 	  c->mapstart = ALIGN_DOWN (ph->p_vaddr, GLRO(dl_pagesize));
 	  c->mapend = ALIGN_UP (ph->p_vaddr + ph->p_filesz, GLRO(dl_pagesize));
 	  c->dataend = ph->p_vaddr + ph->p_filesz;
@@ -1116,16 +1144,21 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
       }
 
     /* Length of the sections to be loaded.  */
-    maplength = loadcmds[nloadcmds - 1].allocend - loadcmds[0].mapstart;
+    const struct loadcmd *lc = loadcmd_list_at (&loadcmds, nloadcmds - 1);
+    const struct loadcmd *l0 = loadcmd_list_begin (&loadcmds);
+    maplength = lc->allocend - l0->mapstart;
 
     /* Now process the load commands and map segments into memory.
        This is responsible for filling in:
        l_map_start, l_map_end, l_addr, l_contiguous, l_text_end, l_phdr
      */
-    errstring = _dl_map_segments (l, fd, header, type, loadcmds, nloadcmds,
+    errstring = _dl_map_segments (l, fd, header, type, l0, nloadcmds,
 				  maplength, has_holes, loader);
     if (__glibc_unlikely (errstring != NULL))
       goto call_lose;
+
+    phdr_list_free (&phdrlist);
+    loadcmd_list_free (&loadcmds);
   }
 
   if (l->l_ld == 0)
@@ -1463,9 +1496,12 @@ open_verify (const char *name, int fd,
       ElfW(Phdr) *phdr, *ph;
       ElfW(Word) *abi_note;
       ElfW(Word) *abi_note_malloced = NULL;
+      struct phdr_list phdrlist;
       unsigned int osversion;
       size_t maplength;
 
+      phdr_list_init (&phdrlist);
+
       /* We successfully opened the file.  Now verify it is a file
 	 we can use.  */
       __set_errno (0);
@@ -1596,7 +1632,13 @@ open_verify (const char *name, int fd,
 	phdr = (void *) (fbp->buf + ehdr->e_phoff);
       else
 	{
-	  phdr = alloca (maplength);
+	  if (!phdr_list_resize (&phdrlist, ehdr->e_phnum))
+	    {
+	      errstring = N_("cannot allocate memory for program header");
+	      goto call_lose;
+	    }
+	  phdr = phdr_list_begin (&phdrlist);
+
 	  __lseek (fd, ehdr->e_phoff, SEEK_SET);
 	  if ((size_t) __libc_read (fd, (void *) phdr, maplength) != maplength)
 	    {
@@ -1687,6 +1729,7 @@ open_verify (const char *name, int fd,
 
 	    break;
 	  }
+      phdr_list_free (&phdrlist);
       free (abi_note_malloced);
     }
 
diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c
index 25ceded..943a960 100644
--- a/elf/dl-minimal.c
+++ b/elf/dl-minimal.c
@@ -28,6 +28,7 @@
 #include <ldsodefs.h>
 #include <_itoa.h>
 #include <malloc/malloc-internal.h>
+#include <malloc/dynarray.h>
 
 #include <assert.h>
 
@@ -191,6 +192,15 @@ __libc_fatal (const char *message)
 rtld_hidden_def (__libc_fatal)
 
 void
+__libc_dynarray_at_failure (size_t size, size_t index)
+{
+  _dl_fatal_printf ("Fatal glibc error: "
+                    "array index %zu not less than array length %zu\n",
+                    index, size);
+}
+rtld_hidden_def (__libc_dynarray_at_failure)
+
+void
 __attribute__ ((noreturn))
 __chk_fail (void)
 {
diff --git a/malloc/dynarray.h b/malloc/dynarray.h
index 0b171da..c4df88b 100644
--- a/malloc/dynarray.h
+++ b/malloc/dynarray.h
@@ -174,6 +174,7 @@ libc_hidden_proto (__libc_dynarray_resize)
 libc_hidden_proto (__libc_dynarray_resize_clear)
 libc_hidden_proto (__libc_dynarray_finalize)
 libc_hidden_proto (__libc_dynarray_at_failure)
+rtld_hidden_proto (__libc_dynarray_at_failure)
 #endif
 
 #endif /* _DYNARRAY_H */
