mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
d93677f652
This reverts commit 1b589f4d4db27e3fcd81fdc5abeb9407753ab790 and relands the D89463 with the fix: update `MappingTraits<FileFilter>::validate()` in ClangTidyOptions.cpp to match the new signature (change the return type to "std::string" from "StringRef"). Original commit message: This: Changes the return type of MappingTraits<T>>::validate to std::string instead of StringRef. It allows to create more complex error messages. It introduces std::vector<std::pair<StringRef, bool>> getEntries(): a new virtual method of Section, which is the base class for all sections. It returns names of special section specific keys (e.g. "Entries") and flags that says if them exist in a YAML. The code in validate() uses this list of entries descriptions to generalize validation. This approach was discussed in the D89039 thread. Differential revision: https://reviews.llvm.org/D89463
330 lines
13 KiB
C++
330 lines
13 KiB
C++
//===- DWARFYAML.cpp - DWARF YAMLIO implementation ------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines classes for handling the YAML representation of DWARF Debug
|
|
// Info.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/ObjectYAML/DWARFYAML.h"
|
|
#include "llvm/BinaryFormat/Dwarf.h"
|
|
#include "llvm/Support/Errc.h"
|
|
#include "llvm/Support/Error.h"
|
|
|
|
namespace llvm {
|
|
|
|
bool DWARFYAML::Data::isEmpty() const {
|
|
return getNonEmptySectionNames().empty();
|
|
}
|
|
|
|
SetVector<StringRef> DWARFYAML::Data::getNonEmptySectionNames() const {
|
|
SetVector<StringRef> SecNames;
|
|
if (DebugStrings)
|
|
SecNames.insert("debug_str");
|
|
if (DebugAranges)
|
|
SecNames.insert("debug_aranges");
|
|
if (DebugRanges)
|
|
SecNames.insert("debug_ranges");
|
|
if (!DebugLines.empty())
|
|
SecNames.insert("debug_line");
|
|
if (DebugAddr)
|
|
SecNames.insert("debug_addr");
|
|
if (!DebugAbbrev.empty())
|
|
SecNames.insert("debug_abbrev");
|
|
if (!CompileUnits.empty())
|
|
SecNames.insert("debug_info");
|
|
if (PubNames)
|
|
SecNames.insert("debug_pubnames");
|
|
if (PubTypes)
|
|
SecNames.insert("debug_pubtypes");
|
|
if (GNUPubNames)
|
|
SecNames.insert("debug_gnu_pubnames");
|
|
if (GNUPubTypes)
|
|
SecNames.insert("debug_gnu_pubtypes");
|
|
if (DebugStrOffsets)
|
|
SecNames.insert("debug_str_offsets");
|
|
if (DebugRnglists)
|
|
SecNames.insert("debug_rnglists");
|
|
if (DebugLoclists)
|
|
SecNames.insert("debug_loclists");
|
|
return SecNames;
|
|
}
|
|
|
|
Expected<DWARFYAML::Data::AbbrevTableInfo>
|
|
DWARFYAML::Data::getAbbrevTableInfoByID(uint64_t ID) const {
|
|
if (AbbrevTableInfoMap.empty()) {
|
|
uint64_t AbbrevTableOffset = 0;
|
|
for (auto &AbbrevTable : enumerate(DebugAbbrev)) {
|
|
// If the abbrev table's ID isn't specified, we use the index as its ID.
|
|
uint64_t AbbrevTableID =
|
|
AbbrevTable.value().ID.getValueOr(AbbrevTable.index());
|
|
auto It = AbbrevTableInfoMap.insert(
|
|
{AbbrevTableID, AbbrevTableInfo{/*Index=*/AbbrevTable.index(),
|
|
/*Offset=*/AbbrevTableOffset}});
|
|
if (!It.second)
|
|
return createStringError(
|
|
errc::invalid_argument,
|
|
"the ID (%" PRIu64 ") of abbrev table with index %zu has been used "
|
|
"by abbrev table with index %" PRIu64,
|
|
AbbrevTableID, AbbrevTable.index(), It.first->second.Index);
|
|
|
|
AbbrevTableOffset +=
|
|
getAbbrevTableContentByIndex(AbbrevTable.index()).size();
|
|
}
|
|
}
|
|
|
|
auto It = AbbrevTableInfoMap.find(ID);
|
|
if (It == AbbrevTableInfoMap.end())
|
|
return createStringError(errc::invalid_argument,
|
|
"cannot find abbrev table whose ID is %" PRIu64,
|
|
ID);
|
|
return It->second;
|
|
}
|
|
|
|
namespace yaml {
|
|
|
|
void MappingTraits<DWARFYAML::Data>::mapping(IO &IO, DWARFYAML::Data &DWARF) {
|
|
void *OldContext = IO.getContext();
|
|
DWARFYAML::DWARFContext DWARFCtx;
|
|
IO.setContext(&DWARFCtx);
|
|
IO.mapOptional("debug_str", DWARF.DebugStrings);
|
|
IO.mapOptional("debug_abbrev", DWARF.DebugAbbrev);
|
|
IO.mapOptional("debug_aranges", DWARF.DebugAranges);
|
|
IO.mapOptional("debug_ranges", DWARF.DebugRanges);
|
|
IO.mapOptional("debug_pubnames", DWARF.PubNames);
|
|
IO.mapOptional("debug_pubtypes", DWARF.PubTypes);
|
|
DWARFCtx.IsGNUPubSec = true;
|
|
IO.mapOptional("debug_gnu_pubnames", DWARF.GNUPubNames);
|
|
IO.mapOptional("debug_gnu_pubtypes", DWARF.GNUPubTypes);
|
|
IO.mapOptional("debug_info", DWARF.CompileUnits);
|
|
IO.mapOptional("debug_line", DWARF.DebugLines);
|
|
IO.mapOptional("debug_addr", DWARF.DebugAddr);
|
|
IO.mapOptional("debug_str_offsets", DWARF.DebugStrOffsets);
|
|
IO.mapOptional("debug_rnglists", DWARF.DebugRnglists);
|
|
IO.mapOptional("debug_loclists", DWARF.DebugLoclists);
|
|
IO.setContext(OldContext);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::AbbrevTable>::mapping(
|
|
IO &IO, DWARFYAML::AbbrevTable &AbbrevTable) {
|
|
IO.mapOptional("ID", AbbrevTable.ID);
|
|
IO.mapOptional("Table", AbbrevTable.Table);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::Abbrev>::mapping(IO &IO,
|
|
DWARFYAML::Abbrev &Abbrev) {
|
|
IO.mapOptional("Code", Abbrev.Code);
|
|
IO.mapRequired("Tag", Abbrev.Tag);
|
|
IO.mapRequired("Children", Abbrev.Children);
|
|
IO.mapOptional("Attributes", Abbrev.Attributes);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::AttributeAbbrev>::mapping(
|
|
IO &IO, DWARFYAML::AttributeAbbrev &AttAbbrev) {
|
|
IO.mapRequired("Attribute", AttAbbrev.Attribute);
|
|
IO.mapRequired("Form", AttAbbrev.Form);
|
|
if(AttAbbrev.Form == dwarf::DW_FORM_implicit_const)
|
|
IO.mapRequired("Value", AttAbbrev.Value);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::ARangeDescriptor>::mapping(
|
|
IO &IO, DWARFYAML::ARangeDescriptor &Descriptor) {
|
|
IO.mapRequired("Address", Descriptor.Address);
|
|
IO.mapRequired("Length", Descriptor.Length);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::ARange>::mapping(IO &IO,
|
|
DWARFYAML::ARange &ARange) {
|
|
IO.mapOptional("Format", ARange.Format, dwarf::DWARF32);
|
|
IO.mapOptional("Length", ARange.Length);
|
|
IO.mapRequired("Version", ARange.Version);
|
|
IO.mapRequired("CuOffset", ARange.CuOffset);
|
|
IO.mapOptional("AddressSize", ARange.AddrSize);
|
|
IO.mapOptional("SegmentSelectorSize", ARange.SegSize, 0);
|
|
IO.mapOptional("Descriptors", ARange.Descriptors);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::RangeEntry>::mapping(
|
|
IO &IO, DWARFYAML::RangeEntry &Descriptor) {
|
|
IO.mapRequired("LowOffset", Descriptor.LowOffset);
|
|
IO.mapRequired("HighOffset", Descriptor.HighOffset);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::Ranges>::mapping(IO &IO,
|
|
DWARFYAML::Ranges &DebugRanges) {
|
|
IO.mapOptional("Offset", DebugRanges.Offset);
|
|
IO.mapOptional("AddrSize", DebugRanges.AddrSize);
|
|
IO.mapRequired("Entries", DebugRanges.Entries);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::PubEntry>::mapping(IO &IO,
|
|
DWARFYAML::PubEntry &Entry) {
|
|
IO.mapRequired("DieOffset", Entry.DieOffset);
|
|
if (static_cast<DWARFYAML::DWARFContext *>(IO.getContext())->IsGNUPubSec)
|
|
IO.mapRequired("Descriptor", Entry.Descriptor);
|
|
IO.mapRequired("Name", Entry.Name);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::PubSection>::mapping(
|
|
IO &IO, DWARFYAML::PubSection &Section) {
|
|
IO.mapOptional("Format", Section.Format, dwarf::DWARF32);
|
|
IO.mapRequired("Length", Section.Length);
|
|
IO.mapRequired("Version", Section.Version);
|
|
IO.mapRequired("UnitOffset", Section.UnitOffset);
|
|
IO.mapRequired("UnitSize", Section.UnitSize);
|
|
IO.mapRequired("Entries", Section.Entries);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::Unit>::mapping(IO &IO, DWARFYAML::Unit &Unit) {
|
|
IO.mapOptional("Format", Unit.Format, dwarf::DWARF32);
|
|
IO.mapOptional("Length", Unit.Length);
|
|
IO.mapRequired("Version", Unit.Version);
|
|
if (Unit.Version >= 5)
|
|
IO.mapRequired("UnitType", Unit.Type);
|
|
IO.mapOptional("AbbrevTableID", Unit.AbbrevTableID);
|
|
IO.mapOptional("AbbrOffset", Unit.AbbrOffset);
|
|
IO.mapOptional("AddrSize", Unit.AddrSize);
|
|
IO.mapOptional("Entries", Unit.Entries);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::Entry>::mapping(IO &IO, DWARFYAML::Entry &Entry) {
|
|
IO.mapRequired("AbbrCode", Entry.AbbrCode);
|
|
IO.mapOptional("Values", Entry.Values);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::FormValue>::mapping(
|
|
IO &IO, DWARFYAML::FormValue &FormValue) {
|
|
IO.mapOptional("Value", FormValue.Value);
|
|
if (!FormValue.CStr.empty() || !IO.outputting())
|
|
IO.mapOptional("CStr", FormValue.CStr);
|
|
if (!FormValue.BlockData.empty() || !IO.outputting())
|
|
IO.mapOptional("BlockData", FormValue.BlockData);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::File>::mapping(IO &IO, DWARFYAML::File &File) {
|
|
IO.mapRequired("Name", File.Name);
|
|
IO.mapRequired("DirIdx", File.DirIdx);
|
|
IO.mapRequired("ModTime", File.ModTime);
|
|
IO.mapRequired("Length", File.Length);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::LineTableOpcode>::mapping(
|
|
IO &IO, DWARFYAML::LineTableOpcode &LineTableOpcode) {
|
|
IO.mapRequired("Opcode", LineTableOpcode.Opcode);
|
|
if (LineTableOpcode.Opcode == dwarf::DW_LNS_extended_op) {
|
|
IO.mapOptional("ExtLen", LineTableOpcode.ExtLen);
|
|
IO.mapRequired("SubOpcode", LineTableOpcode.SubOpcode);
|
|
}
|
|
|
|
if (!LineTableOpcode.UnknownOpcodeData.empty() || !IO.outputting())
|
|
IO.mapOptional("UnknownOpcodeData", LineTableOpcode.UnknownOpcodeData);
|
|
if (!LineTableOpcode.UnknownOpcodeData.empty() || !IO.outputting())
|
|
IO.mapOptional("StandardOpcodeData", LineTableOpcode.StandardOpcodeData);
|
|
if (!LineTableOpcode.FileEntry.Name.empty() || !IO.outputting())
|
|
IO.mapOptional("FileEntry", LineTableOpcode.FileEntry);
|
|
if (LineTableOpcode.Opcode == dwarf::DW_LNS_advance_line || !IO.outputting())
|
|
IO.mapOptional("SData", LineTableOpcode.SData);
|
|
IO.mapOptional("Data", LineTableOpcode.Data);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::LineTable>::mapping(
|
|
IO &IO, DWARFYAML::LineTable &LineTable) {
|
|
IO.mapOptional("Format", LineTable.Format, dwarf::DWARF32);
|
|
IO.mapOptional("Length", LineTable.Length);
|
|
IO.mapRequired("Version", LineTable.Version);
|
|
IO.mapOptional("PrologueLength", LineTable.PrologueLength);
|
|
IO.mapRequired("MinInstLength", LineTable.MinInstLength);
|
|
if(LineTable.Version >= 4)
|
|
IO.mapRequired("MaxOpsPerInst", LineTable.MaxOpsPerInst);
|
|
IO.mapRequired("DefaultIsStmt", LineTable.DefaultIsStmt);
|
|
IO.mapRequired("LineBase", LineTable.LineBase);
|
|
IO.mapRequired("LineRange", LineTable.LineRange);
|
|
IO.mapOptional("OpcodeBase", LineTable.OpcodeBase);
|
|
IO.mapOptional("StandardOpcodeLengths", LineTable.StandardOpcodeLengths);
|
|
IO.mapOptional("IncludeDirs", LineTable.IncludeDirs);
|
|
IO.mapOptional("Files", LineTable.Files);
|
|
IO.mapOptional("Opcodes", LineTable.Opcodes);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::SegAddrPair>::mapping(
|
|
IO &IO, DWARFYAML::SegAddrPair &SegAddrPair) {
|
|
IO.mapOptional("Segment", SegAddrPair.Segment, 0);
|
|
IO.mapOptional("Address", SegAddrPair.Address, 0);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::AddrTableEntry>::mapping(
|
|
IO &IO, DWARFYAML::AddrTableEntry &AddrTable) {
|
|
IO.mapOptional("Format", AddrTable.Format, dwarf::DWARF32);
|
|
IO.mapOptional("Length", AddrTable.Length);
|
|
IO.mapRequired("Version", AddrTable.Version);
|
|
IO.mapOptional("AddressSize", AddrTable.AddrSize);
|
|
IO.mapOptional("SegmentSelectorSize", AddrTable.SegSelectorSize, 0);
|
|
IO.mapOptional("Entries", AddrTable.SegAddrPairs);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::StringOffsetsTable>::mapping(
|
|
IO &IO, DWARFYAML::StringOffsetsTable &StrOffsetsTable) {
|
|
IO.mapOptional("Format", StrOffsetsTable.Format, dwarf::DWARF32);
|
|
IO.mapOptional("Length", StrOffsetsTable.Length);
|
|
IO.mapOptional("Version", StrOffsetsTable.Version, 5);
|
|
IO.mapOptional("Padding", StrOffsetsTable.Padding, 0);
|
|
IO.mapOptional("Offsets", StrOffsetsTable.Offsets);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::DWARFOperation>::mapping(
|
|
IO &IO, DWARFYAML::DWARFOperation &DWARFOperation) {
|
|
IO.mapRequired("Operator", DWARFOperation.Operator);
|
|
IO.mapOptional("Values", DWARFOperation.Values);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::RnglistEntry>::mapping(
|
|
IO &IO, DWARFYAML::RnglistEntry &RnglistEntry) {
|
|
IO.mapRequired("Operator", RnglistEntry.Operator);
|
|
IO.mapOptional("Values", RnglistEntry.Values);
|
|
}
|
|
|
|
void MappingTraits<DWARFYAML::LoclistEntry>::mapping(
|
|
IO &IO, DWARFYAML::LoclistEntry &LoclistEntry) {
|
|
IO.mapRequired("Operator", LoclistEntry.Operator);
|
|
IO.mapOptional("Values", LoclistEntry.Values);
|
|
IO.mapOptional("DescriptionsLength", LoclistEntry.DescriptionsLength);
|
|
IO.mapOptional("Descriptions", LoclistEntry.Descriptions);
|
|
}
|
|
|
|
template <typename EntryType>
|
|
void MappingTraits<DWARFYAML::ListEntries<EntryType>>::mapping(
|
|
IO &IO, DWARFYAML::ListEntries<EntryType> &ListEntries) {
|
|
IO.mapOptional("Entries", ListEntries.Entries);
|
|
IO.mapOptional("Content", ListEntries.Content);
|
|
}
|
|
|
|
template <typename EntryType>
|
|
std::string MappingTraits<DWARFYAML::ListEntries<EntryType>>::validate(
|
|
IO &IO, DWARFYAML::ListEntries<EntryType> &ListEntries) {
|
|
if (ListEntries.Entries && ListEntries.Content)
|
|
return "Entries and Content can't be used together";
|
|
return "";
|
|
}
|
|
|
|
template <typename EntryType>
|
|
void MappingTraits<DWARFYAML::ListTable<EntryType>>::mapping(
|
|
IO &IO, DWARFYAML::ListTable<EntryType> &ListTable) {
|
|
IO.mapOptional("Format", ListTable.Format, dwarf::DWARF32);
|
|
IO.mapOptional("Length", ListTable.Length);
|
|
IO.mapOptional("Version", ListTable.Version, 5);
|
|
IO.mapOptional("AddressSize", ListTable.AddrSize);
|
|
IO.mapOptional("SegmentSelectorSize", ListTable.SegSelectorSize, 0);
|
|
IO.mapOptional("OffsetEntryCount", ListTable.OffsetEntryCount);
|
|
IO.mapOptional("Offsets", ListTable.Offsets);
|
|
IO.mapOptional("Lists", ListTable.Lists);
|
|
}
|
|
|
|
} // end namespace yaml
|
|
|
|
} // end namespace llvm
|