Coverage Report

Created: 2026-09-14 06:45

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