blob: 04642c55de5e46d9ebf6a51ad17a95c2e6746ff3 [file] [log] [blame]
// Copyright 2026 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/lib/unwinder/elf_module_cache.h"
#include <cinttypes>
#include "src/lib/unwinder/loaded_elf_module.h"
namespace unwinder {
ElfModuleCache::ElfModuleCache(std::span<const Module> modules) {
for (const auto& module : modules) {
module_map_.emplace(module.load_address, std::make_unique<LoadedElfModule>(module));
}
}
fit::result<Error, ElfModuleCache::LoadedElfModuleRef> ElfModuleCache::GetLoadedElfModuleForPc(
uint64_t pc) const {
if (module_map_.empty()) {
return fit::error(Error("No modules."));
}
auto it = module_map_.upper_bound(pc);
if (it == module_map_.begin()) {
return fit::error(Error("%#" PRIx64 " is not covered by any module", pc));
}
it--;
LoadedElfModule* loaded_elf_module = it->second.get();
if (auto err = loaded_elf_module->Load(); err.is_error()) {
return err.take_error();
}
if (!loaded_elf_module->IsValidPC(pc)) {
return fit::error(Error("%#" PRIx64 " is not a valid PC in module %#" PRIx64, pc,
loaded_elf_module->load_address()));
}
return fit::ok(LoadedElfModuleRef(*loaded_elf_module));
}
bool ElfModuleCache::IsValidPC(uint64_t pc) const { return GetLoadedElfModuleForPc(pc).is_ok(); }
} // namespace unwinder