mirror of
https://github.com/jart/cosmopolitan.git
synced 2026-11-08 01:58:20 -10:00
Compare commits
663
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a04bc3318 | ||
|
|
8dd4ec68d0 | ||
|
|
b9dc74b672 | ||
|
|
e1590e1e38 | ||
|
|
8569704c1d | ||
|
|
9c017c98d3 | ||
|
|
74879bf067 | ||
|
|
8a3d8497e3 | ||
|
|
3c00d8c29c | ||
|
|
1ef955c33b | ||
|
|
494d74271b | ||
|
|
12212894eb | ||
|
|
a4522fba8d | ||
|
|
0c70e8963d | ||
|
|
b66bd064d8 | ||
|
|
c5c4dfcd21 | ||
|
|
c5659b93f8 | ||
|
|
263711965f | ||
|
|
33b5b5b312 | ||
|
|
d213a48190 | ||
|
|
3f0414e1cb | ||
|
|
adaaeb7dd0 | ||
|
|
164e2ab27b | ||
|
|
d2cec808dc | ||
|
|
91a3252434 | ||
|
|
8cab92a069 | ||
|
|
5a632cf72d | ||
|
|
7b74f6e20e | ||
|
|
253cc1754b | ||
|
|
8722006c46 | ||
|
|
58d22c7c3d | ||
|
|
2227cefa5d | ||
|
|
f0bf9f3389 | ||
|
|
04cd62c319 | ||
|
|
e204fc0820 | ||
|
|
b76540105d | ||
|
|
14e3025749 | ||
|
|
51fa5535ac | ||
|
|
bea0b55576 | ||
|
|
57b39d8793 | ||
|
|
d52170ca34 | ||
|
|
bf757c4646 | ||
|
|
99a92048b4 | ||
|
|
2f1679e5cf | ||
|
|
ee49b71be2 | ||
|
|
73845be1f0 | ||
|
|
35203c0551 | ||
|
|
83d41e4588 | ||
|
|
a51edaa0db | ||
|
|
d76dfadc7a | ||
|
|
8835b82a7c | ||
|
|
2827df688a | ||
|
|
1ce101c5a5 | ||
|
|
fcbf64b906 | ||
|
|
283fd9e590 | ||
|
|
6bb9ce553e | ||
|
|
75832f7379 | ||
|
|
897e33ccc4 | ||
|
|
27416e7dd6 | ||
|
|
6c3048821c | ||
|
|
2d5f2bebb0 | ||
|
|
db509ee158 | ||
|
|
640b9bfb48 | ||
|
|
30e1c5bca9 | ||
|
|
2d479f7b11 | ||
|
|
d7372e651d | ||
|
|
8e176fb026 | ||
|
|
c2211c9e63 | ||
|
|
f7ee9d7d99 | ||
|
|
e3fe127ccd | ||
|
|
fbdab72e3b | ||
|
|
1f735a4af3 | ||
|
|
e5f705ace3 | ||
|
|
a1aaf23dc1 | ||
|
|
ce588dd56b | ||
|
|
255d834f8f | ||
|
|
f0701d2a24 | ||
|
|
d3b599a796 | ||
|
|
0cf9716039 | ||
|
|
7ab15e0b23 | ||
|
|
6c0bbfac4a | ||
|
|
5584f6adcf | ||
|
|
d36d0634db | ||
|
|
e1699c5b68 | ||
|
|
2e54c8f9fc | ||
|
|
ead3fc2b31 | ||
|
|
62ca1b0902 | ||
|
|
ad775a75b8 | ||
|
|
b212f49ef4 | ||
|
|
e62d7b8789 | ||
|
|
0ea0d33a77 | ||
|
|
367d06d9e4 | ||
|
|
17aea99bb3 | ||
|
|
7cf66bc161 | ||
|
|
8a0a2c0c36 | ||
|
|
05b8f82371 | ||
|
|
625aa365f1 | ||
|
|
6b8b58fdf5 | ||
|
|
10fd8bdb70 | ||
|
|
2d64b9994b | ||
|
|
4c3ab6d11e | ||
|
|
7b993d561c | ||
|
|
e015defa70 | ||
|
|
37ebd8f8d5 | ||
|
|
7e1c78b4f3 | ||
|
|
c1d99676c4 | ||
|
|
95f54eeb40 | ||
|
|
5c5cf0e01d | ||
|
|
3b81bec5ae | ||
|
|
de48bae30e | ||
|
|
6746d768c6 | ||
|
|
4e939d1761 | ||
|
|
ae5d06dc53 | ||
|
|
133c693650 | ||
|
|
c464f45692 | ||
|
|
d4744048ba | ||
|
|
6b3d257588 | ||
|
|
0277d7d6e9 | ||
|
|
7bd4179b9b | ||
|
|
b77cae2d57 | ||
|
|
5546559034 | ||
|
|
13c1c45075 | ||
|
|
6a5717a48f | ||
|
|
a8cf0f7e89 | ||
|
|
cf93ecbbb2 | ||
|
|
acdf591833 | ||
|
|
8d9ac3da50 | ||
|
|
638c56e3a5 | ||
|
|
c9d7838213 | ||
|
|
9c06067c84 | ||
|
|
9d7514a906 | ||
|
|
84e89a55d4 | ||
|
|
db8217b37b | ||
|
|
449fb2fb59 | ||
|
|
5f552338d6 | ||
|
|
af3df0893b | ||
|
|
4238e4def9 | ||
|
|
ab301401c7 | ||
|
|
42bd79a461 | ||
|
|
066ed2b2b2 | ||
|
|
bd118dafa0 | ||
|
|
e98514cdb7 | ||
|
|
3443039f34 | ||
|
|
3d2cf95af1 | ||
|
|
c921dc78f0 | ||
|
|
6c71bd5969 | ||
|
|
8593580d0a | ||
|
|
f968e2a726 | ||
|
|
31ac58a57b | ||
|
|
638e14bbf3 | ||
|
|
03dd14c298 | ||
|
|
16fc83f9ce | ||
|
|
ffedbfe14d | ||
|
|
3828c08aa0 | ||
|
|
ce5cb8a2f8 | ||
|
|
31e4b0867b | ||
|
|
513a659dd2 | ||
|
|
48ce3ad7cc | ||
|
|
742251dd92 | ||
|
|
76d2f68c91 | ||
|
|
b5904947e9 | ||
|
|
516b68606f | ||
|
|
6bb8b26d70 | ||
|
|
31e746c937 | ||
|
|
5a2bb07b36 | ||
|
|
84caee23ba | ||
|
|
9de3d8f1e6 | ||
|
|
d4000bb8f7 | ||
|
|
8b469389f6 | ||
|
|
9172fd42a0 | ||
|
|
1837dc2e85 | ||
|
|
439ad21b12 | ||
|
|
7e2eae5c15 | ||
|
|
d3f3cb7ab4 | ||
|
|
097634d75c | ||
|
|
ed205e98a1 | ||
|
|
98254a7c1f | ||
|
|
92cb144fff | ||
|
|
f716435260 | ||
|
|
6e52a84a51 | ||
|
|
f7e22a33a1 | ||
|
|
69f4152f38 | ||
|
|
057e8f5b54 | ||
|
|
bf59defc0c | ||
|
|
574eba8352 | ||
|
|
6598940d8a | ||
|
|
e81edf7b04 | ||
|
|
b1d9d11be1 | ||
|
|
38c3fa63fe | ||
|
|
1c6b5c0acd | ||
|
|
4f4889ddf7 | ||
|
|
5b11033d4d | ||
|
|
4d25f8c3c9 | ||
|
|
866b21a151 | ||
|
|
4700984456 | ||
|
|
ea04d00752 | ||
|
|
6c724c0f1a | ||
|
|
aa34340f3d | ||
|
|
b4e38851ff | ||
|
|
13d67fed38 | ||
|
|
2e3958c6dc | ||
|
|
6c49e36537 | ||
|
|
7f966de489 | ||
|
|
baf51a4a23 | ||
|
|
ccd057a85d | ||
|
|
0a589add41 | ||
|
|
28b9d9f781 | ||
|
|
bcdd5c5f74 | ||
|
|
4901e1b8cb | ||
|
|
1d744ea11b | ||
|
|
b707fca77a | ||
|
|
60164a7266 | ||
|
|
0cea6c560f | ||
|
|
1d490fcb94 | ||
|
|
12d9f7ade6 | ||
|
|
30cc2c8dc1 | ||
|
|
e3cd476a9b | ||
|
|
3027d67037 | ||
|
|
6d52664aa7 | ||
|
|
3f3e7e92d7 | ||
|
|
7965ed0232 | ||
|
|
6ee18986e4 | ||
|
|
4814b6bdf8 | ||
|
|
3c10fb5580 | ||
|
|
0272f638a5 | ||
|
|
9308463b0f | ||
|
|
594615a0ff | ||
|
|
11a1c62d11 | ||
|
|
aeee2f9106 | ||
|
|
694a0da990 | ||
|
|
9877c04fac | ||
|
|
3f015b1e51 | ||
|
|
84764ce7b8 | ||
|
|
68ca49bfdd | ||
|
|
331fdd1d29 | ||
|
|
c0b325bafa | ||
|
|
5fa77f1e8f | ||
|
|
5f4f6b0e69 | ||
|
|
e4d6e263d4 | ||
|
|
28f0104330 | ||
|
|
4a1419fefa | ||
|
|
ee82cee432 | ||
|
|
9e86980191 | ||
|
|
7756e27993 | ||
|
|
2189877856 | ||
|
|
d37536bd4b | ||
|
|
727d9cbf56 | ||
|
|
896db8843f | ||
|
|
c9e68b0ebc | ||
|
|
85aecbda67 | ||
|
|
a9145e7f1e | ||
|
|
182d7720cf | ||
|
|
1c83670229 | ||
|
|
c5b9902ac9 | ||
|
|
50a6df89b8 | ||
|
|
fe5c475f83 | ||
|
|
a18044c504 | ||
|
|
11ac8f11a9 | ||
|
|
059fe22ea3 | ||
|
|
853b6c3864 | ||
|
|
5df3e4e7a8 | ||
|
|
2eebb198a9 | ||
|
|
9f8e6c10dd | ||
|
|
5297897ba1 | ||
|
|
3c92adfd6e | ||
|
|
a6f65eea7c | ||
|
|
32eec7df4c | ||
|
|
283729dfe0 | ||
|
|
b4e9a77e74 | ||
|
|
f6dab99f44 | ||
|
|
b535937fca | ||
|
|
893cc06fc2 | ||
|
|
5cd0e876bd | ||
|
|
b1de862e16 | ||
|
|
2f515ac5e3 | ||
|
|
61257d48d4 | ||
|
|
fa5c2a24b5 | ||
|
|
fbc053e018 | ||
|
|
5d837c4e7c | ||
|
|
1bce1ca2e0 | ||
|
|
a9d77362f9 | ||
|
|
4b9ee980a1 | ||
|
|
e55ef556aa | ||
|
|
7f26779d6f | ||
|
|
3d07f362d7 | ||
|
|
f79b2fe23a | ||
|
|
e4258015b7 | ||
|
|
49905fed0b | ||
|
|
44da16255a | ||
|
|
a4601a24d3 | ||
|
|
0dd9629562 | ||
|
|
3fc23c6cbc | ||
|
|
2b54f1bcf6 | ||
|
|
206f073181 | ||
|
|
17cbe73411 | ||
|
|
2415afab0e | ||
|
|
1235ad6006 | ||
|
|
9545062175 | ||
|
|
0e773e23ad | ||
|
|
fc097ac275 | ||
|
|
4b23985b7f | ||
|
|
ff28e38ef1 | ||
|
|
b8e9f71d33 | ||
|
|
1216b6e7c7 | ||
|
|
56eff8544f | ||
|
|
f317a47cd8 | ||
|
|
a988896048 | ||
|
|
5ddf43332e | ||
|
|
d5312b60f7 | ||
|
|
25041b8026 | ||
|
|
2c7fe0f361 | ||
|
|
8c895453e2 | ||
|
|
c1cfca8ae1 | ||
|
|
67b28b9af1 | ||
|
|
52ed099fe6 | ||
|
|
5e04827949 | ||
|
|
bc90db0d4b | ||
|
|
7b34f32fc4 | ||
|
|
a0ddb889da | ||
|
|
34e39ad027 | ||
|
|
2c7f865b12 | ||
|
|
d0d9cd38c5 | ||
|
|
c06ffd458c | ||
|
|
42c38bc3e3 | ||
|
|
fae2a17d2c | ||
|
|
e466dd0553 | ||
|
|
579080cd4c | ||
|
|
42b34c26f8 | ||
|
|
8b13e1acc8 | ||
|
|
58c77a9b1d | ||
|
|
bba7f5e296 | ||
|
|
1c387727fe | ||
|
|
dae0583ee5 | ||
|
|
a3865ecc3c | ||
|
|
3c285337a2 | ||
|
|
91953dd308 | ||
|
|
8b72490431 | ||
|
|
8cdec62f5b | ||
|
|
4ddfc47d6e | ||
|
|
6070a53e89 | ||
|
|
a5849f8549 | ||
|
|
29af890efa | ||
|
|
517267a577 | ||
|
|
e96aceae41 | ||
|
|
1ae6cfc198 | ||
|
|
e32288d4ea | ||
|
|
c260345e06 | ||
|
|
5ea618f0af | ||
|
|
5deda43766 | ||
|
|
c6d8e516b2 | ||
|
|
41c86fe86b | ||
|
|
8a967ae6fe | ||
|
|
af4687cc3f | ||
|
|
1531f1a4a7 | ||
|
|
fde939291d | ||
|
|
f8520e10b2 | ||
|
|
2528536cff | ||
|
|
a41669dec6 | ||
|
|
fa1e8a3e65 | ||
|
|
3c7ae0fc72 | ||
|
|
ecc8962555 | ||
|
|
e1a40783da | ||
|
|
adac64a52b | ||
|
|
4e7ce1538c | ||
|
|
701564de19 | ||
|
|
cfb5d3e406 | ||
|
|
e011973593 | ||
|
|
da6d610056 | ||
|
|
13ee75150c | ||
|
|
425ff5dff0 | ||
|
|
909e54510d | ||
|
|
de5de19004 | ||
|
|
cb67223051 | ||
|
|
7e9fb0a9f1 | ||
|
|
10b97ca630 | ||
|
|
8f12cd980d | ||
|
|
1a29424c52 | ||
|
|
d230a01222 | ||
|
|
d44ff6ce1f | ||
|
|
cef50f2a6b | ||
|
|
99e67c348b | ||
|
|
e8632cfc30 | ||
|
|
312ed5c67c | ||
|
|
1f229e4efc | ||
|
|
4e9662cbc7 | ||
|
|
056dc5f554 | ||
|
|
db0d8dd806 | ||
|
|
7838edae88 | ||
|
|
96781d0679 | ||
|
|
f4fc16754a | ||
|
|
8141988e92 | ||
|
|
fb4382e9a4 | ||
|
|
c8a2f04058 | ||
|
|
4245da19e2 | ||
|
|
b4ae385a6a | ||
|
|
c21412bc2c | ||
|
|
ec2cb88058 | ||
|
|
6e52cba37a | ||
|
|
9208c83f7a | ||
|
|
c6bbca55e9 | ||
|
|
b2c6ec6eab | ||
|
|
2ad1c9078d | ||
|
|
3d99ebb68c | ||
|
|
f37524ef4f | ||
|
|
2743f3d012 | ||
|
|
ce71677156 | ||
|
|
8bfb70ca3f | ||
|
|
59b6ae1cbd | ||
|
|
55de4ca6b5 | ||
|
|
91ee2b19d4 | ||
|
|
e5e141d9b5 | ||
|
|
c446af799e | ||
|
|
6bf6f9e376 | ||
|
|
54e6f564c1 | ||
|
|
178a6da4b9 | ||
|
|
80b211e314 | ||
|
|
578cb21591 | ||
|
|
f6df29cc3d | ||
|
|
d25a67f4eb | ||
|
|
77b70ba193 | ||
|
|
83b743cf96 | ||
|
|
fec396037a | ||
|
|
4e62cefa6e | ||
|
|
4499f98e76 | ||
|
|
0f6251f4d2 | ||
|
|
ec6e0fa5f4 | ||
|
|
335d158ab6 | ||
|
|
2ea1dc405c | ||
|
|
e7611a8476 | ||
|
|
dd9ab01d25 | ||
|
|
cf73bbd678 | ||
|
|
70c97f598b | ||
|
|
cfc3a953ae | ||
|
|
2aebda7718 | ||
|
|
363d2ec436 | ||
|
|
b30f5c0c4f | ||
|
|
15c59e716f | ||
|
|
c9f966d73c | ||
|
|
93906f8f28 | ||
|
|
42071ffe6f | ||
|
|
854c90f547 | ||
|
|
a85406da4c | ||
|
|
e4b559c76a | ||
|
|
2d1731b995 | ||
|
|
7aafa64ab3 | ||
|
|
c9a981fdbe | ||
|
|
80c4533303 | ||
|
|
47b3274665 | ||
|
|
9a6bd304a5 | ||
|
|
e3a7ab1804 | ||
|
|
92ebef16ee | ||
|
|
cc0d1ec076 | ||
|
|
6a145a9262 | ||
|
|
d57b81aac7 | ||
|
|
860ea18a87 | ||
|
|
e6fab847a0 | ||
|
|
72e9be5c20 | ||
|
|
451e3f73d9 | ||
|
|
2046c0d2ae | ||
|
|
cf3174dc74 | ||
|
|
2f56ebfe78 | ||
|
|
6ff46ca373 | ||
|
|
552525cbdd | ||
|
|
a259e43d84 | ||
|
|
38728cef79 | ||
|
|
0dca4c5799 | ||
|
|
c39d6111f2 | ||
|
|
1599b818d9 | ||
|
|
01b25e267b | ||
|
|
9d61e23c80 | ||
|
|
9bfa6ec06e | ||
|
|
87396f43bc | ||
|
|
ae638c0850 | ||
|
|
c3fb624647 | ||
|
|
5a132f9652 | ||
|
|
7166679620 | ||
|
|
f1dfa4bdfa | ||
|
|
ab38f0823d | ||
|
|
80308079ec | ||
|
|
4a6a34db83 | ||
|
|
a6b02ce5a6 | ||
|
|
f6b6204b9e | ||
|
|
933f33bcc1 | ||
|
|
be7c5e1071 | ||
|
|
dc0ea6640e | ||
|
|
933411ba99 | ||
|
|
233144b19d | ||
|
|
fb7e8ef1e6 | ||
|
|
281a0f2730 | ||
|
|
f684e348d4 | ||
|
|
c95c9d9508 | ||
|
|
046c7ebd4a | ||
|
|
f68f1789bd | ||
|
|
e500e8fb48 | ||
|
|
a157940ba6 | ||
|
|
183b3ed6a2 | ||
|
|
668dc42bac | ||
|
|
d31bebdd2d | ||
|
|
4f98ad1054 | ||
|
|
29bf8b1a30 | ||
|
|
43ba3009b2 | ||
|
|
722d3df711 | ||
|
|
837ff6cb49 | ||
|
|
42fbcff149 | ||
|
|
c13142dad2 | ||
|
|
f59b5dbd7c | ||
|
|
82f2e758c7 | ||
|
|
ce9bdbb0bf | ||
|
|
58d74ede4c | ||
|
|
04d39d47f1 | ||
|
|
9b11206ae3 | ||
|
|
38cb6e71ca | ||
|
|
1ff1854107 | ||
|
|
27bc49034c | ||
|
|
1ccd269cdd | ||
|
|
2fe386ff8c | ||
|
|
072e1d2910 | ||
|
|
3b9e66ecba | ||
|
|
98909b1391 | ||
|
|
b90fa996b4 | ||
|
|
23b72eb617 | ||
|
|
393ca4be40 | ||
|
|
c23b6ecc31 | ||
|
|
e2e0b042c1 | ||
|
|
868af3f950 | ||
|
|
5022f9e920 | ||
|
|
87029ac3f9 | ||
|
|
e5314dedde | ||
|
|
d57f87dc40 | ||
|
|
4881ae7527 | ||
|
|
f78f2fcac3 | ||
|
|
5e8ae2d5bc | ||
|
|
d5ff2c3fb9 | ||
|
|
0cb6b6ff4b | ||
|
|
efedef6e65 | ||
|
|
39688a73e4 | ||
|
|
10a766ebd0 | ||
|
|
14e192e5ba | ||
|
|
c541225af0 | ||
|
|
c4d8f40422 | ||
|
|
96bdd7e90f | ||
|
|
390e22a8c6 | ||
|
|
6c2fd9ecc6 | ||
|
|
b149a9bcc4 | ||
|
|
9d2c8798c1 | ||
|
|
d07a58a763 | ||
|
|
c371db6663 | ||
|
|
af645fcbec | ||
|
|
f5831a62fa | ||
|
|
741c836e9d | ||
|
|
46a3b88594 | ||
|
|
e20fcf02c1 | ||
|
|
bf62140377 | ||
|
|
b45d50b690 | ||
|
|
2a938b3eaa | ||
|
|
cfc557f7c7 | ||
|
|
38112aeb20 | ||
|
|
22409b2b5e | ||
|
|
abac6f729c | ||
|
|
1e3c5e10ad | ||
|
|
4abae20172 | ||
|
|
9bab356c37 | ||
|
|
0f035119b1 | ||
|
|
db6152e21d | ||
|
|
d938b89f4f | ||
|
|
d6a039821f | ||
|
|
f12c6c1b5e | ||
|
|
fdb543cbb3 | ||
|
|
1d6216a775 | ||
|
|
206091617a | ||
|
|
777d08a839 | ||
|
|
98192c1079 | ||
|
|
7064d736e3 | ||
|
|
245a9c206b | ||
|
|
1bdc8faa65 | ||
|
|
8f05990d5a | ||
|
|
7fe9e70117 | ||
|
|
6f658f058b | ||
|
|
ca611efc43 | ||
|
|
e5d1536256 | ||
|
|
d7ff346b52 | ||
|
|
903cc38c37 | ||
|
|
3616f2a432 | ||
|
|
7a50dba812 | ||
|
|
19f70a154e | ||
|
|
0a0997a872 | ||
|
|
30cd28b1f8 | ||
|
|
91d783352a | ||
|
|
45a7435788 | ||
|
|
660ff56d40 | ||
|
|
c00755f921 | ||
|
|
013f03e33f | ||
|
|
49db877fbe | ||
|
|
253ac31a64 | ||
|
|
67b5200a0b | ||
|
|
226aaf3547 | ||
|
|
a0b39f886c | ||
|
|
d852640a1e | ||
|
|
425a57080d | ||
|
|
bba144246a | ||
|
|
7061c79c22 | ||
|
|
28997f3acb | ||
|
|
725f4d79f6 | ||
|
|
7521bf9e73 | ||
|
|
47a53e143b | ||
|
|
9cb54218ab | ||
|
|
57f0eed382 | ||
|
|
2fe8571010 | ||
|
|
9cabdaabfd | ||
|
|
39bf41f4eb | ||
|
|
fa7b4f5bd1 | ||
|
|
b883473a6c | ||
|
|
af1153e057 | ||
|
|
2e4b40042a | ||
|
|
42aafc847e | ||
|
|
b51db9f923 | ||
|
|
6fba9601ff | ||
|
|
9e7773a076 | ||
|
|
48a2668239 | ||
|
|
5ffeaa8e33 | ||
|
|
18ccfeb919 | ||
|
|
b5f743cdc3 | ||
|
|
51904e2687 | ||
|
|
ad52387b74 | ||
|
|
6ad0602392 | ||
|
|
1b93066883 | ||
|
|
559b024e1d | ||
|
|
dfa0359b50 | ||
|
|
4f41f2184d | ||
|
|
5bb2275788 | ||
|
|
a8fb68af4b | ||
|
|
1eed7d47bd | ||
|
|
44c87b83ff | ||
|
|
81287b7ec0 | ||
|
|
34b68f1945 | ||
|
|
ab64c746cc | ||
|
|
a81192e0b9 | ||
|
|
27f7ffd4fd | ||
|
|
31dd714081 | ||
|
|
969174e155 | ||
|
|
5b60e5a37d | ||
|
|
0584684a82 | ||
|
|
50937be752 | ||
|
|
3085ac7837 | ||
|
|
63b867bd2f | ||
|
|
0b7737b20a | ||
|
|
818926dbae | ||
|
|
7d25fb0090 | ||
|
|
41b9eb6873 | ||
|
|
00611e9b06 | ||
|
|
2730c66f4a | ||
|
|
c506584174 | ||
|
|
ed485391da | ||
|
|
d5a37de435 | ||
|
|
65f32fad52 | ||
|
|
da45c7c80b | ||
|
|
7341336b1a | ||
|
|
a63b147a93 | ||
|
|
0ba3617e7f | ||
|
|
8af197560e | ||
|
|
98ccbf44b1 | ||
|
|
ebb8c85496 | ||
|
|
4486ad5c9e |
No files matched your search
@@ -0,0 +1,28 @@
|
||||
name: build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- "master"
|
||||
- "flake"
|
||||
pull_request:
|
||||
branches:
|
||||
- "master"
|
||||
|
||||
# run workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
matrix_on_mode:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
mode: ["", tiny, opt, rel]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: support ape bins
|
||||
run: sudo sh -c "echo ':APE:M::MZqFpD::/bin/sh:' >/proc/sys/fs/binfmt_misc/register"
|
||||
|
||||
- name: make matrix
|
||||
run: V=0 make -j2 MODE=${{ matrix.mode }}
|
||||
+2
-1
@@ -11,4 +11,5 @@ __pycache__
|
||||
/TAGS
|
||||
/bx_enh_dbg.ini
|
||||
/tool/emacs/*.elc
|
||||
/usr/share/dict/words
|
||||
/perf.data
|
||||
/perf.data.old
|
||||
@@ -1,6 +0,0 @@
|
||||
virt: lxd
|
||||
os: linux
|
||||
language: c
|
||||
script: make -j4 V=0
|
||||
notifications:
|
||||
email: false
|
||||
Vendored
+4
-3
@@ -15,7 +15,7 @@
|
||||
"alignas(x)",
|
||||
"alignof(x)",
|
||||
"artificial=",
|
||||
"nodiscard=",
|
||||
"dontdiscard=",
|
||||
"mayalias=",
|
||||
"forceinline=",
|
||||
"forcealign(x)=",
|
||||
@@ -46,9 +46,10 @@
|
||||
"testonly=",
|
||||
"donothing=",
|
||||
"nosideeffect=",
|
||||
"unreachable=",
|
||||
"unreachable=",,
|
||||
"notpossible=",
|
||||
"thatispacked=",
|
||||
"nothrow=",
|
||||
"dontthrow=",
|
||||
"nocallback=",
|
||||
"relegated=",
|
||||
"hidden=",
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#
|
||||
# # basic debugging
|
||||
# make -j8 -O MODE=dbg o/dbg/examples/crashreport.com
|
||||
# o/dbg/examples/crashreport.com
|
||||
# o/examples/crashreport.com
|
||||
# less examples/crashreport.c
|
||||
#
|
||||
# # extremely tiny binaries
|
||||
@@ -59,10 +59,9 @@
|
||||
#
|
||||
# build/config.mk
|
||||
|
||||
SHELL = /bin/sh
|
||||
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 xnu win7 win10
|
||||
SANITY := $(shell build/sanitycheck $$PPID)
|
||||
GNUMAKEFLAGS += --output-sync
|
||||
SHELL = build/bootstrap/cocmd.com
|
||||
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 win10 xnu
|
||||
MAKEFLAGS += --no-builtin-rules
|
||||
|
||||
.SUFFIXES:
|
||||
.DELETE_ON_ERROR:
|
||||
@@ -70,7 +69,10 @@ GNUMAKEFLAGS += --output-sync
|
||||
.PHONY: all o bins check test depend tags
|
||||
|
||||
all: o
|
||||
o: o/$(MODE)/ape \
|
||||
o: o/$(MODE)
|
||||
|
||||
o/$(MODE): \
|
||||
o/$(MODE)/ape \
|
||||
o/$(MODE)/dsp \
|
||||
o/$(MODE)/net \
|
||||
o/$(MODE)/libc \
|
||||
@@ -79,6 +81,19 @@ o: o/$(MODE)/ape \
|
||||
o/$(MODE)/examples \
|
||||
o/$(MODE)/third_party
|
||||
|
||||
.STRICT = 1
|
||||
.PLEDGE = stdio rpath wpath cpath fattr proc
|
||||
.UNVEIL = \
|
||||
libc/integral \
|
||||
libc/disclaimer.inc \
|
||||
rx:build/bootstrap \
|
||||
rx:o/third_party/gcc \
|
||||
/proc/self/status \
|
||||
rw:/dev/null \
|
||||
w:o/stack.log \
|
||||
/etc/hosts \
|
||||
~/.runit.psk
|
||||
|
||||
PKGS =
|
||||
|
||||
-include ~/.cosmo.mk
|
||||
@@ -95,7 +110,6 @@ include libc/intrin/intrin.mk # │ You can use the stack
|
||||
include libc/linux/linux.mk # │ You can manipulate arrays
|
||||
include libc/tinymath/tinymath.mk # │ You can issue raw system calls
|
||||
include third_party/compiler_rt/compiler_rt.mk # │
|
||||
include libc/bits/bits.mk # │
|
||||
include libc/str/str.mk # │
|
||||
include third_party/xed/xed.mk # │
|
||||
include third_party/zlib/zlib.mk # │
|
||||
@@ -105,24 +119,24 @@ include libc/fmt/fmt.mk #─┘
|
||||
include libc/calls/calls.mk #─┐
|
||||
include libc/runtime/runtime.mk # ├──SYSTEMS RUNTIME
|
||||
include libc/crt/crt.mk # │ You can issue system calls
|
||||
include libc/rand/rand.mk # │
|
||||
include libc/unicode/unicode.mk # │
|
||||
include third_party/dlmalloc/dlmalloc.mk #─┘
|
||||
include libc/mem/mem.mk #─┐
|
||||
include libc/ohmyplus/ohmyplus.mk # ├──DYNAMIC RUNTIME
|
||||
include libc/zipos/zipos.mk # │ You can now use stdio
|
||||
include third_party/gdtoa/gdtoa.mk # │ You can finally call malloc()
|
||||
include libc/time/time.mk # │
|
||||
include libc/alg/alg.mk # │
|
||||
include libc/zipos/zipos.mk # ├──DYNAMIC RUNTIME
|
||||
include third_party/gdtoa/gdtoa.mk # │ You can now use stdio
|
||||
include libc/time/time.mk # │ You can finally call malloc()
|
||||
include libc/thread/thread.mk # │
|
||||
include libc/stdio/stdio.mk # │
|
||||
include third_party/libcxx/libcxx.mk # │
|
||||
include net/net.mk # │
|
||||
include libc/log/log.mk # │
|
||||
include third_party/bzip2/bzip2.mk # │
|
||||
include dsp/core/core.mk # │
|
||||
include libc/x/x.mk # │
|
||||
include third_party/stb/stb.mk # │
|
||||
include dsp/scale/scale.mk # │
|
||||
include dsp/mpeg/mpeg.mk # │
|
||||
include dsp/dsp.mk # │
|
||||
include third_party/zlib/gz/gz.mk # │
|
||||
include third_party/musl/musl.mk # │
|
||||
include third_party/getopt/getopt.mk # │
|
||||
include libc/libc.mk #─┘
|
||||
@@ -133,52 +147,72 @@ include net/http/http.mk # │
|
||||
include third_party/mbedtls/mbedtls.mk # │
|
||||
include net/https/https.mk # │
|
||||
include third_party/regex/regex.mk #─┘
|
||||
include third_party/tidy/tidy.mk
|
||||
include third_party/third_party.mk
|
||||
include libc/testlib/testlib.mk
|
||||
include tool/viz/lib/vizlib.mk
|
||||
include tool/args/args.mk
|
||||
include test/tool/args/test.mk
|
||||
include third_party/linenoise/linenoise.mk
|
||||
include third_party/maxmind/maxmind.mk
|
||||
include net/finger/finger.mk
|
||||
include third_party/double-conversion/double-conversion.mk
|
||||
include third_party/lua/lua.mk
|
||||
include third_party/sed/sed.mk
|
||||
include third_party/awk/awk.mk
|
||||
include third_party/make/make.mk
|
||||
include third_party/finger/finger.mk
|
||||
include third_party/argon2/argon2.mk
|
||||
include third_party/smallz4/smallz4.mk
|
||||
include third_party/sqlite3/sqlite3.mk
|
||||
include third_party/mbedtls/test/test.mk
|
||||
include third_party/quickjs/quickjs.mk
|
||||
include third_party/lz4cli/lz4cli.mk
|
||||
include third_party/infozip/infozip.mk
|
||||
include third_party/python/python.mk
|
||||
include third_party/zip/zip.mk
|
||||
include third_party/unzip/unzip.mk
|
||||
include tool/build/lib/buildlib.mk
|
||||
include third_party/chibicc/chibicc.mk
|
||||
include third_party/chibicc/test/test.mk
|
||||
include third_party/python/python.mk
|
||||
include tool/build/emucrt/emucrt.mk
|
||||
include tool/build/emubin/emubin.mk
|
||||
include tool/build/build.mk
|
||||
include examples/examples.mk
|
||||
include examples/pyapp/pyapp.mk
|
||||
include examples/pylife/pylife.mk
|
||||
include tool/decode/lib/decodelib.mk
|
||||
include tool/decode/decode.mk
|
||||
include tool/lambda/lib/lib.mk
|
||||
include tool/lambda/lambda.mk
|
||||
include tool/plinko/lib/lib.mk
|
||||
include tool/plinko/plinko.mk
|
||||
include test/tool/plinko/test.mk
|
||||
include tool/hash/hash.mk
|
||||
include tool/net/net.mk
|
||||
include tool/viz/viz.mk
|
||||
include tool/tool.mk
|
||||
include test/libc/alg/test.mk
|
||||
include test/libc/tinymath/test.mk
|
||||
include test/libc/intrin/test.mk
|
||||
include test/libc/mem/test.mk
|
||||
include test/libc/nexgen32e/test.mk
|
||||
include test/libc/runtime/test.mk
|
||||
include test/libc/thread/test.mk
|
||||
include test/libc/sock/test.mk
|
||||
include test/libc/bits/test.mk
|
||||
include test/libc/str/test.mk
|
||||
include test/libc/unicode/test.mk
|
||||
include test/libc/log/test.mk
|
||||
include test/libc/str/test.mk
|
||||
include test/libc/calls/test.mk
|
||||
include test/libc/x/test.mk
|
||||
include test/libc/xed/test.mk
|
||||
include test/libc/fmt/test.mk
|
||||
include test/libc/dns/test.mk
|
||||
include test/libc/rand/test.mk
|
||||
include test/libc/time/test.mk
|
||||
include test/libc/stdio/test.mk
|
||||
include test/libc/release/test.mk
|
||||
include test/libc/test.mk
|
||||
include test/net/http/test.mk
|
||||
include test/net/https/test.mk
|
||||
include test/net/finger/test.mk
|
||||
include test/net/test.mk
|
||||
include test/tool/build/lib/test.mk
|
||||
include test/tool/build/test.mk
|
||||
@@ -205,55 +239,52 @@ CHECKS = $(foreach x,$(PKGS),$($(x)_CHECKS))
|
||||
|
||||
bins: $(BINS)
|
||||
check: $(CHECKS)
|
||||
test: $(TESTS) all
|
||||
test: $(TESTS)
|
||||
depend: o/$(MODE)/depend
|
||||
tags: TAGS HTAGS
|
||||
|
||||
o/$(MODE)/.x:
|
||||
@mkdir -p $(@D) && touch $@
|
||||
@$(COMPILE) -AMKDIR -tT$@ $(MKDIR) $(@D)
|
||||
|
||||
ifneq ($(findstring 4.,,$(MAKE_VERSION)),$(MAKE_VERSION))
|
||||
o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))
|
||||
$(file >$@,$(SRCS))
|
||||
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(HDRS) $(INCS),$(file >>$@,$(x)))
|
||||
$(file >$@,$(HDRS) $(INCS))
|
||||
o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(INCS) $(INCS),$(file >>$@,$(x)))
|
||||
else
|
||||
o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
|
||||
$(MAKE) MODE=rel -j8 -pn bopit 2>/dev/null | sed -ne '/^SRCS/ {s/.*:= //;s/ */\n/g;p;q}' >$@
|
||||
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
|
||||
$(MAKE) MODE=rel -j8 -pn bopit 2>/dev/null | sed -ne '/^HDRS/ {s/.*:= //;s/ */\n/g;p;q}' >$@
|
||||
o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x))))
|
||||
$(MAKE) MODE=rel -j8 -pn bopit 2>/dev/null | sed -ne '/^INCS/ {s/.*:= //;s/ */\n/g;p;q}' >$@
|
||||
endif
|
||||
|
||||
$(file >$@,$(INCS))
|
||||
o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt o/$(MODE)/incs.txt $(SRCS) $(HDRS) $(INCS)
|
||||
@$(COMPILE) -AMKDEPS $(MKDEPS) -o $@ -r o/$(MODE)/ o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt o/$(MODE)/incs.txt
|
||||
@$(COMPILE) -AMKDEPS -L320 $(MKDEPS) -o $@ -r o/$(MODE)/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt @o/$(MODE)/incs.txt
|
||||
|
||||
TAGS: o/$(MODE)/srcs.txt $(SRCS)
|
||||
@rm -f $@
|
||||
@$(COMPILE) -ATAGS -T$@ $(TAGS) $(TAGSFLAGS) -L $< -o $@
|
||||
o/$(MODE)/srcs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))
|
||||
o/$(MODE)/hdrs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
|
||||
$(file >$@) $(foreach x,$(HDRS) $(INCS),$(file >>$@,$(x)))
|
||||
|
||||
HTAGS: o/$(MODE)/hdrs.txt $(HDRS)
|
||||
@rm -f $@
|
||||
@$(COMPILE) -ATAGS -T$@ build/htags -L $< -o $@
|
||||
TAGS: .UNSANDBOXED = 1
|
||||
TAGS: o/$(MODE)/srcs-old.txt $(SRCS)
|
||||
@$(RM) $@
|
||||
@$(TAGS) $(TAGSFLAGS) -L $< -o $@
|
||||
|
||||
HTAGS: .UNSANDBOXED = 1
|
||||
HTAGS: o/$(MODE)/hdrs-old.txt $(HDRS)
|
||||
@$(RM) $@
|
||||
@build/htags -L $< -o $@
|
||||
|
||||
loc: .UNSANDBOXED = 1
|
||||
loc: o/$(MODE)/tool/build/summy.com
|
||||
find -name \*.h -or -name \*.c -or -name \*.S | \
|
||||
$(XARGS) wc -l | grep total | awk '{print $$1}' | $<
|
||||
|
||||
COSMOPOLITAN_OBJECTS = \
|
||||
NET_HTTP \
|
||||
LIBC_DNS \
|
||||
LIBC_SOCK \
|
||||
LIBC_NT_WS2_32 \
|
||||
LIBC_NT_IPHLPAPI \
|
||||
LIBC_NT_MSWSOCK \
|
||||
LIBC_OHMYPLUS \
|
||||
LIBC_X \
|
||||
THIRD_PARTY_GETOPT \
|
||||
LIBC_LOG \
|
||||
LIBC_UNICODE \
|
||||
LIBC_TIME \
|
||||
LIBC_ZIPOS \
|
||||
THIRD_PARTY_ZLIB \
|
||||
@@ -261,27 +292,26 @@ COSMOPOLITAN_OBJECTS = \
|
||||
LIBC_STDIO \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_REGEX \
|
||||
LIBC_ALG \
|
||||
LIBC_MEM \
|
||||
THIRD_PARTY_DLMALLOC \
|
||||
LIBC_BITS \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_ELF \
|
||||
LIBC_CALLS \
|
||||
LIBC_RAND \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_NT_KERNELBASE \
|
||||
LIBC_NT_SHELL32 \
|
||||
LIBC_NT_PSAPI \
|
||||
LIBC_NT_POWRPROF \
|
||||
LIBC_NT_PDH \
|
||||
LIBC_NT_GDI32 \
|
||||
LIBC_NT_COMDLG32 \
|
||||
LIBC_NT_NETAPI32 \
|
||||
LIBC_NT_URL \
|
||||
LIBC_NT_USER32 \
|
||||
LIBC_NT_NTDLL \
|
||||
LIBC_NT_ADVAPI32 \
|
||||
LIBC_FMT \
|
||||
THIRD_PARTY_COMPILER_RT \
|
||||
LIBC_THREAD \
|
||||
LIBC_TINYMATH \
|
||||
THIRD_PARTY_XED \
|
||||
LIBC_STR \
|
||||
LIBC_SYSV \
|
||||
LIBC_INTRIN \
|
||||
@@ -289,9 +319,8 @@ COSMOPOLITAN_OBJECTS = \
|
||||
LIBC_NEXGEN32E
|
||||
|
||||
COSMOPOLITAN_HEADERS = \
|
||||
APE \
|
||||
LIBC \
|
||||
LIBC_ALG \
|
||||
LIBC_BITS \
|
||||
LIBC_CALLS \
|
||||
LIBC_DNS \
|
||||
LIBC_ELF \
|
||||
@@ -301,40 +330,46 @@ COSMOPOLITAN_HEADERS = \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT \
|
||||
LIBC_OHMYPLUS \
|
||||
LIBC_RAND \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_SOCK \
|
||||
LIBC_STDIO \
|
||||
THIRD_PARTY_XED \
|
||||
LIBC_STR \
|
||||
LIBC_SYSV \
|
||||
LIBC_THREAD \
|
||||
LIBC_TIME \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_UNICODE \
|
||||
LIBC_X \
|
||||
LIBC_ZIPOS \
|
||||
NET_HTTP \
|
||||
THIRD_PARTY_DLMALLOC \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_GETOPT \
|
||||
THIRD_PARTY_MUSL \
|
||||
THIRD_PARTY_ZLIB \
|
||||
THIRD_PARTY_ZLIB_GZ \
|
||||
THIRD_PARTY_REGEX
|
||||
|
||||
o/$(MODE)/cosmopolitan.a.txt:
|
||||
printf "%s\n" $(call reverse,$(call uniq,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)))))
|
||||
o/$(MODE)/cosmopolitan.a: $(filter-out o/libc/stubs/exit11.o,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_A_OBJS)))
|
||||
o/cosmopolitan.h: \
|
||||
o/$(MODE)/tool/build/rollup.com \
|
||||
libc/integral/normalize.inc \
|
||||
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS))
|
||||
@$(COMPILE) -AROLLUP -T$@ $^ >$@
|
||||
o/$(MODE)/cosmopolitan.a: \
|
||||
$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_A_OBJS))
|
||||
|
||||
o/cosmopolitan.h: \
|
||||
o/$(MODE)/tool/build/rollup.com \
|
||||
libc/integral/normalize.inc \
|
||||
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS)) \
|
||||
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_INCS))
|
||||
$(file >$(TMPDIR)/$(subst /,_,$@),libc/integral/normalize.inc $(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS)))
|
||||
@$(COMPILE) -AROLLUP -T$@ o/$(MODE)/tool/build/rollup.com @$(TMPDIR)/$(subst /,_,$@) >$@
|
||||
|
||||
o/cosmopolitan.html: \
|
||||
o/$(MODE)/third_party/chibicc/chibicc.com.dbg \
|
||||
$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS)))
|
||||
$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))) \
|
||||
$(SRCS) \
|
||||
$(HDRS)
|
||||
$(file >$(TMPDIR)/$(subst /,_,$@),$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))))
|
||||
o/$(MODE)/third_party/chibicc/chibicc.com.dbg -J \
|
||||
-fno-common -include libc/integral/normalize.inc -o $@ \
|
||||
$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS)))
|
||||
@$(TMPDIR)/$(subst /,_,$@)
|
||||
|
||||
$(SRCS): \
|
||||
libc/integral/normalize.inc \
|
||||
@@ -368,9 +403,9 @@ $(SRCS):
|
||||
$(HDRS):
|
||||
$(INCS):
|
||||
.DEFAULT:
|
||||
@echo >&2
|
||||
@echo NOTE: deleting o/$(MODE)/depend because of an unspecified prerequisite: $@ >&2
|
||||
@echo >&2
|
||||
rm -f o/$(MODE)/depend
|
||||
@$(ECHO) >&2
|
||||
@$(ECHO) NOTE: deleting o/$(MODE)/depend because of an unspecified prerequisite: $@ >&2
|
||||
@$(ECHO) >&2
|
||||
$(RM) o/$(MODE)/depend
|
||||
|
||||
-include o/$(MODE)/depend
|
||||
@@ -1,5 +1,6 @@
|
||||

|
||||
|
||||
[](https://github.com/jart/cosmopolitan/actions/workflows/build.yml)
|
||||
# Cosmopolitan
|
||||
|
||||
[Cosmopolitan Libc](https://justine.lol/cosmopolitan/index.html) makes C
|
||||
@@ -22,27 +23,90 @@ If you're doing your development work on Linux or BSD then you need just
|
||||
five files to get started. Here's what you do on Linux:
|
||||
|
||||
```sh
|
||||
wget https://justine.lol/cosmopolitan/cosmopolitan-amalgamation-1.0.zip
|
||||
unzip cosmopolitan-amalgamation-1.0.zip
|
||||
wget https://justine.lol/cosmopolitan/cosmopolitan-amalgamation-2.0.1.zip
|
||||
unzip cosmopolitan-amalgamation-2.0.1.zip
|
||||
printf 'main() { printf("hello world\\n"); }\n' >hello.c
|
||||
gcc -g -Os -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \
|
||||
-fno-omit-frame-pointer -pg -mnop-mcount \
|
||||
-o hello.com.dbg hello.c -fuse-ld=bfd -Wl,-T,ape.lds \
|
||||
-include cosmopolitan.h crt.o ape.o cosmopolitan.a
|
||||
-fno-omit-frame-pointer -pg -mnop-mcount -mno-tls-direct-seg-refs \
|
||||
-o hello.com.dbg hello.c -fuse-ld=bfd -Wl,-T,ape.lds -Wl,--gc-sections \
|
||||
-include cosmopolitan.h crt.o ape-no-modify-self.o cosmopolitan.a
|
||||
objcopy -S -O binary hello.com.dbg hello.com
|
||||
```
|
||||
|
||||
You now have a portable program. Please note that your APE binary will
|
||||
assimilate itself as a conventional resident of your platform after the
|
||||
first run, so it can be fast and efficient for subsequent executions.
|
||||
You now have a portable program.
|
||||
|
||||
```sh
|
||||
./hello.com
|
||||
bash -c './hello.com' # zsh/fish workaround (we upstreamed patches)
|
||||
bash -c './hello.com' # zsh/fish workaround (we patched them in 2021)
|
||||
```
|
||||
|
||||
So if you intend to copy the binary to Windows or Mac then please do
|
||||
that before you run it, not after.
|
||||
If `./hello.com` executed on Linux throws an error about not finding an
|
||||
interpreter, it should be fixed by running the following command (although
|
||||
note that it may not survive a system restart):
|
||||
|
||||
```sh
|
||||
sudo sh -c "echo ':APE:M::MZqFpD::/bin/sh:' >/proc/sys/fs/binfmt_misc/register"
|
||||
```
|
||||
|
||||
If the same command produces puzzling errors on WSL or WINE when using
|
||||
Redbean 2.x, they may be fixed by disabling binfmt_misc:
|
||||
|
||||
```sh
|
||||
sudo sh -c 'echo -1 >/proc/sys/fs/binfmt_misc/status'
|
||||
```
|
||||
|
||||
Since we used the `ape-no-modify-self.o` bootloader (rather than
|
||||
`ape.o`) your executable will not modify itself when it's run. What
|
||||
it'll instead do, is extract a 4kb program to `${TMPDIR:-${HOME:-.}}`
|
||||
that maps your program into memory without needing to copy it. It's
|
||||
possible to install the APE loader systemwide as follows.
|
||||
|
||||
```sh
|
||||
# System-Wide APE Install
|
||||
# for Linux, Darwin, and BSDs
|
||||
# 1. Copies APE Loader to /usr/bin/ape
|
||||
# 2. Registers w/ binfmt_misc too if Linux
|
||||
ape/apeinstall.sh
|
||||
|
||||
# System-Wide APE Uninstall
|
||||
# for Linux, Darwin, and BSDs
|
||||
ape/apeuninstall.sh
|
||||
```
|
||||
|
||||
It's also possible to convert APE binaries into the system-local format
|
||||
by using the `--assimilate` flag. Please note that if binfmt_misc is in
|
||||
play, you'll need to unregister it temporarily before doing this, since
|
||||
the assimilate feature is part of the shell script header.
|
||||
|
||||
```sh
|
||||
$ file hello.com
|
||||
hello.com: DOS/MBR boot sector
|
||||
./hello.com --assimilate
|
||||
$ file hello.com
|
||||
hello.com: ELF 64-bit LSB executable
|
||||
```
|
||||
|
||||
Now that you're up and running with Cosmopolitan Libc and APE, here's
|
||||
some of the most important troubleshooting tools APE offers that you
|
||||
should know, in case you encounter any issues:
|
||||
|
||||
```sh
|
||||
./hello.com --strace # log system calls to stderr
|
||||
./hello.com --ftrace # log function calls to stderr
|
||||
```
|
||||
|
||||
Do you love tiny binaries? If so, you may not be happy with Cosmo adding
|
||||
heavyweight features like tracing to your binaries by default. In that
|
||||
case, you may want to consider using our build system:
|
||||
|
||||
```sh
|
||||
make -j8 MODE=tiny
|
||||
```
|
||||
|
||||
Which will cause programs such as `hello.com` and `life.com` to shrink
|
||||
from 60kb in size to about 16kb. There's also a prebuilt amalgamation
|
||||
online <https://justine.lol/cosmopolitan/cosmopolitan-tiny.zip> hosted
|
||||
on our download page <https://justine.lol/cosmopolitan/download.html>.
|
||||
|
||||
### MacOS
|
||||
|
||||
@@ -64,32 +128,137 @@ Windows](https://justine.lol/cosmopolitan/windows-compiling.html)
|
||||
tutorial. It's needed because the ELF object format is what makes
|
||||
universal binaries possible.
|
||||
|
||||
Cosmopolitan officially only builds on Linux. However, one highly
|
||||
experimental (and currently broken) thing you could try, is building the
|
||||
entire cosmo repository from source using the cross9 toolchain.
|
||||
|
||||
```
|
||||
mkdir -p o/third_party
|
||||
rm -rf o/third_party/gcc
|
||||
wget https://justine.lol/linux-compiler-on-windows/cross9.zip
|
||||
unzip cross9.zip
|
||||
mv cross9 o/third_party/gcc
|
||||
build/bootstrap/make.com
|
||||
```
|
||||
|
||||
## Source Builds
|
||||
|
||||
Cosmopolitan can be compiled from source on any Linux distro. GNU make
|
||||
needs to be installed beforehand. This is a freestanding hermetic
|
||||
repository that bootstraps using a vendored static gcc9 executable.
|
||||
No further dependencies are required.
|
||||
Cosmopolitan can be compiled from source on any Linux distro. First, you
|
||||
need to download or clone the repository.
|
||||
|
||||
```sh
|
||||
wget https://justine.lol/cosmopolitan/cosmopolitan-1.0.tar.gz
|
||||
tar xf cosmopolitan-1.0.tar.gz # see releases page
|
||||
wget https://justine.lol/cosmopolitan/cosmopolitan.tar.gz
|
||||
tar xf cosmopolitan.tar.gz # see releases page
|
||||
cd cosmopolitan
|
||||
make -j16
|
||||
```
|
||||
|
||||
This will build the entire repository and run all the tests:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com -j16
|
||||
o//examples/hello.com
|
||||
find o -name \*.com | xargs ls -rShal | less
|
||||
```
|
||||
|
||||
If you get an error running make.com then it's probably because you have
|
||||
WINE installed to `binfmt_misc`. You can fix that by installing the the
|
||||
APE loader as an interpreter. It'll improve build performance too!
|
||||
|
||||
```sh
|
||||
ape/apeinstall.sh
|
||||
```
|
||||
|
||||
Since the Cosmopolitan repository is very large, you might only want to
|
||||
build a particular thing. Cosmopolitan's build config does a good job at
|
||||
having minimal deterministic builds. For example, if you wanted to build
|
||||
only hello.com then you could do that as follows:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com -j16 o//examples/hello.com
|
||||
```
|
||||
|
||||
Sometimes it's desirable to build a subset of targets, without having to
|
||||
list out each individual one. You can do that by asking make to build a
|
||||
directory name. For example, if you wanted to build only the targets and
|
||||
subtargets of the chibicc package including its tests, you would say:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com -j16 o//third_party/chibicc
|
||||
o//third_party/chibicc/chibicc.com --help
|
||||
```
|
||||
|
||||
Cosmopolitan provides a variety of build modes. For example, if you want
|
||||
really tiny binaries (as small as 12kb in size) then you'd say:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com -j16 MODE=tiny
|
||||
```
|
||||
|
||||
Here's some other build modes you can try:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com -j16 MODE=dbg # asan + ubsan + debug
|
||||
build/bootstrap/make.com -j16 MODE=asan # production memory safety
|
||||
build/bootstrap/make.com -j16 MODE=opt # -march=native optimizations
|
||||
build/bootstrap/make.com -j16 MODE=rel # traditional release binaries
|
||||
build/bootstrap/make.com -j16 MODE=optlinux # optimal linux-only performance
|
||||
build/bootstrap/make.com -j16 MODE=tinylinux # tiniest linux-only 4kb binaries
|
||||
```
|
||||
|
||||
For further details, see [//build/config.mk](build/config.mk).
|
||||
|
||||
## GDB
|
||||
|
||||
Here's the recommended `~/.gdbinit` config:
|
||||
|
||||
```gdb
|
||||
set host-charset UTF-8
|
||||
set target-charset UTF-8
|
||||
set target-wide-charset UTF-8
|
||||
set osabi none
|
||||
set complaints 0
|
||||
set confirm off
|
||||
set history save on
|
||||
set history filename ~/.gdb_history
|
||||
define asm
|
||||
layout asm
|
||||
layout reg
|
||||
end
|
||||
define src
|
||||
layout src
|
||||
layout reg
|
||||
end
|
||||
src
|
||||
```
|
||||
|
||||
You normally run the `.com.dbg` file under gdb. If you need to debug the
|
||||
`.com` file itself, then you can load the debug symbols independently as
|
||||
|
||||
```
|
||||
gdb foo.com -ex 'add-symbol-file foo.com.dbg 0x401000'
|
||||
```
|
||||
|
||||
## Support Vector
|
||||
|
||||
| Platform | Min Version | Circa |
|
||||
| :--- | ---: | ---: |
|
||||
| AMD | K8 Venus | 2005 |
|
||||
| Intel | Core | 2006 |
|
||||
| New Technology | Vista | 2006 |
|
||||
| GNU/Systemd | 2.6.18 | 2007 |
|
||||
| XNU's Not UNIX! | 15.6 | 2018 |
|
||||
| FreeBSD | 12 | 2018 |
|
||||
| Windows | Vista | 2006 |
|
||||
| Linux | 2.6.18 | 2007 |
|
||||
| Mac OS X | 15.6 | 2018 |
|
||||
| FreeBSD | 13 | 2020 |
|
||||
| OpenBSD | 6.4 | 2018 |
|
||||
| NetBSD | 9.1 | 2020 |
|
||||
| GNU Make | 3.80 | 2010 |
|
||||
| NetBSD | 9.2 | 2021 |
|
||||
|
||||
## Special Thanks
|
||||
|
||||
Funding for this project is crowdsourced using
|
||||
[GitHub Sponsors](https://github.com/sponsors/jart) and
|
||||
[Patreon](https://www.patreon.com/jart). Your support is what makes this
|
||||
project possible. Thank you! We'd also like to give special thanks to
|
||||
the following individuals:
|
||||
|
||||
- [Joe Drumgoole](https://github.com/jdrumgoole)
|
||||
|
||||
For publicly sponsoring our work at the highest tier.
|
||||
@@ -5,16 +5,16 @@
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ above copyright notice & this permission notice appear in all copies │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL │
|
||||
│ THE AUTHOR BE LIABLE FOR ANY SPECIAL DIRECT INDIRECT, OR EVEN │
|
||||
│ CONSEQUENTIAL DAMAGE OR ANY DAMAGES WHATSOEVER RESULTING FROM │
|
||||
│ LOSS OF USE, DATA OR PROFITS WHETHER IN AN ACTION OF CONTRACT │
|
||||
│ NEGLIGENCE OR OTHER TORTIOUS ACTION, THAT ARISE OUT OF, OR IN │
|
||||
│ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. │
|
||||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
@@ -51,7 +51,7 @@
|
||||
.previous
|
||||
.section .rodata,"a",@progbits
|
||||
.align __SIZEOF_POINTER__
|
||||
__ro: .endobj __ro,globl,hidden # ←for gdb readibility
|
||||
__ro: .endobj __ro,globl,hidden # ←for gdb readability
|
||||
.previous
|
||||
.section .data,"aw",@progbits
|
||||
.align __SIZEOF_POINTER__
|
||||
@@ -60,7 +60,7 @@ __ro: .endobj __ro,globl,hidden # ←for gdb readibility
|
||||
.align __SIZEOF_POINTER__
|
||||
.previous
|
||||
.section .rodata.str1.1,"a",@progbits
|
||||
cstr: .endobj cstr,globl,hidden # ←for gdb readibility
|
||||
cstr: .endobj cstr,globl,hidden # ←for gdb readability
|
||||
.previous
|
||||
.section .head,"ax",@progbits
|
||||
|
||||
@@ -193,12 +193,12 @@ stub: mov $0x40,%dl # *literally* dos
|
||||
to a program as soon as its first sector is loaded. That gives
|
||||
us control over user-facing latency, even though the next step
|
||||
will generally be asking the BIOS to load more.
|
||||
|
||||
|
||||
The process is trivial enough that this entrypoint can support
|
||||
handoffs from alternative program-loaders e.g. Grub and MS-DOS
|
||||
so long as they either load our full program, or implement the
|
||||
PC BIOS disk service API.
|
||||
|
||||
|
||||
Since so many different implementations of these APIs have been
|
||||
built the last forty years these routines also canonicalize the
|
||||
cpu and program state, as it is written in the System V ABI. */
|
||||
@@ -250,6 +250,7 @@ pc: cld
|
||||
xor %cx,%cx # current cylinder
|
||||
xor %dh,%dh # current head
|
||||
mov $v_ape_realsectors,%di # total sectors
|
||||
sub $v_ape_realslacksectors,%di
|
||||
3: call pcread
|
||||
dec %di
|
||||
jnz 3b
|
||||
@@ -301,7 +302,21 @@ pc: cld
|
||||
// @since IBM Personal Computer XT
|
||||
dsknfo: push %bx
|
||||
1: push %dx
|
||||
mov $0x08,%ah # get disk params
|
||||
mov $0x16,%ah # make sure there is disk in drive,
|
||||
int $0x13 # by querying change-line status
|
||||
jnc 2f
|
||||
xor %ax,%ax # if error or change line active,
|
||||
int $0x13 # do a reset...
|
||||
jc 9f
|
||||
mov $0x0201,%ax # ...then do a read, to confirm that
|
||||
mov $0x0001,%cx # there is disk in drive
|
||||
mov $0,%dh # (verify (%ah = 4) does not work
|
||||
mov $IMAGE_BASE_REAL>>4,%bx # under QEMU, which always returns
|
||||
mov %bx,%es # success)
|
||||
xor %bx,%bx
|
||||
int $0x13
|
||||
jc 9f
|
||||
2: mov $0x08,%ah # get disk params
|
||||
int $0x13
|
||||
jc 9f
|
||||
mov %cl,%bh
|
||||
@@ -540,50 +555,85 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
|
||||
// modify the binary to follow the local system's convention.
|
||||
// There isn't a one-size-fits-all approach for this, thus we
|
||||
// present two choices.
|
||||
.ascii "o=\"$(command -v \"$0\")\"\n"
|
||||
// Try to use a system-wide APE loader.
|
||||
.ascii "[ x\"$1\" != x--assimilate ] && "
|
||||
.ascii "type ape >/dev/null 2>&1 && "
|
||||
.ascii "exec ape \"$o\" \"$@\"\n"
|
||||
#ifdef APE_LOADER
|
||||
// There is no system-wide APE loader, but there is one
|
||||
// embedded inside the APE. So if the system is not MacOs,
|
||||
// extract the loader into a temp folder, and use it to
|
||||
// load the APE without modifying it.
|
||||
.ascii "[ x\"$1\" != x--assimilate ] && {\n"
|
||||
.ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape\"\n"
|
||||
.ascii "[ -x \"$t\" ] || {\n"
|
||||
.ascii "mkdir -p \"${t%/*}\" &&\n"
|
||||
.ascii "dd if=\"$o\" of=\"$t.$$\" skip=\""
|
||||
.shstub ape_loader_dd_skip,2
|
||||
.ascii "\" count=\""
|
||||
.shstub ape_loader_dd_count,2
|
||||
.ascii "\" bs=64 2>/dev/null\n"
|
||||
#if SupportsXnu()
|
||||
.ascii "[ -d /Applications ] && "
|
||||
.ascii "dd if=\"$t.$$\""
|
||||
.ascii " of=\"$t.$$\""
|
||||
.ascii " skip=6"
|
||||
.ascii " count=10"
|
||||
.ascii " bs=64"
|
||||
.ascii " conv=notrunc"
|
||||
.ascii " 2>/dev/null\n"
|
||||
#endif /* SupportsXnu() */
|
||||
.ascii "chmod 755 \"$t.$$\"\n"
|
||||
.ascii "mv -f \"$t.$$\" \"$t\"\n"
|
||||
.ascii "}\n"
|
||||
.ascii "exec \"$t\" \"$o\" \"$@\"\n"
|
||||
.ascii "}\n"
|
||||
#endif /* APE_LOADER */
|
||||
#ifndef APE_NO_MODIFY_SELF
|
||||
// The default behavior is: to overwrite the header in place.
|
||||
// We prefer this because it's a tiny constant one time cost.
|
||||
// We simply printf a 64-byte header and call execve() again.
|
||||
.ascii "o=\"$(command -v \"$0\")\"\n"
|
||||
#ifdef APE_BUILDSAFE
|
||||
// This code is intended for binaries in build/bootstrap/. It
|
||||
// causes them to not self-modify since they're checked-in to
|
||||
// version control. It assumes cosmopolitan's build prefix is
|
||||
// being used by convention and that the program has the noop
|
||||
// flag -n which is used to prime the binary.
|
||||
.ascii "if [ ${o##o/} = $o ]; then\n"
|
||||
.ascii " if ! [ o/$o -nt $o ]; then\n"
|
||||
.ascii " mkdir -p o/${o%/*} || exit\n"
|
||||
.ascii " cp -f $o o/$o.$$ || exit\n"
|
||||
.ascii " o/$o.$$ -n || exit\n"
|
||||
.ascii " mv -f o/$o.$$ o/$o || exit\n"
|
||||
.ascii " fi\n"
|
||||
.ascii " exec o/$o \"$@\"\n"
|
||||
.ascii "fi\n"
|
||||
#endif
|
||||
#else
|
||||
// The alternative behavior is to copy to $TMPDIR and edit.
|
||||
// This imposes a variety of caveats of its own that should
|
||||
// be considered by the user beforehand, such as whether or
|
||||
// not /tmp is considered trustworthy on a given system, or
|
||||
// if the administrator chose to mount it with noexec. It's
|
||||
// up to the user to decide what's best in those situations
|
||||
// and also note that argv[0] and getauxval(AT_EXECFN) will
|
||||
// change as a result of this, and lastly note we don't try
|
||||
// to cleanup the tmp copies for the sake of efficiency. It
|
||||
// should also be noted that if $0 has directory components
|
||||
// then permission clashes can happen between system users,
|
||||
// since only root is able to set the sticky bit, which can
|
||||
// be addressed simply by overriding the TMPDIR environment
|
||||
.ascii "o=\"${TMPDIR:-/tmp}/$0\"\n"
|
||||
.ascii "if [ ! -e \"$o\" ]; then\n"
|
||||
.ascii "d=\"$o\"\n"
|
||||
.ascii "o=\"$o.$$\"\n"
|
||||
.ascii "mkdir -p \"${o%/*}\" 2>/dev/null\n"
|
||||
.ascii "cp -f \"$0\" \"$o\" || exit 120\n"
|
||||
// The alternative behavior is to copy to $TMPDIR or $HOME or
|
||||
// the current directory. We like TMPDIR because it's part of
|
||||
// the IEEE POSIX standard whereas alternatives (XDG) aren't.
|
||||
.ascii "t=\"${TMPDIR:-${HOME:-.}}/$0\"\n"
|
||||
.ascii "[ x\"$1\" != x--assimilate ] || [ ! -e \"$t\" ] && {\n"
|
||||
.ascii "[ x\"$1\" != x--assimilate ] && {\n"
|
||||
.ascii "mkdir -p \"${t%/*}\" 2>/dev/null\n"
|
||||
.ascii "cp -f \"$o\" \"$t.$$\" &&\n"
|
||||
.ascii "mv -f \"$t.$$\" \"$t\" || exit 120\n"
|
||||
.ascii "o=\"$t\"\n"
|
||||
.ascii "}\n"
|
||||
#endif /* APE_NO_MODIFY_SELF */
|
||||
.ascii "exec 7<> \"$o\" || exit 121\n"
|
||||
.ascii "printf '"
|
||||
.ascii "\\177ELF" # 0x0: ⌂ELF
|
||||
.ascii "\\2" # 4: long mode
|
||||
.ascii "\\1" # 5: little endian
|
||||
.ascii "\\1" # 6: elf v1.o
|
||||
.ascii "\\011" # 7: FreeBSD
|
||||
.ascii "\\0" # 8: os/abi ver.
|
||||
.ascii "\\0\\0\\0" # 9: padding 3/7
|
||||
.ascii "\\0\\0\\0\\0" # padding 4/7
|
||||
.ascii "\\2\\0" # 10: εxεcµταblε
|
||||
.ascii "\\076\\0" # 12: NexGen32e
|
||||
.ascii "\\1\\0\\0\\0" # 14: elf v1.o
|
||||
.shstub ape_elf_entry,8 # 18: e_entry
|
||||
.shstub ape_elf_phoff,8 # 20: e_phoff
|
||||
.shstub ape_elf_shoff,8 # 28: e_shoff
|
||||
.ascii "\\0\\0\\0\\0" # 30: e_flags
|
||||
.ascii "\\100\\0" # 34: e_ehsize
|
||||
.ascii "\\070\\0" # 36: e_phentsize
|
||||
.shstub ape_elf_phnum,2 # 38: e_phnum
|
||||
.ascii "\\0\\0" # 3a: e_shentsize
|
||||
.shstub ape_elf_shnum,2 # 3c: e_shnum
|
||||
.shstub ape_elf_shstrndx,2 # 3e: e_shstrndx
|
||||
.ascii "' >&7\n"
|
||||
.ascii "exec 7<&-\n"
|
||||
#if SupportsXnu()
|
||||
.ascii "if [ -d /Applications ]; then\n"
|
||||
.ascii "[ -d /Applications ] && "
|
||||
.ascii "dd if=\"$o\""
|
||||
.ascii " of=\"$o\""
|
||||
.ascii " bs=8"
|
||||
@@ -592,63 +642,43 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
|
||||
.ascii "\" count=\""
|
||||
.shstub ape_macho_dd_count,2
|
||||
.ascii "\" conv=notrunc 2>/dev/null\n"
|
||||
.ascii "el"
|
||||
#endif /* XNU */
|
||||
.ascii "if exec 7<> \"$o\"; then\n"
|
||||
.ascii "printf '"
|
||||
.ascii "\\177ELF" # 0x0: ⌂ELF
|
||||
.ascii "\\2" # 4: long mode
|
||||
.ascii "\\1" # 5: little endian
|
||||
.ascii "\\1" # 6: elf v1.o
|
||||
.ascii "\\011" # 7: FreeBSD
|
||||
.ascii "\\0" # 8: os/abi ver.
|
||||
.ascii "\\0\\0\\0" # 9: padding 3/7
|
||||
.ascii "\\0\\0\\0\\0" # padding 4/7
|
||||
.ascii "\\2\\0" # 10: εxεcµταblε
|
||||
.ascii "\\076\\0" # 12: NexGen32e
|
||||
.ascii "\\1\\0\\0\\0" # 14: elf v1.o
|
||||
.shstub ape_elf_entry,8 # 18: e_entry
|
||||
.shstub ape_elf_phoff,8 # 20: e_phoff
|
||||
.shstub ape_elf_shoff,8 # 28: e_shoff
|
||||
.ascii "\\0\\0\\0\\0" # 30: e_flags
|
||||
.ascii "\\100\\0" # 34: e_ehsize
|
||||
.ascii "\\070\\0" # 36: e_phentsize
|
||||
.shstub ape_elf_phnum,2 # 38: e_phnum
|
||||
.ascii "\\0\\0" # 3a: e_shentsize
|
||||
.shstub ape_elf_shnum,2 # 3c: e_shnum
|
||||
.shstub ape_elf_shstrndx,2 # 3e: e_shstrndx
|
||||
.ascii "' >&7\n"
|
||||
.ascii "exec 7<&-\n"
|
||||
.ascii "else\n"
|
||||
.ascii "exit 121\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "[ x\"$1\" = x--assimilate ] && exit 0\n"
|
||||
#ifndef APE_NO_MODIFY_SELF
|
||||
.ascii "exec \"$0\" \"$@\"\n" # optimistic execution
|
||||
.ascii "exec \"$0\" \"$@\"\n" # try to preserve argv[0]
|
||||
#else
|
||||
.ascii "mv -f \"$o\" \"$d\" 2>/dev/null\n"
|
||||
.ascii "o=\"$d\"\n"
|
||||
.ascii "fi\n"
|
||||
.ascii "}\n"
|
||||
.ascii "o=\"$t\"\n"
|
||||
.ascii "exec \"$o\" \"$@\"\n"
|
||||
#endif /* APE_NO_MODIFY_SELF */
|
||||
.ascii "R=$?\n"
|
||||
.ascii "\n"
|
||||
.ascii "if [ $R -eq 126 ] && [ \"$(uname -m)\" != x86_64 ]; then\n"
|
||||
.ascii "if Q=\"$(command -v qemu-x86_64)\"; then\n"
|
||||
.ascii "if [ \"$(uname -m)\" != x86_64 ]; then\n"
|
||||
.ascii "Q=\"$(command -v qemu-x86_64)\" &&\n"
|
||||
.ascii "exec \"$Q\" \"$o\" \"$@\"\n"
|
||||
.ascii "else\n"
|
||||
.ascii "echo error: need qemu-x86_64 >&2\n"
|
||||
.ascii "fi\n"
|
||||
#ifndef APE_NO_MODIFY_SELF
|
||||
.ascii "elif [ $R -eq 127 ]; then\n" # means argv[0] was wrong
|
||||
.ascii "else\n" # means argv[0] was wrong
|
||||
.ascii " exec \"$o\" \"$@\"\n" # so do a path resolution
|
||||
#endif /* APE_NO_MODIFY_SELF */
|
||||
.ascii "fi\n"
|
||||
.ascii "exit $R\n"
|
||||
.endobj apesh
|
||||
#ifdef APE_LOADER
|
||||
.section .ape.loader,"a",@progbits
|
||||
.align 64
|
||||
ape_loader:
|
||||
.incbin APE_LOADER
|
||||
.endobj ape_loader,globl
|
||||
.align 64
|
||||
ape_loader_end:
|
||||
nop
|
||||
.endobj ape_loader_end,globl
|
||||
.previous
|
||||
#endif /* APE_LOADER */
|
||||
#endif /* SupportsWindows() || SupportsMetal() || SupportsXnu() */
|
||||
|
||||
#if SupportsSystemv() || SupportsMetal()
|
||||
.section .elf.phdrs,"a",@progbits
|
||||
|
||||
.long PT_LOAD
|
||||
.long PF_R|PF_X
|
||||
.stub ape_rom_offset,quad
|
||||
@@ -657,6 +687,7 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
|
||||
.stub ape_rom_filesz,quad
|
||||
.stub ape_rom_memsz,quad
|
||||
.stub ape_rom_align,quad
|
||||
|
||||
.long PT_LOAD
|
||||
.long PF_R|PF_W
|
||||
.stub ape_ram_offset,quad
|
||||
@@ -665,14 +696,32 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang
|
||||
.stub ape_ram_filesz,quad
|
||||
.stub ape_ram_memsz,quad
|
||||
.stub ape_ram_align,quad
|
||||
|
||||
// APE Stack Configuration
|
||||
//
|
||||
// We actually respect this when allocating a deterministically
|
||||
// addressed stack on Windows and other operating systems. However
|
||||
// there's a few caveats:
|
||||
//
|
||||
// - If ape_stack_pf has PF_X then OpenBSD probably won't work
|
||||
// - We don't bother creating a deterministic stack in MODE=tiny
|
||||
//
|
||||
// With that said, here's some examples of configuration:
|
||||
//
|
||||
// STATIC_SYMBOL("ape_stack_pf", "7"); // RWX
|
||||
// STATIC_STACK_ADDR(0x6fffffff0000);
|
||||
// STATIC_STACK_SIZE(65536);
|
||||
//
|
||||
// @see ape.lds for defaults
|
||||
.long PT_GNU_STACK
|
||||
.long PF_R|PF_W
|
||||
.stub ape_stack_offset,quad
|
||||
.stub ape_stack_vaddr,quad
|
||||
.stub ape_stack_paddr,quad
|
||||
.stub ape_stack_filesz,quad
|
||||
.stub ape_stack_memsz,quad
|
||||
.stub ape_stack_align,quad
|
||||
.stub ape_stack_pf,long # override w/ PF_X for execstack
|
||||
.stub ape_stack_offset,quad # ignored
|
||||
.stub ape_stack_vaddr,quad # is mmap()'d with MAP_FIXED
|
||||
.stub ape_stack_paddr,quad # ignored
|
||||
.stub ape_stack_filesz,quad # ignored
|
||||
.stub ape_stack_memsz,quad # is mmap(size) argument
|
||||
.stub ape_stack_align,quad # must be 16+
|
||||
|
||||
#if SupportsOpenbsd() || SupportsNetbsd()
|
||||
.long PT_NOTE
|
||||
.long PF_R
|
||||
@@ -825,7 +874,7 @@ ape_macho:
|
||||
.long (520f-510f)/4 # count
|
||||
510: .quad 0 # rax
|
||||
.quad IMAGE_BASE_VIRTUAL # rbx
|
||||
.quad 0 # rcx
|
||||
.quad XNU # rcx
|
||||
.quad 0 # rdx
|
||||
.quad 0 # rdi
|
||||
.quad 0 # rsi
|
||||
@@ -839,7 +888,7 @@ ape_macho:
|
||||
.quad 0 # r13
|
||||
.quad 0 # r14
|
||||
.quad 0 # r15
|
||||
.quad _xnu # rip
|
||||
.quad _start # rip
|
||||
.quad 0 # rflags
|
||||
.quad 0 # cs
|
||||
.quad 0 # fs
|
||||
@@ -876,7 +925,7 @@ ape_macho:
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § the new technology ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│─╝
|
||||
The Portable Executable Format
|
||||
|
||||
|
||||
@see https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format
|
||||
@see "The Portable Executable File Format from Top to Bottom",
|
||||
Randy Kath, Microsoft Developer Network Technology Group. */
|
||||
@@ -923,7 +972,7 @@ DLLEXE = DLLSTD
|
||||
// ││││││││ │ │┌6:Contains Initialized Data
|
||||
// ││││││││ o │ ││┌5:Contains Code
|
||||
// ││││││││┌┴─┐rrrr│ ooror│││rorrr
|
||||
PETEXT = 0b01110000000000000000000001100000
|
||||
PETEXT = 0b01100000000000000000000001100000
|
||||
PEDATA = 0b11000000000000000000000011000000
|
||||
PEIMPS = 0b11000000000000000000000001000000
|
||||
|
||||
@@ -1059,18 +1108,12 @@ str.error:
|
||||
str.crlf:
|
||||
.asciz "\r\n"
|
||||
.endobj str.crlf
|
||||
str.cpuid:
|
||||
.asciz "cpuid"
|
||||
.endobj str.cpuid
|
||||
str.oldskool:
|
||||
.asciz "oldskool"
|
||||
.endobj str.oldskool
|
||||
str.e820:
|
||||
.asciz "e820"
|
||||
.endobj str.e820
|
||||
str.long:
|
||||
.asciz "nolong"
|
||||
.endobj str.long
|
||||
str.oldcpu:
|
||||
.asciz "oldcpu"
|
||||
.endobj str.oldcpu
|
||||
|
||||
// Serial Line Configuration (8250 UART 16550)
|
||||
// If it's hacked, it'll at least get hacked very slowly.
|
||||
@@ -1131,47 +1174,6 @@ gdt: .short 2f-1f # table byte length
|
||||
.quad 0b0000000010101111100100110000000000000000000000001111111111111111 #48
|
||||
2: .endobj gdt,global,hidden
|
||||
|
||||
/*─────────────────────────────────────────────────────────────────────────────╗
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § multiboot stub │
|
||||
╚──────────────────────────────────────────────────────────────────────────────╝
|
||||
boot modernized for the nineties */
|
||||
|
||||
#define GRUB_MAGIC 0x1BADB002
|
||||
#define GRUB_EAX 0x2BADB002
|
||||
#define GRUB_AOUT (1 << 16)
|
||||
#define GRUB_CHECKSUM(FLAGS) (-(GRUB_MAGIC + (FLAGS)) & 0xffffffff)
|
||||
|
||||
// Grub Header.
|
||||
.align 4
|
||||
ape_grub:
|
||||
.long GRUB_MAGIC # Magic
|
||||
.long GRUB_AOUT # Flags
|
||||
.long GRUB_CHECKSUM(GRUB_AOUT) # Checksum
|
||||
.long RVA(ape_grub) # HeaderPhysicalAddress
|
||||
.long IMAGE_BASE_PHYSICAL # TextPhysicalAddress
|
||||
.long PHYSICAL(_edata) # LoadEndPhysicalAddress
|
||||
.long PHYSICAL(_end) # BssEndPhysicalAddress
|
||||
.long RVA(ape_grub_entry) # EntryPhysicalAddress
|
||||
.endobj ape_grub,globl
|
||||
|
||||
// Grub Entrypoint.
|
||||
// Takes CPU out of legacy mode and jumps to normal entrypoint.
|
||||
// @noreturn
|
||||
.align 4
|
||||
ape_grub_entry:
|
||||
.code32
|
||||
// cmp $GRUB_EAX,%eax
|
||||
// jne triplf
|
||||
push $0
|
||||
popf
|
||||
mov $0x40,%dl
|
||||
mov %cr0,%eax
|
||||
and $~CR0_PE,%eax
|
||||
mov %eax,%cr0
|
||||
ljmpw $0,$REAL(pc)
|
||||
.code16
|
||||
.endfn ape_grub_entry
|
||||
|
||||
/*─────────────────────────────────────────────────────────────────────────────╗
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § real mode │
|
||||
╚──────────────────────────────────────────────────────────────────────────────╝
|
||||
@@ -1253,7 +1255,7 @@ longmodeloader:
|
||||
lcheck: pushf # check for i8086 / i8088 / i80186
|
||||
pop %ax
|
||||
test $0x80,%ah # see intel manual volume 1 20.1.2
|
||||
jnz 9f # we now assume 32bit is supported
|
||||
jnz 10f # we now assume 32bit is supported
|
||||
pushfl # now check for i386 or early i486
|
||||
pop %eax # test ability to change cpuid bit
|
||||
mov %eax,%ecx
|
||||
@@ -1264,7 +1266,7 @@ lcheck: pushf # check for i8086 / i8088 / i80186
|
||||
pushfl
|
||||
pop %eax
|
||||
cmp %eax,%ecx
|
||||
je 12f # we assume cpuid inst is available
|
||||
je 10f # we assume cpuid inst is available
|
||||
or %ebx,%eax # puts cpuid bit in the on position
|
||||
push %eax
|
||||
popfl
|
||||
@@ -1282,11 +1284,7 @@ lcheck: pushf # check for i8086 / i8088 / i80186
|
||||
jne 10f
|
||||
xor %ax,%ax
|
||||
1: ret
|
||||
9: mov $REAL(str.oldskool),%di
|
||||
jmp 20f
|
||||
10: mov $REAL(str.long),%di
|
||||
jmp 20f
|
||||
12: mov $REAL(str.cpuid),%di
|
||||
10: mov $REAL(str.oldcpu),%di
|
||||
20: call rldie
|
||||
.endfn lcheck
|
||||
|
||||
@@ -1452,6 +1450,47 @@ long: push $GDT_LONG_DATA
|
||||
jmp *%rax
|
||||
.endfn long
|
||||
|
||||
/*─────────────────────────────────────────────────────────────────────────────╗
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § multiboot stub │
|
||||
╚──────────────────────────────────────────────────────────────────────────────╝
|
||||
boot modernized for the nineties */
|
||||
|
||||
#define GRUB_MAGIC 0x1BADB002
|
||||
#define GRUB_EAX 0x2BADB002
|
||||
#define GRUB_AOUT (1 << 16)
|
||||
#define GRUB_CHECKSUM(FLAGS) (-(GRUB_MAGIC + (FLAGS)) & 0xffffffff)
|
||||
|
||||
// Grub Header.
|
||||
.align 4
|
||||
ape_grub:
|
||||
.long GRUB_MAGIC # Magic
|
||||
.long GRUB_AOUT # Flags
|
||||
.long GRUB_CHECKSUM(GRUB_AOUT) # Checksum
|
||||
.long RVA(ape_grub) # HeaderPhysicalAddress
|
||||
.long IMAGE_BASE_PHYSICAL # TextPhysicalAddress
|
||||
.long PHYSICAL(_edata) # LoadEndPhysicalAddress
|
||||
.long PHYSICAL(_end) # BssEndPhysicalAddress
|
||||
.long RVA(ape_grub_entry) # EntryPhysicalAddress
|
||||
.endobj ape_grub,globl
|
||||
|
||||
// Grub Entrypoint.
|
||||
// Takes CPU out of legacy mode and jumps to normal entrypoint.
|
||||
// @noreturn
|
||||
.align 4
|
||||
ape_grub_entry:
|
||||
.code32
|
||||
// cmp $GRUB_EAX,%eax
|
||||
// jne triplf
|
||||
push $0
|
||||
popf
|
||||
mov $0x40,%dl
|
||||
mov %cr0,%eax
|
||||
and $~CR0_PE,%eax
|
||||
mov %eax,%cr0
|
||||
ljmpw $0,$REAL(pc)
|
||||
.code64
|
||||
.endfn ape_grub_entry
|
||||
|
||||
/* ▄▄▒▀▀▀▀▒▒▄
|
||||
█████▓▓▄░░░░ ▒▒▄
|
||||
▐█▓▓█▓▄█████▓░ ▀▒▄
|
||||
@@ -1487,12 +1526,9 @@ kernel: movabs $ape_stack_vaddr,%rsp
|
||||
.byte 0x0f,0x1f,0207 # nop rdi binbase
|
||||
.long (IMAGE_BASE_VIRTUAL-IMAGE_BASE_REAL)/512
|
||||
#endif
|
||||
.weak __hostos
|
||||
ezlea __hostos,ax
|
||||
test %rax,%rax
|
||||
jz 1f
|
||||
movb $METAL,(%rax)
|
||||
1: push $0
|
||||
push $METAL # sets __hostos in crt.S
|
||||
pop %rcx
|
||||
push $0
|
||||
mov %rsp,%rbp
|
||||
mov .Lenv0(%rip),%rax
|
||||
mov %rax,(%rbp) # envp[0][0]
|
||||
@@ -1508,7 +1544,6 @@ kernel: movabs $ape_stack_vaddr,%rsp
|
||||
push $1 # argc
|
||||
xor %ebp,%ebp
|
||||
xor %eax,%eax
|
||||
xor %ecx,%ecx
|
||||
xor %edx,%edx
|
||||
xor %edi,%edi
|
||||
xor %esi,%esi
|
||||
@@ -1533,6 +1568,7 @@ kernel: movabs $ape_stack_vaddr,%rsp
|
||||
.ldsvar _end
|
||||
.ldsvar _etext
|
||||
.ldsvar v_ape_realsectors
|
||||
.ldsvar v_ape_realslacksectors
|
||||
.ldsvar v_ape_highsectors
|
||||
.ldsvar ape_idata_ro
|
||||
.ldsvar ape_pad_rodata
|
||||
@@ -1549,6 +1585,7 @@ kernel: movabs $ape_stack_vaddr,%rsp
|
||||
.type __test_end,@object
|
||||
|
||||
.section .commentprologue,"a",@progbits
|
||||
.globl kLegalNotices
|
||||
.type kLegalNotices,@object
|
||||
.hidden kLegalNotices
|
||||
kLegalNotices:/*
|
||||
@@ -1576,6 +1613,7 @@ ape_pad_text:
|
||||
.type ape_pad_privileged,@object
|
||||
.hidden ape_pad_privileged
|
||||
ape_pad_privileged:
|
||||
.align 4096
|
||||
.previous
|
||||
|
||||
.section .ape.pad.rodata,"a",@progbits
|
||||
@@ -1603,5 +1641,26 @@ ape_idata_ro:
|
||||
__data_start:
|
||||
.previous
|
||||
|
||||
.section .dataepilogue,"aw",@progbits
|
||||
.type __data_end,@object
|
||||
.globl __data_end
|
||||
.hidden __data_end
|
||||
__data_end:
|
||||
.previous
|
||||
|
||||
.section .bssprologue,"aw",@nobits
|
||||
.type __bss_start,@object
|
||||
.globl __bss_start
|
||||
.hidden __bss_start
|
||||
__bss_start:
|
||||
.previous
|
||||
|
||||
.section .bssepilogue,"aw",@nobits
|
||||
.type __bss_end,@object
|
||||
.globl __bss_end
|
||||
.hidden __bss_end
|
||||
__bss_end:
|
||||
.previous
|
||||
|
||||
.end
|
||||
|
||||
+105
-45
@@ -177,16 +177,20 @@
|
||||
#include "ape/macros.internal.h"
|
||||
#include "ape/relocations.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/elf/def.h"
|
||||
#include "libc/elf/pf2prot.internal.h"
|
||||
#include "libc/nt/pedef.internal.h"
|
||||
#include "libc/zip.h"
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS {
|
||||
Head PT_LOAD FLAGS(5);
|
||||
Rom PT_LOAD FLAGS(5);
|
||||
Ram PT_LOAD FLAGS(6);
|
||||
stack PT_GNU_STACK FLAGS(6);
|
||||
Head PT_LOAD FLAGS(PF_X|PF_R);
|
||||
Rom PT_LOAD FLAGS(PF_X|PF_R);
|
||||
Ram PT_LOAD FLAGS(PF_W|PF_R);
|
||||
Tls PT_TLS FLAGS(PF_W|PF_R);
|
||||
Bss PT_LOAD FLAGS(PF_W|PF_R);
|
||||
stack PT_GNU_STACK FLAGS(PF_W|PF_R);
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
@@ -237,13 +241,16 @@ SECTIONS {
|
||||
/*BEGIN: nt addressability guarantee */
|
||||
|
||||
.text . : {
|
||||
BYTE(0x90) /* TODO: fix blinkenlights symbol __map_phdrs */
|
||||
/* Code that needs to be addressable in Real Mode */
|
||||
*(.text.real)
|
||||
KEEP(*(SORT_BY_NAME(.sort.text.real.*)))
|
||||
/* Code we want earlier in the binary w/o modifications */
|
||||
KEEP(*(.ape.loader))
|
||||
HIDDEN(_ereal = .);
|
||||
. += 1;
|
||||
|
||||
/*END: realmode addressability guarantee */
|
||||
/*BEGIN: morphable code */
|
||||
. += 1;
|
||||
|
||||
/* Normal Code */
|
||||
*(.start)
|
||||
@@ -280,6 +287,7 @@ SECTIONS {
|
||||
/* Privileged code invulnerable to magic */
|
||||
KEEP(*(.ape.pad.privileged));
|
||||
. += . > 0 ? 1 : 0;
|
||||
/*END: morphable code */
|
||||
HIDDEN(__privileged_start = .);
|
||||
. += . > 0 ? 1 : 0;
|
||||
*(.privileged)
|
||||
@@ -289,6 +297,9 @@ SECTIONS {
|
||||
/*BEGIN: Read Only Data */
|
||||
|
||||
KEEP(*(.ape.pad.rodata));
|
||||
KEEP(*(.rodata.pytab.0));
|
||||
KEEP(*(.rodata.pytab.1));
|
||||
KEEP(*(.rodata.pytab.2));
|
||||
|
||||
*(.rodata .rodata.*)
|
||||
*(.ubsan.types)
|
||||
@@ -339,8 +350,10 @@ SECTIONS {
|
||||
/*END: Read Only Data */
|
||||
} :Rom
|
||||
|
||||
.data . : {
|
||||
.data ALIGN(PAGESIZE) : {
|
||||
/*BEGIN: Read/Write Data */
|
||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.iat.*)))
|
||||
/*BEGIN: NT FORK COPYING */
|
||||
KEEP(*(.dataprologue))
|
||||
*(.data .data.*)
|
||||
KEEP(*(SORT_BY_NAME(.sort.data.*)))
|
||||
@@ -361,23 +374,44 @@ SECTIONS {
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
|
||||
KEEP(*(.piro.pad.data))
|
||||
. = ALIGN(PAGESIZE);
|
||||
KEEP(*(.dataepilogue))
|
||||
/*END: NT FORK COPYING */
|
||||
HIDDEN(_edata = .);
|
||||
PROVIDE_HIDDEN(edata = .);
|
||||
KEEP(*(SORT_BY_NAME(.zip.*)))
|
||||
HIDDEN(_ezip = .);
|
||||
. = ALIGN(PAGESIZE);
|
||||
} :Ram
|
||||
. = ALIGN(PAGESIZE);
|
||||
|
||||
.tdata . : {
|
||||
_tdata_start = .;
|
||||
*(SORT_BY_ALIGNMENT(.tdata))
|
||||
*(SORT_BY_ALIGNMENT(.tdata.*))
|
||||
. = ALIGN(16);
|
||||
_tdata_end = .;
|
||||
. = ALIGN(PAGESIZE);
|
||||
} :Tls :Ram
|
||||
. = ALIGN(PAGESIZE);
|
||||
|
||||
/*END: file content that's loaded by o/s */
|
||||
/*BEGIN: bss memory void */
|
||||
|
||||
.zip . : {
|
||||
KEEP(*(SORT_BY_NAME(.zip.*)))
|
||||
HIDDEN(_ezip = .);
|
||||
}
|
||||
.tbss . : {
|
||||
_tbss_start = .;
|
||||
*(SORT_BY_ALIGNMENT(.tbss))
|
||||
*(SORT_BY_ALIGNMENT(.tbss.*))
|
||||
. = ALIGN(16);
|
||||
/* the %fs register is based on this location */
|
||||
_tbss_end = .;
|
||||
} :Tls
|
||||
|
||||
/*END: file content */
|
||||
/*BEGIN: bss memory that's addressable */
|
||||
|
||||
.bss ALIGN(64) : {
|
||||
/*BEGIN: NT FORK COPYING */
|
||||
KEEP(*(.bssprologue))
|
||||
KEEP(*(SORT_BY_NAME(.piro.bss.init.*)))
|
||||
*(.piro.bss)
|
||||
KEEP(*(SORT_BY_NAME(.piro.bss.sort.*)))
|
||||
@@ -392,10 +426,12 @@ SECTIONS {
|
||||
|
||||
KEEP(*(SORT_BY_NAME(.sort.bss.*)))
|
||||
|
||||
KEEP(*(.bssepilogue))
|
||||
/*END: NT FORK COPYING */
|
||||
. = ALIGN(FRAMESIZE); /* for brk()/sbrk() allocation */
|
||||
HIDDEN(_end = .);
|
||||
PROVIDE_HIDDEN(end = .);
|
||||
}
|
||||
} :Bss
|
||||
|
||||
/*END: nt addressability guarantee */
|
||||
/*END: bsd addressability guarantee */
|
||||
@@ -451,9 +487,13 @@ PFSTUB4(ape_elf_phnum, (ape_phdrs_end - ape_phdrs) / 56);
|
||||
PFSTUB4(ape_elf_shnum, 0);
|
||||
PFSTUB4(ape_elf_shstrndx, 0);
|
||||
|
||||
HIDDEN(__privileged_addr = ROUNDDOWN(__privileged_start, PAGESIZE));
|
||||
HIDDEN(_tdata_size = _tdata_end - _tdata_start);
|
||||
HIDDEN(_tls_size = _tbss_end - _tdata_start);
|
||||
HIDDEN(_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start));
|
||||
|
||||
HIDDEN(__privileged_addr = ROUNDDOWN(__privileged_start, PAGESIZE));
|
||||
HIDDEN(__privileged_size = (ROUNDUP(__privileged_end, PAGESIZE) -
|
||||
ROUNDDOWN(__privileged_start, PAGESIZE)));
|
||||
ROUNDDOWN(__privileged_start, PAGESIZE)));
|
||||
|
||||
HIDDEN(ape_rom_offset = 0);
|
||||
HIDDEN(ape_rom_vaddr = ADDR(.head));
|
||||
@@ -466,16 +506,18 @@ HIDDEN(ape_rom_rva = RVA(ape_rom_vaddr));
|
||||
HIDDEN(ape_ram_offset = ape_rom_offset + ape_rom_filesz);
|
||||
HIDDEN(ape_ram_vaddr = ADDR(.data));
|
||||
HIDDEN(ape_ram_paddr = LOADADDR(.data));
|
||||
HIDDEN(ape_ram_filesz = SIZEOF(.data));
|
||||
HIDDEN(ape_ram_filesz = SIZEOF(.data) + SIZEOF(.tdata));
|
||||
HIDDEN(ape_ram_memsz = ADDR(.bss) + SIZEOF(.bss) - ape_ram_vaddr);
|
||||
HIDDEN(ape_ram_align = PAGESIZE);
|
||||
HIDDEN(ape_ram_rva = RVA(ape_ram_vaddr));
|
||||
|
||||
HIDDEN(ape_stack_pf = DEFINED(ape_stack_pf) ? ape_stack_pf : PF_R | PF_W);
|
||||
HIDDEN(ape_stack_prot = _PF2PROT(ape_stack_pf));
|
||||
HIDDEN(ape_stack_offset = ape_ram_offset + ape_ram_filesz);
|
||||
HIDDEN(ape_stack_vaddr = 0x700000000000 - STACKSIZE);
|
||||
HIDDEN(ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000);
|
||||
HIDDEN(ape_stack_paddr = ape_ram_paddr + ape_ram_filesz);
|
||||
HIDDEN(ape_stack_filesz = 0);
|
||||
HIDDEN(ape_stack_memsz = STACKSIZE);
|
||||
HIDDEN(ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : STACKSIZE);
|
||||
HIDDEN(ape_stack_align = 16);
|
||||
|
||||
HIDDEN(ape_note_offset = ape_rom_offset + (ape_note - ape_rom_vaddr));
|
||||
@@ -496,8 +538,8 @@ HIDDEN(ape_text_rva = RVA(ape_text_vaddr));
|
||||
HIDDEN(ape_data_offset = ape_ram_offset + LOADADDR(.data) - ape_ram_paddr);
|
||||
HIDDEN(ape_data_paddr = LOADADDR(.data));
|
||||
HIDDEN(ape_data_vaddr = ADDR(.data));
|
||||
HIDDEN(ape_data_filesz = SIZEOF(.data));
|
||||
HIDDEN(ape_data_memsz = SIZEOF(.data));
|
||||
HIDDEN(ape_data_filesz = SIZEOF(.data) + SIZEOF(.tdata));
|
||||
HIDDEN(ape_data_memsz = SIZEOF(.data) + SIZEOF(.tdata));
|
||||
HIDDEN(ape_data_align = PAGESIZE);
|
||||
HIDDEN(ape_data_rva = RVA(ape_data_vaddr));
|
||||
|
||||
@@ -508,36 +550,22 @@ HIDDEN(ape_bss_filesz = 0);
|
||||
HIDDEN(ape_bss_memsz = SIZEOF(.bss));
|
||||
HIDDEN(ape_bss_align = PAGESIZE);
|
||||
|
||||
#if SupportsXnu()
|
||||
SHSTUB2(ape_macho_dd_skip, RVA(ape_macho) / 8);
|
||||
SHSTUB2(ape_macho_dd_count, (ape_macho_end - ape_macho) / 8);
|
||||
#endif
|
||||
|
||||
#if SupportsWindows() || SupportsMetal()
|
||||
#define LINK_WINDOWS (SupportsWindows() && !DEFINED(EfiMain))
|
||||
PFSTUB4(ape_pe_offset, ape_pe - ape_mz);
|
||||
HIDDEN(ape_pe_optsz = ape_pe_sections - (ape_pe + 24));
|
||||
HIDDEN(ape_pe_shnum = (ape_pe_sections_end - ape_pe_sections) / 40);
|
||||
HIDDEN(ape_pe_base = IMAGE_BASE_VIRTUAL);
|
||||
HIDDEN(ape_idata = LINK_WINDOWS ? RVA(ape_idata_iat) : 0);
|
||||
HIDDEN(ape_idata_iatsize = LINK_WINDOWS ? ape_idata_iatend - ape_idata_iat : 0);
|
||||
HIDDEN(ape_idata = LINK_WINDOWS ? RVA(ape_idata_idt) : 0);
|
||||
HIDDEN(ape_idata_idtsize = LINK_WINDOWS ? ape_idata_idtend - ape_idata_idt : 0);
|
||||
HIDDEN(v_ntversion = LINK_WINDOWS ? 6 : 1);
|
||||
HIDDEN(v_ntdllchar = LINK_WINDOWS ? 288 : 0);
|
||||
HIDDEN(v_ntsubversion = LINK_WINDOWS ? 6 : 5);
|
||||
HIDDEN(v_ntsubsystem = (LINK_WINDOWS
|
||||
? (DEFINED(GetMessage)
|
||||
? kNtImageSubsystemWindowsGui
|
||||
: kNtImageSubsystemWindowsCui)
|
||||
: kNtImageSubsystemEfiApplication));
|
||||
HIDDEN(ape_pe_entry = LINK_WINDOWS ? WinMain : EfiMain);
|
||||
#endif
|
||||
/* we roundup here because xnu wants the file load segments page-aligned */
|
||||
/* but we don't want to add the nop padding to the ape program, so we'll */
|
||||
/* let ape.S dd read past the end of the file into the wrapping binaries */
|
||||
SHSTUB2(ape_loader_dd_skip, DEFINED(ape_loader) ? RVA(ape_loader) / 64 : 0);
|
||||
SHSTUB2(ape_loader_dd_count,
|
||||
DEFINED(ape_loader_end)
|
||||
? ROUNDUP(ape_loader_end - ape_loader, PAGESIZE) / 64
|
||||
: 0);
|
||||
|
||||
#if SupportsMetal()
|
||||
HIDDEN(v_ape_realsectors =
|
||||
MIN(0x70000 - IMAGE_BASE_REAL,
|
||||
ROUNDUP(RVA(_edata), 4096)) / 512);
|
||||
HIDDEN(v_ape_realslacksectors =
|
||||
v_ape_realsectors - MIN(0x70000 - IMAGE_BASE_REAL,
|
||||
ROUNDUP(RVA(_edata), 512)) / 512);
|
||||
HIDDEN(v_ape_realpages = v_ape_realsectors / (4096 / 512));
|
||||
HIDDEN(v_ape_highsectors =
|
||||
(ROUNDUP(RVA(_edata), 512) / 512) - v_ape_realsectors);
|
||||
@@ -640,6 +668,32 @@ CHURN(WinMain);
|
||||
#endif /* SupportsWindows() */
|
||||
#endif /* SupportsXnu() */
|
||||
|
||||
#if SupportsWindows() || SupportsMetal()
|
||||
#define LINK_WINDOWS (SupportsWindows() && !DEFINED(EfiMain))
|
||||
PFSTUB4(ape_pe_offset, ape_pe - ape_mz);
|
||||
HIDDEN(ape_pe_optsz = ape_pe_sections - (ape_pe + 24));
|
||||
HIDDEN(ape_pe_shnum = (ape_pe_sections_end - ape_pe_sections) / 40);
|
||||
HIDDEN(ape_pe_base = IMAGE_BASE_VIRTUAL);
|
||||
HIDDEN(ape_idata = LINK_WINDOWS ? RVA(ape_idata_iat) : 0);
|
||||
HIDDEN(ape_idata_iatsize = LINK_WINDOWS ? ape_idata_iatend - ape_idata_iat : 0);
|
||||
HIDDEN(ape_idata = LINK_WINDOWS ? RVA(ape_idata_idt) : 0);
|
||||
HIDDEN(ape_idata_idtsize = LINK_WINDOWS ? ape_idata_idtend - ape_idata_idt : 0);
|
||||
HIDDEN(v_ntversion = LINK_WINDOWS ? 6 : 1);
|
||||
HIDDEN(v_ntdllchar = LINK_WINDOWS ? 288 : 0);
|
||||
HIDDEN(v_ntsubversion = LINK_WINDOWS ? 6 : 5);
|
||||
HIDDEN(v_ntsubsystem = (LINK_WINDOWS
|
||||
? (DEFINED(GetMessage)
|
||||
? kNtImageSubsystemWindowsGui
|
||||
: kNtImageSubsystemWindowsCui)
|
||||
: kNtImageSubsystemEfiApplication));
|
||||
HIDDEN(ape_pe_entry = LINK_WINDOWS ? WinMain : EfiMain);
|
||||
#endif
|
||||
|
||||
#if SupportsXnu()
|
||||
SHSTUB2(ape_macho_dd_skip, RVA(ape_macho) / 8);
|
||||
SHSTUB2(ape_macho_dd_count, (ape_macho_end - ape_macho) / 8);
|
||||
#endif
|
||||
|
||||
ASSERT(DEFINED(ape_mz) ? ape_mz == IMAGE_BASE_VIRTUAL : 1, "linker panic");
|
||||
ASSERT((DEFINED(__init_bss_end) ? __init_bss_end : 0) % __SIZEOF_POINTER__ == 0,
|
||||
"__init_bss misalign");
|
||||
@@ -656,6 +710,12 @@ ASSERT(DEFINED(_start) || DEFINED(_start16),
|
||||
ASSERT(!DEFINED(_start16) || REAL(_end) < 65536,
|
||||
"ape won't support non-tiny real mode programs");
|
||||
|
||||
ASSERT(IS2POW(ape_stack_memsz),
|
||||
"ape_stack_memsz must be a two power");
|
||||
|
||||
ASSERT(!(ape_stack_vaddr & (ape_stack_memsz - 1)),
|
||||
"ape_stack_vaddr must have ape_stack_memsz alignment; try using STATIC_STACK_ADDR(0x700000000000 - ape_stack_memsz);");
|
||||
|
||||
/* Let's not be like Knight Capital. */
|
||||
/* NOCROSSREFS_TO(.test .text) */
|
||||
|
||||
|
||||
+129
-27
@@ -15,49 +15,151 @@
|
||||
|
||||
PKGS += APE
|
||||
|
||||
APE = $(APE_DEPS) \
|
||||
$(APE_OBJS) \
|
||||
APE = o/$(MODE)/ape/ape.o \
|
||||
o/$(MODE)/ape/ape.lds
|
||||
|
||||
APE_BUILDSAFE = \
|
||||
$(APE_DEPS) \
|
||||
o/$(MODE)/ape/ape-buildsafe.o \
|
||||
o/$(MODE)/ape/ape.lds
|
||||
APE_NO_MODIFY_SELF = \
|
||||
o/$(MODE)/ape/ape.lds \
|
||||
o/$(MODE)/ape/ape-no-modify-self.o
|
||||
|
||||
APELINK = \
|
||||
$(COMPILE) \
|
||||
-ALINK.ape \
|
||||
$(LINK) \
|
||||
$(LINKARGS) \
|
||||
APE_COPY_SELF = \
|
||||
o/$(MODE)/ape/ape.lds \
|
||||
o/$(MODE)/ape/ape-copy-self.o
|
||||
|
||||
APELINK = \
|
||||
$(COMPILE) \
|
||||
-ALINK.ape \
|
||||
$(LINK) \
|
||||
$(LINKARGS) \
|
||||
$(OUTPUT_OPTION)
|
||||
|
||||
APE_LOADER_FLAGS = \
|
||||
-DNDEBUG \
|
||||
-iquote. \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-fpie \
|
||||
-Os \
|
||||
-ffreestanding \
|
||||
-mgeneral-regs-only \
|
||||
-mno-red-zone \
|
||||
-fno-ident \
|
||||
-fno-gnu-unique \
|
||||
-c \
|
||||
$(OUTPUT_OPTION) \
|
||||
$<
|
||||
|
||||
APE_FILES := $(wildcard ape/*.*)
|
||||
APE_HDRS = $(filter %.h,$(APE_FILES))
|
||||
APE_INCS = $(filter %.inc,$(APE_FILES))
|
||||
APE_SRCS = $(filter %.S,$(APE_FILES))
|
||||
APE_OBJS = $(APE_SRCS:%.S=o/$(MODE)/%.o)
|
||||
APE_SRCS_C = ape/loader.c
|
||||
APE_SRCS_S = $(filter %.S,$(APE_FILES))
|
||||
APE_SRCS = $(APE_SRCS_C) $(APE_SRCS_S)
|
||||
APE_OBJS = $(APE_SRCS_S:%.S=o/$(MODE)/%.o)
|
||||
APE_CHECKS = $(APE_HDRS:%=o/%.ok)
|
||||
|
||||
o/$(MODE)/ape/ape.lds: \
|
||||
ape/ape.lds \
|
||||
ape/macros.internal.h \
|
||||
libc/dce.h \
|
||||
o/$(MODE)/ape/ape.lds: \
|
||||
ape/ape.lds \
|
||||
ape/macros.internal.h \
|
||||
ape/relocations.h \
|
||||
libc/intrin/bits.h \
|
||||
libc/calls/struct/timespec.h \
|
||||
libc/dce.h \
|
||||
libc/elf/def.h \
|
||||
libc/elf/pf2prot.internal.h \
|
||||
libc/macros.internal.h \
|
||||
libc/nt/pedef.internal.h \
|
||||
libc/str/str.h \
|
||||
libc/zip.h
|
||||
|
||||
o/ape/idata.inc: \
|
||||
ape/idata.internal.h \
|
||||
o/ape/idata.inc: \
|
||||
ape/idata.internal.h \
|
||||
ape/relocations.h
|
||||
|
||||
$(APE_OBJS): $(BUILD_FILES) \
|
||||
ape/ape.mk
|
||||
o/$(MODE)/ape/ape-no-modify-self.o: \
|
||||
ape/ape.S \
|
||||
ape/macros.internal.h \
|
||||
ape/notice.inc \
|
||||
ape/relocations.h \
|
||||
libc/dce.h \
|
||||
libc/elf/def.h \
|
||||
libc/intrin/asancodes.h \
|
||||
libc/macho.internal.h \
|
||||
libc/macros.internal.h \
|
||||
libc/nexgen32e/uart.internal.h \
|
||||
libc/nexgen32e/vidya.internal.h \
|
||||
libc/nt/pedef.internal.h \
|
||||
libc/runtime/e820.internal.h \
|
||||
libc/runtime/mman.internal.h \
|
||||
libc/runtime/pc.internal.h \
|
||||
libc/runtime/symbolic.h \
|
||||
libc/sysv/consts/prot.h \
|
||||
o/$(MODE)/ape/ape.elf
|
||||
@$(COMPILE) \
|
||||
-AOBJECTIFY.S \
|
||||
$(OBJECTIFY.S) \
|
||||
$(OUTPUT_OPTION) \
|
||||
-DAPE_NO_MODIFY_SELF \
|
||||
-DAPE_LOADER='"o/$(MODE)/ape/ape.elf"' $<
|
||||
|
||||
o/$(MODE)/ape/ape-no-modify-self.o: ape/ape.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -DAPE_NO_MODIFY_SELF $<
|
||||
o/$(MODE)/ape/ape-copy-self.o: \
|
||||
ape/ape.S \
|
||||
ape/macros.internal.h \
|
||||
ape/notice.inc \
|
||||
ape/relocations.h \
|
||||
libc/dce.h \
|
||||
libc/elf/def.h \
|
||||
libc/intrin/asancodes.h \
|
||||
libc/macho.internal.h \
|
||||
libc/macros.internal.h \
|
||||
libc/nexgen32e/uart.internal.h \
|
||||
libc/nexgen32e/vidya.internal.h \
|
||||
libc/nt/pedef.internal.h \
|
||||
libc/runtime/e820.internal.h \
|
||||
libc/runtime/mman.internal.h \
|
||||
libc/runtime/pc.internal.h \
|
||||
libc/runtime/symbolic.h \
|
||||
libc/sysv/consts/prot.h
|
||||
@$(COMPILE) \
|
||||
-AOBJECTIFY.S \
|
||||
$(OBJECTIFY.S) \
|
||||
$(OUTPUT_OPTION) \
|
||||
-DAPE_NO_MODIFY_SELF $<
|
||||
|
||||
o/$(MODE)/ape/ape-buildsafe.o: ape/ape.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -DAPE_BUILDSAFE $<
|
||||
o/$(MODE)/ape/loader.o: ape/loader.c ape/loader.h
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=0b01111001 -g $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/loader-gcc.asm: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=0b01111001 -S -g0 $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/loader-clang.asm: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=0b01111001 -S -g0 $(APE_LOADER_FLAGS)
|
||||
|
||||
o/$(MODE)/ape/loader-xnu.o: ape/loader.c ape/loader.h
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=0b00001000 -g $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/loader-xnu-gcc.asm: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=0b00001000 -S -g0 $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/loader-xnu-clang.asm: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=0b00001000 -S -g0 $(APE_LOADER_FLAGS)
|
||||
|
||||
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
|
||||
o/$(MODE)/ape/ape.macho: o/$(MODE)/ape/ape.macho.dbg
|
||||
|
||||
o/$(MODE)/ape/ape.elf.dbg: \
|
||||
o/$(MODE)/ape/loader.o \
|
||||
o/$(MODE)/ape/loader-elf.o \
|
||||
ape/loader.lds
|
||||
@$(ELFLINK) -z max-page-size=0x10
|
||||
|
||||
o/$(MODE)/ape/ape.macho.dbg: \
|
||||
o/$(MODE)/ape/loader-xnu.o \
|
||||
o/$(MODE)/ape/loader-macho.o \
|
||||
ape/loader-macho.lds
|
||||
@$(ELFLINK) -z max-page-size=0x10
|
||||
|
||||
.PHONY: o/$(MODE)/ape
|
||||
o/$(MODE)/ape: $(APE) \
|
||||
$(APE_CHECKS) \
|
||||
o/$(MODE)/ape: $(APE_CHECKS) \
|
||||
o/$(MODE)/ape/ape.o \
|
||||
o/$(MODE)/ape/ape.lds \
|
||||
o/$(MODE)/ape/ape.elf \
|
||||
o/$(MODE)/ape/ape.macho \
|
||||
o/$(MODE)/ape/ape-copy-self.o \
|
||||
o/$(MODE)/ape/ape-no-modify-self.o
|
||||
Executable
+126
@@ -0,0 +1,126 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ $UID -eq 0 ]; then
|
||||
SUDO=
|
||||
else
|
||||
SUDO=sudo
|
||||
fi
|
||||
|
||||
echo "Actually Portable Executable (APE) Installer" >&2
|
||||
echo "Author: Justine Tunney <[email protected]>" >&2
|
||||
|
||||
################################################################################
|
||||
# INSTALL APE LOADER SYSTEMWIDE
|
||||
|
||||
if [ -f o/depend ]; then
|
||||
# mkdeps.com build was successfully run so assume we can build
|
||||
echo >&2
|
||||
echo "recompiling ape loader" >&2
|
||||
echo "running: make -j8 o//ape" >&2
|
||||
make -j8 o//ape || exit
|
||||
echo "done" >&2
|
||||
elif [ -d build/bootstrap ]; then
|
||||
# if make isn't being used then it's unlikely the user changed the sources
|
||||
# in that case the prebuilt binaries should be completely up-to-date
|
||||
echo "using prebuilt ape loader from cosmo repo" >&2
|
||||
mkdir -p o//ape || exit
|
||||
cp -af build/bootstrap/ape.elf o//ape/ape.elf || exit
|
||||
cp -af build/bootstrap/ape.macho o//ape/ape.macho || exit
|
||||
else
|
||||
echo "no cosmopolitan libc repository here" >&2
|
||||
echo "fetching ape loader from justine.lol" >&2
|
||||
mkdir -p o//ape || exit
|
||||
if command -v wget >/dev/null 2>&1; then
|
||||
wget -qO o//ape/ape.elf https://justine.lol/ape.elf || exit
|
||||
wget -qO o//ape/ape.macho https://justine.lol/ape.macho || exit
|
||||
else
|
||||
curl -Rso o//ape/ape.elf https://justine.lol/ape.elf || exit
|
||||
curl -Rso o//ape/ape.macho https://justine.lol/ape.macho || exit
|
||||
fi
|
||||
chmod +x o//ape/ape.elf || exit
|
||||
chmod +x o//ape/ape.macho || exit
|
||||
fi
|
||||
|
||||
if [ "$(uname -s)" = "Darwin" ]; then
|
||||
if ! [ /usr/bin/ape -nt o//ape/ape.macho ]; then
|
||||
echo >&2
|
||||
echo "installing o//ape/ape.elf to /usr/bin/ape" >&2
|
||||
echo "$SUDO mv -f o//ape/ape.elf /usr/bin/ape" >&2
|
||||
$SUDO cp -f o//ape/ape.macho /usr/bin/ape || exit
|
||||
echo "done" >&2
|
||||
fi
|
||||
else
|
||||
if ! [ /usr/bin/ape -nt o//ape/ape.elf ]; then
|
||||
echo >&2
|
||||
echo "installing o//ape/ape.elf to /usr/bin/ape" >&2
|
||||
echo "$SUDO mv -f o//ape/ape.elf /usr/bin/ape" >&2
|
||||
$SUDO cp -f o//ape/ape.elf /usr/bin/ape || exit
|
||||
echo "done" >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
# REGISTER APE LOADER WITH BINFMT_MISC TOO (LINUX-ONLY)
|
||||
|
||||
if [ x"$(uname -s)" = xLinux ]; then
|
||||
|
||||
if [ -e /proc/sys/fs/binfmt_misc/APE ]; then
|
||||
echo >&2
|
||||
echo it looks like APE is already registered with binfmt_misc >&2
|
||||
echo To reinstall please run ape/apeuninstall.sh first >&2
|
||||
echo please check that it is mapped to ape not /bin/sh >&2
|
||||
echo cat /proc/sys/fs/binfmt_misc/APE >&2
|
||||
cat /proc/sys/fs/binfmt_misc/APE >&2
|
||||
exit
|
||||
fi
|
||||
|
||||
if ! [ -e /proc/sys/fs/binfmt_misc ]; then
|
||||
echo >&2
|
||||
echo loading binfmt_misc into your kernel >&2
|
||||
echo you may need to edit configs to persist across reboot >&2
|
||||
echo $SUDO modprobe binfmt_misc >&2
|
||||
$SUDO modprobe binfmt_misc || exit
|
||||
echo done >&2
|
||||
fi
|
||||
|
||||
if ! [ -e /proc/sys/fs/binfmt_misc/register ]; then
|
||||
echo >&2
|
||||
echo mounting binfmt_misc into your kernel >&2
|
||||
echo you may need to edit configs to persist across reboot >&2
|
||||
echo $SUDO mount -t binfmt_misc none /proc/sys/fs/binfmt_misc >&2
|
||||
$SUDO mount -t binfmt_misc none /proc/sys/fs/binfmt_misc || exit
|
||||
echo done >&2
|
||||
fi
|
||||
|
||||
echo >&2
|
||||
echo registering APE with binfmt_misc >&2
|
||||
echo you may need to edit configs to persist across reboot >&2
|
||||
echo '$SUDO sh -c "echo '"'"':APE:M::MZqFpD::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||
$SUDO sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||
echo done >&2
|
||||
|
||||
if [ x"$(cat /proc/sys/fs/binfmt_misc/status)" = xdisabled ]; then
|
||||
echo >&2
|
||||
echo enabling binfmt_misc >&2
|
||||
echo you may need to edit configs to persist across reboot >&2
|
||||
echo $SUDO sh -c 'echo 1 >/proc/sys/fs/binfmt_misc/status' >&2
|
||||
$SUDO sh -c 'echo 1 >/proc/sys/fs/binfmt_misc/status' || exit
|
||||
echo done >&2
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
|
||||
{
|
||||
echo
|
||||
echo "------------------------------------------------------------------"
|
||||
echo
|
||||
echo "APE INSTALL COMPLETE"
|
||||
echo
|
||||
echo "If you decide to uninstall APE later on"
|
||||
echo "you may do so using ape/apeuninstall.sh"
|
||||
echo
|
||||
echo "Enjoy your APE loader (>'.')>"
|
||||
echo
|
||||
} >&2
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "$UID" = "0" ]; then
|
||||
SUDO=
|
||||
else
|
||||
SUDO=sudo
|
||||
fi
|
||||
|
||||
{
|
||||
echo
|
||||
echo "APE Uninstaller intends to run"
|
||||
echo
|
||||
echo " $SUDO sh -c 'echo -1 >/proc/sys/fs/binfmt_misc/APE'"
|
||||
echo " $SUDO rm -f /usr/bin/ape ~/.ape o/tmp/.ape /tmp/.ape"
|
||||
echo
|
||||
echo "You may then use ape/apeinstall.sh to reinstall it"
|
||||
echo
|
||||
} >&2
|
||||
|
||||
set -ex
|
||||
if [ -f /proc/sys/fs/binfmt_misc/APE ]; then
|
||||
$SUDO sh -c 'echo -1 >/proc/sys/fs/binfmt_misc/APE' || exit
|
||||
fi
|
||||
$SUDO rm -f /usr/bin/ape ~/.ape o/tmp/.ape o/tmp/ape /tmp/.ape /tmp/ape || exit
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef COSMOPOLITAN_APE_CONFIG_H_
|
||||
#define COSMOPOLITAN_APE_CONFIG_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#define STATIC_SYMBOL(NAME, VALUE) \
|
||||
asm(".equ\t" NAME "," VALUE "\n\t" \
|
||||
".globl\t" NAME)
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_APE_CONFIG_H_ */
|
||||
@@ -0,0 +1,249 @@
|
||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/elf/def.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/macho.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
// APE Loader Executable Structure
|
||||
// Linux, FreeBSD, NetBSD, OpenBSD
|
||||
|
||||
.align 8
|
||||
ehdr: .ascii "\177ELF"
|
||||
.byte ELFCLASS64
|
||||
.byte ELFDATA2LSB
|
||||
.byte 1
|
||||
.byte ELFOSABI_FREEBSD
|
||||
.quad 0
|
||||
.word ET_EXEC # e_type
|
||||
.word EM_NEXGEN32E # e_machine
|
||||
.long 1 # e_version
|
||||
.quad _start # e_entry
|
||||
.quad phdrs - ehdr # e_phoff
|
||||
.quad 0 # e_shoff
|
||||
.long 0 # e_flags
|
||||
.word 64 # e_ehsize
|
||||
.word 56 # e_phentsize
|
||||
.word 4 # e_phnum
|
||||
.word 0 # e_shentsize
|
||||
.word 0 # e_shnum
|
||||
.word 0 # e_shstrndx
|
||||
.endobj ehdr,globl
|
||||
|
||||
.align 8
|
||||
phdrs: .long PT_LOAD # p_type
|
||||
.long PF_R|PF_X # p_flags
|
||||
.quad 0 # p_offset
|
||||
.quad ehdr # p_vaddr
|
||||
.quad ehdr # p_paddr
|
||||
.quad filesz # p_filesz
|
||||
.quad filesz # p_memsz
|
||||
.quad PAGESIZE # p_align
|
||||
|
||||
.long PT_LOAD # p_type
|
||||
.long PF_R|PF_W # p_flags
|
||||
.quad 0 # p_offset
|
||||
.quad bss # p_vaddr
|
||||
.quad bss # p_paddr
|
||||
.quad 0 # p_filesz
|
||||
.quad bsssize # p_memsz
|
||||
.quad PAGESIZE # p_align
|
||||
|
||||
.long PT_GNU_STACK # p_type
|
||||
.long PF_R|PF_W # p_flags
|
||||
.quad 0 # p_offset
|
||||
.quad 0 # p_vaddr
|
||||
.quad 0 # p_paddr
|
||||
.quad 0 # p_filesz
|
||||
.quad 0 # p_memsz
|
||||
.quad 16 # p_align
|
||||
|
||||
.long PT_NOTE # p_type
|
||||
.long PF_R # p_flags
|
||||
.quad note - ehdr # p_offset
|
||||
.quad note # p_vaddr
|
||||
.quad note # p_paddr
|
||||
.quad notesize # p_filesz
|
||||
.quad notesize # p_memsz
|
||||
.quad 8 # p_align
|
||||
.endobj phdrs
|
||||
|
||||
note: .long 2f-1f
|
||||
.long 4f-3f
|
||||
.long 1
|
||||
1: .asciz "OpenBSD"
|
||||
2: .align 4
|
||||
3: .long 0
|
||||
4: .long 2f-1f
|
||||
.long 4f-3f
|
||||
.long 1
|
||||
1: .asciz "NetBSD"
|
||||
2: .align 4
|
||||
3: .long 901000000
|
||||
4: .endobj note
|
||||
notesize = . - note
|
||||
|
||||
.align 64,0 # for ape.S dd
|
||||
.org 0x180 # for ape.S dd
|
||||
|
||||
// APE Loader XNU Header
|
||||
//
|
||||
// This header is dd'd backwards by the APE shell script when
|
||||
// running on Mac OS X.
|
||||
//
|
||||
// @see ape/ape.S
|
||||
macho: .long 0xFEEDFACE+1
|
||||
.long MAC_CPU_NEXGEN32E
|
||||
.long MAC_CPU_NEXGEN32E_ALL
|
||||
.long MAC_EXECUTE
|
||||
.long 5 # number of load commands
|
||||
.long 60f-10f # size of all load commands
|
||||
.long MAC_NOUNDEFS # flags
|
||||
.long 0 # reserved
|
||||
10: .long MAC_LC_SEGMENT_64
|
||||
.long 20f-10b # unmaps first page dir
|
||||
.ascin "__PAGEZERO",16 # consistent with linux
|
||||
.quad 0,0x200000,0,0 # which forbids mem <2m
|
||||
.long 0,0,0,0
|
||||
20: .long MAC_LC_SEGMENT_64
|
||||
.long 30f-20b
|
||||
.ascin "__TEXT",16
|
||||
.quad ehdr # vaddr
|
||||
.quad 4096 # memsz
|
||||
.quad 0 # file offset
|
||||
.quad filesz # file size
|
||||
.long PROT_EXEC|PROT_READ|PROT_WRITE # maxprot
|
||||
.long PROT_EXEC|PROT_READ # initprot
|
||||
.long 1 # segment section count
|
||||
.long 0 # flags
|
||||
210: .ascin "__text",16 # section name (.text)
|
||||
.ascin "__TEXT",16
|
||||
.quad _start # vaddr
|
||||
.quad textsz # memsz
|
||||
.long textoff # offset
|
||||
.long 6 # align 2**6 = 64
|
||||
.long 0 # reloc table offset
|
||||
.long 0 # relocation count
|
||||
.long MAC_S_ATTR_SOME_INSTRUCTIONS # section type & attributes
|
||||
.long 0,0,0 # reserved
|
||||
30: .long MAC_LC_SEGMENT_64
|
||||
.long 40f-30b
|
||||
.ascin "__DATA",16
|
||||
.quad bss # vaddr
|
||||
.quad bsssize # memsz
|
||||
.quad 0 # offset
|
||||
.quad 0 # file size
|
||||
.long PROT_EXEC|PROT_READ|PROT_WRITE # maxprot
|
||||
.long PROT_READ|PROT_WRITE # initprot
|
||||
.long 1 # segment section count
|
||||
.long 0 # flags
|
||||
310: .ascin "__bss",16 # section name (.bss)
|
||||
.ascin "__DATA",16
|
||||
.quad bss # vaddr
|
||||
.quad bsssize # memsz
|
||||
.long 0 # offset
|
||||
.long 12 # align 2**12 = 4096
|
||||
.long 0 # reloc table offset
|
||||
.long 0 # relocation count
|
||||
.long MAC_S_ZEROFILL # section type & attributes
|
||||
.long 0,0,0 # reserved
|
||||
40: .long MAC_LC_UUID
|
||||
.long 50f-40b
|
||||
.quad 0x3fb29ee4ac6c87aa # uuid1
|
||||
.quad 0xdd2c9bb866d9eef8 # uuid2
|
||||
50: .long MAC_LC_UNIXTHREAD
|
||||
.long 60f-50b # cmdsize
|
||||
.long MAC_THREAD_NEXGEN32E # flavaflav
|
||||
.long (520f-510f)/4 # count
|
||||
510: .quad 0 # rax
|
||||
.quad 0 # rbx
|
||||
.quad 0 # rcx
|
||||
.quad XNU # rdx
|
||||
.quad 0 # rdi
|
||||
.quad 0 # rsi
|
||||
.quad 0 # rbp
|
||||
.quad 0 # rsp
|
||||
.quad 0 # r8
|
||||
.quad 0 # r9
|
||||
.quad 0 # r10
|
||||
.quad 0 # r11
|
||||
.quad 0 # r12
|
||||
.quad 0 # r13
|
||||
.quad 0 # r14
|
||||
.quad 0 # r15
|
||||
.quad _start # rip
|
||||
.quad 0 # rflags
|
||||
.quad 0 # cs
|
||||
.quad 0 # fs
|
||||
.quad 0 # gs
|
||||
520:
|
||||
60:
|
||||
.endobj macho
|
||||
|
||||
.align 64,0 # for ape.S dd
|
||||
.org 0x400 # for ape.S dd
|
||||
|
||||
// Ape Loader Entrpoint
|
||||
//
|
||||
// This is normally called by the operating system. However it may
|
||||
// be called by the Actually Portable Executables themselves, when
|
||||
// re-executing a program. Just do this:
|
||||
//
|
||||
// memcpy(0x200000, loader)
|
||||
// lea handoff(%rip),%rcx
|
||||
// lea argblock(%rip),%rsp
|
||||
// jmp 0x200400
|
||||
//
|
||||
// @see APE_LOADER_ENTRY
|
||||
// @see ape/loader.h
|
||||
_start:
|
||||
|
||||
// Hack for detecting M1 Rosetta environment.
|
||||
// https://github.com/jart/cosmopolitan/issues/429#issuecomment-1166704377
|
||||
cmp $-1,%ebx
|
||||
jne 0f
|
||||
cmp $+1,%edx
|
||||
jne 0f
|
||||
mov $XNU,%dl
|
||||
xor %ecx,%ecx
|
||||
|
||||
0: mov %rsp,%rsi
|
||||
jmp ApeLoader
|
||||
.endfn _start,globl
|
||||
|
||||
// System Call Entrpoint
|
||||
//
|
||||
// This function is used by the APE loader to make system calls.
|
||||
// We also pass a reference to this function to the APE binary's
|
||||
// _start() function. It's needed because on OpenBSD, msyscall()
|
||||
// restricts which pages can issue system calls, and it can only
|
||||
// be called once. Therefore if we want to be load and re-load a
|
||||
// binary multiple times without calling the system execve(), we
|
||||
// need to be able to handover the SYSCALL function. We hardcode
|
||||
// this to a fixed address, but that shouldn't be used, since we
|
||||
// would ideally want to move it to a random page in the future.
|
||||
__syscall_loader:
|
||||
clc
|
||||
syscall
|
||||
jc 1f
|
||||
ret
|
||||
1: neg %rax
|
||||
ret
|
||||
.endfn __syscall_loader,globl
|
||||
@@ -0,0 +1,138 @@
|
||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macho.internal.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
// APE Loader Executable Structure for XNU
|
||||
|
||||
.align 4096
|
||||
macho: .long 0xFEEDFACE+1
|
||||
.long MAC_CPU_NEXGEN32E
|
||||
.long MAC_CPU_NEXGEN32E_ALL
|
||||
.long MAC_EXECUTE
|
||||
.long 5 # number of load commands
|
||||
.long 60f-10f # size of all load commands
|
||||
.long MAC_NOUNDEFS # flags
|
||||
.long 0 # reserved
|
||||
10: .long MAC_LC_SEGMENT_64
|
||||
.long 20f-10b # unmaps first page dir
|
||||
.ascin "__PAGEZERO",16 # consistent with linux
|
||||
.quad 0,0x200000,0,0 # which forbids mem <2m
|
||||
.long 0,0,0,0
|
||||
20: .long MAC_LC_SEGMENT_64
|
||||
.long 30f-20b
|
||||
.ascin "__TEXT",16
|
||||
.quad macho # vaddr
|
||||
.quad 4096 # memsz
|
||||
.quad 0 # file offset
|
||||
.quad filesz # file size
|
||||
.long PROT_EXEC|PROT_READ|PROT_WRITE # maxprot
|
||||
.long PROT_EXEC|PROT_READ # initprot
|
||||
.long 1 # segment section count
|
||||
.long 0 # flags
|
||||
210: .ascin "__text",16 # section name (.text)
|
||||
.ascin "__TEXT",16
|
||||
.quad _start # vaddr
|
||||
.quad textsz # memsz
|
||||
.long textoff # offset
|
||||
.long 6 # align 2**3 = 64
|
||||
.long 0 # reloc table offset
|
||||
.long 0 # relocation count
|
||||
.long MAC_S_ATTR_SOME_INSTRUCTIONS # section type & attributes
|
||||
.long 0,0,0 # reserved
|
||||
30: .long MAC_LC_SEGMENT_64
|
||||
.long 40f-30b
|
||||
.ascin "__DATA",16
|
||||
.quad bss # vaddr
|
||||
.quad bsssize # memsz
|
||||
.quad 0 # offset
|
||||
.quad 0 # file size
|
||||
.long PROT_EXEC|PROT_READ|PROT_WRITE # maxprot
|
||||
.long PROT_READ|PROT_WRITE # initprot
|
||||
.long 1 # segment section count
|
||||
.long 0 # flags
|
||||
310: .ascin "__bss",16 # section name (.bss)
|
||||
.ascin "__DATA",16
|
||||
.quad bss # vaddr
|
||||
.quad bsssize # memsz
|
||||
.long 0 # offset
|
||||
.long 12 # align 2**12 = 4096
|
||||
.long 0 # reloc table offset
|
||||
.long 0 # relocation count
|
||||
.long MAC_S_ZEROFILL # section type & attributes
|
||||
.long 0,0,0 # reserved
|
||||
40: .long MAC_LC_UUID
|
||||
.long 50f-40b
|
||||
.quad 0x3fb29ee4ac6c87aa # uuid1
|
||||
.quad 0xdd2c9bb866d9eef8 # uuid2
|
||||
50: .long MAC_LC_UNIXTHREAD
|
||||
.long 60f-50b # cmdsize
|
||||
.long MAC_THREAD_NEXGEN32E # flavaflav
|
||||
.long (520f-510f)/4 # count
|
||||
510: .quad 0 # rax
|
||||
.quad 0 # rbx
|
||||
.quad 0 # rcx
|
||||
.quad XNU # rdx
|
||||
.quad 0 # rdi
|
||||
.quad 0 # rsi
|
||||
.quad 0 # rbp
|
||||
.quad 0 # rsp
|
||||
.quad 0 # r8
|
||||
.quad 0 # r9
|
||||
.quad 0 # r10
|
||||
.quad 0 # r11
|
||||
.quad 0 # r12
|
||||
.quad 0 # r13
|
||||
.quad 0 # r14
|
||||
.quad 0 # r15
|
||||
.quad _start # rip
|
||||
.quad 0 # rflags
|
||||
.quad 0 # cs
|
||||
.quad 0 # fs
|
||||
.quad 0 # gs
|
||||
520:
|
||||
60:
|
||||
.endobj macho,globl
|
||||
|
||||
.align 64
|
||||
_start:
|
||||
|
||||
// Hack for detecting M1 Rosetta environment.
|
||||
// https://github.com/jart/cosmopolitan/issues/429#issuecomment-1166704377
|
||||
cmp $-1,%ebx
|
||||
jne 0f
|
||||
cmp $+1,%edx
|
||||
jne 0f
|
||||
mov $XNU,%dl
|
||||
xor %ecx,%ecx
|
||||
|
||||
0: mov %rsp,%rsi
|
||||
jmp ApeLoader
|
||||
.endfn _start,globl
|
||||
|
||||
__syscall_loader:
|
||||
clc
|
||||
syscall
|
||||
jc 1f
|
||||
ret
|
||||
1: neg %rax
|
||||
ret
|
||||
.endfn __syscall_loader,globl
|
||||
@@ -0,0 +1,42 @@
|
||||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x200000;
|
||||
.text : {
|
||||
*(.text)
|
||||
*(.rodata .rodata.*)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
filesz = . - macho;
|
||||
textsz = . - _start;
|
||||
.bss ALIGN(4096) : {
|
||||
bss = .;
|
||||
*(.bss)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
memsz = . - macho;
|
||||
/DISCARD/ : {
|
||||
*(.*)
|
||||
}
|
||||
}
|
||||
|
||||
bsssize = SIZEOF(.bss);
|
||||
textoff = _start - macho;
|
||||
+791
@@ -0,0 +1,791 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/loader.h"
|
||||
|
||||
#define SET_EXE_FILE 0 /* needs root ;_; */
|
||||
#define TROUBLESHOOT 0
|
||||
#define TROUBLESHOOT_OS LINUX
|
||||
|
||||
/**
|
||||
* @fileoverview APE Loader for GNU/Systemd/XNU/FreeBSD/NetBSD/OpenBSD
|
||||
*
|
||||
* We recommend using the normal APE design, where binaries assimilate
|
||||
* themselves once by self-modifying the first 64 bytes. If that can't
|
||||
* meet your requirements then we provide an excellent alternative.
|
||||
*
|
||||
* m=tiny
|
||||
* make -j8 MODE=$m o/$m/ape o/$m/examples/printargs.com
|
||||
* o/$m/ape/ape.elf o/$m/examples/printargs.com
|
||||
*
|
||||
* This is an embeddable Actually Portable Executable interpreter. The
|
||||
* `ape/ape.S` bootloader embeds this binary inside each binary that's
|
||||
* linked using `$(APE_NO_MODIFY_SELF)` so it is an automated seamless
|
||||
* process. the shell script at the top of the .COM files will copy it
|
||||
* to `${TMPDIR:-${HOME:-.}}/.ape` and call execve(). It's a zero copy
|
||||
* operation in praxis since this payload uses mmap() to load the rest
|
||||
* of your executable the same way the kernel does, based on ELF phdrs
|
||||
* which are located in accordance with the first sh printf statement.
|
||||
*
|
||||
* APE executables will look for this program on the system path first
|
||||
* so your APE loader may be installed to your system as follows:
|
||||
*
|
||||
* m=tiny
|
||||
* make -j8 MODE=$m o/$m/ape/ape.elf
|
||||
* sudo cp o/$m/ape/ape.elf /usr/bin/ape
|
||||
*
|
||||
* For Mac OS X systems you should install the `ape.macho` executable:
|
||||
*
|
||||
* sudo cp o/$m/ape/ape.macho /usr/bin/ape
|
||||
*
|
||||
* Your APE loader may be used as a shebang interpreter by doing this:
|
||||
*
|
||||
* #!/usr/bin/ape python.com
|
||||
* # -*- python -*-
|
||||
* print("hello world")
|
||||
*
|
||||
* However you won't need to do that, if your APE Loader is registered
|
||||
* as a binfmt_misc interpreter. You can do that as follows with root:
|
||||
*
|
||||
* sudo cp -f o/$m/ape/ape.elf /usr/bin
|
||||
* f=/proc/sys/fs/binfmt_misc/register
|
||||
* sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >$f"
|
||||
*
|
||||
* If the register file doesn't exist on your Linux machine then you'd
|
||||
* load it using the following commands:
|
||||
*
|
||||
* sudo modprobe binfmt_misc
|
||||
* sudo mount -t binfmt_misc none /proc/sys/fs/binfmt_misc
|
||||
*
|
||||
* You should now experience a performance boost, and you can also now
|
||||
* use the regular shebang form:
|
||||
*
|
||||
* #!/usr/bin/python.com
|
||||
* # -*- python -*-
|
||||
* print("hello world")
|
||||
*
|
||||
* @note this can probably be used as a binfmt_misc interpreter
|
||||
*/
|
||||
|
||||
#define LINUX 1
|
||||
#define XNU 8
|
||||
#define OPENBSD 16
|
||||
#define FREEBSD 32
|
||||
#define NETBSD 64
|
||||
|
||||
#define SupportsLinux() (SUPPORT_VECTOR & LINUX)
|
||||
#define SupportsXnu() (SUPPORT_VECTOR & XNU)
|
||||
#define SupportsFreebsd() (SUPPORT_VECTOR & FREEBSD)
|
||||
#define SupportsOpenbsd() (SUPPORT_VECTOR & OPENBSD)
|
||||
#define SupportsNetbsd() (SUPPORT_VECTOR & NETBSD)
|
||||
|
||||
#define IsLinux() (SupportsLinux() && os == LINUX)
|
||||
#define IsXnu() (SupportsXnu() && os == XNU)
|
||||
#define IsFreebsd() (SupportsFreebsd() && os == FREEBSD)
|
||||
#define IsOpenbsd() (SupportsOpenbsd() && os == OPENBSD)
|
||||
#define IsNetbsd() (SupportsNetbsd() && os == NETBSD)
|
||||
|
||||
#define O_RDONLY 0
|
||||
#define PROT_READ 1
|
||||
#define PROT_WRITE 2
|
||||
#define PROT_EXEC 4
|
||||
#define MAP_SHARED 1
|
||||
#define MAP_PRIVATE 2
|
||||
#define MAP_FIXED 16
|
||||
#define MAP_ANONYMOUS (IsLinux() ? 32 : 4096)
|
||||
#define AT_EXECFN_LINUX 31
|
||||
#define AT_EXECFN_NETBSD 2014
|
||||
#define ELFCLASS64 2
|
||||
#define ELFDATA2LSB 1
|
||||
#define EM_NEXGEN32E 62
|
||||
#define ET_EXEC 2
|
||||
#define PT_LOAD 1
|
||||
#define PT_DYNAMIC 2
|
||||
#define EI_CLASS 4
|
||||
#define EI_DATA 5
|
||||
#define PF_X 1
|
||||
#define PF_W 2
|
||||
#define PF_R 4
|
||||
#define X_OK 1
|
||||
#define XCR0_SSE 2
|
||||
#define XCR0_AVX 4
|
||||
#define PR_SET_MM 35
|
||||
#define PR_SET_MM_EXE_FILE 13
|
||||
|
||||
#define Read32(S) \
|
||||
((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \
|
||||
(unsigned)(255 & (S)[1]) << 010 | (unsigned)(255 & (S)[0]) << 000)
|
||||
|
||||
#define Read64(S) \
|
||||
((unsigned long)(255 & (S)[7]) << 070 | \
|
||||
(unsigned long)(255 & (S)[6]) << 060 | \
|
||||
(unsigned long)(255 & (S)[5]) << 050 | \
|
||||
(unsigned long)(255 & (S)[4]) << 040 | \
|
||||
(unsigned long)(255 & (S)[3]) << 030 | \
|
||||
(unsigned long)(255 & (S)[2]) << 020 | \
|
||||
(unsigned long)(255 & (S)[1]) << 010 | \
|
||||
(unsigned long)(255 & (S)[0]) << 000)
|
||||
|
||||
struct PathSearcher {
|
||||
char os;
|
||||
unsigned long namelen;
|
||||
const char *name;
|
||||
const char *syspath;
|
||||
char path[1024];
|
||||
};
|
||||
|
||||
struct ElfEhdr {
|
||||
unsigned char e_ident[16];
|
||||
unsigned short e_type;
|
||||
unsigned short e_machine;
|
||||
unsigned e_version;
|
||||
unsigned long e_entry;
|
||||
unsigned long e_phoff;
|
||||
unsigned long e_shoff;
|
||||
unsigned e_flags;
|
||||
unsigned short e_ehsize;
|
||||
unsigned short e_phentsize;
|
||||
unsigned short e_phnum;
|
||||
unsigned short e_shentsize;
|
||||
unsigned short e_shnum;
|
||||
unsigned short e_shstrndx;
|
||||
};
|
||||
|
||||
struct ElfPhdr {
|
||||
unsigned p_type;
|
||||
unsigned p_flags;
|
||||
unsigned long p_offset;
|
||||
unsigned long p_vaddr;
|
||||
unsigned long p_paddr;
|
||||
unsigned long p_filesz;
|
||||
unsigned long p_memsz;
|
||||
unsigned long p_align;
|
||||
};
|
||||
|
||||
extern char ehdr[];
|
||||
extern char _end[];
|
||||
static void *syscall;
|
||||
static char relocated;
|
||||
static struct PathSearcher ps;
|
||||
extern char __syscall_loader[];
|
||||
|
||||
static int ToLower(int c) {
|
||||
return 'A' <= c && c <= 'Z' ? c + ('a' - 'A') : c;
|
||||
}
|
||||
|
||||
char *MemCpy(char *d, const char *s, unsigned long n) {
|
||||
unsigned long i = 0;
|
||||
for (; i < n; ++i) d[i] = s[i];
|
||||
return d + n;
|
||||
}
|
||||
|
||||
static unsigned long StrLen(const char *s) {
|
||||
unsigned long n = 0;
|
||||
while (*s++) ++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
static const char *MemChr(const char *s, unsigned char c, unsigned long n) {
|
||||
for (; n; --n, ++s) {
|
||||
if ((*s & 255) == c) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *GetEnv(char **p, const char *s) {
|
||||
unsigned long i, j;
|
||||
if (p) {
|
||||
for (i = 0; p[i]; ++i) {
|
||||
for (j = 0;; ++j) {
|
||||
if (!s[j]) {
|
||||
if (p[i][j] == '=') {
|
||||
return p[i] + j + 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (s[j] != p[i][j]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *Utoa(char p[21], unsigned long x) {
|
||||
char t;
|
||||
unsigned long i, a, b;
|
||||
i = 0;
|
||||
do {
|
||||
p[i++] = x % 10 + '0';
|
||||
x = x / 10;
|
||||
} while (x > 0);
|
||||
p[i] = '\0';
|
||||
if (i) {
|
||||
for (a = 0, b = i - 1; a < b; ++a, --b) {
|
||||
t = p[a];
|
||||
p[a] = p[b];
|
||||
p[b] = t;
|
||||
}
|
||||
}
|
||||
return p + i;
|
||||
}
|
||||
|
||||
static char *Itoa(char p[21], long x) {
|
||||
if (x < 0) *p++ = '-', x = -(unsigned long)x;
|
||||
return Utoa(p, x);
|
||||
}
|
||||
|
||||
#if TROUBLESHOOT
|
||||
const char *DescribeOs(int os) {
|
||||
if (IsLinux()) {
|
||||
return "GNU/SYSTEMD";
|
||||
} else if (IsXnu()) {
|
||||
return "XNU";
|
||||
} else if (IsFreebsd()) {
|
||||
return "FREEBSD";
|
||||
} else if (IsOpenbsd()) {
|
||||
return "OPENBSD";
|
||||
} else if (IsNetbsd()) {
|
||||
return "NETBSD";
|
||||
} else {
|
||||
return "WUT";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
__attribute__((__noreturn__)) static void Exit(int rc, int os) {
|
||||
asm volatile("call\t*%2"
|
||||
: /* no outputs */
|
||||
: "a"((IsLinux() ? 60 : 1) | (IsXnu() ? 0x2000000 : 0)), "D"(rc),
|
||||
"rm"(syscall)
|
||||
: "memory");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
static void Close(int fd, int os) {
|
||||
int ax, di;
|
||||
asm volatile("call\t*%4"
|
||||
: "=a"(ax), "=D"(di)
|
||||
: "0"((IsLinux() ? 3 : 6) | (IsXnu() ? 0x2000000 : 0)), "1"(fd),
|
||||
"rm"(syscall)
|
||||
: "rcx", "rdx", "rsi", "r8", "r9", "r10", "r11", "memory", "cc");
|
||||
}
|
||||
|
||||
static int Read(int fd, void *data, int size, int os) {
|
||||
long si;
|
||||
int ax, di, dx;
|
||||
asm volatile("call\t*%8"
|
||||
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
|
||||
: "0"((IsLinux() ? 0 : 3) | (IsXnu() ? 0x2000000 : 0)), "1"(fd),
|
||||
"2"(data), "3"(size), "rm"(syscall)
|
||||
: "rcx", "r8", "r9", "r10", "r11", "memory");
|
||||
return ax;
|
||||
}
|
||||
|
||||
static void Write(int fd, const void *data, int size, int os) {
|
||||
long si;
|
||||
int ax, di, dx;
|
||||
asm volatile("call\t*%8"
|
||||
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
|
||||
: "0"((IsLinux() ? 1 : 4) | (IsXnu() ? 0x2000000 : 0)), "1"(fd),
|
||||
"2"(data), "3"(size), "rm"(syscall)
|
||||
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
|
||||
}
|
||||
|
||||
static void Execve(const char *prog, char **argv, char **envp, int os) {
|
||||
long ax, di, si, dx;
|
||||
asm volatile("call\t*%8"
|
||||
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
|
||||
: "0"(59 | (IsXnu() ? 0x2000000 : 0)), "1"(prog), "2"(argv),
|
||||
"3"(envp), "rm"(syscall)
|
||||
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
|
||||
}
|
||||
|
||||
static int Access(const char *path, int mode, int os) {
|
||||
int ax, si;
|
||||
long dx, di;
|
||||
asm volatile("call\t*%7"
|
||||
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
|
||||
: "0"((IsLinux() ? 21 : 33) | (IsXnu() ? 0x2000000 : 0)),
|
||||
"1"(path), "2"(mode), "rm"(syscall)
|
||||
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
|
||||
return ax;
|
||||
}
|
||||
|
||||
static int Msyscall(long p, long n, int os) {
|
||||
int ax;
|
||||
long di, si;
|
||||
if (!IsOpenbsd()) {
|
||||
return 0;
|
||||
} else {
|
||||
asm volatile("call\t*%6"
|
||||
: "=a"(ax), "=D"(di), "=S"(si)
|
||||
: "0"(37), "1"(p), "2"(n), "rm"(syscall)
|
||||
: "rcx", "rdx", "r8", "r9", "r10", "r11", "memory", "cc");
|
||||
return ax;
|
||||
}
|
||||
}
|
||||
|
||||
static int Open(const char *path, int flags, int mode, int os) {
|
||||
long di;
|
||||
int ax, dx, si;
|
||||
asm volatile("call\t*%8"
|
||||
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx)
|
||||
: "0"((IsLinux() ? 2 : 5) | (IsXnu() ? 0x2000000 : 0)),
|
||||
"1"(path), "2"(flags), "3"(mode), "rm"(syscall)
|
||||
: "rcx", "r8", "r9", "r10", "r11", "memory", "cc");
|
||||
return ax;
|
||||
}
|
||||
|
||||
__attribute__((__noinline__)) static long Mmap(long addr, long size, int prot,
|
||||
int flags, int fd, long off,
|
||||
int os) {
|
||||
long ax, di, si, dx;
|
||||
register int flags_ asm("r10") = flags;
|
||||
register int fd_ asm("r8") = fd;
|
||||
register long off_ asm("r9") = off;
|
||||
asm volatile("push\t%%r9\n\t"
|
||||
"push\t%%r9\n\t"
|
||||
"call\t*%7\n\t"
|
||||
"pop\t%%r9\n\t"
|
||||
"pop\t%%r9"
|
||||
: "=a"(ax), "=D"(di), "=S"(si), "=d"(dx), "+r"(flags_),
|
||||
"+r"(fd_), "+r"(off_)
|
||||
: "rm"(syscall),
|
||||
"0"((IsLinux() ? 9
|
||||
: IsFreebsd() ? 477
|
||||
: 197) |
|
||||
(IsXnu() ? 0x2000000 : 0)),
|
||||
"1"(addr), "2"(size), "3"(prot)
|
||||
: "rcx", "r11", "memory", "cc");
|
||||
return ax;
|
||||
}
|
||||
|
||||
int MunmapLinux(const void *addr, unsigned long size) {
|
||||
int ax;
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax)
|
||||
: "0"(11), "D"(addr), "S"(size)
|
||||
: "rcx", "r11", "memory");
|
||||
return ax;
|
||||
}
|
||||
|
||||
int PrctlLinux(int op, long a, long b, long c, long d) {
|
||||
int rc;
|
||||
asm volatile("mov\t%5,%%r10\n\t"
|
||||
"mov\t%6,%%r8\n\t"
|
||||
"syscall"
|
||||
: "=a"(rc)
|
||||
: "0"(157), "D"(op), "S"(a), "d"(b), "g"(c), "g"(d)
|
||||
: "rcx", "r8", "r10", "r11", "memory");
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void Emit(int os, const char *s) {
|
||||
Write(2, s, StrLen(s), os);
|
||||
}
|
||||
|
||||
static void Perror(int os, const char *c, int rc, const char *s) {
|
||||
char ibuf[21];
|
||||
Emit(os, "ape error: ");
|
||||
Emit(os, c);
|
||||
Emit(os, ": ");
|
||||
Emit(os, s);
|
||||
if (rc) {
|
||||
Emit(os, " failed errno=");
|
||||
Itoa(ibuf, -rc);
|
||||
Emit(os, ibuf);
|
||||
}
|
||||
Emit(os, "\n");
|
||||
}
|
||||
|
||||
__attribute__((__noreturn__)) static void Pexit(int os, const char *c, int rc,
|
||||
const char *s) {
|
||||
Perror(os, c, rc, s);
|
||||
Exit(127, os);
|
||||
}
|
||||
|
||||
static int StrCmp(const char *l, const char *r) {
|
||||
unsigned long i = 0;
|
||||
while (l[i] == r[i] && r[i]) ++i;
|
||||
return (l[i] & 255) - (r[i] & 255);
|
||||
}
|
||||
|
||||
static char EndsWithIgnoreCase(const char *p, unsigned long n, const char *s) {
|
||||
unsigned long i, m;
|
||||
if (n >= (m = StrLen(s))) {
|
||||
for (i = n - m; i < n; ++i) {
|
||||
if (ToLower(p[i]) != *s++) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static char IsComPath(struct PathSearcher *ps) {
|
||||
return EndsWithIgnoreCase(ps->name, ps->namelen, ".com") ||
|
||||
EndsWithIgnoreCase(ps->name, ps->namelen, ".exe") ||
|
||||
EndsWithIgnoreCase(ps->name, ps->namelen, ".com.dbg");
|
||||
}
|
||||
|
||||
static char AccessCommand(struct PathSearcher *ps, const char *suffix,
|
||||
unsigned long pathlen) {
|
||||
unsigned long suffixlen;
|
||||
suffixlen = StrLen(suffix);
|
||||
if (pathlen + 1 + ps->namelen + suffixlen + 1 > sizeof(ps->path)) return 0;
|
||||
if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/';
|
||||
MemCpy(ps->path + pathlen, ps->name, ps->namelen);
|
||||
MemCpy(ps->path + pathlen + ps->namelen, suffix, suffixlen + 1);
|
||||
return !Access(ps->path, X_OK, ps->os);
|
||||
}
|
||||
|
||||
static char SearchPath(struct PathSearcher *ps, const char *suffix) {
|
||||
const char *p;
|
||||
unsigned long i;
|
||||
for (p = ps->syspath;;) {
|
||||
for (i = 0; p[i] && p[i] != ':'; ++i) {
|
||||
if (i < sizeof(ps->path)) {
|
||||
ps->path[i] = p[i];
|
||||
}
|
||||
}
|
||||
if (AccessCommand(ps, suffix, i)) {
|
||||
return 1;
|
||||
} else if (p[i] == ':') {
|
||||
p += i + 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char FindCommand(struct PathSearcher *ps, const char *suffix) {
|
||||
if (MemChr(ps->name, '/', ps->namelen) ||
|
||||
MemChr(ps->name, '\\', ps->namelen)) {
|
||||
ps->path[0] = 0;
|
||||
return AccessCommand(ps, suffix, 0);
|
||||
} else {
|
||||
if (AccessCommand(ps, suffix, 0)) return 1;
|
||||
}
|
||||
return SearchPath(ps, suffix);
|
||||
}
|
||||
|
||||
static char *Commandv(struct PathSearcher *ps, int os, const char *name,
|
||||
const char *syspath) {
|
||||
ps->os = os;
|
||||
ps->syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin";
|
||||
if (!(ps->namelen = StrLen((ps->name = name)))) return 0;
|
||||
if (ps->namelen + 1 > sizeof(ps->path)) return 0;
|
||||
if (FindCommand(ps, "") || (!IsComPath(ps) && FindCommand(ps, ".com"))) {
|
||||
return ps->path;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd,
|
||||
long *sp, char *page,
|
||||
struct ElfEhdr *e) {
|
||||
long rc;
|
||||
unsigned long i;
|
||||
int prot, flags;
|
||||
struct ElfPhdr *p;
|
||||
long code, codesize;
|
||||
if (e->e_type != ET_EXEC) {
|
||||
Pexit(os, exe, 0, "ELF e_type != ET_EXEC");
|
||||
}
|
||||
if (e->e_machine != EM_NEXGEN32E) {
|
||||
Pexit(os, exe, 0, "ELF e_machine != EM_NEXGEN32E");
|
||||
}
|
||||
if (e->e_ident[EI_CLASS] != ELFCLASS64) {
|
||||
Pexit(os, exe, 0, "ELF e_ident[EI_CLASS] != ELFCLASS64");
|
||||
}
|
||||
if (e->e_ident[EI_DATA] != ELFDATA2LSB) {
|
||||
Pexit(os, exe, 0, "ELF e_ident[EI_DATA] != ELFDATA2LSB");
|
||||
}
|
||||
if (e->e_phoff + e->e_phnum * sizeof(*p) > 0x1000) {
|
||||
Pexit(os, exe, 0, "ELF phdrs need to be in first page");
|
||||
}
|
||||
code = 0;
|
||||
codesize = 0;
|
||||
for (p = (struct ElfPhdr *)(page + e->e_phoff), i = e->e_phnum; i--;) {
|
||||
if (p[i].p_type == PT_DYNAMIC) {
|
||||
Pexit(os, exe, 0, "not a real executable");
|
||||
}
|
||||
if (p[i].p_type != PT_LOAD) continue;
|
||||
if ((p[i].p_vaddr | p[i].p_filesz | p[i].p_memsz | p[i].p_offset) & 0xfff) {
|
||||
Pexit(os, exe, 0, "APE phdrs must be 4096-aligned and 4096-padded");
|
||||
}
|
||||
prot = 0;
|
||||
flags = MAP_FIXED | MAP_PRIVATE;
|
||||
if (p[i].p_flags & PF_R) {
|
||||
prot |= PROT_READ;
|
||||
}
|
||||
if (p[i].p_flags & PF_W) {
|
||||
prot |= PROT_WRITE;
|
||||
}
|
||||
if (p[i].p_flags & PF_X) {
|
||||
prot |= PROT_EXEC;
|
||||
code = p[i].p_vaddr;
|
||||
codesize = p[i].p_filesz;
|
||||
}
|
||||
if (p[i].p_memsz > p[i].p_filesz) {
|
||||
if ((rc = Mmap(p[i].p_vaddr + p[i].p_filesz, p[i].p_memsz - p[i].p_filesz,
|
||||
prot, flags | MAP_ANONYMOUS, -1, 0, os)) < 0) {
|
||||
Pexit(os, exe, rc, "bss mmap()");
|
||||
}
|
||||
}
|
||||
if (p[i].p_filesz) {
|
||||
if ((rc = Mmap(p[i].p_vaddr, p[i].p_filesz, prot, flags, fd,
|
||||
p[i].p_offset, os)) < 0) {
|
||||
Pexit(os, exe, rc, "image mmap()");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!code) {
|
||||
Pexit(os, exe, 0, "ELF needs PT_LOAD phdr w/ PF_X");
|
||||
}
|
||||
|
||||
#if SET_EXE_FILE
|
||||
// change /proc/pid/exe to new executable path
|
||||
if (IsLinux() && relocated) {
|
||||
MunmapLinux((char *)0x200000, (long)(_end - ehdr));
|
||||
PrctlLinux(PR_SET_MM, PR_SET_MM_EXE_FILE, fd, 0, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (relocated) {
|
||||
int ax;
|
||||
asm volatile("syscall"
|
||||
: "=a"(ax)
|
||||
: "0"(1), "D"(1), "S"("hello\n"), "d"(6)
|
||||
: "rcx", "r11", "memory");
|
||||
}
|
||||
|
||||
Close(fd, os);
|
||||
|
||||
// authorize only the loaded program to issue system calls. if this
|
||||
// fails, then we pass a link to our syscall function to the program
|
||||
// since it probably means a userspace program executed this loader
|
||||
// and passed us a custom syscall function earlier.
|
||||
if (Msyscall(code, codesize, os) != -1) {
|
||||
syscall = 0;
|
||||
}
|
||||
|
||||
#if TROUBLESHOOT
|
||||
Emit(TROUBLESHOOT_OS, "preparing to jump\n");
|
||||
#endif
|
||||
|
||||
// we clear all the general registers we can to have some wiggle room
|
||||
// to extend the behavior of this loader in the future. we don't need
|
||||
// to clear the xmm registers since the ape loader should be compiled
|
||||
// with the -mgeneral-regs-only flag.
|
||||
register void *r8 asm("r8") = syscall;
|
||||
asm volatile("xor\t%%eax,%%eax\n\t"
|
||||
"xor\t%%r9d,%%r9d\n\t"
|
||||
"xor\t%%r10d,%%r10d\n\t"
|
||||
"xor\t%%r11d,%%r11d\n\t"
|
||||
"xor\t%%ebx,%%ebx\n\t" // netbsd doesnt't clear this
|
||||
"xor\t%%r12d,%%r12d\n\t" // netbsd doesnt't clear this
|
||||
"xor\t%%r13d,%%r13d\n\t" // netbsd doesnt't clear this
|
||||
"xor\t%%r14d,%%r14d\n\t" // netbsd doesnt't clear this
|
||||
"xor\t%%r15d,%%r15d\n\t" // netbsd doesnt't clear this
|
||||
"mov\t%%rdx,%%rsp\n\t"
|
||||
"xor\t%%edx,%%edx\n\t"
|
||||
"push\t%%rsi\n\t"
|
||||
"xor\t%%esi,%%esi\n\t"
|
||||
"xor\t%%ebp,%%ebp\n\t"
|
||||
"ret"
|
||||
: /* no outputs */
|
||||
: "D"(IsFreebsd() ? sp : 0), "S"(e->e_entry), "d"(sp), "c"(os),
|
||||
"r"(r8)
|
||||
: "memory");
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
__attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl,
|
||||
struct ApeLoader *handoff) {
|
||||
int rc;
|
||||
long *auxv;
|
||||
struct ElfEhdr *eh;
|
||||
int c, i, fd, os, argc;
|
||||
char *p, *exe, *prog, **argv, **envp, *page;
|
||||
static union {
|
||||
struct ElfEhdr ehdr;
|
||||
char p[0x1000];
|
||||
} u;
|
||||
|
||||
// detect freebsd
|
||||
if (handoff) {
|
||||
os = handoff->os;
|
||||
} else if (SupportsXnu() && dl == XNU) {
|
||||
os = XNU;
|
||||
} else if (SupportsFreebsd() && di) {
|
||||
os = FREEBSD;
|
||||
sp = (long *)di;
|
||||
} else {
|
||||
os = 0;
|
||||
}
|
||||
|
||||
// extract arguments
|
||||
argc = *sp;
|
||||
argv = (char **)(sp + 1);
|
||||
envp = (char **)(sp + 1 + argc + 1);
|
||||
auxv = (long *)(sp + 1 + argc + 1);
|
||||
for (;;) {
|
||||
if (!*auxv++) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// get syscall function pointer
|
||||
if (handoff && handoff->syscall) {
|
||||
syscall = handoff->syscall;
|
||||
} else {
|
||||
syscall = __syscall_loader;
|
||||
}
|
||||
|
||||
if (handoff) {
|
||||
// we were called by ape_execve()
|
||||
// no argument parsing is needed
|
||||
// no path searching is needed
|
||||
exe = handoff->prog;
|
||||
fd = handoff->fd;
|
||||
exe = handoff->prog;
|
||||
page = handoff->page;
|
||||
eh = (struct ElfEhdr *)handoff->page;
|
||||
} else {
|
||||
|
||||
// detect openbsd
|
||||
if (SupportsOpenbsd() && !os && !auxv[0]) {
|
||||
os = OPENBSD;
|
||||
}
|
||||
|
||||
// detect netbsd
|
||||
if (SupportsNetbsd() && !os) {
|
||||
for (; auxv[0]; auxv += 2) {
|
||||
if (auxv[0] == AT_EXECFN_NETBSD) {
|
||||
os = NETBSD;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default operating system
|
||||
if (!os) {
|
||||
os = LINUX;
|
||||
}
|
||||
|
||||
#if SET_EXE_FILE
|
||||
if (IsLinux() && !relocated) {
|
||||
char *b1 = (char *)0x200000;
|
||||
char *b2 = (char *)0x300000;
|
||||
void (*pApeLoader)(long, long *, char, struct ApeLoader *);
|
||||
Mmap((long)b2, (long)(_end - ehdr), PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0, os);
|
||||
relocated = 1;
|
||||
MemCpy(b2, b1, (long)(_end - ehdr));
|
||||
pApeLoader = (void *)((char *)&ApeLoader - b1 + b2);
|
||||
pApeLoader(di, sp, dl, handoff);
|
||||
}
|
||||
#endif
|
||||
|
||||
// we can load via shell, shebang, or binfmt_misc
|
||||
if (argc >= 3 && !StrCmp(argv[1], "-")) {
|
||||
// if the first argument is a hyphen then we give the user the
|
||||
// power to change argv[0] or omit it entirely. most operating
|
||||
// systems don't permit the omission of argv[0] but we do, b/c
|
||||
// it's specified by ANSI X3.159-1988.
|
||||
prog = (char *)sp[3];
|
||||
argc = sp[3] = sp[0] - 3;
|
||||
argv = (char **)((sp += 3) + 1);
|
||||
} else if (argc < 2) {
|
||||
Emit(os, "usage: ape PROG [ARGV1,ARGV2,...]\n"
|
||||
" ape - PROG [ARGV0,ARGV1,...]\n"
|
||||
"αcτµαlly pδrταblε εxεcµταblε loader v1.o\n"
|
||||
"copyright 2022 justine alexandra roberts tunney\n"
|
||||
"https://justine.lol/ape.html\n");
|
||||
Exit(1, os);
|
||||
} else {
|
||||
prog = (char *)sp[2];
|
||||
argc = sp[1] = sp[0] - 1;
|
||||
argv = (char **)((sp += 1) + 1);
|
||||
}
|
||||
|
||||
if (!(exe = Commandv(&ps, os, prog, GetEnv(envp, "PATH")))) {
|
||||
Pexit(os, prog, 0, "not found (maybe chmod +x)");
|
||||
} else if ((fd = Open(exe, O_RDONLY, 0, os)) < 0) {
|
||||
Pexit(os, exe, fd, "open");
|
||||
} else if ((rc = Read(fd, u.p, sizeof(u.p), os)) < 0) {
|
||||
Pexit(os, exe, rc, "read");
|
||||
} else if (rc != sizeof(u.p) && Read32(u.p) != Read32("\177ELF")) {
|
||||
Pexit(os, exe, 0, "too small");
|
||||
}
|
||||
|
||||
page = u.p;
|
||||
eh = &u.ehdr;
|
||||
}
|
||||
|
||||
#if TROUBLESHOOT
|
||||
Emit(TROUBLESHOOT_OS, "os = ");
|
||||
Emit(TROUBLESHOOT_OS, DescribeOs(os));
|
||||
Emit(TROUBLESHOOT_OS, "\n");
|
||||
for (i = 0; i < argc; ++i) {
|
||||
Emit(TROUBLESHOOT_OS, "argv = ");
|
||||
Emit(TROUBLESHOOT_OS, argv[i]);
|
||||
Emit(TROUBLESHOOT_OS, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((IsXnu() && Read32(page) == 0xFEEDFACE + 1) ||
|
||||
(!IsXnu() && Read32(page) == Read32("\177ELF"))) {
|
||||
Close(fd, os);
|
||||
Execve(exe, argv, envp, os);
|
||||
}
|
||||
|
||||
// TODO(jart): Parse Mach-O for old APE binary support on XNU.
|
||||
for (p = page; p < page + sizeof(u.p); ++p) {
|
||||
if (Read64(p) != Read64("printf '")) continue;
|
||||
for (i = 0, p += 8; p + 3 < page + sizeof(u.p) && (c = *p++) != '\'';) {
|
||||
if (c == '\\') {
|
||||
if ('0' <= *p && *p <= '7') {
|
||||
c = *p++ - '0';
|
||||
if ('0' <= *p && *p <= '7') {
|
||||
c *= 8;
|
||||
c += *p++ - '0';
|
||||
if ('0' <= *p && *p <= '7') {
|
||||
c *= 8;
|
||||
c += *p++ - '0';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
page[i++] = c;
|
||||
}
|
||||
if (i >= 64 && Read32(page) == Read32("\177ELF")) {
|
||||
Spawn(os, exe, fd, sp, page, eh);
|
||||
}
|
||||
}
|
||||
|
||||
Pexit(os, exe, 0, "could not find printf elf in first page");
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef COSMOPOLITAN_APE_LOADER_H_
|
||||
#define COSMOPOLITAN_APE_LOADER_H_
|
||||
|
||||
#define APE_LOADER_BASE 0x200000
|
||||
#define APE_LOADER_SIZE 0x200000
|
||||
#define APE_LOADER_ENTRY 0x200400
|
||||
#define APE_LOADER_BSS (PAGESIZE * 2)
|
||||
#define APE_LOADER_STACK 0x7f0000000000
|
||||
#define APE_BLOCK_BASE 0x7e0000000000
|
||||
#define APE_BLOCK_SIZE 0x000200000000
|
||||
|
||||
struct ApeLoader {
|
||||
int fd;
|
||||
int os;
|
||||
char *prog;
|
||||
char *page;
|
||||
void *syscall;
|
||||
};
|
||||
|
||||
#endif /* COSMOPOLITAN_APE_LOADER_H_ */
|
||||
@@ -0,0 +1,43 @@
|
||||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x200000;
|
||||
.text : {
|
||||
*(.text)
|
||||
*(.rodata .rodata.*)
|
||||
. = ALIGN(64);
|
||||
}
|
||||
filesz = . - ehdr;
|
||||
textsz = . - _start;
|
||||
.bss ALIGN(4096) : {
|
||||
bss = .;
|
||||
*(.bss)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
_end = .;
|
||||
memsz = _end - ehdr;
|
||||
/DISCARD/ : {
|
||||
*(.*)
|
||||
}
|
||||
}
|
||||
|
||||
bsssize = SIZEOF(.bss);
|
||||
textoff = _start - ehdr;
|
||||
@@ -54,7 +54,7 @@
|
||||
jmp 297f
|
||||
.byte 0xbf # mov $0x????xxxx,%edi
|
||||
.long \address
|
||||
297:
|
||||
297:
|
||||
.endm
|
||||
|
||||
// Loads 16-bit CONSTEXPR into Qw-register w/ optional zero-extend.
|
||||
|
||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
+71
-55
@@ -5,21 +5,19 @@
|
||||
#
|
||||
# - `make`
|
||||
# - Backtraces
|
||||
# - Syscall tracing
|
||||
# - Function tracing
|
||||
# - Reasonably small
|
||||
# - Reasonably optimized
|
||||
# - Reasonably debuggable
|
||||
|
||||
ifeq ($(MODE),)
|
||||
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
$(FTRACE) \
|
||||
-Og
|
||||
|
||||
-DSYSDEBUG \
|
||||
-O2
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
|
||||
endif
|
||||
|
||||
# Optimized Mode
|
||||
@@ -27,25 +25,47 @@ endif
|
||||
# - `make MODE=opt`
|
||||
# - Backtraces
|
||||
# - More optimized
|
||||
# - Syscall tracing
|
||||
# - Function tracing
|
||||
# - Reasonably small
|
||||
# - No memory corruption detection
|
||||
# - assert() / CHECK_xx() may leak code into binary for debuggability
|
||||
# - GCC 8+ hoists check fails into .text.cold, thus minimizing impact
|
||||
|
||||
ifeq ($(MODE), opt)
|
||||
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DNDEBUG \
|
||||
-msse2avx \
|
||||
-Wa,-msse2avx
|
||||
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
-O3
|
||||
|
||||
$(FTRACE) \
|
||||
-DSYSDEBUG \
|
||||
-O3 \
|
||||
-fmerge-all-constants
|
||||
TARGET_ARCH ?= \
|
||||
-march=native
|
||||
endif
|
||||
|
||||
# Optimized Linux Mode
|
||||
#
|
||||
# - `make MODE=optlinux`
|
||||
# - Turns on red zone
|
||||
# - Turns off backtraces
|
||||
# - Turns off function tracing
|
||||
# - Turns off support for older cpu models
|
||||
# - Turns off support for other operating systems
|
||||
ifeq ($(MODE), optlinux)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DNDEBUG \
|
||||
-msse2avx \
|
||||
-Wa,-msse2avx \
|
||||
-DSUPPORT_VECTOR=1
|
||||
CONFIG_CCFLAGS += \
|
||||
-O3 -fmerge-all-constants
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
TARGET_ARCH ?= \
|
||||
-march=native
|
||||
endif
|
||||
|
||||
# Release Mode
|
||||
@@ -61,19 +81,16 @@ endif
|
||||
# - DCHECK_xx() statements removed
|
||||
# - No memory corruption detection
|
||||
# - CHECK_xx() won't leak strings into binary
|
||||
|
||||
ifeq ($(MODE), rel)
|
||||
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DNDEBUG
|
||||
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
-O2
|
||||
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
|
||||
PYFLAGS += \
|
||||
-O1
|
||||
endif
|
||||
|
||||
# Asan Mode
|
||||
@@ -86,19 +103,14 @@ endif
|
||||
# - Backtraces
|
||||
# - Debuggability
|
||||
# - Larger binaries
|
||||
|
||||
ifeq ($(MODE), asan)
|
||||
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
-O2
|
||||
|
||||
CONFIG_COPTS += \
|
||||
-fsanitize=address
|
||||
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
|
||||
endif
|
||||
|
||||
# Debug Mode
|
||||
@@ -110,26 +122,22 @@ endif
|
||||
# - Stack canaries
|
||||
# - No optimization (TODO)
|
||||
# - Enormous binaries
|
||||
|
||||
ifeq ($(MODE), dbg)
|
||||
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DMODE_DBG
|
||||
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
$(FTRACE) \
|
||||
-O2
|
||||
|
||||
-DSYSDEBUG \
|
||||
-O2 \
|
||||
-fno-inline
|
||||
CONFIG_COPTS += \
|
||||
-fsanitize=address
|
||||
|
||||
-fsanitize=address \
|
||||
-fsanitize=undefined
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
|
||||
OVERRIDE_CCFLAGS += \
|
||||
-fno-pie
|
||||
|
||||
endif
|
||||
|
||||
# Tiny Mode
|
||||
@@ -143,20 +151,26 @@ endif
|
||||
# - No backtraces
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
|
||||
ifeq ($(MODE), tiny)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops
|
||||
TARGET_ARCH ?= \
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops \
|
||||
-fschedule-insns2 \
|
||||
-fomit-frame-pointer \
|
||||
-momit-leaf-frame-pointer \
|
||||
-foptimize-sibling-calls
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
PYFLAGS += \
|
||||
-O2 \
|
||||
-B
|
||||
endif
|
||||
|
||||
# Linux-Only Tiny Mode
|
||||
@@ -171,20 +185,21 @@ endif
|
||||
# - No portability
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
|
||||
ifeq ($(MODE), tinylinux)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY \
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY \
|
||||
-DSUPPORT_VECTOR=1
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops
|
||||
TARGET_ARCH ?= \
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
endif
|
||||
|
||||
@@ -201,13 +216,14 @@ endif
|
||||
# - No backtraces
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
|
||||
ifeq ($(MODE), tinylinuxbsd)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY \
|
||||
-DSUPPORT_VECTOR=113
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
@@ -230,13 +246,14 @@ endif
|
||||
# - No backtraces
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
|
||||
ifeq ($(MODE), tinysysv)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY \
|
||||
-DSUPPORT_VECTOR=121
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
@@ -259,7 +276,6 @@ endif
|
||||
# - No backtraces
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
|
||||
ifeq ($(MODE), tinynowin)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
@@ -279,7 +295,7 @@ endif
|
||||
# LLVM Mode
|
||||
ifeq ($(MODE), llvm)
|
||||
TARGET_ARCH ?= -msse3
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -O2
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -DSYSDEBUG -O2
|
||||
AS = clang
|
||||
CC = clang
|
||||
CXX = clang++
|
||||
|
||||
+61
-24
@@ -42,7 +42,6 @@
|
||||
# ASFLAGS assembler flags (don't use -Wa, frontend prefix)
|
||||
# TARGET_ARCH microarchitecture flags (e.g. -march=native)
|
||||
|
||||
V ?= 1
|
||||
LC_ALL = C
|
||||
SOURCE_DATE_EPOCH = 0
|
||||
|
||||
@@ -51,15 +50,43 @@ ARFLAGS = rcsD
|
||||
ZFLAGS ?=
|
||||
XARGS ?= xargs -P4 -rs8000
|
||||
DOT ?= dot
|
||||
GZ ?= gzip
|
||||
CLANG = clang
|
||||
FC = gfortran #/opt/cross9f/bin/x86_64-linux-musl-gfortran
|
||||
TMPDIR = o/tmp
|
||||
|
||||
# see build/compile, etc. which run third_party/gcc/unbundle.sh
|
||||
AR = build/bootstrap/ar.com
|
||||
CP = build/bootstrap/cp.com
|
||||
RM = build/bootstrap/rm.com -f
|
||||
ECHO = build/bootstrap/echo.com
|
||||
TOUCH = build/bootstrap/touch.com
|
||||
PKG = build/bootstrap/package.com
|
||||
MKDEPS = build/bootstrap/mkdeps.com
|
||||
ZIPOBJ = build/bootstrap/zipobj.com
|
||||
FIXUPOBJ = build/bootstrap/fixupobj.com
|
||||
MKDIR = build/bootstrap/mkdir.com -p
|
||||
COMPILE = build/bootstrap/compile.com -V9 -P4096 $(QUOTA)
|
||||
|
||||
COMMA := ,
|
||||
PWD := $(shell build/bootstrap/pwd.com)
|
||||
IMAGE_BASE_VIRTUAL ?= 0x400000
|
||||
|
||||
IGNORE := $(shell $(ECHO) -2 ♥cosmo)
|
||||
IGNORE := $(shell $(MKDIR) o/tmp)
|
||||
|
||||
ifneq ("$(wildcard o/third_party/gcc/bin/x86_64-pc-linux-gnu-as.exe)","")
|
||||
AS = o/third_party/gcc/bin/x86_64-pc-linux-gnu-as.exe
|
||||
CC = o/third_party/gcc/bin/x86_64-pc-linux-gnu-gcc.exe
|
||||
CXX = o/third_party/gcc/bin/x86_64-pc-linux-gnu-g++.exe
|
||||
CXXFILT = o/third_party/gcc/bin/x86_64-pc-linux-gnu-c++filt.exe
|
||||
LD = o/third_party/gcc/bin/x86_64-pc-linux-gnu-ld.bfd.exe
|
||||
NM = o/third_party/gcc/bin/x86_64-pc-linux-gnu-nm.exe
|
||||
GCC = o/third_party/gcc/bin/x86_64-pc-linux-gnu-gcc.exe
|
||||
STRIP = o/third_party/gcc/bin/x86_64-pc-linux-gnu-strip.exe
|
||||
OBJCOPY = o/third_party/gcc/bin/x86_64-pc-linux-gnu-objcopy.exe
|
||||
OBJDUMP = o/third_party/gcc/bin/x86_64-pc-linux-gnu-objdump.exe
|
||||
ADDR2LINE = $(PWD)/o/third_party/gcc/bin/x86_64-pc-linux-gnu-addr2line.exe
|
||||
else
|
||||
IGNORE := $(shell build/bootstrap/unbundle.com)
|
||||
AS = o/third_party/gcc/bin/x86_64-linux-musl-as
|
||||
CC = o/third_party/gcc/bin/x86_64-linux-musl-gcc
|
||||
CXX = o/third_party/gcc/bin/x86_64-linux-musl-g++
|
||||
@@ -70,34 +97,39 @@ GCC = o/third_party/gcc/bin/x86_64-linux-musl-gcc
|
||||
STRIP = o/third_party/gcc/bin/x86_64-linux-musl-strip
|
||||
OBJCOPY = o/third_party/gcc/bin/x86_64-linux-musl-objcopy
|
||||
OBJDUMP = o/third_party/gcc/bin/x86_64-linux-musl-objdump
|
||||
ADDR2LINE = o/third_party/gcc/bin/x86_64-linux-musl-addr2line
|
||||
|
||||
COMMA := ,
|
||||
PWD := $(shell pwd)
|
||||
IMAGE_BASE_VIRTUAL ?= 0x400000
|
||||
HELLO := $(shell build/hello)
|
||||
TMPDIR := $(shell build/findtmp)
|
||||
SPAWNER := $(shell build/getcompile) -V$(shell build/getccversion $(CC))
|
||||
COMPILE = $(SPAWNER) $(QUOTA)
|
||||
ADDR2LINE = $(PWD)/o/third_party/gcc/bin/x86_64-linux-musl-addr2line
|
||||
endif
|
||||
|
||||
export ADDR2LINE
|
||||
export LC_ALL
|
||||
export MKDIR
|
||||
export MODE
|
||||
export SOURCE_DATE_EPOCH
|
||||
export TMPDIR
|
||||
export V
|
||||
|
||||
ifeq ($(LANDLOCKMAKE_VERSION),)
|
||||
TMPSAFE = $(TMPDIR)/$(subst /,_,$@).tmp
|
||||
else
|
||||
TMPSAFE = $(TMPDIR)/
|
||||
endif
|
||||
|
||||
FTRACE = \
|
||||
-pg
|
||||
|
||||
BACKTRACES = \
|
||||
-fno-schedule-insns2 \
|
||||
-fno-omit-frame-pointer \
|
||||
-fno-optimize-sibling-calls \
|
||||
-mno-omit-leaf-frame-pointer
|
||||
|
||||
SANITIZER = \
|
||||
-fsanitize=address
|
||||
|
||||
NO_MAGIC = \
|
||||
-mno-fentry \
|
||||
-fno-stack-protector \
|
||||
-fno-sanitize=all \
|
||||
-fwrapv
|
||||
-fwrapv \
|
||||
-fno-sanitize=all
|
||||
|
||||
OLD_CODE = \
|
||||
-fno-strict-aliasing \
|
||||
@@ -111,7 +143,7 @@ TRADITIONAL = \
|
||||
DEFAULT_CCFLAGS = \
|
||||
-Wall \
|
||||
-Werror \
|
||||
-fdebug-prefix-map="$(PWD)"= \
|
||||
-fdebug-prefix-map='$(PWD)'= \
|
||||
-frecord-gcc-switches
|
||||
|
||||
DEFAULT_OFLAGS = \
|
||||
@@ -128,9 +160,8 @@ DEFAULT_COPTS = \
|
||||
-fno-gnu-unique \
|
||||
-fstrict-aliasing \
|
||||
-fstrict-overflow \
|
||||
-fno-omit-frame-pointer \
|
||||
-fno-semantic-interposition \
|
||||
-mno-omit-leaf-frame-pointer
|
||||
-mno-tls-direct-seg-refs
|
||||
|
||||
MATHEMATICAL = \
|
||||
-O3 \
|
||||
@@ -141,19 +172,19 @@ DEFAULT_CPPFLAGS = \
|
||||
-DMODE='"$(MODE)"' \
|
||||
-DIMAGE_BASE_VIRTUAL=$(IMAGE_BASE_VIRTUAL) \
|
||||
-nostdinc \
|
||||
-iquote.
|
||||
-iquote .
|
||||
|
||||
DEFAULT_CFLAGS = \
|
||||
-std=gnu2x
|
||||
|
||||
DEFAULT_CXXFLAGS = \
|
||||
-std=gnu++11 \
|
||||
-fno-rtti \
|
||||
-fno-exceptions \
|
||||
-fuse-cxa-atexit \
|
||||
-fno-threadsafe-statics \
|
||||
-Wno-int-in-bool-context \
|
||||
-Wno-narrowing
|
||||
-Wno-narrowing \
|
||||
-Wno-literal-suffix
|
||||
|
||||
DEFAULT_ASFLAGS = \
|
||||
-W \
|
||||
@@ -164,19 +195,22 @@ DEFAULT_ASFLAGS = \
|
||||
DEFAULT_LDFLAGS = \
|
||||
-static \
|
||||
-nostdlib \
|
||||
-m elf_x86_64 \
|
||||
-melf_x86_64 \
|
||||
--gc-sections \
|
||||
--build-id=none \
|
||||
--no-dynamic-linker \
|
||||
-z max-page-size=0x1000
|
||||
-zmax-page-size=0x1000 #--cref [email protected]
|
||||
|
||||
ZIPOBJ_FLAGS = \
|
||||
-b$(IMAGE_BASE_VIRTUAL)
|
||||
|
||||
PYFLAGS = \
|
||||
-b$(IMAGE_BASE_VIRTUAL)
|
||||
|
||||
ASONLYFLAGS = \
|
||||
-c \
|
||||
-g \
|
||||
--debug-prefix-map="$(PWD)"=
|
||||
--debug-prefix-map='$(PWD)'=
|
||||
|
||||
DEFAULT_LDLIBS =
|
||||
|
||||
@@ -297,6 +331,9 @@ OBJECTIFY.greg.c = \
|
||||
-fno-instrument-functions \
|
||||
-fno-optimize-sibling-calls \
|
||||
-fno-sanitize=all \
|
||||
-ffreestanding \
|
||||
-mno-fentry \
|
||||
-fwrapv \
|
||||
-c
|
||||
|
||||
OBJECTIFY.ansi.c = $(CC) $(OBJECTIFY.c.flags) -ansi -Wextra -Werror -pedantic-errors -c
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
#!/bin/sh
|
||||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# Temporary Directory Discovery
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# We call this script once per build to ideally find a folder that's
|
||||
# backed by an in-memory file system. We then export it to the TMPDIR
|
||||
# environment variable. Many programs use it under the hood, e.g. gcc,
|
||||
# so it grants many small performance improvements.
|
||||
|
||||
mkdir -p o/tmp
|
||||
echo o/tmp
|
||||
+5
-1
@@ -12,5 +12,9 @@
|
||||
|
||||
tail = $(wordlist 2,$(words $1),$1)
|
||||
reverse = $(if $1,$(call reverse,$(call tail,$1)) $(firstword $1))
|
||||
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
|
||||
uniqr = $(if $1,$(call uniqr,$(filter-out $(firstword $1),$1)) $(firstword $1))
|
||||
|
||||
# polyfill uniq native (landlock make 1.4)
|
||||
ifneq ($(call uniq,c b c a),c b a)
|
||||
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
|
||||
endif
|
||||
@@ -1,39 +0,0 @@
|
||||
#!/bin/sh
|
||||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# Compiler Version Discovery
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Cosmopolitan itself may be built using either GCC and Clang, and our
|
||||
# build irons out many of the differences between the two. This script
|
||||
# is used by build/definitions.mk alongside build/getccname to support
|
||||
# the different versions folks use.
|
||||
#
|
||||
# Our aim is to support GCC 4.2.1+ since that's the last GPLv2 version
|
||||
# with any sort of industry consensus. Please note, Cosmopolitan never
|
||||
# links GCC runtimes when using later versions, so some concerns might
|
||||
# not apply.
|
||||
|
||||
if [ ! -d o/third_party/gcc ]; then
|
||||
third_party/gcc/unbundle.sh
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
MAJOR_VERSION=$(
|
||||
$1 --version |
|
||||
head -n1 |
|
||||
sed -n '
|
||||
s!^[^(]*([^)]*) \([[:digit:]][[:digit:]]*\).*!\1!p
|
||||
s!^.*clang.*version \([[:digit:]][[:digit:]]*\).*!\1!p
|
||||
')
|
||||
|
||||
if [ -z "$MAJOR_VERSION" ]; then
|
||||
echo 6
|
||||
else
|
||||
printf '%s\n' "$MAJOR_VERSION"
|
||||
fi
|
||||
@@ -1,12 +0,0 @@
|
||||
#!/bin/sh
|
||||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
|
||||
if ! [ o/build/bootstrap/compile.com -nt build/bootstrap/compile.com ]; then
|
||||
mkdir -p o/build/bootstrap/
|
||||
cp -f build/bootstrap/compile.com o/build/bootstrap/compile.$$.com
|
||||
o/build/bootstrap/compile.$$.com -n
|
||||
mv -f o/build/bootstrap/compile.$$.com o/build/bootstrap/compile.com
|
||||
fi
|
||||
|
||||
echo o/build/bootstrap/compile.com
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
#!/bin/sh
|
||||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# HELLO BUILD
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
# We generate a line at the start of each Makefile run, because if we
|
||||
# use `make V=0` mode then the terminal logging trick we use in
|
||||
# tool/build/compile.c will delete the previous line, and we'd rather
|
||||
# have that line not be the bash prompt that ran make.
|
||||
#
|
||||
# This script is also useful for giving us an indicator each time the
|
||||
# build restarts itself from scratch, which can happen in cases like
|
||||
# when dependencies need to be regenerated by tool/build/mkdeps.c
|
||||
|
||||
echo ♥cosmo >&2
|
||||
+5
-1
@@ -43,12 +43,16 @@
|
||||
# '(progn
|
||||
# (add-hook 'c-mode-common-hook 'jart-c-mode-common-hook)))
|
||||
|
||||
# ctags doesn't understand atomics, e.g.
|
||||
# extern char **environ;
|
||||
set -- --regex-c='/_Atomic(\([^)]*\))/\1/b' "$@"
|
||||
|
||||
# ctags doesn't understand variable prototypes, e.g.
|
||||
# extern char **environ;
|
||||
set -- --regex-c='/^\(\(hidden\|extern\|const\) \)*[_[:alpha:]][_[:alnum:]]*[ *][ *]*\([_[:alpha:]][_[:alnum:]]*[ *][ *]*\)*\([_[:alpha:]][_$[:alnum:]]*\)/\4/b' "$@"
|
||||
|
||||
# ctags doesn't understand function prototypes, e.g.
|
||||
# bool isheap(void *p) nothrow nocallback;
|
||||
# bool isheap(void *p) dontthrow nocallback;
|
||||
set -- --regex-c='/^[_[:alpha:]][_[:alnum:]]*[ *][ *]*\([_[:alpha:]][_[:alnum:]]*[ *][ *]*\)*\([_[:alpha:]][_$[:alnum:]]*\)(.*/\2/b' "$@"
|
||||
|
||||
# ctags doesn't understand function pointers, e.g.
|
||||
|
||||
+2
-1
@@ -23,8 +23,9 @@
|
||||
# - tool/build/runitd.c
|
||||
|
||||
.PRECIOUS: o/$(MODE)/%.com.ok
|
||||
o/$(MODE)/%.com.ok: .PLEDGE = stdio rpath wpath cpath proc fattr inet
|
||||
o/$(MODE)/%.com.ok: \
|
||||
o/$(MODE)/tool/build/runit.com \
|
||||
o/$(MODE)/tool/build/runitd.com \
|
||||
o/$(MODE)/%.com
|
||||
@$(COMPILE) -ATEST -tT$@ $^ $(HOSTS)
|
||||
@$(COMPILE) -wATEST -tT$@ $^ $(HOSTS)
|
||||
+163
-37
@@ -16,70 +16,196 @@
|
||||
|
||||
MAKEFLAGS += --no-builtin-rules
|
||||
|
||||
o/%.a: ; @$(COMPILE) -AARCHIVE -T$@ $(AR) $(ARFLAGS) $@ $^
|
||||
o/%.o: %.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||
o/%.o: o/%.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||
o/%.s: %.S ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/%.s: o/%.S ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/%.i: %.S ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/%.o: %.S ; @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) $<
|
||||
o/%.o: o/%.S ; @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) $<
|
||||
o/%.s: %.i ; @$(COMPILE) -ACOMPILE.i $(COMPILE.i) $(OUTPUT_OPTION) $<
|
||||
o/%.s: o/%.i ; @$(COMPILE) -ACOMPILE.i $(COMPILE.i) $(OUTPUT_OPTION) $<
|
||||
o/%.o: %.cc ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
o/%.o: o/%.cc ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
o/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
|
||||
o/%.inc: %.h ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) -D__ASSEMBLER__ -P $<
|
||||
o/%.pkg: ; @$(COMPILE) -APACKAGE -T$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) $(filter %.o,$^)
|
||||
o/%.h.ok: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.c) -x c -g0 -o $@ $<
|
||||
o/%.h.okk: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.cxx) -x c++ -g0 -o $@ $<
|
||||
o/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
o/%.zip.o: o/% ; @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%.a: ; @$(COMPILE) -AARCHIVE -T$@ $(AR) $(ARFLAGS) $@ $^
|
||||
o/$(MODE)/%: o/$(MODE)/%.dbg ; @$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
|
||||
o/$(MODE)/%.o: %.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: o/$(MODE)/%.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.s: %.S ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.s: o/$(MODE)/%.S ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: %.f ; @$(COMPILE) -AOBJECTIFY.f $(OBJECTIFY.f) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: %.F ; @$(COMPILE) -AOBJECTIFY.F $(OBJECTIFY.F) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: o/$(MODE)/%.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.ss: %.c ; @$(COMPILE) -ACOMPILE.c $(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.ss: o/$(MODE)/%.c ; @$(COMPILE) -AOBJECTIFY.s $(COMPILE.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.i: %.S ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.i: %.c ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.i: %.cc ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.i: o/$(MODE)/%.c ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.h: %.c ; @$(COMPILE) -AAMALGAMATE $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $<
|
||||
o/$(MODE)/%.h: o/$(MODE)/%.c ; @$(COMPILE) -AAMALGAMATE $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $<
|
||||
o/$(MODE)/%.o: %.S ; @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: o/$(MODE)/%.S ; @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.s: %.i ; @$(COMPILE) -ACOMPILE.i $(COMPILE.i) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.s: o/$(MODE)/%.i ; @$(COMPILE) -ACOMPILE.i $(COMPILE.i) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: %.cc ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: o/$(MODE)/%.cc ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.h.ok: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.c) -x c -g0 -o $@ $<
|
||||
o/$(MODE)/%.h.okk: %.h ; @$(COMPILE) -ACHECK.h $(COMPILE.cxx) -x c++ -g0 -o $@ $<
|
||||
o/$(MODE)/%.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.ansi.o: %.ansi.c ; @$(COMPILE) -AOBJECTIFY.ansi $(OBJECTIFY.ansi.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.ansi.o: %.c ; @$(COMPILE) -AOBJECTIFY.ansi $(OBJECTIFY.ansi.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.c99.o: %.c99.c ; @$(COMPILE) -AOBJECTIFY.c99 $(OBJECTIFY.c99.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.c11.o: %.c11.c ; @$(COMPILE) -AOBJECTIFY.c11 $(OBJECTIFY.c11.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.c2x.o: %.c2x.c ; @$(COMPILE) -AOBJECTIFY.c2x $(OBJECTIFY.c2x.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.initabi.o: %.initabi.c ; @$(COMPILE) -AOBJECTIFY.init $(OBJECTIFY.initabi.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.ncabi.o: %.ncabi.c ; @$(COMPILE) -AOBJECTIFY.nc $(OBJECTIFY.ncabi.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.real.o: %.c ; @$(COMPILE) -AOBJECTIFY.real $(OBJECTIFY.real.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.runs: o/$(MODE)/% ; @$(COMPILE) -ACHECK -tT$@ $< $(TESTARGS)
|
||||
o/$(MODE)/%.pkg: ; @$(COMPILE) -APACKAGE -T$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) $(filter %.o,$^)
|
||||
o/$(MODE)/%.zip.o: % ; @$(COMPILE) -AZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%-gcc.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%-clang.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $< || echo / need $(CLANG) >$@
|
||||
o/$(MODE)/%-gcc.asm: %.cc ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.cxx) -S -g0 $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%-clang.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%-clang.asm: %.cc ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.cxx) -S -g0 $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%-clang.asm: CC = $(CLANG)
|
||||
|
||||
o/%.o: %.cc
|
||||
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||
|
||||
o/%.o: o/%.cc
|
||||
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||
|
||||
o/$(MODE)/%.o: %.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) $(OUTPUT_OPTION) $<
|
||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||
|
||||
o/$(MODE)/%.o: o/$(MODE)/%.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) $(OUTPUT_OPTION) $<
|
||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||
|
||||
o/$(MODE)/%.o: o/$(MODE)/%.cc
|
||||
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||
|
||||
o/%.a:
|
||||
$(file >$(TMPDIR)/$(subst /,_,$@),$^)
|
||||
@$(COMPILE) -AARCHIVE -wT$@ $(AR) $(ARFLAGS) $@ @$(TMPDIR)/$(subst /,_,$@)
|
||||
|
||||
o/%.pkg:
|
||||
$(file >$(TMPSAFE).args,$(filter %.o,$^))
|
||||
@$(COMPILE) -APACKAGE -wT$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) @$(TMPSAFE).args
|
||||
|
||||
o/$(MODE)/%.pkg:
|
||||
$(file >$(TMPSAFE).args,$(filter %.o,$^))
|
||||
@$(COMPILE) -APACKAGE -wT$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) @$(TMPSAFE).args
|
||||
|
||||
o/$(MODE)/%.o: %.py o/$(MODE)/third_party/python/pyobj.com
|
||||
@$(COMPILE) -wAPYOBJ o/$(MODE)/third_party/python/pyobj.com $(PYFLAGS) -o $@ $<
|
||||
|
||||
o/$(MODE)/%.pyc: %.py o/$(MODE)/third_party/python/pycomp.com
|
||||
@$(COMPILE) -wAPYCOMP o/$(MODE)/third_party/python/pycomp.com $(PYCFLAGS) -o $@ $<
|
||||
|
||||
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac.com
|
||||
@$(COMPILE) -ALUAC -T$@ o/$(MODE)/third_party/lua/luac.com -s -o $@ $<
|
||||
@$(COMPILE) -wALUAC o/$(MODE)/third_party/lua/luac.com -s -o $@ $<
|
||||
|
||||
o/$(MODE)/%-clang.asm: CC = $(CLANG)
|
||||
o/$(MODE)/%.lua.runs: %.lua o/$(MODE)/tool/net/redbean.com
|
||||
@$(COMPILE) -wALUA -tT$@ o/$(MODE)/tool/net/redbean.com $(LUAFLAGS) -i $<
|
||||
|
||||
o/$(MODE)/%: o/$(MODE)/%.com o/$(MODE)/tool/build/cp.com o/$(MODE)/tool/build/assimilate.com
|
||||
@$(COMPILE) -wACP -T$@ o/$(MODE)/tool/build/cp.com $< $@
|
||||
@$(COMPILE) -wAASSIMILATE -T$@ o/$(MODE)/tool/build/assimilate.com $@
|
||||
|
||||
################################################################################
|
||||
# LOCAL UNIT TESTS
|
||||
#
|
||||
# We always run unit tests as part of the normal `make` invocation. you
|
||||
# may override the $(TESTARGS) variable to do things such as enable the
|
||||
# benchmarking feature. For example:
|
||||
#
|
||||
# TESTARGS = -b
|
||||
#
|
||||
# May be specified in your ~/.cosmo.mk file. You can also use this to
|
||||
# enable things like function tracing. For example:
|
||||
#
|
||||
# TESTARGS = ----ftrace
|
||||
# .PLEDGE += prot_exec
|
||||
#
|
||||
# You could then run a command like:
|
||||
#
|
||||
# make -j8 o//test/libc/calls/openbsd_test.com.runs
|
||||
#
|
||||
# You need PROT_EXEC permission since ftrace morphs the binary. It's
|
||||
# also worth mentioning that the pledge.com command can simulate what
|
||||
# Landlock Make does:
|
||||
#
|
||||
# o//tool/build/pledge.com \
|
||||
# -v. -p 'stdio rpath wpath cpath tty prot_exec' \
|
||||
# o//test/libc/calls/openbsd_test.com \
|
||||
# ----ftrace
|
||||
#
|
||||
# This is useful in the event a test binary should run by itself, but
|
||||
# fails to run beneath Landlock Make. It's also useful sometimes to
|
||||
# override the verbosity when running tests:
|
||||
#
|
||||
# make V=5 TESTARGS=-b o//test/libc/calls/openbsd_test.com.runs
|
||||
#
|
||||
# This way, if for some reason a test should fail but calls exit(0),
|
||||
# then the stdout/stderr output, which would normally be suppressed,
|
||||
# will actually be displayed.
|
||||
|
||||
o/$(MODE)/%.runs: o/$(MODE)/%
|
||||
@$(COMPILE) -ACHECK -wtT$@ $< $(TESTARGS)
|
||||
|
||||
################################################################################
|
||||
# ELF ZIP FILES
|
||||
#
|
||||
# zipobj.com lets us do fast incremental linking of compressed data.
|
||||
# it's nice because if we link a hundred binaries that use the time zone
|
||||
# database, then that database only needs to be DEFLATE'd once.
|
||||
|
||||
o/%.zip.o: o/%
|
||||
@$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%.zip.o: %
|
||||
@$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%.zip.o: %
|
||||
@$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
|
||||
|
||||
# an issue with sandboxing arises when creating directory entries in the
|
||||
# zip file. we need the trailing slash (e.g. o//foo/.zip.o) but Landlock
|
||||
# Make avoids sandboxing directory names that have a trailing slash (so
|
||||
# they can be used to watch for deleted files, without creating overly
|
||||
# broad unveiling). such rules need to be written more explicitly.
|
||||
o/$(MODE)%/.zip.o: %
|
||||
@$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
|
||||
|
||||
################################################################################
|
||||
# STRICT HEADER CHECKING
|
||||
#
|
||||
# these rules are unsandboxed since they're already a sandboxing test,
|
||||
# and it would be too costly in terms of make latency to have every
|
||||
# header file depend on $(HDRS) and $(INCS).
|
||||
|
||||
o/%.h.ok: .UNSANDBOXED = 1
|
||||
o/%.h.ok: %.h
|
||||
@$(COMPILE) -ACHECK.h $(COMPILE.c) -xc -g0 -o $@ $<
|
||||
|
||||
o/$(MODE)/%.h.ok: .UNSANDBOXED = 1
|
||||
o/$(MODE)/%.h.ok: %.h
|
||||
@$(COMPILE) -ACHECK.h $(COMPILE.c) -xc -g0 -o $@ $<
|
||||
|
||||
o/$(MODE)/%.hh.ok: .UNSANDBOXED = 1
|
||||
o/$(MODE)/%.hh.ok: %.hh
|
||||
@$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
|
||||
|
||||
o/%.okk: .UNSANDBOXED = 1
|
||||
o/%.okk: %
|
||||
@$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
|
||||
|
||||
o/$(MODE)/%.okk: .UNSANDBOXED = 1
|
||||
o/$(MODE)/%.okk: %
|
||||
@$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
|
||||
|
||||
################################################################################
|
||||
# EXECUTABLE HELPERS
|
||||
|
||||
MAKE_OBJCOPY = \
|
||||
$(COMPILE) -AOBJCOPY -T$@ \
|
||||
$(OBJCOPY) -S -O binary $< $@
|
||||
|
||||
MAKE_SYMTAB_CREATE = \
|
||||
$(COMPILE) -wASYMTAB \
|
||||
o/$(MODE)/tool/build/symtab.com \
|
||||
-o $(TMPSAFE)/.symtab \
|
||||
$<
|
||||
|
||||
MAKE_SYMTAB_ZIP = \
|
||||
$(COMPILE) -AZIP -T$@ \
|
||||
o/$(MODE)/third_party/zip/zip.com \
|
||||
-b$(TMPDIR) \
|
||||
-9qj \
|
||||
$@ \
|
||||
$(TMPSAFE)/.symtab
|
||||
+18
-10
@@ -27,29 +27,37 @@ EOF
|
||||
exit 1
|
||||
fi
|
||||
|
||||
build/sanitycheck2
|
||||
if [ $? -ne 123 ]; then
|
||||
if [ ! -f /proc/sys/fs/binfmt_misc/status ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if ! build/bootstrap/echo.com -n; then
|
||||
cat <<'EOF' >&2
|
||||
|
||||
ERROR
|
||||
|
||||
Thompson Shell Backwards Compatibility Issue Detected
|
||||
APE Execution error.
|
||||
|
||||
DETAILS
|
||||
|
||||
Actually Portable Executable assumes stock Linux configuration.
|
||||
Normal behavior is non-ELF files with x bit are run by /bin/sh.
|
||||
Linux lets people globally define arbitrary magic interpreters.
|
||||
Your computer couldve been tuned to run MZ scripts inside WINE.
|
||||
So if you use binfmt_misc you need to explicitly register this.
|
||||
Your system has probably been configured to use binfmt_misc. You need
|
||||
to run the command below to install /usr/bin/ape and register it with
|
||||
binfmt_misc. See ape/loader.c for source code, and technical details.
|
||||
|
||||
WORKAROUND
|
||||
|
||||
sudo sh -c "echo ':APE:M::MZqFpD::/bin/sh:' >/proc/sys/fs/binfmt_misc/register"
|
||||
ape/apeinstall.sh
|
||||
|
||||
NOTES
|
||||
|
||||
If it still doesn't work, possibly due to an overly aggressive WINE
|
||||
or WSL registration, or possibly due to the ordering of definitions,
|
||||
then one troubleshooting step is to just unregister everything using
|
||||
sudo sh -c 'echo -1 >/proc/sys/fs/binfmt_misc/status' and try again.
|
||||
|
||||
SEE ALSO
|
||||
|
||||
https://justine.storage.googleapis.com/ape.html
|
||||
https://justine.lol/ape.html
|
||||
|
||||
EOF
|
||||
kill $1
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
MZqFpD=123
|
||||
exit $MZqFpD
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -40,11 +40,11 @@ $(DSP_BMP_A).pkg: \
|
||||
$(foreach x,$(DSP_BMP_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/dsp/bmp/float2short.o \
|
||||
o/$(MODE)/dsp/bmp/scalevolume.o: \
|
||||
o/$(MODE)/dsp/bmp/scalevolume.o: private \
|
||||
OVERRIDE_CFLAGS += \
|
||||
$(MATHEMATICAL)
|
||||
|
||||
o/tiny/dsp/bmp/scalevolume.o: \
|
||||
o/tiny/dsp/bmp/scalevolume.o: private \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-Os
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
|
||||
/**
|
||||
* Compresses 16-bit signed linear audio sample with a-Law.
|
||||
*
|
||||
* @param x is clamped to 16-bits of which the top 14 are considered
|
||||
* @return coded number in range [0..255]
|
||||
* @see ITU G.711
|
||||
*/
|
||||
int alaw(int x) {
|
||||
int a, b, e, i;
|
||||
if ((a = x) < 0) a = ~a;
|
||||
a >>= 4;
|
||||
if (a > 15) {
|
||||
if ((i = a >> 5)) {
|
||||
b = (__builtin_clz(i) ^ 31) + 1;
|
||||
a >>= b;
|
||||
a -= 16;
|
||||
a += (b + 1) << 4;
|
||||
} else {
|
||||
e = 1;
|
||||
a -= 16;
|
||||
a += 16;
|
||||
}
|
||||
}
|
||||
if (x >= 0) a |= 128;
|
||||
return a ^ 85;
|
||||
}
|
||||
@@ -22,7 +22,7 @@
|
||||
void *byte2double(long n, const void *p, double weight, double bias) {
|
||||
long i;
|
||||
double f, *dst;
|
||||
unsigned char *src;
|
||||
const unsigned char *src;
|
||||
if ((dst = valloc(n * sizeof(double)))) {
|
||||
for (src = p, i = 0; i < n; ++i) {
|
||||
f = src[i];
|
||||
|
||||
+3
-7
@@ -3,23 +3,19 @@
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* @fileoverview Cosmopolitan Digital Signal Processing.
|
||||
*/
|
||||
|
||||
int alaw(int);
|
||||
int unalaw(int);
|
||||
int mulaw(int);
|
||||
int unmulaw(int);
|
||||
void *double2byte(long, const void *, double, double) vallocesque;
|
||||
void *byte2double(long, const void *, double, double) vallocesque;
|
||||
|
||||
void *dct(float[8][8], float, float, float, float, float);
|
||||
void *dctjpeg(float[8][8]);
|
||||
|
||||
double det3(const double[3][3]) nosideeffect;
|
||||
void *inv3(double[restrict 3][3], const double[restrict 3][3], double);
|
||||
void *matmul3(double[restrict 3][3], const double[3][3], const double[3][3]);
|
||||
void *vmatmul3(double[restrict 3], const double[3], const double[3][3]);
|
||||
void *matvmul3(double[restrict 3], const double[3][3], const double[3]);
|
||||
|
||||
double rgb2stdtv(double) pureconst;
|
||||
double rgb2lintv(double) pureconst;
|
||||
double rgb2stdpc(double, double) pureconst;
|
||||
|
||||
+3
-3
@@ -47,15 +47,15 @@ o/$(MODE)/dsp/core/c1331.o \
|
||||
o/$(MODE)/dsp/core/magikarp.o \
|
||||
o/$(MODE)/dsp/core/c93654369.o \
|
||||
o/$(MODE)/dsp/core/float2short.o \
|
||||
o/$(MODE)/dsp/core/scalevolume.o: \
|
||||
o/$(MODE)/dsp/core/scalevolume.o: private \
|
||||
OVERRIDE_CFLAGS += \
|
||||
$(MATHEMATICAL)
|
||||
|
||||
o/tiny/dsp/core/scalevolume.o: \
|
||||
o/tiny/dsp/core/scalevolume.o: private \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-Os
|
||||
|
||||
o/$(MODE)/dsp/core/det3.o: \
|
||||
o/$(MODE)/dsp/core/det3.o: private \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-ffast-math
|
||||
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
#define DCT(A, B, C, D, E, F, G, H, T, C0, C1, C2, C3, C4) \
|
||||
do { \
|
||||
T z1, z2, z3, z4, z5, z11, z13; \
|
||||
T t0, t1, t2, t3, t4, t5, t6, t7, t8, t10, t11, t12, t13; \
|
||||
T t0, t1, t2, t3, t4, t5, t6, t7, t10, t11, t12, t13; \
|
||||
t0 = A + H; \
|
||||
t7 = A - H; \
|
||||
t1 = B + G; \
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
*/
|
||||
void float2short(size_t n, short pcm16[n][8], const float binary32[n][8]) {
|
||||
size_t i, j;
|
||||
float f[8], w[8];
|
||||
for (i = 0; i < n; ++i) {
|
||||
for (j = 0; j < 8; ++j) {
|
||||
pcm16[i][j] =
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
#define BIAS 0x84
|
||||
|
||||
// Encodes audio sample with µ-Law.
|
||||
//
|
||||
// This is both the highest quality and most widely supported
|
||||
// telephony codec, whose use was phased out in the 2000's in
|
||||
// favor of cost-saving GSM audio compression that was so bad
|
||||
// consumers were willing to pay more cash, for the privilege
|
||||
// of saving telcos even more money w/ text messaging. Mu Law
|
||||
// reduces PCM data to half its original size, by diminishing
|
||||
// audio bands not vocalized by human voice.
|
||||
//
|
||||
// @param %edi is pcm sample
|
||||
// @return %eax is uint8_t encoded sample
|
||||
mulaw: .leafprologue
|
||||
.profilable
|
||||
mov $BIAS,%eax
|
||||
xor %edx,%edx
|
||||
test %edi,%edi
|
||||
js 1f
|
||||
lea (%edi,%eax),%eax
|
||||
mov $0xFF,%dl
|
||||
jmp 2f
|
||||
1: sub %edi,%eax
|
||||
mov $0x7F,%dl
|
||||
2: mov %eax,%esi
|
||||
or $0xFF,%sil
|
||||
bsr %esi,%esi
|
||||
sub $7,%esi
|
||||
cmp $8,%esi
|
||||
jge 4f
|
||||
lea 3(%rdx),%ecx
|
||||
sar %cl,%eax
|
||||
and $0xF,%eax
|
||||
shl $4,%esi
|
||||
or %esi,%eax
|
||||
xor %edx,%eax
|
||||
3: .leafepilogue
|
||||
4: xor $0x7F,%dl
|
||||
mov %edx,%eax
|
||||
jmp 3b
|
||||
.endfn mulaw,globl
|
||||
.source __FILE__
|
||||
@@ -0,0 +1,40 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
|
||||
/**
|
||||
* Compresses 16-bit signed linear audio sample with μ-Law.
|
||||
*
|
||||
* @param x is clamped to 16-bits of which the top 14 are considered
|
||||
* @return coded number in range [0..255]
|
||||
* @see ITU G.711
|
||||
*/
|
||||
int mulaw(int x) {
|
||||
int b, i, a, s, l, h;
|
||||
a = x < 0 ? (~x >> 2) + 33 : (x >> 2) + 33;
|
||||
if (a > 8191) a = 8191;
|
||||
i = a >> 6;
|
||||
s = i ? (__builtin_clz(i) ^ 31) + 2 : 1;
|
||||
h = 8 - s;
|
||||
l = (a >> s) & 15;
|
||||
l = 15 - l;
|
||||
b = (h << 4) | l;
|
||||
if (x >= 0) b |= 128;
|
||||
return b;
|
||||
}
|
||||
@@ -37,4 +37,3 @@ sad16x8n:
|
||||
jnz 0b
|
||||
1: .leafepilogue
|
||||
.endfn sad16x8n,globl,hidden
|
||||
.source __FILE__
|
||||
@@ -17,8 +17,8 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/limits.h"
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
|
||||
/**
|
||||
* Expands a-Law coded to audio sample.
|
||||
*
|
||||
* @param x is coded number masked to range [0..255]
|
||||
* @return 16-bit signed linear audio sample
|
||||
* @note generate lut to save 2 cycles
|
||||
* @see ITU G.711
|
||||
*/
|
||||
int unalaw(int x) {
|
||||
int e, i, m;
|
||||
i = (x ^ 85) & 127;
|
||||
e = i >> 4;
|
||||
m = i & 15;
|
||||
if (e > 0) m += 16;
|
||||
m = (m << 4) + 8;
|
||||
if (e > 1) m = m << (e - 1);
|
||||
return x & 128 ? m : -m;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/core/core.h"
|
||||
#include "libc/intrin/likely.h"
|
||||
|
||||
/**
|
||||
* Expands μ-Law coded to audio sample.
|
||||
*
|
||||
* @param x is coded number masked to range [0..255]
|
||||
* @return 16-bit signed linear audio sample
|
||||
* @note generate lut to save 2 cycles
|
||||
* @see ITU G.711
|
||||
*/
|
||||
int unmulaw(int x) {
|
||||
int e, m, k, s;
|
||||
e = (~x >> 4) & 7;
|
||||
m = ~x & 15;
|
||||
k = 4 << (e + 1);
|
||||
s = (128 << e) + k * m + k / 2 - 4 * 33;
|
||||
return x & 128 ? s : -s;
|
||||
}
|
||||
+5
-5
@@ -37,10 +37,10 @@ This library provides several interfaces to load, demux and decode MPEG video
|
||||
and audio data. A high-level API combines the demuxer, video & audio decoders
|
||||
in an easy to use wrapper.
|
||||
|
||||
Lower-level APIs for accessing the demuxer, video decoder and audio decoder,
|
||||
Lower-level APIs for accessing the demuxer, video decoder and audio decoder,
|
||||
as well as providing different data sources are also available.
|
||||
|
||||
Interfaces are written in an object orientet style, meaning you create object
|
||||
Interfaces are written in an object orientet style, meaning you create object
|
||||
instances via various different constructor functions (plm_*create()),
|
||||
do some work on them and later dispose them via plm_*destroy().
|
||||
|
||||
@@ -51,11 +51,11 @@ plm_video_* -- the MPEG1 Video ("mpeg1") decoder
|
||||
plm_audio_* -- the MPEG1 Audio Layer II ("mp2") decoder
|
||||
|
||||
|
||||
This library uses malloc(), realloc() and free() to manage memory. Typically
|
||||
This library uses malloc(), realloc() and free() to manage memory. Typically
|
||||
all allocation happens up-front when creating the interface. However, the
|
||||
default buffer size may be too small for certain inputs. In these cases plmpeg
|
||||
will realloc() the buffer with a larger size whenever needed. You can configure
|
||||
the default buffer size by defining PLM_BUFFER_DEFAULT_SIZE *before*
|
||||
the default buffer size by defining PLM_BUFFER_DEFAULT_SIZE *before*
|
||||
including this library.
|
||||
|
||||
With the high-level interface you have two options to decode video & audio:
|
||||
@@ -85,7 +85,7 @@ mat4 rec601 = mat4(
|
||||
gl_FragColor = vec4(y, cb, cr, 1.0) * rec601;
|
||||
|
||||
Audio data is decoded into a struct with either one single float array with the
|
||||
samples for the left and right channel interleaved, or if the
|
||||
samples for the left and right channel interleaved, or if the
|
||||
PLM_AUDIO_SEPARATE_CHANNELS is defined *before* including this library, into
|
||||
two separate float arrays - one for each channel.
|
||||
|
||||
|
||||
+2
-2
@@ -67,7 +67,7 @@ plm_buffer_t *plm_buffer_create_with_file(FILE *fh, int close_when_done) {
|
||||
|
||||
plm_buffer_t *plm_buffer_create_with_memory(unsigned char *bytes, size_t length, int free_when_done) {
|
||||
plm_buffer_t *b;
|
||||
b = memalign(alignof(plm_buffer_t), sizeof(plm_buffer_t));
|
||||
b = memalign(_Alignof(plm_buffer_t), sizeof(plm_buffer_t));
|
||||
memset(b, 0, sizeof(plm_buffer_t));
|
||||
b->capacity = length;
|
||||
b->length = length;
|
||||
@@ -79,7 +79,7 @@ plm_buffer_t *plm_buffer_create_with_memory(unsigned char *bytes, size_t length,
|
||||
|
||||
plm_buffer_t * plm_buffer_create_with_capacity(size_t capacity) {
|
||||
plm_buffer_t *b;
|
||||
b = memalign(alignof(plm_buffer_t), sizeof(plm_buffer_t));
|
||||
b = memalign(_Alignof(plm_buffer_t), sizeof(plm_buffer_t));
|
||||
memset(b, 0, sizeof(plm_buffer_t));
|
||||
b->capacity = capacity;
|
||||
b->free_when_done = true;
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
.source __FILE__
|
||||
|
||||
clamp4int256$core:
|
||||
.leafprologue
|
||||
|
||||
+2
-2
@@ -115,8 +115,8 @@ plm_packet_t *plm_demux_decode(plm_demux_t *self) {
|
||||
do {
|
||||
code = plm_buffer_next_start_code(self->buffer);
|
||||
if (
|
||||
code == PLM_DEMUX_PACKET_VIDEO_1 ||
|
||||
code == PLM_DEMUX_PACKET_PRIVATE ||
|
||||
code == PLM_DEMUX_PACKET_VIDEO_1 ||
|
||||
code == PLM_DEMUX_PACKET_PRIVATE ||
|
||||
(code >= PLM_DEMUX_PACKET_AUDIO_1 && code <= PLM_DEMUX_PACKET_AUDIO_4)
|
||||
) {
|
||||
return plm_demux_decode_packet(self, code);
|
||||
|
||||
+5
-5
@@ -273,11 +273,11 @@ typedef plm_audio_t plm_audio_t;
|
||||
int plm_audio_decode_header(plm_audio_t *self);
|
||||
void plm_audio_decode_frame(plm_audio_t *self);
|
||||
const plm_quantizer_spec_t *plm_audio_read_allocation(plm_audio_t *self, int sb, int tab3);
|
||||
void plm_audio_read_samples(plm_audio_t *self, int ch, int sb, int part);
|
||||
void plm_audio_read_samples(plm_audio_t *self, int ch, int sb, int part);
|
||||
void plm_audio_matrix_transform(int s[32][3], int ss, float *d, int dp);
|
||||
|
||||
plm_audio_t *plm_audio_create_with_buffer(plm_buffer_t *buffer, int destroy_when_done) {
|
||||
plm_audio_t *self = (plm_audio_t *)memalign(alignof(plm_audio_t), sizeof(plm_audio_t));
|
||||
plm_audio_t *self = (plm_audio_t *)memalign(_Alignof(plm_audio_t), sizeof(plm_audio_t));
|
||||
memset(self, 0, sizeof(plm_audio_t));
|
||||
|
||||
self->samples.count = PLM_AUDIO_SAMPLES_PER_FRAME;
|
||||
@@ -345,7 +345,7 @@ plm_samples_t *plm_audio_decode(plm_audio_t *self) {
|
||||
self->samples.time = self->time;
|
||||
|
||||
self->samples_decoded += PLM_AUDIO_SAMPLES_PER_FRAME;
|
||||
self->time = (double)self->samples_decoded /
|
||||
self->time = (double)self->samples_decoded /
|
||||
(double)PLM_AUDIO_SAMPLE_RATE[self->samplerate_index];
|
||||
|
||||
return &self->samples;
|
||||
@@ -402,7 +402,7 @@ int plm_audio_decode_header(plm_audio_t *self) {
|
||||
plm_buffer_skip(self->buffer, 16);
|
||||
}
|
||||
|
||||
// Compute frame size, check if we have enough data to decode the whole
|
||||
// Compute frame size, check if we have enough data to decode the whole
|
||||
// frame.
|
||||
int bitrate = PLM_AUDIO_BIT_RATE[self->bitrate_index];
|
||||
int samplerate = PLM_AUDIO_SAMPLE_RATE[self->samplerate_index];
|
||||
@@ -561,7 +561,7 @@ void plm_audio_decode_frame(plm_audio_t *self) {
|
||||
}
|
||||
#else
|
||||
for (int j = 0; j < 32; j++) {
|
||||
self->samples.interleaved[((out_pos + j) << 1) + ch] =
|
||||
self->samples.interleaved[((out_pos + j) << 1) + ch] =
|
||||
self->U[j] / 2147418112.0f;
|
||||
}
|
||||
#endif
|
||||
|
||||
+2
-6
@@ -37,8 +37,7 @@ DSP_MPEG_A_DIRECTDEPS = \
|
||||
LIBC_STUBS \
|
||||
LIBC_SYSV \
|
||||
LIBC_TIME \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_UNICODE
|
||||
LIBC_TINYMATH
|
||||
|
||||
DSP_MPEG_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(DSP_MPEG_A_DIRECTDEPS),$($(x))))
|
||||
@@ -51,13 +50,10 @@ $(DSP_MPEG_A).pkg: \
|
||||
$(DSP_MPEG_A_OBJS) \
|
||||
$(foreach x,$(DSP_MPEG_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/dsp/mpeg/clamp4int256-k8.o: \
|
||||
o/$(MODE)/dsp/mpeg/clamp4int256-k8.o: private \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-Os
|
||||
|
||||
#o/$(MODE)/dsp/mpeg/macroblock.o: \
|
||||
CC = $(CLANG)
|
||||
|
||||
DSP_MPEG_LIBS = $(foreach x,$(DSP_MPEG_ARTIFACTS),$($(x)))
|
||||
DSP_MPEG_SRCS = $(foreach x,$(DSP_MPEG_ARTIFACTS),$($(x)_SRCS))
|
||||
DSP_MPEG_HDRS = $(foreach x,$(DSP_MPEG_ARTIFACTS),$($(x)_HDRS))
|
||||
|
||||
+22
-21
@@ -32,7 +32,7 @@
|
||||
#include "dsp/mpeg/idct.h"
|
||||
#include "dsp/mpeg/mpeg.h"
|
||||
#include "dsp/mpeg/video.h"
|
||||
#include "libc/bits/initializer.internal.h"
|
||||
#include "libc/intrin/initializer.internal.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
@@ -72,7 +72,8 @@ static const float PLM_VIDEO_PIXEL_ASPECT_RATIO[] = {
|
||||
0.6735, /* 3:4? */
|
||||
0.7031, /* MPEG-1 / MPEG-2 video encoding divergence? */
|
||||
0.7615, 0.8055, 0.8437, 0.8935, 0.9157, 0.9815,
|
||||
1.0255, 1.0695, 1.0950, 1.1575, 1.2051};
|
||||
1.0255, 1.0695, 1.0950, 1.1575, 1.2051,
|
||||
};
|
||||
|
||||
static const float PLM_VIDEO_PICTURE_RATE[] = {
|
||||
23.976, /* NTSC-Film */
|
||||
@@ -591,24 +592,24 @@ void plm_video_decode_sequence_header(plm_video_t *self) {
|
||||
|
||||
self->has_sequence_header = true;
|
||||
|
||||
LOGF("%s:\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15f;\n"
|
||||
"\t%-20s = %15f;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;",
|
||||
"New MPEG Sequence", "width", self->width, "height", self->height,
|
||||
"framerate", self->framerate, "pixel_aspect_ratio",
|
||||
self->pixel_aspect_ratio, "mb_size", self->mb_size, "mb_width",
|
||||
self->mb_width, "mb_height", self->mb_height, "luma_width",
|
||||
self->luma_width, "luma_height", self->luma_height, "chroma_width",
|
||||
self->chroma_width, "chroma_height", self->chroma_height);
|
||||
INFOF("%s:\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15f;\n"
|
||||
"\t%-20s = %15f;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;\n"
|
||||
"\t%-20s = %15d;",
|
||||
"New MPEG Sequence", "width", self->width, "height", self->height,
|
||||
"framerate", self->framerate, "pixel_aspect_ratio",
|
||||
self->pixel_aspect_ratio, "mb_size", self->mb_size, "mb_width",
|
||||
self->mb_width, "mb_height", self->mb_height, "luma_width",
|
||||
self->luma_width, "luma_height", self->luma_height, "chroma_width",
|
||||
self->chroma_width, "chroma_height", self->chroma_height);
|
||||
}
|
||||
|
||||
static void plm_video_copy_macroblock(plm_video_t *self, int motion_h,
|
||||
@@ -1082,7 +1083,7 @@ static plm_frame_t *plm_video_decode_impl(plm_video_t *self) {
|
||||
plm_frame_t *plm_video_decode(plm_video_t *self) {
|
||||
long double tsc;
|
||||
plm_frame_t *res;
|
||||
LOGF("plm_video_decode");
|
||||
INFOF("plm_video_decode");
|
||||
tsc = nowl();
|
||||
res = plm_video_decode_impl(self);
|
||||
plmpegdecode_latency_ = lroundl((nowl() - tsc) * 1e6l);
|
||||
|
||||
+3
-3
@@ -94,9 +94,9 @@ plm_t *plm_create_with_buffer(plm_buffer_t *buffer, int destroy_when_done) {
|
||||
|
||||
self->demux = plm_demux_create(buffer, destroy_when_done);
|
||||
|
||||
// In theory we should check plm_demux_get_num_video_streams() and
|
||||
// In theory we should check plm_demux_get_num_video_streams() and
|
||||
// plm_demux_get_num_audio_streams() here, but older files typically
|
||||
// do not specify these correcly. So we just assume we have a video and
|
||||
// do not specify these correctly. So we just assume we have a video and
|
||||
// audio stream and create the decoders.
|
||||
|
||||
self->video_packet_type = PLM_DEMUX_PACKET_VIDEO_1;
|
||||
@@ -159,7 +159,7 @@ double plm_get_framerate(plm_t *self) {
|
||||
|
||||
int plm_get_num_audio_streams(plm_t *self) {
|
||||
// Some files do not specify the number of audio streams in the system header.
|
||||
// If the reported number of streams is 0, we check if we have a samplerate,
|
||||
// If the reported number of streams is 0, we check if we have a samplerate,
|
||||
// indicating at least one audio stream.
|
||||
int num_streams = plm_demux_get_num_audio_streams(self->demux);
|
||||
return num_streams == 0 && plm_get_samplerate(self) ? 1 : num_streams;
|
||||
|
||||
+1
-1
@@ -40,7 +40,7 @@ asm(".include \"libc/disclaimer.inc\"");
|
||||
* @see YCbCr2RGB() in tool/viz/lib/ycbcr2rgb.c
|
||||
*/
|
||||
void plm_frame_to_rgb(plm_frame_t *frame, uint8_t *rgb) {
|
||||
// Chroma values are the same for each block of 4 pixels, so we proccess
|
||||
// Chroma values are the same for each block of 4 pixels, so we process
|
||||
// 2 lines at a time, 2 neighboring pixels each.
|
||||
int w = frame->y.width, w2 = w >> 1;
|
||||
int y_index1 = 0, y_index2 = w, y_next_2_lines = w + (w - frame->width);
|
||||
|
||||
@@ -101,7 +101,7 @@ struct SamplingSolution *ComputeSamplingSolution(long dn, long sn, double dar,
|
||||
if (!off) off = (dar - 1) / 2;
|
||||
f = dar < 1 ? 1 / dar : dar;
|
||||
s = 3 * f + 4;
|
||||
fweights = gc(xcalloc(s, sizeof(double)));
|
||||
fweights = gc(xcalloc(s + /*xxx*/ 2, sizeof(double)));
|
||||
res = NewSamplingSolution(dn, s);
|
||||
weights = res->weights;
|
||||
indices = res->indices;
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ $(DSP_SCALE_A).pkg: \
|
||||
o/$(MODE)/dsp/scale/cdecimate2xuint8x8.o \
|
||||
o/$(MODE)/dsp/scale/gyarados.o \
|
||||
o/$(MODE)/dsp/scale/magikarp.o \
|
||||
o/$(MODE)/dsp/scale/scale.o: \
|
||||
o/$(MODE)/dsp/scale/scale.o: private \
|
||||
OVERRIDE_CFLAGS += \
|
||||
$(MATHEMATICAL)
|
||||
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/tty/tty.h"
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/intrin/pushpop.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
@@ -30,7 +31,7 @@
|
||||
static int ttysetcursor(int fd, bool visible) {
|
||||
struct NtConsoleCursorInfo ntcursor;
|
||||
char code[8] = "\e[?25l";
|
||||
if (IsTerminalInarticulate()) return 0;
|
||||
if (__nocolor) return 0;
|
||||
if (visible) code[5] = 'h';
|
||||
if (SupportsWindows()) {
|
||||
GetConsoleCursorInfo(GetStdHandle(kNtStdOutputHandle), &ntcursor);
|
||||
|
||||
+5
-2
@@ -17,14 +17,17 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/tty/tty.h"
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sock/struct/pollfd.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/poll.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#ifndef COSMOPOLITAN_DSP_TTY_INTERNAL_H_
|
||||
#define COSMOPOLITAN_DSP_TTY_INTERNAL_H_
|
||||
#include "dsp/tty/ttyrgb.h"
|
||||
#include "libc/bits/xmmintrin.internal.h"
|
||||
#include "libc/intrin/xmmintrin.internal.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
|
||||
+2
-2
@@ -17,8 +17,8 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/tty/itoa8.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/initializer.internal.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/initializer.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
struct Itoa8 kItoa8;
|
||||
|
||||
+2
-2
@@ -2,8 +2,8 @@
|
||||
#define DSP_TTY_QUANT_H_
|
||||
#include "dsp/tty/ttyrgb.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/xmmintrin.internal.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/xmmintrin.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/str/str.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
+3
-2
@@ -19,7 +19,7 @@
|
||||
#include "dsp/core/core.h"
|
||||
#include "dsp/tty/quant.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/initializer.internal.h"
|
||||
#include "libc/intrin/initializer.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
@@ -47,7 +47,8 @@ __m128 tty2rgbf_(struct TtyRgb rgbxt) {
|
||||
|
||||
static int rgb2xterm256_(int r, int g, int b) {
|
||||
int cerr, gerr, ir, ig, ib, gray, grai, cr, cg, cb, gv;
|
||||
gray = round(r * .299 + g * .587 + b * .114);
|
||||
gray = round(871024 / 4096299. * r + 8788810 / 12288897. * g +
|
||||
887015 / 12288897. * b);
|
||||
grai = gray > 238 ? 23 : (gray - 3) / 10;
|
||||
ir = r < 48 ? 0 : r < 115 ? 1 : (r - 35) / 40;
|
||||
ig = g < 48 ? 0 : g < 115 ? 1 : (g - 35) / 40;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/tty/quant.h"
|
||||
#include "libc/bits/xmmintrin.internal.h"
|
||||
#include "libc/intrin/xmmintrin.internal.h"
|
||||
|
||||
struct TtyRgb rgb2ttyf2i_(__m128 rgb) {
|
||||
__v4si i4;
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/tty/tty.h"
|
||||
#include "libc/alg/arraylist2.internal.h"
|
||||
#include "libc/mem/arraylist2.internal.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/x/x.h"
|
||||
|
||||
|
||||
@@ -31,13 +31,6 @@ int ttysetraw(struct termios *conf, int64_t flags) {
|
||||
conf->c_cflag &= ~(CSIZE | PARENB);
|
||||
conf->c_cflag |= CS8;
|
||||
conf->c_iflag |= IUTF8;
|
||||
/* if (flags & kTtyLfToCrLf) { */
|
||||
/* /\* conf->c_oflag &= ~(OLCUC | OCRNL | ONLRET | OFILL | OFDEL); *\/ */
|
||||
/* /\* conf->c_oflag |= ONLCR | ONOCR; *\/ */
|
||||
/* conf->c_oflag |= ONLCR; */
|
||||
/* } else { */
|
||||
/* conf->c_oflag &= ~OPOST; */
|
||||
/* } */
|
||||
if (!(flags & kTtySigs)) {
|
||||
conf->c_iflag &= ~(IGNBRK | BRKINT);
|
||||
conf->c_lflag &= ~(ISIG);
|
||||
|
||||
+3
-5
@@ -25,7 +25,6 @@ DSP_TTY_A_CHECKS = \
|
||||
|
||||
DSP_TTY_A_DIRECTDEPS = \
|
||||
DSP_CORE \
|
||||
LIBC_ALG \
|
||||
LIBC_CALLS \
|
||||
LIBC_FMT \
|
||||
LIBC_INTRIN \
|
||||
@@ -41,8 +40,7 @@ DSP_TTY_A_DIRECTDEPS = \
|
||||
LIBC_SYSV \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_TIME \
|
||||
LIBC_X \
|
||||
LIBC_UNICODE
|
||||
LIBC_X
|
||||
|
||||
DSP_TTY_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(DSP_TTY_A_DIRECTDEPS),$($(x))))
|
||||
@@ -55,8 +53,8 @@ $(DSP_TTY_A).pkg: \
|
||||
$(DSP_TTY_A_OBJS) \
|
||||
$(foreach x,$(DSP_TTY_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/dsp/tty/ttyraster.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
o/$(MODE)/dsp/tty/ttyraster.o: private \
|
||||
OVERRIDE_CFLAGS += \
|
||||
$(MATHEMATICAL)
|
||||
|
||||
DSP_TTY_LIBS = $(foreach x,$(DSP_TTY_ARTIFACTS),$($(x)))
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/tty/tty.h"
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/nexgen32e/nexgen32e.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/tty/itoa8.h"
|
||||
#include "dsp/tty/tty.h"
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/check.h"
|
||||
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/tty/internal.h"
|
||||
#include "dsp/tty/quant.h"
|
||||
#include "libc/bits/initializer.internal.h"
|
||||
#include "libc/intrin/initializer.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
+22
-18
@@ -22,8 +22,8 @@
|
||||
#include "dsp/tty/ttyrgb.h"
|
||||
#include "dsp/tty/windex.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/safemacros.internal.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
@@ -731,19 +731,19 @@ static bool ChunkEq(struct TtyRgb c[hasatleast 4],
|
||||
}
|
||||
|
||||
static struct TtyRgb *CopyChunk(struct TtyRgb chunk[hasatleast 4],
|
||||
const struct TtyRgb *c, size_t n) {
|
||||
chunk[TL] = c[0 + 0];
|
||||
chunk[TR] = c[0 + 1];
|
||||
chunk[BL] = c[n + 0];
|
||||
chunk[BR] = c[n + 1];
|
||||
const struct TtyRgb *c, size_t xn) {
|
||||
chunk[TL] = c[00 + 0];
|
||||
chunk[TR] = c[00 + 1];
|
||||
chunk[BL] = c[xn + 0];
|
||||
chunk[BR] = c[xn + 1];
|
||||
return chunk;
|
||||
}
|
||||
|
||||
static noinline char *CopyRun(char *v, size_t n,
|
||||
struct TtyRgb lastchunk[hasatleast 4],
|
||||
const struct TtyRgb **c, size_t *x,
|
||||
struct TtyRgb *bg, struct TtyRgb *fg,
|
||||
struct Glyph *glyph) {
|
||||
static dontinline char *CopyRun(char *v, size_t n,
|
||||
struct TtyRgb lastchunk[hasatleast 4],
|
||||
const struct TtyRgb **c, size_t *x,
|
||||
struct TtyRgb *bg, struct TtyRgb *fg,
|
||||
struct Glyph *glyph) {
|
||||
struct TtyRgb chunk[4];
|
||||
if (memcmp(glyph, &kGlyphs[1][0], sizeof(*glyph)) == 0) {
|
||||
if (!ttyeq(*bg, *fg)) {
|
||||
@@ -766,17 +766,21 @@ static noinline char *CopyRun(char *v, size_t n,
|
||||
/**
|
||||
* Maps 2×2 pixel chunks onto ANSI UNICODE cells.
|
||||
* @note h/t Nick Black for his quadrant blitting work on notcurses
|
||||
* @note yn and xn need to be even
|
||||
*/
|
||||
char *ttyraster(char *v, const struct TtyRgb *c, size_t yn, size_t n,
|
||||
char *ttyraster(char *v, const struct TtyRgb *c, size_t yn, size_t xn,
|
||||
struct TtyRgb bg, struct TtyRgb fg) {
|
||||
unsigned y, x;
|
||||
struct Pick p;
|
||||
struct Glyph glyph;
|
||||
struct TtyRgb chun[4], lastchunk[4];
|
||||
for (y = 0; y < yn; y += 2, c += n) {
|
||||
if (y) *v++ = '\r', *v++ = '\n';
|
||||
for (x = 0; x < n; x += 2, c += 2) {
|
||||
CopyChunk(chun, c, n);
|
||||
for (y = 0; y < yn; y += 2, c += xn) {
|
||||
if (y) {
|
||||
v = stpcpy(v, "\e[0m\r\n");
|
||||
v = setbgfg(v, bg, fg);
|
||||
}
|
||||
for (x = 0; x < xn; x += 2, c += 2) {
|
||||
CopyChunk(chun, c, xn);
|
||||
if (ttyquant()->alg == kTtyQuantTrue) {
|
||||
if (ttyquant()->blocks == kTtyBlocksCp437) {
|
||||
p = PickBlockCp437True(chun[TL], chun[TR], chun[BL], chun[BR]);
|
||||
@@ -794,6 +798,6 @@ char *ttyraster(char *v, const struct TtyRgb *c, size_t yn, size_t n,
|
||||
memcpy(lastchunk, chun, sizeof(chun));
|
||||
}
|
||||
}
|
||||
*v = '\0';
|
||||
v = stpcpy(v, "\e[0m");
|
||||
return v;
|
||||
}
|
||||
@@ -19,11 +19,9 @@
|
||||
#include "dsp/tty/tty.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/calls/typedef/sigaction_f.h"
|
||||
#include "libc/calls/ucontext.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns index of minimum uint16 in array.
|
||||
//
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.internal.h"
|
||||
.source __FILE__
|
||||
|
||||
// Returns index of minimum positive int16 in array.
|
||||
//
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/macros.internal.h"
|
||||
.source __FILE__
|
||||
|
||||
// Dispatches to fastest windex() implementation.
|
||||
.initbss 300,_init_windex
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sock/struct/pollfd.h"
|
||||
#include "libc/sysv/consts/poll.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include "libc/log/log.h"
|
||||
|
||||
/**
|
||||
* Automatically launchs GDB Debugger TUI during crash.
|
||||
* Automatically launches GDB Debugger TUI during crash.
|
||||
*
|
||||
* Run the following inside a terminal:
|
||||
*
|
||||
@@ -18,9 +18,12 @@
|
||||
* make -j12 o//examples/auto-launch-gdb-on-crash.com
|
||||
* o//examples/auto-launch-gdb-on-crash.com
|
||||
*
|
||||
* Backtrace is logged instead if run outside interactive terminal.
|
||||
* Environmental factors such as GDB, MAKEFLAGS, ADDR2LINE, TERM, and
|
||||
* isatty(STDERR_FILENO) should also be taken into consideration:
|
||||
* Backtrace is logged instead if run outside interactive terminal. We
|
||||
* also don't auto-launch GDB on non-Linux since the development tools
|
||||
* on other platforms generally can't be relied upon to correctly debug
|
||||
* binaries built with a Linux toolchain. Environmental factors such as
|
||||
* GDB, MAKEFLAGS, ADDR2LINE, TERM, and isatty(STDERR_FILENO) should
|
||||
* also be taken into consideration:
|
||||
*
|
||||
* $ export GDB=eoatuhshtuone
|
||||
* $ o//examples/auto-launch-gdb-on-crash.com
|
||||
@@ -37,7 +40,7 @@
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
showcrashreports();
|
||||
ShowCrashReports();
|
||||
asm("int3"); /* cf. __die(), perror("msg"), abort(), exit(1), _Exit(1) */
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
||||
/**
|
||||
* ASAN static memory safety crash example.
|
||||
*
|
||||
* make -j8 MODE=dbg o/dbg/examples/auto-memory-safety-crash.com
|
||||
* o/dbg/examples/auto-memory-safety-crash.com
|
||||
*
|
||||
* You should see:
|
||||
*
|
||||
* global redzone 1-byte store at 0x42700d shadow 0x8007ce01
|
||||
* ./o/dbg/examples/auto-memory-safety-crash.com
|
||||
* x
|
||||
* ........................................GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG
|
||||
* |0 |0 |0 |0 |5 |-18 |-18 |-18 |-18
|
||||
* f.☼▼ä f.☼▼ä f☼▼D hello
|
||||
* 000000400000-000000427000 .text
|
||||
* 000000427000-000000429000 .data ←address
|
||||
* 00007fff0000-00008000ffff
|
||||
* 000080070000-00008008ffff ←shadow
|
||||
* 0e007fff0000-0e008000ffff
|
||||
* 100047d20000-100047d3ffff
|
||||
* 6ffffffe0000-6fffffffffff
|
||||
* the memory in question belongs to the symbols
|
||||
* buffer [0x427000,0x42700c] size 13
|
||||
* the crash was caused by
|
||||
* 0x00000000004046f3: __die at libc/log/die.c:40
|
||||
* 0x0000000000404aed: __asan_report_store at libc/intrin/asan.c:1183
|
||||
* 0x0000000000402552: main at examples/auto-memory-safety-crash.c:27
|
||||
* 0x000000000040268d: cosmo at libc/runtime/cosmo.S:64
|
||||
* 0x00000000004021ae: _start at libc/crt/crt.S:77
|
||||
*
|
||||
* @see libc/intrin/asancodes.h for meaning of G, etc. and negative numbers
|
||||
* @see libc/nexgen32e/kcp437.S for meaning of symbols
|
||||
*/
|
||||
|
||||
char buffer[13] = "hello";
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (!IsAsan()) {
|
||||
printf("this example is intended for MODE=asan or MODE=dbg\n");
|
||||
exit(1);
|
||||
}
|
||||
ShowCrashReports(); /* not needed but yoinks appropriate symbols */
|
||||
int i = 13;
|
||||
asm("" : "+r"(i)); /* prevent compiler being smart */
|
||||
buffer[i] = 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* ASAN heap memory safety crash example.
|
||||
*
|
||||
* make -j8 MODE=dbg o/dbg/examples/auto-memory-safety-crash2.com
|
||||
* o/dbg/examples/auto-memory-safety-crash2.com
|
||||
*
|
||||
* You should see:
|
||||
*
|
||||
* heap overrun 1-byte store at 0x10008004002d shadow 0x20090000005
|
||||
* ./o/dbg/examples/auto-memory-safety-crash2.com
|
||||
* x
|
||||
* OOOOOOOOOOOUUUUUUUUUUUUUUUU.............OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
|
||||
* |-7 |-6 |-6 |0 |5 |-7 |-7 |-7 |-7
|
||||
* »!@ ÿ▄:Y╩≥= S hello ∙∙∙∙∙∙∙ ♪ GT◘&@ á+@ »!@
|
||||
* 000000400000-00000042b000 .text
|
||||
* 00000042b000-00000042d000 .data
|
||||
* 00007fff0000-00008000ffff
|
||||
* 000080070000-00008008ffff
|
||||
* 02008fff0000-02009000ffff ←shadow
|
||||
* 0e007fff0000-0e008000ffff
|
||||
* 10003ab90000-10003abaffff
|
||||
* 100080000000-10008000ffff ←address
|
||||
* 6ffffffe0000-6fffffffffff
|
||||
*
|
||||
* the memory was allocated by
|
||||
* 0x100080040020 64 bytes [dlmalloc]
|
||||
* 0x100080040030 13 bytes [actual]
|
||||
* 402608 main
|
||||
* 402ba0 cosmo
|
||||
* 4021af _start
|
||||
*
|
||||
* the crash was caused by
|
||||
* 0x0000000000404793: __die at libc/log/die.c:40
|
||||
* 0x0000000000404f56: __asan_report_store at libc/intrin/asan.c:1183
|
||||
* 0x0000000000402579: main at examples/auto-memory-safety-crash2.c:30
|
||||
* 0x000000000040270f: cosmo at libc/runtime/cosmo.S:64
|
||||
* 0x00000000004021ae: _start at libc/crt/crt.S:77
|
||||
*
|
||||
* @see libc/intrin/asancodes.h for meaning of U, O, etc. and negative numbers
|
||||
* @see libc/nexgen32e/kcp437.S for meaning of symbols
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (!IsAsan()) {
|
||||
printf("this example is intended for MODE=asan or MODE=dbg\n");
|
||||
exit(1);
|
||||
}
|
||||
char *buffer;
|
||||
ShowCrashReports(); /* not needed but yoinks appropriate symbols */
|
||||
buffer = malloc(13);
|
||||
strcpy(buffer, "hello");
|
||||
int i = 13;
|
||||
asm("" : "+r"(i)); /* prevent compiler being smart */
|
||||
buffer[i] = 1;
|
||||
asm("" : "+r"(buffer)); /* prevent compiler being smart */
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* ASAN use-after-free memory safety crash example.
|
||||
*
|
||||
* make -j8 MODE=dbg o/dbg/examples/auto-memory-safety-crash3.com
|
||||
* o/dbg/examples/auto-memory-safety-crash3.com
|
||||
*
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (!IsAsan()) {
|
||||
printf("this example is intended for MODE=asan or MODE=dbg\n");
|
||||
exit(1);
|
||||
}
|
||||
char *buffer;
|
||||
ShowCrashReports(); /* not needed but yoinks appropriate symbols */
|
||||
buffer = malloc(13);
|
||||
strcpy(buffer, "hello");
|
||||
free(buffer);
|
||||
asm("" : "+r"(buffer)); /* prevent compiler being smart */
|
||||
buffer[0] = 1;
|
||||
return 0;
|
||||
}
|
||||
+20
-7
@@ -7,17 +7,30 @@
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/backtrace.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/runtime/symbols.internal.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
showcrashreports();
|
||||
ShowCrashReports();
|
||||
|
||||
if (IsDebuggerPresent(false)) {
|
||||
printf("debugger found!\r\n");
|
||||
DebugBreak();
|
||||
return 0;
|
||||
kprintf("debugger found!%n");
|
||||
} else {
|
||||
kprintf("try running: gdb %s%n", argv[0]);
|
||||
kprintf("try running: o//tool/build/strace.com %s%n", argv[0]);
|
||||
}
|
||||
printf("try running: gdb %s\r\n", argv[0]);
|
||||
return 1;
|
||||
|
||||
asm volatile("mov\t%4,%%r10\n\t"
|
||||
"mov\t%5,%%r8\n\t"
|
||||
"mov\t%6,%%r9\n\t"
|
||||
"int3"
|
||||
: /* no outputs */
|
||||
: "a"(0), "D"(1), "S"(2), "d"(3), "g"(4), "g"(5), "g"(6)
|
||||
: "r8", "r9", "r10");
|
||||
|
||||
printf("recovered from SIGTRAP without handler\r\n");
|
||||
return 0;
|
||||
}
|
||||
+1
-1
@@ -35,7 +35,7 @@ STATIC_YOINK("ssl_root_support");
|
||||
#define DFL_FILENAME "cert.crt"
|
||||
#define DFL_CA_FILE ""
|
||||
#define DFL_CRL_FILE ""
|
||||
#define DFL_CA_PATH "zip:usr/share/ssl/root"
|
||||
#define DFL_CA_PATH "/zip/usr/share/ssl/root"
|
||||
#define DFL_SERVER_NAME "localhost"
|
||||
#define DFL_SERVER_PORT "4433"
|
||||
#define DFL_DEBUG_LEVEL 0
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/log/check.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Check Macros
|
||||
*
|
||||
* The simplest assertion is:
|
||||
*
|
||||
* assert(123 == x);
|
||||
*
|
||||
* This has some downsides:
|
||||
*
|
||||
* 1. It's nice to know what `x` is when it crashes
|
||||
* 2. It's sometimes nice to have the check always take effect.
|
||||
* 3. It's problematic that assert() can't do __builtin_assume()
|
||||
*
|
||||
* Cosmopolitan provides alternative macros like:
|
||||
*
|
||||
* - `CHECK(EXPR, ...)`
|
||||
* - `CHECK_EQ(WANT, GOT, ...)`
|
||||
* - `CHECK_NE(WANT, GOT, ...)`
|
||||
* - `CHECK_GT(WANT, GOT, ...)`
|
||||
* - `CHECK_LT(WANT, GOT, ...)`
|
||||
* - `CHECK_NOTNULL(EXPR, ...)`
|
||||
*
|
||||
* The CHECK macros always happen. They always kill the process when
|
||||
* they fail. Printf formatting information may be provided as extra
|
||||
* arguments. On the other hand, there exists:
|
||||
*
|
||||
* - `DCHECK(EXPR, ...)`
|
||||
* - `DCHECK_EQ(WANT, GOT, ...)`
|
||||
* - `DCHECK_NE(WANT, GOT, ...)`
|
||||
* - `DCHECK_GT(WANT, GOT, ...)`
|
||||
* - `DCHECK_LT(WANT, GOT, ...)`
|
||||
* - `DCHECK_NOTNULL(EXPR, ...)`
|
||||
*
|
||||
* The DCHECK macros always happen when NDEBUG isn't defined. When
|
||||
* NDEBUG is defined, they still happen, but in a special way that
|
||||
* causes the compiler to recognize their failure as undefined behavior.
|
||||
* What this means is that, if the provided expressions are pure without
|
||||
* side-effects, then the code compiles down to nothing and the compiler
|
||||
* may be able to use the knowledge of something being the case in order
|
||||
* to optimize other code adjacent to your DCHECK.
|
||||
*
|
||||
* In the default build modes, this prints lots of information:
|
||||
*
|
||||
* error:examples/check.c:23:check.com: check failed on nightmare pid 15412
|
||||
* CHECK_EQ(123, some_source_code);
|
||||
* → 0x7b (123)
|
||||
* == 0x64 (some_source_code)
|
||||
* extra info: hello
|
||||
* EUNKNOWN/0/No error information
|
||||
* ./o//examples/check.com
|
||||
* 0x0000000000407404: __die at libc/log/die.c:42
|
||||
* 0x0000000000407340: __check_fail at libc/log/checkfail.c:73
|
||||
* 0x00000000004071d0: main at examples/check.c:23
|
||||
* 0x000000000040256e: cosmo at libc/runtime/cosmo.S:69
|
||||
* 0x000000000040217d: _start at libc/crt/crt.S:85
|
||||
*
|
||||
* In NDEBUG mode (e.g. MODE=rel, MODE=tiny, etc.) this prints a much
|
||||
* simpler message that, most importantly, doesn't include any source
|
||||
* code, although it still includes the file name for reference.
|
||||
*
|
||||
* error:examples/check.c:14: check failed: 123 == 100: extra info: hello
|
||||
*
|
||||
* That way your release binaries won't leak CI. You may optionally link
|
||||
* the following functions to further expand the information shown by
|
||||
* the NDEBUG check failure:
|
||||
*
|
||||
* STATIC_YOINK("__die");
|
||||
* STATIC_YOINK("strerror");
|
||||
*
|
||||
* Please note that backtraces aren't ever available in MODE=tiny.
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int some_source_code = 100;
|
||||
CHECK_EQ(123, some_source_code, "extra info: %s", "hello");
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
#if 0
|
||||
/*─────────────────────────────────────────────────────────────────╗
|
||||
│ To the extent possible under law, Justine Tunney has waived │
|
||||
│ all copyright and related or neighboring rights to this file, │
|
||||
│ as it is written in the following disclaimers: │
|
||||
│ • http://unlicense.org/ │
|
||||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/assert.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/ex.h"
|
||||
#include "libc/sysv/consts/exit.h"
|
||||
#include "third_party/getopt/getopt.h"
|
||||
#include "third_party/zlib/zlib.h"
|
||||
|
||||
#define CHUNK 32768
|
||||
|
||||
#define USAGE \
|
||||
" <STDIN >STDOUT\n\
|
||||
\n\
|
||||
SYNOPSIS\n\
|
||||
\n\
|
||||
Zlib Compressor\n\
|
||||
\n\
|
||||
FLAGS\n\
|
||||
\n\
|
||||
-?\n\
|
||||
-h help\n\
|
||||
-0 disable compression\n\
|
||||
-1 fastest compression\n\
|
||||
-4 coolest compression\n\
|
||||
-9 maximum compression\n\
|
||||
-F fixed strategy (advanced)\n\
|
||||
-L filtered strategy (advanced)\n\
|
||||
-R run length strategy (advanced)\n\
|
||||
-H huffman only strategy (advanced)\n\
|
||||
\n"
|
||||
|
||||
// clang-format off
|
||||
// make -j8 o//examples && dd if=/dev/urandom count=100 | tee a | o//examples/compress.com | o//examples/decompress.com >b && sha1sum a b
|
||||
/*
|
||||
# data file is o/dbg/third_party/python/python.com
|
||||
# level 0 147517 compress 495 MB/s decompress 1.4 GB/s
|
||||
# level 1 80274 compress 29.2 MB/s decompress 303 MB/s
|
||||
# level 2 79384 compress 33.8 MB/s decompress 212 MB/s
|
||||
# level 3 78875 compress 28.9 MB/s decompress 224 MB/s
|
||||
# level 4 78010 compress 27.1 MB/s decompress 319 MB/s <-- sweet spot?
|
||||
# level 5 77107 compress 19.5 MB/s decompress 273 MB/s
|
||||
# level 6 75081 compress 10.0 MB/s decompress 99.3 MB/s
|
||||
# level 7 75022 compress 7.5 MB/s decompress 287 MB/s
|
||||
# level 8 75016 compress 5.4 MB/s decompress 109 MB/s
|
||||
# level 9 75016 compress 5.4 MB/s decompress 344 MB/s
|
||||
m=
|
||||
make -j8 MODE=$m o/$m/examples || exit
|
||||
for level in $(seq 1 9); do
|
||||
for strategy in F L R H; do
|
||||
o/$m/examples/compress.com -$strategy$level <o/dbg/third_party/python/python.com | dd count=10000 2>/tmp/info >/tmp/comp
|
||||
compspeed=$(grep -Po '[.\d]+ \w+/s' /tmp/info)
|
||||
o/$m/examples/decompress.com </tmp/comp | dd count=10000 2>/tmp/info >/dev/null
|
||||
decompspeed=$(grep -Po '[.\d]+ \w+/s' /tmp/info)
|
||||
size=$(o/$m/examples/compress.com -$strategy$level <o/$m/examples/compress.com | wc -c)
|
||||
echo "level $strategy $level $size compress $compspeed decompress $decompspeed"
|
||||
done
|
||||
done
|
||||
*/
|
||||
// clang-format on
|
||||
|
||||
int level;
|
||||
int strategy;
|
||||
|
||||
wontreturn void PrintUsage(int rc, FILE *f) {
|
||||
fputs("usage: ", f);
|
||||
fputs(program_invocation_name, f);
|
||||
fputs(USAGE, f);
|
||||
exit(rc);
|
||||
}
|
||||
|
||||
void GetOpts(int argc, char *argv[]) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "?hFLRH0123456789")) != -1) {
|
||||
switch (opt) {
|
||||
case 'F':
|
||||
strategy = Z_FIXED;
|
||||
break;
|
||||
case 'L':
|
||||
strategy = Z_FILTERED;
|
||||
break;
|
||||
case 'R':
|
||||
strategy = Z_RLE;
|
||||
break;
|
||||
case 'H':
|
||||
strategy = Z_HUFFMAN_ONLY;
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
level = opt - '0';
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
PrintUsage(EXIT_SUCCESS, stdout);
|
||||
default:
|
||||
PrintUsage(EX_USAGE, stderr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int compressor(int infd, int outfd) {
|
||||
z_stream zs;
|
||||
int rc, flush;
|
||||
unsigned have;
|
||||
unsigned char *inbuf;
|
||||
unsigned char *outbuf;
|
||||
inbuf = gc(valloc(CHUNK));
|
||||
outbuf = gc(valloc(CHUNK));
|
||||
zs.zalloc = 0;
|
||||
zs.zfree = 0;
|
||||
zs.opaque = 0;
|
||||
rc = deflateInit2(&zs, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, strategy);
|
||||
if (rc != Z_OK) return rc;
|
||||
do {
|
||||
rc = read(infd, inbuf, CHUNK);
|
||||
if (rc == -1) {
|
||||
deflateEnd(&zs);
|
||||
return Z_ERRNO;
|
||||
}
|
||||
zs.avail_in = rc;
|
||||
flush = !rc ? Z_FINISH : Z_SYNC_FLUSH;
|
||||
zs.next_in = inbuf;
|
||||
do {
|
||||
zs.avail_out = CHUNK;
|
||||
zs.next_out = outbuf;
|
||||
rc = deflate(&zs, flush);
|
||||
assert(rc != Z_STREAM_ERROR);
|
||||
have = CHUNK - zs.avail_out;
|
||||
if (write(outfd, outbuf, have) != have) {
|
||||
deflateEnd(&zs);
|
||||
return Z_ERRNO;
|
||||
}
|
||||
} while (!zs.avail_out);
|
||||
assert(!zs.avail_in);
|
||||
} while (flush != Z_FINISH);
|
||||
assert(rc == Z_STREAM_END);
|
||||
deflateEnd(&zs);
|
||||
return Z_OK;
|
||||
}
|
||||
|
||||
const char *zerr(int rc) {
|
||||
switch (rc) {
|
||||
case Z_ERRNO:
|
||||
return strerror(errno);
|
||||
case Z_STREAM_ERROR:
|
||||
return "invalid compression level";
|
||||
case Z_DATA_ERROR:
|
||||
return "invalid or incomplete deflate data";
|
||||
case Z_MEM_ERROR:
|
||||
return "out of memory";
|
||||
case Z_VERSION_ERROR:
|
||||
return "zlib version mismatch!";
|
||||
default:
|
||||
unreachable;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int rc;
|
||||
level = Z_DEFAULT_COMPRESSION;
|
||||
strategy = Z_DEFAULT_STRATEGY;
|
||||
GetOpts(argc, argv);
|
||||
rc = compressor(0, 1);
|
||||
if (rc == Z_OK) {
|
||||
return 0;
|
||||
} else {
|
||||
fprintf(stderr, "error: compressor: %s\n", zerr(rc));
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
Loaded 100 of 13630 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user