blob: 47b85c5219bb885f696c1a00334778baa2d6a6a3 [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.
#include "src/developer/debug/zxdb/symbols/symbol_utils.h"
#include <lib/syslog/cpp/macros.h>
#include "src/developer/debug/shared/logging/logging.h"
#include "src/developer/debug/zxdb/symbols/array_type.h"
#include "src/developer/debug/zxdb/symbols/base_type.h"
#include "src/developer/debug/zxdb/symbols/collection.h"
#include "src/developer/debug/zxdb/symbols/compile_unit.h"
#include "src/developer/debug/zxdb/symbols/data_member.h"
#include "src/developer/debug/zxdb/symbols/dwarf_tag.h"
#include "src/developer/debug/zxdb/symbols/modified_type.h"
#include "src/developer/debug/zxdb/symbols/namespace.h"
#include "src/developer/debug/zxdb/symbols/template_parameter.h"
#include "src/developer/debug/zxdb/symbols/type.h"
#include "src/developer/debug/zxdb/symbols/variable.h"
#include "src/lib/fxl/strings/string_printf.h"
namespace zxdb {
namespace {
// Since we can't use the expression system to resolve the actual value from
// DW_TAG_template_value_parameters, we have to do a simple decoding ourselves.
void AddTemplateValueToName(std::string& name, const TemplateParameter* template_value) {
auto base_type = template_value->type().Get()->As<Type>()->StripCVT()->As<BaseType>();
if (!base_type)
return;
// This vector assumes little endian, so it's in LSB -> MSB order.
std::vector<uint8_t> v = template_value->const_value().GetConstValue(base_type->byte_size());
std::string s;
switch (base_type->base_type()) {
case BaseType::kBaseTypeBoolean: {
FX_DCHECK(v.size() == 1);
if (v[0] == 1) {
s = "true";
} else {
s = "false";
}
break;
}
case BaseType::kBaseTypeSignedChar:
case BaseType::kBaseTypeUnsignedChar: {
FX_DCHECK(v.size() == 1);
s = fxl::StringPrintf("'%c'", static_cast<char>(v[0]));
break;
}
case BaseType::kBaseTypeSigned:
case BaseType::kBaseTypeUnsigned: {
FX_DCHECK(v.size() >= 2);
uint64_t t = 0;
for (int i = base_type->byte_size() - 1; i >= 0; i--) {
t |= (static_cast<uint64_t>(v[i]) << (8 * i));
}
s = std::to_string(t);
break;
}
default:
LOGS(Warn) << BaseType::BaseTypeToString(base_type->base_type(), true)
<< " is not supported.";
return;
}
AddTemplateParameterToName(name, s.c_str());
}
} // namespace
Identifier GetSymbolScopePrefix(const Symbol* symbol) {
if (!symbol->parent().is_valid())
return Identifier(IdentifierQualification::kGlobal); // No prefix
fxl::RefPtr<Symbol> parent = symbol->parent().Get();
if (parent->tag() == DwarfTag::kCompileUnit)
return Identifier(IdentifierQualification::kGlobal); // Don't go above compilation units.
if (parent->As<Namespace>() || parent->As<Collection>() || parent->As<Function>()) {
// These are the types that get qualified.
return parent->GetIdentifier();
}
// Anything else is skipped and we just return the parent's prefix. This
// will include things like lexical blocks.
return GetSymbolScopePrefix(parent.get());
}
fxl::RefPtr<Collection> MakeRustTuple(const std::string& name,
const std::vector<fxl::RefPtr<Type>>& members) {
auto coll = fxl::MakeRefCounted<Collection>(DwarfTag::kStructureType, name);
auto unit =
fxl::MakeRefCounted<CompileUnit>(DwarfTag::kCompileUnit, fxl::WeakPtr<ModuleSymbols>(),
nullptr, DwarfLang::kRust, "<no file>", std::nullopt);
coll->set_parent(UncachedLazySymbol::MakeUnsafe(unit));
uint32_t offset = 0;
std::vector<LazySymbol> data_members;
for (size_t i = 0; i < members.size(); i++) {
auto& type = members[i];
auto data = fxl::MakeRefCounted<DataMember>("__" + std::to_string(i), type, offset);
data_members.emplace_back(std::move(data));
offset += type->byte_size();
}
coll->set_byte_size(offset);
coll->set_data_members(std::move(data_members));
return coll;
}
fxl::RefPtr<Type> MakeStringLiteralType(size_t length) {
auto char_type = fxl::MakeRefCounted<BaseType>(BaseType::kBaseTypeSignedChar, 1, "char");
return fxl::MakeRefCounted<ArrayType>(std::move(char_type), length);
}
fxl::RefPtr<Type> AddCVQualifiersToMatch(const Type* reference, fxl::RefPtr<Type> modified) {
const Type* source = reference;
while (source) {
const ModifiedType* mod_source = source->As<ModifiedType>();
if (!mod_source || !DwarfTagIsCVQualifier(mod_source->tag()))
break;
modified = fxl::MakeRefCounted<ModifiedType>(mod_source->tag(), std::move(modified));
source = mod_source->modified().Get()->As<Type>();
}
return modified;
}
bool NameHasTemplate(std::string_view name) { return !name.empty() && name.back() == '>'; }
void AddTemplateParameterToName(std::string& original, const char* type_name) {
if (!type_name)
return;
// This type already has a template type, we need to append this one.
if (NameHasTemplate(original)) {
original.pop_back();
std::string append_str = ", ";
append_str += type_name;
original.append(append_str);
} else {
// No template type yet, add "<...>".
original.push_back('<');
original.append(type_name);
}
original.push_back('>');
}
void AddAllTemplateParametersToName(std::string& name,
const std::vector<LazySymbol>& template_params) {
for (const auto& param : template_params) {
const TemplateParameter* template_parameter = param.Get()->As<TemplateParameter>();
if (template_parameter) {
if (template_parameter->is_value() && template_parameter->const_value().has_value()) {
AddTemplateValueToName(name, template_parameter);
} else {
AddTemplateParameterToName(
name, template_parameter->type().Get()->As<Type>()->GetAssignedName().c_str());
}
}
}
}
} // namespace zxdb