From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pj1-x1036.google.com (mail-pj1-x1036.google.com [IPv6:2607:f8b0:4864:20::1036]) by sourceware.org (Postfix) with ESMTPS id CB5093836419 for ; Fri, 14 Jan 2022 18:40:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org CB5093836419 Received: by mail-pj1-x1036.google.com with SMTP id 59-20020a17090a09c100b001b34a13745eso22981820pjo.5 for ; Fri, 14 Jan 2022 10:40:42 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=h05XnV+k09ti9Hjco6FV4ILFzLNH1jRdjPQvwF/7njM=; b=LLwXWcileksZB+6GgvYaGH9r4BSAjW02YvurUVfgmQPz6m6VSkdvQQtRtbcIQtDswd IHPouLI4tWS/0YGFgDrR7wlGX1NLpI5oudAC7wghVYTcFS6OsJmIZGMTigzo8ZcqYqiN OZldQwOcznsfQrgzIdBLuraNgCPnKGkYmVSL7ul3ZlNrgVyFQzIpNTgkYDLpVxB3RT/s AZJu5cDDIy07ubr+b38fY0V+LzcF3sQtFJdcQlETR8FFAqxk+S7p/dXT9kMddOEMUYnG ROHAueHg9xrH59baePG6XLzZaFeLwatm30pnzWfC7Ec6P9v0aDau2cqn7MtAT1kFbXyF vj+w== X-Gm-Message-State: AOAM533gdmYYelCSgevMk5FXb9DRuYVEBgKXr7OPab6/3E8DNIGphG3r oxHyETz0NNzZMKFsxux4hQm1TVQ/xiLQR8aBwVKsQDBXj8Y= X-Google-Smtp-Source: ABdhPJzxBjFAP0DGg7Mv3MjqqpYQvoCcVcLL+u7Cum1bOF+UJvp97vWJ7SOVHs1wV4bu61E8zR6ioe9VYXbl74nl1QY= X-Received: by 2002:a17:902:e544:b0:14a:555c:add3 with SMTP id n4-20020a170902e54400b0014a555cadd3mr10450888plf.102.1642185641626; Fri, 14 Jan 2022 10:40:41 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: From: "H.J. Lu" Date: Fri, 14 Jan 2022 10:40:05 -0800 Message-ID: Subject: Re: [PATCH v2 2/6] elf: Split dl-printf.c from dl-misc.c To: Florian Weimer Cc: GNU C Library Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-3027.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Jan 2022 18:40:45 -0000 On Fri, Jan 14, 2022 at 8:53 AM Florian Weimer via Libc-alpha wrote: > > This allows to use different compiler flags for the diagnostics > code. > --- > v2: Adjust to Makefile changes in patch 1. > elf/Makefile | 1 + > elf/dl-misc.c | 281 +--------------------------------------------- > elf/dl-printf.c | 292 ++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 297 insertions(+), 277 deletions(-) > create mode 100644 elf/dl-printf.c > > diff --git a/elf/Makefile b/elf/Makefile > index 3065efc485..3df49742ff 100644 > --- a/elf/Makefile > +++ b/elf/Makefile > @@ -69,6 +69,7 @@ dl-routines = \ > dl-object \ > dl-open \ > dl-origin \ > + dl-printf \ > dl-profile \ > dl-reloc \ > dl-runtime \ > diff --git a/elf/dl-misc.c b/elf/dl-misc.c > index 452b79de4a..6f40c28820 100644 > --- a/elf/dl-misc.c > +++ b/elf/dl-misc.c > @@ -16,24 +16,16 @@ > License along with the GNU C Library; if not, see > . */ > > -#include > +#include <_itoa.h> > #include > #include > -#include > #include > -#include > -#include > -#include > -#include > +#include > #include > +#include > #include > -#include > #include > -#include > -#include > -#include <_itoa.h> > -#include > -#include > +#include > > /* Read the whole contents of FILE into new mmap'd space with given > protections. *SIZEP gets the size of the file. On error MAP_FAILED > @@ -70,270 +62,6 @@ _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot) > return result; > } > > - > -/* Bare-bones printf implementation. This function only knows about > - the formats and flags needed and can handle only up to 64 stripes in > - the output. */ > -static void > -_dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg) > -{ > -# define NIOVMAX 64 > - struct iovec iov[NIOVMAX]; > - int niov = 0; > - pid_t pid = 0; > - char pidbuf[12]; > - > - while (*fmt != '\0') > - { > - const char *startp = fmt; > - > - if (tag_p > 0) > - { > - /* Generate the tag line once. It consists of the PID and a > - colon followed by a tab. */ > - if (pid == 0) > - { > - char *p; > - pid = __getpid (); > - assert (pid >= 0 && sizeof (pid_t) <= 4); > - p = _itoa (pid, &pidbuf[10], 10, 0); > - while (p > pidbuf) > - *--p = ' '; > - pidbuf[10] = ':'; > - pidbuf[11] = '\t'; > - } > - > - /* Append to the output. */ > - assert (niov < NIOVMAX); > - iov[niov].iov_len = 12; > - iov[niov++].iov_base = pidbuf; > - > - /* No more tags until we see the next newline. */ > - tag_p = -1; > - } > - > - /* Skip everything except % and \n (if tags are needed). */ > - while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n')) > - ++fmt; > - > - /* Append constant string. */ > - assert (niov < NIOVMAX); > - if ((iov[niov].iov_len = fmt - startp) != 0) > - iov[niov++].iov_base = (char *) startp; > - > - if (*fmt == '%') > - { > - /* It is a format specifier. */ > - char fill = ' '; > - int width = -1; > - int prec = -1; > -#if LONG_MAX != INT_MAX > - int long_mod = 0; > -#endif > - > - /* Recognize zero-digit fill flag. */ > - if (*++fmt == '0') > - { > - fill = '0'; > - ++fmt; > - } > - > - /* See whether with comes from a parameter. Note that no other > - way to specify the width is implemented. */ > - if (*fmt == '*') > - { > - width = va_arg (arg, int); > - ++fmt; > - } > - > - /* Handle precision. */ > - if (*fmt == '.' && fmt[1] == '*') > - { > - prec = va_arg (arg, int); > - fmt += 2; > - } > - > - /* Recognize the l modifier. It is only important on some > - platforms where long and int have a different size. We > - can use the same code for size_t. */ > - if (*fmt == 'l' || *fmt == 'Z') > - { > -#if LONG_MAX != INT_MAX > - long_mod = 1; > -#endif > - ++fmt; > - } > - > - switch (*fmt) > - { > - /* Integer formatting. */ > - case 'd': > - case 'u': > - case 'x': > - { > - /* We have to make a difference if long and int have a > - different size. */ > -#if LONG_MAX != INT_MAX > - unsigned long int num = (long_mod > - ? va_arg (arg, unsigned long int) > - : va_arg (arg, unsigned int)); > -#else > - unsigned long int num = va_arg (arg, unsigned int); > -#endif > - bool negative = false; > - if (*fmt == 'd') > - { > -#if LONG_MAX != INT_MAX > - if (long_mod) > - { > - if ((long int) num < 0) > - negative = true; > - } > - else > - { > - if ((int) num < 0) > - { > - num = (unsigned int) num; > - negative = true; > - } > - } > -#else > - if ((int) num < 0) > - negative = true; > -#endif > - } > - > - /* We use alloca() to allocate the buffer with the most > - pessimistic guess for the size. Using alloca() allows > - having more than one integer formatting in a call. */ > - char *buf = (char *) alloca (1 + 3 * sizeof (unsigned long int)); > - char *endp = &buf[1 + 3 * sizeof (unsigned long int)]; > - char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0); > - > - /* Pad to the width the user specified. */ > - if (width != -1) > - while (endp - cp < width) > - *--cp = fill; > - > - if (negative) > - *--cp = '-'; > - > - iov[niov].iov_base = cp; > - iov[niov].iov_len = endp - cp; > - ++niov; > - } > - break; > - > - case 's': > - /* Get the string argument. */ > - iov[niov].iov_base = va_arg (arg, char *); > - iov[niov].iov_len = strlen (iov[niov].iov_base); > - if (prec != -1) > - iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len); > - ++niov; > - break; > - > - case '%': > - iov[niov].iov_base = (void *) fmt; > - iov[niov].iov_len = 1; > - ++niov; > - break; > - > - default: > - assert (! "invalid format specifier"); > - } > - ++fmt; > - } > - else if (*fmt == '\n') > - { > - /* See whether we have to print a single newline character. */ > - if (fmt == startp) > - { > - iov[niov].iov_base = (char *) startp; > - iov[niov++].iov_len = 1; > - } > - else > - /* No, just add it to the rest of the string. */ > - ++iov[niov - 1].iov_len; > - > - /* Next line, print a tag again. */ > - tag_p = 1; > - ++fmt; > - } > - } > - > - /* Finally write the result. */ > - _dl_writev (fd, iov, niov); > -} > - > - > -/* Write to debug file. */ > -void > -_dl_debug_printf (const char *fmt, ...) > -{ > - va_list arg; > - > - va_start (arg, fmt); > - _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg); > - va_end (arg); > -} > - > - > -/* Write to debug file but don't start with a tag. */ > -void > -_dl_debug_printf_c (const char *fmt, ...) > -{ > - va_list arg; > - > - va_start (arg, fmt); > - _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg); > - va_end (arg); > -} > - > - > -/* Write the given file descriptor. */ > -void > -_dl_dprintf (int fd, const char *fmt, ...) > -{ > - va_list arg; > - > - va_start (arg, fmt); > - _dl_debug_vdprintf (fd, 0, fmt, arg); > - va_end (arg); > -} > - > -void > -_dl_printf (const char *fmt, ...) > -{ > - va_list arg; > - > - va_start (arg, fmt); > - _dl_debug_vdprintf (STDOUT_FILENO, 0, fmt, arg); > - va_end (arg); > -} > - > -void > -_dl_error_printf (const char *fmt, ...) > -{ > - va_list arg; > - > - va_start (arg, fmt); > - _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg); > - va_end (arg); > -} > - > -void > -_dl_fatal_printf (const char *fmt, ...) > -{ > - va_list arg; > - > - va_start (arg, fmt); > - _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg); > - va_end (arg); > - _exit (127); > -} > -rtld_hidden_def (_dl_fatal_printf) > - > /* Test whether given NAME matches any of the names of the given object. */ > int > _dl_name_match_p (const char *name, const struct link_map *map) > @@ -354,7 +82,6 @@ _dl_name_match_p (const char *name, const struct link_map *map) > return 0; > } > > - > unsigned long int > _dl_higher_prime_number (unsigned long int n) > { > diff --git a/elf/dl-printf.c b/elf/dl-printf.c > new file mode 100644 > index 0000000000..d3264ba96c > --- /dev/null > +++ b/elf/dl-printf.c > @@ -0,0 +1,292 @@ > +/* printf implementation for the dynamic loader. > + Copyright (C) 1997-2022 Free Software Foundation, Inc. > + This file is part of the GNU C Library. > + > + The GNU C Library is free software; you can redistribute it and/or > + modify it under the terms of the GNU Lesser General Public > + License as published by the Free Software Foundation; either > + version 2.1 of the License, or (at your option) any later version. > + > + The GNU C Library is distributed in the hope that it will be useful, > + but WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + Lesser General Public License for more details. > + > + You should have received a copy of the GNU Lesser General Public > + License along with the GNU C Library; if not, see > + . */ > + > +#include <_itoa.h> > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/* Bare-bones printf implementation. This function only knows about > + the formats and flags needed and can handle only up to 64 stripes in > + the output. */ > +static void > +_dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg) > +{ > +# define NIOVMAX 64 > + struct iovec iov[NIOVMAX]; > + int niov = 0; > + pid_t pid = 0; > + char pidbuf[12]; > + > + while (*fmt != '\0') > + { > + const char *startp = fmt; > + > + if (tag_p > 0) > + { > + /* Generate the tag line once. It consists of the PID and a > + colon followed by a tab. */ > + if (pid == 0) > + { > + char *p; > + pid = __getpid (); > + assert (pid >= 0 && sizeof (pid_t) <= 4); > + p = _itoa (pid, &pidbuf[10], 10, 0); > + while (p > pidbuf) > + *--p = ' '; > + pidbuf[10] = ':'; > + pidbuf[11] = '\t'; > + } > + > + /* Append to the output. */ > + assert (niov < NIOVMAX); > + iov[niov].iov_len = 12; > + iov[niov++].iov_base = pidbuf; > + > + /* No more tags until we see the next newline. */ > + tag_p = -1; > + } > + > + /* Skip everything except % and \n (if tags are needed). */ > + while (*fmt != '\0' && *fmt != '%' && (! tag_p || *fmt != '\n')) > + ++fmt; > + > + /* Append constant string. */ > + assert (niov < NIOVMAX); > + if ((iov[niov].iov_len = fmt - startp) != 0) > + iov[niov++].iov_base = (char *) startp; > + > + if (*fmt == '%') > + { > + /* It is a format specifier. */ > + char fill = ' '; > + int width = -1; > + int prec = -1; > +#if LONG_MAX != INT_MAX > + int long_mod = 0; > +#endif > + > + /* Recognize zero-digit fill flag. */ > + if (*++fmt == '0') > + { > + fill = '0'; > + ++fmt; > + } > + > + /* See whether with comes from a parameter. Note that no other > + way to specify the width is implemented. */ > + if (*fmt == '*') > + { > + width = va_arg (arg, int); > + ++fmt; > + } > + > + /* Handle precision. */ > + if (*fmt == '.' && fmt[1] == '*') > + { > + prec = va_arg (arg, int); > + fmt += 2; > + } > + > + /* Recognize the l modifier. It is only important on some > + platforms where long and int have a different size. We > + can use the same code for size_t. */ > + if (*fmt == 'l' || *fmt == 'Z') > + { > +#if LONG_MAX != INT_MAX > + long_mod = 1; > +#endif > + ++fmt; > + } > + > + switch (*fmt) > + { > + /* Integer formatting. */ > + case 'd': > + case 'u': > + case 'x': > + { > + /* We have to make a difference if long and int have a > + different size. */ > +#if LONG_MAX != INT_MAX > + unsigned long int num = (long_mod > + ? va_arg (arg, unsigned long int) > + : va_arg (arg, unsigned int)); > +#else > + unsigned long int num = va_arg (arg, unsigned int); > +#endif > + bool negative = false; > + if (*fmt == 'd') > + { > +#if LONG_MAX != INT_MAX > + if (long_mod) > + { > + if ((long int) num < 0) > + negative = true; > + } > + else > + { > + if ((int) num < 0) > + { > + num = (unsigned int) num; > + negative = true; > + } > + } > +#else > + if ((int) num < 0) > + negative = true; > +#endif > + } > + > + /* We use alloca() to allocate the buffer with the most > + pessimistic guess for the size. Using alloca() allows > + having more than one integer formatting in a call. */ > + char *buf = (char *) alloca (1 + 3 * sizeof (unsigned long int)); > + char *endp = &buf[1 + 3 * sizeof (unsigned long int)]; > + char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0); > + > + /* Pad to the width the user specified. */ > + if (width != -1) > + while (endp - cp < width) > + *--cp = fill; > + > + if (negative) > + *--cp = '-'; > + > + iov[niov].iov_base = cp; > + iov[niov].iov_len = endp - cp; > + ++niov; > + } > + break; > + > + case 's': > + /* Get the string argument. */ > + iov[niov].iov_base = va_arg (arg, char *); > + iov[niov].iov_len = strlen (iov[niov].iov_base); > + if (prec != -1) > + iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len); > + ++niov; > + break; > + > + case '%': > + iov[niov].iov_base = (void *) fmt; > + iov[niov].iov_len = 1; > + ++niov; > + break; > + > + default: > + assert (! "invalid format specifier"); > + } > + ++fmt; > + } > + else if (*fmt == '\n') > + { > + /* See whether we have to print a single newline character. */ > + if (fmt == startp) > + { > + iov[niov].iov_base = (char *) startp; > + iov[niov++].iov_len = 1; > + } > + else > + /* No, just add it to the rest of the string. */ > + ++iov[niov - 1].iov_len; > + > + /* Next line, print a tag again. */ > + tag_p = 1; > + ++fmt; > + } > + } > + > + /* Finally write the result. */ > + _dl_writev (fd, iov, niov); > +} > + > + > +/* Write to debug file. */ > +void > +_dl_debug_printf (const char *fmt, ...) > +{ > + va_list arg; > + > + va_start (arg, fmt); > + _dl_debug_vdprintf (GLRO(dl_debug_fd), 1, fmt, arg); > + va_end (arg); > +} > + > + > +/* Write to debug file but don't start with a tag. */ > +void > +_dl_debug_printf_c (const char *fmt, ...) > +{ > + va_list arg; > + > + va_start (arg, fmt); > + _dl_debug_vdprintf (GLRO(dl_debug_fd), -1, fmt, arg); > + va_end (arg); > +} > + > + > +/* Write the given file descriptor. */ > +void > +_dl_dprintf (int fd, const char *fmt, ...) > +{ > + va_list arg; > + > + va_start (arg, fmt); > + _dl_debug_vdprintf (fd, 0, fmt, arg); > + va_end (arg); > +} > + > +void > +_dl_printf (const char *fmt, ...) > +{ > + va_list arg; > + > + va_start (arg, fmt); > + _dl_debug_vdprintf (STDOUT_FILENO, 0, fmt, arg); > + va_end (arg); > +} > + > +void > +_dl_error_printf (const char *fmt, ...) > +{ > + va_list arg; > + > + va_start (arg, fmt); > + _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg); > + va_end (arg); > +} > + > +void > +_dl_fatal_printf (const char *fmt, ...) > +{ > + va_list arg; > + > + va_start (arg, fmt); > + _dl_debug_vdprintf (STDERR_FILENO, 0, fmt, arg); > + va_end (arg); > + _exit (127); > +} > +rtld_hidden_def (_dl_fatal_printf) > -- > 2.34.1 > > LGTM. Reviewed-by: H.J. Lu Thanks. -- H.J.