1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 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 13 * distribution. 14 * 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 26 * SUCH DAMAGE. 27 */ 28 29 #include <stdarg.h> 30 #include <string.h> 31 #include <errno.h> 32 #include <unistd.h> 33 #include <stdint.h> 34 #include <stddef.h> 35 #include "linker_format.h" 36 #include "linker_debug.h" 37 38 /* define UNIT_TESTS to build this file as a single executable that runs 39 * the formatter's unit tests 40 */ 41 #define xxUNIT_TESTS 42 43 /*** Generic output sink 44 ***/ 45 46 typedef struct { 47 void *opaque; 48 void (*send)(void *opaque, const char *data, int len); 49 } Out; 50 51 static void 52 out_send(Out *o, const void *data, size_t len) 53 { 54 o->send(o->opaque, data, (int)len); 55 } 56 57 static void 58 out_send_repeat(Out *o, char ch, int count) 59 { 60 char pad[8]; 61 const int padSize = (int)sizeof(pad); 62 63 memset(pad, ch, sizeof(pad)); 64 while (count > 0) { 65 int avail = count; 66 if (avail > padSize) { 67 avail = padSize; 68 } 69 o->send(o->opaque, pad, avail); 70 count -= avail; 71 } 72 } 73 74 /* forward declaration */ 75 static void 76 out_vformat(Out *o, const char *format, va_list args); 77 78 /*** Bounded buffer output 79 ***/ 80 81 typedef struct { 82 Out out[1]; 83 char *buffer; 84 char *pos; 85 char *end; 86 int total; 87 } BufOut; 88 89 static void 90 buf_out_send(void *opaque, const char *data, int len) 91 { 92 BufOut *bo = opaque; 93 94 if (len < 0) 95 len = strlen(data); 96 97 bo->total += len; 98 99 while (len > 0) { 100 int avail = bo->end - bo->pos; 101 if (avail == 0) 102 break; 103 if (avail > len) 104 avail = len; 105 memcpy(bo->pos, data, avail); 106 bo->pos += avail; 107 bo->pos[0] = '\0'; 108 len -= avail; 109 } 110 } 111 112 static Out* 113 buf_out_init(BufOut *bo, char *buffer, size_t size) 114 { 115 if (size == 0) 116 return NULL; 117 118 bo->out->opaque = bo; 119 bo->out->send = buf_out_send; 120 bo->buffer = buffer; 121 bo->end = buffer + size - 1; 122 bo->pos = bo->buffer; 123 bo->pos[0] = '\0'; 124 bo->total = 0; 125 126 return bo->out; 127 } 128 129 static int 130 buf_out_length(BufOut *bo) 131 { 132 return bo->total; 133 } 134 135 static int 136 vformat_buffer(char *buff, size_t buffsize, const char *format, va_list args) 137 { 138 BufOut bo; 139 Out *out; 140 141 out = buf_out_init(&bo, buff, buffsize); 142 if (out == NULL) 143 return 0; 144 145 out_vformat(out, format, args); 146 147 return buf_out_length(&bo); 148 } 149 150 int 151 format_buffer(char *buff, size_t buffsize, const char *format, ...) 152 { 153 va_list args; 154 int ret; 155 156 va_start(args, format); 157 ret = vformat_buffer(buff, buffsize, format, args); 158 va_end(args); 159 160 return ret; 161 } 162 163 /* The __stack_chk_fail() function calls __libc_android_log_print() 164 * which calls vsnprintf(). 165 * 166 * We define our version of the function here to avoid dragging 167 * about 25 KB of C library routines related to formatting. 168 */ 169 int 170 vsnprintf(char *buff, size_t bufsize, const char *format, va_list args) 171 { 172 return format_buffer(buff, bufsize, format, args); 173 } 174 175 #if LINKER_DEBUG 176 177 #if !LINKER_DEBUG_TO_LOG 178 179 /*** File descriptor output 180 ***/ 181 182 typedef struct { 183 Out out[1]; 184 int fd; 185 int total; 186 } FdOut; 187 188 static void 189 fd_out_send(void *opaque, const char *data, int len) 190 { 191 FdOut *fdo = opaque; 192 193 if (len < 0) 194 len = strlen(data); 195 196 while (len > 0) { 197 int ret = write(fdo->fd, data, len); 198 if (ret < 0) { 199 if (errno == EINTR) 200 continue; 201 break; 202 } 203 data += ret; 204 len -= ret; 205 fdo->total += ret; 206 } 207 } 208 209 static Out* 210 fd_out_init(FdOut *fdo, int fd) 211 { 212 fdo->out->opaque = fdo; 213 fdo->out->send = fd_out_send; 214 fdo->fd = fd; 215 fdo->total = 0; 216 217 return fdo->out; 218 } 219 220 static int 221 fd_out_length(FdOut *fdo) 222 { 223 return fdo->total; 224 } 225 226 227 int 228 format_fd(int fd, const char *format, ...) 229 { 230 FdOut fdo; 231 Out* out; 232 va_list args; 233 234 out = fd_out_init(&fdo, fd); 235 if (out == NULL) 236 return 0; 237 238 va_start(args, format); 239 out_vformat(out, format, args); 240 va_end(args); 241 242 return fd_out_length(&fdo); 243 } 244 245 #else /* LINKER_DEBUG_TO_LOG */ 246 247 /*** Log output 248 ***/ 249 250 /* We need our own version of __libc_android_log_vprint, otherwise 251 * the log output is completely broken. Probably due to the fact 252 * that the C library is not initialized yet. 253 * 254 * You can test that by setting CUSTOM_LOG_VPRINT to 0 255 */ 256 #define CUSTOM_LOG_VPRINT 1 257 258 #if CUSTOM_LOG_VPRINT 259 260 #include <unistd.h> 261 #include <fcntl.h> 262 #include <sys/uio.h> 263 264 static int log_vprint(int prio, const char *tag, const char *fmt, va_list args) 265 { 266 char buf[1024]; 267 int result; 268 static int log_fd = -1; 269 270 result = vformat_buffer(buf, sizeof buf, fmt, args); 271 272 if (log_fd < 0) { 273 log_fd = open("/dev/log/main", O_WRONLY); 274 if (log_fd < 0) 275 return result; 276 } 277 278 { 279 ssize_t ret; 280 struct iovec vec[3]; 281 282 vec[0].iov_base = (unsigned char *) &prio; 283 vec[0].iov_len = 1; 284 vec[1].iov_base = (void *) tag; 285 vec[1].iov_len = strlen(tag) + 1; 286 vec[2].iov_base = (void *) buf; 287 vec[2].iov_len = strlen(buf) + 1; 288 289 do { 290 ret = writev(log_fd, vec, 3); 291 } while ((ret < 0) && (errno == EINTR)); 292 } 293 return result; 294 } 295 296 #define __libc_android_log_vprint log_vprint 297 298 #else /* !CUSTOM_LOG_VPRINT */ 299 300 extern int __libc_android_log_vprint(int prio, const char* tag, const char* format, va_list ap); 301 302 #endif /* !CUSTOM_LOG_VPRINT */ 303 304 int 305 format_log(int prio, const char *tag, const char *format, ...) 306 { 307 int ret; 308 va_list args; 309 va_start(args, format); 310 ret = __libc_android_log_vprint(prio, tag, format, args); 311 va_end(args); 312 return ret; 313 } 314 315 #endif /* LINKER_DEBUG_TO_LOG */ 316 317 #endif /* LINKER_DEBUG */ 318 319 /*** formatted output implementation 320 ***/ 321 322 /* Parse a decimal string from 'format + *ppos', 323 * return the value, and writes the new position past 324 * the decimal string in '*ppos' on exit. 325 * 326 * NOTE: Does *not* handle a sign prefix. 327 */ 328 static unsigned 329 parse_decimal(const char *format, int *ppos) 330 { 331 const char* p = format + *ppos; 332 unsigned result = 0; 333 334 for (;;) { 335 int ch = *p; 336 unsigned d = (unsigned)(ch - '0'); 337 338 if (d >= 10U) 339 break; 340 341 result = result*10 + d; 342 p++; 343 } 344 *ppos = p - format; 345 return result; 346 } 347 348 /* write an octal/decimal/number into a bounded buffer. 349 * assumes that bufsize > 0, and 'digits' is a string of 350 * digits of at least 'base' values. 351 */ 352 static void 353 format_number(char *buffer, size_t bufsize, uint64_t value, int base, const char *digits) 354 { 355 char *pos = buffer; 356 char *end = buffer + bufsize - 1; 357 358 /* generate digit string in reverse order */ 359 while (value) { 360 unsigned d = value % base; 361 value /= base; 362 if (pos < end) { 363 *pos++ = digits[d]; 364 } 365 } 366 367 /* special case for 0 */ 368 if (pos == buffer) { 369 if (pos < end) { 370 *pos++ = '0'; 371 } 372 } 373 pos[0] = '\0'; 374 375 /* now reverse digit string in-place */ 376 end = pos - 1; 377 pos = buffer; 378 while (pos < end) { 379 int ch = pos[0]; 380 pos[0] = end[0]; 381 end[0] = (char) ch; 382 pos++; 383 end--; 384 } 385 } 386 387 /* Write an integer (octal or decimal) into a buffer, assumes buffsize > 2 */ 388 static void 389 format_integer(char *buffer, size_t buffsize, uint64_t value, int base, int isSigned) 390 { 391 if (isSigned && (int64_t)value < 0) { 392 buffer[0] = '-'; 393 buffer += 1; 394 buffsize -= 1; 395 value = (uint64_t)(-(int64_t)value); 396 } 397 398 format_number(buffer, buffsize, value, base, "0123456789"); 399 } 400 401 /* Write an octal into a buffer, assumes buffsize > 2 */ 402 static void 403 format_octal(char *buffer, size_t buffsize, uint64_t value, int isSigned) 404 { 405 format_integer(buffer, buffsize, value, 8, isSigned); 406 } 407 408 /* Write a decimal into a buffer, assumes buffsize > 2 */ 409 static void 410 format_decimal(char *buffer, size_t buffsize, uint64_t value, int isSigned) 411 { 412 format_integer(buffer, buffsize, value, 10, isSigned); 413 } 414 415 /* Write an hexadecimal into a buffer, isCap is true for capital alphas. 416 * Assumes bufsize > 2 */ 417 static void 418 format_hex(char *buffer, size_t buffsize, uint64_t value, int isCap) 419 { 420 const char *digits = isCap ? "0123456789ABCDEF" : "0123456789abcdef"; 421 422 format_number(buffer, buffsize, value, 16, digits); 423 } 424 425 426 /* Perform formatted output to an output target 'o' */ 427 static void 428 out_vformat(Out *o, const char *format, va_list args) 429 { 430 int nn = 0; 431 432 for (;;) { 433 int mm; 434 int padZero = 0; 435 int padLeft = 0; 436 char sign = '\0'; 437 int width = -1; 438 int prec = -1; 439 size_t bytelen = sizeof(int); 440 const char* str; 441 int slen; 442 char buffer[32]; /* temporary buffer used to format numbers */ 443 444 char c; 445 446 /* first, find all characters that are not 0 or '%' */ 447 /* then send them to the output directly */ 448 mm = nn; 449 do { 450 c = format[mm]; 451 if (c == '\0' || c == '%') 452 break; 453 mm++; 454 } while (1); 455 456 if (mm > nn) { 457 out_send(o, format+nn, mm-nn); 458 nn = mm; 459 } 460 461 /* is this it ? then exit */ 462 if (c == '\0') 463 break; 464 465 /* nope, we are at a '%' modifier */ 466 nn++; // skip it 467 468 /* parse flags */ 469 for (;;) { 470 c = format[nn++]; 471 if (c == '\0') { /* single trailing '%' ? */ 472 c = '%'; 473 out_send(o, &c, 1); 474 return; 475 } 476 else if (c == '0') { 477 padZero = 1; 478 continue; 479 } 480 else if (c == '-') { 481 padLeft = 1; 482 continue; 483 } 484 else if (c == ' ' || c == '+') { 485 sign = c; 486 continue; 487 } 488 break; 489 } 490 491 /* parse field width */ 492 if ((c >= '0' && c <= '9')) { 493 nn --; 494 width = (int)parse_decimal(format, &nn); 495 c = format[nn++]; 496 } 497 498 /* parse precision */ 499 if (c == '.') { 500 prec = (int)parse_decimal(format, &nn); 501 c = format[nn++]; 502 } 503 504 /* length modifier */ 505 switch (c) { 506 case 'h': 507 bytelen = sizeof(short); 508 if (format[nn] == 'h') { 509 bytelen = sizeof(char); 510 nn += 1; 511 } 512 c = format[nn++]; 513 break; 514 case 'l': 515 bytelen = sizeof(long); 516 if (format[nn] == 'l') { 517 bytelen = sizeof(long long); 518 nn += 1; 519 } 520 c = format[nn++]; 521 break; 522 case 'z': 523 bytelen = sizeof(size_t); 524 c = format[nn++]; 525 break; 526 case 't': 527 bytelen = sizeof(ptrdiff_t); 528 c = format[nn++]; 529 break; 530 default: 531 ; 532 } 533 534 /* conversion specifier */ 535 if (c == 's') { 536 /* string */ 537 str = va_arg(args, const char*); 538 } else if (c == 'c') { 539 /* character */ 540 /* NOTE: char is promoted to int when passed through the stack */ 541 buffer[0] = (char) va_arg(args, int); 542 buffer[1] = '\0'; 543 str = buffer; 544 } else if (c == 'p') { 545 uint64_t value = (uintptr_t) va_arg(args, void*); 546 buffer[0] = '0'; 547 buffer[1] = 'x'; 548 format_hex(buffer + 2, sizeof buffer-2, value, 0); 549 str = buffer; 550 } else { 551 /* integers - first read value from stack */ 552 uint64_t value; 553 int isSigned = (c == 'd' || c == 'i' || c == 'o'); 554 555 /* NOTE: int8_t and int16_t are promoted to int when passed 556 * through the stack 557 */ 558 switch (bytelen) { 559 case 1: value = (uint8_t) va_arg(args, int); break; 560 case 2: value = (uint16_t) va_arg(args, int); break; 561 case 4: value = va_arg(args, uint32_t); break; 562 case 8: value = va_arg(args, uint64_t); break; 563 default: return; /* should not happen */ 564 } 565 566 /* sign extension, if needed */ 567 if (isSigned) { 568 int shift = 64 - 8*bytelen; 569 value = (uint64_t)(((int64_t)(value << shift)) >> shift); 570 } 571 572 /* format the number properly into our buffer */ 573 switch (c) { 574 case 'i': case 'd': 575 format_integer(buffer, sizeof buffer, value, 10, isSigned); 576 break; 577 case 'o': 578 format_integer(buffer, sizeof buffer, value, 8, isSigned); 579 break; 580 case 'x': case 'X': 581 format_hex(buffer, sizeof buffer, value, (c == 'X')); 582 break; 583 default: 584 buffer[0] = '\0'; 585 } 586 /* then point to it */ 587 str = buffer; 588 } 589 590 /* if we are here, 'str' points to the content that must be 591 * outputted. handle padding and alignment now */ 592 593 slen = strlen(str); 594 595 if (slen < width && !padLeft) { 596 char padChar = padZero ? '0' : ' '; 597 out_send_repeat(o, padChar, width - slen); 598 } 599 600 out_send(o, str, slen); 601 602 if (slen < width && padLeft) { 603 char padChar = padZero ? '0' : ' '; 604 out_send_repeat(o, padChar, width - slen); 605 } 606 } 607 } 608 609 610 #ifdef UNIT_TESTS 611 612 #include <stdio.h> 613 614 static int gFails = 0; 615 616 #define MARGIN 40 617 618 #define UTEST_CHECK(condition,message) \ 619 printf("Checking %-*s: ", MARGIN, message); fflush(stdout); \ 620 if (!(condition)) { \ 621 printf("KO\n"); \ 622 gFails += 1; \ 623 } else { \ 624 printf("ok\n"); \ 625 } 626 627 static void 628 utest_BufOut(void) 629 { 630 char buffer[16]; 631 BufOut bo[1]; 632 Out* out; 633 int ret; 634 635 buffer[0] = '1'; 636 out = buf_out_init(bo, buffer, sizeof buffer); 637 UTEST_CHECK(buffer[0] == '\0', "buf_out_init clears initial byte"); 638 out_send(out, "abc", 3); 639 UTEST_CHECK(!memcmp(buffer, "abc", 4), "out_send() works with BufOut"); 640 out_send_repeat(out, 'X', 4); 641 UTEST_CHECK(!memcmp(buffer, "abcXXXX", 8), "out_send_repeat() works with BufOut"); 642 buffer[sizeof buffer-1] = 'x'; 643 out_send_repeat(out, 'Y', 2*sizeof(buffer)); 644 UTEST_CHECK(buffer[sizeof buffer-1] == '\0', "overflows always zero-terminates"); 645 646 out = buf_out_init(bo, buffer, sizeof buffer); 647 out_send_repeat(out, 'X', 2*sizeof(buffer)); 648 ret = buf_out_length(bo); 649 UTEST_CHECK(ret == 2*sizeof(buffer), "correct size returned on overflow"); 650 } 651 652 static void 653 utest_expect(const char* result, const char* format, ...) 654 { 655 va_list args; 656 BufOut bo[1]; 657 char buffer[256]; 658 Out* out = buf_out_init(bo, buffer, sizeof buffer); 659 660 printf("Checking %-*s: ", MARGIN, format); fflush(stdout); 661 va_start(args, format); 662 out_vformat(out, format, args); 663 va_end(args); 664 665 if (strcmp(result, buffer)) { 666 printf("KO. got '%s' expecting '%s'\n", buffer, result); 667 gFails += 1; 668 } else { 669 printf("ok. got '%s'\n", result); 670 } 671 } 672 673 int main(void) 674 { 675 utest_BufOut(); 676 utest_expect("", ""); 677 utest_expect("a", "a"); 678 utest_expect("01234", "01234", ""); 679 utest_expect("01234", "%s", "01234"); 680 utest_expect("aabbcc", "aa%scc", "bb"); 681 utest_expect("a", "%c", 'a'); 682 utest_expect("1234", "%d", 1234); 683 utest_expect("-8123", "%d", -8123); 684 utest_expect("16", "%hd", 0x7fff0010); 685 utest_expect("16", "%hhd", 0x7fffff10); 686 utest_expect("68719476736", "%lld", 0x1000000000LL); 687 utest_expect("70000", "%ld", 70000); 688 utest_expect("0xb0001234", "%p", (void*)0xb0001234); 689 utest_expect("12ab", "%x", 0x12ab); 690 utest_expect("12AB", "%X", 0x12ab); 691 utest_expect("00123456", "%08x", 0x123456); 692 utest_expect("01234", "0%d", 1234); 693 utest_expect(" 1234", "%5d", 1234); 694 utest_expect("01234", "%05d", 1234); 695 utest_expect(" 1234", "%8d", 1234); 696 utest_expect("1234 ", "%-8d", 1234); 697 utest_expect("abcdef ", "%-11s", "abcdef"); 698 utest_expect("something:1234", "%s:%d", "something", 1234); 699 utest_expect("005:5:05", "%03d:%d:%02d", 5, 5, 5); 700 utest_expect("5,0x0", "%d,%p", 5, NULL); 701 utest_expect("68719476736,6,7,8", "%lld,%d,%d,%d", 0x1000000000LL, 6, 7, 8); 702 return gFails != 0; 703 } 704 705 #endif /* UNIT_TESTS */ 706