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 */
|