|
root / base / usr / src / cmd / sgs / include
include Plain Text 8419 lines 313.2 KB
   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
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
3231
3232
3233
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
3692
3693
3694
3695
3696
3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
3818
3819
3820
3821
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885
3886
3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
3942
3943
3944
3945
3946
3947
3948
3949
3950
3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034
4035
4036
4037
4038
4039
4040
4041
4042
4043
4044
4045
4046
4047
4048
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092
4093
4094
4095
4096
4097
4098
4099
4100
4101
4102
4103
4104
4105
4106
4107
4108
4109
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122
4123
4124
4125
4126
4127
4128
4129
4130
4131
4132
4133
4134
4135
4136
4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220
4221
4222
4223
4224
4225
4226
4227
4228
4229
4230
4231
4232
4233
4234
4235
4236
4237
4238
4239
4240
4241
4242
4243
4244
4245
4246
4247
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
4507
4508
4509
4510
4511
4512
4513
4514
4515
4516
4517
4518
4519
4520
4521
4522
4523
4524
4525
4526
4527
4528
4529
4530
4531
4532
4533
4534
4535
4536
4537
4538
4539
4540
4541
4542
4543
4544
4545
4546
4547
4548
4549
4550
4551
4552
4553
4554
4555
4556
4557
4558
4559
4560
4561
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
4731
4732
4733
4734
4735
4736
4737
4738
4739
4740
4741
4742
4743
4744
4745
4746
4747
4748
4749
4750
4751
4752
4753
4754
4755
4756
4757
4758
4759
4760
4761
4762
4763
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
4824
4825
4826
4827
4828
4829
4830
4831
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842
4843
4844
4845
4846
4847
4848
4849
4850
4851
4852
4853
4854
4855
4856
4857
4858
4859
4860
4861
4862
4863
4864
4865
4866
4867
4868
4869
4870
4871
4872
4873
4874
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
4890
4891
4892
4893
4894
4895
4896
4897
4898
4899
4900
4901
4902
4903
4904
4905
4906
4907
4908
4909
4910
4911
4912
4913
4914
4915
4916
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
4932
4933
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965
4966
4967
4968
4969
4970
4971
4972
4973
4974
4975
4976
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
5022
5023
5024
5025
5026
5027
5028
5029
5030
5031
5032
5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058
5059
5060
5061
5062
5063
5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087
5088
5089
5090
5091
5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
5113
5114
5115
5116
5117
5118
5119
5120
5121
5122
5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
5144
5145
5146
5147
5148
5149
5150
5151
5152
5153
5154
5155
5156
5157
5158
5159
5160
5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675
5676
5677
5678
5679
5680
5681
5682
5683
5684
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
5848
5849
5850
5851
5852
5853
5854
5855
5856
5857
5858
5859
5860
5861
5862
5863
5864
5865
5866
5867
5868
5869
5870
5871
5872
5873
5874
5875
5876
5877
5878
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
5918
5919
5920
5921
5922
5923
5924
5925
5926
5927
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
5962
5963
5964
5965
5966
5967
5968
5969
5970
5971
5972
5973
5974
5975
5976
5977
5978
5979
5980
5981
5982
5983
5984
5985
5986
5987
5988
5989
5990
5991
5992
5993
5994
5995
5996
5997
5998
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011
6012
6013
6014
6015
6016
6017
6018
6019
6020
6021
6022
6023
6024
6025
6026
6027
6028
6029
6030
6031
6032
6033
6034
6035
6036
6037
6038
6039
6040
6041
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
6076
6077
6078
6079
6080
6081
6082
6083
6084
6085
6086
6087
6088
6089
6090
6091
6092
6093
6094
6095
6096
6097
6098
6099
6100
6101
6102
6103
6104
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
6128
6129
6130
6131
6132
6133
6134
6135
6136
6137
6138
6139
6140
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153
6154
6155
6156
6157
6158
6159
6160
6161
6162
6163
6164
6165
6166
6167
6168
6169
6170
6171
6172
6173
6174
6175
6176
6177
6178
6179
6180
6181
6182
6183
6184
6185
6186
6187
6188
6189
6190
6191
6192
6193
6194
6195
6196
6197
6198
6199
6200
6201
6202
6203
6204
6205
6206
6207
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
6228
6229
6230
6231
6232
6233
6234
6235
6236
6237
6238
6239
6240
6241
6242
6243
6244
6245
6246
6247
6248
6249
6250
6251
6252
6253
6254
6255
6256
6257
6258
6259
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270
6271
6272
6273
6274
6275
6276
6277
6278
6279
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
6314
6315
6316
6317
6318
6319
6320
6321
6322
6323
6324
6325
6326
6327
6328
6329
6330
6331
6332
6333
6334
6335
6336
6337
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
6370
6371
6372
6373
6374
6375
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
6502
6503
6504
6505
6506
6507
6508
6509
6510
6511
6512
6513
6514
6515
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
6542
6543
6544
6545
6546
6547
6548
6549
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559
6560
6561
6562
6563
6564
6565
6566
6567
6568
6569
6570
6571
6572
6573
6574
6575
6576
6577
6578
6579
6580
6581
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
6730
6731
6732
6733
6734
6735
6736
6737
6738
6739
6740
6741
6742
6743
6744
6745
6746
6747
6748
6749
6750
6751
6752
6753
6754
6755
6756
6757
6758
6759
6760
6761
6762
6763
6764
6765
6766
6767
6768
6769
6770
6771
6772
6773
6774
6775
6776
6777
6778
6779
6780
6781
6782
6783
6784
6785
6786
6787
6788
6789
6790
6791
6792
6793
6794
6795
6796
6797
6798
6799
6800
6801
6802
6803
6804
6805
6806
6807
6808
6809
6810
6811
6812
6813
6814
6815
6816
6817
6818
6819
6820
6821
6822
6823
6824
6825
6826
6827
6828
6829
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839
6840
6841
6842
6843
6844
6845
6846
6847
6848
6849
6850
6851
6852
6853
6854
6855
6856
6857
6858
6859
6860
6861
6862
6863
6864
6865
6866
6867
6868
6869
6870
6871
6872
6873
6874
6875
6876
6877
6878
6879
6880
6881
6882
6883
6884
6885
6886
6887
6888
6889
6890
6891
6892
6893
6894
6895
6896
6897
6898
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912
6913
6914
6915
6916
6917
6918
6919
6920
6921
6922
6923
6924
6925
6926
6927
6928
6929
6930
6931
6932
6933
6934
6935
6936
6937
6938
6939
6940
6941
6942
6943
6944
6945
6946
6947
6948
6949
6950
6951
6952
6953
6954
6955
6956
6957
6958
6959
6960
6961
6962
6963
6964
6965
6966
6967
6968
6969
6970
6971
6972
6973
6974
6975
6976
6977
6978
6979
6980
6981
6982
6983
6984
6985
6986
6987
6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404
7405
7406
7407
7408
7409
7410
7411
7412
7413
7414
7415
7416
7417
7418
7419
7420
7421
7422
7423
7424
7425
7426
7427
7428
7429
7430
7431
7432
7433
7434
7435
7436
7437
7438
7439
7440
7441
7442
7443
7444
7445
7446
7447
7448
7449
7450
7451
7452
7453
7454
7455
7456
7457
7458
7459
7460
7461
7462
7463
7464
7465
7466
7467
7468
7469
7470
7471
7472
7473
7474
7475
7476
7477
7478
7479
7480
7481
7482
7483
7484
7485
7486
7487
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497
7498
7499
7500
7501
7502
7503
7504
7505
7506
7507
7508
7509
7510
7511
7512
7513
7514
7515
7516
7517
7518
7519
7520
7521
7522
7523
7524
7525
7526
7527
7528
7529
7530
7531
7532
7533
7534
7535
7536
7537
7538
7539
7540
7541
7542
7543
7544
7545
7546
7547
7548
7549
7550
7551
7552
7553
7554
7555
7556
7557
7558
7559
7560
7561
7562
7563
7564
7565
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578
7579
7580
7581
7582
7583
7584
7585
7586
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608
7609
7610
7611
7612
7613
7614
7615
7616
7617
7618
7619
7620
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631
7632
7633
7634
7635
7636
7637
7638
7639
7640
7641
7642
7643
7644
7645
7646
7647
7648
7649
7650
7651
7652
7653
7654
7655
7656
7657
7658
7659
7660
7661
7662
7663
7664
7665
7666
7667
7668
7669
7670
7671
7672
7673
7674
7675
7676
7677
7678
7679
7680
7681
7682
7683
7684
7685
7686
7687
7688
7689
7690
7691
7692
7693
7694
7695
7696
7697
7698
7699
7700
7701
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722
7723
7724
7725
7726
7727
7728
7729
7730
7731
7732
7733
7734
7735
7736
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758
7759
7760
7761
7762
7763
7764
7765
7766
7767
7768
7769
7770
7771
7772
7773
7774
7775
7776
7777
7778
7779
7780
7781
7782
7783
7784
7785
7786
7787
7788
7789
7790
7791
7792
7793
7794
7795
7796
7797
7798
7799
7800
7801
7802
7803
7804
7805
7806
7807
7808
7809
7810
7811
7812
7813
7814
7815
7816
7817
7818
7819
7820
7821
7822
7823
7824
7825
7826
7827
7828
7829
7830
7831
7832
7833
7834
7835
7836
7837
7838
7839
7840
7841
7842
7843
7844
7845
7846
7847
7848
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858
7859
7860
7861
7862
7863
7864
7865
7866
7867
7868
7869
7870
7871
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882
7883
7884
7885
7886
7887
7888
7889
7890
7891
7892
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902
7903
7904
7905
7906
7907
7908
7909
7910
7911
7912
7913
7914
7915
7916
7917
7918
7919
7920
7921
7922
7923
7924
7925
7926
7927
7928
7929
7930
7931
7932
7933
7934
7935
7936
7937
7938
7939
7940
7941
7942
7943
7944
7945
7946
7947
7948
7949
7950
7951
7952
7953
7954
7955
7956
7957
7958
7959
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981
7982
7983
7984
7985
7986
7987
7988
7989
7990
7991
7992
7993
7994
7995
7996
7997
7998
7999
8000
8001
8002
8003
8004
8005
8006
8007
8008
8009
8010
8011
8012
8013
8014
8015
8016
8017
8018
8019
8020
8021
8022
8023
8024
8025
8026
8027
8028
8029
8030
8031
8032
8033
8034
8035
8036
8037
8038
8039
8040
8041
8042
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052
8053
8054
8055
8056
8057
8058
8059
8060
8061
8062
8063
8064
8065
8066
8067
8068
8069
8070
8071
8072
8073
8074
8075
8076
8077
8078
8079
8080
8081
8082
8083
8084
8085
8086
8087
8088
8089
8090
8091
8092
8093
8094
8095
8096
8097
8098
8099
8100
8101
8102
8103
8104
8105
8106
8107
8108
8109
8110
8111
8112
8113
8114
8115
8116
8117
8118
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148
8149
8150
8151
8152
8153
8154
8155
8156
8157
8158
8159
8160
8161
8162
8163
8164
8165
8166
8167
8168
8169
8170
8171
8172
8173
8174
8175
8176
8177
8178
8179
8180
8181
8182
8183
8184
8185
8186
8187
8188
8189
8190
8191
8192
8193
8194
8195
8196
8197
8198
8199
8200
8201
8202
8203
8204
8205
8206
8207
8208
8209
8210
8211
8212
8213
8214
8215
8216
8217
8218
8219
8220
8221
8222
8223
8224
8225
8226
8227
8228
8229
8230
8231
8232
8233
8234
8235
8236
8237
8238
8239
8240
8241
8242
8243
8244
8245
8246
8247
8248
8249
8250
8251
8252
8253
8254
8255
8256
8257
8258
8259
8260
8261
8262
8263
8264
8265
8266
8267
8268
8269
8270
8271
8272
8273
8274
8275
8276
8277
8278
8279
8280
8281
8282
8283
8284
8285
8286
8287
8288
8289
8290
8291
8292
8293
8294
8295
8296
8297
8298
8299
8300
8301
8302
8303
8304
8305
8306
8307
8308
8309
8310
8311
8312
8313
8314
8315
8316
8317
8318
8319
8320
8321
8322
8323
8324
8325
8326
8327
8328
8329
8330
8331
8332
8333
8334
8335
8336
8337
8338
8339
8340
8341
8342
8343
8344
8345
8346
8347
8348
8349
8350
8351
8352
8353
8354
8355
8356
8357
8358
8359
8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371
8372
8373
8374
8375
8376
8377
8378
8379
8380
8381
8382
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394
8395
8396
8397
8398
8399
8400
8401
8402
8403
8404
8405
8406
8407
8408
8409
8410
8411
8412
8413
8414
8415
8416
8417
8418
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
 */

#ifndef	__LIBELF_H
#define	__LIBELF_H

/*
 * Version of libelf.h that supplies definitions for APIs that
 * are private to the linker package. Includes the standard libelf.h
 * and then supplements it with the private additions.
 */

#include <libelf.h>
#include <gelf.h>

#ifdef	__cplusplus
extern "C" {
#endif

typedef void _elf_execfill_func_t(void *, off_t, size_t);

extern void		_elf_execfill(_elf_execfill_func_t *);
extern size_t		_elf_getnextoff(Elf *);
extern off_t		_elf_getarhdrbase(Elf *);
extern size_t		_elf_getarsymwordsize(Elf *);
extern Elf64_Off	_elf_getxoff(Elf_Data *);
extern GElf_Xword	_gelf_getdyndtflags_1(Elf *);
extern GElf_Xword	_gelf_getdynval(Elf *, GElf_Sxword);
extern int		_elf_swap_wrimage(Elf *);
extern uint_t		_elf_sys_encoding(void);

#ifdef	__cplusplus
}
#endif

#endif	/* __LIBELF_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 *
 * Wrapper around the <sys/machelf.h> header that adds
 * definitions used by SGS.
 */

#ifndef	_MACHELF_H
#define	_MACHELF_H

#include <sys/machelf.h>
#include <string.h>		/* memcpy() */

/*
 * Make machine class dependent functions transparent to the common code
 */

/*
 * Note on ELF_R_TYPE: 64-bit sparc relocations require the use of
 * ELF64_R_TYPE_ID instead of the ELF64_R_TYPE macro used for all
 * other platforms. So our ELF_R_TYPE macro requires the caller to
 * supply the machine type.
 */


#if	defined(_ELF64)
#define	ELF_R_TYPE(_info, _mach)  \
	(((_mach) == EM_SPARCV9) ? ELF64_R_TYPE_ID(_info) : ELF64_R_TYPE(_info))
#define	ELF_R_INFO			ELF64_R_INFO
#define	ELF_R_SYM			ELF64_R_SYM
#define	ELF_R_TYPE_DATA(x)		ELF64_R_TYPE_DATA(x)
#define	ELF_R_TYPE_INFO(xoff, type)	ELF64_R_TYPE_INFO(xoff, type)
#define	ELF_ST_BIND			ELF64_ST_BIND
#define	ELF_ST_TYPE			ELF64_ST_TYPE
#define	ELF_ST_INFO			ELF64_ST_INFO
#define	ELF_ST_VISIBILITY		ELF64_ST_VISIBILITY
#define	ELF_M_SYM			ELF64_M_SYM
#define	ELF_M_SIZE			ELF64_M_SIZE
#define	ELF_M_INFO			ELF64_M_INFO
#define	ELF_C_SYM			ELF64_C_SYM
#define	ELF_C_GROUP			ELF64_C_GROUP
#define	ELF_C_INFO			ELF64_C_INFO
#define	elf_checksum			elf64_checksum
#define	elf_fsize			elf64_fsize
#define	elf_getehdr			elf64_getehdr
#define	elf_getphdr			elf64_getphdr
#define	elf_newehdr			elf64_newehdr
#define	elf_newphdr			elf64_newphdr
#define	elf_getshdr			elf64_getshdr
#define	elf_xlatetof			elf64_xlatetof
#define	elf_xlatetom			elf64_xlatetom
#else /* _ELF64 */
#define	ELF_R_TYPE(_info, _mach)	ELF32_R_TYPE(_info)
#define	ELF_R_INFO			ELF32_R_INFO
#define	ELF_R_SYM			ELF32_R_SYM
/* Elf64 can hide extra offset in r_info */
#define	ELF_R_TYPE_DATA(x)		(0)
#define	ELF_R_TYPE_INFO(xoff, type)	(type)
#define	ELF_ST_BIND			ELF32_ST_BIND
#define	ELF_ST_TYPE			ELF32_ST_TYPE
#define	ELF_ST_INFO			ELF32_ST_INFO
#define	ELF_ST_VISIBILITY		ELF32_ST_VISIBILITY
#define	ELF_M_SYM			ELF32_M_SYM
#define	ELF_M_SIZE			ELF32_M_SIZE
#define	ELF_M_INFO			ELF32_M_INFO
#define	ELF_C_SYM			ELF32_C_SYM
#define	ELF_C_GROUP			ELF32_C_GROUP
#define	ELF_C_INFO			ELF32_C_INFO
#define	elf_checksum			elf32_checksum
#define	elf_fsize			elf32_fsize
#define	elf_getehdr			elf32_getehdr
#define	elf_getphdr			elf32_getphdr
#define	elf_newehdr			elf32_newehdr
#define	elf_newphdr			elf32_newphdr
#define	elf_getshdr			elf32_getshdr
#define	elf_xlatetof			elf32_xlatetof
#define	elf_xlatetom			elf32_xlatetom
#endif	/* _ELF32 */


/*
 * Macros for swapping bytes. The type of the argument must
 * match the type given in the macro name.
 */
#define	BSWAP_HALF(_half) \
	(((_half) << 8) | ((_half) >> 8))

#define	BSWAP_WORD(_word) \
	((((_word) << 24) | (((_word) & 0xff00) << 8) | \
	(((_word) >> 8) & 0xff00) | ((_word) >> 24)))

#define	BSWAP_LWORD(_lword) \
	(((_lword) << 56) | \
	(((_lword) & 0x0000ff00) << 40) | \
	(((_lword) & 0x00ff0000) << 24) | \
	(((_lword) & 0xff000000) << 8) | \
	(((_lword) >> 8)  & 0xff000000) | \
	(((_lword) >> 24) & 0x00ff0000) | \
	(((_lword) >> 40) & 0x0000ff00) | \
	((_lword) >> 56))	/* Lword is unsigned - 0 bits enter from left */


#if	defined(_ELF64)
#define	BSWAP_XWORD(_xword) BSWAP_LWORD(_xword)
#else
#define	BSWAP_XWORD(_xword) BSWAP_WORD(_xword)
#endif

/*
 * Macros for assigning Half/Word/Xword items from one location to
 * another that are safe no matter what the data alignment rules of the
 * running platform are. Variants exist to swap the data byteorder
 * at the same time, or not.
 *
 * These macros are useful for code that accesses data that is aligned
 * for a different system architecture, as occurs in cross linking.
 *
 * All of these macros assume the arguments are passed as pointers to
 * bytes (signed or unsigned).
 */

#define	UL_ASSIGN_HALF(_dst, _src) (void) \
	((_dst)[0] = (_src)[0],	(_dst)[1] = (_src)[1])
#define	UL_ASSIGN_WORD(_dst, _src) (void) \
	((_dst)[0] = (_src)[0],	(_dst)[1] = (_src)[1], \
	(_dst)[2] = (_src)[2], 	(_dst)[3] = (_src)[3])
#define	UL_ASSIGN_LWORD(_dst, _src) (void) memcpy(_dst, (_src), sizeof (Lword))
#if	defined(_ELF64)
#define	UL_ASSIGN_XWORD(_dst, _src) UL_ASSIGN_LWORD(_dst, _src)
#else
#define	UL_ASSIGN_XWORD(_xword) UL_ASSIGN_WORD(_xword)
#endif

#define	UL_ASSIGN_BSWAP_HALF(_dst, _src) (void) \
	((_dst)[0] = (_src)[1],	(_dst)[1] = (_src)[0])
#define	UL_ASSIGN_BSWAP_WORD(_dst, _src) (void) \
	((_dst)[0] = (_src)[3],	(_dst)[1] = (_src)[2], \
	(_dst)[2] = (_src)[1],	(_dst)[3] = (_src)[0])
#define	UL_ASSIGN_BSWAP_LWORD(_dst, _src) (void) \
	((_dst)[0] = (_src)[7],	(_dst)[1] = (_src)[6], \
	(_dst)[2] = (_src)[5],	(_dst)[3] = (_src)[4], \
	(_dst)[4] = (_src)[3],	(_dst)[5] = (_src)[2], \
	(_dst)[6] = (_src)[1],	(_dst)[7] = (_src)[0])
#if	defined(_ELF64)
#define	UL_ASSIGN_BSWAP_XWORD(_dst, _src) UL_ASSIGN_BSWAP_LWORD(_dst, _src)
#else
#define	UL_ASSIGN_BSWAP_XWORD(_dst, _src) UL_ASSIGN_BSWAP_WORD(_dst, _src)
#endif


#endif /* _MACHELF_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	__STRING_TABLE_DOT_H
#define	__STRING_TABLE_DOT_H

#include <sys/types.h>
#include <sys/avl.h>
#include <string_table.h>

#ifdef __cplusplus
extern "C" {
#endif

/*
 * A string is represented in a string table using two values: length, and
 * value.  Grouping all the strings of a given length together allows for
 * efficient matching of tail strings, as each input string value is hashed.
 * Each string table uses a 2-level AVL tree of AVL trees to represent this
 * organization.
 *
 * The outer (main) AVL tree contains LenNode structures.  The search key for
 * nodes on this main tree is the string length.  Each such node represents
 * all strings of a given length, and all strings of that length are found
 * within.
 *
 * The strings within each LenNode are maintained using a secondary AVL tree
 * of StrNode structures.  The search key for this inner tree is the string
 * itself.  The strings are maintained in lexical order.
 */
typedef struct {
	avl_node_t	sn_avlnode;	/* AVL book-keeping */
	const char	*sn_str;	/* string */
	size_t		sn_refcnt;	/* reference count */
} StrNode;

typedef struct {
	avl_node_t	ln_avlnode;	/* AVL book-keeping */
	avl_tree_t	*ln_strtree;	/* AVL tree of associated strings */
	size_t		ln_strlen;	/* length of associated strings */
} LenNode;

/*
 * Define a master string data item.  Other strings may be suffixes of this
 * string.  The final string table will consist of the master string values,
 * laid end to end, with the other strings referencing their tails.
 */
typedef	struct str_master	Str_master;

struct str_master {
	const char	*sm_str;	/* pointer to master string */
	Str_master	*sm_next;	/* used for tracking master strings */
	size_t		sm_strlen;	/* length of master string */
	uint_t		sm_hashval;	/* hashval of master string */
	size_t		sm_stroff;	/* offset into destination strtab */
};

/*
 * Define a hash data item.  This item represents an individual string that has
 * been input into the String hash table.  The string may either be a suffix of
 * another string, or a master string.
 */
typedef	struct str_hash	Str_hash;

struct str_hash {
	size_t		hi_strlen;	/* string length */
	size_t		hi_refcnt;	/* number of references to str */
	uint_t		hi_hashval;	/* hash for string */
	Str_master	*hi_mstr;	/* pointer to master string */
	Str_hash	*hi_next;	/* next entry in hash bucket */
};

/*
 * Controlling data structure for a String Table.
 */
struct str_tbl {
	avl_tree_t	*st_lentree;		/* AVL tree of string lengths */
	char		*st_strbuf;		/* string buffer */
	Str_hash	**st_hashbcks;		/* hash buckets */
	Str_master	*st_mstrlist;		/* list of all master strings */
	size_t		st_fullstrsize;		/* uncompressed table size */
	size_t		st_nextoff;		/* next available string */
	size_t		st_strsize;		/* compressed size */
	size_t		st_strcnt;		/* number of strings */
	uint_t		st_hbckcnt;		/* number of buckets in */
						/*    hashlist */
	uint_t		st_flags;
};

#define	FLG_STTAB_COMPRESS	0x01		/* compressed string table */
#define	FLG_STTAB_COOKED	0x02		/* offset has been assigned */

/*
 * Starting value for use with string hashing functions inside of string_table.c
 */
#define	HASHSEED		5381

#ifdef __cplusplus
}
#endif

#endif /* __STRING_TABLE_DOT_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 *
 * Define an Alist, a list maintained as a reallocable array, and a for() loop
 * macro to generalize its traversal.  Note that the array can be reallocated
 * as it is being traversed, thus the offset of each element is recomputed from
 * the start of the structure.
 */

#ifndef	_ALIST_H
#define	_ALIST_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/types.h>
#include <sys/machelf.h>

/*
 * An Alist implements array lists. The functionality is similar to
 * that of a linked list. However, an Alist is represented by a single
 * contigious allocation of memory. The head of the memory is a header
 * that contains control information for the list. Following the header
 * is an array used to hold the user data. In the type definitions that
 * follow, we define these as an array with a single element, but when
 * we allocate the memory, we actually allocate the amount of memory needed.
 *
 * There are two "flavors" of array list:
 *
 *	Alist - Contain arbitrary data, usually structs.
 *	APlist - Contain pointers to data allocated elsewhere.
 *
 * This differentiation is useful, because pointer lists are heavily
 * used, and support a slightly different set of operations that are
 * unique to their purpose.
 *
 * Array lists are initially represented by a NULL pointer. The memory
 * for the list is only allocated if an item is inserted. This is very
 * efficient for data structures that may or may not be needed for a
 * given linker operation --- you only pay for what you use. In addition:
 *
 *	- Array lists grow as needed (memory is reallocated as necessary)
 *	- Data is kept contiguously (no unused holes in between elements)
 *		at the beginning of the data area. This locality has
 *		good cache behavior, as access to adjacent items are
 *		highly likely to be in the same page of memory.
 *	- Insert/Delete operations at the end of the list are very
 *		efficient. However, insert/delete operations elsewhere
 *		will cause a relatively expensive overlapped memory
 *		copy of the data following the insert/delete location.
 *	- As with any generic memory alloctor (i.e. malloc()/free()),
 *		array lists are not type safe for the data they contain.
 *		Data is managed as (void *) pointers to data of a given
 *		length, so the Alist module cannot prevent the caller from
 *		inserting/extracting the wrong type of data. The caller
 *		must guard against this.
 *	- To free an array list, simply call the standard free() function
 *		on the list pointer.
 */



/*
 * Aliste is used to represent list indexes, offsets, and sizes.
 */
typedef	size_t	Aliste;



/*
 * Alist is used to hold non-pointer items --- usually structs:
 *	- There must be an even number of Aliste fields before the
 *		al_data field. This ensures that al_data will have
 *		an alignment of 8, no matter whether sizeof(Aliste)
 *		is 4 or 8. That means that al_data will have sufficient
 *		alignment for any use, just like memory allocated via
 *		malloc().
 *	- al_nitems and al_next are redundant, in that they are
 *		directly related:
 *			al_next = al_nitems * al_size
 *		We do this to make ALIST_TRAVERSE_BYOFFSET maximally
 *		efficient. This doesn't waste space, because of the
 *		requirement to have an even # of Alist fields (above).
 *
 * Note that Alists allow the data to be referenced by 0 based array
 * index, or by their byte offset from the start of the Alist memory
 * allocation. The index form is preferred for most use, as it is simpler.
 * However, by-offset access is used by rtld link maps, and this ability
 * is convenient in that case.
 */
typedef struct {
	Aliste 		al_arritems;	/* # of items in al_data allocation */
	Aliste 		al_nitems;	/* # items (index of next avail item) */
	Aliste 		al_next;	/* offset of next available al_data[] */
	Aliste		al_size;	/* size of each al_data[] item */
	void 		*al_data[1];	/* data (can grow) */
} Alist;

/*
 * APlist is a variant of Alist that contains pointers. There are several
 * benefits to this special type:
 *	- API is simpler
 *	- Pointers are used directly, instead of requiring a
 *		pointer-to-pointer double indirection.
 *	- The implementation is slightly more efficient.
 *	- Operations that make particular sense for pointers
 *		can be supported without confusing the API for the
 *		regular Alists.
 */
typedef struct {
	Aliste		apl_arritems;	/* # of items in apl_data allocation */
	Aliste 		apl_nitems;	/* # items (index of next avail item) */
	void		*apl_data[1];	/* data area: (arrcnt * size) bytes */
} APlist;

#ifdef	_SYSCALL32			/* required by librtld_db */
typedef	struct {
	Elf32_Word	apl_arritems;
	Elf32_Word	apl_nitems;
	Elf32_Addr	apl_data[1];
} APlist32;
#endif	/* _SYSCALL32 */

/*
 * The ALIST_OFF_DATA and APLIST_OFF_DATA macros give the byte offset
 * from the start of an array list to the first byte of the data area
 * used to hold user data. The same trick used by the standard offsetof()
 * macro is used.
 */
#define	ALIST_OFF_DATA	((size_t)(((Alist *)0)->al_data))
#define	APLIST_OFF_DATA	((size_t)(((APlist *)0)->apl_data))


/*
 * The TRAVERSE macros are intended to be used within a for(), and
 * cause the resulting loop to iterate over each item in the loop,
 * in order.
 *	ALIST_TRAVERSE: Traverse over the items in an Alist,
 *		using the zero based item array index to refer to
 *		each item.
 *	ALIST_TRAVERSE_BY_OFFSET: Traverse over the items in an
 *		Alist using the byte offset from the head of the
 *		Alist pointer to refer to each item. It should be noted
 *		that the first such offset is given by ALIST_OFF_DATA,
 *		and as such, there will never be a 0 offset. Some code
 *		uses this fact to treat 0 as a reserved value with
 *		special meaning.
 *
 *		By-offset access is convenient for some parts of
 *		rtld, where a value of 0 is used to indicate an
 *		uninitialized link map control.
 *
 *	APLIST_TRAVERSE: Traverse over the pointers in an APlist, using
 *		the zero based item array index to refer to each pointer.
 */

/*
 * Within the loop:
 *
 *	LIST - Pointer to Alist structure for list
 *	IDX - The current item index
 *	OFF - The current item offset
 *	DATA - Pointer to item
 */
#define	ALIST_TRAVERSE(LIST, IDX, DATA) \
	(IDX) = 0, \
	((LIST) != NULL) && ((DATA) = (void *)(LIST)->al_data); \
	\
	((LIST) != NULL) && ((IDX) < (LIST)->al_nitems); \
	\
	(IDX)++, \
	(DATA) = (void *) (((LIST)->al_size * (IDX)) + (char *)(LIST)->al_data)

#define	ALIST_TRAVERSE_BY_OFFSET(LIST, OFF, DATA) \
	(((LIST) != NULL) && ((OFF) = ALIST_OFF_DATA) && \
	(((DATA) = (void *)((char *)(LIST) + (OFF))))); \
	\
	(((LIST) != NULL) && ((OFF) < (LIST)->al_next)); \
	\
	(((OFF) += ((LIST)->al_size)), \
	((DATA) = (void *)((char *)(LIST) + (OFF))))

/*
 * Within the loop:
 *
 *	LIST - Pointer to APlist structure for list
 *	IDX - The current item index
 *	PTR - item value
 *
 * Note that this macro is designed to ensure that PTR retains the
 * value of the final pointer in the list after exiting the for loop,
 * and to avoid dereferencing an out of range address. This is done by
 * doing the dereference in the middle expression, using the comma
 * operator to ensure that a NULL pointer won't stop the loop.
 */
#define	APLIST_TRAVERSE(LIST, IDX, PTR) \
	(IDX) = 0; \
	\
	((LIST) != NULL) && ((IDX) < (LIST)->apl_nitems) && \
	(((PTR) = ((LIST)->apl_data)[IDX]), 1); \
	\
	(IDX)++


/*
 * Possible values returned by aplist_test()
 */
typedef enum {
	ALE_ALLOCFAIL = 0,	/* memory allocation error */
	ALE_EXISTS =	1,	/* alist entry already exists */
	ALE_NOTFND =	2,	/* item not found and insert not required */
	ALE_CREATE =	3	/* alist entry created */
} aplist_test_t;


/*
 * Access to an Alist item by index or offset. This is needed because the
 * size of an item in an Alist is not known by the C compiler, and we
 * have to do the indexing arithmetic explicitly.
 *
 * For an APlist, index the apl_data field directly --- No macro is needed.
 */
#define	alist_item(_lp, _idx) \
	((void *)(ALIST_OFF_DATA + ((_idx) * (_lp)->al_size) + (char *)(_lp)))
#define	alist_item_by_offset(_lp, _off) \
	((void *)((_off) + (char *)(_lp)))

/*
 * The number of items currently found in a list (nitems), and the total number
 * of slots in the current data allocation (arritems).  These macros handle the
 * case where the list has not been allocated yet.
 */
#define	alist_nitems(_lp)	(((_lp) == NULL) ? 0 : (_lp)->al_nitems)
#define	aplist_nitems(_lp)	(((_lp) == NULL) ? 0 : (_lp)->apl_nitems)
#define	alist_arritems(_lp)	(((_lp) == NULL) ? 0 : (_lp)->al_arritems)
#define	aplist_arritems(_lp)	(((_lp) == NULL) ? 0 : (_lp)->apl_arritems)


extern void		*alist_append(Alist **, const void *, size_t, Aliste);
extern void		alist_delete(Alist *, Aliste *);
extern void		alist_delete_by_offset(Alist *, Aliste *);
extern void		*alist_insert(Alist **, const void *, size_t,
			    Aliste, Aliste);
extern void		*alist_insert_by_offset(Alist **, const void *, size_t,
			    Aliste, Aliste);
extern void		alist_reset(Alist *);


extern void		*aplist_append(APlist **, const void *, Aliste);
extern void		aplist_delete(APlist *, Aliste *);
extern int		aplist_delete_value(APlist *, const void *);
extern void		*aplist_insert(APlist **, const void *,
			    Aliste, Aliste idx);
extern void		aplist_reset(APlist *);
extern aplist_test_t	aplist_test(APlist **, const void *, Aliste);

#ifdef	__cplusplus
}
#endif

#endif /* _ALIST_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 *	Copyright (c) 1988 AT&T
 *	  All Rights Reserved
 *
 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
 * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
 * Copyright (c) 2018, Joyent, Inc.
 * Copyright 2016 RackTop Systems.
 * Copyright 2024 Oxide Computer Company
 */

#ifndef	_CONV_H
#define	_CONV_H

/*
 * Global include file for conversion library.
 */

#include <stdlib.h>
#include <libelf.h>
#include <dlfcn.h>
#include <libld.h>
#include <sgs.h>
#include <sgsmsg.h>
#include <sys/secflags.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Configuration features available - maintained here (instead of debug.h)
 * to save libconv from having to include debug.h which results in numerous
 * "declared but not used or defined" lint errors.
 *
 * AOUT flags (ADLIBPATH, ASLIBPATH) are unused, but retained so they may
 * still be fully dumped under LD_DEBUG.
 */
#define	CONF_EDLIBPATH	0x000100	/* ELF default library path */
#define	CONF_ESLIBPATH	0x000200	/* ELF secure library path */
#define	CONF_ADLIBPATH	0x000400	/* AOUT default library path */
#define	CONF_ASLIBPATH	0x000800	/* AOUT secure library path */
#define	CONF_DIRCFG	0x001000	/* directory configuration available */
#define	CONF_OBJALT	0x002000	/* object alternatives available */
#define	CONF_MEMRESV	0x004000	/* memory reservation required */
#define	CONF_ENVS	0x008000	/* environment variables available */
#define	CONF_FLTR	0x010000	/* filter information available */
#define	CONF_FEATMSK	0xffff00


/*
 * Valid flags for conv_strproc_extract_value().
 */
#define	CONV_SPEXV_F_NOTRIM	0x0001	/* Do not trim whitespace around '=' */
#define	CONV_SPEXV_F_UCASE	0x0002	/* Convert value to uppercase */
#define	CONV_SPEXV_F_NULLOK	0x0004	 /* Empty ("") value is OK */

/*
 * Buffer types:
 *
 * Many of the routines in this module require the user to supply a
 * buffer into which the desired strings may be written. These are
 * all arrays of characters, and might be defined as simple arrays
 * of char. The problem with that approach is that when such an array
 * is passed to a function, the C language considers it to have the
 * type (char *), without any regard to its length. Not all of our
 * buffers have the same length, and we want to ensure that the compiler
 * will refuse to compile code that passes the wrong type of buffer to
 * a given routine. The solution is to define the buffers as unions
 * that contain the needed array, and then to pass the given union
 * by address. The compiler will catch attempts to pass the wrong type
 * of pointer, and the size of a structure/union is implicit in its type.
 *
 * A nice side effect of this approach is that we can use a union with
 * multiple buffers to handle the cases where a given routine needs
 * more than one type of buffer. The end result is a single buffer large
 * enough to handle any of the subcases, but no larger.
 */

/*
 * Size of buffer used by conv_invalid_val():
 *
 * Various values that can't be matched to a symbolic definition are converted
 * to a numeric string.
 *
 * The buffer size reflects the maximum number of digits needed to
 * display an integer as text, plus a trailing null, and with room for
 * a leading "0x" if hexidecimal display is selected.
 *
 * The 32-bit version of this requires 12 characters, and the 64-bit version
 * needs 22. By using the larger value for both, we can have a single
 * definition, which is necessary for code that is ELFCLASS independent. A
 * nice side benefit is that it lets us dispense with a large number of 32/64
 * buffer size definitions that build off CONV_INV_BUFSIZE, and the macros
 * that would then be needed.
 */
#define	CONV_INV_BUFSIZE		22
typedef union {
	char				buf[CONV_INV_BUFSIZE];
} Conv_inv_buf_t;

/* conv_ehdr_flags() */
#define	CONV_EHDR_FLAGS_BUFSIZE		91
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_EHDR_FLAGS_BUFSIZE];
} Conv_ehdr_flags_buf_t;

/* conv_reject_desc() */
typedef union {
	Conv_inv_buf_t			inv_buf;
	Conv_ehdr_flags_buf_t		flags_buf;
} Conv_reject_desc_buf_t;

/*
 * conv_la_bind()
 */
#define	CONV_LA_BIND_BUFSIZE		56
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_LA_BIND_BUFSIZE];
} Conv_la_bind_buf_t;

/*
 * conv_la_search()
 */
#define	CONV_LA_SEARCH_BUFSIZE		111
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_LA_SEARCH_BUFSIZE];
} Conv_la_search_buf_t;

/*
 * conv_la_symbind()
 */
#define	CONV_LA_SYMBIND_BUFSIZE		113
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_LA_SYMBIND_BUFSIZE];
} Conv_la_symbind_buf_t;

/*
 * conv_cap_val_hw/sf()
 *
 * These sizes are based on the maximum number of capabilities that exist.
 * See common/elfcap.
 */
#define	CONV_CAP_VAL_HW1_BUFSIZE	528
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_CAP_VAL_HW1_BUFSIZE];
} Conv_cap_val_hw1_buf_t;

#define	CONV_CAP_VAL_HW2_BUFSIZE	632
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_CAP_VAL_HW2_BUFSIZE];
} Conv_cap_val_hw2_buf_t;

#define	CONV_CAP_VAL_SF1_BUFSIZE	73
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_CAP_VAL_SF1_BUFSIZE];
} Conv_cap_val_sf1_buf_t;

#define	CONV_CAP_VAL_HW3_BUFSIZE	66
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_CAP_VAL_HW3_BUFSIZE];
} Conv_cap_val_hw3_buf_t;

/* conv_cap_val_buf() */
typedef union {
	Conv_inv_buf_t			inv_buf;
	Conv_cap_val_hw1_buf_t		cap_val_hw1_buf;
	Conv_cap_val_sf1_buf_t		cap_val_sf1_buf;
	Conv_cap_val_hw2_buf_t		cap_val_hw2_buf;
	Conv_cap_val_hw3_buf_t		cap_val_hw3_buf;
} Conv_cap_val_buf_t;

/* conv_config_feat() */
#define	CONV_CONFIG_FEAT_BUFSIZE	204
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_CONFIG_FEAT_BUFSIZE];
} Conv_config_feat_buf_t;

/* conv_config_obj() */
#define	CONV_CONFIG_OBJ_BUFSIZE		164
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_CONFIG_OBJ_BUFSIZE];
} Conv_config_obj_buf_t;

/* conv_dl_mode() */
#define	CONV_DL_MODE_BUFSIZE		132
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_DL_MODE_BUFSIZE];
} Conv_dl_mode_buf_t;

/* conv_dl_flag() */
#define	CONV_DL_FLAG_BUFSIZE		185
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_DL_FLAG_BUFSIZE];
} Conv_dl_flag_buf_t;

/* conv_grphdl_flags() */
#define	CONV_GRPHDL_FLAGS_BUFSIZE	78
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_GRPHDL_FLAGS_BUFSIZE];
} Conv_grphdl_flags_buf_t;

/* conv_grpdesc_flags() */
#define	CONV_GRPDESC_FLAGS_BUFSIZE	91
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_GRPDESC_FLAGS_BUFSIZE];
} Conv_grpdesc_flags_buf_t;

/* conv_seg_flags() */
#define	CONV_SEG_FLAGS_BUFSIZE		241
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_SEG_FLAGS_BUFSIZE];
} Conv_seg_flags_buf_t;

/* conv_dyn_posflag1() */
#define	CONV_DYN_POSFLAG1_BUFSIZE	72
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_DYN_POSFLAG1_BUFSIZE];
} Conv_dyn_posflag1_buf_t;

/* conv_dyn_flag() */
#define	CONV_DYN_FLAG_BUFSIZE		85
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_DYN_FLAG_BUFSIZE];
} Conv_dyn_flag_buf_t;

/* conv_dyn_flag1() */
#define	CONV_DYN_FLAG1_BUFSIZE		361
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_DYN_FLAG1_BUFSIZE];
} Conv_dyn_flag1_buf_t;

/* conv_dyn_feature1() */
#define	CONV_DYN_FEATURE1_BUFSIZE	54
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_DYN_FEATURE1_BUFSIZE];
} Conv_dyn_feature1_buf_t;

/* conv_bnd_type() */
#define	CONV_BND_TYPE_BUFSIZE		51
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_BND_TYPE_BUFSIZE];
} Conv_bnd_type_buf_t;

/* conv_bnd_obj() */
#define	CONV_BND_OBJ_BUFSIZE		60
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_BND_OBJ_BUFSIZE];
} Conv_bnd_obj_buf_t;

/* conv_phdr_flags() */
#define	CONV_PHDR_FLAGS_BUFSIZE		88
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_PHDR_FLAGS_BUFSIZE];
} Conv_phdr_flags_buf_t;

/* conv_sec_flags() */
#define	CONV_SEC_FLAGS_BUFSIZE		190
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_SEC_FLAGS_BUFSIZE];
} Conv_sec_flags_buf_t;

/* conv_dwarf_ehe() */
#define	CONV_DWARF_EHE_BUFSIZE		43
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_DWARF_EHE_BUFSIZE];
} Conv_dwarf_ehe_buf_t;

/* conv_syminfo_flags() */
#define	CONV_SYMINFO_FLAGS_BUFSIZE	230
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_SYMINFO_FLAGS_BUFSIZE];
} Conv_syminfo_flags_buf_t;

/* conv_cnote_pr_flags() */
#define	CONV_CNOTE_PR_FLAGS_BUFSIZE	254
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_CNOTE_PR_FLAGS_BUFSIZE];
} Conv_cnote_pr_flags_buf_t;

/* conv_cnote_old_pr_flags() */
#define	CONV_CNOTE_OLD_PR_FLAGS_BUFSIZE	174
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_CNOTE_OLD_PR_FLAGS_BUFSIZE];
} Conv_cnote_old_pr_flags_buf_t;

/* conv_cnote_proc_flag() */
#define	CONV_CNOTE_PROC_FLAG_BUFSIZE	39
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_CNOTE_PROC_FLAG_BUFSIZE];
} Conv_cnote_proc_flag_buf_t;

/* conv_prsecflags() */
#define	CONV_PRSECFLAGS_BUFSIZE		57
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_PRSECFLAGS_BUFSIZE];
} Conv_secflags_buf_t;

/* conv_prupanic() */
#define	CONV_PRUPANIC_BUFSIZE		56
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_PRUPANIC_BUFSIZE];
} Conv_upanic_buf_t;

/* conv_cnote_sigset() */
#define	CONV_CNOTE_SIGSET_BUFSIZE	639
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_CNOTE_SIGSET_BUFSIZE];
} Conv_cnote_sigset_buf_t;

/* conv_cnote_fltset() */
#define	CONV_CNOTE_FLTSET_BUFSIZE	511
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_CNOTE_FLTSET_BUFSIZE];
} Conv_cnote_fltset_buf_t;

/* conv_cnote_sysset() */
#define	CONV_CNOTE_SYSSET_BUFSIZE	3227
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_CNOTE_SYSSET_BUFSIZE];
} Conv_cnote_sysset_buf_t;

/* conv_cnote_sa_flags() */
#define	CONV_CNOTE_SA_FLAGS_BUFSIZE	109
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_CNOTE_SA_FLAGS_BUFSIZE];
} Conv_cnote_sa_flags_buf_t;

/* conv_cnote_ss_flags() */
#define	CONV_CNOTE_SS_FLAGS_BUFSIZE	48
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_CNOTE_SS_FLAGS_BUFSIZE];
} Conv_cnote_ss_flags_buf_t;

/* conv_cnote_cc_content() */
#define	CONV_CNOTE_CC_CONTENT_BUFSIZE	103
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_CNOTE_CC_CONTENT_BUFSIZE];
} Conv_cnote_cc_content_buf_t;

/* conv_cnote_auxv_af() */
#define	CONV_CNOTE_AUXV_AF_BUFSIZE	73
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_CNOTE_AUXV_AF_BUFSIZE];
} Conv_cnote_auxv_af_buf_t;

/* conv_ver_flags() */
#define	CONV_VER_FLAGS_BUFSIZE		41
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_VER_FLAGS_BUFSIZE];
} Conv_ver_flags_buf_t;

/* conv_ent_flags() */
#define	CONV_ENT_FLAGS_BUFSIZE		69
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_ENT_FLAGS_BUFSIZE];
} Conv_ent_flags_buf_t;

/* conv_ent_files_flags() */
#define	CONV_ENT_FILES_FLAGS_BUFSIZE	89
typedef union {
	Conv_inv_buf_t			inv_buf;
	char				buf[CONV_ENT_FILES_FLAGS_BUFSIZE];
} Conv_ent_files_flags_buf_t;

/*
 * conv_time()
 *
 * This size is based on the maximum "hour.min.sec.fraction: " time that
 * would be expected of ld().
 */
#define	CONV_TIME_BUFSIZE		18
typedef union {
	char				buf[CONV_TIME_BUFSIZE];
} Conv_time_buf_t;

/*
 * Many conversion routines accept a fmt_flags argument of this type
 * to allow the caller to modify the output. There are two parts to
 * this value:
 *
 *	(1) Format requests (decimal vs hex, etc...)
 *	(2) The low order bits specified by CONV_MASK_FMT_ALT
 *		and retrieved by CONV_TYPE_FMT_ALT are integer
 *		values that specify that an alternate set of
 *		strings should be used.
 *
 * The fmt_flags value is designed such that a caller can always
 * supply a 0 in order to receive default behavior.
 */
typedef int Conv_fmt_flags_t;

/*
 * Type used to represent ELF constants within libconv. This relies on
 * the fact that there are no ELF constants that need more than 32-bits,
 * nor are there any signed values.
 */
typedef uint32_t Conv_elfvalue_t;

/*
 * Most conversion routines are able to provide strings in one of
 * several alternative styles. The bottom 8 bits of Conv_fmt_flags_t
 * are used to specify which strings should be used for a given call
 * to a conversion routine:
 *
 *   DEFAULT
 *	The default string style used by a given conversion routine is
 *	an independent choice made by that routine. Different routines
 *	make different choices, based largely on historical usage and
 *	the perceived common case. It may be an alias for one of the
 *	specific styles listed below, or it may be unique.
 *
 *   DUMP
 *	Style of strings used by dump(1).
 *
 *   FILE
 *	Style of strings used by file(1).
 *
 *   CRLE
 *	Style of strings used by crle(1).
 *
 *   CF
 *	Canonical Form: The string is exactly the same as the name
 *	of the #define macro that defines it in the public header files.
 *	(e.g. STB_LOCAL, not LOCL, LOCAL, LOC, or any other variation).
 *
 *   CFNP
 *	No Prefix Canonical Form: The same strings supplied by CF,
 *	but without their standard prefix. (e.g. LOCAL, instead of STT_LOCAL).
 *
 *   NF
 *	Natural Form: The form of the strings that might typically be entered
 *	via a keyboard by an interactive user. These are usually the strings
 *	from CFNP, converted to lowercase, although in some cases they may
 *	take some other "natural" form. In command completion applications,
 *	lowercase strings appear less formal, and are easier on the eye.
 *
 * Every routine is required to have a default style. The others are optional,
 * and may not be provided if not needed. If a given conversion routine does
 * not support alternative strings for a given CONV_FMT_ALT type, it silently
 * ignores the request and supplies the default set. This means that a utility
 * like dump(1) is free to specify a style like DUMP to every conversion
 * routine. It will receive its special strings if there are any, and
 * the defaults otherwise.
 */
#define	CONV_MASK_FMT_ALT		0xff
#define	CONV_TYPE_FMT_ALT(fmt_flags)	(fmt_flags & CONV_MASK_FMT_ALT)

#define	CONV_FMT_ALT_DEFAULT	0	/* "Standard" strings */
#define	CONV_FMT_ALT_DUMP	1	/* dump(1) */
#define	CONV_FMT_ALT_FILE	2	/* file(1) */
#define	CONV_FMT_ALT_CRLE	3	/* crle(1) */
#define	CONV_FMT_ALT_CF		4	/* Canonical Form */
#define	CONV_FMT_ALT_CFNP	5	/* No Prefix Canonical Form */
#define	CONV_FMT_ALT_NF		6	/* Natural Form */

/*
 * Flags that alter standard formatting for conversion routines.
 * These bits start after the range occupied by CONV_MASK_FMT_ALT.
 */
#define	CONV_FMT_DECIMAL	0x0100	/* conv_invalid_val() should print */
					/*    integer print as decimal */
					/*    (default is hex) */
#define	CONV_FMT_SPACE		0x0200	/* conv_invalid_val() should append */
					/*    a space after the number.  */
#define	CONV_FMT_NOBKT		0x0400	/* conv_expn_field() should omit */
					/*    prefix and suffix strings */

/*
 * A Val_desc structure is used to associate an ELF constant and
 * the message code (Msg) for the string that corresponds to it.
 *
 * Val_desc2 adds v_osabi and v_mach fields to Val_desc, which allows
 * for non-generic mappings that apply only to a specific OSABI/machine.
 * Setting v_osabi to 0 (ELFOSABI_NONE) specifies that any OSABI matches.
 * Similarly, setting v_mach to 0 (EM_MACH) matches any machine. Hence,
 * setting v_osabi and v_mach to 0 in a Val_desc2 results in a generic item,
 * and is equivalent to simply using a Val_desc.
 *
 * These structs are used in two different contexts:
 *
 * 1)	To expand bit-field data items, using conv_expn_field() to
 *	process a NULL terminated array of Val_desc, or conv_expn_field2()
 *	to process a null terminated array of Val_desc2.
 *
 * 2)	To represent sparse ranges of non-bitfield values, referenced via
 *	conv_ds_vd_t or conv_ds_vd2_t descriptors, as described below.
 */
typedef struct {
	Conv_elfvalue_t	v_val;		/* expansion value */
	Msg		v_msg;		/* associated message string code */
} Val_desc;
typedef struct {
	Conv_elfvalue_t	v_val;		/* expansion value */
	uchar_t		v_osabi;	/* OSABI to which entry applies */
	Half		v_mach;		/* Machine to which entry applies */
	Msg		v_msg;		/* associated message string code */
} Val_desc2;

/*
 * The conv_ds_XXX_t structs are used to pull together the information used
 * to map non-bitfield values to strings. They are a variant family, sharing
 * the same initial fields, with a generic "header" definition that can be
 * used to read those common fields and determine which subcase is being
 * seen. We do this instead of using a single struct containing a type code
 * and a union in order to allow for static compile-time initialization.
 *
 * conv_ds_t is the base type, containing the initial fields common to all
 * the variants. Variables of type conv_ds_t are never instantiated. This
 * type exists only to provide a common pointer type that can reference
 * any of the variants safely. In C++, it would be a virtual base class.
 * The fields common to all the variants are:
 *
 *	ds_type: Identifies the variant
 *	ds_baseval/ds_topval: The lower and upper bound of the range
 *		of values represented by this conv_ds_XXX_t descriptor.
 *
 * There are three different variants:
 *    conv_ds_msg_t (ds_type == CONV_DS_MSGARR)
 *	This structure references an array of message codes corresponding
 *	to consecutive ELF values. The first item in the array is the Msg
 *	code for the value given by ds_baseval. Consecutive strings follow
 *	in consecutive order. The final item corresponds to the value given
 *	by ds_topval. Zero (0) Msg values can be used to represent missing
 *	values. Entries with a 0 are quietly ignored.
 *
 *    conv_ds_vd_t (ds_type == CONV_DS_VD)
 *	This structure employs a NULL terminated array of Val_desc structs.
 *	Each Val_desc supplies a mapping from a value in the range
 *	(ds_baseval <= value <= ds_topval). The values described need not
 *	be consecutive, and can be sparse. ds_baseval does not need to
 *	correspond to the first item, and ds_topval need not correspond to
 *	the final item.
 *
 *    conv_ds_vd2_t (ds_type == CONV_DS_VD2)
 *	This structure employs a NULL terminated array of Val_desc2 structs,
 *	rather than Val_desc, adding the ability to specify OSABI and machine
 *	as part of the value/string mapping. It is otherwise the same thing
 *	as CONV_DS_VD.
 */
typedef enum {
	CONV_DS_MSGARR = 0,		/* Array of Msg */
	CONV_DS_VD = 1,			/* Null terminated array of Val_desc */
	CONV_DS_VD2 = 2,		/* Null terminated array of Val_desc2 */
} conv_ds_type_t;

#define	CONV_DS_COMMON_FIELDS \
	conv_ds_type_t	ds_type;	/* Type of data structure used */ \
	uint32_t	ds_baseval;	/* Value of first item */	\
	uint32_t	ds_topval	/* Value of last item */

typedef struct {		/* Virtual base type --- do not instantiate */
	CONV_DS_COMMON_FIELDS;
} conv_ds_t;
typedef struct {
	CONV_DS_COMMON_FIELDS;
	const Msg		*ds_msg;
} conv_ds_msg_t;
typedef struct {
	CONV_DS_COMMON_FIELDS;
	const Val_desc		*ds_vd;
} conv_ds_vd_t;
typedef struct {
	CONV_DS_COMMON_FIELDS;
	const Val_desc2		*ds_vd2;
} conv_ds_vd2_t;

/*
 * The initialization of conv_ds_msg_t can be completely derived from
 * its base value and the array of Msg codes. CONV_DS_MSG_INIT() is used
 * to do that.
 */
#define	CONV_DS_MSG_INIT(_baseval, _arr) \
	CONV_DS_MSGARR, _baseval, \
	_baseval + (sizeof (_arr) / sizeof (_arr[0])) - 1, _arr

/*
 * Null terminated arrays of pointers to conv_ds_XXX_t structs are processed
 * by conv_map_ds() to convert ELF constants to their symbolic names, and by
 * conv_iter_ds() to iterate over all the available value/name combinations.
 *
 * These pointers are formed by casting the address of the specific
 * variant types (described above) to generic base type pointer.
 * CONV_DS_ADDR() is a convenience macro to take the address of
 * one of these variants and turn it into a generic pointer.
 */
#define	CONV_DS_ADDR(_item) ((conv_ds_t *)&(_item))

/*
 * Type used by libconv to represent osabi values passed to iteration
 * functions. The type in the ELF header is uchar_t. However, every possible
 * value 0-255 has a valid meaning, leaving us no extra value to assign
 * to mean "ALL". Using Half for osabi leaves us the top byte to use for
 * out of bound values.
 *
 * Non-iteration functions, and any code that does not need to use
 * CONV_OSABI_ALL, should use uchar_t for osabi.
 */
typedef Half conv_iter_osabi_t;

/*
 * Many of the iteration functions accept an osabi or mach argument,
 * used to specify the type of object being processed. The following
 * values can be used to specify a wildcard that matches any item. Their
 * values are carefully chosen to ensure that they cannot be interpreted
 * as an otherwise valid osabi or machine.
 */
#define	CONV_OSABI_ALL	1024	/* Larger than can be represented by uchar_t */
#define	CONV_MACH_ALL	EM_NUM	/* Never a valid machine type */

/*
 * We compare Val_Desc2 descriptors with a specified osabi and machine
 * to determine whether to use it or not. This macro encapsulates that logic.
 *
 * We consider an osabi to match when any of the following things hold:
 *
 * -	The descriptor osabi is ELFOSABI_NONE.
 * -	The supplied osabi and the descriptor osabi match
 * -	The supplied osabi is ELFOSABI_NONE, and the descriptor osabi is
 *	ELFOSABI_SOLARIS. Many operating systems, Solaris included,
 *	produce or have produced ELFOSABI_NONE native objects, if only
 *	because OSABI ranges are not an original ELF feature. We
 *	give our own objects the home field advantage.
 * -	Iteration Only: An osabi value of CONV_OSABI_ALL is specified.
 *
 * We consider a machine to match when any of the following things hold:
 *
 * -	The descriptor mach is EM_NONE.
 * -	The supplied mach and the descriptor mach match
 * -	Iteration Only: A mach value of CONV_MACH_ALL is specified.
 *
 * The special extra _ALL case for iteration is handled by defining a separate
 * macro with the extra CONV_xxx_ALL tests.
 */
#define	CONV_VD2_SKIP_OSABI(_osabi, _vdp) \
	((_vdp->v_osabi != ELFOSABI_NONE) && (_vdp->v_osabi != osabi) && \
	((_osabi != ELFOSABI_NONE) || (_vdp->v_osabi != ELFOSABI_SOLARIS)))

#define	CONV_VD2_SKIP_MACH(_mach, _vdp) \
	((_vdp->v_mach != EM_NONE) && (_vdp->v_mach != _mach))

#define	CONV_VD2_SKIP(_osabi, _mach, _vdp) \
	(CONV_VD2_SKIP_OSABI(_osabi, _vdp) || CONV_VD2_SKIP_MACH(_mach, _vdp))

#define	CONV_ITER_VD2_SKIP(_osabi, _mach, _vdp)			      \
	((CONV_VD2_SKIP_OSABI(_osabi, _vdp) && (_osabi != CONV_OSABI_ALL)) || \
	(CONV_VD2_SKIP_MACH(_mach, _vdp) && (_mach != CONV_MACH_ALL)))


/*
 * Possible return values from iteration functions.
 */
typedef enum {
	CONV_ITER_DONE,		/* Stop: No more iterations are desired */
	CONV_ITER_CONT		/* Continue with following iterations */
} conv_iter_ret_t;

/*
 * Prototype for caller supplied callback function to iteration functions.
 */
typedef conv_iter_ret_t (* conv_iter_cb_t)(const char *str,
    Conv_elfvalue_t value, void *uvalue);

/*
 * User value block employed by conv_iter_strtol()
 */
typedef struct {
	const char	*csl_str;	/* String to search for */
	size_t		csl_strlen;	/* # chars in csl_str to examine */
	int		csl_found;	/* Init to 0, set to 1 if item found */
	Conv_elfvalue_t	csl_value;	/* If csl_found, resulting value */
} conv_strtol_uvalue_t;

/*
 * conv_expn_field() is willing to supply default strings for the
 * prefix, separator, and suffix arguments, if they are passed as NULL.
 * The caller needs to know how much room to allow for these items.
 * These values supply those sizes.
 */
#define	CONV_EXPN_FIELD_DEF_PREFIX_SIZE	2	/* Default is "[ " */
#define	CONV_EXPN_FIELD_DEF_SEP_SIZE	1	/* Default is " " */
#define	CONV_EXPN_FIELD_DEF_SUFFIX_SIZE	2	/* Default is " ]" */

/*
 * conv_expn_field() requires a large number of inputs, many of which
 * can be NULL to accept default behavior. An argument of the following
 * type is used to supply them.
 */
typedef struct {
	char *buf;		/* Buffer to receive generated string */
	size_t bufsize;		/* sizeof(buf) */
	const char **lead_str;	/* NULL, or array of pointers to strings to */
				/*	be output at the head of the list. */
				/*	Last entry must be NULL. */
	Xword oflags;		/* Bits for which output strings are desired */
	Xword rflags;		/* Bits for which a numeric value should be */
				/*	output if vdp does not provide str. */
				/*	Must be a proper subset of oflags */
	const char *prefix;	/* NULL, or string to prefix output with */
				/*	If NULL, "[ " is used. */
	const char *sep;	/* NULL, or string to separate output items */
				/*	with. If NULL, " " is used. */
	const char *suffix;	/* NULL, or string to suffix output with */
				/*	If NULL, " ]" is used. */
} CONV_EXPN_FIELD_ARG;

/*
 * Callback function for conv_str_to_c_literal(). A user supplied function
 * of this type is called by conv_str_to_c_literal() in order to dispatch
 * the translated output characters.
 *
 *	buf - Pointer to output text
 *	n - # of characters to output
 *	uvalue - User value argument to conv_str_to_c_literal(),
 *		passed through without interpretation.
 */
typedef	void		Conv_str_to_c_literal_func_t(const void *ptr,
			    size_t size, void *uvalue);

/*
 * Generic miscellaneous interfaces
 */
extern	uchar_t		conv_check_native(char **, char **);
extern	const char	*conv_lddstub(int);
extern	int		conv_strproc_isspace(int);
extern	char		*conv_strproc_trim(char *);
extern	Boolean		conv_strproc_extract_value(char *, size_t, int,
			    const char **);
extern	int		conv_sys_eclass(void);
extern	int		conv_translate_c_esc(char **);

/*
 * Generic core formatting and iteration functionality
 */
extern	conv_iter_ret_t	_conv_iter_ds(conv_iter_osabi_t, Half,
			    const conv_ds_t **, conv_iter_cb_t, void *,
			    const char *);
extern	conv_iter_ret_t	_conv_iter_ds_msg(const conv_ds_msg_t *,
			    conv_iter_cb_t, void *, const char *);
extern	conv_iter_ret_t	_conv_iter_vd(const Val_desc *, conv_iter_cb_t,
			    void *, const char *);
extern	conv_iter_ret_t	_conv_iter_vd2(conv_iter_osabi_t, Half,
			    const Val_desc2 *, conv_iter_cb_t, void *,
			    const char *);
extern	int		conv_iter_strtol_init(const char *,
			    conv_strtol_uvalue_t *);
extern	conv_iter_ret_t	conv_iter_strtol(const char *, Conv_elfvalue_t, void *);
extern	const char	*_conv_map_ds(uchar_t, Half, Conv_elfvalue_t,
			    const conv_ds_t **, Conv_fmt_flags_t,
			    Conv_inv_buf_t *, const char *);


/*
 * Generic formatting interfaces.
 */
extern	const char	*conv_bnd_obj(uint_t, Conv_bnd_obj_buf_t *);
extern	const char	*conv_bnd_type(uint_t, Conv_bnd_type_buf_t *);
extern	const char	*conv_config_feat(int, Conv_config_feat_buf_t *);
extern	const char	*conv_config_obj(ushort_t, Conv_config_obj_buf_t *);
extern	const char	*conv_config_upm(const char *, const char *,
			    const char *, size_t);
extern	const char	*conv_cnote_auxv_af(Word, Conv_fmt_flags_t,
			    Conv_cnote_auxv_af_buf_t *);
extern	const char	*conv_cnote_auxv_type(Word, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_cnote_cc_content(Lword, Conv_fmt_flags_t,
			    Conv_cnote_cc_content_buf_t *);
extern	const char	*conv_cnote_errno(int, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_cnote_fault(Word, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_cnote_fltset(uint32_t *, int,
			    Conv_fmt_flags_t, Conv_cnote_fltset_buf_t *);
extern	const char	*conv_cnote_old_pr_flags(int, Conv_fmt_flags_t,
			    Conv_cnote_old_pr_flags_buf_t *);
extern	const char	*conv_cnote_pr_dmodel(Word, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_cnote_pr_flags(int, Conv_fmt_flags_t,
			    Conv_cnote_pr_flags_buf_t *);
extern	const char	*conv_cnote_proc_flag(int, Conv_fmt_flags_t,
			    Conv_cnote_proc_flag_buf_t *);
extern	const char	*conv_cnote_pr_regname(Half, int, Conv_fmt_flags_t,
			    Conv_inv_buf_t *inv_buf);
extern	const char	*conv_cnote_pr_stype(Word, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_cnote_pr_what(short, short, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_cnote_pr_why(short, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_cnote_priv(int, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_prsecflags(secflagset_t, Conv_fmt_flags_t,
			    Conv_secflags_buf_t *);
extern	const char	*conv_prupanic(uint32_t, Conv_fmt_flags_t,
			    Conv_upanic_buf_t *);
extern	const char	*conv_cnote_psetid(int, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_cnote_sa_flags(int, Conv_fmt_flags_t,
			    Conv_cnote_sa_flags_buf_t *);
extern	const char	*conv_cnote_signal(Word, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_cnote_si_code(Half, int, int, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_cnote_sigset(uint32_t *, int,
			    Conv_fmt_flags_t, Conv_cnote_sigset_buf_t *);
extern	const char	*conv_cnote_ss_flags(int, Conv_fmt_flags_t,
			    Conv_cnote_ss_flags_buf_t *);
extern	const char	*conv_cnote_syscall(Word, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_cnote_sysset(uint32_t *, int,
			    Conv_fmt_flags_t, Conv_cnote_sysset_buf_t *);
extern	const char	*conv_cnote_fdflags(uint32_t, Conv_fmt_flags_t,
			    char *, size_t);
extern	const char	*conv_cnote_fileflags(uint32_t, Conv_fmt_flags_t,
			    char *, size_t);
extern	const char	*conv_cnote_filemode(uint32_t, Conv_fmt_flags_t,
			    char *, size_t);
extern	const char	*conv_cnote_type(Word, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_def_tag(Symref, Conv_inv_buf_t *);
extern	const char	*conv_demangle_name(const char *);
extern	const char	*conv_dl_flag(int, Conv_fmt_flags_t,
			    Conv_dl_flag_buf_t *);
extern	const char	*conv_dl_info(int);
extern	const char	*conv_dl_mode(int, int, Conv_dl_mode_buf_t *);
extern	const char	*conv_dwarf_cfa(uchar_t, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_dwarf_ehe(uint_t, Conv_dwarf_ehe_buf_t *);
extern	const char	*conv_dwarf_regname(Half, Word, Conv_fmt_flags_t,
			    int *, Conv_inv_buf_t *);
extern	const char	*conv_ehdr_abivers(uchar_t, Word, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_ehdr_class(uchar_t, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_ehdr_data(uchar_t, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_ehdr_flags(Half, Word, Conv_fmt_flags_t,
			    Conv_ehdr_flags_buf_t *);
extern	const char	*conv_ehdr_mach(Half, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_ehdr_osabi(uchar_t, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_ehdr_type(uchar_t, Half, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_ehdr_vers(Word, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_elfdata_type(Elf_Type, Conv_inv_buf_t *);
extern	const char	*conv_ent_flags(ec_flags_t, Conv_ent_flags_buf_t *);
extern	const char	*conv_ent_files_flags(Word,  Conv_fmt_flags_t fmt_flags,
			    Conv_ent_files_flags_buf_t *);
extern	const char	*conv_la_activity(uint_t, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_la_bind(uint_t, Conv_la_bind_buf_t *);
extern	const char	*conv_la_search(uint_t, Conv_la_search_buf_t *);
extern	const char	*conv_la_symbind(uint_t, Conv_la_symbind_buf_t *);
extern	const char	*conv_grphdl_flags(uint_t, Conv_grphdl_flags_buf_t *);
extern	const char	*conv_grpdesc_flags(uint_t, Conv_grpdesc_flags_buf_t *);
extern	Isa_desc	*conv_isalist(void);
extern	const char	*conv_mapfile_version(Word, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_phdr_flags(uchar_t, Word, Conv_fmt_flags_t,
			    Conv_phdr_flags_buf_t *);
extern	const char	*conv_phdr_type(uchar_t, Half, Word, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_reject_desc(Rej_desc *, Conv_reject_desc_buf_t *,
			    Half mach);
extern	const char	*conv_reloc_type(Half, Word, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_reloc_type_static(Half, Word, Conv_fmt_flags_t);
extern	const char	*conv_reloc_386_type(Word, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_reloc_amd64_type(Word, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_reloc_SPARC_type(Word, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_sec_type(uchar_t, Half, Word, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_seg_flags(sg_flags_t, Conv_seg_flags_buf_t *);
extern	void		conv_str_to_c_literal(const char *buf, size_t n,
			    Conv_str_to_c_literal_func_t *cb_func,
			    void *uvalue);
extern	const char	*conv_sym_info_bind(uchar_t, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_sym_info_type(Half, uchar_t, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_sym_shndx(uchar_t, Half, Half, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_sym_other(uchar_t, Conv_inv_buf_t *);
extern	const char	*conv_sym_other_vis(uchar_t, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_syminfo_boundto(Half, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_syminfo_flags(Half, Conv_fmt_flags_t,
			    Conv_syminfo_flags_buf_t *);
extern	const char	*conv_time(struct timeval *, struct timeval *,
			    Conv_time_buf_t *);
extern	Uts_desc	*conv_uts(void);
extern	const char	*conv_ver_flags(Half, Conv_fmt_flags_t,
			    Conv_ver_flags_buf_t *);
extern	const char	*conv_ver_index(Versym, int, Conv_inv_buf_t *);


/*
 * Generic iteration interfaces.
 */
extern	conv_iter_ret_t	conv_iter_cap_tags(Conv_fmt_flags_t, conv_iter_cb_t,
			    void *);
extern	conv_iter_ret_t	conv_iter_cap_val_hw1(Half, Conv_fmt_flags_t,
			    conv_iter_cb_t, void *);
extern	conv_iter_ret_t	conv_iter_cap_val_hw2(Half, Conv_fmt_flags_t,
			    conv_iter_cb_t, void *);
extern	conv_iter_ret_t	conv_iter_cap_val_sf1(Conv_fmt_flags_t, conv_iter_cb_t,
			    void *);
extern	conv_iter_ret_t	conv_iter_cap_val_hw3(Half, Conv_fmt_flags_t,
			    conv_iter_cb_t, void *);

extern	conv_iter_ret_t	conv_iter_dyn_feature1(Conv_fmt_flags_t, conv_iter_cb_t,
			    void *);
extern	conv_iter_ret_t	conv_iter_dyn_flag(Conv_fmt_flags_t, conv_iter_cb_t,
			    void *);
extern	conv_iter_ret_t	conv_iter_dyn_flag1(Conv_fmt_flags_t, conv_iter_cb_t,
			    void *);
extern	conv_iter_ret_t	conv_iter_dyn_posflag1(Conv_fmt_flags_t, conv_iter_cb_t,
			    void *);
extern	conv_iter_ret_t	conv_iter_dyn_tag(conv_iter_osabi_t, Half,
			    Conv_fmt_flags_t, conv_iter_cb_t, void *);

extern	conv_iter_ret_t	conv_iter_ehdr_abivers(conv_iter_osabi_t,
			    Conv_fmt_flags_t, conv_iter_cb_t, void *);
extern	conv_iter_ret_t	conv_iter_ehdr_class(Conv_fmt_flags_t, conv_iter_cb_t,
			    void *);
extern	conv_iter_ret_t	conv_iter_ehdr_data(Conv_fmt_flags_t, conv_iter_cb_t,
			    void *);
extern	conv_iter_ret_t	conv_iter_ehdr_eident(Conv_fmt_flags_t, conv_iter_cb_t,
			    void *);
extern	conv_iter_ret_t	conv_iter_ehdr_flags(Half, Conv_fmt_flags_t,
			    conv_iter_cb_t, void *);
extern	conv_iter_ret_t	conv_iter_ehdr_mach(Conv_fmt_flags_t, conv_iter_cb_t,
			    void *);
extern	conv_iter_ret_t	conv_iter_ehdr_osabi(Conv_fmt_flags_t, conv_iter_cb_t,
			    void *);
extern	conv_iter_ret_t	conv_iter_ehdr_type(conv_iter_osabi_t, Conv_fmt_flags_t,
			    conv_iter_cb_t, void *);
extern	conv_iter_ret_t	conv_iter_ehdr_vers(Conv_fmt_flags_t, conv_iter_cb_t,
			    void *);

extern	conv_iter_ret_t	conv_iter_phdr_flags(conv_iter_osabi_t,
			    Conv_fmt_flags_t, conv_iter_cb_t, void *);
extern	conv_iter_ret_t	conv_iter_phdr_type(conv_iter_osabi_t, Conv_fmt_flags_t,
			    conv_iter_cb_t, void *);

extern	conv_iter_ret_t	conv_iter_sec_flags(conv_iter_osabi_t, Half,
			    Conv_fmt_flags_t, conv_iter_cb_t, void *);
extern	conv_iter_ret_t	conv_iter_sec_symtab(conv_iter_osabi_t,
			    Conv_fmt_flags_t, conv_iter_cb_t, void *);
extern	conv_iter_ret_t	conv_iter_sec_type(conv_iter_osabi_t, Half,
			    Conv_fmt_flags_t, conv_iter_cb_t, void *);

extern	conv_iter_ret_t	conv_iter_sym_info_bind(Conv_fmt_flags_t,
			    conv_iter_cb_t, void *);
extern	conv_iter_ret_t	conv_iter_sym_other_vis(Conv_fmt_flags_t,
			    conv_iter_cb_t, void *);
extern	conv_iter_ret_t	conv_iter_sym_shndx(conv_iter_osabi_t, Half,
			    Conv_fmt_flags_t, conv_iter_cb_t, void *);
extern	conv_iter_ret_t	conv_iter_sym_info_type(Half, Conv_fmt_flags_t,
			    conv_iter_cb_t, void *);

extern	conv_iter_ret_t	conv_iter_syminfo_boundto(Conv_fmt_flags_t,
			    conv_iter_cb_t, void *);
extern	conv_iter_ret_t	conv_iter_syminfo_flags(Conv_fmt_flags_t,
			    conv_iter_cb_t, void *);

/*
 * Define all class specific routines.
 */
#if	defined(_ELF64)
#define	conv_cap_tag		conv64_cap_tag
#define	conv_cap_val		conv64_cap_val
#define	conv_cap_val_hw1	conv64_cap_val_hw1
#define	conv_cap_val_hw2	conv64_cap_val_hw2
#define	conv_cap_val_hw3	conv64_cap_val_hw3
#define	conv_cap_val_sf1	conv64_cap_val_sf1
#define	conv_dyn_feature1	conv64_dyn_feature1
#define	conv_dyn_flag1		conv64_dyn_flag1
#define	conv_dyn_flag		conv64_dyn_flag
#define	conv_dyn_posflag1	conv64_dyn_posflag1
#define	conv_dyn_tag		conv64_dyn_tag
#define	_conv_expn_field	_conv64_expn_field
#define	_conv_expn_field2	_conv64_expn_field2
#define	conv_invalid_val	conv64_invalid_val
#define	conv_sec_flags		conv64_sec_flags
#define	conv_sec_linkinfo	conv64_sec_linkinfo
#define	conv_sym_value		conv64_sym_value
#define	conv_sym_SPARC_value	conv64_sym_SPARC_value
#else
#define	conv_cap_tag		conv32_cap_tag
#define	conv_cap_val		conv32_cap_val
#define	conv_cap_val_hw1	conv32_cap_val_hw1
#define	conv_cap_val_hw2	conv32_cap_val_hw2
#define	conv_cap_val_hw3	conv32_cap_val_hw3
#define	conv_cap_val_sf1	conv32_cap_val_sf1
#define	conv_dyn_feature1	conv32_dyn_feature1
#define	conv_dyn_flag1		conv32_dyn_flag1
#define	conv_dyn_flag		conv32_dyn_flag
#define	conv_dyn_posflag1	conv32_dyn_posflag1
#define	conv_dyn_tag		conv32_dyn_tag
#define	_conv_expn_field	_conv32_expn_field
#define	_conv_expn_field2	_conv32_expn_field2
#define	conv_invalid_val	conv32_invalid_val
#define	conv_sec_flags		conv32_sec_flags
#define	conv_sec_linkinfo	conv32_sec_linkinfo
#define	conv_sym_value		conv32_sym_value
#define	conv_sym_SPARC_value	conv32_sym_SPARC_value
#endif

/*
 * ELFCLASS-specific core formatting functionality
 */
extern	int		_conv_expn_field(CONV_EXPN_FIELD_ARG *,
			    const Val_desc *, Conv_fmt_flags_t, const char *);
extern	int		_conv_expn_field2(CONV_EXPN_FIELD_ARG *, uchar_t,
			    Half, const Val_desc2 *, Conv_fmt_flags_t,
			    const char *);
extern	const char	*conv_invalid_val(Conv_inv_buf_t *, Xword,
			    Conv_fmt_flags_t);

/*
 * ELFCLASS-specific formatting interfaces.
 */
extern	const char	*conv_cap_tag(Xword, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_cap_val(Xword, Xword, Half, Conv_fmt_flags_t,
			    Conv_cap_val_buf_t *);
extern	const char	*conv_cap_val_hw1(Xword, Half, Conv_fmt_flags_t,
			    Conv_cap_val_hw1_buf_t *);
extern	const char	*conv_cap_val_hw2(Xword, Half, Conv_fmt_flags_t,
			    Conv_cap_val_hw2_buf_t *);
extern	const char	*conv_cap_val_hw3(Xword, Half, Conv_fmt_flags_t,
			    Conv_cap_val_hw3_buf_t *);
extern	const char	*conv_cap_val_sf1(Xword, Half, Conv_fmt_flags_t,
			    Conv_cap_val_sf1_buf_t *);
extern	const char	*conv_dyn_flag1(Xword, Conv_fmt_flags_t,
			    Conv_dyn_flag1_buf_t *);
extern	const char	*conv_dyn_flag(Xword, Conv_fmt_flags_t,
			    Conv_dyn_flag_buf_t *);
extern	const char	*conv_dyn_posflag1(Xword, Conv_fmt_flags_t,
			    Conv_dyn_posflag1_buf_t *);
extern	const char	*conv_dyn_tag(Xword, uchar_t, Half, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);
extern	const char	*conv_dyn_feature1(Xword, Conv_fmt_flags_t,
			    Conv_dyn_feature1_buf_t *);
extern	const char	*conv_sec_flags(uchar_t osabi, Half mach, Xword,
			    Conv_fmt_flags_t, Conv_sec_flags_buf_t *);
extern	const char	*conv_sec_linkinfo(Word, Xword, Conv_inv_buf_t *);
extern	const char	*conv_sym_value(Half, uchar_t, Addr, Conv_inv_buf_t *);
extern	const char	*conv_sym_SPARC_value(Addr, Conv_fmt_flags_t,
			    Conv_inv_buf_t *);

/*
 * Define macros for _conv_XXX() routines that accept local_sgs_msg as the
 * final argument. The macros hide that argument from the caller's view and
 * supply the SGS message array for the file from which the macro is used
 * in its place. This trick is used to allow these functions to access the
 * message strings from any source file they are called from.
 */
#define	conv_expn_field(_arg, _vdp, _fmt_flags) \
    _conv_expn_field(_arg, _vdp, _fmt_flags, MSG_SGS_LOCAL_ARRAY)

#define	conv_expn_field2(_arg, _osabi, _mach, _vdp, _fmt_flags) \
    _conv_expn_field2(_arg, _osabi, _mach, _vdp, _fmt_flags, \
    MSG_SGS_LOCAL_ARRAY)

#define	conv_iter_ds(_osabi, _mach, _dsp, _func, _uvalue) \
    _conv_iter_ds(_osabi, _mach, _dsp, _func, _uvalue, MSG_SGS_LOCAL_ARRAY)

#define	conv_iter_vd(_vdp, _func, _uvalue)	\
    _conv_iter_vd(_vdp, _func, _uvalue, MSG_SGS_LOCAL_ARRAY)

#define	conv_iter_vd2(_osabi, _mach, _vdp, _func, _uvalue)		\
    _conv_iter_vd2(_osabi, _mach, _vdp, _func, _uvalue, MSG_SGS_LOCAL_ARRAY)

#define	conv_map_ds(_osabi, _mach, _value, _dsp, _fmt_flags, _inv_buf) \
    _conv_map_ds(_osabi, _mach, _value, _dsp, _fmt_flags, _inv_buf, \
    MSG_SGS_LOCAL_ARRAY)


#ifdef	__cplusplus
}
#endif

#endif /* _CONV_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
 * Copyright 2022 Oxide Computer Company
 */

#ifndef	_DEBUG_H
#define	_DEBUG_H

/*
 * Global include file for lddbg debugging.
 *
 * ld(1) and ld.so.1(1) carry out all diagnostic debugging calls via lazy
 * loading the library liblddbg.so.  Thus debugging is always enabled.  The
 * utility elfdump(1) is explicitly dependent upon this library.  There are two
 * categories of routines defined in this library:
 *
 *  o	Debugging routines that have specific linker knowledge, and test the
 *	class of debugging allowable before proceeding, start with the `Dbg_'
 *	prefix.
 *
 *  o	Lower level routines that provide generic ELF structure interpretation
 *	start with the `Elf_' prefix.  These latter routines are the only
 *	routines used by the elfdump(1) utility.
 */
#include <sys/times.h>
#include <sgs.h>
#include <libld.h>
#include <rtld.h>
#include <gelf.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Define Dbg_*() interface values.  These values direct the debugging routine
 * to generate different diagnostics, thus the strings themselves are maintained
 * in the debugging library.
 */
#define	DBG_SUP_ENVIRON		1
#define	DBG_SUP_CMDLINE		2

#define	DBG_CONF_IGNORE		1	/* configuration processing errors */
#define	DBG_CONF_VERSION	2
#define	DBG_CONF_PRCFAIL	3
#define	DBG_CONF_CORRUPT	4
#define	DBG_CONF_ABIMISMATCH	5

#define	DBG_ORDER_INFO_RANGE	1	/* sh_link out of range */
#define	DBG_ORDER_INFO_ORDER	2	/* sh_info also ordered */
#define	DBG_ORDER_LINK_OUTRANGE	3	/* sh_link out of range */
#define	DBG_ORDER_FLAGS		4	/* sh_flags do not match */
#define	DBG_ORDER_CYCLIC	5	/* sh_link cyclic */
#define	DBG_ORDER_LINK_ERROR	6	/* sh_link (one) has an error */

#define	DBG_INIT_SORT		1	/* calling init from sorted order */
#define	DBG_INIT_PEND		2	/* calling pending init */
#define	DBG_INIT_DYN		3	/* dynamically triggered init */
#define	DBG_INIT_DONE		4	/* init completed */

#define	DBG_DLSYM_DEF		0
#define	DBG_DLSYM_NEXT		1
#define	DBG_DLSYM_DEFAULT	2
#define	DBG_DLSYM_SELF		3
#define	DBG_DLSYM_PROBE		4
#define	DBG_DLSYM_SINGLETON	5
#define	DBG_DLSYM_NUM		DBG_DLSYM_SINGLETON + 1

#define	DBG_DLCLOSE_NULL	0
#define	DBG_DLCLOSE_IGNORE	1
#define	DBG_DLCLOSE_RESCAN	2

#define	DBG_SYM_REDUCE_GLOBAL	1	/* reporting global symbols to local */
#define	DBG_SYM_REDUCE_RETAIN	2	/* reporting non reduced local syms */

#define	DBG_AUD_CALL		1	/* original call to auditor */
#define	DBG_AUD_RET		2	/* return from auditor diagnostic */

#define	DBG_AUD_LOCAL		0	/* auditor is local */
#define	DBG_AUD_GLOBAL		1	/* auditor is global */
#define	DBG_AUD_PRELOAD		2	/* auditor is preloaded */

/*
 * Group handle operations - passed to Dbg_file_hdl_title().  Indicate why
 * handle dependencies are being manipulated.
 */
#define	DBG_HDL_CREATE		0	/* handle creation */
#define	DBG_HDL_ADD		1	/* addition to existing handle */
#define	DBG_HDL_DELETE		2	/* deletion from a handle */
#define	DBG_HDL_ORPHAN		3	/* handle being moved to orphan list */
#define	DBG_HDL_REINST		4	/* handle reinstated from orphan list */

/*
 * Group handle dependency operations - passed to Dbg_file_hdl_action().
 * Identify the dependencies that are associated with a handle.
 */
#define	DBG_DEP_ADD		0	/* dependency added */
#define	DBG_DEP_UPDATE		1	/* dependency updated */
#define	DBG_DEP_DELETE		2	/* dependency deleted */
#define	DBG_DEP_REMOVE		3	/* dependency removed from handle */
#define	DBG_DEP_REMAIN		4	/* dependency must remain on handle */
#define	DBG_DEP_ORPHAN		5	/* dependency must remain an orphan */
#define	DBG_DEP_REINST		6	/* dependency reinstated from orphan */

/*
 * Binding information, indicating the result of a symbol binding.  Can also
 * indicate the reference as being EXTERN or PARENT.  Binding information is
 * used to augment diagnostic binding information (which in turn can be used by
 * lari(1)), and to enable ldd(1) -p processing.
 */
#define	DBG_BINFO_FOUND		0x0001	/* information regarding binding */
#define	DBG_BINFO_DIRECT	0x0002	/* bound directly */
#define	DBG_BINFO_COPYREF	0x0004	/* bound to copy relocated reference */
#define	DBG_BINFO_FILTEE	0x0008	/* bound to filtee */
#define	DBG_BINFO_INTERPOSE	0x0010	/* bound to an identified interposer */
#define	DBG_BINFO_PLTADDR	0x0020	/* bound to executables undefined plt */
#define	DBG_BINFO_MSK		0x0fff

#define	DBG_BINFO_REF_EXTERN	0x1000	/* reference to EXTERN */
#define	DBG_BINFO_REF_PARENT	0x2000	/* reference to PARENT */
#define	DBG_BINFO_REF_MSK	0xf000

/*
 * ld.so.1(1) symbol capabilities processing.
 */
#define	DBG_CAP_DEFAULT		0
#define	DBG_CAP_USED		1
#define	DBG_CAP_CANDIDATE	2
#define	DBG_CAP_REJECTED	3
#define	DBG_CAP_HW_1		4
#define	DBG_CAP_SF_1		5
#define	DBG_CAP_HW_2		6
#define	DBG_CAP_PLAT		7
#define	DBG_CAP_MACH		8
#define	DBG_CAP_HW_3		9

#define	DBG_REL_START		1
#define	DBG_REL_FINISH		2
#define	DBG_REL_NONE		3

#define	DBG_NL_STD		0	/* newline controllers - standard and */
#define	DBG_NL_FRC		2	/*    forced. */

#define	DBG_BNDREJ_DIRECT	0	/* bind rejected, direct to nodirect */
#define	DBG_BNDREJ_GROUP	1	/* bind rejected, group to nodirect */
#define	DBG_BNDREJ_SINGLE	2	/* bind rejected, singleton without */
					/*    default search model */
#define	DBG_BNDREJ_NUM		DBG_BNDREJ_SINGLE

/*
 * Dbg_state_str() is used to obtain commonly used "state transition"
 * strings used in various debugging output.
 */
#define	DBG_STATE_ADD		0	/* add */
#define	DBG_STATE_CURRENT	1	/* current */
#define	DBG_STATE_EXCLUDE	2	/* exclude */
#define	DBG_STATE_IGNORED	3	/* ignored */
#define	DBG_STATE_MOD_BEFORE	4	/* modify (before) */
#define	DBG_STATE_MOD_AFTER	5	/* modify (after) */
#define	DBG_STATE_NEW		6	/* new */
#define	DBG_STATE_NEW_IMPLICIT	7	/* new (implicit) */
#define	DBG_STATE_RESET		8	/* reset */
#define	DBG_STATE_ORIGINAL	9	/* original */
#define	DBG_STATE_RESOLVED	10	/* resolved */

#define	DBG_STATE_NUM		11
typedef uint_t dbg_state_t;
extern	const char *Dbg_state_str(dbg_state_t);

/*
 * Define a debug descriptor, and a user macro that inspects the descriptor as
 * a means of triggering a class of diagnostic output.
 */
typedef struct {
	uint_t		d_class;	/* debugging classes */
	uint_t		d_extra;	/* extra public information */
	APlist		*d_list;	/* accepted link-map list names */
	struct timeval	d_totaltime;	/* total time since entry - */
					/*	gettimeofday(3c) */
	struct timeval	d_deltatime;	/* delta time since last diagnostic - */
					/*	gettimeofday(3c) */
} Dbg_desc;

extern	Dbg_desc	*dbg_desc;

/*
 * Macros used to avoid calls to liblddbg unless debugging is enabled.
 * liblddbg is lazy loaded --- this prevents it from happening unless
 * it will actually be used.
 */
#define	DBG_ENABLED	(dbg_desc->d_class)
#define	DBG_CALL(func)	if (DBG_ENABLED) func

/*
 * Most debugging tokens are interpreted within liblddbg, and thus any flags
 * within d_class are only meaningful to this library.  The following flags
 * extend the d_class diagnostic, and are maintained in d_extra.  These flags
 * may be interpreted by the debugging library itself or from the callers
 * dbg_print() routine.
 */
#define	DBG_E_DETAIL	0x00000001	/* add detail to a class */
#define	DBG_E_LONG	0x00000002	/* use long names (ie. no truncation) */
#define	DBG_E_DEMANGLE	0x00000004	/* demangle symbol names */
#define	DBG_E_STDNL	0x00000008	/* standard newline indicator */
#define	DBG_E_HELP	0x00000010	/* help requested */
#define	DBG_E_HELP_EXIT	0x00000020	/* hint: user should exit after help */
#define	DBG_E_TTIME	0x00000040	/* prepend total time */
#define	DBG_E_DTIME	0x00000080	/* prepend delta time */
#define	DBG_E_RESET	0x00000100	/* reset times */

/* ld only */
#define	DBG_E_SNAME	0x00001000	/* prepend simple name */
#define	DBG_E_FNAME	0x00002000	/* prepend full name */
#define	DBG_E_CLASS	0x00004000	/* prepend ELF class */

/* ld.so.1 only */
#define	DBG_E_LMID	0x00100000	/* prepend link-map id */
#define	DBG_E_LMID_LDSO	0x00200000	/* show ldso link-map list */
#define	DBG_E_LMID_ALL	0x00400000	/* show all non-ldso link-map lists */
#define	DBG_E_LMID_ALT	0x00800000	/* show all ALT link-map lists */
#define	DBG_E_LMID_BASE	0x01000000	/* show BASE link-map list */


#define	DBG_NOTDETAIL()	!(dbg_desc->d_extra & DBG_E_DETAIL)
#define	DBG_NOTLONG()	!(dbg_desc->d_extra & DBG_E_LONG)

#define	DBG_ISDEMANGLE() \
			(dbg_desc->d_extra & DBG_E_DEMANGLE)

#define	DBG_TOTALTIME	(dbg_desc->d_totaltime)
#define	DBG_DELTATIME	(dbg_desc->d_deltatime)

#define	DBG_ISTTIME()	(dbg_desc->d_extra & DBG_E_TTIME)
#define	DBG_ISDTIME()	(dbg_desc->d_extra & DBG_E_DTIME)
#define	DBG_ISTIME()	(dbg_desc->d_extra & (DBG_E_TTIME | DBG_E_DTIME))
#define	DBG_NOTTIME()	!(dbg_desc->d_extra & (DBG_E_TTIME | DBG_E_DTIME))

#define	DBG_ISRESET()	(dbg_desc->d_extra & DBG_E_RESET)
#define	DBG_ONRESET()	(dbg_desc->d_extra |= DBG_E_RESET)
#define	DBG_OFFRESET()	(dbg_desc->d_extra &= ~DBG_E_RESET)

#define	DBG_ISSNAME()	(dbg_desc->d_extra & DBG_E_SNAME)
#define	DBG_ISFNAME()	(dbg_desc->d_extra & DBG_E_FNAME)
#define	DBG_ISCLASS()	(dbg_desc->d_extra & DBG_E_CLASS)
#define	DBG_ISLMID()	(dbg_desc->d_extra & DBG_E_LMID)

/*
 * Print routine, this must be supplied by the application.  The initial
 * argument may provide a link-map list to associate with the format statement
 * that follows.
 */
/* PRINTFLIKE2 */
extern	void		dbg_print(Lm_list *, const char *, ...);

/*
 * Initialization routine, called before any other Dbg routines to
 * establish the necessary state.
 */
typedef enum { DBG_CALLER_LD, DBG_CALLER_RTLD } dbg_setup_caller_t;
extern	int		Dbg_setup(dbg_setup_caller_t, const char *,
			    Dbg_desc *, const char **);

/* Call dbg_print() to produce linker version output */
extern void		Dbg_version(void);

/* Call dbg_print() to produce help output */
extern	void		Dbg_help(void);

/*
 * Establish ELF32 and ELF64 class Dbg_*() interfaces.
 */
#if	defined(_ELF64)

#define	Dbg_demangle_name	Dbg64_demangle_name

#define	Dbg_bind_global		Dbg64_bind_global
#define	Dbg_bind_plt_summary	Dbg64_bind_plt_summary
#define	Dbg_bind_pltpad_from	Dbg64_bind_pltpad_from
#define	Dbg_bind_pltpad_to	Dbg64_bind_pltpad_to
#define	Dbg_bind_reject		Dbg64_bind_reject
#define	Dbg_bind_weak		Dbg64_bind_weak

#define	Dbg_cap_candidate	Dbg64_cap_candidate
#define	Dbg_cap_filter		Dbg64_cap_filter
#define	Dbg_cap_id		Dbg64_cap_id
#define	Dbg_cap_identical	Dbg64_cap_identical
#define	Dbg_cap_mapfile_title	Dbg64_cap_mapfile_title
#define	Dbg_cap_post_title	Dbg64_cap_post_title
#define	Dbg_cap_sec_title	Dbg64_cap_sec_title
#define	Dbg_cap_val		Dbg64_cap_val
#define	Dbg_cap_ptr_entry	Dbg64_cap_ptr_entry
#define	Dbg_cap_val_entry	Dbg64_cap_val_entry

#define	Dbg_dl_dladdr		Dbg64_dl_dladdr
#define	Dbg_dl_dlclose		Dbg64_dl_dlclose
#define	Dbg_dl_dldump		Dbg64_dl_dldump
#define	Dbg_dl_dlerror		Dbg64_dl_dlerror
#define	Dbg_dl_dlinfo		Dbg64_dl_dlinfo
#define	Dbg_dl_dlopen		Dbg64_dl_dlopen
#define	Dbg_dl_dlsym		Dbg64_dl_dlsym
#define	Dbg_dl_iphdr_enter	Dbg64_dl_iphdr_enter
#define	Dbg_dl_iphdr_callback	Dbg64_dl_iphdr_callback
#define	Dbg_dl_iphdr_mapchange	Dbg64_dl_iphdr_mapchange
#define	Dbg_dl_iphdr_unmap_ret	Dbg64_dl_iphdr_unmap_ret

#define	Dbg_ent_entry		Dbg64_ent_entry
#define	Dbg_ent_print		Dbg64_ent_print

#define	Dbg_file_analyze	Dbg64_file_analyze
#define	Dbg_file_ar		Dbg64_file_ar
#define	Dbg_file_ar_rescan	Dbg64_file_ar_rescan
#define	Dbg_file_bind_entry	Dbg64_file_bind_entry
#define	Dbg_file_bindings	Dbg64_file_bindings
#define	Dbg_file_bindings_done	Dbg64_file_bindings_done
#define	Dbg_file_cleanup	Dbg64_file_cleanup
#define	Dbg_file_cntl		Dbg64_file_cntl
#define	Dbg_file_config_dis	Dbg64_file_config_dis
#define	Dbg_file_config_obj	Dbg64_file_config_obj
#define	Dbg_file_del_rescan	Dbg64_file_del_rescan
#define	Dbg_file_delete		Dbg64_file_delete
#define	Dbg_file_deferred	Dbg64_file_deferred
#define	Dbg_file_elf		Dbg64_file_elf
#define	Dbg_file_filtee		Dbg64_file_filtee
#define	Dbg_file_filter		Dbg64_file_filter
#define	Dbg_file_fixname	Dbg64_file_fixname
#define	Dbg_file_generic	Dbg64_file_generic
#define	Dbg_file_hdl_action	Dbg64_file_hdl_action
#define	Dbg_file_hdl_collect	Dbg64_file_hdl_collect
#define	Dbg_file_hdl_title	Dbg64_file_hdl_title
#define	Dbg_file_lazyload	Dbg64_file_lazyload
#define	Dbg_file_ldso		Dbg64_file_ldso
#define	Dbg_file_mmapobj	Dbg64_file_mmapobj
#define	Dbg_file_mode_promote	Dbg64_file_mode_promote
#define	Dbg_file_modified	Dbg64_file_modified
#define	Dbg_file_needed		Dbg64_file_needed
#define	Dbg_file_output		Dbg64_file_output
#define	Dbg_file_preload	Dbg64_file_preload
#define	Dbg_file_prot		Dbg64_file_prot
#define	Dbg_file_rejected	Dbg64_file_rejected
#define	Dbg_file_reuse		Dbg64_file_reuse
#define	Dbg_file_skip		Dbg64_file_skip

#define	Dbg_got_display		Dbg64_got_display

#define	Dbg_libs_audit		Dbg64_libs_audit
#define	Dbg_libs_find		Dbg64_libs_find
#define	Dbg_libs_found		Dbg64_libs_found
#define	Dbg_libs_insecure	Dbg64_libs_insecure
#define	Dbg_libs_init		Dbg64_libs_init
#define	Dbg_libs_l		Dbg64_libs_l
#define	Dbg_libs_path		Dbg64_libs_path
#define	Dbg_libs_req		Dbg64_libs_req
#define	Dbg_libs_update		Dbg64_libs_update
#define	Dbg_libs_yp		Dbg64_libs_yp
#define	Dbg_libs_ylu		Dbg64_libs_ylu

#define	Dbg_map_cexp_id		Dbg64_map_cexp_id
#define	Dbg_map_dv		Dbg64_map_dv
#define	Dbg_map_dv_entry	Dbg64_map_dv_entry
#define	Dbg_map_ent		Dbg64_map_ent
#define	Dbg_map_ent_ord_title	Dbg64_map_ent_ord_title
#define	Dbg_map_hdr_noalloc	Dbg64_map_hdr_noalloc
#define	Dbg_map_parse		Dbg64_map_parse
#define	Dbg_map_pass		Dbg64_map_pass
#define	Dbg_map_post_title	Dbg64_map_post_title
#define	Dbg_map_seg		Dbg64_map_seg
#define	Dbg_map_seg_order	Dbg64_map_seg_order
#define	Dbg_map_seg_os_order	Dbg64_map_seg_os_order
#define	Dbg_map_size_new	Dbg64_map_size_new
#define	Dbg_map_size_old	Dbg64_map_size_old
#define	Dbg_map_sort_seg	Dbg64_map_sort_seg
#define	Dbg_map_sort_title	Dbg64_map_sort_title
#define	Dbg_map_symbol		Dbg64_map_symbol
#define	Dbg_map_version		Dbg64_map_version

#define	Dbg_move_adjexpandreloc	Dbg64_move_adjexpandreloc
#define	Dbg_move_adjmovereloc	Dbg64_move_adjmovereloc
#define	Dbg_move_bad		Dbg64_move_bad
#define	Dbg_move_data		Dbg64_move_data
#define	Dbg_move_entry1		Dbg64_move_entry1
#define	Dbg_move_entry2		Dbg64_move_entry2
#define	Dbg_move_expand		Dbg64_move_expand
#define	Dbg_move_input		Dbg64_move_input
#define	Dbg_move_outmove	Dbg64_move_outmove
#define	Dbg_move_outsctadj	Dbg64_move_outsctadj
#define	Dbg_move_parexpn	Dbg64_move_parexpn

#define	Dbg_reloc_apply_reg	Dbg64_reloc_apply_reg
#define	Dbg_reloc_apply_val	Dbg64_reloc_apply_val
#define	Dbg_reloc_ars_entry	Dbg64_reloc_ars_entry
#define	Dbg_reloc_copy		Dbg64_reloc_copy
#define	Dbg_reloc_discard	Dbg64_reloc_discard
#define	Dbg_reloc_doact		Dbg64_reloc_doact
#define	Dbg_reloc_doact_title	Dbg64_reloc_doact_title
#define	Dbg_reloc_dooutrel	Dbg64_reloc_dooutrel
#define	Dbg_reloc_entry		Dbg64_reloc_entry
#define	Dbg_reloc_error		Dbg64_reloc_error
#define	Dbg_reloc_generate	Dbg64_reloc_generate
#define	Dbg_reloc_in		Dbg64_reloc_in
#define	Dbg_reloc_ors_entry	Dbg64_reloc_ors_entry
#define	Dbg_reloc_out		Dbg64_reloc_out
#define	Dbg_reloc_proc		Dbg64_reloc_proc
#define	Dbg_reloc_run		Dbg64_reloc_run
#define	Dbg_reloc_transition	Dbg64_reloc_transition
#define	Dbg_reloc_sloppycomdat	Dbg64_reloc_sloppycomdat

#define	Dbg_sec_added		Dbg64_sec_added
#define	Dbg_sec_backing		Dbg64_sec_backing
#define	Dbg_sec_created		Dbg64_sec_created
#define	Dbg_sec_discarded	Dbg64_sec_discarded
#define	Dbg_sec_genstr_compress	Dbg64_sec_genstr_compress
#define	Dbg_sec_group		Dbg64_sec_group
#define	Dbg_sec_gnu_comdat	Dbg64_sec_gnu_comdat
#define	Dbg_sec_in		Dbg64_sec_in
#define	Dbg_sec_order_error	Dbg64_sec_order_error
#define	Dbg_sec_order_list	Dbg64_sec_order_list
#define	Dbg_sec_redirected	Dbg64_sec_redirected
#define	Dbg_sec_strtab		Dbg64_sec_strtab
#define	Dbg_sec_unsup_strmerge	Dbg64_sec_unsup_strmerge

#define	Dbg_seg_desc_entry	Dbg64_seg_desc_entry
#define	Dbg_seg_entry		Dbg64_seg_entry
#define	Dbg_seg_list		Dbg64_seg_list
#define	Dbg_seg_os		Dbg64_seg_os
#define	Dbg_seg_title		Dbg64_seg_title

#define	Dbg_shdr_modified	Dbg64_shdr_modified

#define	Dbg_statistics_ar	Dbg64_statistics_ar
#define	Dbg_statistics_ld	Dbg64_statistics_ld

#define	Dbg_support_action	Dbg64_support_action
#define	Dbg_support_load	Dbg64_support_load
#define	Dbg_support_req		Dbg64_support_req
#define	Dbg_support_vnone	Dbg64_support_vnone

#define	Dbg_syminfo_entry	Dbg64_syminfo_entry
#define	Dbg_syminfo_title	Dbg64_syminfo_title

#define	Dbg_syms_ar_checking	Dbg64_syms_ar_checking
#define	Dbg_syms_ar_force	Dbg64_syms_ar_force
#define	Dbg_syms_ar_resolve	Dbg64_syms_ar_resolve
#define	Dbg_syms_ar_skip	Dbg64_syms_ar_skip
#define	Dbg_syms_ar_title	Dbg64_syms_ar_title
#define	Dbg_syms_cap_convert	Dbg64_syms_cap_convert
#define	Dbg_syms_cap_local	Dbg64_syms_cap_local
#define	Dbg_syms_cap_lookup	Dbg64_syms_cap_lookup
#define	Dbg_syms_cap_title	Dbg64_syms_cap_title
#define	Dbg_syms_copy_reloc	Dbg64_syms_copy_reloc
#define	Dbg_syms_created	Dbg64_syms_created
#define	Dbg_syms_discarded	Dbg64_syms_discarded
#define	Dbg_syms_dup_discarded	Dbg64_syms_dup_discarded
#define	Dbg_syms_dup_sort_addr	Dbg64_syms_dup_sort_addr
#define	Dbg_syms_entered	Dbg64_syms_entered
#define	Dbg_syms_entry		Dbg64_syms_entry
#define	Dbg_syms_global		Dbg64_syms_global
#define	Dbg_syms_ignore		Dbg64_syms_ignore
#define	Dbg_syms_ignore_gnuver	Dbg64_syms_ignore_gnuver
#define	Dbg_syms_lazy_rescan	Dbg64_syms_lazy_rescan
#define	Dbg_syms_lookup		Dbg64_syms_lookup
#define	Dbg_syms_new		Dbg64_syms_new
#define	Dbg_syms_old		Dbg64_syms_old
#define	Dbg_syms_process	Dbg64_syms_process
#define	Dbg_syms_reduce		Dbg64_syms_reduce
#define	Dbg_syms_resolved	Dbg64_syms_resolved
#define	Dbg_syms_resolving	Dbg64_syms_resolving
#define	Dbg_syms_sec_entry	Dbg64_syms_sec_entry
#define	Dbg_syms_sec_title	Dbg64_syms_sec_title
#define	Dbg_syms_spec_title	Dbg64_syms_spec_title
#define	Dbg_syms_updated	Dbg64_syms_updated
#define	Dbg_syms_up_title	Dbg64_syms_up_title
#define	Dbg_syms_wrap		Dbg64_syms_wrap

#define	Dbg_util_call_array	Dbg64_util_call_array
#define	Dbg_util_call_fini	Dbg64_util_call_fini
#define	Dbg_util_call_init	Dbg64_util_call_init
#define	Dbg_util_call_main	Dbg64_util_call_main
#define	Dbg_util_collect	Dbg64_util_collect
#define	Dbg_util_dbnotify	Dbg64_util_dbnotify
#define	Dbg_util_edge_in	Dbg64_util_edge_in
#define	Dbg_util_edge_out	Dbg64_util_edge_out
#define	Dbg_util_intoolate	Dbg64_util_intoolate
#define	Dbg_util_lcinterface	Dbg64_util_lcinterface
#define	Dbg_util_nl		Dbg64_util_nl
#define	Dbg_util_scc_entry	Dbg64_util_scc_entry
#define	Dbg_util_scc_title	Dbg64_util_scc_title
#define	Dbg_util_str		Dbg64_util_str

#define	Dbg_unused_file		Dbg64_unused_file
#define	Dbg_unused_lcinterface	Dbg64_unused_lcinterface
#define	Dbg_unused_path		Dbg64_unused_path
#define	Dbg_unused_sec		Dbg64_unused_sec
#define	Dbg_unused_unref	Dbg64_unused_unref

#define	Dbg_ver_avail_entry	Dbg64_ver_avail_entry
#define	Dbg_ver_avail_title	Dbg64_ver_avail_title
#define	Dbg_ver_def_title	Dbg64_ver_def_title
#define	Dbg_ver_desc_entry	Dbg64_ver_desc_entry
#define	Dbg_ver_need_done	Dbg64_ver_need_done
#define	Dbg_ver_need_entry	Dbg64_ver_need_entry
#define	Dbg_ver_need_title	Dbg64_ver_need_title
#define	Dbg_ver_nointerface	Dbg64_ver_nointerface
#define	Dbg_ver_symbol		Dbg64_ver_symbol

#else

#define	Dbg_demangle_name	Dbg32_demangle_name

#define	Dbg_bind_global		Dbg32_bind_global
#define	Dbg_bind_plt_summary	Dbg32_bind_plt_summary
#define	Dbg_bind_reject		Dbg32_bind_reject
#define	Dbg_bind_weak		Dbg32_bind_weak

#define	Dbg_cap_candidate	Dbg32_cap_candidate
#define	Dbg_cap_filter		Dbg32_cap_filter
#define	Dbg_cap_id		Dbg32_cap_id
#define	Dbg_cap_identical	Dbg32_cap_identical
#define	Dbg_cap_mapfile_title	Dbg32_cap_mapfile_title
#define	Dbg_cap_post_title	Dbg32_cap_post_title
#define	Dbg_cap_sec_title	Dbg32_cap_sec_title
#define	Dbg_cap_val		Dbg32_cap_val
#define	Dbg_cap_ptr_entry	Dbg32_cap_ptr_entry
#define	Dbg_cap_val_entry	Dbg32_cap_val_entry

#define	Dbg_dl_dladdr		Dbg32_dl_dladdr
#define	Dbg_dl_dlclose		Dbg32_dl_dlclose
#define	Dbg_dl_dldump		Dbg32_dl_dldump
#define	Dbg_dl_dlerror		Dbg32_dl_dlerror
#define	Dbg_dl_dlinfo		Dbg32_dl_dlinfo
#define	Dbg_dl_dlopen		Dbg32_dl_dlopen
#define	Dbg_dl_dlsym		Dbg32_dl_dlsym
#define	Dbg_dl_iphdr_enter	Dbg32_dl_iphdr_enter
#define	Dbg_dl_iphdr_callback	Dbg32_dl_iphdr_callback
#define	Dbg_dl_iphdr_mapchange	Dbg32_dl_iphdr_mapchange
#define	Dbg_dl_iphdr_unmap_ret	Dbg32_dl_iphdr_unmap_ret

#define	Dbg_ent_entry		Dbg32_ent_entry
#define	Dbg_ent_print		Dbg32_ent_print

#define	Dbg_file_analyze	Dbg32_file_analyze
#define	Dbg_file_ar		Dbg32_file_ar
#define	Dbg_file_ar_rescan	Dbg32_file_ar_rescan
#define	Dbg_file_bind_entry	Dbg32_file_bind_entry
#define	Dbg_file_bindings	Dbg32_file_bindings
#define	Dbg_file_bindings_done	Dbg32_file_bindings_done
#define	Dbg_file_cleanup	Dbg32_file_cleanup
#define	Dbg_file_cntl		Dbg32_file_cntl
#define	Dbg_file_config_dis	Dbg32_file_config_dis
#define	Dbg_file_config_obj	Dbg32_file_config_obj
#define	Dbg_file_del_rescan	Dbg32_file_del_rescan
#define	Dbg_file_delete		Dbg32_file_delete
#define	Dbg_file_deferred	Dbg32_file_deferred
#define	Dbg_file_elf		Dbg32_file_elf
#define	Dbg_file_filtee		Dbg32_file_filtee
#define	Dbg_file_filter		Dbg32_file_filter
#define	Dbg_file_fixname	Dbg32_file_fixname
#define	Dbg_file_generic	Dbg32_file_generic
#define	Dbg_file_hdl_action	Dbg32_file_hdl_action
#define	Dbg_file_hdl_collect	Dbg32_file_hdl_collect
#define	Dbg_file_hdl_title	Dbg32_file_hdl_title
#define	Dbg_file_lazyload	Dbg32_file_lazyload
#define	Dbg_file_ldso		Dbg32_file_ldso
#define	Dbg_file_mmapobj	Dbg32_file_mmapobj
#define	Dbg_file_mode_promote	Dbg32_file_mode_promote
#define	Dbg_file_modified	Dbg32_file_modified
#define	Dbg_file_needed		Dbg32_file_needed
#define	Dbg_file_output		Dbg32_file_output
#define	Dbg_file_preload	Dbg32_file_preload
#define	Dbg_file_prot		Dbg32_file_prot
#define	Dbg_file_rejected	Dbg32_file_rejected
#define	Dbg_file_reuse		Dbg32_file_reuse
#define	Dbg_file_skip		Dbg32_file_skip

#define	Dbg_got_display		Dbg32_got_display

#define	Dbg_libs_audit		Dbg32_libs_audit
#define	Dbg_libs_find		Dbg32_libs_find
#define	Dbg_libs_found		Dbg32_libs_found
#define	Dbg_libs_insecure	Dbg32_libs_insecure
#define	Dbg_libs_init		Dbg32_libs_init
#define	Dbg_libs_l		Dbg32_libs_l
#define	Dbg_libs_path		Dbg32_libs_path
#define	Dbg_libs_req		Dbg32_libs_req
#define	Dbg_libs_update		Dbg32_libs_update
#define	Dbg_libs_yp		Dbg32_libs_yp
#define	Dbg_libs_ylu		Dbg32_libs_ylu

#define	Dbg_map_cexp_id		Dbg32_map_cexp_id
#define	Dbg_map_dv		Dbg32_map_dv
#define	Dbg_map_dv_entry	Dbg32_map_dv_entry
#define	Dbg_map_ent		Dbg32_map_ent
#define	Dbg_map_ent_ord_title	Dbg32_map_ent_ord_title
#define	Dbg_map_hdr_noalloc	Dbg32_map_hdr_noalloc
#define	Dbg_map_parse		Dbg32_map_parse
#define	Dbg_map_pass		Dbg32_map_pass
#define	Dbg_map_post_title	Dbg32_map_post_title
#define	Dbg_map_seg		Dbg32_map_seg
#define	Dbg_map_seg_order	Dbg32_map_seg_order
#define	Dbg_map_seg_os_order	Dbg32_map_seg_os_order
#define	Dbg_map_size_new	Dbg32_map_size_new
#define	Dbg_map_size_old	Dbg32_map_size_old
#define	Dbg_map_sort_seg	Dbg32_map_sort_seg
#define	Dbg_map_sort_title	Dbg32_map_sort_title
#define	Dbg_map_symbol		Dbg32_map_symbol
#define	Dbg_map_version		Dbg32_map_version

#define	Dbg_move_adjexpandreloc	Dbg32_move_adjexpandreloc
#define	Dbg_move_adjmovereloc	Dbg32_move_adjmovereloc
#define	Dbg_move_bad		Dbg32_move_bad
#define	Dbg_move_data		Dbg32_move_data
#define	Dbg_move_entry1		Dbg32_move_entry1
#define	Dbg_move_entry2		Dbg32_move_entry2
#define	Dbg_move_expand		Dbg32_move_expand
#define	Dbg_move_input		Dbg32_move_input
#define	Dbg_move_outmove	Dbg32_move_outmove
#define	Dbg_move_outsctadj	Dbg32_move_outsctadj
#define	Dbg_move_parexpn	Dbg32_move_parexpn

#define	Dbg_reloc_apply_reg	Dbg32_reloc_apply_reg
#define	Dbg_reloc_apply_val	Dbg32_reloc_apply_val
#define	Dbg_reloc_ars_entry	Dbg32_reloc_ars_entry
#define	Dbg_reloc_copy		Dbg32_reloc_copy
#define	Dbg_reloc_discard	Dbg32_reloc_discard
#define	Dbg_reloc_doact		Dbg32_reloc_doact
#define	Dbg_reloc_doact_title	Dbg32_reloc_doact_title
#define	Dbg_reloc_dooutrel	Dbg32_reloc_dooutrel
#define	Dbg_reloc_entry		Dbg32_reloc_entry
#define	Dbg_reloc_error		Dbg32_reloc_error
#define	Dbg_reloc_generate	Dbg32_reloc_generate
#define	Dbg_reloc_in		Dbg32_reloc_in
#define	Dbg_reloc_ors_entry	Dbg32_reloc_ors_entry
#define	Dbg_reloc_out		Dbg32_reloc_out
#define	Dbg_reloc_proc		Dbg32_reloc_proc
#define	Dbg_reloc_run		Dbg32_reloc_run
#define	Dbg_reloc_transition	Dbg32_reloc_transition
#define	Dbg_reloc_sloppycomdat	Dbg32_reloc_sloppycomdat

#define	Dbg_sec_added		Dbg32_sec_added
#define	Dbg_sec_backing		Dbg32_sec_backing
#define	Dbg_sec_created		Dbg32_sec_created
#define	Dbg_sec_discarded	Dbg32_sec_discarded
#define	Dbg_sec_genstr_compress	Dbg32_sec_genstr_compress
#define	Dbg_sec_group		Dbg32_sec_group
#define	Dbg_sec_gnu_comdat	Dbg32_sec_gnu_comdat
#define	Dbg_sec_in		Dbg32_sec_in
#define	Dbg_sec_order_error	Dbg32_sec_order_error
#define	Dbg_sec_order_list	Dbg32_sec_order_list
#define	Dbg_sec_redirected	Dbg32_sec_redirected
#define	Dbg_sec_strtab		Dbg32_sec_strtab
#define	Dbg_sec_unsup_strmerge	Dbg32_sec_unsup_strmerge

#define	Dbg_seg_desc_entry	Dbg32_seg_desc_entry
#define	Dbg_seg_entry		Dbg32_seg_entry
#define	Dbg_seg_list		Dbg32_seg_list
#define	Dbg_seg_os		Dbg32_seg_os
#define	Dbg_seg_title		Dbg32_seg_title

#define	Dbg_shdr_modified	Dbg32_shdr_modified

#define	Dbg_statistics_ar	Dbg32_statistics_ar
#define	Dbg_statistics_ld	Dbg32_statistics_ld

#define	Dbg_support_action	Dbg32_support_action
#define	Dbg_support_load	Dbg32_support_load
#define	Dbg_support_req		Dbg32_support_req
#define	Dbg_support_vnone	Dbg32_support_vnone

#define	Dbg_syminfo_entry	Dbg32_syminfo_entry
#define	Dbg_syminfo_title	Dbg32_syminfo_title

#define	Dbg_syms_ar_checking	Dbg32_syms_ar_checking
#define	Dbg_syms_ar_force	Dbg32_syms_ar_force
#define	Dbg_syms_ar_resolve	Dbg32_syms_ar_resolve
#define	Dbg_syms_ar_skip	Dbg32_syms_ar_skip
#define	Dbg_syms_ar_title	Dbg32_syms_ar_title
#define	Dbg_syms_cap_convert	Dbg32_syms_cap_convert
#define	Dbg_syms_cap_local	Dbg32_syms_cap_local
#define	Dbg_syms_cap_lookup	Dbg32_syms_cap_lookup
#define	Dbg_syms_cap_title	Dbg32_syms_cap_title
#define	Dbg_syms_copy_reloc	Dbg32_syms_copy_reloc
#define	Dbg_syms_created	Dbg32_syms_created
#define	Dbg_syms_discarded	Dbg32_syms_discarded
#define	Dbg_syms_dup_discarded	Dbg32_syms_dup_discarded
#define	Dbg_syms_dup_sort_addr	Dbg32_syms_dup_sort_addr
#define	Dbg_syms_entered	Dbg32_syms_entered
#define	Dbg_syms_entry		Dbg32_syms_entry
#define	Dbg_syms_global		Dbg32_syms_global
#define	Dbg_syms_ignore		Dbg32_syms_ignore
#define	Dbg_syms_ignore_gnuver	Dbg32_syms_ignore_gnuver
#define	Dbg_syms_lazy_rescan	Dbg32_syms_lazy_rescan
#define	Dbg_syms_lookup		Dbg32_syms_lookup
#define	Dbg_syms_new		Dbg32_syms_new
#define	Dbg_syms_old		Dbg32_syms_old
#define	Dbg_syms_process	Dbg32_syms_process
#define	Dbg_syms_reduce		Dbg32_syms_reduce
#define	Dbg_syms_resolved	Dbg32_syms_resolved
#define	Dbg_syms_resolving	Dbg32_syms_resolving
#define	Dbg_syms_sec_entry	Dbg32_syms_sec_entry
#define	Dbg_syms_sec_title	Dbg32_syms_sec_title
#define	Dbg_syms_spec_title	Dbg32_syms_spec_title
#define	Dbg_syms_updated	Dbg32_syms_updated
#define	Dbg_syms_up_title	Dbg32_syms_up_title
#define	Dbg_syms_wrap		Dbg32_syms_wrap

#define	Dbg_util_call_array	Dbg32_util_call_array
#define	Dbg_util_call_fini	Dbg32_util_call_fini
#define	Dbg_util_call_init	Dbg32_util_call_init
#define	Dbg_util_call_main	Dbg32_util_call_main
#define	Dbg_util_collect	Dbg32_util_collect
#define	Dbg_util_dbnotify	Dbg32_util_dbnotify
#define	Dbg_util_edge_in	Dbg32_util_edge_in
#define	Dbg_util_edge_out	Dbg32_util_edge_out
#define	Dbg_util_intoolate	Dbg32_util_intoolate
#define	Dbg_util_lcinterface	Dbg32_util_lcinterface
#define	Dbg_util_nl		Dbg32_util_nl
#define	Dbg_util_scc_entry	Dbg32_util_scc_entry
#define	Dbg_util_scc_title	Dbg32_util_scc_title
#define	Dbg_util_str		Dbg32_util_str

#define	Dbg_unused_file		Dbg32_unused_file
#define	Dbg_unused_lcinterface	Dbg32_unused_lcinterface
#define	Dbg_unused_path		Dbg32_unused_path
#define	Dbg_unused_sec		Dbg32_unused_sec
#define	Dbg_unused_unref	Dbg32_unused_unref

#define	Dbg_ver_avail_entry	Dbg32_ver_avail_entry
#define	Dbg_ver_avail_title	Dbg32_ver_avail_title
#define	Dbg_ver_def_title	Dbg32_ver_def_title
#define	Dbg_ver_desc_entry	Dbg32_ver_desc_entry
#define	Dbg_ver_need_done	Dbg32_ver_need_done
#define	Dbg_ver_need_entry	Dbg32_ver_need_entry
#define	Dbg_ver_need_title	Dbg32_ver_need_title
#define	Dbg_ver_nointerface	Dbg32_ver_nointerface
#define	Dbg_ver_symbol		Dbg32_ver_symbol

#endif

/*
 * External Dbg_*() interface routines.
 */
extern	void	Dbg_args_file(Lm_list *, int, char *);
extern	void	Dbg_args_guidance_unknown(Lm_list *, const char *);
extern	void	Dbg_args_option(Lm_list *, int, int, char *);
extern	void	Dbg_args_str2chr(Lm_list *, int, const char *, int);
extern	void	Dbg_args_Wldel(Lm_list *, int, const char *);
extern	void	Dbg_audit_activity(Lm_list *, const char *, const char *,
		    uint_t);
extern	void	Dbg_audit_ignore(Rt_map *);
extern	void	Dbg_audit_interface(Lm_list *, const char *, const char *);
extern	void	Dbg_audit_lib(Rt_map *, const char *, int);
extern	void	Dbg_audit_objclose(Lm_list *, const char *, const char *);
extern	void	Dbg_audit_objopen(Lm_list *, int, const char *, const char *,
		    uint_t, Boolean);
extern	void	Dbg_audit_objfilter(Lm_list *, int, const char *, const char *,
		    const char *, const char *);
extern	void	Dbg_audit_objsearch(Lm_list *, int, const char *, const char *,
		    uint_t, const char *);
extern	void	Dbg_audit_pltenter(Lm_list *, int, const char *, const char *,
		    Addr);
extern	void	Dbg_audit_pltexit(Lm_list *, const char *, const char *);
extern	void	Dbg_audit_preinit(Lm_list *, const char *, const char *);
extern	void	Dbg_audit_symbind(Lm_list *, int, const char *, const char *,
		    Addr, uint_t);
extern	void	Dbg_audit_skip(Lm_list *, const char *, const char *);
extern	void	Dbg_audit_terminate(Lm_list *, const char *);
extern	void	Dbg_audit_version(Lm_list *, const char *, uint_t, uint_t);

extern	void	Dbg_basic_collect(Lm_list *);
extern	void	Dbg_basic_create(Lm_list *);
extern	void	Dbg_basic_finish(Lm_list *);
extern	void	Dbg_basic_files(Lm_list *);
extern	void	Dbg_basic_options(Lm_list *);
extern	void	Dbg_basic_relocate(Lm_list *);
extern	void	Dbg_basic_validate(Lm_list *);

extern	void	Dbg_bind_global(Rt_map *, Addr, Off, Xword, Pltbindtype,
		    Rt_map *, Addr, Off, const char *, uint_t);
extern	void	Dbg_bind_plt_summary(Lm_list *, Half, Word, Word, Word, Word,
		    Word, Word);
#if	defined(_ELF64)
extern	void	Dbg_bind_pltpad_from(Rt_map *, Addr, const char *);
extern	void	Dbg_bind_pltpad_to(Rt_map *, Addr, const char *, const char *);
#endif
extern	void	Dbg_bind_reject(Rt_map *, Rt_map *, const char *, int);
extern	void	Dbg_bind_weak(Rt_map *, Addr, Addr, const char *);

extern	void	Dbg_cap_candidate(Lm_list *, const char *);
extern	void	Dbg_cap_filter(Lm_list *, const char *, Rt_map *);
extern	void	Dbg_cap_id(Lm_list *, Lineno, const char *, const char *);
extern	void	Dbg_cap_identical(Lm_list *, const char *, const char *);
extern	void	Dbg_cap_mapfile_title(Lm_list *, Lineno);
extern	void	Dbg_cap_post_title(Lm_list *, int *);
extern	void	Dbg_cap_sec_title(Lm_list *, const char *);
extern	void	Dbg_cap_val(Lm_list *, Syscapset *, Syscapset *, Half);
extern	void	Dbg_cap_ptr_entry(Lm_list *, dbg_state_t, Xword, const char *);
extern	void	Dbg_cap_val_entry(Lm_list *, dbg_state_t, Xword, Xword, Half);

extern	void	Dbg_dl_dladdr(Rt_map *, void *);
extern	void	Dbg_dl_dlclose(Rt_map *, const char *, int);
extern	void	Dbg_dl_dldump(Rt_map *, const char *, const char *, int);
extern	void	Dbg_dl_dlerror(Rt_map *, const char *);
extern	void	Dbg_dl_dlinfo(Rt_map *, const char *, int, void *);
extern	void	Dbg_dl_dlopen(Rt_map *, const char *, int *, int);
extern	void	Dbg_dl_dlsym(Rt_map *, const char *, int *, const char *, int);
extern	void	Dbg_dl_iphdr_enter(Rt_map *, u_longlong_t, u_longlong_t);
extern	void	Dbg_dl_iphdr_callback(Lm_list *, struct dl_phdr_info *);
extern	void	Dbg_dl_iphdr_mapchange(Lm_list *, u_longlong_t, u_longlong_t);
extern	void	Dbg_dl_iphdr_unmap_ret(Lm_list *);

extern	const char *
		Dbg_demangle_name(const char *);

extern	void	Dbg_ent_entry(Lm_list *, uchar_t, Half, Ent_desc *);
extern	void	Dbg_ent_print(Lm_list *, uchar_t, Half, APlist *);

extern	void	Dbg_file_analyze(Rt_map *);
extern	void	Dbg_file_ar(Lm_list *, const char *, Boolean);
extern	void	Dbg_file_ar_rescan(Lm_list *, int, int);
extern	void	Dbg_file_bind_entry(Lm_list *, Bnd_desc *);
extern	void	Dbg_file_bindings(Rt_map *, int);
extern	void	Dbg_file_bindings_done(Lm_list *);
extern	void	Dbg_file_cleanup(Lm_list *, const char *, Aliste);
extern	void	Dbg_file_cntl(Lm_list *, Aliste, Aliste);
extern	void	Dbg_file_config_dis(Lm_list *, const char *, int);
extern	void	Dbg_file_config_obj(Lm_list *, const char *, const char *,
		    const char *);
extern	void	Dbg_file_del_rescan(Lm_list *);
extern	void	Dbg_file_delete(Rt_map *);
extern	void	Dbg_file_deferred(Lm_list *, const char *, const char *);
extern	void	Dbg_file_elf(Lm_list *, const char *, Addr, size_t,
		    const char *, Aliste);
extern	void	Dbg_file_filtee(Lm_list *, const char *, const char *, int);
extern	void	Dbg_file_filter(Lm_list *, const char *, const char *, int);
extern	void	Dbg_file_fixname(Lm_list *, const char *, const char *);
extern	void	Dbg_file_generic(Lm_list *, Ifl_desc *);
extern	void	Dbg_file_hdl_action(Grp_hdl *, Rt_map *, int, uint_t);
extern	void	Dbg_file_hdl_collect(Grp_hdl *, const char *);
extern	void	Dbg_file_hdl_title(int);
extern	void	Dbg_file_lazyload(Rt_map *, const char *, const char *);
extern	void	Dbg_file_ldso(Rt_map *, char **, auxv_t *, const char *,
		    Aliste);
extern	void	Dbg_file_mmapobj(Lm_list *, const char *, mmapobj_result_t *,
		    uint_t);
extern	void	Dbg_file_mode_promote(Rt_map *, int);
extern	void	Dbg_file_modified(Lm_list *, const char *, const char *,
		    const char *, int, int, Elf *, Elf *);
extern	void	Dbg_file_needed(Rt_map *, const char *);
extern	void	Dbg_file_output(Ofl_desc *);
extern	void	Dbg_file_preload(Lm_list *, const char *);
extern	void	Dbg_file_prot(Rt_map *, int);
extern	void	Dbg_file_rejected(Lm_list *, Rej_desc *, Half mach);
extern	void	Dbg_file_reuse(Lm_list *, const char *, const char *);
extern	void	Dbg_file_skip(Lm_list *, const char *, const char *);

extern	void	Dbg_got_display(Ofl_desc *, Off, int, Word, size_t);

extern	void	Dbg_libs_audit(Lm_list *, const char *, const char *);
extern	void	Dbg_libs_find(Lm_list *, const char *);
extern	void	Dbg_libs_found(Lm_list *, const char *, int);
extern	void	Dbg_libs_insecure(Lm_list *, const char *, int);
extern	void	Dbg_libs_init(Lm_list *, APlist *, APlist *);
extern	void	Dbg_libs_l(Lm_list *, const char *, const char *);
extern	void	Dbg_libs_path(Lm_list *, const char *, uint_t, const char *);
extern	void	Dbg_libs_req(Lm_list *, const char *, const char *,
		    const char *);
extern	void	Dbg_libs_update(Lm_list *, APlist *, APlist *);
extern	void	Dbg_libs_yp(Lm_list *, const char *);
extern	void	Dbg_libs_ylu(Lm_list *, const char *, const char *, int);

extern	void	Dbg_map_cexp_id(Lm_list *, Boolean, const char *, Lineno,
		    const char *);
extern	void	Dbg_map_dv(Lm_list *, const char *, Lineno);
extern	void	Dbg_map_dv_entry(Lm_list *, Lineno, int, const char *);
extern	void	Dbg_map_ent(Lm_list *, Ent_desc *, Ofl_desc *, Lineno);
extern	void	Dbg_map_ent_ord_title(Lm_list *, const char *);
extern	void	Dbg_map_hdr_noalloc(Lm_list *, Lineno);
extern	void	Dbg_map_parse(Lm_list *, const char *, int);
extern	void	Dbg_map_pass(Lm_list *, Boolean, const char *, Lineno,
		    const char *);
extern	void	Dbg_map_post_title(Lm_list *);
extern	void	Dbg_map_seg(Ofl_desc *, dbg_state_t, int, Sg_desc *, Lineno);
extern	void	Dbg_map_seg_order(Ofl_desc *, uchar_t, Half, dbg_state_t,
		    Lineno);
extern	void	Dbg_map_seg_os_order(Lm_list *, Sg_desc *, const char *,
		    Word, Lineno);
extern	void	Dbg_map_size_new(Lm_list *, const char *, const char *, Lineno);
extern	void	Dbg_map_size_old(Ofl_desc *, Sym_desc *, const char *, Lineno);
extern	void	Dbg_map_sort_title(Lm_list *, Boolean);
extern	void	Dbg_map_sort_seg(Lm_list *, uchar_t, Half, Sg_desc *);
extern	void	Dbg_map_symbol(Ofl_desc *, Sym_desc *);
extern	void	Dbg_map_version(Lm_list *, const char *, const char *, int);

extern	void	Dbg_move_adjexpandreloc(Lm_list *, Xword, const char *);
extern	void	Dbg_move_adjmovereloc(Lm_list *, Xword, Xword, const char *);
extern	void	Dbg_move_bad(Lm_list *, ulong_t, const char *, Addr);
extern	void	Dbg_move_data(Rt_map *);
extern	void	Dbg_move_entry1(Lm_list *, int, Move *, Sym_desc *);
extern	void	Dbg_move_entry2(Lm_list *, Move *, Word, const char *);
extern	void	Dbg_move_expand(Lm_list *, Move *, Addr);
extern	void	Dbg_move_input(Lm_list *, const char *);
extern	void	Dbg_move_outmove(Lm_list *, const char *);
extern	void	Dbg_move_outsctadj(Lm_list *, Sym_desc *);
extern	void	Dbg_move_parexpn(Lm_list *, const char *, const char *);

extern	void	Dbg_reloc_apply_reg(Lm_list *, int, Half, Xword, Xword);
extern	void	Dbg_reloc_apply_val(Lm_list *, int, Xword, Xword);
extern	void	Dbg_reloc_ars_entry(Lm_list *, int, Word, Half, Rel_desc *);
extern	void	Dbg_reloc_copy(Rt_map *, Rt_map *, const char *, int);
extern	void	Dbg_reloc_discard(Lm_list *, Half, Rel_desc *);
extern	void	Dbg_reloc_doact(Lm_list *, int, Half, Word, Rel_desc *,
		    Xword, Xword, rel_desc_sname_func_t);
extern	void	Dbg_reloc_doact_title(Lm_list *);
extern	void	Dbg_reloc_dooutrel(Lm_list *, Word);
extern	void	Dbg_reloc_entry(Lm_list *, const char *, Half, Word, void *,
		    const char *, const char *, const char *);
extern	void	Dbg_reloc_error(Lm_list *, int, Half, Word, void *,
		    const char *);
extern	void	Dbg_reloc_generate(Lm_list *, Os_desc *, Word);
extern	void	Dbg_reloc_in(Lm_list *, int, Half, Word, void *, const char *,
		    Word, const char *);
extern	void	Dbg_reloc_ors_entry(Lm_list *, int, Word, Half, Rel_desc *);
extern	void	Dbg_reloc_out(Ofl_desc *, int, Word, void *, const char *,
		    const char *);
extern	void	Dbg_reloc_proc(Lm_list *, Os_desc *, Is_desc *, Is_desc *);
extern	void	Dbg_reloc_run(Rt_map *, uint_t, int, int);
extern	void	Dbg_reloc_transition(Lm_list *, Half, Word, Rel_desc *,
		    rel_desc_sname_func_t);
extern	void	Dbg_reloc_sloppycomdat(Lm_list *, Sym_desc *);

extern	void	Dbg_sec_added(Lm_list *, Os_desc *, Sg_desc *);
extern	void	Dbg_sec_backing(Lm_list *);
extern	void	Dbg_sec_created(Lm_list *, Os_desc *, Sg_desc *);
extern	void	Dbg_sec_discarded(Lm_list *, Is_desc *, Is_desc *);
extern	void	Dbg_sec_genstr_compress(Lm_list *, const char *,
		    Xword, Xword);
extern	void	Dbg_sec_group(Lm_list *, Is_desc *, Group_desc *);
extern	void	Dbg_sec_gnu_comdat(Lm_list *, Is_desc *, Boolean, Boolean);
extern	void	Dbg_sec_in(Lm_list *, Is_desc *);
extern	void	Dbg_sec_order_error(Lm_list *, Ifl_desc *, Word, int);
extern	void	Dbg_sec_order_list(Ofl_desc *, int);
extern	void	Dbg_sec_redirected(Lm_list *, Is_desc *, const char *);
extern	void	Dbg_sec_strtab(Lm_list *, Os_desc *, Str_tbl *);
extern	void	Dbg_sec_unsup_strmerge(Lm_list *, Is_desc *);

extern	void	Dbg_seg_desc_entry(Lm_list *, uchar_t, Half, int, Sg_desc *,
		    Boolean);
extern	void	Dbg_seg_entry(Ofl_desc *, int, Sg_desc *);
extern	void	Dbg_seg_list(Lm_list *, uchar_t, Half, APlist *);
extern	void	Dbg_seg_os(Ofl_desc *, Os_desc *, int);
extern	void	Dbg_seg_title(Lm_list *);

extern	void	Dbg_shdr_modified(Lm_list *, const char *, uchar_t, Half,
		    Word, Shdr *, Shdr *, const char *);

extern	void	Dbg_statistics_ar(Ofl_desc *);
extern	void	Dbg_statistics_ld(Ofl_desc *);

extern	void	Dbg_support_action(Lm_list *, const char *, const char *,
		    Support_ndx, const char *);
extern	void	Dbg_support_load(Lm_list *, const char *, const char *);
extern	void	Dbg_support_req(Lm_list *, const char *, int);
extern	void	Dbg_support_vnone(Lm_list *, const char *);

extern	void	Dbg_syminfo_entry(Lm_list *, Word, Syminfo *, Sym *,
		    const char *, Dyn *);
extern	void	Dbg_syminfo_title(Lm_list *);

extern	void	Dbg_syms_ar_checking(Lm_list *, const char *, const char *,
		    Elf_Arsym *);
extern	void	Dbg_syms_ar_force(Lm_list *, const char *, const char *);
extern	void	Dbg_syms_ar_resolve(Lm_list *, const char *, const char *,
		    Elf_Arsym *);
extern	void	Dbg_syms_ar_skip(Lm_list *, const char *, Elf_Arsym *);
extern	void	Dbg_syms_ar_title(Lm_list *, const char *, Boolean);
extern	void	Dbg_syms_cap_convert(Ofl_desc *, Word, const char *, Sym *);
extern	void	Dbg_syms_cap_local(Ofl_desc *, Word, const char *, Sym *,
		    Sym_desc *);
extern	void	Dbg_syms_cap_lookup(Rt_map *, uint_t, const char *, uint_t,
		    Half, Syscapset *);
extern	void	Dbg_syms_cap_title(Ofl_desc *);
extern	void	Dbg_syms_copy_reloc(Ofl_desc *, Sym_desc *, Word);
extern	void	Dbg_syms_created(Lm_list *, const char *);
extern	void	Dbg_syms_discarded(Lm_list *, Sym_desc *);
extern	void	Dbg_syms_dup_discarded(Lm_list *, Word ndx, Sym_desc *);
extern	void	Dbg_syms_dup_sort_addr(Lm_list *, const char *, const char *,
		    const char *, Addr);
extern	void	Dbg_syms_entered(Ofl_desc *, Sym *, Sym_desc *);
extern	void	Dbg_syms_entry(Lm_list *, Word, Sym_desc *);
extern	void	Dbg_syms_global(Lm_list *, Word, const char *);
extern	void	Dbg_syms_ignore(Ofl_desc *, Sym_desc *);
extern	void	Dbg_syms_ignore_gnuver(Rt_map *, const char *, Word, Versym);
extern	void	Dbg_syms_lazy_rescan(Lm_list *, const char *);
extern	void	Dbg_syms_lookup(Rt_map *, const char *, const char *);
extern	void	Dbg_syms_new(Ofl_desc *, Sym *, Sym_desc *);
extern	void	Dbg_syms_old(Ofl_desc *, Sym_desc *);
extern	void	Dbg_syms_process(Lm_list *, Ifl_desc *);
extern	void	Dbg_syms_reduce(Ofl_desc *, int, Sym_desc *, int,
		    const char *);
extern	void	Dbg_syms_resolved(Ofl_desc *, Sym_desc *);
extern	void	Dbg_syms_resolving(Ofl_desc *, Word, const char *, int, int,
		    Sym *, Sym *, Sym_desc *, Ifl_desc *);
extern	void	Dbg_syms_sec_entry(Lm_list *, Word, Sg_desc *, Os_desc *);
extern	void	Dbg_syms_sec_title(Lm_list *);
extern	void	Dbg_syms_spec_title(Lm_list *);
extern	void	Dbg_syms_updated(Ofl_desc *, Sym_desc *, const char *);
extern	void	Dbg_syms_up_title(Lm_list *);
extern	void	Dbg_syms_wrap(Lm_list *, Word, const char *, const char *);

extern	void	Dbg_tls_modactivity(Lm_list *, void *, uint_t);
extern	void	Dbg_tls_static_block(Lm_list *, void *, ulong_t, ulong_t);
extern	void	Dbg_tls_static_resv(Rt_map *, ulong_t, ulong_t);

extern	void	Dbg_util_call_array(Rt_map *, void *, int, Word);
extern	void	Dbg_util_call_fini(Rt_map *);
extern	void	Dbg_util_call_init(Rt_map *, int);
extern	void	Dbg_util_call_main(Rt_map *);
extern	void	Dbg_util_collect(Rt_map *, int, int);
extern	void	Dbg_util_dbnotify(Lm_list *, rd_event_e, r_state_e);
extern	void	Dbg_util_edge_in(Lm_list *, Rt_map *, uint_t, Rt_map *,
		    int, int);
extern	void	Dbg_util_edge_out(Rt_map *, Rt_map *);
extern	void	Dbg_util_intoolate(Rt_map *);
extern	void	Dbg_util_lcinterface(Rt_map *, int, char *);
extern	void	Dbg_util_nl(Lm_list *, int);
extern	void	Dbg_util_scc_entry(Rt_map *, uint_t);
extern	void	Dbg_util_scc_title(Lm_list *, int);
extern	void	Dbg_util_str(Lm_list *, const char *);

extern	void	Dbg_unused_file(Lm_list *, const char *, int, uint_t);
extern	void	Dbg_unused_lcinterface(Rt_map *, Rt_map *, int);
extern	void	Dbg_unused_path(Lm_list *, const char *, uint_t, uint_t,
		    const char *);
extern	void	Dbg_unused_sec(Lm_list *, Is_desc *);
extern	void	Dbg_unused_unref(Rt_map *, const char *);

extern	void	Dbg_ver_avail_entry(Lm_list *, Ver_index *, const char *);
extern	void	Dbg_ver_avail_title(Lm_list *, const char *);
extern	void	Dbg_ver_def_title(Lm_list *, const char *);
extern	void	Dbg_ver_desc_entry(Lm_list *, Ver_desc *);
extern	void	Dbg_ver_need_done(Lm_list *);
extern	void	Dbg_ver_need_entry(Lm_list *, Half, const char *,
		    const char *);
extern	void	Dbg_ver_need_title(Lm_list *, const char *);
extern	void	Dbg_ver_nointerface(Lm_list *, const char *);
extern	void	Dbg_ver_symbol(Lm_list *, const char *);

/*
 * Define Elf_*() interface flags.
 */
#define	ELF_DBG_ELFDUMP		1
#define	ELF_DBG_RTLD		2
#define	ELF_DBG_LD		3
#define	ELF_DBG_LD_ACT		4

/*
 * Define generic Elf_*() interfaces.
 */
extern	void Elf_syminfo_entry(Lm_list *, Word, Syminfo *, const char *,
	    const char *);
extern	void Elf_syminfo_title(Lm_list *);

/*
 * Establish ELF32 and ELF64 class Elf_*() interfaces.
 */
#if	defined(_ELF64)

#define	Elf_cap_entry		Elf64_cap_entry
#define	Elf_cap_title		Elf64_cap_title

#define	Elf_demangle_name	Elf64_demangle_name
#define	Elf_dyn_entry		Elf64_dyn_entry
#define	Elf_dyn_null_entry	Elf64_dyn_null_entry
#define	Elf_dyn_title		Elf64_dyn_title

#define	Elf_ehdr		Elf64_ehdr

#define	Elf_got_entry		Elf64_got_entry
#define	Elf_got_title		Elf64_got_title

#define	Elf_reloc_apply_reg	Elf64_reloc_apply_reg
#define	Elf_reloc_apply_val	Elf64_reloc_apply_val
#define	Elf_reloc_entry_1	Elf64_reloc_entry_1
#define	Elf_reloc_entry_2	Elf64_reloc_entry_2
#define	Elf_reloc_title		Elf64_reloc_title

#define	Elf_phdr		Elf64_phdr

#define	Elf_shdr		Elf64_shdr

#define	Elf_syms_table_entry	Elf64_syms_table_entry
#define	Elf_syms_table_title	Elf64_syms_table_title

#define	Elf_ver_def_title	Elf64_ver_def_title
#define	Elf_ver_line_1		Elf64_ver_line_1
#define	Elf_ver_line_2		Elf64_ver_line_2
#define	Elf_ver_line_3		Elf64_ver_line_3
#define	Elf_ver_line_4		Elf64_ver_line_4
#define	Elf_ver_line_5		Elf64_ver_line_5
#define	Elf_ver_need_title	Elf64_ver_need_title

#else

#define	Elf_cap_entry		Elf32_cap_entry
#define	Elf_cap_title		Elf32_cap_title

#define	Elf_demangle_name	Elf32_demangle_name
#define	Elf_dyn_entry		Elf32_dyn_entry
#define	Elf_dyn_null_entry	Elf32_dyn_null_entry
#define	Elf_dyn_title		Elf32_dyn_title

#define	Elf_ehdr		Elf32_ehdr

#define	Elf_got_entry		Elf32_got_entry
#define	Elf_got_title		Elf32_got_title

#define	Elf_reloc_apply_reg	Elf32_reloc_apply_reg
#define	Elf_reloc_apply_val	Elf32_reloc_apply_val
#define	Elf_reloc_entry_1	Elf32_reloc_entry_1
#define	Elf_reloc_entry_2	Elf32_reloc_entry_2
#define	Elf_reloc_title		Elf32_reloc_title

#define	Elf_phdr		Elf32_phdr

#define	Elf_shdr		Elf32_shdr

#define	Elf_syms_table_entry	Elf32_syms_table_entry
#define	Elf_syms_table_title	Elf32_syms_table_title

#define	Elf_ver_def_title	Elf32_ver_def_title
#define	Elf_ver_line_1		Elf32_ver_line_1
#define	Elf_ver_line_2		Elf32_ver_line_2
#define	Elf_ver_line_3		Elf32_ver_line_3
#define	Elf_ver_line_4		Elf32_ver_line_4
#define	Elf_ver_line_5		Elf32_ver_line_5
#define	Elf_ver_need_title	Elf32_ver_need_title

#endif

extern	void	Elf_cap_entry(Lm_list *, Cap *, int, const char *, size_t,
		    Half);
extern	void	Elf_cap_title(Lm_list *);

extern	const char \
		*Elf_demangle_name(const char *);
extern	void	Elf_dyn_entry(Lm_list *, Dyn *, int, const char *,
		    uchar_t, Half);
extern	void	Elf_dyn_null_entry(Lm_list *, Dyn *, int, int);
extern	void	Elf_dyn_title(Lm_list *);

extern	void	Elf_ehdr(Lm_list *, Ehdr *, Shdr *);

extern	void	Elf_got_entry(Lm_list *, Sword, Addr, Xword, Half,
		    uchar_t, uchar_t, Word, void *, const char *);
extern	void	Elf_got_title(Lm_list *);

extern	void	Elf_phdr(Lm_list *, uchar_t, Half, Phdr *);

extern	void	Elf_reloc_apply_val(Lm_list *, int, Xword, Xword);
extern	void	Elf_reloc_apply_reg(Lm_list *, int, Half, Xword, Xword);
extern	void	Elf_reloc_entry_1(Lm_list *, int, const char *, Half, Word,
		    void *, const char *, const char *, const char *);
extern	void	Elf_reloc_entry_2(Lm_list *, int, const char *, Word,
		    const char *, Off, Sxword, const char *, const char *,
		    const char *);
extern	void	Elf_reloc_title(Lm_list *, int, Word);

extern	void	Elf_shdr(Lm_list *, uchar_t, Half, Shdr *);

extern	void	Elf_syms_table_entry(Lm_list *, int, const char *, uchar_t,
		    Half, Sym *, Versym, int, const char *, const char *);
extern	void	Elf_syms_table_title(Lm_list *, int);

extern	void	Elf_ver_def_title(Lm_list *);
extern	void	Elf_ver_line_1(Lm_list *, const char *, const char *,
		    const char *, const char *);
extern	void	Elf_ver_line_2(Lm_list *, const char *, const char *);
extern	void	Elf_ver_line_3(Lm_list *, const char *, const char *,
		    const char *);
extern	void	Elf_ver_line_4(Lm_list *, const char *);
extern	void	Elf_ver_line_5(Lm_list *, const char *, const char *);
extern	void	Elf_ver_need_title(Lm_list *, int);


#ifdef	__cplusplus
}
#endif

#endif /* _DEBUG_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*	Copyright (c) 1989 AT&T	*/
/*	  All Rights Reserved  	*/


/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _DWARF_H
#define	_DWARF_H

#include <sys/types.h>


#ifdef	__cplusplus
extern "C" {
#endif



/* dwarf.h - manifest constants used in the .debug section of ELF files */


/* the "tag" - the first short of any legal record */

#define	TAG_padding			0x0000
#define	TAG_array_type			0x0001
#define	TAG_class_type			0x0002
#define	TAG_entry_point			0x0003
#define	TAG_enumeration_type		0x0004
#define	TAG_formal_parameter		0x0005
#define	TAG_global_subroutine		0x0006
#define	TAG_global_variable		0x0007
#define	TAG_imported_declaration	0x0008
#define	TAG_inline_subroutine		0x0009
#define	TAG_label			0x000a
#define	TAG_lexical_block		0x000b
#define	TAG_local_variable		0x000c
#define	TAG_member			0x000d
#define	TAG_member_function		0x000e
#define	TAG_pointer_type		0x000f
#define	TAG_reference_type		0x0010
#define	TAG_source_file			0x0011
#define	TAG_string_type			0x0012
#define	TAG_structure_type		0x0013
#define	TAG_subroutine			0x0014
#define	TAG_subroutine_type		0x0015
#define	TAG_typedef			0x0016
#define	TAG_union_type			0x0017
#define	TAG_unspecified_parameters	0x0018
#define	TAG_variant			0x0019


/* attribute forms are encoded as part */
/* of the attribute name and must fit */
/* into 4 bits */

#define	FORM_MASK	0xf

#define	FORM_NONE	0x0	/* error */
#define	FORM_ADDR	0x1	/* relocated address */
#define	FORM_REF	0x2	/* reference to another .debug entry */
#define	FORM_BLOCK2	0x3	/* block with 2-byte length */
#define	FORM_BLOCK4	0x4	/* block with 4-byte length (unused) */
#define	FORM_DATA2	0x5	/* 2 bytes */
#define	FORM_DATA4	0x6	/* 4 bytes */
#define	FORM_DATA8	0x7	/* 8 bytes (two 4-byte values) */
#define	FORM_STRING	0x8	/* NUL-terminated string */


/* attribute names, halfwords with low 4 bits indicating the form */

#define	AT_padding	 (0x0000|FORM_NONE)	/* just padding */
#define	AT_sibling	 (0x0010|FORM_REF)	/* next owned declaration */
#define	AT_location	 (0x0020|FORM_BLOCK2)	/* location description */
#define	AT_name		 (0x0030|FORM_STRING)	/* symbol name */
#define	AT_dimensions	 (0x0040|FORM_DATA2)	/* array dimensions */
#define	AT_fund_type	 (0x0050|FORM_DATA2)	/* fund type enum */
#define	AT_mod_fund_type (0x0060|FORM_BLOCK2)	/* modifiers & fund type enum */
#define	AT_user_def_type (0x0070|FORM_REF)	/* type entry */
#define	AT_mod_u_d_type  (0x0080|FORM_BLOCK2)	/* modifiers & type entry ref */
#define	AT_ordering	 (0x0090|FORM_DATA2)	/* array row/column major */
#define	AT_subscr_data	 (0x00a0|FORM_BLOCK2)	/* list of array dim info */
#define	AT_byte_size	 (0x00b0|FORM_DATA4)	/* number bytes per instance */
#define	AT_bit_offset	 (0x00c0|FORM_DATA2)	/* number bits padding */
#define	AT_bit_size	 (0x00d0|FORM_DATA4)	/* number bits per instance */
#define	AT_deriv_list	 (0x00e0|FORM_BLOCK2)	/* list of base class refs */
#define	AT_element_list	 (0x00f0|FORM_BLOCK4)	/* list of enum data elements */
#define	AT_stmt_list	 (0x0100|FORM_DATA4)	/* offset in .line sect */
#define	AT_low_pc	 (0x0110|FORM_ADDR)	/* first machine instr */
#define	AT_high_pc	 (0x0120|FORM_ADDR)	/* beyond last machine instr */
#define	AT_language	 (0x0130|FORM_DATA4)	/* compiler enumeration */
#define	AT_member	 (0x0140|FORM_REF)	/* class description */
#define	AT_discr	 (0x0150|FORM_REF)	/* discriminant entry */
#define	AT_discr_value	 (0x0160|FORM_BLOCK2)	/* value of discr */
#define	AT_visibility	 (0x0170|FORM_DATA2)	/* visibility enumeration */
#define	AT_import	 (0x0180|FORM_REF)	/* imported declaration */
#define	AT_string_length (0x0190|FORM_BLOCK2)	/* runtime string size */


/* atoms which compose a location description; must fit in a byte */

#define	OP_UNK		0x00	/* error */
#define	OP_REG		0x01	/* push register (number) */
#define	OP_BASEREG	0x02	/* push value of register (number) */
#define	OP_ADDR		0x03	/* push address (relocated address) */
#define	OP_CONST	0x04	/* push constant (number) */
#define	OP_DEREF2	0x05	/* pop, deref and push 2 bytes (as a long) */
#define	OP_DEREF4	0x06	/* pop, deref and push 4 bytes (as a long) */
#define	OP_ADD		0x07	/* pop top 2 items, add, push result */

/* fundamental types; must fit in two bytes */

#define	FT_none			0x0000	/* error */
#define	FT_char			0x0001	/* "plain" char */
#define	FT_signed_char		0x0002
#define	FT_unsigned_char	0x0003
#define	FT_short		0x0004	/* "plain" short */
#define	FT_signed_short		0x0005
#define	FT_unsigned_short	0x0006
#define	FT_integer		0x0007	/* "plain" integer */
#define	FT_signed_integer	0x0008
#define	FT_unsigned_integer	0x0009
#define	FT_long			0x000a	/* "plain" long */
#define	FT_signed_long		0x000b
#define	FT_unsigned_long	0x000c
#define	FT_pointer		0x000d	/* (void *) */
#define	FT_float		0x000e
#define	FT_dbl_prec_float	0x000f
#define	FT_ext_prec_float	0x0010
#define	FT_complex		0x0011
#define	FT_dbl_prec_complex	0x0012
#define	FT_set			0x0013
#define	FT_void			0x0014


/* type modifiers; must fit in a byte */

#define	MOD_none		0x00	/* error */
#define	MOD_pointer_to		0x01
#define	MOD_reference_to	0x02


/* the "format" byte for array descriptions; formed from three */
/* one-bit fields */

#define	FMT_FT	0		/* fundamental type */
#define	FMT_UDT	1		/* user-defined type */

#define	FMT_CONST	0	/* 4-byte constant */
#define	FMT_EXPR	1	/* block with 2-byte length (loc descr) */

#define	FMT_FT_C_C	((FMT_FT <<2) | (FMT_CONST<<1) | (FMT_CONST))
#define	FMT_FT_C_X	((FMT_FT <<2) | (FMT_CONST<<1) | (FMT_EXPR))
#define	FMT_FT_X_C	((FMT_FT <<2) | (FMT_EXPR <<1) | (FMT_CONST))
#define	FMT_FT_X_X	((FMT_FT <<2) | (FMT_EXPR <<1) | (FMT_EXPR))
#define	FMT_UT_C_C	((FMT_UDT<<2) | (FMT_CONST<<1) | (FMT_CONST))
#define	FMT_UT_C_X	((FMT_UDT<<2) | (FMT_CONST<<1) | (FMT_EXPR))
#define	FMT_UT_X_C	((FMT_UDT<<2) | (FMT_EXPR <<1) | (FMT_CONST))
#define	FMT_UT_X_X	((FMT_UDT<<2) | (FMT_EXPR <<1) | (FMT_EXPR))

#define	FMT_ET		8	/* element type */


/* ordering of arrays */

#define	ORD_row_major	0
#define	ORD_col_major	1


/* visibility values */

#define	VIS_local	0	/* for static functions in C */
#define	VIS_exported	1	/* for Modula */

/*
 * DWARF Exception Header Encoding
 *
 * The DWARF Exception Header Encoding is used to describe the type of data
 * used in the .eh_frame_hdr section. The upper 4 bits indicate how the value
 * is to be applied. The lower 4 bits indicate the format of the data.
 */

/*
 * Dwarf Exception Header Value format
 */
#define	DW_EH_PE_omit		0xff    /* No value is present. */
#define	DW_EH_PE_absptr		0x00    /* Value is a void* */
#define	DW_EH_PE_uleb128	0x01    /* Unsigned value is encoded using */
					/*   the Little Endian */
					/*   Base 128 (LEB128) */
#define	DW_EH_PE_udata2		0x02    /* A 2 bytes unsigned value. */
#define	DW_EH_PE_udata4		0x03    /* A 4 bytes unsigned value. */
#define	DW_EH_PE_udata8		0x04    /* An 8 bytes unsigned value. */
#define	DW_EH_PE_signed		0x08	/* bit on for all signed encodings */
#define	DW_EH_PE_sleb128	0x09	/* Signed value is encoded using */
					/*   the Little Endian */
					/*   Base 128 (LEB128) */
#define	DW_EH_PE_sdata2		0x0a	/* A 2 bytes signed value. */
#define	DW_EH_PE_sdata4		0x0b	/* A 4 bytes signed value. */
#define	DW_EH_PE_sdata8		0x0c	/* An 8 bytes signed value. */

/*
 * Dwarf Exception Header application
 */
#define	DW_EH_PE_absptr		0x00	/* Value is used with no */
					/*  modification. */
#define	DW_EH_PE_pcrel		0x10	/* Value is reletive to the location */
					/*  of itself */
#define	DW_EH_PE_textrel	0x20
#define	DW_EH_PE_datarel	0x30	/* Value is reletive to the beginning */
					/*  of the eh_frame_hdr segment */
					/*  ( segment type PT_AMD64_UNWIND ) */
					/*  when within that segment, or to */
					/*  the GOT when without. */
#define	DW_EH_PE_funcrel	0x40
#define	DW_EH_PE_aligned	0x50	/* value is an aligned void* */
#define	DW_EH_PE_indirect	0x80	/* bit to signal indirection after */
					/*  relocation */


/* language/compiler enumeration */

typedef enum _LANG {
	LANG_UNK = 0,
	LANG_ANSI_C_V1 = 1
} LANG;

typedef enum {
	DW_SUCCESS = 0,
	DW_BAD_ENCODING,
	DW_OVERFLOW,
} dwarf_error_t;

/*
 * Little Endian Base 128 (leb128) encoding/decoding routines
 */
extern	dwarf_error_t	uleb_extract(unsigned char *, uint64_t *, size_t,
			    uint64_t *);
extern	dwarf_error_t	sleb_extract(unsigned char *, uint64_t *, size_t,
			    int64_t *);
extern	dwarf_error_t	dwarf_ehe_extract(unsigned char *, size_t, uint64_t *,
			    uint64_t *, uint_t, unsigned char *, boolean_t,
			    uint64_t, uint64_t, uint64_t);

#ifdef	__cplusplus
}
#endif


#endif /* _DWARF_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 *
 * Copyright 2022 Oxide Computer Company
 */

#ifndef	_ELFEDIT_H
#define	_ELFEDIT_H

#include	<stdio.h>
#include	<stdlib.h>
#include	<sys/types.h>
#include	<libelf.h>
#include	<stdarg.h>

/* The following are here to support use of elfedit_msg() */
#include	<sys/machelf.h>		/* EC_ macros */
#include	<libintl.h>

#ifdef	__cplusplus
extern "C" {
#endif


/*
 * elfedit uses elfedit_printf() to produce generic output to stdout.
 * elfedit_msg() is used to produce error message, or specific types
 * of terse informational messages:
 *
 *	ELFEDIT_MSG_ERR:
 *		Issues an error to stderr. elfedit_msg() does not return
 *		to the caller. Control returns to the outer loop in
 *		interactive use. elfedit exits in non-interactive use.
 *
 *	ELFEDIT_MSG_FATAL:
 *		Issues an error to stderr. elfedit_msg() exits the process,
 *		and does not return to the caller.
 *
 *	ELFEDIT_MSG_USAGE:
 *		Issues an elfedit usage message to stderr, and
 *		returns to the caller.
 *
 *	ELFEDIT_MSG_CMDUSAGE
 *		Issues an elfedit usage message to stderr, and
 *		does not return to the caller.
 *
 *	ELFEDIT_MSG_DEBUG
 *		If the ELFEDIT_F_DEBUG flag is set, the message
 *		is printed to stdout, otherwise no output is produced.
 *		elfedit_msg() returns to the caller.
 *
 *	ELFEDIT_MSG_QUIET
 *		This is a very special case, intended to handle the
 *		case where the pager subprocess exits before we are
 *		done producing output (the user presses 'q'). It acts
 *		just like ELFEDIT_MSG_ERR, except that no message is
 *		actually printed.
 *
 * In the cases where elfedit_msg() does not return to the caller, the
 * behavior depends on the mode of execution. If running in interactive
 * mode (reading from a tty), control is returned directly to the outer
 * elfedit control loop to read another command. If not running in interactive
 * mode, elfedit exits with a non-zero status.
 */
typedef enum {
	ELFEDIT_MSG_ERR = 0,
	ELFEDIT_MSG_FATAL = 1,
	ELFEDIT_MSG_USAGE = 2,
	ELFEDIT_MSG_CMDUSAGE = 3,
	ELFEDIT_MSG_DEBUG = 4,
	ELFEDIT_MSG_QUIET = 5
} elfedit_msg_t;


/*
 * Information for a single ELF section.
 *
 * NOTE: sec_xshndx
 *	A symbol table can have an associated SHT_SYMTAB_SHNDX section. This
 *	happens when the number of sections is too large to fit in the
 *	ELF symbol st_shndx field, which is a 16-bit value. The sec_xshndx
 *	field will be SHN_UNDEF if there is no such section, and will be
 *	the section index of the extended section index section assocated
 *	with the symbol table otherwise.
 *
 * NOTE: sec_versym
 *	Symbol table sections can have an SHT_SUNW_VERSYM section that
 *	contains its version indices. Other types of section will have
 *	this field set to SHN_UNDEF.
 */
typedef struct {
	Elf32_Word	sec_shndx;	/* Section index */
	Elf_Scn		*sec_scn;	/* Section descriptor */
	Elf32_Shdr	*sec_shdr;	/* Section header */
	Elf_Data	*sec_data;	/* Data region of section */
	const char	*sec_name;	/* Name of section */
} elfedit32_section_t;

typedef struct {
	Elf64_Word	sec_shndx;
	Elf_Scn		*sec_scn;
	Elf64_Shdr	*sec_shdr;
	Elf_Data	*sec_data;
	const char	*sec_name;
} elfedit64_section_t;

#ifdef _ELF64
#define	elfedit_section_t	elfedit64_section_t
#else
#define	elfedit_section_t	elfedit32_section_t
#endif


/*
 * We maintain extra information for symbol tables. We look them
 * up frequently, so we want to eliminate expensive linear searches
 * of the entire section header array. Also, symbol tables usually
 * have associated parallal sections (syminfo, versym, extended indexes, etc)
 * and we want to eliminate repeated linear lookups for them, as well as
 * the basic error checking that is necessary to ensure they match the
 * symbol table they're given.
 *
 * This extra information is kept in elfedit_symtab_t structs. Each field
 * is a section index, with SHN_UNDEF used for those that do not apply.
 */
typedef struct {
	Elf32_Word	symt_shndx;	/* Symbol table section index */
	Elf32_Word	symt_xshndx;	/* Index of extended index section */
	Elf32_Word	symt_syminfo;	/* Index of versym section */
	Elf32_Word	symt_versym;	/* Index of versym section */
} elfedit32_symtab_t;

typedef struct {
	Elf64_Word	symt_shndx;
	Elf64_Word	symt_xshndx;
	Elf64_Word	symt_versym;
	Elf64_Word	symt_syminfo;
} elfedit64_symtab_t;

#ifdef _ELF64
#define	elfedit_symtab_t	elfedit64_symtab_t
#else
#define	elfedit_symtab_t	elfedit32_symtab_t
#endif


/*
 * Information for a single ELF object.
 *
 * note:
 *	elfedit is intended to be an expert's tool, capable of modifying
 *	nearly everything in the file, whether or not such modifications
 *	are a good idea. At the same time, elfedit, via libelf, relies
 *	on the contents of the object to properly locate information in
 *	the file. As this is the same information that elfedit allows the
 *	user to modify, it should be obvious that the potential exists
 *	for users to corrupt the file to the degree that elfedit itself
 *	may fail, or produce spurious results. We allow such changes for
 *	several reasons:
 *
 *	1) Such corruption does not happen in the most obvious and
 *		useful operations elfedit supports, but comes as a result
 *		of modifying fields that contain size and offset information
 *		used to navigate the file. Non-ELF developers have
 *		little practical reason to change such things.
 *
 *	2) Producing a corrupt ELF file can be very useful
 *		for R&D and/or testing purposes.
 *
 *	3) ELF is sufficiently complex that no absolute guarantees can
 *		be made about "safe" operations, beyond the basic
 *		and obvious things that are of practical use.
 *
 *	One way we protect ourselves is via the information cached in
 *	the elfedit_obj_state_t structure at startup. By using this
 *	information, rather than constantly fetching it via libelf,
 *	we protect ourselves against many user changes, such as changing the
 *	program or section header offsets, or similar size/position fields.
 *
 *	Of course, we make no assurances that that we will be able to
 *	read the resulting file in a subsequent session.
 */
typedef struct {
	const char		*os_file;	/* Path to ELF file */
	int			os_fd;		/* Open file descriptor */
	Elf			*os_elf;	/* ELF descriptor */
	Elf32_Ehdr		*os_ehdr;	/* ELF header */
	Elf32_Word		os_dynndx;	/* Index of dynamic section */
	size_t			os_shstrndx;	/* Index of section header */
						/*	string table section */
	size_t			os_shnum;	/* # of sections in file */
	elfedit32_section_t	*os_secarr;	/* Section data */
	size_t			os_phnum;	/* # of program headers */
	Elf32_Phdr		*os_phdr;	/* Program header array */
	size_t			os_symtabnum;	/* # items in os_symtab[] */
	elfedit32_symtab_t	*os_symtab;	/* Array of symbol tbl info  */
} elfedit32_obj_state_t;

typedef struct {
	const char		*os_file;
	int			os_fd;
	Elf			*os_elf;
	Elf64_Ehdr		*os_ehdr;
	Elf64_Word		os_dynndx;
	size_t			os_shstrndx;
	size_t			os_shnum;
	elfedit64_section_t	*os_secarr;
	size_t			os_phnum;
	Elf64_Phdr		*os_phdr;
	size_t			os_symtabnum;
	elfedit64_symtab_t	*os_symtab;
} elfedit64_obj_state_t;

#ifdef _ELF64
#define	elfedit_obj_state_t	elfedit64_obj_state_t
#else
#define	elfedit_obj_state_t	elfedit32_obj_state_t
#endif


/*
 * Bit values for editor state.
 */
typedef enum {
	ELFEDIT_F_AUTOPRINT = 1, /* Print informational text about edits */
	ELFEDIT_F_DEBUG = 2,	/* Print informational text about operations */
	ELFEDIT_F_READONLY = 4,	/* File is processed readonly */
} elfedit_flag_t;

/*
 * Type used to represent the output style for printing ELF values.
 *
 * DEFAULT - Output is in 'elfdump' style, designed for human eyes.
 *	Headers, and additional information are shown.
 * SIMPLE - Output is simple, consisting only of the target item.
 *	Integer values are shown as symbolic constants when possible,
 *	and integers otherwise.
 * NUM - Like SIMPLE, except integer values are always shown as
 *	integer constants, and strings are shown as the integer
 *	offset into the string table.
 */
typedef enum {
	ELFEDIT_OUTSTYLE_DEFAULT = 0,
	ELFEDIT_OUTSTYLE_SIMPLE = 1,
	ELFEDIT_OUTSTYLE_NUM = 2
} elfedit_outstyle_t;


/*
 * The elfedit_module_t, and the types it references, are defined
 * by loadable elfedit modules, and used by elfedit. These structures
 * need to communicate internationalized strings for elfedit to print.
 *
 * We want to leave the choice of internationalization APIs, as well as
 * the decision about whether or not to even to it to the individual
 * modules. Hence, we do not use a simple (const char *) pointer to
 * communicate potentially internationalized strings. Instead, we define
 * elfedit_i18nhdl_t, an opaque type guaranteed to be large enough
 * to hold a pointer. Each module casts the handle needed to access the
 * string to this type. Each module also supplies a function
 * (mod_i18nhdl_to_str field of elfedit_module_t) that given one
 * of these opaque keys, will return a (const char *) pointer to the
 * actual string, for elfedit to print.
 *
 * If the underlying module doesn't want to implement i18n support,
 * all it has to do is cast the strings to elfedit_i18nhdl_t and
 * back.
 */
typedef uintptr_t elfedit_i18nhdl_t;



/*
 * Macro to handle casting international string "handles" to the
 * elfedit_i18nhdl_t opaque type.
 */
#define	ELFEDIT_I18NHDL(_i18n_str_ref) ((elfedit_i18nhdl_t)_i18n_str_ref)


/*
 * Return values from command functions
 */
typedef enum {
	ELFEDIT_CMDRET_NONE = 0,	/* Nothing to report */
	ELFEDIT_CMDRET_MOD = 1,		/* Command modified output ELF file */
	ELFEDIT_CMDRET_MOD_OS_MACH = 2, /* As per _MOD, include ELF header */
					/*	osabi or machine change */
	ELFEDIT_CMDRET_FLUSH = 3	/* Output file flushed: elf_update() */
} elfedit_cmdret_t;

/*
 * Prototype of an implementation function for an edit command. Note that
 * commands do not return a status:
 *	- Success is indicated by a normal return.
 *	- The command indicates a fatal error by calling elfedit_msg() with the
 *		ELFEDIT_MSG_ERR type, in which case execution does not return
 *		to the command, and the elfedit command loop knows that an
 *		error occurred.
 *	- The command is responsible for using the standard libelf
 *		mechanisms to indicate when changes have been made to
 *		the ELF file.
 */
typedef elfedit_cmdret_t elfedit32_cmd_func_t(elfedit32_obj_state_t *state,
    int argc, const char *argv[]);
typedef elfedit_cmdret_t elfedit64_cmd_func_t(elfedit64_obj_state_t *state,
    int argc, const char *argv[]);
#ifdef _ELF64
#define	elfedit_cmd_func_t	elfedit64_cmd_func_t
#else
#define	elfedit_cmd_func_t	elfedit32_cmd_func_t
#endif


/*
 * An elfedit command (elfedit_cmd_t) has a cmd_cpl field that
 * can be set to a command completion function. If such a function
 * is present (non-NULL), and the user presses the tab key at the
 * command line while the cursor is at a plain (non option) argument,
 * elfedit calls the function, passing it all the tokens up through
 * the one needing completion.  The function can use elfedit_cpl_match()
 * to enter possible alternatives.  Additionally, there are helper
 * functions built on top of elfedit_cpl_match() that simplify common cases.
 *
 *	elfedit_cpl_ato[iu]() - enter matches from elfedit_ato[iu]_sym_t
 *		mappings.
 *	elfedit_cpl_atoconst() - Enter matches for well known constants
 *	elfedit_cpl_command() - enter matches for all known commands
 *	elfedit_cpl_mod() - enter matches for all known modules.
 *	elfedit_cpl_ndx() - enter numeric index as a match
 *
 * The completion function is passed the following arguments:
 *
 *	obj_state - Object state. Will be NULL if elfedit session does not
 *		have an active object. The completion function must test
 *		the pointer before using it.
 *	cpldata - Completion data, to be passed to elfedit_cpl_match()
 *		or the helper functions built on it to register alternative
 *		strings.
 *	argc, argv - The tokens from the start of the line through
 *		the one needing completion, which will always
 *		be cmdcpl_argv[cmdcpl_argc - 1].
 *	num_opt - A count of the optional arguments (those starting with
 *		'-' at the beginning of argv. This means that argv[num_opt]
 *		is the first plain argument, and the 1-based positional
 *		number of the plain argument for which command completion
 *		is needed is (argc - num_opt).
 */
typedef void elfedit32_cmdcpl_func_t(elfedit32_obj_state_t *state,
    void *cpldata, int argc, const char *argv[], int num_opt);
typedef void elfedit64_cmdcpl_func_t(elfedit64_obj_state_t *state,
    void *cpldata, int argc, const char *argv[], int num_opt);
#ifdef _ELF64
#define	elfedit_cmdcpl_func_t	elfedit64_cmdcpl_func_t
#else
#define	elfedit_cmdcpl_func_t	elfedit32_cmdcpl_func_t
#endif




/*
 * Command option/argument descriptor. These structures
 * are used to represent each option and plain argument accepted
 * by a command, via the cmd_opt and cmd_args fields in the
 * command definition (elfedit_cmd_t). Each descriptor consists
 * of a name, a help string (formatted for display via sys:help),
 * and a flags field that conveys extra information about the
 * item:
 *
 *	ELFEDIT_CMDOA_F_OPT
 *	The item is optional. This flag is implicit for options
 *	and need only be set for plain arguments.
 *
 *	ELFEDIT_CMDOA_F_VALUE
 *	The item has a value, which is found in the following
 *	item. This flag only has meaning for options, and should
 *	not be set for plain arguments. The descriptor for the
 *	value is found in the next array element, and only the
 *	oa_name field is used (the other should be set t 0).
 *
 *	ELFEDIT_CMDOA_F_MULT
 *	More than one of the specified items may be specified
 *
 *	ELFEDIT_CMDOA_F_INHERIT
 *	This is an item for which a common definition exists.
 *	Elfedit will substitute the standard values for the
 *	name, help text, and flags. This enforces consistency
 *	in documentation, plus it is easier for the module author.
 *	When ELFEDIT_CMDOA_F_INHERIT is set:
 *		- oa_name should be set to one of the ELFEDIT_STDOA_
 *			values to specifiy which standard item is being
 *			inherited.
 *		- oa_help must be set to NULL.
 *		- It is an error to set any other flags with
 *			ELFEDIT_CMDOA_F_INHERIT.
 *		- oa_idmask and oa_excmask are used in the normal way.
 *
 * The oa_idmask and oa_excmask fields are used to identify options,
 * and to support mutual exclusion (when two or more options cannot be
 * used together). They are ignored for arguments, and should be set to 0.
 * oa_idmask is used to uniquely identify each item. When elfedit_getopt()
 * matches an option, it returns the value of oa_idmask to the caller to
 * indicate which option was matched. elfedit enforces the following rules
 * for oa_idmask, and will refuse to load a module that does not follow them:
 *	- The value of oa_idmask must be 0, or have a value that
 *		is a power of 2 (i.e. only has one bit set).
 *	- Each item that sets a non-0 value for oa_idmask must have
 *		a unique value.
 *	- If oa_idmask is 0, oa_excmask must be 0 also.
 *	- oa_excmask is set to 0 if an item is not mutually exclusive
 *		to any other item. Otherwise, it should set the bit
 *		values representing the items it is mutually exclusive to.
 *	- An oa_idmask value of 0 can be used for any item that
 *		the module does not need to identify, and which
 *		is not mutually exclusive to any other item.
 * As elfedit_getopt() processes items, it maintains a bitmask combining the
 * oa_idmask fields of all the options already seen. For each option, it uses
 * oa_excmask to check for conflicts.
 *
 * note: elfedit enforces the rule that options consist of a '-'
 *	character followed by at least one character when a module
 *	is loaded.
 */
typedef enum {
	ELFEDIT_CMDOA_F_OPT =	1,	/* Item is optional */
	ELFEDIT_CMDOA_F_VALUE =	2,	/* Item has a value arg following */
	ELFEDIT_CMDOA_F_MULT =	4,	/* More than one are allowed */
	ELFEDIT_CMDOA_F_INHERIT = 8,	/* Inherit definition: See above */
} elfedit_cmd_oa_flag_t;

typedef u_longlong_t elfedit_cmd_oa_mask_t;

typedef struct {
	const char		*oa_name;	/* Name of option */
	elfedit_i18nhdl_t	oa_help;	/* Help text for option */
	elfedit_cmd_oa_flag_t	oa_flags;	/* Additional attributes */
	elfedit_cmd_oa_mask_t	oa_idmask;	/* Unique id, returned by */
						/*	elfedit_getopt */
						/*	for use by caller */
	elfedit_cmd_oa_mask_t	oa_excmask;	/* Mutual exclusion mask */
} elfedit_cmd_optarg_t;



/*
 * These values define the standard options and arguments that a module
 * can inherit using the ELFEDIT_CMDOA_F_INHERIT flag (described above).
 * New items must be added at the end --- reordering the list will
 * require all modules to be rebuilt.
 *
 * Note: 0 cannot be used as a ELFEDIT_STDOA_ value, because a NULL
 *	value of oa_name is used to terminate argument and options lists.
 *	Therefore, these values start at 1.
 */
#define	ELFEDIT_STDOA_OPT_O		((const char *) 1)	/* -o ostyle */
#define	ELFEDIT_STDOA_OPT_AND		((const char *) 2)	/* -and */
#define	ELFEDIT_STDOA_OPT_CMP		((const char *) 3)	/* -cmp */
#define	ELFEDIT_STDOA_OPT_OR		((const char *) 4)	/* -or */

#define	ELFEDIT_NUM_STDOA	4	/* # of ELFEDIT_STDOA_ definitions */



/*
 * Definition of a command
 *
 * This structure includes an elfedit_cmd_func_t pointer, which has
 * different definitions for different ELFCLASS. Rather than needlessly
 * complicate the code with three versions of this type, and any
 * type that uses it, we simply use the GenericClass type. elfedit
 * will always cast this to the correct type before calling a module.
 *
 * cmd_name is an array of pointers to the names for the command.
 * The "primary" name should always be first, followed by any alias
 * names. The final element of the array must be a NULL pointer,
 * which terminates the list. Every command is required to have at
 * least one name, so code is allowed to assume that the first element
 * of cmd_name is non-NULL, and contains the primary name.
 *
 * Many modules provide a "default" command, which is a command
 * that is run if only the module name is specified, followed
 * by a colon (i.e. "sym:"). The way this is implemented is to
 * give the desired default command an empty string as an alias.
 * Note that the primary name cannot be an empty string, only the
 * alias name.
 *
 * cmd_opts and cmd_args are each an array of elfedit_cmd_argdesc_t
 * structures, that describe the options and plain arguments accepted
 * by the command. These arrays are used to general help text for
 * the commands. The cmd_opts array is also used to provide command
 * completion for options. Both of these arrays are terminated by
 * a final NULL element (all fields zero).
 */
typedef struct {
	elfedit32_cmd_func_t	*cmd_func;	/* Implementation */
	elfedit32_cmdcpl_func_t	*cmd_cplfunc;	/* Completion function */
	const char		**cmd_name;	/* Cmd names (null term.) */
	elfedit_i18nhdl_t	cmd_desc;	/* Short desc. of cmd purpose */
	elfedit_i18nhdl_t	cmd_help;	/* Help text for the command */
	elfedit_cmd_optarg_t	*cmd_opt;	/* Options */
	elfedit_cmd_optarg_t	*cmd_args;	/* Plain arguments */
} elfedit32_cmd_t;

typedef struct {
	elfedit64_cmd_func_t	*cmd_func;
	elfedit64_cmdcpl_func_t	*cmd_cplfunc;
	const char		**cmd_name;
	elfedit_i18nhdl_t	cmd_desc;
	elfedit_i18nhdl_t	cmd_help;
	elfedit_cmd_optarg_t	*cmd_opt;
	elfedit_cmd_optarg_t	*cmd_args;
} elfedit64_cmd_t;

#ifdef _ELF64
#define	elfedit_cmd_t		elfedit64_cmd_t
#else
#define	elfedit_cmd_t		elfedit32_cmd_t
#endif



/*
 * elfedit modules version themselves so that we can alter the definition
 * of elfedit_module_t in a backward compatible way.
 */
typedef enum {
	ELFEDIT_VER_NONE = 0,
	ELFEDIT_VER_CURRENT = 1,
	ELFEDIT_VER_NUM = 2
} elfedit_module_version_t;


/*
 * Each module returns a pointer to an elfedit_module_t, describing
 * what commands the module provides.
 *
 * Note: mod_cmds is a NULL terminated array of command defs. This
 * means that the final element in the array should have all of its
 * fields set to NULL.
 *
 * The mod_i18nhdl_to_str function pointer is explained above
 * with the definition of elfedit_i18nhdl_t.
 */
typedef const char *(* elfedit_mod_i18nhdl_to_str_func_t)(elfedit_i18nhdl_t);

typedef struct {
	elfedit_module_version_t mod_version;	/* version */
	const char		*mod_name;	/* Name of module */
	elfedit_i18nhdl_t	mod_desc;	/* Short desc. of mod purpose */
	elfedit32_cmd_t		*mod_cmds;	/* Array of command defs */
						/* i18n -> (char *) fcn */
	elfedit_mod_i18nhdl_to_str_func_t mod_i18nhdl_to_str;
} elfedit32_module_t;

typedef struct {
	elfedit_module_version_t mod_version;
	const char		*mod_name;
	elfedit_i18nhdl_t	mod_desc;
	elfedit64_cmd_t		*mod_cmds;
	elfedit_mod_i18nhdl_to_str_func_t mod_i18nhdl_to_str;
} elfedit64_module_t;

#ifdef _ELF64
#define	elfedit_module_t	elfedit64_module_t
#else
#define	elfedit_module_t	elfedit32_module_t
#endif


/*
 * Each module is a sharable library, expected to provide a single global
 * function, named elfedit_init(), with the following prototype.
 */
typedef elfedit_module_t *elfedit_init_func_t(elfedit_module_version_t version);


/*
 * Prototype for elfedit_write(), and for outfunc argument
 * to elfedit_str_to_c_literal().
 */
typedef void elfedit_write_func_t(const void *ptr, size_t size);


/*
 * Core elfedit functions exported for use by modules
 */
extern void elfedit_command_usage(void);
extern void elfedit_cpl_command(void *cpldata);
extern void elfedit_cpl_match(void *cpldata, const char *str, int casefold);
extern void elfedit_cpl_ndx(void *cpldata, uint_t ndx);
extern void elfedit_elferr(const char *file, const char *libelf_rtn_name);
extern elfedit_flag_t elfedit_flags(void);
extern void *elfedit_malloc(const char *item_name, size_t size);
extern void elfedit_msg(elfedit_msg_t type, const char *format, ...);
extern elfedit_outstyle_t elfedit_outstyle(void);
extern void elfedit_pager_init(void);
extern void elfedit_printf(const char *format, ...);
extern void *elfedit_realloc(const char *item_name, void *ptr, size_t size);
extern void elfedit_str_to_c_literal(const char *str,
    elfedit_write_func_t *outfunc);
extern elfedit_write_func_t elfedit_write;

/*
 * Core elfedit functions exported for use by sys: module only
 */
extern void elfedit_cpl_module(void *cpldata, int load_all_modules);


/*
 * elfedit modules are expected to define two functions, one for
 * each ELFCLASS. Define a generic name for this function, based on
 * the class being supported by the including module.
 */
#ifdef _ELF64
#define	elfedit_init		elfedit64_init
#else
#define	elfedit_init		elfedit32_init
#endif



/*
 * It is common to search the dynamic section for specific elements.
 * Structures of this type are used to represent the contents of such
 * elements in a systematic way. The elfedit_dyn_elt_init() function
 * is used to prepare these strucutres for use.
 */
typedef struct {
	int		dn_seen;	/* True if this item has been seen */
	Elf32_Word	dn_ndx;		/* Index of item in dynamic array */
	Elf32_Dyn	dn_dyn;		/* Contents of dynamic item */
} elfedit32_dyn_elt_t;

typedef struct {
	int		dn_seen;
	Elf64_Word	dn_ndx;
	Elf64_Dyn	dn_dyn;
} elfedit64_dyn_elt_t;

#ifdef _ELF64
#define	elfedit_dyn_elt_t	elfedit64_dyn_elt_t
#else
#define	elfedit_dyn_elt_t	elfedit32_dyn_elt_t
#endif

/*
 * The elfedit_atoi() and elfedit_atoui() functions can optionally
 * accept an array of these structures, giving symbolic names that
 * will be accepted instead of numeric codes. If such an array is
 * present, the supplied string has it's leading and trailing whitespace
 * removed and is then compared to the list, and if there is a match,
 * the corresponding integer value is returned.
 *
 * The final array element must have its name field set to NULL.
 */
typedef u_longlong_t elfedit_atoui_t;
typedef struct {
	const char	*sym_name;
	elfedit_atoui_t	sym_value;
} elfedit_atoui_sym_t;
typedef longlong_t elfedit_atoi_t;
typedef struct {
	const char	*sym_name;
	elfedit_atoi_t	sym_value;
} elfedit_atoi_sym_t;


/*
 * The elfedit_atoconst*() functions are built on top of the atoui routines.
 * These routines accept an elfedit_const_t code instead of a
 * pointer to an elfedit_atoui_sym_t array, and use internally
 * predefined tables of elfedit_atoui_sym_t in order to do the desired
 * mappings. elfedit modules are encouraged to use these standard
 * tables instead of defining their own elfedit_atoui_sym_t arrays.
 *
 * note:
 *	- The values assigned here must be in agreement with the
 *		sym_table[] array defined in elfconst.c.
 *	- Once defined, these values must not change. Reordering the
 *		list will require all modules to be rebuilt, and will
 *		break backward compatability. New items should be
 *		added to the end.
 */
typedef enum {
	ELFEDIT_CONST_OUTSTYLE =	0,	/* elfedit output styles  */
	ELFEDIT_CONST_OUTSTYLE_MO =	1,	/* ostyles with -o prefix */
	ELFEDIT_CONST_BOOL =		2,	/* boolean names */
	ELFEDIT_CONST_SHT_STRTAB =	3,	/* ELF SHT_STRTAB */
	ELFEDIT_CONST_SHT_SYMTAB =	4,	/* ELF SHT_SYMTAB */
	ELFEDIT_CONST_SHT_DYNSYM =	5,	/* ELF SHT_DYNSYM */
	ELFEDIT_CONST_SHT_LDYNSYM =	6,	/* ELF SHT_SUNW_LDYNSYM */
	ELFEDIT_CONST_SHN =		7,	/* ELF SHN_ section indexes  */
	ELFEDIT_CONST_SHT =		8,	/* ELF SHT_ section types  */
	ELFEDIT_CONST_SHT_ALLSYMTAB =	9,	/* ELF SHT_ symbol table */
						/*	section types */
	ELFEDIT_CONST_DT =		10,	/* Dynamic tags: DT_ */
	ELFEDIT_CONST_DF =		11,	/* DT_FLAGS bits */
	ELFEDIT_CONST_DF_P1 =		12,	/* DF_POSFLAG_1 bits */
	ELFEDIT_CONST_DF_1 =		13,	/* DT_FLAGS_1 bits */
	ELFEDIT_CONST_DTF_1 =		14,	/* DT_FEATURE_1 bits */
	ELFEDIT_CONST_EI =		15,	/* ELF header e_ident indexes */
	ELFEDIT_CONST_ET =		16,	/* Ehdr obj type */
	ELFEDIT_CONST_ELFCLASS =	17,	/* Ehdr wordsize (32,64) */
	ELFEDIT_CONST_ELFDATA =		18,	/* Ehdr endian */
	ELFEDIT_CONST_EF =		19,	/* Ehdr flags */
	ELFEDIT_CONST_EV =		20,	/* Ehdr version */
	ELFEDIT_CONST_EM =		21,	/* Ehdr machine */
	ELFEDIT_CONST_ELFOSABI =	22,	/* Ehdr ABI */
	ELFEDIT_CONST_EAV =		23,	/* Ehdr ABI version */
	ELFEDIT_CONST_PT =		24,	/* Phdr type */
	ELFEDIT_CONST_PF =		25,	/* Phdr flags */
	ELFEDIT_CONST_SHF =		26,	/* Shdr flags */
	ELFEDIT_CONST_STB =		27,	/* Sym binding */
	ELFEDIT_CONST_STT =		28,	/* Sym type */
	ELFEDIT_CONST_STV =		29,	/* Sym visibility */
	ELFEDIT_CONST_SYMINFO_BT =	30,	/* Syminfo boundto */
	ELFEDIT_CONST_SYMINFO_FLG =	31,	/* Syminfo flags */
	ELFEDIT_CONST_CA =		32,	/* Capabilities tags */
	ELFEDIT_CONST_HW1_SUNW =	33,	/* hardware capabilities */
	ELFEDIT_CONST_SF1_SUNW =	34,	/* software capabilities */
	ELFEDIT_CONST_HW2_SUNW =	35,	/* hardware capabilities */
	ELFEDIT_CONST_HW3_SUNW =	36,	/* hardware capabilities */

	ELFEDIT_CONST_NUM =		37,	/* # of constant types */
} elfedit_const_t;

/*
 * Given an elfedit_const_t, return the array of elfedit_atoui_sym_t
 * entries that it represents.
 */
extern elfedit_atoui_sym_t *elfedit_const_to_atoui(elfedit_const_t const_type);

/*
 * ato[u]i and const routines, used to turn strings into numeric values,
 * with support for mapping symbol names to numbers, and range checking.
 */
extern elfedit_atoi_t elfedit_atoi(const char *str,
    const elfedit_atoi_sym_t *sym);
extern elfedit_atoui_t elfedit_atoui(const char *str,
    const elfedit_atoui_sym_t *sym);
extern elfedit_atoui_t elfedit_atoconst(const char *str,
    elfedit_const_t const_type);

extern int elfedit_atoi2(const char *str, const elfedit_atoi_sym_t *sym,
    elfedit_atoi_t *v);
extern int elfedit_atoui2(const char *str, const elfedit_atoui_sym_t *sym,
    elfedit_atoui_t *);
extern int elfedit_atoconst2(const char *str, elfedit_const_t const_type,
    elfedit_atoui_t *);

extern elfedit_atoi_t elfedit_atoi_range(const char *str,
    const char *item_name, elfedit_atoi_t min, elfedit_atoi_t max,
    const elfedit_atoi_sym_t *sym);
extern elfedit_atoui_t elfedit_atoui_range(const char *str,
    const char *item_name, elfedit_atoui_t min, elfedit_atoui_t max,
    const elfedit_atoui_sym_t *sym);
extern elfedit_atoui_t elfedit_atoconst_range(const char *str,
    const char *item_name, elfedit_atoui_t min, elfedit_atoui_t max,
    elfedit_const_t const_type);

extern int elfedit_atoi_range2(const char *str, elfedit_atoi_t min,
    elfedit_atoi_t max, const elfedit_atoi_sym_t *sym, elfedit_atoi_t *v);
extern int elfedit_atoui_range2(const char *str, elfedit_atoui_t min,
    elfedit_atoui_t max, const elfedit_atoui_sym_t *sym, elfedit_atoui_t *v);
extern int elfedit_atoconst_range2(const char *str, elfedit_atoui_t min,
    elfedit_atoui_t max, elfedit_const_t const_type, elfedit_atoui_t *v);

extern const char *elfedit_atoi_value_to_str(const elfedit_atoi_sym_t *sym,
    elfedit_atoi_t value, int required);
extern const char *elfedit_atoui_value_to_str(const elfedit_atoui_sym_t *sym,
    elfedit_atoui_t value, int required);
extern const char *elfedit_atoconst_value_to_str(elfedit_const_t const_type,
    elfedit_atoui_t value, int required);

extern void elfedit_cpl_atoi(void *cpldata, const elfedit_atoi_sym_t *sym);
extern void elfedit_cpl_atoui(void *cpldata, const elfedit_atoui_sym_t *sym);
extern void elfedit_cpl_atoconst(void *cpldata, elfedit_const_t const_type);


/*
 * Convenience functions built on top of the ato[u]i routines.
 */
extern int elfedit_atobool(const char *str, const char *item_name);
extern elfedit_atoui_t elfedit_atoshndx(const char *str, size_t shnum);


/*
 * elfedit provides a getopt utility for use by the module commands.
 * elfedit_getopt_state_t is the state block used by elfedit_getopt().
 * elfedit_getopt_ret_t is the definition of the values returned to
 * the user by elfedit_getopt() when an option is matched. Elfedit
 * getopt processing is done as follows:
 *
 * 1) The caller initializes an elfedit_getopt_state_t struct via
 *	a call to elfedit_getopt_init(). The contents of this structure
 *	must not be accessed by the caller, as they are all private and
 *	subject to change.
 * 2) Repeated calls are made to elfedit_getopt(), as long as it returns
 *	a non-NULL pointer to an elfedit_getopt_ret_t structure. If the
 *	matched option has a value (ELFEDIT_CMDOA_F_VALUE), then the gor_value
 *	field contains the pointer to the string. Otherwise, gor_value is NULL.
 * 3) As elfedit_getopt() consumes optional arguments from the argc/argv
 *	passed to elfedit_getopt_init(), it adjusts argc/argc to skip over
 *	them. Once elfedit_getopt() returns NULL to indicate that there are no
 *	more options to match, argc/argv have been adjusted so that they
 *	reference the plain arguments.
 */
typedef struct {
	elfedit_cmd_oa_mask_t gor_idmask;	/* oa_idmask from matching */
					/*	elfedit_cmd_optarg_t. Can be */
					/*	used to quickly identify opt */
	const char	*gor_value;	/* Opt value if ELFEDIT_CMDOA_F_VALUE */
					/*	Otherwise, NULL */
} elfedit_getopt_ret_t;
typedef struct {
	int			*go_argc;	/* Pointer to # of options */
	const char		***go_argv;	/* Ptr to array of opt strs */
	elfedit_cmd_optarg_t	*go_optarg;	/* Array of allowed options */
	elfedit_cmd_oa_mask_t	go_idmask;	/* Combined id masks of all */
						/*	seen options */
	int			go_done;	/* True if last option seen */
	const char		*go_sglgrp;	/* Group of 1-letter opts */
	elfedit_getopt_ret_t	go_ret;		/* Data returned to user */
} elfedit_getopt_state_t;



/*
 * getopt related routines
 */
extern void elfedit_getopt_init(elfedit_getopt_state_t *,
    int *, const char ***);
extern elfedit_getopt_ret_t *elfedit_getopt(elfedit_getopt_state_t *);



/*
 * Additional utility functions exported for use by modules
 */
extern void elfedit_array_elts_delete(const char *name_str, void *data_start,
    size_t entsize, size_t num_ent, size_t start_ndx, size_t cnt);

extern void elfedit_array_elts_move(const char *name_str, void *data_start,
    size_t entsize, size_t num_ent, size_t srcndx,
    size_t dstndx, size_t cnt, void *scr_item);

extern int elfedit_bits_set(u_longlong_t v, int sizeof_orig_v);

extern void elfedit32_dyn_elt_init(elfedit32_dyn_elt_t *dyn_elt);
extern void elfedit64_dyn_elt_init(elfedit64_dyn_elt_t *dyn_elt);

extern void elfedit32_dyn_elt_save(elfedit32_dyn_elt_t *elt, Elf32_Word ndx,
    Elf32_Dyn *dyn);
extern void elfedit64_dyn_elt_save(elfedit64_dyn_elt_t *elt, Elf64_Word ndx,
    Elf64_Dyn *dyn);

const char *elfedit32_dyn_offset_to_str(elfedit32_section_t *strsec,
    elfedit32_dyn_elt_t *dynelt);
const char *elfedit64_dyn_offset_to_str(elfedit64_section_t *strsec,
    elfedit64_dyn_elt_t *dynelt);

extern int elfedit32_dynstr_getpad(elfedit32_obj_state_t *obj_state,
    elfedit32_section_t *dynsec, elfedit32_dyn_elt_t *dyn_strpad);
extern int elfedit64_dynstr_getpad(elfedit64_obj_state_t *obj_state,
    elfedit64_section_t *dynsec, elfedit64_dyn_elt_t *dyn_strpad);

extern Elf32_Word elfedit32_dynstr_insert(elfedit32_section_t *dynsec,
    elfedit32_section_t *strsec, elfedit32_dyn_elt_t *dyn_strpad,
    const char *str);
extern Elf64_Word elfedit64_dynstr_insert(elfedit64_section_t *dynsec,
    elfedit64_section_t *strsec, elfedit64_dyn_elt_t *dyn_strpad,
    const char *str);

extern void elfedit32_modified_data(elfedit32_section_t *s);
extern void elfedit64_modified_data(elfedit64_section_t *s);

extern void elfedit32_modified_ehdr(elfedit32_obj_state_t *obj_state);
extern void elfedit64_modified_ehdr(elfedit64_obj_state_t *obj_state);

extern void elfedit32_modified_phdr(elfedit32_obj_state_t *obj_state);
extern void elfedit64_modified_phdr(elfedit64_obj_state_t *obj_state);

extern void elfedit32_modified_shdr(elfedit32_section_t *s);
extern void elfedit64_modified_shdr(elfedit64_section_t *s);

extern Elf32_Word elfedit32_name_to_shndx(elfedit32_obj_state_t *obj_state,
    const char *shnam);
extern Elf64_Word elfedit64_name_to_shndx(elfedit64_obj_state_t *obj_state,
    const char *shnam);

extern int elfedit32_name_to_symndx(elfedit32_section_t *symsec,
    elfedit32_section_t *strsec, const char *name, elfedit_msg_t msg_type,
    Elf32_Word *ret_symndx);
extern int elfedit64_name_to_symndx(elfedit64_section_t *symsec,
    elfedit64_section_t *strsec, const char *name, elfedit_msg_t msg_type,
    Elf64_Word *ret_symndx);

extern const char *elfedit32_offset_to_str(elfedit32_section_t *strsec,
    Elf32_Word offset, elfedit_msg_t msg_type, int debug_msg);
extern const char *elfedit64_offset_to_str(elfedit64_section_t *strsec,
    Elf64_Word offset, elfedit_msg_t msg_type, int debug_msg);

extern int elfedit32_sec_findstr(elfedit32_section_t *sec, Elf32_Word tail_ign,
    const char *str, Elf32_Word *ret_offset);
extern int elfedit64_sec_findstr(elfedit64_section_t *sec, Elf64_Word tail_ign,
    const char *str, Elf64_Word *ret_offset);

extern elfedit32_section_t *elfedit32_sec_get(
    elfedit32_obj_state_t *obj_state, Elf32_Word shndx);
extern elfedit64_section_t *elfedit64_sec_get(
    elfedit64_obj_state_t *obj_state, Elf64_Word shndx);

extern elfedit32_section_t *elfedit32_sec_getcap(
    elfedit32_obj_state_t *obj_state, Elf32_Cap **cap, Elf32_Word *num);
extern elfedit64_section_t *elfedit64_sec_getcap(
    elfedit64_obj_state_t *obj_state, Elf64_Cap **cap, Elf64_Word *num);

extern elfedit32_section_t *elfedit32_sec_getdyn(
    elfedit32_obj_state_t *obj_state, Elf32_Dyn **dyn, Elf32_Word *num);
extern elfedit64_section_t *elfedit64_sec_getdyn(
    elfedit64_obj_state_t *obj_state, Elf64_Dyn **dyn, Elf64_Word *num);

extern elfedit32_section_t *elfedit32_sec_getstr(
    elfedit32_obj_state_t *obj_state, Elf32_Word shndx, int);
extern elfedit64_section_t *elfedit64_sec_getstr(
    elfedit64_obj_state_t *obj_state, Elf64_Word shndx, int);

extern elfedit32_section_t *elfedit32_sec_getsyminfo(
    elfedit32_obj_state_t *obj_state, Elf32_Syminfo **syminfo, Elf32_Word *num);
extern elfedit64_section_t *elfedit64_sec_getsyminfo(
    elfedit64_obj_state_t *obj_state, Elf64_Syminfo **syminfo, Elf64_Word *num);

extern elfedit32_section_t *elfedit32_sec_getsymtab(
    elfedit32_obj_state_t *obj_state, int by_index, Elf32_Word index,
    const char *name, Elf32_Sym **sym, Elf32_Word *num,
    elfedit32_symtab_t **aux_info);
extern elfedit64_section_t *elfedit64_sec_getsymtab(
    elfedit64_obj_state_t *obj_state, int by_index, Elf64_Word index,
    const char *name, Elf64_Sym **sym, Elf64_Word *num,
    elfedit64_symtab_t **aux_info);

extern elfedit32_section_t *elfedit32_sec_getversym(
    elfedit32_obj_state_t *obj_state, elfedit32_section_t *symsec,
    Elf32_Versym **versym, Elf32_Word *num);
extern elfedit64_section_t *elfedit64_sec_getversym(
    elfedit64_obj_state_t *obj_state, elfedit64_section_t *symsec,
    Elf64_Versym **versym, Elf64_Word *num);

extern elfedit32_section_t *elfedit32_sec_getxshndx(
    elfedit32_obj_state_t *obj_state, elfedit32_section_t *symsec,
    Elf32_Word **xshndx, Elf32_Word *num);
extern elfedit64_section_t *elfedit64_sec_getxshndx(
    elfedit64_obj_state_t *obj_state, elfedit64_section_t *symsec,
    Elf64_Word **xshndx, Elf64_Word *num);

extern int elfedit32_sec_issymtab(elfedit32_obj_state_t *obj_state,
    elfedit32_section_t *sec, int issue_err, elfedit_atoui_sym_t **atoui_list);
extern int elfedit64_sec_issymtab(elfedit64_obj_state_t *obj_state,
    elfedit64_section_t *sec, int issue_err, elfedit_atoui_sym_t **atoui_list);

extern const char *elfedit32_sec_msgprefix(elfedit32_section_t *sec);
extern const char *elfedit64_sec_msgprefix(elfedit64_section_t *sec);

extern const char *elfedit32_shndx_to_name(elfedit32_obj_state_t *obj_state,
    Elf32_Word shndx);
extern const char *elfedit64_shndx_to_name(elfedit64_obj_state_t *obj_state,
    Elf64_Word shndx);

extern Elf32_Word elfedit32_strtab_insert(elfedit32_obj_state_t *obj_state,
    elfedit32_section_t *strsec, elfedit32_section_t *dynsec, const char *str);
extern Elf64_Word elfedit64_strtab_insert(elfedit64_obj_state_t *obj_state,
    elfedit64_section_t *strsec, elfedit64_section_t *dynsec, const char *str);

extern void elfedit32_strtab_insert_test(elfedit32_obj_state_t *obj_state,
    elfedit32_section_t *strsec, elfedit32_section_t *dynsec, const char *str);
extern void elfedit64_strtab_insert_test(elfedit64_obj_state_t *obj_state,
    elfedit64_section_t *strsec, elfedit64_section_t *dynsec, const char *str);

extern int elfedit32_test_osabi(elfedit32_obj_state_t *obj_state, uchar_t osabi,
    int issue_err);
extern int elfedit64_test_osabi(elfedit64_obj_state_t *obj_state, uchar_t osabi,
    int issue_err);

extern Elf32_Word elfedit32_type_to_shndx(elfedit32_obj_state_t *obj_state,
    Elf32_Word shtype);
extern Elf64_Word elfedit64_type_to_shndx(elfedit64_obj_state_t *obj_state,
    Elf64_Word shtype);



/*
 * Map the generic names for each of the ELFCLASS specific routines
 * above to reference the proper routine for the current compilation.
 */
#ifdef _ELF64
#define	elfedit_dyn_elt_init		elfedit64_dyn_elt_init
#define	elfedit_dyn_elt_save		elfedit64_dyn_elt_save
#define	elfedit_dyn_offset_to_str	elfedit64_dyn_offset_to_str
#define	elfedit_dynstr_getpad		elfedit64_dynstr_getpad
#define	elfedit_dynstr_insert		elfedit64_dynstr_insert
#define	elfedit_modified_data		elfedit64_modified_data
#define	elfedit_modified_ehdr		elfedit64_modified_ehdr
#define	elfedit_modified_phdr		elfedit64_modified_phdr
#define	elfedit_modified_shdr		elfedit64_modified_shdr
#define	elfedit_name_to_shndx		elfedit64_name_to_shndx
#define	elfedit_name_to_symndx		elfedit64_name_to_symndx
#define	elfedit_offset_to_str		elfedit64_offset_to_str
#define	elfedit_sec_findstr		elfedit64_sec_findstr
#define	elfedit_sec_get			elfedit64_sec_get
#define	elfedit_sec_getcap		elfedit64_sec_getcap
#define	elfedit_sec_getdyn		elfedit64_sec_getdyn
#define	elfedit_sec_getstr		elfedit64_sec_getstr
#define	elfedit_sec_getsyminfo		elfedit64_sec_getsyminfo
#define	elfedit_sec_getsymtab		elfedit64_sec_getsymtab
#define	elfedit_sec_getversym		elfedit64_sec_getversym
#define	elfedit_sec_getxshndx		elfedit64_sec_getxshndx
#define	elfedit_sec_issymtab		elfedit64_sec_issymtab
#define	elfedit_shndx_to_name		elfedit64_shndx_to_name
#define	elfedit_sec_msgprefix		elfedit64_sec_msgprefix
#define	elfedit_strtab_insert		elfedit64_strtab_insert
#define	elfedit_strtab_insert_test	elfedit64_strtab_insert_test
#define	elfedit_test_osabi		elfedit64_test_osabi
#define	elfedit_type_to_shndx		elfedit64_type_to_shndx
#else
#define	elfedit_dyn_elt_init		elfedit32_dyn_elt_init
#define	elfedit_dyn_elt_save		elfedit32_dyn_elt_save
#define	elfedit_dyn_offset_to_str	elfedit32_dyn_offset_to_str
#define	elfedit_dynstr_getpad		elfedit32_dynstr_getpad
#define	elfedit_dynstr_insert		elfedit32_dynstr_insert
#define	elfedit_modified_data		elfedit32_modified_data
#define	elfedit_modified_ehdr		elfedit32_modified_ehdr
#define	elfedit_modified_phdr		elfedit32_modified_phdr
#define	elfedit_modified_shdr		elfedit32_modified_shdr
#define	elfedit_name_to_shndx		elfedit32_name_to_shndx
#define	elfedit_name_to_symndx		elfedit32_name_to_symndx
#define	elfedit_offset_to_str		elfedit32_offset_to_str
#define	elfedit_sec_findstr		elfedit32_sec_findstr
#define	elfedit_sec_get			elfedit32_sec_get
#define	elfedit_sec_getcap		elfedit32_sec_getcap
#define	elfedit_sec_getdyn		elfedit32_sec_getdyn
#define	elfedit_sec_getstr		elfedit32_sec_getstr
#define	elfedit_sec_getsyminfo		elfedit32_sec_getsyminfo
#define	elfedit_sec_getsymtab		elfedit32_sec_getsymtab
#define	elfedit_sec_getversym		elfedit32_sec_getversym
#define	elfedit_sec_getxshndx		elfedit32_sec_getxshndx
#define	elfedit_sec_issymtab		elfedit32_sec_issymtab
#define	elfedit_shndx_to_name		elfedit32_shndx_to_name
#define	elfedit_sec_msgprefix		elfedit32_sec_msgprefix
#define	elfedit_strtab_insert		elfedit32_strtab_insert
#define	elfedit_strtab_insert_test	elfedit32_strtab_insert_test
#define	elfedit_test_osabi		elfedit32_test_osabi
#define	elfedit_type_to_shndx		elfedit32_type_to_shndx
#endif


#ifdef	__cplusplus
}
#endif

#endif	/* _ELFEDIT_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 *	Copyright (c) 1988 AT&T
 *	  All Rights Reserved
 *
 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
 *
 * Global include file for all sgs ia32 based machine dependent macros,
 * constants and declarations.
 */

#ifndef	_MACHDEP_X86_H
#define	_MACHDEP_X86_H

#include <link.h>
#include <sys/machelf.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Elf header information.
 */
#define	M_MACH_32		EM_386
#define	M_MACH_64		EM_AMD64

#ifdef _ELF64
#define	M_MACH			EM_AMD64
#define	M_CLASS			ELFCLASS64
#else
#define	M_MACH			EM_386
#define	M_CLASS			ELFCLASS32
#endif

#define	M_MACHPLUS		M_MACH
#define	M_DATA			ELFDATA2LSB
#define	M_FLAGSPLUS		0

/*
 * Page boundary Macros: truncate to previous page boundary and round to
 * next page boundary (refer to generic macros in ../sgs.h also).
 */
#define	M_PTRUNC(X)	((X) & ~(syspagsz - 1))
#define	M_PROUND(X)	(((X) + syspagsz - 1) & ~(syspagsz - 1))

/*
 * Segment boundary macros: truncate to previous segment boundary and round
 * to next page boundary.
 */
#if	defined(_ELF64)
#define	M_SEGSIZE	ELF_AMD64_MAXPGSZ
#else
#define	M_SEGSIZE	ELF_386_MAXPGSZ
#endif

#define	M_STRUNC(X)	((X) & ~(M_SEGSIZE - 1))
#define	M_SROUND(X)	(((X) + M_SEGSIZE - 1) & ~(M_SEGSIZE - 1))

/*
 * Relocation type macros.
 */
#if	defined(_ELF64)
#define	M_RELOC		Rela
#else
#define	M_RELOC		Rel
#endif

/*
 * TLS static segments must be rounded to the following requirements,
 * due to libthread stack allocation.
 */
#if	defined(_ELF64)
#define	M_TLSSTATALIGN	0x10
#else
#define	M_TLSSTATALIGN	0x08
#endif

/*
 * Other machine dependent entities
 */
#if	defined(_ELF64)
#define	M_SEGM_ALIGN	0x00010000
#else
#define	M_SEGM_ALIGN	ELF_386_MAXPGSZ
#endif

/*
 * Values for IA32 objects
 */

/*
 * Instruction encodings.
 */
#define	M_INST_JMP		0xe9
#define	M_INST_PUSHL		0x68
#define	M_SPECIAL_INST		0xff
#define	M_PUSHL_DISP		0x35
#define	M_PUSHL_REG_DISP	0xb3
#define	M_JMP_DISP_IND		0x25
#define	M_JMP_REG_DISP_IND	0xa3
#define	M_NOP			0x90

#define	M_BIND_ADJ	1		/* adjustment for end of */
					/*	elf_rtbndr() address */
#ifdef _ELF64
/*
 * Provide default starting addresses.  64-bit programs can also be restricted
 * to a 32-bit address space (SF1_SUNW_ADDR32), and these programs provide an
 * alternative origin.
 */
#define	M_SEGM_ORIGIN	(Addr)0x400000ULL	/* default 1st segment origin */
#define	M_SEGM_AORIGIN	(Addr)0x10000ULL	/* alternative 1st segment */
						/*    origin */
#else
#define	M_STACK_GAP	(0x08000000)
#define	M_STACK_PGS	(0x00048000)
#define	M_SEGM_ORIGIN	(Addr)(M_STACK_GAP + M_STACK_PGS)
#define	M_SEGM_AORIGIN	M_SEGM_ORIGIN
#endif

/*
 * Make common relocation information transparent to the common code
 */
#if	defined(_ELF64)
#define	M_REL_DT_TYPE	DT_RELA		/* .dynamic entry */
#define	M_REL_DT_SIZE	DT_RELASZ	/* .dynamic entry */
#define	M_REL_DT_ENT	DT_RELAENT	/* .dynamic entry */
#define	M_REL_DT_COUNT	DT_RELACOUNT	/* .dynamic entry */
#define	M_REL_SHT_TYPE	SHT_RELA	/* section header type */
#define	M_REL_ELF_TYPE	ELF_T_RELA	/* data buffer type */

#else /* _ELF32 */
#define	M_REL_DT_TYPE	DT_REL		/* .dynamic entry */
#define	M_REL_DT_SIZE	DT_RELSZ	/* .dynamic entry */
#define	M_REL_DT_ENT	DT_RELENT	/* .dynamic entry */
#define	M_REL_DT_COUNT	DT_RELCOUNT	/* .dynamic entry */
#define	M_REL_SHT_TYPE	SHT_REL		/* section header type */
#define	M_REL_ELF_TYPE	ELF_T_REL	/* data buffer type */

#endif /* ELF32 */

/*
 * Make common relocation types transparent to the common code
 */
#if	defined(_ELF64)
#define	M_R_NONE	R_AMD64_NONE
#define	M_R_GLOB_DAT	R_AMD64_GLOB_DAT
#define	M_R_COPY	R_AMD64_COPY
#define	M_R_RELATIVE	R_AMD64_RELATIVE
#define	M_R_JMP_SLOT	R_AMD64_JUMP_SLOT
#define	M_R_FPTR	R_AMD64_NONE
#define	M_R_ARRAYADDR	R_AMD64_GLOB_DAT
#define	M_R_NUM		R_AMD64_NUM
#else
#define	M_R_NONE	R_386_NONE
#define	M_R_GLOB_DAT	R_386_GLOB_DAT
#define	M_R_COPY	R_386_COPY
#define	M_R_RELATIVE	R_386_RELATIVE
#define	M_R_JMP_SLOT	R_386_JMP_SLOT
#define	M_R_FPTR	R_386_NONE
#define	M_R_ARRAYADDR	R_386_GLOB_DAT
#define	M_R_NUM		R_386_NUM
#endif

/*
 * The following are defined as M_R_NONE so that checks
 * for these relocations can be performed in common code - although
 * the checks are really only relevant to SPARC.
 */
#define	M_R_REGISTER	M_R_NONE

/*
 * DT_REGISTER is not valid on i386 or amd64
 */
#define	M_DT_REGISTER	0xffffffff

/*
 * Make plt section information transparent to the common code.
 */
#define	M_PLT_SHF_FLAGS	(SHF_ALLOC | SHF_EXECINSTR)

/*
 * Make default data segment and stack flags transparent to the common code.
 */
#ifdef _ELF64
#define	M_DATASEG_PERM	(PF_R | PF_W)
#define	M_STACK_PERM	(PF_R | PF_W)
#else
#define	M_DATASEG_PERM	(PF_R | PF_W | PF_X)
#define	M_STACK_PERM	(PF_R | PF_W | PF_X)
#endif

/*
 * Define a set of identifies for special sections.  These allow the sections
 * to be ordered within the output file image.  These values should be
 * maintained consistently, where appropriate, in each platform specific header
 * file.
 *
 *  -	null identifies that this section does not need to be added to the
 *	output image (ie. shared object sections or sections we're going to
 *	recreate (sym tables, string tables, relocations, etc.)).
 *
 *  -	any user defined section will be first in the associated segment.
 *
 *  -	interp and capabilities sections are next, as these are accessed
 *	immediately the first page of the image is mapped.
 *
 *  -	objects that do not provide an interp normally have a read-only
 *	.dynamic section that comes next (in this case, there is no need to
 *	update a DT_DEBUG entry at runtime).
 *
 *  -	the syminfo, hash, dynsym, dynstr and rel's are grouped together as
 *	these will all be accessed together by ld.so.1 to perform relocations.
 *
 *  -	the got and dynamic are grouped together as these may also be
 *	accessed first by ld.so.1 to perform relocations, fill in DT_DEBUG
 *	(executables only), and .got[0].
 *
 *  -	unknown sections (stabs, comments, etc.) go at the end.
 *
 * Note that .tlsbss/.bss are given the largest identifiers.  This insures that
 * if any unknown sections become associated to the same segment as the .bss,
 * the .bss sections are always the last section in the segment.
 */
#define	M_ID_NULL	0x00
#define	M_ID_USER	0x01

#define	M_ID_INTERP	0x02			/* SHF_ALLOC */
#define	M_ID_CAP	0x03
#define	M_ID_CAPINFO	0x04
#define	M_ID_CAPCHAIN	0x05

#define	M_ID_DYNAMIC	0x06			/* if no .interp, then no */
						/*    DT_DEBUG is required */
#define	M_ID_UNWINDHDR	0x07
#define	M_ID_UNWIND	0x08

#define	M_ID_SYMINFO	0x09
#define	M_ID_HASH	0x0a
#define	M_ID_LDYNSYM	0x0b			/* always right before DYNSYM */
#define	M_ID_DYNSYM	0x0c
#define	M_ID_DYNSTR	0x0d
#define	M_ID_VERSION	0x0e
#define	M_ID_DYNSORT	0x0f
#define	M_ID_REL	0x10
#define	M_ID_PLT	0x11			/* SHF_ALLOC + SHF_EXECINSTR */
#define	M_ID_ARRAY	0x12
#define	M_ID_TEXT	0x13
#define	M_ID_DATA	0x20

/*	M_ID_USER	0x01			dual entry - listed above */
#define	M_ID_GOT	0x03			/* SHF_ALLOC + SHF_WRITE */
/*	M_ID_DYNAMIC	0x06			dual entry - listed above */
/*	M_ID_UNWIND	0x08			dual entry - listed above */

#define	M_ID_UNKNOWN	0xfb			/* just before TLS */

#define	M_ID_TLS	0xfc			/* just before bss */
#define	M_ID_TLSBSS	0xfd
#define	M_ID_BSS	0xfe
#define	M_ID_LBSS	0xff

#define	M_ID_SYMTAB_NDX	0x02			/* ! SHF_ALLOC */
#define	M_ID_SYMTAB	0x03
#define	M_ID_STRTAB	0x04
#define	M_ID_DYNSYM_NDX	0x05
#define	M_ID_NOTE	0x06


#ifdef	__cplusplus
}
#endif

#endif /* _MACHDEP_X86_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 *	Copyright (c) 1988 AT&T
 *	  All Rights Reserved
 *
 * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
 * Copyright 2024 Oxide Computer Company
 */

#ifndef	_LIBLD_H
#define	_LIBLD_H

#include <stdlib.h>
#include <libelf.h>
#include <sgs.h>
#include <_machelf.h>
#include <string_table.h>
#include <sys/avl.h>
#include <alist.h>
#include <elfcap.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Default directory search path manipulation for the link-editor.  YLDIR
 * indicates which directory in LIBPATH is replaced by the -YL option to cc
 * and ld.  YUDIR indicates which directory is replaced by -YU.
 */
#define	YLDIR	1
#define	YUDIR	2

/*
 * Define a hash value that can never be returned from elf_hash().
 */
#define	SYM_NOHASH	(~(Word)0)

/*
 * Macro that can be used to represent both ORDER flags
 * in a section header.
 */
#define	ALL_SHF_ORDER	(SHF_ORDERED | SHF_LINK_ORDER)

/*
 * The linker merges (concatenates) sections with the same name and
 * compatible section header flags. When comparing these flags,
 * there are some that should not be included in the decision.
 * The ALL_SHF_IGNORE constant defines these flags.
 *
 * NOTE: SHF_MERGE|SHF_STRINGS:
 * The compiler is allowed to set the SHF_MERGE|SHF_STRINGS flags in
 * order to tell the linker that:
 *
 *      1) There is nothing in the section except null terminated strings.
 *	2) Those strings do not contain NULL bytes, except as termination.
 *	3) All references to these strings occur via standard relocation
 *		records.
 *
 * As a result, if two compatible sections both have these flags set, it is
 * OK to combine the strings they contain into a single merged string table
 * with duplicates removed and tail strings merged.
 *
 * This is a different meaning than the simple concatenating of sections
 * that the linker always does. It is a hint that an additional optimization
 * is possible, but not required. This means that sections that do not
 * share the same SHF_MERGE|SHF_STRINGS values can be concatenated,
 * but cannot have their duplicate strings combined. Hence, the
 * SHF_MERGE|SHF_STRINGS flags should be ignored when deciding whether
 * two sections can be concatenated.
 */
#define	ALL_SHF_IGNORE	(ALL_SHF_ORDER | SHF_GROUP | SHF_MERGE | SHF_STRINGS)

/*
 * Define symbol reference types for use in symbol resolution.
 */
typedef enum {
	REF_DYN_SEEN,			/* a .so symbol has been seen */
	REF_DYN_NEED,			/* a .so symbol satisfies a .o symbol */
	REF_REL_NEED,			/* a .o symbol */
	REF_NUM				/* the number of symbol references */
} Symref;

/*
 * Relocation descriptor cache
 */
struct rel_cache {
	APlist		*rc_list;	/* list of Rel_cachebuf */
	Word		rc_cnt;		/*	and count */
};

/*
 * GOT reference models
 */
typedef enum {
	GOT_REF_GENERIC,	/* generic symbol reference */
	GOT_REF_TLSIE,		/* TLS initial exec (gnu) reference */
	GOT_REF_TLSLD,		/* TLS local dynamic reference */
	GOT_REF_TLSGD		/* TLS general dynamic reference */
} Gotref;

typedef struct {
	Xword		gn_addend;	/* addend associated with GOT entry */
	Sword		gn_gotndx;	/* GOT table index */
	Gotref		gn_gotref;
} Gotndx;

/*
 * Got debugging structure.  The got index is defined as a signed value as we
 * do so much mucking around with negative and positive gots on SPARC, and sign
 * extension is necessary when building 64-bit objects.  On intel we explicitly
 * cast this variable to an unsigned value.
 */
typedef struct {
	Sym_desc	*gt_sym;
	Gotndx		gt_gndx;
} Gottable;

/*
 * The link-editor caches the results of sloppy relocation processing
 * in a variable of type Rlxrel_cache. Symbols come for processing in sorted
 * order, so a single item cache suffices to eliminate duplicate lookups.
 *
 * When sloppy relocation processing fails, the Rlxrel_rej enum reports
 * the underlying reason.
 */
typedef enum {
	RLXREL_REJ_NONE = 0,	/* Replacement symbol was found */
	RLXREL_REJ_TARGET,	/* Target sec disallows relaxed relocations */
	RLXREL_REJ_SECTION,	/* Either there is no replacement section, */
				/*	or its attributes are incompatible */
	RLXREL_REJ_SYMBOL,	/* Replacement symbol not found */
} Rlxrel_rej;

typedef struct sreloc_cache {
	Sym_desc	*sr_osdp;	/* Original symbol */
	Sym_desc	*sr_rsdp;	/* Replacement symbol */
	Rlxrel_rej	sr_rej;		/* Reason for failure if NULL sr_rsdp */
} Rlxrel_cache;

/*
 * Nodes in an ofl_wrap AVL tree
 *
 * wsn_name is the name of the symbol to be wrapped. wsn_wrapname is used
 * when we need to refer to the wrap symbol, and consists of the symbol
 * name with a __wrap_ prefix.
 */
typedef struct wrap_sym_node {
	avl_node_t	wsn_avlnode;	/* AVL book-keeping */
	const char	*wsn_name;	/* Symbol name: XXX */
	const char	*wsn_wrapname;	/* Wrap symbol name: __wrap_XXX */
} WrapSymNode;

/*
 * Capabilities structures, used to maintain a capabilities set.
 *
 * Capabilities can be defined within input relocatable objects, and can be
 * augmented or replaced by mapfile directives.  In addition, mapfile directives
 * can be used to exclude capabilities that would otherwise be carried over to
 * the output object.
 *
 * CA_SUNW_HW_1, CA_SUNW_SF_1 and CA_SUNW_HW_2 values are bitmasks.  A current
 * value, and an exclude value are maintained for each capability.
 *
 * There can be multiple CA_SUNW_PLAT and CA_SUNW_MACH entries and thus Alists
 * are used to collect these entries.  A current list for each capability is
 * maintained as Capstr entries, which provide for maintaining the strings
 * eventual index into a string table.  An exclude list is maintained as a
 * list of string pointers.
 */
typedef struct {
	elfcap_mask_t	cm_val;		/* bitmask value */
	elfcap_mask_t	cm_exc;		/* bits to exclude from final object */
} Capmask;

typedef struct {
	Alist		*cl_val;	/* string (Capstr) value */
	APlist		*cl_exc;	/* strings to exclude from final */
} Caplist;				/*	object */

typedef	struct {
	char		*cs_str;	/* platform or machine name */
	Word		cs_ndx;		/* the entries output Cap index */
} Capstr;

typedef	uint_t		oc_flag_t;
typedef	struct {
	Capmask		oc_hw_1;	/* CA_SUNW_HW_1 capabilities */
	Capmask		oc_sf_1;	/* CA_SUNW_SF_1 capabilities */
	Capmask		oc_hw_2;	/* CA_SUNW_HW_2 capabilities */
	Caplist		oc_plat;	/* CA_SUNW_PLAT capabilities */
	Caplist		oc_mach;	/* CA_SUNW_MACH capabilities */
	Capstr		oc_id;		/* CA_SUNW_ID capability */
	Capmask		oc_hw_3;	/* CA_SUNW_HW_3 capabilities */
	oc_flag_t	oc_flags;
} Objcapset;

#define	FLG_OCS_USRDEFID	0x1	/* user defined CA_SUNW_ID */

/*
 * Bitmasks for a single capability. Capabilities come from input objects,
 * augmented or replaced by mapfile directives. In addition, mapfile directives
 * can be used to exclude bits that would otherwise be set in the output object.
 */
typedef struct {
	elfcap_mask_t	cm_value;	/* Bitmask value */
	elfcap_mask_t	cm_exclude;	/* Bits to remove from final object */
} CapMask;

/*
 * Combine the bitmask in a CapMask with the exclusion mask and
 * return the resulting final value.
 */
#define	CAPMASK_VALUE(_cbmp) ((_cbmp)->cm_value & ~(_cbmp)->cm_exclude)

typedef struct {
	CapMask		c_hw_1;		/* CA_SUNW_HW_1 capabilities */
	CapMask		c_sf_1;		/* CA_SUNW_SF_1 capabilities */
	CapMask		c_hw_2;		/* CA_SUNW_HW_2 capabilities */
} Outcapset;


/*
 * Output file processing structure
 */
typedef Lword	ofl_flag_t;
typedef Word	ofl_guideflag_t;
struct ofl_desc {
	char		*ofl_sgsid;	/* link-editor identification */
	const char	*ofl_name;	/* full file name */
	Elf		*ofl_elf;	/* elf_memory() elf descriptor */
	Elf		*ofl_welf;	/* ELF_C_WRITE elf descriptor */
	Ehdr		*ofl_dehdr;	/* default elf header, and new elf */
	Ehdr		*ofl_nehdr;	/*	header describing this file */
	Phdr		*ofl_phdr;	/* program header descriptor */
	Phdr		*ofl_tlsphdr;	/* TLS phdr */
	int		ofl_fd;		/* file descriptor */
	size_t		ofl_size;	/* image size */
	APlist		*ofl_maps;	/* list of input mapfiles */
	APlist		*ofl_segs;	/* list of segments */
	APlist		*ofl_segs_order; /* SEGMENT_ORDER segments */
	avl_tree_t	ofl_segs_avl;	/* O(log N) access to named segments */
	APlist		*ofl_ents;	/* list of entrance descriptors */
	avl_tree_t	ofl_ents_avl;	/* O(log N) access to named ent. desc */
	APlist		*ofl_objs;	/* relocatable object file list */
	Word		ofl_objscnt;	/*	and count */
	APlist		*ofl_ars;	/* archive library list */
	Word		ofl_arscnt;	/*	and count */
	int		ofl_ars_gsandx; /* archive group argv index. 0 means */
					/*	no current group, < 0 means */
					/*	error reported. >0 is cur ndx */
	Word		ofl_ars_gsndx;	/* current -zrescan-start ofl_ars ndx */
	APlist		*ofl_sos;	/* shared object list */
	Word		ofl_soscnt;	/*	and count */
	APlist		*ofl_soneed;	/* list of implicitly required .so's */
	APlist		*ofl_socntl;	/* list of .so control definitions */
	Rel_cache	ofl_outrels;	/* list of output relocations */
	Rel_cache	ofl_actrels;	/* list of relocations to perform */
	APlist		*ofl_relaux;	/* Rel_aux cache for outrels/actrels */
	Word		ofl_entrelscnt;	/* no of relocations entered */
	Alist		*ofl_copyrels;	/* list of copy relocations */
	APlist		*ofl_ordered;	/* list of shf_ordered sections */
	APlist		*ofl_symdtent;	/* list of syminfo symbols that need */
					/*	to reference .dynamic entries */
	APlist		*ofl_ismove;	/* list of .SUNW_move sections */
	APlist		*ofl_ismoverel;	/* list of relocation input section */
					/* targeting to expanded area */
	APlist		*ofl_parsyms;	/* list of partially initialized */
					/*	symbols (ie. move symbols) */
	APlist		*ofl_extrarels;	/* relocation sections which have */
					/*    a NULL sh_info */
	avl_tree_t	*ofl_groups;	/* pointer to head of Groups AVL tree */
	APlist		*ofl_initarray;	/* list of init array func names */
	APlist		*ofl_finiarray;	/* list of fini array func names */
	APlist		*ofl_preiarray;	/* list of preinit array func names */
	APlist		*ofl_rtldinfo;	/* list of rtldinfo syms */
	APlist		*ofl_osgroups;	/* list of output GROUP sections */
	APlist		*ofl_ostlsseg;	/* pointer to sections in TLS segment */
	APlist		*ofl_unwind;	/* list of unwind output sections */
	Os_desc		*ofl_unwindhdr;	/* Unwind hdr */
	avl_tree_t	ofl_symavl;	/* pointer to head of Syms AVL tree */
	Sym_desc	**ofl_regsyms;	/* array of potential register */
	Word		ofl_regsymsno;	/*    symbols and array count */
	Word		ofl_regsymcnt;	/* no. of output register symbols */
	Word		ofl_lregsymcnt;	/* no. of local register symbols */
	Sym_desc	*ofl_dtracesym;	/* ld -zdtrace= */
	ofl_flag_t	ofl_flags;	/* various state bits, args etc. */
	ofl_flag_t	ofl_flags1;	/*	more flags */
	void		*ofl_entry;	/* entry point (-e and Sym_desc *) */
	char		*ofl_filtees;	/* shared objects we are a filter for */
	const char	*ofl_soname;	/* (-h option) output file name for */
					/*	dynamic structure */
	const char	*ofl_interp;	/* interpreter name used by exec() */
	char		*ofl_rpath;	/* run path to store in .dynamic */
	char		*ofl_config;	/* config path to store in .dynamic */
	APlist		*ofl_ulibdirs;	/* user supplied library search list */
	APlist		*ofl_dlibdirs;	/* default library search list */
	Word		ofl_vercnt;	/* number of versions to generate */
	APlist		*ofl_verdesc;	/* list of version descriptors */
	size_t		ofl_verdefsz;	/* size of version definition section */
	size_t		ofl_verneedsz;	/* size of version needed section */
	Word		ofl_entercnt;	/* no. of global symbols entered */
	Word		ofl_globcnt;	/* no. of global symbols to output */
	Word		ofl_scopecnt;	/* no. of scoped symbols to output */
	Word		ofl_dynscopecnt; /* no. scoped syms in .SUNW_ldynsym */
	Word		ofl_elimcnt;	/* no. of eliminated symbols */
	Word		ofl_locscnt;	/* no. of local symbols in .symtab */
	Word		ofl_dynlocscnt;	/* no. local symbols in .SUNW_ldynsym */
	Word		ofl_dynsymsortcnt; /* no. ndx in .SUNW_dynsymsort */
	Word		ofl_dyntlssortcnt; /* no. ndx in .SUNW_dyntlssort */
	Word		ofl_dynshdrcnt;	/* no. of output section in .dynsym */
	Word		ofl_shdrcnt;	/* no. of output sections */
	Word		ofl_caploclcnt;	/* no. of local capabilities symbols */
	Word		ofl_capsymcnt;	/* no. of symbol capabilities entries */
					/*	required */
	Word		ofl_capchaincnt; /* no. of Capchain symbols */
	APlist		*ofl_capgroups;	/* list of capabilities groups */
	avl_tree_t	*ofl_capfamilies; /* capability family AVL tree */
	Str_tbl		*ofl_shdrsttab;	/* Str_tbl for shdr strtab */
	Str_tbl		*ofl_strtab;	/* Str_tbl for symtab strtab */
	Str_tbl		*ofl_dynstrtab;	/* Str_tbl for dymsym strtab */
	Gotndx		*ofl_tlsldgotndx; /* index to LD TLS_index structure */
	Xword		ofl_relocsz;	/* size of output relocations */
	Xword		ofl_relocgotsz;	/* size of .got relocations */
	Xword		ofl_relocpltsz;	/* size of .plt relocations */
	Xword		ofl_relocbsssz;	/* size of .bss (copy) relocations */
	Xword		ofl_relocrelsz;	/* size of .rel[a] relocations */
	Word		ofl_relocincnt;	/* no. of input relocations */
	Word		ofl_reloccnt;	/* tot number of output relocations */
	Word		ofl_reloccntsub; /* tot numb of output relocations to */
					/*	skip (-zignore) */
	Word		ofl_relocrelcnt; /* tot number of relative */
					/*	relocations */
	Word		ofl_gotcnt;	/* no. of .got entries */
	Word		ofl_pltcnt;	/* no. of .plt entries */
	Word		ofl_pltpad;	/* no. of .plt padd entries */
	Word		ofl_hashbkts;	/* no. of hash buckets required */
	Is_desc		*ofl_isbss;	/* .bss input section (globals) */
	Is_desc		*ofl_islbss;	/* .lbss input section (globals) */
	Is_desc		*ofl_istlsbss;	/* .tlsbss input section (globals) */
	Is_desc		*ofl_isparexpn;	/* -z nopartial .data input section */
	Os_desc		*ofl_osdynamic;	/* .dynamic output section */
	Os_desc		*ofl_osdynsym;	/* .dynsym output section */
	Os_desc		*ofl_osldynsym;	/* .SUNW_ldynsym output section */
	Os_desc		*ofl_osdynstr;	/* .dynstr output section */
	Os_desc		*ofl_osdynsymsort; /* .SUNW_dynsymsort output section */
	Os_desc		*ofl_osdyntlssort; /* .SUNW_dyntlssort output section */
	Os_desc		*ofl_osgot;	/* .got output section */
	Os_desc		*ofl_oshash;	/* .hash output section */
	Os_desc		*ofl_osinitarray; /* .init_array output section */
	Os_desc		*ofl_osfiniarray; /* .fini_array output section */
	Os_desc		*ofl_ospreinitarray; /* .preinit_array output section */
	Os_desc		*ofl_osinterp;	/* .interp output section */
	Os_desc		*ofl_oscap;	/* .SUNW_cap output section */
	Os_desc		*ofl_oscapinfo;	/* .SUNW_capinfo output section */
	Os_desc		*ofl_oscapchain; /* .SUNW_capchain output section */
	Os_desc		*ofl_osplt;	/* .plt output section */
	Os_desc		*ofl_osmove;	/* .SUNW_move output section */
	Os_desc		*ofl_osrelhead;	/* first relocation section */
	Os_desc		*ofl_osrel;	/* .rel[a] relocation section */
	Os_desc		*ofl_osshstrtab; /* .shstrtab output section */
	Os_desc		*ofl_osstrtab;	/* .strtab output section */
	Os_desc		*ofl_ossymtab;	/* .symtab output section */
	Os_desc		*ofl_ossymshndx; /* .symtab_shndx output section */
	Os_desc		*ofl_osdynshndx; /* .dynsym_shndx output section */
	Os_desc		*ofl_osldynshndx; /* .SUNW_ldynsym_shndx output sec */
	Os_desc		*ofl_osverdef;	/* .version definition output section */
	Os_desc		*ofl_osverneed;	/* .version needed output section */
	Os_desc		*ofl_osversym;	/* .version symbol ndx output section */
	Word		ofl_dtflags_1;	/* DT_FLAGS_1 entries */
	Word		ofl_dtflags;	/* DT_FLAGS entries */
	Os_desc		*ofl_ossyminfo;	/* .SUNW_syminfo output section */
	Half		ofl_parexpnndx;	/* -z nopartial section index */
					/* Ref. at perform_outreloc() in */
					/* libld/{mach}/machrel.c */
	Xword		*ofl_checksum;	/* DT_CHECKSUM value address */
	char		*ofl_depaudit;	/* dependency auditing required (-P) */
	char		*ofl_audit;	/* object auditing required (-p) */
	Alist		*ofl_symfltrs;	/* per-symbol filtees and their */
	Alist		*ofl_dtsfltrs;	/*	associated .dynamic/.dynstrs */
	Objcapset	ofl_ocapset;	/* object capabilities */
	Lm_list		*ofl_lml;	/* runtime link-map list */
	Gottable	*ofl_gottable;	/* debugging got information */
	Rlxrel_cache	ofl_sr_cache;	/* Cache last result from */
					/*	sloppy_comdat_reloc() */
	APlist		*ofl_maptext;	/* mapfile added text sections */
	APlist		*ofl_mapdata;	/* mapfile added data sections */
	avl_tree_t	*ofl_wrap;	/* -z wrap symbols */
	ofl_guideflag_t	ofl_guideflags;	/* -z guide flags */
	APlist		*ofl_assdeflib;	/* -z assert-deflib exceptions */
	int		ofl_aslr;	/* -z aslr, -1 disable, 1 enable */
	APlist		*ofl_symasserts; /* assertions about symbols */
					/* from mapfiles */
};

#define	FLG_OF_DYNAMIC	0x00000001	/* generate dynamic output module */
#define	FLG_OF_STATIC	0x00000002	/* generate static output module */
#define	FLG_OF_EXEC	0x00000004	/* generate an executable */
#define	FLG_OF_RELOBJ	0x00000008	/* generate a relocatable object */
#define	FLG_OF_SHAROBJ	0x00000010	/* generate a shared object */
#define	FLG_OF_BFLAG	0x00000020	/* do no special plt building: -b */
#define	FLG_OF_IGNENV	0x00000040	/* ignore LD_LIBRARY_PATH: -i */
#define	FLG_OF_STRIP	0x00000080	/* strip output: -s */
#define	FLG_OF_NOWARN	0x00000100	/* disable symbol warnings: -t */
#define	FLG_OF_NOUNDEF	0x00000200	/* allow no undefined symbols: -zdefs */
#define	FLG_OF_PURETXT	0x00000400	/* allow no text relocations: -ztext */
#define	FLG_OF_GENMAP	0x00000800	/* generate a memory map: -m */
#define	FLG_OF_DYNLIBS	0x00001000	/* dynamic input allowed: -Bdynamic */
#define	FLG_OF_SYMBOLIC	0x00002000	/* bind global symbols: -Bsymbolic */
#define	FLG_OF_ADDVERS	0x00004000	/* add version stamp: -Qy */
#define	FLG_OF_NOLDYNSYM 0x00008000	/* -znoldynsym set */
#define	FLG_OF_IS_ORDER	0x00010000	/* input section ordering within a */
					/*	segment is required */
#define	FLG_OF_EC_FILES	0x00020000	/* Ent_desc exist w/non-NULL ec_files */
#define	FLG_OF_TEXTREL	0x00040000	/* text relocations have been found */
#define	FLG_OF_MULDEFS	0x00080000	/* multiple symbols are allowed */
#define	FLG_OF_TLSPHDR	0x00100000	/* a TLS program header is required */
#define	FLG_OF_BLDGOT	0x00200000	/* build GOT table */
#define	FLG_OF_VERDEF	0x00400000	/* record version definitions */
#define	FLG_OF_VERNEED	0x00800000	/* record version dependencies */
#define	FLG_OF_NOVERSEC 0x01000000	/* don't record version sections */
#define	FLG_OF_KEY	0x02000000	/* file requires sort keys */
#define	FLG_OF_PROCRED	0x04000000	/* process any symbol reductions by */
					/*	effecting the symbol table */
					/*	output and relocations */
#define	FLG_OF_SYMINFO	0x08000000	/* create a syminfo section */
#define	FLG_OF_AUX	0x10000000	/* ofl_filter is an auxiliary filter */
#define	FLG_OF_FATAL	0x20000000	/* fatal error during input */
#define	FLG_OF_WARN	0x40000000	/* warning during input processing. */
#define	FLG_OF_VERBOSE	0x80000000	/* -z verbose flag set */

#define	FLG_OF_MAPSYMB	0x000100000000	/* symbolic scope definition seen */
#define	FLG_OF_MAPGLOB	0x000200000000	/* global scope definition seen */
#define	FLG_OF_COMREL	0x000400000000	/* -z combreloc set, which enables */
					/*	DT_RELACNT tracking, */
#define	FLG_OF_NOCOMREL	0x000800000000	/* -z nocombreloc set */
#define	FLG_OF_AUTOLCL	0x001000000000	/* automatically reduce unspecified */
					/*	global symbols to locals */
#define	FLG_OF_AUTOELM	0x002000000000	/* automatically eliminate */
					/*	unspecified global symbols */
#define	FLG_OF_REDLSYM	0x004000000000	/* reduce local symbols */
#define	FLG_OF_OS_ORDER	0x008000000000	/* output section ordering required */
#define	FLG_OF_OSABI	0x010000000000	/* tag object as ELFOSABI_SOLARIS */
#define	FLG_OF_ADJOSCNT	0x020000000000	/* adjust ofl_shdrcnt to accommodate */
					/*	discarded sections */
#define	FLG_OF_OTOSCAP	0x040000000000	/* convert object capabilities to */
					/*	symbol capabilities */
#define	FLG_OF_PTCAP	0x080000000000	/* PT_SUNWCAP required */
#define	FLG_OF_CAPSTRS	0x100000000000	/* capability strings are required */
#define	FLG_OF_EHFRAME	0x200000000000	/* output contains .eh_frame section */
#define	FLG_OF_FATWARN	0x400000000000	/* make warnings fatal */
#define	FLG_OF_ADEFLIB	0x800000000000	/* no libraries in default path */

#define	FLG_OF_KMOD	0x1000000000000	/* output is a kernel module */

/*
 * In the flags1 arena, establish any options that are applicable to archive
 * extraction first, and associate a mask.  These values are recorded with any
 * archive descriptor so that they may be reset should the archive require a
 * rescan to try and resolve undefined symbols.
 */
#define	FLG_OF1_ALLEXRT	0x0000000001	/* extract all members from an */
					/*	archive file */
#define	FLG_OF1_WEAKEXT	0x0000000002	/* allow archive extraction to */
					/*	resolve weak references */
#define	MSK_OF1_ARCHIVE	0x0000000003	/* archive flags mask */

#define	FLG_OF1_NOINTRP	0x0000000008	/* -z nointerp flag set */
#define	FLG_OF1_ZDIRECT	0x0000000010	/* -z direct flag set */
#define	FLG_OF1_NDIRECT	0x0000000020	/* no-direct bindings specified */
#define	FLG_OF1_DEFERRED 0x0000000040	/* deferred dependency recording */

#define	FLG_OF1_RELDYN	0x0000000100	/* process .dynamic in rel obj */
#define	FLG_OF1_NRLXREL	0x0000000200	/* -z norelaxreloc flag set */
#define	FLG_OF1_RLXREL	0x0000000400	/* -z relaxreloc flag set */
#define	FLG_OF1_IGNORE	0x0000000800	/* ignore unused dependencies */
#define	FLG_OF1_NOSGHND	0x0000001000	/* -z nosighandler flag set */
#define	FLG_OF1_TEXTOFF 0x0000002000	/* text relocations are ok */
#define	FLG_OF1_ABSEXEC	0x0000004000	/* -zabsexec set */
#define	FLG_OF1_LAZYLD	0x0000008000	/* lazy loading of objects enabled */
#define	FLG_OF1_GRPPRM	0x0000010000	/* dependencies are to have */
					/*	GROUPPERM enabled */

#define	FLG_OF1_NOPARTI	0x0000040000	/* -znopartial set */
#define	FLG_OF1_BSSOREL	0x0000080000	/* output relocation against bss */
					/*	section */
#define	FLG_OF1_TLSOREL	0x0000100000	/* output relocation against .tlsbss */
					/*	section */
#define	FLG_OF1_MEMORY	0x0000200000	/* produce a memory model */
#define	FLG_OF1_NGLBDIR	0x0000400000	/* no DT_1_DIRECT flag allowed */
#define	FLG_OF1_ENCDIFF	0x0000800000	/* host running linker has different */
					/*	byte order than output object */
#define	FLG_OF1_VADDR	0x0001000000	/* a segment defines explicit vaddr */
#define	FLG_OF1_EXTRACT	0x0002000000	/* archive member has been extracted */
#define	FLG_OF1_RESCAN	0x0004000000	/* any archives should be rescanned */
#define	FLG_OF1_IGNPRC	0x0008000000	/* ignore processing required */
#define	FLG_OF1_NCSTTAB	0x0010000000	/* -znocompstrtab set */
#define	FLG_OF1_DONE	0x0020000000	/* link-editor processing complete */
#define	FLG_OF1_NONREG	0x0040000000	/* non-regular file specified as */
					/*	the output file */
#define	FLG_OF1_ALNODIR	0x0080000000	/* establish NODIRECT for all */
					/*	exported interfaces. */
#define	FLG_OF1_OVHWCAP1 0x0100000000	/* override CA_SUNW_HW_1 capabilities */
#define	FLG_OF1_OVSFCAP1 0x0200000000	/* override CA_SUNW_SF_1 capabilities */
#define	FLG_OF1_OVHWCAP2 0x0400000000	/* override CA_SUNW_HW_2 capabilities */
#define	FLG_OF1_OVMACHCAP 0x0800000000	/* override CA_SUNW_MACH capability */
#define	FLG_OF1_OVPLATCAP 0x1000000000	/* override CA_SUNW_PLAT capability */
#define	FLG_OF1_OVIDCAP	0x2000000000	/* override CA_SUNW_ID capability */
#define	FLG_OF1_OVHWCAP3 0x4000000000	/* override CA_SUNW_HW_3 capabilities */

/*
 * Guidance flags. The flags with the FLG_OFG_NO_ prefix are used to suppress
 * messages for a given category, and use the lower 28 bits of the word,
 * The upper nibble is reserved for other guidance status.
 */
#define	FLG_OFG_ENABLE		0x10000000	/* -z guidance option active */
#define	FLG_OFG_ISSUED		0x20000000	/* -z guidance message issued */

#define	FLG_OFG_NO_ALL		0x0fffffff	/* disable all guidance */
#define	FLG_OFG_NO_DEFS		0x00000001	/* specify all dependencies */
#define	FLG_OFG_NO_DB		0x00000002	/* use direct bindings */
#define	FLG_OFG_NO_LAZY		0x00000004	/* be explicit about lazyload */
#define	FLG_OFG_NO_MF		0x00000008	/* use v2 mapfile syntax */
#define	FLG_OFG_NO_TEXT		0x00000010	/* verify pure text segment */
#define	FLG_OFG_NO_UNUSED	0x00000020	/* remove unused dependency */
#define	FLG_OFG_NO_ASSERTS	0x00000040	/* suggest mapfile assertions */

/*
 * Test to see if a guidance should be given for a given category
 * or not. _no_flag is one of the FLG_OFG_NO_xxx flags. Returns TRUE
 * if the guidance should be issued, and FALSE to remain silent.
 */
#define	OFL_GUIDANCE(_ofl, _no_flag) (((_ofl)->ofl_guideflags & \
	(FLG_OFG_ENABLE | (_no_flag))) == FLG_OFG_ENABLE)

/*
 * Test to see if the output file would allow the presence of
 * a .dynsym section.
 */
#define	OFL_ALLOW_DYNSYM(_ofl) (((_ofl)->ofl_flags & \
	(FLG_OF_DYNAMIC | FLG_OF_RELOBJ)) == FLG_OF_DYNAMIC)

/*
 * Test to see if the output file would allow the presence of
 * a .SUNW_ldynsym section. The requirements are that a .dynsym
 * is allowed, and -znoldynsym has not been specified. Note that
 * even if the answer is True (1), we will only generate one if there
 * are local symbols that require it.
 */
#define	OFL_ALLOW_LDYNSYM(_ofl) (((_ofl)->ofl_flags & \
	(FLG_OF_DYNAMIC | FLG_OF_RELOBJ | FLG_OF_NOLDYNSYM)) == FLG_OF_DYNAMIC)

/*
 * Test to see if relocation processing should be done. This is normally
 * true, but can be disabled via the '-z noreloc' option. Note that
 * relocatable objects are still relocated even if '-z noreloc' is present.
 */
#define	OFL_DO_RELOC(_ofl) (((_ofl)->ofl_flags & FLG_OF_RELOBJ) || \
	!((_ofl)->ofl_dtflags_1 & DF_1_NORELOC))

/*
 * Determine whether a static executable is being built.
 */
#define	OFL_IS_STATIC_EXEC(_ofl) (((_ofl)->ofl_flags & \
	(FLG_OF_STATIC | FLG_OF_EXEC)) == (FLG_OF_STATIC | FLG_OF_EXEC))

/*
 * Determine whether a static object is being built.  This macro is used
 * to select the appropriate string table, and symbol table that other
 * sections need to reference.
 */
#define	OFL_IS_STATIC_OBJ(_ofl) ((_ofl)->ofl_flags & \
	(FLG_OF_RELOBJ | FLG_OF_STATIC))

/*
 * Macros for counting symbol table entries.  These are used to size symbol
 * tables and associated sections (.syminfo, SUNW_capinfo, .hash, etc.) and
 * set required sh_info entries (the offset to the first global symbol).
 */
#define	SYMTAB_LOC_CNT(_ofl)		/* local .symtab entries */	\
	(2 +				/*    NULL and STT_FILE */	\
	(_ofl)->ofl_shdrcnt +		/*    section symbol */		\
	(_ofl)->ofl_caploclcnt +	/*    local capabilities */	\
	(_ofl)->ofl_scopecnt +		/*    scoped symbols */		\
	(_ofl)->ofl_locscnt)		/*    standard locals */
#define	SYMTAB_ALL_CNT(_ofl)		/* all .symtab entries */	\
	(SYMTAB_LOC_CNT(_ofl) +		/*    .symtab locals */		\
	(_ofl)->ofl_globcnt)		/*    standard globals */

#define	DYNSYM_LOC_CNT(_ofl)		/* local .dynsym entries */	\
	(1 +				/*    NULL */			\
	(_ofl)->ofl_dynshdrcnt +	/*    section symbols */	\
	(_ofl)->ofl_caploclcnt +	/*    local capabilities */	\
	(_ofl)->ofl_lregsymcnt)		/*    local register symbols */
#define	DYNSYM_ALL_CNT(_ofl)		/* all .dynsym entries */	\
	(DYNSYM_LOC_CNT(_ofl) +		/*    .dynsym locals */		\
	(_ofl)->ofl_globcnt)		/*    standard globals */

/*
 * Define a move descriptor used within relocation structures.
 */
typedef struct {
	Move		*mr_move;
	Sym_desc	*mr_sym;
} Mv_reloc;

/*
 * Relocation (active & output) processing structure - transparent to common
 * code. There can be millions of these structures in a large link, so it
 * is important to keep it small. You should only add new items to Rel_desc
 * if they are critical, apply to most relocations, and cannot be easily
 * computed from the other information.
 *
 * Items that can be derived should be implemented as a function that accepts
 * a Rel_desc argument, and returns the desired data. ld_reloc_sym_name() is
 * an example of this.
 *
 * Lesser used relocation data is kept in an auxiliary block, Rel_aux,
 * that is only allocated as necessary. In exchange for adding one pointer
 * of overhead to Rel_desc (rel_aux), most relocations are reduced in size
 * by the size of Rel_aux. This strategy relies on the data in Rel_aux
 * being rarely needed --- otherwise it will backfire badly.
 *
 * Note that rel_raddend is primarily only of interest to RELA relocations,
 * and is set to 0 for REL. However, there is an exception: If FLG_REL_NADDEND
 * is set, then rel_raddend contains a replacement value for the implicit
 * addend found in the relocation target.
 *
 * Fields should be ordered from largest to smallest, to minimize packing
 * holes in the struct layout.
 */
struct rel_desc {
	Is_desc		*rel_isdesc;	/* input section reloc is against */
	Sym_desc	*rel_sym;	/* sym relocation is against */
	Rel_aux		*rel_aux;	/* NULL, or auxiliary data */
	Xword		rel_roffset;	/* relocation offset */
	Sxword		rel_raddend;	/* addend from input relocation */
	Word		rel_flags;	/* misc. flags for relocations */
	Word		rel_rtype;	/* relocation type */
};

/*
 * Data that would be kept in Rel_desc if the size of that structure was
 * not an issue. This auxiliary block is only allocated as needed,
 * and must only contain rarely needed items. The goal is for the vast
 * majority of Rel_desc structs to not have an auxiliary block.
 *
 * When a Rel_desc does not have an auxiliary block, a default value
 * is assumed for each auxiliary item:
 *
 * -	ra_osdesc:
 *	Output section to which relocation applies. The default
 *	value for this is the output section associated with the
 *	input section (rel_isdesc->is_osdesc), or NULL if there
 *	is no associated input section.
 *
 * -	ra_usym:
 *	If the symbol associated with a relocation is part of a weak/strong
 *	pair, then ra_usym contains the strong symbol and rel_sym the weak.
 *	Otherwise, the default value is the same value as rel_sym.
 *
 * -	ra_move:
 *	Move table data. The default value is NULL.
 *
 * -	ra_typedata:
 *	ELF_R_TYPE_DATA(info). This value applies only to a small
 *	subset of 64-bit sparc relocations, and is otherwise 0. The
 *	default value is 0.
 *
 * If any value in Rel_aux is non-default, then an auxiliary block is
 * necessary, and each field contains its actual value. If all the auxiliary
 * values are default, no Rel_aux is needed, and the RELAUX_GET_xxx()
 * macros below are able to supply the proper default.
 *
 * To set a Rel_aux value, use the ld_reloc_set_aux_XXX() functions.
 * These functions are written to avoid unnecessary auxiliary allocations,
 * and know the rules for each item.
 */
struct rel_aux {
	Os_desc		*ra_osdesc;	/* output section reloc is against */
	Sym_desc	*ra_usym;	/* strong sym if this is a weak pair */
	Mv_reloc	*ra_move;	/* move table information */
	Word		ra_typedata;	/* ELF_R_TYPE_DATA(info) */
};

/*
 * Test a given auxiliary value to determine if it has the default value
 * for that item, as described above. If all the auxiliary items have
 * their default values, no auxiliary place is necessary to represent them.
 * If any one of them is non-default, the auxiliary block is needed.
 */
#define	RELAUX_ISDEFAULT_MOVE(_rdesc, _mv) (_mv == NULL)
#define	RELAUX_ISDEFAULT_USYM(_rdesc, _usym) ((_rdesc)->rel_sym == _usym)
#define	RELAUX_ISDEFAULT_OSDESC(_rdesc, _osdesc) \
	((((_rdesc)->rel_isdesc == NULL) && (_osdesc == NULL)) || \
	((_rdesc)->rel_isdesc && ((_rdesc)->rel_isdesc->is_osdesc == _osdesc)))
#define	RELAUX_ISDEFAULT_TYPEDATA(_rdesc, _typedata) (_typedata == 0)

/*
 * Retrieve the value of an auxiliary relocation item, preserving the illusion
 * that every relocation descriptor has an auxiliary block attached. The
 * real implementation is that an auxiliary block is only present if one or
 * more auxiliary items have non-default values. These macros return the true
 * value if an auxiliary block is present, and the default value for the
 * item otherwise.
 */
#define	RELAUX_GET_MOVE(_rdesc) \
	((_rdesc)->rel_aux ? (_rdesc)->rel_aux->ra_move : NULL)
#define	RELAUX_GET_USYM(_rdesc) \
	((_rdesc)->rel_aux ? (_rdesc)->rel_aux->ra_usym : (_rdesc)->rel_sym)
#define	RELAUX_GET_OSDESC(_rdesc) \
	((_rdesc)->rel_aux ? (_rdesc)->rel_aux->ra_osdesc : \
	((_rdesc)->rel_isdesc ? (_rdesc)->rel_isdesc->is_osdesc : NULL))
#define	RELAUX_GET_TYPEDATA(_rdesc) \
	((_rdesc)->rel_aux ? (_rdesc)->rel_aux->ra_typedata : 0)

/*
 * common flags used on the Rel_desc structure (defined in machrel.h).
 */
#define	FLG_REL_GOT	0x00000001	/* relocation against GOT */
#define	FLG_REL_PLT	0x00000002	/* relocation against PLT */
#define	FLG_REL_BSS	0x00000004	/* relocation against BSS */
#define	FLG_REL_LOAD	0x00000008	/* section loadable */
#define	FLG_REL_SCNNDX	0x00000010	/* use section index for symbol ndx */
#define	FLG_REL_CLVAL	0x00000020	/* clear VALUE for active relocation */
#define	FLG_REL_ADVAL	0x00000040	/* add VALUE for output relocation, */
					/*	only relevant to SPARC and */
					/*	R_SPARC_RELATIVE */
#define	FLG_REL_GOTCL	0x00000080	/* clear the GOT entry.  This is */
					/* relevant to RELA relocations, */
					/* not REL (i386) relocations */
#define	FLG_REL_MOVETAB	0x00000100	/* Relocation against .SUNW_move */
					/*	adjustments required before */
					/*	actual relocation */
#define	FLG_REL_NOINFO	0x00000200	/* Relocation comes from a section */
					/*	with a null sh_info field */
#define	FLG_REL_REG	0x00000400	/* Relocation target is reg sym */
#define	FLG_REL_FPTR	0x00000800	/* relocation against func. desc. */
#define	FLG_REL_RFPTR1	0x00001000	/* Relative relocation against */
					/*   1st part of FD */
#define	FLG_REL_RFPTR2	0x00002000	/* Relative relocation against */
					/*   2nd part of FD */
#define	FLG_REL_DISP	0x00004000	/* *disp* relocation */
#define	FLG_REL_STLS	0x00008000	/* IE TLS reference to */
					/*	static TLS GOT index */
#define	FLG_REL_DTLS	0x00010000	/* GD TLS reference relative to */
					/*	dynamic TLS GOT index */
#define	FLG_REL_MTLS	0x00020000	/* LD TLS reference against GOT */
#define	FLG_REL_STTLS	0x00040000	/* LE TLS reference directly */
					/*	to static tls index */
#define	FLG_REL_TLSFIX	0x00080000	/* relocation points to TLS instr. */
					/*	which needs updating */
#define	FLG_REL_RELA	0x00100000	/* descriptor captures a Rela */
#define	FLG_REL_GOTFIX	0x00200000	/* relocation points to GOTOP instr. */
					/*	which needs updating */
#define	FLG_REL_NADDEND	0x00400000	/* Replace implicit addend in dest */
					/*	with value in rel_raddend */
					/*	Relevant to REL (i386) */
					/*	relocations, not to RELA. */

/*
 * We often need the name of the symbol contained in a relocation descriptor
 * for diagnostic or error output. This is usually the symbol name, but
 * we substitute a constructed name in some cases. Hence, the name is
 * generated on the fly by a private function within libld. This is the
 * prototype for that function.
 */
typedef const char *(* rel_desc_sname_func_t)(Rel_desc *);

/*
 * Header for a relocation descriptor cache buffer.
 */
struct rel_cachebuf {
	Rel_desc	*rc_end;
	Rel_desc	*rc_free;
	Rel_desc	rc_arr[1];
};

/*
 * Header for a relocation auxiliary descriptor cache buffer.
 */
struct rel_aux_cachebuf {
	Rel_aux		*rac_end;
	Rel_aux		*rac_free;
	Rel_aux		rac_arr[1];
};

/*
 * Convenience macro for traversing every relocation descriptor found within
 * a given relocation cache, transparently handling the cache buffers and
 * skipping any unallocated descriptors within the buffers.
 *
 * entry:
 *	_rel_cache - Relocate descriptor cache (Rel_cache) to traverse
 *	_idx - Aliste index variable for use by the macro
 *	_rcbp - Cache buffer pointer, for use by the macro
 *	_orsp - Rel_desc pointer, which will take on the value of a different
 *		relocation descriptor in the cache in each iteration.
 *
 * The caller must not assign new values to _idx, _rcbp, or _orsp within
 * the scope of REL_CACHE_TRAVERSE.
 */
#define	REL_CACHE_TRAVERSE(_rel_cache, _idx, _rcbp, _orsp) \
	for (APLIST_TRAVERSE((_rel_cache)->rc_list, _idx, _rcbp)) \
		for (_orsp = _rcbp->rc_arr; _orsp < _rcbp->rc_free; _orsp++)

/*
 * Symbol value descriptor.  For relocatable objects, each symbols value is
 * its offset within its associated section.  Therefore, to uniquely define
 * each symbol within a relocatable object, record and sort the sh_offset and
 * symbol value.  This information is used to search for displacement
 * relocations as part of copy relocation validation.
 */
typedef struct {
	Addr		ssv_value;
	Sym_desc	*ssv_sdp;
} Ssv_desc;

/*
 * Input file processing structures.
 */
struct ifl_desc {			/* input file descriptor */
	const char	*ifl_name;	/* full file name */
	const char	*ifl_soname;	/* shared object name */
	dev_t		ifl_stdev;	/* device id and inode number for .so */
	ino_t		ifl_stino;	/*	multiple inclusion checks */
	Ehdr		*ifl_ehdr;	/* elf header describing this file */
	Elf		*ifl_elf;	/* elf descriptor for this file */
	Sym_desc	**ifl_oldndx;	/* original symbol table indices */
	Sym_desc	*ifl_locs;	/* symbol desc version of locals */
	Ssv_desc	*ifl_sortsyms;	/* sorted list of symbols by value */
	Word		ifl_locscnt;	/* no. of local symbols to process */
	Word		ifl_symscnt;	/* total no. of symbols to process */
	Word		ifl_sortcnt;	/* no. of sorted symbols to process */
	Word		ifl_shnum;	/* number of sections in file */
	Word		ifl_shstrndx;	/* index to .shstrtab */
	Word		ifl_vercnt;	/* number of versions in file */
	Half		ifl_neededndx;	/* index to NEEDED in .dyn section */
	Word		ifl_flags;	/* explicit/implicit reference */
	Is_desc		**ifl_isdesc;	/* isdesc[scn ndx] = Is_desc ptr */
	Sdf_desc	*ifl_sdfdesc;	/* control definition */
	Versym		*ifl_versym;	/* version symbol table array */
	Ver_index	*ifl_verndx;	/* verndx[ver ndx] = Ver_index */
	APlist		*ifl_verdesc;	/* version descriptor list */
	APlist		*ifl_relsect;	/* relocation section list */
	Alist		*ifl_groups;	/* SHT_GROUP section list */
	Cap_desc	*ifl_caps;	/* capabilities descriptor */
};

#define	FLG_IF_CMDLINE	0x00000001	/* full filename specified from the */
					/*	command line (no -l) */
#define	FLG_IF_NEEDED	0x00000002	/* shared object should be recorded */
#define	FLG_IF_DIRECT	0x00000004	/* establish direct bindings to this */
					/*	object */
#define	FLG_IF_EXTRACT	0x00000008	/* file extracted from an archive */
#define	FLG_IF_VERNEED	0x00000010	/* version dependency information is */
					/*	required */
#define	FLG_IF_DEPREQD	0x00000020	/* dependency is required to satisfy */
					/*	symbol references */
#define	FLG_IF_NEEDSTR	0x00000040	/* dependency specified by -Nn */
					/*	flag */
#define	FLG_IF_IGNORE	0x00000080	/* ignore unused dependencies */
#define	FLG_IF_NODIRECT	0x00000100	/* object contains symbols that */
					/*	cannot be directly bound to */
#define	FLG_IF_LAZYLD	0x00000200	/* dependency should be lazy loaded */
#define	FLG_IF_GRPPRM	0x00000400	/* dependency establishes a group */
#define	FLG_IF_DISPPEND 0x00000800	/* displacement relocation done */
					/*	in the ld time. */
#define	FLG_IF_DISPDONE 0x00001000	/* displacement relocation done */
					/*	at the run time */
#define	FLG_IF_MAPFILE	0x00002000	/* file is a mapfile */
#define	FLG_IF_HSTRTAB	0x00004000	/* file has a string section */
#define	FLG_IF_FILEREF	0x00008000	/* file contains a section which */
					/*	is included in the output */
					/*	allocatable image */
#define	FLG_IF_GNUVER	0x00010000	/* file used GNU-style versioning */
#define	FLG_IF_ORDERED	0x00020000	/* ordered section processing */
					/*	required */
#define	FLG_IF_OTOSCAP	0x00040000	/* convert object capabilities to */
					/*	symbol capabilities */
#define	FLG_IF_DEFERRED	0x00080000	/* dependency is deferred */
#define	FLG_IF_RTLDINF	0x00100000	/* dependency has DT_SUNW_RTLTINF set */
#define	FLG_IF_GROUPS	0x00200000	/* input file has groups to process */

/*
 * Symbol states that require the generation of a DT_POSFLAG_1 .dynamic entry.
 */
#define	MSK_IF_POSFLAG1	(FLG_IF_LAZYLD | FLG_IF_GRPPRM | FLG_IF_DEFERRED)

/*
 * Symbol states that require an associated Syminfo entry.
 */
#define	MSK_IF_SYMINFO	(FLG_IF_LAZYLD | FLG_IF_DIRECT | FLG_IF_DEFERRED)


struct is_desc {			/* input section descriptor */
	const char	*is_name;	/* original section name */
	const char	*is_sym_name;	/* NULL, or name string to use for */
					/*	related STT_SECTION symbols */
	Shdr		*is_shdr;	/* the elf section header */
	Ifl_desc	*is_file;	/* infile desc for this section */
	Os_desc		*is_osdesc;	/* new output section for this */
					/*	input section */
	Elf_Data	*is_indata;	/* input sections raw data */
	Is_desc		*is_symshndx;	/* related SHT_SYM_SHNDX section */
	Is_desc		*is_comdatkeep;	/* If COMDAT section is discarded, */
					/*	this is section that was kept */
	Word		is_scnndx;	/* original section index in file */
	Word		is_ordndx;	/* index for section.  Used to decide */
					/*	where to insert section when */
					/*	reordering sections */
	Word		is_keyident;	/* key for SHF_{ORDERED|LINK_ORDER} */
					/*	processing and ident used for */
					/*	 placing/ordering sections */
	Word		is_flags;	/* Various flags */
};

#define	FLG_IS_ORDERED	0x0001		/* this is a SHF_ORDERED section */
#define	FLG_IS_KEY	0x0002		/* section requires sort keys */
#define	FLG_IS_DISCARD	0x0004		/* section is to be discarded */
#define	FLG_IS_RELUPD	0x0008		/* symbol defined here may have moved */
#define	FLG_IS_SECTREF	0x0010		/* section has been referenced */
#define	FLG_IS_GDATADEF	0x0020		/* section contains global data sym */
#define	FLG_IS_EXTERNAL	0x0040		/* isp from a user file */
#define	FLG_IS_INSTRMRG	0x0080		/* Usable SHF_MERGE|SHF_STRINGS sec */
#define	FLG_IS_GNSTRMRG	0x0100		/* Generated mergeable string section */

#define	FLG_IS_PLACE	0x0400		/* section requires to be placed */
#define	FLG_IS_COMDAT	0x0800		/* section is COMDAT */
#define	FLG_IS_EHFRAME	0x1000		/* section is .eh_frame */

/*
 * Output sections contain lists of input sections that are assigned to them.
 * These items fall into 4 categories:
 *	BEFORE - Ordered sections that specify SHN_BEFORE, in input order.
 *	ORDERED - Ordered sections that are sorted using unsorted sections
 *		as the sort key.
 *	DEFAULT - Sections that are placed into the output section
 *		in input order.
 *	AFTER - Ordered sections that specify SHN_AFTER, in input order.
 */
#define	OS_ISD_BEFORE	0
#define	OS_ISD_ORDERED	1
#define	OS_ISD_DEFAULT	2
#define	OS_ISD_AFTER	3
#define	OS_ISD_NUM	4
typedef APlist *os_isdecs_arr[OS_ISD_NUM];

/*
 * Convenience macro for traversing every input section associated
 * with a given output section. The primary benefit of this macro
 * is that it preserves a precious level of code indentation in the
 * code that uses it.
 */
#define	OS_ISDESCS_TRAVERSE(_list_idx, _osp, _idx, _isp) \
	for (_list_idx = 0; _list_idx < OS_ISD_NUM; _list_idx++) \
		for (APLIST_TRAVERSE(_osp->os_isdescs[_list_idx], _idx, _isp))


/*
 * Map file and output file processing structures
 */
struct os_desc {			/* Output section descriptor */
	const char	*os_name;	/* the section name */
	Elf_Scn		*os_scn;	/* the elf section descriptor */
	Shdr		*os_shdr;	/* the elf section header */
	Os_desc		*os_relosdesc;	/* the output relocation section */
	APlist		*os_relisdescs;	/* reloc input section descriptors */
					/*	for this output section */
	os_isdecs_arr	os_isdescs;	/* lists of input sections in output */
	APlist		*os_mstrisdescs; /* FLG_IS_INSTRMRG input sections */
	Sg_desc		*os_sgdesc;	/* segment os_desc is placed on */
	Elf_Data	*os_outdata;	/* output sections raw data */
	avl_tree_t	*os_comdats;	/* AVL tree of COMDAT input sections */
					/*	associated to output section */
	Word		os_identndx;	/* section identifier for input */
					/*	section processing, followed */
					/*	by section symbol index */
	Word		os_ordndx;	/* index for section.  Used to decide */
					/*	where to insert section when */
					/*	reordering sections */
	Xword		os_szoutrels;	/* size of output relocation section */
	uint_t		os_namehash;	/* hash on section name */
	uchar_t		os_flags;	/* various flags */
	APlist		*os_mstrsyms;	/* symbols affected by string merge */
	APlist		*os_mstrrels;	/* section relocs affected by... */
	Str_tbl		*os_mstrtab;	/* merged string table */
	Os_desc		*os_hashnext;	/* next hashed */
};

/*
 * Hash of output section descriptors, by namehash.
 */
typedef struct os_desc_hash {
	Os_desc		**osh_hashtab;	/* hash table itself */
	size_t		osh_size;	/* number of elements in hash table */
} os_desc_hash_t;

#define	FLG_OS_KEY		0x01	/* section requires sort keys */
#define	FLG_OS_OUTREL		0x02	/* output rel against this section */
#define	FLG_OS_SECTREF		0x04	/* isps are not affected by -zignore */
#define	FLG_OS_EHFRAME		0x08	/* section is .eh_frame */

/*
 * The sg_id field of the segment descriptor is used to establish the default
 * order for program headers and segments in the output object. Segments are
 * ordered according to the following SGID values that classify them based on
 * their attributes. The initial set of built in segments are in this order,
 * and new mapfile defined segments are inserted into these groups. Within a
 * given SGID group, the position of new segments depends on the syntax
 * version of the mapfile that creates them. Version 1 (original sysv)
 * mapfiles place the new segment at the head of their group (reverse creation
 * order). The newer syntax places them at the end, following the others
 * (creation order).
 *
 * Note that any new segments must always be added after PT_PHDR and
 * PT_INTERP (refer Generic ABI, Page 5-4).
 */
#define	SGID_PHDR	0	/* PT_PHDR */
#define	SGID_INTERP	1	/* PT_INTERP */
#define	SGID_SUNWCAP	2	/* PT_SUNWCAP */
#define	SGID_TEXT	3	/* PT_LOAD */
#define	SGID_DATA	4	/* PT_LOAD */
#define	SGID_BSS	5	/* PT_LOAD */
#if	defined(_ELF64)
#define	SGID_LRODATA	6	/* PT_LOAD (amd64-only) */
#define	SGID_LDATA	7	/* PT_LOAD (amd64-only) */
#endif
#define	SGID_TEXT_EMPTY	8	/* PT_LOAD, reserved (?E in version 1 syntax) */
#define	SGID_NULL_EMPTY	9	/* PT_NULL, reserved (?E in version 1 syntax) */
#define	SGID_DYN	10	/* PT_DYNAMIC */
#define	SGID_DTRACE	11	/* PT_SUNWDTRACE */
#define	SGID_TLS	12	/* PT_TLS */
#define	SGID_UNWIND	13	/* PT_SUNW_UNWIND */
#define	SGID_SUNWSTACK	14	/* PT_SUNWSTACK */
#define	SGID_NOTE	15	/* PT_NOTE */
#define	SGID_NULL	16	/* PT_NULL,  mapfile defined empty phdr slots */
				/*	for use by post processors */
#define	SGID_EXTRA	17	/* PT_NULL (final catchall) */

typedef Half sg_flags_t;
struct sg_desc {			/* output segment descriptor */
	Word		sg_id;		/* segment identifier (for sorting) */
	Phdr		sg_phdr;	/* segment header for output file */
	const char	*sg_name;	/* segment name for PT_LOAD, PT_NOTE, */
					/*	and PT_NULL, otherwise NULL */
	Xword		sg_round;	/* data rounding required (mapfile) */
	Xword		sg_length;	/* maximum segment length; if 0 */
					/*	segment is not specified */
	APlist		*sg_osdescs;	/* list of output section descriptors */
	APlist		*sg_is_order;	/* list of entry criteria */
					/*	giving input section order */
	Alist		*sg_os_order;	/* list specifying output section */
					/*	ordering for the segment */
	sg_flags_t	sg_flags;
	APlist		*sg_sizesym;	/* size symbols for this segment */
	Xword		sg_align;	/* LCM of sh_addralign */
	Elf_Scn		*sg_fscn;	/* the SCN of the first section. */
	avl_node_t	sg_avlnode;	/* AVL book-keeping */
	os_desc_hash_t	*sg_hashtab;	/* hash table of output descriptors */
};

#define	FLG_SG_P_VADDR		0x0001	/* p_vaddr segment attribute set */
#define	FLG_SG_P_PADDR		0x0002	/* p_paddr segment attribute set */
#define	FLG_SG_LENGTH		0x0004	/* length segment attribute set */
#define	FLG_SG_P_ALIGN		0x0008	/* p_align segment attribute set */
#define	FLG_SG_ROUND		0x0010	/* round segment attribute set */
#define	FLG_SG_P_FLAGS		0x0020	/* p_flags segment attribute set */
#define	FLG_SG_P_TYPE		0x0040	/* p_type segment attribute set */
#define	FLG_SG_IS_ORDER		0x0080	/* input section ordering is required */
					/*	for this segment. */
#define	FLG_SG_NOHDR		0x0100	/* don't map ELF or phdrs into */
					/*	this segment */
#define	FLG_SG_EMPTY		0x0200	/* an empty segment specification */
					/*	no input sections will be */
					/*	associated to this section */
#define	FLG_SG_KEY		0x0400	/* segment requires sort keys */
#define	FLG_SG_NODISABLE	0x0800	/* FLG_SG_DISABLED is not allowed on */
					/*	this segment */
#define	FLG_SG_DISABLED		0x1000	/* this segment is disabled */
#define	FLG_SG_PHREQ		0x2000	/* this segment requires a program */
					/* header */
#define	FLG_SG_ORDERED		0x4000	/* SEGMENT_ORDER segment */

struct sec_order {
	const char	*sco_secname;	/* section name to be ordered */
	Half		sco_flags;
};

#define	FLG_SGO_USED	0x0001		/* was ordering used? */

typedef Half ec_flags_t;
struct ent_desc {			/* input section entrance criteria */
	const char	*ec_name;	/* entrace criteria name, or NULL */
	Alist		*ec_files;	/* files from which to accept */
					/*	sections */
	const char	*ec_is_name;	/* input section name to match */
					/*	(NULL if none) */
	Word		ec_type;	/* section type */
	Word		ec_attrmask;	/* section attribute mask (AWX) */
	Word		ec_attrbits;	/* sections attribute bits */
	Sg_desc		*ec_segment;	/* output segment to enter if matched */
	Word		ec_ordndx;	/* index to determine where section */
					/*	meeting this criteria should */
					/*	inserted. Used for reordering */
					/*	of sections. */
	ec_flags_t	ec_flags;
	avl_node_t	ec_avlnode;	/* AVL book-keeping */
};

#define	FLG_EC_BUILTIN	0x0001		/* built in descriptor */
#define	FLG_EC_USED	0x0002		/* entrance criteria met? */
#define	FLG_EC_CATCHALL	0x0004		/* Catches any section */

/*
 * Ent_desc_file is the type of element maintained in the ec_files Alist
 * of an entrance criteria descriptor. Each item maintains one file
 * path, and a set of flags that specify the type of comparison it implies,
 * and other information about it. The comparison type is maintained in
 * the bottom byte of the flags.
 */
#define	TYP_ECF_MASK		0x00ff  /* Comparison type mask */
#define	TYP_ECF_PATH		0	/* Compare to file path */
#define	TYP_ECF_BASENAME	1	/* Compare to file basename */
#define	TYP_ECF_OBJNAME		2	/* Compare to regular file basename, */
					/*	 or to archive member name */
#define	TYP_ECF_NUM		3

#define	FLG_ECF_ARMEMBER	0x0100	/* name includes archive member */

typedef struct {
	Word		edf_flags;	/* Type of comparison */
	const char	*edf_name;	/* String to compare to */
	size_t		edf_name_len;	/* strlen(edf_name) */
} Ent_desc_file;

/*
 * One structure is allocated for a move entry, and associated to the symbol
 * against which a move is targeted.
 */
typedef struct {
	Move		*md_move;	/* original Move entry */
	Xword		md_start;	/* start position */
	Xword		md_len;		/* length of initialization */
	Word		md_oidx;	/* output Move entry index */
} Mv_desc;

#define	SYM_ASSERT_SIZE		0x01
#define	SYM_ASSERT_BIND		0x02
#define	SYM_ASSERT_TYPE		0x04
#define	SYM_ASSERT_BITS		0x08
#define	SYM_ASSERT_ALIAS	0x10

typedef struct {
	Sym_desc	*ass_sdp;
	char		*ass_file;
	Lineno		ass_lineno;
	uchar_t		ass_type;
	uchar_t		ass_bind;
	Lword		ass_size;
	Boolean		ass_bits;
	const char	*ass_alias;
	/* Assertions explicitly enabled by user */
	uint_t		ass_enabled;
} Ass_desc;

/*
 * Symbol descriptor.
 */
typedef	Lword		sd_flag_t;
struct sym_desc {
	Alist		*sd_GOTndxs;	/* list of associated GOT entries */
	Sym		*sd_sym;	/* pointer to symbol table entry */
	Sym		*sd_osym;	/* copy of the original symbol entry */
					/*	used only for local partial */
	Alist		*sd_move;	/* move information associated with a */
					/*	partially initialized symbol */
	const char	*sd_name;	/* symbols name */
	Ifl_desc	*sd_file;	/* file where symbol is taken */
	Is_desc		*sd_isc;	/* input section of symbol definition */
	Sym_aux		*sd_aux;	/* auxiliary global symbol info. */
	Word		sd_symndx;	/* index in output symbol table */
	Word		sd_shndx;	/* sect. index sym is associated w/ */
	sd_flag_t	sd_flags;	/* state flags */
	Half		sd_ref;		/* reference definition of symbol */
	Ass_desc	*sd_ass;	/* pointer back to symbol assertions */
};

/*
 * The auxiliary symbol descriptor contains the additional information (beyond
 * the symbol descriptor) required to process global symbols.  These symbols are
 * accessed via an internal symbol hash table where locality of reference is
 * important for performance.
 */
struct sym_aux {
	APlist		*sa_dfiles;	/* files where symbol is defined */
	Sym		sa_sym;		/* copy of symtab entry */
	const char	*sa_vfile;	/* first unavailable definition */
	const char	*sa_rfile;	/* file with first symbol referenced */
	Word		sa_hash;	/* the pure hash value of symbol */
	Word		sa_PLTndx;	/* index into PLT for symbol */
	Word		sa_PLTGOTndx;	/* GOT entry indx for PLT indirection */
	Word		sa_linkndx;	/* index of associated symbol from */
					/*	ET_DYN file */
	Half		sa_symspec;	/* special symbol ids */
	Half		sa_overndx;	/* output file versioning index */
	Half		sa_dverndx;	/* dependency versioning index */
	Os_desc		*sa_boundsec;	/* output section of SECBOUND_ syms */
};

/*
 * Nodes used to track symbols in the global AVL symbol dictionary.
 */
struct sym_avlnode {
	avl_node_t	sav_node;	/* AVL node */
	Word		sav_hash;	/* symbol hash value */
	const char	*sav_name;	/* symbol name */
	Sym_desc	*sav_sdp;	/* symbol descriptor */
};

/*
 * These are the ids for processing of `Special symbols'.  They are used
 * to set the sym->sd_aux->sa_symspec field.
 */
#define	SDAUX_ID_ETEXT		1	/* etext && _etext symbol */
#define	SDAUX_ID_EDATA		2	/* edata && _edata symbol */
#define	SDAUX_ID_END		3	/* end, _end, && _END_ symbol */
#define	SDAUX_ID_DYN		4	/* DYNAMIC && _DYNAMIC symbol */
#define	SDAUX_ID_PLT		5	/* _PROCEDURE_LINKAGE_TABLE_ symbol */
#define	SDAUX_ID_GOT		6	/* _GLOBAL_OFFSET_TABLE_ symbol */
#define	SDAUX_ID_START		7	/* START_ && _START_ symbol */
#define	SDAUX_ID_SECBOUND_START	8	/* __start_<section> symbols */
#define	SDAUX_ID_SECBOUND_STOP	9	/* __stop_<section> symbols */

/*
 * Flags for sym_desc.sd_flags
 */
#define	FLG_SY_MVTOCOMM	0x00000001	/* assign symbol to common (.bss) */
					/*	this is a result of a */
					/*	copy reloc against sym */
#define	FLG_SY_GLOBREF	0x00000002	/* a global reference has been seen */
#define	FLG_SY_WEAKDEF	0x00000004	/* a weak definition has been used */
#define	FLG_SY_CLEAN	0x00000008	/* `Sym' entry points to original */
					/*	input file (read-only). */
#define	FLG_SY_UPREQD	0x00000010	/* symbol value update is required, */
					/*	either it's used as an entry */
					/*	point or for relocation, but */
					/*	it must be updated even if */
					/*	the -s flag is in effect */
#define	FLG_SY_NOTAVAIL	0x00000020	/* symbol is not available to the */
					/*	application either because it */
					/*	originates from an implicitly */
					/*	referenced shared object, or */
					/*	because it is not part of a */
					/*	specified version. */
#define	FLG_SY_REDUCED	0x00000040	/* a global is reduced to local */
#define	FLG_SY_VERSPROM	0x00000080	/* version definition has been */
					/*	promoted to output file */
#define	FLG_SY_PROT	0x00000100	/* stv_protected visibility seen */
#define	FLG_SY_MAPREF	0x00000200	/* symbol reference generated by user */
					/*	from mapfile */
#define	FLG_SY_REFRSD	0x00000400	/* symbols sd_ref has been raised */
					/*	due to a copy-relocs */
					/*	weak-strong pairing */
#define	FLG_SY_INTPOSE	0x00000800	/* symbol defines an interposer */
#define	FLG_SY_INVALID	0x00001000	/* unwanted/erroneous symbol */
#define	FLG_SY_SMGOT	0x00002000	/* small got index assigned to symbol */
					/*	sparc only */
#define	FLG_SY_PARENT	0x00004000	/* symbol to be found in parent */
					/*    only used with direct bindings */
#define	FLG_SY_LAZYLD	0x00008000	/* symbol to cause lazyloading of */
					/*	parent object */
#define	FLG_SY_ISDISC	0x00010000	/* symbol is a member of a DISCARDED */
					/*	section (COMDAT) */
#define	FLG_SY_PAREXPN	0x00020000	/* partially init. symbol to be */
					/*	expanded */
#define	FLG_SY_PLTPAD	0x00040000	/* pltpadding has been allocated for */
					/*	this symbol */
#define	FLG_SY_REGSYM	0x00080000	/* REGISTER symbol (sparc only) */
#define	FLG_SY_SOFOUND	0x00100000	/* compared against an SO definition */
#define	FLG_SY_EXTERN	0x00200000	/* symbol is external, allows -zdefs */
					/*    error suppression */
#define	FLG_SY_MAPUSED	0x00400000	/* mapfile symbol used (occurred */
					/*    within a relocatable object) */
#define	FLG_SY_COMMEXP	0x00800000	/* COMMON symbol which has been */
					/*	allocated */
#define	FLG_SY_CMDREF	0x01000000	/* symbol was referenced from the */
					/*	command line.  (ld -u <>, */
					/*	ld -zrtldinfo=<>, ...) */
#define	FLG_SY_SPECSEC	0x02000000	/* section index is reserved value */
					/*	ABS, COMMON, ... */
#define	FLG_SY_TENTSYM	0x04000000	/* tentative symbol */
#define	FLG_SY_VISIBLE	0x08000000	/* symbols visibility determined */
#define	FLG_SY_STDFLTR	0x10000000	/* symbol is a standard filter */
#define	FLG_SY_AUXFLTR	0x20000000	/* symbol is an auxiliary filter */
#define	FLG_SY_DYNSORT	0x40000000	/* req. in dyn[sym|tls]sort section */
#define	FLG_SY_NODYNSORT 0x80000000	/* excluded from dyn[sym_tls]sort sec */

#define	FLG_SY_DEFAULT	0x0000100000000	/* global symbol, default */
#define	FLG_SY_SINGLE	0x0000200000000	/* global symbol, singleton defined */
#define	FLG_SY_PROTECT	0x0000400000000	/* global symbol, protected defined */
#define	FLG_SY_EXPORT	0x0000800000000	/* global symbol, exported defined */

#define	MSK_SY_GLOBAL \
	(FLG_SY_DEFAULT | FLG_SY_SINGLE | FLG_SY_PROTECT | FLG_SY_EXPORT)
					/* this mask indicates that the */
					/*    symbol has been explicitly */
					/*    defined within a mapfile */
					/*    definition, and is a candidate */
					/*    for versioning */

#define	FLG_SY_HIDDEN	0x0001000000000	/* global symbol, reduce to local */
#define	FLG_SY_ELIM	0x0002000000000	/* global symbol, eliminate */
#define	FLG_SY_IGNORE	0x0004000000000	/* global symbol, ignored */

#define	MSK_SY_LOCAL	(FLG_SY_HIDDEN | FLG_SY_ELIM | FLG_SY_IGNORE)
					/* this mask allows all local state */
					/*    flags to be removed when the */
					/*    symbol is copy relocated */

#define	FLG_SY_EXPDEF	0x0008000000000	/* symbol visibility defined */
					/*    explicitly */

#define	MSK_SY_NOAUTO	(FLG_SY_SINGLE | FLG_SY_EXPORT | FLG_SY_EXPDEF)
					/* this mask indicates that the */
					/*    symbol is not a candidate for */
					/*    auto-reduction/elimination */

#define	FLG_SY_MAPFILE	0x0010000000000	/* symbol attribute defined in a */
					/*    mapfile */
#define	FLG_SY_DIR	0x0020000000000	/* global symbol, direct bindings */
#define	FLG_SY_NDIR	0x0040000000000	/* global symbol, nondirect bindings */
#define	FLG_SY_OVERLAP	0x0080000000000	/* move entry overlap detected */
#define	FLG_SY_CAP	0x0100000000000	/* symbol is associated with */
					/*    capabilities */
#define	FLG_SY_DEFERRED	0x0200000000000	/* symbol should not be bound to */
					/*	during BIND_NOW relocations */

#define	FLG_SY_MAPASSRT	0x0400000000000 /* Symbol has attribute assertions */

/*
 * A symbol can only be truly hidden if it is not a capabilities symbol.
 */
#define	SYM_IS_HIDDEN(_sdp) \
	(((_sdp)->sd_flags & (FLG_SY_HIDDEN | FLG_SY_CAP)) == FLG_SY_HIDDEN)

/*
 * Create a mask for (sym.st_other & visibility) since the gABI does not yet
 * define a ELF*_ST_OTHER macro.
 */
#define	MSK_SYM_VISIBILITY	0x7

/*
 * Structure to manage the shared object definition lists.  There are two lists
 * that use this structure:
 *
 *  -	ofl_soneed; maintain the list of implicitly required dependencies
 *	(ie. shared objects needed by other shared objects).  These definitions
 *	may include RPATH's required to locate the dependencies, and any
 *	version requirements.
 *
 *  -	ofl_socntl; maintains the shared object control definitions.  These are
 *	provided by the user (via a mapfile) and are used to indicate any
 *	version control requirements.
 */
struct	sdf_desc {
	const char	*sdf_name;	/* the shared objects file name */
	char		*sdf_rpath;	/* library search path DT_RPATH */
	const char	*sdf_rfile;	/* referencing file for diagnostics */
	Ifl_desc	*sdf_file;	/* the final input file descriptor */
	Alist		*sdf_vers;	/* list of versions that are required */
					/*	from this object */
	Alist		*sdf_verneed;	/* list of VERNEEDS to create for */
					/*	object via mapfile ADDVERS */
	Word		sdf_flags;
};

#define	FLG_SDF_SELECT	0x01		/* version control selection required */
#define	FLG_SDF_VERIFY	0x02		/* version definition verification */
					/*	required */
#define	FLG_SDF_ADDVER	0x04		/* add VERNEED references */

/*
 * Structure to manage shared object version usage requirements.
 */
struct	sdv_desc {
	const char	*sdv_name;	/* version name */
	const char	*sdv_ref;	/* versions reference */
	Word		sdv_flags;	/* flags */
};

#define	FLG_SDV_MATCHED	0x01		/* VERDEF found and matched */

/*
 * Structures to manage versioning information.  Two versioning structures are
 * defined:
 *
 *   -	a version descriptor maintains a linked list of versions and their
 *	associated dependencies.  This is used to build the version definitions
 *	for an image being created (see map_symbol), and to determine the
 *	version dependency graph for any input files that are versioned.
 *
 *   -	a version index array contains each version of an input file that is
 *	being processed.  It informs us which versions are available for
 *	binding, and is used to generate any version dependency information.
 */
struct	ver_desc {
	const char	*vd_name;	/* version name */
	Ifl_desc	*vd_file;	/* file that defined version */
	Word		vd_hash;	/* hash value of name */
	Half		vd_ndx;		/* coordinates with symbol index */
	Half		vd_flags;	/* version information */
	APlist		*vd_deps;	/* version dependencies */
	Ver_desc	*vd_ref;	/* dependency's first reference */
};

struct	ver_index {
	const char	*vi_name;	/* dependency version name */
	Half		vi_flags;	/* communicates availability */
	Half		vi_overndx;	/* index assigned to this version in */
					/*	output object Verneed section */
	Ver_desc	*vi_desc;	/* cross reference to descriptor */
};

/*
 * Define any internal version descriptor flags ([vd|vi]_flags).  Note that the
 * first byte is reserved for user visible flags (refer VER_FLG's in link.h).
 */
#define	MSK_VER_USER	0x0f		/* mask for user visible flags */

#define	FLG_VER_AVAIL	0x10		/* version is available for binding */
#define	FLG_VER_REFER	0x20		/* version has been referenced */
#define	FLG_VER_CYCLIC	0x40		/* a member of cyclic dependency */

/*
 * isalist(1) descriptor - used to break an isalist string into its component
 * options.
 */
struct	isa_opt {
	char		*isa_name;	/* individual isa option name */
	size_t		isa_namesz;	/*	and associated size */
};

struct	isa_desc {
	char		*isa_list;	/* sysinfo(SI_ISALIST) list */
	size_t		isa_listsz;	/*	and associated size */
	Isa_opt		*isa_opt;	/* table of individual isa options */
	size_t		isa_optno;	/*	and associated number */
};

/*
 * uname(2) descriptor - used to break a utsname structure into its component
 * options (at least those that we're interested in).
 */
struct	uts_desc {
	char		*uts_osname;	/* operating system name */
	size_t		uts_osnamesz;	/*	and associated size */
	char		*uts_osrel;	/* operating system release */
	size_t		uts_osrelsz;	/*	and associated size */
};

/*
 * SHT_GROUP descriptor - used to track group sections at the global
 * level to resolve conflicts and determine which to keep.
 */
struct group_desc {
	Is_desc		*gd_isc;	/* input section descriptor */
	Is_desc		*gd_oisc;	/* overriding input section */
					/*	descriptor when discarded */
	const char	*gd_name;	/* group name (signature symbol) */
	Word		*gd_data;	/* data for group section */
	size_t		gd_cnt;		/* number of entries in group data */
};

/*
 * Indexes into the ld_support_funcs[] table.
 */
typedef enum {
	LDS_VERSION = 0,	/* Must be first and have value 0 */
	LDS_INPUT_DONE,
	LDS_START,
	LDS_ATEXIT,
	LDS_OPEN,
	LDS_FILE,
	LDS_INSEC,
	LDS_SEC,
	LDS_NUM
} Support_ndx;

/*
 * Structure to manage archive member caching.  Each archive has an archive
 * descriptor (Ar_desc) associated with it.  This contains pointers to the
 * archive symbol table (obtained by elf_getarsym(3ELF)) and an auxiliary
 * structure (Ar_uax[]) that parallels this symbol table.  The member element
 * of this auxiliary table indicates whether the archive member associated with
 * the symbol offset has already been extracted (AREXTRACTED) or partially
 * processed (refer process_member()).
 */
typedef struct ar_mem {
	Elf		*am_elf;	/* elf descriptor for this member */
	const char	*am_name;	/* members name */
	const char	*am_path;	/* path (ie. lib(foo.o)) */
	Sym		*am_syms;	/* start of global symbols */
	char		*am_strs;	/* associated string table start */
	Xword		am_symn;	/* no. of global symbols */
} Ar_mem;

typedef struct ar_aux {
	Sym_desc	*au_syms;	/* internal symbol descriptor */
	Ar_mem		*au_mem;	/* associated member */
} Ar_aux;

#define	FLG_ARMEM_PROC	(Ar_mem *)-1

typedef struct ar_desc {
	const char	*ad_name;	/* archive file name */
	Elf		*ad_elf;	/* elf descriptor for the archive */
	Elf_Arsym	*ad_start;	/* archive symbol table start */
	Ar_aux		*ad_aux;	/* auxiliary symbol information */
	dev_t		ad_stdev;	/* device id and inode number for */
	ino_t		ad_stino;	/*	multiple inclusion checks */
	ofl_flag_t	ad_flags;	/* archive specific cmd line flags */
	Boolean		ad_allextract;	/* archive has been allextract'ed */
} Ar_desc;

/*
 * Define any archive descriptor flags.  NOTE, make sure they do not clash with
 * any output file descriptor archive extraction flags, as these are saved in
 * the same entry (see MSK_OF1_ARCHIVE).
 */
#define	FLG_ARD_EXTRACT	0x00010000	/* archive member has been extracted */

/* Mapfile versions supported by libld */
#define	MFV_NONE	0	/* Not a valid version */
#define	MFV_SYSV	1	/* Original System V syntax */
#define	MFV_SOLARIS	2	/* Solaris mapfile syntax */
#define	MFV_NUM		3	/* # of mapfile versions */


/*
 * Function Declarations.
 */
#if	defined(_ELF64)

#define	ld_create_outfile	ld64_create_outfile
#define	ld_ent_setup		ld64_ent_setup
#define	ld_init_strings		ld64_init_strings
#define	ld_init_target		ld64_init_target
#define	ld_make_sections	ld64_make_sections
#define	ld_main			ld64_main
#define	ld_ofl_cleanup		ld64_ofl_cleanup
#define	ld_process_mem		ld64_process_mem
#define	ld_reloc_init		ld64_reloc_init
#define	ld_reloc_process	ld64_reloc_process
#define	ld_sym_validate		ld64_sym_validate
#define	ld_update_outfile	ld64_update_outfile

#else

#define	ld_create_outfile	ld32_create_outfile
#define	ld_ent_setup		ld32_ent_setup
#define	ld_init_strings		ld32_init_strings
#define	ld_init_target		ld32_init_target
#define	ld_make_sections	ld32_make_sections
#define	ld_main			ld32_main
#define	ld_ofl_cleanup		ld32_ofl_cleanup
#define	ld_process_mem		ld32_process_mem
#define	ld_reloc_init		ld32_reloc_init
#define	ld_reloc_process	ld32_reloc_process
#define	ld_sym_validate		ld32_sym_validate
#define	ld_update_outfile	ld32_update_outfile

#endif

extern int		ld_getopt(Lm_list *, int, int, char **);

extern int		ld32_main(int, char **, Half);
extern int		ld64_main(int, char **, Half);

extern uintptr_t	ld_create_outfile(Ofl_desc *);
extern uintptr_t	ld_ent_setup(Ofl_desc *, Xword);
extern uintptr_t	ld_init_strings(Ofl_desc *);
extern int		ld_init_target(Lm_list *, Half mach);
extern uintptr_t	ld_make_sections(Ofl_desc *);
extern void		ld_ofl_cleanup(Ofl_desc *);
extern Ifl_desc		*ld_process_mem(const char *, const char *, char *,
			    size_t, Ofl_desc *, Rej_desc *);
extern uintptr_t	ld_reloc_init(Ofl_desc *);
extern uintptr_t	ld_reloc_process(Ofl_desc *);
extern uintptr_t	ld_sym_validate(Ofl_desc *);
extern uintptr_t	ld_update_outfile(Ofl_desc *);

#ifdef	__cplusplus
}
#endif

#endif	/* _LIBLD_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 *	Copyright (c) 1988 AT&T
 *	  All Rights Reserved
 *
 *
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 *
 * This file maintains an old style of list processing that is required by
 * librtld_db to iterate over older core files/process images.
 */
#ifndef	_LIST_H
#define	_LIST_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/elftypes.h>

typedef	struct listnode	Listnode;
typedef	struct list	List;

struct	listnode {			/* a node on a linked list */
	void		*data;		/* the data item */
	Listnode	*next;		/* the next element */
};

struct	list {				/* a linked list */
	Listnode	*head;		/* the first element */
	Listnode	*tail;		/* the last element */
};


#ifdef _SYSCALL32
typedef	struct listnode32	Listnode32;
typedef	struct list32		List32;

struct	listnode32 {			/* a node on a linked list */
	Elf32_Addr	data;		/* the data item */
	Elf32_Addr	next;		/* the next element */
};

struct	list32 {			/* a linked list */
	Elf32_Addr	head;		/* the first element */
	Elf32_Addr	tail;		/* the last element */
};
#endif	/* _SYSCALL32 */

#ifdef	__cplusplus
}
#endif

#endif /* _LIST_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 *
 * Global include file for all sgs machine dependent macros, constants
 * and declarations applicable to the current system. This header is
 * to be used for code that supports the native system only. Code that
 * needs to support non-native targets should avoid it, and use the
 * target-specific versions found in the subdirectories below the include
 * directory holding this file.
 */

#ifndef	_MACHDEP_H
#define	_MACHDEP_H

#if defined(__sparc)

#include <sparc/machdep_sparc.h>

#elif defined(__i386) || defined(__amd64)

#include <i386/machdep_x86.h>

#else

#error "machdep.h does not understand current machine"

#endif

#endif /* _MACHDEP_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1998 by Sun Microsystems, Inc.
 * All rights reserved.
 */

#ifndef	_MONV_H
#define	_MONV_H

/*
 * Versioned monitor file
 *
 * Since this is not really a *shared* file between the compilers and OS
 * (each hold a separate copy), care must be taken to see that it is in
 * in sync with the compiler version.
 */

#ifdef	__cplusplus
extern "C" {
#endif

/*
 *	General object structure
 */
#ifndef	PROF_TYPES_PREDEFINED
typedef unsigned long long Index;
typedef unsigned long long Address;
typedef unsigned long long Size;
#endif

typedef struct _prof_object {
	unsigned int		type;
	unsigned int		version;
	Size			size;
} ProfObject;


#define	PROF_MAGIC		0x50524F46	/* "PROF" */
#define	PROF_MAJOR_VERSION	1
#define	PROF_MINOR_VERSION	0

typedef struct _prof_header {
	unsigned int		h_magic;
	unsigned short		h_major_ver;
	unsigned short		h_minor_ver;
	Size			size;
} ProfHeader;

/*
 *	Object types
 */
#define	PROF_DUMMY_T		-1		/* to be ignored by gprof */
#define	PROF_BUFFER_T		1
#define	PROF_CALLGRAPH_T	2
#define	PROF_MODULES_T		3

/*
 *	Object version numbers
 */
#define	PROF_BUFFER_VER		1
#define	PROF_CALLGRAPH_VER	1
#define	PROF_MODULES_VER	1

/*
 * Actual number of pcsample elements that can be held in 1Mb with
 * the size of (Address) equal to 8
 */
#define	PROF_BUFFER_SIZE	131072		/* 1 Mb */

typedef struct _prof_buffer {
	unsigned int		type;		/* PROF_BUFFER_T */
	unsigned int		version;	/* 1 */
	Size			size;
	Index			buffer;
	Size			bufsize;
} ProfBuffer;

typedef struct _prof_call_graph {
	unsigned int		type;		/* PROF_CALLGRAPH_T */
	unsigned int		version;	/* 1 */
	Size			size;
	Index			functions;
} ProfCallGraph;

typedef struct _prof_module_list {
	unsigned int		type;		/* PROF_MODULES_T */
	unsigned int		version;	/* 1 */
	Size			size;
	Index			modules;
} ProfModuleList;

typedef struct _prof_module {
	Index			next;
	Index			path;
	Address			startaddr;
	Address			endaddr;
} ProfModule;

typedef struct _prof_function {
	Index			next_to;
	Index			next_from;
	Address			frompc;
	Address			topc;
	unsigned long long	count;
	Index			next_hash;
} ProfFunction;

#ifdef	__cplusplus
}
#endif

#endif	/* _MONV_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 *	Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 *	Use is subject to license terms.
 */

#ifndef	_PROFILE_H
#define	_PROFILE_H

#ifdef	__cplusplus
extern "C" {
#endif

#ifndef	_ASM

#include <sys/types.h>
#include <synch.h>
#include <link.h>

/*
 * The profile buffer created by ld.so.1 consists of 3 sections; the header,
 * the profil(2) buffer, and an array of call graph arc structures.
 */

typedef struct l_hdr {			/* Linker profile buffer header */
	unsigned int	hd_magic;	/* identifier for file */
	unsigned int	hd_version;	/* version for rtld prof file */
	lwp_mutex_t	hd_mutex;	/* Provides for process locking */
	caddr_t		hd_hpc;		/* Relative high pc address */
	unsigned int	hd_psize;	/* Size of profil(2) buffer */
	unsigned int	hd_fsize;	/* Size of file */
	unsigned int	hd_ncndx;	/* Next (and last) index into */
	unsigned int	hd_lcndx;	/*	call graph arc structure */
} L_hdr;


/*
 * The *64 structs are for gprof, as a 32-bit program,
 * to read 64-bit profiles correctly.
 */

typedef struct l_hdr64 {		/* Linker profile buffer header */
	unsigned int	hd_magic;	/* identifier for file */
	unsigned int	hd_version;	/* version for rtld prof file */
	lwp_mutex_t	hd_mutex;	/* Provides for process locking */
	u_longlong_t	hd_hpc;		/* Relative high pc address */
	unsigned int	hd_psize;	/* Size of profil(2) buffer */
	unsigned int	hd_fsize;	/* Size of file */
	unsigned int	hd_ncndx;	/* Next (and last) index into */
	unsigned int	hd_lcndx;	/*	call graph arc structure */
} L_hdr64;



typedef struct l_cgarc {		/* Linker call graph arc entry */
	caddr_t		cg_from;	/* Source of call */
	caddr_t		cg_to;		/* Destination of call */
	unsigned int	cg_count;	/* Instance count */
	unsigned int	cg_next;	/* Link index for multiple sources */
} L_cgarc;


typedef struct l_cgarc64 {		/* Linker call graph arc entry */
	u_longlong_t	cg_from;	/* Source of call */
	u_longlong_t	cg_to;		/* Destination of call */
	unsigned int	cg_count;	/* Instance count */
	unsigned int	cg_next;	/* Link index for multiple sources */
} L_cgarc64;



/*
 * Generic defines for creating profiled output buffer.
 */

#define	PRF_BARSIZE	2		/* No. of program bytes that */
					/* correspond to each histogram */
					/* bar in the profil(2) buffer */
#define	PRF_SCALE	0x8000		/* Scale to provide above */
					/* histogram correspondence */
#define	PRF_CGNUMB	256		/* Size of call graph extension */
#define	PRF_CGINIT	2		/* Initial symbol blocks to allocate */
					/*	for the call graph structure */
#define	PRF_OUTADDR	(caddr_t)-1	/* Function addresses outside of */
					/*	the range being monitored */
#define	PRF_OUTADDR64	(u_longlong_t)-1	/* Function addresses outside */
					/*	of the range being monitored */
#define	PRF_UNKNOWN	(caddr_t)-2	/* Unknown function address */

#define	PRF_ROUNDUP(x, a) (((x) + ((a) - 1)) & ~((a) - 1))
#define	PRF_ROUNDWN(x, a) ((x) & ~((a) - 1))

#define	PRF_MAGIC	0xffffffff	/* unique number to differentiate */
					/* profiled file from gmon.out for */
					/* gprof */
#define	PRF_VERSION	0x1		/* current PROF file version */
#define	PRF_VERSION_64	0x2		/* 64-bit current PROF file version */


/*
 * Related data and function definitions.
 */

extern	int		profile_rtld;		/* Rtld is being profiled */

extern	uintptr_t (*	p_cg_interp)(int, caddr_t, caddr_t);

#endif

#ifdef	__cplusplus
}
#endif

#endif /* _PROFILE_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_RTC_H
#define	_RTC_H

/*
 * Global include file for the runtime configuration support.
 */
#include <time.h>
#include <machdep.h>

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Linker configuration files are designed to be mapped into memory
 * and accessed directly. Hence, the layout of the data must follow
 * byte order and alignment rules for the program examining it.
 *
 * From its initial design through the release of Solaris 10, runtime
 * linker configuration files started with a configuration header (Rtc_head).
 * The role of Rtc_head is to provide a table of contents to the remainder
 * of the file. It tells what information is contained in the file,
 * and the offset (relative to the base of the Rtc_head structure)
 * within the file at which each item can be found. These offsets are
 * 32-bit values. Linker configuration files are 32-bit limited, even
 * for 64-bit platforms.
 *
 * It should be noted that Rtc_head contains no information that can be
 * used to identify the type of program that created the file (byte order,
 * elf class, and machine architecture). This leads to some difficulties:
 *	- Interpreting a config file using a program with the opposite
 *	  byte order can crash the program.
 *	- Structure layout differences can cause a 64-bit version of the
 *	  program to fail to read a 32-bit config file correctly, or
 *	  vice versa. This was not an issue on sparc (both 32 and 64-bit
 *	  happen to lay out the same way). However, 32 and 64-bit X86
 *	  have differing alignment rules.
 *	- The file command cannot easily identify a linker configuration
 *	  file, and simply reports them as "data".
 * Initially, the design of of these files assumed that a given file
 * would be readable by any system. Experience shows that this is wrong.
 * A linker config file is ABI specific, much like an object file. It should
 * only be interpreted by a compatible program.
 *
 * Linker configuration files now start with an Rtc_id structure, followed
 * immediately by Rtc_head. Rtc_id provides the information necessary to
 * detect the type of program that wrote the file, in a manner that allows
 * backwards compatibility with pre-existing config files:
 *	- We can detect an old config file, because they do not start
 *	  with the characters "\077RLC". In this case, we assume the
 *	  file is compatible with the program interpreting it, and that
 *	  Rtc_head is the first thing in the file.
 *	- Solaris 10 and older will refuse to handle a config
 *	  file that has an Rtc_id, because they will interpret
 *	  the "\077RLC" signature as the ch_version field of Rtc_head,
 *	  and will reject the version as being invalid.
 *	- Rtc_id is specified such that its size will be 16 bytes
 *	  on all systems, sufficient to align Rtc_head on any system, and
 *	  to provide future expansion room.
 *	- Offsets to data in the file continue to be specified relative
 *	  to the Rtc_head address, meaning that existing software will
 *	  continue to work with little or no modification.
 */

/*
 * Identification header.
 *
 * This is defined in usr/src/common/sgsrtcid/sgsrtcid.h
 * so that file(1) can also access it.
 */
#include <sgsrtcid.h>

/*
 * Configuration header.
 *
 * AOUT sections (ch_adlibpath, ch_aslibpath) are obsolete and retained only
 * for file-format compatibility.
 */
typedef struct {
	Word	ch_version;		/* version of config file */
	Word	ch_cnflags;		/* configuration flags */
	Word	ch_dlflags;		/* dldump() flags used */
	Word	ch_app;			/* application that this config file */
					/*	is specific to */
	Word	ch_hash;		/* hash table offset */
	Word	ch_obj;			/* object table offset */
	Word	ch_str;			/* string table offset */
	Word	ch_file;		/* file entries */
	Word	ch_dir;			/* directory entries */
	Word	ch_edlibpath;		/* ELF default library path offset */
	Word	ch_adlibpath;		/* AOUT default library path offset */
	Word	ch_eslibpath;		/* ELF secure library path offset */
	Word	ch_aslibpath;		/* AOUT secure library path offset */
	Lword	ch_resbgn;		/* memory reservation required to map */
	Lword	ch_resend;		/*	alternative objects defined */
					/*	by the configuration info */
	Word	ch_env;			/* environment variables */
	Word	ch_fltr;		/* filter table entries */
	Word	ch_flte;		/* filtee table entries */
} Rtc_head;

#define	RTC_HDR_IGNORE	0x0001		/* ignore config information */
#define	RTC_HDR_ALTER	0x0002		/* alternative objects are defined - */
					/*	these may exist without a */
					/*	memory reservation (see -a) */
#define	RTC_HDR_64	0x0004		/* 64-bit objects used */
#define	RTC_HDR_UPM	0x0008		/* includes unified process model */

/*
 * Object descriptor.
 */
typedef struct {
	Lword	co_info;		/* validation information */
	Word	co_name;		/* object name (directory or file) */
	Word	co_hash;		/* name hash value */
	Half	co_id;			/* directory identifier */
	Half	co_flags;		/* various flags */
	Word	co_alter;		/* alternative object file */
} Rtc_obj;

#define	RTC_OBJ_DIRENT	0x0001		/* object defines a directory */
#define	RTC_OBJ_ALLENTS	0x0002		/* directory was scanned for all */
					/*	containing objects */
#define	RTC_OBJ_NOEXIST	0x0004		/* object does not exist */
#define	RTC_OBJ_EXEC	0x0008		/* object identifies executable */
#define	RTC_OBJ_ALTER	0x0010		/* object has an alternate */
#define	RTC_OBJ_DUMP	0x0020		/* alternate created by dldump(3C) */
#define	RTC_OBJ_REALPTH	0x0040		/* object identifies real path */
#define	RTC_OBJ_NOALTER	0x0080		/* object can't have an alternate */
#define	RTC_OBJ_GROUP	0x0100		/* object was expanded as a group */
#define	RTC_OBJ_APP	0x0200		/* object indicates app which makes */
					/*	configuration file specific */
#define	RTC_OBJ_CMDLINE	0x0400		/* object specified from command line */
#define	RTC_OBJ_FILTER	0x0800		/* object identifies a filter */
#define	RTC_OBJ_FILTEE	0x1000		/* object identifies a filtee */
#define	RTC_OBJ_OPTINAL	0x2000		/* object alternative is optional */

/*
 * Directory and file descriptors.  The configuration cache (cd_dir) points to
 * an array of directory descriptors, this in turn point to their associated
 * arrays of file descriptors.  Both of these provide sequential access for
 * configuration file validation (directory, and possible file stat()'s).
 */
typedef struct {
	Word	cd_obj;			/* index to Rtc_obj */
	Word	cd_file;		/* index to Rtc_file[] */
} Rtc_dir;

typedef	struct {
	Word	cf_obj;			/* index to Rtc_obj */
} Rtc_file;


#define	RTC_VER_NONE	0
#define	RTC_VER_ONE	1		/* original version */
#define	RTC_VER_TWO	2		/* updated for -u use */
#define	RTC_VER_THREE	3		/* updated for -e/-E use */
#define	RTC_VER_FOUR	4		/* updated for filter/filtees */
#define	RTC_VER_CURRENT RTC_VER_FOUR
#define	RTC_VER_NUM	5

/*
 * Environment variable descriptor.  The configuration cache (ch_env) points to
 * an array of these descriptors.
 */
typedef struct {
	Word	env_str;		/* index into string table */
	Word	env_flags;		/* various flags */
} Rtc_env;

#define	RTC_ENV_REPLACE	0x0001		/* replaceable string definition */
#define	RTC_ENV_PERMANT	0x0002		/* permanent string definition */
#define	RTC_ENV_CONFIG	0x1000		/* string originates from config file */

/*
 * Filter descriptor.  The configuration cache (ch_flt) points to an array of
 * these descriptors.
 */
typedef struct {
	Word	fr_filter;		/* filter name, and filtee string */
	Word	fr_string;		/*	as indexs into string table */
	Word	fr_filtee;		/* index into filtee array */
} Rtc_fltr;

typedef struct {
	Word	fe_filtee;
} Rtc_flte;

#ifdef	__cplusplus
}
#endif

#endif	/* _RTC_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2017, Joyent, Inc.
 * Copyright 2022 Oxide Computer Company
 */
#ifndef	_RTLD_H
#define	_RTLD_H

/*
 * Global include file for the runtime linker.
 */
#include <sys/mman.h>
#include <time.h>
#include <sgs.h>
#include <thread.h>
#include <synch.h>
#include <link.h>
#include <sys/avl.h>
#include <alist.h>
#include <libc_int.h>
#include <elfcap.h>

#ifdef	_SYSCALL32
#include <inttypes.h>
#endif

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * We use rtld_ino_t instead of ino_t so that we can get
 * access to large inode values from 32-bit code.
 */
#ifdef _LP64
typedef ino_t		rtld_ino_t;
#else
typedef ino64_t		rtld_ino_t;
#endif

typedef struct rt_map	Rt_map;
typedef struct slookup	Slookup;
typedef struct sresult	Sresult;

/*
 * A binding descriptor.  Establishes the binding relationship between two
 * objects, the caller (originator) and the dependency (destination).
 *
 * Every relationship between two objects is tracked by a binding descriptor.
 * This descriptor is referenced from a link-map's DEPENDS and CALLERS lists.
 * Note, Aplist's are diagramed to fully expose the allocations required to
 * establish the data structure relationships.
 *
 *                                  Bnd_desc
 *                                 ----------
 *                    ------------| b_caller |
 *                   |            | b_depend | ----------
 *                   |            |          |           |
 *      Rt_map       |             ----------            |       Rt_map
 *    ----------     |                ^ ^                |     ----------
 *   |          | <--                 | |                 --> |          |
 *   |          |        --------     | |                     |          |
 *   | DEPENDS  | ----> |        |    | |     --------        |          |
 *   |          |       |        |    | |    |        | <---- | CALLERS  |
 *   |          |       |        | ---  |    |        |       |          |
 *   |          |       |        |       --- |        |       |          |
 *   |          |        --------            |        |       |          |
 *    ----------          Aplist              --------         ----------
 *                                             Aplist
 */
typedef struct {
	Rt_map		*b_caller;	/* caller (originator) of a binding */
	Rt_map		*b_depend;	/* dependency (destination) of a */
					/*	binding */
	uint_t		b_flags;	/* relationship of caller to the */
					/*	dependency */
} Bnd_desc;

#define	BND_NEEDED	0x0001		/* caller NEEDED the dependency */
#define	BND_REFER	0x0002		/* caller relocation references the */
					/*	dependency */
#define	BND_FILTER	0x0004		/* binding identifies filter, used */
					/*	for diagnostics only */
/*
 * Private structure for communication between rtld_db and rtld.
 *
 * We must bump the version number when ever an update in one of the
 * structures/fields that rtld_db reads is updated.  This hopefully permits
 * rtld_db implementations of the future to recognize core files produced on
 * older systems and deal with these core files accordingly.
 *
 * As of version 'R_RTLDDB_VERSION <= 2' the following fields were valid for
 * core file examination (basically the public Link_map):
 *
 *		ADDR()
 *		NAME()
 *		DYN()
 *		NEXT()
 *		PREV()
 *
 * Valid fields for R_RTLDDB_VERSION3
 *
 *		PATHNAME()
 *		PADSTART()
 *		PADIMLEN()
 *		MSIZE()
 *		FLAGS()
 *		FLAGS1()
 *
 * Valid fields for R_RTLDDB_VERSION4
 *
 *		TLSMODID()
 *
 * Valid fields for R_RTLDDB_VERSION5
 *
 *		Added rtld_flags & FLG_RT_RELOCED to stable flags range
 *
 * Valid fields for R_RTLDDB_VERSION6
 *
 *		rtd_dynlmlst converted from a List to APlist
 */
#define	R_RTLDDB_VERSION1	1	/* base version level - used for core */
					/*	file examination */
#define	R_RTLDDB_VERSION2	2	/* minor revision - not relevant for */
					/*	core files */
#define	R_RTLDDB_VERSION3	3
#define	R_RTLDDB_VERSION4	4
#define	R_RTLDDB_VERSION5	5
#define	R_RTLDDB_VERSION6	6
#define	R_RTLDDB_VERSION	R_RTLDDB_VERSION6	/* current version */

typedef struct rtld_db_priv {
	struct r_debug	rtd_rdebug;	/* original r_debug structure */
	Word		rtd_version;	/* version no. */
	size_t		rtd_objpad;	/* padding around mmap()ed objects */
	APlist		**rtd_dynlmlst;	/* pointer to dynlm_list pointer */
} Rtld_db_priv;

#ifdef _SYSCALL32
typedef struct rtld_db_priv32 {
	struct r_debug32 rtd_rdebug;	/* original r_debug structure */
	Elf32_Word	rtd_version;	/* version no. */
	Elf32_Word	rtd_objpad;	/* padding around mmap()ed objects */
	Elf32_Addr	rtd_dynlmlst;	/* pointer to dynlm_list */
} Rtld_db_priv32;
#endif	/* _SYSCALL32 */

/*
 * External function definitions.  ld.so.1 must convey information to libc in
 * regards to threading.  libc also provides routines for atexit() and message
 * localization.  libc provides the necessary interfaces via its RTLDINFO
 * structure and/or later _ld_libc() calls.
 *
 * These external functions are maintained for each link-map list, and used
 * where appropriate.  The functions are associated with the object that
 * provided them, so that should the object be deleted (say, from an alternative
 * link-map), the functions can be removed.
 */
typedef struct {
	Rt_map	*lc_lmp;			/* function provider */
	union {
		int		(*lc_func)();	/* external function pointer */
		uintptr_t	lc_val;		/* external value */
		char		*lc_ptr;	/* external character pointer */
	} lc_un;
} Lc_desc;

/*
 * Link map list definition.  Link-maps are used to describe each loaded object.
 * Lists of these link-maps describe the various namespaces within a process.
 * The process executable and its dependencies are maintained on the lml_main
 * list.  The runtime linker, and its dependencies are maintained on the
 * lml_rtld list.  Additional lists can be created (see dlmopen()) for such
 * things as auditors and their dependencies.
 *
 * Each link-map list maintains an Alist of one, or more, linked lists of
 * link-maps.  For backward compatibility, the lm_head/lm_tail elements are
 * initialized to the first linked-list of link-maps:
 *
 *      Lm_list
 *    ----------
 *   | lm_tail  | ------------------------------------
 *   | lm_head  | --------------------                |
 *   |          |                     |     Rt_map    |     Rt_map
 *   |          |                     |     ------    |     ------
 *   |          |          Alist       --> |      |   |--> |      |
 *   |          |        ---------    |    |      | --     |      |
 *   | lm_lists | ----> |         |   |    |      |    --> |      |
 *   |          |       |---------|   |    |      |   |    |      |
 *   |          |       | lc_head | --      ------    |     ------
 *   |          |       | lc_tail | ------------------
 *   |          |       |---------|
 *    ----------        | lc_head |
 *                      | lc_tail |
 *                      |---------|
 *
 * Multiple link-map lists exist to support the addition of lazy loaded
 * families, filtee families, and dlopen() families.  The intent of these
 * lists is to insure that a family of objects that are to be loaded are
 * fully relocatable, and hence usable, before they become part of the main
 * (al_data[0]) link-map control list.  This main link-map control list is
 * the only list in existence when control is transferred to user code.
 *
 * During process initialization, the dynamic executable and its non-lazy
 * dependencies are maintained on al_data[0].  If a new object is loaded, then
 * this object is added to the next available control list [1], typically
 * al_data[1].  Any dependencies of this object that have not already been
 * loaded are added to the same control list.  Once all of the objects on the
 * new control list have been successfully relocated, the objects are moved from
 * the new control list to the highest control list to which objects of the new
 * control list bound to, typically al_data[1] to al_data[0].
 *
 * Each loading scenario can be broken down as follows:
 *
 *  setup() - only the initial link-map control list is used:
 *   i.	  create al_data[0]
 *   ii.  add new link-map for main on al_data[0]
 *   iii. analyze al_data[0] to add all non-lazy dependencies
 *   iv.  relocate al_data[0] dependencies.
 *
 *  dlopen() - the initiator can only be the initial link-map control list:
 *   i.   create al_data[1] from caller al_data[0]
 *   ii.  add new link-map for the dlopen'ed object on al_data[1]
 *   iii. analyze al_data[1] to add all non-lazy dependencies
 *   iv.  relocate al_data[1] dependencies, and move to al_data[0].
 *
 *  filtee and lazy loading processing - the initiator can be any link-map
 *  control list that is being relocated:
 *   i.   create al_data[y] from caller al_data[x]
 *   ii.  add new link-map for the new object on al_data[y]
 *   iii. analyze al_data[y] to add all non-lazy dependencies
 *   iv.  relocate al_data[y] dependencies, and move to al_data[x].
 *
 * This Alist therefore maintains a stack of link-map control lists.  The newest
 * link-map control list can locate symbols within any of the former lists,
 * however, control is not passed to a former list until the newest lists
 * processing is complete.  Thus, objects can't bind to new objects until they
 * have been fully analyzed and relocated.
 *
 * [1]  Note, additional link-map control list creation occurs after the head
 * link-map object (typically the dynamic executable) has been relocated.  This
 * staging is required to satisfy the binding requirements of copy relocations.
 * Copy relocations, effectively, transfer the bindings of the copied data
 * (say _iob in libc.so.1) to the copy location (_iob in the application).
 * Thus an object that might bind to the original copy data must be redirected
 * to the copy reference.  As the knowledge of a copy relocation having taken
 * place is only known after relocating the application, link-map control list
 * additions are suspended until after this relocation has completed.
 */
typedef struct {
	Rt_map		*lc_head;
	Rt_map		*lc_tail;
	APlist		*lc_now;	/* pending promoted bind-now objects */
	uint_t		lc_flags;
} Lm_cntl;

#define	LMC_FLG_ANALYZING	0x01	/* control list is being analyzed */
#define	LMC_FLG_RELOCATING	0x02	/* control list is being relocated */
#define	LMC_FLG_REANALYZE	0x04	/* repeat analysis (established when */
					/*	interposers are added */

struct lm_list {
	/*
	 * BEGIN: Exposed to rtld_db - don't move, don't delete
	 */
	Rt_map		*lm_head;	/* linked list pointers to active */
	Rt_map		*lm_tail;	/*	link-map list */
	APlist		*lm_handle;	/* not used by rtld_db - but spacing */
					/*	is required for flags */
	Word		lm_flags;
	/*
	 * END: Exposed to rtld_db - don't move, don't delete
	 */
	Alist		*lm_rti;	/* list of RTLDINFO tables */
	Audit_list	*lm_alp;	/* audit list descriptor */
	avl_tree_t	*lm_fpavl;	/* avl tree of objects loaded */
	Alist		*lm_lists;	/* active and pending link-map lists */
	char		***lm_environ;	/* pointer to environment array */
	Word		lm_tflags;	/* transferable flags */
	uint_t		lm_obj;		/* total number of objs on link-map */
	uint_t		lm_init;	/* new obj since last init processing */
	uint_t		lm_lazy;	/* number of objects with pending */
					/*	lazy dependencies */
	uint_t		lm_tls;		/* new obj that require TLS */
	uint_t		lm_lmid;	/* unique link-map list identifier, */
	char		*lm_lmidstr;	/* and associated diagnostic string */
	Alist		*lm_aud_cookies; /* local auditor cookies */
	Lc_desc		lm_lcs[CI_MAX];	/* external libc functions */
};

#ifdef	_SYSCALL32
struct lm_list32 {
	/*
	 * BEGIN: Exposed to rtld_db - don't move, don't delete
	 */
	Elf32_Addr	lm_head;
	Elf32_Addr	lm_tail;
	Elf32_Addr	lm_handle;
	Elf32_Word	lm_flags;
	/*
	 * END: Exposed to rtld_db - don't move, don't delete
	 */
	Elf32_Addr	lm_rti;
	Elf32_Addr	lm_fpavl;
	Elf32_Addr	lm_lists;
	Elf32_Addr	lm_environ;
	Elf32_Word	lm_tflags;
	uint_t		lm_obj;
	uint_t		lm_init;
	uint_t		lm_lazy;
	uint_t		lm_tls;
	uint_t		lm_lmid;
	Elf32_Addr	lm_lmidstr;
	Elf32_Addr	lm_aud_cookies;
	Elf32_Addr	lm_lcs[CI_MAX];
};
#endif /* _SYSCALL32 */

/*
 * Possible Link_map list flags (Lm_list.lm_flags)
 */
/*
 * BEGIN: Exposed to rtld_db - don't move, don't delete
 */
#define	LML_FLG_BASELM		0x00000001	/* primary link-map */
#define	LML_FLG_RTLDLM		0x00000002	/* rtld link-map */
/*
 * END: Exposed to rtld_db - don't move, don't delete
 */
#define	LML_FLG_ACTAUDIT	0x00000004	/* audit activity posted */
#define	LML_FLG_PLTREL		0x00000008	/* deferred plt relocation */
						/*    initialization (ld.so.1 */
						/*    only) */
#define	LML_FLG_HOLDLOCK	0x00000010	/* hold the rtld mutex lock */
#define	LML_FLG_ENVIRON		0x00000020	/* environ var initialized */
#define	LML_FLG_INTRPOSE	0x00000040	/* interposing objs on list */
#define	LML_FLG_LOCAUDIT	0x00000080	/* local auditors exists for */
						/*    this link-map list */
#define	LML_FLG_LOADAVAIL	0x00000100	/* load anything available */
#define	LML_FLG_IGNRELERR	0x00000200	/* ignore relocation errors - */
						/*    internal for crle(1) */
#define	LML_FLG_STARTREL	0x00000400	/* relocation started */
#define	LML_FLG_ATEXIT		0x00000800	/* atexit processing */
#define	LML_FLG_OBJADDED	0x00001000	/* object(s) added */
#define	LML_FLG_OBJDELETED	0x00002000	/* object(s) deleted */
#define	LML_FLG_OBJREEVAL	0x00004000	/* existing object(s) needs */
						/*    tsort reevaluation */
#define	LML_FLG_INTRPOSETSORT	0x00008000	/* interpose tsorting done */
#define	LML_FLG_AUDITNOTIFY	0x00010000	/* audit consistent required */
#define	LML_FLG_GROUPSEXIST	0x00020000	/* local groups exist */

#define	LML_FLG_TRC_LDDSTUB	0x00100000	/* identify lddstub */
#define	LML_FLG_TRC_ENABLE	0x00200000	/* tracing enabled (ldd) */
#define	LML_FLG_TRC_WARN	0x00400000	/* print warnings for undefs */
#define	LML_FLG_TRC_VERBOSE	0x00800000	/* verbose (versioning) trace */
#define	LML_FLG_TRC_SEARCH	0x01000000	/* trace search paths */
#define	LML_FLG_TRC_UNREF	0x02000000	/* trace unreferenced */
						/*    dependencies */
#define	LML_FLG_TRC_UNUSED	0x04000000	/* trace unused dependencies */
#define	LML_FLG_TRC_INIT	0x08000000	/* print .init order */
#define	LML_FLG_TRC_NOUNRESWEAK	0x10000000	/* unresolved weak references */
						/*    are not allowed */
#define	LML_FLG_TRC_NOPAREXT	0x20000000	/* unresolved PARENT/EXTERN */
						/*    references are not */
						/*    allowed */
#define	LML_MSK_TRC		0xfff00000	/* tracing mask */

/*
 * Possible Link_map transferable flags (Lm_list.lm_tflags), i.e., link-map
 * list flags that can be propagated to any new link-map list created.
 */
#define	LML_TFLG_NOLAZYLD	0x00000001	/* lazy loading disabled */
#define	LML_TFLG_NODIRECT	0x00000002	/* direct bindings disabled */
#define	LML_TFLG_NOAUDIT	0x00000004	/* auditing disabled */
#define	LML_TFLG_LOADFLTR	0x00000008	/* trigger filtee loading */

#define	LML_TFLG_AUD_PREINIT	0x00001000	/* preinit (audit) exists */
#define	LML_TFLG_AUD_OBJSEARCH	0x00002000	/* objsearch (audit) exists */
#define	LML_TFLG_AUD_OBJOPEN	0x00004000	/* objopen (audit) exists */
#define	LML_TFLG_AUD_OBJFILTER	0x00008000	/* objfilter (audit) exists */
#define	LML_TFLG_AUD_OBJCLOSE	0x00010000	/* objclose (audit) exists */
#define	LML_TFLG_AUD_SYMBIND	0x00020000	/* symbind (audit) exists */
#define	LML_TFLG_AUD_PLTENTER	0x00040000	/* pltenter (audit) exists */
#define	LML_TFLG_AUD_PLTEXIT	0x00080000	/* pltexit (audit) exists */
#define	LML_TFLG_AUD_ACTIVITY	0x00100000	/* activity (audit) exists */

/*
 * NOTE: Each auditing module establishes a set of audit flags, AFLAGS(), that
 * define the auditing interfaces the module offers.  These auditing flags are
 * the LML_TFLG_AUD_ flags defined above.  Global auditors result in setting
 * the lm_tflags too.  Local auditors only use the AFLAGS().  All tests for
 * auditing inspect the lm_tflags and AFLAGS() for a specific auditing
 * interface, and thus use the same flag to test for both types of auditors.
 */
#define	LML_TFLG_AUD_MASK	0x0ffff000	/* audit interfaces mask */

/*
 * Define a Group Handle.
 *
 * The capability of ld.so.1 to associate a group of objects, look for symbols
 * within that group, ensure that groups are isolated from one another (with
 * regard to relocations), and to unload a group, centers around a handle.
 *
 * Dependencies can be added to an existing handle as the dependencies are
 * lazily loaded.  The core dependencies on the handle are the ldd(1) list of
 * the referenced object.
 *
 * Handles can be created from:
 *
 *  -	a dlopen() request.  This associates a caller to a reference object,
 *	and the referenced objects dependencies.  This group of objects can
 *	then be inspected for symbols (dlsym()).
 *  -	a filtering request.  This associates a filter (caller) to a referenced
 *	object (filtee).  The redirection of filter symbols to their filtee
 *	counterpart is essentially a dlsym() using the filtee's handle.
 *
 * The handle created for these events is referred to as a public handle.  This
 * handle tracks the referenced object, all of the dependencies of the
 * referenced object, and the caller (parent).
 *
 * Presently, an object may have two handles, one requested with RTLD_FIRST
 * and one without.
 *
 * A handle may be referenced by any number of callers (parents).  A reference
 * count tracks the number.  A dlclose() operation drops the reference count,
 * and when the count is zero, the handle is used to determine the family of
 * objects to unload.  As bindings may occur to objects on the handle from
 * other handles, it may not be possible to remove a complete family of objects
 * or the handle itself.  Handles in this state are moved to an orphan list.
 * A handle on the orphan list is taken off the orphan list if the associated
 * object is reopened.  Otherwise, the handle remains on the orphan list for
 * the duration of the process.  The orphan list is inspected any time objects
 * are unloaded, to determine if the orphaned objects can also be unloaded.
 *
 * Handles can also be created for internal uses:
 *
 *  -	to promote objects to RTLD_NOW.
 *  -	to establish families for symbol binding fallback, required when lazy
 *	loadable objects are still pending.
 *
 * The handle created for these events is referred to as a private handle.  This
 * handle does not need to track the caller (parent), and because of this, does
 * not need to be considered during dlclose() operations, as the handle can not
 * be referenced by callers outside of the referenced objects family.
 *
 * Note, a private handle is essentially a subset of a public handle.  Should
 * an internal operation require a private handle, and a public handle already
 * exist, the public handle can be used.  Should an external operation require
 * a public handle, and a private handle exist, the private handle is promoted
 * to a public handle.  Any handle that gets created will remain in existence
 * for the life time of the referenced object.
 *
 * Objects can be dlopened using RTLD_NOW.  This attribute requires that all
 * relocations of the object, and its dependencies are processed immediately,
 * before return to the caller.  Typically, an object is loaded without
 * RTLD_NOW, and procedure linkage relocations are satisfied when their
 * associated function is first called.  If an object is already loaded, and an
 * RTLD_NOW request is made, then the object, and its dependencies, most undergo
 * additional relocation processing.   This promotion from lazy binding to
 * immediate binding is carried out using handles, as the handle defines the
 * dependencies that must be processed.
 *
 * To ensure that objects within a lazy loadable environment can be relocated,
 * no matter whether the objects have their dependencies described completely,
 * a symbol lookup fallback is employed.  Any pending lazy loadable objects are
 * loaded, and a handle established to search the object and it's dependencies
 * for the required symbol.
 *
 * A group handle (and its associated group descriptors), is referenced from
 * a link-map's HANDLES and GROUPS lists.  Note, Aplist's are diagramed to
 * fully expose the allocations required to establish the data structure
 * relationships.
 *
 *                                  Grp_desc
 *                                   Alist
 *                                 -----------
 *                            --> |           |
 *                           |    |-----------|
 *                           |    | gd_depend | ---------
 *                           |    |           |          |
 *                           |    |-----------|          |
 *                   --------|--- | gd_depend |          |
 *                  |        |    | (parent)  |          |
 *                  |        |    |-----------|          |
 *                  |        |    | gd_depend |          |
 *                  |        |    |           |          |
 *                  |        |    |           |          |
 *                  |        |     -----------           |
 *                  |        |                           |
 *                  |        |      Grp_hdl              |
 *                  |        |    -----------            |
 *                  |         -- | gh_depends |          |
 *                  |  --------- | gh_ownlmp  |          |
 *                  | |          |            |          |
 *                  | |          |            |          |
 *                  | |          |            |          |
 *      Rt_map      | |           ------------           |       Rt_map
 *    ----------    | |               ^ ^                |     ----------
 *   |          | <-  |               | |                 --> |          |
 *   |          | <---   --------     | |                     |          |
 *   | HANDLES  | ----> |        |    | |     --------        |          |
 *   |          |       |        |    | |    |        | <---- |  GROUPS  |
 *   |          |       |        | ---  |    |        |       |          |
 *   |          |       |        |       --- |        |       |          |
 *   |          |        --------            |        |       |          |
 *    ----------          Aplist              --------         ----------
 *                                             Aplist
 */
typedef struct {
	Alist		*gh_depends;	/* handle dependency list */
	Rt_map		*gh_ownlmp;	/* handle owners link-map */
	Lm_list		*gh_ownlml;	/* handle owners link-map list */
	uint_t		gh_refcnt;	/* handle reference count */
	uint_t		gh_flags;	/* handle flags (GPH_ values) */
} Grp_hdl;

/*
 * Define the two categories of handle.
 */
#define	GPH_PUBLIC	0x0001		/* handle returned to caller(s) */
#define	GPH_PRIVATE	0x0002		/* handle used internally */

/*
 * Define any flags that affects how the handle is used.
 */
#define	GPH_ZERO	0x0010		/* special handle for dlopen(0) */
#define	GPH_LDSO	0x0020		/* special handle for ld.so.1 */
#define	GPH_FIRST	0x0040		/* dlsym() can only use originating */
					/*	dependency */
#define	GPH_FILTEE	0x0080		/* handle identifies a filtee, used */
					/*	for diagnostics only */
/*
 * Define any state that is associated with the handle.
 */
#define	GPH_INITIAL	0x0100		/* handle is initialized */

/*
 * Define a Group Descriptor.
 *
 * Each dependency associated with a group handle is maintained by a group
 * descriptor.  The descriptor defines the associated dependency together with
 * flags that indicate how the dependency can be used.
 */
typedef struct {
	Rt_map		*gd_depend;	/* dependency */
	uint_t		gd_flags;	/* dependency flags (GPD_ values) */
} Grp_desc;

#define	GPD_DLSYM	0x0001		/* dependency available to dlsym() */
#define	GPD_RELOC	0x0002		/* dependency available to satisfy */
					/*	relocation binding */
#define	GPD_ADDEPS	0x0004		/* dependencies of this dependency */
					/*	should be added to handle */
#define	GPD_PARENT	0x0008		/* dependency is a parent */
#define	GPD_FILTER	0x0010		/* dependency is our filter */
#define	GPD_REMOVE	0x0100		/* descriptor is a candidate for */
					/*	removal from the group */

/*
 * Define threading structures.  For compatibility with libthread (T1_VERSION 1
 * and TI_VERSION 2) our locking structure is sufficient to hold a mutex or a
 * readers/writers lock.
 */
typedef struct {
	union {
		mutex_t		l_mutex;
		rwlock_t	l_rwlock;
	} u;
} Rt_lock;

typedef	cond_t	Rt_cond;

/*
 * Define a dynamic section information descriptor.  This parallels the entries
 * in the .dynamic section and holds auxiliary information to implement lazy
 * loading and filtee processing.
 */
typedef struct {
	uint_t		di_flags;
	void		*di_info;
	const char	*di_name;
} Dyninfo;

#define	FLG_DI_STDFLTR	0x00001		/* .dynamic entry for DT_FILTER */
#define	FLG_DI_AUXFLTR	0x00002		/* .dynamic entry for DT_AUXILIARY */
#define	FLG_DI_SYMFLTR	0x00004		/* .dynamic entry for DT_SYMFILTER */
					/*	and DT_SYMAUXILIARY */
#define	MSK_DI_FILTER	0x0000f		/* mask for all filter possibilities */

#define	FLG_DI_POSFLAG1	0x00010		/* .dynamic entry for DT_POSFLAG_1 */
#define	FLG_DI_NEEDED	0x00020		/* .dynamic entry for DT_NEEDED */
#define	FLG_DI_REGISTER	0x00040		/* .dynamic entry for DT_REGISTER */
#define	FLG_DI_IGNORE	0x00080		/* .dynamic entry should be ignored */

#define	FLG_DI_LAZY	0x00100		/* lazy needed entry, preceded by */
					/*    DF_P1_LAZYLOAD (DT_POSFLAG_1) */
#define	FLG_DI_GROUP	0x00200		/* group needed entry, preceded by */
					/*    DF_P1_GROUPPERM (DT_POSFLAG_1) */
#define	FLG_DI_DEFERRED	0x00400		/* deferred needed entry, preceded by */
					/*    DF_P1_DEFERRED (DT_POSFLAG_1) */

#define	FLG_DI_LAZYFAIL	0x01000		/* the lazy loading of this entry */
					/*    failed */
#define	FLG_DI_LDD_DONE	0x02000		/* entry has been processed (ldd) */
#define	FLG_DI_DEF_DONE	0x04000		/* entry has been processed (dlinfo) */

/*
 * Data structure to track AVL tree of pathnames.  This structure provides the
 * basis of both the "not-found" node tree, and the "full-path" node tree.  Both
 * of these trees persist for the life of a process, although the "not-found"
 * tree may be moved aside during a dlopen() or dlsym() fall back operation.
 */
typedef struct {
	const char	*pn_name;	/* path name */
	avl_node_t	pn_avl;		/* avl book-keeping (see SGSOFFSETOF) */
	uint_t		pn_hash;	/* path name hash value */
} PathNode;

/*
 * Data structure to track AVL tree for full path names of objects that are
 * loaded into memory.
 */
typedef struct {
	PathNode	fpn_node;	/* path node */
	Rt_map		*fpn_lmp;	/* object link-map */
} FullPathNode;

/*
 * A given link-map can hold either a supplier or receiver copy
 * relocation list, but not both. This union is used to overlap
 * the space used for the two lists.
 */
typedef union {
	Alist	*rtc_r;		/* receiver list (Rel_copy) */
	APlist	*rtc_s;		/* supplier list (Rt_map *) */
} Rt_map_copy;


/*
 * Link-map definition.
 */
struct rt_map {
	/*
	 * BEGIN: Exposed to rtld_db - don't move, don't delete
	 */
	Link_map	rt_public;	/* public data */
	const char	*rt_pathname;	/* full pathname of loaded object */
	ulong_t		rt_padstart;	/* start of image (including padding) */
	ulong_t		rt_padimlen;	/* size of image (including padding */
	ulong_t		rt_msize;	/* total memory reservation range */
	uint_t		rt_flags;	/* state flags, see FLG below */
	uint_t		rt_flags1;	/* state flags1, see FL1 below */
	ulong_t		rt_tlsmodid;	/* TLS module id */
	/*
	 * END: Exposed to rtld_db - don't move, don't delete
	 */
	APlist		*rt_alias;	/* list of linked file names */
	APlist		*rt_fpnode;	/* list of FullPathNode AVL nodes */
	char		*rt_runpath;	/* LD_RUN_PATH and its equivalent */
	Alist		*rt_runlist;	/*	Pdesc structures */
	APlist		*rt_depends;	/* list of dependencies */
	APlist		*rt_callers;	/* list of callers */
	APlist		*rt_handles;	/* dlopen handles */
	APlist		*rt_groups;	/* groups we're a member of */
	struct fct	*rt_fct;	/* file class table for this object */
	void		*rt_priv;	/* private data, object type specific */
	Lm_list		*rt_list;	/* link map list we belong to */
	uint_t		rt_objfltrndx;	/* object filtees .dynamic index */
	uint_t		rt_symsfltrcnt;	/* number of standard symbol filtees */
	uint_t		rt_symafltrcnt;	/* number of auxiliary symbol filtees */
	int		rt_mode;	/* usage mode, see RTLD mode flags */
	int		rt_sortval;	/* temporary buffer to traverse graph */
	uint_t		rt_cycgroup;	/* cyclic group */
	dev_t		rt_stdev;	/* device id and inode number for .so */
	rtld_ino_t	rt_stino;	/*	multiple inclusion checks */
	const char	*rt_origname;	/* original pathname of loaded object */
	size_t		rt_dirsz;	/*	and its size */
	size_t		rt_lmsize;	/* size of the link-map allocation */
	Rt_map_copy	rt_copy;	/* list of copy relocations */
	Audit_desc	*rt_auditors;	/* audit descriptor array */
	Audit_info	*rt_audinfo;	/* audit information descriptor */
	Syminfo		*rt_syminfo;	/* elf .syminfo section - here */
					/*	because it is checked in */
					/*	common code */
	Addr		*rt_initarray;	/* .init_array table */
	Addr		*rt_finiarray;	/* .fini_array table */
	Addr		*rt_preinitarray; /* .preinit_array table */
	mmapobj_result_t *rt_mmaps;	/* array of mapping information */
	uint_t		rt_mmapcnt;	/*	and associated number */
	uint_t		rt_initarraysz;	/* size of .init_array table */
	uint_t		rt_finiarraysz;	/* size of .fini_array table */
	uint_t		rt_preinitarraysz; /* size of .preinit_array table */
	Dyninfo		*rt_dyninfo;	/* .dynamic information descriptors */
	uint_t		rt_dyninfocnt;	/* count of dyninfo entries */
	uint_t		rt_relacount;	/* no. of RELATIVE relocations */
	uint_t		rt_idx;		/* hold index within linkmap list */
	uint_t		rt_lazy;	/* number of lazy dependencies */
					/*	pending */
	Cap		*rt_cap;	/* capabilities data */
	Capchain	*rt_capchain;	/* capabilities chain data */
	uint_t		rt_cntl;	/* link-map control list we belong to */
	uint_t		rt_aflags;	/* auditor flags, see LML_TFLG_AUD_ */
	Rt_cond		rt_cv;		/* for waiting on flags changes */
	Rt_lock		rt_lock;	/* for coordinating flags changes */
					/* address of _init */
	thread_t	rt_init_thread;	/* thread id in this lm's _init */
	void		(*rt_init)(void);
					/* address of _fini */
	void		(*rt_fini)(void);
					/* link map symbol interpreter */
	int		(*rt_symintp)(Slookup *, Sresult *, uint_t *, int *);
};

#ifdef _SYSCALL32
/*
 * Structure to allow 64-bit rtld_db to read 32-bit processes out of procfs.
 */
typedef union {
	uint32_t	rtc_r;
	uint32_t	rtc_s;
} Rt_map_copy32;

typedef struct rt_map32 {
	/*
	 * BEGIN: Exposed to rtld_db - don't move, don't delete
	 */
	Link_map32	rt_public;
	uint32_t	rt_pathname;
	uint32_t	rt_padstart;
	uint32_t	rt_padimlen;
	uint32_t	rt_msize;
	uint32_t	rt_flags;
	uint32_t	rt_flags1;
	uint32_t	rt_tlsmodid;
	/*
	 * END: Exposed to rtld_db - don't move, don't delete
	 */
	uint32_t	rt_alias;
	uint32_t	rt_fpnode;
	uint32_t	rt_runpath;
	uint32_t	rt_runlist;
	uint32_t	rt_depends;
	uint32_t	rt_callers;
	uint32_t	rt_handles;
	uint32_t	rt_groups;
	uint32_t	rt_fct;
	uint32_t	rt_priv;
	uint32_t	rt_list;
	uint32_t	rt_objfltrndx;
	uint32_t	rt_symsfltrcnt;
	uint32_t	rt_symafltrcnt;
	int32_t		rt_mode;
	int32_t		rt_sortval;
	uint32_t	rt_cycgroup;
	uint32_t	rt_stdev;
	uint32_t	rt_stino;
	uint32_t	rt_origname;
	uint32_t	rt_dirsz;
	Rt_map_copy32	rt_copy;
	uint32_t	rt_auditors;
	uint32_t	rt_audinfo;
	uint32_t	rt_syminfo;
	uint32_t	rt_initarray;
	uint32_t	rt_finiarray;
	uint32_t	rt_preinitarray;
	uint32_t	rt_mmaps;
	uint32_t	rt_mmapcnt;
	uint32_t	rt_initarraysz;
	uint32_t	rt_finiarraysz;
	uint32_t	rt_preinitarraysz;
	uint32_t	rt_dyninfo;
	uint32_t	rt_dyninfocnt;
	uint32_t	rt_relacount;
	uint32_t	rt_idx;
	uint32_t	rt_lazy;
	uint32_t	rt_cap;
	uint32_t	rt_capchain;
	uint32_t	rt_cntl;
	uint32_t	rt_aflags;
	uint32_t	rt_init;
	uint32_t	rt_fini;
	uint32_t	rt_symintp;
} Rt_map32;

#endif	/* _SYSCALL32 */

/*
 * Link map state flags.
 */
/*
 * BEGIN: Exposed to rtld_db - don't move, don't delete
 */
#define	FLG_RT_ISMAIN	0x00000001	/* object represents main executable */
#define	FLG_RT_IMGALLOC	0x00000002	/* image is allocated (not mmap'ed) */
	/*
	 * Available for r_debug version >= R_RTLDDB_VERSION5
	 */
#define	FLG_RT_RELOCED	0x00000004	/* object has been relocated */
/*
 * END: Exposed to rtld_db - don't move, don't delete
 */
#define	FLG_RT_SETGROUP	0x00000008	/* group establishment required */
#define	FLG_RT_CAP	0x00000010	/* process $CAPABILITY expansion */
#define	FLG_RT_OBJECT	0x00000020	/* object processing (ie. .o's) */
#define	FLG_RT_NEWLOAD	0x00000040	/* object is newly loaded */
#define	FLG_RT_NODUMP	0x00000080	/* object can't be dldump(3C)'ed */
#define	FLG_RT_DELETE	0x00000100	/* object can be deleted */
#define	FLG_RT_ANALYZED	0x00000200	/* object has been analyzed */
#define	FLG_RT_INITDONE	0x00000400	/* objects .init has been completed */
#define	FLG_RT_TRANS	0x00000800	/* object is acting as a translator */
#define	FLG_RT_FIXED	0x00001000	/* image location is fixed */
#define	FLG_RT_PRELOAD	0x00002000	/* object was preloaded */
#define	FLG_RT_ALTER	0x00004000	/* alternative object used */
#define	FLG_RT_LOADFLTR	0x00008000	/* trigger filtee loading */
#define	FLG_RT_AUDIT	0x00010000	/* object is an auditor */
#define	FLG_RT_MODESET	0x00020000	/* MODE() has been initialized */
#define	FLG_RT_ANALZING	0x00040000	/* object is being analyzed */
#define	FLG_RT_INITFRST 0x00080000	/* execute .init first */
#define	FLG_RT_NOOPEN	0x00100000	/* dlopen() not allowed */
#define	FLG_RT_FINICLCT	0x00200000	/* fini has been collected (tsort) */
#define	FLG_RT_INITCALL	0x00400000	/* objects .init has been called */
#define	FLG_RT_OBJINTPO	0x00800000	/* object is a global interposer */
#define	FLG_RT_SYMINTPO	0x01000000	/* object contains symbol interposer */
#define	MSK_RT_INTPOSE	0x01800000	/* mask for all interposer */
					/*	possibilities */
#define	FLG_RT_MOVE	0x02000000	/* object needs move operation */
#define	FLG_RT_RELOCING	0x04000000	/* object is being relocated */
#define	FLG_RT_REGSYMS	0x08000000	/* object has DT_REGISTER entries */
#define	FLG_RT_INITCLCT	0x10000000	/* init has been collected (tsort) */
#define	FLG_RT_PUBHDL	0x20000000	/* generate a handle for this object */
#define	FLG_RT_PRIHDL	0x40000000	/*	either public or private */

#define	FL1_RT_COPYTOOK	0x00000001	/* copy relocation taken */
#define	FL1_RT_ALTCHECK	0x00000002	/* alternative system capabilities */
					/*	checked */
#define	FL1_RT_ALTCAP	0x00000004	/* alternative system capabilities */
					/*	should be used */
#define	FL1_RT_CONFSET	0x00000008	/* object was loaded by crle(1) */
#define	FL1_RT_NODEFLIB	0x00000010	/* ignore default library search */
#define	FL1_RT_ENDFILTE	0x00000020	/* filtee terminates filters search */
#define	FL1_RT_DISPREL	0x00000040	/* object has *disp* relocation */
#define	FL1_RT_DTFLAGS	0x00000080	/* DT_FLAGS element exists */
#define	FL1_RT_LDDSTUB	0x00000100	/* identify lddstub */
#define	FL1_RT_NOINIFIN	0x00000200	/* no .init or .fini exists */
#define	FL1_RT_USED	0x00000400	/* symbol referenced from this object */
#define	FL1_RT_SYMBOLIC	0x00000800	/* DF_SYMBOLIC was set - use */
					/*	symbolic sym resolution */
#define	FL1_RT_OBJSFLTR	0x00001000	/* object is acting as a standard */
#define	FL1_RT_OBJAFLTR	0x00002000	/*	or auxiliary filter */
#define	FL1_RT_SYMSFLTR	0x00004000	/* symbol is acting as a standard */
#define	FL1_RT_SYMAFLTR	0x00008000	/*	or auxiliary filter */
#define	MSK_RT_FILTER	0x0000f000	/* mask for all filter possibilities */

#define	FL1_RT_TLSADD	0x00010000	/* objects TLS has been registered */
#define	FL1_RT_TLSSTAT	0x00020000	/* object requires static TLS */
#define	FL1_RT_DIRECT	0x00040000	/* object has DIRECT bindings enabled */
#define	FL1_RT_GLOBAUD	0x00080000	/* establish global auditing */
#define	FL1_RT_DEPAUD	0x00100000	/* audit library from DT_DEPAUDIT */

/*
 * Flags for the tls_modactivity() routine
 */
#define	TM_FLG_MODADD	0x01		/* call tls_modadd() interface */
#define	TM_FLG_MODREM	0x02		/* call tls_modrem() interface */

/*
 * Macros for getting to exposed, link_map data (R_RTLDDB_VERSION <= 2).
 */
#define	ADDR(X)		((X)->rt_public.l_addr)
#define	NAME(X)		((X)->rt_public.l_name)
#define	DYN(X)		((X)->rt_public.l_ld)
#define	NEXT(X)		((X)->rt_public.l_next)
#define	PREV(X)		((X)->rt_public.l_prev)
#define	REFNAME(X)	((X)->rt_public.l_refname)

/*
 * An Rt_map starts with a Link_map, followed by other information.
 * ld.so.1 allocates Rt_map structures, and then casts them to Link_map,
 * and back, depending on context.
 *
 * On some platforms, Rt_map can have a higher alignment requirement
 * than Link_map. On such platforms, the cast from Link_map to Rt_map will
 * draw an E_BAD_PTR_CAST_ALIGN warning from lint. Since we allocate
 * the memory as the higher alignment Rt_map, we know that this is a safe
 * conversion. The LINKMAP_TO_RTMAP macro is used to handle the conversion
 * in a manner that satisfies lint.
 */
#ifdef lint
#define	LINKMAP_TO_RTMAP(X)	(Rt_map *)(void *)(X)
#else
#define	LINKMAP_TO_RTMAP(X)	(Rt_map *)(X)
#endif

/*
 * Convenience macros for the common case of using
 * NEXT()/PREV() and casting the result to (Rt_map *)
 */
#define	NEXT_RT_MAP(X)	LINKMAP_TO_RTMAP(NEXT(X))
#define	PREV_RT_MAP(X)	LINKMAP_TO_RTMAP(PREV(X))

/*
 * Macros for getting to exposed, link_map data (R_RTLDDB_VERSION3).
 */
#define	PATHNAME(X)	((X)->rt_pathname)
#define	PADSTART(X)	((X)->rt_padstart)
#define	PADIMLEN(X)	((X)->rt_padimlen)
#define	MSIZE(X)	((X)->rt_msize)
#define	FLAGS(X)	((X)->rt_flags)
#define	FLAGS1(X)	((X)->rt_flags1)

/*
 * Macros for getting to exposed, link_map data (R_RTLDDB_VERSION4).
 */
#define	TLSMODID(X)	((X)->rt_tlsmodid)

/*
 * Macros for getting to unexposed, link-map data.
 */
#define	LMSIZE(X)	((X)->rt_lmsize)
#define	AFLAGS(X)	((X)->rt_aflags)
#define	ALIAS(X)	((X)->rt_alias)
#define	FPNODE(X)	((X)->rt_fpnode)
#define	INIT(X)		((X)->rt_init)
#define	FINI(X)		((X)->rt_fini)
#define	RPATH(X)	((X)->rt_runpath)
#define	RLIST(X)	((X)->rt_runlist)
#define	DEPENDS(X)	((X)->rt_depends)
#define	CALLERS(X)	((X)->rt_callers)
#define	HANDLES(X)	((X)->rt_handles)
#define	GROUPS(X)	((X)->rt_groups)
#define	FCT(X)		((X)->rt_fct)
#define	SYMINTP(X)	((X)->rt_symintp)
#define	LIST(X)		((X)->rt_list)
#define	OBJFLTRNDX(X)	((X)->rt_objfltrndx)
#define	SYMSFLTRCNT(X)	((X)->rt_symsfltrcnt)
#define	SYMAFLTRCNT(X)	((X)->rt_symafltrcnt)
#define	MODE(X)		((X)->rt_mode)
#define	SORTVAL(X)	((X)->rt_sortval)
#define	CYCGROUP(X)	((X)->rt_cycgroup)
#define	STDEV(X)	((X)->rt_stdev)
#define	STINO(X)	((X)->rt_stino)
#define	ORIGNAME(X)	((X)->rt_origname)
#define	DIRSZ(X)	((X)->rt_dirsz)
#define	COPY_R(X)	((X)->rt_copy.rtc_r)
#define	COPY_S(X)	((X)->rt_copy.rtc_s)
#define	AUDITORS(X)	((X)->rt_auditors)
#define	AUDINFO(X)	((X)->rt_audinfo)
#define	SYMINFO(X)	((X)->rt_syminfo)
#define	INITARRAY(X)	((X)->rt_initarray)
#define	FINIARRAY(X)	((X)->rt_finiarray)
#define	PREINITARRAY(X)	((X)->rt_preinitarray)
#define	MMAPS(X)	((X)->rt_mmaps)
#define	MMAPCNT(X)	((X)->rt_mmapcnt)
#define	INITARRAYSZ(X)	((X)->rt_initarraysz)
#define	FINIARRAYSZ(X)	((X)->rt_finiarraysz)
#define	PREINITARRAYSZ(X) ((X)->rt_preinitarraysz)
#define	DYNINFO(X)	((X)->rt_dyninfo)
#define	DYNINFOCNT(X)	((X)->rt_dyninfocnt)
#define	RELACOUNT(X)	((X)->rt_relacount)
#define	IDX(X)		((X)->rt_idx)
#define	LAZY(X)		((X)->rt_lazy)
#define	CNTL(X)		((X)->rt_cntl)
#define	CAP(X)		((X)->rt_cap)
#define	CAPCHAIN(X)	((X)->rt_capchain)

/*
 * Flags for tsorting.
 */
#define	RT_SORT_FWD	0x01		/* topological sort (.fini) */
#define	RT_SORT_REV	0x02		/* reverse topological sort (.init) */
#define	RT_SORT_DELETE	0x10		/* process FLG_RT_DELETE objects */
					/*	only (called via dlclose()) */
#define	RT_SORT_INTPOSE	0x20		/* process interposer objects */

/*
 * Flags for lookup_sym (and hence find_sym) routines.
 */
#define	LKUP_DEFT	0x0000		/* simple lookup request */
#define	LKUP_SPEC	0x0001		/* special ELF lookup (allows address */
					/*	resolutions to plt[] entries) */
/* 0x2 was previously used as part of a.out support */
#define	LKUP_FIRST	0x0004		/* lookup symbol in first link map */
					/*	only */
#define	LKUP_COPY	0x0008		/* lookup symbol for a COPY reloc, do */
					/*	not bind to symbol at head */
#define	LKUP_STDRELOC	0x0010		/* lookup originates from a standard */
					/*	relocation (elf_reloc()) */
#define	LKUP_SELF	0x0020		/* lookup symbol in ourself - undef */
					/*	is valid */
#define	LKUP_WEAK	0x0040		/* relocation reference is weak */
#define	LKUP_NEXT	0x0080		/* request originates from RTLD_NEXT */
#define	LKUP_NODESCENT	0x0100		/* don't descend through dependencies */
#define	LKUP_NOFALLBACK	0x0200		/* don't fall back to loading */
					/*	pending lazy dependencies */
#define	LKUP_DIRECT	0x0400		/* direct binding request */
#define	LKUP_SYMNDX	0x0800		/* establish symbol index */
#define	LKUP_SINGLETON	0x1000		/* search for a singleton symbol */
#define	LKUP_STANDARD	0x2000		/* standard lookup - originated from */
					/*	head link-map element */
#define	LKUP_WORLD	0x4000		/* ensure world lookup */
#define	LKUP_DLSYM	0x8000		/* lookup stems from dlsym() request */

/*
 * For the runtime linker to perform a symbol search, a number of data items
 * related to the search are required.  An Slookup data structure is used to
 * convey this data to lookup_sym(), and in special cases, to other core
 * routines that provide the implementation details for lookup_sym()
 *
 * The symbol name (sl_name), the caller (sl_cmap), and the link-map from which
 * to start the search (sl_imap) are fundamental to the symbol search.  The
 * initial search link-map might get modified by the core routines that provide
 * the implementation details for lookup_sym().  This modification accommodates
 * requirements such as processing a handle, direct binding and interposition.
 * The association between the caller and the potential destination also
 * determines whether the destination is a candidate to search.
 *
 * The lookup identifier (sl_id) is used to identify a runtime linker operation.
 * Within this operation, any lazy loads that fail are not re-examined.  This
 * technique keeps the overhead of processing a failed lazy load to a minimum.
 *
 * Symbol searches that originate from a relocation record are accompanied by
 * the relocation index (sl_rsymndx), the symbol reference (sl_rsym) and
 * possibly the relocation type (sl_rtype).  This data provides for determining
 * lazy loading, direct binding, and special symbol processing requirements
 * such as copy relocations and singleton lookup.
 *
 * The symbols hash value is computed by lookup_sym, and propagated throughout
 * the search engine.  Note, occasionally the Slookup data is passed to a core
 * routine that provides the implementation details for lookup_sym(), ie.
 * elf_find_sym(), in which case the caller must initialize the hash value.
 *
 * The symbols binding information is established by lookup_sym() when the
 * symbols relocation type is supplied.  Weak bindings allow relocations to
 * be set to zero should a symbol lookup fail.
 *
 * The flags allow the caller to control aspects of the search, including the
 * interpretation of copy relocations, etc.  Note, a number of flag settings
 * are established in lookup_sym() from attributes of the symbol reference.
 */
struct slookup {
	const char	*sl_name;	/* symbol name */
	Rt_map		*sl_cmap;	/* callers link-map */
	Rt_map		*sl_imap;	/* initial link-map to search */
	ulong_t		sl_id;		/* identifier for this lookup */
	ulong_t		sl_hash;	/* symbol hash value */
	ulong_t		sl_rsymndx;	/* referencing reloc symndx */
	Sym		*sl_rsym;	/* referencing symbol */
	uchar_t		sl_rtype;	/* relocation type associate with */
					/*    symbol */
	uchar_t		sl_bind;	/* symbols binding (returned) */
	uint_t		sl_flags;	/* lookup flags */
};

#define	SLOOKUP_INIT(sl, name, cmap, imap, id, hash, rsymndx, rsym, rtype, \
    flags) \
	(void) (sl.sl_name = (name), sl.sl_cmap = (cmap), sl.sl_imap = (imap), \
	    sl.sl_id = (id), sl.sl_hash = (hash), sl.sl_rsymndx = (rsymndx), \
	    sl.sl_rsym = (rsym), sl.sl_rtype = (rtype), sl.sl_bind = 0, \
	    sl.sl_flags = (flags))

/*
 * After a symbol lookup has been resolved, the runtime linker needs to retain
 * information regarding the bound definition.  An Sresult data structure is
 * used to provide this information.
 *
 * The symbol name (sr_name) may differ from the original referenced symbol if
 * a symbol capabilities family member has resolved the binding.  The defining
 * object (sr_dmap) indicates the object in which the definition has been found.
 * The symbol table entry (sr_sym) defines the bound symbol definition.
 *
 * Note, a symbol lookup may start with one Sresult buffer, but underlying
 * routines (for example, those that probe filters) might employ their own
 * Sresult buffer.  If a binding is allowed, the latter buffer may get inherited
 * by the former.  Along with this chain of requests, binding info (binfo) and
 * not-found information (in_nfavl), may be passed between all the associated
 * functions.  Hence, the binfo and in_nfavl data is not maintained as part of
 * a Sresult structure.
 */
struct sresult {
	const char	*sr_name;	/* symbol definition name */
	Rt_map		*sr_dmap;	/* defining objects link-map */
	Sym		*sr_sym;	/* symbol table pointer */
};

#define	SRESULT_INIT(sr, name) \
	(void) (sr.sr_name = (name), sr.sr_dmap = NULL, sr.sr_sym = NULL)

/*
 * Define a system capabilities structure for maintaining the various
 * capabilities of the system.  This structure follows the Objcapset definition
 * from libld.h, however the system can only have one platform or machine
 * hardware name, thus this structure is a little simpler.
 *
 * Note, the amd64 version of elf_rtbndr assumes that the sc_hw_1 value is at
 * offset zero and sc_hw_2 is at offset 8. If you are changing this structure
 * in a way that invalidates this, you need to update that code.
 */
typedef	struct {
	elfcap_mask_t	sc_hw_1;	/* CA_SUNW_HW_1 capabilities */
	elfcap_mask_t	sc_sf_1;	/* CA_SUNW_SF_1 capabilities */
	elfcap_mask_t	sc_hw_2;	/* CA_SUNW_HW_2 capabilities */
	elfcap_mask_t	sc_hw_3;	/* CA_SUNW_HW_3 capabilities */
	char		*sc_plat;	/* CA_SUNW_PLAT capability */
	size_t		sc_platsz;	/*	and size */
	char		*sc_mach;	/* CA_SUNW_MACH capability */
	size_t		sc_machsz;	/*	and size */
} Syscapset;

/*
 * Define a number of .plt lookup outcomes, for use in binding diagnostics.
 */
typedef	enum {
	PLT_T_NONE = 0,
	PLT_T_21D,
	PLT_T_24D,
	PLT_T_U32,
	PLT_T_U44,
	PLT_T_FULL,
	PLT_T_FAR,
	PLT_T_NUM			/* Must be last */
} Pltbindtype;

/*
 * Prototypes.
 */
extern ulong_t		ld_entry_cnt;	/* counter bumped on each entry to */
					/*    ld.so.1. */
extern Lm_list		lml_main;	/* main's link map list */
extern Lm_list		lml_rtld;	/* rtld's link map list */
extern Lm_list		*lml_list[];

extern Pltbindtype	elf_plt_write(uintptr_t, uintptr_t, void *, uintptr_t,
			    Xword);
extern Rt_map		*is_so_loaded(Lm_list *, const char *, int *);
extern int		lookup_sym(Slookup *, Sresult *, uint_t *, int *);
extern int		rt_dldump(Rt_map *, const char *, int, Addr);

#ifdef	__cplusplus
}
#endif

#endif /* _RTLD_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 *	Copyright (c) 1988 AT&T
 *	  All Rights Reserved
 *
 *
 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
 * Copyright 2022 Oxide Computer Company
 *
 * Global include file for all sgs.
 */

#ifndef	_SGS_H
#define	_SGS_H

#ifdef	__cplusplus
extern "C" {
#endif

/* <assert.h> keys off of NDEBUG */
#ifdef	DEBUG
#undef	NDEBUG
#else
#define	NDEBUG
#endif

#ifndef	_ASM
#include <sys/types.h>
#include <sys/machelf.h>
#include <sys/stddef.h>
#include <stdlib.h>
#include <stdarg.h>
#include <libelf.h>
#include <assert.h>
#include <alist.h>
#endif	/* _ASM */

/*
 * Software identification.
 */
#define	SGS		""
#define	SGU_PKG		"Software Generation Utilities"
#define	SGU_REL		"(SGU) Solaris-ELF (4.0)"


#ifndef _ASM

/*
 * link_ver_string[] contains a version string for use by the link-editor
 * and all other linker components. It is found in libconv, and is
 * generated by sgs/libconv/common/bld_vernote.ksh. That script produces
 * libconv/{plat}/vernote.s, which is in turn assembled/linked into
 * libconv.
 */
extern const char link_ver_string[];
/*
 * Macro to round to next double word boundary.
 */
#define	S_DROUND(x)	(((x) + sizeof (double) - 1) & ~(sizeof (double) - 1))

/*
 * General align and round macros.
 */
#define	S_ALIGN(x, a)	((x) & ~(((a) ? (a) : 1) - 1))
#define	S_ROUND(x, a)   (((x) + (((a) ? (a) : 1) - 1)) & ~(((a) ? (a) : 1) - 1))

/*
 * Bit manipulation macros; generic bit mask and is `v' in the range
 * supportable in `n' bits?
 */
#define	S_MASK(n)	((1 << (n)) - 1)
#define	S_INRANGE(v, n)	(((-(1 << (n)) - 1) < (v)) && ((v) < (1 << (n))))


/*
 * Yet another definition of the OFFSETOF macro, used with the AVL routines.
 */
#define	SGSOFFSETOF(s, m)	offsetof(s, m)

/*
 * When casting between integer and pointer types, gcc will complain
 * if the integer type used is not large enough to hold the pointer
 * value without loss. Although a dubious practice in general, this
 * is sometimes done by design. In those cases, the general solution
 * is to introduce an intermediate cast to widen the integer value. The
 * CAST_PTRINT macro does this, and its use documents the fact that
 * the programmer is doing that sort of cast.
 */
#ifdef __GNUC__
#define	CAST_PTRINT(cast, value) ((cast)(uintptr_t)value)
#else
#define	CAST_PTRINT(cast, value) ((cast)value)
#endif

/*
 * General typedefs.
 */
typedef enum {
	FALSE = 0,
	TRUE = 1
} Boolean;

/*
 * Types of errors (used by veprintf()), together with a generic error return
 * value.
 */
typedef enum {
	ERR_NONE,		/* plain message */
	ERR_WARNING_NF,		/* warning that cannot be promoted to fatal */
	ERR_WARNING,		/* warning that can be promoted to fatal */
	ERR_GUIDANCE,		/* guidance warning that can be promoted */
	ERR_FATAL,		/* fatal error */
	ERR_ELF,		/* fatal libelf error */
	ERR_NUM			/* # of Error codes. Must be last */
} Error;

/*
 * Type used to represent line numbers within files, and a corresponding
 * printing macro for it.
 */
typedef ulong_t Lineno;
#define	EC_LINENO(_x) EC_XWORD(_x)			/* "llu" */


#if defined(_LP64) && !defined(_ELF64)
#define	S_ERROR		(~(uint_t)0)
#else
#define	S_ERROR		(~(uintptr_t)0)
#endif

/*
 * CTF currently does not handle automatic array variables sized via function
 * arguments (VLA arrays) properly, when the code is compiled with gcc.
 * Adding 1 to the size is a workaround.  VLA_SIZE, and its use, should be
 * pulled when CTF is fixed or replaced.
 */
#ifdef __GNUC__
#define	VLA_SIZE(_arg)	((_arg) + 1)
#else
#define	VLA_SIZE(_arg)	(_arg)
#endif

/*
 * Structure to maintain rejected files elf information.  Files that are not
 * applicable to the present link-edit are rejected and a search for an
 * appropriate file may be resumed.  The first rejected files information is
 * retained so that a better error diagnostic can be given should an appropriate
 * file not be located.
 */
typedef struct {
	ushort_t	rej_type;	/* SGS_REJ_ value */
	ushort_t	rej_flags;	/* additional information */
	uint_t		rej_info;	/* numeric and string information */
	const char	*rej_str;	/*	associated with error */
	const char	*rej_name;	/* object name - expanded library */
					/*	name and archive members */
} Rej_desc;

#define	SGS_REJ_NONE		0
#define	SGS_REJ_MACH		1	/* wrong ELF machine type */
#define	SGS_REJ_CLASS		2	/* wrong ELF class (32-bit/64-bit) */
#define	SGS_REJ_DATA		3	/* wrong ELF data format (MSG/LSB) */
#define	SGS_REJ_TYPE		4	/* bad ELF type */
#define	SGS_REJ_BADFLAG		5	/* bad ELF flags value */
#define	SGS_REJ_MISFLAG		6	/* mismatched ELF flags value */
#define	SGS_REJ_VERSION		7	/* mismatched ELF/lib version */
#define	SGS_REJ_HAL		8	/* HAL R1 extensions required */
#define	SGS_REJ_US3		9	/* Sun UltraSPARC III extensions */
					/*	required */
#define	SGS_REJ_STR		10	/* generic error - info is a string */
#define	SGS_REJ_UNKFILE		11	/* unknown file type */
#define	SGS_REJ_UNKCAP		12	/* unknown capabilities */
#define	SGS_REJ_HWCAP_1		13	/* hardware capabilities mismatch */
#define	SGS_REJ_SFCAP_1		14	/* software capabilities mismatch */
#define	SGS_REJ_MACHCAP		15	/* machine capability mismatch */
#define	SGS_REJ_PLATCAP		16	/* platform capability mismatch */
#define	SGS_REJ_HWCAP_2		17	/* hardware capabilities mismatch */
#define	SGS_REJ_ARCHIVE		18	/* archive used in invalid context */
#define	SGS_REJ_KMOD		19	/* object is a kernel module */
#define	SGS_REJ_HWCAP_3		20	/* hardware capabilities mismatch */
#define	SGS_REJ_NUM		21


#define	FLG_REJ_ALTER		0x01	/* object name is an alternative */

/*
 * Data structures (defined in libld.h).
 */
typedef	struct audit_desc	Audit_desc;
typedef	struct audit_info	Audit_info;
typedef	struct audit_list	Audit_list;
typedef struct cap_desc		Cap_desc;
typedef struct ent_desc		Ent_desc;
typedef	struct group_desc	Group_desc;
typedef struct ifl_desc		Ifl_desc;
typedef struct is_desc		Is_desc;
typedef struct isa_desc		Isa_desc;
typedef struct isa_opt		Isa_opt;
typedef struct os_desc		Os_desc;
typedef struct ofl_desc		Ofl_desc;
typedef	struct rel_cache	Rel_cache;
typedef	struct rel_cachebuf	Rel_cachebuf;
typedef	struct rel_aux_cachebuf	Rel_aux_cachebuf;
typedef struct rel_aux		Rel_aux;
typedef struct rel_desc		Rel_desc;
typedef	struct sdf_desc		Sdf_desc;
typedef	struct sdv_desc		Sdv_desc;
typedef struct sec_order	Sec_order;
typedef struct sg_desc		Sg_desc;
typedef struct sort_desc	Sort_desc;
typedef	struct sym_avlnode	Sym_avlnode;
typedef struct sym_aux		Sym_aux;
typedef struct sym_desc		Sym_desc;
typedef	struct uts_desc		Uts_desc;
typedef struct ver_desc		Ver_desc;
typedef struct ver_index	Ver_index;

/*
 * Data structures defined in rtld.h.
 */
typedef struct lm_list		Lm_list;
#ifdef _SYSCALL32
typedef struct lm_list32	Lm_list32;
#endif	/* _SYSCALL32 */

/*
 * For the various utilities that include sgs.h
 */
extern void	eprintf(Lm_list *, Error, const char *, ...);
extern void	veprintf(Lm_list *, Error, const char *, va_list);
extern uint_t	sgs_str_hash(const char *);
extern uint_t	findprime(uint_t);

#endif /* _ASM */

#ifdef	__cplusplus
}
#endif


#endif /* _SGS_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_SGSMSG_DOT_H
#define	_SGSMSG_DOT_H

#ifdef __cplusplus
extern "C" {
#endif

#ifndef	__lint

/*
 * In normal operation, sgsmsg generates an ELF-format string table
 * for strings, and Msg is an integer offset into that table.
 */
typedef int	Msg;

#else	/* __lint */

/*
 * When __lint is defined, Msg is a char *.  This allows lint to
 * check our format strings against its arguments.
 */
typedef char	*Msg;

#endif	/* __lint */


#ifdef __cplusplus
}
#endif

#endif /* _SGSMSG_DOT_H */
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef	_STRING_TABLE_DOT_H
#define	_STRING_TABLE_DOT_H

#include <sys/types.h>

#ifdef __cplusplus
extern "C" {
#endif

/*
 * Exported, opaque string table handle.
 */
typedef struct str_tbl	Str_tbl;

/*
 * Exported string table functions.
 */
extern int		st_delstring(Str_tbl *, const char *);
extern void		st_destroy(Str_tbl *);
extern size_t		st_getstrtab_sz(Str_tbl *);
extern const char	*st_getstrbuf(Str_tbl *);
extern int		st_insert(Str_tbl *, const char *);
extern Str_tbl		*st_new(uint_t);
extern int		st_setstrbuf(Str_tbl *, char *, size_t);
extern int		st_setstring(Str_tbl *, const char *, size_t *);
extern void		st_setallstrings(Str_tbl *);
extern off_t		st_findstring(Str_tbl *, const char *);

/*
 * Exported flags values for st_new().
 */
#define	FLG_STNEW_COMPRESS	0x01	/* compressed string table */

#ifdef __cplusplus
}
#endif

#endif /* _STRING_TABLE_DOT_H */