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