diff --git a/libexec/rtld-elf/Makefile b/libexec/rtld-elf/Makefile index 95bec19..2e7925e 100644 --- a/libexec/rtld-elf/Makefile +++ b/libexec/rtld-elf/Makefile @@ -5,7 +5,7 @@ MK_SSP= no PROG?= ld-elf.so.1 SRCS= rtld_start.S \ - reloc.c rtld.c rtld_lock.c map_object.c \ + reloc.c rtld.c rtld_lock.c rtld_printf.c map_object.c \ malloc.c xmalloc.c debug.c libmap.c MAN= rtld.1 CSTD?= gnu99 diff --git a/libexec/rtld-elf/malloc.c b/libexec/rtld-elf/malloc.c index 38ae89a..da8389b 100644 --- a/libexec/rtld-elf/malloc.c +++ b/libexec/rtld-elf/malloc.c @@ -523,6 +523,8 @@ int n; return n; } +int rtld_vsnprintf(char *buf, size_t bufsize, const char *fmt, va_list ap); + /* * Non-mallocing printf, for use by malloc itself. */ @@ -533,7 +535,7 @@ xprintf(const char *fmt, ...) va_list ap; va_start(ap, fmt); - vsprintf(buf, fmt, ap); + rtld_vsnprintf(buf, sizeof(buf), fmt, ap); (void)write(STDOUT_FILENO, buf, strlen(buf)); va_end(ap); } diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index 722b274..da041e8 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -603,7 +603,7 @@ _rtld_error(const char *fmt, ...) va_list ap; va_start(ap, fmt); - vsnprintf(buf, sizeof buf, fmt, ap); + rtld_vsnprintf(buf, sizeof buf, fmt, ap); error_message = buf; va_end(ap); } @@ -723,7 +723,8 @@ die(void) if (msg == NULL) msg = "Fatal error"; - errx(1, "%s", msg); + rtld_putstr(msg); + _exit(1); } /* @@ -3186,8 +3187,11 @@ trace_loaded_objects(Obj_Entry *obj) char *name, *path; bool is_lib; - if (list_containers && obj->needed != NULL) - printf("%s:\n", obj->path); + if (list_containers && obj->needed != NULL) { + rtld_putstr(obj->path); + rtld_putchar(':'); + rtld_putchar('\n'); + } for (needed = obj->needed; needed; needed = needed->next) { if (needed->obj != NULL) { if (needed->obj->traced && !list_containers) @@ -3204,17 +3208,17 @@ trace_loaded_objects(Obj_Entry *obj) while ((c = *fmt++) != '\0') { switch (c) { default: - putchar(c); + rtld_putchar(c); continue; case '\\': switch (c = *fmt) { case '\0': continue; case 'n': - putchar('\n'); + rtld_putchar('\n'); break; case 't': - putchar('\t'); + rtld_putchar('\t'); break; } break; @@ -3224,30 +3228,30 @@ trace_loaded_objects(Obj_Entry *obj) continue; case '%': default: - putchar(c); + rtld_putchar(c); break; case 'A': - printf("%s", main_local); + rtld_putstr(main_local); break; case 'a': - printf("%s", obj_main->path); + rtld_putstr(obj_main->path); break; case 'o': - printf("%s", name); + rtld_putstr(name); break; #if 0 case 'm': - printf("%d", sodp->sod_major); + rtld_putint(sodp->sod_major); break; case 'n': - printf("%d", sodp->sod_minor); + rtld_putint(sodp->sod_minor); break; #endif case 'p': - printf("%s", path); + rtld_putstr(path); break; case 'x': - printf("%p", needed->obj ? needed->obj->mapbase : 0); + rtld_putptr(needed->obj ? needed->obj->mapbase : 0); break; } break; diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h index bb365a7..325c032 100644 --- a/libexec/rtld-elf/rtld.h +++ b/libexec/rtld-elf/rtld.h @@ -34,6 +34,7 @@ #include #include +#include #include #include @@ -325,6 +326,11 @@ void *allocate_module_tls(int index); bool allocate_tls_offset(Obj_Entry *obj); void free_tls_offset(Obj_Entry *obj); const Ver_Entry *fetch_ventry(const Obj_Entry *obj, unsigned long); +int rtld_vsnprintf(char *buf, size_t bufsize, const char *fmt, va_list ap); +void rtld_putstr(const char *str); +void rtld_putchar(char c); +void rtld_putint(int x); +void rtld_putptr(void *p); /* * MD function declarations. diff --git a/libexec/rtld-elf/rtld_lock.c b/libexec/rtld-elf/rtld_lock.c index 024e1e2..d1563e5 100644 --- a/libexec/rtld-elf/rtld_lock.c +++ b/libexec/rtld-elf/rtld_lock.c @@ -182,8 +182,6 @@ rtld_lock_t rtld_bind_lock = &rtld_locks[0]; rtld_lock_t rtld_libc_lock = &rtld_locks[1]; rtld_lock_t rtld_phdr_lock = &rtld_locks[2]; -#define print_ebp(str) do {register long ebp asm("ebp"); printf("%s 0x%0lx\n", str, ebp);} while (0) - void rlock_acquire(rtld_lock_t lock, RtldLockState *lockstate) { diff --git a/libexec/rtld-elf/rtld_printf.c b/libexec/rtld-elf/rtld_printf.c new file mode 100644 index 0000000..b92f0fa --- /dev/null +++ b/libexec/rtld-elf/rtld_printf.c @@ -0,0 +1,457 @@ +/*- + * Copyright (c) 1986, 1988, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * Copyright (c) 2011 Konstantin Belousov + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 + */ + +#include +#include +#include +#include +#include +#include +#include "rtld.h" + +#define MAXNBUF (sizeof(intmax_t) * NBBY + 1) + +struct snprintf_arg { + char *str; + size_t remain; +}; + +static void +snprintf_func(int ch, void *arg) +{ + struct snprintf_arg *const info = arg; + + if (info->remain >= 2) { + *info->str++ = ch; + info->remain--; + } +} + +static char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz"; +#define hex2ascii(hex) (hex2ascii_data[hex]) + +static __inline int +imax(int a, int b) +{ + + return (a > b ? a : b); +} + +static char * +ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) +{ + char *p, c; + + p = nbuf; + *p = '\0'; + do { + c = hex2ascii(num % base); + *++p = upper ? toupper(c) : c; + } while (num /= base); + if (lenp) + *lenp = p - nbuf; + return (p); +} + +static int +kvprintf(char const *fmt, struct snprintf_arg *arg, int radix, + va_list ap) +{ +#define PCHAR(c) snprintf_func((c), arg) + char nbuf[MAXNBUF]; + const char *p, *percent, *q; + u_char *up; + int ch, n; + uintmax_t num; + int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; + int cflag, hflag, jflag, tflag, zflag; + int dwidth, upper; + char padc; + int stop = 0, retval = 0; + + num = 0; + + if (fmt == NULL) + fmt = "(fmt null)\n"; + + if (radix < 2 || radix > 36) + radix = 10; + + for (;;) { + padc = ' '; + width = 0; + while ((ch = (u_char)*fmt++) != '%' || stop) { + if (ch == '\0') + return (retval); + PCHAR(ch); + } + percent = fmt - 1; + qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; + sign = 0; dot = 0; dwidth = 0; upper = 0; + cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; +reswitch: switch (ch = (u_char)*fmt++) { + case '.': + dot = 1; + goto reswitch; + case '#': + sharpflag = 1; + goto reswitch; + case '+': + sign = 1; + goto reswitch; + case '-': + ladjust = 1; + goto reswitch; + case '%': + PCHAR(ch); + break; + case '*': + if (!dot) { + width = va_arg(ap, int); + if (width < 0) { + ladjust = !ladjust; + width = -width; + } + } else { + dwidth = va_arg(ap, int); + } + goto reswitch; + case '0': + if (!dot) { + padc = '0'; + goto reswitch; + } + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + for (n = 0;; ++fmt) { + n = n * 10 + ch - '0'; + ch = *fmt; + if (ch < '0' || ch > '9') + break; + } + if (dot) + dwidth = n; + else + width = n; + goto reswitch; + case 'b': + num = (u_int)va_arg(ap, int); + p = va_arg(ap, char *); + for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) + PCHAR(*q--); + + if (num == 0) + break; + + for (tmp = 0; *p;) { + n = *p++; + if (num & (1 << (n - 1))) { + PCHAR(tmp ? ',' : '<'); + for (; (n = *p) > ' '; ++p) + PCHAR(n); + tmp = 1; + } else + for (; *p > ' '; ++p) + continue; + } + if (tmp) + PCHAR('>'); + break; + case 'c': + PCHAR(va_arg(ap, int)); + break; + case 'D': + up = va_arg(ap, u_char *); + p = va_arg(ap, char *); + if (!width) + width = 16; + while(width--) { + PCHAR(hex2ascii(*up >> 4)); + PCHAR(hex2ascii(*up & 0x0f)); + up++; + if (width) + for (q=p;*q;q++) + PCHAR(*q); + } + break; + case 'd': + case 'i': + base = 10; + sign = 1; + goto handle_sign; + case 'h': + if (hflag) { + hflag = 0; + cflag = 1; + } else + hflag = 1; + goto reswitch; + case 'j': + jflag = 1; + goto reswitch; + case 'l': + if (lflag) { + lflag = 0; + qflag = 1; + } else + lflag = 1; + goto reswitch; + case 'n': + if (jflag) + *(va_arg(ap, intmax_t *)) = retval; + else if (qflag) + *(va_arg(ap, quad_t *)) = retval; + else if (lflag) + *(va_arg(ap, long *)) = retval; + else if (zflag) + *(va_arg(ap, size_t *)) = retval; + else if (hflag) + *(va_arg(ap, short *)) = retval; + else if (cflag) + *(va_arg(ap, char *)) = retval; + else + *(va_arg(ap, int *)) = retval; + break; + case 'o': + base = 8; + goto handle_nosign; + case 'p': + base = 16; + sharpflag = (width == 0); + sign = 0; + num = (uintptr_t)va_arg(ap, void *); + goto number; + case 'q': + qflag = 1; + goto reswitch; + case 'r': + base = radix; + if (sign) + goto handle_sign; + goto handle_nosign; + case 's': + p = va_arg(ap, char *); + if (p == NULL) + p = "(null)"; + if (!dot) + n = strlen (p); + else + for (n = 0; n < dwidth && p[n]; n++) + continue; + + width -= n; + + if (!ladjust && width > 0) + while (width--) + PCHAR(padc); + while (n--) + PCHAR(*p++); + if (ladjust && width > 0) + while (width--) + PCHAR(padc); + break; + case 't': + tflag = 1; + goto reswitch; + case 'u': + base = 10; + goto handle_nosign; + case 'X': + upper = 1; + case 'x': + base = 16; + goto handle_nosign; + case 'y': + base = 16; + sign = 1; + goto handle_sign; + case 'z': + zflag = 1; + goto reswitch; +handle_nosign: + sign = 0; + if (jflag) + num = va_arg(ap, uintmax_t); + else if (qflag) + num = va_arg(ap, u_quad_t); + else if (tflag) + num = va_arg(ap, ptrdiff_t); + else if (lflag) + num = va_arg(ap, u_long); + else if (zflag) + num = va_arg(ap, size_t); + else if (hflag) + num = (u_short)va_arg(ap, int); + else if (cflag) + num = (u_char)va_arg(ap, int); + else + num = va_arg(ap, u_int); + goto number; +handle_sign: + if (jflag) + num = va_arg(ap, intmax_t); + else if (qflag) + num = va_arg(ap, quad_t); + else if (tflag) + num = va_arg(ap, ptrdiff_t); + else if (lflag) + num = va_arg(ap, long); + else if (zflag) + num = va_arg(ap, ssize_t); + else if (hflag) + num = (short)va_arg(ap, int); + else if (cflag) + num = (char)va_arg(ap, int); + else + num = va_arg(ap, int); +number: + if (sign && (intmax_t)num < 0) { + neg = 1; + num = -(intmax_t)num; + } + p = ksprintn(nbuf, num, base, &n, upper); + tmp = 0; + if (sharpflag && num != 0) { + if (base == 8) + tmp++; + else if (base == 16) + tmp += 2; + } + if (neg) + tmp++; + + if (!ladjust && padc == '0') + dwidth = width - tmp; + width -= tmp + imax(dwidth, n); + dwidth -= n; + if (!ladjust) + while (width-- > 0) + PCHAR(' '); + if (neg) + PCHAR('-'); + if (sharpflag && num != 0) { + if (base == 8) { + PCHAR('0'); + } else if (base == 16) { + PCHAR('0'); + PCHAR('x'); + } + } + while (dwidth-- > 0) + PCHAR('0'); + + while (*p) + PCHAR(*p--); + + if (ladjust) + while (width-- > 0) + PCHAR(' '); + + break; + default: + while (percent < fmt) + PCHAR(*percent++); + /* + * Since we ignore an formatting argument it is no + * longer safe to obey the remaining formatting + * arguments as the arguments will no longer match + * the format specs. + */ + stop = 1; + break; + } + } +#undef PCHAR +} + +int +rtld_vsnprintf(char *buf, size_t bufsize, const char *fmt, va_list ap) +{ + struct snprintf_arg info; + int retval; + + info.str = buf; + info.remain = bufsize; + retval = kvprintf(fmt, &info, 10, ap); + if (info.remain >= 1) + *info.str++ = '\0'; + return (retval); +} + +static int +rtld_snprintf(char *buf, size_t bufsize, const char *fmt, ...) +{ + va_list ap; + int ret; + + va_start(ap, fmt); + ret = rtld_vsnprintf(buf, bufsize, fmt, ap); + va_end(ap); + return (ret); +} + +void +rtld_putstr(const char *str) +{ + + write(1, str, strlen(str)); +} + +void +rtld_putchar(char c) +{ + + write(1, &c, 1); +} + +void +rtld_putint(int x) +{ + char buf[MAXNBUF]; + + rtld_snprintf(buf, sizeof(buf), "%d", x); + rtld_putstr(buf); +} + +void +rtld_putptr(void *p) +{ + char buf[MAXNBUF]; + + rtld_snprintf(buf, sizeof(buf), "%p", p); + rtld_putstr(buf); +}