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