15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2008, Google Inc. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met: 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Redistributions of source code must retain the above copyright 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Redistributions in binary form must reproduce the above 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Neither the name of Google Inc. nor the names of its 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --- 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Paul Pluzhnikov 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Allow dynamic symbol lookup in an in-memory Elf image. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/elf_mem_image.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_ELF_MEM_IMAGE // defined in elf_mem_image.h 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stddef.h> // for size_t, ptrdiff_t 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// From binutils/include/elf/common.h (this doesn't appear to be documented 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// anywhere else). 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// /* This flag appears in a Versym structure. It means that the symbol 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is hidden, and is only visible with an explicit version number. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is a GNU extension. */ 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// #define VERSYM_HIDDEN 0x8000 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// /* This is the mask for the rest of the Versym information. */ 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// #define VERSYM_VERSION 0x7fff 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VERSYM_VERSION 0x7fff 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <int N> class ElfClass { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kElfClass = -1; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int ElfBind(const ElfW(Sym) *) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(false); // << "Unexpected word size"; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int ElfType(const ElfW(Sym) *) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(false); // << "Unexpected word size"; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <> class ElfClass<32> { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kElfClass = ELFCLASS32; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int ElfBind(const ElfW(Sym) *symbol) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ELF32_ST_BIND(symbol->st_info); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int ElfType(const ElfW(Sym) *symbol) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ELF32_ST_TYPE(symbol->st_info); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <> class ElfClass<64> { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kElfClass = ELFCLASS64; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int ElfBind(const ElfW(Sym) *symbol) { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ELF64_ST_BIND(symbol->st_info); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int ElfType(const ElfW(Sym) *symbol) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ELF64_ST_TYPE(symbol->st_info); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef ElfClass<__WORDSIZE> CurrentElfClass; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Extract an element from one of the ELF tables, cast it to desired type. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is just a simple arithmetic and a glorified cast. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Callers are responsible for bounds checking. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T> 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const T* GetTableElement(const ElfW(Ehdr) *ehdr, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ElfW(Off) table_offset, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ElfW(Word) element_size, 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t index) { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<const T*>(reinterpret_cast<const char *>(ehdr) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) + table_offset 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) + index * element_size); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const void *const ElfMemImage::kInvalidBase = 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const void *>(~0L); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ElfMemImage::ElfMemImage(const void *base) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(base != kInvalidBase); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Init(base); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ElfMemImage::GetNumSymbols() const { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!hash_) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See http://www.caldera.com/developers/gabi/latest/ch5.dynamic.html#hash 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hash_[1]; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ElfW(Sym) *ElfMemImage::GetDynsym(int index) const { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LT(index, GetNumSymbols()); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dynsym_ + index; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ElfW(Versym) *ElfMemImage::GetVersym(int index) const { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LT(index, GetNumSymbols()); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return versym_ + index; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ElfW(Phdr) *ElfMemImage::GetPhdr(int index) const { 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LT(index, ehdr_->e_phnum); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetTableElement<ElfW(Phdr)>(ehdr_, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ehdr_->e_phoff, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ehdr_->e_phentsize, 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char *ElfMemImage::GetDynstr(ElfW(Word) offset) const { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LT(offset, strsize_); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dynstr_ + offset; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const void *ElfMemImage::GetSymAddr(const ElfW(Sym) *sym) const { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sym->st_shndx == SHN_UNDEF || sym->st_shndx >= SHN_LORESERVE) { 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Symbol corresponds to "special" (e.g. SHN_ABS) section. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<const void *>(sym->st_value); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LT(link_base_, sym->st_value); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetTableElement<char>(ehdr_, 0, 1, sym->st_value) - link_base_; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ElfW(Verdef) *ElfMemImage::GetVerdef(int index) const { 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LE(index, verdefnum_); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ElfW(Verdef) *version_definition = verdef_; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (version_definition->vd_ndx < index && version_definition->vd_next) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *const version_definition_as_char = 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char *>(version_definition); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_definition = 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const ElfW(Verdef) *>(version_definition_as_char + 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_definition->vd_next); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return version_definition->vd_ndx == index ? version_definition : NULL; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ElfW(Verdaux) *ElfMemImage::GetVerdefAux( 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ElfW(Verdef) *verdef) const { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<const ElfW(Verdaux) *>(verdef+1); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char *ElfMemImage::GetVerstr(ElfW(Word) offset) const { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LT(offset, strsize_); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dynstr_ + offset; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ElfMemImage::Init(const void *base) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ehdr_ = NULL; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dynsym_ = NULL; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dynstr_ = NULL; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) versym_ = NULL; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verdef_ = NULL; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hash_ = NULL; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strsize_ = 0; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verdefnum_ = 0; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) link_base_ = ~0L; // Sentinel: PT_LOAD .p_vaddr can't possibly be this. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base) { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const intptr_t base_as_uintptr_t = reinterpret_cast<uintptr_t>(base); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fake VDSO has low bit set. 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool fake_vdso = ((base_as_uintptr_t & 1) != 0); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base = reinterpret_cast<const void *>(base_as_uintptr_t & ~1); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *const base_as_char = reinterpret_cast<const char *>(base); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (base_as_char[EI_MAG0] != ELFMAG0 || base_as_char[EI_MAG1] != ELFMAG1 || 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base_as_char[EI_MAG2] != ELFMAG2 || base_as_char[EI_MAG3] != ELFMAG3) { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(false, "no ELF magic"); // at %p", base); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int elf_class = base_as_char[EI_CLASS]; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (elf_class != CurrentElfClass::kElfClass) { 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(elf_class, CurrentElfClass::kElfClass); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (base_as_char[EI_DATA]) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ELFDATA2LSB: { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (__LITTLE_ENDIAN != __BYTE_ORDER) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(__LITTLE_ENDIAN, __BYTE_ORDER); // << ": wrong byte order"; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case ELFDATA2MSB: { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (__BIG_ENDIAN != __BYTE_ORDER) { 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(__BIG_ENDIAN, __BYTE_ORDER); // << ": wrong byte order"; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(false, "unexpected data encoding"); // << base_as_char[EI_DATA]; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ehdr_ = reinterpret_cast<const ElfW(Ehdr) *>(base); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ElfW(Phdr) *dynamic_program_header = NULL; 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < ehdr_->e_phnum; ++i) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ElfW(Phdr) *const program_header = GetPhdr(i); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (program_header->p_type) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PT_LOAD: 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (link_base_ == ~0L) { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) link_base_ = program_header->p_vaddr; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PT_DYNAMIC: 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dynamic_program_header = program_header; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (link_base_ == ~0L || !dynamic_program_header) { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(~0L != link_base_, "no PT_LOADs in VDSO"); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(dynamic_program_header, "no PT_DYNAMIC in VDSO"); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mark this image as not present. Can not recur infinitely. 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Init(0); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptrdiff_t relocation = 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base_as_char - reinterpret_cast<const char *>(link_base_); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ElfW(Dyn) *dynamic_entry = 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<ElfW(Dyn) *>(dynamic_program_header->p_vaddr + 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) relocation); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; dynamic_entry->d_tag != DT_NULL; ++dynamic_entry) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ElfW(Xword) value = dynamic_entry->d_un.d_val; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fake_vdso) { 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A complication: in the real VDSO, dynamic entries are not relocated 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (it wasn't loaded by a dynamic loader). But when testing with a 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "fake" dlopen()ed vdso library, the loader relocates some (but 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not all!) of them before we get here. 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dynamic_entry->d_tag == DT_VERDEF) { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The only dynamic entry (of the ones we care about) libc-2.3.6 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // loader doesn't relocate. 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value += relocation; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Real VDSO. Everything needs to be relocated. 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value += relocation; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (dynamic_entry->d_tag) { 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DT_HASH: 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hash_ = reinterpret_cast<ElfW(Word) *>(value); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DT_SYMTAB: 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dynsym_ = reinterpret_cast<ElfW(Sym) *>(value); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DT_STRTAB: 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dynstr_ = reinterpret_cast<const char *>(value); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DT_VERSYM: 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) versym_ = reinterpret_cast<ElfW(Versym) *>(value); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DT_VERDEF: 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verdef_ = reinterpret_cast<ElfW(Verdef) *>(value); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DT_VERDEFNUM: 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verdefnum_ = dynamic_entry->d_un.d_val; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DT_STRSZ: 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strsize_ = dynamic_entry->d_un.d_val; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unrecognized entries explicitly ignored. 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!hash_ || !dynsym_ || !dynstr_ || !versym_ || 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !verdef_ || !verdefnum_ || !strsize_) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(hash_, "invalid VDSO (no DT_HASH)"); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(dynsym_, "invalid VDSO (no DT_SYMTAB)"); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(dynstr_, "invalid VDSO (no DT_STRTAB)"); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(versym_, "invalid VDSO (no DT_VERSYM)"); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(verdef_, "invalid VDSO (no DT_VERDEF)"); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(verdefnum_, "invalid VDSO (no DT_VERDEFNUM)"); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(strsize_, "invalid VDSO (no DT_STRSZ)"); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mark this image as not present. Can not recur infinitely. 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Init(0); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ElfMemImage::LookupSymbol(const char *name, 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *version, 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SymbolInfo *info) const { 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (SymbolIterator it = begin(); it != end(); ++it) { 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strcmp(it->name, name) == 0 && strcmp(it->version, version) == 0 && 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CurrentElfClass::ElfType(it->symbol) == type) { 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (info) { 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *info = *it; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ElfMemImage::LookupSymbolByAddress(const void *address, 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SymbolInfo *info_out) const { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (SymbolIterator it = begin(); it != end(); ++it) { 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *const symbol_start = 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char *>(it->address); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *const symbol_end = symbol_start + it->symbol->st_size; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (symbol_start <= address && address < symbol_end) { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (info_out) { 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Client wants to know details for that symbol (the usual case). 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CurrentElfClass::ElfBind(it->symbol) == STB_GLOBAL) { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Strong symbol; just return it. 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *info_out = *it; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Weak or local. Record it, but keep looking for a strong one. 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *info_out = *it; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Client only cares if there is an overlapping symbol. 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ElfMemImage::SymbolIterator::SymbolIterator(const void *const image, int index) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : index_(index), image_(image) { 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ElfMemImage::SymbolInfo *ElfMemImage::SymbolIterator::operator->() const { 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &info_; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const ElfMemImage::SymbolInfo& ElfMemImage::SymbolIterator::operator*() const { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return info_; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ElfMemImage::SymbolIterator::operator==(const SymbolIterator &rhs) const { 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this->image_ == rhs.image_ && this->index_ == rhs.index_; 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ElfMemImage::SymbolIterator::operator!=(const SymbolIterator &rhs) const { 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !(*this == rhs); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ElfMemImage::SymbolIterator &ElfMemImage::SymbolIterator::operator++() { 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this->Update(1); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *this; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ElfMemImage::SymbolIterator ElfMemImage::begin() const { 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SymbolIterator it(this, 0); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it.Update(0); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return it; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ElfMemImage::SymbolIterator ElfMemImage::end() const { 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SymbolIterator(this, GetNumSymbols()); 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ElfMemImage::SymbolIterator::Update(int increment) { 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ElfMemImage *image = reinterpret_cast<const ElfMemImage *>(image_); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(image->IsPresent() || increment == 0); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!image->IsPresent()) { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index_ += increment; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index_ >= image->GetNumSymbols()) { 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index_ = image->GetNumSymbols(); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ElfW(Sym) *symbol = image->GetDynsym(index_); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ElfW(Versym) *version_symbol = image->GetVersym(index_); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(symbol && version_symbol); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *const symbol_name = image->GetDynstr(symbol->st_name); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ElfW(Versym) version_index = version_symbol[0] & VERSYM_VERSION; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ElfW(Verdef) *version_definition = NULL; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *version_name = ""; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (symbol->st_shndx == SHN_UNDEF) { 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Undefined symbols reference DT_VERNEED, not DT_VERDEF, and 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // version_index could well be greater than verdefnum_, so calling 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // GetVerdef(version_index) may trigger assertion. 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_definition = image->GetVerdef(version_index); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (version_definition) { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // I am expecting 1 or 2 auxiliary entries: 1 for the version itself, 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // optional 2nd if the version has a parent. 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LE(1, version_definition->vd_cnt); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_LE(version_definition->vd_cnt, 2); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ElfW(Verdaux) *version_aux = image->GetVerdefAux(version_definition); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) version_name = image->GetVerstr(version_aux->vda_name); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info_.name = symbol_name; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info_.version = version_name; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info_.address = image->GetSymAddr(symbol); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info_.symbol = symbol; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // HAVE_ELF_MEM_IMAGE 434