2 * Copyright (C) 2010 The Android Open Source Project
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include "linker_format.h"
36 #include "linker_debug.h"
38 /* define UNIT_TESTS to build this file as a single executable that runs
39 * the formatter's unit tests
43 /*** Generic output sink
48 void (*send
)(void *opaque
, const char *data
, int len
);
52 out_send(Out
*o
, const void *data
, size_t len
)
54 o
->send(o
->opaque
, data
, (int)len
);
58 out_send_repeat(Out
*o
, char ch
, int count
)
61 const int padSize
= (int)sizeof(pad
);
63 memset(pad
, ch
, sizeof(pad
));
66 if (avail
> padSize
) {
69 o
->send(o
->opaque
, pad
, avail
);
74 /* forward declaration */
76 out_vformat(Out
*o
, const char *format
, va_list args
);
78 /*** Bounded buffer output
90 buf_out_send(void *opaque
, const char *data
, int len
)
100 int avail
= bo
->end
- bo
->pos
;
105 memcpy(bo
->pos
, data
, avail
);
113 buf_out_init(BufOut
*bo
, char *buffer
, size_t size
)
118 bo
->out
->opaque
= bo
;
119 bo
->out
->send
= buf_out_send
;
121 bo
->end
= buffer
+ size
- 1;
122 bo
->pos
= bo
->buffer
;
130 buf_out_length(BufOut
*bo
)
136 vformat_buffer(char *buff
, size_t buffsize
, const char *format
, va_list args
)
141 out
= buf_out_init(&bo
, buff
, buffsize
);
145 out_vformat(out
, format
, args
);
147 return buf_out_length(&bo
);
151 format_buffer(char *buff
, size_t buffsize
, const char *format
, ...)
156 va_start(args
, format
);
157 ret
= vformat_buffer(buff
, buffsize
, format
, args
);
163 /* The __stack_chk_fail() function calls __libc_android_log_print()
164 * which calls vsnprintf().
166 * We define our version of the function here to avoid dragging
167 * about 25 KB of C library routines related to formatting.
171 vsnprintf(char *buff
, size_t bufsize
, const char *format
, va_list args
)
173 return format_buffer(buff
, bufsize
, format
, args
);
179 #if !LINKER_DEBUG_TO_LOG
181 /*** File descriptor output
191 fd_out_send(void *opaque
, const char *data
, int len
)
199 int ret
= write(fdo
->fd
, data
, len
);
212 fd_out_init(FdOut
*fdo
, int fd
)
214 fdo
->out
->opaque
= fdo
;
215 fdo
->out
->send
= fd_out_send
;
223 fd_out_length(FdOut
*fdo
)
230 format_fd(int fd
, const char *format
, ...)
236 out
= fd_out_init(&fdo
, fd
);
240 va_start(args
, format
);
241 out_vformat(out
, format
, args
);
244 return fd_out_length(&fdo
);
247 #else /* LINKER_DEBUG_TO_LOG */
252 /* We need our own version of __libc_android_log_vprint, otherwise
253 * the log output is completely broken. Probably due to the fact
254 * that the C library is not initialized yet.
256 * You can test that by setting CUSTOM_LOG_VPRINT to 0
258 #define CUSTOM_LOG_VPRINT 1
260 #if CUSTOM_LOG_VPRINT
266 static int log_vprint(int prio
, const char *tag
, const char *fmt
, va_list args
)
270 static int log_fd
= -1;
272 result
= vformat_buffer(buf
, sizeof buf
, fmt
, args
);
275 log_fd
= open("/dev/log/main", O_WRONLY
);
284 vec
[0].iov_base
= (unsigned char *) &prio
;
286 vec
[1].iov_base
= (void *) tag
;
287 vec
[1].iov_len
= strlen(tag
) + 1;
288 vec
[2].iov_base
= (void *) buf
;
289 vec
[2].iov_len
= strlen(buf
) + 1;
292 ret
= writev(log_fd
, vec
, 3);
293 } while ((ret
< 0) && (errno
== EINTR
));
298 #define __libc_android_log_vprint log_vprint
300 #else /* !CUSTOM_LOG_VPRINT */
302 extern int __libc_android_log_vprint(int prio
, const char* tag
, const char* format
, va_list ap
);
304 #endif /* !CUSTOM_LOG_VPRINT */
307 format_log(int prio
, const char *tag
, const char *format
, ...)
311 va_start(args
, format
);
312 ret
= __libc_android_log_vprint(prio
, tag
, format
, args
);
317 #endif /* LINKER_DEBUG_TO_LOG */
319 #endif /* LINKER_DEBUG */
321 /*** formatted output implementation
324 /* Parse a decimal string from 'format + *ppos',
325 * return the value, and writes the new position past
326 * the decimal string in '*ppos' on exit.
328 * NOTE: Does *not* handle a sign prefix.
331 parse_decimal(const char *format
, int *ppos
)
333 const char* p
= format
+ *ppos
;
338 unsigned d
= (unsigned)(ch
- '0');
343 result
= result
*10 + d
;
350 /* write an octal/decimal/number into a bounded buffer.
351 * assumes that bufsize > 0, and 'digits' is a string of
352 * digits of at least 'base' values.
355 format_number(char *buffer
, size_t bufsize
, uint64_t value
, int base
, const char *digits
)
358 char *end
= buffer
+ bufsize
- 1;
360 /* generate digit string in reverse order */
362 unsigned d
= value
% base
;
369 /* special case for 0 */
377 /* now reverse digit string in-place */
389 /* Write an integer (octal or decimal) into a buffer, assumes buffsize > 2 */
391 format_integer(char *buffer
, size_t buffsize
, uint64_t value
, int base
, int isSigned
)
393 if (isSigned
&& (int64_t)value
< 0) {
397 value
= (uint64_t)(-(int64_t)value
);
400 format_number(buffer
, buffsize
, value
, base
, "0123456789");
403 /* Write an octal into a buffer, assumes buffsize > 2 */
405 format_octal(char *buffer
, size_t buffsize
, uint64_t value
, int isSigned
)
407 format_integer(buffer
, buffsize
, value
, 8, isSigned
);
410 /* Write a decimal into a buffer, assumes buffsize > 2 */
412 format_decimal(char *buffer
, size_t buffsize
, uint64_t value
, int isSigned
)
414 format_integer(buffer
, buffsize
, value
, 10, isSigned
);
417 /* Write an hexadecimal into a buffer, isCap is true for capital alphas.
418 * Assumes bufsize > 2 */
420 format_hex(char *buffer
, size_t buffsize
, uint64_t value
, int isCap
)
422 const char *digits
= isCap
? "0123456789ABCDEF" : "0123456789abcdef";
424 format_number(buffer
, buffsize
, value
, 16, digits
);
428 /* Perform formatted output to an output target 'o' */
430 out_vformat(Out
*o
, const char *format
, va_list args
)
441 size_t bytelen
= sizeof(int);
444 char buffer
[32]; /* temporary buffer used to format numbers */
448 /* first, find all characters that are not 0 or '%' */
449 /* then send them to the output directly */
453 if (c
== '\0' || c
== '%')
459 out_send(o
, format
+nn
, mm
-nn
);
463 /* is this it ? then exit */
467 /* nope, we are at a '%' modifier */
473 if (c
== '\0') { /* single trailing '%' ? */
486 else if (c
== ' ' || c
== '+') {
493 /* parse field width */
494 if ((c
>= '0' && c
<= '9')) {
496 width
= (int)parse_decimal(format
, &nn
);
500 /* parse precision */
502 prec
= (int)parse_decimal(format
, &nn
);
506 /* length modifier */
509 bytelen
= sizeof(short);
510 if (format
[nn
] == 'h') {
511 bytelen
= sizeof(char);
517 bytelen
= sizeof(long);
518 if (format
[nn
] == 'l') {
519 bytelen
= sizeof(long long);
525 bytelen
= sizeof(size_t);
529 bytelen
= sizeof(ptrdiff_t);
536 /* conversion specifier */
539 str
= va_arg(args
, const char*);
540 } else if (c
== 'c') {
542 /* NOTE: char is promoted to int when passed through the stack */
543 buffer
[0] = (char) va_arg(args
, int);
546 } else if (c
== 'p') {
547 uint64_t value
= (uintptr_t) va_arg(args
, void*);
550 format_hex(buffer
+ 2, sizeof buffer
-2, value
, 0);
553 /* integers - first read value from stack */
555 int isSigned
= (c
== 'd' || c
== 'i' || c
== 'o');
557 /* NOTE: int8_t and int16_t are promoted to int when passed
561 case 1: value
= (uint8_t) va_arg(args
, int); break;
562 case 2: value
= (uint16_t) va_arg(args
, int); break;
563 case 4: value
= va_arg(args
, uint32_t); break;
564 case 8: value
= va_arg(args
, uint64_t); break;
565 default: return; /* should not happen */
568 /* sign extension, if needed */
570 int shift
= 64 - 8*bytelen
;
571 value
= (uint64_t)(((int64_t)(value
<< shift
)) >> shift
);
574 /* format the number properly into our buffer */
577 format_integer(buffer
, sizeof buffer
, value
, 10, isSigned
);
580 format_integer(buffer
, sizeof buffer
, value
, 8, isSigned
);
583 format_hex(buffer
, sizeof buffer
, value
, (c
== 'X'));
588 /* then point to it */
592 /* if we are here, 'str' points to the content that must be
593 * outputted. handle padding and alignment now */
597 if (slen
< width
&& !padLeft
) {
598 char padChar
= padZero
? '0' : ' ';
599 out_send_repeat(o
, padChar
, width
- slen
);
602 out_send(o
, str
, slen
);
604 if (slen
< width
&& padLeft
) {
605 char padChar
= padZero
? '0' : ' ';
606 out_send_repeat(o
, padChar
, width
- slen
);
616 static int gFails
= 0;
620 #define UTEST_CHECK(condition,message) \
621 printf("Checking %-*s: ", MARGIN, message); fflush(stdout); \
622 if (!(condition)) { \
638 out
= buf_out_init(bo
, buffer
, sizeof buffer
);
639 UTEST_CHECK(buffer
[0] == '\0', "buf_out_init clears initial byte");
640 out_send(out
, "abc", 3);
641 UTEST_CHECK(!memcmp(buffer
, "abc", 4), "out_send() works with BufOut");
642 out_send_repeat(out
, 'X', 4);
643 UTEST_CHECK(!memcmp(buffer
, "abcXXXX", 8), "out_send_repeat() works with BufOut");
644 buffer
[sizeof buffer
-1] = 'x';
645 out_send_repeat(out
, 'Y', 2*sizeof(buffer
));
646 UTEST_CHECK(buffer
[sizeof buffer
-1] == '\0', "overflows always zero-terminates");
648 out
= buf_out_init(bo
, buffer
, sizeof buffer
);
649 out_send_repeat(out
, 'X', 2*sizeof(buffer
));
650 ret
= buf_out_length(bo
);
651 UTEST_CHECK(ret
== 2*sizeof(buffer
), "correct size returned on overflow");
655 utest_expect(const char* result
, const char* format
, ...)
660 Out
* out
= buf_out_init(bo
, buffer
, sizeof buffer
);
662 printf("Checking %-*s: ", MARGIN
, format
); fflush(stdout
);
663 va_start(args
, format
);
664 out_vformat(out
, format
, args
);
667 if (strcmp(result
, buffer
)) {
668 printf("KO. got '%s' expecting '%s'\n", buffer
, result
);
671 printf("ok. got '%s'\n", result
);
678 utest_expect("", "");
679 utest_expect("a", "a");
680 utest_expect("01234", "01234", "");
681 utest_expect("01234", "%s", "01234");
682 utest_expect("aabbcc", "aa%scc", "bb");
683 utest_expect("a", "%c", 'a');
684 utest_expect("1234", "%d", 1234);
685 utest_expect("-8123", "%d", -8123);
686 utest_expect("16", "%hd", 0x7fff0010);
687 utest_expect("16", "%hhd", 0x7fffff10);
688 utest_expect("68719476736", "%lld", 0x1000000000LL
);
689 utest_expect("70000", "%ld", 70000);
690 utest_expect("0xb0001234", "%p", (void*)0xb0001234);
691 utest_expect("12ab", "%x", 0x12ab);
692 utest_expect("12AB", "%X", 0x12ab);
693 utest_expect("00123456", "%08x", 0x123456);
694 utest_expect("01234", "0%d", 1234);
695 utest_expect(" 1234", "%5d", 1234);
696 utest_expect("01234", "%05d", 1234);
697 utest_expect(" 1234", "%8d", 1234);
698 utest_expect("1234 ", "%-8d", 1234);
699 utest_expect("abcdef ", "%-11s", "abcdef");
700 utest_expect("something:1234", "%s:%d", "something", 1234);
701 utest_expect("005:5:05", "%03d:%d:%02d", 5, 5, 5);
702 utest_expect("5,0x0", "%d,%p", 5, NULL
);
703 utest_expect("68719476736,6,7,8", "%lld,%d,%d,%d", 0x1000000000LL
, 6, 7, 8);
707 #endif /* UNIT_TESTS */