Support for better syntax

This commit is contained in:
Robin Nicholson 2018-03-15 19:56:25 +01:00
parent 1016910279
commit b5be3bb5b0
3 changed files with 216 additions and 0 deletions

124
Section.h Normal file
View File

@ -0,0 +1,124 @@
#ifndef ELFSPY_SECTION_H
#define ELFSPY_SECTION_H
#include <elf.h>
#include <stddef.h>
namespace spy
{
#ifdef __x86_64__
using Elf_Shdr = Elf64_Shdr;
#else
using Elf_Shdr = Elf32_Shdr;
#endif
class SectionHeader;
template <typename T>
class Section
{
public:
class Iterator;
Iterator begin() const;
Iterator end() const;
size_t entries() const;
const T& operator[](size_t index) const;
private:
const unsigned char* data_;
const Elf_Shdr* header_;
friend class SectionHeader;
Section(const unsigned char* data, const Elf_Shdr* header);
};
template <typename T>
inline Section<T>::Section(const unsigned char* data, const Elf_Shdr* header)
:data_(data)
,header_(header)
{
}
template <typename T>
class Section<T>::Iterator
{
public:
Iterator& operator++();
Iterator operator++(int);
const T& operator*() const;
const T* operator->() const;
bool operator!=(const Iterator& other) const;
private:
Iterator(const unsigned char* data, size_t size);
const unsigned char* data_;
size_t size_;
friend class Section;
};
template <typename T>
inline Section<T>::Iterator::Iterator(const unsigned char* data, size_t size)
{
data_ = data;
size_ = size;
}
template <typename T>
inline typename Section<T>::Iterator& Section<T>::Iterator::operator++()
{
data_ += size_;
return *this;
}
template <typename T>
inline typename Section<T>::Iterator Section<T>::Iterator::operator++(int)
{
Iterator copy(*this);
data_ += size_;
return copy;
}
template <typename T>
inline const T& Section<T>::Iterator::operator*() const
{
return *reinterpret_cast<const T*>(data_);
}
template <typename T>
inline const T* Section<T>::Iterator::operator->() const
{
return reinterpret_cast<const T*>(data_);
}
template <typename T>
inline bool Section<T>::Iterator::operator!=(const Section<T>::Iterator& other) const
{
return data_ != other.data_;
}
template <typename T>
inline typename Section<T>::Iterator Section<T>::begin() const
{
return { data_ + header_->sh_offset, header_->sh_entsize };
}
template <typename T>
inline typename Section<T>::Iterator Section<T>::end() const
{
return { data_ + header_->sh_offset + header_->sh_size, header_->sh_entsize };
}
template <typename T>
inline size_t Section<T>::entries() const
{
return header_->sh_size / header_->sh_entsize;
}
template <typename T>
const T& Section<T>::operator[](size_t index) const
{
index *= header_->sh_entsize;
return *reinterpret_cast<const T*>(data_ + header_->sh_offset + index);
}
} // namespace spy
#endif

22
SectionHeader.cpp Normal file
View File

@ -0,0 +1,22 @@
#include "elfspy/SectionHeader.h"
#include <string.h>
namespace
{
spy::Elf_Shdr no_header()
{
spy::Elf_Shdr zero_init;
memset(&zero_init, 0, sizeof(zero_init));
return zero_init;
}
} // namespace
namespace spy
{
// allow begin() and end() to work with SectionHeaders that were not found
const Elf_Shdr SectionHeader::no_header_ = no_header();
} // namespace spy

70
SectionHeader.h Normal file
View File

@ -0,0 +1,70 @@
#ifndef ELFSPY_SECTIONHEADER_H
#define ELFSPY_SECTIONHEADER_H
#include <elf.h>
#include "elfspy/Section.h"
namespace spy
{
class ELFInfo;
class SectionHeader
{
public:
SectionHeader() = default;
const unsigned char* begin() const;
const unsigned char* end() const;
size_t entries() const;
bool operator!() const;
explicit operator bool() const;
template <typename T>
Section<T> as_section() const;
private:
static const Elf_Shdr no_header_;
const unsigned char* data_ = nullptr;
const Elf_Shdr* header_ = &no_header_;
friend class ELFInfo;
SectionHeader(const unsigned char* data, const Elf_Shdr* header);
};
inline SectionHeader::SectionHeader(const unsigned char* data, const Elf_Shdr* header)
:data_(data)
,header_(header)
{
}
inline const unsigned char* SectionHeader::begin() const
{
return data_ + header_->sh_offset;
}
inline const unsigned char* SectionHeader::end() const
{
return begin() + header_->sh_size;
}
inline size_t SectionHeader::entries() const
{
return header_->sh_size / header_->sh_entsize;
}
inline bool SectionHeader::operator!() const
{
return header_ == nullptr;
}
inline SectionHeader::operator bool() const
{
return header_ != nullptr;
}
template <typename T>
inline Section<T> SectionHeader::as_section() const
{
return { data_, header_ };
}
} // namespace spy
#endif