blob: 1d1387764a88cc3ef334c39f510a1c41b885943a [file] [log] [blame] [edit]
// Copyright 2020 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_DEVELOPER_DEBUG_ZXDB_SYMBOLS_DWARF_BINARY_H_
#define SRC_DEVELOPER_DEBUG_ZXDB_SYMBOLS_DWARF_BINARY_H_
#include "llvm/BinaryFormat/ELF.h"
#include "src/developer/debug/zxdb/symbols/dwarf_unit.h"
#include "src/developer/debug/zxdb/symbols/symbol_context.h"
#include "src/developer/debug/zxdb/symbols/unit_index.h"
namespace llvm {
namespace object {
class Binary;
class ObjectFile;
} // namespace object
} // namespace llvm
namespace zxdb {
class DwarfSymbolFactory;
class SymbolContext;
// Represents the low-level DWARF file. It provides a mockable wrapper around a llvm::DWARFContext.
//
// Unlike LLVM, a DwarfBinary represents one DWARF file on disk. In the case of Debug Fission
// (--gsplit-dwarf mode where each compilation unit has its own symbols in a .dwo file), there will
// be a separate DwarfBinary for each .dwo file as well as the main binary. These are linked
// together by ModuleSymbols which represents the symbols for a .so or executable file.
//
// In LLVM there will be one llvm::DWARFContext that covers everything but their support for Debug
// Fission is not complete enough for our use case so we roll our own.
//
// This is currently a very leaky abstraction because a lot of code was written before it was
// created and that coded uses llvm objects directly. As a result, this has some accessors for
// the underlying LLVM objects. Mocks may return null for these. If a new test needs to be written
// for such code, wrappers should be added so that the code no longer needs the llvm objects and
// can use the mockable wrappers.
class DwarfBinary {
public:
virtual ~DwarfBinary() = default;
// Getters for basic binary information.
virtual std::string GetName() const = 0;
virtual std::string GetBuildID() const = 0;
virtual std::time_t GetModificationTime() const = 0;
virtual const DwarfSymbolFactory* GetSymbolFactory() const = 0;
// Return whether this module has been given the opportunity to include symbols from the binary
// itself, such as PLT entries.
virtual bool HasBinary() const = 0;
// Returns underlying LLVM objects. May be null in tests since the mock won't have this. See the
// class comment above.
virtual llvm::object::ObjectFile* GetLLVMObjectFile() = 0;
virtual llvm::DWARFContext* GetLLVMContext() = 0;
// Returns the extent of the mapped segments in memory.
virtual uint64_t GetMappedLength() const = 0;
// Returns symbols from the ELF File.
virtual const std::map<std::string, llvm::ELF::Elf64_Sym>& GetELFSymbols() const = 0;
virtual const std::map<std::string, uint64_t> GetPLTSymbols() const = 0;
// Allows access to compile units in this binary. There are two categories, the "normal" units in
// .debug_info and the DWO units in .debug_info.dwo. Normally there are only one or the other,
// but this isn't guaranteed.
virtual uint32_t GetNormalUnitCount() const = 0;
virtual uint32_t GetDWOUnitCount() const = 0;
virtual fxl::RefPtr<DwarfUnit> GetUnitAtIndex(UnitIndex i) = 0;
// Returns the DwarfUnit covering the given absolute address location. Can be null if there's
// no unit that covers this area.
fxl::RefPtr<DwarfUnit> UnitForAddress(const SymbolContext& symbol_context,
TargetPointer absolute_address) {
return UnitForRelativeAddress(symbol_context.AbsoluteToRelative(absolute_address));
}
// Like UnitForAddress but takes an address relative to the load address of the binary.
virtual fxl::RefPtr<DwarfUnit> UnitForRelativeAddress(uint64_t relative_address) = 0;
// Returns the 64-bit value from the .debug_addr section.
//
// The addr_base is an attribute on the compilation unit. This is the byte offset of the address
// table in the .debug_addr section of that compilation unit's address table.
//
// The index is the address index within that compilation unit's table. This is an index into the
// table (of address-sized entries) rather than a byte index.
virtual std::optional<uint64_t> GetDebugAddrEntry(uint64_t addr_base, uint64_t index) const = 0;
// Returns the main unit in a .dwo file. When using DWARF "debug fission" the main binary will
// have "skeleton units" that reference .dwo files containing the real unit information. These
// files will normally have exactly one unit in them. This getter returns that unit.
//
// It's theoretically possible for a .dwo file to have more than one unit. If that happens, it
// would be possible to disambiguate them by name. Currently this does not happen so this just
// returns the first DWO unit.
fxl::RefPtr<DwarfUnit> GetDwoUnit() { return GetUnitAtIndex(UnitIndex(true, 0)); }
// Looks up a DIE by offset. This DIE can be in any unit.
virtual llvm::DWARFDie GetLLVMDieAtOffset(uint64_t offset) const = 0;
virtual void ClearLLVMCache() = 0;
};
} // namespace zxdb
#endif // SRC_DEVELOPER_DEBUG_ZXDB_SYMBOLS_DWARF_BINARY_H_