blob: 46bfade3503ebcfd4c109c25613011671f6905f2 [file] [log] [blame]
Austin Schuh36244a12019-09-21 17:52:38 -07001/*
2 * Copyright 2017 The Abseil Authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// Allow dynamic symbol lookup for in-memory Elf images.
18
19#ifndef ABSL_DEBUGGING_INTERNAL_ELF_MEM_IMAGE_H_
20#define ABSL_DEBUGGING_INTERNAL_ELF_MEM_IMAGE_H_
21
22// Including this will define the __GLIBC__ macro if glibc is being
23// used.
24#include <climits>
25
Austin Schuhb4691e92020-12-31 12:37:18 -080026#include "absl/base/config.h"
27
Austin Schuh36244a12019-09-21 17:52:38 -070028// Maybe one day we can rewrite this file not to require the elf
29// symbol extensions in glibc, but for right now we need them.
30#ifdef ABSL_HAVE_ELF_MEM_IMAGE
31#error ABSL_HAVE_ELF_MEM_IMAGE cannot be directly set
32#endif
33
34#if defined(__ELF__) && defined(__GLIBC__) && !defined(__native_client__) && \
35 !defined(__asmjs__) && !defined(__wasm__)
36#define ABSL_HAVE_ELF_MEM_IMAGE 1
37#endif
38
39#ifdef ABSL_HAVE_ELF_MEM_IMAGE
40
41#include <link.h> // for ElfW
42
43namespace absl {
Austin Schuhb4691e92020-12-31 12:37:18 -080044ABSL_NAMESPACE_BEGIN
Austin Schuh36244a12019-09-21 17:52:38 -070045namespace debugging_internal {
46
47// An in-memory ELF image (may not exist on disk).
48class ElfMemImage {
49 private:
50 // Sentinel: there could never be an elf image at &kInvalidBaseSentinel.
51 static const int kInvalidBaseSentinel;
52
53 public:
54 // Sentinel: there could never be an elf image at this address.
55 static constexpr const void *const kInvalidBase =
56 static_cast<const void*>(&kInvalidBaseSentinel);
57
58 // Information about a single vdso symbol.
59 // All pointers are into .dynsym, .dynstr, or .text of the VDSO.
60 // Do not free() them or modify through them.
61 struct SymbolInfo {
62 const char *name; // E.g. "__vdso_getcpu"
63 const char *version; // E.g. "LINUX_2.6", could be ""
64 // for unversioned symbol.
65 const void *address; // Relocated symbol address.
66 const ElfW(Sym) *symbol; // Symbol in the dynamic symbol table.
67 };
68
69 // Supports iteration over all dynamic symbols.
70 class SymbolIterator {
71 public:
72 friend class ElfMemImage;
73 const SymbolInfo *operator->() const;
74 const SymbolInfo &operator*() const;
75 SymbolIterator& operator++();
76 bool operator!=(const SymbolIterator &rhs) const;
77 bool operator==(const SymbolIterator &rhs) const;
78 private:
79 SymbolIterator(const void *const image, int index);
80 void Update(int incr);
81 SymbolInfo info_;
82 int index_;
83 const void *const image_;
84 };
85
86
87 explicit ElfMemImage(const void *base);
88 void Init(const void *base);
89 bool IsPresent() const { return ehdr_ != nullptr; }
90 const ElfW(Phdr)* GetPhdr(int index) const;
91 const ElfW(Sym)* GetDynsym(int index) const;
92 const ElfW(Versym)* GetVersym(int index) const;
93 const ElfW(Verdef)* GetVerdef(int index) const;
94 const ElfW(Verdaux)* GetVerdefAux(const ElfW(Verdef) *verdef) const;
95 const char* GetDynstr(ElfW(Word) offset) const;
96 const void* GetSymAddr(const ElfW(Sym) *sym) const;
97 const char* GetVerstr(ElfW(Word) offset) const;
98 int GetNumSymbols() const;
99
100 SymbolIterator begin() const;
101 SymbolIterator end() const;
102
103 // Look up versioned dynamic symbol in the image.
104 // Returns false if image is not present, or doesn't contain given
105 // symbol/version/type combination.
106 // If info_out is non-null, additional details are filled in.
107 bool LookupSymbol(const char *name, const char *version,
108 int symbol_type, SymbolInfo *info_out) const;
109
110 // Find info about symbol (if any) which overlaps given address.
111 // Returns true if symbol was found; false if image isn't present
112 // or doesn't have a symbol overlapping given address.
113 // If info_out is non-null, additional details are filled in.
114 bool LookupSymbolByAddress(const void *address, SymbolInfo *info_out) const;
115
116 private:
117 const ElfW(Ehdr) *ehdr_;
118 const ElfW(Sym) *dynsym_;
119 const ElfW(Versym) *versym_;
120 const ElfW(Verdef) *verdef_;
121 const ElfW(Word) *hash_;
122 const char *dynstr_;
123 size_t strsize_;
124 size_t verdefnum_;
125 ElfW(Addr) link_base_; // Link-time base (p_vaddr of first PT_LOAD).
126};
127
128} // namespace debugging_internal
Austin Schuhb4691e92020-12-31 12:37:18 -0800129ABSL_NAMESPACE_END
Austin Schuh36244a12019-09-21 17:52:38 -0700130} // namespace absl
131
132#endif // ABSL_HAVE_ELF_MEM_IMAGE
133
134#endif // ABSL_DEBUGGING_INTERNAL_ELF_MEM_IMAGE_H_