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