brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.6 KiB · 41b8ce1 Raw
481 lines · c
1//===-- ObjectFileELF.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#ifndef LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H10#define LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H11 12#include <cstdint>13 14#include <optional>15#include <vector>16 17#include "lldb/Symbol/ObjectFile.h"18#include "lldb/Utility/ArchSpec.h"19#include "lldb/Utility/FileSpec.h"20#include "lldb/Utility/UUID.h"21#include "lldb/lldb-private.h"22 23#include "ELFHeader.h"24 25struct ELFNote {26  elf::elf_word n_namesz = 0;27  elf::elf_word n_descsz = 0;28  elf::elf_word n_type = 0;29 30  std::string n_name;31 32  ELFNote() = default;33 34  /// Parse an ELFNote entry from the given DataExtractor starting at position35  /// \p offset.36  ///37  /// \param[in] data38  ///    The DataExtractor to read from.39  ///40  /// \param[in,out] offset41  ///    Pointer to an offset in the data.  On return the offset will be42  ///    advanced by the number of bytes read.43  ///44  /// \return45  ///    True if the ELFRel entry was successfully read and false otherwise.46  bool Parse(const lldb_private::DataExtractor &data, lldb::offset_t *offset);47 48  size_t GetByteSize() const {49    return 12 + llvm::alignTo(n_namesz, 4) + llvm::alignTo(n_descsz, 4);50  }51};52 53/// \class ObjectFileELF54/// Generic ELF object file reader.55///56/// This class provides a generic ELF (32/64 bit) reader plugin implementing57/// the ObjectFile protocol.58class ObjectFileELF : public lldb_private::ObjectFile {59public:60  // Static Functions61  static void Initialize();62 63  static void Terminate();64 65  static llvm::StringRef GetPluginNameStatic() { return "elf"; }66 67  static llvm::StringRef GetPluginDescriptionStatic() {68    return "ELF object file reader.";69  }70 71  static lldb_private::ObjectFile *72  CreateInstance(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp,73                 lldb::offset_t data_offset, const lldb_private::FileSpec *file,74                 lldb::offset_t file_offset, lldb::offset_t length);75 76  static lldb_private::ObjectFile *CreateMemoryInstance(77      const lldb::ModuleSP &module_sp, lldb::WritableDataBufferSP data_sp,78      const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);79 80  static size_t GetModuleSpecifications(const lldb_private::FileSpec &file,81                                        lldb::DataBufferSP &data_sp,82                                        lldb::offset_t data_offset,83                                        lldb::offset_t file_offset,84                                        lldb::offset_t length,85                                        lldb_private::ModuleSpecList &specs);86 87  static bool MagicBytesMatch(lldb::DataBufferSP &data_sp, lldb::addr_t offset,88                              lldb::addr_t length);89 90  // PluginInterface protocol91  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }92 93  // LLVM RTTI support94  static char ID;95  bool isA(const void *ClassID) const override {96    return ClassID == &ID || ObjectFile::isA(ClassID);97  }98  static bool classof(const ObjectFile *obj) { return obj->isA(&ID); }99 100  // ObjectFile Protocol.101  bool ParseHeader() override;102 103  bool SetLoadAddress(lldb_private::Target &target, lldb::addr_t value,104                      bool value_is_offset) override;105 106  lldb::ByteOrder GetByteOrder() const override;107 108  bool IsExecutable() const override;109 110  uint32_t GetAddressByteSize() const override;111 112  lldb_private::AddressClass GetAddressClass(lldb::addr_t file_addr) override;113 114  void ParseSymtab(lldb_private::Symtab &symtab) override;115 116  bool IsStripped() override;117 118  void CreateSections(lldb_private::SectionList &unified_section_list) override;119 120  void Dump(lldb_private::Stream *s) override;121 122  lldb_private::ArchSpec GetArchitecture() override;123 124  lldb_private::UUID GetUUID() override;125 126  /// Return the contents of the .gnu_debuglink section, if the object file127  /// contains it.128  std::optional<lldb_private::FileSpec> GetDebugLink();129 130  uint32_t GetDependentModules(lldb_private::FileSpecList &files) override;131 132  lldb_private::Address133  GetImageInfoAddress(lldb_private::Target *target) override;134 135  lldb_private::Address GetEntryPointAddress() override;136 137  lldb_private::Address GetBaseAddress() override;138 139  ObjectFile::Type CalculateType() override;140 141  ObjectFile::Strata CalculateStrata() override;142 143  size_t ReadSectionData(lldb_private::Section *section,144                         lldb::offset_t section_offset, void *dst,145                         size_t dst_len) override;146 147  size_t ReadSectionData(lldb_private::Section *section,148                         lldb_private::DataExtractor &section_data) override;149 150  llvm::ArrayRef<elf::ELFProgramHeader> ProgramHeaders();151  lldb_private::DataExtractor GetSegmentData(const elf::ELFProgramHeader &H);152 153  llvm::StringRef154  StripLinkerSymbolAnnotations(llvm::StringRef symbol_name) const override;155 156  void RelocateSection(lldb_private::Section *section) override;157 158protected:159 160  std::vector<LoadableData>161  GetLoadableData(lldb_private::Target &target) override;162 163  static lldb::WritableDataBufferSP164  MapFileDataWritable(const lldb_private::FileSpec &file, uint64_t Size,165                      uint64_t Offset);166 167private:168  ObjectFileELF(const lldb::ModuleSP &module_sp, lldb::DataBufferSP data_sp,169                lldb::offset_t data_offset, const lldb_private::FileSpec *file,170                lldb::offset_t offset, lldb::offset_t length);171 172  ObjectFileELF(const lldb::ModuleSP &module_sp,173                lldb::DataBufferSP header_data_sp,174                const lldb::ProcessSP &process_sp, lldb::addr_t header_addr);175 176  typedef std::vector<elf::ELFProgramHeader> ProgramHeaderColl;177 178  struct ELFSectionHeaderInfo : public elf::ELFSectionHeader {179    lldb_private::ConstString section_name;180  };181 182  typedef std::vector<ELFSectionHeaderInfo> SectionHeaderColl;183  typedef SectionHeaderColl::iterator SectionHeaderCollIter;184  typedef SectionHeaderColl::const_iterator SectionHeaderCollConstIter;185 186  struct ELFDynamicWithName {187    elf::ELFDynamic symbol;188    std::string name;189  };190  typedef std::vector<ELFDynamicWithName> DynamicSymbolColl;191  typedef DynamicSymbolColl::iterator DynamicSymbolCollIter;192  typedef DynamicSymbolColl::const_iterator DynamicSymbolCollConstIter;193 194  /// An ordered map of file address to address class. Used on architectures195  /// like Arm where there is an alternative ISA mode like Thumb. The container196  /// is ordered so that it can be binary searched.197  typedef std::map<lldb::addr_t, lldb_private::AddressClass>198      FileAddressToAddressClassMap;199 200  /// Version of this reader common to all plugins based on this class.201  static const uint32_t m_plugin_version = 1;202  static const uint32_t g_core_uuid_magic;203 204  /// ELF file header.205  elf::ELFHeader m_header;206 207  /// ELF build ID.208  lldb_private::UUID m_uuid;209 210  /// ELF .gnu_debuglink file and crc data if available.211  std::string m_gnu_debuglink_file;212  uint32_t m_gnu_debuglink_crc = 0;213 214  /// Collection of program headers.215  ProgramHeaderColl m_program_headers;216 217  /// Collection of section headers.218  SectionHeaderColl m_section_headers;219 220  /// The file address of the .dynamic section. This can be found in the p_vaddr221  /// of the PT_DYNAMIC program header.222  lldb::addr_t m_dynamic_base_addr = LLDB_INVALID_ADDRESS;223 224  /// Collection of symbols from the dynamic table.225  DynamicSymbolColl m_dynamic_symbols;226 227  /// Object file parsed from .gnu_debugdata section (\sa228  /// GetGnuDebugDataObjectFile())229  std::shared_ptr<ObjectFileELF> m_gnu_debug_data_object_file;230 231  /// List of file specifications corresponding to the modules (shared232  /// libraries) on which this object file depends.233  mutable std::unique_ptr<lldb_private::FileSpecList> m_filespec_up;234 235  /// Cached value of the entry point for this module.236  lldb_private::Address m_entry_point_address;237 238  /// The architecture detected from parsing elf file contents.239  lldb_private::ArchSpec m_arch_spec;240 241  /// The address class for each symbol in the elf file242  FileAddressToAddressClassMap m_address_class_map;243 244  /// Returns the index of the given section header.245  size_t SectionIndex(const SectionHeaderCollIter &I);246 247  /// Returns the index of the given section header.248  size_t SectionIndex(const SectionHeaderCollConstIter &I) const;249 250  // Parses the ELF program headers.251  static size_t GetProgramHeaderInfo(ProgramHeaderColl &program_headers,252                                     lldb_private::DataExtractor &object_data,253                                     const elf::ELFHeader &header);254 255  // Finds PT_NOTE segments and calculates their crc sum.256  static uint32_t257  CalculateELFNotesSegmentsCRC32(const ProgramHeaderColl &program_headers,258                                 lldb_private::DataExtractor &data);259 260  /// Parses all section headers present in this object file and populates261  /// m_program_headers.  This method will compute the header list only once.262  /// Returns true iff the headers have been successfully parsed.263  bool ParseProgramHeaders();264 265  /// Parses all section headers present in this object file and populates266  /// m_section_headers.  This method will compute the header list only once.267  /// Returns the number of headers parsed.268  size_t ParseSectionHeaders();269 270  lldb::SectionType GetSectionType(const ELFSectionHeaderInfo &H) const;271 272  static void ParseARMAttributes(lldb_private::DataExtractor &data,273                                 uint64_t length,274                                 lldb_private::ArchSpec &arch_spec);275 276  /// Parses the elf section headers and returns the uuid, debug link name,277  /// crc, archspec.278  static size_t GetSectionHeaderInfo(SectionHeaderColl &section_headers,279                                     lldb_private::DataExtractor &object_data,280                                     const elf::ELFHeader &header,281                                     lldb_private::UUID &uuid,282                                     std::string &gnu_debuglink_file,283                                     uint32_t &gnu_debuglink_crc,284                                     lldb_private::ArchSpec &arch_spec);285 286  /// Scans the dynamic section and locates all dependent modules (shared287  /// libraries) populating m_filespec_up.  This method will compute the288  /// dependent module list only once.  Returns the number of dependent289  /// modules parsed.290  size_t ParseDependentModules();291 292  /// Parses the dynamic symbol table and populates m_dynamic_symbols.  The293  /// vector retains the order as found in the object file.  Returns the294  /// number of dynamic symbols parsed.295  size_t ParseDynamicSymbols();296 297  /// Populates the symbol table with all non-dynamic linker symbols.  This298  /// method will parse the symbols only once.  Returns the number of symbols299  /// parsed and a map of address types (used by targets like Arm that have300  /// an alternative ISA mode like Thumb).301  std::pair<unsigned, FileAddressToAddressClassMap>302  ParseSymbolTable(lldb_private::Symtab *symbol_table, lldb::user_id_t start_id,303                   lldb_private::Section *symtab);304 305  /// Helper routine for ParseSymbolTable().306  std::pair<unsigned, FileAddressToAddressClassMap>307  ParseSymbols(lldb_private::Symtab *symbol_table, lldb::user_id_t start_id,308               lldb_private::SectionList *section_list,309               const size_t num_symbols,310               const lldb_private::DataExtractor &symtab_data,311               const lldb_private::DataExtractor &strtab_data);312 313  /// Scans the relocation entries and adds a set of artificial symbols to the314  /// given symbol table for each PLT slot.  Returns the number of symbols315  /// added.316  unsigned ParseTrampolineSymbols(lldb_private::Symtab *symbol_table,317                                  lldb::user_id_t start_id,318                                  const ELFSectionHeaderInfo *rela_hdr,319                                  lldb::user_id_t section_id);320 321  void ParseUnwindSymbols(lldb_private::Symtab *symbol_table,322                          lldb_private::DWARFCallFrameInfo *eh_frame);323 324  /// Relocates debug sections325  unsigned RelocateDebugSections(const elf::ELFSectionHeader *rel_hdr,326                                 lldb::user_id_t rel_id,327                                 lldb_private::Symtab *thetab);328 329  unsigned ApplyRelocations(lldb_private::Symtab *symtab,330                            const elf::ELFHeader *hdr,331                            const elf::ELFSectionHeader *rel_hdr,332                            const elf::ELFSectionHeader *symtab_hdr,333                            const elf::ELFSectionHeader *debug_hdr,334                            lldb_private::DataExtractor &rel_data,335                            lldb_private::DataExtractor &symtab_data,336                            lldb_private::DataExtractor &debug_data,337                            lldb_private::Section *rel_section);338 339  /// Loads the section name string table into m_shstr_data.  Returns the340  /// number of bytes constituting the table.341  size_t GetSectionHeaderStringTable();342 343  /// Utility method for looking up a section given its name.  Returns the344  /// index of the corresponding section or zero if no section with the given345  /// name can be found (note that section indices are always 1 based, and so346  /// section index 0 is never valid).347  lldb::user_id_t GetSectionIndexByName(const char *name);348 349  /// Returns the section header with the given id or NULL.350  const ELFSectionHeaderInfo *GetSectionHeaderByIndex(lldb::user_id_t id);351 352  /// \name  ELF header dump routines353  //@{354  static void DumpELFHeader(lldb_private::Stream *s,355                            const elf::ELFHeader &header);356 357  static void DumpELFHeader_e_ident_EI_DATA(lldb_private::Stream *s,358                                            unsigned char ei_data);359 360  static void DumpELFHeader_e_type(lldb_private::Stream *s,361                                   elf::elf_half e_type);362  //@}363 364  /// \name ELF program header dump routines365  //@{366  void DumpELFProgramHeaders(lldb_private::Stream *s);367 368  static void DumpELFProgramHeader(lldb_private::Stream *s,369                                   const elf::ELFProgramHeader &ph);370 371  static void DumpELFProgramHeader_p_type(lldb_private::Stream *s,372                                          elf::elf_word p_type);373 374  static void DumpELFProgramHeader_p_flags(lldb_private::Stream *s,375                                           elf::elf_word p_flags);376  //@}377 378  /// \name ELF section header dump routines379  //@{380  void DumpELFSectionHeaders(lldb_private::Stream *s);381 382  static void DumpELFSectionHeader(lldb_private::Stream *s,383                                   const ELFSectionHeaderInfo &sh);384 385  static void DumpELFSectionHeader_sh_type(lldb_private::Stream *s,386                                           elf::elf_word sh_type);387 388  static void DumpELFSectionHeader_sh_flags(lldb_private::Stream *s,389                                            elf::elf_xword sh_flags);390  //@}391 392  /// ELF dependent module dump routine.393  void DumpDependentModules(lldb_private::Stream *s);394 395  /// ELF dump the .dynamic section396  void DumpELFDynamic(lldb_private::Stream *s);397 398  const elf::ELFDynamic *FindDynamicSymbol(unsigned tag);399 400  unsigned PLTRelocationType();401 402  static lldb_private::Status403  RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,404                              lldb_private::ArchSpec &arch_spec,405                              lldb_private::UUID &uuid);406 407  bool AnySegmentHasPhysicalAddress();408 409  /// Takes the .gnu_debugdata and returns the decompressed object file that is410  /// stored within that section.411  ///412  /// \returns either the decompressed object file stored within the413  /// .gnu_debugdata section or \c nullptr if an error occured or if there's no414  /// section with that name.415  std::shared_ptr<ObjectFileELF> GetGnuDebugDataObjectFile();416 417  /// Get the bytes that represent the .dynamic section.418  ///419  /// This function will fetch the data for the .dynamic section in an ELF file.420  /// The PT_DYNAMIC program header will be used to extract the data and this421  /// function will fall back to using the section headers if PT_DYNAMIC isn't422  /// found.423  ///424  /// \return The bytes that represent the string table data or \c std::nullopt425  ///         if an error occured.426  std::optional<lldb_private::DataExtractor> GetDynamicData();427 428  /// Get the bytes that represent the dynamic string table data.429  ///430  /// This function will fetch the data for the string table in an ELF file. If431  /// the ELF file is loaded from a file on disk, it will use the section432  /// headers to extract the data and fall back to using the DT_STRTAB and433  /// DT_STRSZ .dynamic entries.434  ///435  /// \return The bytes that represent the string table data or \c std::nullopt436  ///         if an error occured.437  std::optional<lldb_private::DataExtractor> GetDynstrData();438 439  /// Read the bytes pointed to by the \a dyn dynamic entry.440  ///441  /// ELFDynamic::d_ptr values contain file addresses if we load the ELF file442  /// form a file on disk, or they contain load addresses if they were read443  /// from memory. This function will correctly extract the data in both cases444  /// if it is available.445  ///446  /// \param[in] dyn The dynamic entry to use to fetch the data from.447  ///448  /// \param[in] length The number of bytes to read.449  ///450  /// \param[in] offset The number of bytes to skip after the d_ptr value451  ///                   before reading data.452  ///453  /// \return The bytes that represent the dynanic entries data or454  ///         \c std::nullopt if an error occured or the data is not available.455  std::optional<lldb_private::DataExtractor>456  ReadDataFromDynamic(const elf::ELFDynamic *dyn, uint64_t length,457                      uint64_t offset = 0);458 459  /// Get the bytes that represent the dynamic symbol table from the .dynamic460  /// section from process memory.461  ///462  /// This functon uses the DT_SYMTAB value from the .dynamic section to read463  /// the symbols table data from process memory. The number of symbols in the464  /// symbol table is calculated by looking at the DT_HASH or DT_GNU_HASH465  /// values as the symbol count isn't stored in the .dynamic section.466  ///467  /// \return The bytes that represent the symbol table data from the .dynamic468  ///         section or section headers or \c std::nullopt if an error469  ///         occured or if there is no dynamic symbol data available.470  std::optional<lldb_private::DataExtractor>471  GetDynsymDataFromDynamic(uint32_t &num_symbols);472 473  /// Get the number of symbols from the DT_HASH dynamic entry.474  std::optional<uint32_t> GetNumSymbolsFromDynamicHash();475 476  /// Get the number of symbols from the DT_GNU_HASH dynamic entry.477  std::optional<uint32_t> GetNumSymbolsFromDynamicGnuHash();478};479 480#endif // LLDB_SOURCE_PLUGINS_OBJECTFILE_ELF_OBJECTFILEELF_H481