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