Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/build/unix/elfhack/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 18 kB image not shown  

Quelle  elfxx.h   Sprache: C

 
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include <stdexcept>
#include <list>
#include <vector>
#include <cstring>
#include <fstream>
#include <algorithm>
#include <elf.h>
#include <asm/byteorder.h>

// Technically, __*_to_cpu and __cpu_to* function are equivalent,
// so swap can use either of both.
#define def_swap(endian, type, bits)                    \
  static inline type##bits##_t swap(type##bits##_t i) { \
    return __##endian##bits##_to_cpu(i);                \
  }

class little_endian {
 public:
  def_swap(le, uint, 16);
  def_swap(le, uint, 32);
  def_swap(le, uint, 64);
  def_swap(le, int, 16);
  def_swap(le, int, 32);
  def_swap(le, int, 64);
};

class big_endian {
 public:
  def_swap(be, uint, 16);
  def_swap(be, uint, 32);
  def_swap(be, uint, 64);
  def_swap(be, int, 16);
  def_swap(be, int, 32);
  def_swap(be, int, 64);
};

// forward declaration
class ElfSection;
class ElfSegment;
// TODO: Rename Elf_* types
class Elf_Ehdr;
class Elf_Phdr;
class Elf;
class ElfDynamic_Section;
class ElfStrtab_Section;

template <typename X>
class FixedSizeData {
 public:
  struct Wrapper {
    X value;
  };
  typedef Wrapper Type32;
  typedef Wrapper Type64;

  template <class endian, typename R, typename T>
  static void swap(T& t, R& r) {
    r.value = endian::swap(t.value);
  }
};

class Elf_Ehdr_Traits {
 public:
  typedef Elf32_Ehdr Type32;
  typedef Elf64_Ehdr Type64;

  template <class endian, typename R, typename T>
  static void swap(T& t, R& r);
};

class Elf_Phdr_Traits {
 public:
  typedef Elf32_Phdr Type32;
  typedef Elf64_Phdr Type64;

  template <class endian, typename R, typename T>
  static void swap(T& t, R& r);
};

class Elf_Shdr_Traits {
 public:
  typedef Elf32_Shdr Type32;
  typedef Elf64_Shdr Type64;

  template <class endian, typename R, typename T>
  static void swap(T& t, R& r);
};

class Elf_Dyn_Traits {
 public:
  typedef Elf32_Dyn Type32;
  typedef Elf64_Dyn Type64;

  template <class endian, typename R, typename T>
  static void swap(T& t, R& r);
};

class Elf_Sym_Traits {
 public:
  typedef Elf32_Sym Type32;
  typedef Elf64_Sym Type64;

  template <class endian, typename R, typename T>
  static void swap(T& t, R& r);
};

class Elf_Rel_Traits {
 public:
  typedef Elf32_Rel Type32;
  typedef Elf64_Rel Type64;

  template <class endian, typename R, typename T>
  static void swap(T& t, R& r);
};

class Elf_Rela_Traits {
 public:
  typedef Elf32_Rela Type32;
  typedef Elf64_Rela Type64;

  template <class endian, typename R, typename T>
  static void swap(T& t, R& r);
};

class ElfValue {
 public:
  virtual unsigned int getValue() { return 0; }
  virtual ElfSection* getSection() { return nullptr; }
};

class ElfPlainValue : public ElfValue {
  unsigned int value;

 public:
  ElfPlainValue(unsigned int val) : value(val) {};
  unsigned int getValue() { return value; }
};

class ElfLocation : public ElfValue {
  ElfSection* section;
  unsigned int offset;

 public:
  enum position { ABSOLUTE, RELATIVE };
  ElfLocation() : section(nullptr), offset(0) {};
  ElfLocation(ElfSection* section, unsigned int off,
              enum position pos = RELATIVE);
  ElfLocation(unsigned int location, Elf* elf);
  unsigned int getValue();
  ElfSection* getSection() { return section; }
  const char* getBuffer();
};

class ElfSize : public ElfValue {
  ElfSection* section;

 public:
  ElfSize(ElfSection* s) : section(s) {};
  unsigned int getValue();
  ElfSection* getSection() { return section; }
};

class ElfEntSize : public ElfValue {
  ElfSection* section;

 public:
  ElfEntSize(ElfSection* s) : section(s) {};
  unsigned int getValue();
  ElfSection* getSection() { return section; }
};

template <typename T>
class serializable : public T::Type64 {
 public:
  serializable() {};
  serializable(const typename T::Type64& p) : T::Type64(p) {};

 private:
  template <typename R>
  void init(const char* buf, size_t len, unsigned char ei_data) {
    R e;
    assert(len >= sizeof(e));
    memcpy(&e, buf, sizeof(e));
    if (ei_data == ELFDATA2LSB) {
      T::template swap<little_endian>(e, *this);
      return;
    } else if (ei_data == ELFDATA2MSB) {
      T::template swap<big_endian>(e, *this);
      return;
    }
    throw std::runtime_error("Unsupported ELF data encoding");
  }

  template <typename R>
  void serialize(const char* buf, size_t len, unsigned char ei_data) {
    assert(len >= sizeof(R));
    if (ei_data == ELFDATA2LSB) {
      T::template swap<little_endian>(*this, *(R*)buf);
      return;
    } else if (ei_data == ELFDATA2MSB) {
      T::template swap<big_endian>(*this, *(R*)buf);
      return;
    }
    throw std::runtime_error("Unsupported ELF data encoding");
  }

 public:
  serializable(const char* buf, size_t len, unsigned char ei_class,
               unsigned char ei_data) {
    if (ei_class == ELFCLASS32) {
      init<typename T::Type32>(buf, len, ei_data);
      return;
    } else if (ei_class == ELFCLASS64) {
      init<typename T::Type64>(buf, len, ei_data);
      return;
    }
    throw std::runtime_error("Unsupported ELF class");
  }

  serializable(std::ifstream& file, unsigned char ei_class,
               unsigned char ei_data) {
    if (ei_class == ELFCLASS32) {
      typename T::Type32 e;
      file.read((char*)&e, sizeof(e));
      init<typename T::Type32>((char*)&e, sizeof(e), ei_data);
      return;
    } else if (ei_class == ELFCLASS64) {
      typename T::Type64 e;
      file.read((char*)&e, sizeof(e));
      init<typename T::Type64>((char*)&e, sizeof(e), ei_data);
      return;
    }
    throw std::runtime_error("Unsupported ELF class or data encoding");
  }

  void serialize(std::ofstream& file, unsigned char ei_class,
                 unsigned char ei_data) {
    if (ei_class == ELFCLASS32) {
      typename T::Type32 e;
      serialize<typename T::Type32>((char*)&e, sizeof(e), ei_data);
      file.write((char*)&e, sizeof(e));
      return;
    } else if (ei_class == ELFCLASS64) {
      typename T::Type64 e;
      serialize<typename T::Type64>((char*)&e, sizeof(e), ei_data);
      file.write((char*)&e, sizeof(e));
      return;
    }
    throw std::runtime_error("Unsupported ELF class or data encoding");
  }

  void serialize(char* buf, size_t len, unsigned char ei_class,
                 unsigned char ei_data) {
    if (ei_class == ELFCLASS32) {
      serialize<typename T::Type32>(buf, len, ei_data);
      return;
    } else if (ei_class == ELFCLASS64) {
      serialize<typename T::Type64>(buf, len, ei_data);
      return;
    }
    throw std::runtime_error("Unsupported ELF class");
  }

  static inline unsigned int size(unsigned char ei_class) {
    if (ei_class == ELFCLASS32)
      return sizeof(typename T::Type32);
    else if (ei_class == ELFCLASS64)
      return sizeof(typename T::Type64);
    return 0;
  }
};

typedef serializable<Elf_Shdr_Traits> Elf_Shdr;

class Elf {
 public:
  Elf(std::ifstream& file);
  ~Elf();

  /* index == -1 is treated as index == ehdr.e_shstrndx */
  ElfSection* getSection(int index);

  ElfSection* getSectionAt(Elf64_Off offset);

  ElfSegment* getSegmentByType(unsigned int type, ElfSegment* last = nullptr);

  ElfDynamic_Section* getDynSection();

  void normalize();
  void write(std::ofstream& file);

  unsigned char getClass();
  unsigned char getData();
  unsigned char getType();
  unsigned char getMachine();
  unsigned int getSize();

  void insertSegmentAfter(ElfSegment* previous, ElfSegment* segment) {
    std::vector<ElfSegment*>::iterator prev =
        std::find(segments.begin(), segments.end(), previous);
    segments.insert(prev + 1, segment);
  }

  void removeSegment(ElfSegment* segment);

 private:
  Elf_Ehdr* ehdr;
  ElfLocation eh_entry;
  ElfStrtab_Section* eh_shstrndx;
  ElfSection** sections;
  std::vector<ElfSegment*> segments;
  ElfSection *shdr_section, *phdr_section;
  /* Values used only during initialization */
  Elf_Shdr** tmp_shdr;
  std::ifstream* tmp_file;
};

class ElfSection {
 public:
  typedef union {
    ElfSection* section;
    int index;
  } SectionInfo;

  ElfSection(Elf_Shdr& s, std::ifstream* file, Elf* parent);

  virtual ~ElfSection() { free(data); }

  const char* getName() { return name; }
  unsigned int getType() { return shdr.sh_type; }
  unsigned int getFlags() { return shdr.sh_flags; }
  Elf64_Addr getAddr();
  Elf64_Off getSize() { return shdr.sh_size; }
  unsigned int getAddrAlign() { return shdr.sh_addralign; }
  unsigned int getEntSize() { return shdr.sh_entsize; }
  const char* getData() { return data; }
  ElfSection* getLink() { return link; }
  SectionInfo getInfo() { return info; }

  void shrink(unsigned int newsize) {
    if (newsize < shdr.sh_size) {
      shdr.sh_size = newsize;
      markDirty();
    }
  }

  void grow(unsigned int newsize) {
    if (newsize > shdr.sh_size) {
      data = static_cast<char*>(realloc(data, newsize));
      memset(data + shdr.sh_size, 0, newsize - shdr.sh_size);
      shdr.sh_size = newsize;
      markDirty();
    }
  }

  Elf64_Off getOffset();
  int getIndex();
  Elf_Shdr& getShdr();

  ElfSection* getNext() { return next; }
  ElfSection* getPrevious() { return previous; }

  virtual bool isRelocatable() {
    return ((getType() == SHT_SYMTAB) || (getType() == SHT_STRTAB) ||
            (getType() == SHT_RELA) || (getType() == SHT_HASH) ||
            (getType() == SHT_NOTE) || (getType() == SHT_REL) ||
            (getType() == SHT_DYNSYM) || (getType() == SHT_GNU_HASH) ||
            (getType() == SHT_GNU_verdef) || (getType() == SHT_GNU_verneed) ||
            (getType() == SHT_GNU_versym) || getSegmentByType(PT_INTERP)) &&
           (getFlags() & SHF_ALLOC);
  }

  void insertAfter(ElfSection* section, bool dirty = true) {
    if (previous != nullptr) previous->next = next;
    if (next != nullptr) next->previous = previous;
    previous = section;
    if (section != nullptr) {
      next = section->next;
      section->next = this;
    } else
      next = nullptr;
    if (next != nullptr) next->previous = this;
    if (dirty) markDirty();
    insertInSegments(section->segments);
  }

  virtual void insertBefore(ElfSection* section, bool dirty = true) {
    if (previous != nullptr) previous->next = next;
    if (next != nullptr) next->previous = previous;
    next = section;
    if (section != nullptr) {
      previous = section->previous;
      section->previous = this;
    } else
      previous = nullptr;
    if (previous != nullptr) previous->next = this;
    if (dirty) markDirty();
    insertInSegments(section->segments);
  }

  void markDirty() {
    if (link != nullptr) shdr.sh_link = -1;
    if (info.index) shdr.sh_info = -1;
    shdr.sh_offset = -1;
    if (isRelocatable()) shdr.sh_addr = -1;
    if (next) next->markDirty();
  }

  virtual void serialize(std::ofstream& file, unsigned char ei_class,
                         unsigned char ei_data) {
    if (getType() == SHT_NOBITS) return;
    file.seekp(getOffset());
    file.write(data, getSize());
  }

  ElfSegment* getSegmentByType(unsigned int type);

 private:
  friend class ElfSegment;

  void addToSegment(ElfSegment* segment) { segments.push_back(segment); }

  void removeFromSegment(ElfSegment* segment) {
    std::vector<ElfSegment*>::iterator i =
        std::find(segments.begin(), segments.end(), segment);
    segments.erase(i, i + 1);
  }

  void insertInSegments(std::vector<ElfSegment*>& segs);

 protected:
  Elf_Shdr shdr;
  char* data;
  const char* name;

 private:
  ElfSection* link;
  SectionInfo info;
  ElfSection *next, *previous;
  int index;
  std::vector<ElfSegment*> segments;
};

class ElfSegment {
 public:
  ElfSegment(Elf_Phdr* phdr);

  unsigned int getType() { return type; }
  unsigned int getFlags() { return flags; }
  unsigned int getAlign() { return align; }

  ElfSection* getFirstSection() {
    return sections.empty() ? nullptr : sections.front();
  }
  int getVPDiff() { return v_p_diff; }
  unsigned int getFileSize();
  unsigned int getMemSize();
  unsigned int getOffset();
  unsigned int getAddr();

  void addSection(ElfSection* section);
  void removeSection(ElfSection* section);

  std::list<ElfSection*>::iterator begin() { return sections.begin(); }
  std::list<ElfSection*>::iterator end() { return sections.end(); }

  void clear();

 private:
  unsigned int type;
  int v_p_diff;  // Difference between physical and virtual address
  unsigned int flags;
  unsigned int align;
  std::list<ElfSection*> sections;
  // The following are only really used for PT_GNU_RELRO until something
  // better is found.
  unsigned int vaddr;
  unsigned int filesz, memsz;
};

class Elf_Ehdr : public serializable<Elf_Ehdr_Traits>, public ElfSection {
 public:
  Elf_Ehdr(std::ifstream& file, unsigned char ei_class, unsigned char ei_data);
  void serialize(std::ofstream& file, unsigned char ei_class,
                 unsigned char ei_data) {
    serializable<Elf_Ehdr_Traits>::serialize(file, ei_class, ei_data);
  }
};

class Elf_Phdr : public serializable<Elf_Phdr_Traits> {
 public:
  Elf_Phdr() {};
  Elf_Phdr(std::ifstream& file, unsigned char ei_class, unsigned char ei_data)
      : serializable<Elf_Phdr_Traits>(file, ei_class, ei_data) {};
  bool contains(ElfSection* section) {
    unsigned int size = section->getSize();
    unsigned int addr = section->getAddr();
    // This may be biased, but should work in most cases
    if ((section->getFlags() & SHF_ALLOC) == 0) return false;
    // Special case for PT_DYNAMIC. Eventually, this should
    // be better handled than special cases
    if ((p_type == PT_DYNAMIC) && (section->getType() != SHT_DYNAMIC))
      return false;
    // Special case for PT_TLS.
    if ((p_type == PT_TLS) && !(section->getFlags() & SHF_TLS)) return false;
    return (addr >= p_vaddr) && (addr + size <= p_vaddr + p_memsz);
  }
};

typedef serializable<Elf_Dyn_Traits> Elf_Dyn;

struct Elf_DynValue {
  unsigned int tag;
  ElfValue* value;
};

class ElfDynamic_Section : public ElfSection {
 public:
  ElfDynamic_Section(Elf_Shdr& s, std::ifstream* file, Elf* parent);
  ~ElfDynamic_Section();

  void serialize(std::ofstream& file, unsigned char ei_class,
                 unsigned char ei_data);

  ElfValue* getValueForType(unsigned int tag);
  ElfSection* getSectionForType(unsigned int tag);
  bool setValueForType(unsigned int tag, ElfValue* val);

 private:
  std::vector<Elf_DynValue> dyns;
};

typedef serializable<Elf_Sym_Traits> Elf_Sym;

struct Elf_SymValue {
  const char* name;
  unsigned char info;
  unsigned char other;
  ElfLocation value;
  unsigned int size;
  bool defined;
};

#define STT(type) (1 << STT_##type)

class ElfSymtab_Section : public ElfSection {
 public:
  ElfSymtab_Section(Elf_Shdr& s, std::ifstream* file, Elf* parent);

  void serialize(std::ofstream& file, unsigned char ei_class,
                 unsigned char ei_data);

  Elf_SymValue* lookup(const char* name,
                       unsigned int type_filter = STT(OBJECT) | STT(FUNC));

  // private: // Until we have a real API
  std::vector<Elf_SymValue> syms;
};

class Elf_Rel : public serializable<Elf_Rel_Traits> {
 public:
  Elf_Rel() : serializable<Elf_Rel_Traits>() {};

  Elf_Rel(std::ifstream& file, unsigned char ei_class, unsigned char ei_data)
      : serializable<Elf_Rel_Traits>(file, ei_class, ei_data) {};

  static const unsigned int sh_type = SHT_REL;
  static const unsigned int d_tag = DT_REL;
  static const unsigned int d_tag_count = DT_RELCOUNT;
};

class Elf_Rela : public serializable<Elf_Rela_Traits> {
 public:
  Elf_Rela() : serializable<Elf_Rela_Traits>() {};

  Elf_Rela(std::ifstream& file, unsigned char ei_class, unsigned char ei_data)
      : serializable<Elf_Rela_Traits>(file, ei_class, ei_data) {};

  static const unsigned int sh_type = SHT_RELA;
  static const unsigned int d_tag = DT_RELA;
  static const unsigned int d_tag_count = DT_RELACOUNT;
};

template <class Rel>
class ElfRel_Section : public ElfSection {
 public:
  ElfRel_Section(Elf_Shdr& s, std::ifstream* file, Elf* parent)
      : ElfSection(s, file, parent) {
    auto pos = file->tellg();
    file->seekg(shdr.sh_offset);
    for (unsigned int i = 0; i < s.sh_size / s.sh_entsize; i++) {
      Rel r(*file, parent->getClass(), parent->getData());
      rels.push_back(r);
    }
    file->seekg(pos);
  }

  void serialize(std::ofstream& file, unsigned char ei_class,
                 unsigned char ei_data) {
    for (typename std::vector<Rel>::iterator i = rels.begin(); i != rels.end();
         ++i)
      (*i).serialize(file, ei_class, ei_data);
  }
  // private: // Until we have a real API
  std::vector<Rel> rels;
};

class ElfStrtab_Section : public ElfSection {
 public:
  ElfStrtab_Section(Elf_Shdr& s, std::ifstream* file, Elf* parent)
      : ElfSection(s, file, parent) {
    table.push_back(table_storage(data, shdr.sh_size));
  }

  ~ElfStrtab_Section() {
    for (std::vector<table_storage>::iterator t = table.begin() + 1;
         t != table.end(); ++t)
      delete[] t->buf;
  }

  const char* getStr(unsigned int index);

  const char* getStr(const char* string);

  unsigned int getStrIndex(const char* string);

  void serialize(std::ofstream& file, unsigned char ei_class,
                 unsigned char ei_data);

 private:
  struct table_storage {
    unsigned int size, used;
    char* buf;

    table_storage() : size(4096), used(0), buf(new char[4096]) {}
    table_storage(const char* data, unsigned int sz)
        : size(sz), used(sz), buf(const_cast<char*>(data)) {}
  };
  std::vector<table_storage> table;
};

inline unsigned char Elf::getClass() { return ehdr->e_ident[EI_CLASS]; }

inline unsigned char Elf::getData() { return ehdr->e_ident[EI_DATA]; }

inline unsigned char Elf::getType() { return ehdr->e_type; }

inline unsigned char Elf::getMachine() { return ehdr->e_machine; }

inline unsigned int Elf::getSize() {
  ElfSection* section;
  for (section = shdr_section /* It's usually not far from the end */;
       section->getNext() != nullptr; section = section->getNext());
  return section->getOffset() + section->getSize();
}

inline ElfSegment* ElfSection::getSegmentByType(unsigned int type) {
  for (std::vector<ElfSegment*>::iterator seg = segments.begin();
       seg != segments.end(); ++seg)
    if ((*seg)->getType() == type) return *seg;
  return nullptr;
}

inline void ElfSection::insertInSegments(std::vector<ElfSegment*>& segs) {
  for (std::vector<ElfSegment*>::iterator it = segs.begin(); it != segs.end();
       ++it) {
    (*it)->addSection(this);
  }
}

inline ElfLocation::ElfLocation(ElfSection* section, unsigned int off,
                                enum position pos)
    : section(section) {
  if ((pos == ABSOLUTE) && section)
    offset = off - section->getAddr();
  else
    offset = off;
}

inline ElfLocation::ElfLocation(unsigned int location, Elf* elf) {
  section = elf->getSectionAt(location);
  offset = location - (section ? section->getAddr() : 0);
}

inline unsigned int ElfLocation::getValue() {
  return (section ? section->getAddr() : 0) + offset;
}

inline const char* ElfLocation::getBuffer() {
  return section ? section->getData() + offset : nullptr;
}

inline unsigned int ElfSize::getValue() { return section->getSize(); }

inline unsigned int ElfEntSize::getValue() { return section->getEntSize(); }

Messung V0.5
C=98 H=98 G=97

¤ Dauer der Verarbeitung: 0.2 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.