elf_mem_image.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. // Copyright (c) 2008, Google Inc.
  2. // All rights reserved.
  3. //
  4. // Redistribution and use in source and binary forms, with or without
  5. // modification, are permitted provided that the following conditions are
  6. // met:
  7. //
  8. // * Redistributions of source code must retain the above copyright
  9. // notice, this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above
  11. // copyright notice, this list of conditions and the following disclaimer
  12. // in the documentation and/or other materials provided with the
  13. // distribution.
  14. // * Neither the name of Google Inc. nor the names of its
  15. // contributors may be used to endorse or promote products derived from
  16. // this software without specific prior written permission.
  17. //
  18. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. // ---
  30. // Author: Paul Pluzhnikov
  31. //
  32. // Allow dynamic symbol lookup in an in-memory Elf image.
  33. //
  34. #include "elf_mem_image.h"
  35. #include "logging.h"
  36. #ifdef HAVE_ELF_MEM_IMAGE // defined in elf_mem_image.h
  37. #if defined(_musl_)
  38. #include <endian.h>
  39. #endif
  40. #include <stddef.h> // for size_t, ptrdiff_t
  41. // From binutils/include/elf/common.h (this doesn't appear to be documented
  42. // anywhere else).
  43. //
  44. // /* This flag appears in a Versym structure. It means that the symbol
  45. // is hidden, and is only visible with an explicit version number.
  46. // This is a GNU extension. */
  47. // #define VERSYM_HIDDEN 0x8000
  48. //
  49. // /* This is the mask for the rest of the Versym information. */
  50. // #define VERSYM_VERSION 0x7fff
  51. #define VERSYM_VERSION 0x7fff
  52. namespace base {
  53. namespace {
  54. template <int N> class ElfClass {
  55. public:
  56. static const int kElfClass = -1;
  57. static int ElfBind(const ElfW(Sym) *) {
  58. CHECK(false); // << "Unexpected word size";
  59. return 0;
  60. }
  61. static int ElfType(const ElfW(Sym) *) {
  62. CHECK(false); // << "Unexpected word size";
  63. return 0;
  64. }
  65. };
  66. template <> class ElfClass<32> {
  67. public:
  68. static const int kElfClass = ELFCLASS32;
  69. static int ElfBind(const ElfW(Sym) *symbol) {
  70. return ELF32_ST_BIND(symbol->st_info);
  71. }
  72. static int ElfType(const ElfW(Sym) *symbol) {
  73. return ELF32_ST_TYPE(symbol->st_info);
  74. }
  75. };
  76. template <> class ElfClass<64> {
  77. public:
  78. static const int kElfClass = ELFCLASS64;
  79. static int ElfBind(const ElfW(Sym) *symbol) {
  80. return ELF64_ST_BIND(symbol->st_info);
  81. }
  82. static int ElfType(const ElfW(Sym) *symbol) {
  83. return ELF64_ST_TYPE(symbol->st_info);
  84. }
  85. };
  86. typedef ElfClass<__WORDSIZE> CurrentElfClass;
  87. // Extract an element from one of the ELF tables, cast it to desired type.
  88. // This is just a simple arithmetic and a glorified cast.
  89. // Callers are responsible for bounds checking.
  90. template <class T>
  91. const T* GetTableElement(const ElfW(Ehdr) *ehdr,
  92. ElfW(Off) table_offset,
  93. ElfW(Word) element_size,
  94. size_t index) {
  95. return reinterpret_cast<const T*>(reinterpret_cast<const char *>(ehdr)
  96. + table_offset
  97. + index * element_size);
  98. }
  99. } // namespace
  100. const void *const ElfMemImage::kInvalidBase =
  101. reinterpret_cast<const void *>(~0L);
  102. ElfMemImage::ElfMemImage(const void *base) {
  103. Init(base);
  104. }
  105. int ElfMemImage::GetNumSymbols() const {
  106. if (!hash_) {
  107. return 0;
  108. }
  109. // See http://www.caldera.com/developers/gabi/latest/ch5.dynamic.html#hash
  110. return hash_[1];
  111. }
  112. const ElfW(Sym) *ElfMemImage::GetDynsym(int index) const {
  113. CHECK_LT(index, GetNumSymbols());
  114. return dynsym_ + index;
  115. }
  116. const ElfW(Versym) *ElfMemImage::GetVersym(int index) const {
  117. CHECK_LT(index, GetNumSymbols());
  118. return versym_ + index;
  119. }
  120. const ElfW(Phdr) *ElfMemImage::GetPhdr(int index) const {
  121. CHECK_LT(index, ehdr_->e_phnum);
  122. return GetTableElement<ElfW(Phdr)>(ehdr_,
  123. ehdr_->e_phoff,
  124. ehdr_->e_phentsize,
  125. index);
  126. }
  127. const char *ElfMemImage::GetDynstr(ElfW(Word) offset) const {
  128. CHECK_LT(offset, strsize_);
  129. return dynstr_ + offset;
  130. }
  131. const void *ElfMemImage::GetSymAddr(const ElfW(Sym) *sym) const {
  132. if (sym->st_shndx == SHN_UNDEF || sym->st_shndx >= SHN_LORESERVE) {
  133. // Symbol corresponds to "special" (e.g. SHN_ABS) section.
  134. return reinterpret_cast<const void *>(sym->st_value);
  135. }
  136. CHECK_LT(link_base_, sym->st_value);
  137. return GetTableElement<char>(ehdr_, 0, 1, sym->st_value) - link_base_;
  138. }
  139. const ElfW(Verdef) *ElfMemImage::GetVerdef(int index) const {
  140. CHECK_LE(index, verdefnum_);
  141. const ElfW(Verdef) *version_definition = verdef_;
  142. while (version_definition->vd_ndx < index && version_definition->vd_next) {
  143. const char *const version_definition_as_char =
  144. reinterpret_cast<const char *>(version_definition);
  145. version_definition =
  146. reinterpret_cast<const ElfW(Verdef) *>(version_definition_as_char +
  147. version_definition->vd_next);
  148. }
  149. return version_definition->vd_ndx == index ? version_definition : NULL;
  150. }
  151. const ElfW(Verdaux) *ElfMemImage::GetVerdefAux(
  152. const ElfW(Verdef) *verdef) const {
  153. return reinterpret_cast<const ElfW(Verdaux) *>(verdef+1);
  154. }
  155. const char *ElfMemImage::GetVerstr(ElfW(Word) offset) const {
  156. CHECK_LT(offset, strsize_);
  157. return dynstr_ + offset;
  158. }
  159. void ElfMemImage::Init(const void *base) {
  160. ehdr_ = NULL;
  161. dynsym_ = NULL;
  162. dynstr_ = NULL;
  163. versym_ = NULL;
  164. verdef_ = NULL;
  165. hash_ = NULL;
  166. strsize_ = 0;
  167. verdefnum_ = 0;
  168. link_base_ = ~0L; // Sentinel: PT_LOAD .p_vaddr can't possibly be this.
  169. if (!base || base == kInvalidBase) {
  170. return;
  171. }
  172. const intptr_t base_as_uintptr_t = reinterpret_cast<uintptr_t>(base);
  173. // Fake VDSO has low bit set.
  174. const bool fake_vdso = ((base_as_uintptr_t & 1) != 0);
  175. base = reinterpret_cast<const void *>(base_as_uintptr_t & ~1);
  176. const char *const base_as_char = reinterpret_cast<const char *>(base);
  177. if (base_as_char[EI_MAG0] != ELFMAG0 || base_as_char[EI_MAG1] != ELFMAG1 ||
  178. base_as_char[EI_MAG2] != ELFMAG2 || base_as_char[EI_MAG3] != ELFMAG3) {
  179. RAW_DCHECK(false, "no ELF magic"); // at %p", base);
  180. return;
  181. }
  182. int elf_class = base_as_char[EI_CLASS];
  183. if (elf_class != CurrentElfClass::kElfClass) {
  184. DCHECK_EQ(elf_class, CurrentElfClass::kElfClass);
  185. return;
  186. }
  187. switch (base_as_char[EI_DATA]) {
  188. case ELFDATA2LSB: {
  189. if (__LITTLE_ENDIAN != __BYTE_ORDER) {
  190. DCHECK_EQ(__LITTLE_ENDIAN, __BYTE_ORDER); // << ": wrong byte order";
  191. return;
  192. }
  193. break;
  194. }
  195. case ELFDATA2MSB: {
  196. if (__BIG_ENDIAN != __BYTE_ORDER) {
  197. DCHECK_EQ(__BIG_ENDIAN, __BYTE_ORDER); // << ": wrong byte order";
  198. return;
  199. }
  200. break;
  201. }
  202. default: {
  203. RAW_DCHECK(false, "unexpected data encoding"); // << base_as_char[EI_DATA];
  204. return;
  205. }
  206. }
  207. ehdr_ = reinterpret_cast<const ElfW(Ehdr) *>(base);
  208. const ElfW(Phdr) *dynamic_program_header = NULL;
  209. for (int i = 0; i < ehdr_->e_phnum; ++i) {
  210. const ElfW(Phdr) *const program_header = GetPhdr(i);
  211. switch (program_header->p_type) {
  212. case PT_LOAD:
  213. if (link_base_ == ~0L) {
  214. link_base_ = program_header->p_vaddr;
  215. }
  216. break;
  217. case PT_DYNAMIC:
  218. dynamic_program_header = program_header;
  219. break;
  220. }
  221. }
  222. if (link_base_ == ~0L || !dynamic_program_header) {
  223. RAW_DCHECK(~0L != link_base_, "no PT_LOADs in VDSO");
  224. RAW_DCHECK(dynamic_program_header, "no PT_DYNAMIC in VDSO");
  225. // Mark this image as not present. Can not recur infinitely.
  226. Init(0);
  227. return;
  228. }
  229. ptrdiff_t relocation =
  230. base_as_char - reinterpret_cast<const char *>(link_base_);
  231. ElfW(Dyn) *dynamic_entry =
  232. reinterpret_cast<ElfW(Dyn) *>(dynamic_program_header->p_vaddr +
  233. relocation);
  234. for (; dynamic_entry->d_tag != DT_NULL; ++dynamic_entry) {
  235. ElfW(Xword) value = dynamic_entry->d_un.d_val;
  236. if (fake_vdso) {
  237. // A complication: in the real VDSO, dynamic entries are not relocated
  238. // (it wasn't loaded by a dynamic loader). But when testing with a
  239. // "fake" dlopen()ed vdso library, the loader relocates some (but
  240. // not all!) of them before we get here.
  241. if (dynamic_entry->d_tag == DT_VERDEF) {
  242. // The only dynamic entry (of the ones we care about) libc-2.3.6
  243. // loader doesn't relocate.
  244. value += relocation;
  245. }
  246. } else {
  247. // Real VDSO. Everything needs to be relocated.
  248. value += relocation;
  249. }
  250. switch (dynamic_entry->d_tag) {
  251. case DT_HASH:
  252. hash_ = reinterpret_cast<ElfW(Word) *>(value);
  253. break;
  254. case DT_SYMTAB:
  255. dynsym_ = reinterpret_cast<ElfW(Sym) *>(value);
  256. break;
  257. case DT_STRTAB:
  258. dynstr_ = reinterpret_cast<const char *>(value);
  259. break;
  260. case DT_VERSYM:
  261. versym_ = reinterpret_cast<ElfW(Versym) *>(value);
  262. break;
  263. case DT_VERDEF:
  264. verdef_ = reinterpret_cast<ElfW(Verdef) *>(value);
  265. break;
  266. case DT_VERDEFNUM:
  267. verdefnum_ = dynamic_entry->d_un.d_val;
  268. break;
  269. case DT_STRSZ:
  270. strsize_ = dynamic_entry->d_un.d_val;
  271. break;
  272. default:
  273. // Unrecognized entries explicitly ignored.
  274. break;
  275. }
  276. }
  277. if (!hash_ || !dynsym_ || !dynstr_ || !versym_ ||
  278. !verdef_ || !verdefnum_ || !strsize_) {
  279. RAW_DCHECK(hash_, "invalid VDSO (no DT_HASH)");
  280. RAW_DCHECK(dynsym_, "invalid VDSO (no DT_SYMTAB)");
  281. RAW_DCHECK(dynstr_, "invalid VDSO (no DT_STRTAB)");
  282. RAW_DCHECK(versym_, "invalid VDSO (no DT_VERSYM)");
  283. RAW_DCHECK(verdef_, "invalid VDSO (no DT_VERDEF)");
  284. RAW_DCHECK(verdefnum_, "invalid VDSO (no DT_VERDEFNUM)");
  285. RAW_DCHECK(strsize_, "invalid VDSO (no DT_STRSZ)");
  286. // Mark this image as not present. Can not recur infinitely.
  287. Init(0);
  288. return;
  289. }
  290. }
  291. bool ElfMemImage::LookupSymbol(const char *name,
  292. const char *version,
  293. int type,
  294. SymbolInfo *info) const {
  295. for (SymbolIterator it = begin(); it != end(); ++it) {
  296. if (strcmp(it->name, name) == 0 && strcmp(it->version, version) == 0 &&
  297. CurrentElfClass::ElfType(it->symbol) == type) {
  298. if (info) {
  299. *info = *it;
  300. }
  301. return true;
  302. }
  303. }
  304. return false;
  305. }
  306. bool ElfMemImage::LookupSymbolByAddress(const void *address,
  307. SymbolInfo *info_out) const {
  308. for (SymbolIterator it = begin(); it != end(); ++it) {
  309. const char *const symbol_start =
  310. reinterpret_cast<const char *>(it->address);
  311. const char *const symbol_end = symbol_start + it->symbol->st_size;
  312. if (symbol_start <= address && address < symbol_end) {
  313. if (info_out) {
  314. // Client wants to know details for that symbol (the usual case).
  315. if (CurrentElfClass::ElfBind(it->symbol) == STB_GLOBAL) {
  316. // Strong symbol; just return it.
  317. *info_out = *it;
  318. return true;
  319. } else {
  320. // Weak or local. Record it, but keep looking for a strong one.
  321. *info_out = *it;
  322. }
  323. } else {
  324. // Client only cares if there is an overlapping symbol.
  325. return true;
  326. }
  327. }
  328. }
  329. return false;
  330. }
  331. ElfMemImage::SymbolIterator::SymbolIterator(const void *const image, int index)
  332. : index_(index), image_(image) {
  333. }
  334. const ElfMemImage::SymbolInfo *ElfMemImage::SymbolIterator::operator->() const {
  335. return &info_;
  336. }
  337. const ElfMemImage::SymbolInfo& ElfMemImage::SymbolIterator::operator*() const {
  338. return info_;
  339. }
  340. bool ElfMemImage::SymbolIterator::operator==(const SymbolIterator &rhs) const {
  341. return this->image_ == rhs.image_ && this->index_ == rhs.index_;
  342. }
  343. bool ElfMemImage::SymbolIterator::operator!=(const SymbolIterator &rhs) const {
  344. return !(*this == rhs);
  345. }
  346. ElfMemImage::SymbolIterator &ElfMemImage::SymbolIterator::operator++() {
  347. this->Update(1);
  348. return *this;
  349. }
  350. ElfMemImage::SymbolIterator ElfMemImage::begin() const {
  351. SymbolIterator it(this, 0);
  352. it.Update(0);
  353. return it;
  354. }
  355. ElfMemImage::SymbolIterator ElfMemImage::end() const {
  356. return SymbolIterator(this, GetNumSymbols());
  357. }
  358. void ElfMemImage::SymbolIterator::Update(int increment) {
  359. const ElfMemImage *image = reinterpret_cast<const ElfMemImage *>(image_);
  360. CHECK(image->IsPresent() || increment == 0);
  361. if (!image->IsPresent()) {
  362. return;
  363. }
  364. index_ += increment;
  365. if (index_ >= image->GetNumSymbols()) {
  366. index_ = image->GetNumSymbols();
  367. return;
  368. }
  369. const ElfW(Sym) *symbol = image->GetDynsym(index_);
  370. const ElfW(Versym) *version_symbol = image->GetVersym(index_);
  371. CHECK(symbol && version_symbol);
  372. const char *const symbol_name = image->GetDynstr(symbol->st_name);
  373. const ElfW(Versym) version_index = version_symbol[0] & VERSYM_VERSION;
  374. const ElfW(Verdef) *version_definition = NULL;
  375. const char *version_name = "";
  376. if (symbol->st_shndx == SHN_UNDEF) {
  377. // Undefined symbols reference DT_VERNEED, not DT_VERDEF, and
  378. // version_index could well be greater than verdefnum_, so calling
  379. // GetVerdef(version_index) may trigger assertion.
  380. } else {
  381. version_definition = image->GetVerdef(version_index);
  382. }
  383. if (version_definition) {
  384. // I am expecting 1 or 2 auxiliary entries: 1 for the version itself,
  385. // optional 2nd if the version has a parent.
  386. CHECK_LE(1, version_definition->vd_cnt);
  387. CHECK_LE(version_definition->vd_cnt, 2);
  388. const ElfW(Verdaux) *version_aux = image->GetVerdefAux(version_definition);
  389. version_name = image->GetVerstr(version_aux->vda_name);
  390. }
  391. info_.name = symbol_name;
  392. info_.version = version_name;
  393. info_.address = image->GetSymAddr(symbol);
  394. info_.symbol = symbol;
  395. }
  396. } // namespace base
  397. #endif // HAVE_ELF_MEM_IMAGE