Merge changes from topic "multithreaded-header-linker-ir"

am: 6a233fe18a

Change-Id: I0ac785a3c0e1fa007932a465935979dca4fd6470
This commit is contained in:
Jayant Chowdhary
2017-11-21 02:47:38 +00:00
committed by android-build-merger
18 changed files with 620 additions and 419 deletions

View File

@@ -18,9 +18,6 @@
#include <llvm/Support/raw_ostream.h>
#include <google/protobuf/text_format.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <memory>
#include <string>
#include <vector>
@@ -30,16 +27,16 @@
abi_util::CompatibilityStatusIR HeaderAbiDiff::GenerateCompatibilityReport() {
using abi_util::TextFormatToIRReader;
std::unique_ptr<abi_util::TextFormatToIRReader> old_reader =
TextFormatToIRReader::CreateTextFormatToIRReader("protobuf", old_dump_);
TextFormatToIRReader::CreateTextFormatToIRReader(text_format_old_);
std::unique_ptr<abi_util::TextFormatToIRReader> new_reader =
TextFormatToIRReader::CreateTextFormatToIRReader("protobuf", new_dump_);
if (!old_reader || !new_reader || !old_reader->ReadDump() ||
!new_reader->ReadDump()) {
TextFormatToIRReader::CreateTextFormatToIRReader(text_format_new_);
if (!old_reader || !new_reader || !old_reader->ReadDump(old_dump_) ||
!new_reader->ReadDump(new_dump_)) {
llvm::errs() << "Could not create Text Format readers\n";
::exit(1);
}
std::unique_ptr<abi_util::IRDiffDumper> ir_diff_dumper =
abi_util::IRDiffDumper::CreateIRDiffDumper("protobuf", cr_);
abi_util::IRDiffDumper::CreateIRDiffDumper(text_format_diff_, cr_);
abi_util::CompatibilityStatusIR status =
CompareTUs(old_reader.get(), new_reader.get(), ir_diff_dumper.get());
if (!ir_diff_dumper->Dump()) {
@@ -49,17 +46,18 @@ abi_util::CompatibilityStatusIR HeaderAbiDiff::GenerateCompatibilityReport() {
return status;
}
template <typename F>
static void AddTypesToMap(std::map<std::string, const abi_util::TypeIR *> *dst,
const abi_util::TextFormatToIRReader *tu, F func) {
AddToMap(dst, tu->GetRecordTypes(), func);
AddToMap(dst, tu->GetEnumTypes(), func);
AddToMap(dst, tu->GetPointerTypes(), func);
AddToMap(dst, tu->GetBuiltinTypes(), func);
AddToMap(dst, tu->GetArrayTypes(), func);
AddToMap(dst, tu->GetLvalueReferenceTypes(), func);
AddToMap(dst, tu->GetRvalueReferenceTypes(), func);
AddToMap(dst, tu->GetQualifiedTypes(), func);
template <typename KeyGetter, typename ValueGetter>
static void AddTypesToMap(AbiElementMap<const abi_util::TypeIR *> *dst,
const abi_util::TextFormatToIRReader *tu,
KeyGetter get_key, ValueGetter get_value) {
AddToMap(dst, tu->GetRecordTypes(), get_key, get_value);
AddToMap(dst, tu->GetEnumTypes(), get_key, get_value);
AddToMap(dst, tu->GetPointerTypes(), get_key, get_value);
AddToMap(dst, tu->GetBuiltinTypes(), get_key, get_value);
AddToMap(dst, tu->GetArrayTypes(), get_key, get_value);
AddToMap(dst, tu->GetLvalueReferenceTypes(), get_key, get_value);
AddToMap(dst, tu->GetRvalueReferenceTypes(), get_key, get_value);
AddToMap(dst, tu->GetQualifiedTypes(), get_key, get_value);
}
abi_util::CompatibilityStatusIR HeaderAbiDiff::CompareTUs(
@@ -68,12 +66,14 @@ abi_util::CompatibilityStatusIR HeaderAbiDiff::CompareTUs(
abi_util::IRDiffDumper *ir_diff_dumper) {
// Collect all old and new types in maps, so that we can refer to them by
// type name / linker_set_key later.
std::map<std::string, const abi_util::TypeIR *> old_types;
std::map<std::string, const abi_util::TypeIR *> new_types;
AbiElementMap<const abi_util::TypeIR *> old_types;
AbiElementMap<const abi_util::TypeIR *> new_types;
AddTypesToMap(&old_types, old_tu,
[](const abi_util::TypeIR *e) {return e->GetLinkerSetKey();});
[](auto e) {return e->first;},
[](auto e) {return &(e->second);});
AddTypesToMap(&new_types, new_tu,
[](const abi_util::TypeIR *e) {return e->GetLinkerSetKey();});
[](auto e) {return e->first;},
[](auto e) {return &(e->second);});
// Collect fills in added, removed ,unsafe and safe function diffs.
if (!CollectDynsymExportables(old_tu->GetFunctions(), new_tu->GetFunctions(),
@@ -111,8 +111,8 @@ abi_util::CompatibilityStatusIR HeaderAbiDiff::CompareTUs(
bool HeaderAbiDiff::CollectUserDefinedTypes(
const abi_util::TextFormatToIRReader *old_tu,
const abi_util::TextFormatToIRReader *new_tu,
const std::map<std::string, const abi_util::TypeIR *> &old_types_map,
const std::map<std::string, const abi_util::TypeIR *> &new_types_map,
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
abi_util::IRDiffDumper *ir_diff_dumper) {
return CollectUserDefinedTypesInternal(
old_tu->GetRecordTypes(), new_tu->GetRecordTypes(), old_types_map,
@@ -124,22 +124,23 @@ bool HeaderAbiDiff::CollectUserDefinedTypes(
template <typename T>
bool HeaderAbiDiff::CollectUserDefinedTypesInternal(
const std::vector<T> &old_ud_types,
const std::vector<T> &new_ud_types,
const std::map<std::string, const abi_util::TypeIR *> &old_types_map,
const std::map<std::string, const abi_util::TypeIR *> &new_types_map,
const AbiElementMap<T> &old_ud_types,
const AbiElementMap<T> &new_ud_types,
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
abi_util::IRDiffDumper *ir_diff_dumper) {
// No elf information for records and enums.
std::map<std::string, const T *> old_ud_types_map;
std::map<std::string, const T *> new_ud_types_map;
AbiElementMap<const T *> old_ud_types_map;
AbiElementMap<const T *> new_ud_types_map;
abi_util::AddToMap(&old_ud_types_map, old_ud_types,
[](const T *e)
{ return e->GetLinkerSetKey();});
[](auto e) { return e->first;},
[](auto e) {return &(e->second);});
abi_util::AddToMap(&new_ud_types_map, new_ud_types,
[](const T *e)
{ return e->GetLinkerSetKey();});
[](auto e) { return e->first;},
[](auto e) {return &(e->second);});
return Collect(old_ud_types_map, new_ud_types_map, nullptr, nullptr,
ir_diff_dumper) &&
@@ -150,30 +151,34 @@ bool HeaderAbiDiff::CollectUserDefinedTypesInternal(
template <typename T, typename ElfSymbolType>
bool HeaderAbiDiff::CollectDynsymExportables(
const std::vector<T> &old_exportables,
const std::vector<T> &new_exportables,
const std::vector<ElfSymbolType> &old_elf_symbols,
const std::vector<ElfSymbolType> &new_elf_symbols,
const std::map<std::string, const abi_util::TypeIR *> &old_types_map,
const std::map<std::string, const abi_util::TypeIR *> &new_types_map,
const AbiElementMap<T> &old_exportables,
const AbiElementMap<T> &new_exportables,
const AbiElementMap<ElfSymbolType> &old_elf_symbols,
const AbiElementMap<ElfSymbolType> &new_elf_symbols,
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
abi_util::IRDiffDumper *ir_diff_dumper) {
std::map<std::string, const T *> old_exportables_map;
std::map<std::string, const T *> new_exportables_map;
std::map<std::string, const abi_util::ElfSymbolIR *> old_elf_symbol_map;
std::map<std::string, const abi_util::ElfSymbolIR *> new_elf_symbol_map;
AbiElementMap<const T *> old_exportables_map;
AbiElementMap<const T *> new_exportables_map;
AbiElementMap<const abi_util::ElfSymbolIR *> old_elf_symbol_map;
AbiElementMap<const abi_util::ElfSymbolIR *> new_elf_symbol_map;
abi_util::AddToMap(&old_exportables_map, old_exportables,
[](const T *e)
{ return e->GetLinkerSetKey();});
[](auto e) { return e->first;},
[](auto e) {return &(e->second);});
abi_util::AddToMap(&new_exportables_map, new_exportables,
[](const T *e)
{ return e->GetLinkerSetKey();});
[](auto e) { return e->first;},
[](auto e) { return &(e->second);});
abi_util::AddToMap(
&old_elf_symbol_map, old_elf_symbols,
[](const ElfSymbolType *symbol) { return symbol->GetName();});
[](auto e) { return e->first;},
[](auto e) {return &(e->second);});
abi_util::AddToMap(
&new_elf_symbol_map, new_elf_symbols,
[](const ElfSymbolType *symbol) { return symbol->GetName();});
[](auto e) { return e->first;},
[](auto e) {return &(e->second);});
if (!Collect(old_exportables_map,
new_exportables_map, &old_elf_symbol_map, &new_elf_symbol_map,
@@ -197,10 +202,10 @@ bool HeaderAbiDiff::CollectDynsymExportables(
template <typename T>
bool HeaderAbiDiff::Collect(
const std::map<std::string, const T*> &old_elements_map,
const std::map<std::string, const T*> &new_elements_map,
const std::map<std::string, const abi_util::ElfSymbolIR *> *old_elf_map,
const std::map<std::string, const abi_util::ElfSymbolIR *> *new_elf_map,
const AbiElementMap<const T*> &old_elements_map,
const AbiElementMap<const T*> &new_elements_map,
const AbiElementMap<const abi_util::ElfSymbolIR *> *old_elf_map,
const AbiElementMap<const abi_util::ElfSymbolIR *> *new_elf_map,
abi_util::IRDiffDumper *ir_diff_dumper) {
if (!PopulateRemovedElements(
old_elements_map, new_elements_map, new_elf_map, ir_diff_dumper,
@@ -215,8 +220,8 @@ bool HeaderAbiDiff::Collect(
}
bool HeaderAbiDiff::CollectElfSymbols(
const std::map<std::string, const abi_util::ElfSymbolIR *> &old_symbols,
const std::map<std::string, const abi_util::ElfSymbolIR *> &new_symbols,
const AbiElementMap<const abi_util::ElfSymbolIR *> &old_symbols,
const AbiElementMap<const abi_util::ElfSymbolIR *> &new_symbols,
abi_util::IRDiffDumper *ir_diff_dumper) {
std::vector<const abi_util::ElfSymbolIR *> removed_elements =
abi_util::FindRemovedElements(old_symbols, new_symbols);
@@ -244,9 +249,9 @@ bool HeaderAbiDiff::PopulateElfElements(
template <typename T>
bool HeaderAbiDiff::PopulateRemovedElements(
const std::map<std::string, const T*> &old_elements_map,
const std::map<std::string, const T*> &new_elements_map,
const std::map<std::string, const abi_util::ElfSymbolIR *> *elf_map,
const AbiElementMap<const T*> &old_elements_map,
const AbiElementMap<const T*> &new_elements_map,
const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map,
abi_util::IRDiffDumper *ir_diff_dumper,
abi_util::IRDiffDumper::DiffKind diff_kind) {
std::vector<const T *> removed_elements =
@@ -258,12 +263,15 @@ bool HeaderAbiDiff::PopulateRemovedElements(
return true;
}
// Find the common elements (common records, common enums, common functions etc)
// Dump the differences (we need type maps for this diff since we'll get
// reachable types from here)
template <typename T>
bool HeaderAbiDiff::PopulateCommonElements(
const std::map<std::string, const T *> &old_elements_map,
const std::map<std::string, const T *> &new_elements_map,
const std::map<std::string, const abi_util::TypeIR *> &old_types,
const std::map<std::string, const abi_util::TypeIR *> &new_types,
const AbiElementMap<const T *> &old_elements_map,
const AbiElementMap<const T *> &new_elements_map,
const AbiElementMap<const abi_util::TypeIR *> &old_types,
const AbiElementMap<const abi_util::TypeIR *> &new_types,
abi_util::IRDiffDumper *ir_diff_dumper,
abi_util::IRDiffDumper::DiffKind diff_kind) {
std::vector<std::pair<const T *, const T *>> common_elements =
@@ -279,7 +287,7 @@ bool HeaderAbiDiff::PopulateCommonElements(
template <typename T>
bool HeaderAbiDiff::DumpLoneElements(
std::vector<const T *> &elements,
const std::map<std::string, const abi_util::ElfSymbolIR *> *elf_map,
const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map,
abi_util::IRDiffDumper *ir_diff_dumper,
abi_util::IRDiffDumper::DiffKind diff_kind) {
// If the record / enum has source file information, skip it.
@@ -310,12 +318,11 @@ bool HeaderAbiDiff::DumpLoneElements(
return true;
}
template <typename T>
bool HeaderAbiDiff::DumpDiffElements(
std::vector<std::pair<const T *,const T *>> &pairs,
const std::map<std::string, const abi_util::TypeIR *> &old_types,
const std::map<std::string, const abi_util::TypeIR *> &new_types,
const AbiElementMap<const abi_util::TypeIR *> &old_types,
const AbiElementMap<const abi_util::TypeIR *> &new_types,
abi_util::IRDiffDumper *ir_diff_dumper,
abi_util::IRDiffDumper::DiffKind diff_kind) {
for (auto &&pair : pairs) {

View File

@@ -26,16 +26,22 @@
#include <string>
#include <vector>
using abi_util::AbiElementMap;
class HeaderAbiDiff {
public:
HeaderAbiDiff(const std::string &lib_name, const std::string &arch,
const std::string &old_dump, const std::string &new_dump,
const std::string &compatibility_report,
const std::set<std::string> &ignored_symbols,
bool check_all_apis)
bool check_all_apis, abi_util::TextFormatIR text_format_old,
abi_util::TextFormatIR text_format_new,
abi_util::TextFormatIR text_format_diff)
: lib_name_(lib_name), arch_(arch), old_dump_(old_dump),
new_dump_(new_dump), cr_(compatibility_report),
ignored_symbols_(ignored_symbols), check_all_apis_(check_all_apis) { }
ignored_symbols_(ignored_symbols), check_all_apis_(check_all_apis),
text_format_old_(text_format_old), text_format_new_(text_format_new),
text_format_diff_(text_format_diff) { }
abi_util::CompatibilityStatusIR GenerateCompatibilityReport();
@@ -47,25 +53,25 @@ class HeaderAbiDiff {
template <typename T, typename ElfSymbolType>
bool CollectDynsymExportables(
const std::vector<T> &old_exportables,
const std::vector<T> &new_exportables,
const std::vector<ElfSymbolType> &old_elf_symbols,
const std::vector<ElfSymbolType> &new_elf_symbols,
const std::map<std::string, const abi_util::TypeIR *> &old_types_map,
const std::map<std::string, const abi_util::TypeIR *> &new_types_map,
const AbiElementMap<T> &old_exportables,
const AbiElementMap<T> &new_exportables,
const AbiElementMap<ElfSymbolType> &old_elf_symbols,
const AbiElementMap<ElfSymbolType> &new_elf_symbols,
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
abi_util::IRDiffDumper *ir_diff_dumper);
template <typename T>
bool Collect(
const std::map<std::string, const T *> &old_elements_map,
const std::map<std::string, const T *> &new_elements_map,
const std::map<std::string, const abi_util::ElfSymbolIR *> *old_elf_map,
const std::map<std::string, const abi_util::ElfSymbolIR *> *new_elf_map,
const AbiElementMap<const T *> &old_elements_map,
const AbiElementMap<const T *> &new_elements_map,
const AbiElementMap<const abi_util::ElfSymbolIR *> *old_elf_map,
const AbiElementMap<const abi_util::ElfSymbolIR *> *new_elf_map,
abi_util::IRDiffDumper *ir_diff_dumper);
bool CollectElfSymbols(
const std::map<std::string, const abi_util::ElfSymbolIR *> &old_symbols,
const std::map<std::string, const abi_util::ElfSymbolIR *> &new_symbols,
const AbiElementMap<const abi_util::ElfSymbolIR *> &old_symbols,
const AbiElementMap<const abi_util::ElfSymbolIR *> &new_symbols,
abi_util::IRDiffDumper *ir_diff_dumper);
bool PopulateElfElements(
@@ -75,49 +81,49 @@ class HeaderAbiDiff {
template <typename T>
bool PopulateRemovedElements(
const std::map<std::string, const T *> &old_elements_map,
const std::map<std::string, const T *> &new_elements_map,
const std::map<std::string, const abi_util::ElfSymbolIR *> *elf_map,
const AbiElementMap<const T *> &old_elements_map,
const AbiElementMap<const T *> &new_elements_map,
const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map,
abi_util::IRDiffDumper *ir_diff_dumper,
abi_util::IRDiffDumper::DiffKind diff_kind);
template <typename T>
bool PopulateCommonElements(
const std::map<std::string, const T *> &old_elements_map,
const std::map<std::string, const T *> &new_elements_map,
const std::map<std::string, const abi_util::TypeIR *> &old_types,
const std::map<std::string, const abi_util::TypeIR *> &new_types,
const AbiElementMap<const T *> &old_elements_map,
const AbiElementMap<const T *> &new_elements_map,
const AbiElementMap<const abi_util::TypeIR *> &old_types,
const AbiElementMap<const abi_util::TypeIR *> &new_types,
abi_util::IRDiffDumper *ir_diff_dumper,
abi_util::IRDiffDumper::DiffKind diff_kind);
template <typename T>
bool DumpDiffElements(
std::vector<std::pair<const T *, const T *>> &pairs,
const std::map<std::string, const abi_util::TypeIR *> &old_types,
const std::map<std::string, const abi_util::TypeIR *> &new_types,
const AbiElementMap<const abi_util::TypeIR *> &old_types,
const AbiElementMap<const abi_util::TypeIR *> &new_types,
abi_util::IRDiffDumper *ir_diff_dumper,
abi_util::IRDiffDumper::DiffKind diff_kind);
template <typename T>
bool DumpLoneElements(
std::vector<const T *> &elements,
const std::map<std::string, const abi_util::ElfSymbolIR *> *elf_map,
const AbiElementMap<const abi_util::ElfSymbolIR *> *elf_map,
abi_util::IRDiffDumper *ir_diff_dumper,
abi_util::IRDiffDumper::DiffKind diff_kind);
bool CollectUserDefinedTypes(
const abi_util::TextFormatToIRReader *old_tu,
const abi_util::TextFormatToIRReader *new_tu,
const std::map<std::string, const abi_util::TypeIR *> &old_types_map,
const std::map<std::string, const abi_util::TypeIR *> &new_types_map,
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
abi_util::IRDiffDumper *ir_diff_dumper);
template <typename T>
bool CollectUserDefinedTypesInternal(
const std::vector<T> &old_ud_types,
const std::vector<T> &new_ud_types,
const std::map<std::string, const abi_util::TypeIR *> &old_types_map,
const std::map<std::string, const abi_util::TypeIR *> &new_types_map,
const AbiElementMap<T> &old_ud_types,
const AbiElementMap<T> &new_ud_types,
const AbiElementMap<const abi_util::TypeIR *> &old_types_map,
const AbiElementMap<const abi_util::TypeIR *> &new_types_map,
abi_util::IRDiffDumper *ir_diff_dumper);
private:
@@ -129,4 +135,7 @@ class HeaderAbiDiff {
const std::set<std::string> &ignored_symbols_;
bool check_all_apis_;
std::set<std::string> type_cache_;
abi_util::TextFormatIR text_format_old_;
abi_util::TextFormatIR text_format_new_;
abi_util::TextFormatIR text_format_diff_;
};

View File

@@ -20,6 +20,8 @@
namespace abi_diff_wrappers {
using abi_util::AbiElementMap;
static bool IsAccessDownGraded(abi_util::AccessSpecifierIR old_access,
abi_util::AccessSpecifierIR new_access) {
bool access_downgraded = false;
@@ -57,14 +59,16 @@ void DiffWrapperBase::CompareEnumFields(
const std::vector<abi_util::EnumFieldIR> &old_fields,
const std::vector<abi_util::EnumFieldIR> &new_fields,
abi_util::EnumTypeDiffIR *enum_type_diff_ir) {
std::map<std::string, const abi_util::EnumFieldIR *> old_fields_map;
std::map<std::string, const abi_util::EnumFieldIR *> new_fields_map;
AbiElementMap<const abi_util::EnumFieldIR *> old_fields_map;
AbiElementMap<const abi_util::EnumFieldIR *> new_fields_map;
abi_util::AddToMap(&old_fields_map, old_fields,
[](const abi_util::EnumFieldIR *f)
{return f->GetName();});
[](const abi_util::EnumFieldIR *f) {return f->GetName();},
[](const abi_util::EnumFieldIR *f) {return f;});
abi_util::AddToMap(&new_fields_map, new_fields,
[](const abi_util::EnumFieldIR *f)
{return f->GetName();});
[](const abi_util::EnumFieldIR *f) {return f->GetName();},
[](const abi_util::EnumFieldIR *f) {return f;});
std::vector<const abi_util::EnumFieldIR *> removed_fields =
abi_util::FindRemovedElements(old_fields_map, new_fields_map);
@@ -184,23 +188,27 @@ DiffWrapperBase::CompareRecordFields(
abi_util::DiffMessageIR::DiffKind diff_kind) {
std::pair<std::vector<abi_util::RecordFieldDiffIR>,
std::vector<const abi_util::RecordFieldIR *>> diffed_and_removed_fields;
std::map<std::string, const abi_util::RecordFieldIR *> old_fields_map;
std::map<std::string, const abi_util::RecordFieldIR *> new_fields_map;
AbiElementMap<const abi_util::RecordFieldIR *> old_fields_map;
AbiElementMap<const abi_util::RecordFieldIR *> new_fields_map;
std::map<uint64_t, const abi_util::RecordFieldIR *> old_fields_offset_map;
std::map<uint64_t, const abi_util::RecordFieldIR *> new_fields_offset_map;
abi_util::AddToMap(&old_fields_map, old_fields,
[](const abi_util::RecordFieldIR *f)
{return f->GetName();});
abi_util::AddToMap(&new_fields_map, new_fields,
[](const abi_util::RecordFieldIR *f)
{return f->GetName();});
abi_util::AddToMap(&old_fields_offset_map, old_fields,
[](const abi_util::RecordFieldIR *f)
{return f->GetOffset();});
abi_util::AddToMap(&new_fields_offset_map, new_fields,
[](const abi_util::RecordFieldIR *f)
{return f->GetOffset();});
abi_util::AddToMap(
&old_fields_map, old_fields,
[](const abi_util::RecordFieldIR *f) {return f->GetName();},
[](const abi_util::RecordFieldIR *f) {return f;});
abi_util::AddToMap(
&new_fields_map, new_fields,
[](const abi_util::RecordFieldIR *f) {return f->GetName();},
[](const abi_util::RecordFieldIR *f) {return f;});
abi_util::AddToMap(
&old_fields_offset_map, old_fields,
[](const abi_util::RecordFieldIR *f) {return f->GetOffset();},
[](const abi_util::RecordFieldIR *f) {return f;});
abi_util::AddToMap(
&new_fields_offset_map, new_fields,
[](const abi_util::RecordFieldIR *f) {return f->GetOffset();},
[](const abi_util::RecordFieldIR *f) {return f;});
// If a field is removed from the map field_name -> offset see if another
// field is present at the same offset and compare the size and type etc,
// remove it from the removed fields if they're compatible.
@@ -522,9 +530,9 @@ DiffStatus DiffWrapperBase::CompareAndDumpTypeDiff(
}
type_queue->push_back(old_type_str);
}
std::map<std::string, const abi_util::TypeIR *>::const_iterator old_it =
AbiElementMap<const abi_util::TypeIR *>::const_iterator old_it =
old_types_.find(old_type_str);
std::map<std::string, const abi_util::TypeIR *>::const_iterator new_it =
AbiElementMap<const abi_util::TypeIR *>::const_iterator new_it =
new_types_.find(new_type_str);
if (old_it == old_types_.end() || new_it == new_types_.end()) {
// Do a simple string comparison.

View File

@@ -28,6 +28,8 @@
namespace abi_diff_wrappers {
using abi_util::AbiElementMap;
template <typename T, typename F>
static bool IgnoreSymbol(const T *element,
const std::set<std::string> &ignored_symbols,
@@ -50,8 +52,8 @@ class DiffWrapperBase {
protected:
DiffWrapperBase(
abi_util::IRDiffDumper *ir_diff_dumper,
const std::map<std::string, const abi_util::TypeIR *> &old_types,
const std::map<std::string, const abi_util::TypeIR *> &new_types,
const AbiElementMap<const abi_util::TypeIR *> &old_types,
const AbiElementMap<const abi_util::TypeIR *> &new_types,
std::set<std::string> *type_cache)
: ir_diff_dumper_(ir_diff_dumper),
old_types_(old_types), new_types_(new_types),
@@ -157,8 +159,8 @@ class DiffWrapperBase {
std::deque<std::string> *type_queue = nullptr);
protected:
abi_util::IRDiffDumper *ir_diff_dumper_;
const std::map<std::string, const abi_util::TypeIR *> &old_types_;
const std::map<std::string, const abi_util::TypeIR *> &new_types_;
const AbiElementMap<const abi_util::TypeIR *> &old_types_;
const AbiElementMap<const abi_util::TypeIR *> &new_types_;
std::set<std::string> *type_cache_;
};
@@ -167,8 +169,8 @@ class DiffWrapper : public DiffWrapperBase {
public:
DiffWrapper(const T *oldp, const T *newp,
abi_util::IRDiffDumper *ir_diff_dumper,
const std::map<std::string, const abi_util::TypeIR *> &old_types,
const std::map<std::string, const abi_util::TypeIR *> &new_types,
const AbiElementMap<const abi_util::TypeIR *> &old_types,
const AbiElementMap<const abi_util::TypeIR *> &new_types,
std::set<std::string> *type_cache)
: DiffWrapperBase(ir_diff_dumper, old_types, new_types, type_cache),
oldp_(oldp), newp_(newp) { }

View File

@@ -85,6 +85,30 @@ static llvm::cl::opt<bool> allow_unreferenced_changes(
" APIs."),
llvm::cl::Optional, llvm::cl::cat(header_checker_category));
static llvm::cl::opt<abi_util::TextFormatIR> text_format_old(
"text-format-old", llvm::cl::desc("Specify text format of old abi dump"),
llvm::cl::values(clEnumValN(abi_util::TextFormatIR::ProtobufTextFormat,
"ProtobufTextFormat","ProtobufTextFormat"),
clEnumValEnd),
llvm::cl::init(abi_util::TextFormatIR::ProtobufTextFormat),
llvm::cl::cat(header_checker_category));
static llvm::cl::opt<abi_util::TextFormatIR> text_format_new(
"text-format-new", llvm::cl::desc("Specify text format of new abi dump"),
llvm::cl::values(clEnumValN(abi_util::TextFormatIR::ProtobufTextFormat,
"ProtobufTextFormat", "ProtobugTextFormat"),
clEnumValEnd),
llvm::cl::init(abi_util::TextFormatIR::ProtobufTextFormat),
llvm::cl::cat(header_checker_category));
static llvm::cl::opt<abi_util::TextFormatIR> text_format_diff(
"text-format-diff", llvm::cl::desc("Specify text format of abi-diff"),
llvm::cl::values(clEnumValN(abi_util::TextFormatIR::ProtobufTextFormat,
"ProtobufTextFormat", "ProtobufTextFormat"),
clEnumValEnd),
llvm::cl::init(abi_util::TextFormatIR::ProtobufTextFormat),
llvm::cl::cat(header_checker_category));
static std::set<std::string> LoadIgnoredSymbols(std::string &symbol_list_path) {
std::ifstream symbol_ifstream(symbol_list_path);
std::set<std::string> ignored_symbols;
@@ -100,14 +124,14 @@ static std::set<std::string> LoadIgnoredSymbols(std::string &symbol_list_path) {
}
int main(int argc, const char **argv) {
GOOGLE_PROTOBUF_VERIFY_VERSION;
llvm::cl::ParseCommandLineOptions(argc, argv, "header-checker");
std::set<std::string> ignored_symbols;
if (llvm::sys::fs::exists(ignore_symbol_list)) {
ignored_symbols = LoadIgnoredSymbols(ignore_symbol_list);
}
HeaderAbiDiff judge(lib_name, arch, old_dump, new_dump, compatibility_report,
ignored_symbols, check_all_apis);
ignored_symbols, check_all_apis, text_format_old,
text_format_new, text_format_diff);
abi_util::CompatibilityStatusIR status = judge.GenerateCompatibilityReport();

View File

@@ -33,7 +33,6 @@ HeaderASTVisitor::HeaderASTVisitor(
clang::MangleContext *mangle_contextp,
clang::ASTContext *ast_contextp,
const clang::CompilerInstance *compiler_instance_p,
const std::string &current_file_name,
const std::set<std::string> &exported_headers,
const clang::Decl *tu_decl,
std::set<std::string> *type_cache,
@@ -41,7 +40,6 @@ HeaderASTVisitor::HeaderASTVisitor(
: mangle_contextp_(mangle_contextp),
ast_contextp_(ast_contextp),
cip_(compiler_instance_p),
current_file_name_(current_file_name),
exported_headers_(exported_headers),
tu_decl_(tu_decl),
type_cache_(type_cache),
@@ -167,14 +165,14 @@ bool HeaderASTVisitor::TraverseDecl(clang::Decl *decl) {
}
HeaderASTConsumer::HeaderASTConsumer(
const std::string &file_name,
clang::CompilerInstance *compiler_instancep,
const std::string &out_dump_name,
const std::set<std::string> &exported_headers)
: file_name_(file_name),
cip_(compiler_instancep),
const std::set<std::string> &exported_headers,
abi_util::TextFormatIR text_format)
: cip_(compiler_instancep),
out_dump_name_(out_dump_name),
exported_headers_(exported_headers) { }
exported_headers_(exported_headers),
text_format_(text_format){ }
void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) {
clang::PrintingPolicy policy(ctx.getPrintingPolicy());
@@ -188,10 +186,9 @@ void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) {
ctx.createMangleContext());
std::set<std::string> type_cache;
std::unique_ptr<abi_util::IRDumper> ir_dumper =
abi_util::IRDumper::CreateIRDumper("protobuf", out_dump_name_);
HeaderASTVisitor v(mangle_contextp.get(), &ctx, cip_, file_name_,
exported_headers_, translation_unit, &type_cache,
ir_dumper.get());
abi_util::IRDumper::CreateIRDumper(text_format_, out_dump_name_);
HeaderASTVisitor v(mangle_contextp.get(), &ctx, cip_, exported_headers_,
translation_unit, &type_cache, ir_dumper.get());
if (!v.TraverseDecl(translation_unit) || !ir_dumper->Dump()) {
llvm::errs() << "Serialization to ostream failed\n";
::exit(1);

View File

@@ -38,7 +38,6 @@ class HeaderASTVisitor
HeaderASTVisitor(clang::MangleContext *mangle_contextp,
clang::ASTContext *ast_contextp,
const clang::CompilerInstance *compiler_instance_p,
const std::string &current_file_name,
const std::set<std::string> &exported_headers,
const clang::Decl *tu_decl,
std::set<std::string> *type_cache,
@@ -63,7 +62,6 @@ class HeaderASTVisitor
clang::MangleContext *mangle_contextp_;
clang::ASTContext *ast_contextp_;
const clang::CompilerInstance *cip_;
const std::string current_file_name_;
const std::set<std::string> &exported_headers_;
// To optimize recursion into only exported abi.
const clang::Decl *tu_decl_;
@@ -76,18 +74,18 @@ class HeaderASTVisitor
class HeaderASTConsumer : public clang::ASTConsumer {
public:
HeaderASTConsumer(const std::string &file_name,
clang::CompilerInstance *compiler_instancep,
HeaderASTConsumer(clang::CompilerInstance *compiler_instancep,
const std::string &out_dump_name,
const std::set<std::string> &exported_headers);
const std::set<std::string> &exported_headers,
abi_util::TextFormatIR text_format);
void HandleTranslationUnit(clang::ASTContext &ctx) override;
private:
std::string file_name_;
clang::CompilerInstance *cip_;
std::string out_dump_name_;
const std::string &out_dump_name_;
const std::set<std::string> &exported_headers_;
abi_util::TextFormatIR text_format_;
};
#endif // AST_PROCESSING_H_

View File

@@ -16,6 +16,7 @@
#include "ast_processing.h"
#include "frontend_action.h"
#include <header_abi_util.h>
#include <ir_representation.h>
#include <clang/AST/ASTConsumer.h>
#include <clang/Frontend/CompilerInstance.h>
@@ -25,13 +26,15 @@
#include <llvm/Support/Path.h>
HeaderCheckerFrontendAction::HeaderCheckerFrontendAction(
const std::string &dump_name, const std::set<std::string> &exported_headers)
: dump_name_(dump_name), exported_headers_(exported_headers) { }
const std::string &dump_name, const std::set<std::string> &exported_headers,
abi_util::TextFormatIR text_format)
: dump_name_(dump_name), exported_headers_(exported_headers),
text_format_(text_format) { }
std::unique_ptr<clang::ASTConsumer>
HeaderCheckerFrontendAction::CreateASTConsumer(clang::CompilerInstance &ci,
llvm::StringRef header_file) {
// Create AST consumers.
return llvm::make_unique<HeaderASTConsumer>(header_file, &ci, dump_name_,
exported_headers_);
return llvm::make_unique<HeaderASTConsumer>(&ci, dump_name_,
exported_headers_, text_format_);
}

View File

@@ -15,6 +15,8 @@
#ifndef FRONTEND_ACTION_H_
#define FRONTEND_ACTION_H_
#include <ir_representation.h>
#include <clang/Frontend/FrontendAction.h>
#include <llvm/ADT/StringRef.h>
@@ -30,13 +32,15 @@ namespace clang {
class HeaderCheckerFrontendAction : public clang::ASTFrontendAction {
private:
std::string dump_name_;
const std::string &dump_name_;
const std::set<std::string> &exported_headers_;
abi_util::TextFormatIR text_format_;
public:
HeaderCheckerFrontendAction(
const std::string &dump_name,
const std::set<std::string> &exported_headers);
const std::set<std::string> &exported_headers,
abi_util::TextFormatIR text_format);
protected:
std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(

View File

@@ -20,9 +20,12 @@
HeaderCheckerFrontendActionFactory::HeaderCheckerFrontendActionFactory(
const std::string &dump_name,
const std::set<std::string> &exported_headers)
: dump_name_(dump_name), exported_headers_(exported_headers) { }
const std::set<std::string> &exported_headers,
abi_util::TextFormatIR text_format)
: dump_name_(dump_name), exported_headers_(exported_headers),
text_format_(text_format) { }
clang::FrontendAction *HeaderCheckerFrontendActionFactory::create() {
return new HeaderCheckerFrontendAction(dump_name_, exported_headers_);
return new HeaderCheckerFrontendAction(dump_name_, exported_headers_,
text_format_);
}

View File

@@ -15,6 +15,7 @@
#ifndef FRONTEND_ACTION_FACTORY_H_
#define FRONTEND_ACTION_FACTORY_H_
#include <ir_representation.h>
#include <clang/Tooling/Tooling.h>
#include <vector>
@@ -22,13 +23,15 @@
class HeaderCheckerFrontendActionFactory
: public clang::tooling::FrontendActionFactory {
private:
std::string dump_name_;
const std::string &dump_name_;
const std::set<std::string> &exported_headers_;
abi_util::TextFormatIR text_format_;
public:
HeaderCheckerFrontendActionFactory(
const std::string &dump_name,
const std::set<std::string> &exported_headers);
const std::set<std::string> &exported_headers,
abi_util::TextFormatIR text_format);
clang::FrontendAction *create() override;
};

View File

@@ -49,6 +49,14 @@ static llvm::cl::opt<bool> no_filter(
"no-filter", llvm::cl::desc("Do not filter any abi"), llvm::cl::Optional,
llvm::cl::cat(header_checker_category));
static llvm::cl::opt<abi_util::TextFormatIR> text_format(
"text-format", llvm::cl::desc("Specify text format of abi dump"),
llvm::cl::values(clEnumValN(abi_util::TextFormatIR::ProtobufTextFormat,
"ProtobufTextFormat", "ProtobufTextFormat"),
clEnumValEnd),
llvm::cl::init(abi_util::TextFormatIR::ProtobufTextFormat),
llvm::cl::cat(header_checker_category));
// Hide irrelevant command line options defined in LLVM libraries.
static void HideIrrelevantCommandLineOptions() {
llvm::StringMap<llvm::cl::Option *> &map = llvm::cl::getRegisteredOptions();
@@ -108,7 +116,8 @@ int main(int argc, const char **argv) {
clang::tooling::ClangTool tool(*compilations, header_files);
std::unique_ptr<clang::tooling::FrontendActionFactory> factory(
new HeaderCheckerFrontendActionFactory(out_dump, exported_headers));
new HeaderCheckerFrontendActionFactory(out_dump, exported_headers,
text_format));
return tool.run(factory.get());
}

View File

@@ -12,28 +12,24 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-parameter"
#pragma clang diagnostic ignored "-Wnested-anon-types"
#include "proto/abi_dump.pb.h"
#pragma clang diagnostic pop
#include <header_abi_util.h>
#include <ir_representation.h>
#include <llvm/Support/CommandLine.h>
#include <llvm/Support/raw_ostream.h>
#include <google/protobuf/text_format.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <memory>
#include <mutex>
#include <fstream>
#include <iostream>
#include <string>
#include <thread>
#include <vector>
#include <stdlib.h>
static constexpr std::size_t kSourcesPerBatchThread = 7;
static llvm::cl::OptionCategory header_linker_category(
"header-abi-linker options");
@@ -69,6 +65,14 @@ static llvm::cl::opt<std::string> so_file(
"so", llvm::cl::desc("<path to so file>"), llvm::cl::Optional,
llvm::cl::cat(header_linker_category));
static llvm::cl::opt<abi_util::TextFormatIR> text_format(
"text-format", llvm::cl::desc("Specify text format of abi dumps"),
llvm::cl::values(clEnumValN(abi_util::TextFormatIR::ProtobufTextFormat,
"ProtobufTextFormat", "ProtobufTextFormat"),
clEnumValEnd),
llvm::cl::init(abi_util::TextFormatIR::ProtobufTextFormat),
llvm::cl::cat(header_linker_category));
class HeaderAbiLinker {
public:
HeaderAbiLinker(
@@ -85,36 +89,30 @@ class HeaderAbiLinker {
bool LinkAndDump();
template <typename T>
static std::string GetLinkageName(T &element) {
return element.type_info().linker_set_key();
}
template <typename T>
static std::string GetSourceFile(T &element) {
return element.type_info().source_file();
}
private:
bool LinkTypes(const abi_dump::TranslationUnit &dump_tu,
abi_dump::TranslationUnit *linked_tu);
bool LinkFunctions(const abi_dump::TranslationUnit &dump_tu,
abi_dump::TranslationUnit *linked_tu);
bool LinkGlobalVars(const abi_dump::TranslationUnit &dump_tu,
abi_dump::TranslationUnit *linked_tu);
template <typename T>
inline bool LinkDecl(google::protobuf::RepeatedPtrField<T> *dst,
inline bool LinkDecl(abi_util::IRDumper *dst,
std::set<std::string> *link_set,
std::set<std::string> *regex_matched_link_set,
const std::regex *vs_regex,
const google::protobuf::RepeatedPtrField<T> &src,
const std::map<std::string, T> &src,
bool use_version_script);
bool ParseVersionScriptFiles();
bool ParseSoFile();
bool AddElfSymbols(abi_dump::TranslationUnit *linked_tu);
bool LinkTypes(const abi_util::TextFormatToIRReader *ir_reader,
abi_util::IRDumper *ir_dumper);
bool LinkFunctions(const abi_util::TextFormatToIRReader *ir_reader,
abi_util::IRDumper *ir_dumper);
bool LinkGlobalVars(const abi_util::TextFormatToIRReader *ir_reader,
abi_util::IRDumper *ir_dumper);
bool AddElfSymbols(abi_util::IRDumper *ir_dumper);
private:
const std::vector<std::string> &dump_files_;
@@ -138,29 +136,56 @@ class HeaderAbiLinker {
};
template <typename T, typename Iterable>
static bool AddElfSymbols(google::protobuf::RepeatedPtrField<T> *dst,
Iterable symbols) {
static bool AddElfSymbols(abi_util::IRDumper *dst, const Iterable &symbols) {
for (auto &&symbol : symbols) {
auto *added_symbol = dst->Add();
if (added_symbol == nullptr) {
T elf_symbol(symbol);
if (!dst->AddElfSymbolMessageIR(&elf_symbol)) {
return false;
}
added_symbol->set_name(symbol);
}
return true;
}
// To be called right after parsing the .so file / version script.
bool HeaderAbiLinker::AddElfSymbols(abi_dump::TranslationUnit *linked_tu) {
bool HeaderAbiLinker::AddElfSymbols(abi_util::IRDumper *ir_dumper) {
return ::AddElfSymbols<abi_util::ElfFunctionIR>(ir_dumper,
function_decl_set_) &&
::AddElfSymbols<abi_util::ElfObjectIR>(ir_dumper,
globvar_decl_set_);
}
return ::AddElfSymbols(linked_tu->mutable_elf_functions(), function_decl_set_)
&& ::AddElfSymbols(linked_tu->mutable_elf_objects(), globvar_decl_set_);
static void DeDuplicateAbiElementsThread(
const std::vector<std::string> &dump_files,
const std::set<std::string> *exported_headers,
abi_util::TextFormatToIRReader *greader, std::mutex *greader_lock,
std::atomic<std::size_t> *cnt) {
std::unique_ptr<abi_util::TextFormatToIRReader> local_reader =
abi_util::TextFormatToIRReader::CreateTextFormatToIRReader(
text_format, exported_headers);
auto begin_it = dump_files.begin();
std::size_t num_sources = dump_files.size();
while (1) {
std::size_t i = cnt->fetch_add(kSourcesPerBatchThread);
if (i >= num_sources) {
break;
}
std::size_t end = std::min(i + kSourcesPerBatchThread, num_sources);
std::unique_ptr<abi_util::TextFormatToIRReader> reader =
abi_util::TextFormatToIRReader::CreateTextFormatToIRReader(
text_format, exported_headers);
assert(reader != nullptr);
if (!reader->ReadDumps(begin_it + i, begin_it + end)) {
llvm::errs() << "ReadDump failed\n";
::exit(1);
}
// This merge is needed since the iterators might not be contigous.
local_reader->Merge(std::move(*reader));
}
std::lock_guard<std::mutex> lock(*greader_lock);
greader->Merge(std::move(*local_reader));
}
bool HeaderAbiLinker::LinkAndDump() {
abi_dump::TranslationUnit linked_tu;
std::ofstream text_output(out_dump_name_);
google::protobuf::io::OstreamOutputStream text_os(&text_output);
// If the user specifies that a version script should be used, use that.
if (!so_file_.empty()) {
exported_headers_ =
@@ -173,22 +198,40 @@ bool HeaderAbiLinker::LinkAndDump() {
llvm::errs() << "Failed to parse stub files for exported symbols\n";
return false;
}
AddElfSymbols(&linked_tu);
for (auto &&i : dump_files_) {
abi_dump::TranslationUnit dump_tu;
std::ifstream input(i);
google::protobuf::io::IstreamInputStream text_is(&input);
if (!google::protobuf::TextFormat::Parse(&text_is, &dump_tu) ||
!LinkTypes(dump_tu, &linked_tu) ||
!LinkFunctions(dump_tu, &linked_tu) ||
!LinkGlobalVars(dump_tu, &linked_tu)) {
llvm::errs() << "Failed to link elements\n";
return false;
}
std::unique_ptr<abi_util::IRDumper> ir_dumper =
abi_util::IRDumper::CreateIRDumper(text_format, out_dump_name_);
assert(ir_dumper != nullptr);
AddElfSymbols(ir_dumper.get());
// Create a reader, on which we never actually call ReadDump(), since multiple
// dump files are associated with it.
std::unique_ptr<abi_util::TextFormatToIRReader> greader =
abi_util::TextFormatToIRReader::CreateTextFormatToIRReader(
text_format, &exported_headers_);
std::size_t max_threads = std::thread::hardware_concurrency();
std::size_t num_threads = kSourcesPerBatchThread < dump_files_.size() ?
std::min(dump_files_.size() / kSourcesPerBatchThread,
max_threads) : 0;
std::vector<std::thread> threads;
std::atomic<std::size_t> cnt(0);
std::mutex greader_lock;
for (std::size_t i = 1; i < num_threads; i++) {
threads.emplace_back(DeDuplicateAbiElementsThread, dump_files_,
&exported_headers_, greader.get(), &greader_lock,
&cnt);
}
if (!google::protobuf::TextFormat::Print(linked_tu, &text_os)) {
DeDuplicateAbiElementsThread(dump_files_, &exported_headers_, greader.get(),
&greader_lock, &cnt);
for (auto &thread : threads) {
thread.join();
}
if (!LinkTypes(greader.get(), ir_dumper.get()) ||
!LinkFunctions(greader.get(), ir_dumper.get()) ||
!LinkGlobalVars(greader.get(), ir_dumper.get())) {
llvm::errs() << "Failed to link elements\n";
return false;
}
if (!ir_dumper->Dump()) {
llvm::errs() << "Serialization to ostream failed\n";
return false;
}
@@ -228,25 +271,24 @@ static std::regex CreateRegexMatchExprFromSet(
return std::regex(all_regex_match_str);
}
//TODO: make linking decls multi-threaded b/63590537.
template <typename T>
inline bool HeaderAbiLinker::LinkDecl(
google::protobuf::RepeatedPtrField<T> *dst, std::set<std::string> *link_set,
abi_util::IRDumper *dst, std::set<std::string> *link_set,
std::set<std::string> *regex_matched_link_set, const std::regex *vs_regex,
const google::protobuf::RepeatedPtrField<T> &src, bool use_version_script) {
const std::map<std::string, T> &src, bool use_version_script) {
assert(dst != nullptr);
assert(link_set != nullptr);
for (auto &&element : src) {
// If we are not using a version script and exported headers are available,
// filter out unexported abi.
std::string source_file = GetSourceFile(element);
std::string source_file = element.second.GetSourceFile();
// Builtin types will not have source file information.
if (!exported_headers_.empty() && !source_file.empty() &&
exported_headers_.find(source_file) ==
exported_headers_.end()) {
continue;
}
std::string element_str = GetLinkageName(element);
const std::string &element_str = element.first;
// Check for the existence of the element in linked dump / symbol file.
if (!use_version_script) {
if (!link_set->insert(element_str).second) {
@@ -264,86 +306,67 @@ inline bool HeaderAbiLinker::LinkDecl(
link_set->erase(*it); // Avoid multiple instances of the same symbol.
}
}
T *added_element = dst->Add();
if (!added_element) {
if (!dst->AddLinkableMessageIR(&(element.second))) {
llvm::errs() << "Failed to add element to linked dump\n";
return false;
}
*added_element = element;
}
return true;
}
template<>
std::string HeaderAbiLinker::GetLinkageName<const abi_dump::FunctionDecl> (
const abi_dump::FunctionDecl &element) {
return element.linker_set_key();
}
template<>
std::string HeaderAbiLinker::GetSourceFile<const abi_dump::FunctionDecl> (
const abi_dump::FunctionDecl &element) {
return element.source_file();
}
template<>
std::string HeaderAbiLinker::GetLinkageName<const abi_dump::GlobalVarDecl> (
const abi_dump::GlobalVarDecl &element) {
return element.linker_set_key();
}
template<>
std::string HeaderAbiLinker::GetSourceFile<const abi_dump::GlobalVarDecl> (
const abi_dump::GlobalVarDecl &element) {
return element.source_file();
}
bool HeaderAbiLinker::LinkTypes(const abi_dump::TranslationUnit &dump_tu,
abi_dump::TranslationUnit *linked_tu) {
assert(linked_tu != nullptr);
bool HeaderAbiLinker::LinkTypes(const abi_util::TextFormatToIRReader *reader,
abi_util::IRDumper *ir_dumper) {
assert(reader != nullptr);
assert(ir_dumper != nullptr);
// Even if version scripts are available we take in types, since the symbols
// in the version script might reference a type exposed by the library.
return LinkDecl(linked_tu->mutable_record_types(), &types_set_, nullptr,
nullptr, dump_tu.record_types(), false) &&
LinkDecl(linked_tu->mutable_enum_types(), &types_set_, nullptr,
nullptr, dump_tu.enum_types(), false) &&
LinkDecl(linked_tu->mutable_builtin_types(), &types_set_, nullptr,
nullptr, dump_tu.builtin_types(), false) &&
LinkDecl(linked_tu->mutable_pointer_types(), &types_set_, nullptr,
nullptr, dump_tu.pointer_types(), false) &&
LinkDecl(linked_tu->mutable_rvalue_reference_types(), &types_set_, nullptr,
nullptr, dump_tu.rvalue_reference_types(), false) &&
LinkDecl(linked_tu->mutable_lvalue_reference_types(), &types_set_, nullptr,
nullptr, dump_tu.lvalue_reference_types(), false) &&
LinkDecl(linked_tu->mutable_array_types(), &types_set_, nullptr,
nullptr, dump_tu.array_types(), false) &&
LinkDecl(linked_tu->mutable_qualified_types(), &types_set_, nullptr,
nullptr, dump_tu.qualified_types(), false);
return LinkDecl(ir_dumper, &types_set_, nullptr,
nullptr, reader->GetRecordTypes(), false) &&
LinkDecl(ir_dumper, &types_set_, nullptr,
nullptr, reader->GetEnumTypes(), false) &&
LinkDecl(ir_dumper, &types_set_, nullptr,
nullptr, reader->GetBuiltinTypes(), false) &&
LinkDecl(ir_dumper, &types_set_, nullptr,
nullptr, reader->GetPointerTypes(), false) &&
LinkDecl(ir_dumper, &types_set_, nullptr,
nullptr, reader->GetRvalueReferenceTypes(), false) &&
LinkDecl(ir_dumper, &types_set_, nullptr,
nullptr, reader->GetLvalueReferenceTypes(), false) &&
LinkDecl(ir_dumper, &types_set_, nullptr,
nullptr, reader->GetArrayTypes(), false) &&
LinkDecl(ir_dumper, &types_set_, nullptr,
nullptr, reader->GetQualifiedTypes(), false);
}
bool HeaderAbiLinker::LinkFunctions(const abi_dump::TranslationUnit &dump_tu,
abi_dump::TranslationUnit *linked_tu) {
assert(linked_tu != nullptr);
return LinkDecl(linked_tu->mutable_functions(), &function_decl_set_,
bool HeaderAbiLinker::LinkFunctions(
const abi_util::TextFormatToIRReader *reader,
abi_util::IRDumper *ir_dumper) {
assert(reader != nullptr);
return LinkDecl(ir_dumper, &function_decl_set_,
&functions_regex_matched_set, &functions_vs_regex_,
dump_tu.functions(),
reader->GetFunctions(),
(!version_script_.empty() || !so_file_.empty()));
}
bool HeaderAbiLinker::LinkGlobalVars(const abi_dump::TranslationUnit &dump_tu,
abi_dump::TranslationUnit *linked_tu) {
assert(linked_tu != nullptr);
return LinkDecl(linked_tu->mutable_global_vars(), &globvar_decl_set_,
bool HeaderAbiLinker::LinkGlobalVars(
const abi_util::TextFormatToIRReader *reader,
abi_util::IRDumper *ir_dumper) {
assert(reader != nullptr);
return LinkDecl(ir_dumper, &globvar_decl_set_,
&globvars_regex_matched_set, &globvars_vs_regex_,
dump_tu.global_vars(),
reader->GetGlobalVariables(),
(!version_script.empty() || !so_file_.empty()));
}
bool HeaderAbiLinker::ParseVersionScriptFiles() {
abi_util::VersionScriptParser version_script_parser(version_script_, arch_,
api_);
if (!version_script_parser.Parse()) {
llvm::errs() << "Failed to parse version script\n";
return false;
}
function_decl_set_ = version_script_parser.GetFunctions();
@@ -384,7 +407,6 @@ bool HeaderAbiLinker::ParseSoFile() {
}
int main(int argc, const char **argv) {
GOOGLE_PROTOBUF_VERIFY_VERSION;
llvm::cl::ParseCommandLineOptions(argc, argv, "header-linker");
if (so_file.empty() && version_script.empty()) {
llvm::errs() << "One of -so or -v needs to be specified\n";
@@ -397,6 +419,7 @@ int main(int argc, const char **argv) {
so_file, linked_dump, arch, api);
if (!Linker.LinkAndDump()) {
llvm::errs() << "Failed to link and dump elements\n";
return -1;
}
return 0;

View File

@@ -146,15 +146,17 @@ std::vector<T> FindRemovedElements(
return removed_elements;
}
template <typename T, typename F, typename K, typename Iterable>
inline void AddToMap(std::map<K, T> *dst, Iterable &src, F get_key) {
template <typename K, typename T, typename Iterable, typename KeyGetter,
typename ValueGetter>
inline void AddToMap(std::map<K, T> *dst, Iterable &src, KeyGetter get_key,
ValueGetter get_value) {
for (auto &&element : src) {
dst->insert(std::make_pair(get_key(&element), &element));
dst->insert(std::make_pair(get_key(&element), get_value(&element)));
}
}
template <typename F, typename K, typename Iterable>
inline void AddToSet(std::set<K> *dst, Iterable &src, F get_key) {
template <typename K, typename Iterable, typename KeyGetter>
inline void AddToSet(std::set<K> *dst, Iterable &src, KeyGetter get_key) {
for (auto &&element : src) {
dst->insert(get_key(element));
}

View File

@@ -25,6 +25,13 @@
// message format specific dumpers.
namespace abi_util {
template <typename T>
using AbiElementMap = std::map<std::string, T>;
enum TextFormatIR {
ProtobufTextFormat = 0,
};
enum CompatibilityStatusIR {
Compatible = 0,
UnreferencedChanges = 1,
@@ -691,11 +698,13 @@ class IRDumper {
public:
IRDumper(const std::string &dump_path) : dump_path_(dump_path) { }
static std::unique_ptr<IRDumper> CreateIRDumper(const std::string &type,
const std::string &dump_path);
static std::unique_ptr<IRDumper> CreateIRDumper(
TextFormatIR text_format, const std::string &dump_path);
virtual bool AddLinkableMessageIR(const LinkableMessageIR *) = 0;
virtual bool AddElfSymbolMessageIR(const ElfSymbolIR *) = 0;
virtual bool Dump() = 0;
virtual ~IRDumper() {}
@@ -706,77 +715,116 @@ class IRDumper {
class TextFormatToIRReader {
public:
TextFormatToIRReader(const std::string &dump_path) : dump_path_(dump_path) { }
const std::vector<FunctionIR> &GetFunctions() const {
TextFormatToIRReader(const std::set<std::string> *exported_headers)
: exported_headers_(exported_headers) { }
const AbiElementMap<FunctionIR> &GetFunctions() const {
return functions_;
}
const std::vector<GlobalVarIR> &GetGlobalVariables() const {
const AbiElementMap<GlobalVarIR> &GetGlobalVariables() const {
return global_variables_;
}
const std::vector<RecordTypeIR> &GetRecordTypes() const {
const AbiElementMap<RecordTypeIR> &GetRecordTypes() const {
return record_types_;
}
const std::vector<EnumTypeIR> &GetEnumTypes() const {
const AbiElementMap<EnumTypeIR> &GetEnumTypes() const {
return enum_types_;
}
const std::vector<LvalueReferenceTypeIR> &GetLvalueReferenceTypes() const {
const AbiElementMap<LvalueReferenceTypeIR> &
GetLvalueReferenceTypes() const {
return lvalue_reference_types_;
}
const std::vector<RvalueReferenceTypeIR> &GetRvalueReferenceTypes() const {
const AbiElementMap<RvalueReferenceTypeIR> &
GetRvalueReferenceTypes() const {
return rvalue_reference_types_;
}
const std::vector<QualifiedTypeIR> &GetQualifiedTypes() const {
const AbiElementMap<QualifiedTypeIR> &GetQualifiedTypes() const {
return qualified_types_;
}
const std::vector<ArrayTypeIR> &GetArrayTypes() const {
const AbiElementMap<ArrayTypeIR> &GetArrayTypes() const {
return array_types_;
}
const std::vector<PointerTypeIR> &GetPointerTypes() const {
const AbiElementMap<PointerTypeIR> &GetPointerTypes() const {
return pointer_types_;
}
const std::vector<BuiltinTypeIR> &GetBuiltinTypes() const {
const AbiElementMap<BuiltinTypeIR> &GetBuiltinTypes() const {
return builtin_types_;
}
const std::vector<ElfFunctionIR> &GetElfFunctions() const {
const AbiElementMap<ElfFunctionIR> &GetElfFunctions() const {
return elf_functions_;
}
const std::vector<ElfObjectIR> &GetElfObjects() const {
const AbiElementMap<ElfObjectIR> &GetElfObjects() const {
return elf_objects_;
}
virtual bool ReadDump() = 0;
virtual bool ReadDump(const std::string &dump_file) = 0;
template <typename Iterator>
bool ReadDumps(Iterator begin, Iterator end) {
Iterator it = begin;
while(it != end) {
if (!ReadDump(*it)) {
return false;
}
++it;
}
return true;
}
virtual ~TextFormatToIRReader() { }
void Merge(TextFormatToIRReader &&addend) {
MergeElements(&functions_, std::move(addend.functions_));
MergeElements(&global_variables_, std::move(addend.global_variables_));
MergeElements(&record_types_, std::move(addend.record_types_));
MergeElements(&enum_types_, std::move(addend.enum_types_));
MergeElements(&pointer_types_, std::move(addend.pointer_types_));
MergeElements(&lvalue_reference_types_,
std::move(addend.lvalue_reference_types_));
MergeElements(&rvalue_reference_types_,
std::move(addend.rvalue_reference_types_));
MergeElements(&array_types_, std::move(addend.array_types_));
MergeElements(&builtin_types_, std::move(addend.builtin_types_));
MergeElements(&qualified_types_, std::move(addend.qualified_types_));
}
static std::unique_ptr<TextFormatToIRReader> CreateTextFormatToIRReader(
const std::string &text_format, const std::string &dump_path);
TextFormatIR text_format,
const std::set<std::string> *exported_headers = nullptr);
protected:
const std::string &dump_path_;
std::vector<FunctionIR> functions_;
std::vector<GlobalVarIR> global_variables_;
std::vector<RecordTypeIR> record_types_;
std::vector<EnumTypeIR> enum_types_;
std::vector<PointerTypeIR> pointer_types_;
std::vector<LvalueReferenceTypeIR> lvalue_reference_types_;
std::vector<RvalueReferenceTypeIR> rvalue_reference_types_;
std::vector<ArrayTypeIR> array_types_;
std::vector<BuiltinTypeIR> builtin_types_;
std::vector<QualifiedTypeIR> qualified_types_;
std::vector<ElfFunctionIR> elf_functions_;
std::vector<ElfObjectIR> elf_objects_;
template <typename Augend, typename Addend>
inline void MergeElements(Augend *augend, Addend &&addend) {
augend->insert(std::make_move_iterator(addend.begin()),
std::make_move_iterator(addend.end()));
}
AbiElementMap<FunctionIR> functions_;
AbiElementMap<GlobalVarIR> global_variables_;
AbiElementMap<RecordTypeIR> record_types_;
AbiElementMap<EnumTypeIR> enum_types_;
AbiElementMap<PointerTypeIR> pointer_types_;
AbiElementMap<LvalueReferenceTypeIR> lvalue_reference_types_;
AbiElementMap<RvalueReferenceTypeIR> rvalue_reference_types_;
AbiElementMap<ArrayTypeIR> array_types_;
AbiElementMap<BuiltinTypeIR> builtin_types_;
AbiElementMap<QualifiedTypeIR> qualified_types_;
AbiElementMap<ElfFunctionIR> elf_functions_;
AbiElementMap<ElfObjectIR> elf_objects_;
const std::set<std::string> *exported_headers_;
};
class DiffMessageIR {
@@ -1120,7 +1168,7 @@ class IRDiffDumper {
virtual ~IRDiffDumper() {}
static std::unique_ptr<IRDiffDumper> CreateIRDiffDumper(
const std::string &type, const std::string &dump_path);
TextFormatIR, const std::string &dump_path);
protected:
const std::string &dump_path_;
};

View File

@@ -270,11 +270,17 @@ class ProtobufIRDumper : public IRDumper, public IRToProtobufConverter {
bool AddGlobalVarIR(const GlobalVarIR *);
bool AddElfFunctionIR(const ElfFunctionIR *);
bool AddElfObjectIR(const ElfObjectIR *);
public:
ProtobufIRDumper(const std::string &dump_path)
: IRDumper(dump_path), tu_ptr_(new abi_dump::TranslationUnit()) { }
bool AddLinkableMessageIR(const LinkableMessageIR *);
bool AddLinkableMessageIR(const LinkableMessageIR *) override;
bool AddElfSymbolMessageIR(const ElfSymbolIR *) override;
bool Dump() override;
@@ -288,44 +294,35 @@ class ProtobufIRDumper : public IRDumper, public IRToProtobufConverter {
class ProtobufTextFormatToIRReader : public TextFormatToIRReader {
public:
virtual bool ReadDump() override;
ProtobufTextFormatToIRReader(const std::set<std::string> *exported_headers)
: TextFormatToIRReader(exported_headers) { }
ProtobufTextFormatToIRReader(const std::string &dump_path)
: TextFormatToIRReader(dump_path) { }
bool ReadDump(const std::string &dump_file) override;
private:
std::vector<FunctionIR> ReadFunctions(
const abi_dump::TranslationUnit &tu);
void ReadFunctions(const abi_dump::TranslationUnit &tu);
std::vector<GlobalVarIR> ReadGlobalVariables(
const abi_dump::TranslationUnit &tu);
void ReadGlobalVariables(const abi_dump::TranslationUnit &tu);
std::vector<EnumTypeIR> ReadEnumTypes(const abi_dump::TranslationUnit &tu);
void ReadEnumTypes(const abi_dump::TranslationUnit &tu);
std::vector<RecordTypeIR> ReadRecordTypes(
const abi_dump::TranslationUnit &tu);
void ReadRecordTypes(const abi_dump::TranslationUnit &tu);
std::vector<PointerTypeIR> ReadPointerTypes(
const abi_dump::TranslationUnit &tu);
void ReadPointerTypes(const abi_dump::TranslationUnit &tu);
std::vector<BuiltinTypeIR> ReadBuiltinTypes(
const abi_dump::TranslationUnit &tu);
void ReadBuiltinTypes(const abi_dump::TranslationUnit &tu);
std::vector<QualifiedTypeIR> ReadQualifiedTypes(
const abi_dump::TranslationUnit &tu);
void ReadQualifiedTypes(const abi_dump::TranslationUnit &tu);
std::vector<ArrayTypeIR> ReadArrayTypes(const abi_dump::TranslationUnit &tu);
void ReadArrayTypes(const abi_dump::TranslationUnit &tu);
std::vector<LvalueReferenceTypeIR> ReadLvalueReferenceTypes(
const abi_dump::TranslationUnit &tu);
void ReadLvalueReferenceTypes(const abi_dump::TranslationUnit &tu);
std::vector<RvalueReferenceTypeIR> ReadRvalueReferenceTypes(
const abi_dump::TranslationUnit &tu);
void ReadRvalueReferenceTypes(const abi_dump::TranslationUnit &tu);
std::vector<ElfFunctionIR> ReadElfFunctions (
const abi_dump::TranslationUnit &tu);
void ReadElfFunctions (const abi_dump::TranslationUnit &tu);
std::vector<ElfObjectIR> ReadElfObjects (const abi_dump::TranslationUnit &tu);
void ReadElfObjects (const abi_dump::TranslationUnit &tu);
void ReadTypeInfo(const abi_dump::BasicNamedAndTypedDecl &type_info,
TypeIR *typep);

View File

@@ -33,34 +33,40 @@
namespace abi_util {
std::unique_ptr<IRDumper> IRDumper::CreateIRDumper(
const std::string &type, const std::string &dump_path) {
if (type == "protobuf") {
return std::make_unique<ProtobufIRDumper>(dump_path);
TextFormatIR text_format, const std::string &dump_path) {
switch (text_format) {
case TextFormatIR::ProtobufTextFormat:
return std::make_unique<ProtobufIRDumper>(dump_path);
default:
// Nothing else is supported yet.
llvm::errs() << "Text format not supported yet\n";
return nullptr;
}
// Nothing else is supported yet.
llvm::errs() << type << " message format is not supported yet!\n";
return nullptr;
}
std::unique_ptr<IRDiffDumper> IRDiffDumper::CreateIRDiffDumper(
const std::string &type, const std::string &dump_path) {
if (type == "protobuf") {
return std::make_unique<ProtobufIRDiffDumper>(dump_path);
TextFormatIR text_format, const std::string &dump_path) {
switch (text_format) {
case TextFormatIR::ProtobufTextFormat:
return std::make_unique<ProtobufIRDiffDumper>(dump_path);
default:
// Nothing else is supported yet.
llvm::errs() << "Text format not supported yet\n";
return nullptr;
}
// Nothing else is supported yet.
llvm::errs() << type << " message format is not supported yet!\n";
return nullptr;
}
std::unique_ptr<TextFormatToIRReader>
TextFormatToIRReader::CreateTextFormatToIRReader(
const std::string &type, const std::string &dump_path) {
if (type == "protobuf") {
return std::make_unique<ProtobufTextFormatToIRReader>(dump_path);
TextFormatIR text_format, const std::set<std::string> *exported_headers) {
switch (text_format) {
case TextFormatIR::ProtobufTextFormat:
return std::make_unique<ProtobufTextFormatToIRReader>(exported_headers);
default:
// Nothing else is supported yet.
llvm::errs() << "Text format not supported yet\n";
return nullptr;
}
// Nothing else is supported yet.
llvm::errs() << type << " message format is not supported yet!\n";
return nullptr;
}
} // namespace abi_util

View File

@@ -23,6 +23,16 @@
namespace abi_util {
static bool IsPresentInExportedHeaders(
const LinkableMessageIR &linkable_message,
const std::set<std::string> *exported_headers) {
if (exported_headers == nullptr || exported_headers->empty()) {
return true;
}
return exported_headers->find(linkable_message.GetSourceFile())
!= exported_headers->end();
}
void ProtobufTextFormatToIRReader::ReadTypeInfo(
const abi_dump::BasicNamedAndTypedDecl &type_info,
TypeIR *typep) {
@@ -34,9 +44,9 @@ void ProtobufTextFormatToIRReader::ReadTypeInfo(
typep->SetAlignment(type_info.alignment());
}
bool ProtobufTextFormatToIRReader::ReadDump() {
bool ProtobufTextFormatToIRReader::ReadDump(const std::string &dump_file) {
abi_dump::TranslationUnit tu;
std::ifstream input(dump_path_);
std::ifstream input(dump_file);
google::protobuf::io::IstreamInputStream text_is(&input);
if (!google::protobuf::TextFormat::Parse(&text_is, &tu)) {
@@ -44,21 +54,20 @@ bool ProtobufTextFormatToIRReader::ReadDump() {
return false;
}
functions_ = ReadFunctions(tu);
global_variables_ = ReadGlobalVariables(tu);
ReadFunctions(tu);
ReadGlobalVariables(tu);
enum_types_ = ReadEnumTypes(tu);
record_types_ = ReadRecordTypes(tu);
array_types_ = ReadArrayTypes(tu);
pointer_types_ = ReadPointerTypes(tu);
qualified_types_ = ReadQualifiedTypes(tu);
builtin_types_ = ReadBuiltinTypes(tu);
lvalue_reference_types_ = ReadLvalueReferenceTypes(tu);
rvalue_reference_types_ = ReadRvalueReferenceTypes(tu);
elf_functions_ = ReadElfFunctions(tu);
elf_objects_ = ReadElfObjects(tu);
ReadEnumTypes(tu);
ReadRecordTypes(tu);
ReadArrayTypes(tu);
ReadPointerTypes(tu);
ReadQualifiedTypes(tu);
ReadBuiltinTypes(tu);
ReadLvalueReferenceTypes(tu);
ReadRvalueReferenceTypes(tu);
ReadElfFunctions(tu);
ReadElfObjects(tu);
return true;
}
@@ -171,9 +180,8 @@ EnumTypeIR ProtobufTextFormatToIRReader::EnumTypeProtobufToIR(
return enum_type_ir;
}
std::vector<GlobalVarIR> ProtobufTextFormatToIRReader::ReadGlobalVariables(
void ProtobufTextFormatToIRReader::ReadGlobalVariables(
const abi_dump::TranslationUnit &tu) {
std::vector<GlobalVarIR> global_variables;
for (auto &&global_variable_protobuf : tu.global_vars()) {
GlobalVarIR global_variable_ir;
global_variable_ir.SetName(global_variable_protobuf.name());
@@ -182,38 +190,44 @@ std::vector<GlobalVarIR> ProtobufTextFormatToIRReader::ReadGlobalVariables(
global_variable_protobuf.referenced_type());
global_variable_ir.SetLinkerSetKey(
global_variable_protobuf.linker_set_key());
global_variables.emplace_back(std::move(global_variable_ir));
if (!IsPresentInExportedHeaders(global_variable_ir, exported_headers_)) {
continue;
}
global_variables_.insert(
{global_variable_ir.GetLinkerSetKey(), std::move(global_variable_ir)});
}
return global_variables;
}
std::vector<PointerTypeIR> ProtobufTextFormatToIRReader::ReadPointerTypes(
void ProtobufTextFormatToIRReader::ReadPointerTypes(
const abi_dump::TranslationUnit &tu) {
std::vector<PointerTypeIR> pointer_types;
for (auto &&pointer_type_protobuf : tu.pointer_types()) {
PointerTypeIR pointer_type_ir;
ReadTypeInfo(pointer_type_protobuf.type_info(), &pointer_type_ir);
pointer_types.emplace_back(std::move(pointer_type_ir));
if (!IsPresentInExportedHeaders(pointer_type_ir, exported_headers_)) {
continue;
}
pointer_types_.insert(
{pointer_type_ir.GetLinkerSetKey(), std::move(pointer_type_ir)});
}
return pointer_types;
}
std::vector<BuiltinTypeIR> ProtobufTextFormatToIRReader::ReadBuiltinTypes(
void ProtobufTextFormatToIRReader::ReadBuiltinTypes(
const abi_dump::TranslationUnit &tu) {
std::vector<BuiltinTypeIR> builtin_types;
for (auto &&builtin_type_protobuf : tu.builtin_types()) {
BuiltinTypeIR builtin_type_ir;
ReadTypeInfo(builtin_type_protobuf.type_info(), &builtin_type_ir);
builtin_type_ir.SetSignedness(builtin_type_protobuf.is_unsigned());
builtin_type_ir.SetIntegralType(builtin_type_protobuf.is_integral());
builtin_types.emplace_back(std::move(builtin_type_ir));
if (!IsPresentInExportedHeaders(builtin_type_ir, exported_headers_)) {
continue;
}
builtin_types_.insert(
{builtin_type_ir.GetLinkerSetKey(), std::move(builtin_type_ir)});
}
return builtin_types;
}
std::vector<QualifiedTypeIR> ProtobufTextFormatToIRReader::ReadQualifiedTypes(
void ProtobufTextFormatToIRReader::ReadQualifiedTypes(
const abi_dump::TranslationUnit &tu) {
std::vector<QualifiedTypeIR> qualified_types;
for (auto &&qualified_type_protobuf : tu.qualified_types()) {
QualifiedTypeIR qualified_type_ir;
ReadTypeInfo(qualified_type_protobuf.type_info(), &qualified_type_ir);
@@ -221,94 +235,110 @@ std::vector<QualifiedTypeIR> ProtobufTextFormatToIRReader::ReadQualifiedTypes(
qualified_type_ir.SetVolatility(qualified_type_protobuf.is_volatile());
qualified_type_ir.SetRestrictedness(
qualified_type_protobuf.is_restricted());
qualified_types.emplace_back(std::move(qualified_type_ir));
if (!IsPresentInExportedHeaders(qualified_type_ir, exported_headers_)) {
continue;
}
qualified_types_.insert(
{qualified_type_ir.GetLinkerSetKey(), std::move(qualified_type_ir)});
}
return qualified_types;
}
std::vector<ArrayTypeIR> ProtobufTextFormatToIRReader::ReadArrayTypes(
void ProtobufTextFormatToIRReader::ReadArrayTypes(
const abi_dump::TranslationUnit &tu) {
std::vector<ArrayTypeIR> array_types;
for (auto &&array_type_protobuf : tu.array_types()) {
ArrayTypeIR array_type_ir;
ReadTypeInfo(array_type_protobuf.type_info(), &array_type_ir);
array_types.emplace_back(std::move(array_type_ir));
if (!IsPresentInExportedHeaders(array_type_ir, exported_headers_)) {
continue;
}
array_types_.insert(
{array_type_ir.GetLinkerSetKey(), std::move(array_type_ir)});
}
return array_types;
}
std::vector<LvalueReferenceTypeIR>
ProtobufTextFormatToIRReader::ReadLvalueReferenceTypes(
void ProtobufTextFormatToIRReader::ReadLvalueReferenceTypes(
const abi_dump::TranslationUnit &tu) {
std::vector<LvalueReferenceTypeIR> lvalue_reference_types;
for (auto &&lvalue_reference_type_protobuf : tu.lvalue_reference_types()) {
LvalueReferenceTypeIR lvalue_reference_type_ir;
ReadTypeInfo(lvalue_reference_type_protobuf.type_info(),
&lvalue_reference_type_ir);
lvalue_reference_types.emplace_back(std::move(lvalue_reference_type_ir));
if (!IsPresentInExportedHeaders(lvalue_reference_type_ir,
exported_headers_)) {
continue;
}
lvalue_reference_types_.insert(
{lvalue_reference_type_ir.GetLinkerSetKey(),
std::move(lvalue_reference_type_ir)});
}
return lvalue_reference_types;
}
std::vector<RvalueReferenceTypeIR>
ProtobufTextFormatToIRReader::ReadRvalueReferenceTypes(
void ProtobufTextFormatToIRReader::ReadRvalueReferenceTypes(
const abi_dump::TranslationUnit &tu) {
std::vector<RvalueReferenceTypeIR> rvalue_reference_types;
for (auto &&rvalue_reference_type_protobuf : tu.rvalue_reference_types()) {
RvalueReferenceTypeIR rvalue_reference_type_ir;
ReadTypeInfo(rvalue_reference_type_protobuf.type_info(),
&rvalue_reference_type_ir);
rvalue_reference_types.emplace_back(std::move(rvalue_reference_type_ir));
if (!IsPresentInExportedHeaders(rvalue_reference_type_ir,
exported_headers_)) {
continue;
}
rvalue_reference_types_.insert(
{rvalue_reference_type_ir.GetLinkerSetKey(),
std::move(rvalue_reference_type_ir)});
}
return rvalue_reference_types;
}
std::vector<FunctionIR> ProtobufTextFormatToIRReader::ReadFunctions(
void ProtobufTextFormatToIRReader::ReadFunctions(
const abi_dump::TranslationUnit &tu) {
std::vector<FunctionIR> functions;
for (auto &&function_protobuf : tu.functions()) {
FunctionIR function_ir = FunctionProtobufToIR(function_protobuf);
functions.emplace_back(std::move(function_ir));
if (!IsPresentInExportedHeaders(function_ir, exported_headers_)) {
continue;
}
functions_.insert({function_ir.GetLinkerSetKey(), std::move(function_ir)});
}
return functions;
}
std::vector<RecordTypeIR> ProtobufTextFormatToIRReader::ReadRecordTypes(
void ProtobufTextFormatToIRReader::ReadRecordTypes(
const abi_dump::TranslationUnit &tu) {
std::vector<RecordTypeIR> record_types;
for (auto &&record_type_protobuf : tu.record_types()) {
RecordTypeIR record_type_ir = RecordTypeProtobufToIR(record_type_protobuf);
record_types.emplace_back(std::move(record_type_ir));
if (!IsPresentInExportedHeaders(record_type_ir, exported_headers_)) {
continue;
}
record_types_.insert(
{record_type_ir.GetLinkerSetKey(), std::move(record_type_ir)});
}
return record_types;
}
std::vector<EnumTypeIR> ProtobufTextFormatToIRReader::ReadEnumTypes(
void ProtobufTextFormatToIRReader::ReadEnumTypes(
const abi_dump::TranslationUnit &tu) {
std::vector<EnumTypeIR> enum_types;
for (auto &&enum_type_protobuf : tu.enum_types()) {
EnumTypeIR enum_type_ir = EnumTypeProtobufToIR(enum_type_protobuf);
enum_types.emplace_back(std::move(enum_type_ir));
if (!IsPresentInExportedHeaders(enum_type_ir, exported_headers_)) {
continue;
}
enum_types_.insert(
{enum_type_ir.GetLinkerSetKey(), std::move(enum_type_ir)});
}
return enum_types;
}
std::vector<ElfFunctionIR> ProtobufTextFormatToIRReader::ReadElfFunctions(
void ProtobufTextFormatToIRReader::ReadElfFunctions(
const abi_dump::TranslationUnit &tu) {
std::vector<ElfFunctionIR> elf_functions;
for (auto &&elf_function : tu.elf_functions()) {
elf_functions.emplace_back(ElfFunctionIR(elf_function.name()));
ElfFunctionIR elf_function_ir(elf_function.name());
elf_functions_.insert(
{elf_function_ir.GetName(), std::move(elf_function_ir)});
}
return elf_functions;
}
std::vector<ElfObjectIR> ProtobufTextFormatToIRReader::ReadElfObjects(
void ProtobufTextFormatToIRReader::ReadElfObjects(
const abi_dump::TranslationUnit &tu) {
std::vector<ElfObjectIR> elf_objects;
for (auto &&elf_object : tu.elf_objects()) {
elf_objects.emplace_back(ElfObjectIR(elf_object.name()));
ElfObjectIR elf_object_ir(elf_object.name());
elf_objects_.insert(
{elf_object_ir.GetName(), std::move(elf_object_ir)});
}
return elf_objects;
}
bool IRToProtobufConverter::AddTemplateInformation(
@@ -903,6 +933,34 @@ bool ProtobufIRDumper::AddLinkableMessageIR (const LinkableMessageIR *lm) {
return false;
}
bool ProtobufIRDumper::AddElfFunctionIR(const ElfFunctionIR *elf_function) {
abi_dump::ElfFunction *added_elf_function = tu_ptr_->add_elf_functions();
if (!added_elf_function) {
return false;
}
added_elf_function->set_name(elf_function->GetName());
return true;
}
bool ProtobufIRDumper::AddElfObjectIR(const ElfObjectIR *elf_object) {
abi_dump::ElfObject *added_elf_object = tu_ptr_->add_elf_objects();
if (!added_elf_object) {
return false;
}
added_elf_object->set_name(elf_object->GetName());
return true;
}
bool ProtobufIRDumper::AddElfSymbolMessageIR(const ElfSymbolIR *em) {
switch (em->GetKind()) {
case ElfSymbolIR::ElfFunctionKind:
return AddElfFunctionIR(static_cast<const ElfFunctionIR *>(em));
case ElfSymbolIR::ElfObjectKind:
return AddElfObjectIR(static_cast<const ElfObjectIR *>(em));
}
return false;
}
bool ProtobufIRDumper::AddRecordTypeIR(const RecordTypeIR *recordp) {
abi_dump::RecordType *added_record_type = tu_ptr_->add_record_types();
if (!added_record_type) {