]> Git Repo - binutils.git/blob - bfd/elfcore.h
* test-build.mk: Add checking of `hpux9' rather than just `hpux'.
[binutils.git] / bfd / elfcore.h
1 /* ELF core file support for BFD.
2    Copyright  1995 Free Software Foundation, Inc.
3
4 This file is part of BFD, the Binary File Descriptor library.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19 /* Core file support */
20
21 #ifdef HAVE_SYS_PROCFS_H                /* Some core file support requires host /proc files */
22 #include <signal.h>
23 #include <sys/procfs.h>
24 #else
25 #define bfd_prstatus(abfd, descdata, descsz, filepos) true
26 #define bfd_fpregset(abfd, descdata, descsz, filepos) true
27 #define bfd_prpsinfo(abfd, descdata, descsz, filepos) true
28 #endif
29
30 #ifdef HAVE_SYS_PROCFS_H
31
32 static boolean
33 bfd_prstatus (abfd, descdata, descsz, filepos)
34      bfd *abfd;
35      char *descdata;
36      int descsz;
37      long filepos;
38 {
39   asection *newsect;
40   prstatus_t *status = (prstatus_t *) 0;
41
42   if (descsz == sizeof (prstatus_t))
43     {
44       newsect = bfd_make_section (abfd, ".reg");
45       if (newsect == NULL)
46         return false;
47       newsect->_raw_size = sizeof (status->pr_reg);
48       newsect->filepos = filepos + (long) &status->pr_reg;
49       newsect->flags = SEC_HAS_CONTENTS;
50       newsect->alignment_power = 2;
51       if ((core_prstatus (abfd) = bfd_alloc (abfd, descsz)) != NULL)
52         {
53           memcpy (core_prstatus (abfd), descdata, descsz);
54         }
55     }
56   return true;
57 }
58
59 /* Stash a copy of the prpsinfo structure away for future use. */
60
61 static boolean
62 bfd_prpsinfo (abfd, descdata, descsz, filepos)
63      bfd *abfd;
64      char *descdata;
65      int descsz;
66      long filepos;
67 {
68   if (descsz == sizeof (prpsinfo_t))
69     {
70       if ((core_prpsinfo (abfd) = bfd_alloc (abfd, descsz)) == NULL)
71         return false;
72       memcpy (core_prpsinfo (abfd), descdata, descsz);
73     }
74   return true;
75 }
76
77 static boolean
78 bfd_fpregset (abfd, descdata, descsz, filepos)
79      bfd *abfd;
80      char *descdata;
81      int descsz;
82      long filepos;
83 {
84   asection *newsect;
85
86   newsect = bfd_make_section (abfd, ".reg2");
87   if (newsect == NULL)
88     return false;
89   newsect->_raw_size = descsz;
90   newsect->filepos = filepos;
91   newsect->flags = SEC_HAS_CONTENTS;
92   newsect->alignment_power = 2;
93   return true;
94 }
95
96 #endif /* HAVE_SYS_PROCFS_H */
97
98 /* Return a pointer to the args (including the command name) that were
99    seen by the program that generated the core dump.  Note that for
100    some reason, a spurious space is tacked onto the end of the args
101    in some (at least one anyway) implementations, so strip it off if
102    it exists. */
103
104 char *
105 elf_core_file_failing_command (abfd)
106      bfd *abfd;
107 {
108 #ifdef HAVE_SYS_PROCFS_H
109   if (core_prpsinfo (abfd))
110     {
111       prpsinfo_t *p = core_prpsinfo (abfd);
112       char *scan = p->pr_psargs;
113       while (*scan++)
114         {;
115         }
116       scan -= 2;
117       if ((scan > p->pr_psargs) && (*scan == ' '))
118         {
119           *scan = '\000';
120         }
121       return p->pr_psargs;
122     }
123 #endif
124   return NULL;
125 }
126
127 /* Return the number of the signal that caused the core dump.  Presumably,
128    since we have a core file, we got a signal of some kind, so don't bother
129    checking the other process status fields, just return the signal number.
130    */
131
132 int
133 elf_core_file_failing_signal (abfd)
134      bfd *abfd;
135 {
136 #ifdef HAVE_SYS_PROCFS_H
137   if (core_prstatus (abfd))
138     {
139       return ((prstatus_t *) (core_prstatus (abfd)))->pr_cursig;
140     }
141 #endif
142   return -1;
143 }
144
145 /* Check to see if the core file could reasonably be expected to have
146    come for the current executable file.  Note that by default we return
147    true unless we find something that indicates that there might be a
148    problem.
149    */
150
151 boolean
152 elf_core_file_matches_executable_p (core_bfd, exec_bfd)
153      bfd *core_bfd;
154      bfd *exec_bfd;
155 {
156 #ifdef HAVE_SYS_PROCFS_H
157   char *corename;
158   char *execname;
159 #endif
160
161   /* First, xvecs must match since both are ELF files for the same target. */
162
163   if (core_bfd->xvec != exec_bfd->xvec)
164     {
165       bfd_set_error (bfd_error_system_call);
166       return false;
167     }
168
169 #ifdef HAVE_SYS_PROCFS_H
170
171   /* If no prpsinfo, just return true.  Otherwise, grab the last component
172      of the exec'd pathname from the prpsinfo. */
173
174   if (core_prpsinfo (core_bfd))
175     {
176       corename = (((prpsinfo_t *) core_prpsinfo (core_bfd))->pr_fname);
177     }
178   else
179     {
180       return true;
181     }
182
183   /* Find the last component of the executable pathname. */
184
185   if ((execname = strrchr (exec_bfd->filename, '/')) != NULL)
186     {
187       execname++;
188     }
189   else
190     {
191       execname = (char *) exec_bfd->filename;
192     }
193
194   /* See if they match */
195
196   return strcmp (execname, corename) ? false : true;
197
198 #else
199
200   return true;
201
202 #endif /* HAVE_SYS_PROCFS_H */
203 }
204
205 /* ELF core files contain a segment of type PT_NOTE, that holds much of
206    the information that would normally be available from the /proc interface
207    for the process, at the time the process dumped core.  Currently this
208    includes copies of the prstatus, prpsinfo, and fpregset structures.
209
210    Since these structures are potentially machine dependent in size and
211    ordering, bfd provides two levels of support for them.  The first level,
212    available on all machines since it does not require that the host
213    have /proc support or the relevant include files, is to create a bfd
214    section for each of the prstatus, prpsinfo, and fpregset structures,
215    without any interpretation of their contents.  With just this support,
216    the bfd client will have to interpret the structures itself.  Even with
217    /proc support, it might want these full structures for it's own reasons.
218
219    In the second level of support, where HAVE_SYS_PROCFS_H is defined,
220    bfd will pick apart the structures to gather some additional
221    information that clients may want, such as the general register
222    set, the name of the exec'ed file and its arguments, the signal (if
223    any) that caused the core dump, etc.
224
225    */
226
227 static boolean
228 elf_corefile_note (abfd, hdr)
229      bfd *abfd;
230      Elf_Internal_Phdr *hdr;
231 {
232   Elf_External_Note *x_note_p;  /* Elf note, external form */
233   Elf_Internal_Note i_note;     /* Elf note, internal form */
234   char *buf = NULL;             /* Entire note segment contents */
235   char *namedata;               /* Name portion of the note */
236   char *descdata;               /* Descriptor portion of the note */
237   char *sectname;               /* Name to use for new section */
238   long filepos;                 /* File offset to descriptor data */
239   asection *newsect;
240
241   if (hdr->p_filesz > 0
242       && (buf = (char *) bfd_malloc ((size_t) hdr->p_filesz)) != NULL
243       && bfd_seek (abfd, hdr->p_offset, SEEK_SET) != -1
244       && bfd_read ((PTR) buf, hdr->p_filesz, 1, abfd) == hdr->p_filesz)
245     {
246       x_note_p = (Elf_External_Note *) buf;
247       while ((char *) x_note_p < (buf + hdr->p_filesz))
248         {
249           i_note.namesz = bfd_h_get_32 (abfd, (bfd_byte *) x_note_p->namesz);
250           i_note.descsz = bfd_h_get_32 (abfd, (bfd_byte *) x_note_p->descsz);
251           i_note.type = bfd_h_get_32 (abfd, (bfd_byte *) x_note_p->type);
252           namedata = x_note_p->name;
253           descdata = namedata + BFD_ALIGN (i_note.namesz, 4);
254           filepos = hdr->p_offset + (descdata - buf);
255           switch (i_note.type)
256             {
257             case NT_PRSTATUS:
258               /* process descdata as prstatus info */
259               if (! bfd_prstatus (abfd, descdata, i_note.descsz, filepos))
260                 return false;
261               sectname = ".prstatus";
262               break;
263             case NT_FPREGSET:
264               /* process descdata as fpregset info */
265               if (! bfd_fpregset (abfd, descdata, i_note.descsz, filepos))
266                 return false;
267               sectname = ".fpregset";
268               break;
269             case NT_PRPSINFO:
270               /* process descdata as prpsinfo */
271               if (! bfd_prpsinfo (abfd, descdata, i_note.descsz, filepos))
272                 return false;
273               sectname = ".prpsinfo";
274               break;
275             default:
276               /* Unknown descriptor, just ignore it. */
277               sectname = NULL;
278               break;
279             }
280           if (sectname != NULL)
281             {
282               newsect = bfd_make_section (abfd, sectname);
283               if (newsect == NULL)
284                 return false;
285               newsect->_raw_size = i_note.descsz;
286               newsect->filepos = filepos;
287               newsect->flags = SEC_ALLOC | SEC_HAS_CONTENTS;
288               newsect->alignment_power = 2;
289             }
290           x_note_p = (Elf_External_Note *)
291             (descdata + BFD_ALIGN (i_note.descsz, 4));
292         }
293     }
294   if (buf != NULL)
295     {
296       free (buf);
297     }
298   else if (hdr->p_filesz > 0)
299     {
300       return false;
301     }
302   return true;
303
304 }
305
306 /*  Core files are simply standard ELF formatted files that partition
307     the file using the execution view of the file (program header table)
308     rather than the linking view.  In fact, there is no section header
309     table in a core file.
310
311     The process status information (including the contents of the general
312     register set) and the floating point register set are stored in a
313     segment of type PT_NOTE.  We handcraft a couple of extra bfd sections
314     that allow standard bfd access to the general registers (.reg) and the
315     floating point registers (.reg2).
316
317  */
318
319 const bfd_target *
320 elf_core_file_p (abfd)
321      bfd *abfd;
322 {
323   Elf_External_Ehdr x_ehdr;     /* Elf file header, external form */
324   Elf_Internal_Ehdr *i_ehdrp;   /* Elf file header, internal form */
325   Elf_External_Phdr x_phdr;     /* Program header table entry, external form */
326   Elf_Internal_Phdr *i_phdrp;   /* Program header table, internal form */
327   unsigned int phindex;
328   struct elf_backend_data *ebd;
329
330   /* Read in the ELF header in external format.  */
331
332   if (bfd_read ((PTR) & x_ehdr, sizeof (x_ehdr), 1, abfd) != sizeof (x_ehdr))
333     {
334       if (bfd_get_error () != bfd_error_system_call)
335         bfd_set_error (bfd_error_wrong_format);
336       return NULL;
337     }
338
339   /* Now check to see if we have a valid ELF file, and one that BFD can
340      make use of.  The magic number must match, the address size ('class')
341      and byte-swapping must match our XVEC entry, and it must have a
342      program header table (FIXME: See comments re segments at top of this
343      file). */
344
345   if (elf_file_p (&x_ehdr) == false)
346     {
347     wrong:
348       bfd_set_error (bfd_error_wrong_format);
349       return NULL;
350     }
351
352   /* FIXME, Check EI_VERSION here !  */
353
354   {
355 #if ARCH_SIZE == 32
356     int desired_address_size = ELFCLASS32;
357 #endif
358 #if ARCH_SIZE == 64
359     int desired_address_size = ELFCLASS64;
360 #endif
361
362     if (x_ehdr.e_ident[EI_CLASS] != desired_address_size)
363       goto wrong;
364   }
365
366   /* Switch xvec to match the specified byte order.  */
367   switch (x_ehdr.e_ident[EI_DATA])
368     {
369     case ELFDATA2MSB:           /* Big-endian */
370       if (! bfd_big_endian (abfd))
371         goto wrong;
372       break;
373     case ELFDATA2LSB:           /* Little-endian */
374       if (! bfd_little_endian (abfd))
375         goto wrong;
376       break;
377     case ELFDATANONE:           /* No data encoding specified */
378     default:                    /* Unknown data encoding specified */
379       goto wrong;
380     }
381
382   /* Allocate an instance of the elf_obj_tdata structure and hook it up to
383      the tdata pointer in the bfd. */
384
385   elf_tdata (abfd) =
386     (struct elf_obj_tdata *) bfd_zalloc (abfd, sizeof (struct elf_obj_tdata));
387   if (elf_tdata (abfd) == NULL)
388     return NULL;
389
390   /* FIXME, `wrong' returns from this point onward, leak memory.  */
391
392   /* Now that we know the byte order, swap in the rest of the header */
393   i_ehdrp = elf_elfheader (abfd);
394   elf_swap_ehdr_in (abfd, &x_ehdr, i_ehdrp);
395 #if DEBUG & 1
396   elf_debug_file (i_ehdrp);
397 #endif
398
399   ebd = get_elf_backend_data (abfd);
400
401   /* Check that the ELF e_machine field matches what this particular
402      BFD format expects.  */
403   if (ebd->elf_machine_code != i_ehdrp->e_machine
404       && (ebd->elf_machine_alt1 == 0 || i_ehdrp->e_machine != ebd->elf_machine_alt1)
405       && (ebd->elf_machine_alt2 == 0 || i_ehdrp->e_machine != ebd->elf_machine_alt2))
406     {
407       const bfd_target * const *target_ptr;
408
409       if (ebd->elf_machine_code != EM_NONE)
410         goto wrong;
411
412       /* This is the generic ELF target.  Let it match any ELF target
413          for which we do not have a specific backend.  */
414       for (target_ptr = bfd_target_vector; *target_ptr != NULL; target_ptr++)
415         {
416           struct elf_backend_data *back;
417
418           if ((*target_ptr)->flavour != bfd_target_elf_flavour)
419             continue;
420           back = (struct elf_backend_data *) (*target_ptr)->backend_data;
421           if (back->elf_machine_code == i_ehdrp->e_machine)
422             {
423               /* target_ptr is an ELF backend which matches this
424                  object file, so reject the generic ELF target.  */
425               goto wrong;
426             }
427         }
428     }
429
430   /* If there is no program header, or the type is not a core file, then
431      we are hosed. */
432   if (i_ehdrp->e_phoff == 0 || i_ehdrp->e_type != ET_CORE)
433     goto wrong;
434
435   /* Allocate space for a copy of the program header table in
436      internal form, seek to the program header table in the file,
437      read it in, and convert it to internal form.  As a simple sanity
438      check, verify that the what BFD thinks is the size of each program
439      header table entry actually matches the size recorded in the file. */
440
441   if (i_ehdrp->e_phentsize != sizeof (x_phdr))
442     goto wrong;
443   i_phdrp = (Elf_Internal_Phdr *)
444     bfd_alloc (abfd, sizeof (*i_phdrp) * i_ehdrp->e_phnum);
445   if (!i_phdrp)
446     return NULL;
447   if (bfd_seek (abfd, i_ehdrp->e_phoff, SEEK_SET) == -1)
448     return NULL;
449   for (phindex = 0; phindex < i_ehdrp->e_phnum; phindex++)
450     {
451       if (bfd_read ((PTR) & x_phdr, sizeof (x_phdr), 1, abfd)
452           != sizeof (x_phdr))
453         return NULL;
454       elf_swap_phdr_in (abfd, &x_phdr, i_phdrp + phindex);
455     }
456
457   /* Once all of the program headers have been read and converted, we
458      can start processing them. */
459
460   for (phindex = 0; phindex < i_ehdrp->e_phnum; phindex++)
461     {
462       bfd_section_from_phdr (abfd, i_phdrp + phindex, phindex);
463       if ((i_phdrp + phindex)->p_type == PT_NOTE)
464         {
465           if (! elf_corefile_note (abfd, i_phdrp + phindex))
466             return NULL;
467         }
468     }
469
470   /* Remember the entry point specified in the ELF file header. */
471
472   bfd_get_start_address (abfd) = i_ehdrp->e_entry;
473
474   return abfd->xvec;
475 }
This page took 0.051865 seconds and 4 git commands to generate.