OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [binutils-2.20.1/] [elfcpp/] [elfcpp_file.h] - Blame information for rev 859

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 205 julius
// elfcpp_file.h -- file access for elfcpp   -*- C++ -*-
2
 
3
// Copyright 2006, 2007, Free Software Foundation, Inc.
4
// Written by Ian Lance Taylor <iant@google.com>.
5
 
6
// This file is part of elfcpp.
7
 
8
// This program is free software; you can redistribute it and/or
9
// modify it under the terms of the GNU Library General Public License
10
// as published by the Free Software Foundation; either version 2, or
11
// (at your option) any later version.
12
 
13
// In addition to the permissions in the GNU Library General Public
14
// License, the Free Software Foundation gives you unlimited
15
// permission to link the compiled version of this file into
16
// combinations with other programs, and to distribute those
17
// combinations without any restriction coming from the use of this
18
// file.  (The Library Public License restrictions do apply in other
19
// respects; for example, they cover modification of the file, and
20
/// distribution when not linked into a combined executable.)
21
 
22
// This program is distributed in the hope that it will be useful, but
23
// WITHOUT ANY WARRANTY; without even the implied warranty of
24
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25
// Library General Public License for more details.
26
 
27
// You should have received a copy of the GNU Library General Public
28
// License along with this program; if not, write to the Free Software
29
// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
30
// 02110-1301, USA.
31
 
32
// This header file defines the class Elf_file which can be used to
33
// read useful data from an ELF file.  The functions here are all
34
// templates which take a file interface object as a parameter.  This
35
// type must have a subtype View.  This type must support two methods:
36
//     View view(off_t file_offset, off_t data_size)
37
// returns a View for the specified part of the file.
38
//     void error(const char* printf_format, ...)
39
// prints an error message and does not return.  The subtype View must
40
// support a method
41
//     const unsigned char* data()
42
// which returns a pointer to a buffer containing the requested data.
43
// This general interface is used to read data from the file.  Objects
44
// of type View will never survive longer than the elfcpp function.
45
 
46
// Some of these functions must return a reference to part of the
47
// file.  To use these, the file interface must support a subtype
48
// Location:
49
//    Location(off_t file_offset, off_t data_size)
50
// To use this in conjunction with the accessors types Shdr, etc., the
51
// file interface should support an overload of view:
52
//    View view(Location)
53
// This permits writing
54
//    elfcpp::Shdr shdr(file, ef.section_header(n));
55
 
56
#ifndef ELFCPP_FILE_H
57
#define ELFCPP_FILE_H
58
 
59
#include <string>
60
#include <cstdio>
61
#include <cstring>
62
 
63
namespace elfcpp
64
{
65
 
66
// A simple helper class to recognize if a file has an ELF header.
67
 
68
class Elf_recognizer
69
{
70
 public:
71
  // Maximum header size.  The user should try to read this much of
72
  // the file when using this class.
73
 
74
  static const int max_header_size = Elf_sizes<64>::ehdr_size;
75
 
76
  // Checks if the file contains the ELF magic.  Other header fields
77
  // are not checked.
78
 
79
  static bool
80
  is_elf_file(const unsigned char* ehdr_buf, int size);
81
 
82
  // Check if EHDR_BUF/BUFSIZE is a valid header of a 32-bit or
83
  // 64-bit, little-endian or big-endian ELF file.  Assumes
84
  // is_elf_file() has been checked to be true.  If the header is not
85
  // valid, *ERROR contains a human-readable error message.  If is is,
86
  // *SIZE is set to either 32 or 64, *BIG_ENDIAN is set to indicate
87
  // whether the file is big-endian.
88
 
89
  static bool
90
  is_valid_header(const unsigned char* ehdr_buf, off_t bufsize,
91
                  int* size, bool* big_endian,
92
                  std::string* error);
93
};
94
 
95
// This object is used to read an ELF file.
96
//   SIZE: The size of file, 32 or 64.
97
//   BIG_ENDIAN: Whether the file is in big-endian format.
98
//   FILE: A file reading type as described above.
99
 
100
template<int size, bool big_endian, typename File>
101
class Elf_file
102
{
103
 private:
104
  typedef Elf_file<size, big_endian, File> This;
105
 
106
 public:
107
  static const int ehdr_size = Elf_sizes<size>::ehdr_size;
108
  static const int phdr_size = Elf_sizes<size>::phdr_size;
109
  static const int shdr_size = Elf_sizes<size>::shdr_size;
110
  static const int sym_size = Elf_sizes<size>::sym_size;
111
  static const int rel_size = Elf_sizes<size>::rel_size;
112
  static const int rela_size = Elf_sizes<size>::rela_size;
113
 
114
  typedef Ehdr<size, big_endian> Ef_ehdr;
115
  typedef Phdr<size, big_endian> Ef_phdr;
116
  typedef Shdr<size, big_endian> Ef_shdr;
117
  typedef Sym<size, big_endian> Ef_sym;
118
 
119
  // Construct an Elf_file given an ELF file header.
120
  Elf_file(File* file, const Ef_ehdr& ehdr)
121
  { this->construct(file, ehdr); }
122
 
123
  // Construct an ELF file.
124
  inline
125
  Elf_file(File* file);
126
 
127
  // Return the file offset to the section headers.
128
  off_t
129
  shoff() const
130
  { return this->shoff_; }
131
 
132
  // Find the first section with an sh_type field equal to TYPE and
133
  // return its index.  Returns SHN_UNDEF if there is no such section.
134
  unsigned int
135
  find_section_by_type(unsigned int type);
136
 
137
  // Return the number of sections.
138
  unsigned int
139
  shnum()
140
  {
141
    this->initialize_shnum();
142
    return this->shnum_;
143
  }
144
 
145
  // Return the section index of the section name string table.
146
  unsigned int
147
  shstrndx()
148
  {
149
    this->initialize_shnum();
150
    return this->shstrndx_;
151
  }
152
 
153
  // Return the value to subtract from section indexes >=
154
  // SHN_LORESERVE.  See the comment in initialize_shnum.
155
  int
156
  large_shndx_offset()
157
  {
158
    this->initialize_shnum();
159
    return this->large_shndx_offset_;
160
  }
161
 
162
  // Return the location of the header of section SHNDX.
163
  typename File::Location
164
  section_header(unsigned int shndx)
165
  {
166
    return typename File::Location(this->section_header_offset(shndx),
167
                                   shdr_size);
168
  }
169
 
170
  // Return the name of section SHNDX.
171
  std::string
172
  section_name(unsigned int shndx);
173
 
174
  // Return the location of the contents of section SHNDX.
175
  typename File::Location
176
  section_contents(unsigned int shndx);
177
 
178
  // Return the size of section SHNDX.
179
  typename Elf_types<size>::Elf_WXword
180
  section_size(unsigned int shndx);
181
 
182
  // Return the flags of section SHNDX.
183
  typename Elf_types<size>::Elf_WXword
184
  section_flags(unsigned int shndx);
185
 
186
  // Return the address of section SHNDX.
187
  typename Elf_types<size>::Elf_Addr
188
  section_addr(unsigned int shndx);
189
 
190
  // Return the type of section SHNDX.
191
  Elf_Word
192
  section_type(unsigned int shndx);
193
 
194
  // Return the link field of section SHNDX.
195
  Elf_Word
196
  section_link(unsigned int shndx);
197
 
198
  // Return the info field of section SHNDX.
199
  Elf_Word
200
  section_info(unsigned int shndx);
201
 
202
  // Return the addralign field of section SHNDX.
203
  typename Elf_types<size>::Elf_WXword
204
  section_addralign(unsigned int shndx);
205
 
206
 private:
207
  // Shared constructor code.
208
  void
209
  construct(File* file, const Ef_ehdr& ehdr);
210
 
211
  // Initialize shnum_ and shstrndx_.
212
  void
213
  initialize_shnum();
214
 
215
  // Return the file offset of the header of section SHNDX.
216
  off_t
217
  section_header_offset(unsigned int shndx);
218
 
219
  // The file we are reading.
220
  File* file_;
221
  // The file offset to the section headers.
222
  off_t shoff_;
223
  // The number of sections.
224
  unsigned int shnum_;
225
  // The section index of the section name string table.
226
  unsigned int shstrndx_;
227
  // Offset to add to sections larger than SHN_LORESERVE.
228
  int large_shndx_offset_;
229
};
230
 
231
// A small wrapper around SHT_STRTAB data mapped to memory. It checks that the
232
// index is not out of bounds and the string is NULL-terminated.
233
 
234
class Elf_strtab
235
{
236
 public:
237
  // Construct an Elf_strtab for a section with contents *P and size SIZE.
238
  Elf_strtab(const unsigned char* p, size_t size);
239
 
240
  // Return the file offset to the section headers.
241
  bool
242
  get_c_string(size_t offset, const char** cstring) const
243
  {
244
    if (offset >= this->usable_size_)
245
      return false;
246
    *cstring = this->base_ + offset;
247
    return true;
248
  }
249
 
250
 private:
251
  // Contents of the section mapped to memory.
252
  const char* base_;
253
  // One larger that the position of the last NULL character in the section.
254
  // For valid SHT_STRTAB sections, this is the size of the section.
255
  size_t usable_size_;
256
};
257
 
258
// Inline function definitions.
259
 
260
// Check for presence of the ELF magic number.
261
 
262
inline bool
263
Elf_recognizer::is_elf_file(const unsigned char* ehdr_buf, int size)
264
{
265
  if (size < 4)
266
    return false;
267
 
268
  static unsigned char elfmagic[4] =
269
    {
270
      elfcpp::ELFMAG0, elfcpp::ELFMAG1,
271
      elfcpp::ELFMAG2, elfcpp::ELFMAG3
272
    };
273
  return memcmp(ehdr_buf, elfmagic, 4) == 0;
274
}
275
 
276
namespace
277
{
278
 
279
// Print a number to a string.
280
 
281
inline std::string
282
internal_printf_int(const char* format, int arg)
283
{
284
  char buf[256];
285
  snprintf(buf, sizeof(buf), format, arg);
286
  return std::string(buf);
287
}
288
 
289
}  // End anonymous namespace.
290
 
291
// Check the validity of the ELF header.
292
 
293
inline bool
294
Elf_recognizer::is_valid_header(
295
    const unsigned char* ehdr_buf,
296
    off_t bufsize,
297
    int* size,
298
    bool* big_endian,
299
    std::string* error)
300
{
301
  if (bufsize < elfcpp::EI_NIDENT)
302
    {
303
      *error = _("ELF file too short");
304
      return false;
305
    }
306
 
307
  int v = ehdr_buf[elfcpp::EI_VERSION];
308
  if (v != elfcpp::EV_CURRENT)
309
    {
310
      if (v == elfcpp::EV_NONE)
311
        *error = _("invalid ELF version 0");
312
      else
313
        *error = internal_printf_int(_("unsupported ELF version %d"), v);
314
      return false;
315
    }
316
 
317
  int c = ehdr_buf[elfcpp::EI_CLASS];
318
  if (c == elfcpp::ELFCLASSNONE)
319
    {
320
      *error = _("invalid ELF class 0");
321
      return false;
322
    }
323
  else if (c != elfcpp::ELFCLASS32
324
           && c != elfcpp::ELFCLASS64)
325
    {
326
      *error = internal_printf_int(_("unsupported ELF class %d"), c);
327
      return false;
328
    }
329
 
330
  int d = ehdr_buf[elfcpp::EI_DATA];
331
  if (d == elfcpp::ELFDATANONE)
332
    {
333
      *error = _("invalid ELF data encoding");
334
      return false;
335
    }
336
  else if (d != elfcpp::ELFDATA2LSB
337
           && d != elfcpp::ELFDATA2MSB)
338
    {
339
      *error = internal_printf_int(_("unsupported ELF data encoding %d"), d);
340
      return false;
341
    }
342
 
343
  *big_endian = (d == elfcpp::ELFDATA2MSB);
344
 
345
  if (c == elfcpp::ELFCLASS32)
346
    {
347
      if (bufsize < elfcpp::Elf_sizes<32>::ehdr_size)
348
        {
349
          *error = _("ELF file too short");
350
          return false;
351
        }
352
      *size = 32;
353
    }
354
  else
355
    {
356
      if (bufsize < elfcpp::Elf_sizes<64>::ehdr_size)
357
        {
358
          *error = _("ELF file too short");
359
          return false;
360
        }
361
      *size = 64;
362
    }
363
 
364
  return true;
365
}
366
 
367
// Template function definitions.
368
 
369
// Construct an Elf_file given an ELF file header.
370
 
371
template<int size, bool big_endian, typename File>
372
void
373
Elf_file<size, big_endian, File>::construct(File* file, const Ef_ehdr& ehdr)
374
{
375
  this->file_ = file;
376
  this->shoff_ = ehdr.get_e_shoff();
377
  this->shnum_ = ehdr.get_e_shnum();
378
  this->shstrndx_ = ehdr.get_e_shstrndx();
379
  this->large_shndx_offset_ = 0;
380
  if (ehdr.get_e_ehsize() != This::ehdr_size)
381
    file->error(_("bad e_ehsize (%d != %d)"),
382
                ehdr.get_e_ehsize(), This::ehdr_size);
383
  if (ehdr.get_e_shentsize() != This::shdr_size)
384
    file->error(_("bad e_shentsize (%d != %d)"),
385
                ehdr.get_e_shentsize(), This::shdr_size);
386
}
387
 
388
// Construct an ELF file.
389
 
390
template<int size, bool big_endian, typename File>
391
inline
392
Elf_file<size, big_endian, File>::Elf_file(File* file)
393
{
394
  typename File::View v(file->view(file_header_offset, This::ehdr_size));
395
  this->construct(file, Ef_ehdr(v.data()));
396
}
397
 
398
// Initialize the shnum_ and shstrndx_ fields, handling overflow.
399
 
400
template<int size, bool big_endian, typename File>
401
void
402
Elf_file<size, big_endian, File>::initialize_shnum()
403
{
404
  if ((this->shnum_ == 0 || this->shstrndx_ == SHN_XINDEX)
405
      && this->shoff_ != 0)
406
    {
407
      typename File::View v(this->file_->view(this->shoff_, This::shdr_size));
408
      Ef_shdr shdr(v.data());
409
 
410
      if (this->shnum_ == 0)
411
        this->shnum_ = shdr.get_sh_size();
412
 
413
      if (this->shstrndx_ == SHN_XINDEX)
414
        {
415
          this->shstrndx_ = shdr.get_sh_link();
416
 
417
          // Versions of the GNU binutils between 2.12 and 2.18 did
418
          // not handle objects with more than SHN_LORESERVE sections
419
          // correctly.  All large section indexes were offset by
420
          // 0x100.  Some information can be found here:
421
          // http://sourceware.org/bugzilla/show_bug.cgi?id=5900 .
422
          // Fortunately these object files are easy to detect, as the
423
          // GNU binutils always put the section header string table
424
          // near the end of the list of sections.  Thus if the
425
          // section header string table index is larger than the
426
          // number of sections, then we know we have to subtract
427
          // 0x100 to get the real section index.
428
          if (this->shstrndx_ >= this->shnum_)
429
            {
430
              if (this->shstrndx_ >= elfcpp::SHN_LORESERVE + 0x100)
431
                {
432
                  this->large_shndx_offset_ = - 0x100;
433
                  this->shstrndx_ -= 0x100;
434
                }
435
              if (this->shstrndx_ >= this->shnum_)
436
                this->file_->error(_("bad shstrndx: %u >= %u"),
437
                                   this->shstrndx_, this->shnum_);
438
            }
439
        }
440
    }
441
}
442
 
443
// Find section with sh_type equal to TYPE and return its index.
444
// Returns SHN_UNDEF if not found.
445
 
446
template<int size, bool big_endian, typename File>
447
unsigned int
448
Elf_file<size, big_endian, File>::find_section_by_type(unsigned int type)
449
{
450
  unsigned int shnum = this->shnum();
451
  typename File::View v(this->file_->view(this->shoff_,
452
                                          This::shdr_size * shnum));
453
  for (unsigned int i = 0; i < shnum; i++)
454
    {
455
      Ef_shdr shdr(v.data() + This::shdr_size * i);
456
      if (shdr.get_sh_type() == type)
457
        return i;
458
    }
459
  return SHN_UNDEF;
460
}
461
 
462
// Return the file offset of the section header of section SHNDX.
463
 
464
template<int size, bool big_endian, typename File>
465
off_t
466
Elf_file<size, big_endian, File>::section_header_offset(unsigned int shndx)
467
{
468
  if (shndx >= this->shnum())
469
    this->file_->error(_("section_header_offset: bad shndx %u >= %u"),
470
                       shndx, this->shnum());
471
  return this->shoff_ + This::shdr_size * shndx;
472
}
473
 
474
// Return the name of section SHNDX.
475
 
476
template<int size, bool big_endian, typename File>
477
std::string
478
Elf_file<size, big_endian, File>::section_name(unsigned int shndx)
479
{
480
  File* const file = this->file_;
481
 
482
  // Get the section name offset.
483
  unsigned int sh_name;
484
  {
485
    typename File::View v(file->view(this->section_header_offset(shndx),
486
                                     This::shdr_size));
487
    Ef_shdr shdr(v.data());
488
    sh_name = shdr.get_sh_name();
489
  }
490
 
491
  // Get the file offset for the section name string table data.
492
  off_t shstr_off;
493
  typename Elf_types<size>::Elf_WXword shstr_size;
494
  {
495
    const unsigned int shstrndx = this->shstrndx_;
496
    typename File::View v(file->view(this->section_header_offset(shstrndx),
497
                                     This::shdr_size));
498
    Ef_shdr shstr_shdr(v.data());
499
    shstr_off = shstr_shdr.get_sh_offset();
500
    shstr_size = shstr_shdr.get_sh_size();
501
  }
502
 
503
  if (sh_name >= shstr_size)
504
    file->error(_("bad section name offset for section %u: %u"),
505
                shndx, sh_name);
506
 
507
  typename File::View v(file->view(shstr_off, shstr_size));
508
 
509
  const unsigned char* datau = v.data();
510
  const char* data = reinterpret_cast<const char*>(datau);
511
  const void* p = ::memchr(data + sh_name, '\0', shstr_size - sh_name);
512
  if (p == NULL)
513
    file->error(_("missing null terminator for name of section %u"),
514
                shndx);
515
 
516
  size_t len = static_cast<const char*>(p) - (data + sh_name);
517
 
518
  return std::string(data + sh_name, len);
519
}
520
 
521
// Return the contents of section SHNDX.
522
 
523
template<int size, bool big_endian, typename File>
524
typename File::Location
525
Elf_file<size, big_endian, File>::section_contents(unsigned int shndx)
526
{
527
  File* const file = this->file_;
528
 
529
  if (shndx >= this->shnum())
530
    file->error(_("section_contents: bad shndx %u >= %u"),
531
                shndx, this->shnum());
532
 
533
  typename File::View v(file->view(this->section_header_offset(shndx),
534
                                   This::shdr_size));
535
  Ef_shdr shdr(v.data());
536
  return typename File::Location(shdr.get_sh_offset(), shdr.get_sh_size());
537
}
538
 
539
// Get the size of section SHNDX.
540
 
541
template<int size, bool big_endian, typename File>
542
typename Elf_types<size>::Elf_WXword
543
Elf_file<size, big_endian, File>::section_size(unsigned int shndx)
544
{
545
  File* const file = this->file_;
546
 
547
  if (shndx >= this->shnum())
548
    file->error(_("section_size: bad shndx %u >= %u"),
549
                shndx, this->shnum());
550
 
551
  typename File::View v(file->view(this->section_header_offset(shndx),
552
                                   This::shdr_size));
553
 
554
  Ef_shdr shdr(v.data());
555
  return shdr.get_sh_size();
556
}
557
 
558
// Return the section flags of section SHNDX.
559
 
560
template<int size, bool big_endian, typename File>
561
typename Elf_types<size>::Elf_WXword
562
Elf_file<size, big_endian, File>::section_flags(unsigned int shndx)
563
{
564
  File* const file = this->file_;
565
 
566
  if (shndx >= this->shnum())
567
    file->error(_("section_flags: bad shndx %u >= %u"),
568
                shndx, this->shnum());
569
 
570
  typename File::View v(file->view(this->section_header_offset(shndx),
571
                                   This::shdr_size));
572
 
573
  Ef_shdr shdr(v.data());
574
  return shdr.get_sh_flags();
575
}
576
 
577
// Return the address of section SHNDX.
578
 
579
template<int size, bool big_endian, typename File>
580
typename Elf_types<size>::Elf_Addr
581
Elf_file<size, big_endian, File>::section_addr(unsigned int shndx)
582
{
583
  File* const file = this->file_;
584
 
585
  if (shndx >= this->shnum())
586
    file->error(_("section_flags: bad shndx %u >= %u"),
587
                shndx, this->shnum());
588
 
589
  typename File::View v(file->view(this->section_header_offset(shndx),
590
                                   This::shdr_size));
591
 
592
  Ef_shdr shdr(v.data());
593
  return shdr.get_sh_addr();
594
}
595
 
596
// Return the type of section SHNDX.
597
 
598
template<int size, bool big_endian, typename File>
599
Elf_Word
600
Elf_file<size, big_endian, File>::section_type(unsigned int shndx)
601
{
602
  File* const file = this->file_;
603
 
604
  if (shndx >= this->shnum())
605
    file->error(_("section_type: bad shndx %u >= %u"),
606
                shndx, this->shnum());
607
 
608
  typename File::View v(file->view(this->section_header_offset(shndx),
609
                                   This::shdr_size));
610
 
611
  Ef_shdr shdr(v.data());
612
  return shdr.get_sh_type();
613
}
614
 
615
// Return the sh_link field of section SHNDX.
616
 
617
template<int size, bool big_endian, typename File>
618
Elf_Word
619
Elf_file<size, big_endian, File>::section_link(unsigned int shndx)
620
{
621
  File* const file = this->file_;
622
 
623
  if (shndx >= this->shnum())
624
    file->error(_("section_link: bad shndx %u >= %u"),
625
                shndx, this->shnum());
626
 
627
  typename File::View v(file->view(this->section_header_offset(shndx),
628
                                   This::shdr_size));
629
 
630
  Ef_shdr shdr(v.data());
631
  return shdr.get_sh_link();
632
}
633
 
634
// Return the sh_info field of section SHNDX.
635
 
636
template<int size, bool big_endian, typename File>
637
Elf_Word
638
Elf_file<size, big_endian, File>::section_info(unsigned int shndx)
639
{
640
  File* const file = this->file_;
641
 
642
  if (shndx >= this->shnum())
643
    file->error(_("section_info: bad shndx %u >= %u"),
644
                shndx, this->shnum());
645
 
646
  typename File::View v(file->view(this->section_header_offset(shndx),
647
                                   This::shdr_size));
648
 
649
  Ef_shdr shdr(v.data());
650
  return shdr.get_sh_info();
651
}
652
 
653
// Return the sh_addralign field of section SHNDX.
654
 
655
template<int size, bool big_endian, typename File>
656
typename Elf_types<size>::Elf_WXword
657
Elf_file<size, big_endian, File>::section_addralign(unsigned int shndx)
658
{
659
  File* const file = this->file_;
660
 
661
  if (shndx >= this->shnum())
662
    file->error(_("section_addralign: bad shndx %u >= %u"),
663
                shndx, this->shnum());
664
 
665
  typename File::View v(file->view(this->section_header_offset(shndx),
666
                                   This::shdr_size));
667
 
668
  Ef_shdr shdr(v.data());
669
  return shdr.get_sh_addralign();
670
}
671
 
672
inline
673
Elf_strtab::Elf_strtab(const unsigned char* p, size_t size)
674
{
675
  // Check if the section is NUL-terminated. If it isn't, we ignore
676
  // the last part to make sure we don't return non-NUL-terminated
677
  // strings.
678
  while (size > 0 && p[size - 1] != 0)
679
    size--;
680
  this->base_ = reinterpret_cast<const char*>(p);
681
  this->usable_size_ = size;
682
}
683
 
684
} // End namespace elfcpp.
685
 
686
#endif // !defined(ELFCPP_FILE_H)

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.