[lldb] Refactor IRExecutionUnit::FindInSymbols (NFC)

This patch refactors IRExecutionUnit::FindInSymbols. It eliminates a few
potential pitfalls and tries to be more explicit about the state carried
between symbol resolution attempts.

Differential revision: https://reviews.llvm.org/D107206
This commit is contained in:
Jonas Devlieghere 2021-08-05 09:35:37 -07:00
parent c020be17ce
commit a46bcc60e5
1 changed files with 105 additions and 112 deletions

View File

@ -769,134 +769,127 @@ void IRExecutionUnit::CollectFallbackNames(
}
}
lldb::addr_t IRExecutionUnit::FindInSymbols(
const std::vector<IRExecutionUnit::SearchSpec> &specs,
const lldb_private::SymbolContext &sc,
bool &symbol_was_missing_weak) {
symbol_was_missing_weak = false;
Target *target = sc.target_sp.get();
class LoadAddressResolver {
public:
LoadAddressResolver(Target *target, bool &symbol_was_missing_weak)
: m_target(target), m_symbol_was_missing_weak(symbol_was_missing_weak) {}
if (!target) {
// we shouldn't be doing any symbol lookup at all without a target
return LLDB_INVALID_ADDRESS;
llvm::Optional<lldb::addr_t> Resolve(SymbolContextList &sc_list) {
if (sc_list.IsEmpty())
return llvm::None;
lldb::addr_t load_address = LLDB_INVALID_ADDRESS;
// Missing_weak_symbol will be true only if we found only weak undefined
// references to this symbol.
m_symbol_was_missing_weak = true;
for (auto candidate_sc : sc_list.SymbolContexts()) {
// Only symbols can be weak undefined.
if (!candidate_sc.symbol ||
candidate_sc.symbol->GetType() != lldb::eSymbolTypeUndefined ||
!candidate_sc.symbol->IsWeak())
m_symbol_was_missing_weak = false;
// First try the symbol.
if (candidate_sc.symbol) {
load_address = candidate_sc.symbol->ResolveCallableAddress(*m_target);
if (load_address == LLDB_INVALID_ADDRESS) {
Address addr = candidate_sc.symbol->GetAddress();
load_address = m_target->GetProcessSP()
? addr.GetLoadAddress(m_target)
: addr.GetFileAddress();
}
}
for (const SearchSpec &spec : specs) {
SymbolContextList sc_list;
lldb::addr_t best_internal_load_address = LLDB_INVALID_ADDRESS;
std::function<bool(lldb::addr_t &, SymbolContextList &,
const lldb_private::SymbolContext &)>
get_external_load_address = [&best_internal_load_address, target,
&symbol_was_missing_weak](
lldb::addr_t &load_address, SymbolContextList &sc_list,
const lldb_private::SymbolContext &sc) -> lldb::addr_t {
load_address = LLDB_INVALID_ADDRESS;
if (sc_list.GetSize() == 0)
return false;
// missing_weak_symbol will be true only if we found only weak undefined
// references to this symbol.
symbol_was_missing_weak = true;
for (auto candidate_sc : sc_list.SymbolContexts()) {
// Only symbols can be weak undefined:
if (!candidate_sc.symbol)
symbol_was_missing_weak = false;
else if (candidate_sc.symbol->GetType() != lldb::eSymbolTypeUndefined
|| !candidate_sc.symbol->IsWeak())
symbol_was_missing_weak = false;
// If that didn't work, try the function.
if (load_address == LLDB_INVALID_ADDRESS && candidate_sc.function) {
Address addr =
candidate_sc.function->GetAddressRange().GetBaseAddress();
load_address = m_target->GetProcessSP() ? addr.GetLoadAddress(m_target)
: addr.GetFileAddress();
}
// We found a load address.
if (load_address != LLDB_INVALID_ADDRESS) {
// If the load address is external, we're done.
const bool is_external =
(candidate_sc.function) ||
(candidate_sc.symbol && candidate_sc.symbol->IsExternal());
if (candidate_sc.symbol) {
load_address = candidate_sc.symbol->ResolveCallableAddress(*target);
if (is_external)
return load_address;
if (load_address == LLDB_INVALID_ADDRESS) {
if (target->GetProcessSP())
load_address =
candidate_sc.symbol->GetAddress().GetLoadAddress(target);
else
load_address = candidate_sc.symbol->GetAddress().GetFileAddress();
}
}
if (load_address == LLDB_INVALID_ADDRESS && candidate_sc.function) {
if (target->GetProcessSP())
load_address = candidate_sc.function->GetAddressRange()
.GetBaseAddress()
.GetLoadAddress(target);
else
load_address = candidate_sc.function->GetAddressRange()
.GetBaseAddress()
.GetFileAddress();
}
if (load_address != LLDB_INVALID_ADDRESS) {
if (is_external) {
return true;
} else if (best_internal_load_address == LLDB_INVALID_ADDRESS) {
best_internal_load_address = load_address;
load_address = LLDB_INVALID_ADDRESS;
}
// Otherwise, remember the best internal load address.
if (m_best_internal_load_address == LLDB_INVALID_ADDRESS)
m_best_internal_load_address = load_address;
}
}
// You test the address of a weak symbol against NULL to see if it is
// present. So we should return 0 for a missing weak symbol.
if (symbol_was_missing_weak) {
load_address = 0;
return true;
if (m_symbol_was_missing_weak)
return 0;
return llvm::None;
}
return false;
lldb::addr_t GetBestInternalLoadAddress() const {
return m_best_internal_load_address;
}
private:
Target *m_target;
bool &m_symbol_was_missing_weak;
lldb::addr_t m_best_internal_load_address = LLDB_INVALID_ADDRESS;
};
lldb::addr_t IRExecutionUnit::FindInSymbols(
const std::vector<IRExecutionUnit::SearchSpec> &specs,
const lldb_private::SymbolContext &sc, bool &symbol_was_missing_weak) {
symbol_was_missing_weak = false;
Target *target = sc.target_sp.get();
if (!target) {
// We shouldn't be doing any symbol lookup at all without a target.
return LLDB_INVALID_ADDRESS;
}
LoadAddressResolver resolver(target, symbol_was_missing_weak);
ModuleFunctionSearchOptions function_options;
function_options.include_symbols = true;
function_options.include_inlines = false;
for (const SearchSpec &spec : specs) {
if (sc.module_sp) {
SymbolContextList sc_list;
sc.module_sp->FindFunctions(spec.name, CompilerDeclContext(), spec.mask,
function_options, sc_list);
if (auto load_addr = resolver.Resolve(sc_list))
return *load_addr;
}
lldb::addr_t load_address = LLDB_INVALID_ADDRESS;
if (get_external_load_address(load_address, sc_list, sc)) {
return load_address;
} else {
sc_list.Clear();
}
if (sc_list.GetSize() == 0 && sc.target_sp) {
if (sc.target_sp) {
SymbolContextList sc_list;
sc.target_sp->GetImages().FindFunctions(spec.name, spec.mask,
function_options, sc_list);
if (auto load_addr = resolver.Resolve(sc_list))
return *load_addr;
}
if (get_external_load_address(load_address, sc_list, sc)) {
return load_address;
} else {
sc_list.Clear();
}
if (sc_list.GetSize() == 0 && sc.target_sp) {
if (sc.target_sp) {
SymbolContextList sc_list;
sc.target_sp->GetImages().FindSymbolsWithNameAndType(
spec.name, lldb::eSymbolTypeAny, sc_list);
if (auto load_addr = resolver.Resolve(sc_list))
return *load_addr;
}
if (get_external_load_address(load_address, sc_list, sc)) {
return load_address;
}
// if there are any searches we try after this, add an sc_list.Clear() in
// an "else" clause here
if (best_internal_load_address != LLDB_INVALID_ADDRESS) {
lldb::addr_t best_internal_load_address =
resolver.GetBestInternalLoadAddress();
if (best_internal_load_address != LLDB_INVALID_ADDRESS)
return best_internal_load_address;
}
}
return LLDB_INVALID_ADDRESS;
}