Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 | /* * Copyright (c) 2015 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ /* * * THE KCDATA MANIFESTO * * Kcdata is a self-describing data serialization format. It is meant to get * nested data structures out of xnu with minimum fuss, but also for that data * to be easy to parse. It is also meant to allow us to add new fields and * evolve the data format without breaking old parsers. * * Kcdata is a permanent data format suitable for long-term storage including * in files. It is very important that we continue to be able to parse old * versions of kcdata-based formats. To this end, there are several * invariants you MUST MAINTAIN if you alter this file. * * * None of the magic numbers should ever be a byteswap of themselves or * of any of the other magic numbers. * * * Never remove any type. * * * All kcdata structs must be packed, and must exclusively use fixed-size * types. * * * Never change the definition of any type, except to add new fields to * the end. * * * If you do add new fields to the end of a type, do not actually change * the definition of the old structure. Instead, define a new structure * with the new fields. See thread_snapshot_v3 as an example. This * provides source compatibility for old readers, and also documents where * the potential size cutoffs are. * * * If you change libkdd, or kcdata.py run the unit tests under libkdd. * * * If you add a type or extend an existing one, add a sample test to * libkdd/tests so future changes to libkdd will always parse your struct * correctly. * * For example to add a field to this: * * struct foobar { * uint32_t baz; * uint32_t quux; * } __attribute__ ((packed)); * * Define an evolved structure alongside it like this: * * struct foobar_v2 { * uint32_t baz; * uint32_t quux; * ///////// This is where the original structure's layout ended! sizeof(struct foobar) was 8 //////// * uint32_t frozzle; * } __attribute__ ((packed)); * * If you are parsing kcdata formats, you MUST * * * Check the length field of each struct, including array elements. If the * struct is longer than you expect, you must ignore the extra data. * * * Ignore any data types you do not understand. * * Additionally, we want to be as forward compatible as we can. Meaning old * tools should still be able to use new data whenever possible. To this end, * you should: * * * Try not to add new versions of types that supplant old ones. Instead * extend the length of existing types or add supplemental types. * * * Try not to remove information from existing kcdata formats, unless * removal was explicitly asked for. For example it is fine to add a * stackshot flag to remove unwanted information, but you should not * remove it from the default stackshot if the new flag is absent. * * * (TBD) If you do break old readers by removing information or * supplanting old structs, then increase the major version number. * * * * The following is a description of the kcdata format. * * * The format for data is setup in a generic format as follows * * Layout of data structure: * * | 8 - bytes | * | type = MAGIC | LENGTH | * | 0 | * | type | size | * | flags | * | data | * |___________data____________| * | type | size | * | flags | * |___________data____________| * | type = END | size=0 | * | 0 | * * * The type field describes what kind of data is passed. For example type = TASK_CRASHINFO_UUID means the following data is a uuid. * These types need to be defined in task_corpse.h for easy consumption by userspace inspection tools. * * Some range of types is reserved for special types like ints, longs etc. A cool new functionality made possible with this * extensible data format is that kernel can decide to put more information as required without requiring user space tools to * re-compile to be compatible. The case of rusage struct versions could be introduced without breaking existing tools. * * Feature description: Generic data with description * ------------------- * Further more generic data with description is very much possible now. For example * * - kcdata_add_uint64_with_description(cdatainfo, 0x700, "NUM MACH PORTS"); * - and more functions that allow adding description. * The userspace tools can then look at the description and print the data even if they are not compiled with knowledge of the field apriori. * * Example data: * 0000 57 f1 ad de 00 00 00 00 00 00 00 00 00 00 00 00 W............... * 0010 01 00 00 00 00 00 00 00 30 00 00 00 00 00 00 00 ........0....... * 0020 50 49 44 00 00 00 00 00 00 00 00 00 00 00 00 00 PID............. * 0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ * 0040 9c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ * 0050 01 00 00 00 00 00 00 00 30 00 00 00 00 00 00 00 ........0....... * 0060 50 41 52 45 4e 54 20 50 49 44 00 00 00 00 00 00 PARENT PID...... * 0070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ * 0080 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ * 0090 ed 58 91 f1 * * Feature description: Container markers for compound data * ------------------ * If a given kernel data type is complex and requires adding multiple optional fields inside a container * object for a consumer to understand arbitrary data, we package it using container markers. * * For example, the stackshot code gathers information and describes the state of a given task with respect * to many subsystems. It includes data such as io stats, vm counters, process names/flags and syscall counts. * * kcdata_add_container_marker(kcdata_p, KCDATA_TYPE_CONTAINER_BEGIN, STACKSHOT_KCCONTAINER_TASK, task_uniqueid); * // add multiple data, or add_<type>_with_description()s here * * kcdata_add_container_marker(kcdata_p, KCDATA_TYPE_CONTAINER_END, STACKSHOT_KCCONTAINER_TASK, task_uniqueid); * * Feature description: Custom Data formats on demand * -------------------- * With the self describing nature of format, the kernel provider can describe a data type (uniquely identified by a number) and use * it in the buffer for sending data. The consumer can parse the type information and have knowledge of describing incoming data. * Following is an example of how we can describe a kernel specific struct sample_disk_io_stats in buffer. * * struct sample_disk_io_stats { * uint64_t disk_reads_count; * uint64_t disk_reads_size; * uint64_t io_priority_count[4]; * uint64_t io_priority_size; * } __attribute__ ((packed)); * * * struct kcdata_subtype_descriptor disk_io_stats_def[] = { * {KCS_SUBTYPE_FLAGS_NONE, KC_ST_UINT64, 0 * sizeof(uint64_t), sizeof(uint64_t), "disk_reads_count"}, * {KCS_SUBTYPE_FLAGS_NONE, KC_ST_UINT64, 1 * sizeof(uint64_t), sizeof(uint64_t), "disk_reads_size"}, * {KCS_SUBTYPE_FLAGS_ARRAY, KC_ST_UINT64, 2 * sizeof(uint64_t), KCS_SUBTYPE_PACK_SIZE(4, sizeof(uint64_t)), "io_priority_count"}, * {KCS_SUBTYPE_FLAGS_ARRAY, KC_ST_UINT64, (2 + 4) * sizeof(uint64_t), sizeof(uint64_t), "io_priority_size"}, * }; * * Now you can add this custom type definition into the buffer as * kcdata_add_type_definition(kcdata_p, KCTYPE_SAMPLE_DISK_IO_STATS, "sample_disk_io_stats", * &disk_io_stats_def[0], sizeof(disk_io_stats_def)/sizeof(struct kcdata_subtype_descriptor)); * * Feature description: Compression * -------------------- * In order to avoid keeping large amounts of memory reserved for a panic stackshot, kcdata has support * for compressing the buffer in a streaming fashion. New data pushed to the kcdata buffer will be * automatically compressed using an algorithm selected by the API user (currently, we only support * pass-through and zlib, in the future we plan to add WKDM support, see: 57913859). * * To start using compression, call: * kcdata_init_compress(kcdata_p, hdr_tag, memcpy_f, comp_type); * where: * `kcdata_p` is the kcdata buffer that will be used * `hdr_tag` is the usual header tag denoting what type of kcdata buffer this will be * `memcpy_f` a memcpy(3) function to use to copy into the buffer, optional. * `compy_type` is the compression type, see KCDCT_ZLIB for an example. * * Once compression is initialized: * (1) all self-describing APIs will automatically compress * (2) you can now use the following APIs to compress data into the buffer: * (None of the following will compress unless kcdata_init_compress() has been called) * * - kcdata_push_data(kcdata_descriptor_t data, uint32_t type, uint32_t size, const void *input_data) * Pushes the buffer of kctype @type at[@input_data, @input_data + @size] * into the kcdata buffer @data, compressing if needed. * * - kcdata_push_array(kcdata_descriptor_t data, uint32_t type_of_element, * uint32_t size_of_element, uint32_t count, const void *input_data) * Pushes the array found at @input_data, with element type @type_of_element, where * each element is of size @size_of_element and there are @count elements into the kcdata buffer * at @data. * * - kcdata_compression_window_open/close(kcdata_descriptor_t data) * In case the data you are trying to push to the kcdata buffer @data is difficult to predict, * you can open a "compression window". Between an open and a close, no compression will be done. * Once you close the window, the underlying compression algorithm will compress the data into the buffer * and automatically rewind the current end marker of the kcdata buffer. * There is an ASCII art in kern_cdata.c to aid the reader in understanding * this. * * - kcdata_finish_compression(kcdata_descriptor_t data) * Must be called at the end to flush any underlying buffers used by the compression algorithms. * This function will also add some statistics about the compression to the buffer which helps with * decompressing later. * */ #ifndef _KCDATA_H_ #define _KCDATA_H_ #include <stdint.h> #include <string.h> #include <uuid/uuid.h> #define KCDATA_DESC_MAXLEN 32 /* including NULL byte at end */ #define KCDATA_FLAGS_STRUCT_PADDING_MASK 0xf #define KCDATA_FLAGS_STRUCT_HAS_PADDING 0x80 /* * kcdata aligns elements to 16 byte boundaries. */ #define KCDATA_ALIGNMENT_SIZE 0x10 struct kcdata_item { uint32_t type; uint32_t size; /* len(data) */ /* flags. * * For structures: * padding = flags & 0xf * has_padding = (flags & 0x80) >> 7 * * has_padding is needed to disambiguate cases such as * thread_snapshot_v2 and thread_snapshot_v3. Their * respective sizes are 0x68 and 0x70, and thread_snapshot_v2 * was emitted by old kernels *before* we started recording * padding. Since legacy thread_snapsht_v2 and modern * thread_snapshot_v3 will both record 0 for the padding * flags, we need some other bit which will be nonzero in the * flags to disambiguate. * * This is why we hardcode a special case for * STACKSHOT_KCTYPE_THREAD_SNAPSHOT into the iterator * functions below. There is only a finite number of such * hardcodings which will ever be needed. They can occur * when: * * * We have a legacy structure that predates padding flags * * * which we want to extend without changing the kcdata type * * * by only so many bytes as would fit in the space that * was previously unused padding. * * For containers: * container_id = flags * * For arrays: * element_count = flags & UINT32_MAX * element_type = (flags >> 32) & UINT32_MAX */ uint64_t flags; char data[]; /* must be at the end */ }; typedef struct kcdata_item * kcdata_item_t; enum KCDATA_SUBTYPE_TYPES { KC_ST_CHAR = 1, KC_ST_INT8, KC_ST_UINT8, KC_ST_INT16, KC_ST_UINT16, KC_ST_INT32, KC_ST_UINT32, KC_ST_INT64, KC_ST_UINT64 }; typedef enum KCDATA_SUBTYPE_TYPES kctype_subtype_t; /* * A subtype description structure that defines * how a compound data is laid out in memory. This * provides on the fly definition of types and consumption * by the parser. */ struct kcdata_subtype_descriptor { uint8_t kcs_flags; #define KCS_SUBTYPE_FLAGS_NONE 0x0 #define KCS_SUBTYPE_FLAGS_ARRAY 0x1 /* Force struct type even if only one element. * * Normally a kcdata_type_definition is treated as a structure if it has * more than one subtype descriptor. Otherwise it is treated as a simple * type. For example libkdd will represent a simple integer 42 as simply * 42, but it will represent a structure containing an integer 42 as * {"field_name": 42}.. * * If a kcdata_type_definition has only single subtype, then it will be * treated as a structure iff KCS_SUBTYPE_FLAGS_STRUCT is set. If it has * multiple subtypes, it will always be treated as a structure. * * KCS_SUBTYPE_FLAGS_MERGE has the opposite effect. If this flag is used then * even if there are multiple elements, they will all be treated as individual * properties of the parent dictionary. */ #define KCS_SUBTYPE_FLAGS_STRUCT 0x2 /* force struct type even if only one element */ #define KCS_SUBTYPE_FLAGS_MERGE 0x4 /* treat as multiple elements of parents instead of struct */ uint8_t kcs_elem_type; /* restricted to kctype_subtype_t */ uint16_t kcs_elem_offset; /* offset in struct where data is found */ uint32_t kcs_elem_size; /* size of element (or) packed state for array type */ char kcs_name[KCDATA_DESC_MAXLEN]; /* max 31 bytes for name of field */ }; typedef struct kcdata_subtype_descriptor * kcdata_subtype_descriptor_t; /* * In case of array of basic c types in kctype_subtype_t, * size is packed in lower 16 bits and * count is packed in upper 16 bits of kcs_elem_size field. */ #define KCS_SUBTYPE_PACK_SIZE(e_count, e_size) (((e_count)&0xffffu) << 16 | ((e_size)&0xffffu)) static inline uint32_t kcs_get_elem_size(kcdata_subtype_descriptor_t d) { if (d->kcs_flags & KCS_SUBTYPE_FLAGS_ARRAY) { /* size is composed as ((count &0xffff)<<16 | (elem_size & 0xffff)) */ return (uint32_t)((d->kcs_elem_size & 0xffff) * ((d->kcs_elem_size & 0xffff0000) >> 16)); } return d->kcs_elem_size; } static inline uint32_t kcs_get_elem_count(kcdata_subtype_descriptor_t d) { if (d->kcs_flags & KCS_SUBTYPE_FLAGS_ARRAY) { return (d->kcs_elem_size >> 16) & 0xffff; } return 1; } static inline int kcs_set_elem_size(kcdata_subtype_descriptor_t d, uint32_t size, uint32_t count) { if (count > 1) { /* means we are setting up an array */ if (size > 0xffff || count > 0xffff) { return -1; //invalid argument } d->kcs_elem_size = ((count & 0xffff) << 16 | (size & 0xffff)); } else { d->kcs_elem_size = size; } return 0; } struct kcdata_type_definition { uint32_t kct_type_identifier; uint32_t kct_num_elements; char kct_name[KCDATA_DESC_MAXLEN]; struct kcdata_subtype_descriptor kct_elements[]; }; /* chunk type definitions. 0 - 0x7ff are reserved and defined here * NOTE: Please update kcdata/libkdd/kcdtypes.c if you make any changes * in STACKSHOT_KCTYPE_* types. */ /* * Types with description value. * these will have KCDATA_DESC_MAXLEN-1 length string description * and rest of kcdata_iter_size() - KCDATA_DESC_MAXLEN bytes as data */ #define KCDATA_TYPE_INVALID 0x0u #define KCDATA_TYPE_STRING_DESC 0x1u #define KCDATA_TYPE_UINT32_DESC 0x2u #define KCDATA_TYPE_UINT64_DESC 0x3u #define KCDATA_TYPE_INT32_DESC 0x4u #define KCDATA_TYPE_INT64_DESC 0x5u #define KCDATA_TYPE_BINDATA_DESC 0x6u /* * Compound type definitions */ #define KCDATA_TYPE_ARRAY 0x11u /* Array of data OBSOLETE DONT USE THIS*/ #define KCDATA_TYPE_TYPEDEFINTION 0x12u /* Meta type that describes a type on the fly. */ #define KCDATA_TYPE_CONTAINER_BEGIN \ 0x13u /* Container type which has corresponding CONTAINER_END header. \ * KCDATA_TYPE_CONTAINER_BEGIN has type in the data segment. \ * Both headers have (uint64_t) ID for matching up nested data. \ */ #define KCDATA_TYPE_CONTAINER_END 0x14u #define KCDATA_TYPE_ARRAY_PAD0 0x20u /* Array of data with 0 byte of padding*/ #define KCDATA_TYPE_ARRAY_PAD1 0x21u /* Array of data with 1 byte of padding*/ #define KCDATA_TYPE_ARRAY_PAD2 0x22u /* Array of data with 2 byte of padding*/ #define KCDATA_TYPE_ARRAY_PAD3 0x23u /* Array of data with 3 byte of padding*/ #define KCDATA_TYPE_ARRAY_PAD4 0x24u /* Array of data with 4 byte of padding*/ #define KCDATA_TYPE_ARRAY_PAD5 0x25u /* Array of data with 5 byte of padding*/ #define KCDATA_TYPE_ARRAY_PAD6 0x26u /* Array of data with 6 byte of padding*/ #define KCDATA_TYPE_ARRAY_PAD7 0x27u /* Array of data with 7 byte of padding*/ #define KCDATA_TYPE_ARRAY_PAD8 0x28u /* Array of data with 8 byte of padding*/ #define KCDATA_TYPE_ARRAY_PAD9 0x29u /* Array of data with 9 byte of padding*/ #define KCDATA_TYPE_ARRAY_PADa 0x2au /* Array of data with a byte of padding*/ #define KCDATA_TYPE_ARRAY_PADb 0x2bu /* Array of data with b byte of padding*/ #define KCDATA_TYPE_ARRAY_PADc 0x2cu /* Array of data with c byte of padding*/ #define KCDATA_TYPE_ARRAY_PADd 0x2du /* Array of data with d byte of padding*/ #define KCDATA_TYPE_ARRAY_PADe 0x2eu /* Array of data with e byte of padding*/ #define KCDATA_TYPE_ARRAY_PADf 0x2fu /* Array of data with f byte of padding*/ /* * Generic data types that are most commonly used */ #define KCDATA_TYPE_LIBRARY_LOADINFO 0x30u /* struct dyld_uuid_info_32 */ #define KCDATA_TYPE_LIBRARY_LOADINFO64 0x31u /* struct dyld_uuid_info_64 */ #define KCDATA_TYPE_TIMEBASE 0x32u /* struct mach_timebase_info */ #define KCDATA_TYPE_MACH_ABSOLUTE_TIME 0x33u /* uint64_t */ #define KCDATA_TYPE_TIMEVAL 0x34u /* struct timeval64 */ #define KCDATA_TYPE_USECS_SINCE_EPOCH 0x35u /* time in usecs uint64_t */ #define KCDATA_TYPE_PID 0x36u /* int32_t */ #define KCDATA_TYPE_PROCNAME 0x37u /* char * */ #define KCDATA_TYPE_NESTED_KCDATA 0x38u /* nested kcdata buffer */ #define KCDATA_TYPE_LIBRARY_AOTINFO 0x39u /* struct user64_dyld_aot_info */ #define KCDATA_TYPE_BUFFER_END 0xF19158EDu /* MAGIC numbers defined for each class of chunked data * * To future-proof against big-endian arches, make sure none of these magic * numbers are byteswaps of each other */ #define KCDATA_BUFFER_BEGIN_CRASHINFO 0xDEADF157u /* owner: corpses/task_corpse.h */ /* type-range: 0x800 - 0x8ff */ #define KCDATA_BUFFER_BEGIN_STACKSHOT 0x59a25807u /* owner: sys/stackshot.h */ /* type-range: 0x900 - 0x93f */ #define KCDATA_BUFFER_BEGIN_COMPRESSED 0x434f4d50u /* owner: sys/stackshot.h */ /* type-range: 0x900 - 0x93f */ #define KCDATA_BUFFER_BEGIN_DELTA_STACKSHOT 0xDE17A59Au /* owner: sys/stackshot.h */ /* type-range: 0x940 - 0x9ff */ #define KCDATA_BUFFER_BEGIN_BTINFO 0x46414E47u /* owner: kern/kern_exit.c */ /* type-range: 0xa01 - 0xaff */ #define KCDATA_BUFFER_BEGIN_OS_REASON 0x53A20900u /* owner: sys/reason.h */ /* type-range: 0x1000-0x103f */ #define KCDATA_BUFFER_BEGIN_XNUPOST_CONFIG 0x1e21c09fu /* owner: osfmk/tests/kernel_tests.c */ /* type-range: 0x1040-0x105f */ /* next type range number available 0x1060 */ /**************** definitions for XNUPOST *********************/ #define XNUPOST_KCTYPE_TESTCONFIG 0x1040 /**************** definitions for stackshot *********************/ /* This value must always match IO_NUM_PRIORITIES defined in thread_info.h */ #define STACKSHOT_IO_NUM_PRIORITIES 4 /* This value must always match MAXTHREADNAMESIZE used in bsd */ #define STACKSHOT_MAX_THREAD_NAME_SIZE 64 /* * NOTE: Please update kcdata/libkdd/kcdtypes.c if you make any changes * in STACKSHOT_KCTYPE_* types. */ #define STACKSHOT_KCTYPE_IOSTATS 0x901u /* io_stats_snapshot */ #define STACKSHOT_KCTYPE_GLOBAL_MEM_STATS 0x902u /* struct mem_and_io_snapshot_v2 */ #define STACKSHOT_KCCONTAINER_TASK 0x903u #define STACKSHOT_KCCONTAINER_THREAD 0x904u #define STACKSHOT_KCTYPE_TASK_SNAPSHOT 0x905u /* task_snapshot_v2, task_snapshot_v3 */ #define STACKSHOT_KCTYPE_THREAD_SNAPSHOT 0x906u /* thread_snapshot_v2, thread_snapshot_v3 */ #define STACKSHOT_KCTYPE_DONATING_PIDS 0x907u /* int[] */ #define STACKSHOT_KCTYPE_SHAREDCACHE_LOADINFO 0x908u /* dyld_shared_cache_loadinfo */ #define STACKSHOT_KCTYPE_THREAD_NAME 0x909u /* char[] */ #define STACKSHOT_KCTYPE_KERN_STACKFRAME 0x90Au /* struct stack_snapshot_frame32 */ #define STACKSHOT_KCTYPE_KERN_STACKFRAME64 0x90Bu /* struct stack_snapshot_frame64 */ #define STACKSHOT_KCTYPE_USER_STACKFRAME 0x90Cu /* struct stack_snapshot_frame32 */ #define STACKSHOT_KCTYPE_USER_STACKFRAME64 0x90Du /* struct stack_snapshot_frame64 */ #define STACKSHOT_KCTYPE_BOOTARGS 0x90Eu /* boot args string */ #define STACKSHOT_KCTYPE_OSVERSION 0x90Fu /* os version string, same as running uname -a */ #define STACKSHOT_KCTYPE_KERN_PAGE_SIZE 0x910u /* kernel page size in uint32_t */ #define STACKSHOT_KCTYPE_JETSAM_LEVEL 0x911u /* jetsam level in uint32_t */ #define STACKSHOT_KCTYPE_DELTA_SINCE_TIMESTAMP 0x912u /* timestamp used for the delta stackshot */ #define STACKSHOT_KCTYPE_KERN_STACKLR 0x913u /* uint32_t */ #define STACKSHOT_KCTYPE_KERN_STACKLR64 0x914u /* uint64_t */ #define STACKSHOT_KCTYPE_USER_STACKLR 0x915u /* uint32_t */ #define STACKSHOT_KCTYPE_USER_STACKLR64 0x916u /* uint64_t */ #define STACKSHOT_KCTYPE_NONRUNNABLE_TIDS 0x917u /* uint64_t */ #define STACKSHOT_KCTYPE_NONRUNNABLE_TASKS 0x918u /* uint64_t */ #define STACKSHOT_KCTYPE_CPU_TIMES 0x919u /* struct stackshot_cpu_times or stackshot_cpu_times_v2 */ #define STACKSHOT_KCTYPE_STACKSHOT_DURATION 0x91au /* struct stackshot_duration */ #define STACKSHOT_KCTYPE_STACKSHOT_FAULT_STATS 0x91bu /* struct stackshot_fault_stats */ #define STACKSHOT_KCTYPE_KERNELCACHE_LOADINFO 0x91cu /* kernelcache UUID -- same as KCDATA_TYPE_LIBRARY_LOADINFO64 */ #define STACKSHOT_KCTYPE_THREAD_WAITINFO 0x91du /* struct stackshot_thread_waitinfo */ #define STACKSHOT_KCTYPE_THREAD_GROUP_SNAPSHOT 0x91eu /* struct thread_group_snapshot{,_v2,_v3} */ #define STACKSHOT_KCTYPE_THREAD_GROUP 0x91fu /* uint64_t */ #define STACKSHOT_KCTYPE_JETSAM_COALITION_SNAPSHOT 0x920u /* struct jetsam_coalition_snapshot */ #define STACKSHOT_KCTYPE_JETSAM_COALITION 0x921u /* uint64_t */ #define STACKSHOT_KCTYPE_THREAD_POLICY_VERSION 0x922u /* THREAD_POLICY_INTERNAL_STRUCT_VERSION in uint32 */ #define STACKSHOT_KCTYPE_INSTRS_CYCLES 0x923u /* struct instrs_cycles_snapshot_v2 */ #define STACKSHOT_KCTYPE_USER_STACKTOP 0x924u /* struct stack_snapshot_stacktop */ #define STACKSHOT_KCTYPE_ASID 0x925u /* uint32_t */ #define STACKSHOT_KCTYPE_PAGE_TABLES 0x926u /* uint64_t */ #define STACKSHOT_KCTYPE_SYS_SHAREDCACHE_LAYOUT 0x927u /* same as KCDATA_TYPE_LIBRARY_LOADINFO64 */ #define STACKSHOT_KCTYPE_THREAD_DISPATCH_QUEUE_LABEL 0x928u /* dispatch queue label */ #define STACKSHOT_KCTYPE_THREAD_TURNSTILEINFO 0x929u /* struct stackshot_thread_turnstileinfo */ #define STACKSHOT_KCTYPE_TASK_CPU_ARCHITECTURE 0x92au /* struct stackshot_cpu_architecture */ #define STACKSHOT_KCTYPE_LATENCY_INFO 0x92bu /* struct stackshot_latency_collection_v2 */ #define STACKSHOT_KCTYPE_LATENCY_INFO_TASK 0x92cu /* struct stackshot_latency_task */ #define STACKSHOT_KCTYPE_LATENCY_INFO_THREAD 0x92du /* struct stackshot_latency_thread */ #define STACKSHOT_KCTYPE_LOADINFO64_TEXT_EXEC 0x92eu /* TEXT_EXEC load info -- same as KCDATA_TYPE_LIBRARY_LOADINFO64 */ #define STACKSHOT_KCTYPE_AOTCACHE_LOADINFO 0x92fu /* struct dyld_aot_cache_uuid_info */ #define STACKSHOT_KCTYPE_TRANSITIONING_TASK_SNAPSHOT 0x930u /* transitioning_task_snapshot */ #define STACKSHOT_KCCONTAINER_TRANSITIONING_TASK 0x931u #define STACKSHOT_KCTYPE_USER_ASYNC_START_INDEX 0x932u /* uint32_t index in user_stack of beginning of async stack */ #define STACKSHOT_KCTYPE_USER_ASYNC_STACKLR64 0x933u /* uint64_t async stack pointers */ #define STACKSHOT_KCCONTAINER_PORTLABEL 0x934u /* container for port label info */ #define STACKSHOT_KCTYPE_PORTLABEL 0x935u /* struct stackshot_portlabel */ #define STACKSHOT_KCTYPE_PORTLABEL_NAME 0x936u /* string port name */ #define STACKSHOT_KCTYPE_DYLD_COMPACTINFO 0x937u /* binary blob of dyld info (variable size) */ #define STACKSHOT_KCTYPE_SUSPENSION_INFO 0x938u /* struct stackshot_suspension_info */ #define STACKSHOT_KCTYPE_SUSPENSION_SOURCE 0x939u /* struct stackshot_suspension_source */ #define STACKSHOT_KCTYPE_TASK_DELTA_SNAPSHOT 0x940u /* task_delta_snapshot_v2 */ #define STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT 0x941u /* thread_delta_snapshot_v* */ #define STACKSHOT_KCCONTAINER_SHAREDCACHE 0x942u /* container for shared cache info */ #define STACKSHOT_KCTYPE_SHAREDCACHE_INFO 0x943u /* dyld_shared_cache_loadinfo_v2 */ #define STACKSHOT_KCTYPE_SHAREDCACHE_AOTINFO 0x944u /* struct dyld_aot_cache_uuid_info */ #define STACKSHOT_KCTYPE_SHAREDCACHE_ID 0x945u /* uint32_t in task: if we aren't attached to Primary, which one */ #define STACKSHOT_KCTYPE_CODESIGNING_INFO 0x946u /* struct stackshot_task_codesigning_info */ #define STACKSHOT_KCTYPE_OS_BUILD_VERSION 0x947u /* os build version string (ex: 20A123) */ #define STACKSHOT_KCTYPE_KERN_EXCLAVES_THREADINFO 0x948u /* struct thread_exclaves_info */ #define STACKSHOT_KCCONTAINER_EXCLAVES 0x949u /* exclave threads info */ #define STACKSHOT_KCCONTAINER_EXCLAVE_SCRESULT 0x94au /* exclave thread container for one scid */ #define STACKSHOT_KCTYPE_EXCLAVE_SCRESULT_INFO 0x94bu /* struct exclave_scresult_info */ #define STACKSHOT_KCCONTAINER_EXCLAVE_IPCSTACKENTRY 0x94cu /* container for one chunk of exclave IPC chain */ #define STACKSHOT_KCTYPE_EXCLAVE_IPCSTACKENTRY_INFO 0x94du /* struct exclave_ipcstackentry_info */ #define STACKSHOT_KCTYPE_EXCLAVE_IPCSTACKENTRY_ECSTACK 0x94eu /* exclave_ecstackentry_addr_t */ #define STACKSHOT_KCCONTAINER_EXCLAVE_ADDRESSSPACE 0x94fu /* exclave address space container */ #define STACKSHOT_KCTYPE_EXCLAVE_ADDRESSSPACE_INFO 0x950u /* struct exclave_addressspace_info */ #define STACKSHOT_KCTYPE_EXCLAVE_ADDRESSSPACE_NAME 0x951u /* exclave component name */ #define STACKSHOT_KCCONTAINER_EXCLAVE_TEXTLAYOUT 0x952u /* exclave text layout container */ #define STACKSHOT_KCTYPE_EXCLAVE_TEXTLAYOUT_INFO 0x953u /* struct exclave_textlayout_info */ #define STACKSHOT_KCTYPE_EXCLAVE_TEXTLAYOUT_SEGMENTS 0x954u /* struct exclave_textlayout_segment_v2 */ #define STACKSHOT_KCTYPE_KERN_EXCLAVES_CRASH_THREADINFO 0x955u /* struct thread_crash_exclaves_info */ #define STACKSHOT_KCTYPE_LATENCY_INFO_CPU 0x956u /* struct stackshot_latency_cpu */ #define STACKSHOT_KCTYPE_TASK_EXEC_META 0x957u /* struct task_exec_meta */ #define STACKSHOT_KCTYPE_TASK_MEMORYSTATUS 0x958u /* struct task_memorystatus_snapshot */ #define STACKSHOT_KCTYPE_MTEINFO_CELL 0x959u /* struct mteinfo_cell */ #define STACKSHOT_KCTYPE_LATENCY_INFO_BUFFER 0x95au /* struct stackshot_latency_buffer */ #define STACKSHOT_KCTYPE_VMRL_BLOCKING_RELS 0x95bu /* struct stackshot_vmrl_blocking_relationship */ #define STACKSHOT_KCTYPE_LOCK_STATE 0x95cu /* struct stackshot_device_lock_state */ struct stack_snapshot_frame32 { uint32_t lr; uint32_t sp; }; struct stack_snapshot_frame64 { uint64_t lr; uint64_t sp; }; struct dyld_uuid_info_32 { uint32_t imageLoadAddress; /* base address image is mapped at */ uuid_t imageUUID; }; struct dyld_uuid_info_64 { uint64_t imageLoadAddress; /* XXX image slide */ uuid_t imageUUID; }; /* * N.B.: Newer kernels output dyld_shared_cache_loadinfo structures * instead of this, since the field names match their contents better. */ struct dyld_uuid_info_64_v2 { uint64_t imageLoadAddress; /* XXX image slide */ uuid_t imageUUID; /* end of version 1 of dyld_uuid_info_64. sizeof v1 was 24 */ uint64_t imageSlidBaseAddress; /* slid base address or slid first mapping of image */ }; enum dyld_shared_cache_flags { kSharedCacheSystemPrimary = 0x1, /* primary shared cache on the system; attached tasks will have kTaskSharedRegionSystem set */ kSharedCacheDriverkit = 0x2, /* driverkit shared cache */ kSharedCacheAOT = 0x4, /* Rosetta shared cache */ }; /* * This is the renamed version of dyld_uuid_info_64 with more accurate * field names, for STACKSHOT_KCTYPE_SHAREDCACHE_LOADINFO. Any users * must be aware of the dyld_uuid_info_64* version history and ensure * the fields they are accessing are within the actual bounds. * * OLD_FIELD NEW_FIELD * imageLoadAddress sharedCacheSlide * imageUUID sharedCacheUUID * imageSlidBaseAddress sharedCacheUnreliableSlidBaseAddress * - sharedCacheSlidFirstMapping * - sharedCacheID * - sharedCacheFlags */ struct dyld_shared_cache_loadinfo_v2 { uint64_t sharedCacheSlide; /* image slide value */ uuid_t sharedCacheUUID; /* end of version 1 of dyld_uuid_info_64. sizeof v1 was 24 */ uint64_t sharedCacheUnreliableSlidBaseAddress; /* for backwards-compatibility; use sharedCacheSlidFirstMapping if available */ /* end of version 2 of dyld_uuid_info_64. sizeof v2 was 32 */ uint64_t sharedCacheSlidFirstMapping; /* slid base address of first mapping */ /* end of version 1 of dyld_shared_cache_loadinfo. sizeof was 40 */ uint32_t sharedCacheID; /* ID of shared cache */ uint32_t sharedCacheFlags; }; struct dyld_shared_cache_loadinfo { uint64_t sharedCacheSlide; /* image slide value */ uuid_t sharedCacheUUID; /* end of version 1 of dyld_uuid_info_64. sizeof v1 was 24 */ uint64_t sharedCacheUnreliableSlidBaseAddress; /* for backwards-compatibility; use sharedCacheSlidFirstMapping if available */ /* end of version 2 of dyld_uuid_info_64. sizeof v2 was 32 */ uint64_t sharedCacheSlidFirstMapping; /* slid base address of first mapping */ }; struct dyld_aot_cache_uuid_info { uint64_t x86SlidBaseAddress; /* slid first mapping address of x86 shared cache */ uuid_t x86UUID; /* UUID of x86 shared cache */ uint64_t aotSlidBaseAddress; /* slide first mapping address of aot cache */ uuid_t aotUUID; /* UUID of aot shared cache */ }; struct user32_dyld_uuid_info { uint32_t imageLoadAddress; /* base address image is mapped into */ uuid_t imageUUID; /* UUID of image */ }; struct user64_dyld_uuid_info { uint64_t imageLoadAddress; /* base address image is mapped into */ uuid_t imageUUID; /* UUID of image */ }; #define DYLD_AOT_IMAGE_KEY_SIZE 32 struct user64_dyld_aot_info { uint64_t x86LoadAddress; uint64_t aotLoadAddress; uint64_t aotImageSize; uint8_t aotImageKey[DYLD_AOT_IMAGE_KEY_SIZE]; }; enum task_snapshot_flags { /* k{User,Kernel}64_p (values 0x1 and 0x2) are defined in generic_snapshot_flags */ kTaskRsrcFlagged = 0x4, // In the EXC_RESOURCE danger zone? kTerminatedSnapshot = 0x8, kPidSuspended = 0x10, // true for suspended task kFrozen = 0x20, // true for hibernated task (along with pidsuspended) kTaskDarwinBG = 0x40, kTaskExtDarwinBG = 0x80, kTaskVisVisible = 0x100, kTaskVisNonvisible = 0x200, kTaskIsForeground = 0x400, kTaskIsBoosted = 0x800, kTaskIsSuppressed = 0x1000, kTaskIsTimerThrottled = 0x2000, /* deprecated */ kTaskIsImpDonor = 0x4000, kTaskIsLiveImpDonor = 0x8000, kTaskIsDirty = 0x10000, kTaskWqExceededConstrainedThreadLimit = 0x20000, kTaskWqExceededTotalThreadLimit = 0x40000, kTaskWqFlagsAvailable = 0x80000, kTaskUUIDInfoFaultedIn = 0x100000, /* successfully faulted in some UUID info */ kTaskUUIDInfoMissing = 0x200000, /* some UUID info was paged out */ kTaskUUIDInfoTriedFault = 0x400000, /* tried to fault in UUID info */ kTaskSharedRegionInfoUnavailable = 0x800000, /* shared region info unavailable */ kTaskTALEngaged = 0x1000000, /* 0x2000000 unused */ kTaskIsDirtyTracked = 0x4000000, kTaskAllowIdleExit = 0x8000000, kTaskIsTranslated = 0x10000000, kTaskSharedRegionNone = 0x20000000, /* task doesn't have a shared region */ kTaskSharedRegionSystem = 0x40000000, /* task attached to region with kSharedCacheSystemPrimary set */ kTaskSharedRegionOther = 0x80000000, /* task is attached to a different shared region */ kTaskDyldCompactInfoNone = 0x100000000, kTaskDyldCompactInfoTooBig = 0x200000000, kTaskDyldCompactInfoFaultedIn = 0x400000000, kTaskDyldCompactInfoMissing = 0x800000000, kTaskDyldCompactInfoTriedFault = 0x1000000000, kTaskWqExceededCooperativeThreadLimit = 0x2000000000, kTaskWqExceededActiveConstrainedThreadLimit = 0x4000000000, kTaskRunawayMitigation = 0x8000000000, kTaskIsActive = 0x10000000000, kTaskIsManaged = 0x20000000000, kTaskHasAssertion = 0x40000000000, }; // Note: Add any new flags to kcdata.py (ts_ss_flags) enum task_transition_type { kTaskIsTerminated = 0x1,// Past LPEXIT }; /* See kcdata_private.h for more flag definitions */ enum task_exec_flags : uint64_t { kTaskExecTranslated = 0x01, /* Task is running under translation (eg, Rosetta) */ kTaskExecHardenedHeap = 0x02, /* Task has the hardened heap security feature */ kTaskExecReserved00 = 0x04, kTaskExecReserved01 = 0x08, kTaskExecReserved02 = 0x10, kTaskExecReserved03 = 0x20 }; /* metadata about a task that is fixed at spawn/exec time */ struct task_exec_meta { uint64_t tem_flags; /* task_exec_flags */ } __attribute__((packed)); /* MTE info cell state, must match mte_cell_state_t */ __enum_closed_decl(mte_info_cell_state_t, uint8_t, { MTE_INFO_STATE_DISABLED, MTE_INFO_STATE_PINNED, MTE_INFO_STATE_DEACTIVATING, MTE_INFO_STATE_CLAIMED, MTE_INFO_STATE_INACTIVE, MTE_INFO_STATE_RECLAIMING, MTE_INFO_STATE_ACTIVATING, MTE_INFO_STATE_ACTIVE, }); /* MTE info cell data */ struct mte_info_cell { uint8_t mic_state; uint8_t mic_tagged_count; /* Number of tagged pages in this tag storage page */ uint8_t mic_free_count; /* Number of free pages in this tag storage page */ uint8_t mic_wired_count; /* Number of wired pages in this tag storage page, regardless of tagging */ uint8_t mic_wired_tagged_count; /* Number of tagged pages wired that aren't used by kernel memory allocators */ uint8_t mic_kernel_wired_tagged_count; /* Number of tagged pages wired for use by the kernel memory allocators, kmem and zalloc */ } __attribute__((packed)); enum thread_snapshot_flags { /* k{User,Kernel}64_p (values 0x1 and 0x2) are defined in generic_snapshot_flags */ kHasDispatchSerial = 0x4, kStacksPCOnly = 0x8, /* Stack traces have no frame pointers. */ kThreadDarwinBG = 0x10, /* Thread is darwinbg */ kThreadIOPassive = 0x20, /* Thread uses passive IO */ kThreadSuspended = 0x40, /* Thread is suspended */ kThreadTruncatedBT = 0x80, /* Unmapped pages caused truncated backtrace */ kGlobalForcedIdle = 0x100, /* Thread performs global forced idle */ kThreadFaultedBT = 0x200, /* Some thread stack pages were faulted in as part of BT */ kThreadTriedFaultBT = 0x400, /* We tried to fault in thread stack pages as part of BT */ kThreadOnCore = 0x800, /* Thread was on-core when we entered debugger context */ kThreadIdleWorker = 0x1000, /* Thread is an idle libpthread worker thread */ kThreadMain = 0x2000, /* Thread is the main thread */ kThreadTruncKernBT = 0x4000, /* Unmapped pages caused truncated kernel BT */ kThreadTruncUserBT = 0x8000, /* Unmapped pages caused truncated user BT */ kThreadTruncUserAsyncBT = 0x10000, /* Unmapped pages caused truncated user async BT */ }; // Note: Add any new flags to kcdata.py (ths_ss_flags) struct mem_and_io_snapshot { uint32_t snapshot_magic; uint32_t free_pages; uint32_t active_pages; uint32_t inactive_pages; uint32_t purgeable_pages; uint32_t wired_pages; uint32_t speculative_pages; uint32_t throttled_pages; uint32_t filebacked_pages; uint32_t compressions; uint32_t decompressions; uint32_t compressor_size; int32_t busy_buffer_count; uint32_t pages_wanted; uint32_t pages_reclaimed; uint8_t pages_wanted_reclaimed_valid; // did mach_vm_pressure_monitor succeed? } __attribute__((packed)); struct mem_and_io_snapshot_v2 { uint32_t snapshot_magic; uint32_t free_pages; uint32_t active_pages; uint32_t inactive_pages; uint32_t purgeable_pages; uint32_t wired_pages; uint32_t speculative_pages; uint32_t throttled_pages; uint32_t filebacked_pages; uint32_t compressions; uint32_t decompressions; uint32_t compressor_size; int32_t busy_buffer_count; uint32_t pages_wanted; uint32_t pages_reclaimed; uint8_t pages_wanted_reclaimed_valid; // did mach_vm_pressure_monitor succeed? uint32_t shared_region_pages; uint32_t compressed_pages; uint32_t swapped_pages; } __attribute__((packed)); /* SS_TH_* macros are for ths_state */ #define SS_TH_WAIT 0x01 /* queued for waiting */ #define SS_TH_SUSP 0x02 /* stopped or requested to stop */ #define SS_TH_RUN 0x04 /* running or on runq */ #define SS_TH_UNINT 0x08 /* waiting uninteruptibly */ #define SS_TH_TERMINATE 0x10 /* halted at termination */ #define SS_TH_TERMINATE2 0x20 /* added to termination queue */ #define SS_TH_IDLE 0x80 /* idling processor */ struct thread_snapshot_v2 { uint64_t ths_thread_id; uint64_t ths_wait_event; uint64_t ths_continuation; uint64_t ths_total_syscalls; uint64_t ths_voucher_identifier; uint64_t ths_dqserialnum; uint64_t ths_user_time; uint64_t ths_sys_time; uint64_t ths_ss_flags; uint64_t ths_last_run_time; uint64_t ths_last_made_runnable_time; uint32_t ths_state; uint32_t ths_sched_flags; int16_t ths_base_priority; int16_t ths_sched_priority; uint8_t ths_eqos; uint8_t ths_rqos; uint8_t ths_rqos_override; uint8_t ths_io_tier; } __attribute__((packed)); struct thread_snapshot_v3 { uint64_t ths_thread_id; uint64_t ths_wait_event; uint64_t ths_continuation; uint64_t ths_total_syscalls; uint64_t ths_voucher_identifier; uint64_t ths_dqserialnum; uint64_t ths_user_time; uint64_t ths_sys_time; uint64_t ths_ss_flags; uint64_t ths_last_run_time; uint64_t ths_last_made_runnable_time; uint32_t ths_state; uint32_t ths_sched_flags; int16_t ths_base_priority; int16_t ths_sched_priority; uint8_t ths_eqos; uint8_t ths_rqos; uint8_t ths_rqos_override; uint8_t ths_io_tier; uint64_t ths_thread_t; } __attribute__((packed)); struct thread_snapshot_v4 { uint64_t ths_thread_id; uint64_t ths_wait_event; uint64_t ths_continuation; uint64_t ths_total_syscalls; uint64_t ths_voucher_identifier; uint64_t ths_dqserialnum; uint64_t ths_user_time; uint64_t ths_sys_time; uint64_t ths_ss_flags; uint64_t ths_last_run_time; uint64_t ths_last_made_runnable_time; uint32_t ths_state; uint32_t ths_sched_flags; int16_t ths_base_priority; int16_t ths_sched_priority; uint8_t ths_eqos; uint8_t ths_rqos; uint8_t ths_rqos_override; uint8_t ths_io_tier; uint64_t ths_thread_t; uint64_t ths_requested_policy; uint64_t ths_effective_policy; } __attribute__((packed)); struct thread_group_snapshot { uint64_t tgs_id; char tgs_name[16]; } __attribute__((packed)); /* * In general these flags mirror their THREAD_GROUP_FLAGS_ counterparts. * THREAD_GROUP_FLAGS_UI_APP was repurposed and THREAD_GROUP_FLAGS_APPLICATION * introduced to take its place. To remain compatible, kThreadGroupUIApp is * kept around and kThreadGroupUIApplication introduced. */ enum thread_group_flags { kThreadGroupEfficient = 0x1, kThreadGroupApplication = 0x2, kThreadGroupUIApp = 0x2, kThreadGroupCritical = 0x4, kThreadGroupBestEffort = 0x8, kThreadGroupUIApplication = 0x100, kThreadGroupManaged = 0x200, kThreadGroupStrictTimers = 0x400, }; // Note: Add any new flags to kcdata.py (tgs_flags) struct thread_group_snapshot_v2 { uint64_t tgs_id; char tgs_name[16]; uint64_t tgs_flags; } __attribute__((packed)); struct thread_group_snapshot_v3 { uint64_t tgs_id; char tgs_name[16]; uint64_t tgs_flags; char tgs_name_cont[16]; } __attribute__((packed)); enum coalition_flags { kCoalitionTermRequested = 0x1, kCoalitionTerminated = 0x2, kCoalitionReaped = 0x4, kCoalitionPrivileged = 0x8, }; // Note: Add any new flags to kcdata.py (jcs_flags) struct jetsam_coalition_snapshot { uint64_t jcs_id; uint64_t jcs_flags; uint64_t jcs_thread_group; uint64_t jcs_leader_task_uniqueid; } __attribute__((packed)); struct instrs_cycles_snapshot { uint64_t ics_instructions; uint64_t ics_cycles; } __attribute__((packed)); struct instrs_cycles_snapshot_v2 { uint64_t ics_instructions; uint64_t ics_cycles; uint64_t ics_p_instructions; uint64_t ics_p_cycles; } __attribute__((packed)); struct thread_delta_snapshot_v2 { uint64_t tds_thread_id; uint64_t tds_voucher_identifier; uint64_t tds_ss_flags; uint64_t tds_last_made_runnable_time; uint32_t tds_state; uint32_t tds_sched_flags; int16_t tds_base_priority; int16_t tds_sched_priority; uint8_t tds_eqos; uint8_t tds_rqos; uint8_t tds_rqos_override; uint8_t tds_io_tier; } __attribute__ ((packed)); struct thread_delta_snapshot_v3 { uint64_t tds_thread_id; uint64_t tds_voucher_identifier; uint64_t tds_ss_flags; uint64_t tds_last_made_runnable_time; uint32_t tds_state; uint32_t tds_sched_flags; int16_t tds_base_priority; int16_t tds_sched_priority; uint8_t tds_eqos; uint8_t tds_rqos; uint8_t tds_rqos_override; uint8_t tds_io_tier; uint64_t tds_requested_policy; uint64_t tds_effective_policy; } __attribute__ ((packed)); struct io_stats_snapshot { /* * I/O Statistics * XXX: These fields must be together. */ uint64_t ss_disk_reads_count; uint64_t ss_disk_reads_size; uint64_t ss_disk_writes_count; uint64_t ss_disk_writes_size; uint64_t ss_io_priority_count[STACKSHOT_IO_NUM_PRIORITIES]; uint64_t ss_io_priority_size[STACKSHOT_IO_NUM_PRIORITIES]; uint64_t ss_paging_count; uint64_t ss_paging_size; uint64_t ss_non_paging_count; uint64_t ss_non_paging_size; uint64_t ss_data_count; uint64_t ss_data_size; uint64_t ss_metadata_count; uint64_t ss_metadata_size; /* XXX: I/O Statistics end */ } __attribute__ ((packed)); struct task_snapshot_v2 { uint64_t ts_unique_pid; uint64_t ts_ss_flags; uint64_t ts_user_time_in_terminated_threads; uint64_t ts_system_time_in_terminated_threads; uint64_t ts_p_start_sec; uint64_t ts_task_size; uint64_t ts_max_resident_size; uint32_t ts_suspend_count; uint32_t ts_faults; uint32_t ts_pageins; uint32_t ts_cow_faults; uint32_t ts_was_throttled; uint32_t ts_did_throttle; uint32_t ts_latency_qos; int32_t ts_pid; char ts_p_comm[32]; } __attribute__ ((packed)); struct task_snapshot_v3 { uint64_t ts_unique_pid; uint64_t ts_ss_flags; uint64_t ts_user_time_in_terminated_threads; uint64_t ts_system_time_in_terminated_threads; uint64_t ts_p_start_sec; uint64_t ts_task_size; uint64_t ts_max_resident_size; uint32_t ts_suspend_count; uint32_t ts_faults; uint32_t ts_pageins; uint32_t ts_cow_faults; uint32_t ts_was_throttled; uint32_t ts_did_throttle; uint32_t ts_latency_qos; int32_t ts_pid; char ts_p_comm[32]; uint32_t ts_uid; uint32_t ts_gid; } __attribute__ ((packed)); struct transitioning_task_snapshot { uint64_t tts_unique_pid; uint64_t tts_ss_flags; uint64_t tts_transition_type; int32_t tts_pid; char tts_p_comm[32]; } __attribute__ ((packed)); struct task_delta_snapshot_v2 { uint64_t tds_unique_pid; uint64_t tds_ss_flags; uint64_t tds_user_time_in_terminated_threads; uint64_t tds_system_time_in_terminated_threads; uint64_t tds_task_size; uint64_t tds_max_resident_size; uint32_t tds_suspend_count; uint32_t tds_faults; uint32_t tds_pageins; uint32_t tds_cow_faults; uint32_t tds_was_throttled; uint32_t tds_did_throttle; uint32_t tds_latency_qos; } __attribute__ ((packed)); struct task_memorystatus_snapshot { int32_t tms_current_memlimit; int32_t tms_effectivepriority; int32_t tms_requestedpriority; int32_t tms_assertionpriority; } __attribute__ ((packed)); #define KCDATA_INVALID_CS_TRUST_LEVEL 0xffffffff struct stackshot_task_codesigning_info { uint64_t csflags; uint32_t cs_trust_level; } __attribute__ ((packed)); struct stackshot_cpu_times { uint64_t user_usec; uint64_t system_usec; } __attribute__((packed)); struct stackshot_cpu_times_v2 { uint64_t user_usec; uint64_t system_usec; uint64_t runnable_usec; } __attribute__((packed)); struct stackshot_duration { uint64_t stackshot_duration; uint64_t stackshot_duration_outer; } __attribute__((packed)); struct stackshot_duration_v2 { uint64_t stackshot_duration; uint64_t stackshot_duration_outer; uint64_t stackshot_duration_prior; } __attribute__((packed)); struct stackshot_fault_stats { uint32_t sfs_pages_faulted_in; /* number of pages faulted in using KDP fault path */ uint64_t sfs_time_spent_faulting; /* MATUs spent faulting */ uint64_t sfs_system_max_fault_time; /* MATUs fault time limit per stackshot */ uint8_t sfs_stopped_faulting; /* we stopped decompressing because we hit the limit */ } __attribute__((packed)); typedef struct stackshot_thread_waitinfo { uint64_t owner; /* The thread that owns the object */ uint64_t waiter; /* The thread that's waiting on the object */ uint64_t context; /* A context uniquely identifying the object */ uint8_t wait_type; /* The type of object that the thread is waiting on */ } __attribute__((packed)) thread_waitinfo_t; typedef struct stackshot_thread_waitinfo_v2 { uint64_t owner; /* The thread that owns the object */ uint64_t waiter; /* The thread that's waiting on the object */ uint64_t context; /* A context uniquely identifying the object */ uint8_t wait_type; /* The type of object that the thread is waiting on */ int16_t portlabel_id; /* matches to a stackshot_portlabel, or NONE or MISSING */ uint32_t wait_flags; /* info about the wait */ #define STACKSHOT_WAITINFO_FLAGS_SPECIALREPLY 0x1 /* We're waiting on a special reply port */ #define STACKSHOT_WAITINFO_FLAGS_BOOTSTRAP 0x2 /* We're waiting on a bootstrap port */ } __attribute__((packed)) thread_waitinfo_v2_t; typedef struct stackshot_vmrl_blocking_relationship { uint64_t waiter_tid; uint64_t blocker_tid; uint64_t entry_hash; uint32_t flags; } __attribute__((packed)) vmrl_blocking_relationship_t; #define STACKSHOT_WAITER_VMRL_SHARED 0x01 #define STACKSHOT_BLOCKER_VMRL_SHARED 0x02 #define STACKSHOT_WAITER_VMRL_EXCLUSIVE 0x04 #define STACKSHOT_BLOCKER_VMRL_EXCLUSIVE 0x08 #define STACKSHOT_WAITER_VMRL_STREAMING 0x10 #define STACKSHOT_BLOCKER_VMRL_STREAMING 0x20 #define STACKSHOT_WAITER_VMRL_ATOMIC 0x40 #define STACKSHOT_BLOCKER_VMRL_ATOMIC 0x80 typedef struct stackshot_thread_turnstileinfo { uint64_t waiter; /* The thread that's waiting on the object */ uint64_t turnstile_context; /* Associated data (either thread id, or workq addr) */ uint8_t turnstile_priority; uint8_t number_of_hops; uint64_t turnstile_flags; /* see below */ } __attribute__((packed)) thread_turnstileinfo_t; typedef struct stackshot_thread_turnstileinfo_v2 { uint64_t waiter; /* The thread that's waiting on the object */ uint64_t turnstile_context; /* Associated data (either thread id, or workq addr) */ uint8_t turnstile_priority; uint8_t number_of_hops; #define STACKSHOT_TURNSTILE_STATUS_UNKNOWN 0x01 /* The final inheritor is unknown (bug?) */ #define STACKSHOT_TURNSTILE_STATUS_LOCKED_WAITQ 0x02 /* A waitq was found to be locked */ #define STACKSHOT_TURNSTILE_STATUS_WORKQUEUE 0x04 /* The final inheritor is a workqueue */ #define STACKSHOT_TURNSTILE_STATUS_THREAD 0x08 /* The final inheritor is a thread */ #define STACKSHOT_TURNSTILE_STATUS_BLOCKED_ON_TASK 0x10 /* blocked on task, dind't find thread */ #define STACKSHOT_TURNSTILE_STATUS_HELD_IPLOCK 0x20 /* the ip_lock was held */ #define STACKSHOT_TURNSTILE_STATUS_SENDPORT 0x40 /* port_labelid was from a send port */ #define STACKSHOT_TURNSTILE_STATUS_RECEIVEPORT 0x80 /* port_labelid was from a receive port */ uint64_t turnstile_flags; // Note: Add any new flags to kcdata.py (turnstile_flags) int16_t portlabel_id; /* matches to a stackshot_portlabel, or NONE or MISSING */ } __attribute__((packed)) thread_turnstileinfo_v2_t; #define STACKSHOT_TURNSTILE_STATUS_PORTFLAGS (STACKSHOT_TURNSTILE_STATUS_SENDPORT | STACKSHOT_TURNSTILE_STATUS_RECEIVEPORT) #define STACKSHOT_PORTLABELID_NONE (0) /* No port label found */ #define STACKSHOT_PORTLABELID_MISSING (-1) /* portlabel found, but stackshot ran out of space to track it */ #define STACKSHOT_WAITOWNER_KERNEL (UINT64_MAX - 1) #define STACKSHOT_WAITOWNER_PORT_LOCKED (UINT64_MAX - 2) #define STACKSHOT_WAITOWNER_PSET_LOCKED (UINT64_MAX - 3) #define STACKSHOT_WAITOWNER_INTRANSIT (UINT64_MAX - 4) #define STACKSHOT_WAITOWNER_MTXSPIN (UINT64_MAX - 5) #define STACKSHOT_WAITOWNER_THREQUESTED (UINT64_MAX - 6) /* workloop waiting for a new worker thread */ #define STACKSHOT_WAITOWNER_SUSPENDED (UINT64_MAX - 7) /* workloop is suspended */ #define STACKSHOT_PORTLABEL_READFAILED 0x1 /* could not read port information */ #define STACKSHOT_PORTLABEL_THROTTLED 0x2 /* service port is marked as throttled */ struct portlabel_info { int16_t portlabel_id; /* kcdata-specific ID for this port label */ uint16_t portlabel_flags; /* STACKSHOT_PORTLABEL_* */ uint8_t portlabel_domain; /* launchd domain */ } __attribute__((packed)); struct stackshot_cpu_architecture { int32_t cputype; int32_t cpusubtype; } __attribute__((packed)); struct stack_snapshot_stacktop { uint64_t sp; uint8_t stack_contents[8]; }; /* only collected if STACKSHOT_COLLECTS_LATENCY_INFO is set to !0 */ struct stackshot_latency_collection { uint64_t latency_version; uint64_t setup_latency; uint64_t total_task_iteration_latency; uint64_t total_terminated_task_iteration_latency; } __attribute__((packed)); /* only collected if STACKSHOT_COLLECTS_LATENCY_INFO is set to !0 */ struct stackshot_latency_collection_v2 { uint64_t latency_version; uint64_t setup_latency_mt; uint64_t total_task_iteration_latency_mt; uint64_t total_terminated_task_iteration_latency_mt; uint64_t task_queue_building_latency_mt; uint64_t terminated_task_queue_building_latency_mt; uint64_t cpu_wait_latency_mt; int32_t main_cpu_number; int32_t calling_cpu_number; uint64_t buffer_size; uint64_t buffer_used; uint64_t buffer_overhead; uint64_t buffer_count; } __attribute__((packed)); /* only collected if STACKSHOT_COLLECTS_LATENCY_INFO is set to !0 */ struct stackshot_latency_cpu { int32_t cpu_number; int32_t cluster_type; uint64_t init_latency_mt; uint64_t workqueue_latency_mt; uint64_t total_latency_mt; uint64_t total_cycles; uint64_t total_instrs; uint64_t tasks_processed; uint64_t threads_processed; uint64_t faulting_time_mt; uint64_t total_buf; uint64_t intercluster_buf_used; } __attribute__((packed)); /* only collected if STACKSHOT_COLLECTS_LATENCY_INFO is set to !0 */ struct stackshot_latency_buffer { int32_t cluster_type; uint64_t size; uint64_t used; uint64_t overhead; } __attribute__ ((packed)); /* only collected if STACKSHOT_COLLECTS_LATENCY_INFO is set to !0 */ struct stackshot_latency_task { uint64_t task_uniqueid; uint64_t setup_latency; uint64_t task_thread_count_loop_latency; uint64_t task_thread_data_loop_latency; uint64_t cur_tsnap_latency; uint64_t pmap_latency; uint64_t bsd_proc_ids_latency; uint64_t misc_latency; uint64_t misc2_latency; uint64_t end_latency; } __attribute__((packed)); /* only collected if STACKSHOT_COLLECTS_LATENCY_INFO is set to !0 */ struct stackshot_latency_thread { uint64_t thread_id; uint64_t cur_thsnap1_latency; uint64_t dispatch_serial_latency; uint64_t dispatch_label_latency; uint64_t cur_thsnap2_latency; uint64_t thread_name_latency; uint64_t sur_times_latency; uint64_t user_stack_latency; uint64_t kernel_stack_latency; uint64_t misc_latency; } __attribute__((packed)); struct stackshot_suspension_info { uint64_t tss_last_start; /* mach_absolute_time of beginning of last suspension*/ uint64_t tss_last_end; /* mach_absolute_time of end of last suspension */ uint64_t tss_count; /* number of times this task has been suspended */ uint64_t tss_duration; /* sum(mach_absolute_time) of time spend suspended */ } __attribute__((packed)); struct stackshot_suspension_source { uint64_t tss_time; /* mach_absolute_time of suspend */ uint64_t tss_tid; /* tid of suspending thread */ int tss_pid; /* pid of suspending task */ char tss_procname[65]; /* name of suspending task */ } __attribute__((packed)); struct stackshot_device_lock_state { uint8_t flags; /* interpret as a stackshot_device_lock_flags_t */ uint8_t passcode_status; /* interpret as a passcode_status_t */ uint8_t lock_state; /* interpret as a device_lock_state_t */ } __attribute__((packed)); /**************** definitions for exclaves *********************/ enum thread_exclaves_flags : uint32_t { kExclaveRPCActive = 0x1, /* Thread is handling RPC call in secure world */ kExclaveUpcallActive = 0x2, /* Thread has upcalled back into xnu while handling RPC */ kExclaveSchedulerRequest = 0x4, /* Thread is handling scheduler request */ }; struct thread_exclaves_info { uint64_t tei_scid; /* Scheduling context for exclave IPC stack */ uint32_t tei_thread_offset; /* # frames from top of stack exclave frames should be inserted */ uint32_t tei_flags; /* A combination of enum thread_exclaves_flags values */ } __attribute__((packed)); struct thread_crash_exclaves_info { uint64_t tcei_scid; /* Scheduling context for exclave IPC stack */ uint64_t tcei_thread_id; /* Corresponding xnu thread id */ uint32_t tcei_flags; /* A combination of enum thread_exclaves_flags values */ } __attribute__((packed)); enum exclave_scresult_flags : uint64_t { kExclaveScresultHaveIPCStack = 0x1, }; struct exclave_scresult_info { uint64_t esc_id; uint64_t esc_flags; /* A combination of enum exclave_scresult_flags values */ } __attribute__((packed)); enum exclave_ipcstackentry_flags : uint64_t { kExclaveIpcStackEntryHaveInvocationID = 0x1, kExclaveIpcStackEntryHaveStack = 0x2, }; struct exclave_ipcstackentry_info { uint64_t eise_asid; /* ASID */ uint64_t eise_tnid; /* Thread numeric ID, may be UINT64_MAX if ommitted */ uint64_t eise_invocationid; /* Invocation ID, may be UINT64_MAX if ommitted */ uint64_t eise_flags; /* A combination of enum exclave_ipcstackentry_flags values */ } __attribute__((packed)); typedef uint64_t exclave_ecstackentry_addr_t; enum exclave_addressspace_flags : uint64_t { kExclaveAddressSpaceHaveSlide = 0x1, /* slide info provided */ }; struct exclave_addressspace_info { uint64_t eas_id; /* ASID */ uint64_t eas_flags; /* A combination of enum exclave_addressspace_flags values */ uint64_t eas_layoutid; /* textLayout for this address space */ uint64_t eas_slide; /* slide to apply to textlayout, or UINT64_MAX if omitted */ uint64_t eas_asroot; /* ASRoot/TTBR0 value used as an identifier for the address space by cL4 */ } __attribute__((packed)); enum exclave_textlayout_flags : uint64_t { kExclaveTextLayoutLoadAddressesSynthetic = 0x1, /* Load Addresses are synthetic */ kExclaveTextLayoutLoadAddressesUnslid = 0x2, /* Load Addresses are accurate and unslid */ kExclaveTextLayoutHasSharedCache = 0x4, /* sharedcache_index is valid, refers to entry # in STACKSHOT_KCTYPE_EXCLAVE_TEXTLAYOUT_SEGMENTS array */ }; struct exclave_textlayout_info_v1 { uint64_t layout_id; uint64_t etl_flags; /* A combination of enum exclave_textlayout_flags values */ } __attribute__((packed)); struct exclave_textlayout_info { uint64_t layout_id; uint64_t etl_flags; /* A combination of enum exclave_textlayout_flags values */ uint32_t sharedcache_index; /* index in SEGMENTs, or UINT32_MAX */ } __attribute__((packed)); struct exclave_textlayout_segment { uuid_t layoutSegment_uuid; uint64_t layoutSegment_loadAddress; /* Synthetic Load Address */ } __attribute__((packed)); struct exclave_textlayout_segment_v2 { uuid_t layoutSegment_uuid; uint64_t layoutSegment_loadAddress; /* Synthetic Load Address */ uint64_t layoutSegment_rawLoadAddress; /* Raw Load Address when unslided */ } __attribute__((packed)); /**************** definitions for crashinfo *********************/ /* * NOTE: Please update kcdata/libkdd/kcdtypes.c if you make any changes * in TASK_CRASHINFO_* types. */ /* FIXME some of these types aren't clean (fixed width, packed, and defined *here*) */ struct crashinfo_proc_uniqidentifierinfo { uint8_t p_uuid[16]; /* UUID of the main executable */ uint64_t p_uniqueid; /* 64 bit unique identifier for process */ uint64_t p_puniqueid; /* unique identifier for process's parent */ uint64_t p_reserve2; /* reserved for future use */ uint64_t p_reserve3; /* reserved for future use */ uint64_t p_reserve4; /* reserved for future use */ } __attribute__((packed)); #define MAX_TRIAGE_STRING_LEN (128) struct kernel_triage_info_v1 { char triage_string1[MAX_TRIAGE_STRING_LEN]; char triage_string2[MAX_TRIAGE_STRING_LEN]; char triage_string3[MAX_TRIAGE_STRING_LEN]; char triage_string4[MAX_TRIAGE_STRING_LEN]; char triage_string5[MAX_TRIAGE_STRING_LEN]; } __attribute__((packed)); struct crashinfo_jit_address_range { uint64_t start_address; uint64_t end_address; } __attribute__((packed)); struct crashinfo_mb { uint64_t start_address; uint64_t data[64]; } __attribute__((packed)); struct crashinfo_task_security_config { uint32_t task_security_config; /* struct task_security_config */ } __attribute__((packed)); struct crashinfo_voucher { uint64_t thread_id; uint32_t originator_pid; uint32_t proximate_pid; } __attribute__((packed)); #define MAX_CRASHINFO_SIGNING_ID_LEN 64 #define MAX_CRASHINFO_TEAM_ID_LEN 32 #define MAX_CRASHINFO_SANDBOX_PROFILE_LEN 32 #define TASK_CRASHINFO_BEGIN KCDATA_BUFFER_BEGIN_CRASHINFO #define TASK_CRASHINFO_STRING_DESC KCDATA_TYPE_STRING_DESC #define TASK_CRASHINFO_UINT32_DESC KCDATA_TYPE_UINT32_DESC #define TASK_CRASHINFO_UINT64_DESC KCDATA_TYPE_UINT64_DESC #define TASK_CRASHINFO_EXTMODINFO 0x801 #define TASK_CRASHINFO_BSDINFOWITHUNIQID 0x802 /* struct crashinfo_proc_uniqidentifierinfo */ #define TASK_CRASHINFO_TASKDYLD_INFO 0x803 #define TASK_CRASHINFO_UUID 0x804 #define TASK_CRASHINFO_PID 0x805 #define TASK_CRASHINFO_PPID 0x806 #define TASK_CRASHINFO_RUSAGE 0x807 /* struct rusage DEPRECATED do not use. * This struct has longs in it */ #define TASK_CRASHINFO_RUSAGE_INFO 0x808 /* struct rusage_info_v3 from resource.h */ #define TASK_CRASHINFO_PROC_NAME 0x809 /* char * */ #define TASK_CRASHINFO_PROC_STARTTIME 0x80B /* struct timeval64 */ #define TASK_CRASHINFO_USERSTACK 0x80C /* uint64_t */ #define TASK_CRASHINFO_ARGSLEN 0x80D #define TASK_CRASHINFO_EXCEPTION_CODES 0x80E /* mach_exception_data_t */ #define TASK_CRASHINFO_PROC_PATH 0x80F /* string of len MAXPATHLEN */ #define TASK_CRASHINFO_PROC_CSFLAGS 0x810 /* uint32_t */ #define TASK_CRASHINFO_PROC_STATUS 0x811 /* char */ #define TASK_CRASHINFO_UID 0x812 /* uid_t */ #define TASK_CRASHINFO_GID 0x813 /* gid_t */ #define TASK_CRASHINFO_PROC_ARGC 0x814 /* int */ #define TASK_CRASHINFO_PROC_FLAGS 0x815 /* unsigned int */ #define TASK_CRASHINFO_CPUTYPE 0x816 /* cpu_type_t */ #define TASK_CRASHINFO_WORKQUEUEINFO 0x817 /* struct proc_workqueueinfo */ #define TASK_CRASHINFO_RESPONSIBLE_PID 0x818 /* pid_t */ #define TASK_CRASHINFO_DIRTY_FLAGS 0x819 /* int */ #define TASK_CRASHINFO_CRASHED_THREADID 0x81A /* uint64_t */ #define TASK_CRASHINFO_COALITION_ID 0x81B /* uint64_t */ #define TASK_CRASHINFO_UDATA_PTRS 0x81C /* uint64_t */ #define TASK_CRASHINFO_MEMORY_LIMIT 0x81D /* uint64_t */ #define TASK_CRASHINFO_LEDGER_INTERNAL 0x81E /* uint64_t */ #define TASK_CRASHINFO_LEDGER_INTERNAL_COMPRESSED 0x81F /* uint64_t */ #define TASK_CRASHINFO_LEDGER_IOKIT_MAPPED 0x820 /* uint64_t */ #define TASK_CRASHINFO_LEDGER_ALTERNATE_ACCOUNTING 0x821 /* uint64_t */ #define TASK_CRASHINFO_LEDGER_ALTERNATE_ACCOUNTING_COMPRESSED 0x822 /* uint64_t */ #define TASK_CRASHINFO_LEDGER_PURGEABLE_NONVOLATILE 0x823 /* uint64_t */ #define TASK_CRASHINFO_LEDGER_PURGEABLE_NONVOLATILE_COMPRESSED 0x824 /* uint64_t */ #define TASK_CRASHINFO_LEDGER_PAGE_TABLE 0x825 /* uint64_t */ #define TASK_CRASHINFO_LEDGER_PHYS_FOOTPRINT 0x826 /* uint64_t */ #define TASK_CRASHINFO_LEDGER_PHYS_FOOTPRINT_LIFETIME_MAX 0x827 /* uint64_t */ #define TASK_CRASHINFO_LEDGER_NETWORK_NONVOLATILE 0x828 /* uint64_t */ #define TASK_CRASHINFO_LEDGER_NETWORK_NONVOLATILE_COMPRESSED 0x829 /* uint64_t */ #define TASK_CRASHINFO_LEDGER_WIRED_MEM 0x82A /* uint64_t */ #define TASK_CRASHINFO_PROC_PERSONA_ID 0x82B /* uid_t */ #define TASK_CRASHINFO_MEMORY_LIMIT_INCREASE 0x82C /* uint32_t */ #define TASK_CRASHINFO_LEDGER_TAGGED_FOOTPRINT 0x82D /* uint64_t */ #define TASK_CRASHINFO_LEDGER_TAGGED_FOOTPRINT_COMPRESSED 0x82E /* uint64_t */ #define TASK_CRASHINFO_LEDGER_MEDIA_FOOTPRINT 0x82F /* uint64_t */ #define TASK_CRASHINFO_LEDGER_MEDIA_FOOTPRINT_COMPRESSED 0x830 /* uint64_t */ #define TASK_CRASHINFO_LEDGER_GRAPHICS_FOOTPRINT 0x831 /* uint64_t */ #define TASK_CRASHINFO_LEDGER_GRAPHICS_FOOTPRINT_COMPRESSED 0x832 /* uint64_t */ #define TASK_CRASHINFO_LEDGER_NEURAL_FOOTPRINT 0x833 /* uint64_t */ #define TASK_CRASHINFO_LEDGER_NEURAL_FOOTPRINT_COMPRESSED 0x834 /* uint64_t */ #define TASK_CRASHINFO_MEMORYSTATUS_EFFECTIVE_PRIORITY 0x835 /* int32_t */ #define TASK_CRASHINFO_KERNEL_TRIAGE_INFO_V1 0x836 /* struct kernel_triage_info_v1 */ #define TASK_CRASHINFO_TASK_IS_CORPSE_FORK 0x837 /* boolean_t */ #define TASK_CRASHINFO_EXCEPTION_TYPE 0x838 /* int */ #define TASK_CRASHINFO_CRASH_COUNT 0x839 /* int */ #define TASK_CRASHINFO_THROTTLE_TIMEOUT 0x83A /* int */ #define TASK_CRASHINFO_CS_SIGNING_ID 0x83B /* string of len MAX_CRASHINFO_SIGNING_ID_LEN */ #define TASK_CRASHINFO_CS_TEAM_ID 0x83C /* string of len MAX_CRASHINFO_TEAM_ID_LEN */ #define TASK_CRASHINFO_CS_VALIDATION_CATEGORY 0x83D /* uint32_t */ #define TASK_CRASHINFO_CS_TRUST_LEVEL 0x83E /* uint32_t */ #define TASK_CRASHINFO_PROC_CPUTYPE 0x83F /* cpu_type_t */ #define TASK_CRASHINFO_JIT_ADDRESS_RANGE 0x840 /* struct crashinfo_jit_address_range */ #define TASK_CRASHINFO_MB 0x841 /* struct crashinfo_mb */ #define TASK_CRASHINFO_CS_AUXILIARY_INFO 0x842 /* uint64_t */ #define TASK_CRASHINFO_RLIM_CORE 0x843 /* rlim_t */ #define TASK_CRASHINFO_CORE_ALLOWED 0x844 /* uint8_t */ #define TASK_CRASHINFO_TASK_SECURITY_CONFIG 0x845 /* struct task_security_config */ #define TASK_CRASHINFO_VOUCHER_INFO 0x846 /* struct crashinfo_voucher */ #define TASK_CRASHINFO_SANDBOX_PROFILE 0x847 /* string of len MAX_CRASHINFO_SANDBOX_PROFILE_LEN */ #define TASK_CRASHINFO_END KCDATA_TYPE_BUFFER_END /**************** definitions for backtrace info *********************/ /* tstate is variable length with count elements */ struct btinfo_thread_state_data_t { uint32_t flavor; uint32_t count; int tstate[]; }; struct btinfo_sc_load_info64 { uint64_t sharedCacheSlide; uuid_t sharedCacheUUID; uint64_t sharedCacheBaseAddress; }; struct btinfo_sc_load_info { uint32_t sharedCacheSlide; uuid_t sharedCacheUUID; uint32_t sharedCacheBaseAddress; }; #define TASK_BTINFO_BEGIN KCDATA_BUFFER_BEGIN_BTINFO /* Shared keys with CRASHINFO */ #define TASK_BTINFO_PID 0xA01 #define TASK_BTINFO_PPID 0xA02 #define TASK_BTINFO_PROC_NAME 0xA03 #define TASK_BTINFO_PROC_PATH 0xA04 #define TASK_BTINFO_UID 0xA05 #define TASK_BTINFO_GID 0xA06 #define TASK_BTINFO_PROC_FLAGS 0xA07 #define TASK_BTINFO_CPUTYPE 0xA08 #define TASK_BTINFO_EXCEPTION_CODES 0xA09 #define TASK_BTINFO_EXCEPTION_TYPE 0xA0A #define TASK_BTINFO_RUSAGE_INFO 0xA0B #define TASK_BTINFO_COALITION_ID 0xA0C #define TASK_BTINFO_CRASH_COUNT 0xA0D #define TASK_BTINFO_THROTTLE_TIMEOUT 0xA0E /* Only in BTINFO */ #define TASK_BTINFO_THREAD_ID 0xA20 /* uint64_t */ #define TASK_BTINFO_THREAD_NAME 0xA21 /* string of len MAXTHREADNAMESIZE */ #define TASK_BTINFO_THREAD_STATE 0xA22 /* struct btinfo_thread_state_data_t */ #define TASK_BTINFO_THREAD_EXCEPTION_STATE 0xA23 /* struct btinfo_thread_state_data_t */ #define TASK_BTINFO_BACKTRACE 0xA24 /* array of uintptr_t */ #define TASK_BTINFO_BACKTRACE64 0xA25 /* array of uintptr_t */ #define TASK_BTINFO_ASYNC_BACKTRACE64 0xA26 /* array of uintptr_t */ #define TASK_BTINFO_ASYNC_START_INDEX 0xA27 /* uint32_t */ #define TASK_BTINFO_PLATFORM 0xA28 /* uint32_t */ #define TASK_BTINFO_SC_LOADINFO 0xA29 /* struct btinfo_sc_load_info */ #define TASK_BTINFO_SC_LOADINFO64 0xA2A /* struct btinfo_sc_load_info64 */ #define TASK_BTINFO_DYLD_LOADINFO KCDATA_TYPE_LIBRARY_LOADINFO #define TASK_BTINFO_DYLD_LOADINFO64 KCDATA_TYPE_LIBRARY_LOADINFO64 /* Last one */ #define TASK_BTINFO_FLAGS 0xAFF /* uint32_t */ #define TASK_BTINFO_FLAG_BT_TRUNCATED 0x1 #define TASK_BTINFO_FLAG_ASYNC_BT_TRUNCATED 0x2 #define TASK_BTINFO_FLAG_TASK_TERMINATED 0x4 /* task is terminated */ #define TASK_BTINFO_FLAG_KCDATA_INCOMPLETE 0x8 /* lw corpse collection is incomplete */ #define TASK_BTINFO_END KCDATA_TYPE_BUFFER_END /**************** definitions for os reasons *********************/ #define EXIT_REASON_SNAPSHOT 0x1001 #define EXIT_REASON_USER_DESC 0x1002 /* string description of reason */ #define EXIT_REASON_USER_PAYLOAD 0x1003 /* user payload data */ #define EXIT_REASON_CODESIGNING_INFO 0x1004 #define EXIT_REASON_WORKLOOP_ID 0x1005 #define EXIT_REASON_DISPATCH_QUEUE_NO 0x1006 struct exit_reason_snapshot { uint32_t ers_namespace; uint64_t ers_code; /* end of version 1 of exit_reason_snapshot. sizeof v1 was 12 */ uint64_t ers_flags; } __attribute__((packed)); #define EXIT_REASON_CODESIG_PATH_MAX 1024 struct codesigning_exit_reason_info { uint64_t ceri_virt_addr; uint64_t ceri_file_offset; char ceri_pathname[EXIT_REASON_CODESIG_PATH_MAX]; char ceri_filename[EXIT_REASON_CODESIG_PATH_MAX]; uint64_t ceri_codesig_modtime_secs; uint64_t ceri_codesig_modtime_nsecs; uint64_t ceri_page_modtime_secs; uint64_t ceri_page_modtime_nsecs; uint8_t ceri_path_truncated; uint8_t ceri_object_codesigned; uint8_t ceri_page_codesig_validated; uint8_t ceri_page_codesig_tainted; uint8_t ceri_page_codesig_nx; uint8_t ceri_page_wpmapped; uint8_t ceri_page_slid; uint8_t ceri_page_dirty; uint32_t ceri_page_shadow_depth; } __attribute__((packed)); #define EXIT_REASON_USER_DESC_MAX_LEN 1024 #define EXIT_REASON_PAYLOAD_MAX_LEN 2048 /**************** safe iterators *********************/ #if !__has_ptrcheck typedef struct kcdata_iter { kcdata_item_t item; void *end; } kcdata_iter_t; static inline kcdata_iter_t kcdata_iter(void *buffer, unsigned long size) { kcdata_iter_t iter; iter.item = (kcdata_item_t) buffer; iter.end = (void*) (((uintptr_t)buffer) + size); return iter; } static inline kcdata_iter_t kcdata_iter_unsafe(void *buffer) __attribute__((deprecated)); static inline kcdata_iter_t kcdata_iter_unsafe(void *buffer) { kcdata_iter_t iter; iter.item = (kcdata_item_t) buffer; iter.end = (void*) (uintptr_t) ~0; return iter; } static const kcdata_iter_t kcdata_invalid_iter = { .item = NULL, .end = NULL }; static inline int kcdata_iter_valid(kcdata_iter_t iter) { return ((uintptr_t)iter.item + sizeof(struct kcdata_item) <= (uintptr_t)iter.end) && ((uintptr_t)iter.item + sizeof(struct kcdata_item) + iter.item->size <= (uintptr_t)iter.end); } static inline kcdata_iter_t kcdata_iter_next(kcdata_iter_t iter) { iter.item = (kcdata_item_t) (((uintptr_t)iter.item) + sizeof(struct kcdata_item) + (iter.item->size)); return iter; } static inline uint32_t kcdata_iter_type(kcdata_iter_t iter) { if ((iter.item->type & ~0xfu) == KCDATA_TYPE_ARRAY_PAD0) { return KCDATA_TYPE_ARRAY; } else { return iter.item->type; } } static inline uint32_t kcdata_calc_padding(uint32_t size) { /* calculate number of bytes to add to size to get something divisible by 16 */ return (-size) & 0xf; } static inline uint32_t kcdata_flags_get_padding(uint64_t flags) { return flags & KCDATA_FLAGS_STRUCT_PADDING_MASK; } /* see comment above about has_padding */ static inline int kcdata_iter_is_legacy_item(kcdata_iter_t iter, uint32_t legacy_size) { uint32_t legacy_size_padded = legacy_size + kcdata_calc_padding(legacy_size); return iter.item->size == legacy_size_padded && (iter.item->flags & (KCDATA_FLAGS_STRUCT_PADDING_MASK | KCDATA_FLAGS_STRUCT_HAS_PADDING)) == 0; } static inline uint32_t kcdata_iter_size(kcdata_iter_t iter) { uint32_t legacy_size = 0; switch (kcdata_iter_type(iter)) { case KCDATA_TYPE_ARRAY: case KCDATA_TYPE_CONTAINER_BEGIN: return iter.item->size; case STACKSHOT_KCTYPE_THREAD_SNAPSHOT: { legacy_size = sizeof(struct thread_snapshot_v2); if (kcdata_iter_is_legacy_item(iter, legacy_size)) { return legacy_size; } goto not_legacy; } case STACKSHOT_KCTYPE_SHAREDCACHE_LOADINFO: { legacy_size = sizeof(struct dyld_uuid_info_64); if (kcdata_iter_is_legacy_item(iter, legacy_size)) { return legacy_size; } goto not_legacy; } not_legacy: default: if (iter.item->size < kcdata_flags_get_padding(iter.item->flags)) { return 0; } else { return iter.item->size - kcdata_flags_get_padding(iter.item->flags); } } } static inline uint64_t kcdata_iter_flags(kcdata_iter_t iter) { return iter.item->flags; } static inline void * kcdata_iter_payload(kcdata_iter_t iter) { return &iter.item->data; } static inline uint32_t kcdata_iter_array_elem_type(kcdata_iter_t iter) { return (iter.item->flags >> 32) & UINT32_MAX; } static inline uint32_t kcdata_iter_array_elem_count(kcdata_iter_t iter) { return (iter.item->flags) & UINT32_MAX; } /* KCDATA_TYPE_ARRAY is ambiguous about the size of the array elements. Size is * calculated as total_size / elements_count, but total size got padded out to a * 16 byte alignment. New kernels will generate KCDATA_TYPE_ARRAY_PAD* instead * to explicitly tell us how much padding was used. Here we have a fixed, never * to be altered list of the sizes of array elements that were used before I * discovered this issue. If you find a KCDATA_TYPE_ARRAY that is not one of * these types, treat it as invalid data. */ static inline uint32_t kcdata_iter_array_size_switch(kcdata_iter_t iter) { switch (kcdata_iter_array_elem_type(iter)) { case KCDATA_TYPE_LIBRARY_LOADINFO: return sizeof(struct dyld_uuid_info_32); case KCDATA_TYPE_LIBRARY_LOADINFO64: return sizeof(struct dyld_uuid_info_64); case STACKSHOT_KCTYPE_KERN_STACKFRAME: case STACKSHOT_KCTYPE_USER_STACKFRAME: return sizeof(struct stack_snapshot_frame32); case STACKSHOT_KCTYPE_KERN_STACKFRAME64: case STACKSHOT_KCTYPE_USER_STACKFRAME64: return sizeof(struct stack_snapshot_frame64); case STACKSHOT_KCTYPE_DONATING_PIDS: return sizeof(int32_t); case STACKSHOT_KCTYPE_THREAD_DELTA_SNAPSHOT: return sizeof(struct thread_delta_snapshot_v2); // This one is only here to make some unit tests work. It should be OK to // remove. case TASK_CRASHINFO_CRASHED_THREADID: return sizeof(uint64_t); default: return 0; } } static inline int kcdata_iter_array_valid(kcdata_iter_t iter) { if (!kcdata_iter_valid(iter)) { return 0; } if (kcdata_iter_type(iter) != KCDATA_TYPE_ARRAY) { return 0; } if (kcdata_iter_array_elem_count(iter) == 0) { return iter.item->size == 0; } if (iter.item->type == KCDATA_TYPE_ARRAY) { uint32_t elem_size = kcdata_iter_array_size_switch(iter); if (elem_size == 0) { return 0; } /* sizes get aligned to the nearest 16. */ return kcdata_iter_array_elem_count(iter) <= iter.item->size / elem_size && iter.item->size % kcdata_iter_array_elem_count(iter) < 16; } else { return (iter.item->type & 0xf) <= iter.item->size && kcdata_iter_array_elem_count(iter) <= iter.item->size - (iter.item->type & 0xf) && (iter.item->size - (iter.item->type & 0xf)) % kcdata_iter_array_elem_count(iter) == 0; } } static inline uint32_t kcdata_iter_array_elem_size(kcdata_iter_t iter) { if (iter.item->type == KCDATA_TYPE_ARRAY) { return kcdata_iter_array_size_switch(iter); } if (kcdata_iter_array_elem_count(iter) == 0) { return 0; } return (iter.item->size - (iter.item->type & 0xf)) / kcdata_iter_array_elem_count(iter); } static inline int kcdata_iter_container_valid(kcdata_iter_t iter) { return kcdata_iter_valid(iter) && kcdata_iter_type(iter) == KCDATA_TYPE_CONTAINER_BEGIN && iter.item->size >= sizeof(uint32_t); } static inline uint32_t kcdata_iter_container_type(kcdata_iter_t iter) { return *(uint32_t *) kcdata_iter_payload(iter); } static inline uint64_t kcdata_iter_container_id(kcdata_iter_t iter) { return iter.item->flags; } #define KCDATA_ITER_FOREACH(iter) for(; kcdata_iter_valid(iter) && iter.item->type != KCDATA_TYPE_BUFFER_END; iter = kcdata_iter_next(iter)) #define KCDATA_ITER_FOREACH_FAILED(iter) (!kcdata_iter_valid(iter) || (iter).item->type != KCDATA_TYPE_BUFFER_END) static inline kcdata_iter_t kcdata_iter_find_type(kcdata_iter_t iter, uint32_t type) { KCDATA_ITER_FOREACH(iter) { if (kcdata_iter_type(iter) == type) { return iter; } } return kcdata_invalid_iter; } static inline int kcdata_iter_data_with_desc_valid(kcdata_iter_t iter, uint32_t minsize) { return kcdata_iter_valid(iter) && kcdata_iter_size(iter) >= KCDATA_DESC_MAXLEN + minsize && ((char*)kcdata_iter_payload(iter))[KCDATA_DESC_MAXLEN - 1] == 0; } static inline char * kcdata_iter_string(kcdata_iter_t iter, uint32_t offset) { if (offset > kcdata_iter_size(iter)) { return NULL; } uint32_t maxlen = kcdata_iter_size(iter) - offset; char *s = ((char*)kcdata_iter_payload(iter)) + offset; if (strnlen(s, maxlen) < maxlen) { return s; } else { return NULL; } } static inline void kcdata_iter_get_data_with_desc(kcdata_iter_t iter, char **desc_ptr, void **data_ptr, uint32_t *size_ptr) { if (desc_ptr) { *desc_ptr = (char *)kcdata_iter_payload(iter); } if (data_ptr) { *data_ptr = (void *)((uintptr_t)kcdata_iter_payload(iter) + KCDATA_DESC_MAXLEN); } if (size_ptr) { *size_ptr = kcdata_iter_size(iter) - KCDATA_DESC_MAXLEN; } } #endif /* !__has_ptrcheck */ #endif |