Coverage Report

Created: 2024-09-23 06:29

/src/abseil-cpp/absl/debugging/internal/elf_mem_image.h
Line
Count
Source (jump to first uncovered line)
1
/*
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
#include <cstdint>
26
27
#include "absl/base/config.h"
28
29
// Maybe one day we can rewrite this file not to require the elf
30
// symbol extensions in glibc, but for right now we need them.
31
#ifdef ABSL_HAVE_ELF_MEM_IMAGE
32
#error ABSL_HAVE_ELF_MEM_IMAGE cannot be directly set
33
#endif
34
35
#if defined(__ELF__) && !defined(__OpenBSD__) && !defined(__QNX__) && \
36
    !defined(__native_client__) && !defined(__asmjs__) &&             \
37
    !defined(__wasm__) && !defined(__HAIKU__) && !defined(__sun) &&   \
38
    !defined(__VXWORKS__) && !defined(__hexagon__)
39
#define ABSL_HAVE_ELF_MEM_IMAGE 1
40
#endif
41
42
#ifdef ABSL_HAVE_ELF_MEM_IMAGE
43
44
#include <link.h>  // for ElfW
45
46
#if defined(__FreeBSD__) && !defined(ElfW)
47
#define ElfW(x) __ElfN(x)
48
#endif
49
50
namespace absl {
51
ABSL_NAMESPACE_BEGIN
52
namespace debugging_internal {
53
54
// An in-memory ELF image (may not exist on disk).
55
class ElfMemImage {
56
 private:
57
  // Sentinel: there could never be an elf image at &kInvalidBaseSentinel.
58
  static const int kInvalidBaseSentinel;
59
60
 public:
61
  // Sentinel: there could never be an elf image at this address.
62
  static constexpr const void *const kInvalidBase =
63
    static_cast<const void*>(&kInvalidBaseSentinel);
64
65
  // Information about a single vdso symbol.
66
  // All pointers are into .dynsym, .dynstr, or .text of the VDSO.
67
  // Do not free() them or modify through them.
68
  struct SymbolInfo {
69
    const char      *name;      // E.g. "__vdso_getcpu"
70
    const char      *version;   // E.g. "LINUX_2.6", could be ""
71
                                // for unversioned symbol.
72
    const void      *address;   // Relocated symbol address.
73
    const ElfW(Sym) *symbol;    // Symbol in the dynamic symbol table.
74
  };
75
76
  // Supports iteration over all dynamic symbols.
77
  class SymbolIterator {
78
   public:
79
    friend class ElfMemImage;
80
    const SymbolInfo *operator->() const;
81
    const SymbolInfo &operator*() const;
82
    SymbolIterator& operator++();
83
    bool operator!=(const SymbolIterator &rhs) const;
84
    bool operator==(const SymbolIterator &rhs) const;
85
   private:
86
    SymbolIterator(const void *const image, uint32_t index);
87
    void Update(uint32_t incr);
88
    SymbolInfo info_;
89
    uint32_t index_;
90
    const void *const image_;
91
  };
92
93
94
  explicit ElfMemImage(const void *base);
95
  void                 Init(const void *base);
96
0
  bool                 IsPresent() const { return ehdr_ != nullptr; }
97
  const ElfW(Phdr)*    GetPhdr(int index) const;
98
  const ElfW(Sym) * GetDynsym(uint32_t index) const;
99
  const ElfW(Versym)*  GetVersym(uint32_t index) const;
100
  const ElfW(Verdef)*  GetVerdef(int index) const;
101
  const ElfW(Verdaux)* GetVerdefAux(const ElfW(Verdef) *verdef) const;
102
  const char*          GetDynstr(ElfW(Word) offset) const;
103
  const void*          GetSymAddr(const ElfW(Sym) *sym) const;
104
  const char*          GetVerstr(ElfW(Word) offset) const;
105
  uint32_t GetNumSymbols() const;
106
107
  SymbolIterator begin() const;
108
  SymbolIterator end() const;
109
110
  // Look up versioned dynamic symbol in the image.
111
  // Returns false if image is not present, or doesn't contain given
112
  // symbol/version/type combination.
113
  // If info_out is non-null, additional details are filled in.
114
  bool LookupSymbol(const char *name, const char *version,
115
                    int symbol_type, SymbolInfo *info_out) const;
116
117
  // Find info about symbol (if any) which overlaps given address.
118
  // Returns true if symbol was found; false if image isn't present
119
  // or doesn't have a symbol overlapping given address.
120
  // If info_out is non-null, additional details are filled in.
121
  bool LookupSymbolByAddress(const void *address, SymbolInfo *info_out) const;
122
123
 private:
124
  const ElfW(Ehdr) *ehdr_;
125
  const ElfW(Sym) *dynsym_;
126
  const ElfW(Versym) *versym_;
127
  const ElfW(Verdef) *verdef_;
128
  const char *dynstr_;
129
  uint32_t num_syms_;
130
  size_t strsize_;
131
  size_t verdefnum_;
132
  ElfW(Addr) link_base_;     // Link-time base (p_vaddr of first PT_LOAD).
133
};
134
135
}  // namespace debugging_internal
136
ABSL_NAMESPACE_END
137
}  // namespace absl
138
139
#endif  // ABSL_HAVE_ELF_MEM_IMAGE
140
141
#endif  // ABSL_DEBUGGING_INTERNAL_ELF_MEM_IMAGE_H_