blob: 2d915d53594f82600b9ffb8e10822b430cc2b908 [file] [log] [blame]
// Copyright 2018 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.
#pragma once
#include <stdint.h>
#include "garnet/bin/zxdb/symbols/file_line.h"
#include "garnet/bin/zxdb/symbols/lazy_symbol.h"
#include "garnet/bin/zxdb/symbols/symbol_context.h"
namespace zxdb {
class CodeBlock;
class Function;
// Represents all the symbol information for a code location.
class Location {
public:
// A location can be invalid (has no address), can have an address that we
// haven't tried to symbolize, and a symbolized address. The latter two
// states allow symbolizing on demand without having additional types.
//
// The "symbolized" state doesn't necessarily mean there are symbols, it
// just means we tried to symbolize it.
enum class State {
// There is no address or data for this location.
kInvalid,
// There is an address for this location but we haven't tried to symbolize
// it.
kAddress,
// There is an address for the location and we tried to symbolize it. This
// doesn't mean that symbolization succeeded, so the symbol() and file/line
// could still be empty.
kSymbolized,
// The symbol corresponds to a Variable, but its location has not been
// computed so it will have a null address.
//
// Some global variables actually need to be evaluated asynchronously
// based on the current CPU state. For example, TLS values are located
// relative to the CPU register that indicates the TLS base. When
// resolving a symbolic name, we can encounter these which can't be
// evaluated in the global context of the synbol system.
//
// Currently these aren't handled in most places. But if a caller is in a
// position to evaluate this it can fill out the address from the symbol.
kUnlocatedVariable,
};
Location();
Location(State state, uint64_t address);
// Symbolized location.
Location(uint64_t address, FileLine file_line, int column,
const SymbolContext& symbol_context,
LazySymbol symbol = LazySymbol());
// Unlocated variable.
Location(const SymbolContext& symbol_context, LazySymbol symbol);
~Location();
bool is_valid() const { return state_ != State::kInvalid; }
// The different between "symbolized" and "has_symbols" is that the former
// means we tried to symbolize it, and the latter means we actually
// succeeded to symbolize EITHER the line or the function. One or the other
// could be missing, however.
bool is_symbolized() const { return state_ == State::kSymbolized; }
bool has_symbols() const { return file_line_.is_valid() || symbol_; }
// The absolute address of this location.
uint64_t address() const { return address_; }
const FileLine& file_line() const { return file_line_; }
int column() const { return column_; }
// The symbol associated with this address, if any. In the case of code this
// will be a Function. It will not be the code block inside the function
// (code wanting lexical blocks can look inside the function's children as
// needed). It could also be a variable symbol corresponding to a global or
// static variable.
//
// When looking up code locations from the symbol system, this will be the
// most specific function covering the code in question (the innermost
// inlined function if there is one). But Locations may be generated (e.g. by
// the stack unwinder) for any of the other inlined functions that may cover
// the same address.
//
// This isn't necessarily valid, even if the State == kSymbolized. It could
// be the symbol table indicates file/line info for this address but could
// lack a function record for it.
const LazySymbol& symbol() const { return symbol_; }
// Symbolized locations will have a valid symbol context for converting
// addresses.
const SymbolContext& symbol_context() const { return symbol_context_; }
// Offsets the code addresses in this by adding an amount. This is used to
// convert module-relative addresses to global ones by adding the module
// load address.
void AddAddressOffset(uint64_t offset);
private:
State state_ = State::kInvalid;
uint64_t address_ = 0;
FileLine file_line_;
int column_ = 0;
LazySymbol symbol_;
SymbolContext symbol_context_ = SymbolContext::ForRelativeAddresses();
};
} // namespace zxdb