1 // elfcpp_file.h -- file access for elfcpp -*- C++ -*- 2 3 // Copyright 2006, 2007, Free Software Foundation, Inc. 4 // Written by Ian Lance Taylor <iant@google.com>. 5 6 // This file is part of elfcpp. 7 8 // This program is free software; you can redistribute it and/or 9 // modify it under the terms of the GNU Library General Public License 10 // as published by the Free Software Foundation; either version 2, or 11 // (at your option) any later version. 12 13 // In addition to the permissions in the GNU Library General Public 14 // License, the Free Software Foundation gives you unlimited 15 // permission to link the compiled version of this file into 16 // combinations with other programs, and to distribute those 17 // combinations without any restriction coming from the use of this 18 // file. (The Library Public License restrictions do apply in other 19 // respects; for example, they cover modification of the file, and 20 /// distribution when not linked into a combined executable.) 21 22 // This program is distributed in the hope that it will be useful, but 23 // WITHOUT ANY WARRANTY; without even the implied warranty of 24 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 25 // Library General Public License for more details. 26 27 // You should have received a copy of the GNU Library General Public 28 // License along with this program; if not, write to the Free Software 29 // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 30 // 02110-1301, USA. 31 32 // This header file defines the class Elf_file which can be used to 33 // read useful data from an ELF file. The functions here are all 34 // templates which take a file interface object as a parameter. This 35 // type must have a subtype View. This type must support two methods: 36 // View view(off_t file_offset, off_t data_size) 37 // returns a View for the specified part of the file. 38 // void error(const char* printf_format, ...) 39 // prints an error message and does not return. The subtype View must 40 // support a method 41 // const unsigned char* data() 42 // which returns a pointer to a buffer containing the requested data. 43 // This general interface is used to read data from the file. Objects 44 // of type View will never survive longer than the elfcpp function. 45 46 // Some of these functions must return a reference to part of the 47 // file. To use these, the file interface must support a subtype 48 // Location: 49 // Location(off_t file_offset, off_t data_size) 50 // To use this in conjunction with the accessors types Shdr, etc., the 51 // file interface should support an overload of view: 52 // View view(Location) 53 // This permits writing 54 // elfcpp::Shdr shdr(file, ef.section_header(n)); 55 56 #ifndef ELFPCP_FILE_H 57 #define ELFCPP_FILE_H 58 59 #include <string> 60 #include <cstring> 61 62 namespace elfcpp 63 { 64 65 // This object is used to read an ELF file. 66 // SIZE: The size of file, 32 or 64. 67 // BIG_ENDIAN: Whether the file is in big-endian format. 68 // FILE: A file reading type as described above. 69 70 template<int size, bool big_endian, typename File> 71 class Elf_file 72 { 73 private: 74 typedef Elf_file<size, big_endian, File> This; 75 76 public: 77 static const int ehdr_size = Elf_sizes<size>::ehdr_size; 78 static const int phdr_size = Elf_sizes<size>::phdr_size; 79 static const int shdr_size = Elf_sizes<size>::shdr_size; 80 static const int sym_size = Elf_sizes<size>::sym_size; 81 static const int rel_size = Elf_sizes<size>::rel_size; 82 static const int rela_size = Elf_sizes<size>::rela_size; 83 84 typedef Ehdr<size, big_endian> Ef_ehdr; 85 typedef Phdr<size, big_endian> Ef_phdr; 86 typedef Shdr<size, big_endian> Ef_shdr; 87 typedef Sym<size, big_endian> Ef_sym; 88 89 // Construct an Elf_file given an ELF file header. 90 Elf_file(File* file, const Ef_ehdr& ehdr) 91 { this->construct(file, ehdr); } 92 93 // Construct an ELF file. 94 inline 95 Elf_file(File* file); 96 97 // Return the file offset to the section headers. 98 off_t 99 shoff() const 100 { return this->shoff_; } 101 102 // Return the number of sections. 103 unsigned int 104 shnum() 105 { 106 this->initialize_shnum(); 107 return this->shnum_; 108 } 109 110 // Return the section index of the section name string table. 111 unsigned int 112 shstrndx() 113 { 114 this->initialize_shnum(); 115 return this->shstrndx_; 116 } 117 118 // Return the value to subtract from section indexes >= 119 // SHN_LORESERVE. See the comment in initialize_shnum. 120 int 121 large_shndx_offset() 122 { 123 this->initialize_shnum(); 124 return this->large_shndx_offset_; 125 } 126 127 // Return the location of the header of section SHNDX. 128 typename File::Location 129 section_header(unsigned int shndx) 130 { 131 return typename File::Location(this->section_header_offset(shndx), 132 shdr_size); 133 } 134 135 // Return the name of section SHNDX. 136 std::string 137 section_name(unsigned int shndx); 138 139 // Return the location of the contents of section SHNDX. 140 typename File::Location 141 section_contents(unsigned int shndx); 142 143 // Return the size of section SHNDX. 144 typename Elf_types<size>::Elf_WXword 145 section_size(unsigned int shndx); 146 147 // Return the flags of section SHNDX. 148 typename Elf_types<size>::Elf_WXword 149 section_flags(unsigned int shndx); 150 151 // Return the address of section SHNDX. 152 typename Elf_types<size>::Elf_Addr 153 section_addr(unsigned int shndx); 154 155 // Return the type of section SHNDX. 156 Elf_Word 157 section_type(unsigned int shndx); 158 159 // Return the link field of section SHNDX. 160 Elf_Word 161 section_link(unsigned int shndx); 162 163 // Return the info field of section SHNDX. 164 Elf_Word 165 section_info(unsigned int shndx); 166 167 // Return the addralign field of section SHNDX. 168 typename Elf_types<size>::Elf_WXword 169 section_addralign(unsigned int shndx); 170 171 private: 172 // Shared constructor code. 173 void 174 construct(File* file, const Ef_ehdr& ehdr); 175 176 // Initialize shnum_ and shstrndx_. 177 void 178 initialize_shnum(); 179 180 // Return the file offset of the header of section SHNDX. 181 off_t 182 section_header_offset(unsigned int shndx); 183 184 // The file we are reading. 185 File* file_; 186 // The file offset to the section headers. 187 off_t shoff_; 188 // The number of sections. 189 unsigned int shnum_; 190 // The section index of the section name string table. 191 unsigned int shstrndx_; 192 // Offset to add to sections larger than SHN_LORESERVE. 193 int large_shndx_offset_; 194 }; 195 196 // Template function definitions. 197 198 // Construct an Elf_file given an ELF file header. 199 200 template<int size, bool big_endian, typename File> 201 void 202 Elf_file<size, big_endian, File>::construct(File* file, const Ef_ehdr& ehdr) 203 { 204 this->file_ = file; 205 this->shoff_ = ehdr.get_e_shoff(); 206 this->shnum_ = ehdr.get_e_shnum(); 207 this->shstrndx_ = ehdr.get_e_shstrndx(); 208 this->large_shndx_offset_ = 0; 209 if (ehdr.get_e_ehsize() != This::ehdr_size) 210 file->error(_("bad e_ehsize (%d != %d)"), 211 ehdr.get_e_ehsize(), This::ehdr_size); 212 if (ehdr.get_e_shentsize() != This::shdr_size) 213 file->error(_("bad e_shentsize (%d != %d)"), 214 ehdr.get_e_shentsize(), This::shdr_size); 215 } 216 217 // Construct an ELF file. 218 219 template<int size, bool big_endian, typename File> 220 inline 221 Elf_file<size, big_endian, File>::Elf_file(File* file) 222 { 223 typename File::View v(file->view(file_header_offset, This::ehdr_size)); 224 this->construct(file, Ef_ehdr(v.data())); 225 } 226 227 // Initialize the shnum_ and shstrndx_ fields, handling overflow. 228 229 template<int size, bool big_endian, typename File> 230 void 231 Elf_file<size, big_endian, File>::initialize_shnum() 232 { 233 if ((this->shnum_ == 0 || this->shstrndx_ == SHN_XINDEX) 234 && this->shoff_ != 0) 235 { 236 typename File::View v(this->file_->view(this->shoff_, This::shdr_size)); 237 Ef_shdr shdr(v.data()); 238 239 if (this->shnum_ == 0) 240 this->shnum_ = shdr.get_sh_size(); 241 242 if (this->shstrndx_ == SHN_XINDEX) 243 { 244 this->shstrndx_ = shdr.get_sh_link(); 245 246 // Versions of the GNU binutils between 2.12 and 2.18 did 247 // not handle objects with more than SHN_LORESERVE sections 248 // correctly. All large section indexes were offset by 249 // 0x100. Some information can be found here: 250 // http://sourceware.org/bugzilla/show_bug.cgi?id=5900 . 251 // Fortunately these object files are easy to detect, as the 252 // GNU binutils always put the section header string table 253 // near the end of the list of sections. Thus if the 254 // section header string table index is larger than the 255 // number of sections, then we know we have to subtract 256 // 0x100 to get the real section index. 257 if (this->shstrndx_ >= this->shnum_) 258 { 259 if (this->shstrndx_ >= elfcpp::SHN_LORESERVE + 0x100) 260 { 261 this->large_shndx_offset_ = - 0x100; 262 this->shstrndx_ -= 0x100; 263 } 264 if (this->shstrndx_ >= this->shnum_) 265 this->file_->error(_("bad shstrndx: %u >= %u"), 266 this->shstrndx_, this->shnum_); 267 } 268 } 269 } 270 } 271 272 // Return the file offset of the section header of section SHNDX. 273 274 template<int size, bool big_endian, typename File> 275 off_t 276 Elf_file<size, big_endian, File>::section_header_offset(unsigned int shndx) 277 { 278 if (shndx >= this->shnum()) 279 this->file_->error(_("section_header_offset: bad shndx %u >= %u"), 280 shndx, this->shnum()); 281 return this->shoff_ + This::shdr_size * shndx; 282 } 283 284 // Return the name of section SHNDX. 285 286 template<int size, bool big_endian, typename File> 287 std::string 288 Elf_file<size, big_endian, File>::section_name(unsigned int shndx) 289 { 290 File* const file = this->file_; 291 292 // Get the section name offset. 293 unsigned int sh_name; 294 { 295 typename File::View v(file->view(this->section_header_offset(shndx), 296 This::shdr_size)); 297 Ef_shdr shdr(v.data()); 298 sh_name = shdr.get_sh_name(); 299 } 300 301 // Get the file offset for the section name string table data. 302 off_t shstr_off; 303 off_t shstr_size; 304 { 305 const unsigned int shstrndx = this->shstrndx_; 306 typename File::View v(file->view(this->section_header_offset(shstrndx), 307 This::shdr_size)); 308 Ef_shdr shstr_shdr(v.data()); 309 shstr_off = shstr_shdr.get_sh_offset(); 310 shstr_size = shstr_shdr.get_sh_size(); 311 } 312 313 if (sh_name >= shstr_size) 314 file->error(_("bad section name offset for section %u: %u"), 315 shndx, sh_name); 316 317 typename File::View v(file->view(shstr_off, shstr_size)); 318 319 const unsigned char* datau = v.data(); 320 const char* data = reinterpret_cast<const char*>(datau); 321 const void* p = ::memchr(data + sh_name, '\0', shstr_size - sh_name); 322 if (p == NULL) 323 file->error(_("missing null terminator for name of section %u"), 324 shndx); 325 326 size_t len = static_cast<const char*>(p) - (data + sh_name); 327 328 return std::string(data + sh_name, len); 329 } 330 331 // Return the contents of section SHNDX. 332 333 template<int size, bool big_endian, typename File> 334 typename File::Location 335 Elf_file<size, big_endian, File>::section_contents(unsigned int shndx) 336 { 337 File* const file = this->file_; 338 339 if (shndx >= this->shnum()) 340 file->error(_("section_contents: bad shndx %u >= %u"), 341 shndx, this->shnum()); 342 343 typename File::View v(file->view(this->section_header_offset(shndx), 344 This::shdr_size)); 345 Ef_shdr shdr(v.data()); 346 return typename File::Location(shdr.get_sh_offset(), shdr.get_sh_size()); 347 } 348 349 // Get the size of section SHNDX. 350 351 template<int size, bool big_endian, typename File> 352 typename Elf_types<size>::Elf_WXword 353 Elf_file<size, big_endian, File>::section_size(unsigned int shndx) 354 { 355 File* const file = this->file_; 356 357 if (shndx >= this->shnum()) 358 file->error(_("section_size: bad shndx %u >= %u"), 359 shndx, this->shnum()); 360 361 typename File::View v(file->view(this->section_header_offset(shndx), 362 This::shdr_size)); 363 364 Ef_shdr shdr(v.data()); 365 return shdr.get_sh_size(); 366 } 367 368 // Return the section flags of section SHNDX. 369 370 template<int size, bool big_endian, typename File> 371 typename Elf_types<size>::Elf_WXword 372 Elf_file<size, big_endian, File>::section_flags(unsigned int shndx) 373 { 374 File* const file = this->file_; 375 376 if (shndx >= this->shnum()) 377 file->error(_("section_flags: bad shndx %u >= %u"), 378 shndx, this->shnum()); 379 380 typename File::View v(file->view(this->section_header_offset(shndx), 381 This::shdr_size)); 382 383 Ef_shdr shdr(v.data()); 384 return shdr.get_sh_flags(); 385 } 386 387 // Return the address of section SHNDX. 388 389 template<int size, bool big_endian, typename File> 390 typename Elf_types<size>::Elf_Addr 391 Elf_file<size, big_endian, File>::section_addr(unsigned int shndx) 392 { 393 File* const file = this->file_; 394 395 if (shndx >= this->shnum()) 396 file->error(_("section_flags: bad shndx %u >= %u"), 397 shndx, this->shnum()); 398 399 typename File::View v(file->view(this->section_header_offset(shndx), 400 This::shdr_size)); 401 402 Ef_shdr shdr(v.data()); 403 return shdr.get_sh_addr(); 404 } 405 406 // Return the type of section SHNDX. 407 408 template<int size, bool big_endian, typename File> 409 Elf_Word 410 Elf_file<size, big_endian, File>::section_type(unsigned int shndx) 411 { 412 File* const file = this->file_; 413 414 if (shndx >= this->shnum()) 415 file->error(_("section_type: bad shndx %u >= %u"), 416 shndx, this->shnum()); 417 418 typename File::View v(file->view(this->section_header_offset(shndx), 419 This::shdr_size)); 420 421 Ef_shdr shdr(v.data()); 422 return shdr.get_sh_type(); 423 } 424 425 // Return the sh_link field of section SHNDX. 426 427 template<int size, bool big_endian, typename File> 428 Elf_Word 429 Elf_file<size, big_endian, File>::section_link(unsigned int shndx) 430 { 431 File* const file = this->file_; 432 433 if (shndx >= this->shnum()) 434 file->error(_("section_link: bad shndx %u >= %u"), 435 shndx, this->shnum()); 436 437 typename File::View v(file->view(this->section_header_offset(shndx), 438 This::shdr_size)); 439 440 Ef_shdr shdr(v.data()); 441 return shdr.get_sh_link(); 442 } 443 444 // Return the sh_info field of section SHNDX. 445 446 template<int size, bool big_endian, typename File> 447 Elf_Word 448 Elf_file<size, big_endian, File>::section_info(unsigned int shndx) 449 { 450 File* const file = this->file_; 451 452 if (shndx >= this->shnum()) 453 file->error(_("section_info: bad shndx %u >= %u"), 454 shndx, this->shnum()); 455 456 typename File::View v(file->view(this->section_header_offset(shndx), 457 This::shdr_size)); 458 459 Ef_shdr shdr(v.data()); 460 return shdr.get_sh_info(); 461 } 462 463 // Return the sh_addralign field of section SHNDX. 464 465 template<int size, bool big_endian, typename File> 466 typename Elf_types<size>::Elf_WXword 467 Elf_file<size, big_endian, File>::section_addralign(unsigned int shndx) 468 { 469 File* const file = this->file_; 470 471 if (shndx >= this->shnum()) 472 file->error(_("section_addralign: bad shndx %u >= %u"), 473 shndx, this->shnum()); 474 475 typename File::View v(file->view(this->section_header_offset(shndx), 476 This::shdr_size)); 477 478 Ef_shdr shdr(v.data()); 479 return shdr.get_sh_addralign(); 480 } 481 482 } // End namespace elfcpp. 483 484 #endif // !defined(ELFCPP_FILE_H) 485