Merge "Added libprotobuf to extract and dump ABI."
am: 7272d52f76
Change-Id: I696beff34a2052eaca4c78e08ac362b0c277a5a6
This commit is contained in:
@@ -25,7 +25,14 @@ cc_defaults {
|
||||
"-Wall",
|
||||
"-Werror",
|
||||
"-std=c++11",
|
||||
"-DGOOGLE_PROTOBUF_NO_RTTI",
|
||||
],
|
||||
|
||||
target: {
|
||||
windows: {
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cc_defaults {
|
||||
@@ -34,6 +41,7 @@ cc_defaults {
|
||||
shared_libs: [
|
||||
"libclang",
|
||||
"libLLVM",
|
||||
"libprotobuf-cpp-full",
|
||||
],
|
||||
}
|
||||
|
||||
@@ -42,6 +50,7 @@ cc_defaults {
|
||||
|
||||
static_libs: [
|
||||
"libclangTooling",
|
||||
"libclangToolingCore",
|
||||
"libclangFrontendTool",
|
||||
"libclangFrontend",
|
||||
"libclangDriver",
|
||||
@@ -74,6 +83,30 @@ cc_defaults {
|
||||
"libLLVMMCDisassembler",
|
||||
"libLLVMSupport",
|
||||
],
|
||||
|
||||
shared_libs: [
|
||||
"libprotobuf-cpp-full",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libheader-checker-proto",
|
||||
host_supported: true,
|
||||
export_include_dirs: ["."],
|
||||
|
||||
srcs: [
|
||||
"proto/abi_dump.proto",
|
||||
],
|
||||
|
||||
proto: {
|
||||
export_proto_headers: true,
|
||||
},
|
||||
|
||||
cflags: [
|
||||
"-Wcast-qual",
|
||||
"-Wno-long-long",
|
||||
"-Wno-unused-parameter",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary_host {
|
||||
@@ -84,20 +117,15 @@ cc_binary_host {
|
||||
"header-checker-lib-debug-defaults",
|
||||
],
|
||||
|
||||
srcs: ["header-abi-dumper/src/*.cpp"],
|
||||
srcs: [
|
||||
"header-abi-dumper/src/*.cpp",
|
||||
],
|
||||
|
||||
static_libs: [
|
||||
"libheader-checker-proto",
|
||||
],
|
||||
|
||||
target: {
|
||||
windows: {
|
||||
host_ldlibs: [
|
||||
"-limagehlp",
|
||||
"-lole32",
|
||||
"-lversion",
|
||||
],
|
||||
cflags: [
|
||||
// Skip missing-field-initializer warnings for mingw.
|
||||
"-Wno-error=missing-field-initializers",
|
||||
],
|
||||
},
|
||||
linux: {
|
||||
host_ldlibs: [
|
||||
"-ldl",
|
||||
@@ -111,10 +139,4 @@ cc_binary_host {
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
product_variables: {
|
||||
unbundled_build: {
|
||||
enabled: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,37 +1,154 @@
|
||||
// Copyright (C) 2016 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "ast_processing.h"
|
||||
|
||||
bool HeaderASTVisitor::VisitRecordDecl(const clang::RecordDecl *decl) {
|
||||
llvm::errs() << "struct: " << decl->getName() << "\n";
|
||||
return true;
|
||||
}
|
||||
#include <clang/Lex/Token.h>
|
||||
#include <clang/Tooling/Core/QualTypeNames.h>
|
||||
|
||||
bool HeaderASTVisitor::VisitCXXRecordDecl(const clang::CXXRecordDecl *decl) {
|
||||
llvm::errs() << "class: " << decl->getName() << "\n";
|
||||
#include <google/protobuf/text_format.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
HeaderASTVisitor::HeaderASTVisitor(
|
||||
abi_dump::TranslationUnit *tu_ptr,
|
||||
clang::MangleContext *mangle_contextp,
|
||||
const clang::ASTContext *ast_contextp,
|
||||
const clang::CompilerInstance *compiler_instance_p)
|
||||
: tu_ptr_(tu_ptr),
|
||||
mangle_contextp_(mangle_contextp),
|
||||
ast_contextp_(ast_contextp),
|
||||
cip_(compiler_instance_p) { }
|
||||
|
||||
bool HeaderASTVisitor::VisitRecordDecl(const clang::RecordDecl *decl) {
|
||||
abi_dump::RecordDecl *record_decl = tu_ptr_->add_classes();
|
||||
SetupClassFields(record_decl, decl);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HeaderASTVisitor::VisitFunctionDecl(const clang::FunctionDecl *decl) {
|
||||
llvm::errs() << "func: " << decl->getName() << "\n";
|
||||
abi_dump::FunctionDecl *function_decl = tu_ptr_->add_functions();
|
||||
// FIXME: Use return value.
|
||||
SetupFunction(function_decl, decl);
|
||||
return true;
|
||||
}
|
||||
|
||||
HeaderASTConsumer::HeaderASTConsumer(
|
||||
const std::string &file_name,
|
||||
clang::CompilerInstance *compiler_instancep,
|
||||
const std::string &out_dump_name)
|
||||
: file_name_(file_name),
|
||||
cip_(compiler_instancep),
|
||||
out_dump_name_(out_dump_name) { }
|
||||
|
||||
void HeaderASTConsumer::HandleTranslationUnit(clang::ASTContext &ctx) {
|
||||
llvm::errs() << "HandleTranslationUnit ------------------------------\n";
|
||||
clang::TranslationUnitDecl* translation_unit = ctx.getTranslationUnitDecl();
|
||||
HeaderASTVisitor v;
|
||||
std::unique_ptr<clang::MangleContext> mangle_contextp(
|
||||
ctx.createMangleContext());
|
||||
abi_dump::TranslationUnit tu;
|
||||
HeaderASTVisitor v(&tu, mangle_contextp.get(), &ctx, cip_);
|
||||
v.TraverseDecl(translation_unit);
|
||||
std::ofstream text_output(out_dump_name_ + ".txt");
|
||||
std::fstream binary_output(
|
||||
(out_dump_name_).c_str(),
|
||||
std::ios::out | std::ios::trunc | std::ios::binary);
|
||||
std::string str_out;
|
||||
google::protobuf::TextFormat::PrintToString(tu, &str_out);
|
||||
text_output << str_out;
|
||||
if (!tu.SerializeToOstream(&binary_output)) {
|
||||
llvm::errs() << "Serialization to ostream failed\n";
|
||||
}
|
||||
}
|
||||
|
||||
void HeaderASTConsumer::HandleVTable(clang::CXXRecordDecl *crd) {
|
||||
llvm::errs() << "HandleVTable: " << crd->getName() << "\n";
|
||||
}
|
||||
|
||||
llvm::StringRef HeaderASTPPCallbacks::ToString(const clang::Token &tok) {
|
||||
return tok.getIdentifierInfo()->getName();
|
||||
std::string HeaderASTVisitor::GetDeclSourceFile(const clang::NamedDecl *decl) {
|
||||
clang::SourceManager &SM = cip_->getSourceManager();
|
||||
clang::SourceLocation location = decl->getLocation();
|
||||
llvm::StringRef file_name= SM.getFilename(location);
|
||||
return file_name.str();
|
||||
}
|
||||
|
||||
std::string HeaderASTVisitor::GetMangledNameDecl(const clang::NamedDecl *decl) {
|
||||
std::string mangled_or_demangled_name = decl->getName();
|
||||
if (mangle_contextp_->shouldMangleDeclName(decl)) {
|
||||
llvm::raw_string_ostream ostream(mangled_or_demangled_name);
|
||||
mangle_contextp_->mangleName(decl, ostream);
|
||||
ostream.flush();
|
||||
}
|
||||
return mangled_or_demangled_name;
|
||||
}
|
||||
|
||||
bool HeaderASTVisitor::SetupFunction(abi_dump::FunctionDecl *functionp,
|
||||
const clang::FunctionDecl *decl) {
|
||||
// Go through all the parameters in the method and add them to the fields.
|
||||
// Also get the fully qualfied name and mangled name and store them.
|
||||
functionp->set_function_name(decl->getQualifiedNameAsString());
|
||||
functionp->set_mangled_function_name(GetMangledNameDecl(decl));
|
||||
functionp->set_source_file(GetDeclSourceFile(decl));
|
||||
clang::QualType return_type =
|
||||
decl->getReturnType().getDesugaredType(*ast_contextp_);
|
||||
functionp->set_return_type(
|
||||
clang::TypeName::getFullyQualifiedName(return_type, *ast_contextp_));
|
||||
clang::FunctionDecl::param_const_iterator param_it = decl->param_begin();
|
||||
while (param_it != decl->param_end()) {
|
||||
abi_dump::FieldDecl *function_fieldp = functionp->add_parameters();
|
||||
if (!function_fieldp) {
|
||||
llvm::errs() << "Couldn't add parameter to method. Aborting";
|
||||
return false;
|
||||
}
|
||||
function_fieldp->set_field_name((*param_it)->getName());
|
||||
clang::QualType field_type =
|
||||
(*param_it)->getType().getDesugaredType(*ast_contextp_);
|
||||
|
||||
function_fieldp->set_field_type(
|
||||
clang::TypeName::getFullyQualifiedName(field_type, *ast_contextp_));
|
||||
|
||||
param_it++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HeaderASTVisitor::SetupClassFields(abi_dump::RecordDecl *classp,
|
||||
const clang::RecordDecl *decl) {
|
||||
classp->set_fully_qualified_name(decl->getQualifiedNameAsString());
|
||||
classp->set_source_file(GetDeclSourceFile(decl));
|
||||
classp->set_entity_type("class");
|
||||
clang::RecordDecl::field_iterator field = decl->field_begin();
|
||||
while (field != decl->field_end()) {
|
||||
abi_dump::FieldDecl *class_fieldp = classp->add_fields();
|
||||
if (!class_fieldp) {
|
||||
llvm::errs() << " Couldn't add class field: " << field->getName()
|
||||
<< " to reference dump\n";
|
||||
return false;
|
||||
}
|
||||
class_fieldp->set_field_name(field->getName());
|
||||
//FIXME: This needs to change. Resolve typedef, class name, built-in etc.
|
||||
clang::QualType field_type =
|
||||
field->getType().getDesugaredType(*ast_contextp_);
|
||||
class_fieldp->set_field_type(
|
||||
clang::TypeName::getFullyQualifiedName(field_type, *ast_contextp_));
|
||||
field++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void HeaderASTPPCallbacks::MacroDefined(const clang::Token ¯o_name_tok,
|
||||
const clang::MacroDirective *) {
|
||||
const clang::MacroDirective *) {
|
||||
assert(macro_name_tok.isAnyIdentifier());
|
||||
llvm::errs() << "defines: " << ToString(macro_name_tok) << "\n";
|
||||
}
|
||||
|
||||
@@ -1,28 +1,83 @@
|
||||
// Copyright (C) 2016 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef AST_PROCESSING_H_
|
||||
#define AST_PROCESSING_H_
|
||||
|
||||
#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 <clang/AST/AST.h>
|
||||
#include <clang/AST/ASTConsumer.h>
|
||||
#include <clang/AST/Mangle.h>
|
||||
#include <clang/AST/RecursiveASTVisitor.h>
|
||||
#include <clang/Frontend/CompilerInstance.h>
|
||||
#include <clang/Lex/PPCallbacks.h>
|
||||
#include <clang/Lex/Preprocessor.h>
|
||||
|
||||
class HeaderASTVisitor
|
||||
: public clang::RecursiveASTVisitor<HeaderASTVisitor> {
|
||||
public:
|
||||
HeaderASTVisitor(abi_dump::TranslationUnit *tu_ptr,
|
||||
clang::MangleContext *mangle_contextp,
|
||||
const clang::ASTContext *ast_contextp,
|
||||
const clang::CompilerInstance *compiler_instance_p);
|
||||
|
||||
bool VisitRecordDecl(const clang::RecordDecl *decl);
|
||||
bool VisitCXXRecordDecl(const clang::CXXRecordDecl *decl);
|
||||
|
||||
bool VisitFunctionDecl(const clang::FunctionDecl *decl);
|
||||
|
||||
private:
|
||||
bool SetupFunction(abi_dump::FunctionDecl *methodp,
|
||||
const clang::FunctionDecl *decl);
|
||||
|
||||
bool SetupClassFields(abi_dump::RecordDecl *classp,
|
||||
const clang::RecordDecl *decl);
|
||||
|
||||
std::string GetDeclSourceFile(const clang::NamedDecl *decl);
|
||||
|
||||
std::string GetMangledNameDecl(const clang::NamedDecl *decl);
|
||||
|
||||
private:
|
||||
abi_dump::TranslationUnit *tu_ptr_;
|
||||
clang::MangleContext *mangle_contextp_;
|
||||
const clang::ASTContext *ast_contextp_;
|
||||
const clang::CompilerInstance *cip_;
|
||||
};
|
||||
|
||||
class HeaderASTConsumer : public clang::ASTConsumer {
|
||||
public:
|
||||
HeaderASTConsumer(const std::string &file_name,
|
||||
clang::CompilerInstance *compiler_instancep,
|
||||
const std::string &out_dump_name);
|
||||
|
||||
void HandleTranslationUnit(clang::ASTContext &ctx) override;
|
||||
|
||||
void HandleVTable(clang::CXXRecordDecl *crd) override;
|
||||
|
||||
private:
|
||||
std::string file_name_;
|
||||
clang::CompilerInstance *cip_;
|
||||
std::string out_dump_name_;
|
||||
};
|
||||
|
||||
class HeaderASTPPCallbacks : public clang::PPCallbacks {
|
||||
private:
|
||||
llvm::StringRef ToString(const clang::Token &tok);
|
||||
|
||||
public:
|
||||
void MacroDefined(const clang::Token ¯o_name_tok,
|
||||
const clang::MacroDirective *) override;
|
||||
};
|
||||
|
||||
#endif // AST_PROCESSING_H_
|
||||
|
||||
@@ -13,16 +13,13 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include "frontend_action.h"
|
||||
|
||||
#include "ast_processing.h"
|
||||
|
||||
#include <clang/AST/AST.h>
|
||||
#include <clang/AST/ASTConsumer.h>
|
||||
#include <clang/Frontend/CompilerInstance.h>
|
||||
#include <clang/Frontend/MultiplexConsumer.h>
|
||||
#include <clang/Lex/Token.h>
|
||||
#include <clang/Serialization/ASTWriter.h>
|
||||
#include <clang/Lex/Preprocessor.h>
|
||||
#include <llvm/ADT/STLExtras.h>
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -39,9 +36,5 @@ HeaderCheckerFrontendAction::CreateASTConsumer(clang::CompilerInstance &ci,
|
||||
pp.addPPCallbacks(llvm::make_unique<HeaderASTPPCallbacks>());
|
||||
|
||||
// Create AST consumers.
|
||||
std::vector<std::unique_ptr<clang::ASTConsumer>> consumers;
|
||||
consumers.push_back(llvm::make_unique<HeaderASTConsumer>());
|
||||
// Still have a MultiplexConsumer in case other consumers need to be
|
||||
// added later.
|
||||
return llvm::make_unique<clang::MultiplexConsumer>(std::move(consumers));
|
||||
return llvm::make_unique<HeaderASTConsumer>(header_file, &ci, dump_name_);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
37
vndk/tools/header-checker/proto/abi_dump.proto
Normal file
37
vndk/tools/header-checker/proto/abi_dump.proto
Normal file
@@ -0,0 +1,37 @@
|
||||
syntax = "proto2";
|
||||
|
||||
package abi_dump;
|
||||
|
||||
message FunctionDecl {
|
||||
// Fully Qualified Name.
|
||||
required string function_name = 1 [default = "NONE"];
|
||||
|
||||
// Mangled name.
|
||||
required string mangled_function_name = 2 [default = "NONE"];
|
||||
|
||||
required string source_file = 3;
|
||||
required string parent_name = 4 [default = "NONE"];
|
||||
repeated string template_arguments = 5 ;
|
||||
repeated FieldDecl parameters = 6;
|
||||
required string return_type = 7 [default = "VOID"];
|
||||
}
|
||||
|
||||
message FieldDecl {
|
||||
required string field_name = 1 [default = "NONE"];
|
||||
required string field_type = 2 [default = "VOID"];
|
||||
}
|
||||
|
||||
message RecordDecl {
|
||||
repeated FieldDecl fields = 2;
|
||||
repeated string inner_classes = 3;
|
||||
repeated string base_classes = 4;
|
||||
required string fully_qualified_name = 5 [default = "NONE"];
|
||||
required int64 id = 6 [default = 0];
|
||||
required string entity_type = 7 [default = "NONE"];
|
||||
required string source_file = 9;
|
||||
}
|
||||
|
||||
message TranslationUnit {
|
||||
repeated RecordDecl classes = 1;
|
||||
repeated FunctionDecl functions = 2;
|
||||
}
|
||||
Reference in New Issue
Block a user