Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5197 serge 1
/* ELF core file support for BFD.
2
   Copyright 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007,
3
   2008, 2010 Free Software Foundation, Inc.
4
 
5
   This file is part of BFD, the Binary File Descriptor library.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program; if not, write to the Free Software
19
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20
   MA 02110-1301, USA.  */
21
 
22
char*
23
elf_core_file_failing_command (bfd *abfd)
24
{
25
  return elf_tdata (abfd)->core->command;
26
}
27
 
28
int
29
elf_core_file_failing_signal (bfd *abfd)
30
{
31
  return elf_tdata (abfd)->core->signal;
32
}
33
 
34
int
35
elf_core_file_pid (bfd *abfd)
36
{
37
  return elf_tdata (abfd)->core->pid;
38
}
39
 
40
bfd_boolean
41
elf_core_file_matches_executable_p (bfd *core_bfd, bfd *exec_bfd)
42
{
43
  char* corename;
44
 
45
  /* xvecs must match if both are ELF files for the same target.  */
46
 
47
  if (core_bfd->xvec != exec_bfd->xvec)
48
    {
49
      bfd_set_error (bfd_error_system_call);
50
      return FALSE;
51
    }
52
 
53
  /* See if the name in the corefile matches the executable name.  */
54
  corename = elf_tdata (core_bfd)->core->program;
55
  if (corename != NULL)
56
    {
57
      const char* execname = strrchr (exec_bfd->filename, '/');
58
 
59
      execname = execname ? execname + 1 : exec_bfd->filename;
60
 
61
      if (strcmp (execname, corename) != 0)
62
	return FALSE;
63
    }
64
 
65
  return TRUE;
66
}
67
 
68
/*  Core files are simply standard ELF formatted files that partition
69
    the file using the execution view of the file (program header table)
70
    rather than the linking view.  In fact, there is no section header
71
    table in a core file.
72
 
73
    The process status information (including the contents of the general
74
    register set) and the floating point register set are stored in a
75
    segment of type PT_NOTE.  We handcraft a couple of extra bfd sections
76
    that allow standard bfd access to the general registers (.reg) and the
77
    floating point registers (.reg2).  */
78
 
79
const bfd_target *
80
elf_core_file_p (bfd *abfd)
81
{
82
  Elf_External_Ehdr x_ehdr;	/* Elf file header, external form.  */
83
  Elf_Internal_Ehdr *i_ehdrp;	/* Elf file header, internal form.  */
84
  Elf_Internal_Phdr *i_phdrp;	/* Elf program header, internal form.  */
85
  unsigned int phindex;
86
  const struct elf_backend_data *ebd;
87
  bfd_size_type amt;
88
 
89
  /* Read in the ELF header in external format.  */
90
  if (bfd_bread (&x_ehdr, sizeof (x_ehdr), abfd) != sizeof (x_ehdr))
91
    {
92
      if (bfd_get_error () != bfd_error_system_call)
93
	goto wrong;
94
      else
95
	goto fail;
96
    }
97
 
98
  /* Check the magic number.  */
99
  if (! elf_file_p (&x_ehdr))
100
    goto wrong;
101
 
102
  /* FIXME: Check EI_VERSION here !  */
103
 
104
  /* Check the address size ("class").  */
105
  if (x_ehdr.e_ident[EI_CLASS] != ELFCLASS)
106
    goto wrong;
107
 
108
  /* Check the byteorder.  */
109
  switch (x_ehdr.e_ident[EI_DATA])
110
    {
111
    case ELFDATA2MSB:		/* Big-endian.  */
112
      if (! bfd_big_endian (abfd))
113
	goto wrong;
114
      break;
115
    case ELFDATA2LSB:		/* Little-endian.  */
116
      if (! bfd_little_endian (abfd))
117
	goto wrong;
118
      break;
119
    default:
120
      goto wrong;
121
    }
122
 
123
  /* Give abfd an elf_obj_tdata.  */
124
  if (! (*abfd->xvec->_bfd_set_format[bfd_core]) (abfd))
125
    goto fail;
126
 
127
  /* Swap in the rest of the header, now that we have the byte order.  */
128
  i_ehdrp = elf_elfheader (abfd);
129
  elf_swap_ehdr_in (abfd, &x_ehdr, i_ehdrp);
130
 
131
#if DEBUG & 1
132
  elf_debug_file (i_ehdrp);
133
#endif
134
 
135
  ebd = get_elf_backend_data (abfd);
136
 
137
  /* Check that the ELF e_machine field matches what this particular
138
     BFD format expects.  */
139
 
140
  if (ebd->elf_machine_code != i_ehdrp->e_machine
141
      && (ebd->elf_machine_alt1 == 0
142
	  || i_ehdrp->e_machine != ebd->elf_machine_alt1)
143
      && (ebd->elf_machine_alt2 == 0
144
	  || i_ehdrp->e_machine != ebd->elf_machine_alt2))
145
    {
146
      const bfd_target * const *target_ptr;
147
 
148
      if (ebd->elf_machine_code != EM_NONE)
149
	goto wrong;
150
 
151
      /* This is the generic ELF target.  Let it match any ELF target
152
	 for which we do not have a specific backend.  */
153
 
154
      for (target_ptr = bfd_target_vector; *target_ptr != NULL; target_ptr++)
155
	{
156
	  const struct elf_backend_data *back;
157
 
158
	  if ((*target_ptr)->flavour != bfd_target_elf_flavour)
159
	    continue;
160
	  back = xvec_get_elf_backend_data (*target_ptr);
161
	  if (back->s->arch_size != ARCH_SIZE)
162
	    continue;
163
	  if (back->elf_machine_code == i_ehdrp->e_machine
164
	      || (back->elf_machine_alt1 != 0
165
	          && i_ehdrp->e_machine == back->elf_machine_alt1)
166
	      || (back->elf_machine_alt2 != 0
167
	          && i_ehdrp->e_machine == back->elf_machine_alt2))
168
	    {
169
	      /* target_ptr is an ELF backend which matches this
170
		 object file, so reject the generic ELF target.  */
171
	      goto wrong;
172
	    }
173
	}
174
    }
175
 
176
  /* If there is no program header, or the type is not a core file, then
177
     we are hosed.  */
178
  if (i_ehdrp->e_phoff == 0 || i_ehdrp->e_type != ET_CORE)
179
    goto wrong;
180
 
181
  /* Does BFD's idea of the phdr size match the size
182
     recorded in the file? */
183
  if (i_ehdrp->e_phentsize != sizeof (Elf_External_Phdr))
184
    goto wrong;
185
 
186
  /* If the program header count is PN_XNUM(0xffff), the actual
187
     count is in the first section header.  */
188
  if (i_ehdrp->e_shoff != 0 && i_ehdrp->e_phnum == PN_XNUM)
189
    {
190
      Elf_External_Shdr x_shdr;
191
      Elf_Internal_Shdr i_shdr;
192
      bfd_signed_vma where = i_ehdrp->e_shoff;
193
 
194
      if (where != (file_ptr) where)
195
	goto wrong;
196
 
197
      /* Seek to the section header table in the file.  */
198
      if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0)
199
	goto fail;
200
 
201
      /* Read the first section header at index 0, and convert to internal
202
	 form.  */
203
      if (bfd_bread (&x_shdr, sizeof (x_shdr), abfd) != sizeof (x_shdr))
204
	goto fail;
205
      elf_swap_shdr_in (abfd, &x_shdr, &i_shdr);
206
 
207
      if (i_shdr.sh_info != 0)
208
	{
209
	  i_ehdrp->e_phnum = i_shdr.sh_info;
210
	  if (i_ehdrp->e_phnum != i_shdr.sh_info)
211
	    goto wrong;
212
	}
213
    }
214
 
215
  /* Sanity check that we can read all of the program headers.
216
     It ought to be good enough to just read the last one.  */
217
  if (i_ehdrp->e_phnum > 1)
218
    {
219
      Elf_External_Phdr x_phdr;
220
      Elf_Internal_Phdr i_phdr;
221
      bfd_signed_vma where;
222
 
223
      /* Check that we don't have a totally silly number of
224
	 program headers.  */
225
      if (i_ehdrp->e_phnum > (unsigned int) -1 / sizeof (x_phdr)
226
	  || i_ehdrp->e_phnum > (unsigned int) -1 / sizeof (i_phdr))
227
	goto wrong;
228
 
229
      where = i_ehdrp->e_phoff + (i_ehdrp->e_phnum - 1) * sizeof (x_phdr);
230
      if (where != (file_ptr) where)
231
	goto wrong;
232
      if ((bfd_size_type) where <= i_ehdrp->e_phoff)
233
	goto wrong;
234
 
235
      if (bfd_seek (abfd, (file_ptr) where, SEEK_SET) != 0)
236
	goto fail;
237
      if (bfd_bread (&x_phdr, sizeof (x_phdr), abfd) != sizeof (x_phdr))
238
	goto fail;
239
    }
240
 
241
  /* Move to the start of the program headers.  */
242
  if (bfd_seek (abfd, (file_ptr) i_ehdrp->e_phoff, SEEK_SET) != 0)
243
    goto wrong;
244
 
245
  /* Allocate space for the program headers.  */
246
  amt = sizeof (*i_phdrp) * i_ehdrp->e_phnum;
247
  i_phdrp = (Elf_Internal_Phdr *) bfd_alloc (abfd, amt);
248
  if (!i_phdrp)
249
    goto fail;
250
 
251
  elf_tdata (abfd)->phdr = i_phdrp;
252
 
253
  /* Read and convert to internal form.  */
254
  for (phindex = 0; phindex < i_ehdrp->e_phnum; ++phindex)
255
    {
256
      Elf_External_Phdr x_phdr;
257
 
258
      if (bfd_bread (&x_phdr, sizeof (x_phdr), abfd) != sizeof (x_phdr))
259
	goto fail;
260
 
261
      elf_swap_phdr_in (abfd, &x_phdr, i_phdrp + phindex);
262
    }
263
 
264
  /* Set the machine architecture.  Do this before processing the
265
     program headers since we need to know the architecture type
266
     when processing the notes of some systems' core files.  */
267
  if (! bfd_default_set_arch_mach (abfd, ebd->arch, 0)
268
      /* It's OK if this fails for the generic target.  */
269
      && ebd->elf_machine_code != EM_NONE)
270
    goto fail;
271
 
272
  /* Let the backend double check the format and override global
273
     information.  We do this before processing the program headers
274
     to allow the correct machine (as opposed to just the default
275
     machine) to be set, making it possible for grok_prstatus and
276
     grok_psinfo to rely on the mach setting.  */
277
  if (ebd->elf_backend_object_p != NULL
278
      && ! ebd->elf_backend_object_p (abfd))
279
    goto wrong;
280
 
281
  /* Process each program header.  */
282
  for (phindex = 0; phindex < i_ehdrp->e_phnum; ++phindex)
283
    if (! bfd_section_from_phdr (abfd, i_phdrp + phindex, (int) phindex))
284
      goto fail;
285
 
286
  /* Check for core truncation.  */
287
  {
288
    bfd_size_type high = 0;
289
    struct stat statbuf;
290
    for (phindex = 0; phindex < i_ehdrp->e_phnum; ++phindex)
291
      {
292
	Elf_Internal_Phdr *p = i_phdrp + phindex;
293
	if (p->p_filesz)
294
	  {
295
	    bfd_size_type current = p->p_offset + p->p_filesz;
296
	    if (high < current)
297
	      high = current;
298
	  }
299
      }
300
    if (bfd_stat (abfd, &statbuf) == 0)
301
      {
302
	if ((bfd_size_type) statbuf.st_size < high)
303
	  {
304
	    (*_bfd_error_handler)
305
	      (_("Warning: %B is truncated: expected core file "
306
		 "size >= %lu, found: %lu."),
307
	       abfd, (unsigned long) high, (unsigned long) statbuf.st_size);
308
	  }
309
      }
310
  }
311
 
312
  /* Save the entry point from the ELF header.  */
313
  bfd_get_start_address (abfd) = i_ehdrp->e_entry;
314
  return abfd->xvec;
315
 
316
wrong:
317
  bfd_set_error (bfd_error_wrong_format);
318
fail:
319
  return NULL;
320
}