diff options
author | Logan Chien <loganchien@google.com> | 2019-12-20 10:27:45 -0800 |
---|---|---|
committer | Logan Chien <loganchien@google.com> | 2019-12-23 07:22:48 -0800 |
commit | c88331b062803cf2a5257e41b9e38c6a2ea25122 (patch) | |
tree | b46535897888d14c00dea3a16672987feec52064 /tools | |
parent | a6bf7f2ee355559ec95378c7290702290aafb73c (diff) |
versioner: Add versioner_fortify_inline annotation
This commit adds versioner_fortify_inline annotation. This annotation
indicates that the annotated function is an overloaded inline function
for _FORTIFY_SOURCE implementation. They are usually enabled/disabled
by the enable_if attribute, thus the versioner don't have to check
whether they have conflicting definitions.
Bug: 118991081
Test: source development/vndk/tools/header-checker/android/envsetup.sh && \
source build/envsetup.sh && \
lunch aosp_arm64-userdebug && \
m versioner && \
./bionic/tools/versioner/run_tests.py
Change-Id: If5c739fc0c8a218907855939c1fe5338134da7f7
Diffstat (limited to 'tools')
-rw-r--r-- | tools/versioner/src/DeclarationDatabase.cpp | 7 | ||||
-rw-r--r-- | tools/versioner/src/DeclarationDatabase.h | 4 | ||||
-rw-r--r-- | tools/versioner/src/versioner.cpp | 6 | ||||
-rw-r--r-- | tools/versioner/tests/fortify_inline/headers/fcntl.h | 29 | ||||
-rw-r--r-- | tools/versioner/tests/fortify_inline/platforms/libc.map.txt | 4 | ||||
-rw-r--r-- | tools/versioner/tests/fortify_inline/run.sh | 1 |
6 files changed, 48 insertions, 3 deletions
diff --git a/tools/versioner/src/DeclarationDatabase.cpp b/tools/versioner/src/DeclarationDatabase.cpp index 0ba51d1b8..afae509ae 100644 --- a/tools/versioner/src/DeclarationDatabase.cpp +++ b/tools/versioner/src/DeclarationDatabase.cpp @@ -106,6 +106,7 @@ class Visitor : public RecursiveASTVisitor<Visitor> { bool is_extern = named_decl->getFormalLinkage() == ExternalLinkage; bool is_definition = false; bool no_guard = false; + bool fortify_inline = false; if (auto function_decl = dyn_cast<FunctionDecl>(decl)) { is_definition = function_decl->isThisDeclarationADefinition(); @@ -147,6 +148,8 @@ class Visitor : public RecursiveASTVisitor<Visitor> { llvm::StringRef annotation = attr->getAnnotation(); if (annotation == "versioner_no_guard") { no_guard = true; + } else if (annotation == "versioner_fortify_inline") { + fortify_inline = true; } else { llvm::SmallVector<llvm::StringRef, 2> fragments; annotation.split(fragments, "="); @@ -217,7 +220,8 @@ class Visitor : public RecursiveASTVisitor<Visitor> { declaration_it != symbol_it->second.declarations.end()) { if (declaration_it->second.is_extern != is_extern || declaration_it->second.is_definition != is_definition || - declaration_it->second.no_guard != no_guard) { + declaration_it->second.no_guard != no_guard || + declaration_it->second.fortify_inline != fortify_inline) { errx(1, "varying declaration of '%s' at %s:%u:%u", declaration_name.c_str(), location.filename.c_str(), location.start.line, location.start.column); } @@ -229,6 +233,7 @@ class Visitor : public RecursiveASTVisitor<Visitor> { declaration.is_extern = is_extern; declaration.is_definition = is_definition; declaration.no_guard = no_guard; + declaration.fortify_inline = fortify_inline; declaration.availability.insert(std::make_pair(type, availability)); symbol_it->second.declarations.insert(std::make_pair(location, declaration)); } diff --git a/tools/versioner/src/DeclarationDatabase.h b/tools/versioner/src/DeclarationDatabase.h index 4496ee94b..9a4522791 100644 --- a/tools/versioner/src/DeclarationDatabase.h +++ b/tools/versioner/src/DeclarationDatabase.h @@ -127,6 +127,7 @@ struct Declaration { bool is_extern; bool is_definition; bool no_guard; + bool fortify_inline; std::map<CompilationType, DeclarationAvailability> availability; bool calculateAvailability(DeclarationAvailability* output) const; @@ -143,6 +144,9 @@ struct Declaration { if (no_guard) { fprintf(out, "no_guard "); } + if (fortify_inline) { + fprintf(out, "fortify_inline "); + } fprintf(out, "@ %s:%u:%u", StripPrefix(location.filename, base_path).str().c_str(), location.start.line, location.start.column); diff --git a/tools/versioner/src/versioner.cpp b/tools/versioner/src/versioner.cpp index d3c2f7cab..473f1f920 100644 --- a/tools/versioner/src/versioner.cpp +++ b/tools/versioner/src/versioner.cpp @@ -277,7 +277,9 @@ static std::vector<T> Intersection(const std::set<T>& a, const std::set<T>& b) { } // Perform a sanity check on a symbol's declarations, enforcing the following invariants: -// 1. At most one inline definition of the function exists. +// 1. At most one inline definition of the function exists (overloaded inline functions for +// _FORTIFY_SOURCE do not count because they are usually introduced to intercept the original +// functions or usually have enable_if attributes). // 2. All of the availability declarations for a symbol are compatible. // If a function is declared as an inline before a certain version, the inline definition // should have no version tag. @@ -290,7 +292,7 @@ static bool checkSymbol(const Symbol& symbol) { std::unordered_map<const Declaration*, std::set<CompilationType>> inline_definitions; for (const auto& decl_it : symbol.declarations) { const Declaration* decl = &decl_it.second; - if (decl->is_definition) { + if (decl->is_definition && !decl->fortify_inline) { std::set<CompilationType> compilation_types = getCompilationTypes(decl); for (const auto& inline_def_it : inline_definitions) { auto intersection = Intersection(compilation_types, inline_def_it.second); diff --git a/tools/versioner/tests/fortify_inline/headers/fcntl.h b/tools/versioner/tests/fortify_inline/headers/fcntl.h new file mode 100644 index 000000000..dc81ef8c9 --- /dev/null +++ b/tools/versioner/tests/fortify_inline/headers/fcntl.h @@ -0,0 +1,29 @@ +#if defined(__cplusplus) +extern "C" { +#endif + +extern int open_real(const char* name, int flags, ...) __asm__("open"); + +#define O_CREAT 00000100 + +typedef unsigned int mode_t; + +static inline __attribute__((always_inline)) +int open(const char* name, int flags) + __attribute__((annotate("versioner_fortify_inline"))) + __attribute__((overloadable)) + __attribute__((enable_if(!(flags & O_CREAT), ""))) { + return open_real(name, flags); +} + +static inline __attribute__((always_inline)) +int open(const char* name, int flags, mode_t mode) + __attribute__((annotate("versioner_fortify_inline"))) + __attribute__((overloadable)) + __attribute__((enable_if(flags & O_CREAT, ""))) { + return open_real(name, flags, mode); +} + +#if defined(__cplusplus) +} +#endif diff --git a/tools/versioner/tests/fortify_inline/platforms/libc.map.txt b/tools/versioner/tests/fortify_inline/platforms/libc.map.txt new file mode 100644 index 000000000..2f09034c1 --- /dev/null +++ b/tools/versioner/tests/fortify_inline/platforms/libc.map.txt @@ -0,0 +1,4 @@ +LIBC { + global: + open; +}; diff --git a/tools/versioner/tests/fortify_inline/run.sh b/tools/versioner/tests/fortify_inline/run.sh new file mode 100644 index 000000000..9bfbe6d59 --- /dev/null +++ b/tools/versioner/tests/fortify_inline/run.sh @@ -0,0 +1 @@ +versioner headers -p platforms -r arm -a 9 -a 12 -i
\ No newline at end of file |