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 friend bool operator<(const Cie&, const Cie&); 326 friend bool operator==(const Cie&, const Cie&); 327 328 private: 329 // The class is not assignable. 330 Cie& operator=(const Cie&); 331 332 // The object in which this CIE was first seen. This will be NULL 333 // for a linker generated CIE. 334 Relobj* object_; 335 // Input section index for this CIE. This will be 0 for a linker 336 // generated CIE. 337 unsigned int shndx_; 338 // Offset within the input section for this CIE. This will be 0 for 339 // a linker generated CIE. 340 section_offset_type input_offset_; 341 // The encoding of the FDE. This is a DW_EH_PE code. 342 unsigned char fde_encoding_; 343 // The name of the personality routine. This will be the name of a 344 // global symbol, or will be the empty string. 345 std::string personality_name_; 346 // List of FDEs. 347 std::vector<Fde*> fdes_; 348 // CIE data. 349 std::string contents_; 350 }; 351 352 extern bool operator<(const Cie&, const Cie&); 353 extern bool operator==(const Cie&, const Cie&); 354 355 // This class manages .eh_frame sections. It discards duplicate 356 // exception information. 357 358 class Eh_frame : public Output_section_data 359 { 360 public: 361 enum Eh_frame_section_disposition 362 { 363 EH_EMPTY_SECTION, 364 EH_UNRECOGNIZED_SECTION, 365 EH_OPTIMIZABLE_SECTION, 366 EH_END_MARKER_SECTION 367 }; 368 369 Eh_frame(); 370 371 // Record the associated Eh_frame_hdr, if any. 372 void 373 set_eh_frame_hdr(Eh_frame_hdr* hdr) 374 { this->eh_frame_hdr_ = hdr; } 375 376 // Add the input section SHNDX in OBJECT. SYMBOLS is the contents 377 // of the symbol table section (size SYMBOLS_SIZE), SYMBOL_NAMES is 378 // the symbol names section (size SYMBOL_NAMES_SIZE). RELOC_SHNDX 379 // is the relocation section if any (0 for none, -1U for multiple). 380 // RELOC_TYPE is the type of the relocation section if any. This 381 // returns whether the section was incorporated into the .eh_frame 382 // data. 383 template<int size, bool big_endian> 384 Eh_frame_section_disposition 385 add_ehframe_input_section(Sized_relobj_file<size, big_endian>* object, 386 const unsigned char* symbols, 387 section_size_type symbols_size, 388 const unsigned char* symbol_names, 389 section_size_type symbol_names_size, 390 unsigned int shndx, unsigned int reloc_shndx, 391 unsigned int reloc_type); 392 393 // Add a CIE and an FDE for a PLT section, to permit unwinding 394 // through a PLT. The FDE data should start with 8 bytes of zero, 395 // which will be replaced by a 4 byte PC relative reference to the 396 // address of PLT and a 4 byte size of PLT. 397 void 398 add_ehframe_for_plt(Output_data* plt, const unsigned char* cie_data, 399 size_t cie_length, const unsigned char* fde_data, 400 size_t fde_length); 401 402 // Return the number of FDEs. 403 unsigned int 404 fde_count() const; 405 406 protected: 407 // Set the final data size. 408 void 409 set_final_data_size(); 410 411 // Return the output address for an input address. 412 bool 413 do_output_offset(const Relobj*, unsigned int shndx, 414 section_offset_type offset, 415 section_offset_type* poutput) const; 416 417 // Return whether this is the merge section for an input section. 418 bool 419 do_is_merge_section_for(const Relobj*, unsigned int shndx) const; 420 421 // Write the data to the file. 422 void 423 do_write(Output_file*); 424 425 // Write to a map file. 426 void 427 do_print_to_mapfile(Mapfile* mapfile) const 428 { mapfile->print_output_data(this, _("** eh_frame")); } 429 430 private: 431 // The comparison routine for the CIE map. 432 struct Cie_less 433 { 434 bool 435 operator()(const Cie* cie1, const Cie* cie2) const 436 { return *cie1 < *cie2; } 437 }; 438 439 // A set of unique CIEs. 440 typedef std::set<Cie*, Cie_less> Cie_offsets; 441 442 // A list of unmergeable CIEs. 443 typedef std::vector<Cie*> Unmergeable_cie_offsets; 444 445 // A mapping from offsets to CIEs. This is used while reading an 446 // input section. 447 typedef std::map<uint64_t, Cie*> Offsets_to_cie; 448 449 // A list of CIEs, and a bool indicating whether the CIE is 450 // mergeable. 451 typedef std::vector<std::pair<Cie*, bool> > New_cies; 452 453 // Skip an LEB128. 454 static bool 455 skip_leb128(const unsigned char**, const unsigned char*); 456 457 // The implementation of add_ehframe_input_section. 458 template<int size, bool big_endian> 459 bool 460 do_add_ehframe_input_section(Sized_relobj_file<size, big_endian>* object, 461 const unsigned char* symbols, 462 section_size_type symbols_size, 463 const unsigned char* symbol_names, 464 section_size_type symbol_names_size, 465 unsigned int shndx, 466 unsigned int reloc_shndx, 467 unsigned int reloc_type, 468 const unsigned char* pcontents, 469 section_size_type contents_len, 470 New_cies*); 471 472 // Read a CIE. 473 template<int size, bool big_endian> 474 bool 475 read_cie(Sized_relobj_file<size, big_endian>* object, 476 unsigned int shndx, 477 const unsigned char* symbols, 478 section_size_type symbols_size, 479 const unsigned char* symbol_names, 480 section_size_type symbol_names_size, 481 const unsigned char* pcontents, 482 const unsigned char* pcie, 483 const unsigned char* pcieend, 484 Track_relocs<size, big_endian>* relocs, 485 Offsets_to_cie* cies, 486 New_cies* new_cies); 487 488 // Read an FDE. 489 template<int size, bool big_endian> 490 bool 491 read_fde(Sized_relobj_file<size, big_endian>* object, 492 unsigned int shndx, 493 const unsigned char* symbols, 494 section_size_type symbols_size, 495 const unsigned char* pcontents, 496 unsigned int offset, 497 const unsigned char* pfde, 498 const unsigned char* pfdeend, 499 Track_relocs<size, big_endian>* relocs, 500 Offsets_to_cie* cies); 501 502 // Template version of write function. 503 template<int size, bool big_endian> 504 void 505 do_sized_write(unsigned char* oview); 506 507 // The exception frame header, if any. 508 Eh_frame_hdr* eh_frame_hdr_; 509 // A mapping from all unique CIEs to their offset in the output 510 // file. 511 Cie_offsets cie_offsets_; 512 // A mapping from unmergeable CIEs to their offset in the output 513 // file. 514 Unmergeable_cie_offsets unmergeable_cie_offsets_; 515 // A mapping from input sections to the output section. 516 Merge_map merge_map_; 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