aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorGeorge Burgess IV <gbiv@google.com>2017-07-24 15:05:05 -0700
committerGeorge Burgess IV <gbiv@google.com>2017-07-27 17:00:13 -0700
commitb97049c0390cb1a11b9cb0b14391972e69398ce5 (patch)
treec331f88d0cb75e427564fdebd15738adf410f501 /tools
parent38bcf2b704eb5038668759d2dd37115aea1dc437 (diff)
downloadandroid_bionic-b97049c0390cb1a11b9cb0b14391972e69398ce5.tar.gz
android_bionic-b97049c0390cb1a11b9cb0b14391972e69398ce5.tar.bz2
android_bionic-b97049c0390cb1a11b9cb0b14391972e69398ce5.zip
libc: Split FORTIFY into its own headers
This patch cleans up our standard headers by moving most of the FORTIFY cruft out in to its own sandbox. In order to include the *_chk and *_real declarations, you can either enable FORTIFY, or `#define __BIONIC_DECLARE_FORTIFY_HELPERS`. Both sys/select.h and strings.h are explicitly ignored by this patch. Both of these files have very small __BIONIC_FORTIFY blocks, and don't define any actual FORTIFY'ed functions (just macros, and 3 *_chk functions). This patch also makes the versioner ignore the FORTIFY implementation headers, since we're guaranteed to pick the FORTIFY'ed headers up when looking at the regular headers. (...Not to mention that making the FORTIFY'ed headers freestanding would be annoying to do and maintain for ~no benefit). We bake the knowledge of where FORTIFY headers live directly into the versioner. We could go with a more general approach (e.g. adding an -X IGNORED_FILE flag that tells the versioner to ignore $HEADER_PATH/$IGNORED_FILE), but we'd then have to repeat that for every test, every manual invocation of the versioner, etc. for no benefit that's obvious to me. Bug: 12231437 Test: m checkbuild on bullhead internal master + CtsBionicTestCases. no new errors. Change-Id: Iffc0cc609009b33d989cdaddde0a809282131a5b
Diffstat (limited to 'tools')
-rw-r--r--tools/versioner/src/Utils.cpp27
-rw-r--r--tools/versioner/src/Utils.h4
-rw-r--r--tools/versioner/src/versioner.cpp74
3 files changed, 76 insertions, 29 deletions
diff --git a/tools/versioner/src/Utils.cpp b/tools/versioner/src/Utils.cpp
index ef7facc08..ca186a461 100644
--- a/tools/versioner/src/Utils.cpp
+++ b/tools/versioner/src/Utils.cpp
@@ -37,7 +37,8 @@ std::string getWorkingDir() {
return buf;
}
-std::vector<std::string> collectHeaders(const std::string& directory) {
+std::vector<std::string> collectHeaders(const std::string& directory,
+ const std::unordered_set<std::string>& ignored_directories) {
std::vector<std::string> headers;
char* dir_argv[2] = { const_cast<char*>(directory.c_str()), nullptr };
@@ -48,16 +49,34 @@ std::vector<std::string> collectHeaders(const std::string& directory) {
err(1, "failed to open directory '%s'", directory.c_str());
}
+ FTSENT* skipping = nullptr;
while (FTSENT* ent = fts_read(fts.get())) {
- if (ent->fts_info & (FTS_D | FTS_DP)) {
+ if (ent->fts_info & FTS_DP) {
+ if (ent == skipping) {
+ skipping = nullptr;
+ }
continue;
}
- if (!android::base::EndsWith(ent->fts_path, ".h")) {
+ if (skipping != nullptr) {
continue;
}
- headers.push_back(ent->fts_path);
+ if (ent->fts_info & FTS_D) {
+ if (ignored_directories.count(ent->fts_path) != 0) {
+ // fts_read guarantees that `ent` is valid and sane to hold on to until
+ // after it's returned with FTS_DP set.
+ skipping = ent;
+ }
+ continue;
+ }
+
+ std::string path = ent->fts_path;
+ if (!android::base::EndsWith(path, ".h")) {
+ continue;
+ }
+
+ headers.push_back(std::move(path));
}
return headers;
diff --git a/tools/versioner/src/Utils.h b/tools/versioner/src/Utils.h
index 44a34f832..9b45dcd49 100644
--- a/tools/versioner/src/Utils.h
+++ b/tools/versioner/src/Utils.h
@@ -22,12 +22,14 @@
#include <unistd.h>
#include <string>
+#include <unordered_set>
#include <vector>
#include <llvm/ADT/StringRef.h>
std::string getWorkingDir();
-std::vector<std::string> collectHeaders(const std::string& directory);
+std::vector<std::string> collectHeaders(const std::string& directory,
+ const std::unordered_set<std::string>& ignored_directories);
static inline std::string dirname(const std::string& path) {
std::unique_ptr<char, decltype(&free)> path_copy(strdup(path.c_str()), free);
diff --git a/tools/versioner/src/versioner.cpp b/tools/versioner/src/versioner.cpp
index 735ea04e9..bb09bea9e 100644
--- a/tools/versioner/src/versioner.cpp
+++ b/tools/versioner/src/versioner.cpp
@@ -44,6 +44,7 @@
#include <android-base/file.h>
#include <android-base/macros.h>
#include <android-base/parseint.h>
+#include <android-base/strings.h>
#include "Arch.h"
#include "DeclarationDatabase.h"
@@ -78,11 +79,21 @@ static int getCpuCount() {
#endif
}
-static CompilationRequirements collectRequirements(const Arch& arch, const std::string& header_dir,
- const std::string& dependency_dir) {
- std::vector<std::string> headers = collectHeaders(header_dir);
- std::vector<std::string> dependencies = { header_dir };
- if (!dependency_dir.empty()) {
+namespace {
+struct HeaderLocationInformation {
+ std::string header_dir;
+ std::string dependency_dir;
+ // Absolute paths to ignore all children -- including subdirectories -- of.
+ std::unordered_set<std::string> ignored_directories;
+};
+}
+
+static CompilationRequirements collectRequirements(const Arch& arch,
+ const HeaderLocationInformation& location) {
+ std::vector<std::string> headers =
+ collectHeaders(location.header_dir, location.ignored_directories);
+ std::vector<std::string> dependencies = { location.header_dir };
+ if (!location.dependency_dir.empty()) {
auto collect_children = [&dependencies](const std::string& dir_path) {
DIR* dir = opendir(dir_path.c_str());
if (!dir) {
@@ -113,8 +124,8 @@ static CompilationRequirements collectRequirements(const Arch& arch, const std::
closedir(dir);
};
- collect_children(dependency_dir + "/common");
- collect_children(dependency_dir + "/" + to_string(arch));
+ collect_children(location.dependency_dir + "/common");
+ collect_children(location.dependency_dir + "/" + to_string(arch));
}
auto new_end = std::remove_if(headers.begin(), headers.end(), [&arch](llvm::StringRef header) {
@@ -158,13 +169,12 @@ static std::set<CompilationType> generateCompilationTypes(const std::set<Arch> s
}
static std::unique_ptr<HeaderDatabase> compileHeaders(const std::set<CompilationType>& types,
- const std::string& header_dir,
- const std::string& dependency_dir) {
+ const HeaderLocationInformation& location) {
if (types.empty()) {
errx(1, "compileHeaders received no CompilationTypes");
}
- auto vfs = createCommonVFS(header_dir, dependency_dir, add_include);
+ auto vfs = createCommonVFS(location.header_dir, location.dependency_dir, add_include);
size_t thread_count = max_thread_count;
std::vector<std::thread> threads;
@@ -175,7 +185,7 @@ static std::unique_ptr<HeaderDatabase> compileHeaders(const std::set<Compilation
auto result = std::make_unique<HeaderDatabase>();
for (const auto& type : types) {
if (requirements.count(type.arch) == 0) {
- requirements[type.arch] = collectRequirements(type.arch, header_dir, dependency_dir);
+ requirements[type.arch] = collectRequirements(type.arch, location);
}
}
@@ -438,6 +448,7 @@ static void usage(bool help = false) {
fprintf(stderr, " -f\t\tpreprocess header files even if validation fails\n");
fprintf(stderr, "\n");
fprintf(stderr, "Miscellaneous:\n");
+ fprintf(stderr, " -F\t\tdo not ignore FORTIFY headers by default\n");
fprintf(stderr, " -d\t\tdump function availability\n");
fprintf(stderr, " -j THREADS\tmaximum number of threads to use\n");
fprintf(stderr, " -v\t\tenable verbose logging\n");
@@ -461,9 +472,10 @@ int main(int argc, char** argv) {
std::string preprocessor_output_path;
bool force = false;
bool dump = false;
+ bool ignore_fortify_headers = true;
int c;
- while ((c = getopt(argc, argv, "a:r:p:so:fdj:vhi")) != -1) {
+ while ((c = getopt(argc, argv, "a:r:p:so:fdj:vhFi")) != -1) {
default_args = false;
switch (c) {
case 'a': {
@@ -549,6 +561,10 @@ int main(int argc, char** argv) {
add_include = true;
break;
+ case 'F':
+ ignore_fortify_headers = false;
+ break;
+
default:
usage();
break;
@@ -559,8 +575,7 @@ int main(int argc, char** argv) {
usage();
}
- std::string header_dir;
- std::string dependency_dir;
+ HeaderLocationInformation location;
const char* top = getenv("ANDROID_BUILD_TOP");
if (!top && (optind == argc || add_include)) {
@@ -571,19 +586,30 @@ int main(int argc, char** argv) {
if (optind == argc) {
// Neither HEADER_PATH nor DEPS_PATH were specified, so try to figure them out.
std::string versioner_dir = to_string(top) + "/bionic/tools/versioner";
- header_dir = versioner_dir + "/current";
- dependency_dir = versioner_dir + "/dependencies";
+ location.header_dir = versioner_dir + "/current";
+ location.dependency_dir = versioner_dir + "/dependencies";
if (platform_dir.empty()) {
platform_dir = versioner_dir + "/platforms";
}
} else {
- if (!android::base::Realpath(argv[optind], &header_dir)) {
+ if (!android::base::Realpath(argv[optind], &location.header_dir)) {
err(1, "failed to get realpath for path '%s'", argv[optind]);
}
if (argc - optind == 2) {
- dependency_dir = argv[optind + 1];
+ location.dependency_dir = argv[optind + 1];
+ }
+ }
+
+ // Every file that lives in bits/fortify is logically a part of a header outside of bits/fortify.
+ // This makes the files there impossible to build on their own.
+ if (ignore_fortify_headers) {
+ std::string fortify_path = location.header_dir;
+ if (!android::base::EndsWith(location.header_dir, "/")) {
+ fortify_path += '/';
}
+ fortify_path += "bits/fortify";
+ location.ignored_directories.insert(std::move(fortify_path));
}
if (selected_levels.empty()) {
@@ -596,10 +622,10 @@ int main(int argc, char** argv) {
struct stat st;
- if (stat(header_dir.c_str(), &st) != 0) {
- err(1, "failed to stat '%s'", header_dir.c_str());
+ if (const char *dir = location.header_dir.c_str(); stat(dir, &st) != 0) {
+ err(1, "failed to stat '%s'", dir);
} else if (!S_ISDIR(st.st_mode)) {
- errx(1, "'%s' is not a directory", header_dir.c_str());
+ errx(1, "'%s' is not a directory", dir);
}
std::set<CompilationType> compilation_types;
@@ -615,7 +641,7 @@ int main(int argc, char** argv) {
auto start = std::chrono::high_resolution_clock::now();
std::unique_ptr<HeaderDatabase> declaration_database =
- compileHeaders(compilation_types, header_dir, dependency_dir);
+ compileHeaders(compilation_types, location);
auto end = std::chrono::high_resolution_clock::now();
if (verbose) {
@@ -625,7 +651,7 @@ int main(int argc, char** argv) {
bool failed = false;
if (dump) {
- declaration_database->dump(header_dir + "/");
+ declaration_database->dump(location.header_dir + "/");
} else {
if (!sanityCheck(declaration_database.get())) {
printf("versioner: sanity check failed\n");
@@ -641,7 +667,7 @@ int main(int argc, char** argv) {
}
if (!preprocessor_output_path.empty() && (force || !failed)) {
- failed = !preprocessHeaders(preprocessor_output_path, header_dir, declaration_database.get());
+ failed = !preprocessHeaders(preprocessor_output_path, location.header_dir, declaration_database.get());
}
return failed;
}