[前][次][番号順一覧][スレッド一覧]

ruby-changes:27835

From: naruse <ko1@a...>
Date: Sun, 24 Mar 2013 01:06:02 +0900 (JST)
Subject: [ruby-changes:27835] naruse:r39887 (trunk): * addr2line.c (kprintf): added from FreeBSD libstand's printf.

naruse	2013-03-24 01:05:51 +0900 (Sun, 24 Mar 2013)

  New Revision: 39887

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=39887

  Log:
    * addr2line.c (kprintf): added from FreeBSD libstand's printf.
      this is consided as async signal safe function.
    
    * addr2line.c (rb_dump_backtrace_with_lines): use kfprintf.
      [Bug #8144] [ruby-core:53632]

  Modified files:
    trunk/ChangeLog
    trunk/addr2line.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 39886)
+++ ChangeLog	(revision 39887)
@@ -1,3 +1,11 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sat Mar 23 23:50:04 2013  NARUSE, Yui  <naruse@r...>
+
+	* addr2line.c (kprintf): added from FreeBSD libstand's printf.
+	  this is consided as async signal safe function.
+
+	* addr2line.c (rb_dump_backtrace_with_lines): use kfprintf.
+	  [Bug #8144] [ruby-core:53632]
+
 Sat Mar 23 23:28:00 2013  Kenta Murata  <mrkn@m...>
 
 	* ext/bigdecimal/bigdecimal.c (BigDecimal_divide): Use Qnil and NIL_P
Index: addr2line.c
===================================================================
--- addr2line.c	(revision 39886)
+++ addr2line.c	(revision 39887)
@@ -90,6 +90,8 @@ void *alloca(); https://github.com/ruby/ruby/blob/trunk/addr2line.c#L90
 #define PATH_MAX 4096
 #endif
 
+int kprintf(const char *fmt, ...);
+
 typedef struct {
     const char *dirname;
     const char *filename;
@@ -153,7 +155,7 @@ get_nth_dirname(unsigned long dir, char https://github.com/ruby/ruby/blob/trunk/addr2line.c#L155
 	while (*p) p++;
 	p++;
 	if (!*p) {
-	    fprintf(stderr, "Unexpected directory number %lu in %s\n",
+	    kprintf("Unexpected directory number %lu in %s\n",
 		    dir, binary_filename);
 	    return "";
 	}
@@ -173,7 +175,7 @@ fill_filename(int file, char *include_di https://github.com/ruby/ruby/blob/trunk/addr2line.c#L175
 	filename = p;
 	if (!*p) {
 	    /* Need to output binary file name? */
-	    fprintf(stderr, "Unexpected file number %d in %s\n",
+	    kprintf("Unexpected file number %d in %s\n",
 		    file, binary_filename);
 	    return;
 	}
@@ -375,7 +377,7 @@ parse_debug_line_cu(int num_traces, void https://github.com/ruby/ruby/blob/trunk/addr2line.c#L377
 		p += sizeof(unsigned long);
 		break;
 	    case DW_LNE_define_file:
-		fprintf(stderr, "Unsupported operation in %s\n",
+		kprintf("Unsupported operation in %s\n",
 			binary_filename);
 		break;
 	    case DW_LNE_set_discriminator:
@@ -383,7 +385,7 @@ parse_debug_line_cu(int num_traces, void https://github.com/ruby/ruby/blob/trunk/addr2line.c#L385
 		uleb128(&p);
 		break;
 	    default:
-		fprintf(stderr, "Unknown extended opcode: %d in %s\n",
+		kprintf("Unknown extended opcode: %d in %s\n",
 			op, binary_filename);
 	    }
 	    break;
@@ -411,7 +413,7 @@ parse_debug_line(int num_traces, void ** https://github.com/ruby/ruby/blob/trunk/addr2line.c#L413
 	parse_debug_line_cu(num_traces, traces, &debug_line, lines);
     }
     if (debug_line != debug_line_end) {
-	fprintf(stderr, "Unexpected size of .debug_line in %s\n",
+	kprintf("Unexpected size of .debug_line in %s\n",
 		binary_filename);
     }
 }
@@ -473,13 +475,13 @@ fill_lines(int num_traces, void **traces https://github.com/ruby/ruby/blob/trunk/addr2line.c#L475
     if (filesize < 0) {
 	int e = errno;
 	close(fd);
-	fprintf(stderr, "lseek: %s\n", strerror(e));
+	kprintf("lseek: %s\n", strerror(e));
 	return;
     }
 #if SIZEOF_OFF_T > SIZEOF_SIZE_T
     if (filesize > (off_t)SIZE_MAX) {
 	close(fd);
-	fprintf(stderr, "Too large file %s\n", binary_filename);
+	kprintf("Too large file %s\n", binary_filename);
 	return;
     }
 #endif
@@ -489,7 +491,7 @@ fill_lines(int num_traces, void **traces https://github.com/ruby/ruby/blob/trunk/addr2line.c#L491
     if (file == MAP_FAILED) {
 	int e = errno;
 	close(fd);
-	fprintf(stderr, "mmap: %s\n", strerror(e));
+	kprintf("mmap: %s\n", strerror(e));
 	return;
     }
 
@@ -614,23 +616,22 @@ rb_dump_backtrace_with_lines(int num_tra https://github.com/ruby/ruby/blob/trunk/addr2line.c#L616
 	fill_lines(num_traces, trace, syms, 1, &lines[i], lines);
     }
 
-    /* fprintf may not be async-signal safe */
     for (i = 0; i < num_traces; i++) {
 	line_info_t *line = &lines[i];
 
 	if (line->line > 0) {
 	    if (line->filename) {
 		if (line->dirname && line->dirname[0]) {
-		    fprintf(stderr, "%s %s/%s:%d\n", syms[i], line->dirname, line->filename, line->line);
+		    kprintf("%s %s/%s:%d\n", syms[i], line->dirname, line->filename, line->line);
 		}
 		else {
-		    fprintf(stderr, "%s %s:%d\n", syms[i], line->filename, line->line);
+		    kprintf("%s %s:%d\n", syms[i], line->filename, line->line);
 		}
 	    } else {
-		fprintf(stderr, "%s ???:%d\n", syms[i], line->line);
+		kprintf("%s ???:%d\n", syms[i], line->line);
 	    }
 	} else {
-	    fprintf(stderr, "%s\n", syms[i]);
+	    kprintf("%s\n", syms[i]);
 	}
     }
 
@@ -644,6 +645,433 @@ rb_dump_backtrace_with_lines(int num_tra https://github.com/ruby/ruby/blob/trunk/addr2line.c#L645
     free(lines);
 }
 
+/* From FreeBSD's lib/libstand/printf.c */
+/*-
+ * 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.
+ *
+ * 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 <stdarg.h>
+#define MAXNBUF (sizeof(intmax_t) * CHAR_BIT + 1)
+extern int rb_toupper(int c);
+#define    toupper(c)  rb_toupper(c)
+#define    hex2ascii(hex)  (hex2ascii_data[hex])
+char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+static __inline int imax(int a, int b) { return (a > b ? a : b); }
+static int kvprintf(char const *fmt, void (*func)(int), void *arg, int radix, va_list ap);
+
+static void putce(int c)
+{
+    char s[1];
+    s[0] = (char)c;
+    write(2, s, 1);
+}
+
+int
+kprintf(const char *fmt, ...)
+{
+	va_list ap;
+	int retval;
+
+	va_start(ap, fmt);
+	retval = kvprintf(fmt, putce, NULL, 10, ap);
+	va_end(ap);
+	return retval;
+}
+
+/*
+ * 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 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);
+}
+
+/*
+ * Scaled down version of printf(3).
+ *
+ * Two additional formats:
+ *
+ * The format %b is supported to decode error registers.
+ * Its usage is:
+ *
+ *	printf("reg=%b\n", regval, "<base><arg>*");
+ *
+ * where <base> is the output base expressed as a control character, e.g.
+ * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
+ * the first of which gives the bit number to be inspected (origin 1), and
+ * the next characters (up to a control character, i.e. a character <= 32),
+ * give the name of the register.  Thus:
+ *
+ *	kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
+ *
+ * would produce output:
+ *
+ *	reg=3<BITTWO,BITONE>
+ *
+ * XXX:  %D  -- Hexdump, takes pointer and separator string:
+ *		("%6D", ptr, ":")   -> XX:XX:XX:XX:XX:XX
+ *		("%*D", len, ptr, " " -> XX XX XX XX ...
+ */
+static int
+kvprintf(char const *fmt, void (*func)(int), void *arg, int radix, va_list ap)
+{
+#define PCHAR(c) {int cc=(c); if (func) (*func)(cc); else *d++ = cc; retval++; }
+	char nbuf[MAXNBUF];
+	char *d;
+	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 (!func)
+		d = (char *) arg;
+	else
+		d = NULL;
+
+	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
+}
 #else /* defined(USE_ELF) */
 #error not supported
 #endif

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]