diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libc-stdio.c | 42 | ||||
-rw-r--r-- | src/libc-stdio.h | 102 | ||||
-rw-r--r-- | src/libc.c | 9 |
3 files changed, 50 insertions, 103 deletions
diff --git a/src/libc-stdio.c b/src/libc-stdio.c new file mode 100644 index 0000000..713497b --- /dev/null +++ b/src/libc-stdio.c @@ -0,0 +1,42 @@ +#include <stdio.h> + +struct bionic___sFILE { +#if defined(__LP64__) + char __private[152]; +#else + char __private[84]; +#endif +} __attribute__((aligned(sizeof(void*)))); + +// Bionic standard stream support pre-M Android +// Post-M it's saner and they point to stdin/stdout/stderr symbols instead +const struct bionic___sFILE bionic___sF[3] = { + {{ 's', 't', 'd', 'i', 'n' }}, + {{ 's', 't', 'd', 'o', 'u', 't' }}, + {{ 's', 't', 'd', 'e', 'r', 'r' }} +}; + +static inline FILE* +bionic_file_to_glibc_file(FILE *f) +{ + if (f == (void*)&bionic___sF[0]) + return stdin; + else if (f == (void*)&bionic___sF[1]) + return stdout; + else if (f == (void*)&bionic___sF[2]) + return stderr; + return f; +} + +// Wrapping internal glibc VTABLE functions to handle bionic's pre-M crap +// We define __real_IO_file_xsputn in libc.c so linker will link our library, +// it's not used however for anything. + +extern size_t +__real_IO_file_xsputn(FILE *f, const void *buf, size_t n); + +size_t +__wrap_IO_file_xsputn(FILE *f, const void *buf, size_t n) +{ + return __real_IO_file_xsputn(bionic_file_to_glibc_file(f), buf, n); +} diff --git a/src/libc-stdio.h b/src/libc-stdio.h deleted file mode 100644 index 9dacd21..0000000 --- a/src/libc-stdio.h +++ /dev/null @@ -1,102 +0,0 @@ -#pragma once - -#include <wchar.h> - -struct bionic___sFILE { -#if defined(__LP64__) - char __private[152]; -#else - char __private[84]; -#endif -} __attribute__((aligned(sizeof(void*)))); - -// Bionic standard stream support pre-M Android -// Post-M it's saner and they point to stdin/stdout/stderr symbols instead -const struct bionic___sFILE bionic___sF[3] = { - {{ 's', 't', 'd', 'i', 'n' }}, - {{ 's', 't', 'd', 'o', 'u', 't' }}, - {{ 's', 't', 'd', 'e', 'r', 'r' }} -}; - -static inline FILE* -bionic_file_to_glibc_file(FILE *f) -{ - if (f == (void*)&bionic___sF[0]) - return stdin; - else if (f == (void*)&bionic___sF[1]) - return stdout; - else if (f == (void*)&bionic___sF[2]) - return stderr; - return f; -} - -FILE* -bionic_freopen(const char *filename, const char *modes, FILE *stream) -{ - return freopen(filename, modes, bionic_file_to_glibc_file(stream)); -} - -int -bionic_fclose(FILE *stream) -{ - return fclose(bionic_file_to_glibc_file(stream)); -} - -int -bionic_fputc(int c, FILE *stream) -{ - return fputc(c, bionic_file_to_glibc_file(stream)); -} - -int -bionic_putc(int c, FILE *stream) -{ - return putc(c, bionic_file_to_glibc_file(stream)); -} - - -int -bionic_fputs(const char *c, FILE *stream) -{ - return fputs(c, bionic_file_to_glibc_file(stream)); -} - -wint_t -bionic_fputwc(wchar_t wc, FILE *stream) -{ - return fputwc(wc, bionic_file_to_glibc_file(stream)); -} - -wint_t -bionic_putwc(wchar_t wc, FILE *stream) -{ - return putwc(wc, bionic_file_to_glibc_file(stream)); -} - -size_t -bionic_fread(void *ptr, size_t size, size_t nmemb, FILE *stream) -{ - char buf[256], fname[256] = {0}; - stream = bionic_file_to_glibc_file(stream); - snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fileno(stream)); - readlink(buf, fname, sizeof(fname)); - verbose("%s (%d)\n%p, %zu, %zu, %p", fname, fileno(stream), ptr, size, nmemb, (void*)stream); - return fread(ptr, size, nmemb, stream); -} - -size_t -bionic_fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream) -{ - char buf[256], fname[256] = {0}; - stream = bionic_file_to_glibc_file(stream); - snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fileno(stream)); - readlink(buf, fname, sizeof(fname)); - verbose("%s (%d)\n%p, %zu, %zu, %p", fname, fileno(stream), ptr, size, nmemb, (void*)stream); - return fwrite(ptr, size, nmemb, stream); -} - -int -bionic_fflush(FILE *stream) -{ - return fflush(bionic_file_to_glibc_file(stream)); -} @@ -72,7 +72,14 @@ tkill(int tid, int sig) // Stuff needed for runtime compatibility, but not neccessary for linking // Also stuff that exists in glibc, but needs to be wrapped for runtime compatibility -#include "libc-stdio.h" +// Some defines from app-stdio.c as per GNU linker's manual for --wrap: +// You may wish to provide a __real_malloc function as well, so that links without the +// --wrap option will succeed. If you do this, you should not put the definition of +// __real_malloc in the same file as __wrap_malloc; if you do, the assembler may resolve +// the call before the linker has a chance to wrap it to malloc. + +size_t __real_IO_file_xsputn(FILE *f, const void *buf, size_t n) {} + #include "libc-ctype.h" const unsigned int bionic___page_size = PAGE_SIZE; |