blob: 760f11b1e445991a5e80ab3c4abdecea5c1438b4 [file]
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef MPACT_SIM_UTIL_PROGRAM_LOADER_ELF_PROGRAM_LOADER_H_
#define MPACT_SIM_UTIL_PROGRAM_LOADER_ELF_PROGRAM_LOADER_H_
#include <cstdint>
#include <map>
#include <string>
#include <utility>
#include <vector>
#include "absl/container/flat_hash_map.h"
#include "absl/status/statusor.h"
#include "elfio/elfio.hpp"
#include "elfio/elfio_symbols.hpp"
#include "mpact/sim/generic/core_debug_interface.h"
#include "mpact/sim/util/memory/memory_interface.h"
#include "mpact/sim/util/program_loader/program_loader_interface.h"
namespace mpact {
namespace sim {
namespace util {
struct AddressRange {
explicit AddressRange(uint64_t start) : start(start), end(start + 1) {}
AddressRange(uint64_t start, uint64_t size)
: start(start), end(start + size) {}
uint64_t start;
uint64_t end;
};
struct AddressRangeComp {
bool operator()(const AddressRange& lhs, const AddressRange& rhs) const {
if (lhs.end <= rhs.start) {
return true;
}
return false;
}
};
// This class wraps the elfio class to provide an easy interface to load the
// segments of an elf executable file into memory. If both code and data
// memories are given, then executable segments are loaded into code memory and
// all other segments into data memory.
//
// TODO(): Allow for a multiple memories to be passed in to allow
// segments to be loaded into different memories, not just one big contiguous
// memory.
class ElfProgramLoader : public ProgramLoaderInterface {
public:
ElfProgramLoader(util::MemoryInterface* code_memory,
util::MemoryInterface* data_memory);
explicit ElfProgramLoader(util::MemoryInterface* memory);
explicit ElfProgramLoader(generic::CoreDebugInterface* dbg_if);
ElfProgramLoader() = delete;
~ElfProgramLoader() override;
absl::StatusOr<uint64_t> LoadSymbols(const std::string& file_name) override;
absl::StatusOr<uint64_t> LoadProgram(const std::string& file_name) override;
// Return the value and size of the symbol 'name' if it exists in the symbol
// table.
absl::StatusOr<std::pair<uint64_t, uint64_t>> GetSymbol(
const std::string& name) const;
// If there is a function with symbol table value 'address' return its name.
absl::StatusOr<std::string> GetFcnSymbolName(uint64_t address) const;
// Looks up to see if the address is in the range of a function symbol, and
// if so, returns the functions name.
absl::StatusOr<std::string> GetFunctionName(uint64_t address) const;
// If the GNU stack size program header exists, return the memory size.
absl::StatusOr<uint64_t> GetStackSize() const;
const ELFIO::elfio* elf_reader() const { return &elf_reader_; }
private:
bool loaded_ = false;
ELFIO::elfio elf_reader_;
util::MemoryInterface* code_memory_ = nullptr;
util::MemoryInterface* data_memory_ = nullptr;
generic::CoreDebugInterface* dbg_if_ = nullptr;
std::vector<const ELFIO::symbol_section_accessor*> symbol_accessors_;
absl::flat_hash_map<uint64_t, std::string> fcn_symbol_map_;
std::map<AddressRange, std::string, AddressRangeComp> function_range_map_;
uint64_t has_stack_size_ = false;
uint64_t stack_size_ = 0;
};
} // namespace util
} // namespace sim
} // namespace mpact
#endif // MPACT_SIM_UTIL_PROGRAM_LOADER_ELF_PROGRAM_LOADER_H_