[BACK]Return to ehframe.h CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / gpl3 / binutils.old / dist / gold

Annotation of src/external/gpl3/binutils.old/dist/gold/ehframe.h, Revision 1.1

1.1     ! christos    1: // ehframe.h -- handle exception frame sections for gold  -*- C++ -*-
        !             2:
        !             3: // Copyright 2006, 2007, 2008, 2010, 2011 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:
        !            33: namespace gold
        !            34: {
        !            35:
        !            36: template<int size, bool big_endian>
        !            37: class Track_relocs;
        !            38:
        !            39: class 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:
        !            48: class 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:
        !           164: class 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:     : object_(NULL),
        !           179:       contents_(reinterpret_cast<const char*>(contents), length)
        !           180:   { this->u_.from_linker.plt = plt; }
        !           181:
        !           182:   // Return the length of this FDE.  Add 4 for the length and 4 for
        !           183:   // the offset to the CIE.
        !           184:   size_t
        !           185:   length() const
        !           186:   { return this->contents_.length() + 8; }
        !           187:
        !           188:   // Add a mapping for this FDE to MERGE_MAP, so that relocations
        !           189:   // against the FDE are applied to right part of the output file.
        !           190:   void
        !           191:   add_mapping(section_offset_type output_offset, Merge_map* merge_map) const
        !           192:   {
        !           193:     if (this->object_ != NULL)
        !           194:       merge_map->add_mapping(this->object_, this->u_.from_object.shndx,
        !           195:                             this->u_.from_object.input_offset, this->length(),
        !           196:                             output_offset);
        !           197:   }
        !           198:
        !           199:   // Write the FDE to OVIEW starting at OFFSET.  FDE_ENCODING is the
        !           200:   // encoding, from the CIE.  Round up the bytes to ADDRALIGN if
        !           201:   // necessary.  ADDRESS is the virtual address of OVIEW.  Record the
        !           202:   // FDE in EH_FRAME_HDR.  Return the new offset.
        !           203:   template<int size, bool big_endian>
        !           204:   section_offset_type
        !           205:   write(unsigned char* oview, section_offset_type offset,
        !           206:        uint64_t address, unsigned int addralign,
        !           207:        section_offset_type cie_offset, unsigned char fde_encoding,
        !           208:        Eh_frame_hdr* eh_frame_hdr);
        !           209:
        !           210:  private:
        !           211:   // The object in which this FDE was seen.  This will be NULL for a
        !           212:   // linker generated FDE.
        !           213:   Relobj* object_;
        !           214:   union
        !           215:   {
        !           216:     // These fields are used if the FDE is from an input object (the
        !           217:     // object_ field is not NULL).
        !           218:     struct
        !           219:     {
        !           220:       // Input section index for this FDE.
        !           221:       unsigned int shndx;
        !           222:       // Offset within the input section for this FDE.
        !           223:       section_offset_type input_offset;
        !           224:     } from_object;
        !           225:     // This field is used if the FDE is generated by the linker (the
        !           226:     // object_ field is NULL).
        !           227:     struct
        !           228:     {
        !           229:       // The only linker generated FDEs are for PLT sections, and this
        !           230:       // points to the PLT section.
        !           231:       Output_data* plt;
        !           232:     } from_linker;
        !           233:   } u_;
        !           234:   // FDE data.
        !           235:   std::string contents_;
        !           236: };
        !           237:
        !           238: // This class holds a CIE.
        !           239:
        !           240: class Cie
        !           241: {
        !           242:  public:
        !           243:   Cie(Relobj* object, unsigned int shndx, section_offset_type input_offset,
        !           244:       unsigned char fde_encoding, const char* personality_name,
        !           245:       const unsigned char* contents, size_t length)
        !           246:     : object_(object),
        !           247:       shndx_(shndx),
        !           248:       input_offset_(input_offset),
        !           249:       fde_encoding_(fde_encoding),
        !           250:       personality_name_(personality_name),
        !           251:       fdes_(),
        !           252:       contents_(reinterpret_cast<const char*>(contents), length)
        !           253:   { }
        !           254:
        !           255:   ~Cie();
        !           256:
        !           257:   // We permit copying a CIE when there are no FDEs.  This is
        !           258:   // convenient in the code which creates them.
        !           259:   Cie(const Cie& cie)
        !           260:     : object_(cie.object_),
        !           261:       shndx_(cie.shndx_),
        !           262:       input_offset_(cie.input_offset_),
        !           263:       fde_encoding_(cie.fde_encoding_),
        !           264:       personality_name_(cie.personality_name_),
        !           265:       fdes_(),
        !           266:       contents_(cie.contents_)
        !           267:   { gold_assert(cie.fdes_.empty()); }
        !           268:
        !           269:   // Add an FDE associated with this CIE.
        !           270:   void
        !           271:   add_fde(Fde* fde)
        !           272:   { this->fdes_.push_back(fde); }
        !           273:
        !           274:   // Return the number of FDEs.
        !           275:   unsigned int
        !           276:   fde_count() const
        !           277:   { return this->fdes_.size(); }
        !           278:
        !           279:   // Set the output offset of this CIE to OUTPUT_OFFSET.  It will be
        !           280:   // followed by all its FDEs.  ADDRALIGN is the required address
        !           281:   // alignment, typically 4 or 8.  This updates MERGE_MAP with the
        !           282:   // mapping.  It returns the new output offset.
        !           283:   section_offset_type
        !           284:   set_output_offset(section_offset_type output_offset, unsigned int addralign,
        !           285:                    Merge_map*);
        !           286:
        !           287:   // Write the CIE to OVIEW starting at OFFSET.  EH_FRAME_HDR is the
        !           288:   // exception frame header for FDE recording.  Round up the bytes to
        !           289:   // ADDRALIGN.  ADDRESS is the virtual address of OVIEW.  Return the
        !           290:   // new offset.
        !           291:   template<int size, bool big_endian>
        !           292:   section_offset_type
        !           293:   write(unsigned char* oview, section_offset_type offset, uint64_t address,
        !           294:        unsigned int addralign, Eh_frame_hdr* eh_frame_hdr);
        !           295:
        !           296:   friend bool operator<(const Cie&, const Cie&);
        !           297:   friend bool operator==(const Cie&, const Cie&);
        !           298:
        !           299:  private:
        !           300:   // The class is not assignable.
        !           301:   Cie& operator=(const Cie&);
        !           302:
        !           303:   // The object in which this CIE was first seen.  This will be NULL
        !           304:   // for a linker generated CIE.
        !           305:   Relobj* object_;
        !           306:   // Input section index for this CIE.  This will be 0 for a linker
        !           307:   // generated CIE.
        !           308:   unsigned int shndx_;
        !           309:   // Offset within the input section for this CIE.  This will be 0 for
        !           310:   // a linker generated CIE.
        !           311:   section_offset_type input_offset_;
        !           312:   // The encoding of the FDE.  This is a DW_EH_PE code.
        !           313:   unsigned char fde_encoding_;
        !           314:   // The name of the personality routine.  This will be the name of a
        !           315:   // global symbol, or will be the empty string.
        !           316:   std::string personality_name_;
        !           317:   // List of FDEs.
        !           318:   std::vector<Fde*> fdes_;
        !           319:   // CIE data.
        !           320:   std::string contents_;
        !           321: };
        !           322:
        !           323: extern bool operator<(const Cie&, const Cie&);
        !           324: extern bool operator==(const Cie&, const Cie&);
        !           325:
        !           326: // This class manages .eh_frame sections.  It discards duplicate
        !           327: // exception information.
        !           328:
        !           329: class Eh_frame : public Output_section_data
        !           330: {
        !           331:  public:
        !           332:   Eh_frame();
        !           333:
        !           334:   // Record the associated Eh_frame_hdr, if any.
        !           335:   void
        !           336:   set_eh_frame_hdr(Eh_frame_hdr* hdr)
        !           337:   { this->eh_frame_hdr_ = hdr; }
        !           338:
        !           339:   // Add the input section SHNDX in OBJECT.  SYMBOLS is the contents
        !           340:   // of the symbol table section (size SYMBOLS_SIZE), SYMBOL_NAMES is
        !           341:   // the symbol names section (size SYMBOL_NAMES_SIZE).  RELOC_SHNDX
        !           342:   // is the relocation section if any (0 for none, -1U for multiple).
        !           343:   // RELOC_TYPE is the type of the relocation section if any.  This
        !           344:   // returns whether the section was incorporated into the .eh_frame
        !           345:   // data.
        !           346:   template<int size, bool big_endian>
        !           347:   bool
        !           348:   add_ehframe_input_section(Sized_relobj_file<size, big_endian>* object,
        !           349:                            const unsigned char* symbols,
        !           350:                            section_size_type symbols_size,
        !           351:                            const unsigned char* symbol_names,
        !           352:                            section_size_type symbol_names_size,
        !           353:                            unsigned int shndx, unsigned int reloc_shndx,
        !           354:                            unsigned int reloc_type);
        !           355:
        !           356:   // Add a CIE and an FDE for a PLT section, to permit unwinding
        !           357:   // through a PLT.  The FDE data should start with 8 bytes of zero,
        !           358:   // which will be replaced by a 4 byte PC relative reference to the
        !           359:   // address of PLT and a 4 byte size of PLT.
        !           360:   void
        !           361:   add_ehframe_for_plt(Output_data* plt, const unsigned char* cie_data,
        !           362:                      size_t cie_length, const unsigned char* fde_data,
        !           363:                      size_t fde_length);
        !           364:
        !           365:   // Return the number of FDEs.
        !           366:   unsigned int
        !           367:   fde_count() const;
        !           368:
        !           369:  protected:
        !           370:   // Set the final data size.
        !           371:   void
        !           372:   set_final_data_size();
        !           373:
        !           374:   // Return the output address for an input address.
        !           375:   bool
        !           376:   do_output_offset(const Relobj*, unsigned int shndx,
        !           377:                   section_offset_type offset,
        !           378:                   section_offset_type* poutput) const;
        !           379:
        !           380:   // Return whether this is the merge section for an input section.
        !           381:   bool
        !           382:   do_is_merge_section_for(const Relobj*, unsigned int shndx) const;
        !           383:
        !           384:   // Write the data to the file.
        !           385:   void
        !           386:   do_write(Output_file*);
        !           387:
        !           388:   // Write to a map file.
        !           389:   void
        !           390:   do_print_to_mapfile(Mapfile* mapfile) const
        !           391:   { mapfile->print_output_data(this, _("** eh_frame")); }
        !           392:
        !           393:  private:
        !           394:   // The comparison routine for the CIE map.
        !           395:   struct Cie_less
        !           396:   {
        !           397:     bool
        !           398:     operator()(const Cie* cie1, const Cie* cie2) const
        !           399:     { return *cie1 < *cie2; }
        !           400:   };
        !           401:
        !           402:   // A set of unique CIEs.
        !           403:   typedef std::set<Cie*, Cie_less> Cie_offsets;
        !           404:
        !           405:   // A list of unmergeable CIEs.
        !           406:   typedef std::vector<Cie*> Unmergeable_cie_offsets;
        !           407:
        !           408:   // A mapping from offsets to CIEs.  This is used while reading an
        !           409:   // input section.
        !           410:   typedef std::map<uint64_t, Cie*> Offsets_to_cie;
        !           411:
        !           412:   // A list of CIEs, and a bool indicating whether the CIE is
        !           413:   // mergeable.
        !           414:   typedef std::vector<std::pair<Cie*, bool> > New_cies;
        !           415:
        !           416:   // Skip an LEB128.
        !           417:   static bool
        !           418:   skip_leb128(const unsigned char**, const unsigned char*);
        !           419:
        !           420:   // The implementation of add_ehframe_input_section.
        !           421:   template<int size, bool big_endian>
        !           422:   bool
        !           423:   do_add_ehframe_input_section(Sized_relobj_file<size, big_endian>* object,
        !           424:                               const unsigned char* symbols,
        !           425:                               section_size_type symbols_size,
        !           426:                               const unsigned char* symbol_names,
        !           427:                               section_size_type symbol_names_size,
        !           428:                               unsigned int shndx,
        !           429:                               unsigned int reloc_shndx,
        !           430:                               unsigned int reloc_type,
        !           431:                               const unsigned char* pcontents,
        !           432:                               section_size_type contents_len,
        !           433:                               New_cies*);
        !           434:
        !           435:   // Read a CIE.
        !           436:   template<int size, bool big_endian>
        !           437:   bool
        !           438:   read_cie(Sized_relobj_file<size, big_endian>* object,
        !           439:           unsigned int shndx,
        !           440:           const unsigned char* symbols,
        !           441:           section_size_type symbols_size,
        !           442:           const unsigned char* symbol_names,
        !           443:           section_size_type symbol_names_size,
        !           444:           const unsigned char* pcontents,
        !           445:           const unsigned char* pcie,
        !           446:           const unsigned char* pcieend,
        !           447:           Track_relocs<size, big_endian>* relocs,
        !           448:           Offsets_to_cie* cies,
        !           449:           New_cies* new_cies);
        !           450:
        !           451:   // Read an FDE.
        !           452:   template<int size, bool big_endian>
        !           453:   bool
        !           454:   read_fde(Sized_relobj_file<size, big_endian>* object,
        !           455:           unsigned int shndx,
        !           456:           const unsigned char* symbols,
        !           457:           section_size_type symbols_size,
        !           458:           const unsigned char* pcontents,
        !           459:           unsigned int offset,
        !           460:           const unsigned char* pfde,
        !           461:           const unsigned char* pfdeend,
        !           462:           Track_relocs<size, big_endian>* relocs,
        !           463:           Offsets_to_cie* cies);
        !           464:
        !           465:   // Template version of write function.
        !           466:   template<int size, bool big_endian>
        !           467:   void
        !           468:   do_sized_write(unsigned char* oview);
        !           469:
        !           470:   // The exception frame header, if any.
        !           471:   Eh_frame_hdr* eh_frame_hdr_;
        !           472:   // A mapping from all unique CIEs to their offset in the output
        !           473:   // file.
        !           474:   Cie_offsets cie_offsets_;
        !           475:   // A mapping from unmergeable CIEs to their offset in the output
        !           476:   // file.
        !           477:   Unmergeable_cie_offsets unmergeable_cie_offsets_;
        !           478:   // A mapping from input sections to the output section.
        !           479:   Merge_map merge_map_;
        !           480:   // Whether we have created the mappings to the output section.
        !           481:   bool mappings_are_done_;
        !           482:   // The final data size.  This is only set if mappings_are_done_ is
        !           483:   // true.
        !           484:   section_size_type final_data_size_;
        !           485: };
        !           486:
        !           487: } // End namespace gold.
        !           488:
        !           489: #endif // !defined(GOLD_EHFRAME_H)

CVSweb <webmaster@jp.NetBSD.org>