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