1// ehframe.h -- handle exception frame sections for gold  -*- C++ -*-
2
3// Copyright (C) 2006-2017 Free Software Foundation, Inc.
4// Written by Ian Lance Taylor <iant@google.com>.
5
6// This file is part of gold.
7
8// This program is free software; you can redistribute it and/or modify
9// it under the terms of the GNU General Public License as published by
10// the Free Software Foundation; either version 3 of the License, or
11// (at your option) any later version.
12
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16// GNU General Public License for more details.
17
18// You should have received a copy of the GNU General Public License
19// along with this program; if not, write to the Free Software
20// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21// MA 02110-1301, USA.
22
23#ifndef GOLD_EHFRAME_H
24#define GOLD_EHFRAME_H
25
26#include <map>
27#include <set>
28#include <vector>
29
30#include "output.h"
31#include "merge.h"
32
33namespace gold
34{
35
36template<int size, bool big_endian>
37class Track_relocs;
38
39class Eh_frame;
40
41// This class manages the .eh_frame_hdr section, which holds the data
42// for the PT_GNU_EH_FRAME segment.  gcc's unwind support code uses
43// the PT_GNU_EH_FRAME segment to find the list of FDEs.  This saves
44// the time required to register the exception handlers at startup
45// time and when a shared object is loaded, and the time required to
46// deregister the exception handlers when a shared object is unloaded.
47
48class Eh_frame_hdr : public Output_section_data
49{
50 public:
51  Eh_frame_hdr(Output_section* eh_frame_section, const Eh_frame*);
52
53  // Record that we found an unrecognized .eh_frame section.
54  void
55  found_unrecognized_eh_frame_section()
56  { this->any_unrecognized_eh_frame_sections_ = true; }
57
58  // Record an FDE.
59  void
60  record_fde(section_offset_type fde_offset, unsigned char fde_encoding)
61  {
62    if (!this->any_unrecognized_eh_frame_sections_)
63      this->fde_offsets_.push_back(std::make_pair(fde_offset, fde_encoding));
64  }
65
66 protected:
67  // Set the final data size.
68  void
69  set_final_data_size();
70
71  // Write the data to the file.
72  void
73  do_write(Output_file*);
74
75  // Write to a map file.
76  void
77  do_print_to_mapfile(Mapfile* mapfile) const
78  { mapfile->print_output_data(this, _("** eh_frame_hdr")); }
79
80 private:
81  // Write the data to the file with the right endianness.
82  template<int size, bool big_endian>
83  void
84  do_sized_write(Output_file*);
85
86  // The data we record for one FDE: the offset of the FDE within the
87  // .eh_frame section, and the FDE encoding.
88  typedef std::pair<section_offset_type, unsigned char> Fde_offset;
89
90  // The list of information we record for an FDE.
91  typedef std::vector<Fde_offset> Fde_offsets;
92
93  // When writing out the header, we convert the FDE offsets into FDE
94  // addresses.  This is a list of pairs of the offset from the header
95  // to the FDE PC and to the FDE itself.
96  template<int size>
97  class Fde_addresses
98  {
99   public:
100    typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
101    typedef typename std::pair<Address, Address> Fde_address;
102    typedef typename std::vector<Fde_address> Fde_address_list;
103    typedef typename Fde_address_list::iterator iterator;
104
105    Fde_addresses(unsigned int reserve)
106      : fde_addresses_()
107    { this->fde_addresses_.reserve(reserve); }
108
109    void
110    push_back(Address pc_address, Address fde_address)
111    {
112      this->fde_addresses_.push_back(std::make_pair(pc_address, fde_address));
113    }
114
115    iterator
116    begin()
117    { return this->fde_addresses_.begin(); }
118
119    iterator
120    end()
121    { return this->fde_addresses_.end(); }
122
123   private:
124    Fde_address_list fde_addresses_;
125  };
126
127  // Compare Fde_address objects.
128  template<int size>
129  struct Fde_address_compare
130  {
131    bool
132    operator()(const typename Fde_addresses<size>::Fde_address& f1,
133	       const typename Fde_addresses<size>::Fde_address& f2) const
134    { return f1.first < f2.first; }
135  };
136
137  // Return the PC to which an FDE refers.
138  template<int size, bool big_endian>
139  typename elfcpp::Elf_types<size>::Elf_Addr
140  get_fde_pc(typename elfcpp::Elf_types<size>::Elf_Addr eh_frame_address,
141	     const unsigned char* eh_frame_contents,
142	     section_offset_type fde_offset, unsigned char fde_encoding);
143
144  // Convert Fde_offsets to Fde_addresses.
145  template<int size, bool big_endian>
146  void
147  get_fde_addresses(Output_file* of,
148		    const Fde_offsets* fde_offsets,
149		    Fde_addresses<size>* fde_addresses);
150
151  // The .eh_frame section.
152  Output_section* eh_frame_section_;
153  // The .eh_frame section data.
154  const Eh_frame* eh_frame_data_;
155  // Data from the FDEs in the .eh_frame sections.
156  Fde_offsets fde_offsets_;
157  // Whether we found any .eh_frame sections which we could not
158  // process.
159  bool any_unrecognized_eh_frame_sections_;
160};
161
162// This class holds an FDE.
163
164class Fde
165{
166 public:
167  Fde(Relobj* object, unsigned int shndx, section_offset_type input_offset,
168      const unsigned char* contents, size_t length)
169    : object_(object),
170      contents_(reinterpret_cast<const char*>(contents), length)
171  {
172    this->u_.from_object.shndx = shndx;
173    this->u_.from_object.input_offset = input_offset;
174  }
175
176  // Create an FDE associated with a PLT.
177  Fde(Output_data* plt, const unsigned char* contents, size_t length,
178      bool post_map)
179    : object_(NULL),
180      contents_(reinterpret_cast<const char*>(contents), length)
181  {
182    this->u_.from_linker.plt = plt;
183    this->u_.from_linker.post_map = post_map;
184  }
185
186  // Return the length of this FDE.  Add 4 for the length and 4 for
187  // the offset to the CIE.
188  size_t
189  length() const
190  { return this->contents_.length() + 8; }
191
192  // Add a mapping for this FDE to MERGE_MAP, so that relocations
193  // against the FDE are applied to right part of the output file.
194  void
195  add_mapping(section_offset_type output_offset,
196              Output_section_data* output_data) const
197  {
198    if (this->object_ != NULL)
199      this->object_->add_merge_mapping(output_data, this->u_.from_object.shndx,
200			     this->u_.from_object.input_offset, this->length(),
201			     output_offset);
202  }
203
204  // Return whether this FDE was added after merge mapping.
205  bool
206  post_map()
207  { return this->object_ == NULL && this->u_.from_linker.post_map; }
208
209  // Write the FDE to OVIEW starting at OFFSET.  FDE_ENCODING is the
210  // encoding, from the CIE.  Round up the bytes to ADDRALIGN if
211  // necessary.  ADDRESS is the virtual address of OVIEW.  Record the
212  // FDE in EH_FRAME_HDR.  Return the new offset.
213  template<int size, bool big_endian>
214  section_offset_type
215  write(unsigned char* oview, section_offset_type output_section_offset,
216	section_offset_type offset, uint64_t address, unsigned int addralign,
217	section_offset_type cie_offset, unsigned char fde_encoding,
218	Eh_frame_hdr* eh_frame_hdr);
219
220 private:
221  // The object in which this FDE was seen.  This will be NULL for a
222  // linker generated FDE.
223  Relobj* object_;
224  union
225  {
226    // These fields are used if the FDE is from an input object (the
227    // object_ field is not NULL).
228    struct
229    {
230      // Input section index for this FDE.
231      unsigned int shndx;
232      // Offset within the input section for this FDE.
233      section_offset_type input_offset;
234    } from_object;
235    // This field is used if the FDE is generated by the linker (the
236    // object_ field is NULL).
237    struct
238    {
239      // The only linker generated FDEs are for PLT sections, and this
240      // points to the PLT section.
241      Output_data* plt;
242      // Set if the FDE was added after merge mapping.
243      bool post_map;
244    } from_linker;
245  } u_;
246  // FDE data.
247  std::string contents_;
248};
249
250// A FDE plus some info from a CIE to allow later writing of the FDE.
251
252struct Post_fde
253{
254  Post_fde(Fde* f, section_offset_type cie_off, unsigned char encoding)
255    : fde(f), cie_offset(cie_off), fde_encoding(encoding)
256  { }
257
258  Fde* fde;
259  section_offset_type cie_offset;
260  unsigned char fde_encoding;
261};
262
263typedef std::vector<Post_fde> Post_fdes;
264
265// This class holds a CIE.
266
267class Cie
268{
269 public:
270  Cie(Relobj* object, unsigned int shndx, section_offset_type input_offset,
271      unsigned char fde_encoding, const char* personality_name,
272      const unsigned char* contents, size_t length)
273    : object_(object),
274      shndx_(shndx),
275      input_offset_(input_offset),
276      fde_encoding_(fde_encoding),
277      personality_name_(personality_name),
278      fdes_(),
279      contents_(reinterpret_cast<const char*>(contents), length)
280  { }
281
282  ~Cie();
283
284  // We permit copying a CIE when there are no FDEs.  This is
285  // convenient in the code which creates them.
286  Cie(const Cie& cie)
287    : object_(cie.object_),
288      shndx_(cie.shndx_),
289      input_offset_(cie.input_offset_),
290      fde_encoding_(cie.fde_encoding_),
291      personality_name_(cie.personality_name_),
292      fdes_(),
293      contents_(cie.contents_)
294  { gold_assert(cie.fdes_.empty()); }
295
296  // Add an FDE associated with this CIE.
297  void
298  add_fde(Fde* fde)
299  { this->fdes_.push_back(fde); }
300
301  // Return the number of FDEs.
302  unsigned int
303  fde_count() const
304  { return this->fdes_.size(); }
305
306  // Set the output offset of this CIE to OUTPUT_OFFSET.  It will be
307  // followed by all its FDEs.  ADDRALIGN is the required address
308  // alignment, typically 4 or 8.  This updates MERGE_MAP with the
309  // mapping.  It returns the new output offset.
310  section_offset_type
311  set_output_offset(section_offset_type output_offset, unsigned int addralign,
312		    Output_section_data*);
313
314  // Write the CIE to OVIEW starting at OFFSET.  Round up the bytes to
315  // ADDRALIGN.  ADDRESS is the virtual address of OVIEW.
316  // EH_FRAME_HDR is the exception frame header for FDE recording.
317  // POST_FDES stashes FDEs created after mappings were done, for later
318  // writing.  Return the new offset.
319  template<int size, bool big_endian>
320  section_offset_type
321  write(unsigned char* oview, section_offset_type output_section_offset,
322	section_offset_type offset, uint64_t address,
323	unsigned int addralign, Eh_frame_hdr* eh_frame_hdr,
324	Post_fdes* post_fdes);
325
326  // Return the FDE encoding.
327  unsigned char
328  fde_encoding() const
329  { return this->fde_encoding_; }
330
331  friend bool operator<(const Cie&, const Cie&);
332  friend bool operator==(const Cie&, const Cie&);
333
334 private:
335  // The class is not assignable.
336  Cie& operator=(const Cie&);
337
338  // The object in which this CIE was first seen.  This will be NULL
339  // for a linker generated CIE.
340  Relobj* object_;
341  // Input section index for this CIE.  This will be 0 for a linker
342  // generated CIE.
343  unsigned int shndx_;
344  // Offset within the input section for this CIE.  This will be 0 for
345  // a linker generated CIE.
346  section_offset_type input_offset_;
347  // The encoding of the FDE.  This is a DW_EH_PE code.
348  unsigned char fde_encoding_;
349  // The name of the personality routine.  This will be the name of a
350  // global symbol, or will be the empty string.
351  std::string personality_name_;
352  // List of FDEs.
353  std::vector<Fde*> fdes_;
354  // CIE data.
355  std::string contents_;
356};
357
358extern bool operator<(const Cie&, const Cie&);
359extern bool operator==(const Cie&, const Cie&);
360
361// This class manages .eh_frame sections.  It discards duplicate
362// exception information.
363
364class Eh_frame : public Output_section_data
365{
366 public:
367  enum Eh_frame_section_disposition
368  {
369    EH_EMPTY_SECTION,
370    EH_UNRECOGNIZED_SECTION,
371    EH_OPTIMIZABLE_SECTION,
372    EH_END_MARKER_SECTION
373  };
374
375  Eh_frame();
376
377  // Record the associated Eh_frame_hdr, if any.
378  void
379  set_eh_frame_hdr(Eh_frame_hdr* hdr)
380  { this->eh_frame_hdr_ = hdr; }
381
382  // Add the input section SHNDX in OBJECT.  SYMBOLS is the contents
383  // of the symbol table section (size SYMBOLS_SIZE), SYMBOL_NAMES is
384  // the symbol names section (size SYMBOL_NAMES_SIZE).  RELOC_SHNDX
385  // is the relocation section if any (0 for none, -1U for multiple).
386  // RELOC_TYPE is the type of the relocation section if any.  This
387  // returns whether the section was incorporated into the .eh_frame
388  // data.
389  template<int size, bool big_endian>
390  Eh_frame_section_disposition
391  add_ehframe_input_section(Sized_relobj_file<size, big_endian>* object,
392			    const unsigned char* symbols,
393			    section_size_type symbols_size,
394			    const unsigned char* symbol_names,
395			    section_size_type symbol_names_size,
396			    unsigned int shndx, unsigned int reloc_shndx,
397			    unsigned int reloc_type);
398
399  // Add a CIE and an FDE for a PLT section, to permit unwinding
400  // through a PLT.  The FDE data should start with 8 bytes of zero,
401  // which will be replaced by a 4 byte PC relative reference to the
402  // address of PLT and a 4 byte size of PLT.
403  void
404  add_ehframe_for_plt(Output_data* plt, const unsigned char* cie_data,
405		      size_t cie_length, const unsigned char* fde_data,
406		      size_t fde_length);
407
408  // Return the number of FDEs.
409  unsigned int
410  fde_count() const;
411
412 protected:
413  // Set the final data size.
414  void
415  set_final_data_size();
416
417  // Return the output address for an input address.
418  bool
419  do_output_offset(const Relobj*, unsigned int shndx,
420		   section_offset_type offset,
421		   section_offset_type* poutput) const;
422
423  // Write the data to the file.
424  void
425  do_write(Output_file*);
426
427  // Write to a map file.
428  void
429  do_print_to_mapfile(Mapfile* mapfile) const
430  { mapfile->print_output_data(this, _("** eh_frame")); }
431
432 private:
433  // The comparison routine for the CIE map.
434  struct Cie_less
435  {
436    bool
437    operator()(const Cie* cie1, const Cie* cie2) const
438    { return *cie1 < *cie2; }
439  };
440
441  // A set of unique CIEs.
442  typedef std::set<Cie*, Cie_less> Cie_offsets;
443
444  // A list of unmergeable CIEs.
445  typedef std::vector<Cie*> Unmergeable_cie_offsets;
446
447  // A mapping from offsets to CIEs.  This is used while reading an
448  // input section.
449  typedef std::map<uint64_t, Cie*> Offsets_to_cie;
450
451  // A list of CIEs, and a bool indicating whether the CIE is
452  // mergeable.
453  typedef std::vector<std::pair<Cie*, bool> > New_cies;
454
455  // Skip an LEB128.
456  static bool
457  skip_leb128(const unsigned char**, const unsigned char*);
458
459  // The implementation of add_ehframe_input_section.
460  template<int size, bool big_endian>
461  bool
462  do_add_ehframe_input_section(Sized_relobj_file<size, big_endian>* object,
463			       const unsigned char* symbols,
464			       section_size_type symbols_size,
465			       const unsigned char* symbol_names,
466			       section_size_type symbol_names_size,
467			       unsigned int shndx,
468			       unsigned int reloc_shndx,
469			       unsigned int reloc_type,
470			       const unsigned char* pcontents,
471			       section_size_type contents_len,
472			       New_cies*);
473
474  // Read a CIE.
475  template<int size, bool big_endian>
476  bool
477  read_cie(Sized_relobj_file<size, big_endian>* object,
478	   unsigned int shndx,
479	   const unsigned char* symbols,
480	   section_size_type symbols_size,
481	   const unsigned char* symbol_names,
482	   section_size_type symbol_names_size,
483	   const unsigned char* pcontents,
484	   const unsigned char* pcie,
485	   const unsigned char* pcieend,
486	   Track_relocs<size, big_endian>* relocs,
487	   Offsets_to_cie* cies,
488	   New_cies* new_cies);
489
490  // Read an FDE.
491  template<int size, bool big_endian>
492  bool
493  read_fde(Sized_relobj_file<size, big_endian>* object,
494	   unsigned int shndx,
495	   const unsigned char* symbols,
496	   section_size_type symbols_size,
497	   const unsigned char* pcontents,
498	   unsigned int offset,
499	   const unsigned char* pfde,
500	   const unsigned char* pfdeend,
501	   Track_relocs<size, big_endian>* relocs,
502	   Offsets_to_cie* cies);
503
504  // Template version of write function.
505  template<int size, bool big_endian>
506  void
507  do_sized_write(unsigned char* oview);
508
509  // The exception frame header, if any.
510  Eh_frame_hdr* eh_frame_hdr_;
511  // A mapping from all unique CIEs to their offset in the output
512  // file.
513  Cie_offsets cie_offsets_;
514  // A mapping from unmergeable CIEs to their offset in the output
515  // file.
516  Unmergeable_cie_offsets unmergeable_cie_offsets_;
517  // Whether we have created the mappings to the output section.
518  bool mappings_are_done_;
519  // The final data size.  This is only set if mappings_are_done_ is
520  // true.
521  section_size_type final_data_size_;
522};
523
524} // End namespace gold.
525
526#endif // !defined(GOLD_EHFRAME_H)
527