395 lines · c
1//===-- ELFHeader.h ------------------------------------------- -*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9/// \file10/// Generic structures and typedefs for ELF files.11///12/// This file provides definitions for the various entities comprising an ELF13/// file. The structures are generic in the sense that they do not correspond14/// to the exact binary layout of an ELF, but can be used to hold the15/// information present in both 32 and 64 bit variants of the format. Each16/// entity provides a \c Parse method which is capable of transparently17/// reading both 32 and 64 bit instances of the object.18//===----------------------------------------------------------------------===//19 20#ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_ELFHEADER_H21#define LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_ELFHEADER_H22 23#include "llvm/BinaryFormat/ELF.h"24 25#include "lldb/lldb-enumerations.h"26#include "lldb/lldb-types.h"27 28namespace lldb_private {29class DataExtractor;30} // End namespace lldb_private.31 32namespace elf {33 34/// \name ELF type definitions.35///36/// Types used to represent the various components of ELF structures. All37/// types are signed or unsigned integral types wide enough to hold values38/// from both39/// 32 and 64 bit ELF variants.40//@{41typedef uint64_t elf_addr;42typedef uint64_t elf_off;43typedef uint16_t elf_half;44typedef uint32_t elf_word;45typedef int32_t elf_sword;46typedef uint64_t elf_size;47typedef uint64_t elf_xword;48typedef int64_t elf_sxword;49//@}50 51/// \class ELFHeader52/// Generic representation of an ELF file header.53///54/// This object is used to identify the general attributes on an ELF file and55/// to locate additional sections within the file.56struct ELFHeader {57 unsigned char e_ident[llvm::ELF::EI_NIDENT]; ///< ELF file identification.58 elf_addr e_entry; ///< Virtual address program entry point.59 elf_off e_phoff; ///< File offset of program header table.60 elf_off e_shoff; ///< File offset of section header table.61 elf_word e_flags; ///< Processor specific flags.62 elf_word e_version; ///< Version of object file (always 1).63 elf_half e_type; ///< Object file type.64 elf_half e_machine; ///< Target architecture.65 elf_half e_ehsize; ///< Byte size of the ELF header.66 elf_half e_phentsize; ///< Size of a program header table entry.67 elf_half e_phnum_hdr; ///< Number of program header entries.68 elf_half e_shentsize; ///< Size of a section header table entry.69 elf_half e_shnum_hdr; ///< Number of section header entries.70 elf_half e_shstrndx_hdr; ///< String table section index.71 72 // In some cases these numbers do not fit in 16 bits and they are73 // stored outside of the header in section #0. Here are the actual74 // values.75 elf_word e_phnum; ///< Number of program header entries.76 elf_word e_shnum; ///< Number of section header entries.77 elf_word e_shstrndx; ///< String table section index.78 79 ELFHeader();80 81 /// Returns true if this is a 32 bit ELF file header.82 ///83 /// \return84 /// True if this is a 32 bit ELF file header.85 bool Is32Bit() const {86 return e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS32;87 }88 89 /// Returns true if this is a 64 bit ELF file header.90 ///91 /// \return92 /// True if this is a 64 bit ELF file header.93 bool Is64Bit() const {94 return e_ident[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS64;95 }96 97 /// The byte order of this ELF file header.98 ///99 /// \return100 /// The byte order of this ELF file as described by the header.101 lldb::ByteOrder GetByteOrder() const;102 103 /// The jump slot relocation type of this ELF.104 unsigned GetRelocationJumpSlotType() const;105 106 /// Check if there should be header extension in section header #0107 ///108 /// \return109 /// True if parsing the ELFHeader requires reading header extension110 /// and false otherwise.111 bool HasHeaderExtension() const;112 113 /// Parse an ELFHeader entry starting at position \p offset and update the114 /// data extractor with the address size and byte order attributes as115 /// defined by the header.116 ///117 /// \param[in,out] data118 /// The DataExtractor to read from. Updated with the address size and119 /// byte order attributes appropriate to this header.120 ///121 /// \param[in,out] offset122 /// Pointer to an offset in the data. On return the offset will be123 /// advanced by the number of bytes read.124 ///125 /// \return126 /// True if the ELFHeader was successfully read and false127 /// otherwise.128 bool Parse(lldb_private::DataExtractor &data, lldb::offset_t *offset);129 130 /// Examines at most EI_NIDENT bytes starting from the given pointer and131 /// determines if the magic ELF identification exists.132 ///133 /// \return134 /// True if the given sequence of bytes identifies an ELF file.135 static bool MagicBytesMatch(const uint8_t *magic);136 137 /// Examines at most EI_NIDENT bytes starting from the given address and138 /// determines the address size of the underlying ELF file. This function139 /// should only be called on an pointer for which MagicBytesMatch returns140 /// true.141 ///142 /// \return143 /// The number of bytes forming an address in the ELF file (either 4 or144 /// 8), else zero if the address size could not be determined.145 static unsigned AddressSizeInBytes(const uint8_t *magic);146 147private:148 149 /// Parse an ELFHeader header extension entry. This method is called by150 /// Parse().151 ///152 /// \param[in] data153 /// The DataExtractor to read from.154 void ParseHeaderExtension(lldb_private::DataExtractor &data);155};156 157/// \class ELFSectionHeader158/// Generic representation of an ELF section header.159struct ELFSectionHeader {160 elf_word sh_name; ///< Section name string index.161 elf_word sh_type; ///< Section type.162 elf_xword sh_flags; ///< Section attributes.163 elf_addr sh_addr; ///< Virtual address of the section in memory.164 elf_off sh_offset; ///< Start of section from beginning of file.165 elf_xword sh_size; ///< Number of bytes occupied in the file.166 elf_word sh_link; ///< Index of associated section.167 elf_word sh_info; ///< Extra section info (overloaded).168 elf_xword sh_addralign; ///< Power of two alignment constraint.169 elf_xword sh_entsize; ///< Byte size of each section entry.170 171 ELFSectionHeader();172 173 /// Parse an ELFSectionHeader entry from the given DataExtracter starting at174 /// position \p offset.175 ///176 /// \param[in] data177 /// The DataExtractor to read from. The address size of the extractor178 /// determines if a 32 or 64 bit object should be read.179 ///180 /// \param[in,out] offset181 /// Pointer to an offset in the data. On return the offset will be182 /// advanced by the number of bytes read.183 ///184 /// \return185 /// True if the ELFSectionHeader was successfully read and false186 /// otherwise.187 bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);188};189 190/// \class ELFProgramHeader191/// Generic representation of an ELF program header.192struct ELFProgramHeader {193 elf_word p_type; ///< Type of program segment.194 elf_word p_flags; ///< Segment attributes.195 elf_off p_offset; ///< Start of segment from beginning of file.196 elf_addr p_vaddr; ///< Virtual address of segment in memory.197 elf_addr p_paddr; ///< Physical address (for non-VM systems).198 elf_xword p_filesz; ///< Byte size of the segment in file.199 elf_xword p_memsz; ///< Byte size of the segment in memory.200 elf_xword p_align; ///< Segment alignment constraint.201 202 ELFProgramHeader();203 204 /// Parse an ELFProgramHeader entry from the given DataExtractor starting at205 /// position \p offset. The address size of the DataExtractor determines if206 /// a 32 or 64 bit object is to be parsed.207 ///208 /// \param[in] data209 /// The DataExtractor to read from. The address size of the extractor210 /// determines if a 32 or 64 bit object should be read.211 ///212 /// \param[in,out] offset213 /// Pointer to an offset in the data. On return the offset will be214 /// advanced by the number of bytes read.215 ///216 /// \return217 /// True if the ELFProgramHeader was successfully read and false218 /// otherwise.219 bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);220};221 222/// \class ELFSymbol223/// Represents a symbol within an ELF symbol table.224struct ELFSymbol {225 elf_addr st_value; ///< Absolute or relocatable address.226 elf_xword st_size; ///< Size of the symbol or zero.227 elf_word st_name; ///< Symbol name string index.228 unsigned char st_info; ///< Symbol type and binding attributes.229 unsigned char st_other; ///< Reserved for future use.230 elf_half st_shndx; ///< Section to which this symbol applies.231 232 ELFSymbol();233 234 /// Returns the binding attribute of the st_info member.235 unsigned char getBinding() const { return st_info >> 4; }236 237 /// Returns the type attribute of the st_info member.238 unsigned char getType() const { return st_info & 0x0F; }239 240 /// Sets the binding and type of the st_info member.241 void setBindingAndType(unsigned char binding, unsigned char type) {242 st_info = (binding << 4) + (type & 0x0F);243 }244 245 static const char *bindingToCString(unsigned char binding);246 247 static const char *typeToCString(unsigned char type);248 249 static const char *250 sectionIndexToCString(elf_half shndx,251 const lldb_private::SectionList *section_list);252 253 /// Parse an ELFSymbol entry from the given DataExtractor starting at254 /// position \p offset. The address size of the DataExtractor determines if255 /// a 32 or 64 bit object is to be parsed.256 ///257 /// \param[in] data258 /// The DataExtractor to read from. The address size of the extractor259 /// determines if a 32 or 64 bit object should be read.260 ///261 /// \param[in,out] offset262 /// Pointer to an offset in the data. On return the offset will be263 /// advanced by the number of bytes read.264 ///265 /// \return266 /// True if the ELFSymbol was successfully read and false otherwise.267 bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);268 269 void Dump(lldb_private::Stream *s, uint32_t idx,270 const lldb_private::DataExtractor *strtab_data,271 const lldb_private::SectionList *section_list);272};273 274/// \class ELFDynamic275/// Represents an entry in an ELF dynamic table.276struct ELFDynamic {277 elf_sxword d_tag; ///< Type of dynamic table entry.278 union {279 elf_xword d_val; ///< Integer value of the table entry.280 elf_addr d_ptr; ///< Pointer value of the table entry.281 };282 283 ELFDynamic();284 285 /// Parse an ELFDynamic entry from the given DataExtractor starting at286 /// position \p offset. The address size of the DataExtractor determines if287 /// a 32 or 64 bit object is to be parsed.288 ///289 /// \param[in] data290 /// The DataExtractor to read from. The address size of the extractor291 /// determines if a 32 or 64 bit object should be read.292 ///293 /// \param[in,out] offset294 /// Pointer to an offset in the data. On return the offset will be295 /// advanced by the number of bytes read.296 ///297 /// \return298 /// True if the ELFDynamic entry was successfully read and false299 /// otherwise.300 bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);301};302 303/// \class ELFRel304/// Represents a relocation entry with an implicit addend.305struct ELFRel {306 elf_addr r_offset; ///< Address of reference.307 elf_xword r_info; ///< symbol index and type of relocation.308 309 ELFRel();310 311 /// Parse an ELFRel entry from the given DataExtractor starting at position312 /// \p offset. The address size of the DataExtractor determines if a 32 or313 /// 64 bit object is to be parsed.314 ///315 /// \param[in] data316 /// The DataExtractor to read from. The address size of the extractor317 /// determines if a 32 or 64 bit object should be read.318 ///319 /// \param[in,out] offset320 /// Pointer to an offset in the data. On return the offset will be321 /// advanced by the number of bytes read.322 ///323 /// \return324 /// True if the ELFRel entry was successfully read and false otherwise.325 bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);326 327 /// Returns the type when the given entry represents a 32-bit relocation.328 static unsigned RelocType32(const ELFRel &rel) { return rel.r_info & 0x0ff; }329 330 /// Returns the type when the given entry represents a 64-bit relocation.331 static unsigned RelocType64(const ELFRel &rel) {332 return rel.r_info & 0xffffffff;333 }334 335 /// Returns the symbol index when the given entry represents a 32-bit336 /// relocation.337 static unsigned RelocSymbol32(const ELFRel &rel) { return rel.r_info >> 8; }338 339 /// Returns the symbol index when the given entry represents a 64-bit340 /// relocation.341 static unsigned RelocSymbol64(const ELFRel &rel) { return rel.r_info >> 32; }342};343 344/// \class ELFRela345/// Represents a relocation entry with an explicit addend.346struct ELFRela {347 elf_addr r_offset; ///< Address of reference.348 elf_xword r_info; ///< Symbol index and type of relocation.349 elf_sxword r_addend; ///< Constant part of expression.350 351 ELFRela();352 353 /// Parse an ELFRela entry from the given DataExtractor starting at position354 /// \p offset. The address size of the DataExtractor determines if a 32 or355 /// 64 bit object is to be parsed.356 ///357 /// \param[in] data358 /// The DataExtractor to read from. The address size of the extractor359 /// determines if a 32 or 64 bit object should be read.360 ///361 /// \param[in,out] offset362 /// Pointer to an offset in the data. On return the offset will be363 /// advanced by the number of bytes read.364 ///365 /// \return366 /// True if the ELFRela entry was successfully read and false otherwise.367 bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);368 369 /// Returns the type when the given entry represents a 32-bit relocation.370 static unsigned RelocType32(const ELFRela &rela) {371 return rela.r_info & 0x0ff;372 }373 374 /// Returns the type when the given entry represents a 64-bit relocation.375 static unsigned RelocType64(const ELFRela &rela) {376 return rela.r_info & 0xffffffff;377 }378 379 /// Returns the symbol index when the given entry represents a 32-bit380 /// relocation.381 static unsigned RelocSymbol32(const ELFRela &rela) {382 return rela.r_info >> 8;383 }384 385 /// Returns the symbol index when the given entry represents a 64-bit386 /// relocation.387 static unsigned RelocSymbol64(const ELFRela &rela) {388 return rela.r_info >> 32;389 }390};391 392} // End namespace elf.393 394#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_ELFHEADER_H395