Coverage Report

Created: 2026-10-28 06:49

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
#if __has_include(<link.h>)
46
#include <link.h>  // for ElfW
47
#else
48
#include <elf.h>
49
#endif
50
51
#ifndef ElfW
52
#if defined(__FreeBSD__)
53
#define ElfW(type) __ElfN(type)
54
#elif __SIZEOF_POINTER__ == 8
55
#define ElfW(type) Elf64_##type
56
#else
57
#define ElfW(type) Elf32_##type
58
#endif
59
#endif
60
61
namespace absl {
62
ABSL_NAMESPACE_BEGIN
63
namespace debugging_internal {
64
65
// An in-memory ELF image (may not exist on disk).
66
class ElfMemImage {
67
 private:
68
  // Sentinel: there could never be an elf image at &kInvalidBaseSentinel.
69
  static const int kInvalidBaseSentinel;
70
71
 public:
72
  // Sentinel: there could never be an elf image at this address.
73
  static constexpr const void *const kInvalidBase =
74
    static_cast<const void*>(&kInvalidBaseSentinel);
75
76
  // Information about a single vdso symbol.
77
  // All pointers are into .dynsym, .dynstr, or .text of the VDSO.
78
  // Do not free() them or modify through them.
79
  struct SymbolInfo {
80
    const char      *name;      // E.g. "__vdso_getcpu"
81
    const char      *version;   // E.g. "LINUX_2.6", could be ""
82
                                // for unversioned symbol.
83
    const void      *address;   // Relocated symbol address.
84
    const ElfW(Sym) *symbol;    // Symbol in the dynamic symbol table.
85
  };
86
87
  // Supports iteration over all dynamic symbols.
88
  class SymbolIterator {
89
   public:
90
    friend class ElfMemImage;
91
    const SymbolInfo *operator->() const;
92
    const SymbolInfo &operator*() const;
93
    SymbolIterator& operator++();
94
    bool operator!=(const SymbolIterator &rhs) const;
95
    bool operator==(const SymbolIterator &rhs) const;
96
   private:
97
    SymbolIterator(const void *const image, uint32_t index);
98
    void Update(uint32_t incr);
99
    SymbolInfo info_;
100
    uint32_t index_;
101
    const void *const image_;
102
  };
103
104
105
  explicit ElfMemImage(const void *base);
106
  void                 Init(const void *base);
107
0
  bool                 IsPresent() const { return ehdr_ != nullptr; }
108
  const ElfW(Phdr)*    GetPhdr(int index) const;
109
  const ElfW(Sym) * GetDynsym(uint32_t index) const;
110
  const ElfW(Versym)*  GetVersym(uint32_t index) const;
111
  const ElfW(Verdef)*  GetVerdef(int index) const;
112
  const ElfW(Verdaux)* GetVerdefAux(const ElfW(Verdef) *verdef) const;
113
  const char*          GetDynstr(ElfW(Word) offset) const;
114
  const void*          GetSymAddr(const ElfW(Sym) *sym) const;
115
  const char*          GetVerstr(ElfW(Word) offset) const;
116
  uint32_t GetNumSymbols() const;
117
118
  SymbolIterator begin() const;
119
  SymbolIterator end() const;
120
121
  // Look up versioned dynamic symbol in the image.
122
  // Returns false if image is not present, or doesn't contain given
123
  // symbol/version/type combination.
124
  // If info_out is non-null, additional details are filled in.
125
  bool LookupSymbol(const char *name, const char *version,
126
                    int symbol_type, SymbolInfo *info_out) const;
127
128
  // Find info about symbol (if any) which overlaps given address.
129
  // Returns true if symbol was found; false if image isn't present
130
  // or doesn't have a symbol overlapping given address.
131
  // If info_out is non-null, additional details are filled in.
132
  bool LookupSymbolByAddress(const void *address, SymbolInfo *info_out) const;
133
134
 private:
135
  const ElfW(Ehdr) *ehdr_;
136
  const ElfW(Sym) *dynsym_;
137
  const ElfW(Versym) *versym_;
138
  const ElfW(Verdef) *verdef_;
139
  const char *dynstr_;
140
  uint32_t num_syms_;
141
  size_t strsize_;
142
  size_t verdefnum_;
143
  ElfW(Addr) link_base_;     // Link-time base (p_vaddr of first PT_LOAD).
144
};
145
146
}  // namespace debugging_internal
147
ABSL_NAMESPACE_END
148
}  // namespace absl
149
150
#endif  // ABSL_HAVE_ELF_MEM_IMAGE
151
152
#endif  // ABSL_DEBUGGING_INTERNAL_ELF_MEM_IMAGE_H_