Compare commits
576 Commits
brillo-m7-
...
brillo-m8-
Author | SHA1 | Date | |
---|---|---|---|
![]() |
881673cb45 | ||
![]() |
585e959849 | ||
![]() |
a3dd076126 | ||
![]() |
162a8524ea | ||
![]() |
61cf963efe | ||
![]() |
a7ff3964ab | ||
![]() |
31951b7f0d | ||
![]() |
52e2db647c | ||
![]() |
2f019872dc | ||
![]() |
0bc3977537 | ||
![]() |
4a2c5aa30c | ||
![]() |
e46ded5ce1 | ||
![]() |
46e2eadad2 | ||
![]() |
cb025e55f7 | ||
![]() |
9d8632e1a7 | ||
![]() |
39801757c3 | ||
![]() |
6500f51c0e | ||
![]() |
284ae3559e | ||
![]() |
5a3ab3422d | ||
![]() |
db43526581 | ||
![]() |
40728bccbc | ||
![]() |
df196131f3 | ||
![]() |
5736959094 | ||
![]() |
9da687e2f4 | ||
![]() |
6c54ddd20f | ||
![]() |
89a50fe1eb | ||
![]() |
eaccfde075 | ||
![]() |
cf0c1af1dd | ||
![]() |
36545d2e76 | ||
![]() |
1190230f33 | ||
![]() |
568ad51d80 | ||
![]() |
f0a451dcd1 | ||
![]() |
d51a0b0f9d | ||
![]() |
9dec0a775b | ||
![]() |
cfd5a46b09 | ||
![]() |
7bd33cdf15 | ||
![]() |
29ee6397a8 | ||
![]() |
c4eef1fb5b | ||
![]() |
bb46afd6c4 | ||
![]() |
d5ce2a93af | ||
![]() |
e371ae68ac | ||
![]() |
22840aab47 | ||
![]() |
f4e511ecf9 | ||
![]() |
0d89913e74 | ||
![]() |
c8bae05f3f | ||
![]() |
071234cfd9 | ||
![]() |
4ade5195f1 | ||
![]() |
70d477c913 | ||
![]() |
21eadee6e9 | ||
![]() |
ef2ba3dbf9 | ||
![]() |
8766edc098 | ||
![]() |
a3f5912129 | ||
![]() |
942d81c246 | ||
![]() |
0b40c13a5a | ||
![]() |
939a7e0119 | ||
![]() |
2558b11230 | ||
![]() |
e049fa71cb | ||
![]() |
136bf8fa45 | ||
![]() |
870f165ceb | ||
![]() |
6ed51c0e85 | ||
![]() |
a29ed0bbce | ||
![]() |
21cca02a52 | ||
![]() |
2452cf3c33 | ||
![]() |
304348af19 | ||
![]() |
fb3708640f | ||
![]() |
514f46b74c | ||
![]() |
a32fc8685d | ||
![]() |
e670e2f859 | ||
![]() |
0ee40ef239 | ||
![]() |
b35a2fb370 | ||
![]() |
bf20d0226b | ||
![]() |
845e24a05e | ||
![]() |
a2ead18657 | ||
![]() |
84bc4f5cc7 | ||
![]() |
376b94f1e7 | ||
![]() |
b561043d3a | ||
![]() |
f57ae1cd43 | ||
![]() |
4371961e00 | ||
![]() |
d4c9b9d5ac | ||
![]() |
5bfa22ceab | ||
![]() |
22dca83e1c | ||
![]() |
b9055518fc | ||
![]() |
49a309ff6a | ||
![]() |
9f525b66eb | ||
![]() |
b24f7a0513 | ||
![]() |
a5e183c066 | ||
![]() |
d74566026d | ||
![]() |
9cbabd8fe5 | ||
![]() |
1f4b0c44b3 | ||
![]() |
4262d3e9ac | ||
![]() |
6bef152af2 | ||
![]() |
af87c9ccfc | ||
![]() |
9b687dc243 | ||
![]() |
51ca18d2a1 | ||
![]() |
28d3f00cf4 | ||
![]() |
d68c9e5906 | ||
![]() |
6ac2fdd0f4 | ||
![]() |
aec13988da | ||
![]() |
4f94b7bfc0 | ||
![]() |
2bb85c848a | ||
![]() |
f688c5d5b4 | ||
![]() |
83f314f060 | ||
![]() |
952e9eb086 | ||
![]() |
a36d1e0d31 | ||
![]() |
a01108d9bf | ||
![]() |
912e27a4b2 | ||
![]() |
8bd27182c5 | ||
![]() |
bff87d19f1 | ||
![]() |
321314f2e9 | ||
![]() |
db8caa740a | ||
![]() |
1ffec1cc4d | ||
![]() |
6ab8f89d1c | ||
![]() |
edcee4e401 | ||
![]() |
17554356cc | ||
![]() |
a8f8cbb3fc | ||
![]() |
a7fc7f9909 | ||
![]() |
3c5248182e | ||
![]() |
4469973bfb | ||
![]() |
74ed96d597 | ||
![]() |
76144aaa63 | ||
![]() |
8bd9e9ec69 | ||
![]() |
fb3219fbd1 | ||
![]() |
84bab5a955 | ||
![]() |
d34c33764e | ||
![]() |
a1ab0d8ed1 | ||
![]() |
bb06a84672 | ||
![]() |
b76123fed8 | ||
![]() |
8d5fb0d787 | ||
![]() |
b4bc156c6c | ||
![]() |
cb3af215dc | ||
![]() |
43c9045017 | ||
![]() |
ee67dd75e2 | ||
![]() |
8af9a739c9 | ||
![]() |
f30170dfa5 | ||
![]() |
b690cae8dd | ||
![]() |
79f8d64632 | ||
![]() |
75ba57de43 | ||
![]() |
9c6157c81d | ||
![]() |
284068f44f | ||
![]() |
a35d23d251 | ||
![]() |
2feb9dde60 | ||
![]() |
c9a659c57b | ||
![]() |
ce77e47b2f | ||
![]() |
0ebe2f07c3 | ||
![]() |
c22a7de798 | ||
![]() |
1ab4088062 | ||
![]() |
313632db57 | ||
![]() |
ff35b1e659 | ||
![]() |
f091c1f2f1 | ||
![]() |
9d4bd6f0ca | ||
![]() |
2c09e5de29 | ||
![]() |
ea5bb151af | ||
![]() |
fe3a83a934 | ||
![]() |
f74b041cce | ||
![]() |
3f539a1655 | ||
![]() |
63f0e0db76 | ||
![]() |
3cc35e224c | ||
![]() |
0307eee293 | ||
![]() |
a36158a77d | ||
![]() |
278fe431b6 | ||
![]() |
b804b9d67b | ||
![]() |
159c3d617f | ||
![]() |
3c8c16022a | ||
![]() |
fbfba64068 | ||
![]() |
e7c2fffa16 | ||
![]() |
4d87f17621 | ||
![]() |
949bfb9e3c | ||
![]() |
b061c9250d | ||
![]() |
61f186d067 | ||
![]() |
d9b08a0bc0 | ||
![]() |
2616cdcdb9 | ||
![]() |
1f0ccbb59c | ||
![]() |
1e79540807 | ||
![]() |
42d5fcb9f4 | ||
![]() |
69536213d6 | ||
![]() |
1b42c54471 | ||
![]() |
d1c28a361b | ||
![]() |
5187baa387 | ||
![]() |
5780f9d809 | ||
![]() |
bb725f7b77 | ||
![]() |
4ea67f6950 | ||
![]() |
a9cac4c87a | ||
![]() |
2ed1b29d00 | ||
![]() |
a2e9d90811 | ||
![]() |
7c10ee9473 | ||
![]() |
c04647f8c2 | ||
![]() |
c0116bd3db | ||
![]() |
0c447053de | ||
![]() |
fd57638117 | ||
![]() |
dbc6398e95 | ||
![]() |
5058a005b8 | ||
![]() |
504e3274a0 | ||
![]() |
b03e6bf924 | ||
![]() |
615f3aa8b4 | ||
![]() |
f208361b2b | ||
![]() |
2b1e258fec | ||
![]() |
ffe5c24c86 | ||
![]() |
de1246202a | ||
![]() |
8640233fef | ||
![]() |
6209b99a73 | ||
![]() |
2fb02651c8 | ||
![]() |
8e86f33690 | ||
![]() |
2a7f1b335d | ||
![]() |
926ebe1094 | ||
![]() |
2fdaa6c599 | ||
![]() |
11b3916b83 | ||
![]() |
09fac86ca3 | ||
![]() |
dcf501913d | ||
![]() |
704e048cbf | ||
![]() |
dc6b0a7b93 | ||
![]() |
a74eb4dbf5 | ||
![]() |
0e6542b75b | ||
![]() |
fb994f4c04 | ||
![]() |
4eba804ca0 | ||
![]() |
8b5b2c4672 | ||
![]() |
4200e260d2 | ||
![]() |
bc0b61e407 | ||
![]() |
3482613685 | ||
![]() |
fd7a91e692 | ||
![]() |
2dc1e91dba | ||
![]() |
004fead6bc | ||
![]() |
7a9311f7f1 | ||
![]() |
10c6a7c7b9 | ||
![]() |
ef5e647891 | ||
![]() |
824084ce76 | ||
![]() |
dd7dcfcfdb | ||
![]() |
eb9b925012 | ||
![]() |
50c21ab47d | ||
![]() |
021d959eba | ||
![]() |
a59479434c | ||
![]() |
4b920f042a | ||
![]() |
9e6f98fe9d | ||
![]() |
a4bff2106b | ||
![]() |
af909869d8 | ||
![]() |
706186d266 | ||
![]() |
9fe02f3e3c | ||
![]() |
86bf87c054 | ||
![]() |
0ba085de2c | ||
![]() |
a8f69017e5 | ||
![]() |
caa61b03b2 | ||
![]() |
6297e3231c | ||
![]() |
6ebfb7b4ea | ||
![]() |
fedb167c55 | ||
![]() |
316938a676 | ||
![]() |
bd5bf272a0 | ||
![]() |
c5f943eb2e | ||
![]() |
b420ddd27e | ||
![]() |
7f337bd1e3 | ||
![]() |
601183efaf | ||
![]() |
2c11b07ee0 | ||
![]() |
a1be410fd7 | ||
![]() |
75347e52b0 | ||
![]() |
9e599956b2 | ||
![]() |
3b9b14830b | ||
![]() |
6e780f2f47 | ||
![]() |
164bd7349b | ||
![]() |
00e9bfe523 | ||
![]() |
159f0d4013 | ||
![]() |
3d784087cd | ||
![]() |
382524878a | ||
![]() |
25a7efa7e9 | ||
![]() |
c9ad2274b2 | ||
![]() |
172cdd79a5 | ||
![]() |
c5b9c4d72f | ||
![]() |
67e282d511 | ||
![]() |
bdff4ce8ed | ||
![]() |
807032d0e1 | ||
![]() |
12b46fb00e | ||
![]() |
0507b6e9e6 | ||
![]() |
216bff9ff3 | ||
![]() |
afff4442ae | ||
![]() |
d676080a37 | ||
![]() |
258a775d75 | ||
![]() |
788eae7286 | ||
![]() |
4e0c4032d1 | ||
![]() |
0fb6704e82 | ||
![]() |
56ecb9bf2a | ||
![]() |
053867ded8 | ||
![]() |
64f628f8d3 | ||
![]() |
055a66c9b1 | ||
![]() |
43b1f823b5 | ||
![]() |
1a61896b1b | ||
![]() |
98384649b2 | ||
![]() |
753162836a | ||
![]() |
2d23418e68 | ||
![]() |
18442e0235 | ||
![]() |
630855a6d5 | ||
![]() |
6764e0b5e5 | ||
![]() |
beb6e08abf | ||
![]() |
a60b1aebb7 | ||
![]() |
56cd1962b2 | ||
![]() |
114605b036 | ||
![]() |
c0e917abe5 | ||
![]() |
3676052ce7 | ||
![]() |
842866bd00 | ||
![]() |
845dd0266b | ||
![]() |
c70d479dc6 | ||
![]() |
8c9cb6820f | ||
![]() |
9e2d37ccae | ||
![]() |
95ac6dbbb2 | ||
![]() |
3c30a15652 | ||
![]() |
b16f1b4b89 | ||
![]() |
559d9cf5fa | ||
![]() |
9a9572d577 | ||
![]() |
cf92738fa5 | ||
![]() |
cd9278798a | ||
![]() |
87bb58064d | ||
![]() |
36ebee4f49 | ||
![]() |
b8ab96910f | ||
![]() |
090278d6c6 | ||
![]() |
1002265d0a | ||
![]() |
7197c2909d | ||
![]() |
5db60c04c6 | ||
![]() |
f32b689d3d | ||
![]() |
1cdd99bcb9 | ||
![]() |
12b4f21e19 | ||
![]() |
433cdaa85f | ||
![]() |
5a805d919c | ||
![]() |
78f1871f4e | ||
![]() |
452ab8f7e3 | ||
![]() |
7c585f2b01 | ||
![]() |
d8c03b774e | ||
![]() |
132b9c90fc | ||
![]() |
ac47790ad8 | ||
![]() |
dc9ff1b80b | ||
![]() |
8733118fa5 | ||
![]() |
c1d7d92201 | ||
![]() |
533d7e403d | ||
![]() |
786807b26c | ||
![]() |
17e3aec523 | ||
![]() |
ec48a72a00 | ||
![]() |
a828a2f8e6 | ||
![]() |
10f71abc4e | ||
![]() |
b5e05d29b5 | ||
![]() |
29fe356575 | ||
![]() |
8daf53db75 | ||
![]() |
991a8a6bf7 | ||
![]() |
e22d32d06c | ||
![]() |
a978ec9e7b | ||
![]() |
03d14f9276 | ||
![]() |
240a0a9068 | ||
![]() |
b33e6097fe | ||
![]() |
84b24d62d0 | ||
![]() |
8db320637c | ||
![]() |
86fdb6bf23 | ||
![]() |
4f3e3591ac | ||
![]() |
6a753ffec6 | ||
![]() |
195a5bef1f | ||
![]() |
3fb798c8ac | ||
![]() |
2027e5e4ca | ||
![]() |
fd7251acd4 | ||
![]() |
b74e9ddda5 | ||
![]() |
93a91f0cf4 | ||
![]() |
a64bb4c172 | ||
![]() |
aaff959fc0 | ||
![]() |
774a4703e8 | ||
![]() |
609716ae95 | ||
![]() |
01030c24b0 | ||
![]() |
2c60af3e81 | ||
![]() |
678752ed2a | ||
![]() |
fff13b9196 | ||
![]() |
afba67bd2f | ||
![]() |
eb83e971b4 | ||
![]() |
4e9118c25c | ||
![]() |
78f5504b92 | ||
![]() |
cccb36036f | ||
![]() |
a2308b7f67 | ||
![]() |
a1ae03e21d | ||
![]() |
672ff19c65 | ||
![]() |
51c4d51d8f | ||
![]() |
10292607e4 | ||
![]() |
1e9b59d37e | ||
![]() |
e06ef6709f | ||
![]() |
ec94ca9284 | ||
![]() |
5c12a504cf | ||
![]() |
c101cc20bf | ||
![]() |
a59905b80c | ||
![]() |
5278af69ac | ||
![]() |
8abd365509 | ||
![]() |
a4b45b70f5 | ||
![]() |
b3c3fb5b59 | ||
![]() |
a775a41130 | ||
![]() |
23ff8fc4ee | ||
![]() |
407dea47bd | ||
![]() |
eb457e212e | ||
![]() |
80dbedc95a | ||
![]() |
695d4c62fd | ||
![]() |
0cc8e665fd | ||
![]() |
0f0c7197b5 | ||
![]() |
5e98eaee2d | ||
![]() |
4afb130399 | ||
![]() |
a0d1cda1a6 | ||
![]() |
ed90d4caea | ||
![]() |
a56db54d1d | ||
![]() |
83c7b596e4 | ||
![]() |
268344457e | ||
![]() |
b455457761 | ||
![]() |
356868f8ac | ||
![]() |
11a740e879 | ||
![]() |
82f20c916e | ||
![]() |
d32cadd1a5 | ||
![]() |
b8c276b778 | ||
![]() |
756574d53e | ||
![]() |
4ca3de4502 | ||
![]() |
437c3e48f9 | ||
![]() |
40773fb797 | ||
![]() |
3aa60b82ef | ||
![]() |
806055dace | ||
![]() |
f962a1848e | ||
![]() |
91aeb800d6 | ||
![]() |
393e69d77e | ||
![]() |
a849fe6e2e | ||
![]() |
8abc375ec9 | ||
![]() |
f92664cbe5 | ||
![]() |
b635c4ebb2 | ||
![]() |
ec6a557b38 | ||
![]() |
79697a7096 | ||
![]() |
8cc0d89a9d | ||
![]() |
0bbda9838b | ||
![]() |
3ce99a04a9 | ||
![]() |
7b02991de7 | ||
![]() |
29eaaa6ee5 | ||
![]() |
34df06eb8a | ||
![]() |
45f262c084 | ||
![]() |
a31ba88d4c | ||
![]() |
f1a2cd9713 | ||
![]() |
37c4110f41 | ||
![]() |
ba06d5519e | ||
![]() |
dc5970d025 | ||
![]() |
e6623ebcaf | ||
![]() |
b51b07117c | ||
![]() |
1dd6f6436b | ||
![]() |
3cb8b52334 | ||
![]() |
d4cc5122d2 | ||
![]() |
6ed2717b28 | ||
![]() |
6141acb75f | ||
![]() |
9f80696d4e | ||
![]() |
21b3d798e8 | ||
![]() |
8a955e1493 | ||
![]() |
741d5ae03d | ||
![]() |
73a6ac348d | ||
![]() |
273292a11a | ||
![]() |
a3b90f275a | ||
![]() |
89722d9f65 | ||
![]() |
010563c886 | ||
![]() |
f616c70e20 | ||
![]() |
fda41cce04 | ||
![]() |
1ebd90caf1 | ||
![]() |
5ca7a74838 | ||
![]() |
775339f00e | ||
![]() |
5f8b4eb2a8 | ||
![]() |
0931e46f64 | ||
![]() |
9405119369 | ||
![]() |
8f137f06ea | ||
![]() |
3ff0bae759 | ||
![]() |
3a647e158d | ||
![]() |
78f34b981e | ||
![]() |
930936ae7b | ||
![]() |
f98c881d8e | ||
![]() |
70a5005ea6 | ||
![]() |
4110bb6452 | ||
![]() |
f86b5a751c | ||
![]() |
93ec254b9e | ||
![]() |
3d397fa661 | ||
![]() |
09f2ae9b40 | ||
![]() |
256e992517 | ||
![]() |
4972c73602 | ||
![]() |
67e5c7f06f | ||
![]() |
9d4bfe17b9 | ||
![]() |
eafe28f85a | ||
![]() |
74484e8bd4 | ||
![]() |
ac02082fa0 | ||
![]() |
44cb343e4d | ||
![]() |
44808d163f | ||
![]() |
91ceb2b70a | ||
![]() |
e875510e17 | ||
![]() |
9b8179fb7e | ||
![]() |
22b9e685bc | ||
![]() |
9b484289e1 | ||
![]() |
82ff96be56 | ||
![]() |
e75d37eb5a | ||
![]() |
0746d0f175 | ||
![]() |
fca5c4413a | ||
![]() |
12ec03e3af | ||
![]() |
6501864af4 | ||
![]() |
f2700df2ae | ||
![]() |
7443dd5805 | ||
![]() |
cc4245a8de | ||
![]() |
ff78def4fc | ||
![]() |
650e66cd7e | ||
![]() |
1b22327893 | ||
![]() |
66a7be9961 | ||
![]() |
5ad3ebf08d | ||
![]() |
aad7f33e2a | ||
![]() |
b8c08f44ab | ||
![]() |
784ccf07bf | ||
![]() |
f17f8157b2 | ||
![]() |
51d2579367 | ||
![]() |
d54d116352 | ||
![]() |
21a285029b | ||
![]() |
3c0d78d576 | ||
![]() |
4a8f4867fc | ||
![]() |
e6f16b2d7d | ||
![]() |
4400c1d448 | ||
![]() |
fa20d51e91 | ||
![]() |
6ac9e42958 | ||
![]() |
12229387f4 | ||
![]() |
ee6c6845c0 | ||
![]() |
e7cf1de6b9 | ||
![]() |
4c615501e5 | ||
![]() |
857336809e | ||
![]() |
4b99bef35b | ||
![]() |
b23720dfc4 | ||
![]() |
9a549011ad | ||
![]() |
5e64d60690 | ||
![]() |
6a5a09be4e | ||
![]() |
d6edf15728 | ||
![]() |
3926593b36 | ||
![]() |
c028e4aaa3 | ||
![]() |
90acccbd97 | ||
![]() |
52d8e318f9 | ||
![]() |
f11ff78db5 | ||
![]() |
125481fe3c | ||
![]() |
73854d9f1a | ||
![]() |
45ea30c472 | ||
![]() |
73ca982c97 | ||
![]() |
475b542458 | ||
![]() |
cd6b01e214 | ||
![]() |
6f0c9b4827 | ||
![]() |
26ac060046 | ||
![]() |
d3d40b1531 | ||
![]() |
4f4dd3caae | ||
![]() |
98fc81cf5e | ||
![]() |
e6464678b3 | ||
![]() |
291c314005 | ||
![]() |
9816016893 | ||
![]() |
e9f23862fe | ||
![]() |
22091a09ae | ||
![]() |
beebbff0a0 | ||
![]() |
c9d373e2d9 | ||
![]() |
bb65e61f6b | ||
![]() |
758bc0a806 | ||
![]() |
cf3d602b28 | ||
![]() |
788e7c9937 | ||
![]() |
e16cf1d531 | ||
![]() |
41298d1aae | ||
![]() |
bbfdd50518 | ||
![]() |
e47102098b | ||
![]() |
c2b097252a | ||
![]() |
5905cee174 | ||
![]() |
d2aeefed8e | ||
![]() |
2733ec035d | ||
![]() |
039b290b9d | ||
![]() |
af584b5e7b | ||
![]() |
87b64fb447 | ||
![]() |
c6a87cc8cb | ||
![]() |
cca803af0c | ||
![]() |
9bd373c4fc | ||
![]() |
beaf565cd4 | ||
![]() |
43a783714f | ||
![]() |
2f54a44110 | ||
![]() |
3b9900d346 | ||
![]() |
653f4b1504 | ||
![]() |
287cf2664f | ||
![]() |
acf2b7bea6 | ||
![]() |
533efc20b7 | ||
![]() |
538a4d7029 | ||
![]() |
9d4402a95c | ||
![]() |
a13ece0d6c | ||
![]() |
16d78688b4 | ||
![]() |
c9bd26e96b | ||
![]() |
a2e2c3d2ae | ||
![]() |
049a5ae002 | ||
![]() |
805844ff0c | ||
![]() |
b6c2d3f30b | ||
![]() |
6a31a37cc1 |
@@ -2,6 +2,7 @@ BasedOnStyle: Google
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
|
||||
ColumnLimit: 100
|
||||
CommentPragmas: NOLINT:.*
|
||||
DerivePointerAlignment: false
|
||||
IndentWidth: 2
|
||||
|
@@ -24,7 +24,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <base/stringprintf.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
|
||||
#include <benchmark/Benchmark.h>
|
||||
|
||||
|
@@ -23,7 +23,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <base/stringprintf.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
|
||||
int Round(int n) {
|
||||
int base = 1;
|
||||
|
1326
libc/Android.bp
1326
libc/Android.bp
File diff suppressed because it is too large
Load Diff
@@ -47,7 +47,6 @@ libc_common_src_files := \
|
||||
bionic/if_indextoname.c \
|
||||
bionic/if_nametoindex.c \
|
||||
bionic/initgroups.c \
|
||||
bionic/ioctl.c \
|
||||
bionic/isatty.c \
|
||||
bionic/memmem.c \
|
||||
bionic/pututline.c \
|
||||
@@ -151,6 +150,7 @@ libc_bionic_ndk_src_files := \
|
||||
bionic/gettid.cpp \
|
||||
bionic/__gnu_basename.cpp \
|
||||
bionic/inotify_init.cpp \
|
||||
bionic/ioctl.cpp \
|
||||
bionic/lchown.cpp \
|
||||
bionic/lfs64_support.cpp \
|
||||
bionic/__libc_current_sigrtmax.cpp \
|
||||
@@ -170,6 +170,7 @@ libc_bionic_ndk_src_files := \
|
||||
bionic/mkfifo.cpp \
|
||||
bionic/mknod.cpp \
|
||||
bionic/mntent.cpp \
|
||||
bionic/mremap.cpp \
|
||||
bionic/NetdClientDispatch.cpp \
|
||||
bionic/open.cpp \
|
||||
bionic/pathconf.cpp \
|
||||
@@ -242,9 +243,11 @@ libc_bionic_ndk_src_files := \
|
||||
|
||||
libc_bionic_src_files :=
|
||||
|
||||
# The fork implementation depends on pthread data, so we can't include it in
|
||||
# libc_ndk.a.
|
||||
libc_bionic_src_files += bionic/fork.cpp
|
||||
# The following implementations depend on pthread data, so we can't include
|
||||
# them in libc_ndk.a.
|
||||
libc_bionic_src_files += \
|
||||
bionic/__cxa_thread_atexit_impl.cpp \
|
||||
bionic/fork.cpp \
|
||||
|
||||
# The data that backs getauxval is initialized in the libc init functions which
|
||||
# are invoked by the linker. If this file is included in libc_ndk.a, only one of
|
||||
@@ -563,6 +566,7 @@ libc_upstream_openbsd_ndk_src_files := \
|
||||
libc_pthread_src_files := \
|
||||
bionic/pthread_atfork.cpp \
|
||||
bionic/pthread_attr.cpp \
|
||||
bionic/pthread_barrier.cpp \
|
||||
bionic/pthread_cond.cpp \
|
||||
bionic/pthread_create.cpp \
|
||||
bionic/pthread_detach.cpp \
|
||||
@@ -582,9 +586,7 @@ libc_pthread_src_files := \
|
||||
bionic/pthread_setname_np.cpp \
|
||||
bionic/pthread_setschedparam.cpp \
|
||||
bionic/pthread_sigmask.cpp \
|
||||
|
||||
libc_thread_atexit_impl_src_files := \
|
||||
bionic/__cxa_thread_atexit_impl.cpp \
|
||||
bionic/pthread_spinlock.cpp \
|
||||
|
||||
libc_arch_static_src_files := \
|
||||
bionic/dl_iterate_phdr_static.cpp \
|
||||
@@ -622,6 +624,11 @@ ifeq ($(TARGET_ARCH),x86_64)
|
||||
use_clang := false
|
||||
endif
|
||||
|
||||
# b/25291096, Clang/llvm compiled libc.so for mips/mips64 failed to boot.
|
||||
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),mips mips64))
|
||||
use_clang := false
|
||||
endif
|
||||
|
||||
ifeq ($(use_clang),)
|
||||
use_clang := false
|
||||
endif
|
||||
@@ -690,6 +697,9 @@ endef
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := bionic/__stack_chk_fail.cpp
|
||||
# On x86, the __set_tls implementation is complex enough that
|
||||
# -fstack-protector-strong inserts a check.
|
||||
LOCAL_SRC_FILES_x86 := arch-x86/bionic/__set_tls.c
|
||||
LOCAL_CFLAGS := $(libc_common_cflags) -fno-stack-protector
|
||||
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
|
||||
LOCAL_CPPFLAGS := $(libc_common_cppflags)
|
||||
@@ -724,6 +734,7 @@ LOCAL_CFLAGS := $(libc_common_cflags) \
|
||||
LOCAL_CFLAGS += -DALL_STATE
|
||||
# Include tzsetwall, timelocal, timegm, time2posix, and posix2time.
|
||||
LOCAL_CFLAGS += -DSTD_INSPIRED
|
||||
# Obviously, we want to be thread-safe.
|
||||
LOCAL_CFLAGS += -DTHREAD_SAFE
|
||||
# The name of the tm_gmtoff field in our struct tm.
|
||||
LOCAL_CFLAGS += -DTM_GMTOFF=tm_gmtoff
|
||||
@@ -731,6 +742,8 @@ LOCAL_CFLAGS += -DTM_GMTOFF=tm_gmtoff
|
||||
LOCAL_CFLAGS += -DTZDIR=\"/system/usr/share/zoneinfo\"
|
||||
# Include timezone and daylight globals.
|
||||
LOCAL_CFLAGS += -DUSG_COMPAT=1
|
||||
# Use the empty string (instead of " ") as the timezone abbreviation fallback.
|
||||
LOCAL_CFLAGS += -DWILDABBR=\"\"
|
||||
LOCAL_CFLAGS += -DNO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
|
||||
LOCAL_CFLAGS += -Dlint
|
||||
|
||||
@@ -939,6 +952,7 @@ LOCAL_SANITIZE := never
|
||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
|
||||
|
||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
|
||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_openbsd_src_files))
|
||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES_EXCLUDE,libc_openbsd_src_files_exclude))
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
@@ -1034,24 +1048,6 @@ $(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
|
||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_bionic_ndk_src_files))
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := $(libc_thread_atexit_impl_src_files)
|
||||
LOCAL_CFLAGS := $(libc_common_cflags) -Wframe-larger-than=2048
|
||||
|
||||
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
|
||||
LOCAL_CPPFLAGS := $(libc_common_cppflags) -Wold-style-cast
|
||||
LOCAL_C_INCLUDES := $(libc_common_c_includes)
|
||||
LOCAL_MODULE := libc_thread_atexit_impl
|
||||
# TODO: Clang tries to use __tls_get_addr which is not supported yet
|
||||
# remove after it is implemented.
|
||||
LOCAL_CLANG := false
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
|
||||
LOCAL_CXX_STL := none
|
||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
|
||||
LOCAL_SANITIZE := never
|
||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
# ========================================================
|
||||
# libc_pthread.a - pthreads parts that previously lived in
|
||||
@@ -1249,7 +1245,6 @@ LOCAL_WHOLE_STATIC_LIBRARIES := \
|
||||
libc_pthread \
|
||||
libc_stack_protector \
|
||||
libc_syscalls \
|
||||
libc_thread_atexit_impl \
|
||||
libc_tzcode \
|
||||
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES_arm := libc_aeabi
|
||||
@@ -1391,6 +1386,12 @@ LOCAL_ADDITIONAL_DEPENDENCIES := \
|
||||
$(LOCAL_PATH)/libc.mips64.map \
|
||||
$(LOCAL_PATH)/libc.x86.map \
|
||||
$(LOCAL_PATH)/libc.x86_64.map \
|
||||
$(LOCAL_PATH)/libc.arm.brillo.map \
|
||||
$(LOCAL_PATH)/libc.arm64.brillo.map \
|
||||
$(LOCAL_PATH)/libc.mips.brillo.map \
|
||||
$(LOCAL_PATH)/libc.mips64.brillo.map \
|
||||
$(LOCAL_PATH)/libc.x86.brillo.map \
|
||||
$(LOCAL_PATH)/libc.x86_64.brillo.map \
|
||||
|
||||
# Leave the symbols in the shared library so that stack unwinders can produce
|
||||
# meaningful name resolution.
|
||||
@@ -1422,12 +1423,21 @@ LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
|
||||
LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both
|
||||
|
||||
# Don't re-export new/delete and friends, even if the compiler really wants to.
|
||||
ifdef BRILLO
|
||||
LOCAL_LDFLAGS_arm += -Wl,--version-script,$(LOCAL_PATH)/libc.arm.brillo.map
|
||||
LOCAL_LDFLAGS_mips += -Wl,--version-script,$(LOCAL_PATH)/libc.mips.brillo.map
|
||||
LOCAL_LDFLAGS_x86 += -Wl,--version-script,$(LOCAL_PATH)/libc.x86.brillo.map
|
||||
LOCAL_LDFLAGS_arm64 += -Wl,--version-script,$(LOCAL_PATH)/libc.arm64.brillo.map
|
||||
LOCAL_LDFLAGS_mips64 += -Wl,--version-script,$(LOCAL_PATH)/libc.mips64.brillo.map
|
||||
LOCAL_LDFLAGS_x86_64 += -Wl,--version-script,$(LOCAL_PATH)/libc.x86_64.brillo.map
|
||||
else
|
||||
LOCAL_LDFLAGS_arm += -Wl,--version-script,$(LOCAL_PATH)/libc.arm.map
|
||||
LOCAL_LDFLAGS_arm64 += -Wl,--version-script,$(LOCAL_PATH)/libc.arm64.map
|
||||
LOCAL_LDFLAGS_mips += -Wl,--version-script,$(LOCAL_PATH)/libc.mips.map
|
||||
LOCAL_LDFLAGS_mips64 += -Wl,--version-script,$(LOCAL_PATH)/libc.mips64.map
|
||||
LOCAL_LDFLAGS_x86 += -Wl,--version-script,$(LOCAL_PATH)/libc.x86.map
|
||||
LOCAL_LDFLAGS_arm64 += -Wl,--version-script,$(LOCAL_PATH)/libc.arm64.map
|
||||
LOCAL_LDFLAGS_mips64 += -Wl,--version-script,$(LOCAL_PATH)/libc.mips64.map
|
||||
LOCAL_LDFLAGS_x86_64 += -Wl,--version-script,$(LOCAL_PATH)/libc.x86_64.map
|
||||
endif
|
||||
|
||||
# We'd really like to do this for all architectures, but since this wasn't done
|
||||
# before, these symbols must continue to be exported on LP32 for binary
|
||||
|
@@ -107,7 +107,7 @@ ssize_t pwritev|pwritev64(int, const struct iovec*, int, off_t) arm64,mips64
|
||||
int ___close:close(int) all
|
||||
pid_t __getpid:getpid() all
|
||||
int munmap(void*, size_t) all
|
||||
void* mremap(void*, size_t, size_t, unsigned long) all
|
||||
void* ___mremap:mremap(void*, size_t, size_t, int, void*) all
|
||||
int msync(const void*, size_t, int) all
|
||||
int mprotect(const void*, size_t, int) all
|
||||
int madvise(void*, size_t, int) all
|
||||
|
23
libc/arch-arm/syscalls/___mremap.S
Normal file
23
libc/arch-arm/syscalls/___mremap.S
Normal file
@@ -0,0 +1,23 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(___mremap)
|
||||
mov ip, sp
|
||||
stmfd sp!, {r4, r5, r6, r7}
|
||||
.cfi_def_cfa_offset 16
|
||||
.cfi_rel_offset r4, 0
|
||||
.cfi_rel_offset r5, 4
|
||||
.cfi_rel_offset r6, 8
|
||||
.cfi_rel_offset r7, 12
|
||||
ldmfd ip, {r4, r5, r6}
|
||||
ldr r7, =__NR_mremap
|
||||
swi #0
|
||||
ldmfd sp!, {r4, r5, r6, r7}
|
||||
.cfi_def_cfa_offset 0
|
||||
cmn r0, #(MAX_ERRNO + 1)
|
||||
bxls lr
|
||||
neg r0, r0
|
||||
b __set_errno_internal
|
||||
END(___mremap)
|
||||
.hidden ___mremap
|
@@ -1,14 +0,0 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(mremap)
|
||||
mov ip, r7
|
||||
ldr r7, =__NR_mremap
|
||||
swi #0
|
||||
mov r7, ip
|
||||
cmn r0, #(MAX_ERRNO + 1)
|
||||
bxls lr
|
||||
neg r0, r0
|
||||
b __set_errno_internal
|
||||
END(mremap)
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(mremap)
|
||||
ENTRY(___mremap)
|
||||
mov x8, __NR_mremap
|
||||
svc #0
|
||||
|
||||
@@ -11,4 +11,5 @@ ENTRY(mremap)
|
||||
b.hi __set_errno_internal
|
||||
|
||||
ret
|
||||
END(mremap)
|
||||
END(___mremap)
|
||||
.hidden ___mremap
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(mremap)
|
||||
ENTRY(___mremap)
|
||||
.set noreorder
|
||||
.cpload t9
|
||||
li v0, __NR_mremap
|
||||
@@ -16,4 +16,5 @@ ENTRY(mremap)
|
||||
j t9
|
||||
nop
|
||||
.set reorder
|
||||
END(mremap)
|
||||
END(___mremap)
|
||||
.hidden ___mremap
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(mremap)
|
||||
ENTRY(___mremap)
|
||||
.set push
|
||||
.set noreorder
|
||||
li v0, __NR_mremap
|
||||
@@ -22,4 +22,5 @@ ENTRY(mremap)
|
||||
j t9
|
||||
move ra, t0
|
||||
.set pop
|
||||
END(mremap)
|
||||
END(___mremap)
|
||||
.hidden ___mremap
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(mremap)
|
||||
ENTRY(___mremap)
|
||||
pushl %ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset ebx, 0
|
||||
@@ -15,10 +15,14 @@ ENTRY(mremap)
|
||||
pushl %esi
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset esi, 0
|
||||
mov 20(%esp), %ebx
|
||||
mov 24(%esp), %ecx
|
||||
mov 28(%esp), %edx
|
||||
mov 32(%esp), %esi
|
||||
pushl %edi
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset edi, 0
|
||||
mov 24(%esp), %ebx
|
||||
mov 28(%esp), %ecx
|
||||
mov 32(%esp), %edx
|
||||
mov 36(%esp), %esi
|
||||
mov 40(%esp), %edi
|
||||
movl $__NR_mremap, %eax
|
||||
int $0x80
|
||||
cmpl $-MAX_ERRNO, %eax
|
||||
@@ -28,9 +32,11 @@ ENTRY(mremap)
|
||||
call __set_errno_internal
|
||||
addl $4, %esp
|
||||
1:
|
||||
popl %edi
|
||||
popl %esi
|
||||
popl %edx
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
ret
|
||||
END(mremap)
|
||||
END(___mremap)
|
||||
.hidden ___mremap
|
@@ -109,7 +109,6 @@ libc_bionic_src_files_x86 += \
|
||||
arch-x86/bionic/libgcc_compat.c \
|
||||
arch-x86/bionic/__restore.S \
|
||||
arch-x86/bionic/setjmp.S \
|
||||
arch-x86/bionic/__set_tls.c \
|
||||
arch-x86/bionic/syscall.S \
|
||||
arch-x86/bionic/vfork.S \
|
||||
|
||||
|
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(mremap)
|
||||
ENTRY(___mremap)
|
||||
movq %rcx, %r10
|
||||
movl $__NR_mremap, %eax
|
||||
syscall
|
||||
@@ -13,4 +13,5 @@ ENTRY(mremap)
|
||||
call __set_errno_internal
|
||||
1:
|
||||
ret
|
||||
END(mremap)
|
||||
END(___mremap)
|
||||
.hidden ___mremap
|
@@ -109,7 +109,7 @@ extern "C" int __cxa_guard_acquire(_guard_t* gv) {
|
||||
}
|
||||
}
|
||||
|
||||
__futex_wait_ex(&gv->state, false, CONSTRUCTION_UNDERWAY_WITH_WAITER, NULL);
|
||||
__futex_wait_ex(&gv->state, false, CONSTRUCTION_UNDERWAY_WITH_WAITER, false, nullptr);
|
||||
old_value = atomic_load_explicit(&gv->state, memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
|
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include "pthread_internal.h"
|
||||
|
||||
struct thread_local_dtor {
|
||||
void (*func) (void *);
|
||||
void *arg;
|
||||
@@ -22,25 +24,24 @@ struct thread_local_dtor {
|
||||
thread_local_dtor* next;
|
||||
};
|
||||
|
||||
static __thread thread_local_dtor* thread_local_dtors = nullptr;
|
||||
|
||||
extern "C" int __cxa_thread_atexit_impl(void (*func) (void *), void *arg, void *dso_handle) {
|
||||
thread_local_dtor* dtor = new thread_local_dtor();
|
||||
|
||||
dtor->func = func;
|
||||
dtor->arg = arg;
|
||||
dtor->dso_handle = dso_handle;
|
||||
dtor->next = thread_local_dtors;
|
||||
|
||||
thread_local_dtors = dtor;
|
||||
|
||||
pthread_internal_t* thread = __get_thread();
|
||||
dtor->next = thread->thread_local_dtors;
|
||||
thread->thread_local_dtors = dtor;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" __LIBC_HIDDEN__ void __cxa_thread_finalize() {
|
||||
while (thread_local_dtors != nullptr) {
|
||||
thread_local_dtor* current = thread_local_dtors;
|
||||
thread_local_dtors = current->next;
|
||||
pthread_internal_t* thread = __get_thread();
|
||||
while (thread->thread_local_dtors != nullptr) {
|
||||
thread_local_dtor* current = thread->thread_local_dtors;
|
||||
thread->thread_local_dtors = current->next;
|
||||
|
||||
current->func(current->arg);
|
||||
delete current;
|
||||
|
@@ -34,27 +34,25 @@ constexpr char SYSTRACE_PROPERTY_NAME[] = "debug.atrace.tags.enableflags";
|
||||
|
||||
static Lock g_lock;
|
||||
static const prop_info* g_pinfo;
|
||||
static uint32_t g_serial = -1;
|
||||
static uint32_t g_property_serial = -1;
|
||||
static uint32_t g_property_area_serial = -1;
|
||||
static uint64_t g_tags;
|
||||
static int g_trace_marker_fd = -1;
|
||||
|
||||
static bool should_trace() {
|
||||
bool result = false;
|
||||
g_lock.lock();
|
||||
// If g_pinfo is null, this means that systrace hasn't been run and it's safe to
|
||||
// assume that no trace writing will need to take place. However, to avoid running
|
||||
// this costly find check each time, we set it to a non-tracing value so that next
|
||||
// time, it will just check the serial to see if the value has been changed.
|
||||
// this function also deals with the bootup case, during which the call to property
|
||||
// set will fail if the property server hasn't yet started.
|
||||
if (g_pinfo == NULL) {
|
||||
// debug.atrace.tags.enableflags is set to a safe non-tracing value during property
|
||||
// space initialization, so it should only be null in two cases, if there are
|
||||
// insufficient permissions for this process to access the property, in which
|
||||
// case an audit will be logged, and during boot before the property server has
|
||||
// been started, in which case we store the global property_area serial to prevent
|
||||
// the costly find operation until we see a changed property_area.
|
||||
if (!g_pinfo && g_property_area_serial != __system_property_area_serial()) {
|
||||
g_property_area_serial = __system_property_area_serial();
|
||||
g_pinfo = __system_property_find(SYSTRACE_PROPERTY_NAME);
|
||||
if (g_pinfo == NULL) {
|
||||
__system_property_set(SYSTRACE_PROPERTY_NAME, "0");
|
||||
g_pinfo = __system_property_find(SYSTRACE_PROPERTY_NAME);
|
||||
}
|
||||
}
|
||||
if (g_pinfo != NULL) {
|
||||
if (g_pinfo) {
|
||||
// Find out which tags have been enabled on the command line and set
|
||||
// the value of tags accordingly. If the value of the property changes,
|
||||
// the serial will also change, so the costly system_property_read function
|
||||
@@ -62,11 +60,11 @@ static bool should_trace() {
|
||||
// first. The values within pinfo may change, but its location is guaranteed
|
||||
// not to move.
|
||||
uint32_t cur_serial = __system_property_serial(g_pinfo);
|
||||
if (cur_serial != g_serial) {
|
||||
g_serial = cur_serial;
|
||||
if (cur_serial != g_property_serial) {
|
||||
g_property_serial = cur_serial;
|
||||
char value[PROP_VALUE_MAX];
|
||||
__system_property_read(g_pinfo, 0, value);
|
||||
g_tags = strtoull(value, NULL, 0);
|
||||
g_tags = strtoull(value, nullptr, 0);
|
||||
}
|
||||
result = ((g_tags & ATRACE_TAG_BIONIC) != 0);
|
||||
}
|
||||
|
@@ -52,18 +52,12 @@ void timeval_from_timespec(timeval& tv, const timespec& ts) {
|
||||
tv.tv_usec = ts.tv_nsec / 1000;
|
||||
}
|
||||
|
||||
// Initializes 'ts' with the difference between 'abs_ts' and the current time
|
||||
// according to 'clock'. Returns false if abstime already expired, true otherwise.
|
||||
bool timespec_from_absolute_timespec(timespec& ts, const timespec& abs_ts, clockid_t clock) {
|
||||
clock_gettime(clock, &ts);
|
||||
ts.tv_sec = abs_ts.tv_sec - ts.tv_sec;
|
||||
ts.tv_nsec = abs_ts.tv_nsec - ts.tv_nsec;
|
||||
if (ts.tv_nsec < 0) {
|
||||
ts.tv_sec--;
|
||||
ts.tv_nsec += NS_PER_S;
|
||||
void absolute_timespec_from_timespec(timespec& abs_ts, const timespec& ts, clockid_t clock) {
|
||||
clock_gettime(clock, &abs_ts);
|
||||
abs_ts.tv_sec += ts.tv_sec;
|
||||
abs_ts.tv_nsec += ts.tv_nsec;
|
||||
if (abs_ts.tv_nsec >= NS_PER_S) {
|
||||
abs_ts.tv_nsec -= NS_PER_S;
|
||||
abs_ts.tv_sec++;
|
||||
}
|
||||
if (ts.tv_nsec < 0 || ts.tv_sec < 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@@ -36,23 +36,15 @@
|
||||
// struct __sfileext (see fileext.h).
|
||||
|
||||
void flockfile(FILE* fp) {
|
||||
if (!__sdidinit) {
|
||||
__sinit();
|
||||
}
|
||||
|
||||
if (fp != NULL) {
|
||||
if (fp != nullptr) {
|
||||
pthread_mutex_lock(&_FLOCK(fp));
|
||||
}
|
||||
}
|
||||
|
||||
int ftrylockfile(FILE* fp) {
|
||||
if (!__sdidinit) {
|
||||
__sinit();
|
||||
}
|
||||
|
||||
// The specification for ftrylockfile() says it returns 0 on success,
|
||||
// or non-zero on error. So return an errno code directly on error.
|
||||
if (fp == NULL) {
|
||||
if (fp == nullptr) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
@@ -60,11 +52,7 @@ int ftrylockfile(FILE* fp) {
|
||||
}
|
||||
|
||||
void funlockfile(FILE* fp) {
|
||||
if (!__sdidinit) {
|
||||
__sinit();
|
||||
}
|
||||
|
||||
if (fp != NULL) {
|
||||
if (fp != nullptr) {
|
||||
pthread_mutex_unlock(&_FLOCK(fp));
|
||||
}
|
||||
}
|
||||
|
@@ -25,19 +25,16 @@
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
extern int __ioctl(int, int, void *);
|
||||
extern "C" int __ioctl(int, int, void *);
|
||||
|
||||
int ioctl(int fd, int request, ...)
|
||||
{
|
||||
va_list ap;
|
||||
void * arg;
|
||||
|
||||
va_start(ap, request);
|
||||
arg = va_arg(ap, void *);
|
||||
va_end(ap);
|
||||
|
||||
return __ioctl(fd, request, arg);
|
||||
int ioctl(int fd, int request, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, request);
|
||||
void* arg = va_arg(ap, void*);
|
||||
va_end(ap);
|
||||
return __ioctl(fd, request, arg);
|
||||
}
|
||||
|
@@ -79,6 +79,10 @@ void __libc_init_main_thread(KernelArgumentBlock& args) {
|
||||
|
||||
static pthread_internal_t main_thread;
|
||||
|
||||
// The x86 -fstack-protector implementation uses TLS, so make sure that's
|
||||
// set up before we call any function that might get a stack check inserted.
|
||||
__set_tls(main_thread.tls);
|
||||
|
||||
// Tell the kernel to clear our tid field when we exit, so we're like any other pthread.
|
||||
// As a side-effect, this tells us our pid (which is the same as the main thread's tid).
|
||||
main_thread.tid = __set_tid_address(&main_thread.tid);
|
||||
@@ -97,7 +101,6 @@ void __libc_init_main_thread(KernelArgumentBlock& args) {
|
||||
|
||||
__init_thread(&main_thread);
|
||||
__init_tls(&main_thread);
|
||||
__set_tls(main_thread.tls);
|
||||
|
||||
// Store a pointer to the kernel argument block in a TLS slot to be
|
||||
// picked up by the libc constructor.
|
||||
@@ -110,6 +113,7 @@ void __libc_init_globals(KernelArgumentBlock& args) {
|
||||
// Initialize libc globals that are needed in both the linker and in libc.
|
||||
// In dynamic binaries, this is run at least twice for different copies of the
|
||||
// globals, once for the linker's copy and once for the one in libc.so.
|
||||
__libc_auxv = args.auxv;
|
||||
__libc_globals.initialize();
|
||||
__libc_globals.mutate([&args](libc_globals* globals) {
|
||||
__libc_init_vdso(globals, args);
|
||||
@@ -121,7 +125,6 @@ void __libc_init_common(KernelArgumentBlock& args) {
|
||||
// Initialize various globals.
|
||||
environ = args.envp;
|
||||
errno = 0;
|
||||
__libc_auxv = args.auxv;
|
||||
__progname = args.argv[0] ? args.argv[0] : "<unknown>";
|
||||
__abort_message_ptr = args.abort_message_ptr;
|
||||
|
||||
@@ -245,7 +248,11 @@ static bool __is_valid_environment_variable(const char* name) {
|
||||
}
|
||||
|
||||
static bool __is_unsafe_environment_variable(const char* name) {
|
||||
// None of these should be allowed in setuid programs.
|
||||
// None of these should be allowed when the AT_SECURE auxv
|
||||
// flag is set. This flag is set to inform userspace that a
|
||||
// security transition has occurred, for example, as a result
|
||||
// of executing a setuid program or the result of an SELinux
|
||||
// security transition.
|
||||
static constexpr const char* UNSAFE_VARIABLE_NAMES[] = {
|
||||
"GCONV_PATH",
|
||||
"GETCONF_DIR",
|
||||
|
@@ -31,6 +31,7 @@
|
||||
|
||||
#include <android/set_abort_message.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
@@ -46,6 +47,9 @@
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
|
||||
#include <sys/_system_properties.h>
|
||||
|
||||
static pthread_mutex_t g_abort_msg_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
__LIBC_HIDDEN__ abort_msg_t** __abort_message_ptr; // Accessible to __libc_init_common.
|
||||
@@ -481,6 +485,64 @@ static int __libc_open_log_socket() {
|
||||
return log_fd;
|
||||
}
|
||||
|
||||
struct cache {
|
||||
const prop_info* pinfo;
|
||||
uint32_t serial;
|
||||
char c;
|
||||
};
|
||||
|
||||
static void refresh_cache(struct cache *cache, const char *key)
|
||||
{
|
||||
if (!cache->pinfo) {
|
||||
cache->pinfo = __system_property_find(key);
|
||||
if (!cache->pinfo) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
uint32_t serial = __system_property_serial(cache->pinfo);
|
||||
if (serial == cache->serial) {
|
||||
return;
|
||||
}
|
||||
cache->serial = serial;
|
||||
|
||||
char buf[PROP_VALUE_MAX];
|
||||
__system_property_read(cache->pinfo, 0, buf);
|
||||
cache->c = buf[0];
|
||||
}
|
||||
|
||||
// Timestamp state generally remains constant, since a change is
|
||||
// rare, we can accept a trylock failure gracefully.
|
||||
static pthread_mutex_t lock_clockid = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static clockid_t __android_log_clockid()
|
||||
{
|
||||
static struct cache r_time_cache = { NULL, static_cast<uint32_t>(-1), 0 };
|
||||
static struct cache p_time_cache = { NULL, static_cast<uint32_t>(-1), 0 };
|
||||
char c;
|
||||
|
||||
if (pthread_mutex_trylock(&lock_clockid)) {
|
||||
// We are willing to accept some race in this context
|
||||
if (!(c = p_time_cache.c)) {
|
||||
c = r_time_cache.c;
|
||||
}
|
||||
} else {
|
||||
static uint32_t serial;
|
||||
uint32_t current_serial = __system_property_area_serial();
|
||||
if (current_serial != serial) {
|
||||
refresh_cache(&r_time_cache, "ro.logd.timestamp");
|
||||
refresh_cache(&p_time_cache, "persist.logd.timestamp");
|
||||
serial = current_serial;
|
||||
}
|
||||
if (!(c = p_time_cache.c)) {
|
||||
c = r_time_cache.c;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&lock_clockid);
|
||||
}
|
||||
|
||||
return (tolower(c) == 'm') ? CLOCK_MONOTONIC : CLOCK_REALTIME;
|
||||
}
|
||||
|
||||
struct log_time { // Wire format
|
||||
uint32_t tv_sec;
|
||||
uint32_t tv_nsec;
|
||||
@@ -501,7 +563,7 @@ static int __libc_write_log(int priority, const char* tag, const char* msg) {
|
||||
vec[1].iov_base = &tid;
|
||||
vec[1].iov_len = sizeof(tid);
|
||||
timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
clock_gettime(__android_log_clockid(), &ts);
|
||||
log_time realtime_ts;
|
||||
realtime_ts.tv_sec = ts.tv_sec;
|
||||
realtime_ts.tv_nsec = ts.tv_nsec;
|
||||
@@ -544,7 +606,7 @@ static int __libc_android_log_event(int32_t tag, char type, const void* payload,
|
||||
vec[1].iov_base = &tid;
|
||||
vec[1].iov_len = sizeof(tid);
|
||||
timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
clock_gettime(__android_log_clockid(), &ts);
|
||||
log_time realtime_ts;
|
||||
realtime_ts.tv_sec = ts.tv_sec;
|
||||
realtime_ts.tv_nsec = ts.tv_nsec;
|
||||
|
@@ -27,6 +27,7 @@
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
@@ -48,15 +49,19 @@ void* mmap64(void* addr, size_t size, int prot, int flags, int fd, off64_t offse
|
||||
|
||||
// prevent allocations large enough for `end - start` to overflow
|
||||
size_t rounded = BIONIC_ALIGN(size, PAGE_SIZE);
|
||||
if (rounded < size || size > PTRDIFF_MAX) {
|
||||
if (rounded < size || rounded > PTRDIFF_MAX) {
|
||||
errno = ENOMEM;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
bool is_private_anonymous = (flags & (MAP_PRIVATE | MAP_ANONYMOUS)) != 0;
|
||||
bool is_private_anonymous =
|
||||
(flags & (MAP_PRIVATE | MAP_ANONYMOUS)) == (MAP_PRIVATE | MAP_ANONYMOUS);
|
||||
bool is_stack_or_grows_down = (flags & (MAP_STACK | MAP_GROWSDOWN)) != 0;
|
||||
|
||||
void* result = __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
|
||||
|
||||
if (result != MAP_FAILED && kernel_has_MADV_MERGEABLE && is_private_anonymous) {
|
||||
if (result != MAP_FAILED && kernel_has_MADV_MERGEABLE &&
|
||||
is_private_anonymous && !is_stack_or_grows_down) {
|
||||
ErrnoRestorer errno_restorer;
|
||||
int rc = madvise(result, size, MADV_MERGEABLE);
|
||||
if (rc == -1 && errno == EINVAL) {
|
||||
|
57
libc/bionic/mremap.cpp
Normal file
57
libc/bionic/mremap.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "private/bionic_macros.h"
|
||||
|
||||
extern "C" void* ___mremap(void*, size_t, size_t, int, void*);
|
||||
|
||||
void* mremap(void* old_address, size_t old_size, size_t new_size, int flags, ...) {
|
||||
// prevent allocations large enough for `end - start` to overflow
|
||||
size_t rounded = BIONIC_ALIGN(new_size, PAGE_SIZE);
|
||||
if (rounded < new_size || rounded > PTRDIFF_MAX) {
|
||||
errno = ENOMEM;
|
||||
return MAP_FAILED;
|
||||
}
|
||||
|
||||
void* new_address = nullptr;
|
||||
// The optional argument is only valid if the MREMAP_FIXED flag is set,
|
||||
// so we assume it's not present otherwise.
|
||||
if ((flags & MREMAP_FIXED) != 0) {
|
||||
va_list ap;
|
||||
va_start(ap, flags);
|
||||
new_address = va_arg(ap, void*);
|
||||
va_end(ap);
|
||||
}
|
||||
return ___mremap(old_address, old_size, new_size, flags, new_address);
|
||||
}
|
@@ -47,6 +47,8 @@
|
||||
|
||||
#include "private/libc_logging.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
// Brillo doesn't need to support any legacy cruft.
|
||||
#if !defined(__BRILLO__)
|
||||
|
||||
@@ -55,29 +57,27 @@
|
||||
|
||||
// These were accidentally declared in <unistd.h> because we stupidly used to inline
|
||||
// getpagesize() and __getpageshift(). Needed for backwards compatibility with old NDK apps.
|
||||
extern "C" {
|
||||
unsigned int __page_size = PAGE_SIZE;
|
||||
unsigned int __page_shift = 12;
|
||||
}
|
||||
unsigned int __page_size = PAGE_SIZE;
|
||||
unsigned int __page_shift = 12;
|
||||
|
||||
// TODO: remove this backward compatibility hack (for jb-mr1 strace binaries).
|
||||
extern "C" pid_t __wait4(pid_t pid, int* status, int options, struct rusage* rusage) {
|
||||
pid_t __wait4(pid_t pid, int* status, int options, struct rusage* rusage) {
|
||||
return wait4(pid, status, options, rusage);
|
||||
}
|
||||
|
||||
// TODO: does anything still need this?
|
||||
extern "C" int __open() {
|
||||
int __open() {
|
||||
abort();
|
||||
}
|
||||
|
||||
// TODO: does anything still need this?
|
||||
extern "C" void** __get_tls() {
|
||||
void** __get_tls() {
|
||||
#include "private/__get_tls.h"
|
||||
return __get_tls();
|
||||
}
|
||||
|
||||
// This non-standard function was in our <string.h> for some reason.
|
||||
extern "C" void memswap(void* m1, void* m2, size_t n) {
|
||||
void memswap(void* m1, void* m2, size_t n) {
|
||||
char* p = reinterpret_cast<char*>(m1);
|
||||
char* p_end = p + n;
|
||||
char* q = reinterpret_cast<char*>(m2);
|
||||
@@ -90,13 +90,13 @@ extern "C" void memswap(void* m1, void* m2, size_t n) {
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int pthread_attr_setstackaddr(pthread_attr_t*, void*) {
|
||||
int pthread_attr_setstackaddr(pthread_attr_t*, void*) {
|
||||
// This was removed from POSIX.1-2008, and is not implemented on bionic.
|
||||
// Needed for ABI compatibility with the NDK.
|
||||
return ENOSYS;
|
||||
}
|
||||
|
||||
extern "C" int pthread_attr_getstackaddr(const pthread_attr_t* attr, void** stack_addr) {
|
||||
int pthread_attr_getstackaddr(const pthread_attr_t* attr, void** stack_addr) {
|
||||
// This was removed from POSIX.1-2008.
|
||||
// Needed for ABI compatibility with the NDK.
|
||||
*stack_addr = (char*)attr->stack_base + attr->stack_size;
|
||||
@@ -104,7 +104,7 @@ extern "C" int pthread_attr_getstackaddr(const pthread_attr_t* attr, void** stac
|
||||
}
|
||||
|
||||
// Non-standard cruft that should only ever have been in system/core/toolbox.
|
||||
extern "C" char* strtotimeval(const char* str, struct timeval* ts) {
|
||||
char* strtotimeval(const char* str, struct timeval* ts) {
|
||||
char* s;
|
||||
ts->tv_sec = strtoumax(str, &s, 10);
|
||||
|
||||
@@ -146,7 +146,7 @@ static inline int digitval(int ch) {
|
||||
}
|
||||
|
||||
// This non-standard function was in our <inttypes.h> for some reason.
|
||||
extern "C" uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n) {
|
||||
uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n) {
|
||||
const unsigned char* p = (const unsigned char *)nptr;
|
||||
const unsigned char* end = p + n;
|
||||
int minus = 0;
|
||||
@@ -194,12 +194,12 @@ extern "C" uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_
|
||||
}
|
||||
|
||||
// This non-standard function was in our <inttypes.h> for some reason.
|
||||
extern "C" intmax_t strntoimax(const char* nptr, char** endptr, int base, size_t n) {
|
||||
intmax_t strntoimax(const char* nptr, char** endptr, int base, size_t n) {
|
||||
return (intmax_t) strntoumax(nptr, endptr, base, n);
|
||||
}
|
||||
|
||||
// POSIX calls this dprintf, but LP32 Android had fdprintf instead.
|
||||
extern "C" int fdprintf(int fd, const char* fmt, ...) {
|
||||
int fdprintf(int fd, const char* fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
int rc = vdprintf(fd, fmt, ap);
|
||||
@@ -208,7 +208,7 @@ extern "C" int fdprintf(int fd, const char* fmt, ...) {
|
||||
}
|
||||
|
||||
// POSIX calls this vdprintf, but LP32 Android had fdprintf instead.
|
||||
extern "C" int vfdprintf(int fd, const char* fmt, va_list ap) {
|
||||
int vfdprintf(int fd, const char* fmt, va_list ap) {
|
||||
return vdprintf(fd, fmt, ap);
|
||||
}
|
||||
|
||||
@@ -219,64 +219,64 @@ extern "C" int vfdprintf(int fd, const char* fmt, va_list ap) {
|
||||
#undef __futex_wait
|
||||
|
||||
// This used to be in <sys/atomics.h>.
|
||||
extern "C" int __futex_wake(volatile void* ftx, int count) {
|
||||
int __futex_wake(volatile void* ftx, int count) {
|
||||
return __real_futex_wake(ftx, count);
|
||||
}
|
||||
|
||||
// This used to be in <sys/atomics.h>.
|
||||
extern "C" int __futex_wait(volatile void* ftx, int value, const struct timespec* timeout) {
|
||||
int __futex_wait(volatile void* ftx, int value, const struct timespec* timeout) {
|
||||
return __real_futex_wait(ftx, value, timeout);
|
||||
}
|
||||
|
||||
// Unity's libmono uses this.
|
||||
extern "C" int tkill(pid_t tid, int sig) {
|
||||
int tkill(pid_t tid, int sig) {
|
||||
return syscall(__NR_tkill, tid, sig);
|
||||
}
|
||||
|
||||
// This was removed from POSIX 2008.
|
||||
extern "C" wchar_t* wcswcs(wchar_t* haystack, wchar_t* needle) {
|
||||
wchar_t* wcswcs(wchar_t* haystack, wchar_t* needle) {
|
||||
return wcsstr(haystack, needle);
|
||||
}
|
||||
|
||||
// This was removed from POSIX 2008.
|
||||
extern "C" sighandler_t bsd_signal(int signum, sighandler_t handler) {
|
||||
sighandler_t bsd_signal(int signum, sighandler_t handler) {
|
||||
return signal(signum, handler);
|
||||
}
|
||||
|
||||
#if !defined(__i386__)
|
||||
// This was removed from POSIX 2008.
|
||||
#undef bcopy
|
||||
extern "C" void bcopy(const void* src, void* dst, size_t n) {
|
||||
memcpy(dst, src, n);
|
||||
void bcopy(const void* src, void* dst, size_t n) {
|
||||
memmove(dst, src, n);
|
||||
}
|
||||
#else
|
||||
// x86 has an assembler implementation.
|
||||
#endif
|
||||
|
||||
// sysv_signal() was never in POSIX.
|
||||
extern sighandler_t _signal(int signum, sighandler_t handler, int flags);
|
||||
extern "C" sighandler_t sysv_signal(int signum, sighandler_t handler) {
|
||||
extern "C++" sighandler_t _signal(int signum, sighandler_t handler, int flags);
|
||||
sighandler_t sysv_signal(int signum, sighandler_t handler) {
|
||||
return _signal(signum, handler, SA_RESETHAND);
|
||||
}
|
||||
|
||||
// This is a system call that was never in POSIX. Use readdir(3) instead.
|
||||
extern "C" int __getdents64(unsigned int, dirent*, unsigned int);
|
||||
extern "C" int getdents(unsigned int fd, dirent* dirp, unsigned int count) {
|
||||
int __getdents64(unsigned int, dirent*, unsigned int);
|
||||
int getdents(unsigned int fd, dirent* dirp, unsigned int count) {
|
||||
return __getdents64(fd, dirp, count);
|
||||
}
|
||||
|
||||
// This is a BSDism that we never implemented correctly. Used by Firefox.
|
||||
extern "C" int issetugid() {
|
||||
int issetugid() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This was removed from POSIX 2004.
|
||||
extern "C" pid_t wait3(int* status, int options, struct rusage* rusage) {
|
||||
pid_t wait3(int* status, int options, struct rusage* rusage) {
|
||||
return wait4(-1, status, options, rusage);
|
||||
}
|
||||
|
||||
// This was removed from POSIX 2004.
|
||||
extern "C" int getdtablesize() {
|
||||
int getdtablesize() {
|
||||
struct rlimit r;
|
||||
|
||||
if (getrlimit(RLIMIT_NOFILE, &r) < 0) {
|
||||
@@ -286,6 +286,10 @@ extern "C" int getdtablesize() {
|
||||
return r.rlim_cur;
|
||||
}
|
||||
|
||||
// A leaked BSD stdio implementation detail that's now a no-op.
|
||||
void __sinit() {}
|
||||
int __sdidinit = 1;
|
||||
|
||||
// Only used by ftime, which was removed from POSIX 2008.
|
||||
struct timeb {
|
||||
time_t time;
|
||||
@@ -295,7 +299,7 @@ struct timeb {
|
||||
};
|
||||
|
||||
// This was removed from POSIX 2008.
|
||||
extern "C" int ftime(struct timeb* tb) {
|
||||
int ftime(struct timeb* tb) {
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
|
||||
@@ -317,35 +321,35 @@ extern "C" int ftime(struct timeb* tb) {
|
||||
}
|
||||
|
||||
// This was removed from POSIX 2008.
|
||||
extern "C" char* index(const char* str, int ch) {
|
||||
char* index(const char* str, int ch) {
|
||||
return strchr(str, ch);
|
||||
}
|
||||
|
||||
// This was removed from BSD.
|
||||
extern "C" void arc4random_stir(void) {
|
||||
void arc4random_stir(void) {
|
||||
// The current implementation stirs itself as needed.
|
||||
}
|
||||
|
||||
// This was removed from BSD.
|
||||
extern "C" void arc4random_addrandom(unsigned char*, int) {
|
||||
void arc4random_addrandom(unsigned char*, int) {
|
||||
// The current implementation adds randomness as needed.
|
||||
}
|
||||
|
||||
// Old versions of the NDK did not export malloc_usable_size, but did
|
||||
// export dlmalloc_usable_size. We are moving away from dlmalloc in L
|
||||
// so make this call malloc_usable_size.
|
||||
extern "C" size_t dlmalloc_usable_size(void* ptr) {
|
||||
size_t dlmalloc_usable_size(void* ptr) {
|
||||
return malloc_usable_size(ptr);
|
||||
}
|
||||
|
||||
// In L we added a public pthread_gettid_np, but some apps were using the private API.
|
||||
extern "C" pid_t __pthread_gettid(pthread_t t) {
|
||||
pid_t __pthread_gettid(pthread_t t) {
|
||||
return pthread_gettid_np(t);
|
||||
}
|
||||
|
||||
// Older versions of apportable used dlmalloc directly instead of malloc,
|
||||
// so export this compatibility shim that simply calls malloc.
|
||||
extern "C" void* dlmalloc(size_t size) {
|
||||
void* dlmalloc(size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
@@ -353,13 +357,13 @@ extern "C" void* dlmalloc(size_t size) {
|
||||
#include "pthread_internal.h"
|
||||
#undef __get_thread
|
||||
// Various third-party apps contain a backport of our pthread_rwlock implementation that uses this.
|
||||
extern "C" pthread_internal_t* __get_thread() {
|
||||
pthread_internal_t* __get_thread() {
|
||||
return __real_get_thread();
|
||||
}
|
||||
|
||||
// This one exists only for the LP32 NDK and is not present anywhere else.
|
||||
extern "C" long __set_errno_internal(int);
|
||||
extern "C" long __set_errno(int n) {
|
||||
extern long __set_errno_internal(int);
|
||||
long __set_errno(int n) {
|
||||
return __set_errno_internal(n);
|
||||
}
|
||||
|
||||
@@ -367,25 +371,27 @@ extern "C" long __set_errno(int n) {
|
||||
|
||||
// This was never implemented in bionic, only needed for ABI compatibility with the NDK.
|
||||
// In the M time frame, over 1000 apps have a reference to this!
|
||||
extern "C" void endpwent() { }
|
||||
void endpwent() { }
|
||||
|
||||
// Since dlmalloc_inspect_all and dlmalloc_trim are exported for systems
|
||||
// that use dlmalloc, be consistent and export them everywhere.
|
||||
#if defined(USE_JEMALLOC)
|
||||
extern "C" void dlmalloc_inspect_all(void (*)(void*, void*, size_t, void*), void*) {
|
||||
void dlmalloc_inspect_all(void (*)(void*, void*, size_t, void*), void*) {
|
||||
}
|
||||
extern "C" int dlmalloc_trim(size_t) {
|
||||
int dlmalloc_trim(size_t) {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
extern "C" void dlmalloc_inspect_all_real(void (*)(void*, void*, size_t, void*), void*);
|
||||
extern "C" void dlmalloc_inspect_all(void (*handler)(void*, void*, size_t, void*), void* arg) {
|
||||
void dlmalloc_inspect_all_real(void (*)(void*, void*, size_t, void*), void*);
|
||||
void dlmalloc_inspect_all(void (*handler)(void*, void*, size_t, void*), void* arg) {
|
||||
dlmalloc_inspect_all_real(handler, arg);
|
||||
}
|
||||
extern "C" int dlmalloc_trim_real(size_t);
|
||||
extern "C" int dlmalloc_trim(size_t pad) {
|
||||
int dlmalloc_trim_real(size_t);
|
||||
int dlmalloc_trim(size_t pad) {
|
||||
return dlmalloc_trim_real(pad);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // !defined(__BRILLO__)
|
||||
|
||||
} // extern "C"
|
||||
|
@@ -45,7 +45,7 @@ struct atfork_t {
|
||||
|
||||
class atfork_list_t {
|
||||
public:
|
||||
atfork_list_t() : first_(nullptr), last_(nullptr) {}
|
||||
constexpr atfork_list_t() : first_(nullptr), last_(nullptr) {}
|
||||
|
||||
template<typename F>
|
||||
void walk_forward(F f) {
|
||||
|
183
libc/bionic/pthread_barrier.cpp
Normal file
183
libc/bionic/pthread_barrier.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "private/bionic_futex.h"
|
||||
|
||||
int pthread_barrierattr_init(pthread_barrierattr_t* attr) {
|
||||
*attr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_barrierattr_destroy(pthread_barrierattr_t* attr) {
|
||||
*attr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_barrierattr_getpshared(pthread_barrierattr_t* attr, int* pshared) {
|
||||
*pshared = (*attr & 1) ? PTHREAD_PROCESS_SHARED : PTHREAD_PROCESS_PRIVATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_barrierattr_setpshared(pthread_barrierattr_t* attr, int pshared) {
|
||||
if (pshared == PTHREAD_PROCESS_SHARED) {
|
||||
*attr |= 1;
|
||||
} else {
|
||||
*attr &= ~1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum BarrierState {
|
||||
WAIT,
|
||||
RELEASE,
|
||||
};
|
||||
|
||||
struct pthread_barrier_internal_t {
|
||||
// One barrier can be used for unlimited number of cycles. In each cycle, [init_count]
|
||||
// threads must call pthread_barrier_wait() before any of them successfully return from
|
||||
// the call. It is undefined behavior if there are more than [init_count] threads call
|
||||
// pthread_barrier_wait() in one cycle.
|
||||
uint32_t init_count;
|
||||
// Barrier state. It is WAIT if waiting for more threads to enter the barrier in this cycle,
|
||||
// otherwise threads are leaving the barrier.
|
||||
_Atomic(BarrierState) state;
|
||||
// Number of threads having entered but not left the barrier in this cycle.
|
||||
atomic_uint wait_count;
|
||||
// Whether the barrier is shared across processes.
|
||||
bool pshared;
|
||||
uint32_t __reserved[4];
|
||||
};
|
||||
|
||||
static_assert(sizeof(pthread_barrier_t) == sizeof(pthread_barrier_internal_t),
|
||||
"pthread_barrier_t should actually be pthread_barrier_internal_t in implementation."
|
||||
);
|
||||
|
||||
static_assert(alignof(pthread_barrier_t) >= 4,
|
||||
"pthread_barrier_t should fulfill the alignment of pthread_barrier_internal_t.");
|
||||
|
||||
static inline pthread_barrier_internal_t* __get_internal_barrier(pthread_barrier_t* barrier) {
|
||||
return reinterpret_cast<pthread_barrier_internal_t*>(barrier);
|
||||
}
|
||||
|
||||
int pthread_barrier_init(pthread_barrier_t* barrier_interface, const pthread_barrierattr_t* attr,
|
||||
unsigned count) {
|
||||
pthread_barrier_internal_t* barrier = __get_internal_barrier(barrier_interface);
|
||||
if (count == 0) {
|
||||
return EINVAL;
|
||||
}
|
||||
barrier->init_count = count;
|
||||
atomic_init(&barrier->state, WAIT);
|
||||
atomic_init(&barrier->wait_count, 0);
|
||||
barrier->pshared = false;
|
||||
if (attr != nullptr && (*attr & 1)) {
|
||||
barrier->pshared = true;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// According to POSIX standard, pthread_barrier_wait() synchronizes memory between participating
|
||||
// threads. It means all memory operations made by participating threads before calling
|
||||
// pthread_barrier_wait() can be seen by all participating threads after the function call.
|
||||
// We establish this by making a happens-before relation between all threads entering the barrier
|
||||
// with the last thread entering the barrier, and a happens-before relation between the last
|
||||
// thread entering the barrier with all threads leaving the barrier.
|
||||
int pthread_barrier_wait(pthread_barrier_t* barrier_interface) {
|
||||
pthread_barrier_internal_t* barrier = __get_internal_barrier(barrier_interface);
|
||||
|
||||
// Wait until all threads for the previous cycle have left the barrier. This is needed
|
||||
// as a participating thread can call pthread_barrier_wait() again before other
|
||||
// threads have left the barrier. Use acquire operation here to synchronize with
|
||||
// the last thread leaving the previous cycle, so we can read correct wait_count below.
|
||||
while(atomic_load_explicit(&barrier->state, memory_order_acquire) == RELEASE) {
|
||||
__futex_wait_ex(&barrier->state, barrier->pshared, RELEASE, false, nullptr);
|
||||
}
|
||||
|
||||
uint32_t prev_wait_count = atomic_load_explicit(&barrier->wait_count, memory_order_relaxed);
|
||||
while (true) {
|
||||
// It happens when there are more than [init_count] threads trying to enter the barrier
|
||||
// at one cycle. We read the POSIX standard as disallowing this, since additional arriving
|
||||
// threads are not synchronized with respect to the barrier reset. We also don't know of
|
||||
// any reasonable cases in which this would be intentional.
|
||||
if (prev_wait_count >= barrier->init_count) {
|
||||
return EINVAL;
|
||||
}
|
||||
// Use memory_order_acq_rel operation here to synchronize between all threads entering
|
||||
// the barrier with the last thread entering the barrier.
|
||||
if (atomic_compare_exchange_weak_explicit(&barrier->wait_count, &prev_wait_count,
|
||||
prev_wait_count + 1u, memory_order_acq_rel,
|
||||
memory_order_relaxed)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int result = 0;
|
||||
if (prev_wait_count + 1 == barrier->init_count) {
|
||||
result = PTHREAD_BARRIER_SERIAL_THREAD;
|
||||
if (prev_wait_count != 0) {
|
||||
// Use release operation here to synchronize between the last thread entering the
|
||||
// barrier with all threads leaving the barrier.
|
||||
atomic_store_explicit(&barrier->state, RELEASE, memory_order_release);
|
||||
__futex_wake_ex(&barrier->state, barrier->pshared, prev_wait_count);
|
||||
}
|
||||
} else {
|
||||
// Use acquire operation here to synchronize between the last thread entering the
|
||||
// barrier with all threads leaving the barrier.
|
||||
while (atomic_load_explicit(&barrier->state, memory_order_acquire) == WAIT) {
|
||||
__futex_wait_ex(&barrier->state, barrier->pshared, WAIT, false, nullptr);
|
||||
}
|
||||
}
|
||||
// Use release operation here to make it not reordered with previous operations.
|
||||
if (atomic_fetch_sub_explicit(&barrier->wait_count, 1, memory_order_release) == 1) {
|
||||
// Use release operation here to synchronize with threads entering the barrier for
|
||||
// the next cycle, or the thread calling pthread_barrier_destroy().
|
||||
atomic_store_explicit(&barrier->state, WAIT, memory_order_release);
|
||||
__futex_wake_ex(&barrier->state, barrier->pshared, barrier->init_count);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int pthread_barrier_destroy(pthread_barrier_t* barrier_interface) {
|
||||
pthread_barrier_internal_t* barrier = __get_internal_barrier(barrier_interface);
|
||||
if (barrier->init_count == 0) {
|
||||
return EINVAL;
|
||||
}
|
||||
// Use acquire operation here to synchronize with the last thread leaving the barrier.
|
||||
// So we can read correct wait_count below.
|
||||
while (atomic_load_explicit(&barrier->state, memory_order_acquire) == RELEASE) {
|
||||
__futex_wait_ex(&barrier->state, barrier->pshared, RELEASE, false, nullptr);
|
||||
}
|
||||
if (atomic_load_explicit(&barrier->wait_count, memory_order_relaxed) != 0) {
|
||||
return EBUSY;
|
||||
}
|
||||
barrier->init_count = 0;
|
||||
return 0;
|
||||
}
|
@@ -111,8 +111,8 @@ struct pthread_cond_internal_t {
|
||||
return COND_IS_SHARED(atomic_load_explicit(&state, memory_order_relaxed));
|
||||
}
|
||||
|
||||
int get_clock() {
|
||||
return COND_GET_CLOCK(atomic_load_explicit(&state, memory_order_relaxed));
|
||||
bool use_realtime_clock() {
|
||||
return COND_GET_CLOCK(atomic_load_explicit(&state, memory_order_relaxed)) == CLOCK_REALTIME;
|
||||
}
|
||||
|
||||
#if defined(__LP64__)
|
||||
@@ -170,12 +170,17 @@ static int __pthread_cond_pulse(pthread_cond_internal_t* cond, int thread_count)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __pthread_cond_timedwait_relative(pthread_cond_internal_t* cond, pthread_mutex_t* mutex,
|
||||
const timespec* rel_timeout_or_null) {
|
||||
unsigned int old_state = atomic_load_explicit(&cond->state, memory_order_relaxed);
|
||||
static int __pthread_cond_timedwait(pthread_cond_internal_t* cond, pthread_mutex_t* mutex,
|
||||
bool use_realtime_clock, const timespec* abs_timeout_or_null) {
|
||||
int result = check_timespec(abs_timeout_or_null);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned int old_state = atomic_load_explicit(&cond->state, memory_order_relaxed);
|
||||
pthread_mutex_unlock(mutex);
|
||||
int status = __futex_wait_ex(&cond->state, cond->process_shared(), old_state, rel_timeout_or_null);
|
||||
int status = __futex_wait_ex(&cond->state, cond->process_shared(), old_state,
|
||||
use_realtime_clock, abs_timeout_or_null);
|
||||
pthread_mutex_lock(mutex);
|
||||
|
||||
if (status == -ETIMEDOUT) {
|
||||
@@ -184,21 +189,6 @@ static int __pthread_cond_timedwait_relative(pthread_cond_internal_t* cond, pthr
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __pthread_cond_timedwait(pthread_cond_internal_t* cond, pthread_mutex_t* mutex,
|
||||
const timespec* abs_timeout_or_null, clockid_t clock) {
|
||||
timespec ts;
|
||||
timespec* rel_timeout = NULL;
|
||||
|
||||
if (abs_timeout_or_null != NULL) {
|
||||
rel_timeout = &ts;
|
||||
if (!timespec_from_absolute_timespec(*rel_timeout, *abs_timeout_or_null, clock)) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
return __pthread_cond_timedwait_relative(cond, mutex, rel_timeout);
|
||||
}
|
||||
|
||||
int pthread_cond_broadcast(pthread_cond_t* cond_interface) {
|
||||
return __pthread_cond_pulse(__get_internal_cond(cond_interface), INT_MAX);
|
||||
}
|
||||
@@ -209,14 +199,14 @@ int pthread_cond_signal(pthread_cond_t* cond_interface) {
|
||||
|
||||
int pthread_cond_wait(pthread_cond_t* cond_interface, pthread_mutex_t* mutex) {
|
||||
pthread_cond_internal_t* cond = __get_internal_cond(cond_interface);
|
||||
return __pthread_cond_timedwait(cond, mutex, NULL, cond->get_clock());
|
||||
return __pthread_cond_timedwait(cond, mutex, false, nullptr);
|
||||
}
|
||||
|
||||
int pthread_cond_timedwait(pthread_cond_t *cond_interface, pthread_mutex_t * mutex,
|
||||
const timespec *abstime) {
|
||||
|
||||
pthread_cond_internal_t* cond = __get_internal_cond(cond_interface);
|
||||
return __pthread_cond_timedwait(cond, mutex, abstime, cond->get_clock());
|
||||
return __pthread_cond_timedwait(cond, mutex, cond->use_realtime_clock(), abstime);
|
||||
}
|
||||
|
||||
#if !defined(__LP64__)
|
||||
@@ -225,8 +215,7 @@ extern "C" int pthread_cond_timedwait_monotonic(pthread_cond_t* cond_interface,
|
||||
pthread_mutex_t* mutex,
|
||||
const timespec* abs_timeout) {
|
||||
|
||||
return __pthread_cond_timedwait(__get_internal_cond(cond_interface), mutex, abs_timeout,
|
||||
CLOCK_MONOTONIC);
|
||||
return __pthread_cond_timedwait(__get_internal_cond(cond_interface), mutex, false, abs_timeout);
|
||||
}
|
||||
|
||||
extern "C" int pthread_cond_timedwait_monotonic_np(pthread_cond_t* cond_interface,
|
||||
@@ -238,8 +227,13 @@ extern "C" int pthread_cond_timedwait_monotonic_np(pthread_cond_t* cond_interfac
|
||||
extern "C" int pthread_cond_timedwait_relative_np(pthread_cond_t* cond_interface,
|
||||
pthread_mutex_t* mutex,
|
||||
const timespec* rel_timeout) {
|
||||
|
||||
return __pthread_cond_timedwait_relative(__get_internal_cond(cond_interface), mutex, rel_timeout);
|
||||
timespec ts;
|
||||
timespec* abs_timeout = nullptr;
|
||||
if (rel_timeout != nullptr) {
|
||||
absolute_timespec_from_timespec(ts, *rel_timeout, CLOCK_REALTIME);
|
||||
abs_timeout = &ts;
|
||||
}
|
||||
return __pthread_cond_timedwait(__get_internal_cond(cond_interface), mutex, true, abs_timeout);
|
||||
}
|
||||
|
||||
extern "C" int pthread_cond_timeout_np(pthread_cond_t* cond_interface,
|
||||
|
@@ -53,13 +53,6 @@ extern "C" int __isthreaded;
|
||||
|
||||
// This code is used both by each new pthread and the code that initializes the main thread.
|
||||
void __init_tls(pthread_internal_t* thread) {
|
||||
if (thread->mmap_size == 0) {
|
||||
// If the TLS area was not allocated by mmap(), it may not have been cleared to zero.
|
||||
// So assume the worst and zero the TLS area.
|
||||
memset(thread->tls, 0, sizeof(thread->tls));
|
||||
memset(thread->key_data, 0, sizeof(thread->key_data));
|
||||
}
|
||||
|
||||
// Slot 0 must point to itself. The x86 Linux kernel reads the TLS from %fs:0.
|
||||
thread->tls[TLS_SLOT_SELF] = thread->tls;
|
||||
thread->tls[TLS_SLOT_THREAD_ID] = thread;
|
||||
@@ -175,6 +168,11 @@ static int __allocate_thread(pthread_attr_t* attr, pthread_internal_t** threadp,
|
||||
(reinterpret_cast<uintptr_t>(stack_top) - sizeof(pthread_internal_t)) & ~0xf);
|
||||
|
||||
pthread_internal_t* thread = reinterpret_cast<pthread_internal_t*>(stack_top);
|
||||
if (mmap_size == 0) {
|
||||
// If thread was not allocated by mmap(), it may not have been cleared to zero.
|
||||
// So assume the worst and zero it.
|
||||
memset(thread, 0, sizeof(pthread_internal_t));
|
||||
}
|
||||
attr->stack_size = stack_top - reinterpret_cast<uint8_t*>(attr->stack_base);
|
||||
|
||||
thread->mmap_size = mmap_size;
|
||||
|
@@ -52,6 +52,8 @@ enum ThreadJoinState {
|
||||
THREAD_DETACHED
|
||||
};
|
||||
|
||||
struct thread_local_dtor;
|
||||
|
||||
struct pthread_internal_t {
|
||||
struct pthread_internal_t* next;
|
||||
struct pthread_internal_t* prev;
|
||||
@@ -94,6 +96,8 @@ struct pthread_internal_t {
|
||||
|
||||
size_t mmap_size;
|
||||
|
||||
thread_local_dtor* thread_local_dtors;
|
||||
|
||||
void* tls[BIONIC_TLS_SLOTS];
|
||||
|
||||
pthread_key_data_t key_data[BIONIC_PTHREAD_KEY_COUNT];
|
||||
|
@@ -166,11 +166,14 @@ int pthread_mutexattr_getpshared(const pthread_mutexattr_t* attr, int* pshared)
|
||||
#define MUTEX_STATE_BITS_LOCKED_UNCONTENDED MUTEX_STATE_TO_BITS(MUTEX_STATE_LOCKED_UNCONTENDED)
|
||||
#define MUTEX_STATE_BITS_LOCKED_CONTENDED MUTEX_STATE_TO_BITS(MUTEX_STATE_LOCKED_CONTENDED)
|
||||
|
||||
/* return true iff the mutex if locked with no waiters */
|
||||
#define MUTEX_STATE_BITS_IS_LOCKED_UNCONTENDED(v) (((v) & MUTEX_STATE_MASK) == MUTEX_STATE_BITS_LOCKED_UNCONTENDED)
|
||||
// Return true iff the mutex is unlocked.
|
||||
#define MUTEX_STATE_BITS_IS_UNLOCKED(v) (((v) & MUTEX_STATE_MASK) == MUTEX_STATE_BITS_UNLOCKED)
|
||||
|
||||
/* return true iff the mutex if locked with maybe waiters */
|
||||
#define MUTEX_STATE_BITS_IS_LOCKED_CONTENDED(v) (((v) & MUTEX_STATE_MASK) == MUTEX_STATE_BITS_LOCKED_CONTENDED)
|
||||
// Return true iff the mutex is locked with no waiters.
|
||||
#define MUTEX_STATE_BITS_IS_LOCKED_UNCONTENDED(v) (((v) & MUTEX_STATE_MASK) == MUTEX_STATE_BITS_LOCKED_UNCONTENDED)
|
||||
|
||||
// return true iff the mutex is locked with maybe waiters.
|
||||
#define MUTEX_STATE_BITS_IS_LOCKED_CONTENDED(v) (((v) & MUTEX_STATE_MASK) == MUTEX_STATE_BITS_LOCKED_CONTENDED)
|
||||
|
||||
/* used to flip from LOCKED_UNCONTENDED to LOCKED_CONTENDED */
|
||||
#define MUTEX_STATE_BITS_FLIP_CONTENTION(v) ((v) ^ (MUTEX_STATE_BITS_LOCKED_CONTENDED ^ MUTEX_STATE_BITS_LOCKED_UNCONTENDED))
|
||||
@@ -296,11 +299,15 @@ static inline __always_inline int __pthread_normal_mutex_trylock(pthread_mutex_i
|
||||
*/
|
||||
static inline __always_inline int __pthread_normal_mutex_lock(pthread_mutex_internal_t* mutex,
|
||||
uint16_t shared,
|
||||
const timespec* abs_timeout_or_null,
|
||||
clockid_t clock) {
|
||||
bool use_realtime_clock,
|
||||
const timespec* abs_timeout_or_null) {
|
||||
if (__predict_true(__pthread_normal_mutex_trylock(mutex, shared) == 0)) {
|
||||
return 0;
|
||||
}
|
||||
int result = check_timespec(abs_timeout_or_null);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
ScopedTrace trace("Contending for pthread mutex");
|
||||
|
||||
@@ -317,15 +324,8 @@ static inline __always_inline int __pthread_normal_mutex_lock(pthread_mutex_inte
|
||||
// made by other threads visible to the current CPU.
|
||||
while (atomic_exchange_explicit(&mutex->state, locked_contended,
|
||||
memory_order_acquire) != unlocked) {
|
||||
timespec ts;
|
||||
timespec* rel_timeout = NULL;
|
||||
if (abs_timeout_or_null != NULL) {
|
||||
rel_timeout = &ts;
|
||||
if (!timespec_from_absolute_timespec(*rel_timeout, *abs_timeout_or_null, clock)) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
if (__futex_wait_ex(&mutex->state, shared, locked_contended, rel_timeout) == -ETIMEDOUT) {
|
||||
if (__futex_wait_ex(&mutex->state, shared, locked_contended, use_realtime_clock,
|
||||
abs_timeout_or_null) == -ETIMEDOUT) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
@@ -396,14 +396,15 @@ static inline __always_inline int __recursive_or_errorcheck_mutex_wait(
|
||||
pthread_mutex_internal_t* mutex,
|
||||
uint16_t shared,
|
||||
uint16_t old_state,
|
||||
const timespec* rel_timeout) {
|
||||
bool use_realtime_clock,
|
||||
const timespec* abs_timeout) {
|
||||
// __futex_wait always waits on a 32-bit value. But state is 16-bit. For a normal mutex, the owner_tid
|
||||
// field in mutex is not used. On 64-bit devices, the __pad field in mutex is not used.
|
||||
// But when a recursive or errorcheck mutex is used on 32-bit devices, we need to add the
|
||||
// owner_tid value in the value argument for __futex_wait, otherwise we may always get EAGAIN error.
|
||||
|
||||
#if defined(__LP64__)
|
||||
return __futex_wait_ex(&mutex->state, shared, old_state, rel_timeout);
|
||||
return __futex_wait_ex(&mutex->state, shared, old_state, use_realtime_clock, abs_timeout);
|
||||
|
||||
#else
|
||||
// This implementation works only when the layout of pthread_mutex_internal_t matches below expectation.
|
||||
@@ -412,19 +413,21 @@ static inline __always_inline int __recursive_or_errorcheck_mutex_wait(
|
||||
static_assert(offsetof(pthread_mutex_internal_t, owner_tid) == 2, "");
|
||||
|
||||
uint32_t owner_tid = atomic_load_explicit(&mutex->owner_tid, memory_order_relaxed);
|
||||
return __futex_wait_ex(&mutex->state, shared, (owner_tid << 16) | old_state, rel_timeout);
|
||||
return __futex_wait_ex(&mutex->state, shared, (owner_tid << 16) | old_state,
|
||||
use_realtime_clock, abs_timeout);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int __pthread_mutex_lock_with_timeout(pthread_mutex_internal_t* mutex,
|
||||
const timespec* abs_timeout_or_null, clockid_t clock) {
|
||||
bool use_realtime_clock,
|
||||
const timespec* abs_timeout_or_null) {
|
||||
uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
|
||||
uint16_t mtype = (old_state & MUTEX_TYPE_MASK);
|
||||
uint16_t shared = (old_state & MUTEX_SHARED_MASK);
|
||||
|
||||
// Handle common case first.
|
||||
if ( __predict_true(mtype == MUTEX_TYPE_BITS_NORMAL) ) {
|
||||
return __pthread_normal_mutex_lock(mutex, shared, abs_timeout_or_null, clock);
|
||||
return __pthread_normal_mutex_lock(mutex, shared, use_realtime_clock, abs_timeout_or_null);
|
||||
}
|
||||
|
||||
// Do we already own this recursive or error-check mutex?
|
||||
@@ -484,16 +487,13 @@ static int __pthread_mutex_lock_with_timeout(pthread_mutex_internal_t* mutex,
|
||||
old_state = new_state;
|
||||
}
|
||||
|
||||
// We are in locked_contended state, sleep until someone wakes us up.
|
||||
timespec ts;
|
||||
timespec* rel_timeout = NULL;
|
||||
if (abs_timeout_or_null != NULL) {
|
||||
rel_timeout = &ts;
|
||||
if (!timespec_from_absolute_timespec(*rel_timeout, *abs_timeout_or_null, clock)) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
int result = check_timespec(abs_timeout_or_null);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
if (__recursive_or_errorcheck_mutex_wait(mutex, shared, old_state, rel_timeout) == -ETIMEDOUT) {
|
||||
// We are in locked_contended state, sleep until someone wakes us up.
|
||||
if (__recursive_or_errorcheck_mutex_wait(mutex, shared, old_state, use_realtime_clock,
|
||||
abs_timeout_or_null) == -ETIMEDOUT) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
|
||||
@@ -518,7 +518,7 @@ int pthread_mutex_lock(pthread_mutex_t* mutex_interface) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return __pthread_mutex_lock_with_timeout(mutex, NULL, 0);
|
||||
return __pthread_mutex_lock_with_timeout(mutex, false, nullptr);
|
||||
}
|
||||
|
||||
int pthread_mutex_unlock(pthread_mutex_t* mutex_interface) {
|
||||
@@ -613,17 +613,12 @@ int pthread_mutex_trylock(pthread_mutex_t* mutex_interface) {
|
||||
|
||||
#if !defined(__LP64__)
|
||||
extern "C" int pthread_mutex_lock_timeout_np(pthread_mutex_t* mutex_interface, unsigned ms) {
|
||||
timespec ts;
|
||||
timespec_from_ms(ts, ms);
|
||||
timespec abs_timeout;
|
||||
clock_gettime(CLOCK_MONOTONIC, &abs_timeout);
|
||||
abs_timeout.tv_sec += ms / 1000;
|
||||
abs_timeout.tv_nsec += (ms % 1000) * 1000000;
|
||||
if (abs_timeout.tv_nsec >= NS_PER_S) {
|
||||
abs_timeout.tv_sec++;
|
||||
abs_timeout.tv_nsec -= NS_PER_S;
|
||||
}
|
||||
|
||||
absolute_timespec_from_timespec(abs_timeout, ts, CLOCK_MONOTONIC);
|
||||
int error = __pthread_mutex_lock_with_timeout(__get_internal_mutex(mutex_interface),
|
||||
&abs_timeout, CLOCK_MONOTONIC);
|
||||
false, &abs_timeout);
|
||||
if (error == ETIMEDOUT) {
|
||||
error = EBUSY;
|
||||
}
|
||||
@@ -633,14 +628,18 @@ extern "C" int pthread_mutex_lock_timeout_np(pthread_mutex_t* mutex_interface, u
|
||||
|
||||
int pthread_mutex_timedlock(pthread_mutex_t* mutex_interface, const timespec* abs_timeout) {
|
||||
return __pthread_mutex_lock_with_timeout(__get_internal_mutex(mutex_interface),
|
||||
abs_timeout, CLOCK_REALTIME);
|
||||
true, abs_timeout);
|
||||
}
|
||||
|
||||
int pthread_mutex_destroy(pthread_mutex_t* mutex_interface) {
|
||||
// Use trylock to ensure that the mutex is valid and not already locked.
|
||||
int error = pthread_mutex_trylock(mutex_interface);
|
||||
if (error != 0) {
|
||||
return error;
|
||||
pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);
|
||||
uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
|
||||
// Store 0xffff to make the mutex unusable. Although POSIX standard says it is undefined
|
||||
// behavior to destroy a locked mutex, we prefer not to change mutex->state in that situation.
|
||||
if (MUTEX_STATE_BITS_IS_UNLOCKED(old_state) &&
|
||||
atomic_compare_exchange_strong_explicit(&mutex->state, &old_state, 0xffff,
|
||||
memory_order_relaxed, memory_order_relaxed)) {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
return EBUSY;
|
||||
}
|
||||
|
@@ -79,7 +79,7 @@ int pthread_once(pthread_once_t* once_control, void (*init_routine)(void)) {
|
||||
}
|
||||
|
||||
// The initialization is underway, wait for its finish.
|
||||
__futex_wait_ex(once_control_ptr, 0, old_value, NULL);
|
||||
__futex_wait_ex(once_control_ptr, 0, old_value, false, nullptr);
|
||||
old_value = atomic_load_explicit(once_control_ptr, memory_order_acquire);
|
||||
}
|
||||
}
|
||||
|
@@ -294,9 +294,13 @@ static int __pthread_rwlock_timedrdlock(pthread_rwlock_internal_t* rwlock,
|
||||
}
|
||||
|
||||
while (true) {
|
||||
int ret = __pthread_rwlock_tryrdlock(rwlock);
|
||||
if (ret == 0 || ret == EAGAIN) {
|
||||
return ret;
|
||||
int result = __pthread_rwlock_tryrdlock(rwlock);
|
||||
if (result == 0 || result == EAGAIN) {
|
||||
return result;
|
||||
}
|
||||
result = check_timespec(abs_timeout_or_null);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int old_state = atomic_load_explicit(&rwlock->state, memory_order_relaxed);
|
||||
@@ -304,16 +308,6 @@ static int __pthread_rwlock_timedrdlock(pthread_rwlock_internal_t* rwlock,
|
||||
continue;
|
||||
}
|
||||
|
||||
timespec ts;
|
||||
timespec* rel_timeout = NULL;
|
||||
|
||||
if (abs_timeout_or_null != NULL) {
|
||||
rel_timeout = &ts;
|
||||
if (!timespec_from_absolute_timespec(*rel_timeout, *abs_timeout_or_null, CLOCK_REALTIME)) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
rwlock->pending_lock.lock();
|
||||
rwlock->pending_reader_count++;
|
||||
|
||||
@@ -327,10 +321,10 @@ static int __pthread_rwlock_timedrdlock(pthread_rwlock_internal_t* rwlock,
|
||||
int old_serial = rwlock->pending_reader_wakeup_serial;
|
||||
rwlock->pending_lock.unlock();
|
||||
|
||||
int futex_ret = 0;
|
||||
int futex_result = 0;
|
||||
if (!__can_acquire_read_lock(old_state, rwlock->writer_nonrecursive_preferred)) {
|
||||
futex_ret = __futex_wait_ex(&rwlock->pending_reader_wakeup_serial, rwlock->pshared,
|
||||
old_serial, rel_timeout);
|
||||
futex_result = __futex_wait_ex(&rwlock->pending_reader_wakeup_serial, rwlock->pshared,
|
||||
old_serial, true, abs_timeout_or_null);
|
||||
}
|
||||
|
||||
rwlock->pending_lock.lock();
|
||||
@@ -341,7 +335,7 @@ static int __pthread_rwlock_timedrdlock(pthread_rwlock_internal_t* rwlock,
|
||||
}
|
||||
rwlock->pending_lock.unlock();
|
||||
|
||||
if (futex_ret == -ETIMEDOUT) {
|
||||
if (futex_result == -ETIMEDOUT) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
@@ -372,9 +366,13 @@ static int __pthread_rwlock_timedwrlock(pthread_rwlock_internal_t* rwlock,
|
||||
return EDEADLK;
|
||||
}
|
||||
while (true) {
|
||||
int ret = __pthread_rwlock_trywrlock(rwlock);
|
||||
if (ret == 0) {
|
||||
return ret;
|
||||
int result = __pthread_rwlock_trywrlock(rwlock);
|
||||
if (result == 0) {
|
||||
return result;
|
||||
}
|
||||
result = check_timespec(abs_timeout_or_null);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int old_state = atomic_load_explicit(&rwlock->state, memory_order_relaxed);
|
||||
@@ -382,16 +380,6 @@ static int __pthread_rwlock_timedwrlock(pthread_rwlock_internal_t* rwlock,
|
||||
continue;
|
||||
}
|
||||
|
||||
timespec ts;
|
||||
timespec* rel_timeout = NULL;
|
||||
|
||||
if (abs_timeout_or_null != NULL) {
|
||||
rel_timeout = &ts;
|
||||
if (!timespec_from_absolute_timespec(*rel_timeout, *abs_timeout_or_null, CLOCK_REALTIME)) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
|
||||
rwlock->pending_lock.lock();
|
||||
rwlock->pending_writer_count++;
|
||||
|
||||
@@ -401,10 +389,10 @@ static int __pthread_rwlock_timedwrlock(pthread_rwlock_internal_t* rwlock,
|
||||
int old_serial = rwlock->pending_writer_wakeup_serial;
|
||||
rwlock->pending_lock.unlock();
|
||||
|
||||
int futex_ret = 0;
|
||||
int futex_result = 0;
|
||||
if (!__can_acquire_write_lock(old_state)) {
|
||||
futex_ret = __futex_wait_ex(&rwlock->pending_writer_wakeup_serial, rwlock->pshared,
|
||||
old_serial, rel_timeout);
|
||||
futex_result = __futex_wait_ex(&rwlock->pending_writer_wakeup_serial, rwlock->pshared,
|
||||
old_serial, true, abs_timeout_or_null);
|
||||
}
|
||||
|
||||
rwlock->pending_lock.lock();
|
||||
@@ -415,7 +403,7 @@ static int __pthread_rwlock_timedwrlock(pthread_rwlock_internal_t* rwlock,
|
||||
}
|
||||
rwlock->pending_lock.unlock();
|
||||
|
||||
if (futex_ret == -ETIMEDOUT) {
|
||||
if (futex_result == -ETIMEDOUT) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
@@ -427,7 +415,7 @@ int pthread_rwlock_rdlock(pthread_rwlock_t* rwlock_interface) {
|
||||
if (__predict_true(__pthread_rwlock_tryrdlock(rwlock) == 0)) {
|
||||
return 0;
|
||||
}
|
||||
return __pthread_rwlock_timedrdlock(rwlock, NULL);
|
||||
return __pthread_rwlock_timedrdlock(rwlock, nullptr);
|
||||
}
|
||||
|
||||
int pthread_rwlock_timedrdlock(pthread_rwlock_t* rwlock_interface, const timespec* abs_timeout) {
|
||||
@@ -446,7 +434,7 @@ int pthread_rwlock_wrlock(pthread_rwlock_t* rwlock_interface) {
|
||||
if (__predict_true(__pthread_rwlock_trywrlock(rwlock) == 0)) {
|
||||
return 0;
|
||||
}
|
||||
return __pthread_rwlock_timedwrlock(rwlock, NULL);
|
||||
return __pthread_rwlock_timedwrlock(rwlock, nullptr);
|
||||
}
|
||||
|
||||
int pthread_rwlock_timedwrlock(pthread_rwlock_t* rwlock_interface, const timespec* abs_timeout) {
|
||||
|
81
libc/bionic/pthread_spinlock.cpp
Normal file
81
libc/bionic/pthread_spinlock.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#include <pthread.h>
|
||||
|
||||
#include "private/bionic_lock.h"
|
||||
|
||||
// User-level spinlocks can be hazardous to battery life on Android.
|
||||
// We implement a simple compromise that behaves mostly like a spinlock,
|
||||
// but prevents excessively long spinning.
|
||||
|
||||
struct pthread_spinlock_internal_t {
|
||||
Lock lock;
|
||||
};
|
||||
|
||||
static_assert(sizeof(pthread_spinlock_t) == sizeof(pthread_spinlock_internal_t),
|
||||
"pthread_spinlock_t should actually be pthread_spinlock_internal_t.");
|
||||
|
||||
static_assert(alignof(pthread_spinlock_t) >= 4,
|
||||
"pthread_spinlock_t should fulfill the alignment of pthread_spinlock_internal_t.");
|
||||
|
||||
static inline pthread_spinlock_internal_t* __get_internal_spinlock(pthread_spinlock_t* lock) {
|
||||
return reinterpret_cast<pthread_spinlock_internal_t*>(lock);
|
||||
}
|
||||
|
||||
int pthread_spin_init(pthread_spinlock_t* lock_interface, int pshared) {
|
||||
pthread_spinlock_internal_t* lock = __get_internal_spinlock(lock_interface);
|
||||
lock->lock.init(pshared);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_spin_destroy(pthread_spinlock_t* lock_interface) {
|
||||
pthread_spinlock_internal_t* lock = __get_internal_spinlock(lock_interface);
|
||||
return lock->lock.trylock() ? 0 : EBUSY;
|
||||
}
|
||||
|
||||
int pthread_spin_trylock(pthread_spinlock_t* lock_interface) {
|
||||
pthread_spinlock_internal_t* lock = __get_internal_spinlock(lock_interface);
|
||||
return lock->lock.trylock() ? 0 : EBUSY;
|
||||
}
|
||||
|
||||
int pthread_spin_lock(pthread_spinlock_t* lock_interface) {
|
||||
pthread_spinlock_internal_t* lock = __get_internal_spinlock(lock_interface);
|
||||
for (int i = 0; i < 10000; ++i) {
|
||||
if (lock->lock.trylock()) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
lock->lock.lock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pthread_spin_unlock(pthread_spinlock_t* lock_interface) {
|
||||
pthread_spinlock_internal_t* lock = __get_internal_spinlock(lock_interface);
|
||||
lock->lock.unlock();
|
||||
return 0;
|
||||
}
|
@@ -220,7 +220,7 @@ int sem_wait(sem_t* sem) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
__futex_wait_ex(sem_count_ptr, shared, shared | SEMCOUNT_MINUS_ONE, NULL);
|
||||
__futex_wait_ex(sem_count_ptr, shared, shared | SEMCOUNT_MINUS_ONE, false, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,36 +235,29 @@ int sem_timedwait(sem_t* sem, const timespec* abs_timeout) {
|
||||
}
|
||||
|
||||
// Check it as per POSIX.
|
||||
if (abs_timeout == NULL || abs_timeout->tv_sec < 0 || abs_timeout->tv_nsec < 0 || abs_timeout->tv_nsec >= NS_PER_S) {
|
||||
errno = EINVAL;
|
||||
int result = check_timespec(abs_timeout);
|
||||
if (result != 0) {
|
||||
errno = result;
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned int shared = SEM_GET_SHARED(sem_count_ptr);
|
||||
|
||||
while (true) {
|
||||
// POSIX mandates CLOCK_REALTIME here.
|
||||
timespec ts;
|
||||
if (!timespec_from_absolute_timespec(ts, *abs_timeout, CLOCK_REALTIME)) {
|
||||
errno = ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Try to grab the semaphore. If the value was 0, this will also change it to -1.
|
||||
if (__sem_dec(sem_count_ptr) > 0) {
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Contention detected. Wait for a wakeup event.
|
||||
int ret = __futex_wait_ex(sem_count_ptr, shared, shared | SEMCOUNT_MINUS_ONE, &ts);
|
||||
int result = __futex_wait_ex(sem_count_ptr, shared, shared | SEMCOUNT_MINUS_ONE, true, abs_timeout);
|
||||
|
||||
// Return in case of timeout or interrupt.
|
||||
if (ret == -ETIMEDOUT || ret == -EINTR) {
|
||||
errno = -ret;
|
||||
if (result == -ETIMEDOUT || result == -EINTR) {
|
||||
errno = -result;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sem_post(sem_t* sem) {
|
||||
|
@@ -25,34 +25,38 @@
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#include <new>
|
||||
#include <stdatomic.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stddef.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <stdatomic.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <new>
|
||||
|
||||
#include <linux/xattr.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/xattr.h>
|
||||
|
||||
#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
|
||||
#include <sys/_system_properties.h>
|
||||
#include <sys/system_properties.h>
|
||||
|
||||
#include "private/bionic_futex.h"
|
||||
#include "private/bionic_lock.h"
|
||||
#include "private/bionic_macros.h"
|
||||
#include "private/libc_logging.h"
|
||||
|
||||
static const char property_service_socket[] = "/dev/socket/" PROP_SERVICE_NAME;
|
||||
|
||||
@@ -112,23 +116,57 @@ private:
|
||||
DISALLOW_COPY_AND_ASSIGN(prop_bt);
|
||||
};
|
||||
|
||||
struct prop_area {
|
||||
uint32_t bytes_used;
|
||||
atomic_uint_least32_t serial;
|
||||
uint32_t magic;
|
||||
uint32_t version;
|
||||
uint32_t reserved[28];
|
||||
char data[0];
|
||||
class prop_area {
|
||||
public:
|
||||
|
||||
prop_area(const uint32_t magic, const uint32_t version) :
|
||||
magic(magic), version(version) {
|
||||
atomic_init(&serial, 0);
|
||||
memset(reserved, 0, sizeof(reserved));
|
||||
magic_(magic), version_(version) {
|
||||
atomic_init(&serial_, 0);
|
||||
memset(reserved_, 0, sizeof(reserved_));
|
||||
// Allocate enough space for the root node.
|
||||
bytes_used = sizeof(prop_bt);
|
||||
bytes_used_ = sizeof(prop_bt);
|
||||
}
|
||||
|
||||
const prop_info *find(const char *name);
|
||||
bool add(const char *name, unsigned int namelen,
|
||||
const char *value, unsigned int valuelen);
|
||||
|
||||
bool foreach(void (*propfn)(const prop_info *pi, void *cookie), void *cookie);
|
||||
|
||||
atomic_uint_least32_t *serial() { return &serial_; }
|
||||
uint32_t magic() const { return magic_; }
|
||||
uint32_t version() const { return version_; }
|
||||
|
||||
private:
|
||||
void *allocate_obj(const size_t size, uint_least32_t *const off);
|
||||
prop_bt *new_prop_bt(const char *name, uint8_t namelen, uint_least32_t *const off);
|
||||
prop_info *new_prop_info(const char *name, uint8_t namelen,
|
||||
const char *value, uint8_t valuelen,
|
||||
uint_least32_t *const off);
|
||||
void *to_prop_obj(uint_least32_t off);
|
||||
prop_bt *to_prop_bt(atomic_uint_least32_t *off_p);
|
||||
prop_info *to_prop_info(atomic_uint_least32_t *off_p);
|
||||
|
||||
prop_bt *root_node();
|
||||
|
||||
prop_bt *find_prop_bt(prop_bt *const bt, const char *name,
|
||||
uint8_t namelen, bool alloc_if_needed);
|
||||
|
||||
const prop_info *find_property(prop_bt *const trie, const char *name,
|
||||
uint8_t namelen, const char *value,
|
||||
uint8_t valuelen, bool alloc_if_needed);
|
||||
|
||||
bool foreach_property(prop_bt *const trie,
|
||||
void (*propfn)(const prop_info *pi, void *cookie),
|
||||
void *cookie);
|
||||
|
||||
uint32_t bytes_used_;
|
||||
atomic_uint_least32_t serial_;
|
||||
uint32_t magic_;
|
||||
uint32_t version_;
|
||||
uint32_t reserved_[28];
|
||||
char data_[0];
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(prop_area);
|
||||
};
|
||||
|
||||
@@ -158,7 +196,7 @@ struct find_nth_cookie {
|
||||
}
|
||||
};
|
||||
|
||||
static char property_filename[PATH_MAX] = PROP_FILENAME;
|
||||
static char property_filename[PROP_FILENAME_MAX] = PROP_FILENAME;
|
||||
static bool compat_mode = false;
|
||||
static size_t pa_data_size;
|
||||
static size_t pa_size;
|
||||
@@ -182,13 +220,12 @@ static int get_fd_from_env(void)
|
||||
return atoi(env);
|
||||
}
|
||||
|
||||
static int map_prop_area_rw()
|
||||
{
|
||||
static prop_area* map_prop_area_rw(const char* filename, const char* context,
|
||||
bool* fsetxattr_failed) {
|
||||
/* dev is a tmpfs that we can use to carve a shared workspace
|
||||
* out of, so let's do that...
|
||||
*/
|
||||
const int fd = open(property_filename,
|
||||
O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC | O_EXCL, 0444);
|
||||
const int fd = open(filename, O_RDWR | O_CREAT | O_NOFOLLOW | O_CLOEXEC | O_EXCL, 0444);
|
||||
|
||||
if (fd < 0) {
|
||||
if (errno == EACCES) {
|
||||
@@ -197,12 +234,31 @@ static int map_prop_area_rw()
|
||||
*/
|
||||
abort();
|
||||
}
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (context) {
|
||||
if (fsetxattr(fd, XATTR_NAME_SELINUX, context, strlen(context) + 1, 0) != 0) {
|
||||
__libc_format_log(ANDROID_LOG_ERROR, "libc",
|
||||
"fsetxattr failed to set context (%s) for \"%s\"", context, filename);
|
||||
/*
|
||||
* fsetxattr() will fail during system properties tests due to selinux policy.
|
||||
* We do not want to create a custom policy for the tester, so we will continue in
|
||||
* this function but set a flag that an error has occurred.
|
||||
* Init, which is the only daemon that should ever call this function will abort
|
||||
* when this error occurs.
|
||||
* Otherwise, the tester will ignore it and continue, albeit without any selinux
|
||||
* property separation.
|
||||
*/
|
||||
if (fsetxattr_failed) {
|
||||
*fsetxattr_failed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ftruncate(fd, PA_SIZE) < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
pa_size = PA_SIZE;
|
||||
@@ -212,29 +268,26 @@ static int map_prop_area_rw()
|
||||
void *const memory_area = mmap(NULL, pa_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (memory_area == MAP_FAILED) {
|
||||
close(fd);
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
prop_area *pa = new(memory_area) prop_area(PROP_AREA_MAGIC, PROP_AREA_VERSION);
|
||||
|
||||
/* plug into the lib property services */
|
||||
__system_property_area__ = pa;
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
return pa;
|
||||
}
|
||||
|
||||
static int map_fd_ro(const int fd) {
|
||||
static prop_area* map_fd_ro(const int fd) {
|
||||
struct stat fd_stat;
|
||||
if (fstat(fd, &fd_stat) < 0) {
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if ((fd_stat.st_uid != 0)
|
||||
|| (fd_stat.st_gid != 0)
|
||||
|| ((fd_stat.st_mode & (S_IWGRP | S_IWOTH)) != 0)
|
||||
|| (fd_stat.st_size < static_cast<off_t>(sizeof(prop_area))) ) {
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
pa_size = fd_stat.st_size;
|
||||
@@ -242,29 +295,28 @@ static int map_fd_ro(const int fd) {
|
||||
|
||||
void* const map_result = mmap(NULL, pa_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (map_result == MAP_FAILED) {
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
prop_area* pa = reinterpret_cast<prop_area*>(map_result);
|
||||
if ((pa->magic != PROP_AREA_MAGIC) || (pa->version != PROP_AREA_VERSION &&
|
||||
pa->version != PROP_AREA_VERSION_COMPAT)) {
|
||||
if ((pa->magic() != PROP_AREA_MAGIC) ||
|
||||
(pa->version() != PROP_AREA_VERSION &&
|
||||
pa->version() != PROP_AREA_VERSION_COMPAT)) {
|
||||
munmap(pa, pa_size);
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (pa->version == PROP_AREA_VERSION_COMPAT) {
|
||||
if (pa->version() == PROP_AREA_VERSION_COMPAT) {
|
||||
compat_mode = true;
|
||||
}
|
||||
|
||||
__system_property_area__ = pa;
|
||||
return 0;
|
||||
return pa;
|
||||
}
|
||||
|
||||
static int map_prop_area()
|
||||
{
|
||||
int fd = open(property_filename, O_CLOEXEC | O_NOFOLLOW | O_RDONLY);
|
||||
static prop_area* map_prop_area(const char* filename, bool is_legacy) {
|
||||
int fd = open(filename, O_CLOEXEC | O_NOFOLLOW | O_RDONLY);
|
||||
bool close_fd = true;
|
||||
if (fd == -1 && errno == ENOENT) {
|
||||
if (fd == -1 && errno == ENOENT && is_legacy) {
|
||||
/*
|
||||
* For backwards compatibility, if the file doesn't
|
||||
* exist, we use the environment to get the file descriptor.
|
||||
@@ -273,16 +325,18 @@ static int map_prop_area()
|
||||
* returns other errors such as ENOMEM or ENFILE, since it
|
||||
* might be possible for an external program to trigger this
|
||||
* condition.
|
||||
* Only do this for the legacy prop file, secured prop files
|
||||
* do not have a backup
|
||||
*/
|
||||
fd = get_fd_from_env();
|
||||
close_fd = false;
|
||||
}
|
||||
|
||||
if (fd < 0) {
|
||||
return -1;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const int map_result = map_fd_ro(fd);
|
||||
prop_area* map_result = map_fd_ro(fd);
|
||||
if (close_fd) {
|
||||
close(fd);
|
||||
}
|
||||
@@ -290,20 +344,19 @@ static int map_prop_area()
|
||||
return map_result;
|
||||
}
|
||||
|
||||
static void *allocate_obj(const size_t size, uint_least32_t *const off)
|
||||
void *prop_area::allocate_obj(const size_t size, uint_least32_t *const off)
|
||||
{
|
||||
prop_area *pa = __system_property_area__;
|
||||
const size_t aligned = BIONIC_ALIGN(size, sizeof(uint_least32_t));
|
||||
if (pa->bytes_used + aligned > pa_data_size) {
|
||||
if (bytes_used_ + aligned > pa_data_size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*off = pa->bytes_used;
|
||||
pa->bytes_used += aligned;
|
||||
return pa->data + *off;
|
||||
*off = bytes_used_;
|
||||
bytes_used_ += aligned;
|
||||
return data_ + *off;
|
||||
}
|
||||
|
||||
static prop_bt *new_prop_bt(const char *name, uint8_t namelen, uint_least32_t *const off)
|
||||
prop_bt *prop_area::new_prop_bt(const char *name, uint8_t namelen, uint_least32_t *const off)
|
||||
{
|
||||
uint_least32_t new_offset;
|
||||
void *const p = allocate_obj(sizeof(prop_bt) + namelen + 1, &new_offset);
|
||||
@@ -316,7 +369,7 @@ static prop_bt *new_prop_bt(const char *name, uint8_t namelen, uint_least32_t *c
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static prop_info *new_prop_info(const char *name, uint8_t namelen,
|
||||
prop_info *prop_area::new_prop_info(const char *name, uint8_t namelen,
|
||||
const char *value, uint8_t valuelen, uint_least32_t *const off)
|
||||
{
|
||||
uint_least32_t new_offset;
|
||||
@@ -330,27 +383,25 @@ static prop_info *new_prop_info(const char *name, uint8_t namelen,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *to_prop_obj(uint_least32_t off)
|
||||
void *prop_area::to_prop_obj(uint_least32_t off)
|
||||
{
|
||||
if (off > pa_data_size)
|
||||
return NULL;
|
||||
if (!__system_property_area__)
|
||||
return NULL;
|
||||
|
||||
return (__system_property_area__->data + off);
|
||||
return (data_ + off);
|
||||
}
|
||||
|
||||
static inline prop_bt *to_prop_bt(atomic_uint_least32_t* off_p) {
|
||||
inline prop_bt *prop_area::to_prop_bt(atomic_uint_least32_t* off_p) {
|
||||
uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume);
|
||||
return reinterpret_cast<prop_bt*>(to_prop_obj(off));
|
||||
}
|
||||
|
||||
static inline prop_info *to_prop_info(atomic_uint_least32_t* off_p) {
|
||||
inline prop_info *prop_area::to_prop_info(atomic_uint_least32_t* off_p) {
|
||||
uint_least32_t off = atomic_load_explicit(off_p, memory_order_consume);
|
||||
return reinterpret_cast<prop_info*>(to_prop_obj(off));
|
||||
}
|
||||
|
||||
static inline prop_bt *root_node()
|
||||
inline prop_bt *prop_area::root_node()
|
||||
{
|
||||
return reinterpret_cast<prop_bt*>(to_prop_obj(0));
|
||||
}
|
||||
@@ -366,8 +417,8 @@ static int cmp_prop_name(const char *one, uint8_t one_len, const char *two,
|
||||
return strncmp(one, two, one_len);
|
||||
}
|
||||
|
||||
static prop_bt *find_prop_bt(prop_bt *const bt, const char *name,
|
||||
uint8_t namelen, bool alloc_if_needed)
|
||||
prop_bt *prop_area::find_prop_bt(prop_bt *const bt, const char *name,
|
||||
uint8_t namelen, bool alloc_if_needed)
|
||||
{
|
||||
|
||||
prop_bt* current = bt;
|
||||
@@ -417,7 +468,7 @@ static prop_bt *find_prop_bt(prop_bt *const bt, const char *name,
|
||||
}
|
||||
}
|
||||
|
||||
static const prop_info *find_property(prop_bt *const trie, const char *name,
|
||||
const prop_info *prop_area::find_property(prop_bt *const trie, const char *name,
|
||||
uint8_t namelen, const char *value, uint8_t valuelen,
|
||||
bool alloc_if_needed)
|
||||
{
|
||||
@@ -543,44 +594,383 @@ static void find_nth_fn(const prop_info *pi, void *ptr)
|
||||
cookie->count++;
|
||||
}
|
||||
|
||||
static int foreach_property(prop_bt *const trie,
|
||||
bool prop_area::foreach_property(prop_bt *const trie,
|
||||
void (*propfn)(const prop_info *pi, void *cookie), void *cookie)
|
||||
{
|
||||
if (!trie)
|
||||
return -1;
|
||||
return false;
|
||||
|
||||
uint_least32_t left_offset = atomic_load_explicit(&trie->left, memory_order_relaxed);
|
||||
if (left_offset != 0) {
|
||||
const int err = foreach_property(to_prop_bt(&trie->left), propfn, cookie);
|
||||
if (err < 0)
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
uint_least32_t prop_offset = atomic_load_explicit(&trie->prop, memory_order_relaxed);
|
||||
if (prop_offset != 0) {
|
||||
prop_info *info = to_prop_info(&trie->prop);
|
||||
if (!info)
|
||||
return -1;
|
||||
return false;
|
||||
propfn(info, cookie);
|
||||
}
|
||||
uint_least32_t children_offset = atomic_load_explicit(&trie->children, memory_order_relaxed);
|
||||
if (children_offset != 0) {
|
||||
const int err = foreach_property(to_prop_bt(&trie->children), propfn, cookie);
|
||||
if (err < 0)
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
uint_least32_t right_offset = atomic_load_explicit(&trie->right, memory_order_relaxed);
|
||||
if (right_offset != 0) {
|
||||
const int err = foreach_property(to_prop_bt(&trie->right), propfn, cookie);
|
||||
if (err < 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const prop_info *prop_area::find(const char *name) {
|
||||
return find_property(root_node(), name, strlen(name), nullptr, 0, false);
|
||||
}
|
||||
|
||||
bool prop_area::add(const char *name, unsigned int namelen,
|
||||
const char *value, unsigned int valuelen) {
|
||||
return find_property(root_node(), name, namelen, value, valuelen, true);
|
||||
}
|
||||
|
||||
bool prop_area::foreach(void (*propfn)(const prop_info* pi, void* cookie), void* cookie) {
|
||||
return foreach_property(root_node(), propfn, cookie);
|
||||
}
|
||||
|
||||
struct context_node {
|
||||
context_node(struct context_node* next, const char* context, prop_area* pa)
|
||||
: context(strdup(context)), pa(pa), checked_access(false), next(next) {
|
||||
lock.init(false);
|
||||
}
|
||||
~context_node() {
|
||||
if (pa) {
|
||||
munmap(pa, pa_size);
|
||||
}
|
||||
free(context);
|
||||
}
|
||||
Lock lock;
|
||||
char* context;
|
||||
prop_area* pa;
|
||||
bool checked_access;
|
||||
struct context_node* next;
|
||||
};
|
||||
|
||||
struct prefix_node {
|
||||
prefix_node(struct prefix_node* next, const char* prefix, context_node* context)
|
||||
: prefix(strdup(prefix)), prefix_len(strlen(prefix)), context(context), next(next) {
|
||||
}
|
||||
~prefix_node() {
|
||||
free(prefix);
|
||||
}
|
||||
char* prefix;
|
||||
const size_t prefix_len;
|
||||
context_node* context;
|
||||
struct prefix_node* next;
|
||||
};
|
||||
|
||||
template <typename List, typename... Args>
|
||||
static inline void list_add(List** list, Args... args) {
|
||||
*list = new List(*list, args...);
|
||||
}
|
||||
|
||||
static void list_add_after_len(prefix_node** list, const char* prefix, context_node* context) {
|
||||
size_t prefix_len = strlen(prefix);
|
||||
|
||||
auto next_list = list;
|
||||
|
||||
while (*next_list) {
|
||||
if ((*next_list)->prefix_len < prefix_len || (*next_list)->prefix[0] == '*') {
|
||||
list_add(next_list, prefix, context);
|
||||
return;
|
||||
}
|
||||
next_list = &(*next_list)->next;
|
||||
}
|
||||
list_add(next_list, prefix, context);
|
||||
}
|
||||
|
||||
template <typename List, typename Func>
|
||||
static void list_foreach(List* list, Func func) {
|
||||
while (list) {
|
||||
func(list);
|
||||
list = list->next;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename List, typename Func>
|
||||
static List* list_find(List* list, Func func) {
|
||||
while (list) {
|
||||
if (func(list)) {
|
||||
return list;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename List>
|
||||
static void list_free(List** list) {
|
||||
while (*list) {
|
||||
auto old_list = *list;
|
||||
*list = old_list->next;
|
||||
delete old_list;
|
||||
}
|
||||
}
|
||||
|
||||
static prefix_node* prefixes = nullptr;
|
||||
static context_node* contexts = nullptr;
|
||||
|
||||
/*
|
||||
* pthread_mutex_lock() calls into system_properties in the case of contention.
|
||||
* This creates a risk of dead lock if any system_properties functions
|
||||
* use pthread locks after system_property initialization.
|
||||
*
|
||||
* For this reason, the below three functions use a bionic Lock and static
|
||||
* allocation of memory for each filename.
|
||||
*/
|
||||
|
||||
static bool open_prop_file(context_node* cnode, bool access_rw, bool* fsetxattr_failed) {
|
||||
cnode->lock.lock();
|
||||
if (cnode->pa) {
|
||||
cnode->lock.unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
char filename[PROP_FILENAME_MAX];
|
||||
int len = snprintf(filename, sizeof(filename), "%s/%s", property_filename, cnode->context);
|
||||
if (len < 0 || len > PROP_FILENAME_MAX) {
|
||||
cnode->lock.unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (access_rw) {
|
||||
cnode->pa = map_prop_area_rw(filename, cnode->context, fsetxattr_failed);
|
||||
} else {
|
||||
cnode->pa = map_prop_area(filename, false);
|
||||
}
|
||||
cnode->lock.unlock();
|
||||
return cnode->pa;
|
||||
}
|
||||
|
||||
static bool check_access(context_node* cnode) {
|
||||
char filename[PROP_FILENAME_MAX];
|
||||
int len = snprintf(filename, sizeof(filename), "%s/%s", property_filename, cnode->context);
|
||||
if (len < 0 || len > PROP_FILENAME_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return access(filename, R_OK) == 0;
|
||||
}
|
||||
|
||||
static bool map_system_property_area(bool access_rw, bool* fsetxattr_failed) {
|
||||
char filename[PROP_FILENAME_MAX];
|
||||
int len = snprintf(filename, sizeof(filename), "%s/properties_serial", property_filename);
|
||||
if (len < 0 || len > PROP_FILENAME_MAX) {
|
||||
__system_property_area__ = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (access_rw) {
|
||||
__system_property_area__ =
|
||||
map_prop_area_rw(filename, "u:object_r:properties_serial:s0", fsetxattr_failed);
|
||||
} else {
|
||||
__system_property_area__ = map_prop_area(filename, false);
|
||||
}
|
||||
return __system_property_area__;
|
||||
}
|
||||
|
||||
static prop_area* get_prop_area_for_name(const char* name) {
|
||||
auto entry = list_find(prefixes, [name](prefix_node* l) {
|
||||
return l->prefix[0] == '*' || !strncmp(l->prefix, name, l->prefix_len);
|
||||
});
|
||||
if (!entry) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto cnode = entry->context;
|
||||
if (!cnode->pa) {
|
||||
open_prop_file(cnode, false, nullptr);
|
||||
}
|
||||
return cnode->pa;
|
||||
}
|
||||
|
||||
/*
|
||||
* The below two functions are duplicated from label_support.c in libselinux.
|
||||
* TODO: Find a location suitable for these functions such that both libc and
|
||||
* libselinux can share a common source file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The read_spec_entries and read_spec_entry functions may be used to
|
||||
* replace sscanf to read entries from spec files. The file and
|
||||
* property services now use these.
|
||||
*/
|
||||
|
||||
/* Read an entry from a spec file (e.g. file_contexts) */
|
||||
static inline int read_spec_entry(char **entry, char **ptr, int *len)
|
||||
{
|
||||
*entry = NULL;
|
||||
char *tmp_buf = NULL;
|
||||
|
||||
while (isspace(**ptr) && **ptr != '\0')
|
||||
(*ptr)++;
|
||||
|
||||
tmp_buf = *ptr;
|
||||
*len = 0;
|
||||
|
||||
while (!isspace(**ptr) && **ptr != '\0') {
|
||||
(*ptr)++;
|
||||
(*len)++;
|
||||
}
|
||||
|
||||
if (*len) {
|
||||
*entry = strndup(tmp_buf, *len);
|
||||
if (!*entry)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* line_buf - Buffer containing the spec entries .
|
||||
* num_args - The number of spec parameter entries to process.
|
||||
* ... - A 'char **spec_entry' for each parameter.
|
||||
* returns - The number of items processed.
|
||||
*
|
||||
* This function calls read_spec_entry() to do the actual string processing.
|
||||
*/
|
||||
static int read_spec_entries(char *line_buf, int num_args, ...)
|
||||
{
|
||||
char **spec_entry, *buf_p;
|
||||
int len, rc, items, entry_len = 0;
|
||||
va_list ap;
|
||||
|
||||
len = strlen(line_buf);
|
||||
if (line_buf[len - 1] == '\n')
|
||||
line_buf[len - 1] = '\0';
|
||||
else
|
||||
/* Handle case if line not \n terminated by bumping
|
||||
* the len for the check below (as the line is NUL
|
||||
* terminated by getline(3)) */
|
||||
len++;
|
||||
|
||||
buf_p = line_buf;
|
||||
while (isspace(*buf_p))
|
||||
buf_p++;
|
||||
|
||||
/* Skip comment lines and empty lines. */
|
||||
if (*buf_p == '#' || *buf_p == '\0')
|
||||
return 0;
|
||||
|
||||
/* Process the spec file entries */
|
||||
va_start(ap, num_args);
|
||||
|
||||
items = 0;
|
||||
while (items < num_args) {
|
||||
spec_entry = va_arg(ap, char **);
|
||||
|
||||
if (len - 1 == buf_p - line_buf) {
|
||||
va_end(ap);
|
||||
return items;
|
||||
}
|
||||
|
||||
rc = read_spec_entry(spec_entry, &buf_p, &entry_len);
|
||||
if (rc < 0) {
|
||||
va_end(ap);
|
||||
return rc;
|
||||
}
|
||||
if (entry_len)
|
||||
items++;
|
||||
}
|
||||
va_end(ap);
|
||||
return items;
|
||||
}
|
||||
|
||||
static bool initialize_properties() {
|
||||
list_free(&prefixes);
|
||||
list_free(&contexts);
|
||||
|
||||
FILE* file = fopen("/property_contexts", "re");
|
||||
|
||||
if (!file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char* buffer = nullptr;
|
||||
size_t line_len;
|
||||
char* prop_prefix = nullptr;
|
||||
char* context = nullptr;
|
||||
|
||||
while (getline(&buffer, &line_len, file) > 0) {
|
||||
int items = read_spec_entries(buffer, 2, &prop_prefix, &context);
|
||||
if (items <= 0) {
|
||||
continue;
|
||||
}
|
||||
if (items == 1) {
|
||||
free(prop_prefix);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* init uses ctl.* properties as an IPC mechanism and does not write them
|
||||
* to a property file, therefore we do not need to create property files
|
||||
* to store them.
|
||||
*/
|
||||
if (!strncmp(prop_prefix, "ctl.", 4)) {
|
||||
free(prop_prefix);
|
||||
free(context);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto old_context = list_find(
|
||||
contexts, [context](context_node* l) { return !strcmp(l->context, context); });
|
||||
if (old_context) {
|
||||
list_add_after_len(&prefixes, prop_prefix, old_context);
|
||||
} else {
|
||||
list_add(&contexts, context, nullptr);
|
||||
list_add_after_len(&prefixes, prop_prefix, contexts);
|
||||
}
|
||||
free(prop_prefix);
|
||||
free(context);
|
||||
}
|
||||
|
||||
free(buffer);
|
||||
fclose(file);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool is_dir(const char* pathname) {
|
||||
struct stat info;
|
||||
if (stat(pathname, &info) == -1) {
|
||||
return false;
|
||||
}
|
||||
return S_ISDIR(info.st_mode);
|
||||
}
|
||||
|
||||
int __system_properties_init()
|
||||
{
|
||||
return map_prop_area();
|
||||
if (is_dir(property_filename)) {
|
||||
if (!initialize_properties()) {
|
||||
return -1;
|
||||
}
|
||||
if (!map_system_property_area(false, nullptr)) {
|
||||
list_free(&prefixes);
|
||||
list_free(&contexts);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
__system_property_area__ = map_prop_area(property_filename, true);
|
||||
if (!__system_property_area__) {
|
||||
return -1;
|
||||
}
|
||||
list_add(&contexts, "legacy_system_prop_area", __system_property_area__);
|
||||
list_add_after_len(&prefixes, "*", contexts);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __system_property_set_filename(const char *filename)
|
||||
@@ -595,7 +985,23 @@ int __system_property_set_filename(const char *filename)
|
||||
|
||||
int __system_property_area_init()
|
||||
{
|
||||
return map_prop_area_rw();
|
||||
mkdir(property_filename, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
||||
if (!initialize_properties()) {
|
||||
return -1;
|
||||
}
|
||||
bool open_prop_file_failed = false;
|
||||
bool fsetxattr_failed = false;
|
||||
list_foreach(contexts, [&fsetxattr_failed, &open_prop_file_failed](context_node* l) {
|
||||
if (!open_prop_file(l, true, &fsetxattr_failed)) {
|
||||
open_prop_file_failed = true;
|
||||
}
|
||||
});
|
||||
if (open_prop_file_failed || !map_system_property_area(true, &fsetxattr_failed)) {
|
||||
list_free(&prefixes);
|
||||
list_free(&contexts);
|
||||
return -1;
|
||||
}
|
||||
return fsetxattr_failed ? -2 : 0;
|
||||
}
|
||||
|
||||
unsigned int __system_property_area_serial()
|
||||
@@ -605,15 +1011,26 @@ unsigned int __system_property_area_serial()
|
||||
return -1;
|
||||
}
|
||||
// Make sure this read fulfilled before __system_property_serial
|
||||
return atomic_load_explicit(&(pa->serial), memory_order_acquire);
|
||||
return atomic_load_explicit(pa->serial(), memory_order_acquire);
|
||||
}
|
||||
|
||||
const prop_info *__system_property_find(const char *name)
|
||||
{
|
||||
if (!__system_property_area__) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (__predict_false(compat_mode)) {
|
||||
return __system_property_find_compat(name);
|
||||
}
|
||||
return find_property(root_node(), name, strlen(name), NULL, 0, false);
|
||||
|
||||
prop_area* pa = get_prop_area_for_name(name);
|
||||
if (!pa) {
|
||||
__libc_format_log(ANDROID_LOG_ERROR, "libc", "Access denied finding property \"%s\"", name);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return pa->find(name);
|
||||
}
|
||||
|
||||
// The C11 standard doesn't allow atomic loads from const fields,
|
||||
@@ -688,11 +1105,15 @@ int __system_property_set(const char *key, const char *value)
|
||||
|
||||
int __system_property_update(prop_info *pi, const char *value, unsigned int len)
|
||||
{
|
||||
prop_area *pa = __system_property_area__;
|
||||
|
||||
if (len >= PROP_VALUE_MAX)
|
||||
return -1;
|
||||
|
||||
prop_area* pa = __system_property_area__;
|
||||
|
||||
if (!pa) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t serial = atomic_load_explicit(&pi->serial, memory_order_relaxed);
|
||||
serial |= 1;
|
||||
atomic_store_explicit(&pi->serial, serial, memory_order_relaxed);
|
||||
@@ -708,10 +1129,10 @@ int __system_property_update(prop_info *pi, const char *value, unsigned int len)
|
||||
__futex_wake(&pi->serial, INT32_MAX);
|
||||
|
||||
atomic_store_explicit(
|
||||
&pa->serial,
|
||||
atomic_load_explicit(&pa->serial, memory_order_relaxed) + 1,
|
||||
pa->serial(),
|
||||
atomic_load_explicit(pa->serial(), memory_order_relaxed) + 1,
|
||||
memory_order_release);
|
||||
__futex_wake(&pa->serial, INT32_MAX);
|
||||
__futex_wake(pa->serial(), INT32_MAX);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -719,9 +1140,6 @@ int __system_property_update(prop_info *pi, const char *value, unsigned int len)
|
||||
int __system_property_add(const char *name, unsigned int namelen,
|
||||
const char *value, unsigned int valuelen)
|
||||
{
|
||||
prop_area *pa = __system_property_area__;
|
||||
const prop_info *pi;
|
||||
|
||||
if (namelen >= PROP_NAME_MAX)
|
||||
return -1;
|
||||
if (valuelen >= PROP_VALUE_MAX)
|
||||
@@ -729,17 +1147,28 @@ int __system_property_add(const char *name, unsigned int namelen,
|
||||
if (namelen < 1)
|
||||
return -1;
|
||||
|
||||
pi = find_property(root_node(), name, namelen, value, valuelen, true);
|
||||
if (!pi)
|
||||
if (!__system_property_area__) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
prop_area* pa = get_prop_area_for_name(name);
|
||||
|
||||
if (!pa) {
|
||||
__libc_format_log(ANDROID_LOG_ERROR, "libc", "Access denied adding property \"%s\"", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool ret = pa->add(name, namelen, value, valuelen);
|
||||
if (!ret)
|
||||
return -1;
|
||||
|
||||
// There is only a single mutator, but we want to make sure that
|
||||
// updates are visible to a reader waiting for the update.
|
||||
atomic_store_explicit(
|
||||
&pa->serial,
|
||||
atomic_load_explicit(&pa->serial, memory_order_relaxed) + 1,
|
||||
__system_property_area__->serial(),
|
||||
atomic_load_explicit(__system_property_area__->serial(), memory_order_relaxed) + 1,
|
||||
memory_order_release);
|
||||
__futex_wake(&pa->serial, INT32_MAX);
|
||||
__futex_wake(__system_property_area__->serial(), INT32_MAX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -761,9 +1190,13 @@ unsigned int __system_property_wait_any(unsigned int serial)
|
||||
prop_area *pa = __system_property_area__;
|
||||
uint32_t my_serial;
|
||||
|
||||
if (!pa) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
do {
|
||||
__futex_wait(&pa->serial, serial, NULL);
|
||||
my_serial = atomic_load_explicit(&pa->serial, memory_order_acquire);
|
||||
__futex_wait(pa->serial(), serial, NULL);
|
||||
my_serial = atomic_load_explicit(pa->serial(), memory_order_acquire);
|
||||
} while (my_serial == serial);
|
||||
|
||||
return my_serial;
|
||||
@@ -784,9 +1217,24 @@ const prop_info *__system_property_find_nth(unsigned n)
|
||||
int __system_property_foreach(void (*propfn)(const prop_info *pi, void *cookie),
|
||||
void *cookie)
|
||||
{
|
||||
if (!__system_property_area__) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (__predict_false(compat_mode)) {
|
||||
return __system_property_foreach_compat(propfn, cookie);
|
||||
}
|
||||
|
||||
return foreach_property(root_node(), propfn, cookie);
|
||||
list_foreach(contexts, [propfn, cookie](context_node* l) {
|
||||
if (!l->pa && !l->checked_access) {
|
||||
if (check_access(l)) {
|
||||
open_prop_file(l, false, nullptr);
|
||||
}
|
||||
l->checked_access = true;
|
||||
}
|
||||
if (l->pa) {
|
||||
l->pa->foreach(propfn, cookie);
|
||||
}
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
@@ -98,6 +98,11 @@ enum {
|
||||
*/
|
||||
ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS = 0x100,
|
||||
|
||||
/* This flag used to load library in a different namespace. The namespace is
|
||||
* specified in library_namespace.
|
||||
*/
|
||||
ANDROID_DLEXT_USE_NAMESPACE = 0x200,
|
||||
|
||||
/* Mask of valid bits */
|
||||
ANDROID_DLEXT_VALID_FLAG_BITS = ANDROID_DLEXT_RESERVED_ADDRESS |
|
||||
ANDROID_DLEXT_RESERVED_ADDRESS_HINT |
|
||||
@@ -107,9 +112,12 @@ enum {
|
||||
ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET |
|
||||
ANDROID_DLEXT_FORCE_LOAD |
|
||||
ANDROID_DLEXT_FORCE_FIXED_VADDR |
|
||||
ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS,
|
||||
ANDROID_DLEXT_LOAD_AT_FIXED_ADDRESS |
|
||||
ANDROID_DLEXT_USE_NAMESPACE,
|
||||
};
|
||||
|
||||
struct android_namespace_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t flags;
|
||||
void* reserved_addr;
|
||||
@@ -117,10 +125,48 @@ typedef struct {
|
||||
int relro_fd;
|
||||
int library_fd;
|
||||
off64_t library_fd_offset;
|
||||
struct android_namespace_t* library_namespace;
|
||||
} android_dlextinfo;
|
||||
|
||||
extern void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo);
|
||||
|
||||
/*
|
||||
* Initializes public and anonymous namespaces. The public_ns_sonames is the list of sonames
|
||||
* to be included into public namespace separated by colon. Example: "libc.so:libm.so:libdl.so".
|
||||
* The libraries in this list should be loaded prior to this call.
|
||||
*
|
||||
* The anon_ns_library_path is the search path for anonymous namespace. The anonymous namespace
|
||||
* is used in the case when linker cannot identify the caller of dlopen/dlsym. This happens
|
||||
* for the code not loaded by dynamic linker; for example calls from the mono-compiled code.
|
||||
*/
|
||||
extern bool android_init_namespaces(const char* public_ns_sonames,
|
||||
const char* anon_ns_library_path);
|
||||
|
||||
/*
|
||||
* Creates new linker namespace.
|
||||
* ld_library_path and default_library_path represent the search path
|
||||
* for the libraries in the namespace.
|
||||
*
|
||||
* The libraries in the namespace are searched by folowing order:
|
||||
* 1. ld_library_path (Think of this as namespace-local LD_LIBRARY_PATH)
|
||||
* 2. In directories specified by DT_RUNPATH of the "needed by" binary.
|
||||
* 3. deault_library_path (This of this as namespace-local default library path)
|
||||
*
|
||||
* When is_isolated is true the resulting namespace requires all of the libraries
|
||||
* to be on the search path or under the permitted_when_isolated_path; the search_path is
|
||||
* ld_library_path:default_library_path. Note that the permitted_when_isolated_path path
|
||||
* is not part of the search_path and does not affect the search order. It is a way
|
||||
* to allow loading libraries from specific locations when using absolute path.
|
||||
*
|
||||
* If a library or any of its dependencies are outside of the permitted_when_isolated_path
|
||||
* and search_path, and it is not part of the public namespace dlopen will fail.
|
||||
*/
|
||||
extern struct android_namespace_t* android_create_namespace(const char* name,
|
||||
const char* ld_library_path,
|
||||
const char* default_library_path,
|
||||
bool is_isolated,
|
||||
const char* permitted_when_isolated_path);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* __ANDROID_DLEXT_H__ */
|
||||
|
@@ -32,18 +32,19 @@
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
#if !defined(__bionic_using_gnu_basename)
|
||||
/*
|
||||
* <string.h> gets you the GNU basename.
|
||||
* <libgen.h> the POSIX one.
|
||||
* Note that our "POSIX" one has the wrong argument cv-qualifiers, but doesn't
|
||||
* modify its input and uses thread-local storage for the result if necessary.
|
||||
* Including <string.h> will get you the GNU basename, unless <libgen.h> is
|
||||
* included, either before or after including <string.h>.
|
||||
*
|
||||
* Note that this has the wrong argument cv-qualifiers, but doesn't modify its
|
||||
* input and uses thread-local storage for the result if necessary.
|
||||
*/
|
||||
extern char* basename(const char*);
|
||||
#define __bionic_using_posix_basename
|
||||
#endif
|
||||
extern char* __posix_basename(const char*) __RENAME(basename);
|
||||
|
||||
#define basename __posix_basename
|
||||
|
||||
/* This has the wrong argument cv-qualifiers, but doesn't modify its input and uses thread-local storage for the result if necessary. */
|
||||
extern char* dirname(const char*);
|
||||
|
@@ -96,6 +96,26 @@ typedef int pthread_once_t;
|
||||
|
||||
#define PTHREAD_ONCE_INIT 0
|
||||
|
||||
typedef struct {
|
||||
#if defined(__LP64__)
|
||||
int64_t __private[4];
|
||||
#else
|
||||
int32_t __private[8];
|
||||
#endif
|
||||
} pthread_barrier_t;
|
||||
|
||||
typedef int pthread_barrierattr_t;
|
||||
|
||||
#define PTHREAD_BARRIER_SERIAL_THREAD -1
|
||||
|
||||
typedef struct {
|
||||
#if defined(__LP64__)
|
||||
int64_t __private;
|
||||
#else
|
||||
int32_t __private[2];
|
||||
#endif
|
||||
} pthread_spinlock_t;
|
||||
|
||||
#if defined(__LP64__)
|
||||
#define PTHREAD_STACK_MIN (4 * PAGE_SIZE)
|
||||
#else
|
||||
@@ -130,7 +150,7 @@ int pthread_attr_setschedparam(pthread_attr_t*, const struct sched_param*) __non
|
||||
int pthread_attr_setschedpolicy(pthread_attr_t*, int) __nonnull((1));
|
||||
int pthread_attr_setscope(pthread_attr_t*, int) __nonnull((1));
|
||||
int pthread_attr_setstack(pthread_attr_t*, void*, size_t) __nonnull((1));
|
||||
int pthread_attr_setstacksize(pthread_attr_t*, size_t stack_size) __nonnull((1));
|
||||
int pthread_attr_setstacksize(pthread_attr_t*, size_t) __nonnull((1));
|
||||
|
||||
int pthread_condattr_destroy(pthread_condattr_t*) __nonnull((1));
|
||||
int pthread_condattr_getclock(const pthread_condattr_t*, clockid_t*) __nonnull((1, 2));
|
||||
@@ -205,9 +225,24 @@ int pthread_rwlock_timedrdlock(pthread_rwlock_t*, const struct timespec*) __nonn
|
||||
int pthread_rwlock_timedwrlock(pthread_rwlock_t*, const struct timespec*) __nonnull((1, 2));
|
||||
int pthread_rwlock_tryrdlock(pthread_rwlock_t*) __nonnull((1));
|
||||
int pthread_rwlock_trywrlock(pthread_rwlock_t*) __nonnull((1));
|
||||
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) __nonnull((1));
|
||||
int pthread_rwlock_unlock(pthread_rwlock_t *) __nonnull((1));
|
||||
int pthread_rwlock_wrlock(pthread_rwlock_t*) __nonnull((1));
|
||||
|
||||
int pthread_barrierattr_init(pthread_barrierattr_t* attr) __nonnull((1));
|
||||
int pthread_barrierattr_destroy(pthread_barrierattr_t* attr) __nonnull((1));
|
||||
int pthread_barrierattr_getpshared(pthread_barrierattr_t* attr, int* pshared) __nonnull((1, 2));
|
||||
int pthread_barrierattr_setpshared(pthread_barrierattr_t* attr, int pshared) __nonnull((1));
|
||||
|
||||
int pthread_barrier_init(pthread_barrier_t*, const pthread_barrierattr_t*, unsigned) __nonnull((1));
|
||||
int pthread_barrier_destroy(pthread_barrier_t*) __nonnull((1));
|
||||
int pthread_barrier_wait(pthread_barrier_t*) __nonnull((1));
|
||||
|
||||
int pthread_spin_destroy(pthread_spinlock_t*) __nonnull((1));
|
||||
int pthread_spin_init(pthread_spinlock_t*, int) __nonnull((1));
|
||||
int pthread_spin_lock(pthread_spinlock_t*) __nonnull((1));
|
||||
int pthread_spin_trylock(pthread_spinlock_t*) __nonnull((1));
|
||||
int pthread_spin_unlock(pthread_spinlock_t*) __nonnull((1));
|
||||
|
||||
pthread_t pthread_self(void) __pure2;
|
||||
|
||||
int pthread_setname_np(pthread_t, const char*) __nonnull((2));
|
||||
|
@@ -270,6 +270,7 @@ int vasprintf(char ** __restrict, const char * __restrict,
|
||||
void clearerr_unlocked(FILE*);
|
||||
int feof_unlocked(FILE*);
|
||||
int ferror_unlocked(FILE*);
|
||||
int fileno_unlocked(FILE*);
|
||||
|
||||
/*
|
||||
* Stdio function-access interface.
|
||||
|
@@ -115,18 +115,18 @@ extern size_t strxfrm(char* __restrict, const char* __restrict, size_t);
|
||||
extern int strcoll_l(const char *, const char *, locale_t) __purefunc;
|
||||
extern size_t strxfrm_l(char* __restrict, const char* __restrict, size_t, locale_t);
|
||||
|
||||
#if defined(__USE_GNU) && !defined(__bionic_using_posix_basename)
|
||||
#if defined(__USE_GNU) && !defined(basename)
|
||||
/*
|
||||
* glibc has a basename in <string.h> that's different to the POSIX one in <libgen.h>.
|
||||
* It doesn't modify its argument, and in C++ it's const-correct.
|
||||
*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C++" char* basename(char*) __RENAME(__gnu_basename) __nonnull((1));
|
||||
extern "C++" const char* basename(const char*) __RENAME(__gnu_basename) __nonnull((1));
|
||||
#else
|
||||
extern char* basename(const char*) __RENAME(__gnu_basename) __nonnull((1));
|
||||
#endif
|
||||
#define __bionic_using_gnu_basename
|
||||
#endif
|
||||
|
||||
extern void* __memchr_chk(const void*, int, size_t, size_t);
|
||||
|
@@ -41,6 +41,7 @@ typedef struct prop_msg prop_msg;
|
||||
#define PROP_AREA_VERSION_COMPAT 0x45434f76
|
||||
|
||||
#define PROP_SERVICE_NAME "property_service"
|
||||
#define PROP_FILENAME_MAX 1024
|
||||
#define PROP_FILENAME "/dev/__properties__"
|
||||
|
||||
#define PA_SIZE (128 * 1024)
|
||||
|
@@ -59,7 +59,7 @@ extern void* mmap64(void*, size_t, int, int, int, off64_t);
|
||||
extern int munmap(void*, size_t);
|
||||
extern int msync(const void*, size_t, int);
|
||||
extern int mprotect(const void*, size_t, int);
|
||||
extern void* mremap(void*, size_t, size_t, unsigned long);
|
||||
extern void* mremap(void*, size_t, size_t, int, ...);
|
||||
|
||||
extern int mlockall(int);
|
||||
extern int munlockall(void);
|
||||
|
1420
libc/libc.arm.brillo.map
Normal file
1420
libc/libc.arm.brillo.map
Normal file
File diff suppressed because it is too large
Load Diff
@@ -58,13 +58,13 @@ LIBC {
|
||||
__freadable;
|
||||
__fsetlocking;
|
||||
__fstatfs64; # arm x86 mips
|
||||
__futex_wait; # arm x86 mips
|
||||
__futex_wake; # arm x86 mips
|
||||
__futex_wait; # arm x86 mips nobrillo
|
||||
__futex_wake; # arm x86 mips nobrillo
|
||||
__fwritable;
|
||||
__gedf2; # arm
|
||||
__get_h_errno;
|
||||
__get_thread; # arm x86 mips
|
||||
__get_tls; # arm x86 mips
|
||||
__get_thread; # arm x86 mips nobrillo
|
||||
__get_tls; # arm x86 mips nobrillo
|
||||
__getcpu; # arm x86 mips
|
||||
__getcwd; # arm x86 mips
|
||||
__getdents64; # arm x86 mips
|
||||
@@ -131,7 +131,7 @@ LIBC {
|
||||
__ns_skiprr; # arm x86 mips
|
||||
__ns_sprintrr; # arm x86 mips
|
||||
__ns_sprintrrf; # arm x86 mips
|
||||
__open; # arm x86 mips
|
||||
__open; # arm x86 mips nobrillo
|
||||
__open_2;
|
||||
__openat; # arm x86 mips
|
||||
__openat_2;
|
||||
@@ -148,8 +148,8 @@ LIBC {
|
||||
__p_time;
|
||||
__p_type;
|
||||
__p_type_syms;
|
||||
__page_shift; # arm x86 mips
|
||||
__page_size; # arm x86 mips
|
||||
__page_shift; # arm x86 mips nobrillo
|
||||
__page_size; # arm x86 mips nobrillo
|
||||
__poll_chk;
|
||||
__popcount_tab; # arm
|
||||
__popcountsi2; # arm x86 mips
|
||||
@@ -161,7 +161,7 @@ LIBC {
|
||||
__pselect6; # arm x86 mips
|
||||
__pthread_cleanup_pop;
|
||||
__pthread_cleanup_push;
|
||||
__pthread_gettid; # arm x86 mips
|
||||
__pthread_gettid; # arm x86 mips nobrillo
|
||||
__ptrace; # arm x86 mips
|
||||
__putlong;
|
||||
__putshort;
|
||||
@@ -202,8 +202,8 @@ LIBC {
|
||||
__sched_cpufree;
|
||||
__sched_getaffinity; # arm x86 mips
|
||||
__sclose; # arm x86 mips
|
||||
__sdidinit; # arm x86 mips
|
||||
__set_errno; # arm x86 mips
|
||||
__sdidinit; # arm x86 mips nobrillo
|
||||
__set_errno; # arm x86 mips nobrillo
|
||||
__set_tid_address; # arm x86 mips
|
||||
__set_tls; # arm mips
|
||||
__sF;
|
||||
@@ -213,7 +213,7 @@ LIBC {
|
||||
__sglue; # arm x86 mips
|
||||
__sigaction; # arm x86 mips
|
||||
__signalfd4; # arm x86 mips
|
||||
__sinit; # arm x86 mips
|
||||
__sinit; # arm x86 mips nobrillo
|
||||
__smakebuf; # arm x86 mips
|
||||
__snprintf_chk;
|
||||
__socket; # arm x86 mips
|
||||
@@ -274,7 +274,7 @@ LIBC {
|
||||
__unordsf2; # arm
|
||||
__vsnprintf_chk;
|
||||
__vsprintf_chk;
|
||||
__wait4; # arm x86 mips
|
||||
__wait4; # arm x86 mips nobrillo
|
||||
__waitid; # arm x86 mips
|
||||
_ctype_;
|
||||
_Exit;
|
||||
@@ -307,9 +307,9 @@ LIBC {
|
||||
android_gethostbynamefornet;
|
||||
android_set_abort_message;
|
||||
arc4random;
|
||||
arc4random_addrandom; # arm x86 mips
|
||||
arc4random_addrandom; # arm x86 mips nobrillo
|
||||
arc4random_buf;
|
||||
arc4random_stir; # arm x86 mips
|
||||
arc4random_stir; # arm x86 mips nobrillo
|
||||
arc4random_uniform;
|
||||
asctime;
|
||||
asctime64; # arm x86 mips
|
||||
@@ -323,11 +323,11 @@ LIBC {
|
||||
atoll;
|
||||
basename;
|
||||
basename_r; # arm x86 mips
|
||||
bcopy; # arm x86 mips
|
||||
bcopy; # arm x86 mips nobrillo
|
||||
bind;
|
||||
bindresvport;
|
||||
brk;
|
||||
bsd_signal; # arm x86 mips
|
||||
bsd_signal; # arm x86 mips nobrillo
|
||||
bsearch;
|
||||
btowc;
|
||||
bzero; # arm x86 mips
|
||||
@@ -383,7 +383,7 @@ LIBC {
|
||||
dup3;
|
||||
duplocale;
|
||||
endmntent;
|
||||
endpwent;
|
||||
endpwent; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
endservent;
|
||||
endutent;
|
||||
environ;
|
||||
@@ -430,7 +430,7 @@ LIBC {
|
||||
fdatasync;
|
||||
fdopen;
|
||||
fdopendir;
|
||||
fdprintf; # arm x86 mips
|
||||
fdprintf; # arm x86 mips nobrillo
|
||||
feof;
|
||||
feof_unlocked;
|
||||
ferror;
|
||||
@@ -483,7 +483,7 @@ LIBC {
|
||||
fsync;
|
||||
ftell;
|
||||
ftello;
|
||||
ftime; # arm x86 mips
|
||||
ftime; # arm x86 mips nobrillo
|
||||
ftok;
|
||||
ftruncate;
|
||||
ftruncate64;
|
||||
@@ -516,8 +516,8 @@ LIBC {
|
||||
getchar_unlocked;
|
||||
getcwd;
|
||||
getdelim;
|
||||
getdents; # arm x86 mips
|
||||
getdtablesize; # arm x86 mips
|
||||
getdents; # arm x86 mips nobrillo
|
||||
getdtablesize; # arm x86 mips nobrillo
|
||||
getegid;
|
||||
getenv;
|
||||
geteuid;
|
||||
@@ -592,7 +592,7 @@ LIBC {
|
||||
if_nametoindex;
|
||||
imaxabs;
|
||||
imaxdiv;
|
||||
index; # arm x86 mips
|
||||
index; # arm x86 mips nobrillo
|
||||
inet_addr;
|
||||
inet_aton;
|
||||
inet_lnaof;
|
||||
@@ -645,7 +645,7 @@ LIBC {
|
||||
isprint_l;
|
||||
ispunct;
|
||||
ispunct_l;
|
||||
issetugid; # arm x86 mips
|
||||
issetugid; # arm x86 mips nobrillo
|
||||
isspace;
|
||||
isspace_l;
|
||||
isupper;
|
||||
@@ -735,7 +735,7 @@ LIBC {
|
||||
mempcpy;
|
||||
memrchr;
|
||||
memset;
|
||||
memswap; # arm x86 mips
|
||||
memswap; # arm x86 mips nobrillo
|
||||
mincore;
|
||||
mkdir;
|
||||
mkdirat;
|
||||
@@ -826,7 +826,7 @@ LIBC {
|
||||
pthread_attr_getschedpolicy;
|
||||
pthread_attr_getscope;
|
||||
pthread_attr_getstack;
|
||||
pthread_attr_getstackaddr; # arm x86 mips
|
||||
pthread_attr_getstackaddr; # arm x86 mips nobrillo
|
||||
pthread_attr_getstacksize;
|
||||
pthread_attr_init;
|
||||
pthread_attr_setdetachstate;
|
||||
@@ -835,7 +835,7 @@ LIBC {
|
||||
pthread_attr_setschedpolicy;
|
||||
pthread_attr_setscope;
|
||||
pthread_attr_setstack;
|
||||
pthread_attr_setstackaddr; # arm x86 mips
|
||||
pthread_attr_setstackaddr; # arm x86 mips nobrillo
|
||||
pthread_attr_setstacksize;
|
||||
pthread_cond_broadcast;
|
||||
pthread_cond_destroy;
|
||||
@@ -1094,8 +1094,8 @@ LIBC {
|
||||
strncpy;
|
||||
strndup;
|
||||
strnlen;
|
||||
strntoimax; # arm x86 mips
|
||||
strntoumax; # arm x86 mips
|
||||
strntoimax; # arm x86 mips nobrillo
|
||||
strntoumax; # arm x86 mips nobrillo
|
||||
strpbrk;
|
||||
strptime;
|
||||
strrchr;
|
||||
@@ -1114,7 +1114,7 @@ LIBC {
|
||||
strtoll;
|
||||
strtoll_l;
|
||||
strtoq;
|
||||
strtotimeval; # arm x86 mips
|
||||
strtotimeval; # arm x86 mips nobrillo
|
||||
strtoul;
|
||||
strtoull;
|
||||
strtoull_l;
|
||||
@@ -1136,7 +1136,7 @@ LIBC {
|
||||
sysinfo;
|
||||
syslog;
|
||||
system;
|
||||
sysv_signal; # arm x86 mips
|
||||
sysv_signal; # arm x86 mips nobrillo
|
||||
tcdrain;
|
||||
tcflow;
|
||||
tcflush;
|
||||
@@ -1168,7 +1168,7 @@ LIBC {
|
||||
timerfd_settime;
|
||||
times;
|
||||
timezone;
|
||||
tkill; # arm x86 mips
|
||||
tkill; # arm x86 mips nobrillo
|
||||
tmpfile;
|
||||
tmpnam;
|
||||
toascii;
|
||||
@@ -1210,7 +1210,7 @@ LIBC {
|
||||
vdprintf;
|
||||
verr;
|
||||
verrx;
|
||||
vfdprintf; # arm x86 mips
|
||||
vfdprintf; # arm x86 mips nobrillo
|
||||
vfork;
|
||||
vfprintf;
|
||||
vfscanf;
|
||||
@@ -1230,7 +1230,7 @@ LIBC {
|
||||
vwprintf;
|
||||
vwscanf;
|
||||
wait;
|
||||
wait3; # arm x86 mips
|
||||
wait3; # arm x86 mips nobrillo
|
||||
wait4;
|
||||
waitid;
|
||||
waitpid;
|
||||
@@ -1279,7 +1279,7 @@ LIBC {
|
||||
wcstoull;
|
||||
wcstoull_l;
|
||||
wcstoumax;
|
||||
wcswcs; # arm x86 mips
|
||||
wcswcs; # arm x86 mips nobrillo
|
||||
wcswidth;
|
||||
wcsxfrm;
|
||||
wcsxfrm_l;
|
||||
@@ -1310,11 +1310,24 @@ LIBC_N {
|
||||
__pwrite_chk;
|
||||
__pwrite64_chk;
|
||||
__write_chk;
|
||||
fileno_unlocked;
|
||||
getgrgid_r;
|
||||
getgrnam_r;
|
||||
preadv;
|
||||
preadv64;
|
||||
prlimit; # arm mips x86
|
||||
pthread_barrierattr_destroy;
|
||||
pthread_barrierattr_getpshared;
|
||||
pthread_barrierattr_init;
|
||||
pthread_barrierattr_setpshared;
|
||||
pthread_barrier_destroy;
|
||||
pthread_barrier_init;
|
||||
pthread_barrier_wait;
|
||||
pthread_spin_destroy;
|
||||
pthread_spin_init;
|
||||
pthread_spin_lock;
|
||||
pthread_spin_trylock;
|
||||
pthread_spin_unlock;
|
||||
pwritev;
|
||||
pwritev64;
|
||||
scandirat;
|
||||
@@ -1398,7 +1411,6 @@ LIBC_PRIVATE {
|
||||
__ashrdi3; # arm
|
||||
__bionic_brk; # arm x86 mips
|
||||
__bionic_libgcc_compat_symbols; # arm x86
|
||||
__bionic_libgcc_unwind_symbols; # arm
|
||||
__dso_handle; # arm
|
||||
__gnu_Unwind_Backtrace; # arm
|
||||
__gnu_unwind_execute; # arm
|
||||
@@ -1434,10 +1446,10 @@ LIBC_PRIVATE {
|
||||
_Unwind_VRS_Pop; # arm
|
||||
_Unwind_VRS_Set; # arm
|
||||
atexit; # arm
|
||||
dlmalloc; # arm x86 mips
|
||||
dlmalloc_inspect_all;
|
||||
dlmalloc_trim;
|
||||
dlmalloc_usable_size; # arm x86 mips
|
||||
dlmalloc; # arm x86 mips nobrillo
|
||||
dlmalloc_inspect_all; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
dlmalloc_trim; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
dlmalloc_usable_size; # arm x86 mips nobrillo
|
||||
gMallocLeakZygoteChild;
|
||||
SHA1Final; # arm x86 mips
|
||||
SHA1Init; # arm x86 mips
|
||||
|
1185
libc/libc.arm64.brillo.map
Normal file
1185
libc/libc.arm64.brillo.map
Normal file
File diff suppressed because it is too large
Load Diff
@@ -241,7 +241,7 @@ LIBC {
|
||||
dup3;
|
||||
duplocale;
|
||||
endmntent;
|
||||
endpwent;
|
||||
endpwent; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
endservent;
|
||||
endutent;
|
||||
environ;
|
||||
@@ -1156,10 +1156,23 @@ LIBC_N {
|
||||
__pwrite_chk;
|
||||
__pwrite64_chk;
|
||||
__write_chk;
|
||||
fileno_unlocked;
|
||||
getgrgid_r;
|
||||
getgrnam_r;
|
||||
preadv;
|
||||
preadv64;
|
||||
pthread_barrierattr_destroy;
|
||||
pthread_barrierattr_getpshared;
|
||||
pthread_barrierattr_init;
|
||||
pthread_barrierattr_setpshared;
|
||||
pthread_barrier_destroy;
|
||||
pthread_barrier_init;
|
||||
pthread_barrier_wait;
|
||||
pthread_spin_destroy;
|
||||
pthread_spin_init;
|
||||
pthread_spin_lock;
|
||||
pthread_spin_trylock;
|
||||
pthread_spin_unlock;
|
||||
pwritev;
|
||||
pwritev64;
|
||||
scandirat;
|
||||
@@ -1169,7 +1182,7 @@ LIBC_N {
|
||||
|
||||
LIBC_PRIVATE {
|
||||
global:
|
||||
dlmalloc_inspect_all;
|
||||
dlmalloc_trim;
|
||||
dlmalloc_inspect_all; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
dlmalloc_trim; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
gMallocLeakZygoteChild;
|
||||
} LIBC_N;
|
||||
|
@@ -58,13 +58,13 @@ LIBC {
|
||||
__freadable;
|
||||
__fsetlocking;
|
||||
__fstatfs64; # arm x86 mips
|
||||
__futex_wait; # arm x86 mips
|
||||
__futex_wake; # arm x86 mips
|
||||
__futex_wait; # arm x86 mips nobrillo
|
||||
__futex_wake; # arm x86 mips nobrillo
|
||||
__fwritable;
|
||||
__gedf2; # arm
|
||||
__get_h_errno;
|
||||
__get_thread; # arm x86 mips
|
||||
__get_tls; # arm x86 mips
|
||||
__get_thread; # arm x86 mips nobrillo
|
||||
__get_tls; # arm x86 mips nobrillo
|
||||
__getcpu; # arm x86 mips
|
||||
__getcwd; # arm x86 mips
|
||||
__getdents64; # arm x86 mips
|
||||
@@ -132,7 +132,7 @@ LIBC {
|
||||
__ns_skiprr; # arm x86 mips
|
||||
__ns_sprintrr; # arm x86 mips
|
||||
__ns_sprintrrf; # arm x86 mips
|
||||
__open; # arm x86 mips
|
||||
__open; # arm x86 mips nobrillo
|
||||
__open_2;
|
||||
__openat; # arm x86 mips
|
||||
__openat_2;
|
||||
@@ -149,8 +149,8 @@ LIBC {
|
||||
__p_time;
|
||||
__p_type;
|
||||
__p_type_syms;
|
||||
__page_shift; # arm x86 mips
|
||||
__page_size; # arm x86 mips
|
||||
__page_shift; # arm x86 mips nobrillo
|
||||
__page_size; # arm x86 mips nobrillo
|
||||
__poll_chk;
|
||||
__popcount_tab; # arm
|
||||
__popcountsi2; # arm x86 mips
|
||||
@@ -162,7 +162,7 @@ LIBC {
|
||||
__pselect6; # arm x86 mips
|
||||
__pthread_cleanup_pop;
|
||||
__pthread_cleanup_push;
|
||||
__pthread_gettid; # arm x86 mips
|
||||
__pthread_gettid; # arm x86 mips nobrillo
|
||||
__ptrace; # arm x86 mips
|
||||
__putlong;
|
||||
__putshort;
|
||||
@@ -203,8 +203,8 @@ LIBC {
|
||||
__sched_cpufree;
|
||||
__sched_getaffinity; # arm x86 mips
|
||||
__sclose; # arm x86 mips
|
||||
__sdidinit; # arm x86 mips
|
||||
__set_errno; # arm x86 mips
|
||||
__sdidinit; # arm x86 mips nobrillo
|
||||
__set_errno; # arm x86 mips nobrillo
|
||||
__set_thread_area; # x86
|
||||
__set_tid_address; # arm x86 mips
|
||||
__set_tls; # arm mips
|
||||
@@ -215,7 +215,7 @@ LIBC {
|
||||
__sglue; # arm x86 mips
|
||||
__sigaction; # arm x86 mips
|
||||
__signalfd4; # arm x86 mips
|
||||
__sinit; # arm x86 mips
|
||||
__sinit; # arm x86 mips nobrillo
|
||||
__smakebuf; # arm x86 mips
|
||||
__snprintf_chk;
|
||||
__socket; # arm x86 mips
|
||||
@@ -277,7 +277,7 @@ LIBC {
|
||||
__unordsf2; # arm
|
||||
__vsnprintf_chk;
|
||||
__vsprintf_chk;
|
||||
__wait4; # arm x86 mips
|
||||
__wait4; # arm x86 mips nobrillo
|
||||
__waitid; # arm x86 mips
|
||||
_ctype_;
|
||||
_Exit;
|
||||
@@ -311,9 +311,9 @@ LIBC {
|
||||
android_gethostbynamefornet;
|
||||
android_set_abort_message;
|
||||
arc4random;
|
||||
arc4random_addrandom; # arm x86 mips
|
||||
arc4random_addrandom; # arm x86 mips nobrillo
|
||||
arc4random_buf;
|
||||
arc4random_stir; # arm x86 mips
|
||||
arc4random_stir; # arm x86 mips nobrillo
|
||||
arc4random_uniform;
|
||||
asctime;
|
||||
asctime64; # arm x86 mips
|
||||
@@ -327,11 +327,11 @@ LIBC {
|
||||
atoll;
|
||||
basename;
|
||||
basename_r; # arm x86 mips
|
||||
bcopy; # arm x86 mips
|
||||
bcopy; # arm x86 mips nobrillo
|
||||
bind;
|
||||
bindresvport;
|
||||
brk;
|
||||
bsd_signal; # arm x86 mips
|
||||
bsd_signal; # arm x86 mips nobrillo
|
||||
bsearch;
|
||||
btowc;
|
||||
bzero; # arm x86 mips
|
||||
@@ -387,7 +387,7 @@ LIBC {
|
||||
dup3;
|
||||
duplocale;
|
||||
endmntent;
|
||||
endpwent;
|
||||
endpwent; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
endservent;
|
||||
endutent;
|
||||
environ;
|
||||
@@ -434,7 +434,7 @@ LIBC {
|
||||
fdatasync;
|
||||
fdopen;
|
||||
fdopendir;
|
||||
fdprintf; # arm x86 mips
|
||||
fdprintf; # arm x86 mips nobrillo
|
||||
feof;
|
||||
feof_unlocked;
|
||||
ferror;
|
||||
@@ -487,7 +487,7 @@ LIBC {
|
||||
fsync;
|
||||
ftell;
|
||||
ftello;
|
||||
ftime; # arm x86 mips
|
||||
ftime; # arm x86 mips nobrillo
|
||||
ftok;
|
||||
ftruncate;
|
||||
ftruncate64;
|
||||
@@ -520,8 +520,8 @@ LIBC {
|
||||
getchar_unlocked;
|
||||
getcwd;
|
||||
getdelim;
|
||||
getdents; # arm x86 mips
|
||||
getdtablesize; # arm x86 mips
|
||||
getdents; # arm x86 mips nobrillo
|
||||
getdtablesize; # arm x86 mips nobrillo
|
||||
getegid;
|
||||
getenv;
|
||||
geteuid;
|
||||
@@ -596,7 +596,7 @@ LIBC {
|
||||
if_nametoindex;
|
||||
imaxabs;
|
||||
imaxdiv;
|
||||
index; # arm x86 mips
|
||||
index; # arm x86 mips nobrillo
|
||||
inet_addr;
|
||||
inet_aton;
|
||||
inet_lnaof;
|
||||
@@ -649,7 +649,7 @@ LIBC {
|
||||
isprint_l;
|
||||
ispunct;
|
||||
ispunct_l;
|
||||
issetugid; # arm x86 mips
|
||||
issetugid; # arm x86 mips nobrillo
|
||||
isspace;
|
||||
isspace_l;
|
||||
isupper;
|
||||
@@ -739,7 +739,7 @@ LIBC {
|
||||
mempcpy;
|
||||
memrchr;
|
||||
memset;
|
||||
memswap; # arm x86 mips
|
||||
memswap; # arm x86 mips nobrillo
|
||||
mincore;
|
||||
mkdir;
|
||||
mkdirat;
|
||||
@@ -853,7 +853,7 @@ LIBC {
|
||||
pthread_attr_getschedpolicy;
|
||||
pthread_attr_getscope;
|
||||
pthread_attr_getstack;
|
||||
pthread_attr_getstackaddr; # arm x86 mips
|
||||
pthread_attr_getstackaddr; # arm x86 mips nobrillo
|
||||
pthread_attr_getstacksize;
|
||||
pthread_attr_init;
|
||||
pthread_attr_setdetachstate;
|
||||
@@ -862,7 +862,7 @@ LIBC {
|
||||
pthread_attr_setschedpolicy;
|
||||
pthread_attr_setscope;
|
||||
pthread_attr_setstack;
|
||||
pthread_attr_setstackaddr; # arm x86 mips
|
||||
pthread_attr_setstackaddr; # arm x86 mips nobrillo
|
||||
pthread_attr_setstacksize;
|
||||
pthread_cond_broadcast;
|
||||
pthread_cond_destroy;
|
||||
@@ -1121,8 +1121,8 @@ LIBC {
|
||||
strncpy;
|
||||
strndup;
|
||||
strnlen;
|
||||
strntoimax; # arm x86 mips
|
||||
strntoumax; # arm x86 mips
|
||||
strntoimax; # arm x86 mips nobrillo
|
||||
strntoumax; # arm x86 mips nobrillo
|
||||
strpbrk;
|
||||
strptime;
|
||||
strrchr;
|
||||
@@ -1141,7 +1141,7 @@ LIBC {
|
||||
strtoll;
|
||||
strtoll_l;
|
||||
strtoq;
|
||||
strtotimeval; # arm x86 mips
|
||||
strtotimeval; # arm x86 mips nobrillo
|
||||
strtoul;
|
||||
strtoull;
|
||||
strtoull_l;
|
||||
@@ -1163,7 +1163,7 @@ LIBC {
|
||||
sysinfo;
|
||||
syslog;
|
||||
system;
|
||||
sysv_signal; # arm x86 mips
|
||||
sysv_signal; # arm x86 mips nobrillo
|
||||
tcdrain;
|
||||
tcflow;
|
||||
tcflush;
|
||||
@@ -1195,7 +1195,7 @@ LIBC {
|
||||
timerfd_settime;
|
||||
times;
|
||||
timezone;
|
||||
tkill; # arm x86 mips
|
||||
tkill; # arm x86 mips nobrillo
|
||||
tmpfile;
|
||||
tmpnam;
|
||||
toascii;
|
||||
@@ -1237,7 +1237,7 @@ LIBC {
|
||||
vdprintf;
|
||||
verr;
|
||||
verrx;
|
||||
vfdprintf; # arm x86 mips
|
||||
vfdprintf; # arm x86 mips nobrillo
|
||||
vfork;
|
||||
vfprintf;
|
||||
vfscanf;
|
||||
@@ -1257,7 +1257,7 @@ LIBC {
|
||||
vwprintf;
|
||||
vwscanf;
|
||||
wait;
|
||||
wait3; # arm x86 mips
|
||||
wait3; # arm x86 mips nobrillo
|
||||
wait4;
|
||||
waitid;
|
||||
waitpid;
|
||||
@@ -1306,7 +1306,7 @@ LIBC {
|
||||
wcstoull;
|
||||
wcstoull_l;
|
||||
wcstoumax;
|
||||
wcswcs; # arm x86 mips
|
||||
wcswcs; # arm x86 mips nobrillo
|
||||
wcswidth;
|
||||
wcsxfrm;
|
||||
wcsxfrm_l;
|
||||
@@ -1337,11 +1337,24 @@ LIBC_N {
|
||||
__pwrite_chk;
|
||||
__pwrite64_chk;
|
||||
__write_chk;
|
||||
fileno_unlocked;
|
||||
getgrgid_r;
|
||||
getgrnam_r;
|
||||
preadv;
|
||||
preadv64;
|
||||
prlimit; # arm mips x86
|
||||
pthread_barrierattr_destroy;
|
||||
pthread_barrierattr_getpshared;
|
||||
pthread_barrierattr_init;
|
||||
pthread_barrierattr_setpshared;
|
||||
pthread_barrier_destroy;
|
||||
pthread_barrier_init;
|
||||
pthread_barrier_wait;
|
||||
pthread_spin_destroy;
|
||||
pthread_spin_init;
|
||||
pthread_spin_lock;
|
||||
pthread_spin_trylock;
|
||||
pthread_spin_unlock;
|
||||
pwritev;
|
||||
pwritev64;
|
||||
scandirat;
|
||||
@@ -1425,7 +1438,6 @@ LIBC_PRIVATE {
|
||||
__ashrdi3; # arm
|
||||
__bionic_brk; # arm x86 mips
|
||||
__bionic_libgcc_compat_symbols; # arm x86
|
||||
__bionic_libgcc_unwind_symbols; # arm
|
||||
__dso_handle; # arm
|
||||
__gnu_Unwind_Backtrace; # arm
|
||||
__gnu_unwind_execute; # arm
|
||||
@@ -1461,10 +1473,10 @@ LIBC_PRIVATE {
|
||||
_Unwind_VRS_Pop; # arm
|
||||
_Unwind_VRS_Set; # arm
|
||||
atexit; # arm
|
||||
dlmalloc; # arm x86 mips
|
||||
dlmalloc_inspect_all;
|
||||
dlmalloc_trim;
|
||||
dlmalloc_usable_size; # arm x86 mips
|
||||
dlmalloc; # arm x86 mips nobrillo
|
||||
dlmalloc_inspect_all; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
dlmalloc_trim; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
dlmalloc_usable_size; # arm x86 mips nobrillo
|
||||
gMallocLeakZygoteChild;
|
||||
SHA1Final; # arm x86 mips
|
||||
SHA1Init; # arm x86 mips
|
||||
|
1276
libc/libc.mips.brillo.map
Normal file
1276
libc/libc.mips.brillo.map
Normal file
File diff suppressed because it is too large
Load Diff
@@ -38,12 +38,12 @@ LIBC {
|
||||
__freadable;
|
||||
__fsetlocking;
|
||||
__fstatfs64; # arm x86 mips
|
||||
__futex_wait; # arm x86 mips
|
||||
__futex_wake; # arm x86 mips
|
||||
__futex_wait; # arm x86 mips nobrillo
|
||||
__futex_wake; # arm x86 mips nobrillo
|
||||
__fwritable;
|
||||
__get_h_errno;
|
||||
__get_thread; # arm x86 mips
|
||||
__get_tls; # arm x86 mips
|
||||
__get_thread; # arm x86 mips nobrillo
|
||||
__get_tls; # arm x86 mips nobrillo
|
||||
__getcpu; # arm x86 mips
|
||||
__getcwd; # arm x86 mips
|
||||
__getdents64; # arm x86 mips
|
||||
@@ -101,7 +101,7 @@ LIBC {
|
||||
__ns_skiprr; # arm x86 mips
|
||||
__ns_sprintrr; # arm x86 mips
|
||||
__ns_sprintrrf; # arm x86 mips
|
||||
__open; # arm x86 mips
|
||||
__open; # arm x86 mips nobrillo
|
||||
__open_2;
|
||||
__openat; # arm x86 mips
|
||||
__openat_2;
|
||||
@@ -118,8 +118,8 @@ LIBC {
|
||||
__p_time;
|
||||
__p_type;
|
||||
__p_type_syms;
|
||||
__page_shift; # arm x86 mips
|
||||
__page_size; # arm x86 mips
|
||||
__page_shift; # arm x86 mips nobrillo
|
||||
__page_size; # arm x86 mips nobrillo
|
||||
__poll_chk;
|
||||
__popcountsi2; # arm x86 mips
|
||||
__ppoll; # arm x86 mips
|
||||
@@ -130,7 +130,7 @@ LIBC {
|
||||
__pselect6; # arm x86 mips
|
||||
__pthread_cleanup_pop;
|
||||
__pthread_cleanup_push;
|
||||
__pthread_gettid; # arm x86 mips
|
||||
__pthread_gettid; # arm x86 mips nobrillo
|
||||
__ptrace; # arm x86 mips
|
||||
__putlong;
|
||||
__putshort;
|
||||
@@ -170,8 +170,8 @@ LIBC {
|
||||
__sched_cpufree;
|
||||
__sched_getaffinity; # arm x86 mips
|
||||
__sclose; # arm x86 mips
|
||||
__sdidinit; # arm x86 mips
|
||||
__set_errno; # arm x86 mips
|
||||
__sdidinit; # arm x86 mips nobrillo
|
||||
__set_errno; # arm x86 mips nobrillo
|
||||
__set_tid_address; # arm x86 mips
|
||||
__set_tls; # arm mips
|
||||
__sF;
|
||||
@@ -181,7 +181,7 @@ LIBC {
|
||||
__sglue; # arm x86 mips
|
||||
__sigaction; # arm x86 mips
|
||||
__signalfd4; # arm x86 mips
|
||||
__sinit; # arm x86 mips
|
||||
__sinit; # arm x86 mips nobrillo
|
||||
__smakebuf; # arm x86 mips
|
||||
__snprintf_chk;
|
||||
__socket; # arm x86 mips
|
||||
@@ -237,7 +237,7 @@ LIBC {
|
||||
__umoddi3; # x86 mips
|
||||
__vsnprintf_chk;
|
||||
__vsprintf_chk;
|
||||
__wait4; # arm x86 mips
|
||||
__wait4; # arm x86 mips nobrillo
|
||||
__waitid; # arm x86 mips
|
||||
_ctype_;
|
||||
_Exit;
|
||||
@@ -271,9 +271,9 @@ LIBC {
|
||||
android_gethostbynamefornet;
|
||||
android_set_abort_message;
|
||||
arc4random;
|
||||
arc4random_addrandom; # arm x86 mips
|
||||
arc4random_addrandom; # arm x86 mips nobrillo
|
||||
arc4random_buf;
|
||||
arc4random_stir; # arm x86 mips
|
||||
arc4random_stir; # arm x86 mips nobrillo
|
||||
arc4random_uniform;
|
||||
asctime;
|
||||
asctime64; # arm x86 mips
|
||||
@@ -287,11 +287,11 @@ LIBC {
|
||||
atoll;
|
||||
basename;
|
||||
basename_r; # arm x86 mips
|
||||
bcopy; # arm x86 mips
|
||||
bcopy; # arm x86 mips nobrillo
|
||||
bind;
|
||||
bindresvport;
|
||||
brk;
|
||||
bsd_signal; # arm x86 mips
|
||||
bsd_signal; # arm x86 mips nobrillo
|
||||
bsearch;
|
||||
btowc;
|
||||
bzero; # arm x86 mips
|
||||
@@ -347,7 +347,7 @@ LIBC {
|
||||
dup3;
|
||||
duplocale;
|
||||
endmntent;
|
||||
endpwent;
|
||||
endpwent; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
endservent;
|
||||
endutent;
|
||||
environ;
|
||||
@@ -394,7 +394,7 @@ LIBC {
|
||||
fdatasync;
|
||||
fdopen;
|
||||
fdopendir;
|
||||
fdprintf; # arm x86 mips
|
||||
fdprintf; # arm x86 mips nobrillo
|
||||
feof;
|
||||
feof_unlocked;
|
||||
ferror;
|
||||
@@ -447,7 +447,7 @@ LIBC {
|
||||
fsync;
|
||||
ftell;
|
||||
ftello;
|
||||
ftime; # arm x86 mips
|
||||
ftime; # arm x86 mips nobrillo
|
||||
ftok;
|
||||
ftruncate;
|
||||
ftruncate64;
|
||||
@@ -480,8 +480,8 @@ LIBC {
|
||||
getchar_unlocked;
|
||||
getcwd;
|
||||
getdelim;
|
||||
getdents; # arm x86 mips
|
||||
getdtablesize; # arm x86 mips
|
||||
getdents; # arm x86 mips nobrillo
|
||||
getdtablesize; # arm x86 mips nobrillo
|
||||
getegid;
|
||||
getenv;
|
||||
geteuid;
|
||||
@@ -556,7 +556,7 @@ LIBC {
|
||||
if_nametoindex;
|
||||
imaxabs;
|
||||
imaxdiv;
|
||||
index; # arm x86 mips
|
||||
index; # arm x86 mips nobrillo
|
||||
inet_addr;
|
||||
inet_aton;
|
||||
inet_lnaof;
|
||||
@@ -609,7 +609,7 @@ LIBC {
|
||||
isprint_l;
|
||||
ispunct;
|
||||
ispunct_l;
|
||||
issetugid; # arm x86 mips
|
||||
issetugid; # arm x86 mips nobrillo
|
||||
isspace;
|
||||
isspace_l;
|
||||
isupper;
|
||||
@@ -699,7 +699,7 @@ LIBC {
|
||||
mempcpy;
|
||||
memrchr;
|
||||
memset;
|
||||
memswap; # arm x86 mips
|
||||
memswap; # arm x86 mips nobrillo
|
||||
mincore;
|
||||
mkdir;
|
||||
mkdirat;
|
||||
@@ -790,7 +790,7 @@ LIBC {
|
||||
pthread_attr_getschedpolicy;
|
||||
pthread_attr_getscope;
|
||||
pthread_attr_getstack;
|
||||
pthread_attr_getstackaddr; # arm x86 mips
|
||||
pthread_attr_getstackaddr; # arm x86 mips nobrillo
|
||||
pthread_attr_getstacksize;
|
||||
pthread_attr_init;
|
||||
pthread_attr_setdetachstate;
|
||||
@@ -799,7 +799,7 @@ LIBC {
|
||||
pthread_attr_setschedpolicy;
|
||||
pthread_attr_setscope;
|
||||
pthread_attr_setstack;
|
||||
pthread_attr_setstackaddr; # arm x86 mips
|
||||
pthread_attr_setstackaddr; # arm x86 mips nobrillo
|
||||
pthread_attr_setstacksize;
|
||||
pthread_cond_broadcast;
|
||||
pthread_cond_destroy;
|
||||
@@ -1057,8 +1057,8 @@ LIBC {
|
||||
strncpy;
|
||||
strndup;
|
||||
strnlen;
|
||||
strntoimax; # arm x86 mips
|
||||
strntoumax; # arm x86 mips
|
||||
strntoimax; # arm x86 mips nobrillo
|
||||
strntoumax; # arm x86 mips nobrillo
|
||||
strpbrk;
|
||||
strptime;
|
||||
strrchr;
|
||||
@@ -1077,7 +1077,7 @@ LIBC {
|
||||
strtoll;
|
||||
strtoll_l;
|
||||
strtoq;
|
||||
strtotimeval; # arm x86 mips
|
||||
strtotimeval; # arm x86 mips nobrillo
|
||||
strtoul;
|
||||
strtoull;
|
||||
strtoull_l;
|
||||
@@ -1099,7 +1099,7 @@ LIBC {
|
||||
sysinfo;
|
||||
syslog;
|
||||
system;
|
||||
sysv_signal; # arm x86 mips
|
||||
sysv_signal; # arm x86 mips nobrillo
|
||||
tcdrain;
|
||||
tcflow;
|
||||
tcflush;
|
||||
@@ -1131,7 +1131,7 @@ LIBC {
|
||||
timerfd_settime;
|
||||
times;
|
||||
timezone;
|
||||
tkill; # arm x86 mips
|
||||
tkill; # arm x86 mips nobrillo
|
||||
tmpfile;
|
||||
tmpnam;
|
||||
toascii;
|
||||
@@ -1173,7 +1173,7 @@ LIBC {
|
||||
vdprintf;
|
||||
verr;
|
||||
verrx;
|
||||
vfdprintf; # arm x86 mips
|
||||
vfdprintf; # arm x86 mips nobrillo
|
||||
vfork;
|
||||
vfprintf;
|
||||
vfscanf;
|
||||
@@ -1193,7 +1193,7 @@ LIBC {
|
||||
vwprintf;
|
||||
vwscanf;
|
||||
wait;
|
||||
wait3; # arm x86 mips
|
||||
wait3; # arm x86 mips nobrillo
|
||||
wait4;
|
||||
waitid;
|
||||
waitpid;
|
||||
@@ -1242,7 +1242,7 @@ LIBC {
|
||||
wcstoull;
|
||||
wcstoull_l;
|
||||
wcstoumax;
|
||||
wcswcs; # arm x86 mips
|
||||
wcswcs; # arm x86 mips nobrillo
|
||||
wcswidth;
|
||||
wcsxfrm;
|
||||
wcsxfrm_l;
|
||||
@@ -1273,11 +1273,24 @@ LIBC_N {
|
||||
__pwrite_chk;
|
||||
__pwrite64_chk;
|
||||
__write_chk;
|
||||
fileno_unlocked;
|
||||
getgrgid_r;
|
||||
getgrnam_r;
|
||||
preadv;
|
||||
preadv64;
|
||||
prlimit; # arm mips x86
|
||||
pthread_barrierattr_destroy;
|
||||
pthread_barrierattr_getpshared;
|
||||
pthread_barrierattr_init;
|
||||
pthread_barrierattr_setpshared;
|
||||
pthread_barrier_destroy;
|
||||
pthread_barrier_init;
|
||||
pthread_barrier_wait;
|
||||
pthread_spin_destroy;
|
||||
pthread_spin_init;
|
||||
pthread_spin_lock;
|
||||
pthread_spin_trylock;
|
||||
pthread_spin_unlock;
|
||||
pwritev;
|
||||
pwritev64;
|
||||
scandirat;
|
||||
@@ -1289,10 +1302,10 @@ LIBC_PRIVATE {
|
||||
global:
|
||||
__accept4; # arm x86 mips
|
||||
__bionic_brk; # arm x86 mips
|
||||
dlmalloc; # arm x86 mips
|
||||
dlmalloc_inspect_all;
|
||||
dlmalloc_trim;
|
||||
dlmalloc_usable_size; # arm x86 mips
|
||||
dlmalloc; # arm x86 mips nobrillo
|
||||
dlmalloc_inspect_all; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
dlmalloc_trim; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
dlmalloc_usable_size; # arm x86 mips nobrillo
|
||||
gMallocLeakZygoteChild;
|
||||
SHA1Final; # arm x86 mips
|
||||
SHA1Init; # arm x86 mips
|
||||
|
1185
libc/libc.mips64.brillo.map
Normal file
1185
libc/libc.mips64.brillo.map
Normal file
File diff suppressed because it is too large
Load Diff
@@ -241,7 +241,7 @@ LIBC {
|
||||
dup3;
|
||||
duplocale;
|
||||
endmntent;
|
||||
endpwent;
|
||||
endpwent; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
endservent;
|
||||
endutent;
|
||||
environ;
|
||||
@@ -1156,10 +1156,23 @@ LIBC_N {
|
||||
__pwrite_chk;
|
||||
__pwrite64_chk;
|
||||
__write_chk;
|
||||
fileno_unlocked;
|
||||
getgrgid_r;
|
||||
getgrnam_r;
|
||||
preadv;
|
||||
preadv64;
|
||||
pthread_barrierattr_destroy;
|
||||
pthread_barrierattr_getpshared;
|
||||
pthread_barrierattr_init;
|
||||
pthread_barrierattr_setpshared;
|
||||
pthread_barrier_destroy;
|
||||
pthread_barrier_init;
|
||||
pthread_barrier_wait;
|
||||
pthread_spin_destroy;
|
||||
pthread_spin_init;
|
||||
pthread_spin_lock;
|
||||
pthread_spin_trylock;
|
||||
pthread_spin_unlock;
|
||||
pwritev;
|
||||
pwritev64;
|
||||
scandirat;
|
||||
@@ -1169,7 +1182,7 @@ LIBC_N {
|
||||
|
||||
LIBC_PRIVATE {
|
||||
global:
|
||||
dlmalloc_inspect_all;
|
||||
dlmalloc_trim;
|
||||
dlmalloc_inspect_all; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
dlmalloc_trim; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
gMallocLeakZygoteChild;
|
||||
} LIBC_N;
|
||||
|
1275
libc/libc.x86.brillo.map
Normal file
1275
libc/libc.x86.brillo.map
Normal file
File diff suppressed because it is too large
Load Diff
@@ -38,12 +38,12 @@ LIBC {
|
||||
__freadable;
|
||||
__fsetlocking;
|
||||
__fstatfs64; # arm x86 mips
|
||||
__futex_wait; # arm x86 mips
|
||||
__futex_wake; # arm x86 mips
|
||||
__futex_wait; # arm x86 mips nobrillo
|
||||
__futex_wake; # arm x86 mips nobrillo
|
||||
__fwritable;
|
||||
__get_h_errno;
|
||||
__get_thread; # arm x86 mips
|
||||
__get_tls; # arm x86 mips
|
||||
__get_thread; # arm x86 mips nobrillo
|
||||
__get_tls; # arm x86 mips nobrillo
|
||||
__getcpu; # arm x86 mips
|
||||
__getcwd; # arm x86 mips
|
||||
__getdents64; # arm x86 mips
|
||||
@@ -101,7 +101,7 @@ LIBC {
|
||||
__ns_skiprr; # arm x86 mips
|
||||
__ns_sprintrr; # arm x86 mips
|
||||
__ns_sprintrrf; # arm x86 mips
|
||||
__open; # arm x86 mips
|
||||
__open; # arm x86 mips nobrillo
|
||||
__open_2;
|
||||
__openat; # arm x86 mips
|
||||
__openat_2;
|
||||
@@ -118,8 +118,8 @@ LIBC {
|
||||
__p_time;
|
||||
__p_type;
|
||||
__p_type_syms;
|
||||
__page_shift; # arm x86 mips
|
||||
__page_size; # arm x86 mips
|
||||
__page_shift; # arm x86 mips nobrillo
|
||||
__page_size; # arm x86 mips nobrillo
|
||||
__poll_chk;
|
||||
__popcountsi2; # arm x86 mips
|
||||
__ppoll; # arm x86 mips
|
||||
@@ -130,7 +130,7 @@ LIBC {
|
||||
__pselect6; # arm x86 mips
|
||||
__pthread_cleanup_pop;
|
||||
__pthread_cleanup_push;
|
||||
__pthread_gettid; # arm x86 mips
|
||||
__pthread_gettid; # arm x86 mips nobrillo
|
||||
__ptrace; # arm x86 mips
|
||||
__putlong;
|
||||
__putshort;
|
||||
@@ -170,8 +170,8 @@ LIBC {
|
||||
__sched_cpufree;
|
||||
__sched_getaffinity; # arm x86 mips
|
||||
__sclose; # arm x86 mips
|
||||
__sdidinit; # arm x86 mips
|
||||
__set_errno; # arm x86 mips
|
||||
__sdidinit; # arm x86 mips nobrillo
|
||||
__set_errno; # arm x86 mips nobrillo
|
||||
__set_thread_area; # x86
|
||||
__set_tid_address; # arm x86 mips
|
||||
__sF;
|
||||
@@ -181,7 +181,7 @@ LIBC {
|
||||
__sglue; # arm x86 mips
|
||||
__sigaction; # arm x86 mips
|
||||
__signalfd4; # arm x86 mips
|
||||
__sinit; # arm x86 mips
|
||||
__sinit; # arm x86 mips nobrillo
|
||||
__smakebuf; # arm x86 mips
|
||||
__snprintf_chk;
|
||||
__socket; # arm x86 mips
|
||||
@@ -237,7 +237,7 @@ LIBC {
|
||||
__umoddi3; # x86 mips
|
||||
__vsnprintf_chk;
|
||||
__vsprintf_chk;
|
||||
__wait4; # arm x86 mips
|
||||
__wait4; # arm x86 mips nobrillo
|
||||
__waitid; # arm x86 mips
|
||||
_ctype_;
|
||||
_Exit;
|
||||
@@ -270,9 +270,9 @@ LIBC {
|
||||
android_gethostbynamefornet;
|
||||
android_set_abort_message;
|
||||
arc4random;
|
||||
arc4random_addrandom; # arm x86 mips
|
||||
arc4random_addrandom; # arm x86 mips nobrillo
|
||||
arc4random_buf;
|
||||
arc4random_stir; # arm x86 mips
|
||||
arc4random_stir; # arm x86 mips nobrillo
|
||||
arc4random_uniform;
|
||||
asctime;
|
||||
asctime64; # arm x86 mips
|
||||
@@ -286,11 +286,11 @@ LIBC {
|
||||
atoll;
|
||||
basename;
|
||||
basename_r; # arm x86 mips
|
||||
bcopy; # arm x86 mips
|
||||
bcopy; # arm x86 mips nobrillo
|
||||
bind;
|
||||
bindresvport;
|
||||
brk;
|
||||
bsd_signal; # arm x86 mips
|
||||
bsd_signal; # arm x86 mips nobrillo
|
||||
bsearch;
|
||||
btowc;
|
||||
bzero; # arm x86 mips
|
||||
@@ -345,7 +345,7 @@ LIBC {
|
||||
dup3;
|
||||
duplocale;
|
||||
endmntent;
|
||||
endpwent;
|
||||
endpwent; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
endservent;
|
||||
endutent;
|
||||
environ;
|
||||
@@ -392,7 +392,7 @@ LIBC {
|
||||
fdatasync;
|
||||
fdopen;
|
||||
fdopendir;
|
||||
fdprintf; # arm x86 mips
|
||||
fdprintf; # arm x86 mips nobrillo
|
||||
feof;
|
||||
feof_unlocked;
|
||||
ferror;
|
||||
@@ -445,7 +445,7 @@ LIBC {
|
||||
fsync;
|
||||
ftell;
|
||||
ftello;
|
||||
ftime; # arm x86 mips
|
||||
ftime; # arm x86 mips nobrillo
|
||||
ftok;
|
||||
ftruncate;
|
||||
ftruncate64;
|
||||
@@ -478,8 +478,8 @@ LIBC {
|
||||
getchar_unlocked;
|
||||
getcwd;
|
||||
getdelim;
|
||||
getdents; # arm x86 mips
|
||||
getdtablesize; # arm x86 mips
|
||||
getdents; # arm x86 mips nobrillo
|
||||
getdtablesize; # arm x86 mips nobrillo
|
||||
getegid;
|
||||
getenv;
|
||||
geteuid;
|
||||
@@ -554,7 +554,7 @@ LIBC {
|
||||
if_nametoindex;
|
||||
imaxabs;
|
||||
imaxdiv;
|
||||
index; # arm x86 mips
|
||||
index; # arm x86 mips nobrillo
|
||||
inet_addr;
|
||||
inet_aton;
|
||||
inet_lnaof;
|
||||
@@ -607,7 +607,7 @@ LIBC {
|
||||
isprint_l;
|
||||
ispunct;
|
||||
ispunct_l;
|
||||
issetugid; # arm x86 mips
|
||||
issetugid; # arm x86 mips nobrillo
|
||||
isspace;
|
||||
isspace_l;
|
||||
isupper;
|
||||
@@ -697,7 +697,7 @@ LIBC {
|
||||
mempcpy;
|
||||
memrchr;
|
||||
memset;
|
||||
memswap; # arm x86 mips
|
||||
memswap; # arm x86 mips nobrillo
|
||||
mincore;
|
||||
mkdir;
|
||||
mkdirat;
|
||||
@@ -788,7 +788,7 @@ LIBC {
|
||||
pthread_attr_getschedpolicy;
|
||||
pthread_attr_getscope;
|
||||
pthread_attr_getstack;
|
||||
pthread_attr_getstackaddr; # arm x86 mips
|
||||
pthread_attr_getstackaddr; # arm x86 mips nobrillo
|
||||
pthread_attr_getstacksize;
|
||||
pthread_attr_init;
|
||||
pthread_attr_setdetachstate;
|
||||
@@ -797,7 +797,7 @@ LIBC {
|
||||
pthread_attr_setschedpolicy;
|
||||
pthread_attr_setscope;
|
||||
pthread_attr_setstack;
|
||||
pthread_attr_setstackaddr; # arm x86 mips
|
||||
pthread_attr_setstackaddr; # arm x86 mips nobrillo
|
||||
pthread_attr_setstacksize;
|
||||
pthread_cond_broadcast;
|
||||
pthread_cond_destroy;
|
||||
@@ -1055,8 +1055,8 @@ LIBC {
|
||||
strncpy;
|
||||
strndup;
|
||||
strnlen;
|
||||
strntoimax; # arm x86 mips
|
||||
strntoumax; # arm x86 mips
|
||||
strntoimax; # arm x86 mips nobrillo
|
||||
strntoumax; # arm x86 mips nobrillo
|
||||
strpbrk;
|
||||
strptime;
|
||||
strrchr;
|
||||
@@ -1075,7 +1075,7 @@ LIBC {
|
||||
strtoll;
|
||||
strtoll_l;
|
||||
strtoq;
|
||||
strtotimeval; # arm x86 mips
|
||||
strtotimeval; # arm x86 mips nobrillo
|
||||
strtoul;
|
||||
strtoull;
|
||||
strtoull_l;
|
||||
@@ -1097,7 +1097,7 @@ LIBC {
|
||||
sysinfo;
|
||||
syslog;
|
||||
system;
|
||||
sysv_signal; # arm x86 mips
|
||||
sysv_signal; # arm x86 mips nobrillo
|
||||
tcdrain;
|
||||
tcflow;
|
||||
tcflush;
|
||||
@@ -1129,7 +1129,7 @@ LIBC {
|
||||
timerfd_settime;
|
||||
times;
|
||||
timezone;
|
||||
tkill; # arm x86 mips
|
||||
tkill; # arm x86 mips nobrillo
|
||||
tmpfile;
|
||||
tmpnam;
|
||||
toascii;
|
||||
@@ -1171,7 +1171,7 @@ LIBC {
|
||||
vdprintf;
|
||||
verr;
|
||||
verrx;
|
||||
vfdprintf; # arm x86 mips
|
||||
vfdprintf; # arm x86 mips nobrillo
|
||||
vfork;
|
||||
vfprintf;
|
||||
vfscanf;
|
||||
@@ -1191,7 +1191,7 @@ LIBC {
|
||||
vwprintf;
|
||||
vwscanf;
|
||||
wait;
|
||||
wait3; # arm x86 mips
|
||||
wait3; # arm x86 mips nobrillo
|
||||
wait4;
|
||||
waitid;
|
||||
waitpid;
|
||||
@@ -1240,7 +1240,7 @@ LIBC {
|
||||
wcstoull;
|
||||
wcstoull_l;
|
||||
wcstoumax;
|
||||
wcswcs; # arm x86 mips
|
||||
wcswcs; # arm x86 mips nobrillo
|
||||
wcswidth;
|
||||
wcsxfrm;
|
||||
wcsxfrm_l;
|
||||
@@ -1271,11 +1271,24 @@ LIBC_N {
|
||||
__pwrite_chk;
|
||||
__pwrite64_chk;
|
||||
__write_chk;
|
||||
fileno_unlocked;
|
||||
getgrgid_r;
|
||||
getgrnam_r;
|
||||
preadv;
|
||||
preadv64;
|
||||
prlimit; # arm mips x86
|
||||
pthread_barrierattr_destroy;
|
||||
pthread_barrierattr_getpshared;
|
||||
pthread_barrierattr_init;
|
||||
pthread_barrierattr_setpshared;
|
||||
pthread_barrier_destroy;
|
||||
pthread_barrier_init;
|
||||
pthread_barrier_wait;
|
||||
pthread_spin_destroy;
|
||||
pthread_spin_init;
|
||||
pthread_spin_lock;
|
||||
pthread_spin_trylock;
|
||||
pthread_spin_unlock;
|
||||
pwritev;
|
||||
pwritev64;
|
||||
scandirat;
|
||||
@@ -1288,10 +1301,10 @@ LIBC_PRIVATE {
|
||||
__accept4; # arm x86 mips
|
||||
__bionic_brk; # arm x86 mips
|
||||
__bionic_libgcc_compat_symbols; # arm x86
|
||||
dlmalloc; # arm x86 mips
|
||||
dlmalloc_inspect_all;
|
||||
dlmalloc_trim;
|
||||
dlmalloc_usable_size; # arm x86 mips
|
||||
dlmalloc; # arm x86 mips nobrillo
|
||||
dlmalloc_inspect_all; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
dlmalloc_trim; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
dlmalloc_usable_size; # arm x86 mips nobrillo
|
||||
gMallocLeakZygoteChild;
|
||||
SHA1Final; # arm x86 mips
|
||||
SHA1Init; # arm x86 mips
|
||||
|
1185
libc/libc.x86_64.brillo.map
Normal file
1185
libc/libc.x86_64.brillo.map
Normal file
File diff suppressed because it is too large
Load Diff
@@ -241,7 +241,7 @@ LIBC {
|
||||
dup3;
|
||||
duplocale;
|
||||
endmntent;
|
||||
endpwent;
|
||||
endpwent; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
endservent;
|
||||
endutent;
|
||||
environ;
|
||||
@@ -1156,10 +1156,23 @@ LIBC_N {
|
||||
__pwrite_chk;
|
||||
__pwrite64_chk;
|
||||
__write_chk;
|
||||
fileno_unlocked;
|
||||
getgrgid_r;
|
||||
getgrnam_r;
|
||||
preadv;
|
||||
preadv64;
|
||||
pthread_barrierattr_destroy;
|
||||
pthread_barrierattr_getpshared;
|
||||
pthread_barrierattr_init;
|
||||
pthread_barrierattr_setpshared;
|
||||
pthread_barrier_destroy;
|
||||
pthread_barrier_init;
|
||||
pthread_barrier_wait;
|
||||
pthread_spin_destroy;
|
||||
pthread_spin_init;
|
||||
pthread_spin_lock;
|
||||
pthread_spin_trylock;
|
||||
pthread_spin_unlock;
|
||||
pwritev;
|
||||
pwritev64;
|
||||
scandirat;
|
||||
@@ -1169,7 +1182,7 @@ LIBC_N {
|
||||
|
||||
LIBC_PRIVATE {
|
||||
global:
|
||||
dlmalloc_inspect_all;
|
||||
dlmalloc_trim;
|
||||
dlmalloc_inspect_all; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
dlmalloc_trim; # arm arm64 x86 x86_64 mips mips64 nobrillo
|
||||
gMallocLeakZygoteChild;
|
||||
} LIBC_N;
|
||||
|
@@ -34,7 +34,7 @@ class ScopedPthreadMutexLocker {
|
||||
private:
|
||||
pthread_mutex_t* mu_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ScopedPthreadMutexLocker);
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedPthreadMutexLocker);
|
||||
};
|
||||
|
||||
#endif // SCOPED_PTHREAD_MUTEX_LOCKER_H
|
||||
|
@@ -40,10 +40,12 @@ __BEGIN_DECLS
|
||||
|
||||
struct timespec;
|
||||
|
||||
static inline __always_inline int __futex(volatile void* ftx, int op, int value, const struct timespec* timeout) {
|
||||
static inline __always_inline int __futex(volatile void* ftx, int op, int value,
|
||||
const struct timespec* timeout,
|
||||
int bitset) {
|
||||
// Our generated syscall assembler sets errno, but our callers (pthread functions) don't want to.
|
||||
int saved_errno = errno;
|
||||
int result = syscall(__NR_futex, ftx, op, value, timeout);
|
||||
int result = syscall(__NR_futex, ftx, op, value, timeout, NULL, bitset);
|
||||
if (__predict_false(result == -1)) {
|
||||
result = -errno;
|
||||
errno = saved_errno;
|
||||
@@ -52,19 +54,22 @@ static inline __always_inline int __futex(volatile void* ftx, int op, int value,
|
||||
}
|
||||
|
||||
static inline int __futex_wake(volatile void* ftx, int count) {
|
||||
return __futex(ftx, FUTEX_WAKE, count, NULL);
|
||||
return __futex(ftx, FUTEX_WAKE, count, NULL, 0);
|
||||
}
|
||||
|
||||
static inline int __futex_wake_ex(volatile void* ftx, bool shared, int count) {
|
||||
return __futex(ftx, shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, count, NULL);
|
||||
return __futex(ftx, shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, count, NULL, 0);
|
||||
}
|
||||
|
||||
static inline int __futex_wait(volatile void* ftx, int value, const struct timespec* timeout) {
|
||||
return __futex(ftx, FUTEX_WAIT, value, timeout);
|
||||
return __futex(ftx, FUTEX_WAIT, value, timeout, 0);
|
||||
}
|
||||
|
||||
static inline int __futex_wait_ex(volatile void* ftx, bool shared, int value, const struct timespec* timeout) {
|
||||
return __futex(ftx, shared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE, value, timeout);
|
||||
static inline int __futex_wait_ex(volatile void* ftx, bool shared, int value,
|
||||
bool use_realtime_clock, const struct timespec* abs_timeout) {
|
||||
return __futex(ftx, (shared ? FUTEX_WAIT_BITSET : FUTEX_WAIT_BITSET_PRIVATE) |
|
||||
(use_realtime_clock ? FUTEX_CLOCK_REALTIME : 0), value, abs_timeout,
|
||||
FUTEX_BITSET_MATCH_ANY);
|
||||
}
|
||||
|
||||
__END_DECLS
|
||||
|
@@ -30,6 +30,7 @@
|
||||
|
||||
#include <stdatomic.h>
|
||||
#include "private/bionic_futex.h"
|
||||
#include "private/bionic_macros.h"
|
||||
|
||||
// Lock is used in places like pthread_rwlock_t, which can be initialized without calling
|
||||
// an initialization function. So make sure Lock can be initialized by setting its memory to 0.
|
||||
@@ -49,6 +50,12 @@ class Lock {
|
||||
this->process_shared = process_shared;
|
||||
}
|
||||
|
||||
bool trylock() {
|
||||
LockState old_state = Unlocked;
|
||||
return __predict_true(atomic_compare_exchange_strong_explicit(&state, &old_state,
|
||||
LockedWithoutWaiter, memory_order_acquire, memory_order_relaxed));
|
||||
}
|
||||
|
||||
void lock() {
|
||||
LockState old_state = Unlocked;
|
||||
if (__predict_true(atomic_compare_exchange_strong_explicit(&state, &old_state,
|
||||
@@ -57,7 +64,7 @@ class Lock {
|
||||
}
|
||||
while (atomic_exchange_explicit(&state, LockedWithWaiter, memory_order_acquire) != Unlocked) {
|
||||
// TODO: As the critical section is brief, it is a better choice to spin a few times befor sleeping.
|
||||
__futex_wait_ex(&state, process_shared, LockedWithWaiter, NULL);
|
||||
__futex_wait_ex(&state, process_shared, LockedWithWaiter, false, nullptr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@@ -29,9 +29,12 @@
|
||||
#ifndef _BIONIC_TIME_CONVERSIONS_H
|
||||
#define _BIONIC_TIME_CONVERSIONS_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include "private/bionic_constants.h"
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
__LIBC_HIDDEN__ bool timespec_from_timeval(timespec& ts, const timeval& tv);
|
||||
@@ -39,8 +42,21 @@ __LIBC_HIDDEN__ void timespec_from_ms(timespec& ts, const int ms);
|
||||
|
||||
__LIBC_HIDDEN__ void timeval_from_timespec(timeval& tv, const timespec& ts);
|
||||
|
||||
__LIBC_HIDDEN__ bool timespec_from_absolute_timespec(timespec& ts, const timespec& abs_ts, clockid_t clock);
|
||||
__LIBC_HIDDEN__ void absolute_timespec_from_timespec(timespec& abs_ts, const timespec& ts,
|
||||
clockid_t clock);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
static inline int check_timespec(const timespec* ts) {
|
||||
if (ts != nullptr) {
|
||||
if (ts->tv_nsec < 0 || ts->tv_nsec >= NS_PER_S) {
|
||||
return EINVAL;
|
||||
}
|
||||
if (ts->tv_sec < 0) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -44,37 +44,44 @@
|
||||
#define ALIGNBYTES (sizeof(uintptr_t) - 1)
|
||||
#define ALIGN(p) (((uintptr_t)(p) + ALIGNBYTES) &~ ALIGNBYTES)
|
||||
|
||||
int __sdidinit;
|
||||
|
||||
#define NDYNAMIC 10 /* add ten more whenever necessary */
|
||||
|
||||
#define std(flags, file) \
|
||||
{0,0,0,flags,file,{0,0},0,__sF+file,__sclose,__sread,__sseek,__swrite, \
|
||||
{(unsigned char *)(__sFext+file), 0},NULL,0,{0},{0},{0,0},0,0}
|
||||
|
||||
/* the usual - (stdin + stdout + stderr) */
|
||||
static FILE usual[FOPEN_MAX - 3];
|
||||
static struct __sfileext usualext[FOPEN_MAX - 3];
|
||||
static struct glue uglue = { 0, FOPEN_MAX - 3, usual };
|
||||
static struct glue *lastglue = &uglue;
|
||||
_THREAD_PRIVATE_MUTEX(__sfp_mutex);
|
||||
|
||||
static struct __sfileext __sFext[3];
|
||||
// TODO: when we no longer have to support both clang and GCC, we can simplify all this.
|
||||
#define SBUF_INIT {0,0}
|
||||
#if defined(__LP64__)
|
||||
#define MBSTATE_T_INIT {{0},{0}}
|
||||
#else
|
||||
#define MBSTATE_T_INIT {{0}}
|
||||
#endif
|
||||
#define WCHAR_IO_DATA_INIT {MBSTATE_T_INIT,MBSTATE_T_INIT,{0},0,0}
|
||||
|
||||
static struct __sfileext __sFext[3] = {
|
||||
{ SBUF_INIT, WCHAR_IO_DATA_INIT, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, false },
|
||||
{ SBUF_INIT, WCHAR_IO_DATA_INIT, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, false },
|
||||
{ SBUF_INIT, WCHAR_IO_DATA_INIT, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, false },
|
||||
};
|
||||
|
||||
// __sF is exported for backwards compatibility. Until M, we didn't have symbols
|
||||
// for stdin/stdout/stderr; they were macros accessing __sF.
|
||||
FILE __sF[3] = {
|
||||
std(__SRD, STDIN_FILENO), /* stdin */
|
||||
std(__SWR, STDOUT_FILENO), /* stdout */
|
||||
std(__SWR|__SNBF, STDERR_FILENO) /* stderr */
|
||||
std(__SRD, STDIN_FILENO),
|
||||
std(__SWR, STDOUT_FILENO),
|
||||
std(__SWR|__SNBF, STDERR_FILENO),
|
||||
};
|
||||
|
||||
struct glue __sglue = { &uglue, 3, __sF };
|
||||
|
||||
FILE* stdin = &__sF[0];
|
||||
FILE* stdout = &__sF[1];
|
||||
FILE* stderr = &__sF[2];
|
||||
|
||||
struct glue __sglue = { NULL, 3, __sF };
|
||||
static struct glue* lastglue = &__sglue;
|
||||
|
||||
static struct glue *
|
||||
moreglue(int n)
|
||||
{
|
||||
@@ -114,9 +121,6 @@ __sfp(void)
|
||||
int n;
|
||||
struct glue *g;
|
||||
|
||||
if (!__sdidinit)
|
||||
__sinit();
|
||||
|
||||
_THREAD_PRIVATE_MUTEX_LOCK(__sfp_mutex);
|
||||
for (g = &__sglue; g != NULL; g = g->next) {
|
||||
for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
|
||||
@@ -149,48 +153,7 @@ found:
|
||||
return (fp);
|
||||
}
|
||||
|
||||
/*
|
||||
* exit() and abort() call _cleanup() through the callback registered
|
||||
* with __atexit_register_cleanup(), set whenever we open or buffer a
|
||||
* file. This chicanery is done so that programs that do not use stdio
|
||||
* need not link it all in.
|
||||
*
|
||||
* The name `_cleanup' is, alas, fairly well known outside stdio.
|
||||
*/
|
||||
void
|
||||
_cleanup(void)
|
||||
{
|
||||
__LIBC_HIDDEN__ void __libc_stdio_cleanup(void) {
|
||||
/* (void) _fwalk(fclose); */
|
||||
(void) _fwalk(__sflush); /* `cheating' */
|
||||
}
|
||||
|
||||
/*
|
||||
* __sinit() is called whenever stdio's internal variables must be set up.
|
||||
*/
|
||||
void
|
||||
__sinit(void)
|
||||
{
|
||||
_THREAD_PRIVATE_MUTEX(__sinit_mutex);
|
||||
|
||||
_THREAD_PRIVATE_MUTEX_LOCK(__sinit_mutex);
|
||||
if (__sdidinit) {
|
||||
/* bail out if caller lost the race */
|
||||
_THREAD_PRIVATE_MUTEX_UNLOCK(__sinit_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize stdin/stdout/stderr (for the recursive mutex). http://b/18208568. */
|
||||
for (size_t i = 0; i < 3; ++i) {
|
||||
_FILEEXT_SETUP(__sF+i, __sFext+i);
|
||||
}
|
||||
/* Initialize the pre-allocated (but initially unused) streams. */
|
||||
for (size_t i = 0; i < FOPEN_MAX - 3; ++i) {
|
||||
_FILEEXT_SETUP(usual+i, usualext+i);
|
||||
}
|
||||
|
||||
/* make sure we clean up on exit */
|
||||
__atexit_register_cleanup(_cleanup); /* conservative */
|
||||
__sdidinit = 1;
|
||||
|
||||
_THREAD_PRIVATE_MUTEX_UNLOCK(__sinit_mutex);
|
||||
}
|
||||
|
@@ -109,7 +109,7 @@ struct __sfileext {
|
||||
pthread_mutex_t _lock;
|
||||
|
||||
/* __fsetlocking support */
|
||||
bool _stdio_handles_locking;
|
||||
bool _caller_handles_locking;
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
@@ -131,7 +131,7 @@ do { \
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \
|
||||
pthread_mutex_init(&_FLOCK(fp), &attr); \
|
||||
pthread_mutexattr_destroy(&attr); \
|
||||
_EXT(fp)->_stdio_handles_locking = true; \
|
||||
_EXT(fp)->_caller_handles_locking = false; \
|
||||
} while (0)
|
||||
|
||||
#define _FILEEXT_SETUP(f, fext) \
|
||||
@@ -153,10 +153,8 @@ __LIBC32_LEGACY_PUBLIC__ int __srefill(FILE*);
|
||||
__LIBC32_LEGACY_PUBLIC__ int __swsetup(FILE*);
|
||||
|
||||
/* These were referenced by a couple of different pieces of middleware and the Crystax NDK. */
|
||||
__LIBC32_LEGACY_PUBLIC__ extern int __sdidinit;
|
||||
__LIBC32_LEGACY_PUBLIC__ int __sflags(const char*, int*);
|
||||
__LIBC32_LEGACY_PUBLIC__ FILE* __sfp(void);
|
||||
__LIBC32_LEGACY_PUBLIC__ void __sinit(void);
|
||||
__LIBC32_LEGACY_PUBLIC__ void __smakebuf(FILE*);
|
||||
|
||||
/* These are referenced by the Greed for Glory franchise. */
|
||||
@@ -170,7 +168,6 @@ __LIBC32_LEGACY_PUBLIC__ int _fwalk(int (*)(FILE *));
|
||||
#pragma GCC visibility push(hidden)
|
||||
|
||||
int __sflush_locked(FILE *);
|
||||
void _cleanup(void);
|
||||
int __swhatbuf(FILE *, size_t *, int *);
|
||||
wint_t __fgetwc_unlock(FILE *);
|
||||
wint_t __ungetwc(wint_t, FILE *);
|
||||
@@ -179,8 +176,6 @@ int __svfscanf(FILE * __restrict, const char * __restrict, __va_list);
|
||||
int __vfwprintf(FILE * __restrict, const wchar_t * __restrict, __va_list);
|
||||
int __vfwscanf(FILE * __restrict, const wchar_t * __restrict, __va_list);
|
||||
|
||||
extern void __atexit_register_cleanup(void (*)(void));
|
||||
|
||||
/*
|
||||
* Return true if the given FILE cannot be written now.
|
||||
*/
|
||||
@@ -208,8 +203,8 @@ extern void __atexit_register_cleanup(void (*)(void));
|
||||
(fp)->_lb._base = NULL; \
|
||||
}
|
||||
|
||||
#define FLOCKFILE(fp) if (_EXT(fp)->_stdio_handles_locking) flockfile(fp)
|
||||
#define FUNLOCKFILE(fp) if (_EXT(fp)->_stdio_handles_locking) funlockfile(fp)
|
||||
#define FLOCKFILE(fp) if (!_EXT(fp)->_caller_handles_locking) flockfile(fp)
|
||||
#define FUNLOCKFILE(fp) if (!_EXT(fp)->_caller_handles_locking) funlockfile(fp)
|
||||
|
||||
#define FLOATING_POINT
|
||||
#define PRINTF_WIDE_CHAR
|
||||
@@ -237,6 +232,10 @@ struct __suio;
|
||||
extern int __sfvwrite(FILE *, struct __suio *);
|
||||
wint_t __fputwc_unlock(wchar_t wc, FILE *fp);
|
||||
|
||||
/* Remove the if (!__sdidinit) __sinit() idiom from untouched upstream stdio code. */
|
||||
extern void __sinit(void); // Not actually implemented.
|
||||
#define __sdidinit 1
|
||||
|
||||
#pragma GCC visibility pop
|
||||
|
||||
__END_DECLS
|
||||
|
@@ -51,11 +51,6 @@ lflush(FILE *fp)
|
||||
int
|
||||
__srefill(FILE *fp)
|
||||
{
|
||||
|
||||
/* make sure stdio is set up */
|
||||
if (!__sdidinit)
|
||||
__sinit();
|
||||
|
||||
fp->_r = 0; /* largely a convenience for callers */
|
||||
|
||||
#if !defined(__ANDROID__)
|
||||
|
@@ -74,7 +74,7 @@ void _flushlbf() {
|
||||
}
|
||||
|
||||
int __fsetlocking(FILE* fp, int type) {
|
||||
int old_state = _EXT(fp)->_stdio_handles_locking ? FSETLOCKING_INTERNAL : FSETLOCKING_BYCALLER;
|
||||
int old_state = _EXT(fp)->_caller_handles_locking ? FSETLOCKING_BYCALLER : FSETLOCKING_INTERNAL;
|
||||
if (type == FSETLOCKING_QUERY) {
|
||||
return old_state;
|
||||
}
|
||||
@@ -84,7 +84,7 @@ int __fsetlocking(FILE* fp, int type) {
|
||||
__libc_fatal("Bad type (%d) passed to __fsetlocking", type);
|
||||
}
|
||||
|
||||
_EXT(fp)->_stdio_handles_locking = (type == FSETLOCKING_INTERNAL);
|
||||
_EXT(fp)->_caller_handles_locking = (type == FSETLOCKING_BYCALLER);
|
||||
return old_state;
|
||||
}
|
||||
|
||||
@@ -99,3 +99,7 @@ int feof_unlocked(FILE* fp) {
|
||||
int ferror_unlocked(FILE* fp) {
|
||||
return __sferror(fp);
|
||||
}
|
||||
|
||||
int fileno_unlocked(FILE* fp) {
|
||||
return __sfileno(fp);
|
||||
}
|
||||
|
@@ -185,51 +185,12 @@ restart:
|
||||
}
|
||||
_ATEXIT_UNLOCK();
|
||||
|
||||
extern void __libc_stdio_cleanup(void);
|
||||
__libc_stdio_cleanup();
|
||||
|
||||
/* BEGIN android-changed: call __unregister_atfork if dso is not null */
|
||||
if (dso != NULL) {
|
||||
__unregister_atfork(dso);
|
||||
}
|
||||
/* END android-changed */
|
||||
}
|
||||
|
||||
/*
|
||||
* Register the cleanup function
|
||||
*/
|
||||
void
|
||||
__atexit_register_cleanup(void (*func)(void))
|
||||
{
|
||||
struct atexit *p;
|
||||
size_t pgsize = getpagesize();
|
||||
|
||||
if (pgsize < sizeof(*p))
|
||||
return;
|
||||
_ATEXIT_LOCK();
|
||||
p = __atexit;
|
||||
while (p != NULL && p->next != NULL)
|
||||
p = p->next;
|
||||
if (p == NULL) {
|
||||
p = mmap(NULL, pgsize, PROT_READ | PROT_WRITE,
|
||||
MAP_ANON | MAP_PRIVATE, -1, 0);
|
||||
if (p == MAP_FAILED)
|
||||
goto unlock;
|
||||
/* BEGIN android-changed */
|
||||
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, pgsize,
|
||||
"atexit handlers");
|
||||
/* END android-changed */
|
||||
p->ind = 1;
|
||||
p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
|
||||
sizeof(p->fns[0]);
|
||||
p->next = NULL;
|
||||
__atexit = p;
|
||||
} else {
|
||||
if (mprotect(p, pgsize, PROT_READ | PROT_WRITE))
|
||||
goto unlock;
|
||||
}
|
||||
p->fns[0].fn_ptr = (void (*)(void *))func;
|
||||
p->fns[0].fn_arg = NULL;
|
||||
p->fns[0].fn_dso = NULL;
|
||||
mprotect(p, pgsize, PROT_READ);
|
||||
restartloop = 1;
|
||||
unlock:
|
||||
_ATEXIT_UNLOCK();
|
||||
}
|
||||
|
@@ -36,20 +36,26 @@ class VersionScriptGenerator(object):
|
||||
basename = os.path.basename(script)
|
||||
dirname = os.path.dirname(script)
|
||||
for arch in all_arches:
|
||||
name = basename.split(".")[0] + "." + arch + ".map"
|
||||
tmp_path = os.path.join(bionic_temp, name)
|
||||
dest_path = os.path.join(dirname, name)
|
||||
with open(tmp_path, "w") as fout:
|
||||
with open(script, "r") as fin:
|
||||
fout.write("# %s\n" % warning)
|
||||
for line in fin:
|
||||
index = line.find("#")
|
||||
if index != -1:
|
||||
arches = line[index+1:].split()
|
||||
if arch not in arches:
|
||||
continue
|
||||
fout.write(line)
|
||||
shutil.copyfile(tmp_path, dest_path)
|
||||
for brillo in [False, True]:
|
||||
has_nobrillo = False
|
||||
name = basename.split(".")[0] + "." + arch + (".brillo" if brillo else "") + ".map"
|
||||
tmp_path = os.path.join(bionic_temp, name)
|
||||
dest_path = os.path.join(dirname, name)
|
||||
with open(tmp_path, "w") as fout:
|
||||
with open(script, "r") as fin:
|
||||
fout.write("# %s\n" % warning)
|
||||
for line in fin:
|
||||
index = line.find("#")
|
||||
if index != -1:
|
||||
tags = line[index+1:].split()
|
||||
if arch not in tags:
|
||||
continue
|
||||
if brillo and "nobrillo" in tags:
|
||||
has_nobrillo = True
|
||||
continue
|
||||
fout.write(line)
|
||||
if not brillo or has_nobrillo:
|
||||
shutil.copyfile(tmp_path, dest_path)
|
||||
|
||||
|
||||
generator = VersionScriptGenerator()
|
||||
|
@@ -1316,9 +1316,10 @@ static void
|
||||
tzset_unlocked(void)
|
||||
{
|
||||
#if defined(__ANDROID__)
|
||||
// The TZ environment variable is meant to override the system-wide setting.
|
||||
const char * name = getenv("TZ");
|
||||
|
||||
// Try the "persist.sys.timezone" system property.
|
||||
// If that's not set, look at the "persist.sys.timezone" system property.
|
||||
if (name == NULL) {
|
||||
static const prop_info *pi;
|
||||
|
||||
@@ -1340,6 +1341,10 @@ tzset_unlocked(void)
|
||||
}
|
||||
}
|
||||
|
||||
// If that's not available (because you're running AOSP on a WiFi-only
|
||||
// device, say), fall back to GMT.
|
||||
if (name == NULL) name = gmt;
|
||||
|
||||
tzsetlcl(name);
|
||||
#else
|
||||
tzsetlcl(getenv("TZ"));
|
||||
|
@@ -502,7 +502,23 @@ label:
|
||||
continue;
|
||||
case 'Z':
|
||||
#ifdef TM_ZONE
|
||||
pt = _add(t->TM_ZONE, pt, ptlim, modifier);
|
||||
// BEGIN: Android-changed.
|
||||
{
|
||||
const char* zone = t->TM_ZONE;
|
||||
if (!zone || !*zone) {
|
||||
// "The value of tm_isdst shall be positive if Daylight Savings Time is
|
||||
// in effect, 0 if Daylight Savings Time is not in effect, and negative
|
||||
// if the information is not available."
|
||||
if (t->tm_isdst == 0) zone = tzname[0];
|
||||
else if (t->tm_isdst > 0) zone = tzname[1];
|
||||
|
||||
// "Replaced by the timezone name or abbreviation, or by no bytes if no
|
||||
// timezone information exists."
|
||||
if (!zone || !*zone) zone = "";
|
||||
}
|
||||
pt = _add(zone, pt, ptlim, modifier);
|
||||
}
|
||||
// END: Android-changed.
|
||||
#else
|
||||
if (t->tm_isdst >= 0)
|
||||
pt = _add(tzname[t->tm_isdst != 0],
|
||||
|
@@ -32,6 +32,6 @@
|
||||
#define __unlockenv() 0
|
||||
|
||||
#include <stddef.h>
|
||||
int reallocarr(void*, size_t, size_t);
|
||||
__LIBC_HIDDEN__ int reallocarr(void*, size_t, size_t);
|
||||
|
||||
#endif
|
||||
|
@@ -13,15 +13,28 @@ cc_library {
|
||||
// DO NOT REMOVE --exclude-libs!
|
||||
|
||||
ldflags: ["-Wl,--exclude-libs=libgcc.a"],
|
||||
version_script: "libdl.map",
|
||||
|
||||
// for x86, exclude libgcc_eh.a for the same reasons as above
|
||||
arch: {
|
||||
arm: {
|
||||
version_script: "libdl.arm.map",
|
||||
},
|
||||
arm64: {
|
||||
version_script: "libdl.arm64.map",
|
||||
},
|
||||
mips: {
|
||||
version_script: "libdl.mips.map",
|
||||
},
|
||||
mips64: {
|
||||
version_script: "libdl.mips64.map",
|
||||
},
|
||||
x86: {
|
||||
ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
|
||||
version_script: "libdl.x86.map",
|
||||
},
|
||||
x86_64: {
|
||||
ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
|
||||
version_script: "libdl.x86_64.map",
|
||||
},
|
||||
},
|
||||
srcs: ["libdl.c"],
|
||||
|
@@ -33,7 +33,13 @@ LOCAL_CFLAGS := -Wall -Wextra -Wunused -Werror
|
||||
LOCAL_CXX_STL := none
|
||||
|
||||
LOCAL_MODULE := libdl
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk \
|
||||
$(LOCAL_PATH)/libdl.arm.map \
|
||||
$(LOCAL_PATH)/libdl.arm64.map \
|
||||
$(LOCAL_PATH)/libdl.mips.map \
|
||||
$(LOCAL_PATH)/libdl.mips64.map \
|
||||
$(LOCAL_PATH)/libdl.x86.map \
|
||||
$(LOCAL_PATH)/libdl.x86_64.map \
|
||||
|
||||
# NOTE: libdl needs __aeabi_unwind_cpp_pr0 from libgcc.a but libgcc.a needs a
|
||||
# few symbols from libc. Using --no-undefined here results in having to link
|
||||
|
@@ -14,10 +14,16 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_N {
|
||||
global:
|
||||
android_init_namespaces;
|
||||
android_create_namespace;
|
||||
} LIBC;
|
||||
|
||||
LIBC_PRIVATE {
|
||||
global:
|
||||
android_get_application_target_sdk_version;
|
||||
android_set_application_target_sdk_version;
|
||||
android_get_LD_LIBRARY_PATH;
|
||||
android_update_LD_LIBRARY_PATH;
|
||||
} LIBC;
|
||||
} LIBC_N;
|
||||
|
@@ -13,10 +13,16 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_N {
|
||||
global:
|
||||
android_init_namespaces;
|
||||
android_create_namespace;
|
||||
} LIBC;
|
||||
|
||||
LIBC_PRIVATE {
|
||||
global:
|
||||
android_get_application_target_sdk_version;
|
||||
android_set_application_target_sdk_version;
|
||||
android_get_LD_LIBRARY_PATH;
|
||||
android_update_LD_LIBRARY_PATH;
|
||||
} LIBC;
|
||||
} LIBC_N;
|
||||
|
@@ -33,12 +33,31 @@ int dlclose(void* handle __unused) { return 0; }
|
||||
_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc __unused, int* pcount __unused) { return 0; }
|
||||
#endif
|
||||
|
||||
int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data) __unused, void* data __unused) { return 0; }
|
||||
int dl_iterate_phdr(int (*cb)(struct dl_phdr_info* info, size_t size, void* data) __unused,
|
||||
void* data __unused) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void android_get_LD_LIBRARY_PATH(char* buffer __unused, size_t buffer_size __unused) { }
|
||||
void android_update_LD_LIBRARY_PATH(const char* ld_library_path __unused) { }
|
||||
|
||||
void* android_dlopen_ext(const char* filename __unused, int flag __unused, const android_dlextinfo* extinfo __unused) { return 0; }
|
||||
void* android_dlopen_ext(const char* filename __unused, int flag __unused,
|
||||
const android_dlextinfo* extinfo __unused) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void android_set_application_target_sdk_version(uint32_t target __unused) { }
|
||||
uint32_t android_get_application_target_sdk_version() { return 0; }
|
||||
|
||||
bool android_init_namespaces(const char* public_ns_sonames __unused,
|
||||
const char* anon_ns_library_path __unused) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct android_namespace_t* android_create_namespace(const char* name __unused,
|
||||
const char* ld_library_path __unused,
|
||||
const char* default_library_path __unused,
|
||||
bool isolated __unused,
|
||||
const char* permitted_when_isolated_path __unused) {
|
||||
return 0;
|
||||
}
|
||||
|
@@ -28,10 +28,16 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_N {
|
||||
global:
|
||||
android_init_namespaces;
|
||||
android_create_namespace;
|
||||
} LIBC;
|
||||
|
||||
LIBC_PRIVATE {
|
||||
global:
|
||||
android_get_application_target_sdk_version;
|
||||
android_set_application_target_sdk_version;
|
||||
android_get_LD_LIBRARY_PATH;
|
||||
android_update_LD_LIBRARY_PATH;
|
||||
} LIBC;
|
||||
} LIBC_N;
|
||||
|
@@ -13,10 +13,16 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_N {
|
||||
global:
|
||||
android_init_namespaces;
|
||||
android_create_namespace;
|
||||
} LIBC;
|
||||
|
||||
LIBC_PRIVATE {
|
||||
global:
|
||||
android_get_application_target_sdk_version;
|
||||
android_set_application_target_sdk_version;
|
||||
android_get_LD_LIBRARY_PATH;
|
||||
android_update_LD_LIBRARY_PATH;
|
||||
} LIBC;
|
||||
} LIBC_N;
|
||||
|
@@ -13,10 +13,16 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_N {
|
||||
global:
|
||||
android_init_namespaces;
|
||||
android_create_namespace;
|
||||
} LIBC;
|
||||
|
||||
LIBC_PRIVATE {
|
||||
global:
|
||||
android_get_application_target_sdk_version;
|
||||
android_set_application_target_sdk_version;
|
||||
android_get_LD_LIBRARY_PATH;
|
||||
android_update_LD_LIBRARY_PATH;
|
||||
} LIBC;
|
||||
} LIBC_N;
|
||||
|
@@ -13,10 +13,16 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_N {
|
||||
global:
|
||||
android_init_namespaces;
|
||||
android_create_namespace;
|
||||
} LIBC;
|
||||
|
||||
LIBC_PRIVATE {
|
||||
global:
|
||||
android_get_application_target_sdk_version;
|
||||
android_set_application_target_sdk_version;
|
||||
android_get_LD_LIBRARY_PATH;
|
||||
android_update_LD_LIBRARY_PATH;
|
||||
} LIBC;
|
||||
} LIBC_N;
|
||||
|
@@ -13,10 +13,16 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_N {
|
||||
global:
|
||||
android_init_namespaces;
|
||||
android_create_namespace;
|
||||
} LIBC;
|
||||
|
||||
LIBC_PRIVATE {
|
||||
global:
|
||||
android_get_application_target_sdk_version;
|
||||
android_set_application_target_sdk_version;
|
||||
android_get_LD_LIBRARY_PATH;
|
||||
android_update_LD_LIBRARY_PATH;
|
||||
} LIBC;
|
||||
} LIBC_N;
|
||||
|
194
libm/Android.bp
194
libm/Android.bp
@@ -3,18 +3,7 @@
|
||||
|
||||
bionic_coverage = false
|
||||
|
||||
// TODO: this comes from from upstream's libc, not libm, but it's an
|
||||
// implementation detail that should have hidden visibility, so it needs
|
||||
// to be in whatever library the math code is in.
|
||||
libm_common_src_files = ["digittoint.c"]
|
||||
|
||||
// TODO: this is not in the BSDs.
|
||||
libm_common_src_files += [
|
||||
"significandl.c",
|
||||
"sincos.c",
|
||||
]
|
||||
|
||||
libm_common_src_files += [
|
||||
libm_common_src_files = [
|
||||
"upstream-freebsd/lib/msun/bsdsrc/b_exp.c",
|
||||
"upstream-freebsd/lib/msun/bsdsrc/b_log.c",
|
||||
"upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c",
|
||||
@@ -186,8 +175,19 @@ libm_common_src_files += [
|
||||
]
|
||||
|
||||
libm_common_src_files += [
|
||||
"fake_long_double.c",
|
||||
// TODO: this comes from from upstream's libc, not libm, but it's an
|
||||
// implementation detail that should have hidden visibility, so it needs
|
||||
// to be in whatever library the math code is in.
|
||||
"digittoint.c",
|
||||
|
||||
// Functionality not in the BSDs.
|
||||
"significandl.c",
|
||||
"sincos.c",
|
||||
|
||||
// Modified versions of BSD code.
|
||||
"signbit.c",
|
||||
|
||||
// Home-grown stuff.
|
||||
"fabs.cpp",
|
||||
]
|
||||
|
||||
@@ -254,6 +254,7 @@ libm_common_cflags = [
|
||||
"-D__BIONIC_NO_MATH_INLINES",
|
||||
"-DFLT_EVAL_METHOD=0",
|
||||
"-include freebsd-compat.h",
|
||||
"-Werror",
|
||||
"-Wno-missing-braces",
|
||||
"-Wno-parentheses",
|
||||
"-Wno-sign-compare",
|
||||
@@ -290,9 +291,10 @@ cc_library {
|
||||
native_coverage: bionic_coverage,
|
||||
sanitize: ["never"],
|
||||
|
||||
version_script: "libm.map",
|
||||
|
||||
multilib: {
|
||||
lib32: {
|
||||
srcs: ["fake_long_double.c"],
|
||||
},
|
||||
lib64: {
|
||||
srcs: libm_ld128_src_files,
|
||||
local_include_dirs: libm_ld_local_includes,
|
||||
@@ -308,23 +310,27 @@ cc_library {
|
||||
arm: {
|
||||
srcs: [
|
||||
"arm/fenv.c",
|
||||
"arm/sqrt.S",
|
||||
"arm/floor.S",
|
||||
],
|
||||
exclude_srcs: [
|
||||
// TODO: these require neon not available in arm
|
||||
"upstream-freebsd/lib/msun/src/e_sqrt.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sqrtf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_floor.c",
|
||||
],
|
||||
armv7_a_neon: {
|
||||
srcs: [
|
||||
"arm/sqrt.S",
|
||||
"arm/floor.S",
|
||||
],
|
||||
exclude_srcs: [
|
||||
"upstream-freebsd/lib/msun/src/e_sqrt.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sqrtf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_floor.c",
|
||||
],
|
||||
},
|
||||
instruction_set: "arm",
|
||||
ldflags: ["-Wl,--hash-style=both"],
|
||||
version_script: "libm.arm.map",
|
||||
},
|
||||
|
||||
arm64: {
|
||||
srcs: [
|
||||
"arm64/fenv.c",
|
||||
"arm64/ceil.S",
|
||||
"arm64/fenv.c",
|
||||
"arm64/fma.S",
|
||||
"arm64/floor.S",
|
||||
"arm64/lrint.S",
|
||||
@@ -333,6 +339,8 @@ cc_library {
|
||||
"arm64/trunc.S",
|
||||
],
|
||||
exclude_srcs: [
|
||||
"upstream-freebsd/lib/msun/src/e_sqrt.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sqrtf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_ceil.c",
|
||||
"upstream-freebsd/lib/msun/src/s_ceilf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_fma.c",
|
||||
@@ -345,33 +353,163 @@ cc_library {
|
||||
"upstream-freebsd/lib/msun/src/s_lrintf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_rint.c",
|
||||
"upstream-freebsd/lib/msun/src/s_rintf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sqrt.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sqrtf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_trunc.c",
|
||||
"upstream-freebsd/lib/msun/src/s_truncf.c",
|
||||
],
|
||||
version_script: "libm.arm64.map",
|
||||
},
|
||||
|
||||
mips: {
|
||||
srcs: ["mips/fenv.c"],
|
||||
version_script: "libm.mips.map",
|
||||
},
|
||||
|
||||
mips64: {
|
||||
srcs: ["mips/fenv.c"],
|
||||
version_script: "libm.mips64.map",
|
||||
},
|
||||
|
||||
x86: {
|
||||
srcs: [
|
||||
"i387/fenv.c",
|
||||
"x86/sqrt.S",
|
||||
"x86/sqrtf.S",
|
||||
"x86/e_acos.S",
|
||||
"x86/e_asin.S",
|
||||
"x86/e_atan2.S",
|
||||
"x86/e_cosh.S",
|
||||
"x86/e_exp.S",
|
||||
"x86/e_hypot.S",
|
||||
"x86/e_log10.S",
|
||||
"x86/e_log.S",
|
||||
"x86/e_pow.S",
|
||||
"x86/e_sinh.S",
|
||||
"x86/libm_reduce_pi04l.S",
|
||||
"x86/libm_sincos_huge.S",
|
||||
"x86/libm_tancot_huge.S",
|
||||
"x86/s_atan.S",
|
||||
"x86/s_cbrt.S",
|
||||
"x86/s_cos.S",
|
||||
"x86/s_expm1.S",
|
||||
"x86/s_log1p.S",
|
||||
"x86/s_sin.S",
|
||||
"x86/s_tanh.S",
|
||||
"x86/s_tan.S",
|
||||
],
|
||||
exclude_srcs: [
|
||||
"upstream-freebsd/lib/msun/src/e_acos.c",
|
||||
"upstream-freebsd/lib/msun/src/e_asin.c",
|
||||
"upstream-freebsd/lib/msun/src/e_atan2.c",
|
||||
"upstream-freebsd/lib/msun/src/e_cosh.c",
|
||||
"upstream-freebsd/lib/msun/src/e_exp.c",
|
||||
"upstream-freebsd/lib/msun/src/e_hypot.c",
|
||||
"upstream-freebsd/lib/msun/src/e_log.c",
|
||||
"upstream-freebsd/lib/msun/src/e_log10.c",
|
||||
"upstream-freebsd/lib/msun/src/e_pow.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sinh.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sqrt.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sqrtf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_atan.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cbrt.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cos.c",
|
||||
"upstream-freebsd/lib/msun/src/s_expm1.c",
|
||||
"upstream-freebsd/lib/msun/src/s_log1p.c",
|
||||
"upstream-freebsd/lib/msun/src/s_sin.c",
|
||||
"upstream-freebsd/lib/msun/src/s_tan.c",
|
||||
"upstream-freebsd/lib/msun/src/s_tanh.c",
|
||||
],
|
||||
sse4_1: {
|
||||
srcs: [
|
||||
"x86/ceil.S",
|
||||
"x86/ceilf.S",
|
||||
"x86/floor.S",
|
||||
"x86/floorf.S",
|
||||
"x86/trunc.S",
|
||||
"x86/truncf.S",
|
||||
],
|
||||
exclude_srcs: [
|
||||
"upstream-freebsd/lib/msun/src/s_ceil.c",
|
||||
"upstream-freebsd/lib/msun/src/s_ceilf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_floor.c",
|
||||
"upstream-freebsd/lib/msun/src/s_floorf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_trunc.c",
|
||||
"upstream-freebsd/lib/msun/src/s_truncf.c",
|
||||
],
|
||||
},
|
||||
local_include_dirs: ["i387"],
|
||||
srcs: ["i387/fenv.c"],
|
||||
// Clang has wrong long double sizes for x86.
|
||||
clang: false,
|
||||
ldflags: ["-Wl,--hash-style=both"],
|
||||
version_script: "libm.x86.map",
|
||||
},
|
||||
|
||||
x86_64: {
|
||||
srcs: ["amd64/fenv.c"],
|
||||
srcs: [
|
||||
"amd64/fenv.c",
|
||||
"x86_64/sqrt.S",
|
||||
"x86_64/sqrtf.S",
|
||||
"x86_64/e_acos.S",
|
||||
"x86_64/e_asin.S",
|
||||
"x86_64/e_atan2.S",
|
||||
"x86_64/e_cosh.S",
|
||||
"x86_64/e_exp.S",
|
||||
"x86_64/e_hypot.S",
|
||||
"x86_64/e_log10.S",
|
||||
"x86_64/e_log.S",
|
||||
"x86_64/e_pow.S",
|
||||
"x86_64/e_sinh.S",
|
||||
"x86_64/s_atan.S",
|
||||
"x86_64/s_cbrt.S",
|
||||
"x86_64/s_cos.S",
|
||||
"x86_64/s_expm1.S",
|
||||
"x86_64/s_log1p.S",
|
||||
"x86_64/s_sin.S",
|
||||
"x86_64/s_tanh.S",
|
||||
"x86_64/s_tan.S",
|
||||
],
|
||||
exclude_srcs: [
|
||||
"upstream-freebsd/lib/msun/src/e_acos.c",
|
||||
"upstream-freebsd/lib/msun/src/e_asin.c",
|
||||
"upstream-freebsd/lib/msun/src/e_atan2.c",
|
||||
"upstream-freebsd/lib/msun/src/e_cosh.c",
|
||||
"upstream-freebsd/lib/msun/src/e_exp.c",
|
||||
"upstream-freebsd/lib/msun/src/e_hypot.c",
|
||||
"upstream-freebsd/lib/msun/src/e_log.c",
|
||||
"upstream-freebsd/lib/msun/src/e_log10.c",
|
||||
"upstream-freebsd/lib/msun/src/e_pow.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sinh.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sqrt.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sqrtf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_atan.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cbrt.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cos.c",
|
||||
"upstream-freebsd/lib/msun/src/s_expm1.c",
|
||||
"upstream-freebsd/lib/msun/src/s_log1p.c",
|
||||
"upstream-freebsd/lib/msun/src/s_sin.c",
|
||||
"upstream-freebsd/lib/msun/src/s_tan.c",
|
||||
"upstream-freebsd/lib/msun/src/s_tanh.c",
|
||||
],
|
||||
sse4_1: {
|
||||
srcs: [
|
||||
"x86_64/ceil.S",
|
||||
"x86_64/ceilf.S",
|
||||
"x86_64/floor.S",
|
||||
"x86_64/floorf.S",
|
||||
"x86_64/trunc.S",
|
||||
"x86_64/truncf.S",
|
||||
],
|
||||
exclude_srcs: [
|
||||
"upstream-freebsd/lib/msun/src/s_ceil.c",
|
||||
"upstream-freebsd/lib/msun/src/s_ceilf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_floor.c",
|
||||
"upstream-freebsd/lib/msun/src/s_floorf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_trunc.c",
|
||||
"upstream-freebsd/lib/msun/src/s_truncf.c",
|
||||
],
|
||||
},
|
||||
// Clang has wrong long double sizes for x86.
|
||||
clang: false,
|
||||
version_script: "libm.x86_64.map",
|
||||
},
|
||||
},
|
||||
|
||||
|
214
libm/Android.mk
214
libm/Android.mk
@@ -22,14 +22,19 @@ LOCAL_SRC_FILES := \
|
||||
upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c \
|
||||
upstream-freebsd/lib/msun/src/catrig.c \
|
||||
upstream-freebsd/lib/msun/src/catrigf.c \
|
||||
upstream-freebsd/lib/msun/src/e_acos.c \
|
||||
upstream-freebsd/lib/msun/src/e_acosf.c \
|
||||
upstream-freebsd/lib/msun/src/e_acosh.c \
|
||||
upstream-freebsd/lib/msun/src/e_acoshf.c \
|
||||
upstream-freebsd/lib/msun/src/e_asin.c \
|
||||
upstream-freebsd/lib/msun/src/e_asinf.c \
|
||||
upstream-freebsd/lib/msun/src/e_atan2.c \
|
||||
upstream-freebsd/lib/msun/src/e_atan2f.c \
|
||||
upstream-freebsd/lib/msun/src/e_atanh.c \
|
||||
upstream-freebsd/lib/msun/src/e_atanhf.c \
|
||||
upstream-freebsd/lib/msun/src/e_cosh.c \
|
||||
upstream-freebsd/lib/msun/src/e_coshf.c \
|
||||
upstream-freebsd/lib/msun/src/e_exp.c \
|
||||
upstream-freebsd/lib/msun/src/e_expf.c \
|
||||
upstream-freebsd/lib/msun/src/e_fmod.c \
|
||||
upstream-freebsd/lib/msun/src/e_fmodf.c \
|
||||
@@ -37,6 +42,7 @@ LOCAL_SRC_FILES := \
|
||||
upstream-freebsd/lib/msun/src/e_gammaf.c \
|
||||
upstream-freebsd/lib/msun/src/e_gammaf_r.c \
|
||||
upstream-freebsd/lib/msun/src/e_gamma_r.c \
|
||||
upstream-freebsd/lib/msun/src/e_hypot.c \
|
||||
upstream-freebsd/lib/msun/src/e_hypotf.c \
|
||||
upstream-freebsd/lib/msun/src/e_j0.c \
|
||||
upstream-freebsd/lib/msun/src/e_j0f.c \
|
||||
@@ -48,10 +54,13 @@ LOCAL_SRC_FILES := \
|
||||
upstream-freebsd/lib/msun/src/e_lgammaf.c \
|
||||
upstream-freebsd/lib/msun/src/e_lgammaf_r.c \
|
||||
upstream-freebsd/lib/msun/src/e_lgamma_r.c \
|
||||
upstream-freebsd/lib/msun/src/e_log10.c \
|
||||
upstream-freebsd/lib/msun/src/e_log10f.c \
|
||||
upstream-freebsd/lib/msun/src/e_log2.c \
|
||||
upstream-freebsd/lib/msun/src/e_log2f.c \
|
||||
upstream-freebsd/lib/msun/src/e_log.c \
|
||||
upstream-freebsd/lib/msun/src/e_logf.c \
|
||||
upstream-freebsd/lib/msun/src/e_pow.c \
|
||||
upstream-freebsd/lib/msun/src/e_powf.c \
|
||||
upstream-freebsd/lib/msun/src/e_remainder.c \
|
||||
upstream-freebsd/lib/msun/src/e_remainderf.c \
|
||||
@@ -59,7 +68,10 @@ LOCAL_SRC_FILES := \
|
||||
upstream-freebsd/lib/msun/src/e_rem_pio2f.c \
|
||||
upstream-freebsd/lib/msun/src/e_scalb.c \
|
||||
upstream-freebsd/lib/msun/src/e_scalbf.c \
|
||||
upstream-freebsd/lib/msun/src/e_sinh.c \
|
||||
upstream-freebsd/lib/msun/src/e_sinhf.c \
|
||||
upstream-freebsd/lib/msun/src/e_sqrt.c \
|
||||
upstream-freebsd/lib/msun/src/e_sqrtf.c \
|
||||
upstream-freebsd/lib/msun/src/imprecise.c \
|
||||
upstream-freebsd/lib/msun/src/k_cos.c \
|
||||
upstream-freebsd/lib/msun/src/k_cosf.c \
|
||||
@@ -72,13 +84,17 @@ LOCAL_SRC_FILES := \
|
||||
upstream-freebsd/lib/msun/src/k_tanf.c \
|
||||
upstream-freebsd/lib/msun/src/s_asinh.c \
|
||||
upstream-freebsd/lib/msun/src/s_asinhf.c \
|
||||
upstream-freebsd/lib/msun/src/s_atan.c \
|
||||
upstream-freebsd/lib/msun/src/s_atanf.c \
|
||||
upstream-freebsd/lib/msun/src/s_carg.c \
|
||||
upstream-freebsd/lib/msun/src/s_cargf.c \
|
||||
upstream-freebsd/lib/msun/src/s_cargl.c \
|
||||
upstream-freebsd/lib/msun/src/s_cbrt.c \
|
||||
upstream-freebsd/lib/msun/src/s_cbrtf.c \
|
||||
upstream-freebsd/lib/msun/src/s_ccosh.c \
|
||||
upstream-freebsd/lib/msun/src/s_ccoshf.c \
|
||||
upstream-freebsd/lib/msun/src/s_ceil.c \
|
||||
upstream-freebsd/lib/msun/src/s_ceilf.c \
|
||||
upstream-freebsd/lib/msun/src/s_cexp.c \
|
||||
upstream-freebsd/lib/msun/src/s_cexpf.c \
|
||||
upstream-freebsd/lib/msun/src/s_cimag.c \
|
||||
@@ -89,6 +105,7 @@ LOCAL_SRC_FILES := \
|
||||
upstream-freebsd/lib/msun/src/s_conjl.c \
|
||||
upstream-freebsd/lib/msun/src/s_copysign.c \
|
||||
upstream-freebsd/lib/msun/src/s_copysignf.c \
|
||||
upstream-freebsd/lib/msun/src/s_cos.c \
|
||||
upstream-freebsd/lib/msun/src/s_cosf.c \
|
||||
upstream-freebsd/lib/msun/src/s_cproj.c \
|
||||
upstream-freebsd/lib/msun/src/s_cprojf.c \
|
||||
@@ -107,10 +124,15 @@ LOCAL_SRC_FILES := \
|
||||
upstream-freebsd/lib/msun/src/s_erff.c \
|
||||
upstream-freebsd/lib/msun/src/s_exp2.c \
|
||||
upstream-freebsd/lib/msun/src/s_exp2f.c \
|
||||
upstream-freebsd/lib/msun/src/s_expm1.c \
|
||||
upstream-freebsd/lib/msun/src/s_expm1f.c \
|
||||
upstream-freebsd/lib/msun/src/s_fdim.c \
|
||||
upstream-freebsd/lib/msun/src/s_finite.c \
|
||||
upstream-freebsd/lib/msun/src/s_finitef.c \
|
||||
upstream-freebsd/lib/msun/src/s_floor.c \
|
||||
upstream-freebsd/lib/msun/src/s_floorf.c \
|
||||
upstream-freebsd/lib/msun/src/s_fma.c \
|
||||
upstream-freebsd/lib/msun/src/s_fmaf.c \
|
||||
upstream-freebsd/lib/msun/src/s_fmax.c \
|
||||
upstream-freebsd/lib/msun/src/s_fmaxf.c \
|
||||
upstream-freebsd/lib/msun/src/s_fmin.c \
|
||||
@@ -119,11 +141,16 @@ LOCAL_SRC_FILES := \
|
||||
upstream-freebsd/lib/msun/src/s_frexpf.c \
|
||||
upstream-freebsd/lib/msun/src/s_ilogb.c \
|
||||
upstream-freebsd/lib/msun/src/s_ilogbf.c \
|
||||
upstream-freebsd/lib/msun/src/s_llrint.c \
|
||||
upstream-freebsd/lib/msun/src/s_llrintf.c \
|
||||
upstream-freebsd/lib/msun/src/s_llround.c \
|
||||
upstream-freebsd/lib/msun/src/s_llroundf.c \
|
||||
upstream-freebsd/lib/msun/src/s_log1p.c \
|
||||
upstream-freebsd/lib/msun/src/s_log1pf.c \
|
||||
upstream-freebsd/lib/msun/src/s_logb.c \
|
||||
upstream-freebsd/lib/msun/src/s_logbf.c \
|
||||
upstream-freebsd/lib/msun/src/s_lrint.c \
|
||||
upstream-freebsd/lib/msun/src/s_lrintf.c \
|
||||
upstream-freebsd/lib/msun/src/s_lround.c \
|
||||
upstream-freebsd/lib/msun/src/s_lroundf.c \
|
||||
upstream-freebsd/lib/msun/src/s_modf.c \
|
||||
@@ -134,6 +161,8 @@ LOCAL_SRC_FILES := \
|
||||
upstream-freebsd/lib/msun/src/s_nextafterf.c \
|
||||
upstream-freebsd/lib/msun/src/s_remquo.c \
|
||||
upstream-freebsd/lib/msun/src/s_remquof.c \
|
||||
upstream-freebsd/lib/msun/src/s_rint.c \
|
||||
upstream-freebsd/lib/msun/src/s_rintf.c \
|
||||
upstream-freebsd/lib/msun/src/s_round.c \
|
||||
upstream-freebsd/lib/msun/src/s_roundf.c \
|
||||
upstream-freebsd/lib/msun/src/s_scalbln.c \
|
||||
@@ -142,10 +171,15 @@ LOCAL_SRC_FILES := \
|
||||
upstream-freebsd/lib/msun/src/s_signgam.c \
|
||||
upstream-freebsd/lib/msun/src/s_significand.c \
|
||||
upstream-freebsd/lib/msun/src/s_significandf.c \
|
||||
upstream-freebsd/lib/msun/src/s_sin.c \
|
||||
upstream-freebsd/lib/msun/src/s_sinf.c \
|
||||
upstream-freebsd/lib/msun/src/s_tan.c \
|
||||
upstream-freebsd/lib/msun/src/s_tanf.c \
|
||||
upstream-freebsd/lib/msun/src/s_tanh.c \
|
||||
upstream-freebsd/lib/msun/src/s_tanhf.c \
|
||||
upstream-freebsd/lib/msun/src/s_tgammaf.c \
|
||||
upstream-freebsd/lib/msun/src/s_trunc.c \
|
||||
upstream-freebsd/lib/msun/src/s_truncf.c \
|
||||
upstream-freebsd/lib/msun/src/w_cabs.c \
|
||||
upstream-freebsd/lib/msun/src/w_cabsf.c \
|
||||
upstream-freebsd/lib/msun/src/w_cabsl.c \
|
||||
@@ -236,37 +270,6 @@ LOCAL_SRC_FILES += \
|
||||
# -----------------------------------------------------------------------------
|
||||
LOCAL_SRC_FILES_arm += \
|
||||
arm/fenv.c \
|
||||
upstream-freebsd/lib/msun/src/e_acos.c \
|
||||
upstream-freebsd/lib/msun/src/e_asin.c \
|
||||
upstream-freebsd/lib/msun/src/e_atan2.c \
|
||||
upstream-freebsd/lib/msun/src/e_cosh.c \
|
||||
upstream-freebsd/lib/msun/src/e_exp.c \
|
||||
upstream-freebsd/lib/msun/src/e_hypot.c \
|
||||
upstream-freebsd/lib/msun/src/e_log.c \
|
||||
upstream-freebsd/lib/msun/src/e_log10.c \
|
||||
upstream-freebsd/lib/msun/src/e_pow.c \
|
||||
upstream-freebsd/lib/msun/src/e_sinh.c \
|
||||
upstream-freebsd/lib/msun/src/s_atan.c \
|
||||
upstream-freebsd/lib/msun/src/s_cbrt.c \
|
||||
upstream-freebsd/lib/msun/src/s_ceil.c \
|
||||
upstream-freebsd/lib/msun/src/s_ceilf.c \
|
||||
upstream-freebsd/lib/msun/src/s_cos.c \
|
||||
upstream-freebsd/lib/msun/src/s_fma.c \
|
||||
upstream-freebsd/lib/msun/src/s_fmaf.c \
|
||||
upstream-freebsd/lib/msun/src/s_floorf.c \
|
||||
upstream-freebsd/lib/msun/src/s_expm1.c \
|
||||
upstream-freebsd/lib/msun/src/s_llrint.c \
|
||||
upstream-freebsd/lib/msun/src/s_llrintf.c \
|
||||
upstream-freebsd/lib/msun/src/s_log1p.c \
|
||||
upstream-freebsd/lib/msun/src/s_lrint.c \
|
||||
upstream-freebsd/lib/msun/src/s_lrintf.c \
|
||||
upstream-freebsd/lib/msun/src/s_rint.c \
|
||||
upstream-freebsd/lib/msun/src/s_rintf.c \
|
||||
upstream-freebsd/lib/msun/src/s_sin.c \
|
||||
upstream-freebsd/lib/msun/src/s_tan.c \
|
||||
upstream-freebsd/lib/msun/src/s_tanh.c \
|
||||
upstream-freebsd/lib/msun/src/s_trunc.c \
|
||||
upstream-freebsd/lib/msun/src/s_truncf.c \
|
||||
|
||||
# s_floor.S requires neon instructions.
|
||||
ifdef TARGET_2ND_ARCH
|
||||
@@ -276,17 +279,16 @@ arch_variant := $(TARGET_ARCH_VARIANT)
|
||||
endif
|
||||
|
||||
# Use the C version on armv7-a since it doesn't support neon instructions.
|
||||
ifeq ($(arch_variant),armv7-a)
|
||||
LOCAL_SRC_FILES_arm += \
|
||||
upstream-freebsd/lib/msun/src/e_sqrt.c \
|
||||
upstream-freebsd/lib/msun/src/e_sqrtf.c \
|
||||
upstream-freebsd/lib/msun/src/s_floor.c \
|
||||
|
||||
else
|
||||
ifneq ($(arch_variant),armv7-a)
|
||||
LOCAL_SRC_FILES_arm += \
|
||||
arm/sqrt.S \
|
||||
arm/floor.S \
|
||||
|
||||
LOCAL_SRC_FILES_EXCLUDE_arm += \
|
||||
upstream-freebsd/lib/msun/src/e_sqrt.c \
|
||||
upstream-freebsd/lib/msun/src/e_sqrtf.c \
|
||||
upstream-freebsd/lib/msun/src/s_floor.c \
|
||||
|
||||
endif
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
@@ -301,64 +303,30 @@ LOCAL_SRC_FILES_arm64 += \
|
||||
arm64/rint.S \
|
||||
arm64/sqrt.S \
|
||||
arm64/trunc.S \
|
||||
upstream-freebsd/lib/msun/src/e_acos.c \
|
||||
upstream-freebsd/lib/msun/src/e_asin.c \
|
||||
upstream-freebsd/lib/msun/src/e_atan2.c \
|
||||
upstream-freebsd/lib/msun/src/e_cosh.c \
|
||||
upstream-freebsd/lib/msun/src/e_exp.c \
|
||||
upstream-freebsd/lib/msun/src/e_hypot.c \
|
||||
upstream-freebsd/lib/msun/src/e_log.c \
|
||||
upstream-freebsd/lib/msun/src/e_log10.c \
|
||||
upstream-freebsd/lib/msun/src/e_pow.c \
|
||||
upstream-freebsd/lib/msun/src/e_sinh.c \
|
||||
upstream-freebsd/lib/msun/src/s_atan.c \
|
||||
upstream-freebsd/lib/msun/src/s_cbrt.c \
|
||||
upstream-freebsd/lib/msun/src/s_cos.c \
|
||||
upstream-freebsd/lib/msun/src/s_expm1.c \
|
||||
upstream-freebsd/lib/msun/src/s_log1p.c \
|
||||
upstream-freebsd/lib/msun/src/s_sin.c \
|
||||
upstream-freebsd/lib/msun/src/s_tan.c \
|
||||
upstream-freebsd/lib/msun/src/s_tanh.c \
|
||||
|
||||
LOCAL_SRC_FILES_EXCLUDE_arm64 += \
|
||||
upstream-freebsd/lib/msun/src/e_sqrt.c \
|
||||
upstream-freebsd/lib/msun/src/e_sqrtf.c \
|
||||
upstream-freebsd/lib/msun/src/s_ceil.c \
|
||||
upstream-freebsd/lib/msun/src/s_ceilf.c \
|
||||
upstream-freebsd/lib/msun/src/s_fma.c \
|
||||
upstream-freebsd/lib/msun/src/s_fmaf.c \
|
||||
upstream-freebsd/lib/msun/src/s_floor.c \
|
||||
upstream-freebsd/lib/msun/src/s_floorf.c \
|
||||
upstream-freebsd/lib/msun/src/s_llrint.c \
|
||||
upstream-freebsd/lib/msun/src/s_llrintf.c \
|
||||
upstream-freebsd/lib/msun/src/s_lrint.c \
|
||||
upstream-freebsd/lib/msun/src/s_lrintf.c \
|
||||
upstream-freebsd/lib/msun/src/s_rint.c \
|
||||
upstream-freebsd/lib/msun/src/s_rintf.c \
|
||||
upstream-freebsd/lib/msun/src/s_trunc.c \
|
||||
upstream-freebsd/lib/msun/src/s_truncf.c \
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# mips
|
||||
# -----------------------------------------------------------------------------
|
||||
libm_mips_arch_files := \
|
||||
mips/fenv.c \
|
||||
upstream-freebsd/lib/msun/src/e_acos.c \
|
||||
upstream-freebsd/lib/msun/src/e_asin.c \
|
||||
upstream-freebsd/lib/msun/src/e_atan2.c \
|
||||
upstream-freebsd/lib/msun/src/e_cosh.c \
|
||||
upstream-freebsd/lib/msun/src/e_exp.c \
|
||||
upstream-freebsd/lib/msun/src/e_hypot.c \
|
||||
upstream-freebsd/lib/msun/src/e_log.c \
|
||||
upstream-freebsd/lib/msun/src/e_log10.c \
|
||||
upstream-freebsd/lib/msun/src/e_pow.c \
|
||||
upstream-freebsd/lib/msun/src/e_sinh.c \
|
||||
upstream-freebsd/lib/msun/src/e_sqrt.c \
|
||||
upstream-freebsd/lib/msun/src/e_sqrtf.c \
|
||||
upstream-freebsd/lib/msun/src/s_atan.c \
|
||||
upstream-freebsd/lib/msun/src/s_cbrt.c \
|
||||
upstream-freebsd/lib/msun/src/s_ceil.c \
|
||||
upstream-freebsd/lib/msun/src/s_ceilf.c \
|
||||
upstream-freebsd/lib/msun/src/s_cos.c \
|
||||
upstream-freebsd/lib/msun/src/s_fma.c \
|
||||
upstream-freebsd/lib/msun/src/s_fmaf.c \
|
||||
upstream-freebsd/lib/msun/src/s_floor.c \
|
||||
upstream-freebsd/lib/msun/src/s_floorf.c \
|
||||
upstream-freebsd/lib/msun/src/s_expm1.c \
|
||||
upstream-freebsd/lib/msun/src/s_llrint.c \
|
||||
upstream-freebsd/lib/msun/src/s_llrintf.c \
|
||||
upstream-freebsd/lib/msun/src/s_log1p.c \
|
||||
upstream-freebsd/lib/msun/src/s_lrint.c \
|
||||
upstream-freebsd/lib/msun/src/s_lrintf.c \
|
||||
upstream-freebsd/lib/msun/src/s_rint.c \
|
||||
upstream-freebsd/lib/msun/src/s_rintf.c \
|
||||
upstream-freebsd/lib/msun/src/s_sin.c \
|
||||
upstream-freebsd/lib/msun/src/s_tan.c \
|
||||
upstream-freebsd/lib/msun/src/s_tanh.c \
|
||||
upstream-freebsd/lib/msun/src/s_trunc.c \
|
||||
upstream-freebsd/lib/msun/src/s_truncf.c \
|
||||
|
||||
LOCAL_SRC_FILES_mips += $(libm_mips_arch_files)
|
||||
LOCAL_SRC_FILES_mips64 += $(libm_mips_arch_files)
|
||||
@@ -368,14 +336,6 @@ LOCAL_SRC_FILES_mips64 += $(libm_mips_arch_files)
|
||||
# -----------------------------------------------------------------------------
|
||||
LOCAL_SRC_FILES_x86 += \
|
||||
i387/fenv.c \
|
||||
upstream-freebsd/lib/msun/src/s_fma.c \
|
||||
upstream-freebsd/lib/msun/src/s_fmaf.c \
|
||||
upstream-freebsd/lib/msun/src/s_llrint.c \
|
||||
upstream-freebsd/lib/msun/src/s_llrintf.c \
|
||||
upstream-freebsd/lib/msun/src/s_lrint.c \
|
||||
upstream-freebsd/lib/msun/src/s_lrintf.c \
|
||||
upstream-freebsd/lib/msun/src/s_rint.c \
|
||||
upstream-freebsd/lib/msun/src/s_rintf.c \
|
||||
x86/sqrt.S \
|
||||
x86/sqrtf.S \
|
||||
x86/e_acos.S \
|
||||
@@ -400,6 +360,28 @@ LOCAL_SRC_FILES_x86 += \
|
||||
x86/s_tanh.S \
|
||||
x86/s_tan.S \
|
||||
|
||||
LOCAL_SRC_FILES_EXCLUDE_x86 += \
|
||||
upstream-freebsd/lib/msun/src/e_acos.c \
|
||||
upstream-freebsd/lib/msun/src/e_asin.c \
|
||||
upstream-freebsd/lib/msun/src/e_atan2.c \
|
||||
upstream-freebsd/lib/msun/src/e_cosh.c \
|
||||
upstream-freebsd/lib/msun/src/e_exp.c \
|
||||
upstream-freebsd/lib/msun/src/e_hypot.c \
|
||||
upstream-freebsd/lib/msun/src/e_log.c \
|
||||
upstream-freebsd/lib/msun/src/e_log10.c \
|
||||
upstream-freebsd/lib/msun/src/e_pow.c \
|
||||
upstream-freebsd/lib/msun/src/e_sinh.c \
|
||||
upstream-freebsd/lib/msun/src/e_sqrt.c \
|
||||
upstream-freebsd/lib/msun/src/e_sqrtf.c \
|
||||
upstream-freebsd/lib/msun/src/s_atan.c \
|
||||
upstream-freebsd/lib/msun/src/s_cbrt.c \
|
||||
upstream-freebsd/lib/msun/src/s_cos.c \
|
||||
upstream-freebsd/lib/msun/src/s_expm1.c \
|
||||
upstream-freebsd/lib/msun/src/s_log1p.c \
|
||||
upstream-freebsd/lib/msun/src/s_sin.c \
|
||||
upstream-freebsd/lib/msun/src/s_tan.c \
|
||||
upstream-freebsd/lib/msun/src/s_tanh.c \
|
||||
|
||||
ifeq ($(ARCH_X86_HAVE_SSE4_1),true)
|
||||
LOCAL_SRC_FILES_x86 += \
|
||||
x86/ceil.S \
|
||||
@@ -409,8 +391,7 @@ LOCAL_SRC_FILES_x86 += \
|
||||
x86/trunc.S \
|
||||
x86/truncf.S \
|
||||
|
||||
else
|
||||
LOCAL_SRC_FILES_x86 += \
|
||||
LOCAL_SRC_FILES_EXCLUDE_x86 += \
|
||||
upstream-freebsd/lib/msun/src/s_ceil.c \
|
||||
upstream-freebsd/lib/msun/src/s_ceilf.c \
|
||||
upstream-freebsd/lib/msun/src/s_floor.c \
|
||||
@@ -425,14 +406,6 @@ endif
|
||||
# -----------------------------------------------------------------------------
|
||||
LOCAL_SRC_FILES_x86_64 += \
|
||||
amd64/fenv.c \
|
||||
upstream-freebsd/lib/msun/src/s_fma.c \
|
||||
upstream-freebsd/lib/msun/src/s_fmaf.c \
|
||||
upstream-freebsd/lib/msun/src/s_llrint.c \
|
||||
upstream-freebsd/lib/msun/src/s_llrintf.c \
|
||||
upstream-freebsd/lib/msun/src/s_lrint.c \
|
||||
upstream-freebsd/lib/msun/src/s_lrintf.c \
|
||||
upstream-freebsd/lib/msun/src/s_rint.c \
|
||||
upstream-freebsd/lib/msun/src/s_rintf.c \
|
||||
x86_64/sqrt.S \
|
||||
x86_64/sqrtf.S \
|
||||
x86_64/e_acos.S \
|
||||
@@ -454,6 +427,28 @@ LOCAL_SRC_FILES_x86_64 += \
|
||||
x86_64/s_tanh.S \
|
||||
x86_64/s_tan.S \
|
||||
|
||||
LOCAL_SRC_FILES_EXCLUDE_x86_64 += \
|
||||
upstream-freebsd/lib/msun/src/e_acos.c \
|
||||
upstream-freebsd/lib/msun/src/e_asin.c \
|
||||
upstream-freebsd/lib/msun/src/e_atan2.c \
|
||||
upstream-freebsd/lib/msun/src/e_cosh.c \
|
||||
upstream-freebsd/lib/msun/src/e_exp.c \
|
||||
upstream-freebsd/lib/msun/src/e_hypot.c \
|
||||
upstream-freebsd/lib/msun/src/e_log.c \
|
||||
upstream-freebsd/lib/msun/src/e_log10.c \
|
||||
upstream-freebsd/lib/msun/src/e_pow.c \
|
||||
upstream-freebsd/lib/msun/src/e_sinh.c \
|
||||
upstream-freebsd/lib/msun/src/e_sqrt.c \
|
||||
upstream-freebsd/lib/msun/src/e_sqrtf.c \
|
||||
upstream-freebsd/lib/msun/src/s_atan.c \
|
||||
upstream-freebsd/lib/msun/src/s_cbrt.c \
|
||||
upstream-freebsd/lib/msun/src/s_cos.c \
|
||||
upstream-freebsd/lib/msun/src/s_expm1.c \
|
||||
upstream-freebsd/lib/msun/src/s_log1p.c \
|
||||
upstream-freebsd/lib/msun/src/s_sin.c \
|
||||
upstream-freebsd/lib/msun/src/s_tan.c \
|
||||
upstream-freebsd/lib/msun/src/s_tanh.c \
|
||||
|
||||
ifeq ($(ARCH_X86_HAVE_SSE4_1),true)
|
||||
LOCAL_SRC_FILES_x86_64 += \
|
||||
x86_64/ceil.S \
|
||||
@@ -463,8 +458,7 @@ LOCAL_SRC_FILES_x86_64 += \
|
||||
x86_64/trunc.S \
|
||||
x86_64/truncf.S \
|
||||
|
||||
else
|
||||
LOCAL_SRC_FILES_x86_64 += \
|
||||
LOCAL_SRC_FILES_EXCLUDE_x86_64 += \
|
||||
upstream-freebsd/lib/msun/src/s_ceil.c \
|
||||
upstream-freebsd/lib/msun/src/s_ceilf.c \
|
||||
upstream-freebsd/lib/msun/src/s_floor.c \
|
||||
|
@@ -272,8 +272,8 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_PRIVATE { # arm x86 mips
|
||||
global: # arm x86 mips
|
||||
LIBC_PRIVATE { # arm mips
|
||||
global: # arm mips
|
||||
___Unwind_Backtrace; # arm
|
||||
___Unwind_ForcedUnwind; # arm
|
||||
___Unwind_RaiseException; # arm
|
||||
@@ -354,7 +354,6 @@ LIBC_PRIVATE { # arm x86 mips
|
||||
__lesf2; # arm
|
||||
__ltdf2; # arm
|
||||
__ltsf2; # arm
|
||||
__muldc3; # arm x86 mips
|
||||
__muldf3; # arm
|
||||
__nedf2; # arm
|
||||
__nesf2; # arm
|
||||
@@ -376,4 +375,4 @@ LIBC_PRIVATE { # arm x86 mips
|
||||
_Unwind_VRS_Pop; # arm
|
||||
_Unwind_VRS_Set; # arm
|
||||
restore_core_regs; # arm
|
||||
} LIBC; # arm x86 mips
|
||||
} LIBC; # arm mips
|
||||
|
@@ -271,8 +271,8 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_PRIVATE { # arm x86 mips
|
||||
global: # arm x86 mips
|
||||
LIBC_PRIVATE { # arm mips
|
||||
global: # arm mips
|
||||
___Unwind_Backtrace; # arm
|
||||
___Unwind_ForcedUnwind; # arm
|
||||
___Unwind_RaiseException; # arm
|
||||
@@ -353,7 +353,6 @@ LIBC_PRIVATE { # arm x86 mips
|
||||
__lesf2; # arm
|
||||
__ltdf2; # arm
|
||||
__ltsf2; # arm
|
||||
__muldc3; # arm x86 mips
|
||||
__muldf3; # arm
|
||||
__nedf2; # arm
|
||||
__nesf2; # arm
|
||||
@@ -375,4 +374,4 @@ LIBC_PRIVATE { # arm x86 mips
|
||||
_Unwind_VRS_Pop; # arm
|
||||
_Unwind_VRS_Set; # arm
|
||||
restore_core_regs; # arm
|
||||
} LIBC; # arm x86 mips
|
||||
} LIBC; # arm mips
|
||||
|
@@ -272,11 +272,10 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_PRIVATE { # arm x86 mips
|
||||
global: # arm x86 mips
|
||||
LIBC_PRIVATE { # arm mips
|
||||
global: # arm mips
|
||||
__fixdfdi; # arm mips
|
||||
__fixsfdi; # arm mips
|
||||
__fixunsdfdi; # arm mips
|
||||
__fixunssfdi; # arm mips
|
||||
__muldc3; # arm x86 mips
|
||||
} LIBC; # arm x86 mips
|
||||
} LIBC; # arm mips
|
||||
|
@@ -272,7 +272,3 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_PRIVATE { # arm x86 mips
|
||||
global: # arm x86 mips
|
||||
__muldc3; # arm x86 mips
|
||||
} LIBC; # arm x86 mips
|
||||
|
@@ -9,12 +9,12 @@ LOCAL_SRC_FILES := \
|
||||
dlfcn.cpp \
|
||||
linker.cpp \
|
||||
linker_allocator.cpp \
|
||||
linker_sdk_versions.cpp \
|
||||
linker_block_allocator.cpp \
|
||||
linker_libc_support.c \
|
||||
linker_mapped_file_fragment.cpp \
|
||||
linker_memory.cpp \
|
||||
linker_phdr.cpp \
|
||||
linker_sdk_versions.cpp \
|
||||
linker_utils.cpp \
|
||||
rt.cpp \
|
||||
|
||||
|
116
linker/dlfcn.cpp
116
linker/dlfcn.cpp
@@ -16,12 +16,10 @@
|
||||
|
||||
#include "linker.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <android/dlext.h>
|
||||
#include <android/api-level.h>
|
||||
|
||||
#include <bionic/pthread_internal.h>
|
||||
@@ -70,8 +68,7 @@ void android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
|
||||
static void* dlopen_ext(const char* filename, int flags,
|
||||
const android_dlextinfo* extinfo, void* caller_addr) {
|
||||
ScopedPthreadMutexLocker locker(&g_dl_mutex);
|
||||
soinfo* caller = find_containing_library(caller_addr);
|
||||
soinfo* result = do_dlopen(filename, flags, extinfo, caller);
|
||||
soinfo* result = do_dlopen(filename, flags, extinfo, caller_addr);
|
||||
if (result == nullptr) {
|
||||
__bionic_format_dlerror("dlopen failed", linker_get_error_buffer());
|
||||
return nullptr;
|
||||
@@ -89,70 +86,23 @@ void* dlopen(const char* filename, int flags) {
|
||||
return dlopen_ext(filename, flags, nullptr, caller_addr);
|
||||
}
|
||||
|
||||
extern android_namespace_t* g_anonymous_namespace;
|
||||
|
||||
void* dlsym(void* handle, const char* symbol) {
|
||||
ScopedPthreadMutexLocker locker(&g_dl_mutex);
|
||||
|
||||
#if !defined(__LP64__)
|
||||
if (handle == nullptr) {
|
||||
__bionic_format_dlerror("dlsym library handle is null", nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (symbol == nullptr) {
|
||||
__bionic_format_dlerror("dlsym symbol name is null", nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
soinfo* found = nullptr;
|
||||
const ElfW(Sym)* sym = nullptr;
|
||||
void* caller_addr = __builtin_return_address(0);
|
||||
soinfo* caller = find_containing_library(caller_addr);
|
||||
|
||||
if (handle == RTLD_DEFAULT || handle == RTLD_NEXT) {
|
||||
sym = dlsym_linear_lookup(symbol, &found, caller, handle);
|
||||
} else {
|
||||
sym = dlsym_handle_lookup(reinterpret_cast<soinfo*>(handle), &found, symbol);
|
||||
}
|
||||
|
||||
if (sym != nullptr) {
|
||||
unsigned bind = ELF_ST_BIND(sym->st_info);
|
||||
|
||||
if ((bind == STB_GLOBAL || bind == STB_WEAK) && sym->st_shndx != 0) {
|
||||
return reinterpret_cast<void*>(found->resolve_symbol_address(sym));
|
||||
}
|
||||
|
||||
__bionic_format_dlerror("symbol found but not global", symbol);
|
||||
return nullptr;
|
||||
} else {
|
||||
__bionic_format_dlerror("undefined symbol", symbol);
|
||||
ScopedPthreadMutexLocker locker(&g_dl_mutex);
|
||||
void* result;
|
||||
if (!do_dlsym(handle, symbol, nullptr, caller_addr, &result)) {
|
||||
__bionic_format_dlerror(linker_get_error_buffer(), nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int dladdr(const void* addr, Dl_info* info) {
|
||||
ScopedPthreadMutexLocker locker(&g_dl_mutex);
|
||||
|
||||
// Determine if this address can be found in any library currently mapped.
|
||||
soinfo* si = find_containing_library(addr);
|
||||
if (si == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(info, 0, sizeof(Dl_info));
|
||||
|
||||
info->dli_fname = si->get_realpath();
|
||||
// Address at which the shared object is loaded.
|
||||
info->dli_fbase = reinterpret_cast<void*>(si->base);
|
||||
|
||||
// Determine if any symbol in the library contains the specified address.
|
||||
ElfW(Sym)* sym = si->find_symbol_by_address(addr);
|
||||
if (sym != nullptr) {
|
||||
info->dli_sname = si->get_string(sym->st_name);
|
||||
info->dli_saddr = reinterpret_cast<void*>(si->resolve_symbol_address(sym));
|
||||
}
|
||||
|
||||
return 1;
|
||||
return do_dladdr(addr, info);
|
||||
}
|
||||
|
||||
int dlclose(void* handle) {
|
||||
@@ -177,6 +127,32 @@ uint32_t android_get_application_target_sdk_version() {
|
||||
return get_application_target_sdk_version();
|
||||
}
|
||||
|
||||
bool android_init_namespaces(const char* public_ns_sonames,
|
||||
const char* anon_ns_library_path) {
|
||||
ScopedPthreadMutexLocker locker(&g_dl_mutex);
|
||||
bool success = init_namespaces(public_ns_sonames, anon_ns_library_path);
|
||||
if (!success) {
|
||||
__bionic_format_dlerror("android_init_namespaces failed", linker_get_error_buffer());
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
android_namespace_t* android_create_namespace(const char* name, const char* ld_library_path,
|
||||
const char* default_library_path, bool is_isolated,
|
||||
const char* permitted_when_isolated_path) {
|
||||
ScopedPthreadMutexLocker locker(&g_dl_mutex);
|
||||
|
||||
android_namespace_t* result = create_namespace(name, ld_library_path, default_library_path,
|
||||
is_isolated, permitted_when_isolated_path);
|
||||
|
||||
if (result == nullptr) {
|
||||
__bionic_format_dlerror("android_create_namespace failed", linker_get_error_buffer());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// name_offset: starting index of the name in libdl_info.strtab
|
||||
#define ELF32_SYM_INITIALIZER(name_offset, value, shndx) \
|
||||
{ name_offset, \
|
||||
@@ -203,11 +179,11 @@ static const char ANDROID_LIBDL_STRTAB[] =
|
||||
// 00000000001 1111111112222222222 3333333333444444444455555555556666666666777 777777788888888889999999999
|
||||
// 01234567890 1234567890123456789 0123456789012345678901234567890123456789012 345678901234567890123456789
|
||||
"erate_phdr\0android_dlopen_ext\0android_set_application_target_sdk_version\0android_get_application_tar"
|
||||
// 0000000000111111
|
||||
// 0123456789012345
|
||||
"get_sdk_version\0"
|
||||
// 0000000000111111 111122222222223333333333 4444444444555555555566666
|
||||
// 0123456789012345 678901234567890123456789 0123456789012345678901234
|
||||
"get_sdk_version\0android_init_namespaces\0android_create_namespace\0"
|
||||
#if defined(__arm__)
|
||||
// 216
|
||||
// 265
|
||||
"dl_unwind_find_exidx\0"
|
||||
#endif
|
||||
;
|
||||
@@ -229,8 +205,10 @@ static ElfW(Sym) g_libdl_symtab[] = {
|
||||
ELFW(SYM_INITIALIZER)(111, &android_dlopen_ext, 1),
|
||||
ELFW(SYM_INITIALIZER)(130, &android_set_application_target_sdk_version, 1),
|
||||
ELFW(SYM_INITIALIZER)(173, &android_get_application_target_sdk_version, 1),
|
||||
ELFW(SYM_INITIALIZER)(216, &android_init_namespaces, 1),
|
||||
ELFW(SYM_INITIALIZER)(240, &android_create_namespace, 1),
|
||||
#if defined(__arm__)
|
||||
ELFW(SYM_INITIALIZER)(216, &dl_unwind_find_exidx, 1),
|
||||
ELFW(SYM_INITIALIZER)(265, &dl_unwind_find_exidx, 1),
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -247,18 +225,20 @@ static ElfW(Sym) g_libdl_symtab[] = {
|
||||
// Note that adding any new symbols here requires stubbing them out in libdl.
|
||||
static unsigned g_libdl_buckets[1] = { 1 };
|
||||
#if defined(__arm__)
|
||||
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 };
|
||||
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 0 };
|
||||
#else
|
||||
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 };
|
||||
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 0 };
|
||||
#endif
|
||||
|
||||
static uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8)));
|
||||
static soinfo* __libdl_info = nullptr;
|
||||
|
||||
extern android_namespace_t g_default_namespace;
|
||||
|
||||
// This is used by the dynamic linker. Every process gets these symbols for free.
|
||||
soinfo* get_libdl_info() {
|
||||
if (__libdl_info == nullptr) {
|
||||
__libdl_info = new (__libdl_info_buf) soinfo("libdl.so", nullptr, 0, RTLD_GLOBAL);
|
||||
__libdl_info = new (__libdl_info_buf) soinfo(&g_default_namespace, "libdl.so", nullptr, 0, RTLD_GLOBAL);
|
||||
__libdl_info->flags_ |= FLAG_LINKED;
|
||||
__libdl_info->strtab_ = ANDROID_LIBDL_STRTAB;
|
||||
__libdl_info->symtab_ = g_libdl_symtab;
|
||||
|
@@ -25,12 +25,49 @@ struct LinkedListEntry {
|
||||
T* element;
|
||||
};
|
||||
|
||||
// ForwardInputIterator
|
||||
template<typename T>
|
||||
class LinkedListIterator {
|
||||
public:
|
||||
LinkedListIterator() : entry_(nullptr) {}
|
||||
LinkedListIterator(const LinkedListIterator<T>& that) : entry_(that.entry_) {}
|
||||
explicit LinkedListIterator(LinkedListEntry<T>* entry) : entry_(entry) {}
|
||||
|
||||
LinkedListIterator<T>& operator=(const LinkedListIterator<T>& that) {
|
||||
entry_ = that.entry_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
LinkedListIterator<T>& operator++() {
|
||||
entry_ = entry_->next;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T* operator*() {
|
||||
return entry_->element;
|
||||
}
|
||||
|
||||
bool operator==(const LinkedListIterator<T>& that) const {
|
||||
return entry_ == that.entry_;
|
||||
}
|
||||
|
||||
bool operator!=(const LinkedListIterator<T>& that) const {
|
||||
return entry_ != that.entry_;
|
||||
}
|
||||
|
||||
private:
|
||||
LinkedListEntry<T> *entry_;
|
||||
};
|
||||
|
||||
/*
|
||||
* Represents linked list of objects of type T
|
||||
*/
|
||||
template<typename T, typename Allocator>
|
||||
class LinkedList {
|
||||
public:
|
||||
typedef LinkedListIterator<T> iterator;
|
||||
typedef T* value_type;
|
||||
|
||||
LinkedList() : head_(nullptr), tail_(nullptr) {}
|
||||
~LinkedList() {
|
||||
clear();
|
||||
@@ -127,7 +164,13 @@ class LinkedList {
|
||||
} else {
|
||||
p->next = next;
|
||||
}
|
||||
|
||||
if (tail_ == e) {
|
||||
tail_ = p;
|
||||
}
|
||||
|
||||
Allocator::free(e);
|
||||
|
||||
e = next;
|
||||
} else {
|
||||
p = e;
|
||||
@@ -147,6 +190,24 @@ class LinkedList {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
iterator begin() {
|
||||
return iterator(head_);
|
||||
}
|
||||
|
||||
iterator end() {
|
||||
return iterator(nullptr);
|
||||
}
|
||||
|
||||
iterator find(T* value) {
|
||||
for (LinkedListEntry<T>* e = head_; e != nullptr; e = e->next) {
|
||||
if (e->element == value) {
|
||||
return iterator(e);
|
||||
}
|
||||
}
|
||||
|
||||
return end();
|
||||
}
|
||||
|
||||
size_t copy_to_array(T* array[], size_t array_length) const {
|
||||
size_t sz = 0;
|
||||
for (LinkedListEntry<T>* e = head_; sz < array_length && e != nullptr; e = e->next) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -29,6 +29,7 @@
|
||||
#ifndef _LINKER_H_
|
||||
#define _LINKER_H_
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <android/dlext.h>
|
||||
#include <elf.h>
|
||||
#include <inttypes.h>
|
||||
@@ -86,7 +87,7 @@
|
||||
|
||||
#define SUPPORTED_DT_FLAGS_1 (DF_1_NOW | DF_1_GLOBAL | DF_1_NODELETE)
|
||||
|
||||
#define SOINFO_VERSION 2
|
||||
#define SOINFO_VERSION 3
|
||||
|
||||
#if defined(__work_around_b_24465209__)
|
||||
#define SOINFO_NAME_LEN 128
|
||||
@@ -135,7 +136,7 @@ class SymbolName {
|
||||
};
|
||||
|
||||
struct version_info {
|
||||
version_info() : elf_hash(0), name(nullptr), target_si(nullptr) {}
|
||||
constexpr version_info() : elf_hash(0), name(nullptr), target_si(nullptr) {}
|
||||
|
||||
uint32_t elf_hash;
|
||||
const char* name;
|
||||
@@ -261,7 +262,8 @@ struct soinfo {
|
||||
bool has_DT_SYMBOLIC;
|
||||
|
||||
public:
|
||||
soinfo(const char* name, const struct stat* file_stat, off64_t file_offset, int rtld_flags);
|
||||
soinfo(android_namespace_t* ns, const char* name, const struct stat* file_stat,
|
||||
off64_t file_offset, int rtld_flags);
|
||||
|
||||
void call_constructors();
|
||||
void call_destructors();
|
||||
@@ -311,6 +313,7 @@ struct soinfo {
|
||||
void set_linked();
|
||||
void set_linker_flag();
|
||||
void set_main_executable();
|
||||
void set_nodelete();
|
||||
|
||||
void increment_ref_count();
|
||||
size_t decrement_ref_count();
|
||||
@@ -332,6 +335,7 @@ struct soinfo {
|
||||
|
||||
void set_dt_runpath(const char *);
|
||||
const std::vector<std::string>& get_dt_runpath() const;
|
||||
android_namespace_t* get_namespace();
|
||||
|
||||
private:
|
||||
bool elf_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const;
|
||||
@@ -394,7 +398,9 @@ struct soinfo {
|
||||
|
||||
uint32_t target_sdk_version_;
|
||||
|
||||
// version >= 3
|
||||
std::vector<std::string> dt_runpath_;
|
||||
android_namespace_t* namespace_;
|
||||
|
||||
friend soinfo* get_libdl_info();
|
||||
};
|
||||
@@ -417,15 +423,15 @@ soinfo* get_libdl_info();
|
||||
|
||||
void do_android_get_LD_LIBRARY_PATH(char*, size_t);
|
||||
void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path);
|
||||
soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo, soinfo *caller);
|
||||
soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo, void* caller_addr);
|
||||
void do_dlclose(soinfo* si);
|
||||
|
||||
int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data);
|
||||
|
||||
const ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* caller, void* handle);
|
||||
soinfo* find_containing_library(const void* addr);
|
||||
bool do_dlsym(void* handle, const char* sym_name, const char* sym_ver,
|
||||
void* caller_addr, void** symbol);
|
||||
|
||||
const ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name);
|
||||
int do_dladdr(const void* addr, Dl_info* info);
|
||||
|
||||
void debuggerd_init();
|
||||
extern "C" abort_msg_t* g_abort_message;
|
||||
@@ -437,4 +443,9 @@ size_t linker_get_error_buffer_size();
|
||||
void set_application_target_sdk_version(uint32_t target);
|
||||
uint32_t get_application_target_sdk_version();
|
||||
|
||||
bool init_namespaces(const char* public_ns_sonames, const char* anon_ns_library_path);
|
||||
android_namespace_t* create_namespace(const char* name, const char* ld_library_path,
|
||||
const char* default_library_path, bool is_isolated,
|
||||
const char* permitted_when_isolated_path);
|
||||
|
||||
#endif
|
||||
|
@@ -16,32 +16,13 @@
|
||||
|
||||
#include "linker_mapped_file_fragment.h"
|
||||
#include "linker_debug.h"
|
||||
#include "linker_utils.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
constexpr off64_t kPageMask = ~static_cast<off64_t>(PAGE_SIZE-1);
|
||||
|
||||
static off64_t page_start(off64_t offset) {
|
||||
return offset & kPageMask;
|
||||
}
|
||||
|
||||
static bool safe_add(off64_t* out, off64_t a, size_t b) {
|
||||
CHECK(a >= 0);
|
||||
if (static_cast<uint64_t>(INT64_MAX - a) < b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*out = a + b;
|
||||
return true;
|
||||
}
|
||||
|
||||
static size_t page_offset(off64_t offset) {
|
||||
return static_cast<size_t>(offset & (PAGE_SIZE-1));
|
||||
}
|
||||
|
||||
MappedFileFragment::MappedFileFragment() : map_start_(nullptr), map_size_(0),
|
||||
data_(nullptr), size_ (0)
|
||||
{ }
|
||||
|
@@ -37,6 +37,7 @@
|
||||
|
||||
#include "linker.h"
|
||||
#include "linker_debug.h"
|
||||
#include "linker_utils.h"
|
||||
|
||||
static int GetTargetElfMachine() {
|
||||
#if defined(__arm__)
|
||||
@@ -244,6 +245,16 @@ bool ElfReader::VerifyElfHeader() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ElfReader::CheckFileRange(ElfW(Addr) offset, size_t size) {
|
||||
off64_t range_start;
|
||||
off64_t range_end;
|
||||
|
||||
return safe_add(&range_start, file_offset_, offset) &&
|
||||
safe_add(&range_end, range_start, size) &&
|
||||
range_start < file_size_ &&
|
||||
range_end <= file_size_;
|
||||
}
|
||||
|
||||
// Loads the program header table from an ELF file into a read-only private
|
||||
// anonymous mmap-ed block.
|
||||
bool ElfReader::ReadProgramHeaders() {
|
||||
@@ -256,7 +267,14 @@ bool ElfReader::ReadProgramHeaders() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!phdr_fragment_.Map(fd_, file_offset_, header_.e_phoff, phdr_num_ * sizeof(ElfW(Phdr)))) {
|
||||
// Boundary checks
|
||||
size_t size = phdr_num_ * sizeof(ElfW(Phdr));
|
||||
if (!CheckFileRange(header_.e_phoff, size)) {
|
||||
DL_ERR("\"%s\" has invalid phdr offset/size", name_.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!phdr_fragment_.Map(fd_, file_offset_, header_.e_phoff, size)) {
|
||||
DL_ERR("\"%s\" phdr mmap failed: %s", name_.c_str(), strerror(errno));
|
||||
return false;
|
||||
}
|
||||
@@ -268,7 +286,18 @@ bool ElfReader::ReadProgramHeaders() {
|
||||
bool ElfReader::ReadSectionHeaders() {
|
||||
shdr_num_ = header_.e_shnum;
|
||||
|
||||
if (!shdr_fragment_.Map(fd_, file_offset_, header_.e_shoff, shdr_num_ * sizeof(ElfW(Shdr)))) {
|
||||
if (shdr_num_ == 0) {
|
||||
DL_ERR("\"%s\" has no section headers", name_.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t size = shdr_num_ * sizeof(ElfW(Shdr));
|
||||
if (!CheckFileRange(header_.e_shoff, size)) {
|
||||
DL_ERR("\"%s\" has invalid shdr offset/size", name_.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!shdr_fragment_.Map(fd_, file_offset_, header_.e_shoff, size)) {
|
||||
DL_ERR("\"%s\" shdr mmap failed: %s", name_.c_str(), strerror(errno));
|
||||
return false;
|
||||
}
|
||||
@@ -288,7 +317,7 @@ bool ElfReader::ReadDynamicSection() {
|
||||
}
|
||||
|
||||
if (dynamic_shdr == nullptr) {
|
||||
DL_ERR("\"%s\" .dynamic section was not found", name_.c_str());
|
||||
DL_ERR("\"%s\" .dynamic section header was not found", name_.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -305,6 +334,12 @@ bool ElfReader::ReadDynamicSection() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CheckFileRange(dynamic_shdr->sh_offset, dynamic_shdr->sh_size)) {
|
||||
DL_ERR("\"%s\" has invalid offset/size of .dynamic section", name_.c_str());
|
||||
PRINT("\"%s\" has invalid offset/size of .dynamic section", name_.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!dynamic_fragment_.Map(fd_, file_offset_, dynamic_shdr->sh_offset, dynamic_shdr->sh_size)) {
|
||||
DL_ERR("\"%s\" dynamic section mmap failed: %s", name_.c_str(), strerror(errno));
|
||||
return false;
|
||||
@@ -312,6 +347,12 @@ bool ElfReader::ReadDynamicSection() {
|
||||
|
||||
dynamic_ = static_cast<const ElfW(Dyn)*>(dynamic_fragment_.data());
|
||||
|
||||
if (!CheckFileRange(strtab_shdr->sh_offset, strtab_shdr->sh_size)) {
|
||||
DL_ERR("\"%s\" has invalid offset/size of the .strtab section linked from .dynamic section",
|
||||
name_.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!strtab_fragment_.Map(fd_, file_offset_, strtab_shdr->sh_offset, strtab_shdr->sh_size)) {
|
||||
DL_ERR("\"%s\" strtab section mmap failed: %s", name_.c_str(), strerror(errno));
|
||||
return false;
|
||||
|
@@ -64,6 +64,7 @@ class ElfReader {
|
||||
bool LoadSegments();
|
||||
bool FindPhdr();
|
||||
bool CheckPhdr(ElfW(Addr));
|
||||
bool CheckFileRange(ElfW(Addr) offset, size_t size);
|
||||
|
||||
bool did_read_;
|
||||
bool did_load_;
|
||||
|
@@ -20,7 +20,7 @@
|
||||
bool normalize_path(const char* path, std::string* normalized_path) {
|
||||
// Input should be an absolute path
|
||||
if (path[0] != '/') {
|
||||
PRINT("canonize_path - invalid input: '%s', the input path should be absolute", path);
|
||||
PRINT("normalize_path - invalid input: '%s', the input path should be absolute", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -61,3 +61,76 @@ bool normalize_path(const char* path, std::string* normalized_path) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool file_is_in_dir(const std::string& file, const std::string& dir) {
|
||||
const char* needle = dir.c_str();
|
||||
const char* haystack = file.c_str();
|
||||
size_t needle_len = strlen(needle);
|
||||
|
||||
return strncmp(haystack, needle, needle_len) == 0 &&
|
||||
haystack[needle_len] == '/' &&
|
||||
strchr(haystack + needle_len + 1, '/') == nullptr;
|
||||
}
|
||||
|
||||
bool file_is_under_dir(const std::string& file, const std::string& dir) {
|
||||
const char* needle = dir.c_str();
|
||||
const char* haystack = file.c_str();
|
||||
size_t needle_len = strlen(needle);
|
||||
|
||||
return strncmp(haystack, needle, needle_len) == 0 &&
|
||||
haystack[needle_len] == '/';
|
||||
}
|
||||
|
||||
const char* const kZipFileSeparator = "!/";
|
||||
|
||||
bool parse_zip_path(const char* input_path, std::string* zip_path, std::string* entry_path) {
|
||||
std::string normalized_path;
|
||||
if (!normalize_path(input_path, &normalized_path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* const path = normalized_path.c_str();
|
||||
TRACE("Trying zip file open from path '%s' -> normalized '%s'", input_path, path);
|
||||
|
||||
// Treat an '!/' separator inside a path as the separator between the name
|
||||
// of the zip file on disk and the subdirectory to search within it.
|
||||
// For example, if path is "foo.zip!/bar/bas/x.so", then we search for
|
||||
// "bar/bas/x.so" within "foo.zip".
|
||||
const char* const separator = strstr(path, kZipFileSeparator);
|
||||
if (separator == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
char buf[512];
|
||||
if (strlcpy(buf, path, sizeof(buf)) >= sizeof(buf)) {
|
||||
PRINT("Warning: ignoring very long library path: %s", path);
|
||||
return false;
|
||||
}
|
||||
|
||||
buf[separator - path] = '\0';
|
||||
|
||||
*zip_path = buf;
|
||||
*entry_path = &buf[separator - path + 2];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
constexpr off64_t kPageMask = ~static_cast<off64_t>(PAGE_SIZE-1);
|
||||
|
||||
off64_t page_start(off64_t offset) {
|
||||
return offset & kPageMask;
|
||||
}
|
||||
|
||||
bool safe_add(off64_t* out, off64_t a, size_t b) {
|
||||
CHECK(a >= 0);
|
||||
if (static_cast<uint64_t>(INT64_MAX - a) < b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*out = a + b;
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t page_offset(off64_t offset) {
|
||||
return static_cast<size_t>(offset & (PAGE_SIZE-1));
|
||||
}
|
||||
|
||||
|
@@ -18,6 +18,15 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
extern const char* const kZipFileSeparator;
|
||||
|
||||
bool normalize_path(const char* path, std::string* normalized_path);
|
||||
bool file_is_in_dir(const std::string& file, const std::string& dir);
|
||||
bool file_is_under_dir(const std::string& file, const std::string& dir);
|
||||
bool parse_zip_path(const char* input_path, std::string* zip_path, std::string* entry_path);
|
||||
|
||||
off64_t page_start(off64_t offset);
|
||||
size_t page_offset(off64_t offset);
|
||||
bool safe_add(off64_t* out, off64_t a, size_t b);
|
||||
|
||||
#endif
|
||||
|
@@ -133,6 +133,23 @@ TEST(linked_list, remove_if_then_pop) {
|
||||
ASSERT_TRUE(list.pop_front() == nullptr);
|
||||
}
|
||||
|
||||
TEST(linked_list, remove_if_last_then_push_back) {
|
||||
test_list_t list;
|
||||
|
||||
list.push_back("a");
|
||||
list.push_back("b");
|
||||
list.push_back("c");
|
||||
list.push_back("d");
|
||||
|
||||
list.remove_if([](const char* c) {
|
||||
return *c == 'c' || *c == 'd';
|
||||
});
|
||||
|
||||
ASSERT_EQ("ab", test_list_to_string(list));
|
||||
list.push_back("d");
|
||||
ASSERT_EQ("abd", test_list_to_string(list));
|
||||
}
|
||||
|
||||
TEST(linked_list, copy_to_array) {
|
||||
test_list_t list;
|
||||
const size_t max_size = 128;
|
||||
|
@@ -43,3 +43,62 @@ TEST(linker_utils, normalize_path_smoke) {
|
||||
ASSERT_FALSE(normalize_path("root///dir/.///dir2/somedir/../zipfile!/dir/dir9//..///afile", &output));
|
||||
ASSERT_EQ("unchanged", output);
|
||||
}
|
||||
|
||||
TEST(linker_utils, file_is_in_dir_smoke) {
|
||||
ASSERT_TRUE(file_is_in_dir("/foo/bar/file", "/foo/bar"));
|
||||
ASSERT_FALSE(file_is_in_dir("/foo/bar/file", "/foo"));
|
||||
|
||||
ASSERT_FALSE(file_is_in_dir("/foo/bar/file", "/bar/foo"));
|
||||
|
||||
ASSERT_TRUE(file_is_in_dir("/file", ""));
|
||||
ASSERT_FALSE(file_is_in_dir("/file", "/"));
|
||||
}
|
||||
|
||||
TEST(linker_utils, file_is_under_dir_smoke) {
|
||||
ASSERT_TRUE(file_is_under_dir("/foo/bar/file", "/foo/bar"));
|
||||
ASSERT_TRUE(file_is_under_dir("/foo/bar/file", "/foo"));
|
||||
|
||||
ASSERT_FALSE(file_is_under_dir("/foo/bar/file", "/bar/foo"));
|
||||
|
||||
ASSERT_TRUE(file_is_under_dir("/file", ""));
|
||||
ASSERT_TRUE(file_is_under_dir("/foo/bar/file", ""));
|
||||
ASSERT_FALSE(file_is_under_dir("/file", "/"));
|
||||
ASSERT_FALSE(file_is_under_dir("/foo/bar/file", "/"));
|
||||
}
|
||||
|
||||
TEST(linker_utils, parse_zip_path_smoke) {
|
||||
std::string zip_path;
|
||||
std::string entry_path;
|
||||
|
||||
ASSERT_FALSE(parse_zip_path("/not/a/zip/path/file.zip", &zip_path, &entry_path));
|
||||
ASSERT_FALSE(parse_zip_path("/not/a/zip/path/file.zip!path/in/zip", &zip_path, &entry_path));
|
||||
ASSERT_TRUE(parse_zip_path("/zip/path/file.zip!/path/in/zip", &zip_path, &entry_path));
|
||||
ASSERT_EQ("/zip/path/file.zip", zip_path);
|
||||
ASSERT_EQ("path/in/zip", entry_path);
|
||||
|
||||
ASSERT_TRUE(parse_zip_path("/zip/path/file2.zip!/", &zip_path, &entry_path));
|
||||
ASSERT_EQ("/zip/path/file2.zip", zip_path);
|
||||
ASSERT_EQ("", entry_path);
|
||||
}
|
||||
|
||||
TEST(linker_utils, page_start) {
|
||||
ASSERT_EQ(0x0001000, page_start(0x0001000));
|
||||
ASSERT_EQ(0x3002000, page_start(0x300222f));
|
||||
ASSERT_EQ(0x6001000, page_start(0x6001fff));
|
||||
}
|
||||
|
||||
TEST(linker_utils, page_offset) {
|
||||
ASSERT_EQ(0x0U, page_offset(0x0001000));
|
||||
ASSERT_EQ(0x22fU, page_offset(0x300222f));
|
||||
ASSERT_EQ(0xfffU, page_offset(0x6001fff));
|
||||
}
|
||||
|
||||
TEST(linker_utils, safe_add) {
|
||||
int64_t val = 42;
|
||||
ASSERT_FALSE(safe_add(&val, INT64_MAX-20, 21U));
|
||||
ASSERT_EQ(42, val);
|
||||
ASSERT_TRUE(safe_add(&val, INT64_MAX-42, 42U));
|
||||
ASSERT_EQ(INT64_MAX, val);
|
||||
ASSERT_TRUE(safe_add(&val, 2000, 42U));
|
||||
ASSERT_EQ(2042, val);
|
||||
}
|
||||
|
@@ -28,9 +28,17 @@ ifneq ($(findstring LIBRARY, $(build_target)),LIBRARY)
|
||||
LOCAL_MODULE_STEM_32 := $(module)32
|
||||
LOCAL_MODULE_STEM_64 := $(module)64
|
||||
else
|
||||
|
||||
ifneq ($($(module)_install_to_out_data_dir),)
|
||||
$(module)_install_to_out_data := true
|
||||
endif
|
||||
|
||||
ifeq ($($(module)_install_to_out_data),true)
|
||||
LOCAL_MODULE_PATH_32 := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_NATIVE_TESTS)/$(module)
|
||||
LOCAL_MODULE_PATH_64 := $(TARGET_OUT_DATA_NATIVE_TESTS)/$(module)
|
||||
ifeq ($($(module)_install_to_out_data_dir),)
|
||||
$(module)_install_to_out_data_dir := $(module)
|
||||
endif
|
||||
LOCAL_MODULE_PATH_32 := $($(TARGET_2ND_ARCH_VAR_PREFIX)TARGET_OUT_DATA_NATIVE_TESTS)/$($(module)_install_to_out_data_dir)
|
||||
LOCAL_MODULE_PATH_64 := $(TARGET_OUT_DATA_NATIVE_TESTS)/$($(module)_install_to_out_data_dir)
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@@ -63,6 +63,7 @@ libBionicStandardTests_src_files := \
|
||||
getcwd_test.cpp \
|
||||
inttypes_test.cpp \
|
||||
libc_logging_test.cpp \
|
||||
libgen_basename_test.cpp \
|
||||
libgen_test.cpp \
|
||||
locale_test.cpp \
|
||||
malloc_test.cpp \
|
||||
@@ -141,7 +142,9 @@ libBionicStandardTests_ldlibs_host := \
|
||||
# Clang/llvm has incompatible long double (fp128) for x86_64.
|
||||
# https://llvm.org/bugs/show_bug.cgi?id=23897
|
||||
# This affects most of math_test.cpp.
|
||||
ifeq ($(TARGET_ARCH),$(filter $(TARGET_ARCH),x86_64))
|
||||
libBionicStandardTests_clang_target := false
|
||||
endif
|
||||
|
||||
module := libBionicStandardTests
|
||||
module_tag := optional
|
||||
@@ -168,6 +171,7 @@ $(foreach compiler,gcc clang, \
|
||||
) \
|
||||
)
|
||||
|
||||
fortify1-tests-gcc_clang_target := false
|
||||
module := fortify1-tests-gcc
|
||||
module_tag := optional
|
||||
build_type := target
|
||||
@@ -176,6 +180,7 @@ include $(LOCAL_PATH)/Android.build.mk
|
||||
build_type := host
|
||||
include $(LOCAL_PATH)/Android.build.mk
|
||||
|
||||
fortify2-tests-gcc_clang_target := false
|
||||
module := fortify2-tests-gcc
|
||||
module_tag := optional
|
||||
build_type := target
|
||||
@@ -267,18 +272,20 @@ include $(LOCAL_PATH)/Android.build.mk
|
||||
# Tests for the device using bionic's .so. Run with:
|
||||
# adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests32
|
||||
# adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests64
|
||||
# adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests-gcc32
|
||||
# adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests-gcc64
|
||||
# -----------------------------------------------------------------------------
|
||||
bionic-unit-tests_whole_static_libraries := \
|
||||
common_bionic-unit-tests_whole_static_libraries := \
|
||||
libBionicTests \
|
||||
libBionicGtestMain \
|
||||
|
||||
bionic-unit-tests_static_libraries := \
|
||||
common_bionic-unit-tests_static_libraries := \
|
||||
libtinyxml2 \
|
||||
liblog \
|
||||
libbase \
|
||||
|
||||
# TODO: Include __cxa_thread_atexit_test.cpp to glibc tests once it is upgraded (glibc 2.18+)
|
||||
bionic-unit-tests_src_files := \
|
||||
common_bionic-unit-tests_src_files := \
|
||||
atexit_test.cpp \
|
||||
dl_test.cpp \
|
||||
dlext_test.cpp \
|
||||
@@ -288,36 +295,56 @@ bionic-unit-tests_src_files := \
|
||||
pthread_dlfcn_test.cpp \
|
||||
thread_local_test.cpp \
|
||||
|
||||
bionic-unit-tests_cflags := $(test_cflags)
|
||||
common_bionic-unit-tests_cflags := $(test_cflags)
|
||||
|
||||
bionic-unit-tests_conlyflags := \
|
||||
common_bionic-unit-tests_conlyflags := \
|
||||
-fexceptions \
|
||||
-fnon-call-exceptions \
|
||||
|
||||
bionic-unit-tests_cppflags := $(test_cppflags)
|
||||
common_bionic-unit-tests_cppflags := $(test_cppflags)
|
||||
|
||||
bionic-unit-tests_ldflags := \
|
||||
common_bionic-unit-tests_ldflags := \
|
||||
-Wl,--export-dynamic
|
||||
|
||||
bionic-unit-tests_c_includes := \
|
||||
common_bionic-unit-tests_c_includes := \
|
||||
bionic/libc \
|
||||
|
||||
bionic-unit-tests_shared_libraries_target := \
|
||||
common_bionic-unit-tests_shared_libraries_target := \
|
||||
libdl \
|
||||
libpagemap \
|
||||
libdl_preempt_test_1 \
|
||||
libdl_preempt_test_2
|
||||
|
||||
# TODO: clang support for thread_local on arm is done via __aeabi_read_tp()
|
||||
# which bionic does not support. Reenable this once this question is resolved.
|
||||
bionic-unit-tests_clang_target := false
|
||||
common_bionic-unit-tests_shared_libraries_target += libdl_test_df_1_global
|
||||
|
||||
bionic-unit-tests_shared_libraries_target += libdl_test_df_1_global
|
||||
|
||||
module := bionic-unit-tests
|
||||
module_tag := optional
|
||||
build_type := target
|
||||
build_target := NATIVE_TEST
|
||||
|
||||
module := bionic-unit-tests
|
||||
bionic-unit-tests_clang_target := true
|
||||
bionic-unit-tests_whole_static_libraries := $(common_bionic-unit-tests_whole_static_libraries)
|
||||
bionic-unit-tests_static_libraries := $(common_bionic-unit-tests_static_libraries)
|
||||
bionic-unit-tests_src_files := $(common_bionic-unit-tests_src_files)
|
||||
bionic-unit-tests_cflags := $(common_bionic-unit-tests_cflags)
|
||||
bionic-unit-tests_conlyflags := $(common_bionic-unit-tests_conlyflags)
|
||||
bionic-unit-tests_cppflags := $(common_bionic-unit-tests_cppflags)
|
||||
bionic-unit-tests_ldflags := $(common_bionic-unit-tests_ldflags)
|
||||
bionic-unit-tests_c_includes := $(common_bionic-unit-tests_c_includes)
|
||||
bionic-unit-tests_shared_libraries_target := $(common_bionic-unit-tests_shared_libraries_target)
|
||||
include $(LOCAL_PATH)/Android.build.mk
|
||||
|
||||
module := bionic-unit-tests-gcc
|
||||
bionic-unit-tests-gcc_clang_target := false
|
||||
bionic-unit-tests-gcc_whole_static_libraries := $(common_bionic-unit-tests_whole_static_libraries)
|
||||
bionic-unit-tests-gcc_static_libraries := $(common_bionic-unit-tests_static_libraries)
|
||||
bionic-unit-tests-gcc_src_files := $(common_bionic-unit-tests_src_files)
|
||||
bionic-unit-tests-gcc_cflags := $(common_bionic-unit-tests_cflags)
|
||||
bionic-unit-tests-gcc_conlyflags := $(common_bionic-unit-tests_conlyflags)
|
||||
bionic-unit-tests-gcc_cppflags := $(common_bionic-unit-tests_cppflags)
|
||||
bionic-unit-tests-gcc_ldflags := $(common_bionic-unit-tests_ldflags)
|
||||
bionic-unit-tests-gcc_c_includes := $(common_bionic-unit-tests_c_includes)
|
||||
bionic-unit-tests-gcc_shared_libraries_target := $(common_bionic-unit-tests_shared_libraries_target)
|
||||
include $(LOCAL_PATH)/Android.build.mk
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
@@ -35,7 +35,12 @@ class ClassWithDtor {
|
||||
std::string message;
|
||||
};
|
||||
|
||||
#if defined(__clang__) && defined(__aarch64__)
|
||||
// b/25642296, aarch64 clang compiled "thread_local" does not link.
|
||||
static ClassWithDtor class_with_dtor;
|
||||
#else
|
||||
static thread_local ClassWithDtor class_with_dtor;
|
||||
#endif
|
||||
|
||||
static void* thread_nop(void* arg) {
|
||||
class_with_dtor.set_message(*static_cast<std::string*>(arg));
|
||||
@@ -47,7 +52,12 @@ TEST(thread_local, smoke) {
|
||||
pthread_t t;
|
||||
ASSERT_EQ(0, pthread_create(&t, nullptr, thread_nop, &msg));
|
||||
ASSERT_EQ(0, pthread_join(t, nullptr));
|
||||
#if defined(__clang__) && defined(__aarch64__)
|
||||
GTEST_LOG_(INFO) << "Skipping test, b/25642296, "
|
||||
<< "thread_local does not work with aarch64 clang/llvm.\n";
|
||||
#else
|
||||
ASSERT_EQ("dtor called.", class_with_dtor_output);
|
||||
#endif
|
||||
}
|
||||
|
||||
class ClassWithDtorForMainThread {
|
||||
@@ -64,7 +74,13 @@ class ClassWithDtorForMainThread {
|
||||
};
|
||||
|
||||
static void thread_atexit_main() {
|
||||
#if defined(__clang__) && defined(__aarch64__)
|
||||
static ClassWithDtorForMainThread class_with_dtor_for_main_thread;
|
||||
GTEST_LOG_(INFO) << "Skipping test, b/25642296, "
|
||||
<< "thread_local does not work with aarch64 clang/llvm.\n";
|
||||
#else
|
||||
static thread_local ClassWithDtorForMainThread class_with_dtor_for_main_thread;
|
||||
#endif
|
||||
class_with_dtor_for_main_thread.set_message("d-tor for main thread called.");
|
||||
exit(0);
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user