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