[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Minios-devel] [UNIKRAFT PATCH] lib/ukdebug: Do not rely on libc for uk_pr_*()



Hi Simon, 

This patch looks fine. Thanks. 

Reviewed-by: Gaulthier Gain <gaulthier.gain@xxxxxxxxx>

On 24 Jan 2020, at 12:19, Simon Kuenzer <simon.kuenzer@xxxxxxxxx> wrote:

This commit places a copy nolibc's (v)snprintf function to
ukdebug. ukdebug is going to use it as soon as nolibc is not
selected. We do this in order to bypass a libc printing system and to
make sure that the kernel and debug printing functions
uk_pr_(crit|err|warn|info|debug) can work already early during boot
without requiring any initialization. The standard functions provided
by libc's may potentially require additional initialization steps (e.g.,
TLS, malloc, constructors) and may not work properly when used too
early during boot.

Signed-off-by: Simon Kuenzer <simon.kuenzer@xxxxxxxxx>
---
lib/ukdebug/Makefile.uk |   1 +
lib/ukdebug/hexdump.c   |   4 +-
lib/ukdebug/print.c     |  14 +-
lib/ukdebug/snprintf.c  | 401 ++++++++++++++++++++++++++++++++++++++++
lib/ukdebug/snprintf.h  |  61 ++++++
5 files changed, 473 insertions(+), 8 deletions(-)
create mode 100644 lib/ukdebug/snprintf.c
create mode 100644 lib/ukdebug/snprintf.h

diff --git a/lib/ukdebug/Makefile.uk b/lib/ukdebug/Makefile.uk
index d82cacad..8f46061d 100644
--- a/lib/ukdebug/Makefile.uk
+++ b/lib/ukdebug/Makefile.uk
@@ -7,6 +7,7 @@ LIBUKDEBUG_CFLAGS-y   += -D__IN_LIBUKDEBUG__
LIBUKDEBUG_CXXFLAGS-y += -D__IN_LIBUKDEBUG__

LIBUKDEBUG_SRCS-y += $(LIBUKDEBUG_BASE)/print.c
+LIBUKDEBUG_SRCS-$(CONFIG_HAVE_LIBC) += $(LIBUKDEBUG_BASE)/snprintf.c
LIBUKDEBUG_SRCS-y += $(LIBUKDEBUG_BASE)/hexdump.c
LIBUKDEBUG_SRCS-$(CONFIG_LIBUKDEBUG_TRACEPOINTS) += $(LIBUKDEBUG_BASE)/trace.c
LIBUKDEBUG_SRCS-$(CONFIG_LIBVFSCORE) += $(LIBUKDEBUG_BASE)/extra.ld
diff --git a/lib/ukdebug/hexdump.c b/lib/ukdebug/hexdump.c
index eb533bdb..fc57c673 100644
--- a/lib/ukdebug/hexdump.c
+++ b/lib/ukdebug/hexdump.c
@@ -38,6 +38,7 @@
#include <string.h>
#include <inttypes.h>
#include <stdarg.h>
+#include "snprintf.h"

#include <uk/arch/types.h>
#include <uk/essentials.h>
@@ -93,10 +94,11 @@ static int _hxd_outf(struct _hxd_output *o, const char *fmt, ...)
va_start(ap, fmt);
switch (o->type) {
case UK_HXDOUT_FILE:
+ /* Use standard libc approach when printing to a file */
ret = vfprintf(o->file.fp, fmt, ap);
break;
case UK_HXDOUT_BUFFER:
- ret = vsnprintf(o->buffer.pos, o->buffer.left, fmt, ap);
+ ret = __uk_vsnprintf(o->buffer.pos, o->buffer.left, fmt, ap);

if (ret > 0) {
/* in order to overwrite '\0' by successive calls,
diff --git a/lib/ukdebug/print.c b/lib/ukdebug/print.c
index f43ab86e..e34199c8 100644
--- a/lib/ukdebug/print.c
+++ b/lib/ukdebug/print.c
@@ -35,7 +35,7 @@
 * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
 */

-#include <stdio.h>
+#include "snprintf.h"
#include <stdint.h>
#include <limits.h>
#include <string.h>
@@ -83,8 +83,8 @@ static void _print_timestamp(struct _vprint_console *cons)
__nsec rem_usec = ukarch_time_subsec(nansec);

rem_usec = ukarch_time_nsec_to_usec(rem_usec);
- len = snprintf(buf, BUFLEN, "[%5" __PRInsec ".%06" __PRInsec "] ",
- sec, rem_usec);
+ len = __uk_snprintf(buf, BUFLEN, "[%5" __PRInsec ".%06" __PRInsec "] ",
+    sec, rem_usec);
cons->cout((char *)buf, len);
}
#endif
@@ -98,7 +98,7 @@ static void _print_stack(struct _vprint_console *cons)

stackb = (ukarch_read_sp() & STACK_MASK_TOP) + __STACK_SIZE;

- len = snprintf(buf, BUFLEN, "<%p> ", (void *) stackb);
+ len = __uk_snprintf(buf, BUFLEN, "<%p> ", (void *) stackb);
cons->cout((char *)buf, len);
}
#endif
@@ -146,7 +146,7 @@ static void _vprint(struct _vprint_console *cons,
cons->newline = 1; /* enforce printing the message header */
}

- len = vsnprintf(lbuf, BUFLEN, fmt, ap);
+ len = __uk_vsnprintf(lbuf, BUFLEN, fmt, ap);
lptr = lbuf;
while (len > 0) {
if (cons->newline) {
@@ -170,8 +170,8 @@ static void _vprint(struct _vprint_console *cons,
  strlen(srcname));
cons->cout(" @ ", 3);
cons->cout(lnobuf,
-   snprintf(lnobuf, sizeof(lnobuf),
-    "%-5u", srcline));
+   __uk_snprintf(lnobuf, sizeof(lnobuf),
+ "%-5u", srcline));
cons->cout(": ", 2);
}
cons->newline = 0;
diff --git a/lib/ukdebug/snprintf.c b/lib/ukdebug/snprintf.c
new file mode 100644
index 00000000..bfdd7057
--- /dev/null
+++ b/lib/ukdebug/snprintf.c
@@ -0,0 +1,401 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ ****************************************************************************
+ *
+ *        File: printf.c
+ *      Author: Juergen Gross <jgross@xxxxxxxx>
+ *              Simon Kuenzer <simon.kuenzer@xxxxxxxxx>
+ *
+ *        Date: Jun 2016, Jan 2020
+ *
+ * Environment: Unikraft
+ * Description: Internal low-weight snprintf function for ukdebug
+ *              (FreeBSD port)
+ *
+ ****************************************************************************
+ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * 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.
+ * 3. 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.
+ */
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <limits.h>
+#include <ctype.h>
+#include <string.h>
+#include "snprintf.h"
+
+/* 64 bits + 0-Byte at end */
+#define MAXNBUF 65
+
+static char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+/*
+ * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse
+ * order; return an optional length and a pointer to the last character
+ * written in the buffer (i.e., the first character of the string).
+ * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
+ */
+static inline char *ksprintn(char *nbuf, uintmax_t num, int base, int *lenp,
+     int upper)
+{
+ char *p, c;
+
+ p = nbuf;
+ *p = '\0';
+ do {
+ c = hex2ascii_data[num % base];
+ *++p = upper ? toupper(c) : c;
+ } while (num /= base);
+ if (lenp)
+ *lenp = p - nbuf;
+ return p;
+}
+
+/*
+ * Scaled down version of printf(3).
+ */
+int __uk_vsnprintf(char *str, size_t size, const char *fmt, va_list ap)
+{
+#define PCHAR(c)                                                               \
+ {                                                                      \
+ int cc = (c);                                                  \
+ if (size >= 2) {                                               \
+ *str++ = cc;                                           \
+ size--;                                                \
+ }                                                              \
+ retval++;                                                      \
+ }
+ char nbuf[MAXNBUF];
+ const char *p, *percent;
+ int ch, n;
+ uintmax_t num;
+ int base, lflag, llflag, 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";
+
+ for (;;) {
+ padc = ' ';
+ width = 0;
+ while ((ch = (unsigned char)*fmt++) != '%' || stop) {
+ if (ch == '\0') {
+ if (size >= 1)
+ *str++ = '\0';
+ return retval;
+ }
+ PCHAR(ch);
+ }
+ percent = fmt - 1;
+ llflag = 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 = (unsigned 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;
+ }
+ /* fallthrough */
+ 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 'c':
+ PCHAR(va_arg(ap, int));
+ 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;
+ llflag = 1;
+ } else
+ lflag = 1;
+ goto reswitch;
+ case 'n':
+ if (jflag)
+ *(va_arg(ap, intmax_t *)) = retval;
+ else if (llflag)
+ *(va_arg(ap, long long *)) = 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':
+ llflag = 1;
+ goto reswitch;
+ case 'r':
+ base = 10;
+ 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;
+ /* Fall through */
+ 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 (llflag)
+ num = va_arg(ap, unsigned long long);
+ else if (tflag)
+ num = va_arg(ap, ptrdiff_t);
+ else if (lflag)
+ num = va_arg(ap, unsigned long);
+ else if (zflag)
+ num = va_arg(ap, size_t);
+ else if (hflag)
+ num = (unsigned short)va_arg(ap, int);
+ else if (cflag)
+ num = (unsigned char)va_arg(ap, int);
+ else
+ num = va_arg(ap, unsigned int);
+ goto number;
+handle_sign:
+ if (jflag)
+ num = va_arg(ap, intmax_t);
+ else if (llflag)
+ num = va_arg(ap, long long);
+ 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 + (dwidth > n ? 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 a 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 __uk_snprintf(char *str, size_t size, const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = __uk_vsnprintf(str, size, fmt, ap);
+ va_end(ap);
+
+ return ret;
+}
diff --git a/lib/ukdebug/snprintf.h b/lib/ukdebug/snprintf.h
new file mode 100644
index 00000000..fa167e68
--- /dev/null
+++ b/lib/ukdebug/snprintf.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Authors: Simon Kuenzer <simon.kuenzer@xxxxxxxxx>
+ *
+ *
+ * Copyright (c) 2020, NEC Europe Ltd., NEC Corporation. All rights reserved.
+ *
+ * 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.
+ * 3. Neither the name of the copyright holder 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
+ *
+ * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY.
+ */
+
+#ifndef __UKDEBUG_INTERNAL_SNPRINTF_H__
+#define __UKDEBUG_INTERNAL_SNPRINTF_H__
+
+#include <uk/config.h>
+
+/*
+ * Point __uk_(v)snprintf to library-internal implementation as soon as
+ * we do not use lib/nolibc as libc.
+ */
+#if CONFIG_LIBNOLIBC
+#include <stdio.h>
+
+#define __uk_vsnprintf(...) vsnprintf(__VA_ARGS__)
+#define  __uk_snprintf(...)  snprintf(__VA_ARGS__)
+
+#else /* CONFIG_LIBNOLIBC */
+#include <stddef.h>
+#include <stdarg.h>
+#include <uk/essentials.h>
+
+int __uk_vsnprintf(char *str, size_t size, const char *fmt, va_list ap);
+int  __uk_snprintf(char *str, size_t size, const char *fmt, ...) __printf(3, 4);
+
+#endif /* CONFIG_LIBNOLIBC */
+
+#endif /* __UKDEBUG_INTERNAL_SNPRINTF_H__ */
--
2.20.1


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.