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, mm; 431 int padZero = 0; 432 int padLeft = 0; 433 char sign = '\0'; 434 int width = -1; 435 int prec = -1; 436 size_t bytelen = sizeof(int); 437 const char* str; 438 int slen; 439 char buffer[32]; /* temporary buffer used to format numbers */ 440 441 for (;;) { 442 char c; 443 444 /* first, find all characters that are not 0 or '%' */ 445 /* then send them to the output directly */ 446 mm = nn; 447 do { 448 c = format[mm]; 449 if (c == '\0' || c == '%') 450 break; 451 mm++; 452 } while (1); 453 454 if (mm > nn) { 455 out_send(o, format+nn, mm-nn); 456 nn = mm; 457 } 458 459 /* is this it ? then exit */ 460 if (c == '\0') 461 break; 462 463 /* nope, we are at a '%' modifier */ 464 nn++; // skip it 465 466 /* parse flags */ 467 for (;;) { 468 c = format[nn++]; 469 if (c == '\0') { /* single trailing '%' ? */ 470 c = '%'; 471 out_send(o, &c, 1); 472 return; 473 } 474 else if (c == '0') { 475 padZero = 1; 476 continue; 477 } 478 else if (c == '-') { 479 padLeft = 1; 480 continue; 481 } 482 else if (c == ' ' || c == '+') { 483 sign = c; 484 continue; 485 } 486 break; 487 } 488 489 /* parse field width */ 490 if ((c >= '0' && c <= '9')) { 491 nn --; 492 width = (int)parse_decimal(format, &nn); 493 c = format[nn++]; 494 } 495 496 /* parse precision */ 497 if (c == '.') { 498 prec = (int)parse_decimal(format, &nn); 499 c = format[nn++]; 500 } 501 502 /* length modifier */ 503 switch (c) { 504 case 'h': 505 bytelen = sizeof(short); 506 if (format[nn] == 'h') { 507 bytelen = sizeof(char); 508 nn += 1; 509 } 510 c = format[nn++]; 511 break; 512 case 'l': 513 bytelen = sizeof(long); 514 if (format[nn] == 'l') { 515 bytelen = sizeof(long long); 516 nn += 1; 517 } 518 c = format[nn++]; 519 break; 520 case 'z': 521 bytelen = sizeof(size_t); 522 c = format[nn++]; 523 break; 524 case 't': 525 bytelen = sizeof(ptrdiff_t); 526 c = format[nn++]; 527 break; 528 case 'p': 529 bytelen = sizeof(void*); 530 c = format[nn++]; 531 default: 532 ; 533 } 534 535 /* conversion specifier */ 536 if (c == 's') { 537 /* string */ 538 str = va_arg(args, const char*); 539 } else if (c == 'c') { 540 /* character */ 541 /* NOTE: char is promoted to int when passed through the stack */ 542 buffer[0] = (char) va_arg(args, int); 543 buffer[1] = '\0'; 544 str = buffer; 545 } else if (c == 'p') { 546 uint64_t value = (uint64_t)(ptrdiff_t) va_arg(args, void*); 547 buffer[0] = '0'; 548 buffer[1] = 'x'; 549 format_hex(buffer + 2, sizeof buffer-2, value, 0); 550 str = buffer; 551 } else { 552 /* integers - first read value from stack */ 553 uint64_t value; 554 int isSigned = (c == 'd' || c == 'i' || c == 'o'); 555 556 /* NOTE: int8_t and int16_t are promoted to int when passed 557 * through the stack 558 */ 559 switch (bytelen) { 560 case 1: value = (uint8_t) va_arg(args, int); break; 561 case 2: value = (uint16_t) va_arg(args, int); break; 562 case 4: value = va_arg(args, uint32_t); break; 563 case 8: value = va_arg(args, uint64_t); break; 564 default: return; /* should not happen */ 565 } 566 567 /* sign extension, if needed */ 568 if (isSigned) { 569 int shift = 64 - 8*bytelen; 570 value = (uint64_t)(((int64_t)(value << shift)) >> shift); 571 } 572 573 /* format the number properly into our buffer */ 574 switch (c) { 575 case 'i': case 'd': 576 format_integer(buffer, sizeof buffer, value, 10, isSigned); 577 break; 578 case 'o': 579 format_integer(buffer, sizeof buffer, value, 8, isSigned); 580 break; 581 case 'x': case 'X': 582 format_hex(buffer, sizeof buffer, value, (c == 'X')); 583 break; 584 default: 585 buffer[0] = '\0'; 586 } 587 /* then point to it */ 588 str = buffer; 589 } 590 591 /* if we are here, 'str' points to the content that must be 592 * outputted. handle padding and alignment now */ 593 594 slen = strlen(str); 595 596 if (slen < width && !padLeft) { 597 char padChar = padZero ? '0' : ' '; 598 out_send_repeat(o, padChar, width - slen); 599 } 600 601 out_send(o, str, slen); 602 603 if (slen < width && padLeft) { 604 char padChar = padZero ? '0' : ' '; 605 out_send_repeat(o, padChar, width - slen); 606 } 607 } 608 } 609 610 611 #ifdef UNIT_TESTS 612 613 #include <stdio.h> 614 615 static int gFails = 0; 616 617 #define MARGIN 40 618 619 #define UTEST_CHECK(condition,message) \ 620 printf("Checking %-*s: ", MARGIN, message); fflush(stdout); \ 621 if (!(condition)) { \ 622 printf("KO\n"); \ 623 gFails += 1; \ 624 } else { \ 625 printf("ok\n"); \ 626 } 627 628 static void 629 utest_BufOut(void) 630 { 631 char buffer[16]; 632 BufOut bo[1]; 633 Out* out; 634 int ret; 635 636 buffer[0] = '1'; 637 out = buf_out_init(bo, buffer, sizeof buffer); 638 UTEST_CHECK(buffer[0] == '\0', "buf_out_init clears initial byte"); 639 out_send(out, "abc", 3); 640 UTEST_CHECK(!memcmp(buffer, "abc", 4), "out_send() works with BufOut"); 641 out_send_repeat(out, 'X', 4); 642 UTEST_CHECK(!memcmp(buffer, "abcXXXX", 8), "out_send_repeat() works with BufOut"); 643 buffer[sizeof buffer-1] = 'x'; 644 out_send_repeat(out, 'Y', 2*sizeof(buffer)); 645 UTEST_CHECK(buffer[sizeof buffer-1] == '\0', "overflows always zero-terminates"); 646 647 out = buf_out_init(bo, buffer, sizeof buffer); 648 out_send_repeat(out, 'X', 2*sizeof(buffer)); 649 ret = buf_out_length(bo); 650 UTEST_CHECK(ret == 2*sizeof(buffer), "correct size returned on overflow"); 651 } 652 653 static void 654 utest_expect(const char* result, const char* format, ...) 655 { 656 va_list args; 657 BufOut bo[1]; 658 char buffer[256]; 659 Out* out = buf_out_init(bo, buffer, sizeof buffer); 660 661 printf("Checking %-*s: ", MARGIN, format); fflush(stdout); 662 va_start(args, format); 663 out_vformat(out, format, args); 664 va_end(args); 665 666 if (strcmp(result, buffer)) { 667 printf("KO. got '%s' expecting '%s'\n", buffer, result); 668 gFails += 1; 669 } else { 670 printf("ok. got '%s'\n", result); 671 } 672 } 673 674 int main(void) 675 { 676 utest_BufOut(); 677 utest_expect("", ""); 678 utest_expect("a", "a"); 679 utest_expect("01234", "01234", ""); 680 utest_expect("01234", "%s", "01234"); 681 utest_expect("aabbcc", "aa%scc", "bb"); 682 utest_expect("a", "%c", 'a'); 683 utest_expect("1234", "%d", 1234); 684 utest_expect("-8123", "%d", -8123); 685 utest_expect("16", "%hd", 0x7fff0010); 686 utest_expect("16", "%hhd", 0x7fffff10); 687 utest_expect("68719476736", "%lld", 0x1000000000); 688 utest_expect("70000", "%ld", 70000); 689 utest_expect("0xb0001234", "%p", (void*)0xb0001234); 690 utest_expect("12ab", "%x", 0x12ab); 691 utest_expect("12AB", "%X", 0x12ab); 692 utest_expect("00123456", "%08x", 0x123456); 693 utest_expect("01234", "0%d", 1234); 694 utest_expect(" 1234", "%5d", 1234); 695 utest_expect("01234", "%05d", 1234); 696 utest_expect(" 1234", "%8d", 1234); 697 utest_expect("1234 ", "%-8d", 1234); 698 utest_expect("abcdef ", "%-11s", "abcdef"); 699 utest_expect("something:1234", "%s:%d", "something", 1234); 700 return gFails != 0; 701 } 702 703 #endif /* UNIT_TESTS */ 704