patch.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. #pragma once
  2. #include "elf.h"
  3. #include <util/generic/string.h>
  4. #include <util/stream/file.h>
  5. #include <util/system/filemap.h>
  6. namespace NElf {
  7. template<typename TTo, typename TFrom>
  8. inline TTo Offset(TFrom from, size_t off) {
  9. return reinterpret_cast<TTo>(reinterpret_cast<char*>(from) + off);
  10. }
  11. bool IsElf(const TString& path);
  12. class TElf {
  13. public:
  14. TElf(const TString& path)
  15. : Map(path, TFileMap::oRdWr)
  16. {
  17. Map.Map(0, Map.Length());
  18. Begin = reinterpret_cast<char*>(Map.Ptr());
  19. if (Map.Length() < static_cast<i64>(sizeof(Elf64_Ehdr)) || TStringBuf(Begin, SELFMAG) != ELFMAG) {
  20. ythrow yexception() << path << " is not an ELF file";
  21. }
  22. }
  23. Elf64_Ehdr* GetHeader() const noexcept {
  24. return reinterpret_cast<Elf64_Ehdr*>(Begin);
  25. }
  26. char* GetPtr(size_t offset = 0) const noexcept {
  27. return Begin + offset;
  28. }
  29. Elf64_Shdr* GetSectionByType(Elf64_Word type) const {
  30. Elf64_Shdr* r = nullptr;
  31. for (Elf64_Shdr* p = GetSectionBegin(), *end = GetSectionEnd(); p != end; ++p) {
  32. if (p->sh_type == type) {
  33. if (r) {
  34. ythrow yexception() << "More than one section of type " << type << Endl;
  35. }
  36. r = p;
  37. }
  38. }
  39. return r;
  40. }
  41. size_t GetSectionCount() const noexcept {
  42. size_t count = GetHeader()->e_shnum;
  43. if (count == 0) {
  44. count = GetSection(0)->sh_size;
  45. }
  46. return count;
  47. }
  48. Elf64_Shdr* GetSectionBegin() const noexcept {
  49. return reinterpret_cast<Elf64_Shdr*>(Begin + GetHeader()->e_shoff);
  50. }
  51. Elf64_Shdr* GetSectionEnd() const noexcept {
  52. return reinterpret_cast<Elf64_Shdr*>(Begin + GetHeader()->e_shoff) + GetSectionCount();
  53. }
  54. Elf64_Shdr* GetSection(size_t i) const noexcept {
  55. return GetSectionBegin() + i;
  56. }
  57. Elf64_Shdr* GetSectionsNameSection() const noexcept {
  58. size_t index = GetHeader()->e_shstrndx;
  59. if (index == SHN_XINDEX) {
  60. index = GetSection(0)->sh_link;
  61. }
  62. return GetSection(index);
  63. }
  64. private:
  65. TFileMap Map;
  66. char* Begin;
  67. };
  68. class TSection {
  69. public:
  70. TSection(TElf* elf, Elf64_Shdr* this_)
  71. : Elf(elf)
  72. , This(this_)
  73. {
  74. }
  75. bool IsNull() const noexcept {
  76. return !This;
  77. }
  78. char* GetPtr(size_t offset = 0) const noexcept {
  79. return Elf->GetPtr(This->sh_offset) + offset;
  80. }
  81. TStringBuf GetStr(size_t offset) const noexcept {
  82. return GetPtr(offset);
  83. }
  84. TStringBuf GetName() const noexcept {
  85. return TSection{Elf, Elf->GetSectionsNameSection()}.GetPtr(This->sh_name);
  86. }
  87. size_t GetLink() const noexcept {
  88. return This->sh_link;
  89. }
  90. size_t GetSize() const noexcept {
  91. return This->sh_size;
  92. }
  93. size_t GetEntryCount() const noexcept {
  94. return GetSize() / This->sh_entsize;
  95. }
  96. template<typename TTo = char>
  97. TTo* GetEntry(size_t i) const noexcept {
  98. return reinterpret_cast<TTo*>(GetPtr(i * This->sh_entsize));
  99. }
  100. private:
  101. TElf* Elf;
  102. Elf64_Shdr* This;
  103. };
  104. class TVerneedSection : public TSection {
  105. public:
  106. TVerneedSection(TElf* elf)
  107. : TSection(elf, elf->GetSectionByType(SHT_GNU_verneed))
  108. {
  109. }
  110. Elf64_Verneed* GetFirstVerneed() const noexcept {
  111. if (!GetSize()) {
  112. return nullptr;
  113. }
  114. return reinterpret_cast<Elf64_Verneed*>(GetPtr());
  115. }
  116. Elf64_Verneed* GetNextVerneed(Elf64_Verneed* v) const noexcept {
  117. if (!v->vn_next) {
  118. return nullptr;
  119. }
  120. return Offset<Elf64_Verneed*>(v, v->vn_next);
  121. }
  122. Elf64_Vernaux* GetFirstVernaux(Elf64_Verneed* v) const noexcept {
  123. if (!v->vn_cnt) {
  124. return nullptr;
  125. }
  126. return Offset<Elf64_Vernaux*>(v, v->vn_aux);
  127. }
  128. Elf64_Vernaux* GetNextVernaux(Elf64_Vernaux* v) const noexcept {
  129. if (!v->vna_next) {
  130. return nullptr;
  131. }
  132. return Offset<Elf64_Vernaux*>(v, v->vna_next);
  133. }
  134. };
  135. }