2 * Copyright 2014 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #ifndef FOLLY_SYMBOLIZER_ELFCACHE_H_
18 #define FOLLY_SYMBOLIZER_ELFCACHE_H_
21 #include <limits.h> // for PATH_MAX
26 #include <unordered_map>
28 #include <boost/operators.hpp>
29 #include <boost/container/flat_map.hpp>
30 #include <boost/intrusive/list.hpp>
31 #include <glog/logging.h>
33 #include "folly/experimental/symbolizer/Elf.h"
35 namespace folly { namespace symbolizer {
39 virtual std::shared_ptr<ElfFile> getFile(StringPiece path) = 0;
40 virtual ~ElfCacheBase() { }
44 * Cache ELF files. Async-signal-safe: does memory allocation upfront.
46 * Will not grow; once the capacity is reached, lookups for files that
47 * aren't already in the cache will fail (return nullptr).
49 * Not MT-safe. May not be used concurrently from multiple threads.
51 * NOTE that async-signal-safety is preserved only as long as the
52 * SignalSafeElfCache object exists; after the SignalSafeElfCache object
53 * is destroyed, destroying returned shared_ptr<ElfFile> objects may
54 * cause ElfFile objects to be destroyed, and that's not async-signal-safe.
56 class SignalSafeElfCache : public ElfCacheBase {
58 explicit SignalSafeElfCache(size_t capacity);
60 std::shared_ptr<ElfFile> getFile(StringPiece path) override;
63 // We can't use std::string (allocating memory is bad!) so we roll our
64 // own wrapper around a fixed-size, null-terminated string.
65 class Path : private boost::totally_ordered<Path> {
67 explicit Path(StringPiece s) {
68 DCHECK_LE(s.size(), kMaxSize);
69 memcpy(data_, s.data(), s.size());
70 data_[s.size()] = '\0';
73 bool operator<(const Path& other) const {
74 return strcmp(data_, other.data_) < 0;
77 bool operator==(const Path& other) const {
78 return strcmp(data_, other.data_) == 0;
81 const char* data() const {
85 static constexpr size_t kMaxSize = PATH_MAX - 1;
88 char data_[kMaxSize + 1];
91 boost::container::flat_map<Path, int> map_;
92 std::vector<std::shared_ptr<ElfFile>> slots_;
96 * General-purpose ELF file cache.
98 * LRU of given capacity. MT-safe (uses locking). Not async-signal-safe.
100 class ElfCache : public ElfCacheBase {
102 explicit ElfCache(size_t capacity);
104 std::shared_ptr<ElfFile> getFile(StringPiece path) override;
109 typedef boost::intrusive::list_member_hook<> LruLink;
115 static std::shared_ptr<ElfFile> filePtr(const std::shared_ptr<Entry>& e);
118 std::unordered_map<std::string, std::shared_ptr<Entry>> files_;
120 typedef boost::intrusive::list<
122 boost::intrusive::member_hook<Entry, LruLink, &Entry::lruLink>,
123 boost::intrusive::constant_time_size<false>> LruList;
129 #endif /* FOLLY_SYMBOLIZER_ELFCACHE_H_ */