Merge changes I300b7645,Ibd11ef97,If24c85b5,I9ff02cd2 into main
* changes:
linker: LoadSegments: Factor out MapBssSection()
linker: LoadSegments: Factor out DropPaddingPages()
linker: LoadSegments: Factor out ZeroFillSegment()
linker: LoadSegments: Factor out MapSegment()
diff --git a/docs/fdtrack.md b/docs/fdtrack.md
index 07c69b3..8928a5c 100644
--- a/docs/fdtrack.md
+++ b/docs/fdtrack.md
@@ -4,9 +4,11 @@
fdtrack is a file descriptor leak checker added to Android in API level 30.
-fdtrack consists of two parts: a set of hooks in bionic to register a callback
-that's invoked on file descriptor operations, and a library that implements a
-hook to perform and store backtraces for file descriptor creation.
+fdtrack consists of several parts: a set of hooks in bionic to register a
+callback that's invoked on file descriptor operations, a library that implements
+a hook to perform and store backtraces for file descriptor creation, and
+code in frameworks to automatically enable it (and deliberately crash a process
+that's leaking).
### bionic hooks
bionic provides a header in the `bionic_libc_platform_headers` header_lib at <[bionic/fdtrack.h](https://android.googlesource.com/platform/bionic/+/refs/heads/main/libc/platform/bionic/fdtrack.h)>.
@@ -21,6 +23,28 @@
[libfdtrack](https://android.googlesource.com/platform/bionic/+/refs/heads/main/libfdtrack)
implements a library that uses libunwindstack to unwind and store fd creation backtraces.
+### frameworks
+As the name implies, `spawnFdLeakCheckThread` in SystemServer spawns a thread
+to monitor the number of open file descriptors every so often.
+If that passes a certain threshold, fdtrack is enabled.
+If it passes another threshold, the process is aborted.
+These thresholds are configurable via system properties:
+```
+ // Number of open file descriptors before fdtrack starts; default 1600.
+ private static final String SYSPROP_FDTRACK_ENABLE_THRESHOLD =
+ "persist.sys.debug.fdtrack_enable_threshold";
+
+ // Number of open file descriptors before aborting; default 3000.
+ private static final String SYSPROP_FDTRACK_ABORT_THRESHOLD =
+ "persist.sys.debug.fdtrack_abort_threshold";
+
+ // Number of seconds between open fd count checks; default 120s.
+ private static final String SYSPROP_FDTRACK_INTERVAL =
+ "persist.sys.debug.fdtrack_interval";
+```
+Note that it's also possible to monitor the number of open file descriptors for
+a given process from the shell. `adb shell watch ls -l /proc/<pid>/fd` will show
+them (and you can choose your own update rate as an argument to `watch`).
#### Using libfdtrack
libfdtrack registers its hook upon being loaded, so to start capturing
diff --git a/libc/bionic/pthread_mutex.cpp b/libc/bionic/pthread_mutex.cpp
index 9b37225..0a452e9 100644
--- a/libc/bionic/pthread_mutex.cpp
+++ b/libc/bionic/pthread_mutex.cpp
@@ -182,7 +182,12 @@
return 0;
}
if (ret == EBUSY) {
- ScopedTrace trace("Contending for pthread mutex");
+ char trace_msg[64];
+ const pid_t owner = atomic_load_explicit(&mutex.owner_tid, memory_order_relaxed)
+ & FUTEX_TID_MASK;
+ snprintf(trace_msg, sizeof(trace_msg),
+ "Contending for pthread mutex owned by tid: %d", owner);
+ ScopedTrace trace(trace_msg);
ret = -__futex_pi_lock_ex(&mutex.owner_tid, mutex.shared, use_realtime_clock, abs_timeout);
}
return ret;
diff --git a/libc/include/bits/getentropy.h b/libc/include/bits/getentropy.h
index 4cd44f7..98d8879 100644
--- a/libc/include/bits/getentropy.h
+++ b/libc/include/bits/getentropy.h
@@ -48,6 +48,6 @@
*
* See also arc4random_buf() which is available in all API levels.
*/
-int getentropy(void* _Nonnull __buffer, size_t __buffer_size) __wur __INTRODUCED_IN(28);
+__nodiscard int getentropy(void* _Nonnull __buffer, size_t __buffer_size) __INTRODUCED_IN(28);
__END_DECLS
diff --git a/libc/include/malloc.h b/libc/include/malloc.h
index 5904519..2fa4b49 100644
--- a/libc/include/malloc.h
+++ b/libc/include/malloc.h
@@ -55,7 +55,7 @@
* other processes. Obviously this is not the case for apps, which will
* be killed in preference to killing other processes.
*/
-void* _Nullable malloc(size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(1) __wur;
+__nodiscard void* _Nullable malloc(size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(1);
/**
* [calloc(3)](https://man7.org/linux/man-pages/man3/calloc.3.html) allocates
@@ -64,7 +64,7 @@
* Returns a pointer to the allocated memory on success and returns a null
* pointer and sets `errno` on failure (but see the notes for malloc()).
*/
-void* _Nullable calloc(size_t __item_count, size_t __item_size) __mallocfunc __BIONIC_ALLOC_SIZE(1,2) __wur;
+__nodiscard void* _Nullable calloc(size_t __item_count, size_t __item_size) __mallocfunc __BIONIC_ALLOC_SIZE(1,2);
/**
* [realloc(3)](https://man7.org/linux/man-pages/man3/realloc.3.html) resizes
@@ -74,11 +74,8 @@
* memory on success and returns a null pointer and sets `errno` on failure
* (but see the notes for malloc()).
*/
-void* _Nullable realloc(void* _Nullable __ptr, size_t __byte_count) __BIONIC_ALLOC_SIZE(2) __wur;
+__nodiscard void* _Nullable realloc(void* _Nullable __ptr, size_t __byte_count) __BIONIC_ALLOC_SIZE(2);
-// Remove the explicit guard once //external/giflib has been fixed so that it no
-// longer provides a conflicting definition: http://b/352784252
-#if __ANDROID_API__ >= 29
/**
* [reallocarray(3)](https://man7.org/linux/man-pages/man3/realloc.3.html) resizes
* allocated memory on the heap.
@@ -90,7 +87,18 @@
* memory on success and returns a null pointer and sets `errno` on failure
* (but see the notes for malloc()).
*/
-void* _Nullable reallocarray(void* _Nullable __ptr, size_t __item_count, size_t __item_size) __BIONIC_ALLOC_SIZE(2, 3) __wur __INTRODUCED_IN(29);
+#if __ANDROID_API__ >= 29
+__nodiscard void* _Nullable reallocarray(void* _Nullable __ptr, size_t __item_count, size_t __item_size) __BIONIC_ALLOC_SIZE(2, 3) __INTRODUCED_IN(29);
+#else
+#include <errno.h>
+static __inline __nodiscard void* _Nullable reallocarray(void* _Nullable __ptr, size_t __item_count, size_t __item_size) {
+ size_t __new_size;
+ if (__builtin_mul_overflow(__item_count, __item_size, &__new_size)) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ return realloc(__ptr, __new_size);
+}
#endif
/**
@@ -108,13 +116,13 @@
*
* See also posix_memalign().
*/
-void* _Nullable memalign(size_t __alignment, size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(2) __wur;
+__nodiscard void* _Nullable memalign(size_t __alignment, size_t __byte_count) __mallocfunc __BIONIC_ALLOC_SIZE(2);
/**
* [malloc_usable_size(3)](https://man7.org/linux/man-pages/man3/malloc_usable_size.3.html)
* returns the actual size of the given heap block.
*/
-size_t malloc_usable_size(const void* _Nullable __ptr) __wur;
+__nodiscard size_t malloc_usable_size(const void* _Nullable __ptr);
#define __MALLINFO_BODY \
/** Total number of non-mmapped bytes currently allocated from OS. */ \
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index d99d032..d24f6af 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -105,10 +105,10 @@
void clearerr(FILE* _Nonnull __fp);
int fclose(FILE* _Nonnull __fp);
-__wur int feof(FILE* _Nonnull __fp);
-__wur int ferror(FILE* _Nonnull __fp);
+__nodiscard int feof(FILE* _Nonnull __fp);
+__nodiscard int ferror(FILE* _Nonnull __fp);
int fflush(FILE* _Nullable __fp);
-__wur int fgetc(FILE* _Nonnull __fp);
+__nodiscard int fgetc(FILE* _Nonnull __fp);
char* _Nullable fgets(char* _Nonnull __buf, int __size, FILE* _Nonnull __fp);
int fprintf(FILE* _Nonnull __fp , const char* _Nonnull __fmt, ...) __printflike(2, 3);
int fputc(int __ch, FILE* _Nonnull __fp);
@@ -116,8 +116,8 @@
size_t fread(void* _Nonnull __buf, size_t __size, size_t __count, FILE* _Nonnull __fp);
int fscanf(FILE* _Nonnull __fp, const char* _Nonnull __fmt, ...) __scanflike(2, 3);
size_t fwrite(const void* _Nonnull __buf, size_t __size, size_t __count, FILE* _Nonnull __fp);
-__wur int getc(FILE* _Nonnull __fp);
-__wur int getchar(void);
+__nodiscard int getc(FILE* _Nonnull __fp);
+__nodiscard int getchar(void);
ssize_t getdelim(char* _Nullable * _Nonnull __line_ptr, size_t* _Nonnull __line_length_ptr, int __delimiter, FILE* _Nonnull __fp);
ssize_t getline(char* _Nullable * _Nonnull __line_ptr, size_t* _Nonnull __line_length_ptr, FILE* _Nonnull __fp);
@@ -201,17 +201,17 @@
#endif
int fseek(FILE* _Nonnull __fp, long __offset, int __whence);
-__wur long ftell(FILE* _Nonnull __fp);
+__nodiscard long ftell(FILE* _Nonnull __fp);
/* See https://android.googlesource.com/platform/bionic/+/main/docs/32-bit-abi.md */
#if defined(__USE_FILE_OFFSET64)
int fgetpos(FILE* _Nonnull __fp, fpos_t* _Nonnull __pos) __RENAME(fgetpos64) __INTRODUCED_IN(24);
int fsetpos(FILE* _Nonnull __fp, const fpos_t* _Nonnull __pos) __RENAME(fsetpos64) __INTRODUCED_IN(24);
int fseeko(FILE* _Nonnull __fp, off_t __offset, int __whence) __RENAME(fseeko64) __INTRODUCED_IN(24);
-__wur off_t ftello(FILE* _Nonnull __fp) __RENAME(ftello64) __INTRODUCED_IN(24);
+__nodiscard off_t ftello(FILE* _Nonnull __fp) __RENAME(ftello64) __INTRODUCED_IN(24);
# if defined(__USE_BSD)
/* If __read_fn and __write_fn are both nullptr, it will cause EINVAL */
-__wur FILE* _Nullable funopen(const void* _Nullable __cookie,
+__nodiscard FILE* _Nullable funopen(const void* _Nullable __cookie,
int (* __BIONIC_COMPLICATED_NULLNESS __read_fn)(void* _Nonnull, char* _Nonnull, int),
int (* __BIONIC_COMPLICATED_NULLNESS __write_fn)(void* _Nonnull, const char* _Nonnull, int),
fpos_t (* _Nullable __seek_fn)(void* _Nonnull, fpos_t, int),
@@ -221,10 +221,10 @@
int fgetpos(FILE* _Nonnull __fp, fpos_t* _Nonnull __pos);
int fsetpos(FILE* _Nonnull __fp, const fpos_t* _Nonnull __pos);
int fseeko(FILE* _Nonnull __fp, off_t __offset, int __whence);
-__wur off_t ftello(FILE* _Nonnull __fp);
+__nodiscard off_t ftello(FILE* _Nonnull __fp);
# if defined(__USE_BSD)
/* If __read_fn and __write_fn are both nullptr, it will cause EINVAL */
-__wur FILE* _Nullable funopen(const void* _Nullable __cookie,
+__nodiscard FILE* _Nullable funopen(const void* _Nullable __cookie,
int (* __BIONIC_COMPLICATED_NULLNESS __read_fn)(void* _Nonnull, char* _Nonnull, int),
int (* __BIONIC_COMPLICATED_NULLNESS __write_fn)(void* _Nonnull, const char* _Nonnull, int),
fpos_t (* _Nullable __seek_fn)(void* _Nonnull, fpos_t, int),
@@ -234,22 +234,22 @@
int fgetpos64(FILE* _Nonnull __fp, fpos64_t* _Nonnull __pos) __INTRODUCED_IN(24);
int fsetpos64(FILE* _Nonnull __fp, const fpos64_t* _Nonnull __pos) __INTRODUCED_IN(24);
int fseeko64(FILE* _Nonnull __fp, off64_t __offset, int __whence) __INTRODUCED_IN(24);
-__wur off64_t ftello64(FILE* _Nonnull __fp) __INTRODUCED_IN(24);
+__nodiscard off64_t ftello64(FILE* _Nonnull __fp) __INTRODUCED_IN(24);
#if defined(__USE_BSD)
/* If __read_fn and __write_fn are both nullptr, it will cause EINVAL */
-__wur FILE* _Nullable funopen64(const void* _Nullable __cookie,
+__nodiscard FILE* _Nullable funopen64(const void* _Nullable __cookie,
int (* __BIONIC_COMPLICATED_NULLNESS __read_fn)(void* _Nonnull, char* _Nonnull, int),
int (* __BIONIC_COMPLICATED_NULLNESS __write_fn)(void* _Nonnull, const char* _Nonnull, int),
fpos64_t (* _Nullable __seek_fn)(void* _Nonnull, fpos64_t, int),
int (* _Nullable __close_fn)(void* _Nonnull)) __INTRODUCED_IN(24);
#endif
-__wur FILE* _Nullable fopen(const char* _Nonnull __path, const char* _Nonnull __mode);
-__wur FILE* _Nullable fopen64(const char* _Nonnull __path, const char* _Nonnull __mode) __INTRODUCED_IN(24);
+__nodiscard FILE* _Nullable fopen(const char* _Nonnull __path, const char* _Nonnull __mode);
+__nodiscard FILE* _Nullable fopen64(const char* _Nonnull __path, const char* _Nonnull __mode) __INTRODUCED_IN(24);
FILE* _Nullable freopen(const char* _Nullable __path, const char* _Nonnull __mode, FILE* _Nonnull __fp);
FILE* _Nullable freopen64(const char* _Nullable __path, const char* _Nonnull __mode, FILE* _Nonnull __fp) __INTRODUCED_IN(24);
-__wur FILE* _Nullable tmpfile(void);
-__wur FILE* _Nullable tmpfile64(void) __INTRODUCED_IN(24);
+__nodiscard FILE* _Nullable tmpfile(void);
+__nodiscard FILE* _Nullable tmpfile64(void) __INTRODUCED_IN(24);
int snprintf(char* __BIONIC_COMPLICATED_NULLNESS __buf, size_t __size, const char* _Nonnull __fmt, ...) __printflike(3, 4);
int vfscanf(FILE* _Nonnull __fp, const char* _Nonnull __fmt, va_list __args) __scanflike(2, 0);
@@ -260,20 +260,20 @@
#define L_ctermid 1024 /* size for ctermid() */
char* _Nonnull ctermid(char* _Nullable __buf) __INTRODUCED_IN(26);
-__wur FILE* _Nullable fdopen(int __fd, const char* _Nonnull __mode);
-__wur int fileno(FILE* _Nonnull __fp);
+__nodiscard FILE* _Nullable fdopen(int __fd, const char* _Nonnull __mode);
+__nodiscard int fileno(FILE* _Nonnull __fp);
int pclose(FILE* _Nonnull __fp);
-__wur FILE* _Nullable popen(const char* _Nonnull __command, const char* _Nonnull __mode);
+__nodiscard FILE* _Nullable popen(const char* _Nonnull __command, const char* _Nonnull __mode);
void flockfile(FILE* _Nonnull __fp);
int ftrylockfile(FILE* _Nonnull __fp);
void funlockfile(FILE* _Nonnull __fp);
-__wur int getc_unlocked(FILE* _Nonnull __fp);
-__wur int getchar_unlocked(void);
+__nodiscard int getc_unlocked(FILE* _Nonnull __fp);
+__nodiscard int getchar_unlocked(void);
int putc_unlocked(int __ch, FILE* _Nonnull __fp);
int putchar_unlocked(int __ch);
-__wur FILE* _Nullable fmemopen(void* _Nullable __buf, size_t __size, const char* _Nonnull __mode) __INTRODUCED_IN(23);
-__wur FILE* _Nullable open_memstream(char* _Nonnull * _Nonnull __ptr, size_t* _Nonnull __size_ptr) __INTRODUCED_IN(23);
+__nodiscard FILE* _Nullable fmemopen(void* _Nullable __buf, size_t __size, const char* _Nonnull __mode) __INTRODUCED_IN(23);
+__nodiscard FILE* _Nullable open_memstream(char* _Nonnull * _Nonnull __ptr, size_t* _Nonnull __size_ptr) __INTRODUCED_IN(23);
#if defined(__USE_BSD) || defined(__BIONIC__) /* Historically bionic exposed these. */
int asprintf(char* _Nullable * _Nonnull __s_ptr, const char* _Nonnull __fmt, ...) __printflike(2, 3);
@@ -283,16 +283,16 @@
int setlinebuf(FILE* _Nonnull __fp);
int vasprintf(char* _Nullable * _Nonnull __s_ptr, const char* _Nonnull __fmt, va_list __args) __printflike(2, 0);
void clearerr_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
-__wur int feof_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
-__wur int ferror_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
-__wur int fileno_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(24);
+__nodiscard int feof_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
+__nodiscard int ferror_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(23);
+__nodiscard int fileno_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(24);
#define fropen(cookie, fn) funopen(cookie, fn, 0, 0, 0)
#define fwopen(cookie, fn) funopen(cookie, 0, fn, 0, 0)
#endif
#if defined(__USE_BSD)
int fflush_unlocked(FILE* _Nullable __fp) __INTRODUCED_IN(28);
-__wur int fgetc_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(28);
+__nodiscard int fgetc_unlocked(FILE* _Nonnull __fp) __INTRODUCED_IN(28);
int fputc_unlocked(int __ch, FILE* _Nonnull __fp) __INTRODUCED_IN(28);
size_t fread_unlocked(void* _Nonnull __buf, size_t __size, size_t __count, FILE* _Nonnull __fp) __INTRODUCED_IN(28);
size_t fwrite_unlocked(const void* _Nonnull __buf, size_t __size, size_t __count, FILE* _Nonnull __fp) __INTRODUCED_IN(28);
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index b31b122..076a978 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -79,9 +79,9 @@
*
* Available since API level 28.
*/
-__wur void* _Nullable aligned_alloc(size_t __alignment, size_t __size) __INTRODUCED_IN(28);
+__nodiscard void* _Nullable aligned_alloc(size_t __alignment, size_t __size) __INTRODUCED_IN(28);
-__wur char* _Nullable realpath(const char* _Nonnull __path, char* _Nullable __resolved);
+__nodiscard char* _Nullable realpath(const char* _Nonnull __path, char* _Nullable __resolved);
/**
* [system(3)](https://man7.org/linux/man-pages/man3/system.3.html) executes
@@ -107,7 +107,7 @@
* Returns a pointer to a matching item on success,
* or NULL if no matching item is found.
*/
-__wur void* _Nullable bsearch(const void* _Nonnull __key, const void* _Nullable __base, size_t __nmemb, size_t __size, int (* _Nonnull __comparator)(const void* _Nonnull __lhs, const void* _Nonnull __rhs));
+__nodiscard void* _Nullable bsearch(const void* _Nonnull __key, const void* _Nullable __base, size_t __nmemb, size_t __size, int (* _Nonnull __comparator)(const void* _Nonnull __lhs, const void* _Nonnull __rhs));
/**
* [qsort(3)](https://man7.org/linux/man-pages/man3/qsort.3.html) sorts an array
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 5d1718e..4aea97a 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -140,7 +140,8 @@
#define __predict_true(exp) __builtin_expect((exp) != 0, 1)
#define __predict_false(exp) __builtin_expect((exp) != 0, 0)
-#define __wur __attribute__((__warn_unused_result__))
+#define __nodiscard __attribute__((__warn_unused_result__))
+#define __wur __nodiscard
#define __errorattr(msg) __attribute__((__unavailable__(msg)))
#define __warnattr(msg) __attribute__((__deprecated__(msg)))
diff --git a/libc/include/sys/random.h b/libc/include/sys/random.h
index fcea419..b4a9993 100644
--- a/libc/include/sys/random.h
+++ b/libc/include/sys/random.h
@@ -52,6 +52,6 @@
*
* See also arc4random_buf() which is available in all API levels.
*/
-ssize_t getrandom(void* _Nonnull __buffer, size_t __buffer_size, unsigned int __flags) __wur __INTRODUCED_IN(28);
+__nodiscard ssize_t getrandom(void* _Nonnull __buffer, size_t __buffer_size, unsigned int __flags) __INTRODUCED_IN(28);
__END_DECLS
diff --git a/libc/include/threads.h b/libc/include/threads.h
index b1008de..1074fa4 100644
--- a/libc/include/threads.h
+++ b/libc/include/threads.h
@@ -72,8 +72,10 @@
thrd_timedout = 4,
};
-#if !defined(__cplusplus)
-#define thread_local _Thread_local
+/* `thread_local` is a keyword in C++11 and C23; C11 had `_Thread_local` instead. */
+#if !defined(__cplusplus) && (__STDC_VERSION__ >= 201112L && __STDC_VERSION__ < 202311L)
+# undef thread_local
+# define thread_local _Thread_local
#endif
__BEGIN_DECLS
diff --git a/libc/private/bionic_mbstate.h b/libc/private/bionic_mbstate.h
index 0e5f861..fb85775 100644
--- a/libc/private/bionic_mbstate.h
+++ b/libc/private/bionic_mbstate.h
@@ -38,11 +38,11 @@
(rv == BIONIC_MULTIBYTE_RESULT_ILLEGAL_SEQUENCE || \
rv == BIONIC_MULTIBYTE_RESULT_INCOMPLETE_SEQUENCE)
-static inline __wur bool mbstate_is_initial(const mbstate_t* ps) {
+static inline __nodiscard bool mbstate_is_initial(const mbstate_t* ps) {
return *(reinterpret_cast<const uint32_t*>(ps->__seq)) == 0;
}
-static inline __wur size_t mbstate_bytes_so_far(const mbstate_t* ps) {
+static inline __nodiscard size_t mbstate_bytes_so_far(const mbstate_t* ps) {
return
(ps->__seq[2] != 0) ? 3 :
(ps->__seq[1] != 0) ? 2 :
@@ -53,7 +53,7 @@
ps->__seq[i] = static_cast<uint8_t>(byte);
}
-static inline __wur uint8_t mbstate_get_byte(const mbstate_t* ps, int n) {
+static inline __nodiscard uint8_t mbstate_get_byte(const mbstate_t* ps, int n) {
return ps->__seq[n];
}
@@ -61,13 +61,13 @@
*(reinterpret_cast<uint32_t*>(ps->__seq)) = 0;
}
-static inline __wur size_t mbstate_reset_and_return_illegal(int _errno, mbstate_t* ps) {
+static inline __nodiscard size_t mbstate_reset_and_return_illegal(int _errno, mbstate_t* ps) {
errno = _errno;
mbstate_reset(ps);
return BIONIC_MULTIBYTE_RESULT_ILLEGAL_SEQUENCE;
}
-static inline __wur size_t mbstate_reset_and_return(size_t _return, mbstate_t* ps) {
+static inline __nodiscard size_t mbstate_reset_and_return(size_t _return, mbstate_t* ps) {
mbstate_reset(ps);
return _return;
}
diff --git a/libdl/Android.bp b/libdl/Android.bp
index 1bbd902..87db4b1 100644
--- a/libdl/Android.bp
+++ b/libdl/Android.bp
@@ -123,7 +123,6 @@
},
apex_available: [
- "//apex_available:platform",
"com.android.runtime",
],
}
@@ -170,7 +169,6 @@
},
apex_available: [
- "//apex_available:platform",
"com.android.runtime",
],
}
diff --git a/libm/Android.bp b/libm/Android.bp
index 9fd79f8..ee86959 100644
--- a/libm/Android.bp
+++ b/libm/Android.bp
@@ -435,7 +435,6 @@
},
apex_available: [
- "//apex_available:platform",
"com.android.runtime",
],
diff --git a/linker/Android.bp b/linker/Android.bp
index 563cf3d..d82e687 100644
--- a/linker/Android.bp
+++ b/linker/Android.bp
@@ -394,6 +394,10 @@
},
afdo: true,
+
+ // FIXME: Workaround compat issue with obfuscation libraries.
+ // http://b/352456802
+ lto_O0: true,
}
// ========================================================
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 4365ea5..bcc2500 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -316,7 +316,7 @@
async_safe_fatal("library name \"%s\" too long", name);
}
- TRACE("name %s: allocating soinfo for ns=%p", name, ns);
+ LD_DEBUG(any, "name %s: allocating soinfo for ns=%p", name, ns);
soinfo* si = new (g_soinfo_allocator.alloc()) soinfo(ns, name, file_stat,
file_offset, rtld_flags);
@@ -326,7 +326,7 @@
si->generate_handle();
ns->add_soinfo(si);
- TRACE("name %s: allocated soinfo @ %p", name, si);
+ LD_DEBUG(any, "name %s: allocated soinfo @ %p", name, si);
return si;
}
@@ -349,7 +349,7 @@
munmap(reinterpret_cast<void*>(si->get_gap_start()), si->get_gap_size());
}
- TRACE("name %s: freeing soinfo @ %p", si->get_realpath(), si);
+ LD_DEBUG(any, "name %s: freeing soinfo @ %p", si->get_realpath(), si);
if (!solist_remove_soinfo(si)) {
async_safe_fatal("soinfo=%p is not in soinfo_list (double unload?)", si);
@@ -387,7 +387,7 @@
auto length = readlink(proc_self_fd, buf, sizeof(buf));
if (length == -1) {
if (!is_first_stage_init()) {
- PRINT("readlink(\"%s\" [fd=%d]) failed: %m", proc_self_fd, fd);
+ DL_WARN("readlink(\"%s\" [fd=%d]) failed: %m", proc_self_fd, fd);
}
return false;
}
@@ -818,8 +818,8 @@
}
if (s != nullptr) {
- TRACE_TYPE(LOOKUP, "%s s->st_value = %p, found->base = %p",
- name, reinterpret_cast<void*>(s->st_value), reinterpret_cast<void*>((*found)->base));
+ LD_DEBUG(lookup, "%s s->st_value = %p, found->base = %p",
+ name, reinterpret_cast<void*>(s->st_value), reinterpret_cast<void*>((*found)->base));
}
return s;
@@ -923,7 +923,7 @@
}
const char* const path = normalized_path.c_str();
- TRACE("Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path);
+ LD_DEBUG(any, "Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path);
// Treat an '!/' separator inside a path as the separator between the name
// of the zip file on disk and the subdirectory to search within it.
@@ -936,7 +936,7 @@
char buf[512];
if (strlcpy(buf, path, sizeof(buf)) >= sizeof(buf)) {
- PRINT("Warning: ignoring very long library path: %s", path);
+ DL_WARN("ignoring very long library path: %s", path);
return -1;
}
@@ -976,8 +976,8 @@
*realpath += separator;
} else {
if (!is_first_stage_init()) {
- PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.",
- normalized_path.c_str());
+ DL_WARN("unable to get realpath for the library \"%s\". Will use given path.",
+ normalized_path.c_str());
}
*realpath = normalized_path;
}
@@ -988,7 +988,7 @@
static bool format_path(char* buf, size_t buf_size, const char* path, const char* name) {
int n = async_safe_format_buffer(buf, buf_size, "%s/%s", path, name);
if (n < 0 || n >= static_cast<int>(buf_size)) {
- PRINT("Warning: ignoring very long library path: %s/%s", path, name);
+ DL_WARN("ignoring very long library path: %s/%s", path, name);
return false;
}
@@ -1009,8 +1009,7 @@
*file_offset = 0;
if (!realpath_fd(fd, realpath)) {
if (!is_first_stage_init()) {
- PRINT("warning: unable to get realpath for the library \"%s\". Will use given path.",
- path);
+ DL_WARN("unable to get realpath for the library \"%s\". Will use given path.", path);
}
*realpath = path;
}
@@ -1043,7 +1042,7 @@
ZipArchiveCache* zip_archive_cache,
const char* name, soinfo *needed_by,
off64_t* file_offset, std::string* realpath) {
- TRACE("[ opening %s from namespace %s ]", name, ns->get_name());
+ LD_DEBUG(any, "[ opening %s from namespace %s ]", name, ns->get_name());
// If the name contains a slash, we should attempt to open it directly and not search the paths.
if (strchr(name, '/') != nullptr) {
@@ -1249,15 +1248,15 @@
// do not print this if a library is in the list of shared libraries for linked namespaces
if (!maybe_accessible_via_namespace_links(ns, name)) {
- PRINT("library \"%s\" (\"%s\") needed or dlopened by \"%s\" is not accessible for the"
- " namespace: [name=\"%s\", ld_library_paths=\"%s\", default_library_paths=\"%s\","
- " permitted_paths=\"%s\"]",
- name, realpath.c_str(),
- needed_or_dlopened_by,
- ns->get_name(),
- android::base::Join(ns->get_ld_library_paths(), ':').c_str(),
- android::base::Join(ns->get_default_library_paths(), ':').c_str(),
- android::base::Join(ns->get_permitted_paths(), ':').c_str());
+ DL_WARN("library \"%s\" (\"%s\") needed or dlopened by \"%s\" is not accessible for the"
+ " namespace: [name=\"%s\", ld_library_paths=\"%s\", default_library_paths=\"%s\","
+ " permitted_paths=\"%s\"]",
+ name, realpath.c_str(),
+ needed_or_dlopened_by,
+ ns->get_name(),
+ android::base::Join(ns->get_ld_library_paths(), ':').c_str(),
+ android::base::Join(ns->get_default_library_paths(), ':').c_str(),
+ android::base::Join(ns->get_permitted_paths(), ':').c_str());
}
return false;
}
@@ -1330,10 +1329,9 @@
std::string realpath;
if (!realpath_fd(extinfo->library_fd, &realpath)) {
if (!is_first_stage_init()) {
- PRINT(
- "warning: unable to get realpath for the library \"%s\" by extinfo->library_fd. "
- "Will use given name.",
- name);
+ DL_WARN("unable to get realpath for the library \"%s\" by extinfo->library_fd. "
+ "Will use given name.",
+ name);
}
realpath = name;
}
@@ -1474,8 +1472,8 @@
// Library might still be loaded, the accurate detection
// of this fact is done by load_library.
- TRACE("[ \"%s\" find_loaded_library_by_soname failed (*candidate=%s@%p). Trying harder... ]",
- task->get_name(), candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
+ LD_DEBUG(any, "[ \"%s\" find_loaded_library_by_soname failed (*candidate=%s@%p). Trying harder... ]",
+ task->get_name(), candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
if (load_library(ns, task, zip_archive_cache, load_tasks, rtld_flags,
true /* search_linked_namespaces */)) {
@@ -1906,8 +1904,8 @@
if (si->has_min_version(0)) {
soinfo* child = nullptr;
while ((child = si->get_children().pop_front()) != nullptr) {
- TRACE("%s@%p needs to unload %s@%p", si->get_realpath(), si,
- child->get_realpath(), child);
+ LD_DEBUG(any, "%s@%p needs to unload %s@%p", si->get_realpath(), si,
+ child->get_realpath(), child);
child->get_parents().remove(si);
@@ -2197,10 +2195,10 @@
if (file_exists(translated_name_holder.c_str())) {
soinfo* si = nullptr;
if (find_loaded_library_by_realpath(ns, original_path, true, &si)) {
- PRINT("linker_asan dlopen NOT translating \"%s\" -> \"%s\": library already loaded", name,
- translated_name_holder.c_str());
+ DL_WARN("linker_asan dlopen NOT translating \"%s\" -> \"%s\": library already loaded", name,
+ translated_name_holder.c_str());
} else {
- PRINT("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
+ DL_WARN("linker_asan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
translated_name = translated_name_holder.c_str();
}
}
@@ -2217,10 +2215,10 @@
if (!translated_name_holder.empty() && file_exists(translated_name_holder.c_str())) {
soinfo* si = nullptr;
if (find_loaded_library_by_realpath(ns, original_path, true, &si)) {
- PRINT("linker_hwasan dlopen NOT translating \"%s\" -> \"%s\": library already loaded", name,
- translated_name_holder.c_str());
+ DL_WARN("linker_hwasan dlopen NOT translating \"%s\" -> \"%s\": library already loaded",
+ name, translated_name_holder.c_str());
} else {
- PRINT("linker_hwasan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
+ DL_WARN("linker_hwasan dlopen translating \"%s\" -> \"%s\"", name, translated_name);
translated_name = translated_name_holder.c_str();
}
}
@@ -2589,8 +2587,8 @@
if (g_is_ldd) return 0;
ElfW(Addr) ifunc_addr = __bionic_call_ifunc_resolver(resolver_addr);
- TRACE_TYPE(RELO, "Called ifunc_resolver@%p. The result is %p",
- reinterpret_cast<void *>(resolver_addr), reinterpret_cast<void*>(ifunc_addr));
+ LD_DEBUG(calls, "ifunc_resolver@%p returned %p",
+ reinterpret_cast<void *>(resolver_addr), reinterpret_cast<void*>(ifunc_addr));
return ifunc_addr;
}
@@ -2842,8 +2840,8 @@
/* We can't log anything until the linker is relocated */
bool relocating_linker = (flags_ & FLAG_LINKER) != 0;
if (!relocating_linker) {
- INFO("[ Linking \"%s\" ]", get_realpath());
- DEBUG("si->base = %p si->flags = 0x%08x", reinterpret_cast<void*>(base), flags_);
+ LD_DEBUG(any, "[ Linking \"%s\" ]", get_realpath());
+ LD_DEBUG(any, "si->base = %p si->flags = 0x%08x", reinterpret_cast<void*>(base), flags_);
}
if (dynamic == nullptr) {
@@ -2853,7 +2851,7 @@
return false;
} else {
if (!relocating_linker) {
- DEBUG("dynamic = %p", dynamic);
+ LD_DEBUG(dynamic, "dynamic section @%p", dynamic);
}
}
@@ -2883,8 +2881,8 @@
// source: http://www.sco.com/developers/gabi/1998-04-29/ch5.dynamic.html
uint32_t needed_count = 0;
for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
- DEBUG("d = %p, d[0](tag) = %p d[1](val) = %p",
- d, reinterpret_cast<void*>(d->d_tag), reinterpret_cast<void*>(d->d_un.d_val));
+ LD_DEBUG(dynamic, "dynamic entry @%p: d_tag=%p, d_val=%p",
+ d, reinterpret_cast<void*>(d->d_tag), reinterpret_cast<void*>(d->d_un.d_val));
switch (d->d_tag) {
case DT_SONAME:
// this is parsed after we have strtab initialized (see below).
@@ -3098,17 +3096,17 @@
case DT_INIT:
init_func_ = reinterpret_cast<linker_ctor_function_t>(load_bias + d->d_un.d_ptr);
- DEBUG("%s constructors (DT_INIT) found at %p", get_realpath(), init_func_);
+ LD_DEBUG(dynamic, "%s constructors (DT_INIT) found at %p", get_realpath(), init_func_);
break;
case DT_FINI:
fini_func_ = reinterpret_cast<linker_dtor_function_t>(load_bias + d->d_un.d_ptr);
- DEBUG("%s destructors (DT_FINI) found at %p", get_realpath(), fini_func_);
+ LD_DEBUG(dynamic, "%s destructors (DT_FINI) found at %p", get_realpath(), fini_func_);
break;
case DT_INIT_ARRAY:
init_array_ = reinterpret_cast<linker_ctor_function_t*>(load_bias + d->d_un.d_ptr);
- DEBUG("%s constructors (DT_INIT_ARRAY) found at %p", get_realpath(), init_array_);
+ LD_DEBUG(dynamic, "%s constructors (DT_INIT_ARRAY) found at %p", get_realpath(), init_array_);
break;
case DT_INIT_ARRAYSZ:
@@ -3117,7 +3115,7 @@
case DT_FINI_ARRAY:
fini_array_ = reinterpret_cast<linker_dtor_function_t*>(load_bias + d->d_un.d_ptr);
- DEBUG("%s destructors (DT_FINI_ARRAY) found at %p", get_realpath(), fini_array_);
+ LD_DEBUG(dynamic, "%s destructors (DT_FINI_ARRAY) found at %p", get_realpath(), fini_array_);
break;
case DT_FINI_ARRAYSZ:
@@ -3126,7 +3124,7 @@
case DT_PREINIT_ARRAY:
preinit_array_ = reinterpret_cast<linker_ctor_function_t*>(load_bias + d->d_un.d_ptr);
- DEBUG("%s constructors (DT_PREINIT_ARRAY) found at %p", get_realpath(), preinit_array_);
+ LD_DEBUG(dynamic, "%s constructors (DT_PREINIT_ARRAY) found at %p", get_realpath(), preinit_array_);
break;
case DT_PREINIT_ARRAYSZ:
@@ -3266,8 +3264,8 @@
}
}
- DEBUG("si->base = %p, si->strtab = %p, si->symtab = %p",
- reinterpret_cast<void*>(base), strtab_, symtab_);
+ LD_DEBUG(dynamic, "si->base = %p, si->strtab = %p, si->symtab = %p",
+ reinterpret_cast<void*>(base), strtab_, symtab_);
// Validity checks.
if (relocating_linker && needed_count != 0) {
@@ -3374,7 +3372,7 @@
return false;
}
- DEBUG("[ finished linking %s ]", get_realpath());
+ LD_DEBUG(any, "[ finished linking %s ]", get_realpath());
#if !defined(__LP64__)
if (has_text_relocations) {
@@ -3556,7 +3554,7 @@
{
std::string ld_config_file_path = get_ld_config_file_path(executable_path);
- INFO("[ Reading linker config \"%s\" ]", ld_config_file_path.c_str());
+ LD_DEBUG(any, "[ Reading linker config \"%s\" ]", ld_config_file_path.c_str());
ScopedTrace trace(("linker config " + ld_config_file_path).c_str());
std::string error_msg;
if (!Config::read_binary_config(ld_config_file_path.c_str(), executable_path, g_is_asan, g_is_hwasan,
diff --git a/linker/linker_cfi.cpp b/linker/linker_cfi.cpp
index 247a25d..92ec53e 100644
--- a/linker/linker_cfi.cpp
+++ b/linker/linker_cfi.cpp
@@ -166,13 +166,13 @@
}
uintptr_t cfi_check = soinfo_find_cfi_check(si);
if (cfi_check == 0) {
- INFO("[ CFI add 0x%zx + 0x%zx %s ]", static_cast<uintptr_t>(si->base),
+ LD_DEBUG(cfi, "[ CFI add 0x%zx + 0x%zx %s ]", static_cast<uintptr_t>(si->base),
static_cast<uintptr_t>(si->size), si->get_soname());
AddUnchecked(si->base, si->base + si->size);
return true;
}
- INFO("[ CFI add 0x%zx + 0x%zx %s: 0x%zx ]", static_cast<uintptr_t>(si->base),
+ LD_DEBUG(cfi, "[ CFI add 0x%zx + 0x%zx %s: 0x%zx ]", static_cast<uintptr_t>(si->base),
static_cast<uintptr_t>(si->size), si->get_soname(), cfi_check);
#ifdef __arm__
// Require Thumb encoding.
@@ -263,8 +263,8 @@
void CFIShadowWriter::BeforeUnload(soinfo* si) {
if (shadow_start == nullptr) return;
if (si->base == 0 || si->size == 0) return;
- INFO("[ CFI remove 0x%zx + 0x%zx: %s ]", static_cast<uintptr_t>(si->base),
- static_cast<uintptr_t>(si->size), si->get_soname());
+ LD_DEBUG(cfi, "[ CFI remove 0x%zx + 0x%zx: %s ]", static_cast<uintptr_t>(si->base),
+ static_cast<uintptr_t>(si->size), si->get_soname());
AddInvalid(si->base, si->base + si->size);
FixupVmaName();
}
diff --git a/linker/linker_config.cpp b/linker/linker_config.cpp
index 73ae2ef..35a93fc 100644
--- a/linker/linker_config.cpp
+++ b/linker/linker_config.cpp
@@ -251,10 +251,8 @@
// the failure with INFO rather than DL_WARN. e.g. A binary in
// /data/local/tmp may attempt to stat /postinstall. See
// http://b/120996057.
- INFO("%s:%zd: warning: path \"%s\" couldn't be resolved: %m",
- ld_config_file_path,
- cp.lineno(),
- value.c_str());
+ LD_DEBUG(any, "%s:%zd: warning: path \"%s\" couldn't be resolved: %m",
+ ld_config_file_path, cp.lineno(), value.c_str());
resolved_path = value;
}
@@ -265,7 +263,7 @@
}
}
- INFO("[ Using config section \"%s\" ]", section_name.c_str());
+ LD_DEBUG(any, "[ Using config section \"%s\" ]", section_name.c_str());
// skip everything until we meet a correct section
while (true) {
diff --git a/linker/linker_debug.cpp b/linker/linker_debug.cpp
index e6211f7..430a151 100644
--- a/linker/linker_debug.cpp
+++ b/linker/linker_debug.cpp
@@ -30,19 +30,76 @@
#include <unistd.h>
-void linker_log_va_list(int prio, const char* fmt, va_list ap) {
+#include <android-base/strings.h>
+
+LinkerDebugConfig g_linker_debug_config;
+
+void init_LD_DEBUG(const std::string& value) {
+ if (value.empty()) return;
+ std::vector<std::string> options = android::base::Split(value, ",");
+ for (const auto& o : options) {
+ if (o == "calls") g_linker_debug_config.calls = true;
+ else if (o == "cfi") g_linker_debug_config.cfi = true;
+ else if (o == "dynamic") g_linker_debug_config.dynamic = true;
+ else if (o == "lookup") g_linker_debug_config.lookup = true;
+ else if (o == "props") g_linker_debug_config.props = true;
+ else if (o == "reloc") g_linker_debug_config.reloc = true;
+ else if (o == "statistics") g_linker_debug_config.statistics = true;
+ else if (o == "timing") g_linker_debug_config.timing = true;
+ else if (o == "all") {
+ g_linker_debug_config.calls = true;
+ g_linker_debug_config.cfi = true;
+ g_linker_debug_config.dynamic = true;
+ g_linker_debug_config.lookup = true;
+ g_linker_debug_config.props = true;
+ g_linker_debug_config.reloc = true;
+ g_linker_debug_config.statistics = true;
+ g_linker_debug_config.timing = true;
+ } else {
+ __linker_error("$LD_DEBUG is a comma-separated list of:\n"
+ "\n"
+ " calls ctors/dtors/ifuncs\n"
+ " cfi control flow integrity messages\n"
+ " dynamic dynamic section processing\n"
+ " lookup symbol lookup\n"
+ " props ELF property processing\n"
+ " reloc relocation resolution\n"
+ " statistics relocation statistics\n"
+ " timing timing information\n"
+ "\n"
+ "or 'all' for all of the above.\n");
+ }
+ }
+ if (g_linker_debug_config.calls || g_linker_debug_config.cfi ||
+ g_linker_debug_config.dynamic || g_linker_debug_config.lookup ||
+ g_linker_debug_config.props || g_linker_debug_config.reloc ||
+ g_linker_debug_config.statistics || g_linker_debug_config.timing) {
+ g_linker_debug_config.any = true;
+ }
+}
+
+static void linker_log_va_list(int prio, const char* fmt, va_list ap) {
va_list ap2;
va_copy(ap2, ap);
- async_safe_format_log_va_list(5 - prio, "linker", fmt, ap2);
+ async_safe_format_log_va_list(prio, "linker", fmt, ap2);
va_end(ap2);
async_safe_format_fd_va_list(STDERR_FILENO, fmt, ap);
write(STDERR_FILENO, "\n", 1);
}
-void linker_log(int prio, const char* fmt, ...) {
+void __linker_log(int prio, const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
linker_log_va_list(prio, fmt, ap);
va_end(ap);
}
+
+void __linker_error(const char* fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ linker_log_va_list(ANDROID_LOG_FATAL, fmt, ap);
+ va_end(ap);
+
+ _exit(EXIT_FAILURE);
+}
diff --git a/linker/linker_debug.h b/linker/linker_debug.h
index 3aab185..e5f17c4 100644
--- a/linker/linker_debug.h
+++ b/linker/linker_debug.h
@@ -28,54 +28,45 @@
#pragma once
-// You can increase the verbosity of debug traces by defining the LD_DEBUG
-// environment variable to a numeric value from 0 to 2 (corresponding to
-// INFO, TRACE, and DEBUG calls in the source). This will only
-// affect new processes being launched.
-
-#define TRACE_DEBUG 1
-#define DO_TRACE_LOOKUP 1
-#define DO_TRACE_RELO 1
-#define DO_TRACE_IFUNC 1
-#define TIMING 0
-#define STATS 0
-
-/*********************************************************************
- * You shouldn't need to modify anything below unless you are adding
- * more debugging information.
- *
- * To enable/disable specific debug options, change the defines above
- *********************************************************************/
-
#include <stdarg.h>
#include <unistd.h>
+#include <string>
+
#include <async_safe/log.h>
#include <async_safe/CHECK.h>
-#define LINKER_VERBOSITY_PRINT (-1)
-#define LINKER_VERBOSITY_INFO 0
-#define LINKER_VERBOSITY_TRACE 1
-#define LINKER_VERBOSITY_DEBUG 2
+struct LinkerDebugConfig {
+ // Set automatically if any of the more specific options are set.
+ bool any;
-__LIBC_HIDDEN__ extern int g_ld_debug_verbosity;
+ // Messages relating to calling ctors/dtors/ifuncs.
+ bool calls;
+ // Messages relating to CFI.
+ bool cfi;
+ // Messages relating to the dynamic section.
+ bool dynamic;
+ // Messages relating to symbol lookup.
+ bool lookup;
+ // Messages relating to relocation processing.
+ bool reloc;
+ // Messages relating to ELF properties.
+ bool props;
+ // TODO: "config" and "zip" seem likely to want to be separate?
-__LIBC_HIDDEN__ void linker_log_va_list(int prio, const char* fmt, va_list ap);
-__LIBC_HIDDEN__ void linker_log(int prio, const char* fmt, ...) __printflike(2, 3);
+ bool timing;
+ bool statistics;
+};
-#define _PRINTVF(v, x...) \
- do { \
- if (g_ld_debug_verbosity > (v)) linker_log((v), x); \
- } while (0)
+extern LinkerDebugConfig g_linker_debug_config;
-#define PRINT(x...) _PRINTVF(LINKER_VERBOSITY_PRINT, x)
-#define INFO(x...) _PRINTVF(LINKER_VERBOSITY_INFO, x)
-#define TRACE(x...) _PRINTVF(LINKER_VERBOSITY_TRACE, x)
+__LIBC_HIDDEN__ void init_LD_DEBUG(const std::string& value);
+__LIBC_HIDDEN__ void __linker_log(int prio, const char* fmt, ...) __printflike(2, 3);
+__LIBC_HIDDEN__ void __linker_error(const char* fmt, ...) __printflike(1, 2);
-#if TRACE_DEBUG
-#define DEBUG(x...) _PRINTVF(LINKER_VERBOSITY_DEBUG, "DEBUG: " x)
-#else /* !TRACE_DEBUG */
-#define DEBUG(x...) do {} while (0)
-#endif /* TRACE_DEBUG */
-
-#define TRACE_TYPE(t, x...) do { if (DO_TRACE_##t) { TRACE(x); } } while (0)
+#define LD_DEBUG(what, x...) \
+ do { \
+ if (g_linker_debug_config.what) { \
+ __linker_log(ANDROID_LOG_INFO, x); \
+ } \
+ } while (false)
diff --git a/linker/linker_globals.h b/linker/linker_globals.h
index 0cb7ca9..2bfdccd 100644
--- a/linker/linker_globals.h
+++ b/linker/linker_globals.h
@@ -54,7 +54,7 @@
#define DL_ERR_AND_LOG(fmt, x...) \
do { \
DL_ERR(fmt, ##x); \
- PRINT(fmt, ##x); \
+ __linker_log(ANDROID_LOG_ERROR, fmt, ##x); \
} while (false)
#define DL_OPEN_ERR(fmt, x...) \
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index 86b6509..6ccd75b 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -73,21 +73,6 @@
void __libc_init_mte(const memtag_dynamic_entries_t* memtag_dynamic_entries, const void* phdr_start,
size_t phdr_count, uintptr_t load_bias, void* stack_top);
-__printflike(1, 2) static void __linker_error(const char* fmt, ...) {
- va_list ap;
-
- va_start(ap, fmt);
- async_safe_format_fd_va_list(STDERR_FILENO, fmt, ap);
- write(STDERR_FILENO, "\n", 1);
- va_end(ap);
-
- va_start(ap, fmt);
- async_safe_format_log_va_list(ANDROID_LOG_FATAL, "linker", fmt, ap);
- va_end(ap);
-
- _exit(EXIT_FAILURE);
-}
-
static void __linker_cannot_link(const char* argv0) {
__linker_error("CANNOT LINK EXECUTABLE \"%s\": %s", argv0, linker_get_error_buffer());
}
@@ -119,7 +104,7 @@
if (trav == nullptr) {
// si was not in solist
- PRINT("name \"%s\"@%p is not in solist!", si->get_realpath(), si);
+ DL_WARN("name \"%s\"@%p is not in solist!", si->get_realpath(), si);
return false;
}
@@ -147,7 +132,6 @@
}
bool g_is_ldd;
-int g_ld_debug_verbosity;
static std::vector<std::string> g_ld_preload_names;
@@ -296,10 +280,8 @@
static ElfW(Addr) linker_main(KernelArgumentBlock& args, const char* exe_to_load) {
ProtectedDataGuard guard;
-#if TIMING
- struct timeval t0, t1;
- gettimeofday(&t0, 0);
-#endif
+ timeval t0, t1;
+ gettimeofday(&t0, nullptr);
// Sanitize the environment.
__libc_init_AT_SECURE(args.envp);
@@ -317,13 +299,11 @@
// Enable debugging logs?
const char* LD_DEBUG = getenv("LD_DEBUG");
- if (LD_DEBUG != nullptr) {
- g_ld_debug_verbosity = atoi(LD_DEBUG);
- }
+ if (LD_DEBUG != nullptr) init_LD_DEBUG(LD_DEBUG);
if (getenv("LD_SHOW_AUXV") != nullptr) ld_show_auxv(args.auxv);
- INFO("[ Android dynamic linker (" ABI_STRING ") ]");
+ LD_DEBUG(any, "[ Android dynamic linker (" ABI_STRING ") ]");
// These should have been sanitized by __libc_init_AT_SECURE, but the test
// doesn't cost us anything.
@@ -332,18 +312,18 @@
if (!getauxval(AT_SECURE)) {
ldpath_env = getenv("LD_LIBRARY_PATH");
if (ldpath_env != nullptr) {
- INFO("[ LD_LIBRARY_PATH set to \"%s\" ]", ldpath_env);
+ LD_DEBUG(any, "[ LD_LIBRARY_PATH set to \"%s\" ]", ldpath_env);
}
ldpreload_env = getenv("LD_PRELOAD");
if (ldpreload_env != nullptr) {
- INFO("[ LD_PRELOAD set to \"%s\" ]", ldpreload_env);
+ LD_DEBUG(any, "[ LD_PRELOAD set to \"%s\" ]", ldpreload_env);
}
}
const ExecutableInfo exe_info = exe_to_load ? load_executable(exe_to_load) :
get_executable_info(args.argv[0]);
- INFO("[ Linking executable \"%s\" ]", exe_info.path.c_str());
+ LD_DEBUG(any, "[ Linking executable \"%s\" ]", exe_info.path.c_str());
// Initialize the main exe's soinfo.
soinfo* si = soinfo_alloc(&g_default_namespace,
@@ -496,27 +476,22 @@
si->call_pre_init_constructors();
si->call_constructors();
-#if TIMING
- gettimeofday(&t1, nullptr);
- PRINT("LINKER TIME: %s: %d microseconds", g_argv[0],
- static_cast<int>(((static_cast<long long>(t1.tv_sec) * 1000000LL) +
- static_cast<long long>(t1.tv_usec)) -
- ((static_cast<long long>(t0.tv_sec) * 1000000LL) +
- static_cast<long long>(t0.tv_usec))));
-#endif
-#if STATS
- print_linker_stats();
-#endif
-#if TIMING || STATS
- fflush(stdout);
-#endif
+ if (g_linker_debug_config.timing) {
+ gettimeofday(&t1, nullptr);
+ long long t0_us = (t0.tv_sec * 1000000LL) + t0.tv_usec;
+ long long t1_us = (t1.tv_sec * 1000000LL) + t1.tv_usec;
+ LD_DEBUG(timing, "LINKER TIME: %s: %lld microseconds", g_argv[0], t1_us - t0_us);
+ }
+ if (g_linker_debug_config.statistics) {
+ print_linker_stats();
+ }
// We are about to hand control over to the executable loaded. We don't want
// to leave dirty pages behind unnecessarily.
purge_unused_memory();
ElfW(Addr) entry = exe_info.entry_point;
- TRACE("[ Ready to execute \"%s\" @ %p ]", si->get_realpath(), reinterpret_cast<void*>(entry));
+ LD_DEBUG(any, "[ Ready to execute \"%s\" @ %p ]", si->get_realpath(), reinterpret_cast<void*>(entry));
return entry;
}
@@ -833,7 +808,7 @@
ElfW(Addr) start_address = linker_main(args, exe_to_load);
- INFO("[ Jumping to _start (%p)... ]", reinterpret_cast<void*>(start_address));
+ LD_DEBUG(any, "[ Jumping to _start (%p)... ]", reinterpret_cast<void*>(start_address));
// Return the address that the calling assembly stub should jump to.
return start_address;
diff --git a/linker/linker_note_gnu_property.cpp b/linker/linker_note_gnu_property.cpp
index be1aebc..082a604 100644
--- a/linker/linker_note_gnu_property.cpp
+++ b/linker/linker_note_gnu_property.cpp
@@ -62,7 +62,7 @@
continue;
}
- TRACE("\"%s\" PT_GNU_PROPERTY: found at segment index %zu", name, i);
+ LD_DEBUG(props, "\"%s\" PT_GNU_PROPERTY: found at segment index %zu", name, i);
// Check segment size.
if (phdr[i].p_memsz < sizeof(ElfW(NhdrGNUProperty))) {
@@ -90,7 +90,7 @@
}
}
- TRACE("\"%s\" PT_GNU_PROPERTY: not found", name);
+ LD_DEBUG(props, "\"%s\" PT_GNU_PROPERTY: not found", name);
return nullptr;
}
@@ -122,7 +122,7 @@
// The total length of the program property array is in _bytes_.
ElfW(Word) offset = 0;
while (offset < note_nhdr->nhdr.n_descsz) {
- DEBUG("\"%s\" .note.gnu.property: processing at offset 0x%x", name, offset);
+ LD_DEBUG(props, "\"%s\" .note.gnu.property: processing at offset 0x%x", name, offset);
// At least the "header" part must fit.
// The ABI doesn't say that pr_datasz can't be 0.
@@ -161,14 +161,14 @@
const ElfW(Word) flags = *reinterpret_cast<const ElfW(Word)*>(&property->pr_data[0]);
properties_.bti_compatible = (flags & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) != 0;
if (properties_.bti_compatible) {
- INFO("[ BTI compatible: \"%s\" ]", name);
+ LD_DEBUG(props, "[ BTI compatible: \"%s\" ]", name);
}
break;
}
#endif
default:
- DEBUG("\"%s\" .note.gnu.property: found property pr_type %u pr_datasz 0x%x", name,
- property->pr_type, property->pr_datasz);
+ LD_DEBUG(props, "\"%s\" .note.gnu.property: found property pr_type %u pr_datasz 0x%x",
+ name, property->pr_type, property->pr_datasz);
break;
}
diff --git a/linker/linker_relocate.cpp b/linker/linker_relocate.cpp
index 8f85871..bcb1efc 100644
--- a/linker/linker_relocate.cpp
+++ b/linker/linker_relocate.cpp
@@ -147,12 +147,13 @@
}
void print_linker_stats() {
- PRINT("RELO STATS: %s: %d abs, %d rel, %d symbol (%d cached)",
- g_argv[0],
- linker_stats.count[kRelocAbsolute],
- linker_stats.count[kRelocRelative],
- linker_stats.count[kRelocSymbol],
- linker_stats.count[kRelocSymbolCached]);
+ LD_DEBUG(statistics,
+ "RELO STATS: %s: %d abs, %d rel, %d symbol (%d cached)",
+ g_argv[0],
+ linker_stats.count[kRelocAbsolute],
+ linker_stats.count[kRelocRelative],
+ linker_stats.count[kRelocSymbol],
+ linker_stats.count[kRelocSymbolCached]);
}
static bool process_relocation_general(Relocator& relocator, const rel_t& reloc);
@@ -207,20 +208,9 @@
};
#endif
- auto trace_reloc = [](const char* fmt, ...) __printflike(2, 3) {
- if (IsGeneral &&
- g_ld_debug_verbosity > LINKER_VERBOSITY_TRACE &&
- DO_TRACE_RELO) {
- va_list ap;
- va_start(ap, fmt);
- linker_log_va_list(LINKER_VERBOSITY_TRACE, fmt, ap);
- va_end(ap);
- }
- };
-
// Skip symbol lookup for R_GENERIC_NONE relocations.
if (__predict_false(r_type == R_GENERIC_NONE)) {
- trace_reloc("RELO NONE");
+ LD_DEBUG(reloc && IsGeneral, "RELO NONE");
return true;
}
@@ -313,8 +303,8 @@
if (r_type == R_GENERIC_JUMP_SLOT) {
count_relocation_if<IsGeneral>(kRelocAbsolute);
const ElfW(Addr) result = sym_addr + get_addend_norel();
- trace_reloc("RELO JMP_SLOT %16p <- %16p %s",
- rel_target, reinterpret_cast<void*>(result), sym_name);
+ LD_DEBUG(reloc && IsGeneral, "RELO JMP_SLOT %16p <- %16p %s",
+ rel_target, reinterpret_cast<void*>(result), sym_name);
*static_cast<ElfW(Addr)*>(rel_target) = result;
return true;
}
@@ -327,8 +317,8 @@
if (r_type == R_GENERIC_ABSOLUTE) {
count_relocation_if<IsGeneral>(kRelocAbsolute);
const ElfW(Addr) result = sym_addr + get_addend_rel();
- trace_reloc("RELO ABSOLUTE %16p <- %16p %s",
- rel_target, reinterpret_cast<void*>(result), sym_name);
+ LD_DEBUG(reloc && IsGeneral, "RELO ABSOLUTE %16p <- %16p %s",
+ rel_target, reinterpret_cast<void*>(result), sym_name);
*static_cast<ElfW(Addr)*>(rel_target) = result;
return true;
} else if (r_type == R_GENERIC_GLOB_DAT) {
@@ -337,8 +327,8 @@
// it.
count_relocation_if<IsGeneral>(kRelocAbsolute);
const ElfW(Addr) result = sym_addr + get_addend_norel();
- trace_reloc("RELO GLOB_DAT %16p <- %16p %s",
- rel_target, reinterpret_cast<void*>(result), sym_name);
+ LD_DEBUG(reloc && IsGeneral, "RELO GLOB_DAT %16p <- %16p %s",
+ rel_target, reinterpret_cast<void*>(result), sym_name);
*static_cast<ElfW(Addr)*>(rel_target) = result;
return true;
} else if (r_type == R_GENERIC_RELATIVE) {
@@ -346,8 +336,8 @@
// referenced symbol (and abort if the symbol isn't found), even though it isn't used.
count_relocation_if<IsGeneral>(kRelocRelative);
const ElfW(Addr) result = relocator.si->load_bias + get_addend_rel();
- trace_reloc("RELO RELATIVE %16p <- %16p",
- rel_target, reinterpret_cast<void*>(result));
+ LD_DEBUG(reloc && IsGeneral, "RELO RELATIVE %16p <- %16p",
+ rel_target, reinterpret_cast<void*>(result));
*static_cast<ElfW(Addr)*>(rel_target) = result;
return true;
}
@@ -368,8 +358,8 @@
if (!relocator.si->is_linker()) {
count_relocation_if<IsGeneral>(kRelocRelative);
const ElfW(Addr) ifunc_addr = relocator.si->load_bias + get_addend_rel();
- trace_reloc("RELO IRELATIVE %16p <- %16p",
- rel_target, reinterpret_cast<void*>(ifunc_addr));
+ LD_DEBUG(reloc && IsGeneral, "RELO IRELATIVE %16p <- %16p",
+ rel_target, reinterpret_cast<void*>(ifunc_addr));
if (handle_text_relocs && !protect_segments()) return false;
const ElfW(Addr) result = call_ifunc_resolver(ifunc_addr);
if (handle_text_relocs && !unprotect_segments()) return false;
@@ -406,8 +396,8 @@
}
}
tpoff += sym_addr + get_addend_rel();
- trace_reloc("RELO TLS_TPREL %16p <- %16p %s",
- rel_target, reinterpret_cast<void*>(tpoff), sym_name);
+ LD_DEBUG(reloc && IsGeneral, "RELO TLS_TPREL %16p <- %16p %s",
+ rel_target, reinterpret_cast<void*>(tpoff), sym_name);
*static_cast<ElfW(Addr)*>(rel_target) = tpoff;
}
break;
@@ -422,8 +412,8 @@
module_id = found_in->get_tls()->module_id;
CHECK(module_id != kTlsUninitializedModuleId);
}
- trace_reloc("RELO TLS_DTPMOD %16p <- %zu %s",
- rel_target, module_id, sym_name);
+ LD_DEBUG(reloc && IsGeneral, "RELO TLS_DTPMOD %16p <- %zu %s",
+ rel_target, module_id, sym_name);
*static_cast<ElfW(Addr)*>(rel_target) = module_id;
}
break;
@@ -431,8 +421,8 @@
count_relocation_if<IsGeneral>(kRelocRelative);
{
const ElfW(Addr) result = sym_addr + get_addend_rel() - TLS_DTV_OFFSET;
- trace_reloc("RELO TLS_DTPREL %16p <- %16p %s",
- rel_target, reinterpret_cast<void*>(result), sym_name);
+ LD_DEBUG(reloc && IsGeneral, "RELO TLS_DTPREL %16p <- %16p %s",
+ rel_target, reinterpret_cast<void*>(result), sym_name);
*static_cast<ElfW(Addr)*>(rel_target) = result;
}
break;
@@ -449,8 +439,8 @@
// Unresolved weak relocation.
desc->func = tlsdesc_resolver_unresolved_weak;
desc->arg = addend;
- trace_reloc("RELO TLSDESC %16p <- unresolved weak, addend 0x%zx %s",
- rel_target, static_cast<size_t>(addend), sym_name);
+ LD_DEBUG(reloc && IsGeneral, "RELO TLSDESC %16p <- unresolved weak, addend 0x%zx %s",
+ rel_target, static_cast<size_t>(addend), sym_name);
} else {
CHECK(found_in->get_tls() != nullptr); // We rejected a missing TLS segment above.
size_t module_id = found_in->get_tls()->module_id;
@@ -458,10 +448,10 @@
if (mod.static_offset != SIZE_MAX) {
desc->func = tlsdesc_resolver_static;
desc->arg = mod.static_offset - relocator.tls_tp_base + sym_addr + addend;
- trace_reloc("RELO TLSDESC %16p <- static (0x%zx - 0x%zx + 0x%zx + 0x%zx) %s",
- rel_target, mod.static_offset, relocator.tls_tp_base,
- static_cast<size_t>(sym_addr), static_cast<size_t>(addend),
- sym_name);
+ LD_DEBUG(reloc && IsGeneral, "RELO TLSDESC %16p <- static (0x%zx - 0x%zx + 0x%zx + 0x%zx) %s",
+ rel_target, mod.static_offset, relocator.tls_tp_base,
+ static_cast<size_t>(sym_addr), static_cast<size_t>(addend),
+ sym_name);
} else {
relocator.tlsdesc_args->push_back({
.generation = mod.first_generation,
@@ -474,9 +464,9 @@
desc, relocator.tlsdesc_args->size() - 1
});
const TlsDynamicResolverArg& desc_arg = relocator.tlsdesc_args->back();
- trace_reloc("RELO TLSDESC %16p <- dynamic (gen %zu, mod %zu, off %zu) %s",
- rel_target, desc_arg.generation, desc_arg.index.module_id,
- desc_arg.index.offset, sym_name);
+ LD_DEBUG(reloc && IsGeneral, "RELO TLSDESC %16p <- dynamic (gen %zu, mod %zu, off %zu) %s",
+ rel_target, desc_arg.generation, desc_arg.index.module_id,
+ desc_arg.index.offset, sym_name);
}
}
}
@@ -488,8 +478,8 @@
count_relocation_if<IsGeneral>(kRelocAbsolute);
{
const Elf32_Addr result = sym_addr + reloc.r_addend;
- trace_reloc("RELO R_X86_64_32 %16p <- 0x%08x %s",
- rel_target, result, sym_name);
+ LD_DEBUG(reloc && IsGeneral, "RELO R_X86_64_32 %16p <- 0x%08x %s",
+ rel_target, result, sym_name);
*static_cast<Elf32_Addr*>(rel_target) = result;
}
break;
@@ -499,9 +489,9 @@
const ElfW(Addr) target = sym_addr + reloc.r_addend;
const ElfW(Addr) base = reinterpret_cast<ElfW(Addr)>(rel_target);
const Elf32_Addr result = target - base;
- trace_reloc("RELO R_X86_64_PC32 %16p <- 0x%08x (%16p - %16p) %s",
- rel_target, result, reinterpret_cast<void*>(target),
- reinterpret_cast<void*>(base), sym_name);
+ LD_DEBUG(reloc && IsGeneral, "RELO R_X86_64_PC32 %16p <- 0x%08x (%16p - %16p) %s",
+ rel_target, result, reinterpret_cast<void*>(target),
+ reinterpret_cast<void*>(base), sym_name);
*static_cast<Elf32_Addr*>(rel_target) = result;
}
break;
@@ -512,9 +502,9 @@
const ElfW(Addr) target = sym_addr + get_addend_rel();
const ElfW(Addr) base = reinterpret_cast<ElfW(Addr)>(rel_target);
const ElfW(Addr) result = target - base;
- trace_reloc("RELO R_386_PC32 %16p <- 0x%08x (%16p - %16p) %s",
- rel_target, result, reinterpret_cast<void*>(target),
- reinterpret_cast<void*>(base), sym_name);
+ LD_DEBUG(reloc && IsGeneral, "RELO R_386_PC32 %16p <- 0x%08x (%16p - %16p) %s",
+ rel_target, result, reinterpret_cast<void*>(target),
+ reinterpret_cast<void*>(base), sym_name);
*static_cast<ElfW(Addr)*>(rel_target) = result;
}
break;
@@ -559,15 +549,11 @@
}
static bool needs_slow_relocate_loop(const Relocator& relocator __unused) {
-#if STATS
- // TODO: This could become a run-time flag.
- return true;
-#endif
#if !defined(__LP64__)
if (relocator.si->has_text_relocations) return true;
#endif
- if (g_ld_debug_verbosity > LINKER_VERBOSITY_TRACE) {
- // If linker TRACE() is enabled, then each relocation is logged.
+ // Both LD_DEBUG relocation logging and statistics need the slow path.
+ if (g_linker_debug_config.any || g_linker_debug_config.statistics) {
return true;
}
return false;
@@ -611,7 +597,7 @@
// The linker already applied its RELR relocations in an earlier pass, so
// skip the RELR relocations for the linker.
if (relr_ != nullptr && !is_linker()) {
- DEBUG("[ relocating %s relr ]", get_realpath());
+ LD_DEBUG(reloc, "[ relocating %s relr ]", get_realpath());
const ElfW(Relr)* begin = relr_;
const ElfW(Relr)* end = relr_ + relr_count_;
if (!relocate_relr(begin, end, load_bias)) {
@@ -626,7 +612,7 @@
android_relocs_[1] == 'P' &&
android_relocs_[2] == 'S' &&
android_relocs_[3] == '2') {
- DEBUG("[ relocating %s android rel/rela ]", get_realpath());
+ LD_DEBUG(reloc, "[ relocating %s android rel/rela ]", get_realpath());
const uint8_t* packed_relocs = android_relocs_ + 4;
const size_t packed_relocs_size = android_relocs_size_ - 4;
@@ -642,27 +628,27 @@
#if defined(USE_RELA)
if (rela_ != nullptr) {
- DEBUG("[ relocating %s rela ]", get_realpath());
+ LD_DEBUG(reloc, "[ relocating %s rela ]", get_realpath());
if (!plain_relocate<RelocMode::Typical>(relocator, rela_, rela_count_)) {
return false;
}
}
if (plt_rela_ != nullptr) {
- DEBUG("[ relocating %s plt rela ]", get_realpath());
+ LD_DEBUG(reloc, "[ relocating %s plt rela ]", get_realpath());
if (!plain_relocate<RelocMode::JumpTable>(relocator, plt_rela_, plt_rela_count_)) {
return false;
}
}
#else
if (rel_ != nullptr) {
- DEBUG("[ relocating %s rel ]", get_realpath());
+ LD_DEBUG(reloc, "[ relocating %s rel ]", get_realpath());
if (!plain_relocate<RelocMode::Typical>(relocator, rel_, rel_count_)) {
return false;
}
}
if (plt_rel_ != nullptr) {
- DEBUG("[ relocating %s plt rel ]", get_realpath());
+ LD_DEBUG(reloc, "[ relocating %s plt rel ]", get_realpath());
if (!plain_relocate<RelocMode::JumpTable>(relocator, plt_rel_, plt_rel_count_)) {
return false;
}
diff --git a/linker/linker_soinfo.cpp b/linker/linker_soinfo.cpp
index b2170d8..0549d36 100644
--- a/linker/linker_soinfo.cpp
+++ b/linker/linker_soinfo.cpp
@@ -45,20 +45,15 @@
#include "linker_relocate.h"
#include "linker_utils.h"
-// Enable the slow lookup path if symbol lookups should be logged.
-static bool is_lookup_tracing_enabled() {
- return g_ld_debug_verbosity > LINKER_VERBOSITY_TRACE && DO_TRACE_LOOKUP;
-}
-
SymbolLookupList::SymbolLookupList(soinfo* si)
: sole_lib_(si->get_lookup_lib()), begin_(&sole_lib_), end_(&sole_lib_ + 1) {
CHECK(si != nullptr);
- slow_path_count_ += is_lookup_tracing_enabled();
+ slow_path_count_ += !!g_linker_debug_config.lookup;
slow_path_count_ += sole_lib_.needs_sysv_lookup();
}
SymbolLookupList::SymbolLookupList(const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
- slow_path_count_ += is_lookup_tracing_enabled();
+ slow_path_count_ += !!g_linker_debug_config.lookup;
libs_.reserve(1 + global_group.size() + local_group.size());
// Reserve a space in front for DT_SYMBOLIC lookup.
@@ -144,8 +139,8 @@
}
if (IsGeneral) {
- TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p (gnu)",
- name, lib->si_->get_realpath(), reinterpret_cast<void*>(lib->si_->base));
+ LD_DEBUG(lookup, "SEARCH %s in %s@%p (gnu)",
+ name, lib->si_->get_realpath(), reinterpret_cast<void*>(lib->si_->base));
}
const uint32_t word_num = (hash / kBloomMaskBits) & lib->gnu_maskwords_;
@@ -318,8 +313,8 @@
const uint32_t h1 = hash % kBloomMaskBits;
const uint32_t h2 = (hash >> gnu_shift2_) % kBloomMaskBits;
- TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p (gnu)",
- symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
+ LD_DEBUG(lookup, "SEARCH %s in %s@%p (gnu)",
+ symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
// test against bloom filter
if ((1 & (bloom_word >> h1) & (bloom_word >> h2)) == 0) {
@@ -352,9 +347,9 @@
const ElfW(Sym)* soinfo::elf_lookup(SymbolName& symbol_name, const version_info* vi) const {
uint32_t hash = symbol_name.elf_hash();
- TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p h=%x(elf) %zd",
- symbol_name.get_name(), get_realpath(),
- reinterpret_cast<void*>(base), hash, hash % nbucket_);
+ LD_DEBUG(lookup, "SEARCH %s in %s@%p h=%x(elf) %zd",
+ symbol_name.get_name(), get_realpath(),
+ reinterpret_cast<void*>(base), hash, hash % nbucket_);
const ElfW(Versym) verneed = find_verdef_version_index(this, vi);
const ElfW(Versym)* versym = get_versym_table();
@@ -429,9 +424,9 @@
return;
}
- TRACE("[ Calling c-tor %s @ %p for '%s' ]", function_name, function, realpath);
+ LD_DEBUG(calls, "[ Calling c-tor %s @ %p for '%s' ]", function_name, function, realpath);
function(g_argc, g_argv, g_envp);
- TRACE("[ Done calling c-tor %s @ %p for '%s' ]", function_name, function, realpath);
+ LD_DEBUG(calls, "[ Done calling c-tor %s @ %p for '%s' ]", function_name, function, realpath);
}
static void call_function(const char* function_name __unused,
@@ -441,9 +436,9 @@
return;
}
- TRACE("[ Calling d-tor %s @ %p for '%s' ]", function_name, function, realpath);
+ LD_DEBUG(calls, "[ Calling d-tor %s @ %p for '%s' ]", function_name, function, realpath);
function();
- TRACE("[ Done calling d-tor %s @ %p for '%s' ]", function_name, function, realpath);
+ LD_DEBUG(calls, "[ Done calling d-tor %s @ %p for '%s' ]", function_name, function, realpath);
}
template <typename F>
@@ -453,18 +448,18 @@
return;
}
- TRACE("[ Calling %s (size %zd) @ %p for '%s' ]", array_name, count, functions, realpath);
+ LD_DEBUG(calls, "[ Calling %s (size %zd) @ %p for '%s' ]", array_name, count, functions, realpath);
int begin = reverse ? (count - 1) : 0;
int end = reverse ? -1 : count;
int step = reverse ? -1 : 1;
for (int i = begin; i != end; i += step) {
- TRACE("[ %s[%d] == %p ]", array_name, i, functions[i]);
+ LD_DEBUG(calls, "[ %s[%d] == %p ]", array_name, i, functions[i]);
call_function("function", functions[i], realpath);
}
- TRACE("[ Done calling %s for '%s' ]", array_name, realpath);
+ LD_DEBUG(calls, "[ Done calling %s for '%s' ]", array_name, realpath);
}
void soinfo::call_pre_init_constructors() {
@@ -492,7 +487,7 @@
if (!is_main_executable() && preinit_array_ != nullptr) {
// The GNU dynamic linker silently ignores these, but we warn the developer.
- PRINT("\"%s\": ignoring DT_PREINIT_ARRAY in shared library!", get_realpath());
+ DL_WARN("\"%s\": ignoring DT_PREINIT_ARRAY in shared library!", get_realpath());
}
get_children().for_each([] (soinfo* si) {
diff --git a/linker/linker_test_globals.cpp b/linker/linker_test_globals.cpp
index 4b41eed..27ec6f7 100644
--- a/linker/linker_test_globals.cpp
+++ b/linker/linker_test_globals.cpp
@@ -26,9 +26,6 @@
* SUCH DAMAGE.
*/
-// To enable logging
-int g_ld_debug_verbosity = 0;
-
// Stub some symbols to avoid linking issues
void DL_WARN_documented_change(int api_level [[maybe_unused]],
const char* doc_link [[maybe_unused]],
diff --git a/linker/linker_utils.cpp b/linker/linker_utils.cpp
index 9abe542..f72716e 100644
--- a/linker/linker_utils.cpp
+++ b/linker/linker_utils.cpp
@@ -75,7 +75,7 @@
bool normalize_path(const char* path, std::string* normalized_path) {
// Input should be an absolute path
if (path[0] != '/') {
- PRINT("normalize_path - invalid input: \"%s\", the input path should be absolute", path);
+ DL_WARN("normalize_path - invalid input: \"%s\", the input path should be absolute", path);
return false;
}
@@ -144,7 +144,7 @@
}
const char* const path = normalized_path.c_str();
- TRACE("Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path);
+ LD_DEBUG(any, "Trying zip file open from path \"%s\" -> normalized \"%s\"", input_path, path);
// Treat an '!/' separator inside a path as the separator between the name
// of the zip file on disk and the subdirectory to search within it.
@@ -157,7 +157,7 @@
char buf[512];
if (strlcpy(buf, path, sizeof(buf)) >= sizeof(buf)) {
- PRINT("Warning: ignoring very long library path: %s", path);
+ DL_WARN("ignoring very long library path: %s", path);
return false;
}
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-rw_load_segment.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-rw_load_segment.so
index 6463c6b..46af37f 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-rw_load_segment.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-rw_load_segment.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shentsize.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shentsize.so
index 4ffc7e8..c186b1d 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shentsize.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shentsize.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shstrndx.so b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shstrndx.so
index 9098310..857f702 100755
--- a/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shstrndx.so
+++ b/tests/prebuilt-elf-files/arm64/libtest_invalid-zero_shstrndx.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-rw_load_segment.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-rw_load_segment.so
index 113e455..9d2c5f1 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-rw_load_segment.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-rw_load_segment.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shentsize.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shentsize.so
index 78fed79..8146676 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shentsize.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shentsize.so
Binary files differ
diff --git a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shstrndx.so b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shstrndx.so
index 0953633..4ac70f7 100755
--- a/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shstrndx.so
+++ b/tests/prebuilt-elf-files/x86_64/libtest_invalid-zero_shstrndx.so
Binary files differ