Merge "Track library name change."
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 21ebdbd..517d5f9 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -217,7 +217,7 @@
int nanosleep(const struct timespec*, struct timespec*) all
int clock_settime(clockid_t, const struct timespec*) all
int __clock_nanosleep:clock_nanosleep(clockid_t, int, const struct timespec*, struct timespec*) all
-int getitimer(int, const struct itimerval*) all
+int getitimer(int, struct itimerval*) all
int setitimer(int, const struct itimerval*, struct itimerval*) all
int __timer_create:timer_create(clockid_t clockid, struct sigevent* evp, __kernel_timer_t* timerid) all
int __timer_settime:timer_settime(__kernel_timer_t, int, const struct itimerspec*, struct itimerspec*) all
@@ -249,8 +249,8 @@
int __accept4:accept4(int, struct sockaddr*, socklen_t*, int) arm,arm64,mips,mips64,x86_64
int getsockname(int, struct sockaddr*, socklen_t*) arm,arm64,mips,mips64,x86_64
int getpeername(int, struct sockaddr*, socklen_t*) arm,arm64,mips,mips64,x86_64
-int __sendto:sendto(int, const void*, size_t, int, const struct sockaddr*, socklen_t) arm,arm64,mips,mips64,x86_64
-int recvfrom(int, void*, size_t, unsigned int, struct sockaddr*, socklen_t*) arm,arm64,mips,mips64,x86_64
+ssize_t __sendto:sendto(int, const void*, size_t, int, const struct sockaddr*, socklen_t) arm,arm64,mips,mips64,x86_64
+ssize_t recvfrom(int, void*, size_t, unsigned int, struct sockaddr*, socklen_t*) arm,arm64,mips,mips64,x86_64
int shutdown(int, int) arm,arm64,mips,mips64,x86_64
int setsockopt(int, int, int, const void*, socklen_t) arm,arm64,mips,mips64,x86_64
int getsockopt(int, int, int, void*, socklen_t*) arm,arm64,mips,mips64,x86_64
@@ -267,8 +267,8 @@
int getsockname:socketcall:6(int, struct sockaddr*, socklen_t*) x86
int getpeername:socketcall:7(int, struct sockaddr*, socklen_t*) x86
int socketpair:socketcall:8(int, int, int, int*) x86
-int __sendto:socketcall:11(int, const void*, size_t, int, const struct sockaddr*, socklen_t) x86
-int recvfrom:socketcall:12(int, void*, size_t, unsigned int, struct sockaddr*, socklen_t*) x86
+ssize_t __sendto:socketcall:11(int, const void*, size_t, int, const struct sockaddr*, socklen_t) x86
+ssize_t recvfrom:socketcall:12(int, void*, size_t, unsigned int, struct sockaddr*, socklen_t*) x86
int shutdown:socketcall:13(int, int) x86
int setsockopt:socketcall:14(int, int, int, const void*, socklen_t) x86
int getsockopt:socketcall:15(int, int, int, void*, socklen_t*) x86
@@ -340,7 +340,7 @@
int __sync_file_range2:sync_file_range2(int, unsigned int, off64_t, off64_t) arm
pid_t wait4(pid_t, int*, int, struct rusage*) all
-int __waitid:waitid(int, pid_t, struct siginfo_t*, int, void*) all
+int __waitid:waitid(int, pid_t, siginfo_t*, int, void*) all
# ARM-specific
int __set_tls:__ARM_NR_set_tls(void*) arm
@@ -355,8 +355,8 @@
# vdso stuff.
int __clock_getres:clock_getres(clockid_t, struct timespec*) all
-int __clock_gettime:clock_gettime(clockid_t, timespec*) all
-int __gettimeofday:gettimeofday(timeval*, timezone*) all
+int __clock_gettime:clock_gettime(clockid_t, struct timespec*) all
+int __gettimeofday:gettimeofday(struct timeval*, struct timezone*) all
# <sys/random.h>
ssize_t getrandom(void*, size_t, unsigned) all
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 54e0703..8b0520a 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -4202,11 +4202,13 @@
// we also need vdso to be available for all namespaces (if present)
soinfo* vdso = solist_get_vdso();
for (auto it : namespaces) {
- it.second->add_soinfo(ld_android_so);
- if (vdso != nullptr) {
- it.second->add_soinfo(vdso);
+ if (it.second != &g_default_namespace) {
+ it.second->add_soinfo(ld_android_so);
+ if (vdso != nullptr) {
+ it.second->add_soinfo(vdso);
+ }
+ // somain and ld_preloads are added to these namespaces after LD_PRELOAD libs are linked
}
- // somain and ld_preloads are added to these namespaces after LD_PRELOAD libs are linked
}
set_application_target_sdk_version(config->target_sdk_version());
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index a0cda1b..75abbd2 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -853,6 +853,20 @@
ASSERT_EQ(ENOMEM, errno);
}
+// Inspired by https://github.com/landley/toybox/issues/163.
+TEST(STDIO_TEST, printf_NULL) {
+ char buf[128];
+ char* null = nullptr;
+ EXPECT_EQ(4, snprintf(buf, sizeof(buf), "<%*.*s>", 2, 2, null));
+ EXPECT_STREQ("<(n>", buf);
+ EXPECT_EQ(8, snprintf(buf, sizeof(buf), "<%*.*s>", 2, 8, null));
+ EXPECT_STREQ("<(null)>", buf);
+ EXPECT_EQ(10, snprintf(buf, sizeof(buf), "<%*.*s>", 8, 2, null));
+ EXPECT_STREQ("< (n>", buf);
+ EXPECT_EQ(10, snprintf(buf, sizeof(buf), "<%*.*s>", 8, 8, null));
+ EXPECT_STREQ("< (null)>", buf);
+}
+
TEST(STDIO_TEST, fprintf) {
TemporaryFile tf;
diff --git a/tools/versioner/src/DeclarationDatabase.cpp b/tools/versioner/src/DeclarationDatabase.cpp
index 0ba51d1..afae509 100644
--- a/tools/versioner/src/DeclarationDatabase.cpp
+++ b/tools/versioner/src/DeclarationDatabase.cpp
@@ -106,6 +106,7 @@
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 @@
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 @@
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 @@
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 4496ee9..9a45227 100644
--- a/tools/versioner/src/DeclarationDatabase.h
+++ b/tools/versioner/src/DeclarationDatabase.h
@@ -127,6 +127,7 @@
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 @@
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 d3c2f7c..473f1f9 100644
--- a/tools/versioner/src/versioner.cpp
+++ b/tools/versioner/src/versioner.cpp
@@ -277,7 +277,9 @@
}
// 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 @@
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 0000000..dc81ef8
--- /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 0000000..2f09034
--- /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 0000000..9bfbe6d
--- /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