Add more flexibility to abi checking.

1) Marking a field "required" robs us of flexibility. Make fields optional
allows us to update the message format without needing to necessarily
update the reference abi-dumps.

2) Allow local warnings with the invocation of header-abi-diff.

Test: Added a function to libjpeg, got a warning claiming abi extended.

3) Introduce a flag which allows us to not filter any abi. This is
useful for cases when libraries do not include what they export. eg :
libsqlite.

Test: abi-dump size of libsqlite:
	without no-filter : 0
	with no-filter : ~9M

Change-Id: I6cfeacc8711f6df7a4136c2a27b5638988a2c54b
This commit is contained in:
Jayant Chowdhary
2017-05-23 13:49:40 -07:00
parent 0a318e9244
commit e6a88775e9
6 changed files with 78 additions and 35 deletions

View File

@@ -294,6 +294,7 @@ DiffWrapper<FunctionDecl, FunctionDeclDiff>::Get() {
google::protobuf::RepeatedPtrField<ParamDeclDiff> *pdiffs = google::protobuf::RepeatedPtrField<ParamDeclDiff> *pdiffs =
func_diff->mutable_param_diffs(); func_diff->mutable_param_diffs();
assert(func_diff->mutable_return_type_diffs() != nullptr); assert(func_diff->mutable_return_type_diffs() != nullptr);
func_diff->set_name(oldp_->basic_abi().linker_set_key());
if (DiffBasicNamedAndTypedDecl( if (DiffBasicNamedAndTypedDecl(
func_diff->mutable_return_type_diffs()->mutable_old(), func_diff->mutable_return_type_diffs()->mutable_old(),
func_diff->mutable_return_type_diffs()->mutable_new_(), func_diff->mutable_return_type_diffs()->mutable_new_(),

View File

@@ -49,6 +49,10 @@ static llvm::cl::opt<bool> advice_only(
"advice-only", llvm::cl::desc("Advisory mode only"), llvm::cl::Optional, "advice-only", llvm::cl::desc("Advisory mode only"), llvm::cl::Optional,
llvm::cl::cat(header_checker_category)); llvm::cl::cat(header_checker_category));
static llvm::cl::opt<bool> suppress_local_warnings(
"suppress_local_warnings", llvm::cl::desc("suppress local warnings"),
llvm::cl::Optional, llvm::cl::cat(header_checker_category));
static llvm::cl::opt<bool> allow_extensions( static llvm::cl::opt<bool> allow_extensions(
"allow-extensions", "allow-extensions",
llvm::cl::desc("Do not return a non zero status on extensions"), llvm::cl::desc("Do not return a non zero status on extensions"),
@@ -80,6 +84,28 @@ int main(int argc, const char **argv) {
CompatibilityStatus status = judge.GenerateCompatibilityReport(); CompatibilityStatus status = judge.GenerateCompatibilityReport();
std::string status_str = "";
switch (status) {
case CompatibilityStatus::INCOMPATIBLE:
status_str = "broken";
break;
case CompatibilityStatus::EXTENSION:
status_str = "extended";
break;
default:
break;
}
if (!suppress_local_warnings && status) {
llvm::errs() << "******************************************************\n"
<< "VNDK Abi "
<< status_str
<< ":"
<< " Please check compatiblity report at : "
<< compatibility_report << "\n"
<< "*****************************************************\n";
}
if (advice_only) { if (advice_only) {
return CompatibilityStatus::COMPATIBLE; return CompatibilityStatus::COMPATIBLE;
} }

View File

@@ -44,6 +44,10 @@ static llvm::cl::list<std::string> exported_header_dirs(
"I", llvm::cl::desc("<export_include_dirs>"), llvm::cl::Prefix, "I", llvm::cl::desc("<export_include_dirs>"), llvm::cl::Prefix,
llvm::cl::ZeroOrMore, llvm::cl::cat(header_checker_category)); llvm::cl::ZeroOrMore, llvm::cl::cat(header_checker_category));
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));
// Hide irrelevant command line options defined in LLVM libraries. // Hide irrelevant command line options defined in LLVM libraries.
static void HideIrrelevantCommandLineOptions() { static void HideIrrelevantCommandLineOptions() {
llvm::StringMap<llvm::cl::Option *> &map = llvm::cl::getRegisteredOptions(); llvm::StringMap<llvm::cl::Option *> &map = llvm::cl::getRegisteredOptions();
@@ -92,6 +96,10 @@ int main(int argc, const char **argv) {
::exit(1); ::exit(1);
} }
if (no_filter) {
static_cast<std::vector<std::string> &>(exported_header_dirs).clear();
}
// Initialize clang tools and run front-end action. // Initialize clang tools and run front-end action.
std::vector<std::string> header_files{ header_file }; std::vector<std::string> header_files{ header_file };

View File

@@ -61,6 +61,10 @@ static llvm::cl::opt<std::string> arch(
"arch", llvm::cl::desc("<arch>"), llvm::cl::Optional, "arch", llvm::cl::desc("<arch>"), llvm::cl::Optional,
llvm::cl::cat(header_linker_category)); llvm::cl::cat(header_linker_category));
static llvm::cl::opt<bool> no_filter(
"no-filter", llvm::cl::desc("Do not filter any abi"), llvm::cl::Optional,
llvm::cl::cat(header_linker_category));
class HeaderAbiLinker { class HeaderAbiLinker {
public: public:
HeaderAbiLinker( HeaderAbiLinker(
@@ -301,6 +305,9 @@ bool HeaderAbiLinker::ParseVersionScriptFiles() {
int main(int argc, const char **argv) { int main(int argc, const char **argv) {
GOOGLE_PROTOBUF_VERIFY_VERSION; GOOGLE_PROTOBUF_VERIFY_VERSION;
llvm::cl::ParseCommandLineOptions(argc, argv, "header-linker"); llvm::cl::ParseCommandLineOptions(argc, argv, "header-linker");
if (no_filter) {
static_cast<std::vector<std::string> &>(exported_header_dirs).clear();
}
HeaderAbiLinker Linker(dump_files, exported_header_dirs, HeaderAbiLinker Linker(dump_files, exported_header_dirs,
version_script, linked_dump, arch, api); version_script, linked_dump, arch, api);
if (!Linker.LinkAndDump()) { if (!Linker.LinkAndDump()) {

View File

@@ -7,30 +7,30 @@ package abi_diff;
message RecordFieldDeclDiff { message RecordFieldDeclDiff {
optional abi_dump.RecordFieldDecl old = 1; optional abi_dump.RecordFieldDecl old = 1;
optional abi_dump.RecordFieldDecl new = 2; optional abi_dump.RecordFieldDecl new = 2;
required uint32 index = 3; optional uint32 index = 3;
} }
message EnumFieldDeclDiff { message EnumFieldDeclDiff {
optional abi_dump.EnumFieldDecl old = 1; optional abi_dump.EnumFieldDecl old = 1;
optional abi_dump.EnumFieldDecl new = 2; optional abi_dump.EnumFieldDecl new = 2;
required uint32 index = 3; optional uint32 index = 3;
} }
message CXXBaseSpecifierDiff { message CXXBaseSpecifierDiff {
optional abi_dump.CXXBaseSpecifier old = 1; optional abi_dump.CXXBaseSpecifier old = 1;
optional abi_dump.CXXBaseSpecifier new = 2; optional abi_dump.CXXBaseSpecifier new = 2;
required uint32 index = 3; optional uint32 index = 3;
} }
message CXXVTableDiff { message CXXVTableDiff {
optional abi_dump.VTableComponent old = 1; optional abi_dump.VTableComponent old = 1;
optional abi_dump.VTableComponent new = 2; optional abi_dump.VTableComponent new = 2;
required uint32 index = 3; optional uint32 index = 3;
} }
message BasicNamedAndTypedDeclDiff { message BasicNamedAndTypedDeclDiff {
required abi_dump.BasicNamedAndTypedDecl old = 1; optional abi_dump.BasicNamedAndTypedDecl old = 1;
required abi_dump.BasicNamedAndTypedDecl new = 2; optional abi_dump.BasicNamedAndTypedDecl new = 2;
} }
message RecordDeclDiff { message RecordDeclDiff {
@@ -38,29 +38,30 @@ message RecordDeclDiff {
repeated CXXBaseSpecifierDiff base_diffs = 2; repeated CXXBaseSpecifierDiff base_diffs = 2;
repeated CXXVTableDiff vtable_diffs = 3; repeated CXXVTableDiff vtable_diffs = 3;
optional BasicNamedAndTypedDeclDiff type_diff = 4; optional BasicNamedAndTypedDeclDiff type_diff = 4;
required string name = 5; optional string name = 5;
} }
message EnumDeclDiff { message EnumDeclDiff {
repeated EnumFieldDeclDiff field_diffs = 1; repeated EnumFieldDeclDiff field_diffs = 1;
optional BasicNamedAndTypedDeclDiff type_diff = 2; optional BasicNamedAndTypedDeclDiff type_diff = 2;
required string name = 3; optional string name = 3;
} }
message ReturnTypeDiff { message ReturnTypeDiff {
required abi_dump.BasicNamedAndTypedDecl old = 1; optional abi_dump.BasicNamedAndTypedDecl old = 1;
required abi_dump.BasicNamedAndTypedDecl new = 2; optional abi_dump.BasicNamedAndTypedDecl new = 2;
} }
message ParamDeclDiff { message ParamDeclDiff {
optional abi_dump.ParamDecl old = 1; optional abi_dump.ParamDecl old = 1;
optional abi_dump.ParamDecl new = 2; optional abi_dump.ParamDecl new = 2;
required uint32 index = 3; optional uint32 index = 3;
} }
message FunctionDeclDiff { message FunctionDeclDiff {
optional ReturnTypeDiff return_type_diffs = 1; optional ReturnTypeDiff return_type_diffs = 1;
repeated ParamDeclDiff param_diffs = 2; repeated ParamDeclDiff param_diffs = 2;
optional string name = 3;
} }
message GlobalVarDeclDiff { message GlobalVarDeclDiff {

View File

@@ -4,7 +4,7 @@ package abi_dump;
message BasicTypeAbi { message BasicTypeAbi {
// The type's name. for eg : a record field's type. // The type's name. for eg : a record field's type.
required string name = 1; optional string name = 1;
// Optional since templated types will not have this information. // Optional since templated types will not have this information.
optional uint64 size = 2 [default = 0]; optional uint64 size = 2 [default = 0];
optional uint32 alignment = 3 [default = 0]; optional uint32 alignment = 3 [default = 0];
@@ -17,35 +17,35 @@ enum AccessSpecifier {
} }
message BasicNamedAndTypedDecl { message BasicNamedAndTypedDecl {
required BasicTypeAbi type_abi = 1; optional BasicTypeAbi type_abi = 1;
// The TypedDecl's name. // The TypedDecl's name.
required string name = 2; optional string name = 2;
required AccessSpecifier access = 3; optional AccessSpecifier access = 3;
optional string linker_set_key = 4; optional string linker_set_key = 4;
} }
message FunctionDecl { message FunctionDecl {
required BasicNamedAndTypedDecl basic_abi = 1; optional BasicNamedAndTypedDecl basic_abi = 1;
// Mangled name. // Mangled name.
required string mangled_function_name = 2; optional string mangled_function_name = 2;
required string source_file = 3; optional string source_file = 3;
repeated ParamDecl parameters = 4; repeated ParamDecl parameters = 4;
optional TemplateInfo template_info = 5; optional TemplateInfo template_info = 5;
} }
message ParamDecl { message ParamDecl {
required BasicNamedAndTypedDecl basic_abi = 1; optional BasicNamedAndTypedDecl basic_abi = 1;
required bool default_arg = 2; optional bool default_arg = 2;
} }
message RecordFieldDecl { message RecordFieldDecl {
// For future additions. // For future additions.
required BasicNamedAndTypedDecl basic_abi = 1; optional BasicNamedAndTypedDecl basic_abi = 1;
} }
message EnumFieldDecl { message EnumFieldDecl {
required BasicNamedAndTypedDecl basic_abi = 1; optional BasicNamedAndTypedDecl basic_abi = 1;
required int64 enum_field_value = 2; // assumption: fits int64 optional int64 enum_field_value = 2; // assumption: fits int64
} }
message TemplateInfo { message TemplateInfo {
@@ -53,17 +53,17 @@ message TemplateInfo {
} }
message TemplateElement { message TemplateElement {
required BasicTemplateElementAbi basic_abi = 1; optional BasicTemplateElementAbi basic_abi = 1;
message BasicTemplateElementAbi { message BasicTemplateElementAbi {
optional BasicTypeAbi type_abi = 1; optional BasicTypeAbi type_abi = 1;
optional string name = 2; optional string name = 2;
required string linker_set_key = 3; optional string linker_set_key = 3;
} }
} }
message CXXBaseSpecifier { message CXXBaseSpecifier {
required BasicNamedAndTypedDecl basic_abi = 1; optional BasicNamedAndTypedDecl basic_abi = 1;
required bool is_virtual = 2; optional bool is_virtual = 2;
} }
message VTableComponent { message VTableComponent {
@@ -77,7 +77,7 @@ message VTableComponent {
DeletingDtorPointer = 6; DeletingDtorPointer = 6;
UnusedFunctionPointer = 7; UnusedFunctionPointer = 7;
} }
required Kind kind = 1; optional Kind kind = 1;
optional string mangled_component_name = 2 [default = ""]; optional string mangled_component_name = 2 [default = ""];
optional uint64 value = 3 [default = 0]; optional uint64 value = 3 [default = 0];
} }
@@ -87,24 +87,24 @@ message VTableLayout {
} }
message RecordDecl { message RecordDecl {
required BasicNamedAndTypedDecl basic_abi = 1; optional BasicNamedAndTypedDecl basic_abi = 1;
repeated RecordFieldDecl fields = 2; repeated RecordFieldDecl fields = 2;
repeated CXXBaseSpecifier base_specifiers = 3; repeated CXXBaseSpecifier base_specifiers = 3;
required string source_file = 4; optional string source_file = 4;
optional TemplateInfo template_info = 5; optional TemplateInfo template_info = 5;
required string mangled_record_name = 6; optional string mangled_record_name = 6;
optional VTableLayout vtable_layout = 7; optional VTableLayout vtable_layout = 7;
} }
message EnumDecl { message EnumDecl {
required BasicNamedAndTypedDecl basic_abi = 1; optional BasicNamedAndTypedDecl basic_abi = 1;
repeated EnumFieldDecl enum_fields = 2; repeated EnumFieldDecl enum_fields = 2;
required string source_file = 3; optional string source_file = 3;
} }
message GlobalVarDecl { message GlobalVarDecl {
required BasicNamedAndTypedDecl basic_abi = 1; optional BasicNamedAndTypedDecl basic_abi = 1;
required string source_file = 2; optional string source_file = 2;
} }
message TranslationUnit { message TranslationUnit {