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