diff options
author | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
---|---|---|
committer | Devtools Arcadia <[email protected]> | 2022-02-07 18:08:42 +0300 |
commit | 1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch) | |
tree | e26c9fed0de5d9873cce7e00bc214573dc2195b7 /tools/fix_elf/patch.h |
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'tools/fix_elf/patch.h')
-rw-r--r-- | tools/fix_elf/patch.h | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/tools/fix_elf/patch.h b/tools/fix_elf/patch.h new file mode 100644 index 00000000000..c3dcd242249 --- /dev/null +++ b/tools/fix_elf/patch.h @@ -0,0 +1,175 @@ +#pragma once + +#include "elf.h" + +#include <util/generic/string.h> +#include <util/stream/file.h> +#include <util/system/filemap.h> + +namespace NElf { + +template<typename TTo, typename TFrom> +inline TTo Offset(TFrom from, size_t off) { + return reinterpret_cast<TTo>(reinterpret_cast<char*>(from) + off); +} + +bool IsElf(const TString& path); + +class TElf { +public: + TElf(const TString& path) + : Map(path, TFileMap::oRdWr) + { + Map.Map(0, Map.Length()); + Begin = reinterpret_cast<char*>(Map.Ptr()); + + if (Map.Length() < static_cast<i64>(sizeof(Elf64_Ehdr)) || TStringBuf(Begin, SELFMAG) != ELFMAG) { + ythrow yexception() << path << " is not an ELF file"; + } + } + + Elf64_Ehdr* GetHeader() const noexcept { + return reinterpret_cast<Elf64_Ehdr*>(Begin); + } + + char* GetPtr(size_t offset = 0) const noexcept { + return Begin + offset; + } + + Elf64_Shdr* GetSectionByType(Elf64_Word type) const { + Elf64_Shdr* r = nullptr; + + for (Elf64_Shdr* p = GetSectionBegin(), *end = GetSectionEnd(); p != end; ++p) { + if (p->sh_type == type) { + if (r) { + ythrow yexception() << "More than one section of type " << type << Endl; + } + + r = p; + } + } + + return r; + } + + size_t GetSectionCount() const noexcept { + size_t count = GetHeader()->e_shnum; + if (count == 0) { + count = GetSection(0)->sh_size; + } + + return count; + } + + Elf64_Shdr* GetSectionBegin() const noexcept { + return reinterpret_cast<Elf64_Shdr*>(Begin + GetHeader()->e_shoff); + } + + Elf64_Shdr* GetSectionEnd() const noexcept { + return reinterpret_cast<Elf64_Shdr*>(Begin + GetHeader()->e_shoff) + GetSectionCount(); + } + + Elf64_Shdr* GetSection(size_t i) const noexcept { + return GetSectionBegin() + i; + } + + Elf64_Shdr* GetSectionsNameSection() const noexcept { + size_t index = GetHeader()->e_shstrndx; + if (index == SHN_XINDEX) { + index = GetSection(0)->sh_link; + } + return GetSection(index); + } + +private: + TFileMap Map; + char* Begin; +}; + +class TSection { +public: + TSection(TElf* elf, Elf64_Shdr* this_) + : Elf(elf) + , This(this_) + { + } + + bool IsNull() const noexcept { + return !This; + } + + char* GetPtr(size_t offset = 0) const noexcept { + return Elf->GetPtr(This->sh_offset) + offset; + } + + TStringBuf GetStr(size_t offset) const noexcept { + return GetPtr(offset); + } + + TStringBuf GetName() const noexcept { + return TSection{Elf, Elf->GetSectionsNameSection()}.GetPtr(This->sh_name); + } + + size_t GetLink() const noexcept { + return This->sh_link; + } + + size_t GetSize() const noexcept { + return This->sh_size; + } + + size_t GetEntryCount() const noexcept { + return GetSize() / This->sh_entsize; + } + + template<typename TTo = char> + TTo* GetEntry(size_t i) const noexcept { + return reinterpret_cast<TTo*>(GetPtr(i * This->sh_entsize)); + } + +private: + TElf* Elf; + Elf64_Shdr* This; +}; + +class TVerneedSection : public TSection { +public: + TVerneedSection(TElf* elf) + : TSection(elf, elf->GetSectionByType(SHT_GNU_verneed)) + { + } + + Elf64_Verneed* GetFirstVerneed() const noexcept { + if (!GetSize()) { + return nullptr; + } + + return reinterpret_cast<Elf64_Verneed*>(GetPtr()); + } + + Elf64_Verneed* GetNextVerneed(Elf64_Verneed* v) const noexcept { + if (!v->vn_next) { + return nullptr; + } + + return Offset<Elf64_Verneed*>(v, v->vn_next); + } + + Elf64_Vernaux* GetFirstVernaux(Elf64_Verneed* v) const noexcept { + if (!v->vn_cnt) { + return nullptr; + } + + return Offset<Elf64_Vernaux*>(v, v->vn_aux); + } + + Elf64_Vernaux* GetNextVernaux(Elf64_Vernaux* v) const noexcept { + if (!v->vna_next) { + return nullptr; + } + + return Offset<Elf64_Vernaux*>(v, v->vna_next); + } +}; + +} |