Subversion Repositories Kolibri OS

Rev

Rev 5197 | Details | Compare with Previous | Last modification | View Log | RSS feed

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