blob: 7a439685ed52bc7fc8609c56399db6dce444f30a [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.
#ifndef SRC_LIB_UNWINDER_LOADED_ELF_MODULE_H_
#define SRC_LIB_UNWINDER_LOADED_ELF_MODULE_H_
#include <elf.h>
#include <lib/fit/result.h>
#include <cstdint>
#include <vector>
#include "src/lib/unwinder/error.h"
#include "src/lib/unwinder/module.h"
namespace unwinder {
class Memory;
// Provides a high level interface over a |Module|. Eventually these classes will be merged.
//
// A LoadedElfModule can represent either a literally loaded ELF program in a program's address
// space, or an ELF file (or files) on disk, depending on the corresponding Module's |mode|. In
// either case, there is always a live process associated with this object that has a load address.
//
// This class assumes that is has synchronous access to both |binary_memory| and |debug_info_memory|
// members of the corresponding Module object.
class LoadedElfModule {
public:
explicit LoadedElfModule(const Module& module) : module_(module) {}
// Load ELF headers and program headers.
[[nodiscard]] fit::result<Error> Load();
// Check whether a given PC is in the valid range of this module.
bool IsValidPC(uint64_t pc) const { return pc >= pc_begin_ && pc < pc_end_; }
const Module& module() const { return module_; }
uint64_t load_address() const { return module_.load_address; }
Memory* binary_memory() const { return module_.binary_memory; }
Memory* debug_info_memory() const { return module_.debug_info_memory; }
Module::AddressMode mode() const { return module_.mode; }
Module::AddressSize size() const { return module_.size; }
const std::vector<Elf64_Phdr>& phdrs() const { return phdrs_; }
// Helpers to get sections or segments.
[[nodiscard]] fit::result<Error, Elf64_Shdr> GetSectionByName(
std::string_view target_section) const;
// Always returns an Elf64_Phdr, even if this module is 32 bits.
[[nodiscard]] fit::result<Error, Elf64_Phdr> GetSegmentByType(uint32_t p_type) const;
private:
// Loads the ELF header to |ehdr_| (upcasting if necessary). |module_.binary_memory| is assumed to
// be valid when this function is called.
fit::result<Error> LoadElfHeader();
// Loads all Program Headers to |phdrs_| (upcasting them if necessary). |module_.binary_memory| is
// assumed to be valid when this function is called.
fit::result<Error> LoadPhdrs(const Elf64_Ehdr& ehdr);
const Module module_;
// Marks the executable section.
uint64_t pc_begin_ = 0; // inclusive
uint64_t pc_end_ = 0; // exclusive
std::optional<Elf64_Ehdr> ehdr_;
std::vector<Elf64_Phdr> phdrs_;
};
} // namespace unwinder
#endif // SRC_LIB_UNWINDER_LOADED_ELF_MODULE_H_