Stephen Wilson | ddd2962 | 2010-07-13 23:07:23 +0000 | [diff] [blame] | 1 | //===-- ELFHeader.h ------------------------------------------- -*- C++ -*-===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | /// @file |
| 11 | /// @brief Generic structures and typedefs for ELF files. |
| 12 | /// |
| 13 | /// This file provides definitions for the various entities comprising an ELF |
| 14 | /// file. The structures are generic in the sense that they do not correspond |
| 15 | /// to the exact binary layout of an ELF, but can be used to hold the |
| 16 | /// information present in both 32 and 64 bit variants of the format. Each |
| 17 | /// entity provides a \c Parse method which is capable of transparently reading |
| 18 | /// both 32 and 64 bit instances of the object. |
| 19 | //===----------------------------------------------------------------------===// |
| 20 | |
| 21 | #ifndef liblldb_ELFHeader_h_ |
| 22 | #define liblldb_ELFHeader_h_ |
| 23 | |
| 24 | #include "llvm/Support/ELF.h" |
| 25 | |
| 26 | #include "lldb/lldb-enumerations.h" |
| 27 | |
| 28 | namespace lldb_private |
| 29 | { |
| 30 | class DataExtractor; |
| 31 | } // End namespace lldb_private. |
| 32 | |
| 33 | namespace elf |
| 34 | { |
| 35 | |
| 36 | //------------------------------------------------------------------------------ |
| 37 | /// @name ELF type definitions. |
| 38 | /// |
| 39 | /// Types used to represent the various components of ELF structures. All types |
| 40 | /// are signed or unsigned integral types wide enough to hold values from both |
| 41 | /// 32 and 64 bit ELF variants. |
| 42 | //@{ |
| 43 | typedef uint64_t elf_addr; |
| 44 | typedef uint64_t elf_off; |
| 45 | typedef uint16_t elf_half; |
| 46 | typedef uint32_t elf_word; |
| 47 | typedef int32_t elf_sword; |
| 48 | typedef uint64_t elf_size; |
| 49 | typedef uint64_t elf_xword; |
| 50 | typedef int64_t elf_sxword; |
| 51 | //@} |
| 52 | |
| 53 | //------------------------------------------------------------------------------ |
| 54 | /// @class ELFHeader |
| 55 | /// @brief Generic representation of an ELF file header. |
| 56 | /// |
| 57 | /// This object is used to identify the general attributes on an ELF file and to |
| 58 | /// locate additional sections within the file. |
| 59 | struct ELFHeader |
| 60 | { |
| 61 | unsigned char e_ident[llvm::ELF::EI_NIDENT]; ///< ELF file identification. |
| 62 | elf_addr e_entry; ///< Virtual address program entry point. |
| 63 | elf_off e_phoff; ///< File offset of program header table. |
| 64 | elf_off e_shoff; ///< File offset of section header table. |
| 65 | elf_word e_flags; ///< Processor specific flags. |
| 66 | elf_word e_version; ///< Version of object file (always 1). |
| 67 | elf_half e_type; ///< Object file type. |
| 68 | elf_half e_machine; ///< Target architecture. |
| 69 | elf_half e_ehsize; ///< Byte size of the ELF header. |
| 70 | elf_half e_phentsize; ///< Size of a program header table entry. |
Greg Clayton | 5d187e5 | 2011-01-08 20:28:42 +0000 | [diff] [blame] | 71 | elf_half e_phnum; ///< Number of program header entries. |
Stephen Wilson | ddd2962 | 2010-07-13 23:07:23 +0000 | [diff] [blame] | 72 | elf_half e_shentsize; ///< Size of a section header table entry. |
Greg Clayton | 5d187e5 | 2011-01-08 20:28:42 +0000 | [diff] [blame] | 73 | elf_half e_shnum; ///< Number of section header entries. |
Stephen Wilson | ddd2962 | 2010-07-13 23:07:23 +0000 | [diff] [blame] | 74 | elf_half e_shstrndx; ///< String table section index. |
| 75 | |
| 76 | ELFHeader(); |
| 77 | |
| 78 | //-------------------------------------------------------------------------- |
| 79 | /// Returns true if this is a 32 bit ELF file header. |
| 80 | /// |
| 81 | /// @return |
| 82 | /// True if this is a 32 bit ELF file header. |
| 83 | bool Is32Bit() const { |
| 84 | return e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS32; |
| 85 | } |
| 86 | |
| 87 | //-------------------------------------------------------------------------- |
| 88 | /// Returns true if this is a 64 bit ELF file header. |
| 89 | /// |
| 90 | /// @return |
| 91 | /// True if this is a 64 bit ELF file header. |
| 92 | bool Is64Bit() const { |
| 93 | return e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS64; |
| 94 | } |
| 95 | |
| 96 | //-------------------------------------------------------------------------- |
| 97 | /// The byte order of this ELF file header. |
| 98 | /// |
| 99 | /// @return |
| 100 | /// The byte order of this ELF file as described by the header. |
| 101 | lldb::ByteOrder |
| 102 | GetByteOrder() const; |
| 103 | |
| 104 | //-------------------------------------------------------------------------- |
Stephen Wilson | 9b01e48 | 2011-03-30 15:59:12 +0000 | [diff] [blame] | 105 | /// The jump slot relocation type of this ELF. |
| 106 | unsigned |
| 107 | GetRelocationJumpSlotType() const; |
| 108 | |
| 109 | //-------------------------------------------------------------------------- |
Stephen Wilson | ddd2962 | 2010-07-13 23:07:23 +0000 | [diff] [blame] | 110 | /// Parse an ELFSectionHeader entry starting at position \p offset and |
| 111 | /// update the data extractor with the address size and byte order |
| 112 | /// attributes as defined by the header. |
| 113 | /// |
| 114 | /// @param[in,out] data |
| 115 | /// The DataExtractor to read from. Updated with the address size and |
| 116 | /// byte order attributes appropriate to this header. |
| 117 | /// |
| 118 | /// @param[in,out] offset |
| 119 | /// Pointer to an offset in the data. On return the offset will be |
| 120 | /// advanced by the number of bytes read. |
| 121 | /// |
| 122 | /// @return |
| 123 | /// True if the ELFSectionHeader was successfully read and false |
| 124 | /// otherwise. |
| 125 | bool |
| 126 | Parse(lldb_private::DataExtractor &data, uint32_t *offset); |
| 127 | |
| 128 | //-------------------------------------------------------------------------- |
| 129 | /// Examines at most EI_NIDENT bytes starting from the given pointer and |
| 130 | /// determines if the magic ELF identification exists. |
| 131 | /// |
| 132 | /// @return |
| 133 | /// True if the given sequence of bytes identifies an ELF file. |
| 134 | static bool |
| 135 | MagicBytesMatch(const uint8_t *magic); |
| 136 | |
| 137 | //-------------------------------------------------------------------------- |
| 138 | /// Examines at most EI_NIDENT bytes starting from the given address and |
| 139 | /// determines the address size of the underlying ELF file. This function |
| 140 | /// should only be called on an pointer for which MagicBytesMatch returns |
| 141 | /// true. |
| 142 | /// |
| 143 | /// @return |
| 144 | /// The number of bytes forming an address in the ELF file (either 4 or |
| 145 | /// 8), else zero if the address size could not be determined. |
| 146 | static unsigned |
| 147 | AddressSizeInBytes(const uint8_t *magic); |
| 148 | }; |
| 149 | |
| 150 | //------------------------------------------------------------------------------ |
| 151 | /// @class ELFSectionHeader |
| 152 | /// @brief Generic representation of an ELF section header. |
| 153 | struct ELFSectionHeader |
| 154 | { |
| 155 | elf_word sh_name; ///< Section name string index. |
| 156 | elf_word sh_type; ///< Section type. |
| 157 | elf_xword sh_flags; ///< Section attributes. |
| 158 | elf_addr sh_addr; ///< Virtual address of the section in memory. |
| 159 | elf_off sh_offset; ///< Start of section from beginning of file. |
| 160 | elf_xword sh_size; ///< Number of bytes occupied in the file. |
| 161 | elf_word sh_link; ///< Index of associated section. |
| 162 | elf_word sh_info; ///< Extra section info (overloaded). |
| 163 | elf_xword sh_addralign; ///< Power of two alignment constraint. |
| 164 | elf_xword sh_entsize; ///< Byte size of each section entry. |
| 165 | |
| 166 | ELFSectionHeader(); |
| 167 | |
| 168 | //-------------------------------------------------------------------------- |
| 169 | /// Parse an ELFSectionHeader entry from the given DataExtracter starting at |
| 170 | /// position \p offset. |
| 171 | /// |
| 172 | /// @param[in] data |
| 173 | /// The DataExtractor to read from. The address size of the extractor |
| 174 | /// determines if a 32 or 64 bit object should be read. |
| 175 | /// |
| 176 | /// @param[in,out] offset |
| 177 | /// Pointer to an offset in the data. On return the offset will be |
| 178 | /// advanced by the number of bytes read. |
| 179 | /// |
| 180 | /// @return |
| 181 | /// True if the ELFSectionHeader was successfully read and false |
| 182 | /// otherwise. |
| 183 | bool |
| 184 | Parse(const lldb_private::DataExtractor &data, uint32_t *offset); |
| 185 | }; |
| 186 | |
| 187 | //------------------------------------------------------------------------------ |
| 188 | /// @class ELFProgramHeader |
| 189 | /// @brief Generic representation of an ELF program header. |
| 190 | struct ELFProgramHeader |
| 191 | { |
Greg Clayton | 5d187e5 | 2011-01-08 20:28:42 +0000 | [diff] [blame] | 192 | elf_word p_type; ///< Type of program segment. |
| 193 | elf_word p_flags; ///< Segment attributes. |
| 194 | elf_off p_offset; ///< Start of segment from beginning of file. |
Stephen Wilson | ddd2962 | 2010-07-13 23:07:23 +0000 | [diff] [blame] | 195 | elf_addr p_vaddr; ///< Virtual address of segment in memory. |
| 196 | elf_addr p_paddr; ///< Physical address (for non-VM systems). |
| 197 | elf_xword p_filesz; ///< Byte size of the segment in file. |
| 198 | elf_xword p_memsz; ///< Byte size of the segment in memory. |
Greg Clayton | 5d187e5 | 2011-01-08 20:28:42 +0000 | [diff] [blame] | 199 | elf_xword p_align; ///< Segment alignment constraint. |
Stephen Wilson | ddd2962 | 2010-07-13 23:07:23 +0000 | [diff] [blame] | 200 | |
| 201 | ELFProgramHeader(); |
| 202 | |
Greg Clayton | 5d187e5 | 2011-01-08 20:28:42 +0000 | [diff] [blame] | 203 | /// Parse an ELFProgramHeader entry from the given DataExtractor starting at |
| 204 | /// position \p offset. The address size of the DataExtractor determines if |
Stephen Wilson | ddd2962 | 2010-07-13 23:07:23 +0000 | [diff] [blame] | 205 | /// a 32 or 64 bit object is to be parsed. |
| 206 | /// |
| 207 | /// @param[in] data |
| 208 | /// The DataExtractor to read from. The address size of the extractor |
| 209 | /// determines if a 32 or 64 bit object should be read. |
| 210 | /// |
| 211 | /// @param[in,out] offset |
| 212 | /// Pointer to an offset in the data. On return the offset will be |
| 213 | /// advanced by the number of bytes read. |
| 214 | /// |
| 215 | /// @return |
| 216 | /// True if the ELFProgramHeader was successfully read and false |
| 217 | /// otherwise. |
| 218 | bool |
| 219 | Parse(const lldb_private::DataExtractor &data, uint32_t *offset); |
| 220 | }; |
| 221 | |
| 222 | //------------------------------------------------------------------------------ |
| 223 | /// @class ELFSymbol |
| 224 | /// @brief Represents a symbol within an ELF symbol table. |
| 225 | struct ELFSymbol |
| 226 | { |
| 227 | elf_addr st_value; ///< Absolute or relocatable address. |
| 228 | elf_xword st_size; ///< Size of the symbol or zero. |
| 229 | elf_word st_name; ///< Symbol name string index. |
| 230 | unsigned char st_info; ///< Symbol type and binding attributes. |
| 231 | unsigned char st_other; ///< Reserved for future use. |
| 232 | elf_half st_shndx; ///< Section to which this symbol applies. |
| 233 | |
| 234 | ELFSymbol(); |
| 235 | |
| 236 | /// Returns the binding attribute of the st_info member. |
| 237 | unsigned char getBinding() const { return st_info >> 4; } |
| 238 | |
| 239 | /// Returns the type attribute of the st_info member. |
| 240 | unsigned char getType() const { return st_info & 0x0F; } |
| 241 | |
Greg Clayton | 5d187e5 | 2011-01-08 20:28:42 +0000 | [diff] [blame] | 242 | /// Sets the binding and type of the st_info member. |
Stephen Wilson | ddd2962 | 2010-07-13 23:07:23 +0000 | [diff] [blame] | 243 | void setBindingAndType(unsigned char binding, unsigned char type) { |
| 244 | st_info = (binding << 4) + (type & 0x0F); |
| 245 | } |
| 246 | |
Greg Clayton | 5d187e5 | 2011-01-08 20:28:42 +0000 | [diff] [blame] | 247 | /// Parse an ELFSymbol entry from the given DataExtractor starting at |
| 248 | /// position \p offset. The address size of the DataExtractor determines if |
Stephen Wilson | ddd2962 | 2010-07-13 23:07:23 +0000 | [diff] [blame] | 249 | /// a 32 or 64 bit object is to be parsed. |
| 250 | /// |
| 251 | /// @param[in] data |
| 252 | /// The DataExtractor to read from. The address size of the extractor |
| 253 | /// determines if a 32 or 64 bit object should be read. |
| 254 | /// |
| 255 | /// @param[in,out] offset |
| 256 | /// Pointer to an offset in the data. On return the offset will be |
| 257 | /// advanced by the number of bytes read. |
| 258 | /// |
| 259 | /// @return |
| 260 | /// True if the ELFSymbol was successfully read and false otherwise. |
| 261 | bool |
| 262 | Parse(const lldb_private::DataExtractor &data, uint32_t *offset); |
| 263 | }; |
| 264 | |
| 265 | //------------------------------------------------------------------------------ |
| 266 | /// @class ELFDynamic |
| 267 | /// @brief Represents an entry in an ELF dynamic table. |
| 268 | struct ELFDynamic |
| 269 | { |
| 270 | elf_sxword d_tag; ///< Type of dynamic table entry. |
| 271 | union |
| 272 | { |
| 273 | elf_xword d_val; ///< Integer value of the table entry. |
| 274 | elf_addr d_ptr; ///< Pointer value of the table entry. |
| 275 | }; |
| 276 | |
| 277 | ELFDynamic(); |
| 278 | |
Greg Clayton | 5d187e5 | 2011-01-08 20:28:42 +0000 | [diff] [blame] | 279 | /// Parse an ELFDynamic entry from the given DataExtractor starting at |
| 280 | /// position \p offset. The address size of the DataExtractor determines if |
Stephen Wilson | ddd2962 | 2010-07-13 23:07:23 +0000 | [diff] [blame] | 281 | /// a 32 or 64 bit object is to be parsed. |
| 282 | /// |
| 283 | /// @param[in] data |
| 284 | /// The DataExtractor to read from. The address size of the extractor |
| 285 | /// determines if a 32 or 64 bit object should be read. |
| 286 | /// |
| 287 | /// @param[in,out] offset |
| 288 | /// Pointer to an offset in the data. On return the offset will be |
| 289 | /// advanced by the number of bytes read. |
| 290 | /// |
| 291 | /// @return |
| 292 | /// True if the ELFDynamic entry was successfully read and false |
| 293 | /// otherwise. |
| 294 | bool |
| 295 | Parse(const lldb_private::DataExtractor &data, uint32_t *offset); |
| 296 | }; |
| 297 | |
Stephen Wilson | 9b01e48 | 2011-03-30 15:59:12 +0000 | [diff] [blame] | 298 | //------------------------------------------------------------------------------ |
| 299 | /// @class ELFRel |
| 300 | /// @brief Represents a relocation entry with an implicit addend. |
| 301 | struct ELFRel |
| 302 | { |
| 303 | elf_addr r_offset; ///< Address of reference. |
| 304 | elf_xword r_info; ///< symbol index and type of relocation. |
| 305 | |
| 306 | ELFRel(); |
| 307 | |
| 308 | /// Parse an ELFRel entry from the given DataExtractor starting at position |
| 309 | /// \p offset. The address size of the DataExtractor determines if a 32 or |
| 310 | /// 64 bit object is to be parsed. |
| 311 | /// |
| 312 | /// @param[in] data |
| 313 | /// The DataExtractor to read from. The address size of the extractor |
| 314 | /// determines if a 32 or 64 bit object should be read. |
| 315 | /// |
| 316 | /// @param[in,out] offset |
| 317 | /// Pointer to an offset in the data. On return the offset will be |
| 318 | /// advanced by the number of bytes read. |
| 319 | /// |
| 320 | /// @return |
| 321 | /// True if the ELFRel entry was successfully read and false otherwise. |
| 322 | bool |
| 323 | Parse(const lldb_private::DataExtractor &data, uint32_t *offset); |
| 324 | |
| 325 | /// Returns the type when the given entry represents a 32-bit relocation. |
| 326 | static unsigned |
| 327 | RelocType32(const ELFRel &rel) |
| 328 | { |
| 329 | return rel.r_info & 0x0ff; |
| 330 | } |
| 331 | |
| 332 | /// Returns the type when the given entry represents a 64-bit relocation. |
| 333 | static unsigned |
| 334 | RelocType64(const ELFRel &rel) |
| 335 | { |
| 336 | return rel.r_info & 0xffffffff; |
| 337 | } |
| 338 | |
| 339 | /// Returns the symbol index when the given entry represents a 32-bit |
| 340 | /// reloction. |
| 341 | static unsigned |
| 342 | RelocSymbol32(const ELFRel &rel) |
| 343 | { |
| 344 | return rel.r_info >> 8; |
| 345 | } |
| 346 | |
| 347 | /// Returns the symbol index when the given entry represents a 64-bit |
| 348 | /// reloction. |
| 349 | static unsigned |
| 350 | RelocSymbol64(const ELFRel &rel) |
| 351 | { |
| 352 | return rel.r_info >> 32; |
| 353 | } |
| 354 | }; |
| 355 | |
| 356 | //------------------------------------------------------------------------------ |
| 357 | /// @class ELFRela |
| 358 | /// @brief Represents a relocation entry with an explicit addend. |
| 359 | struct ELFRela |
| 360 | { |
| 361 | elf_addr r_offset; ///< Address of reference. |
| 362 | elf_xword r_info; ///< Symbol index and type of relocation. |
| 363 | elf_sxword r_addend; ///< Constant part of expression. |
| 364 | |
| 365 | ELFRela(); |
| 366 | |
| 367 | /// Parse an ELFRela entry from the given DataExtractor starting at position |
| 368 | /// \p offset. The address size of the DataExtractor determines if a 32 or |
| 369 | /// 64 bit object is to be parsed. |
| 370 | /// |
| 371 | /// @param[in] data |
| 372 | /// The DataExtractor to read from. The address size of the extractor |
| 373 | /// determines if a 32 or 64 bit object should be read. |
| 374 | /// |
| 375 | /// @param[in,out] offset |
| 376 | /// Pointer to an offset in the data. On return the offset will be |
| 377 | /// advanced by the number of bytes read. |
| 378 | /// |
| 379 | /// @return |
| 380 | /// True if the ELFRela entry was successfully read and false otherwise. |
| 381 | bool |
| 382 | Parse(const lldb_private::DataExtractor &data, uint32_t *offset); |
| 383 | |
| 384 | /// Returns the type when the given entry represents a 32-bit relocation. |
| 385 | static unsigned |
| 386 | RelocType32(const ELFRela &rela) |
| 387 | { |
| 388 | return rela.r_info & 0x0ff; |
| 389 | } |
| 390 | |
| 391 | /// Returns the type when the given entry represents a 64-bit relocation. |
| 392 | static unsigned |
| 393 | RelocType64(const ELFRela &rela) |
| 394 | { |
| 395 | return rela.r_info & 0xffffffff; |
| 396 | } |
| 397 | |
| 398 | /// Returns the symbol index when the given entry represents a 32-bit |
| 399 | /// reloction. |
| 400 | static unsigned |
| 401 | RelocSymbol32(const ELFRela &rela) |
| 402 | { |
| 403 | return rela.r_info >> 8; |
| 404 | } |
| 405 | |
| 406 | /// Returns the symbol index when the given entry represents a 64-bit |
| 407 | /// reloction. |
| 408 | static unsigned |
| 409 | RelocSymbol64(const ELFRela &rela) |
| 410 | { |
| 411 | return rela.r_info >> 32; |
| 412 | } |
| 413 | }; |
| 414 | |
Stephen Wilson | ddd2962 | 2010-07-13 23:07:23 +0000 | [diff] [blame] | 415 | } // End namespace elf. |
| 416 | |
| 417 | #endif // #ifndef liblldb_ELFHeader_h_ |