1 /* 2 * Copyright (c) 2013-2018, Intel Corporation 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * * Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright notice, 10 * this list of conditions and the following disclaimer in the documentation 11 * and/or other materials provided with the distribution. 12 * * Neither the name of Intel Corporation nor the names of its contributors 13 * may be used to endorse or promote products derived from this software 14 * without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "ptunit_threads.h" 30 #include "ptunit_mkfile.h" 31 32 #include "pt_section.h" 33 #include "pt_block_cache.h" 34 35 #include "intel-pt.h" 36 37 #include <stdlib.h> 38 #include <stdio.h> 39 40 41 42 struct pt_image_section_cache { 43 int map; 44 }; 45 46 extern int pt_iscache_notify_map(struct pt_image_section_cache *iscache, 47 struct pt_section *section); 48 extern int pt_iscache_notify_resize(struct pt_image_section_cache *iscache, 49 struct pt_section *section, uint64_t size); 50 51 int pt_iscache_notify_map(struct pt_image_section_cache *iscache, 52 struct pt_section *section) 53 { 54 if (!iscache) 55 return -pte_internal; 56 57 if (iscache->map <= 0) 58 return iscache->map; 59 60 /* Avoid recursion. */ 61 iscache->map = 0; 62 63 return pt_section_map_share(section); 64 } 65 66 int pt_iscache_notify_resize(struct pt_image_section_cache *iscache, 67 struct pt_section *section, uint64_t size) 68 { 69 uint64_t memsize; 70 int errcode; 71 72 if (!iscache) 73 return -pte_internal; 74 75 if (iscache->map <= 0) 76 return iscache->map; 77 78 /* Avoid recursion. */ 79 iscache->map = 0; 80 81 errcode = pt_section_memsize(section, &memsize); 82 if (errcode < 0) 83 return errcode; 84 85 if (size != memsize) 86 return -pte_internal; 87 88 return pt_section_map_share(section); 89 } 90 91 struct pt_block_cache *pt_bcache_alloc(uint64_t nentries) 92 { 93 struct pt_block_cache *bcache; 94 95 if (!nentries || (UINT32_MAX < nentries)) 96 return NULL; 97 98 /* The cache is not really used by tests. It suffices to allocate only 99 * the cache struct with the single default entry. 100 * 101 * We still set the number of entries to the requested size. 102 */ 103 bcache = malloc(sizeof(*bcache)); 104 if (bcache) 105 bcache->nentries = (uint32_t) nentries; 106 107 return bcache; 108 } 109 110 void pt_bcache_free(struct pt_block_cache *bcache) 111 { 112 free(bcache); 113 } 114 115 /* A test fixture providing a temporary file and an initially NULL section. */ 116 struct section_fixture { 117 /* Threading support. */ 118 struct ptunit_thrd_fixture thrd; 119 120 /* A temporary file name. */ 121 char *name; 122 123 /* That file opened for writing. */ 124 FILE *file; 125 126 /* The section. */ 127 struct pt_section *section; 128 129 /* The test fixture initialization and finalization functions. */ 130 struct ptunit_result (*init)(struct section_fixture *); 131 struct ptunit_result (*fini)(struct section_fixture *); 132 }; 133 134 enum { 135 #if defined(FEATURE_THREADS) 136 137 num_threads = 4, 138 139 #endif /* defined(FEATURE_THREADS) */ 140 141 num_work = 0x4000 142 }; 143 144 static struct ptunit_result sfix_write_aux(struct section_fixture *sfix, 145 const uint8_t *buffer, size_t size) 146 { 147 size_t written; 148 149 written = fwrite(buffer, 1, size, sfix->file); 150 ptu_uint_eq(written, size); 151 152 fflush(sfix->file); 153 154 return ptu_passed(); 155 } 156 157 #define sfix_write(sfix, buffer) \ 158 ptu_check(sfix_write_aux, sfix, buffer, sizeof(buffer)) 159 160 static struct ptunit_result create(struct section_fixture *sfix) 161 { 162 const char *name; 163 uint8_t bytes[] = { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc }; 164 uint64_t offset, size; 165 166 sfix_write(sfix, bytes); 167 168 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 169 ptu_ptr(sfix->section); 170 171 name = pt_section_filename(sfix->section); 172 ptu_str_eq(name, sfix->name); 173 174 offset = pt_section_offset(sfix->section); 175 ptu_uint_eq(offset, 0x1ull); 176 177 size = pt_section_size(sfix->section); 178 ptu_uint_eq(size, 0x3ull); 179 180 return ptu_passed(); 181 } 182 183 static struct ptunit_result create_bad_offset(struct section_fixture *sfix) 184 { 185 sfix->section = pt_mk_section(sfix->name, 0x10ull, 0x0ull); 186 ptu_null(sfix->section); 187 188 return ptu_passed(); 189 } 190 191 static struct ptunit_result create_truncated(struct section_fixture *sfix) 192 { 193 const char *name; 194 uint8_t bytes[] = { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc }; 195 uint64_t offset, size; 196 197 sfix_write(sfix, bytes); 198 199 sfix->section = pt_mk_section(sfix->name, 0x1ull, UINT64_MAX); 200 ptu_ptr(sfix->section); 201 202 name = pt_section_filename(sfix->section); 203 ptu_str_eq(name, sfix->name); 204 205 offset = pt_section_offset(sfix->section); 206 ptu_uint_eq(offset, 0x1ull); 207 208 size = pt_section_size(sfix->section); 209 ptu_uint_eq(size, sizeof(bytes) - 1); 210 211 return ptu_passed(); 212 } 213 214 static struct ptunit_result create_empty(struct section_fixture *sfix) 215 { 216 sfix->section = pt_mk_section(sfix->name, 0x0ull, 0x10ull); 217 ptu_null(sfix->section); 218 219 return ptu_passed(); 220 } 221 222 static struct ptunit_result filename_null(void) 223 { 224 const char *name; 225 226 name = pt_section_filename(NULL); 227 ptu_null(name); 228 229 return ptu_passed(); 230 } 231 232 static struct ptunit_result size_null(void) 233 { 234 uint64_t size; 235 236 size = pt_section_size(NULL); 237 ptu_uint_eq(size, 0ull); 238 239 return ptu_passed(); 240 } 241 242 static struct ptunit_result memsize_null(struct section_fixture *sfix) 243 { 244 uint64_t size; 245 int errcode; 246 247 errcode = pt_section_memsize(NULL, &size); 248 ptu_int_eq(errcode, -pte_internal); 249 250 errcode = pt_section_memsize(sfix->section, NULL); 251 ptu_int_eq(errcode, -pte_internal); 252 253 errcode = pt_section_memsize(NULL, NULL); 254 ptu_int_eq(errcode, -pte_internal); 255 256 return ptu_passed(); 257 } 258 259 static struct ptunit_result offset_null(void) 260 { 261 uint64_t offset; 262 263 offset = pt_section_offset(NULL); 264 ptu_uint_eq(offset, 0ull); 265 266 return ptu_passed(); 267 } 268 269 static struct ptunit_result get_null(void) 270 { 271 int errcode; 272 273 errcode = pt_section_get(NULL); 274 ptu_int_eq(errcode, -pte_internal); 275 276 return ptu_passed(); 277 } 278 279 static struct ptunit_result put_null(void) 280 { 281 int errcode; 282 283 errcode = pt_section_put(NULL); 284 ptu_int_eq(errcode, -pte_internal); 285 286 return ptu_passed(); 287 } 288 289 static struct ptunit_result attach_null(void) 290 { 291 struct pt_image_section_cache iscache; 292 struct pt_section section; 293 int errcode; 294 295 errcode = pt_section_attach(NULL, &iscache); 296 ptu_int_eq(errcode, -pte_internal); 297 298 errcode = pt_section_attach(§ion, NULL); 299 ptu_int_eq(errcode, -pte_internal); 300 301 errcode = pt_section_attach(NULL, NULL); 302 ptu_int_eq(errcode, -pte_internal); 303 304 return ptu_passed(); 305 } 306 307 static struct ptunit_result detach_null(void) 308 { 309 struct pt_image_section_cache iscache; 310 struct pt_section section; 311 int errcode; 312 313 errcode = pt_section_detach(NULL, &iscache); 314 ptu_int_eq(errcode, -pte_internal); 315 316 errcode = pt_section_detach(§ion, NULL); 317 ptu_int_eq(errcode, -pte_internal); 318 319 errcode = pt_section_detach(NULL, NULL); 320 ptu_int_eq(errcode, -pte_internal); 321 322 return ptu_passed(); 323 } 324 325 static struct ptunit_result map_null(void) 326 { 327 int errcode; 328 329 errcode = pt_section_map(NULL); 330 ptu_int_eq(errcode, -pte_internal); 331 332 return ptu_passed(); 333 } 334 335 static struct ptunit_result unmap_null(void) 336 { 337 int errcode; 338 339 errcode = pt_section_unmap(NULL); 340 ptu_int_eq(errcode, -pte_internal); 341 342 return ptu_passed(); 343 } 344 345 static struct ptunit_result cache_null(void) 346 { 347 struct pt_block_cache *bcache; 348 349 bcache = pt_section_bcache(NULL); 350 ptu_null(bcache); 351 352 return ptu_passed(); 353 } 354 355 static struct ptunit_result get_overflow(struct section_fixture *sfix) 356 { 357 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 358 int errcode; 359 360 sfix_write(sfix, bytes); 361 362 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 363 ptu_ptr(sfix->section); 364 365 sfix->section->ucount = UINT16_MAX; 366 367 errcode = pt_section_get(sfix->section); 368 ptu_int_eq(errcode, -pte_overflow); 369 370 sfix->section->ucount = 1; 371 372 return ptu_passed(); 373 } 374 375 static struct ptunit_result attach_overflow(struct section_fixture *sfix) 376 { 377 struct pt_image_section_cache iscache; 378 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 379 int errcode; 380 381 sfix_write(sfix, bytes); 382 383 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 384 ptu_ptr(sfix->section); 385 386 sfix->section->acount = UINT16_MAX; 387 388 errcode = pt_section_attach(sfix->section, &iscache); 389 ptu_int_eq(errcode, -pte_overflow); 390 391 sfix->section->acount = 0; 392 393 return ptu_passed(); 394 } 395 396 static struct ptunit_result attach_bad_ucount(struct section_fixture *sfix) 397 { 398 struct pt_image_section_cache iscache; 399 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 400 int errcode; 401 402 sfix_write(sfix, bytes); 403 404 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 405 ptu_ptr(sfix->section); 406 407 sfix->section->acount = 2; 408 409 errcode = pt_section_attach(sfix->section, &iscache); 410 ptu_int_eq(errcode, -pte_internal); 411 412 sfix->section->acount = 0; 413 414 return ptu_passed(); 415 } 416 417 static struct ptunit_result map_change(struct section_fixture *sfix) 418 { 419 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 420 int errcode; 421 422 sfix_write(sfix, bytes); 423 424 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 425 ptu_ptr(sfix->section); 426 427 sfix_write(sfix, bytes); 428 429 errcode = pt_section_map(sfix->section); 430 ptu_int_eq(errcode, -pte_bad_image); 431 432 return ptu_passed(); 433 } 434 435 static struct ptunit_result map_put(struct section_fixture *sfix) 436 { 437 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 438 int errcode; 439 440 sfix_write(sfix, bytes); 441 442 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 443 ptu_ptr(sfix->section); 444 445 errcode = pt_section_map(sfix->section); 446 ptu_int_eq(errcode, 0); 447 448 errcode = pt_section_put(sfix->section); 449 ptu_int_eq(errcode, -pte_internal); 450 451 errcode = pt_section_unmap(sfix->section); 452 ptu_int_eq(errcode, 0); 453 454 return ptu_passed(); 455 } 456 457 static struct ptunit_result unmap_nomap(struct section_fixture *sfix) 458 { 459 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 460 int errcode; 461 462 sfix_write(sfix, bytes); 463 464 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 465 ptu_ptr(sfix->section); 466 467 errcode = pt_section_unmap(sfix->section); 468 ptu_int_eq(errcode, -pte_nomap); 469 470 return ptu_passed(); 471 } 472 473 static struct ptunit_result map_overflow(struct section_fixture *sfix) 474 { 475 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 476 int errcode; 477 478 sfix_write(sfix, bytes); 479 480 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 481 ptu_ptr(sfix->section); 482 483 sfix->section->mcount = UINT16_MAX; 484 485 errcode = pt_section_map(sfix->section); 486 ptu_int_eq(errcode, -pte_overflow); 487 488 sfix->section->mcount = 0; 489 490 return ptu_passed(); 491 } 492 493 static struct ptunit_result get_put(struct section_fixture *sfix) 494 { 495 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 496 int errcode; 497 498 sfix_write(sfix, bytes); 499 500 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 501 ptu_ptr(sfix->section); 502 503 errcode = pt_section_get(sfix->section); 504 ptu_int_eq(errcode, 0); 505 506 errcode = pt_section_get(sfix->section); 507 ptu_int_eq(errcode, 0); 508 509 errcode = pt_section_put(sfix->section); 510 ptu_int_eq(errcode, 0); 511 512 errcode = pt_section_put(sfix->section); 513 ptu_int_eq(errcode, 0); 514 515 return ptu_passed(); 516 } 517 518 static struct ptunit_result attach_detach(struct section_fixture *sfix) 519 { 520 struct pt_image_section_cache iscache; 521 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 522 int errcode; 523 524 sfix_write(sfix, bytes); 525 526 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 527 ptu_ptr(sfix->section); 528 529 sfix->section->ucount += 2; 530 531 errcode = pt_section_attach(sfix->section, &iscache); 532 ptu_int_eq(errcode, 0); 533 534 errcode = pt_section_attach(sfix->section, &iscache); 535 ptu_int_eq(errcode, 0); 536 537 errcode = pt_section_detach(sfix->section, &iscache); 538 ptu_int_eq(errcode, 0); 539 540 errcode = pt_section_detach(sfix->section, &iscache); 541 ptu_int_eq(errcode, 0); 542 543 sfix->section->ucount -= 2; 544 545 return ptu_passed(); 546 } 547 548 static struct ptunit_result attach_bad_iscache(struct section_fixture *sfix) 549 { 550 struct pt_image_section_cache iscache, bad; 551 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 552 int errcode; 553 554 sfix_write(sfix, bytes); 555 556 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 557 ptu_ptr(sfix->section); 558 559 sfix->section->ucount += 2; 560 561 errcode = pt_section_attach(sfix->section, &iscache); 562 ptu_int_eq(errcode, 0); 563 564 errcode = pt_section_attach(sfix->section, &bad); 565 ptu_int_eq(errcode, -pte_internal); 566 567 errcode = pt_section_detach(sfix->section, &iscache); 568 ptu_int_eq(errcode, 0); 569 570 sfix->section->ucount -= 2; 571 572 return ptu_passed(); 573 } 574 575 static struct ptunit_result detach_bad_iscache(struct section_fixture *sfix) 576 { 577 struct pt_image_section_cache iscache, bad; 578 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 579 int errcode; 580 581 sfix_write(sfix, bytes); 582 583 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 584 ptu_ptr(sfix->section); 585 586 errcode = pt_section_attach(sfix->section, &iscache); 587 ptu_int_eq(errcode, 0); 588 589 errcode = pt_section_detach(sfix->section, &bad); 590 ptu_int_eq(errcode, -pte_internal); 591 592 errcode = pt_section_detach(sfix->section, &iscache); 593 ptu_int_eq(errcode, 0); 594 595 return ptu_passed(); 596 } 597 598 static struct ptunit_result map_unmap(struct section_fixture *sfix) 599 { 600 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 601 int errcode; 602 603 sfix_write(sfix, bytes); 604 605 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 606 ptu_ptr(sfix->section); 607 608 errcode = pt_section_map(sfix->section); 609 ptu_int_eq(errcode, 0); 610 611 errcode = pt_section_map(sfix->section); 612 ptu_int_eq(errcode, 0); 613 614 errcode = pt_section_unmap(sfix->section); 615 ptu_int_eq(errcode, 0); 616 617 errcode = pt_section_unmap(sfix->section); 618 ptu_int_eq(errcode, 0); 619 620 return ptu_passed(); 621 } 622 623 static struct ptunit_result attach_map(struct section_fixture *sfix) 624 { 625 struct pt_image_section_cache iscache; 626 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 627 int errcode; 628 629 iscache.map = 0; 630 631 sfix_write(sfix, bytes); 632 633 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 634 ptu_ptr(sfix->section); 635 636 errcode = pt_section_attach(sfix->section, &iscache); 637 ptu_int_eq(errcode, 0); 638 639 errcode = pt_section_map(sfix->section); 640 ptu_int_eq(errcode, 0); 641 642 errcode = pt_section_map(sfix->section); 643 ptu_int_eq(errcode, 0); 644 645 ptu_uint_eq(sfix->section->mcount, 2); 646 647 errcode = pt_section_unmap(sfix->section); 648 ptu_int_eq(errcode, 0); 649 650 errcode = pt_section_unmap(sfix->section); 651 ptu_int_eq(errcode, 0); 652 653 errcode = pt_section_detach(sfix->section, &iscache); 654 ptu_int_eq(errcode, 0); 655 656 return ptu_passed(); 657 } 658 659 static struct ptunit_result attach_bad_map(struct section_fixture *sfix) 660 { 661 struct pt_image_section_cache iscache; 662 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 663 int errcode; 664 665 iscache.map = -pte_eos; 666 667 sfix_write(sfix, bytes); 668 669 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 670 ptu_ptr(sfix->section); 671 672 errcode = pt_section_attach(sfix->section, &iscache); 673 ptu_int_eq(errcode, 0); 674 675 errcode = pt_section_map(sfix->section); 676 ptu_int_eq(errcode, -pte_eos); 677 678 errcode = pt_section_detach(sfix->section, &iscache); 679 ptu_int_eq(errcode, 0); 680 681 return ptu_passed(); 682 } 683 684 static struct ptunit_result attach_map_overflow(struct section_fixture *sfix) 685 { 686 struct pt_image_section_cache iscache; 687 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 688 int errcode; 689 690 iscache.map = 1; 691 692 sfix_write(sfix, bytes); 693 694 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 695 ptu_ptr(sfix->section); 696 697 errcode = pt_section_attach(sfix->section, &iscache); 698 ptu_int_eq(errcode, 0); 699 700 sfix->section->mcount = UINT16_MAX - 1; 701 702 errcode = pt_section_map(sfix->section); 703 ptu_int_eq(errcode, -pte_overflow); 704 705 errcode = pt_section_detach(sfix->section, &iscache); 706 ptu_int_eq(errcode, 0); 707 708 return ptu_passed(); 709 } 710 711 static struct ptunit_result read(struct section_fixture *sfix) 712 { 713 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 714 uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; 715 int status; 716 717 sfix_write(sfix, bytes); 718 719 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 720 ptu_ptr(sfix->section); 721 722 status = pt_section_map(sfix->section); 723 ptu_int_eq(status, 0); 724 725 status = pt_section_read(sfix->section, buffer, 2, 0x0ull); 726 ptu_int_eq(status, 2); 727 ptu_uint_eq(buffer[0], bytes[1]); 728 ptu_uint_eq(buffer[1], bytes[2]); 729 ptu_uint_eq(buffer[2], 0xcc); 730 731 status = pt_section_unmap(sfix->section); 732 ptu_int_eq(status, 0); 733 734 return ptu_passed(); 735 } 736 737 static struct ptunit_result read_null(struct section_fixture *sfix) 738 { 739 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 740 uint8_t buffer[] = { 0xcc }; 741 int status; 742 743 sfix_write(sfix, bytes); 744 745 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 746 ptu_ptr(sfix->section); 747 748 status = pt_section_map(sfix->section); 749 ptu_int_eq(status, 0); 750 751 status = pt_section_read(sfix->section, NULL, 1, 0x0ull); 752 ptu_int_eq(status, -pte_internal); 753 ptu_uint_eq(buffer[0], 0xcc); 754 755 status = pt_section_read(NULL, buffer, 1, 0x0ull); 756 ptu_int_eq(status, -pte_internal); 757 ptu_uint_eq(buffer[0], 0xcc); 758 759 status = pt_section_unmap(sfix->section); 760 ptu_int_eq(status, 0); 761 762 return ptu_passed(); 763 } 764 765 static struct ptunit_result read_offset(struct section_fixture *sfix) 766 { 767 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 768 uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; 769 int status; 770 771 sfix_write(sfix, bytes); 772 773 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 774 ptu_ptr(sfix->section); 775 776 status = pt_section_map(sfix->section); 777 ptu_int_eq(status, 0); 778 779 status = pt_section_read(sfix->section, buffer, 2, 0x1ull); 780 ptu_int_eq(status, 2); 781 ptu_uint_eq(buffer[0], bytes[2]); 782 ptu_uint_eq(buffer[1], bytes[3]); 783 ptu_uint_eq(buffer[2], 0xcc); 784 785 status = pt_section_unmap(sfix->section); 786 ptu_int_eq(status, 0); 787 788 return ptu_passed(); 789 } 790 791 static struct ptunit_result read_truncated(struct section_fixture *sfix) 792 { 793 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc, 0xcc }; 794 int status; 795 796 sfix_write(sfix, bytes); 797 798 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 799 ptu_ptr(sfix->section); 800 801 status = pt_section_map(sfix->section); 802 ptu_int_eq(status, 0); 803 804 status = pt_section_read(sfix->section, buffer, 2, 0x2ull); 805 ptu_int_eq(status, 1); 806 ptu_uint_eq(buffer[0], bytes[3]); 807 ptu_uint_eq(buffer[1], 0xcc); 808 809 status = pt_section_unmap(sfix->section); 810 ptu_int_eq(status, 0); 811 812 return ptu_passed(); 813 } 814 815 static struct ptunit_result read_from_truncated(struct section_fixture *sfix) 816 { 817 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc, 0xcc }; 818 int status; 819 820 sfix_write(sfix, bytes); 821 822 sfix->section = pt_mk_section(sfix->name, 0x2ull, 0x10ull); 823 ptu_ptr(sfix->section); 824 825 status = pt_section_map(sfix->section); 826 ptu_int_eq(status, 0); 827 828 status = pt_section_read(sfix->section, buffer, 2, 0x1ull); 829 ptu_int_eq(status, 1); 830 ptu_uint_eq(buffer[0], bytes[3]); 831 ptu_uint_eq(buffer[1], 0xcc); 832 833 status = pt_section_unmap(sfix->section); 834 ptu_int_eq(status, 0); 835 836 return ptu_passed(); 837 } 838 839 static struct ptunit_result read_nomem(struct section_fixture *sfix) 840 { 841 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc }; 842 int status; 843 844 sfix_write(sfix, bytes); 845 846 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 847 ptu_ptr(sfix->section); 848 849 status = pt_section_map(sfix->section); 850 ptu_int_eq(status, 0); 851 852 status = pt_section_read(sfix->section, buffer, 1, 0x3ull); 853 ptu_int_eq(status, -pte_nomap); 854 ptu_uint_eq(buffer[0], 0xcc); 855 856 status = pt_section_unmap(sfix->section); 857 ptu_int_eq(status, 0); 858 859 return ptu_passed(); 860 } 861 862 static struct ptunit_result read_overflow(struct section_fixture *sfix) 863 { 864 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc }; 865 int status; 866 867 sfix_write(sfix, bytes); 868 869 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 870 ptu_ptr(sfix->section); 871 872 status = pt_section_map(sfix->section); 873 ptu_int_eq(status, 0); 874 875 status = pt_section_read(sfix->section, buffer, 1, 876 0xffffffffffff0000ull); 877 ptu_int_eq(status, -pte_nomap); 878 ptu_uint_eq(buffer[0], 0xcc); 879 880 status = pt_section_unmap(sfix->section); 881 ptu_int_eq(status, 0); 882 883 return ptu_passed(); 884 } 885 886 static struct ptunit_result read_overflow_32bit(struct section_fixture *sfix) 887 { 888 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc }; 889 int status; 890 891 sfix_write(sfix, bytes); 892 893 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 894 ptu_ptr(sfix->section); 895 896 status = pt_section_map(sfix->section); 897 ptu_int_eq(status, 0); 898 899 status = pt_section_read(sfix->section, buffer, 1, 900 0xff00000000ull); 901 ptu_int_eq(status, -pte_nomap); 902 ptu_uint_eq(buffer[0], 0xcc); 903 904 status = pt_section_unmap(sfix->section); 905 ptu_int_eq(status, 0); 906 907 return ptu_passed(); 908 } 909 910 static struct ptunit_result read_nomap(struct section_fixture *sfix) 911 { 912 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }, buffer[] = { 0xcc }; 913 int status; 914 915 sfix_write(sfix, bytes); 916 917 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 918 ptu_ptr(sfix->section); 919 920 status = pt_section_read(sfix->section, buffer, 1, 0x0ull); 921 ptu_int_eq(status, -pte_nomap); 922 ptu_uint_eq(buffer[0], 0xcc); 923 924 return ptu_passed(); 925 } 926 927 static struct ptunit_result read_unmap_map(struct section_fixture *sfix) 928 { 929 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 930 uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; 931 int status; 932 933 sfix_write(sfix, bytes); 934 935 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 936 ptu_ptr(sfix->section); 937 938 status = pt_section_map(sfix->section); 939 ptu_int_eq(status, 0); 940 941 status = pt_section_read(sfix->section, buffer, 2, 0x0ull); 942 ptu_int_eq(status, 2); 943 ptu_uint_eq(buffer[0], bytes[1]); 944 ptu_uint_eq(buffer[1], bytes[2]); 945 ptu_uint_eq(buffer[2], 0xcc); 946 947 memset(buffer, 0xcc, sizeof(buffer)); 948 949 status = pt_section_unmap(sfix->section); 950 ptu_int_eq(status, 0); 951 952 status = pt_section_read(sfix->section, buffer, 2, 0x0ull); 953 ptu_int_eq(status, -pte_nomap); 954 ptu_uint_eq(buffer[0], 0xcc); 955 ptu_uint_eq(buffer[1], 0xcc); 956 ptu_uint_eq(buffer[2], 0xcc); 957 958 status = pt_section_map(sfix->section); 959 ptu_int_eq(status, 0); 960 961 status = pt_section_read(sfix->section, buffer, 2, 0x0ull); 962 ptu_int_eq(status, 2); 963 ptu_uint_eq(buffer[0], bytes[1]); 964 ptu_uint_eq(buffer[1], bytes[2]); 965 ptu_uint_eq(buffer[2], 0xcc); 966 967 status = pt_section_unmap(sfix->section); 968 ptu_int_eq(status, 0); 969 970 return ptu_passed(); 971 } 972 973 static int worker_read(void *arg) 974 { 975 struct section_fixture *sfix; 976 int it, errcode; 977 978 sfix = arg; 979 if (!sfix) 980 return -pte_internal; 981 982 for (it = 0; it < num_work; ++it) { 983 uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; 984 int read; 985 986 errcode = pt_section_get(sfix->section); 987 if (errcode < 0) 988 return errcode; 989 990 errcode = pt_section_map(sfix->section); 991 if (errcode < 0) 992 goto out_put; 993 994 read = pt_section_read(sfix->section, buffer, 2, 0x0ull); 995 if (read < 0) 996 goto out_unmap; 997 998 errcode = -pte_invalid; 999 if ((read != 2) || (buffer[0] != 0x2) || (buffer[1] != 0x4)) 1000 goto out_unmap; 1001 1002 errcode = pt_section_unmap(sfix->section); 1003 if (errcode < 0) 1004 goto out_put; 1005 1006 errcode = pt_section_put(sfix->section); 1007 if (errcode < 0) 1008 return errcode; 1009 } 1010 1011 return 0; 1012 1013 out_unmap: 1014 (void) pt_section_unmap(sfix->section); 1015 1016 out_put: 1017 (void) pt_section_put(sfix->section); 1018 return errcode; 1019 } 1020 1021 static int worker_bcache(void *arg) 1022 { 1023 struct section_fixture *sfix; 1024 int it, errcode; 1025 1026 sfix = arg; 1027 if (!sfix) 1028 return -pte_internal; 1029 1030 errcode = pt_section_get(sfix->section); 1031 if (errcode < 0) 1032 return errcode; 1033 1034 for (it = 0; it < num_work; ++it) { 1035 struct pt_block_cache *bcache; 1036 1037 errcode = pt_section_map(sfix->section); 1038 if (errcode < 0) 1039 goto out_put; 1040 1041 errcode = pt_section_request_bcache(sfix->section); 1042 if (errcode < 0) 1043 goto out_unmap; 1044 1045 bcache = pt_section_bcache(sfix->section); 1046 if (!bcache) { 1047 errcode = -pte_nomem; 1048 goto out_unmap; 1049 } 1050 1051 errcode = pt_section_unmap(sfix->section); 1052 if (errcode < 0) 1053 goto out_put; 1054 } 1055 1056 return pt_section_put(sfix->section); 1057 1058 out_unmap: 1059 (void) pt_section_unmap(sfix->section); 1060 1061 out_put: 1062 (void) pt_section_put(sfix->section); 1063 return errcode; 1064 } 1065 1066 static struct ptunit_result stress(struct section_fixture *sfix, 1067 int (*worker)(void *)) 1068 { 1069 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 1070 int errcode; 1071 1072 sfix_write(sfix, bytes); 1073 1074 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 1075 ptu_ptr(sfix->section); 1076 1077 #if defined(FEATURE_THREADS) 1078 { 1079 int thrd; 1080 1081 for (thrd = 0; thrd < num_threads; ++thrd) 1082 ptu_test(ptunit_thrd_create, &sfix->thrd, worker, sfix); 1083 } 1084 #endif /* defined(FEATURE_THREADS) */ 1085 1086 errcode = worker(sfix); 1087 ptu_int_eq(errcode, 0); 1088 1089 return ptu_passed(); 1090 } 1091 1092 static struct ptunit_result init_no_bcache(struct section_fixture *sfix) 1093 { 1094 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 1095 struct pt_block_cache *bcache; 1096 int errcode; 1097 1098 sfix_write(sfix, bytes); 1099 1100 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 1101 ptu_ptr(sfix->section); 1102 1103 errcode = pt_section_map(sfix->section); 1104 ptu_int_eq(errcode, 0); 1105 1106 bcache = pt_section_bcache(sfix->section); 1107 ptu_null(bcache); 1108 1109 errcode = pt_section_unmap(sfix->section); 1110 ptu_int_eq(errcode, 0); 1111 1112 return ptu_passed(); 1113 } 1114 1115 static struct ptunit_result bcache_alloc_free(struct section_fixture *sfix) 1116 { 1117 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 1118 struct pt_block_cache *bcache; 1119 int errcode; 1120 1121 sfix_write(sfix, bytes); 1122 1123 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 1124 ptu_ptr(sfix->section); 1125 1126 errcode = pt_section_map(sfix->section); 1127 ptu_int_eq(errcode, 0); 1128 1129 errcode = pt_section_alloc_bcache(sfix->section); 1130 ptu_int_eq(errcode, 0); 1131 1132 bcache = pt_section_bcache(sfix->section); 1133 ptu_ptr(bcache); 1134 ptu_uint_eq(bcache->nentries, sfix->section->size); 1135 1136 errcode = pt_section_unmap(sfix->section); 1137 ptu_int_eq(errcode, 0); 1138 1139 bcache = pt_section_bcache(sfix->section); 1140 ptu_null(bcache); 1141 1142 return ptu_passed(); 1143 } 1144 1145 static struct ptunit_result bcache_alloc_twice(struct section_fixture *sfix) 1146 { 1147 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 1148 int errcode; 1149 1150 sfix_write(sfix, bytes); 1151 1152 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 1153 ptu_ptr(sfix->section); 1154 1155 errcode = pt_section_map(sfix->section); 1156 ptu_int_eq(errcode, 0); 1157 1158 errcode = pt_section_alloc_bcache(sfix->section); 1159 ptu_int_eq(errcode, 0); 1160 1161 errcode = pt_section_alloc_bcache(sfix->section); 1162 ptu_int_eq(errcode, 0); 1163 1164 errcode = pt_section_unmap(sfix->section); 1165 ptu_int_eq(errcode, 0); 1166 1167 return ptu_passed(); 1168 } 1169 1170 static struct ptunit_result bcache_alloc_nomap(struct section_fixture *sfix) 1171 { 1172 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 1173 int errcode; 1174 1175 sfix_write(sfix, bytes); 1176 1177 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 1178 ptu_ptr(sfix->section); 1179 1180 errcode = pt_section_alloc_bcache(sfix->section); 1181 ptu_int_eq(errcode, -pte_internal); 1182 1183 return ptu_passed(); 1184 } 1185 1186 static struct ptunit_result memsize_nomap(struct section_fixture *sfix) 1187 { 1188 uint64_t memsize; 1189 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 1190 int errcode; 1191 1192 sfix_write(sfix, bytes); 1193 1194 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 1195 ptu_ptr(sfix->section); 1196 1197 errcode = pt_section_memsize(sfix->section, &memsize); 1198 ptu_int_eq(errcode, 0); 1199 ptu_uint_eq(memsize, 0ull); 1200 1201 return ptu_passed(); 1202 } 1203 1204 static struct ptunit_result memsize_unmap(struct section_fixture *sfix) 1205 { 1206 uint64_t memsize; 1207 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 1208 int errcode; 1209 1210 sfix_write(sfix, bytes); 1211 1212 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 1213 ptu_ptr(sfix->section); 1214 1215 errcode = pt_section_map(sfix->section); 1216 ptu_int_eq(errcode, 0); 1217 1218 errcode = pt_section_unmap(sfix->section); 1219 ptu_int_eq(errcode, 0); 1220 1221 errcode = pt_section_memsize(sfix->section, &memsize); 1222 ptu_int_eq(errcode, 0); 1223 ptu_uint_eq(memsize, 0ull); 1224 1225 return ptu_passed(); 1226 } 1227 1228 static struct ptunit_result memsize_map_nobcache(struct section_fixture *sfix) 1229 { 1230 uint64_t memsize; 1231 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 1232 int errcode; 1233 1234 sfix_write(sfix, bytes); 1235 1236 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 1237 ptu_ptr(sfix->section); 1238 1239 errcode = pt_section_map(sfix->section); 1240 ptu_int_eq(errcode, 0); 1241 1242 memsize = 0xfefefefefefefefeull; 1243 1244 errcode = pt_section_memsize(sfix->section, &memsize); 1245 ptu_int_eq(errcode, 0); 1246 ptu_uint_ge(memsize, 0ull); 1247 ptu_uint_le(memsize, 0x2000ull); 1248 1249 errcode = pt_section_unmap(sfix->section); 1250 ptu_int_eq(errcode, 0); 1251 1252 return ptu_passed(); 1253 } 1254 1255 static struct ptunit_result memsize_map_bcache(struct section_fixture *sfix) 1256 { 1257 uint64_t memsize; 1258 uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; 1259 int errcode; 1260 1261 sfix_write(sfix, bytes); 1262 1263 sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); 1264 ptu_ptr(sfix->section); 1265 1266 errcode = pt_section_map(sfix->section); 1267 ptu_int_eq(errcode, 0); 1268 1269 errcode = pt_section_alloc_bcache(sfix->section); 1270 ptu_int_eq(errcode, 0); 1271 1272 errcode = pt_section_memsize(sfix->section, &memsize); 1273 ptu_int_eq(errcode, 0); 1274 ptu_uint_ge(memsize, 1275 sfix->section->size * sizeof(struct pt_bcache_entry)); 1276 1277 errcode = pt_section_unmap(sfix->section); 1278 ptu_int_eq(errcode, 0); 1279 1280 return ptu_passed(); 1281 } 1282 1283 static struct ptunit_result sfix_init(struct section_fixture *sfix) 1284 { 1285 int errcode; 1286 1287 sfix->section = NULL; 1288 sfix->file = NULL; 1289 sfix->name = NULL; 1290 1291 errcode = ptunit_mkfile(&sfix->file, &sfix->name, "wb"); 1292 ptu_int_eq(errcode, 0); 1293 1294 ptu_test(ptunit_thrd_init, &sfix->thrd); 1295 1296 return ptu_passed(); 1297 } 1298 1299 static struct ptunit_result sfix_fini(struct section_fixture *sfix) 1300 { 1301 int thrd; 1302 1303 ptu_test(ptunit_thrd_fini, &sfix->thrd); 1304 1305 for (thrd = 0; thrd < sfix->thrd.nthreads; ++thrd) 1306 ptu_int_eq(sfix->thrd.result[thrd], 0); 1307 1308 if (sfix->section) { 1309 pt_section_put(sfix->section); 1310 sfix->section = NULL; 1311 } 1312 1313 if (sfix->file) { 1314 fclose(sfix->file); 1315 sfix->file = NULL; 1316 1317 if (sfix->name) 1318 remove(sfix->name); 1319 } 1320 1321 if (sfix->name) { 1322 free(sfix->name); 1323 sfix->name = NULL; 1324 } 1325 1326 return ptu_passed(); 1327 } 1328 1329 int main(int argc, char **argv) 1330 { 1331 struct section_fixture sfix; 1332 struct ptunit_suite suite; 1333 1334 sfix.init = sfix_init; 1335 sfix.fini = sfix_fini; 1336 1337 suite = ptunit_mk_suite(argc, argv); 1338 1339 ptu_run_f(suite, create, sfix); 1340 ptu_run_f(suite, create_bad_offset, sfix); 1341 ptu_run_f(suite, create_truncated, sfix); 1342 ptu_run_f(suite, create_empty, sfix); 1343 1344 ptu_run(suite, filename_null); 1345 ptu_run(suite, offset_null); 1346 ptu_run(suite, size_null); 1347 ptu_run(suite, get_null); 1348 ptu_run(suite, put_null); 1349 ptu_run(suite, attach_null); 1350 ptu_run(suite, detach_null); 1351 ptu_run(suite, map_null); 1352 ptu_run(suite, unmap_null); 1353 ptu_run(suite, cache_null); 1354 1355 ptu_run_f(suite, get_overflow, sfix); 1356 ptu_run_f(suite, attach_overflow, sfix); 1357 ptu_run_f(suite, attach_bad_ucount, sfix); 1358 ptu_run_f(suite, map_change, sfix); 1359 ptu_run_f(suite, map_put, sfix); 1360 ptu_run_f(suite, unmap_nomap, sfix); 1361 ptu_run_f(suite, map_overflow, sfix); 1362 ptu_run_f(suite, get_put, sfix); 1363 ptu_run_f(suite, attach_detach, sfix); 1364 ptu_run_f(suite, attach_bad_iscache, sfix); 1365 ptu_run_f(suite, detach_bad_iscache, sfix); 1366 ptu_run_f(suite, map_unmap, sfix); 1367 ptu_run_f(suite, attach_map, sfix); 1368 ptu_run_f(suite, attach_bad_map, sfix); 1369 ptu_run_f(suite, attach_map_overflow, sfix); 1370 ptu_run_f(suite, read, sfix); 1371 ptu_run_f(suite, read_null, sfix); 1372 ptu_run_f(suite, read_offset, sfix); 1373 ptu_run_f(suite, read_truncated, sfix); 1374 ptu_run_f(suite, read_from_truncated, sfix); 1375 ptu_run_f(suite, read_nomem, sfix); 1376 ptu_run_f(suite, read_overflow, sfix); 1377 ptu_run_f(suite, read_overflow_32bit, sfix); 1378 ptu_run_f(suite, read_nomap, sfix); 1379 ptu_run_f(suite, read_unmap_map, sfix); 1380 1381 ptu_run_f(suite, init_no_bcache, sfix); 1382 ptu_run_f(suite, bcache_alloc_free, sfix); 1383 ptu_run_f(suite, bcache_alloc_twice, sfix); 1384 ptu_run_f(suite, bcache_alloc_nomap, sfix); 1385 1386 ptu_run_f(suite, memsize_null, sfix); 1387 ptu_run_f(suite, memsize_nomap, sfix); 1388 ptu_run_f(suite, memsize_unmap, sfix); 1389 ptu_run_f(suite, memsize_map_nobcache, sfix); 1390 ptu_run_f(suite, memsize_map_bcache, sfix); 1391 1392 ptu_run_fp(suite, stress, sfix, worker_bcache); 1393 ptu_run_fp(suite, stress, sfix, worker_read); 1394 1395 return ptunit_report(&suite); 1396 } 1397