]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - binutils/readelf.c
Add new Dutch translation.
[thirdparty/binutils-gdb.git] / binutils / readelf.c
index 1a50541fb10aee084008e2c88b4bbcace23e3c87..5780bfae1f705ba07c55e08fe18ef21082960b14 100644 (file)
@@ -106,11 +106,11 @@ Elf_Internal_Syminfo *dynamic_syminfo;
 unsigned long dynamic_syminfo_offset;
 unsigned int dynamic_syminfo_nent;
 char program_interpreter[64];
-long dynamic_info[DT_JMPREL + 1];
-long version_info[16];
-long loadaddr = 0;
+bfd_vma dynamic_info[DT_JMPREL + 1];
+bfd_vma version_info[16];
 Elf_Internal_Ehdr elf_header;
 Elf_Internal_Shdr *section_headers;
+Elf_Internal_Phdr *program_headers;
 Elf_Internal_Dyn *dynamic_segment;
 Elf_Internal_Shdr *symtab_shndx_hdr;
 int show_name;
@@ -173,6 +173,8 @@ static bfd_vma byte_get_little_endian
   PARAMS ((unsigned char *, int));
 static bfd_vma byte_get_big_endian
   PARAMS ((unsigned char *, int));
+static bfd_vma byte_get_signed
+  PARAMS ((unsigned char *, int));
 static void (*byte_put)
   PARAMS ((unsigned char *, bfd_vma, int));
 static void byte_put_little_endian
@@ -280,6 +282,8 @@ static int get_32bit_program_headers
   PARAMS ((FILE *, Elf_Internal_Phdr *));
 static int get_64bit_program_headers
   PARAMS ((FILE *, Elf_Internal_Phdr *));
+static int get_program_headers
+  PARAMS ((FILE *));
 static int get_file_header
   PARAMS ((FILE *));
 static Elf_Internal_Sym *get_32bit_elf_symbols
@@ -294,6 +298,8 @@ static int get_32bit_dynamic_segment
   PARAMS ((FILE *));
 static int get_64bit_dynamic_segment
   PARAMS ((FILE *));
+static long offset_from_vma
+  PARAMS ((FILE *, bfd_vma vma, bfd_size_type size));
 #ifdef SUPPORT_DISASSEMBLY
 static int disassemble_section
   PARAMS ((Elf_Internal_Shdr *, FILE *));
@@ -479,7 +485,7 @@ get_data (var, file, offset, size, reason)
 
   if (fseek (file, offset, SEEK_SET))
     {
-      error (_("Unable to seek to %x for %s\n"), offset, reason);
+      error (_("Unable to seek to 0x%x for %s\n"), offset, reason);
       return NULL;
     }
 
@@ -490,7 +496,7 @@ get_data (var, file, offset, size, reason)
 
       if (mvar == NULL)
        {
-         error (_("Out of memory allocating %d bytes for %s\n"),
+         error (_("Out of memory allocating 0x%x bytes for %s\n"),
                 size, reason);
          return NULL;
        }
@@ -498,7 +504,7 @@ get_data (var, file, offset, size, reason)
 
   if (fread (mvar, size, 1, file) != 1)
     {
-      error (_("Unable to read in %d bytes of %s\n"), size, reason);
+      error (_("Unable to read in 0x%x bytes of %s\n"), size, reason);
       if (mvar != var)
        free (mvar);
       return NULL;
@@ -556,6 +562,29 @@ byte_get_little_endian (field, size)
     }
 }
 
+static bfd_vma
+byte_get_signed (field, size)
+     unsigned char *field;
+     int size;
+{
+  bfd_vma x = byte_get (field, size);
+
+  switch (size)
+    {
+    case 1:
+      return (x ^ 0x80) - 0x80;
+    case 2:
+      return (x ^ 0x8000) - 0x8000;
+    case 4:
+      return (x ^ 0x80000000) - 0x80000000;
+    case 8:
+    case -8:
+      return x;
+    default:
+      abort ();
+    }
+}
+
 static void
 byte_put_little_endian (field, value, size)
      unsigned char * field;
@@ -599,13 +628,34 @@ print_vma (vma, mode)
     {
       switch (mode)
        {
-       case FULL_HEX: printf ("0x"); /* drop through */
-       case LONG_HEX: printf ("%8.8lx", (unsigned long) vma); break;
-       case PREFIX_HEX: printf ("0x"); /* drop through */
-       case HEX: printf ("%lx", (unsigned long) vma); break;
-       case DEC: printf ("%ld", (unsigned long) vma); break;
-       case DEC_5: printf ("%5ld", (long) vma); break;
-       case UNSIGNED: printf ("%lu", (unsigned long) vma); break;
+       case FULL_HEX:
+         printf ("0x");
+         /* Drop through.  */
+       case LONG_HEX:
+         printf ("%8.8lx", (unsigned long) vma);
+         break;
+
+       case DEC_5:
+         if (vma <= 99999)
+           {
+             printf ("%5ld", (long) vma);
+             break;
+           }
+         /* Drop through.  */
+       case PREFIX_HEX:
+         printf ("0x");
+         /* Drop through.  */
+       case HEX:
+         printf ("%lx", (unsigned long) vma);
+         break;
+
+       case DEC:
+         printf ("%ld", (unsigned long) vma);
+         break;
+
+       case UNSIGNED:
+         printf ("%lu", (unsigned long) vma);
+         break;
        }
     }
 #ifdef BFD64
@@ -615,7 +665,7 @@ print_vma (vma, mode)
        {
        case FULL_HEX:
          printf ("0x");
-         /* drop through */
+         /* Drop through.  */
 
        case LONG_HEX:
          printf_vma (vma);
@@ -623,7 +673,7 @@ print_vma (vma, mode)
 
        case PREFIX_HEX:
          printf ("0x");
-         /* drop through */
+         /* Drop through.  */
 
        case HEX:
 #if BFD_HOST_64BIT_LONG
@@ -650,13 +700,18 @@ print_vma (vma, mode)
 
        case DEC_5:
 #if BFD_HOST_64BIT_LONG
-         printf ("%5ld", vma);
+         if (vma <= 99999)
+           printf ("%5ld", vma);
+         else
+           printf ("%#lx", vma);
 #else
          if (_bfd_int64_high (vma))
            /* ugg */
            printf ("++%ld", _bfd_int64_low (vma));
-         else
+         else if (vma <= 99999)
            printf ("%5ld", _bfd_int64_low (vma));
+         else
+           printf ("%#lx", _bfd_int64_low (vma));
 #endif
          break;
 
@@ -1071,14 +1126,14 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
       if (is_rela)
        {
          if (do_wide)
-           printf (_("    Offset             Info            Type               Symbol's Value  Symbol's Name + Addend\n"));
+           printf (_("    Offset             Info             Type               Symbol's Value  Symbol's Name + Addend\n"));
          else
            printf (_("  Offset          Info           Type           Sym. Value    Sym. Name + Addend\n"));
        }
       else
        {
          if (do_wide)
-           printf (_("    Offset             Info            Type               Symbol's Value  Symbol's Name\n"));
+           printf (_("    Offset             Info             Type               Symbol's Value  Symbol's Name\n"));
          else
            printf (_("  Offset          Info           Type           Sym. Value    Sym. Name\n"));
        }
@@ -1361,7 +1416,7 @@ dump_relocations (file, rel_offset, rel_size, symtab, nsyms, strtab, is_rela)
        printf (_("unrecognized: %-7lx"), type);
 #endif
       else
-       printf (do_wide ? "%-21.21s" : "%-17.17s", rtype);
+       printf (do_wide ? "%-22.22s" : "%-17.17s", rtype);
 
       if (symtab_index)
        {
@@ -2307,6 +2362,7 @@ get_segment_type (p_type)
 
     case PT_GNU_EH_FRAME:
                        return "GNU_EH_FRAME";
+    case PT_GNU_STACK: return "STACK";
 
     default:
       if ((p_type >= PT_LOPROC) && (p_type <= PT_HIPROC))
@@ -3127,13 +3183,45 @@ get_64bit_program_headers (file, program_headers)
   return 1;
 }
 
+/* Returns 1 if the program headers were read into `program_headers'.  */
+
+static int
+get_program_headers (file)
+     FILE *file;
+{
+  Elf_Internal_Phdr *phdrs;
+
+  /* Check cache of prior read.  */
+  if (program_headers != NULL)
+    return 1;
+
+  phdrs = (Elf_Internal_Phdr *) malloc
+    (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
+
+  if (phdrs == NULL)
+    {
+      error (_("Out of memory\n"));
+      return 0;
+    }
+
+  if (is_32bit_elf
+      ? get_32bit_program_headers (file, phdrs)
+      : get_64bit_program_headers (file, phdrs))
+    {
+      program_headers = phdrs;
+      return 1;
+    }
+
+  free (phdrs);
+  return 0;
+}
+
 /* Returns 1 if the program headers were loaded.  */
 
 static int
 process_program_headers (file)
      FILE *file;
 {
-  Elf_Internal_Phdr *program_headers;
   Elf_Internal_Phdr *segment;
   unsigned int i;
 
@@ -3155,25 +3243,8 @@ process_program_headers (file)
       printf ("\n");
     }
 
-  program_headers = (Elf_Internal_Phdr *) malloc
-    (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
-
-  if (program_headers == NULL)
-    {
-      error (_("Out of memory\n"));
+  if (! get_program_headers (file))
       return 0;
-    }
-
-  if (is_32bit_elf)
-    i = get_32bit_program_headers (file, program_headers);
-  else
-    i = get_64bit_program_headers (file, program_headers);
-
-  if (i == 0)
-    {
-      free (program_headers);
-      return 0;
-    }
 
   if (do_segments)
     {
@@ -3197,7 +3268,6 @@ process_program_headers (file)
        }
     }
 
-  loadaddr = -1;
   dynamic_addr = 0;
   dynamic_size = 0;
 
@@ -3285,18 +3355,6 @@ process_program_headers (file)
 
       switch (segment->p_type)
        {
-       case PT_LOAD:
-         if (loadaddr == -1)
-           {
-             unsigned long align_mask = -segment->p_align;
-
-             if (align_mask == 0)
-               --align_mask;
-             loadaddr = ((segment->p_vaddr & align_mask)
-                         - (segment->p_offset & align_mask));
-           }
-         break;
-
        case PT_DYNAMIC:
          if (dynamic_addr)
            error (_("more than one dynamic segment\n"));
@@ -3324,12 +3382,6 @@ process_program_headers (file)
        putc ('\n', stdout);
     }
 
-  if (loadaddr == -1)
-    {
-      /* Very strange.  */
-      loadaddr = 0;
-    }
-
   if (do_segments && section_headers != NULL)
     {
       printf (_("\n Section to Segment mapping:\n"));
@@ -3366,12 +3418,44 @@ process_program_headers (file)
        }
     }
 
-  free (program_headers);
-
   return 1;
 }
 
 
+/* Find the file offset corresponding to VMA by using the program headers.  */
+
+static long
+offset_from_vma (file, vma, size)
+     FILE *file;
+     bfd_vma vma;
+     bfd_size_type size;
+{
+  Elf_Internal_Phdr *seg;
+
+  if (! get_program_headers (file))
+    {
+      warn (_("Cannot interpret virtual addresses without program headers.\n"));
+      return (long) vma;
+    }
+
+  for (seg = program_headers;
+       seg < program_headers + elf_header.e_phnum;
+       ++seg)
+    {
+      if (seg->p_type != PT_LOAD)
+       continue;
+
+      if (vma >= (seg->p_vaddr & -seg->p_align)
+         && vma + size <= seg->p_vaddr + seg->p_filesz)
+       return vma - seg->p_vaddr + seg->p_offset;
+    }
+
+  warn (_("Virtual address 0x%lx not located in any PT_LOAD segment.\n"),
+       (long) vma);
+  return (long) vma;
+}
+
+
 static int
 get_32bit_section_headers (file, num)
      FILE *file;
@@ -3683,6 +3767,9 @@ process_section_headers (file)
       string_table = (char *) get_data (NULL, file, section->sh_offset,
                                        section->sh_size, _("string table"));
 
+      if (string_table == NULL)
+       return 0;
+      
       string_table_length = section->sh_size;
     }
 
@@ -3944,7 +4031,9 @@ process_relocs (file)
                (_("\n'%s' relocation section at offset 0x%lx contains %ld bytes:\n"),
                 name, rel_offset, rel_size);
 
-             dump_relocations (file, rel_offset - loadaddr, rel_size,
+             dump_relocations (file,
+                               offset_from_vma (file, rel_offset, rel_size),
+                               rel_size,
                                dynamic_symbols, num_dynamic_syms,
                                dynamic_strings, is_rela);
            }
@@ -4170,14 +4259,13 @@ slurp_ia64_unwind_table (file, aux, sec)
      Elf_Internal_Shdr *sec;
 {
   unsigned long size, addr_size, nrelas, i;
-  Elf_Internal_Phdr *prog_hdrs, *seg;
+  Elf_Internal_Phdr *seg;
   struct unw_table_entry *tep;
   Elf_Internal_Shdr *relsec;
   Elf_Internal_Rela *rela, *rp;
   unsigned char *table, *tp;
   Elf_Internal_Sym *sym;
   const char *relname;
-  int result;
 
   addr_size = is_32bit_elf ? 4 : 8;
 
@@ -4186,21 +4274,12 @@ slurp_ia64_unwind_table (file, aux, sec)
 
   if (elf_header.e_phnum)
     {
-      prog_hdrs = (Elf_Internal_Phdr *)
-       xmalloc (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
-
-      if (is_32bit_elf)
-       result = get_32bit_program_headers (file, prog_hdrs);
-      else
-       result = get_64bit_program_headers (file, prog_hdrs);
-
-      if (!result)
-       {
-         free (prog_hdrs);
+      if (! get_program_headers (file))
          return 0;
-       }
 
-      for (seg = prog_hdrs; seg < prog_hdrs + elf_header.e_phnum; ++seg)
+      for (seg = program_headers;
+          seg < program_headers + elf_header.e_phnum;
+          ++seg)
        {
          if (seg->p_type != PT_LOAD)
            continue;
@@ -4212,8 +4291,6 @@ slurp_ia64_unwind_table (file, aux, sec)
              break;
            }
        }
-
-      free (prog_hdrs);
     }
 
   /* Second, build the unwind table from the contents of the unwind section:  */
@@ -4597,12 +4674,17 @@ dynamic_segment_ia64_val (entry)
   switch (entry->d_tag)
     {
     case DT_IA_64_PLT_RESERVE: 
-      /* First 3 bytes reserved.  */
+      /* First 3 slots reserved.  */
       print_vma (entry->d_un.d_ptr, PREFIX_HEX);
       printf (" -- ");
       print_vma (entry->d_un.d_ptr + (3 * 8), PREFIX_HEX);
-      printf ("\n");
+      break;
+
+    default:
+      print_vma (entry->d_un.d_ptr, PREFIX_HEX);
+      break;
     }
+  putchar ('\n');
 }
 
 static int
@@ -4766,7 +4848,7 @@ process_dynamic_segment (file)
             we default to reading in the entire file (!) and
             processing that.  This is overkill, I know, but it
             should work.  */
-         section.sh_offset = entry->d_un.d_val - loadaddr;
+         section.sh_offset = offset_from_vma (file, entry->d_un.d_val, 0);
 
          if (fseek (file, 0, SEEK_END))
            error (_("Unable to seek to end of file!"));
@@ -4808,7 +4890,7 @@ process_dynamic_segment (file)
             processing that.  This is overkill, I know, but it
             should work.  */
 
-         offset = entry->d_un.d_val - loadaddr;
+         offset = offset_from_vma (file, entry->d_un.d_val, 0);
          if (fseek (file, 0, SEEK_END))
            error (_("Unable to seek to end of file\n"));
          str_tab_len = ftell (file) - offset;
@@ -4844,7 +4926,8 @@ process_dynamic_segment (file)
          else if (entry->d_tag == DT_SYMINSZ)
            syminsz = entry->d_un.d_val;
          else if (entry->d_tag == DT_SYMINFO)
-           dynamic_syminfo_offset = entry->d_un.d_val - loadaddr;
+           dynamic_syminfo_offset = offset_from_vma (file, entry->d_un.d_val,
+                                                     syminsz);
        }
 
       if (dynamic_syminfo_offset != 0 && syminsz != 0)
@@ -5533,7 +5616,9 @@ process_version_sections (file)
            edata =
              ((unsigned char *)
               get_data (NULL, file,
-                        version_info[DT_VERSIONTAGIDX (DT_VERSYM)] - loadaddr,
+                        offset_from_vma
+                        (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
+                         total * sizeof (short)),
                         total * sizeof (short), _("version symbol data")));
            if (!edata)
              {
@@ -5589,8 +5674,9 @@ process_version_sections (file)
                          Elf_Internal_Verneed ivn;
                          unsigned long offset;
 
-                         offset = version_info[DT_VERSIONTAGIDX (DT_VERNEED)]
-                           - loadaddr;
+                         offset = offset_from_vma
+                           (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)],
+                            sizeof (Elf_External_Verneed));
 
                          do
                            {
@@ -5645,8 +5731,9 @@ process_version_sections (file)
                          Elf_External_Verdef evd;
                          unsigned long offset;
 
-                         offset = (version_info[DT_VERSIONTAGIDX (DT_VERDEF)]
-                                   - loadaddr);
+                         offset = offset_from_vma
+                           (file, version_info[DT_VERSIONTAGIDX (DT_VERDEF)],
+                            sizeof evd);
 
                          do
                            {
@@ -5873,7 +5960,9 @@ process_symbol_table (file)
   if (dynamic_info[DT_HASH] && ((do_using_dynamic && dynamic_strings != NULL)
                                || do_histogram))
     {
-      if (fseek (file, dynamic_info[DT_HASH] - loadaddr, SEEK_SET))
+      if (fseek (file, offset_from_vma (file, dynamic_info[DT_HASH],
+                                       sizeof nb + sizeof nc),
+                SEEK_SET))
        {
          error (_("Unable to seek to start of dynamic information"));
          return 0;
@@ -6004,8 +6093,9 @@ process_symbol_table (file)
                  int is_nobits;
                  int check_def;
 
-                 offset = version_info[DT_VERSIONTAGIDX (DT_VERSYM)]
-                   - loadaddr;
+                 offset = offset_from_vma
+                   (file, version_info[DT_VERSIONTAGIDX (DT_VERSYM)],
+                    sizeof data + si * sizeof (vers_data));
 
                  get_data (&data, file, offset + si * sizeof (vers_data),
                            sizeof (data), _("version data"));
@@ -6027,8 +6117,9 @@ process_symbol_table (file)
                          Elf_Internal_Vernaux ivna;
 
                          /* We must test both.  */
-                         offset = (version_info[DT_VERSIONTAGIDX (DT_VERNEED)]
-                                   - loadaddr);
+                         offset = offset_from_vma
+                           (file, version_info[DT_VERSIONTAGIDX (DT_VERNEED)],
+                            sizeof evn);
 
                          do
                            {
@@ -6088,9 +6179,10 @@ process_symbol_table (file)
                              Elf_External_Verdaux evda;
                              unsigned long offset;
 
-                             offset
-                               = (version_info[DT_VERSIONTAGIDX (DT_VERDEF)]
-                                  - loadaddr);
+                             offset = offset_from_vma
+                               (file,
+                                version_info[DT_VERSIONTAGIDX (DT_VERDEF)],
+                                sizeof (Elf_External_Verdef));
 
                              do
                                {
@@ -8668,6 +8760,7 @@ Frame_Chunk;
 static void frame_need_space PARAMS ((Frame_Chunk *, int));
 static void frame_display_row PARAMS ((Frame_Chunk *, int *, int *));
 static int size_of_encoded_value PARAMS ((int));
+static bfd_vma get_encoded_value PARAMS ((unsigned char *, int));
 
 static void
 frame_need_space (fc, reg)
@@ -8775,6 +8868,18 @@ size_of_encoded_value (encoding)
     }
 }
 
+static bfd_vma
+get_encoded_value (data, encoding)
+     unsigned char *data;
+     int encoding;
+{
+  int size = size_of_encoded_value (encoding);
+  if (encoding & DW_EH_PE_signed)
+    return byte_get_signed (data, size);
+  else
+    return byte_get (data, size);
+}
+
 #define GET(N) byte_get (start, N); start += N
 #define LEB()  read_leb128 (start, & length_return, 0); start += length_return
 #define SLEB() read_leb128 (start, & length_return, 1); start += length_return
@@ -8980,7 +9085,7 @@ display_debug_frames (section, start, file)
          if (fc->fde_encoding)
            encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
 
-         fc->pc_begin = byte_get (start, encoded_ptr_size);
+         fc->pc_begin = get_encoded_value (start, fc->fde_encoding);
          if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel)
            fc->pc_begin += section->sh_addr + (start - section_start);
          start += encoded_ptr_size;
@@ -9011,8 +9116,12 @@ display_debug_frames (section, start, file)
 
       /* At this point, fc is the current chunk, cie (if any) is set, and we're
         about to interpret instructions for the chunk.  */
-
-      if (do_debug_frames_interp)
+      /* ??? At present we need to do this always, since this sizes the
+        fc->col_type and fc->col_offset arrays, which we write into always.
+        We should probably split the interpreted and non-interpreted bits
+        into two different routines, since there's so much that doesn't
+        really overlap between them.  */
+      if (1 || do_debug_frames_interp)
        {
          /* Start by making a pass over the chunk, allocating storage
             and taking note of what registers are used.  */
@@ -9175,7 +9284,7 @@ display_debug_frames (section, start, file)
              break;
 
            case DW_CFA_set_loc:
-             vma = byte_get (start, encoded_ptr_size);
+             vma = get_encoded_value (start, fc->fde_encoding);
              if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel)
                vma += section->sh_addr + (start - section_start);
              start += encoded_ptr_size;
@@ -9257,7 +9366,7 @@ display_debug_frames (section, start, file)
              reg = LEB ();
              roffs = LEB ();
              if (! do_debug_frames_interp)
-               printf ("  DW_CFA_register: r%ld\n", reg);
+               printf ("  DW_CFA_register: r%ld in r%ld\n", reg, roffs);
              fc->col_type[reg] = DW_CFA_register;
              fc->col_offset[reg] = roffs;
              break;
@@ -9664,16 +9773,20 @@ process_mips_specific (file)
     switch (entry->d_tag)
       {
       case DT_MIPS_LIBLIST:
-       liblist_offset = entry->d_un.d_val - loadaddr;
+       liblist_offset
+         = offset_from_vma (file, entry->d_un.d_val,
+                            liblistno * sizeof (Elf32_External_Lib));
        break;
       case DT_MIPS_LIBLISTNO:
        liblistno = entry->d_un.d_val;
        break;
       case DT_MIPS_OPTIONS:
-       options_offset = entry->d_un.d_val - loadaddr;
+       options_offset = offset_from_vma (file, entry->d_un.d_val, 0);
        break;
       case DT_MIPS_CONFLICT:
-       conflicts_offset = entry->d_un.d_val - loadaddr;
+       conflicts_offset
+         = offset_from_vma (file, entry->d_un.d_val,
+                            conflictsno * sizeof (Elf32_External_Conflict));
        break;
       case DT_MIPS_CONFLICTNO:
        conflictsno = entry->d_un.d_val;
@@ -10325,30 +10438,12 @@ static int
 process_corefile_note_segments (file)
      FILE *file;
 {
-  Elf_Internal_Phdr *program_headers;
   Elf_Internal_Phdr *segment;
   unsigned int i;
   int res = 1;
 
-  program_headers = (Elf_Internal_Phdr *) malloc
-    (elf_header.e_phnum * sizeof (Elf_Internal_Phdr));
-
-  if (program_headers == NULL)
-    {
-      error (_("Out of memory\n"));
-      return 0;
-    }
-
-  if (is_32bit_elf)
-    i = get_32bit_program_headers (file, program_headers);
-  else
-    i = get_64bit_program_headers (file, program_headers);
-
-  if (i == 0)
-    {
-      free (program_headers);
+  if (! get_program_headers (file))
       return 0;
-    }
 
   for (i = 0, segment = program_headers;
        i < elf_header.e_phnum;
@@ -10360,8 +10455,6 @@ process_corefile_note_segments (file)
                                              (bfd_vma) segment->p_filesz);
     }
 
-  free (program_headers);
-
   return res;
 }
 
@@ -10578,6 +10671,12 @@ process_file (file_name)
 
   fclose (file);
 
+  if (program_headers)
+    {
+      free (program_headers);
+      program_headers = NULL;
+    }
+
   if (section_headers)
     {
       free (section_headers);