Compare commits
652 Commits
brillo-m7-
...
main
Author | SHA1 | Date | |
---|---|---|---|
![]() |
195b85a80f | ||
![]() |
2afe5af77f | ||
![]() |
6d142bcf34 | ||
![]() |
42d949ff9d | ||
![]() |
988e71b2b2 | ||
![]() |
63a42070fc | ||
![]() |
e1f8c66d0b | ||
![]() |
32388ba4dc | ||
![]() |
9353089262 | ||
![]() |
e97ce31fe7 | ||
![]() |
2489161ce5 | ||
![]() |
1464f6d8d9 | ||
![]() |
4664c14fa4 | ||
![]() |
bc02fb964a | ||
![]() |
76dfa6e351 | ||
![]() |
74d7aa1c34 | ||
![]() |
6f72fdede8 | ||
![]() |
52fd4ca0a0 | ||
![]() |
609156e266 | ||
![]() |
d90d067312 | ||
![]() |
031dfe198b | ||
![]() |
7d27b68ef4 | ||
![]() |
6134ed8b8f | ||
![]() |
ffa54cd7ba | ||
![]() |
40c2bf6cf6 | ||
![]() |
c5fd81ab25 | ||
![]() |
63fbb233cb | ||
![]() |
507d6f2a51 | ||
![]() |
9b59acc9c7 | ||
![]() |
e647db7485 | ||
![]() |
bb5730ecdb | ||
![]() |
09f4651c0e | ||
![]() |
c6c3b47be2 | ||
![]() |
116b5698d4 | ||
![]() |
ff164ef661 | ||
![]() |
0ef1d121b5 | ||
![]() |
c1113a3fc7 | ||
![]() |
c8bb96a163 | ||
![]() |
56ecf28014 | ||
![]() |
eb90e91cb5 | ||
![]() |
04673ee997 | ||
![]() |
ff14fb5a1f | ||
![]() |
eac1d371f6 | ||
![]() |
e13434f9da | ||
![]() |
9cddb482b4 | ||
![]() |
2fed6aa9f0 | ||
![]() |
fa8b9312d9 | ||
![]() |
bd4d45d55b | ||
![]() |
b62e633ff6 | ||
![]() |
76814a8250 | ||
![]() |
71417caa92 | ||
![]() |
788a2bc756 | ||
![]() |
5ce79b0af3 | ||
![]() |
be7c7fe218 | ||
![]() |
7331fe18d7 | ||
![]() |
0945ed5cc5 | ||
![]() |
4afd635be1 | ||
![]() |
59fc2e8557 | ||
![]() |
dd57119ced | ||
![]() |
7cb3c4af13 | ||
![]() |
d4f86aed42 | ||
![]() |
27032a39dd | ||
![]() |
0b13f29b2c | ||
![]() |
9f20db1c94 | ||
![]() |
9cf99cbad8 | ||
![]() |
dd586f2ebd | ||
![]() |
ad33ebead8 | ||
![]() |
d3e5301a75 | ||
![]() |
bc2e88a85d | ||
![]() |
4d57e669dc | ||
![]() |
52a05f3ce7 | ||
![]() |
d31d4c1cc6 | ||
![]() |
23af25b747 | ||
![]() |
b34ae08cc6 | ||
![]() |
b1d0a2ae77 | ||
![]() |
881673cb45 | ||
![]() |
585e959849 | ||
![]() |
a3dd076126 | ||
![]() |
162a8524ea | ||
![]() |
61cf963efe | ||
![]() |
a7ff3964ab | ||
![]() |
31951b7f0d | ||
![]() |
52e2db647c | ||
![]() |
2f019872dc | ||
![]() |
b417169d80 | ||
![]() |
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
|
||||
|
27
README.md
27
README.md
@ -169,9 +169,10 @@ As mentioned above, this is currently a two-step process:
|
||||
Updating tzdata
|
||||
---------------
|
||||
|
||||
This is fully automated:
|
||||
This is fully automated (and these days handled by the libcore team, because
|
||||
they own icu, and that needs to be updated in sync with bionic):
|
||||
|
||||
1. Run update-tzdata.py.
|
||||
1. Run update-tzdata.py in external/icu/tools/.
|
||||
|
||||
|
||||
Verifying changes
|
||||
@ -268,18 +269,22 @@ However, this also makes it difficult to run the tests under GDB. To prevent
|
||||
each test from being forked, run the tests with the flag `--no-isolate`.
|
||||
|
||||
|
||||
LP32 ABI bugs
|
||||
-------------
|
||||
32-bit ABI bugs
|
||||
---------------
|
||||
|
||||
This probably belongs in the NDK documentation rather than here, but these
|
||||
are the known ABI bugs in LP32:
|
||||
are the known ABI bugs in the 32-bit ABI:
|
||||
|
||||
* `time_t` is 32-bit. <http://b/5819737>
|
||||
* `time_t` is 32-bit. <http://b/5819737>. In the 64-bit ABI, time_t is
|
||||
64-bit.
|
||||
|
||||
* `off_t` is 32-bit. There is `off64_t`, but no `_FILE_OFFSET_BITS` support.
|
||||
Many of the `off64_t` functions are missing in older releases, and
|
||||
stdio uses 32-bit offsets, so there's no way to fully implement
|
||||
`_FILE_OFFSET_BITS`.
|
||||
* `off_t` is 32-bit. There is `off64_t`, and in newer releases there is
|
||||
almost-complete support for `_FILE_OFFSET_BITS`. Unfortunately our stdio
|
||||
implementation uses 32-bit offsets and -- worse -- function pointers to
|
||||
functions that use 32-bit offsets, so there's no good way to implement
|
||||
the last few pieces <http://b/24807045>. In the 64-bit ABI, off_t is
|
||||
off64_t.
|
||||
|
||||
* `sigset_t` is too small on ARM and x86 (but correct on MIPS), so support
|
||||
for real-time signals is broken. <http://b/5828899>
|
||||
for real-time signals is broken. <http://b/5828899> In the 64-bit ABI,
|
||||
`sigset_t` is the correct size for every architecture.
|
||||
|
@ -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;
|
||||
|
1340
libc/Android.bp
1340
libc/Android.bp
File diff suppressed because it is too large
Load Diff
120
libc/Android.mk
120
libc/Android.mk
@ -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 \
|
||||
@ -150,7 +149,9 @@ libc_bionic_ndk_src_files := \
|
||||
bionic/getpid.cpp \
|
||||
bionic/gettid.cpp \
|
||||
bionic/__gnu_basename.cpp \
|
||||
bionic/ifaddrs.cpp \
|
||||
bionic/inotify_init.cpp \
|
||||
bionic/ioctl.cpp \
|
||||
bionic/lchown.cpp \
|
||||
bionic/lfs64_support.cpp \
|
||||
bionic/__libc_current_sigrtmax.cpp \
|
||||
@ -170,6 +171,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 +244,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 +567,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 +587,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 +625,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
|
||||
@ -637,7 +645,7 @@ ifeq ($(strip $(DEBUG_BIONIC_LIBC)),true)
|
||||
libc_common_cflags += -DDEBUG
|
||||
endif
|
||||
|
||||
ifeq ($(MALLOC_IMPL),dlmalloc)
|
||||
ifeq ($(MALLOC_SVELTE),true)
|
||||
libc_common_cflags += -DUSE_DLMALLOC
|
||||
libc_malloc_src := bionic/dlmalloc.c
|
||||
else
|
||||
@ -646,13 +654,6 @@ else
|
||||
libc_common_c_includes += external/jemalloc/include
|
||||
endif
|
||||
|
||||
# To customize dlmalloc's alignment, set BOARD_MALLOC_ALIGNMENT in
|
||||
# the appropriate BoardConfig.mk file.
|
||||
#
|
||||
ifneq ($(BOARD_MALLOC_ALIGNMENT),)
|
||||
libc_common_cflags += -DMALLOC_ALIGNMENT=$(BOARD_MALLOC_ALIGNMENT)
|
||||
endif
|
||||
|
||||
# Define some common conlyflags
|
||||
libc_common_conlyflags := \
|
||||
-std=gnu99
|
||||
@ -683,13 +684,21 @@ endef
|
||||
# libc_stack_protector.a - stack protector code
|
||||
# ========================================================
|
||||
#
|
||||
# The stack protector code needs to be compiled
|
||||
# with -fno-stack-protector, since it modifies the
|
||||
# stack canary.
|
||||
# Code that implements the stack protector (or that runs
|
||||
# before TLS has been set up) needs to be compiled with
|
||||
# -fno-stack-protector, since it accesses the stack canary
|
||||
# TLS slot.
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := bionic/__stack_chk_fail.cpp
|
||||
LOCAL_SRC_FILES := \
|
||||
bionic/__libc_init_main_thread.cpp \
|
||||
bionic/__stack_chk_fail.cpp \
|
||||
|
||||
LOCAL_SRC_FILES_arm64 := arch-arm64/bionic/__set_tls.c
|
||||
LOCAL_SRC_FILES_x86 := arch-x86/bionic/__set_tls.c
|
||||
LOCAL_SRC_FILES_x86_64 := arch-x86_64/bionic/__set_tls.c
|
||||
|
||||
LOCAL_CFLAGS := $(libc_common_cflags) -fno-stack-protector
|
||||
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
|
||||
LOCAL_CPPFLAGS := $(libc_common_cppflags)
|
||||
@ -706,6 +715,30 @@ $(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
|
||||
# libc_init_static.cpp also needs to be built without stack protector,
|
||||
# because it's responsible for setting up TLS for static executables.
|
||||
# This isn't the case for dynamic executables because the dynamic linker
|
||||
# has already set up the main thread's TLS.
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := bionic/libc_init_static.cpp
|
||||
LOCAL_CFLAGS := $(libc_common_cflags) -fno-stack-protector
|
||||
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
|
||||
LOCAL_CPPFLAGS := $(libc_common_cppflags)
|
||||
LOCAL_C_INCLUDES := $(libc_common_c_includes)
|
||||
LOCAL_MODULE := libc_init_static
|
||||
LOCAL_CLANG := $(use_clang)
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
|
||||
LOCAL_CXX_STL := none
|
||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
|
||||
LOCAL_SANITIZE := never
|
||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
|
||||
|
||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
|
||||
# ========================================================
|
||||
# libc_tzcode.a - upstream 'tzcode' code
|
||||
# ========================================================
|
||||
@ -724,6 +757,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 +765,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 +975,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 +1071,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
|
||||
@ -1209,7 +1228,7 @@ LOCAL_WHOLE_STATIC_LIBRARIES := \
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES_arm := libc_aeabi
|
||||
LOCAL_CXX_STL := none
|
||||
|
||||
ifneq ($(MALLOC_IMPL),dlmalloc)
|
||||
ifneq ($(MALLOC_SVELTE),true)
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES += libjemalloc
|
||||
endif
|
||||
|
||||
@ -1249,7 +1268,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
|
||||
@ -1282,7 +1300,6 @@ include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
$(libc_arch_static_src_files) \
|
||||
bionic/libc_init_static.cpp
|
||||
|
||||
LOCAL_C_INCLUDES := $(libc_common_c_includes)
|
||||
LOCAL_CFLAGS := $(libc_common_cflags) \
|
||||
@ -1294,7 +1311,7 @@ LOCAL_CPPFLAGS := $(libc_common_cppflags)
|
||||
LOCAL_MODULE := libc_nomalloc
|
||||
LOCAL_CLANG := $(use_clang)
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES := libc_common libc_init_static
|
||||
LOCAL_CXX_STL := none
|
||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
|
||||
LOCAL_SANITIZE := never
|
||||
@ -1334,7 +1351,6 @@ include $(CLEAR_VARS)
|
||||
LOCAL_SRC_FILES := \
|
||||
$(libc_arch_static_src_files) \
|
||||
bionic/malloc_debug_common.cpp \
|
||||
bionic/libc_init_static.cpp \
|
||||
|
||||
LOCAL_CFLAGS := $(libc_common_cflags) \
|
||||
-DLIBC_STATIC \
|
||||
@ -1345,9 +1361,9 @@ LOCAL_C_INCLUDES := $(libc_common_c_includes)
|
||||
LOCAL_MODULE := libc
|
||||
LOCAL_CLANG := $(use_clang)
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(libc_common_additional_dependencies)
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES := libc_common libc_init_static
|
||||
|
||||
ifneq ($(MALLOC_IMPL),dlmalloc)
|
||||
ifneq ($(MALLOC_SVELTE),true)
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES += libjemalloc
|
||||
endif
|
||||
|
||||
@ -1391,6 +1407,9 @@ 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.mips.brillo.map \
|
||||
$(LOCAL_PATH)/libc.x86.brillo.map \
|
||||
|
||||
# Leave the symbols in the shared library so that stack unwinders can produce
|
||||
# meaningful name resolution.
|
||||
@ -1410,7 +1429,7 @@ LOCAL_PACK_MODULE_RELOCATIONS := false
|
||||
LOCAL_SHARED_LIBRARIES := libdl
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES := libc_common
|
||||
|
||||
ifneq ($(MALLOC_IMPL),dlmalloc)
|
||||
ifneq ($(MALLOC_SVELTE),true)
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES += libjemalloc
|
||||
endif
|
||||
|
||||
@ -1422,11 +1441,18 @@ 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
|
||||
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
|
||||
endif
|
||||
|
||||
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
|
||||
|
||||
# We'd really like to do this for all architectures, but since this wasn't done
|
||||
|
@ -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
|
||||
|
@ -51,34 +51,62 @@ extern int __cxa_atexit(void (*)(void*), void*, void*);
|
||||
*/
|
||||
|
||||
int __attribute__((weak))
|
||||
__aeabi_atexit(void *object, void (*destructor) (void *), void *dso_handle) {
|
||||
__aeabi_atexit_impl(void *object, void (*destructor) (void *), void *dso_handle) {
|
||||
return __cxa_atexit(destructor, object, dso_handle);
|
||||
}
|
||||
|
||||
int __attribute__((weak))
|
||||
__aeabi_atexit_impl2(void *object, void (*destructor) (void *), void *dso_handle) {
|
||||
return __cxa_atexit(destructor, object, dso_handle);
|
||||
}
|
||||
|
||||
|
||||
void __attribute__((weak))
|
||||
__aeabi_memcpy8(void *dest, const void *src, size_t n) {
|
||||
void __attribute__((weak)) __aeabi_memcpy8_impl(void *dest, const void *src, size_t n) {
|
||||
memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memcpy4(void *dest, const void *src, size_t n) {
|
||||
void __attribute__((weak)) __aeabi_memcpy4_impl(void *dest, const void *src, size_t n) {
|
||||
memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memcpy(void *dest, const void *src, size_t n) {
|
||||
void __attribute__((weak)) __aeabi_memcpy_impl(void *dest, const void *src, size_t n) {
|
||||
memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memcpy8_impl2(void *dest, const void *src, size_t n) {
|
||||
memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memcpy4_impl2(void *dest, const void *src, size_t n) {
|
||||
memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memcpy_impl2(void *dest, const void *src, size_t n) {
|
||||
memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
|
||||
void __attribute__((weak)) __aeabi_memmove8(void *dest, const void *src, size_t n) {
|
||||
void __attribute__((weak)) __aeabi_memmove8_impl(void *dest, const void *src, size_t n) {
|
||||
memmove(dest, src, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memmove4(void *dest, const void *src, size_t n) {
|
||||
void __attribute__((weak)) __aeabi_memmove4_impl(void *dest, const void *src, size_t n) {
|
||||
memmove(dest, src, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memmove(void *dest, const void *src, size_t n) {
|
||||
void __attribute__((weak)) __aeabi_memmove_impl(void *dest, const void *src, size_t n) {
|
||||
memmove(dest, src, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memmove8_impl2(void *dest, const void *src, size_t n) {
|
||||
memmove(dest, src, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memmove4_impl2(void *dest, const void *src, size_t n) {
|
||||
memmove(dest, src, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memmove_impl2(void *dest, const void *src, size_t n) {
|
||||
memmove(dest, src, n);
|
||||
}
|
||||
|
||||
@ -87,27 +115,71 @@ void __attribute__((weak)) __aeabi_memmove(void *dest, const void *src, size_t n
|
||||
* This allows __aeabi_memclr to tail-call __aeabi_memset
|
||||
*/
|
||||
|
||||
void __attribute__((weak)) __aeabi_memset8(void *dest, size_t n, int c) {
|
||||
void __attribute__((weak)) __aeabi_memset8_impl(void *dest, size_t n, int c) {
|
||||
memset(dest, c, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memset4(void *dest, size_t n, int c) {
|
||||
void __attribute__((weak)) __aeabi_memset4_impl(void *dest, size_t n, int c) {
|
||||
memset(dest, c, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memset(void *dest, size_t n, int c) {
|
||||
void __attribute__((weak)) __aeabi_memset_impl(void *dest, size_t n, int c) {
|
||||
memset(dest, c, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memset8_impl2(void *dest, size_t n, int c) {
|
||||
memset(dest, c, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memset4_impl2(void *dest, size_t n, int c) {
|
||||
memset(dest, c, n);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memset_impl2(void *dest, size_t n, int c) {
|
||||
memset(dest, c, n);
|
||||
}
|
||||
|
||||
|
||||
void __attribute__((weak)) __aeabi_memclr8(void *dest, size_t n) {
|
||||
__aeabi_memset8(dest, n, 0);
|
||||
void __attribute__((weak)) __aeabi_memclr8_impl(void *dest, size_t n) {
|
||||
__aeabi_memset8_impl(dest, n, 0);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memclr4(void *dest, size_t n) {
|
||||
__aeabi_memset4(dest, n, 0);
|
||||
void __attribute__((weak)) __aeabi_memclr4_impl(void *dest, size_t n) {
|
||||
__aeabi_memset4_impl(dest, n, 0);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memclr(void *dest, size_t n) {
|
||||
__aeabi_memset(dest, n, 0);
|
||||
void __attribute__((weak)) __aeabi_memclr_impl(void *dest, size_t n) {
|
||||
__aeabi_memset_impl(dest, n, 0);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memclr8_impl2(void *dest, size_t n) {
|
||||
__aeabi_memset8_impl(dest, n, 0);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memclr4_impl2(void *dest, size_t n) {
|
||||
__aeabi_memset4_impl(dest, n, 0);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) __aeabi_memclr_impl2(void *dest, size_t n) {
|
||||
__aeabi_memset_impl(dest, n, 0);
|
||||
}
|
||||
|
||||
#define __AEABI_SYMVERS(fn_name) \
|
||||
__asm__(".symver " #fn_name "_impl, " #fn_name "@@LIBC_N"); \
|
||||
__asm__(".symver " #fn_name "_impl2, " #fn_name "@LIBC_PRIVATE")
|
||||
|
||||
__AEABI_SYMVERS(__aeabi_atexit);
|
||||
__AEABI_SYMVERS(__aeabi_memcpy8);
|
||||
__AEABI_SYMVERS(__aeabi_memcpy4);
|
||||
__AEABI_SYMVERS(__aeabi_memcpy);
|
||||
__AEABI_SYMVERS(__aeabi_memmove8);
|
||||
__AEABI_SYMVERS(__aeabi_memmove4);
|
||||
__AEABI_SYMVERS(__aeabi_memmove);
|
||||
__AEABI_SYMVERS(__aeabi_memset8);
|
||||
__AEABI_SYMVERS(__aeabi_memset4);
|
||||
__AEABI_SYMVERS(__aeabi_memset);
|
||||
__AEABI_SYMVERS(__aeabi_memclr8);
|
||||
__AEABI_SYMVERS(__aeabi_memclr4);
|
||||
__AEABI_SYMVERS(__aeabi_memclr);
|
||||
|
||||
#undef __AEABI_SYMVERS
|
||||
|
@ -37,7 +37,13 @@
|
||||
* the expectation that libc will define it and call through to
|
||||
* a differently-named function in the dynamic linker.
|
||||
*/
|
||||
_Unwind_Ptr __gnu_Unwind_Find_exidx(_Unwind_Ptr pc, int *pcount)
|
||||
{
|
||||
_Unwind_Ptr __gnu_Unwind_Find_exidx_impl(_Unwind_Ptr pc, int *pcount) {
|
||||
return dl_unwind_find_exidx(pc, pcount);
|
||||
}
|
||||
|
||||
_Unwind_Ptr __gnu_Unwind_Find_exidx_impl2(_Unwind_Ptr pc, int *pcount) {
|
||||
return dl_unwind_find_exidx(pc, pcount);
|
||||
}
|
||||
|
||||
__asm__(".symver __gnu_Unwind_Find_exidx_impl,__gnu_Unwind_Find_exidx@LIBC_PRIVATE");
|
||||
__asm__(".symver __gnu_Unwind_Find_exidx_impl2,__gnu_Unwind_Find_exidx@@LIBC_N");
|
||||
|
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)
|
@ -42,7 +42,6 @@ libc_bionic_src_files_arm64 += \
|
||||
arch-arm64/bionic/__bionic_clone.S \
|
||||
arch-arm64/bionic/_exit_with_stack_teardown.S \
|
||||
arch-arm64/bionic/setjmp.S \
|
||||
arch-arm64/bionic/__set_tls.c \
|
||||
arch-arm64/bionic/syscall.S \
|
||||
arch-arm64/bionic/vfork.S \
|
||||
|
||||
|
@ -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
|
@ -25,7 +25,6 @@ libc_bionic_src_files_x86_64 += \
|
||||
arch-x86_64/bionic/_exit_with_stack_teardown.S \
|
||||
arch-x86_64/bionic/__restore_rt.S \
|
||||
arch-x86_64/bionic/setjmp.S \
|
||||
arch-x86_64/bionic/__set_tls.c \
|
||||
arch-x86_64/bionic/syscall.S \
|
||||
arch-x86_64/bionic/vfork.S \
|
||||
|
||||
|
@ -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,32 +15,34 @@
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
struct thread_local_dtor {
|
||||
#include "pthread_internal.h"
|
||||
|
||||
class thread_local_dtor {
|
||||
public:
|
||||
void (*func) (void *);
|
||||
void *arg;
|
||||
void *dso_handle; // unused...
|
||||
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;
|
||||
|
85
libc/bionic/__libc_init_main_thread.cpp
Normal file
85
libc/bionic/__libc_init_main_thread.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (C) 2008 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 "libc_init_common.h"
|
||||
|
||||
#include "private/bionic_auxv.h"
|
||||
#include "private/bionic_globals.h"
|
||||
#include "private/KernelArgumentBlock.h"
|
||||
#include "pthread_internal.h"
|
||||
|
||||
extern "C" int __set_tls(void* ptr);
|
||||
extern "C" int __set_tid_address(int* tid_address);
|
||||
|
||||
// Setup for the main thread. For dynamic executables, this is called by the
|
||||
// linker _before_ libc is mapped in memory. This means that all writes to
|
||||
// globals from this function will apply to linker-private copies and will not
|
||||
// be visible from libc later on.
|
||||
//
|
||||
// Note: this function creates a pthread_internal_t for the initial thread and
|
||||
// stores the pointer in TLS, but does not add it to pthread's thread list. This
|
||||
// has to be done later from libc itself (see __libc_init_common).
|
||||
//
|
||||
// This is in a file by itself because it needs to be built with
|
||||
// -fno-stack-protector because it's responsible for setting up the main
|
||||
// thread's TLS (which stack protector relies on).
|
||||
|
||||
void __libc_init_main_thread(KernelArgumentBlock& args) {
|
||||
__libc_auxv = args.auxv;
|
||||
|
||||
static pthread_internal_t main_thread;
|
||||
|
||||
// The -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);
|
||||
main_thread.set_cached_pid(main_thread.tid);
|
||||
|
||||
// We don't want to free the main thread's stack even when the main thread exits
|
||||
// because things like environment variables with global scope live on it.
|
||||
// We also can't free the pthread_internal_t itself, since that lives on the main
|
||||
// thread's stack rather than on the heap.
|
||||
// The main thread has no mmap allocated space for stack or pthread_internal_t.
|
||||
main_thread.mmap_size = 0;
|
||||
pthread_attr_init(&main_thread.attr);
|
||||
main_thread.attr.guard_size = 0; // The main thread has no guard page.
|
||||
main_thread.attr.stack_size = 0; // User code should never see this; we'll compute it when asked.
|
||||
// TODO: the main thread's sched_policy and sched_priority need to be queried.
|
||||
|
||||
__init_thread(&main_thread);
|
||||
__init_tls(&main_thread);
|
||||
|
||||
// Store a pointer to the kernel argument block in a TLS slot to be
|
||||
// picked up by the libc constructor.
|
||||
main_thread.tls[TLS_SLOT_BIONIC_PREINIT] = &args;
|
||||
|
||||
__init_alternate_signal_stack(&main_thread);
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
241
libc/bionic/ifaddrs.cpp
Normal file
241
libc/bionic/ifaddrs.cpp
Normal file
@ -0,0 +1,241 @@
|
||||
/*
|
||||
* 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 <ifaddrs.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <linux/netlink.h>
|
||||
#include <linux/rtnetlink.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// The public ifaddrs struct is full of pointers. Rather than track several
|
||||
// different allocations, we use a maximally-sized structure with the public
|
||||
// part at offset 0, and pointers into its hidden tail.
|
||||
struct ifaddrs_storage {
|
||||
// Must come first, so that `ifaddrs_storage` is-a `ifaddrs`.
|
||||
ifaddrs ifa;
|
||||
|
||||
// The interface index, so we can match RTM_NEWADDR messages with
|
||||
// earlier RTM_NEWLINK messages (to copy the interface flags).
|
||||
int interface_index;
|
||||
|
||||
// Storage for the pointers in `ifa`.
|
||||
sockaddr_storage addr;
|
||||
sockaddr_storage netmask;
|
||||
sockaddr_storage ifa_ifu;
|
||||
char name[IFNAMSIZ + 1];
|
||||
|
||||
ifaddrs_storage(ifaddrs** list) {
|
||||
memset(this, 0, sizeof(*this));
|
||||
|
||||
// push_front onto `list`.
|
||||
ifa.ifa_next = *list;
|
||||
*list = reinterpret_cast<ifaddrs*>(this);
|
||||
}
|
||||
|
||||
// Netlink gives us the address family in the header, and the
|
||||
// sockaddr_in or sockaddr_in6 bytes as the payload. We need to
|
||||
// stitch the two bits together into the sockaddr that's part of
|
||||
// our portable interface.
|
||||
void SetAddress(int family, const void* data, size_t byteCount) {
|
||||
addr.ss_family = family;
|
||||
memcpy(SockaddrBytes(family, &addr), data, byteCount);
|
||||
ifa.ifa_addr = reinterpret_cast<sockaddr*>(&addr);
|
||||
}
|
||||
|
||||
void SetBroadcastAddress(int family, const void* data, size_t byteCount) {
|
||||
ifa_ifu.ss_family = family;
|
||||
memcpy(SockaddrBytes(family, &ifa_ifu), data, byteCount);
|
||||
ifa.ifa_dstaddr = reinterpret_cast<sockaddr*>(&ifa_ifu);
|
||||
}
|
||||
|
||||
// Netlink gives us the prefix length as a bit count. We need to turn
|
||||
// that into a BSD-compatible netmask represented by a sockaddr*.
|
||||
void SetNetmask(int family, size_t prefix_length) {
|
||||
// ...and work out the netmask from the prefix length.
|
||||
netmask.ss_family = family;
|
||||
uint8_t* dst = SockaddrBytes(family, &netmask);
|
||||
memset(dst, 0xff, prefix_length / 8);
|
||||
if ((prefix_length % 8) != 0) {
|
||||
dst[prefix_length/8] = (0xff << (8 - (prefix_length % 8)));
|
||||
}
|
||||
ifa.ifa_netmask = reinterpret_cast<sockaddr*>(&netmask);
|
||||
}
|
||||
|
||||
private:
|
||||
// Returns a pointer to the first byte in the address data (which is
|
||||
// stored in network byte order).
|
||||
uint8_t* SockaddrBytes(int family, sockaddr_storage* ss) {
|
||||
if (family == AF_INET) {
|
||||
sockaddr_in* ss4 = reinterpret_cast<sockaddr_in*>(ss);
|
||||
return reinterpret_cast<uint8_t*>(&ss4->sin_addr);
|
||||
} else if (family == AF_INET6) {
|
||||
sockaddr_in6* ss6 = reinterpret_cast<sockaddr_in6*>(ss);
|
||||
return reinterpret_cast<uint8_t*>(&ss6->sin6_addr);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
#if !defined(__clang__)
|
||||
// GCC gets confused by NLMSG_DATA and doesn't realize that the old-style
|
||||
// cast is from a system header and should be ignored.
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#endif
|
||||
|
||||
static void __handle_netlink_response(ifaddrs** out, nlmsghdr* hdr) {
|
||||
if (hdr->nlmsg_type == RTM_NEWLINK) {
|
||||
ifinfomsg* ifi = reinterpret_cast<ifinfomsg*>(NLMSG_DATA(hdr));
|
||||
|
||||
// Create a new ifaddr entry, and set the interface index and flags.
|
||||
ifaddrs_storage* new_addr = new ifaddrs_storage(out);
|
||||
new_addr->interface_index = ifi->ifi_index;
|
||||
new_addr->ifa.ifa_flags = ifi->ifi_flags;
|
||||
|
||||
// Go through the various bits of information and find the name.
|
||||
rtattr* rta = IFLA_RTA(ifi);
|
||||
size_t rta_len = IFLA_PAYLOAD(hdr);
|
||||
while (RTA_OK(rta, rta_len)) {
|
||||
if (rta->rta_type == IFLA_IFNAME) {
|
||||
if (RTA_PAYLOAD(rta) < sizeof(new_addr->name)) {
|
||||
memcpy(new_addr->name, RTA_DATA(rta), RTA_PAYLOAD(rta));
|
||||
new_addr->ifa.ifa_name = new_addr->name;
|
||||
}
|
||||
}
|
||||
rta = RTA_NEXT(rta, rta_len);
|
||||
}
|
||||
} else if (hdr->nlmsg_type == RTM_NEWADDR) {
|
||||
ifaddrmsg* msg = reinterpret_cast<ifaddrmsg*>(NLMSG_DATA(hdr));
|
||||
|
||||
// We should already know about this from an RTM_NEWLINK message.
|
||||
ifaddrs_storage* addr = reinterpret_cast<ifaddrs_storage*>(*out);
|
||||
while (addr != nullptr && addr->interface_index != static_cast<int>(msg->ifa_index)) {
|
||||
addr = reinterpret_cast<ifaddrs_storage*>(addr->ifa.ifa_next);
|
||||
}
|
||||
// If this is an unknown interface, ignore whatever we're being told about it.
|
||||
if (addr == nullptr) return;
|
||||
|
||||
// Create a new ifaddr entry and copy what we already know.
|
||||
ifaddrs_storage* new_addr = new ifaddrs_storage(out);
|
||||
// We can just copy the name rather than look for IFA_LABEL.
|
||||
strcpy(new_addr->name, addr->name);
|
||||
new_addr->ifa.ifa_name = new_addr->name;
|
||||
new_addr->ifa.ifa_flags = addr->ifa.ifa_flags;
|
||||
new_addr->interface_index = addr->interface_index;
|
||||
|
||||
// Go through the various bits of information and find the address
|
||||
// and any broadcast/destination address.
|
||||
rtattr* rta = IFA_RTA(msg);
|
||||
size_t rta_len = IFA_PAYLOAD(hdr);
|
||||
while (RTA_OK(rta, rta_len)) {
|
||||
if (rta->rta_type == IFA_ADDRESS) {
|
||||
if (msg->ifa_family == AF_INET || msg->ifa_family == AF_INET6) {
|
||||
addr->SetAddress(msg->ifa_family, RTA_DATA(rta), RTA_PAYLOAD(rta));
|
||||
addr->SetNetmask(msg->ifa_family, msg->ifa_prefixlen);
|
||||
}
|
||||
} else if (rta->rta_type == IFA_BROADCAST) {
|
||||
if (msg->ifa_family == AF_INET || msg->ifa_family == AF_INET6) {
|
||||
addr->SetBroadcastAddress(msg->ifa_family, RTA_DATA(rta), RTA_PAYLOAD(rta));
|
||||
}
|
||||
}
|
||||
rta = RTA_NEXT(rta, rta_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool __send_netlink_request(int fd, int type) {
|
||||
struct NetlinkMessage {
|
||||
nlmsghdr hdr;
|
||||
rtgenmsg msg;
|
||||
} request;
|
||||
memset(&request, 0, sizeof(request));
|
||||
request.hdr.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
|
||||
request.hdr.nlmsg_type = type;
|
||||
request.hdr.nlmsg_len = sizeof(request);
|
||||
request.msg.rtgen_family = AF_UNSPEC; // All families.
|
||||
return (TEMP_FAILURE_RETRY(send(fd, &request, sizeof(request), 0)) == sizeof(request));
|
||||
}
|
||||
|
||||
static bool __read_netlink_responses(int fd, ifaddrs** out, char* buf, size_t buf_len) {
|
||||
ssize_t bytes_read;
|
||||
// Read through all the responses, handing interesting ones to __handle_netlink_response.
|
||||
while ((bytes_read = TEMP_FAILURE_RETRY(recv(fd, buf, buf_len, 0))) > 0) {
|
||||
nlmsghdr* hdr = reinterpret_cast<nlmsghdr*>(buf);
|
||||
for (; NLMSG_OK(hdr, static_cast<size_t>(bytes_read)); hdr = NLMSG_NEXT(hdr, bytes_read)) {
|
||||
if (hdr->nlmsg_type == NLMSG_DONE) return true;
|
||||
if (hdr->nlmsg_type == NLMSG_ERROR) return false;
|
||||
__handle_netlink_response(out, hdr);
|
||||
}
|
||||
}
|
||||
// We only get here if recv fails before we see a NLMSG_DONE.
|
||||
return false;
|
||||
}
|
||||
|
||||
int getifaddrs(ifaddrs** out) {
|
||||
// Make cleanup easy.
|
||||
*out = nullptr;
|
||||
|
||||
// The kernel keeps packets under 8KiB (NLMSG_GOODSIZE),
|
||||
// but that's a bit too large to go on the stack.
|
||||
size_t buf_len = 8192;
|
||||
char* buf = new char[buf_len];
|
||||
if (buf == nullptr) return -1;
|
||||
|
||||
// Open the netlink socket and ask for all the links and addresses.
|
||||
int fd = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
|
||||
bool okay = fd != -1 &&
|
||||
__send_netlink_request(fd, RTM_GETLINK) && __read_netlink_responses(fd, out, buf, buf_len) &&
|
||||
__send_netlink_request(fd, RTM_GETADDR) && __read_netlink_responses(fd, out, buf, buf_len);
|
||||
|
||||
if (!okay) {
|
||||
freeifaddrs(*out);
|
||||
// Ensure that callers crash if they forget to check for success.
|
||||
*out = nullptr;
|
||||
}
|
||||
{
|
||||
int saved_errno = errno;
|
||||
close(fd);
|
||||
delete[] buf;
|
||||
errno = saved_errno;
|
||||
}
|
||||
return okay ? 0 : -1;
|
||||
}
|
||||
|
||||
void freeifaddrs(ifaddrs* list) {
|
||||
while (list != nullptr) {
|
||||
ifaddrs* current = list;
|
||||
list = list->ifa_next;
|
||||
free(current);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -52,8 +52,6 @@
|
||||
|
||||
extern "C" abort_msg_t** __abort_message_ptr;
|
||||
extern "C" int __system_properties_init(void);
|
||||
extern "C" int __set_tls(void* ptr);
|
||||
extern "C" int __set_tid_address(int* tid_address);
|
||||
|
||||
__LIBC_HIDDEN__ WriteProtected<libc_globals> __libc_globals;
|
||||
|
||||
@ -66,50 +64,11 @@ char** environ;
|
||||
// Declared in "private/bionic_ssp.h".
|
||||
uintptr_t __stack_chk_guard = 0;
|
||||
|
||||
// Setup for the main thread. For dynamic executables, this is called by the
|
||||
// linker _before_ libc is mapped in memory. This means that all writes to
|
||||
// globals from this function will apply to linker-private copies and will not
|
||||
// be visible from libc later on.
|
||||
//
|
||||
// Note: this function creates a pthread_internal_t for the initial thread and
|
||||
// stores the pointer in TLS, but does not add it to pthread's thread list. This
|
||||
// has to be done later from libc itself (see __libc_init_common).
|
||||
void __libc_init_main_thread(KernelArgumentBlock& args) {
|
||||
__libc_auxv = args.auxv;
|
||||
|
||||
static pthread_internal_t main_thread;
|
||||
|
||||
// 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);
|
||||
main_thread.set_cached_pid(main_thread.tid);
|
||||
|
||||
// We don't want to free the main thread's stack even when the main thread exits
|
||||
// because things like environment variables with global scope live on it.
|
||||
// We also can't free the pthread_internal_t itself, since that lives on the main
|
||||
// thread's stack rather than on the heap.
|
||||
// The main thread has no mmap allocated space for stack or pthread_internal_t.
|
||||
main_thread.mmap_size = 0;
|
||||
pthread_attr_init(&main_thread.attr);
|
||||
main_thread.attr.guard_size = 0; // The main thread has no guard page.
|
||||
main_thread.attr.stack_size = 0; // User code should never see this; we'll compute it when asked.
|
||||
// TODO: the main thread's sched_policy and sched_priority need to be queried.
|
||||
|
||||
__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.
|
||||
main_thread.tls[TLS_SLOT_BIONIC_PREINIT] = &args;
|
||||
|
||||
__init_alternate_signal_stack(&main_thread);
|
||||
}
|
||||
|
||||
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 +80,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 +203,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",
|
||||
@ -329,7 +291,7 @@ void __libc_init_AT_SECURE(KernelArgumentBlock& args) {
|
||||
|
||||
if (getauxval(AT_SECURE)) {
|
||||
// If this is a setuid/setgid program, close the security hole described in
|
||||
// ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-02:23.stdio.asc
|
||||
// https://www.freebsd.org/security/advisories/FreeBSD-SA-02:23.stdio.asc
|
||||
__nullify_closed_stdio();
|
||||
|
||||
__sanitize_environment_variables(args.envp);
|
||||
|
@ -25,6 +25,7 @@
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* libc_init_dynamic.c
|
||||
*
|
||||
|
@ -25,17 +25,6 @@
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
/*
|
||||
* libc_init_static.c
|
||||
*
|
||||
* The program startup function __libc_init() defined here is
|
||||
* used for static executables only (i.e. those that don't depend
|
||||
* on shared libraries). It is called from arch-$ARCH/bionic/crtbegin_static.S
|
||||
* which is directly invoked by the kernel when the program is launched.
|
||||
*
|
||||
* The 'structors' parameter contains pointers to various initializer
|
||||
* arrays that must be run before the program's 'main' routine is launched.
|
||||
*/
|
||||
|
||||
#include <elf.h>
|
||||
#include <errno.h>
|
||||
@ -79,12 +68,19 @@ static void apply_gnu_relro() {
|
||||
}
|
||||
}
|
||||
|
||||
// The program startup function __libc_init() defined here is
|
||||
// used for static executables only (i.e. those that don't depend
|
||||
// on shared libraries). It is called from arch-$ARCH/bionic/crtbegin_static.S
|
||||
// which is directly invoked by the kernel when the program is launched.
|
||||
//
|
||||
// The 'structors' parameter contains pointers to various initializer
|
||||
// arrays that must be run before the program's 'main' routine is launched.
|
||||
|
||||
__noreturn void __libc_init(void* raw_args,
|
||||
void (*onexit)(void) __unused,
|
||||
int (*slingshot)(int, char**, char**),
|
||||
structors_array_t const * const structors) {
|
||||
KernelArgumentBlock args(raw_args);
|
||||
|
||||
__libc_init_main_thread(args);
|
||||
|
||||
// Initializing the globals requires TLS to be available for errno.
|
||||
|
@ -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,37 +47,34 @@
|
||||
|
||||
#include "private/libc_logging.h"
|
||||
|
||||
// Brillo doesn't need to support any legacy cruft.
|
||||
#if !defined(__BRILLO__)
|
||||
extern "C" {
|
||||
|
||||
// Most of the cruft is only for 32-bit Android targets.
|
||||
#if !defined(__LP64__)
|
||||
// Brillo and LP64 don't need to support any legacy cruft.
|
||||
#if !defined(__BRILLO__) && !defined(__LP64__)
|
||||
|
||||
// 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 +87,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 +101,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 +143,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 +191,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 +205,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 +216,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 +283,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 +296,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 +318,42 @@ 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_libc(pthread_t t) {
|
||||
return pthread_gettid_np(t);
|
||||
}
|
||||
|
||||
pid_t __pthread_gettid_libc_private(pthread_t t) {
|
||||
return pthread_gettid_np(t);
|
||||
}
|
||||
|
||||
__asm__(".symver __pthread_gettid_libc,__pthread_gettid@LIBC");
|
||||
__asm__(".symver __pthread_gettid_libc_private,__pthread_gettid@@LIBC_PRIVATE");
|
||||
|
||||
// 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,39 +361,39 @@ 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);
|
||||
}
|
||||
|
||||
#endif // !defined(__LP64__)
|
||||
|
||||
// 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__)
|
||||
#endif // !defined(__BRILLO__) && !defined (__LP64__)
|
||||
|
||||
} // 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, true);
|
||||
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;
|
||||
|
@ -40,7 +40,8 @@
|
||||
/* Has the thread been joined by another thread? */
|
||||
#define PTHREAD_ATTR_FLAG_JOINED 0x00000002
|
||||
|
||||
struct pthread_key_data_t {
|
||||
class pthread_key_data_t {
|
||||
public:
|
||||
uintptr_t seq; // Use uintptr_t just for alignment, as we use pointer below.
|
||||
void* data;
|
||||
};
|
||||
@ -52,9 +53,12 @@ enum ThreadJoinState {
|
||||
THREAD_DETACHED
|
||||
};
|
||||
|
||||
struct pthread_internal_t {
|
||||
struct pthread_internal_t* next;
|
||||
struct pthread_internal_t* prev;
|
||||
class thread_local_dtor;
|
||||
|
||||
class pthread_internal_t {
|
||||
public:
|
||||
class pthread_internal_t* next;
|
||||
class pthread_internal_t* prev;
|
||||
|
||||
pid_t tid;
|
||||
|
||||
@ -94,6 +98,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, true);
|
||||
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, true);
|
||||
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, true);
|
||||
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, true);
|
||||
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, false);
|
||||
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,10 +196,11 @@ 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;
|
||||
static bool initialized = false;
|
||||
|
||||
// NOTE: This isn't static because system_properties_compat.c
|
||||
// requires it.
|
||||
@ -182,13 +221,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 +235,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 +269,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 +296,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 +326,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 +345,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 +370,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 +384,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 +418,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 +469,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 +595,439 @@ 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);
|
||||
}
|
||||
|
||||
class context_node {
|
||||
public:
|
||||
context_node(context_node* next, const char* context, prop_area* pa)
|
||||
: next(next), context_(strdup(context)), pa_(pa), no_access_(false) {
|
||||
lock_.init(false);
|
||||
}
|
||||
~context_node() {
|
||||
unmap();
|
||||
free(context_);
|
||||
}
|
||||
bool open(bool access_rw, bool* fsetxattr_failed);
|
||||
bool check_access_and_open();
|
||||
void reset_access();
|
||||
|
||||
const char* context() const { return context_; }
|
||||
prop_area* pa() { return pa_; }
|
||||
|
||||
context_node* next;
|
||||
|
||||
private:
|
||||
bool check_access();
|
||||
void unmap();
|
||||
|
||||
Lock lock_;
|
||||
char* context_;
|
||||
prop_area* pa_;
|
||||
bool no_access_;
|
||||
};
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
bool context_node::open(bool access_rw, bool* fsetxattr_failed) {
|
||||
lock_.lock();
|
||||
if (pa_) {
|
||||
lock_.unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
char filename[PROP_FILENAME_MAX];
|
||||
int len = snprintf(filename, sizeof(filename), "%s/%s", property_filename, context_);
|
||||
if (len < 0 || len > PROP_FILENAME_MAX) {
|
||||
lock_.unlock();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (access_rw) {
|
||||
pa_ = map_prop_area_rw(filename, context_, fsetxattr_failed);
|
||||
} else {
|
||||
pa_ = map_prop_area(filename, false);
|
||||
}
|
||||
lock_.unlock();
|
||||
return pa_;
|
||||
}
|
||||
|
||||
bool context_node::check_access_and_open() {
|
||||
if (!pa_ && !no_access_) {
|
||||
if (!check_access() || !open(false, nullptr)) {
|
||||
no_access_ = true;
|
||||
}
|
||||
}
|
||||
return pa_;
|
||||
}
|
||||
|
||||
void context_node::reset_access() {
|
||||
if (!check_access()) {
|
||||
unmap();
|
||||
no_access_ = true;
|
||||
} else {
|
||||
no_access_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool context_node::check_access() {
|
||||
char filename[PROP_FILENAME_MAX];
|
||||
int len = snprintf(filename, sizeof(filename), "%s/%s", property_filename, context_);
|
||||
if (len < 0 || len > PROP_FILENAME_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return access(filename, R_OK) == 0;
|
||||
}
|
||||
|
||||
void context_node::unmap() {
|
||||
if (!pa_) {
|
||||
return;
|
||||
}
|
||||
|
||||
munmap(pa_, pa_size);
|
||||
if (pa_ == __system_property_area__) {
|
||||
__system_property_area__ = nullptr;
|
||||
}
|
||||
pa_ = nullptr;
|
||||
}
|
||||
|
||||
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()) {
|
||||
/*
|
||||
* We explicitly do not check no_access_ in this case because unlike the
|
||||
* case of foreach(), we want to generate an selinux audit for each
|
||||
* non-permitted property access in this function.
|
||||
*/
|
||||
cnode->open(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() {
|
||||
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);
|
||||
}
|
||||
|
||||
static void free_and_unmap_contexts() {
|
||||
list_free(&prefixes);
|
||||
list_free(&contexts);
|
||||
if (__system_property_area__) {
|
||||
munmap(__system_property_area__, pa_size);
|
||||
__system_property_area__ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int __system_properties_init()
|
||||
{
|
||||
return map_prop_area();
|
||||
if (initialized) {
|
||||
list_foreach(contexts, [](context_node* l) { l->reset_access(); });
|
||||
return 0;
|
||||
}
|
||||
if (is_dir(property_filename)) {
|
||||
if (!initialize_properties()) {
|
||||
return -1;
|
||||
}
|
||||
if (!map_system_property_area(false, nullptr)) {
|
||||
free_and_unmap_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);
|
||||
}
|
||||
initialized = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int __system_property_set_filename(const char *filename)
|
||||
@ -595,7 +1042,24 @@ int __system_property_set_filename(const char *filename)
|
||||
|
||||
int __system_property_area_init()
|
||||
{
|
||||
return map_prop_area_rw();
|
||||
free_and_unmap_contexts();
|
||||
mkdir(property_filename, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
|
||||
if (!initialize_properties()) {
|
||||
return -1;
|
||||
}
|
||||
bool open_failed = false;
|
||||
bool fsetxattr_failed = false;
|
||||
list_foreach(contexts, [&fsetxattr_failed, &open_failed](context_node* l) {
|
||||
if (!l->open(true, &fsetxattr_failed)) {
|
||||
open_failed = true;
|
||||
}
|
||||
});
|
||||
if (open_failed || !map_system_property_area(true, &fsetxattr_failed)) {
|
||||
free_and_unmap_contexts();
|
||||
return -1;
|
||||
}
|
||||
initialized = true;
|
||||
return fsetxattr_failed ? -2 : 0;
|
||||
}
|
||||
|
||||
unsigned int __system_property_area_serial()
|
||||
@ -605,15 +1069,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 +1163,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 +1187,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 +1198,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 +1205,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 +1248,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 +1275,18 @@ 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->check_access_and_open()) {
|
||||
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,75 @@ 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);
|
||||
|
||||
|
||||
enum {
|
||||
/* A regular namespace is the namespace with a custom search path that does
|
||||
* not impose any restrictions on the location of native libraries.
|
||||
*/
|
||||
ANDROID_NAMESPACE_TYPE_REGULAR = 0,
|
||||
|
||||
/* An isolated namespace requires all the libraries to be on the search path
|
||||
* or under permitted_when_isolated_path. The search path is the union of
|
||||
* ld_library_path and default_library_path.
|
||||
*/
|
||||
ANDROID_NAMESPACE_TYPE_ISOLATED = 1,
|
||||
|
||||
/* The shared namespace clones the list of libraries of the caller namespace upon creation
|
||||
* which means that they are shared between namespaces - the caller namespace and the new one
|
||||
* will use the same copy of a library if it was loaded prior to android_create_namespace call.
|
||||
*
|
||||
* Note that libraries loaded after the namespace is created will not be shared.
|
||||
*
|
||||
* Shared namespaces can be isolated or regular. Note that they do not inherit the search path nor
|
||||
* permitted_path from the caller's namespace.
|
||||
*/
|
||||
ANDROID_NAMESPACE_TYPE_SHARED = 2,
|
||||
ANDROID_NAMESPACE_TYPE_SHARED_ISOLATED = ANDROID_NAMESPACE_TYPE_SHARED |
|
||||
ANDROID_NAMESPACE_TYPE_ISOLATED,
|
||||
};
|
||||
|
||||
/*
|
||||
* 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 type is ANDROID_NAMESPACE_TYPE_ISOLATED 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,
|
||||
uint64_t type,
|
||||
const char* permitted_when_isolated_path);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* __ANDROID_DLEXT_H__ */
|
||||
|
@ -43,11 +43,12 @@ typedef struct {
|
||||
in dli_sname */
|
||||
} Dl_info;
|
||||
|
||||
extern void* dlopen(const char* filename, int flag);
|
||||
extern int dlclose(void* handle);
|
||||
extern const char* dlerror(void);
|
||||
extern void* dlsym(void* handle, const char* symbol);
|
||||
extern int dladdr(const void* addr, Dl_info *info);
|
||||
extern void* dlopen(const char* filename, int flag);
|
||||
extern int dlclose(void* handle);
|
||||
extern const char* dlerror(void);
|
||||
extern void* dlsym(void* handle, const char* symbol) __nonnull((2));
|
||||
extern void* dlvsym(void* handle, const char* symbol, const char* version) __nonnull((2, 3));
|
||||
extern int dladdr(const void* addr, Dl_info *info);
|
||||
|
||||
enum {
|
||||
#if defined(__LP64__)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -25,17 +25,35 @@
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _BIONIC_TIME_H
|
||||
#define _BIONIC_TIME_H
|
||||
|
||||
#include <time.h>
|
||||
#ifndef _IFADDRS_H_
|
||||
#define _IFADDRS_H_
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
// We can't remove this (and this file) until we fix MtpUtils.cpp.
|
||||
time_t mktime_tz(struct tm* const, char const*);
|
||||
struct ifaddrs {
|
||||
struct ifaddrs* ifa_next;
|
||||
char* ifa_name;
|
||||
unsigned int ifa_flags;
|
||||
struct sockaddr* ifa_addr;
|
||||
struct sockaddr* ifa_netmask;
|
||||
union {
|
||||
struct sockaddr* ifu_broadaddr;
|
||||
struct sockaddr* ifu_dstaddr;
|
||||
} ifa_ifu;
|
||||
void* ifa_data;
|
||||
};
|
||||
|
||||
#define ifa_broadaddr ifa_ifu.ifu_broadaddr
|
||||
#define ifa_dstaddr ifa_ifu.ifu_dstaddr
|
||||
|
||||
void freeifaddrs(struct ifaddrs*);
|
||||
int getifaddrs(struct ifaddrs**);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _BIONIC_TIME_H */
|
||||
#endif
|
@ -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);
|
||||
|
1434
libc/libc.arm.brillo.map
Normal file
1434
libc/libc.arm.brillo.map
Normal file
File diff suppressed because it is too large
Load Diff
@ -10,43 +10,25 @@ LIBC {
|
||||
__b64_ntop;
|
||||
__b64_pton;
|
||||
__brk; # arm x86 mips
|
||||
__cmpdf2; # arm
|
||||
__cmsg_nxthdr;
|
||||
__connect; # arm x86 mips
|
||||
__ctype_get_mb_cur_max;
|
||||
__cxa_atexit;
|
||||
__cxa_finalize;
|
||||
__cxa_thread_atexit_impl;
|
||||
__divdf3; # arm
|
||||
__divdi3; # arm x86 mips
|
||||
__divsf3; # arm
|
||||
__divsi3; # arm
|
||||
__dn_comp;
|
||||
__dn_count_labels;
|
||||
__dn_skipname;
|
||||
__epoll_pwait; # arm x86 mips
|
||||
__eqdf2; # arm
|
||||
__errno;
|
||||
__exit; # arm x86 mips
|
||||
__extendsfdf2; # arm
|
||||
__fbufsize;
|
||||
__fcntl64; # arm x86 mips
|
||||
__FD_CLR_chk;
|
||||
__FD_ISSET_chk;
|
||||
__FD_SET_chk;
|
||||
__fgets_chk;
|
||||
__fixdfsi; # arm
|
||||
__fixsfsi; # arm
|
||||
__fixunssfsi; # arm
|
||||
__flbf;
|
||||
__floatdidf; # arm
|
||||
__floatdisf; # arm
|
||||
__floatsidf; # arm
|
||||
__floatsisf; # arm
|
||||
__floatundidf; # arm
|
||||
__floatundisf; # arm
|
||||
__floatunsidf; # arm
|
||||
__floatunsisf; # arm
|
||||
__fp_nquery;
|
||||
__fp_query;
|
||||
__fpclassify;
|
||||
@ -58,23 +40,14 @@ LIBC {
|
||||
__freadable;
|
||||
__fsetlocking;
|
||||
__fstatfs64; # arm x86 mips
|
||||
__futex_wait; # arm x86 mips
|
||||
__futex_wake; # arm x86 mips
|
||||
__fwritable;
|
||||
__gedf2; # arm
|
||||
__get_h_errno;
|
||||
__get_thread; # arm x86 mips
|
||||
__get_tls; # arm x86 mips
|
||||
__getcpu; # arm x86 mips
|
||||
__getcwd; # arm x86 mips
|
||||
__getdents64; # arm x86 mips
|
||||
__getpid; # arm x86 mips
|
||||
__getpriority; # arm x86 mips
|
||||
__gnu_basename;
|
||||
__gnu_ldivmod_helper; # arm
|
||||
__gnu_strerror_r;
|
||||
__gnu_uldivmod_helper; # arm
|
||||
__gtdf2; # arm
|
||||
__hostalias;
|
||||
__ioctl; # arm x86 mips
|
||||
__isfinite;
|
||||
@ -90,25 +63,18 @@ LIBC {
|
||||
__isnormalf;
|
||||
__isnormall;
|
||||
__isthreaded;
|
||||
__ledf2; # arm
|
||||
__libc_current_sigrtmax;
|
||||
__libc_current_sigrtmin;
|
||||
__libc_init;
|
||||
__llseek; # arm x86 mips
|
||||
__loc_aton;
|
||||
__loc_ntoa;
|
||||
__lshrdi3; # arm
|
||||
__ltdf2; # arm
|
||||
__memchr_chk;
|
||||
__memcpy_chk;
|
||||
__memmove_chk;
|
||||
__memrchr_chk;
|
||||
__memset_chk;
|
||||
__mmap2; # arm x86 mips
|
||||
__muldf3; # arm
|
||||
__muldi3; # arm
|
||||
__mulsf3; # arm
|
||||
__nedf2; # arm
|
||||
__ns_format_ttl; # arm x86 mips
|
||||
__ns_get16; # arm x86 mips
|
||||
__ns_get32; # arm x86 mips
|
||||
@ -131,7 +97,6 @@ LIBC {
|
||||
__ns_skiprr; # arm x86 mips
|
||||
__ns_sprintrr; # arm x86 mips
|
||||
__ns_sprintrrf; # arm x86 mips
|
||||
__open; # arm x86 mips
|
||||
__open_2;
|
||||
__openat; # arm x86 mips
|
||||
__openat_2;
|
||||
@ -148,11 +113,7 @@ LIBC {
|
||||
__p_time;
|
||||
__p_type;
|
||||
__p_type_syms;
|
||||
__page_shift; # arm x86 mips
|
||||
__page_size; # arm x86 mips
|
||||
__poll_chk;
|
||||
__popcount_tab; # arm
|
||||
__popcountsi2; # arm x86 mips
|
||||
__ppoll; # arm x86 mips
|
||||
__ppoll_chk;
|
||||
__pread64_chk;
|
||||
@ -161,7 +122,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;
|
||||
@ -191,7 +152,6 @@ LIBC {
|
||||
__res_send;
|
||||
__res_send_setqhook;
|
||||
__res_send_setrhook;
|
||||
__restore_core_regs; # arm
|
||||
__rt_sigaction; # arm x86 mips
|
||||
__rt_sigpending; # arm x86 mips
|
||||
__rt_sigprocmask; # arm x86 mips
|
||||
@ -201,27 +161,14 @@ LIBC {
|
||||
__sched_cpucount;
|
||||
__sched_cpufree;
|
||||
__sched_getaffinity; # arm x86 mips
|
||||
__sclose; # arm x86 mips
|
||||
__sdidinit; # arm x86 mips
|
||||
__set_errno; # arm x86 mips
|
||||
__set_tid_address; # arm x86 mips
|
||||
__set_tls; # arm mips
|
||||
__sF;
|
||||
__sflags; # arm x86 mips
|
||||
__sflush; # arm x86 mips
|
||||
__sfp; # arm x86 mips
|
||||
__sglue; # arm x86 mips
|
||||
__sigaction; # arm x86 mips
|
||||
__signalfd4; # arm x86 mips
|
||||
__sinit; # arm x86 mips
|
||||
__smakebuf; # arm x86 mips
|
||||
__snprintf_chk;
|
||||
__socket; # arm x86 mips
|
||||
__sprintf_chk;
|
||||
__sread; # arm x86 mips
|
||||
__srefill; # arm x86 mips
|
||||
__srget; # arm x86 mips
|
||||
__sseek; # arm x86 mips
|
||||
__stack_chk_fail;
|
||||
__stack_chk_guard;
|
||||
__statfs64; # arm x86 mips
|
||||
@ -238,49 +185,37 @@ LIBC {
|
||||
__strncpy_chk;
|
||||
__strncpy_chk2;
|
||||
__strrchr_chk;
|
||||
__subdf3; # arm
|
||||
__subsf3; # arm
|
||||
__swbuf; # arm x86 mips
|
||||
__swrite; # arm x86 mips
|
||||
__swsetup; # arm x86 mips
|
||||
__sym_ntop;
|
||||
__sym_ntos;
|
||||
__sym_ston;
|
||||
__system_properties_init;
|
||||
__system_property_add;
|
||||
__system_property_area__;
|
||||
__system_property_area_init;
|
||||
__system_property_area_serial;
|
||||
__system_property_find;
|
||||
__system_property_find_nth;
|
||||
__system_property_foreach;
|
||||
__system_property_get;
|
||||
__system_property_read;
|
||||
__system_property_serial;
|
||||
__system_property_set;
|
||||
__system_property_set_filename;
|
||||
__system_property_update;
|
||||
__system_property_wait_any;
|
||||
__system_properties_init; # arm x86 mips
|
||||
__system_property_add; # arm x86 mips
|
||||
__system_property_area__; # arm x86 mips
|
||||
__system_property_area_init; # arm x86 mips
|
||||
__system_property_area_serial; # arm x86 mips
|
||||
__system_property_find; # arm x86 mips
|
||||
__system_property_find_nth; # arm x86 mips
|
||||
__system_property_foreach; # arm x86 mips
|
||||
__system_property_get; # arm x86 mips
|
||||
__system_property_read; # arm x86 mips
|
||||
__system_property_serial; # arm x86 mips
|
||||
__system_property_set; # arm x86 mips
|
||||
__system_property_set_filename; # arm x86 mips
|
||||
__system_property_update; # arm x86 mips
|
||||
__system_property_wait_any; # arm x86 mips
|
||||
__timer_create; # arm x86 mips
|
||||
__timer_delete; # arm x86 mips
|
||||
__timer_getoverrun; # arm x86 mips
|
||||
__timer_gettime; # arm x86 mips
|
||||
__timer_settime; # arm x86 mips
|
||||
__truncdfsf2; # arm
|
||||
__udivdi3; # arm x86 mips
|
||||
__udivsi3; # arm
|
||||
__umask_chk;
|
||||
__unorddf2; # arm
|
||||
__unordsf2; # arm
|
||||
__vsnprintf_chk;
|
||||
__vsprintf_chk;
|
||||
__wait4; # arm x86 mips
|
||||
__waitid; # arm x86 mips
|
||||
_ctype_;
|
||||
_Exit;
|
||||
_exit;
|
||||
_flushlbf;
|
||||
_fwalk; # arm x86 mips
|
||||
_getlong;
|
||||
_getshort;
|
||||
_longjmp;
|
||||
@ -307,9 +242,7 @@ LIBC {
|
||||
android_gethostbynamefornet;
|
||||
android_set_abort_message;
|
||||
arc4random;
|
||||
arc4random_addrandom; # arm x86 mips
|
||||
arc4random_buf;
|
||||
arc4random_stir; # arm x86 mips
|
||||
arc4random_uniform;
|
||||
asctime;
|
||||
asctime64; # arm x86 mips
|
||||
@ -323,14 +256,11 @@ LIBC {
|
||||
atoll;
|
||||
basename;
|
||||
basename_r; # arm x86 mips
|
||||
bcopy; # arm x86 mips
|
||||
bind;
|
||||
bindresvport;
|
||||
brk;
|
||||
bsd_signal; # arm x86 mips
|
||||
bsearch;
|
||||
btowc;
|
||||
bzero; # arm x86 mips
|
||||
c16rtomb;
|
||||
c32rtomb;
|
||||
cacheflush; # arm mips
|
||||
@ -383,7 +313,6 @@ LIBC {
|
||||
dup3;
|
||||
duplocale;
|
||||
endmntent;
|
||||
endpwent;
|
||||
endservent;
|
||||
endutent;
|
||||
environ;
|
||||
@ -430,7 +359,6 @@ LIBC {
|
||||
fdatasync;
|
||||
fdopen;
|
||||
fdopendir;
|
||||
fdprintf; # arm x86 mips
|
||||
feof;
|
||||
feof_unlocked;
|
||||
ferror;
|
||||
@ -462,7 +390,6 @@ LIBC {
|
||||
fputws;
|
||||
fread;
|
||||
free;
|
||||
free_malloc_leak_info;
|
||||
freeaddrinfo;
|
||||
freelocale;
|
||||
fremovexattr;
|
||||
@ -483,7 +410,6 @@ LIBC {
|
||||
fsync;
|
||||
ftell;
|
||||
ftello;
|
||||
ftime; # arm x86 mips
|
||||
ftok;
|
||||
ftruncate;
|
||||
ftruncate64;
|
||||
@ -504,7 +430,6 @@ LIBC {
|
||||
fwscanf;
|
||||
gai_strerror;
|
||||
get_avphys_pages;
|
||||
get_malloc_leak_info;
|
||||
get_nprocs;
|
||||
get_nprocs_conf;
|
||||
get_phys_pages;
|
||||
@ -516,8 +441,6 @@ LIBC {
|
||||
getchar_unlocked;
|
||||
getcwd;
|
||||
getdelim;
|
||||
getdents; # arm x86 mips
|
||||
getdtablesize; # arm x86 mips
|
||||
getegid;
|
||||
getenv;
|
||||
geteuid;
|
||||
@ -592,7 +515,6 @@ LIBC {
|
||||
if_nametoindex;
|
||||
imaxabs;
|
||||
imaxdiv;
|
||||
index; # arm x86 mips
|
||||
inet_addr;
|
||||
inet_aton;
|
||||
inet_lnaof;
|
||||
@ -645,7 +567,6 @@ LIBC {
|
||||
isprint_l;
|
||||
ispunct;
|
||||
ispunct_l;
|
||||
issetugid; # arm x86 mips
|
||||
isspace;
|
||||
isspace_l;
|
||||
isupper;
|
||||
@ -735,7 +656,6 @@ LIBC {
|
||||
mempcpy;
|
||||
memrchr;
|
||||
memset;
|
||||
memswap; # arm x86 mips
|
||||
mincore;
|
||||
mkdir;
|
||||
mkdirat;
|
||||
@ -755,7 +675,6 @@ LIBC {
|
||||
mktemp;
|
||||
mktime;
|
||||
mktime64; # arm x86 mips
|
||||
mktime_tz;
|
||||
mlock;
|
||||
mlockall;
|
||||
mmap;
|
||||
@ -826,7 +745,6 @@ LIBC {
|
||||
pthread_attr_getschedpolicy;
|
||||
pthread_attr_getscope;
|
||||
pthread_attr_getstack;
|
||||
pthread_attr_getstackaddr; # arm x86 mips
|
||||
pthread_attr_getstacksize;
|
||||
pthread_attr_init;
|
||||
pthread_attr_setdetachstate;
|
||||
@ -835,7 +753,6 @@ LIBC {
|
||||
pthread_attr_setschedpolicy;
|
||||
pthread_attr_setscope;
|
||||
pthread_attr_setstack;
|
||||
pthread_attr_setstackaddr; # arm x86 mips
|
||||
pthread_attr_setstacksize;
|
||||
pthread_cond_broadcast;
|
||||
pthread_cond_destroy;
|
||||
@ -951,7 +868,6 @@ LIBC {
|
||||
res_mkquery;
|
||||
res_query;
|
||||
res_search;
|
||||
restore_core_regs; # arm
|
||||
rewind;
|
||||
rewinddir;
|
||||
rmdir;
|
||||
@ -1094,8 +1010,6 @@ LIBC {
|
||||
strncpy;
|
||||
strndup;
|
||||
strnlen;
|
||||
strntoimax; # arm x86 mips
|
||||
strntoumax; # arm x86 mips
|
||||
strpbrk;
|
||||
strptime;
|
||||
strrchr;
|
||||
@ -1114,7 +1028,6 @@ LIBC {
|
||||
strtoll;
|
||||
strtoll_l;
|
||||
strtoq;
|
||||
strtotimeval; # arm x86 mips
|
||||
strtoul;
|
||||
strtoull;
|
||||
strtoull_l;
|
||||
@ -1136,7 +1049,6 @@ LIBC {
|
||||
sysinfo;
|
||||
syslog;
|
||||
system;
|
||||
sysv_signal; # arm x86 mips
|
||||
tcdrain;
|
||||
tcflow;
|
||||
tcflush;
|
||||
@ -1168,7 +1080,6 @@ LIBC {
|
||||
timerfd_settime;
|
||||
times;
|
||||
timezone;
|
||||
tkill; # arm x86 mips
|
||||
tmpfile;
|
||||
tmpnam;
|
||||
toascii;
|
||||
@ -1210,7 +1121,6 @@ LIBC {
|
||||
vdprintf;
|
||||
verr;
|
||||
verrx;
|
||||
vfdprintf; # arm x86 mips
|
||||
vfork;
|
||||
vfprintf;
|
||||
vfscanf;
|
||||
@ -1230,7 +1140,6 @@ LIBC {
|
||||
vwprintf;
|
||||
vwscanf;
|
||||
wait;
|
||||
wait3; # arm x86 mips
|
||||
wait4;
|
||||
waitid;
|
||||
waitpid;
|
||||
@ -1279,7 +1188,6 @@ LIBC {
|
||||
wcstoull;
|
||||
wcstoull_l;
|
||||
wcstoumax;
|
||||
wcswcs; # arm x86 mips
|
||||
wcswidth;
|
||||
wcsxfrm;
|
||||
wcsxfrm_l;
|
||||
@ -1304,17 +1212,46 @@ LIBC {
|
||||
|
||||
LIBC_N {
|
||||
global:
|
||||
__aeabi_atexit; # arm
|
||||
__aeabi_memclr; # arm
|
||||
__aeabi_memclr4; # arm
|
||||
__aeabi_memclr8; # arm
|
||||
__aeabi_memcpy; # arm
|
||||
__aeabi_memcpy4; # arm
|
||||
__aeabi_memcpy8; # arm
|
||||
__aeabi_memmove; # arm
|
||||
__aeabi_memmove4; # arm
|
||||
__aeabi_memmove8; # arm
|
||||
__aeabi_memset; # arm
|
||||
__aeabi_memset4; # arm
|
||||
__aeabi_memset8; # arm
|
||||
__fread_chk;
|
||||
__fwrite_chk;
|
||||
__getcwd_chk;
|
||||
__gnu_Unwind_Find_exidx; # arm
|
||||
__pwrite_chk;
|
||||
__pwrite64_chk;
|
||||
__write_chk;
|
||||
fileno_unlocked;
|
||||
freeifaddrs;
|
||||
getgrgid_r;
|
||||
getgrnam_r;
|
||||
getifaddrs;
|
||||
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,8 +1335,33 @@ LIBC_PRIVATE {
|
||||
__ashrdi3; # arm
|
||||
__bionic_brk; # arm x86 mips
|
||||
__bionic_libgcc_compat_symbols; # arm x86
|
||||
__bionic_libgcc_unwind_symbols; # arm
|
||||
__cmpdf2; # arm
|
||||
__divdf3; # arm
|
||||
__divdi3; # arm x86 mips
|
||||
__divsf3; # arm
|
||||
__divsi3; # arm
|
||||
__dso_handle; # arm
|
||||
__eqdf2; # arm
|
||||
__extendsfdf2; # arm
|
||||
__fixdfsi; # arm
|
||||
__fixsfsi; # arm
|
||||
__fixunssfsi; # arm
|
||||
__floatdidf; # arm
|
||||
__floatdisf; # arm
|
||||
__floatsidf; # arm
|
||||
__floatsisf; # arm
|
||||
__floatundidf; # arm
|
||||
__floatundisf; # arm
|
||||
__floatunsidf; # arm
|
||||
__floatunsisf; # arm
|
||||
__futex_wait; # arm x86 mips nobrillo
|
||||
__futex_wake; # arm x86 mips nobrillo
|
||||
__gedf2; # arm
|
||||
__get_thread; # arm x86 mips nobrillo
|
||||
__get_tls; # arm x86 mips nobrillo
|
||||
__getdents64; # arm x86 mips
|
||||
__gnu_ldivmod_helper; # arm
|
||||
__gnu_uldivmod_helper; # arm
|
||||
__gnu_Unwind_Backtrace; # arm
|
||||
__gnu_unwind_execute; # arm
|
||||
__gnu_Unwind_Find_exidx; # arm
|
||||
@ -1418,6 +1380,46 @@ LIBC_PRIVATE {
|
||||
__gnu_Unwind_Save_VFP_D_16_to_31; # arm
|
||||
__gnu_Unwind_Save_WMMXC; # arm
|
||||
__gnu_Unwind_Save_WMMXD; # arm
|
||||
__gtdf2; # arm
|
||||
__ledf2; # arm
|
||||
__lshrdi3; # arm
|
||||
__ltdf2; # arm
|
||||
__muldf3; # arm
|
||||
__muldi3; # arm
|
||||
__mulsf3; # arm
|
||||
__nedf2; # arm
|
||||
__open; # arm x86 mips nobrillo
|
||||
__page_shift; # arm x86 mips nobrillo
|
||||
__page_size; # arm x86 mips nobrillo
|
||||
__popcount_tab; # arm
|
||||
__popcountsi2; # arm x86 mips
|
||||
__pthread_gettid; # arm x86 mips nobrillo
|
||||
__restore_core_regs; # arm
|
||||
__sclose; # arm x86 mips
|
||||
__sdidinit; # arm x86 mips nobrillo
|
||||
__set_errno; # arm x86 mips nobrillo
|
||||
__sflags; # arm x86 mips
|
||||
__sflush; # arm x86 mips
|
||||
__sfp; # arm x86 mips
|
||||
__sglue; # arm x86 mips
|
||||
__sinit; # arm x86 mips nobrillo
|
||||
__smakebuf; # arm x86 mips
|
||||
__sread; # arm x86 mips
|
||||
__srefill; # arm x86 mips
|
||||
__srget; # arm x86 mips
|
||||
__sseek; # arm x86 mips
|
||||
__subdf3; # arm
|
||||
__subsf3; # arm
|
||||
__swbuf; # arm x86 mips
|
||||
__swrite; # arm x86 mips
|
||||
__swsetup; # arm x86 mips
|
||||
__truncdfsf2; # arm
|
||||
__udivdi3; # arm mips
|
||||
__udivsi3; # arm
|
||||
__unorddf2; # arm
|
||||
__unordsf2; # arm
|
||||
__wait4; # arm x86 mips nobrillo
|
||||
_fwalk; # arm x86 mips
|
||||
_Unwind_Backtrace; # arm
|
||||
_Unwind_Complete; # arm
|
||||
_Unwind_DeleteException; # arm
|
||||
@ -1433,14 +1435,40 @@ LIBC_PRIVATE {
|
||||
_Unwind_VRS_Get; # arm
|
||||
_Unwind_VRS_Pop; # arm
|
||||
_Unwind_VRS_Set; # arm
|
||||
arc4random_addrandom; # arm x86 mips nobrillo
|
||||
arc4random_stir; # arm x86 mips nobrillo
|
||||
atexit; # arm
|
||||
dlmalloc; # arm x86 mips
|
||||
dlmalloc_inspect_all;
|
||||
dlmalloc_trim;
|
||||
dlmalloc_usable_size; # arm x86 mips
|
||||
bcopy; # arm x86 mips nobrillo
|
||||
bzero; # arm x86 mips nobrillo
|
||||
bsd_signal; # arm x86 mips nobrillo
|
||||
dlmalloc; # arm x86 mips nobrillo
|
||||
dlmalloc_inspect_all; # arm x86 mips nobrillo
|
||||
dlmalloc_trim; # arm x86 mips nobrillo
|
||||
dlmalloc_usable_size; # arm x86 mips nobrillo
|
||||
endpwent; # arm x86 mips nobrillo
|
||||
fdprintf; # arm x86 mips nobrillo
|
||||
free_malloc_leak_info;
|
||||
ftime; # arm x86 mips nobrillo
|
||||
get_malloc_leak_info;
|
||||
getdents; # arm x86 mips nobrillo
|
||||
getdtablesize; # arm x86 mips nobrillo
|
||||
gMallocLeakZygoteChild;
|
||||
index; # arm x86 mips nobrillo
|
||||
issetugid; # arm x86 mips nobrillo
|
||||
memswap; # arm x86 mips nobrillo
|
||||
pthread_attr_getstackaddr; # arm x86 mips nobrillo
|
||||
pthread_attr_setstackaddr; # arm x86 mips nobrillo
|
||||
restore_core_regs; # arm
|
||||
SHA1Final; # arm x86 mips
|
||||
SHA1Init; # arm x86 mips
|
||||
SHA1Transform; # arm x86 mips
|
||||
SHA1Update; # arm x86 mips
|
||||
strntoimax; # arm x86 mips nobrillo
|
||||
strntoumax; # arm x86 mips nobrillo
|
||||
strtotimeval; # arm x86 mips nobrillo
|
||||
sysv_signal; # arm x86 mips nobrillo
|
||||
tkill; # arm x86 mips nobrillo
|
||||
vfdprintf; # arm x86 mips nobrillo
|
||||
wait3; # arm x86 mips nobrillo
|
||||
wcswcs; # arm x86 mips nobrillo
|
||||
} LIBC_N;
|
||||
|
@ -131,21 +131,6 @@ LIBC {
|
||||
__sym_ntop;
|
||||
__sym_ntos;
|
||||
__sym_ston;
|
||||
__system_properties_init;
|
||||
__system_property_add;
|
||||
__system_property_area__;
|
||||
__system_property_area_init;
|
||||
__system_property_area_serial;
|
||||
__system_property_find;
|
||||
__system_property_find_nth;
|
||||
__system_property_foreach;
|
||||
__system_property_get;
|
||||
__system_property_read;
|
||||
__system_property_serial;
|
||||
__system_property_set;
|
||||
__system_property_set_filename;
|
||||
__system_property_update;
|
||||
__system_property_wait_any;
|
||||
__umask_chk;
|
||||
__vsnprintf_chk;
|
||||
__vsprintf_chk;
|
||||
@ -241,7 +226,6 @@ LIBC {
|
||||
dup3;
|
||||
duplocale;
|
||||
endmntent;
|
||||
endpwent;
|
||||
endservent;
|
||||
endutent;
|
||||
environ;
|
||||
@ -317,7 +301,6 @@ LIBC {
|
||||
fputws;
|
||||
fread;
|
||||
free;
|
||||
free_malloc_leak_info;
|
||||
freeaddrinfo;
|
||||
freelocale;
|
||||
fremovexattr;
|
||||
@ -358,7 +341,6 @@ LIBC {
|
||||
fwscanf;
|
||||
gai_strerror;
|
||||
get_avphys_pages;
|
||||
get_malloc_leak_info;
|
||||
get_nprocs;
|
||||
get_nprocs_conf;
|
||||
get_phys_pages;
|
||||
@ -599,7 +581,6 @@ LIBC {
|
||||
mkstemps64;
|
||||
mktemp;
|
||||
mktime;
|
||||
mktime_tz;
|
||||
mlock;
|
||||
mlockall;
|
||||
mmap;
|
||||
@ -1156,10 +1137,25 @@ LIBC_N {
|
||||
__pwrite_chk;
|
||||
__pwrite64_chk;
|
||||
__write_chk;
|
||||
fileno_unlocked;
|
||||
freeifaddrs;
|
||||
getgrgid_r;
|
||||
getgrnam_r;
|
||||
getifaddrs;
|
||||
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 +1165,22 @@ LIBC_N {
|
||||
|
||||
LIBC_PRIVATE {
|
||||
global:
|
||||
dlmalloc_inspect_all;
|
||||
dlmalloc_trim;
|
||||
__system_properties_init; # arm64 x86_64 mips64
|
||||
__system_property_add; # arm64 x86_64 mips64
|
||||
__system_property_area__; # arm64 x86_64 mips64
|
||||
__system_property_area_init; # arm64 x86_64 mips64
|
||||
__system_property_area_serial; # arm64 x86_64 mips64
|
||||
__system_property_find; # arm64 x86_64 mips64
|
||||
__system_property_find_nth; # arm64 x86_64 mips64
|
||||
__system_property_foreach; # arm64 x86_64 mips64
|
||||
__system_property_get; # arm64 x86_64 mips64
|
||||
__system_property_read; # arm64 x86_64 mips64
|
||||
__system_property_serial; # arm64 x86_64 mips64
|
||||
__system_property_set; # arm64 x86_64 mips64
|
||||
__system_property_set_filename; # arm64 x86_64 mips64
|
||||
__system_property_update; # arm64 x86_64 mips64
|
||||
__system_property_wait_any; # arm64 x86_64 mips64
|
||||
free_malloc_leak_info;
|
||||
get_malloc_leak_info;
|
||||
gMallocLeakZygoteChild;
|
||||
} LIBC_N;
|
||||
|
@ -9,25 +9,18 @@ LIBC {
|
||||
__b64_ntop;
|
||||
__b64_pton;
|
||||
__brk; # arm x86 mips
|
||||
__cmpdf2; # arm
|
||||
__cmsg_nxthdr;
|
||||
__connect; # arm x86 mips
|
||||
__ctype_get_mb_cur_max;
|
||||
__cxa_atexit;
|
||||
__cxa_finalize;
|
||||
__cxa_thread_atexit_impl;
|
||||
__divdf3; # arm
|
||||
__divdi3; # arm x86 mips
|
||||
__divsf3; # arm
|
||||
__divsi3; # arm
|
||||
__dn_comp;
|
||||
__dn_count_labels;
|
||||
__dn_skipname;
|
||||
__epoll_pwait; # arm x86 mips
|
||||
__eqdf2; # arm
|
||||
__errno;
|
||||
__exit; # arm x86 mips
|
||||
__extendsfdf2; # arm
|
||||
__fadvise64; # x86 mips
|
||||
__fbufsize;
|
||||
__fcntl64; # arm x86 mips
|
||||
@ -35,18 +28,7 @@ LIBC {
|
||||
__FD_ISSET_chk;
|
||||
__FD_SET_chk;
|
||||
__fgets_chk;
|
||||
__fixdfsi; # arm
|
||||
__fixsfsi; # arm
|
||||
__fixunssfsi; # arm
|
||||
__flbf;
|
||||
__floatdidf; # arm
|
||||
__floatdisf; # arm
|
||||
__floatsidf; # arm
|
||||
__floatsisf; # arm
|
||||
__floatundidf; # arm
|
||||
__floatundisf; # arm
|
||||
__floatunsidf; # arm
|
||||
__floatunsisf; # arm
|
||||
__fp_nquery;
|
||||
__fp_query;
|
||||
__fpclassify;
|
||||
@ -58,23 +40,14 @@ LIBC {
|
||||
__freadable;
|
||||
__fsetlocking;
|
||||
__fstatfs64; # arm x86 mips
|
||||
__futex_wait; # arm x86 mips
|
||||
__futex_wake; # arm x86 mips
|
||||
__fwritable;
|
||||
__gedf2; # arm
|
||||
__get_h_errno;
|
||||
__get_thread; # arm x86 mips
|
||||
__get_tls; # arm x86 mips
|
||||
__getcpu; # arm x86 mips
|
||||
__getcwd; # arm x86 mips
|
||||
__getdents64; # arm x86 mips
|
||||
__getpid; # arm x86 mips
|
||||
__getpriority; # arm x86 mips
|
||||
__gnu_basename;
|
||||
__gnu_ldivmod_helper; # arm
|
||||
__gnu_strerror_r;
|
||||
__gnu_uldivmod_helper; # arm
|
||||
__gtdf2; # arm
|
||||
__hostalias;
|
||||
__ioctl; # arm x86 mips
|
||||
__isfinite;
|
||||
@ -90,15 +63,12 @@ LIBC {
|
||||
__isnormalf;
|
||||
__isnormall;
|
||||
__isthreaded;
|
||||
__ledf2; # arm
|
||||
__libc_current_sigrtmax;
|
||||
__libc_current_sigrtmin;
|
||||
__libc_init;
|
||||
__llseek; # arm x86 mips
|
||||
__loc_aton;
|
||||
__loc_ntoa;
|
||||
__lshrdi3; # arm
|
||||
__ltdf2; # arm
|
||||
__memchr_chk;
|
||||
__memcpy_chk;
|
||||
__memmove_chk;
|
||||
@ -106,10 +76,6 @@ LIBC {
|
||||
__memset_chk;
|
||||
__mmap2; # arm x86 mips
|
||||
__moddi3; # x86 mips
|
||||
__muldf3; # arm
|
||||
__muldi3; # arm
|
||||
__mulsf3; # arm
|
||||
__nedf2; # arm
|
||||
__ns_format_ttl; # arm x86 mips
|
||||
__ns_get16; # arm x86 mips
|
||||
__ns_get32; # arm x86 mips
|
||||
@ -132,7 +98,6 @@ LIBC {
|
||||
__ns_skiprr; # arm x86 mips
|
||||
__ns_sprintrr; # arm x86 mips
|
||||
__ns_sprintrrf; # arm x86 mips
|
||||
__open; # arm x86 mips
|
||||
__open_2;
|
||||
__openat; # arm x86 mips
|
||||
__openat_2;
|
||||
@ -149,11 +114,7 @@ LIBC {
|
||||
__p_time;
|
||||
__p_type;
|
||||
__p_type_syms;
|
||||
__page_shift; # arm x86 mips
|
||||
__page_size; # arm x86 mips
|
||||
__poll_chk;
|
||||
__popcount_tab; # arm
|
||||
__popcountsi2; # arm x86 mips
|
||||
__ppoll; # arm x86 mips
|
||||
__ppoll_chk;
|
||||
__pread64_chk;
|
||||
@ -162,7 +123,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;
|
||||
@ -192,7 +153,6 @@ LIBC {
|
||||
__res_send;
|
||||
__res_send_setqhook;
|
||||
__res_send_setrhook;
|
||||
__restore_core_regs; # arm
|
||||
__rt_sigaction; # arm x86 mips
|
||||
__rt_sigpending; # arm x86 mips
|
||||
__rt_sigprocmask; # arm x86 mips
|
||||
@ -202,28 +162,15 @@ LIBC {
|
||||
__sched_cpucount;
|
||||
__sched_cpufree;
|
||||
__sched_getaffinity; # arm x86 mips
|
||||
__sclose; # arm x86 mips
|
||||
__sdidinit; # arm x86 mips
|
||||
__set_errno; # arm x86 mips
|
||||
__set_thread_area; # x86
|
||||
__set_tid_address; # arm x86 mips
|
||||
__set_tls; # arm mips
|
||||
__sF;
|
||||
__sflags; # arm x86 mips
|
||||
__sflush; # arm x86 mips
|
||||
__sfp; # arm x86 mips
|
||||
__sglue; # arm x86 mips
|
||||
__sigaction; # arm x86 mips
|
||||
__signalfd4; # arm x86 mips
|
||||
__sinit; # arm x86 mips
|
||||
__smakebuf; # arm x86 mips
|
||||
__snprintf_chk;
|
||||
__socket; # arm x86 mips
|
||||
__sprintf_chk;
|
||||
__sread; # arm x86 mips
|
||||
__srefill; # arm x86 mips
|
||||
__srget; # arm x86 mips
|
||||
__sseek; # arm x86 mips
|
||||
__stack_chk_fail;
|
||||
__stack_chk_guard;
|
||||
__statfs64; # arm x86 mips
|
||||
@ -240,51 +187,39 @@ LIBC {
|
||||
__strncpy_chk;
|
||||
__strncpy_chk2;
|
||||
__strrchr_chk;
|
||||
__subdf3; # arm
|
||||
__subsf3; # arm
|
||||
__swbuf; # arm x86 mips
|
||||
__swrite; # arm x86 mips
|
||||
__swsetup; # arm x86 mips
|
||||
__sym_ntop;
|
||||
__sym_ntos;
|
||||
__sym_ston;
|
||||
__system_properties_init;
|
||||
__system_property_add;
|
||||
__system_property_area__;
|
||||
__system_property_area_init;
|
||||
__system_property_area_serial;
|
||||
__system_property_find;
|
||||
__system_property_find_nth;
|
||||
__system_property_foreach;
|
||||
__system_property_get;
|
||||
__system_property_read;
|
||||
__system_property_serial;
|
||||
__system_property_set;
|
||||
__system_property_set_filename;
|
||||
__system_property_update;
|
||||
__system_property_wait_any;
|
||||
__system_properties_init; # arm x86 mips
|
||||
__system_property_add; # arm x86 mips
|
||||
__system_property_area__; # arm x86 mips
|
||||
__system_property_area_init; # arm x86 mips
|
||||
__system_property_area_serial; # arm x86 mips
|
||||
__system_property_find; # arm x86 mips
|
||||
__system_property_find_nth; # arm x86 mips
|
||||
__system_property_foreach; # arm x86 mips
|
||||
__system_property_get; # arm x86 mips
|
||||
__system_property_read; # arm x86 mips
|
||||
__system_property_serial; # arm x86 mips
|
||||
__system_property_set; # arm x86 mips
|
||||
__system_property_set_filename; # arm x86 mips
|
||||
__system_property_update; # arm x86 mips
|
||||
__system_property_wait_any; # arm x86 mips
|
||||
__timer_create; # arm x86 mips
|
||||
__timer_delete; # arm x86 mips
|
||||
__timer_getoverrun; # arm x86 mips
|
||||
__timer_gettime; # arm x86 mips
|
||||
__timer_settime; # arm x86 mips
|
||||
__truncdfsf2; # arm
|
||||
__udivdi3; # arm x86 mips
|
||||
__udivsi3; # arm
|
||||
__udivdi3; # x86
|
||||
__umask_chk;
|
||||
__umoddi3; # x86 mips
|
||||
__unorddf2; # arm
|
||||
__unordsf2; # arm
|
||||
__vsnprintf_chk;
|
||||
__vsprintf_chk;
|
||||
__wait4; # arm x86 mips
|
||||
__waitid; # arm x86 mips
|
||||
_ctype_;
|
||||
_Exit;
|
||||
_exit;
|
||||
_flush_cache; # mips
|
||||
_flushlbf;
|
||||
_fwalk; # arm x86 mips
|
||||
_getlong;
|
||||
_getshort;
|
||||
_longjmp;
|
||||
@ -311,9 +246,7 @@ LIBC {
|
||||
android_gethostbynamefornet;
|
||||
android_set_abort_message;
|
||||
arc4random;
|
||||
arc4random_addrandom; # arm x86 mips
|
||||
arc4random_buf;
|
||||
arc4random_stir; # arm x86 mips
|
||||
arc4random_uniform;
|
||||
asctime;
|
||||
asctime64; # arm x86 mips
|
||||
@ -327,14 +260,11 @@ LIBC {
|
||||
atoll;
|
||||
basename;
|
||||
basename_r; # arm x86 mips
|
||||
bcopy; # arm x86 mips
|
||||
bind;
|
||||
bindresvport;
|
||||
brk;
|
||||
bsd_signal; # arm x86 mips
|
||||
bsearch;
|
||||
btowc;
|
||||
bzero; # arm x86 mips
|
||||
c16rtomb;
|
||||
c32rtomb;
|
||||
cacheflush; # arm mips
|
||||
@ -387,7 +317,6 @@ LIBC {
|
||||
dup3;
|
||||
duplocale;
|
||||
endmntent;
|
||||
endpwent;
|
||||
endservent;
|
||||
endutent;
|
||||
environ;
|
||||
@ -434,7 +363,6 @@ LIBC {
|
||||
fdatasync;
|
||||
fdopen;
|
||||
fdopendir;
|
||||
fdprintf; # arm x86 mips
|
||||
feof;
|
||||
feof_unlocked;
|
||||
ferror;
|
||||
@ -466,7 +394,6 @@ LIBC {
|
||||
fputws;
|
||||
fread;
|
||||
free;
|
||||
free_malloc_leak_info;
|
||||
freeaddrinfo;
|
||||
freelocale;
|
||||
fremovexattr;
|
||||
@ -487,7 +414,6 @@ LIBC {
|
||||
fsync;
|
||||
ftell;
|
||||
ftello;
|
||||
ftime; # arm x86 mips
|
||||
ftok;
|
||||
ftruncate;
|
||||
ftruncate64;
|
||||
@ -508,7 +434,6 @@ LIBC {
|
||||
fwscanf;
|
||||
gai_strerror;
|
||||
get_avphys_pages;
|
||||
get_malloc_leak_info;
|
||||
get_nprocs;
|
||||
get_nprocs_conf;
|
||||
get_phys_pages;
|
||||
@ -520,8 +445,6 @@ LIBC {
|
||||
getchar_unlocked;
|
||||
getcwd;
|
||||
getdelim;
|
||||
getdents; # arm x86 mips
|
||||
getdtablesize; # arm x86 mips
|
||||
getegid;
|
||||
getenv;
|
||||
geteuid;
|
||||
@ -596,7 +519,6 @@ LIBC {
|
||||
if_nametoindex;
|
||||
imaxabs;
|
||||
imaxdiv;
|
||||
index; # arm x86 mips
|
||||
inet_addr;
|
||||
inet_aton;
|
||||
inet_lnaof;
|
||||
@ -649,7 +571,6 @@ LIBC {
|
||||
isprint_l;
|
||||
ispunct;
|
||||
ispunct_l;
|
||||
issetugid; # arm x86 mips
|
||||
isspace;
|
||||
isspace_l;
|
||||
isupper;
|
||||
@ -739,7 +660,6 @@ LIBC {
|
||||
mempcpy;
|
||||
memrchr;
|
||||
memset;
|
||||
memswap; # arm x86 mips
|
||||
mincore;
|
||||
mkdir;
|
||||
mkdirat;
|
||||
@ -759,7 +679,6 @@ LIBC {
|
||||
mktemp;
|
||||
mktime;
|
||||
mktime64; # arm x86 mips
|
||||
mktime_tz;
|
||||
mlock;
|
||||
mlockall;
|
||||
mmap;
|
||||
@ -853,7 +772,6 @@ LIBC {
|
||||
pthread_attr_getschedpolicy;
|
||||
pthread_attr_getscope;
|
||||
pthread_attr_getstack;
|
||||
pthread_attr_getstackaddr; # arm x86 mips
|
||||
pthread_attr_getstacksize;
|
||||
pthread_attr_init;
|
||||
pthread_attr_setdetachstate;
|
||||
@ -862,7 +780,6 @@ LIBC {
|
||||
pthread_attr_setschedpolicy;
|
||||
pthread_attr_setscope;
|
||||
pthread_attr_setstack;
|
||||
pthread_attr_setstackaddr; # arm x86 mips
|
||||
pthread_attr_setstacksize;
|
||||
pthread_cond_broadcast;
|
||||
pthread_cond_destroy;
|
||||
@ -978,7 +895,6 @@ LIBC {
|
||||
res_mkquery;
|
||||
res_query;
|
||||
res_search;
|
||||
restore_core_regs; # arm
|
||||
rewind;
|
||||
rewinddir;
|
||||
rmdir;
|
||||
@ -1121,8 +1037,6 @@ LIBC {
|
||||
strncpy;
|
||||
strndup;
|
||||
strnlen;
|
||||
strntoimax; # arm x86 mips
|
||||
strntoumax; # arm x86 mips
|
||||
strpbrk;
|
||||
strptime;
|
||||
strrchr;
|
||||
@ -1141,7 +1055,6 @@ LIBC {
|
||||
strtoll;
|
||||
strtoll_l;
|
||||
strtoq;
|
||||
strtotimeval; # arm x86 mips
|
||||
strtoul;
|
||||
strtoull;
|
||||
strtoull_l;
|
||||
@ -1163,7 +1076,6 @@ LIBC {
|
||||
sysinfo;
|
||||
syslog;
|
||||
system;
|
||||
sysv_signal; # arm x86 mips
|
||||
tcdrain;
|
||||
tcflow;
|
||||
tcflush;
|
||||
@ -1195,7 +1107,6 @@ LIBC {
|
||||
timerfd_settime;
|
||||
times;
|
||||
timezone;
|
||||
tkill; # arm x86 mips
|
||||
tmpfile;
|
||||
tmpnam;
|
||||
toascii;
|
||||
@ -1237,7 +1148,6 @@ LIBC {
|
||||
vdprintf;
|
||||
verr;
|
||||
verrx;
|
||||
vfdprintf; # arm x86 mips
|
||||
vfork;
|
||||
vfprintf;
|
||||
vfscanf;
|
||||
@ -1257,7 +1167,6 @@ LIBC {
|
||||
vwprintf;
|
||||
vwscanf;
|
||||
wait;
|
||||
wait3; # arm x86 mips
|
||||
wait4;
|
||||
waitid;
|
||||
waitpid;
|
||||
@ -1306,7 +1215,6 @@ LIBC {
|
||||
wcstoull;
|
||||
wcstoull_l;
|
||||
wcstoumax;
|
||||
wcswcs; # arm x86 mips
|
||||
wcswidth;
|
||||
wcsxfrm;
|
||||
wcsxfrm_l;
|
||||
@ -1331,17 +1239,46 @@ LIBC {
|
||||
|
||||
LIBC_N {
|
||||
global:
|
||||
__aeabi_atexit; # arm
|
||||
__aeabi_memclr; # arm
|
||||
__aeabi_memclr4; # arm
|
||||
__aeabi_memclr8; # arm
|
||||
__aeabi_memcpy; # arm
|
||||
__aeabi_memcpy4; # arm
|
||||
__aeabi_memcpy8; # arm
|
||||
__aeabi_memmove; # arm
|
||||
__aeabi_memmove4; # arm
|
||||
__aeabi_memmove8; # arm
|
||||
__aeabi_memset; # arm
|
||||
__aeabi_memset4; # arm
|
||||
__aeabi_memset8; # arm
|
||||
__fread_chk;
|
||||
__fwrite_chk;
|
||||
__getcwd_chk;
|
||||
__gnu_Unwind_Find_exidx; # arm
|
||||
__pwrite_chk;
|
||||
__pwrite64_chk;
|
||||
__write_chk;
|
||||
fileno_unlocked;
|
||||
freeifaddrs;
|
||||
getgrgid_r;
|
||||
getgrnam_r;
|
||||
getifaddrs;
|
||||
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,8 +1362,33 @@ LIBC_PRIVATE {
|
||||
__ashrdi3; # arm
|
||||
__bionic_brk; # arm x86 mips
|
||||
__bionic_libgcc_compat_symbols; # arm x86
|
||||
__bionic_libgcc_unwind_symbols; # arm
|
||||
__cmpdf2; # arm
|
||||
__divdf3; # arm
|
||||
__divdi3; # arm x86 mips
|
||||
__divsf3; # arm
|
||||
__divsi3; # arm
|
||||
__dso_handle; # arm
|
||||
__eqdf2; # arm
|
||||
__extendsfdf2; # arm
|
||||
__fixdfsi; # arm
|
||||
__fixsfsi; # arm
|
||||
__fixunssfsi; # arm
|
||||
__floatdidf; # arm
|
||||
__floatdisf; # arm
|
||||
__floatsidf; # arm
|
||||
__floatsisf; # arm
|
||||
__floatundidf; # arm
|
||||
__floatundisf; # arm
|
||||
__floatunsidf; # arm
|
||||
__floatunsisf; # arm
|
||||
__futex_wait; # arm x86 mips nobrillo
|
||||
__futex_wake; # arm x86 mips nobrillo
|
||||
__gedf2; # arm
|
||||
__get_thread; # arm x86 mips nobrillo
|
||||
__get_tls; # arm x86 mips nobrillo
|
||||
__getdents64; # arm x86 mips
|
||||
__gnu_ldivmod_helper; # arm
|
||||
__gnu_uldivmod_helper; # arm
|
||||
__gnu_Unwind_Backtrace; # arm
|
||||
__gnu_unwind_execute; # arm
|
||||
__gnu_Unwind_Find_exidx; # arm
|
||||
@ -1445,6 +1407,62 @@ LIBC_PRIVATE {
|
||||
__gnu_Unwind_Save_VFP_D_16_to_31; # arm
|
||||
__gnu_Unwind_Save_WMMXC; # arm
|
||||
__gnu_Unwind_Save_WMMXD; # arm
|
||||
__gtdf2; # arm
|
||||
__ledf2; # arm
|
||||
__lshrdi3; # arm
|
||||
__ltdf2; # arm
|
||||
__muldf3; # arm
|
||||
__muldi3; # arm
|
||||
__mulsf3; # arm
|
||||
__nedf2; # arm
|
||||
__open; # arm x86 mips nobrillo
|
||||
__page_shift; # arm x86 mips nobrillo
|
||||
__page_size; # arm x86 mips nobrillo
|
||||
__popcount_tab; # arm
|
||||
__popcountsi2; # arm x86 mips
|
||||
__pthread_gettid; # arm x86 mips nobrillo
|
||||
__restore_core_regs; # arm
|
||||
__sclose; # arm x86 mips
|
||||
__sdidinit; # arm x86 mips nobrillo
|
||||
__set_errno; # arm x86 mips nobrillo
|
||||
__sflags; # arm x86 mips
|
||||
__sflush; # arm x86 mips
|
||||
__sfp; # arm x86 mips
|
||||
__sglue; # arm x86 mips
|
||||
__sinit; # arm x86 mips nobrillo
|
||||
__smakebuf; # arm x86 mips
|
||||
__sread; # arm x86 mips
|
||||
__srefill; # arm x86 mips
|
||||
__srget; # arm x86 mips
|
||||
__sseek; # arm x86 mips
|
||||
__subdf3; # arm
|
||||
__subsf3; # arm
|
||||
__swbuf; # arm x86 mips
|
||||
__swrite; # arm x86 mips
|
||||
__swsetup; # arm x86 mips
|
||||
__system_properties_init; # arm64 x86_64 mips64
|
||||
__system_property_add; # arm64 x86_64 mips64
|
||||
__system_property_area__; # arm64 x86_64 mips64
|
||||
__system_property_area_init; # arm64 x86_64 mips64
|
||||
__system_property_area_serial; # arm64 x86_64 mips64
|
||||
__system_property_find; # arm64 x86_64 mips64
|
||||
__system_property_find_nth; # arm64 x86_64 mips64
|
||||
__system_property_foreach; # arm64 x86_64 mips64
|
||||
__system_property_get; # arm64 x86_64 mips64
|
||||
__system_property_read; # arm64 x86_64 mips64
|
||||
__system_property_serial; # arm64 x86_64 mips64
|
||||
__system_property_set; # arm64 x86_64 mips64
|
||||
__system_property_set_filename; # arm64 x86_64 mips64
|
||||
__system_property_update; # arm64 x86_64 mips64
|
||||
__system_property_wait_any; # arm64 x86_64 mips64
|
||||
__truncdfsf2; # arm
|
||||
__udivdi3; # arm mips
|
||||
__udivsi3; # arm
|
||||
__umoddi3; # x86 mips
|
||||
__unorddf2; # arm
|
||||
__unordsf2; # arm
|
||||
__wait4; # arm x86 mips nobrillo
|
||||
_fwalk; # arm x86 mips
|
||||
_Unwind_Backtrace; # arm
|
||||
_Unwind_Complete; # arm
|
||||
_Unwind_DeleteException; # arm
|
||||
@ -1460,14 +1478,40 @@ LIBC_PRIVATE {
|
||||
_Unwind_VRS_Get; # arm
|
||||
_Unwind_VRS_Pop; # arm
|
||||
_Unwind_VRS_Set; # arm
|
||||
arc4random_addrandom; # arm x86 mips nobrillo
|
||||
arc4random_stir; # arm x86 mips nobrillo
|
||||
atexit; # arm
|
||||
dlmalloc; # arm x86 mips
|
||||
dlmalloc_inspect_all;
|
||||
dlmalloc_trim;
|
||||
dlmalloc_usable_size; # arm x86 mips
|
||||
bcopy; # arm x86 mips nobrillo
|
||||
bzero; # arm x86 mips nobrillo
|
||||
bsd_signal; # arm x86 mips nobrillo
|
||||
dlmalloc; # arm x86 mips nobrillo
|
||||
dlmalloc_inspect_all; # arm x86 mips nobrillo
|
||||
dlmalloc_trim; # arm x86 mips nobrillo
|
||||
dlmalloc_usable_size; # arm x86 mips nobrillo
|
||||
endpwent; # arm x86 mips nobrillo
|
||||
fdprintf; # arm x86 mips nobrillo
|
||||
free_malloc_leak_info;
|
||||
ftime; # arm x86 mips nobrillo
|
||||
get_malloc_leak_info;
|
||||
getdents; # arm x86 mips nobrillo
|
||||
getdtablesize; # arm x86 mips nobrillo
|
||||
gMallocLeakZygoteChild;
|
||||
index; # arm x86 mips nobrillo
|
||||
issetugid; # arm x86 mips nobrillo
|
||||
memswap; # arm x86 mips nobrillo
|
||||
pthread_attr_getstackaddr; # arm x86 mips nobrillo
|
||||
pthread_attr_setstackaddr; # arm x86 mips nobrillo
|
||||
restore_core_regs; # arm
|
||||
SHA1Final; # arm x86 mips
|
||||
SHA1Init; # arm x86 mips
|
||||
SHA1Transform; # arm x86 mips
|
||||
SHA1Update; # arm x86 mips
|
||||
strntoimax; # arm x86 mips nobrillo
|
||||
strntoumax; # arm x86 mips nobrillo
|
||||
strtotimeval; # arm x86 mips nobrillo
|
||||
sysv_signal; # arm x86 mips nobrillo
|
||||
tkill; # arm x86 mips nobrillo
|
||||
vfdprintf; # arm x86 mips nobrillo
|
||||
wait3; # arm x86 mips nobrillo
|
||||
wcswcs; # arm x86 mips nobrillo
|
||||
} LIBC_N;
|
||||
|
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
@ -12,7 +12,6 @@ LIBC {
|
||||
__cxa_atexit;
|
||||
__cxa_finalize;
|
||||
__cxa_thread_atexit_impl;
|
||||
__divdi3; # arm x86 mips
|
||||
__dn_comp;
|
||||
__dn_count_labels;
|
||||
__dn_skipname;
|
||||
@ -38,15 +37,10 @@ LIBC {
|
||||
__freadable;
|
||||
__fsetlocking;
|
||||
__fstatfs64; # arm x86 mips
|
||||
__futex_wait; # arm x86 mips
|
||||
__futex_wake; # arm x86 mips
|
||||
__fwritable;
|
||||
__get_h_errno;
|
||||
__get_thread; # arm x86 mips
|
||||
__get_tls; # arm x86 mips
|
||||
__getcpu; # arm x86 mips
|
||||
__getcwd; # arm x86 mips
|
||||
__getdents64; # arm x86 mips
|
||||
__getpid; # arm x86 mips
|
||||
__getpriority; # arm x86 mips
|
||||
__gnu_basename;
|
||||
@ -101,7 +95,6 @@ LIBC {
|
||||
__ns_skiprr; # arm x86 mips
|
||||
__ns_sprintrr; # arm x86 mips
|
||||
__ns_sprintrrf; # arm x86 mips
|
||||
__open; # arm x86 mips
|
||||
__open_2;
|
||||
__openat; # arm x86 mips
|
||||
__openat_2;
|
||||
@ -118,10 +111,7 @@ LIBC {
|
||||
__p_time;
|
||||
__p_type;
|
||||
__p_type_syms;
|
||||
__page_shift; # arm x86 mips
|
||||
__page_size; # arm x86 mips
|
||||
__poll_chk;
|
||||
__popcountsi2; # arm x86 mips
|
||||
__ppoll; # arm x86 mips
|
||||
__ppoll_chk;
|
||||
__pread64_chk;
|
||||
@ -130,7 +120,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;
|
||||
@ -169,27 +159,14 @@ LIBC {
|
||||
__sched_cpucount;
|
||||
__sched_cpufree;
|
||||
__sched_getaffinity; # arm x86 mips
|
||||
__sclose; # arm x86 mips
|
||||
__sdidinit; # arm x86 mips
|
||||
__set_errno; # arm x86 mips
|
||||
__set_tid_address; # arm x86 mips
|
||||
__set_tls; # arm mips
|
||||
__sF;
|
||||
__sflags; # arm x86 mips
|
||||
__sflush; # arm x86 mips
|
||||
__sfp; # arm x86 mips
|
||||
__sglue; # arm x86 mips
|
||||
__sigaction; # arm x86 mips
|
||||
__signalfd4; # arm x86 mips
|
||||
__sinit; # arm x86 mips
|
||||
__smakebuf; # arm x86 mips
|
||||
__snprintf_chk;
|
||||
__socket; # arm x86 mips
|
||||
__sprintf_chk;
|
||||
__sread; # arm x86 mips
|
||||
__srefill; # arm x86 mips
|
||||
__srget; # arm x86 mips
|
||||
__sseek; # arm x86 mips
|
||||
__stack_chk_fail;
|
||||
__stack_chk_guard;
|
||||
__statfs64; # arm x86 mips
|
||||
@ -206,45 +183,38 @@ LIBC {
|
||||
__strncpy_chk;
|
||||
__strncpy_chk2;
|
||||
__strrchr_chk;
|
||||
__swbuf; # arm x86 mips
|
||||
__swrite; # arm x86 mips
|
||||
__swsetup; # arm x86 mips
|
||||
__sym_ntop;
|
||||
__sym_ntos;
|
||||
__sym_ston;
|
||||
__system_properties_init;
|
||||
__system_property_add;
|
||||
__system_property_area__;
|
||||
__system_property_area_init;
|
||||
__system_property_area_serial;
|
||||
__system_property_find;
|
||||
__system_property_find_nth;
|
||||
__system_property_foreach;
|
||||
__system_property_get;
|
||||
__system_property_read;
|
||||
__system_property_serial;
|
||||
__system_property_set;
|
||||
__system_property_set_filename;
|
||||
__system_property_update;
|
||||
__system_property_wait_any;
|
||||
__system_properties_init; # arm x86 mips
|
||||
__system_property_add; # arm x86 mips
|
||||
__system_property_area__; # arm x86 mips
|
||||
__system_property_area_init; # arm x86 mips
|
||||
__system_property_area_serial; # arm x86 mips
|
||||
__system_property_find; # arm x86 mips
|
||||
__system_property_find_nth; # arm x86 mips
|
||||
__system_property_foreach; # arm x86 mips
|
||||
__system_property_get; # arm x86 mips
|
||||
__system_property_read; # arm x86 mips
|
||||
__system_property_serial; # arm x86 mips
|
||||
__system_property_set; # arm x86 mips
|
||||
__system_property_set_filename; # arm x86 mips
|
||||
__system_property_update; # arm x86 mips
|
||||
__system_property_wait_any; # arm x86 mips
|
||||
__timer_create; # arm x86 mips
|
||||
__timer_delete; # arm x86 mips
|
||||
__timer_getoverrun; # arm x86 mips
|
||||
__timer_gettime; # arm x86 mips
|
||||
__timer_settime; # arm x86 mips
|
||||
__udivdi3; # arm x86 mips
|
||||
__umask_chk;
|
||||
__umoddi3; # x86 mips
|
||||
__vsnprintf_chk;
|
||||
__vsprintf_chk;
|
||||
__wait4; # arm x86 mips
|
||||
__waitid; # arm x86 mips
|
||||
_ctype_;
|
||||
_Exit;
|
||||
_exit;
|
||||
_flush_cache; # mips
|
||||
_flushlbf;
|
||||
_fwalk; # arm x86 mips
|
||||
_getlong;
|
||||
_getshort;
|
||||
_longjmp;
|
||||
@ -271,9 +241,7 @@ LIBC {
|
||||
android_gethostbynamefornet;
|
||||
android_set_abort_message;
|
||||
arc4random;
|
||||
arc4random_addrandom; # arm x86 mips
|
||||
arc4random_buf;
|
||||
arc4random_stir; # arm x86 mips
|
||||
arc4random_uniform;
|
||||
asctime;
|
||||
asctime64; # arm x86 mips
|
||||
@ -287,14 +255,11 @@ LIBC {
|
||||
atoll;
|
||||
basename;
|
||||
basename_r; # arm x86 mips
|
||||
bcopy; # arm x86 mips
|
||||
bind;
|
||||
bindresvport;
|
||||
brk;
|
||||
bsd_signal; # arm x86 mips
|
||||
bsearch;
|
||||
btowc;
|
||||
bzero; # arm x86 mips
|
||||
c16rtomb;
|
||||
c32rtomb;
|
||||
cacheflush; # arm mips
|
||||
@ -347,7 +312,6 @@ LIBC {
|
||||
dup3;
|
||||
duplocale;
|
||||
endmntent;
|
||||
endpwent;
|
||||
endservent;
|
||||
endutent;
|
||||
environ;
|
||||
@ -394,7 +358,6 @@ LIBC {
|
||||
fdatasync;
|
||||
fdopen;
|
||||
fdopendir;
|
||||
fdprintf; # arm x86 mips
|
||||
feof;
|
||||
feof_unlocked;
|
||||
ferror;
|
||||
@ -426,7 +389,6 @@ LIBC {
|
||||
fputws;
|
||||
fread;
|
||||
free;
|
||||
free_malloc_leak_info;
|
||||
freeaddrinfo;
|
||||
freelocale;
|
||||
fremovexattr;
|
||||
@ -447,7 +409,6 @@ LIBC {
|
||||
fsync;
|
||||
ftell;
|
||||
ftello;
|
||||
ftime; # arm x86 mips
|
||||
ftok;
|
||||
ftruncate;
|
||||
ftruncate64;
|
||||
@ -468,7 +429,6 @@ LIBC {
|
||||
fwscanf;
|
||||
gai_strerror;
|
||||
get_avphys_pages;
|
||||
get_malloc_leak_info;
|
||||
get_nprocs;
|
||||
get_nprocs_conf;
|
||||
get_phys_pages;
|
||||
@ -480,8 +440,6 @@ LIBC {
|
||||
getchar_unlocked;
|
||||
getcwd;
|
||||
getdelim;
|
||||
getdents; # arm x86 mips
|
||||
getdtablesize; # arm x86 mips
|
||||
getegid;
|
||||
getenv;
|
||||
geteuid;
|
||||
@ -556,7 +514,6 @@ LIBC {
|
||||
if_nametoindex;
|
||||
imaxabs;
|
||||
imaxdiv;
|
||||
index; # arm x86 mips
|
||||
inet_addr;
|
||||
inet_aton;
|
||||
inet_lnaof;
|
||||
@ -609,7 +566,6 @@ LIBC {
|
||||
isprint_l;
|
||||
ispunct;
|
||||
ispunct_l;
|
||||
issetugid; # arm x86 mips
|
||||
isspace;
|
||||
isspace_l;
|
||||
isupper;
|
||||
@ -699,7 +655,6 @@ LIBC {
|
||||
mempcpy;
|
||||
memrchr;
|
||||
memset;
|
||||
memswap; # arm x86 mips
|
||||
mincore;
|
||||
mkdir;
|
||||
mkdirat;
|
||||
@ -719,7 +674,6 @@ LIBC {
|
||||
mktemp;
|
||||
mktime;
|
||||
mktime64; # arm x86 mips
|
||||
mktime_tz;
|
||||
mlock;
|
||||
mlockall;
|
||||
mmap;
|
||||
@ -790,7 +744,6 @@ LIBC {
|
||||
pthread_attr_getschedpolicy;
|
||||
pthread_attr_getscope;
|
||||
pthread_attr_getstack;
|
||||
pthread_attr_getstackaddr; # arm x86 mips
|
||||
pthread_attr_getstacksize;
|
||||
pthread_attr_init;
|
||||
pthread_attr_setdetachstate;
|
||||
@ -799,7 +752,6 @@ LIBC {
|
||||
pthread_attr_setschedpolicy;
|
||||
pthread_attr_setscope;
|
||||
pthread_attr_setstack;
|
||||
pthread_attr_setstackaddr; # arm x86 mips
|
||||
pthread_attr_setstacksize;
|
||||
pthread_cond_broadcast;
|
||||
pthread_cond_destroy;
|
||||
@ -1057,8 +1009,6 @@ LIBC {
|
||||
strncpy;
|
||||
strndup;
|
||||
strnlen;
|
||||
strntoimax; # arm x86 mips
|
||||
strntoumax; # arm x86 mips
|
||||
strpbrk;
|
||||
strptime;
|
||||
strrchr;
|
||||
@ -1077,7 +1027,6 @@ LIBC {
|
||||
strtoll;
|
||||
strtoll_l;
|
||||
strtoq;
|
||||
strtotimeval; # arm x86 mips
|
||||
strtoul;
|
||||
strtoull;
|
||||
strtoull_l;
|
||||
@ -1099,7 +1048,6 @@ LIBC {
|
||||
sysinfo;
|
||||
syslog;
|
||||
system;
|
||||
sysv_signal; # arm x86 mips
|
||||
tcdrain;
|
||||
tcflow;
|
||||
tcflush;
|
||||
@ -1131,7 +1079,6 @@ LIBC {
|
||||
timerfd_settime;
|
||||
times;
|
||||
timezone;
|
||||
tkill; # arm x86 mips
|
||||
tmpfile;
|
||||
tmpnam;
|
||||
toascii;
|
||||
@ -1173,7 +1120,6 @@ LIBC {
|
||||
vdprintf;
|
||||
verr;
|
||||
verrx;
|
||||
vfdprintf; # arm x86 mips
|
||||
vfork;
|
||||
vfprintf;
|
||||
vfscanf;
|
||||
@ -1193,7 +1139,6 @@ LIBC {
|
||||
vwprintf;
|
||||
vwscanf;
|
||||
wait;
|
||||
wait3; # arm x86 mips
|
||||
wait4;
|
||||
waitid;
|
||||
waitpid;
|
||||
@ -1242,7 +1187,6 @@ LIBC {
|
||||
wcstoull;
|
||||
wcstoull_l;
|
||||
wcstoumax;
|
||||
wcswcs; # arm x86 mips
|
||||
wcswidth;
|
||||
wcsxfrm;
|
||||
wcsxfrm_l;
|
||||
@ -1273,11 +1217,26 @@ LIBC_N {
|
||||
__pwrite_chk;
|
||||
__pwrite64_chk;
|
||||
__write_chk;
|
||||
fileno_unlocked;
|
||||
freeifaddrs;
|
||||
getgrgid_r;
|
||||
getgrnam_r;
|
||||
getifaddrs;
|
||||
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,13 +1248,69 @@ 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
|
||||
__divdi3; # arm x86 mips
|
||||
__futex_wait; # arm x86 mips nobrillo
|
||||
__futex_wake; # arm x86 mips nobrillo
|
||||
__get_thread; # arm x86 mips nobrillo
|
||||
__get_tls; # arm x86 mips nobrillo
|
||||
__getdents64; # arm x86 mips
|
||||
__open; # arm x86 mips nobrillo
|
||||
__page_shift; # arm x86 mips nobrillo
|
||||
__page_size; # arm x86 mips nobrillo
|
||||
__popcountsi2; # arm x86 mips
|
||||
__pthread_gettid; # arm x86 mips nobrillo
|
||||
__sclose; # arm x86 mips
|
||||
__sdidinit; # arm x86 mips nobrillo
|
||||
__set_errno; # arm x86 mips nobrillo
|
||||
__sflags; # arm x86 mips
|
||||
__sflush; # arm x86 mips
|
||||
__sfp; # arm x86 mips
|
||||
__sglue; # arm x86 mips
|
||||
__sinit; # arm x86 mips nobrillo
|
||||
__smakebuf; # arm x86 mips
|
||||
__sread; # arm x86 mips
|
||||
__srefill; # arm x86 mips
|
||||
__srget; # arm x86 mips
|
||||
__sseek; # arm x86 mips
|
||||
__swbuf; # arm x86 mips
|
||||
__swrite; # arm x86 mips
|
||||
__swsetup; # arm x86 mips
|
||||
__udivdi3; # arm mips
|
||||
__umoddi3; # x86 mips
|
||||
__wait4; # arm x86 mips nobrillo
|
||||
_fwalk; # arm x86 mips
|
||||
arc4random_addrandom; # arm x86 mips nobrillo
|
||||
arc4random_stir; # arm x86 mips nobrillo
|
||||
bcopy; # arm x86 mips nobrillo
|
||||
bzero; # arm x86 mips nobrillo
|
||||
bsd_signal; # arm x86 mips nobrillo
|
||||
dlmalloc; # arm x86 mips nobrillo
|
||||
dlmalloc_inspect_all; # arm x86 mips nobrillo
|
||||
dlmalloc_trim; # arm x86 mips nobrillo
|
||||
dlmalloc_usable_size; # arm x86 mips nobrillo
|
||||
endpwent; # arm x86 mips nobrillo
|
||||
fdprintf; # arm x86 mips nobrillo
|
||||
free_malloc_leak_info;
|
||||
ftime; # arm x86 mips nobrillo
|
||||
get_malloc_leak_info;
|
||||
getdents; # arm x86 mips nobrillo
|
||||
getdtablesize; # arm x86 mips nobrillo
|
||||
gMallocLeakZygoteChild;
|
||||
index; # arm x86 mips nobrillo
|
||||
issetugid; # arm x86 mips nobrillo
|
||||
memswap; # arm x86 mips nobrillo
|
||||
pthread_attr_getstackaddr; # arm x86 mips nobrillo
|
||||
pthread_attr_setstackaddr; # arm x86 mips nobrillo
|
||||
SHA1Final; # arm x86 mips
|
||||
SHA1Init; # arm x86 mips
|
||||
SHA1Transform; # arm x86 mips
|
||||
SHA1Update; # arm x86 mips
|
||||
strntoimax; # arm x86 mips nobrillo
|
||||
strntoumax; # arm x86 mips nobrillo
|
||||
strtotimeval; # arm x86 mips nobrillo
|
||||
sysv_signal; # arm x86 mips nobrillo
|
||||
tkill; # arm x86 mips nobrillo
|
||||
vfdprintf; # arm x86 mips nobrillo
|
||||
wait3; # arm x86 mips nobrillo
|
||||
wcswcs; # arm x86 mips nobrillo
|
||||
} LIBC_N;
|
||||
|
@ -131,21 +131,6 @@ LIBC {
|
||||
__sym_ntop;
|
||||
__sym_ntos;
|
||||
__sym_ston;
|
||||
__system_properties_init;
|
||||
__system_property_add;
|
||||
__system_property_area__;
|
||||
__system_property_area_init;
|
||||
__system_property_area_serial;
|
||||
__system_property_find;
|
||||
__system_property_find_nth;
|
||||
__system_property_foreach;
|
||||
__system_property_get;
|
||||
__system_property_read;
|
||||
__system_property_serial;
|
||||
__system_property_set;
|
||||
__system_property_set_filename;
|
||||
__system_property_update;
|
||||
__system_property_wait_any;
|
||||
__umask_chk;
|
||||
__vsnprintf_chk;
|
||||
__vsprintf_chk;
|
||||
@ -241,7 +226,6 @@ LIBC {
|
||||
dup3;
|
||||
duplocale;
|
||||
endmntent;
|
||||
endpwent;
|
||||
endservent;
|
||||
endutent;
|
||||
environ;
|
||||
@ -317,7 +301,6 @@ LIBC {
|
||||
fputws;
|
||||
fread;
|
||||
free;
|
||||
free_malloc_leak_info;
|
||||
freeaddrinfo;
|
||||
freelocale;
|
||||
fremovexattr;
|
||||
@ -358,7 +341,6 @@ LIBC {
|
||||
fwscanf;
|
||||
gai_strerror;
|
||||
get_avphys_pages;
|
||||
get_malloc_leak_info;
|
||||
get_nprocs;
|
||||
get_nprocs_conf;
|
||||
get_phys_pages;
|
||||
@ -599,7 +581,6 @@ LIBC {
|
||||
mkstemps64;
|
||||
mktemp;
|
||||
mktime;
|
||||
mktime_tz;
|
||||
mlock;
|
||||
mlockall;
|
||||
mmap;
|
||||
@ -1156,10 +1137,25 @@ LIBC_N {
|
||||
__pwrite_chk;
|
||||
__pwrite64_chk;
|
||||
__write_chk;
|
||||
fileno_unlocked;
|
||||
freeifaddrs;
|
||||
getgrgid_r;
|
||||
getgrnam_r;
|
||||
getifaddrs;
|
||||
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 +1165,22 @@ LIBC_N {
|
||||
|
||||
LIBC_PRIVATE {
|
||||
global:
|
||||
dlmalloc_inspect_all;
|
||||
dlmalloc_trim;
|
||||
__system_properties_init; # arm64 x86_64 mips64
|
||||
__system_property_add; # arm64 x86_64 mips64
|
||||
__system_property_area__; # arm64 x86_64 mips64
|
||||
__system_property_area_init; # arm64 x86_64 mips64
|
||||
__system_property_area_serial; # arm64 x86_64 mips64
|
||||
__system_property_find; # arm64 x86_64 mips64
|
||||
__system_property_find_nth; # arm64 x86_64 mips64
|
||||
__system_property_foreach; # arm64 x86_64 mips64
|
||||
__system_property_get; # arm64 x86_64 mips64
|
||||
__system_property_read; # arm64 x86_64 mips64
|
||||
__system_property_serial; # arm64 x86_64 mips64
|
||||
__system_property_set; # arm64 x86_64 mips64
|
||||
__system_property_set_filename; # arm64 x86_64 mips64
|
||||
__system_property_update; # arm64 x86_64 mips64
|
||||
__system_property_wait_any; # arm64 x86_64 mips64
|
||||
free_malloc_leak_info;
|
||||
get_malloc_leak_info;
|
||||
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
@ -12,7 +12,6 @@ LIBC {
|
||||
__cxa_atexit;
|
||||
__cxa_finalize;
|
||||
__cxa_thread_atexit_impl;
|
||||
__divdi3; # arm x86 mips
|
||||
__dn_comp;
|
||||
__dn_count_labels;
|
||||
__dn_skipname;
|
||||
@ -38,15 +37,10 @@ LIBC {
|
||||
__freadable;
|
||||
__fsetlocking;
|
||||
__fstatfs64; # arm x86 mips
|
||||
__futex_wait; # arm x86 mips
|
||||
__futex_wake; # arm x86 mips
|
||||
__fwritable;
|
||||
__get_h_errno;
|
||||
__get_thread; # arm x86 mips
|
||||
__get_tls; # arm x86 mips
|
||||
__getcpu; # arm x86 mips
|
||||
__getcwd; # arm x86 mips
|
||||
__getdents64; # arm x86 mips
|
||||
__getpid; # arm x86 mips
|
||||
__getpriority; # arm x86 mips
|
||||
__gnu_basename;
|
||||
@ -101,7 +95,6 @@ LIBC {
|
||||
__ns_skiprr; # arm x86 mips
|
||||
__ns_sprintrr; # arm x86 mips
|
||||
__ns_sprintrrf; # arm x86 mips
|
||||
__open; # arm x86 mips
|
||||
__open_2;
|
||||
__openat; # arm x86 mips
|
||||
__openat_2;
|
||||
@ -118,10 +111,7 @@ LIBC {
|
||||
__p_time;
|
||||
__p_type;
|
||||
__p_type_syms;
|
||||
__page_shift; # arm x86 mips
|
||||
__page_size; # arm x86 mips
|
||||
__poll_chk;
|
||||
__popcountsi2; # arm x86 mips
|
||||
__ppoll; # arm x86 mips
|
||||
__ppoll_chk;
|
||||
__pread64_chk;
|
||||
@ -130,7 +120,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;
|
||||
@ -169,27 +159,14 @@ LIBC {
|
||||
__sched_cpucount;
|
||||
__sched_cpufree;
|
||||
__sched_getaffinity; # arm x86 mips
|
||||
__sclose; # arm x86 mips
|
||||
__sdidinit; # arm x86 mips
|
||||
__set_errno; # arm x86 mips
|
||||
__set_thread_area; # x86
|
||||
__set_tid_address; # arm x86 mips
|
||||
__sF;
|
||||
__sflags; # arm x86 mips
|
||||
__sflush; # arm x86 mips
|
||||
__sfp; # arm x86 mips
|
||||
__sglue; # arm x86 mips
|
||||
__sigaction; # arm x86 mips
|
||||
__signalfd4; # arm x86 mips
|
||||
__sinit; # arm x86 mips
|
||||
__smakebuf; # arm x86 mips
|
||||
__snprintf_chk;
|
||||
__socket; # arm x86 mips
|
||||
__sprintf_chk;
|
||||
__sread; # arm x86 mips
|
||||
__srefill; # arm x86 mips
|
||||
__srget; # arm x86 mips
|
||||
__sseek; # arm x86 mips
|
||||
__stack_chk_fail;
|
||||
__stack_chk_guard;
|
||||
__statfs64; # arm x86 mips
|
||||
@ -206,44 +183,38 @@ LIBC {
|
||||
__strncpy_chk;
|
||||
__strncpy_chk2;
|
||||
__strrchr_chk;
|
||||
__swbuf; # arm x86 mips
|
||||
__swrite; # arm x86 mips
|
||||
__swsetup; # arm x86 mips
|
||||
__sym_ntop;
|
||||
__sym_ntos;
|
||||
__sym_ston;
|
||||
__system_properties_init;
|
||||
__system_property_add;
|
||||
__system_property_area__;
|
||||
__system_property_area_init;
|
||||
__system_property_area_serial;
|
||||
__system_property_find;
|
||||
__system_property_find_nth;
|
||||
__system_property_foreach;
|
||||
__system_property_get;
|
||||
__system_property_read;
|
||||
__system_property_serial;
|
||||
__system_property_set;
|
||||
__system_property_set_filename;
|
||||
__system_property_update;
|
||||
__system_property_wait_any;
|
||||
__system_properties_init; # arm x86 mips
|
||||
__system_property_add; # arm x86 mips
|
||||
__system_property_area__; # arm x86 mips
|
||||
__system_property_area_init; # arm x86 mips
|
||||
__system_property_area_serial; # arm x86 mips
|
||||
__system_property_find; # arm x86 mips
|
||||
__system_property_find_nth; # arm x86 mips
|
||||
__system_property_foreach; # arm x86 mips
|
||||
__system_property_get; # arm x86 mips
|
||||
__system_property_read; # arm x86 mips
|
||||
__system_property_serial; # arm x86 mips
|
||||
__system_property_set; # arm x86 mips
|
||||
__system_property_set_filename; # arm x86 mips
|
||||
__system_property_update; # arm x86 mips
|
||||
__system_property_wait_any; # arm x86 mips
|
||||
__timer_create; # arm x86 mips
|
||||
__timer_delete; # arm x86 mips
|
||||
__timer_getoverrun; # arm x86 mips
|
||||
__timer_gettime; # arm x86 mips
|
||||
__timer_settime; # arm x86 mips
|
||||
__udivdi3; # arm x86 mips
|
||||
__udivdi3; # x86
|
||||
__umask_chk;
|
||||
__umoddi3; # x86 mips
|
||||
__vsnprintf_chk;
|
||||
__vsprintf_chk;
|
||||
__wait4; # arm x86 mips
|
||||
__waitid; # arm x86 mips
|
||||
_ctype_;
|
||||
_Exit;
|
||||
_exit;
|
||||
_flushlbf;
|
||||
_fwalk; # arm x86 mips
|
||||
_getlong;
|
||||
_getshort;
|
||||
_longjmp;
|
||||
@ -270,9 +241,7 @@ LIBC {
|
||||
android_gethostbynamefornet;
|
||||
android_set_abort_message;
|
||||
arc4random;
|
||||
arc4random_addrandom; # arm x86 mips
|
||||
arc4random_buf;
|
||||
arc4random_stir; # arm x86 mips
|
||||
arc4random_uniform;
|
||||
asctime;
|
||||
asctime64; # arm x86 mips
|
||||
@ -286,14 +255,11 @@ LIBC {
|
||||
atoll;
|
||||
basename;
|
||||
basename_r; # arm x86 mips
|
||||
bcopy; # arm x86 mips
|
||||
bind;
|
||||
bindresvport;
|
||||
brk;
|
||||
bsd_signal; # arm x86 mips
|
||||
bsearch;
|
||||
btowc;
|
||||
bzero; # arm x86 mips
|
||||
c16rtomb;
|
||||
c32rtomb;
|
||||
calloc;
|
||||
@ -345,7 +311,6 @@ LIBC {
|
||||
dup3;
|
||||
duplocale;
|
||||
endmntent;
|
||||
endpwent;
|
||||
endservent;
|
||||
endutent;
|
||||
environ;
|
||||
@ -392,7 +357,6 @@ LIBC {
|
||||
fdatasync;
|
||||
fdopen;
|
||||
fdopendir;
|
||||
fdprintf; # arm x86 mips
|
||||
feof;
|
||||
feof_unlocked;
|
||||
ferror;
|
||||
@ -424,7 +388,6 @@ LIBC {
|
||||
fputws;
|
||||
fread;
|
||||
free;
|
||||
free_malloc_leak_info;
|
||||
freeaddrinfo;
|
||||
freelocale;
|
||||
fremovexattr;
|
||||
@ -445,7 +408,6 @@ LIBC {
|
||||
fsync;
|
||||
ftell;
|
||||
ftello;
|
||||
ftime; # arm x86 mips
|
||||
ftok;
|
||||
ftruncate;
|
||||
ftruncate64;
|
||||
@ -466,7 +428,6 @@ LIBC {
|
||||
fwscanf;
|
||||
gai_strerror;
|
||||
get_avphys_pages;
|
||||
get_malloc_leak_info;
|
||||
get_nprocs;
|
||||
get_nprocs_conf;
|
||||
get_phys_pages;
|
||||
@ -478,8 +439,6 @@ LIBC {
|
||||
getchar_unlocked;
|
||||
getcwd;
|
||||
getdelim;
|
||||
getdents; # arm x86 mips
|
||||
getdtablesize; # arm x86 mips
|
||||
getegid;
|
||||
getenv;
|
||||
geteuid;
|
||||
@ -554,7 +513,6 @@ LIBC {
|
||||
if_nametoindex;
|
||||
imaxabs;
|
||||
imaxdiv;
|
||||
index; # arm x86 mips
|
||||
inet_addr;
|
||||
inet_aton;
|
||||
inet_lnaof;
|
||||
@ -607,7 +565,6 @@ LIBC {
|
||||
isprint_l;
|
||||
ispunct;
|
||||
ispunct_l;
|
||||
issetugid; # arm x86 mips
|
||||
isspace;
|
||||
isspace_l;
|
||||
isupper;
|
||||
@ -697,7 +654,6 @@ LIBC {
|
||||
mempcpy;
|
||||
memrchr;
|
||||
memset;
|
||||
memswap; # arm x86 mips
|
||||
mincore;
|
||||
mkdir;
|
||||
mkdirat;
|
||||
@ -717,7 +673,6 @@ LIBC {
|
||||
mktemp;
|
||||
mktime;
|
||||
mktime64; # arm x86 mips
|
||||
mktime_tz;
|
||||
mlock;
|
||||
mlockall;
|
||||
mmap;
|
||||
@ -788,7 +743,6 @@ LIBC {
|
||||
pthread_attr_getschedpolicy;
|
||||
pthread_attr_getscope;
|
||||
pthread_attr_getstack;
|
||||
pthread_attr_getstackaddr; # arm x86 mips
|
||||
pthread_attr_getstacksize;
|
||||
pthread_attr_init;
|
||||
pthread_attr_setdetachstate;
|
||||
@ -797,7 +751,6 @@ LIBC {
|
||||
pthread_attr_setschedpolicy;
|
||||
pthread_attr_setscope;
|
||||
pthread_attr_setstack;
|
||||
pthread_attr_setstackaddr; # arm x86 mips
|
||||
pthread_attr_setstacksize;
|
||||
pthread_cond_broadcast;
|
||||
pthread_cond_destroy;
|
||||
@ -1055,8 +1008,6 @@ LIBC {
|
||||
strncpy;
|
||||
strndup;
|
||||
strnlen;
|
||||
strntoimax; # arm x86 mips
|
||||
strntoumax; # arm x86 mips
|
||||
strpbrk;
|
||||
strptime;
|
||||
strrchr;
|
||||
@ -1075,7 +1026,6 @@ LIBC {
|
||||
strtoll;
|
||||
strtoll_l;
|
||||
strtoq;
|
||||
strtotimeval; # arm x86 mips
|
||||
strtoul;
|
||||
strtoull;
|
||||
strtoull_l;
|
||||
@ -1097,7 +1047,6 @@ LIBC {
|
||||
sysinfo;
|
||||
syslog;
|
||||
system;
|
||||
sysv_signal; # arm x86 mips
|
||||
tcdrain;
|
||||
tcflow;
|
||||
tcflush;
|
||||
@ -1129,7 +1078,6 @@ LIBC {
|
||||
timerfd_settime;
|
||||
times;
|
||||
timezone;
|
||||
tkill; # arm x86 mips
|
||||
tmpfile;
|
||||
tmpnam;
|
||||
toascii;
|
||||
@ -1171,7 +1119,6 @@ LIBC {
|
||||
vdprintf;
|
||||
verr;
|
||||
verrx;
|
||||
vfdprintf; # arm x86 mips
|
||||
vfork;
|
||||
vfprintf;
|
||||
vfscanf;
|
||||
@ -1191,7 +1138,6 @@ LIBC {
|
||||
vwprintf;
|
||||
vwscanf;
|
||||
wait;
|
||||
wait3; # arm x86 mips
|
||||
wait4;
|
||||
waitid;
|
||||
waitpid;
|
||||
@ -1240,7 +1186,6 @@ LIBC {
|
||||
wcstoull;
|
||||
wcstoull_l;
|
||||
wcstoumax;
|
||||
wcswcs; # arm x86 mips
|
||||
wcswidth;
|
||||
wcsxfrm;
|
||||
wcsxfrm_l;
|
||||
@ -1271,11 +1216,26 @@ LIBC_N {
|
||||
__pwrite_chk;
|
||||
__pwrite64_chk;
|
||||
__write_chk;
|
||||
fileno_unlocked;
|
||||
freeifaddrs;
|
||||
getgrgid_r;
|
||||
getgrnam_r;
|
||||
getifaddrs;
|
||||
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,13 +1248,68 @@ 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
|
||||
__divdi3; # arm x86 mips
|
||||
__futex_wait; # arm x86 mips nobrillo
|
||||
__futex_wake; # arm x86 mips nobrillo
|
||||
__get_thread; # arm x86 mips nobrillo
|
||||
__get_tls; # arm x86 mips nobrillo
|
||||
__getdents64; # arm x86 mips
|
||||
__open; # arm x86 mips nobrillo
|
||||
__page_shift; # arm x86 mips nobrillo
|
||||
__page_size; # arm x86 mips nobrillo
|
||||
__popcountsi2; # arm x86 mips
|
||||
__pthread_gettid; # arm x86 mips nobrillo
|
||||
__sclose; # arm x86 mips
|
||||
__sdidinit; # arm x86 mips nobrillo
|
||||
__set_errno; # arm x86 mips nobrillo
|
||||
__sflags; # arm x86 mips
|
||||
__sflush; # arm x86 mips
|
||||
__sfp; # arm x86 mips
|
||||
__sglue; # arm x86 mips
|
||||
__sinit; # arm x86 mips nobrillo
|
||||
__smakebuf; # arm x86 mips
|
||||
__sread; # arm x86 mips
|
||||
__srefill; # arm x86 mips
|
||||
__srget; # arm x86 mips
|
||||
__sseek; # arm x86 mips
|
||||
__swbuf; # arm x86 mips
|
||||
__swrite; # arm x86 mips
|
||||
__swsetup; # arm x86 mips
|
||||
__umoddi3; # x86 mips
|
||||
__wait4; # arm x86 mips nobrillo
|
||||
_fwalk; # arm x86 mips
|
||||
arc4random_addrandom; # arm x86 mips nobrillo
|
||||
arc4random_stir; # arm x86 mips nobrillo
|
||||
bcopy; # arm x86 mips nobrillo
|
||||
bzero; # arm x86 mips nobrillo
|
||||
bsd_signal; # arm x86 mips nobrillo
|
||||
dlmalloc; # arm x86 mips nobrillo
|
||||
dlmalloc_inspect_all; # arm x86 mips nobrillo
|
||||
dlmalloc_trim; # arm x86 mips nobrillo
|
||||
dlmalloc_usable_size; # arm x86 mips nobrillo
|
||||
endpwent; # arm x86 mips nobrillo
|
||||
fdprintf; # arm x86 mips nobrillo
|
||||
free_malloc_leak_info;
|
||||
ftime; # arm x86 mips nobrillo
|
||||
get_malloc_leak_info;
|
||||
getdents; # arm x86 mips nobrillo
|
||||
getdtablesize; # arm x86 mips nobrillo
|
||||
gMallocLeakZygoteChild;
|
||||
index; # arm x86 mips nobrillo
|
||||
issetugid; # arm x86 mips nobrillo
|
||||
memswap; # arm x86 mips nobrillo
|
||||
pthread_attr_getstackaddr; # arm x86 mips nobrillo
|
||||
pthread_attr_setstackaddr; # arm x86 mips nobrillo
|
||||
SHA1Final; # arm x86 mips
|
||||
SHA1Init; # arm x86 mips
|
||||
SHA1Transform; # arm x86 mips
|
||||
SHA1Update; # arm x86 mips
|
||||
strntoimax; # arm x86 mips nobrillo
|
||||
strntoumax; # arm x86 mips nobrillo
|
||||
strtotimeval; # arm x86 mips nobrillo
|
||||
sysv_signal; # arm x86 mips nobrillo
|
||||
tkill; # arm x86 mips nobrillo
|
||||
vfdprintf; # arm x86 mips nobrillo
|
||||
wait3; # arm x86 mips nobrillo
|
||||
wcswcs; # arm x86 mips nobrillo
|
||||
} LIBC_N;
|
||||
|
@ -131,21 +131,6 @@ LIBC {
|
||||
__sym_ntop;
|
||||
__sym_ntos;
|
||||
__sym_ston;
|
||||
__system_properties_init;
|
||||
__system_property_add;
|
||||
__system_property_area__;
|
||||
__system_property_area_init;
|
||||
__system_property_area_serial;
|
||||
__system_property_find;
|
||||
__system_property_find_nth;
|
||||
__system_property_foreach;
|
||||
__system_property_get;
|
||||
__system_property_read;
|
||||
__system_property_serial;
|
||||
__system_property_set;
|
||||
__system_property_set_filename;
|
||||
__system_property_update;
|
||||
__system_property_wait_any;
|
||||
__umask_chk;
|
||||
__vsnprintf_chk;
|
||||
__vsprintf_chk;
|
||||
@ -241,7 +226,6 @@ LIBC {
|
||||
dup3;
|
||||
duplocale;
|
||||
endmntent;
|
||||
endpwent;
|
||||
endservent;
|
||||
endutent;
|
||||
environ;
|
||||
@ -317,7 +301,6 @@ LIBC {
|
||||
fputws;
|
||||
fread;
|
||||
free;
|
||||
free_malloc_leak_info;
|
||||
freeaddrinfo;
|
||||
freelocale;
|
||||
fremovexattr;
|
||||
@ -358,7 +341,6 @@ LIBC {
|
||||
fwscanf;
|
||||
gai_strerror;
|
||||
get_avphys_pages;
|
||||
get_malloc_leak_info;
|
||||
get_nprocs;
|
||||
get_nprocs_conf;
|
||||
get_phys_pages;
|
||||
@ -599,7 +581,6 @@ LIBC {
|
||||
mkstemps64;
|
||||
mktemp;
|
||||
mktime;
|
||||
mktime_tz;
|
||||
mlock;
|
||||
mlockall;
|
||||
mmap;
|
||||
@ -1156,10 +1137,25 @@ LIBC_N {
|
||||
__pwrite_chk;
|
||||
__pwrite64_chk;
|
||||
__write_chk;
|
||||
fileno_unlocked;
|
||||
freeifaddrs;
|
||||
getgrgid_r;
|
||||
getgrnam_r;
|
||||
getifaddrs;
|
||||
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 +1165,22 @@ LIBC_N {
|
||||
|
||||
LIBC_PRIVATE {
|
||||
global:
|
||||
dlmalloc_inspect_all;
|
||||
dlmalloc_trim;
|
||||
__system_properties_init; # arm64 x86_64 mips64
|
||||
__system_property_add; # arm64 x86_64 mips64
|
||||
__system_property_area__; # arm64 x86_64 mips64
|
||||
__system_property_area_init; # arm64 x86_64 mips64
|
||||
__system_property_area_serial; # arm64 x86_64 mips64
|
||||
__system_property_find; # arm64 x86_64 mips64
|
||||
__system_property_find_nth; # arm64 x86_64 mips64
|
||||
__system_property_foreach; # arm64 x86_64 mips64
|
||||
__system_property_get; # arm64 x86_64 mips64
|
||||
__system_property_read; # arm64 x86_64 mips64
|
||||
__system_property_serial; # arm64 x86_64 mips64
|
||||
__system_property_set; # arm64 x86_64 mips64
|
||||
__system_property_set_filename; # arm64 x86_64 mips64
|
||||
__system_property_update; # arm64 x86_64 mips64
|
||||
__system_property_wait_any; # arm64 x86_64 mips64
|
||||
free_malloc_leak_info;
|
||||
get_malloc_leak_info;
|
||||
gMallocLeakZygoteChild;
|
||||
} LIBC_N;
|
||||
|
@ -38,32 +38,25 @@ class KernelArgumentBlock {
|
||||
argv = reinterpret_cast<char**>(args + 1);
|
||||
envp = argv + argc + 1;
|
||||
|
||||
// Skip over all environment variable definitions to find aux vector.
|
||||
// The end of the environment block is marked by two NULL pointers.
|
||||
// Skip over all environment variable definitions to find the aux vector.
|
||||
// The end of the environment block is marked by a NULL pointer.
|
||||
char** p = envp;
|
||||
while (*p != NULL) {
|
||||
++p;
|
||||
}
|
||||
++p; // Skip second NULL;
|
||||
++p; // Skip the NULL itself.
|
||||
|
||||
auxv = reinterpret_cast<ElfW(auxv_t)*>(p);
|
||||
}
|
||||
|
||||
// Similar to ::getauxval but doesn't require the libc global variables to be set up,
|
||||
// so it's safe to call this really early on. This function also lets you distinguish
|
||||
// between the inability to find the given type and its value just happening to be 0.
|
||||
unsigned long getauxval(unsigned long type, bool* found_match = NULL) {
|
||||
// so it's safe to call this really early on.
|
||||
unsigned long getauxval(unsigned long type) {
|
||||
for (ElfW(auxv_t)* v = auxv; v->a_type != AT_NULL; ++v) {
|
||||
if (v->a_type == type) {
|
||||
if (found_match != NULL) {
|
||||
*found_match = true;
|
||||
}
|
||||
return v->a_un.a_val;
|
||||
}
|
||||
}
|
||||
if (found_match != NULL) {
|
||||
*found_match = false;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -42,8 +42,8 @@
|
||||
(((value) + (alignment) - 1) & ~((alignment) - 1))
|
||||
|
||||
#define BIONIC_ROUND_UP_POWER_OF_2(value) \
|
||||
(sizeof(value) == 8) \
|
||||
((sizeof(value) == 8) \
|
||||
? (1UL << (64 - __builtin_clzl(static_cast<unsigned long>(value)))) \
|
||||
: (1UL << (32 - __builtin_clz(static_cast<unsigned int>(value))))
|
||||
: (1UL << (32 - __builtin_clz(static_cast<unsigned int>(value)))))
|
||||
|
||||
#endif // _BIONIC_MACROS_H_
|
||||
|
@ -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,24 @@ __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, bool null_allowed) {
|
||||
if (null_allowed && ts == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
// glibc just segfaults if you pass a null timespec.
|
||||
// That seems a lot more likely to catch bad code than returning EINVAL.
|
||||
if (ts->tv_nsec < 0 || ts->tv_nsec >= NS_PER_S) {
|
||||
return EINVAL;
|
||||
}
|
||||
if (ts->tv_sec < 0) {
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -121,7 +121,7 @@ __END_DECLS
|
||||
|
||||
#if defined(__cplusplus)
|
||||
class KernelArgumentBlock;
|
||||
extern __LIBC_HIDDEN__ void __libc_init_main_thread(KernelArgumentBlock& args);
|
||||
extern __LIBC_HIDDEN__ void __libc_init_main_thread(KernelArgumentBlock&);
|
||||
#endif
|
||||
|
||||
#endif /* __BIONIC_PRIVATE_BIONIC_TLS_H_ */
|
||||
|
@ -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"));
|
||||
@ -2457,50 +2462,4 @@ static int __bionic_open_tzdata(const char* olson_id) {
|
||||
return fd;
|
||||
}
|
||||
|
||||
// Caches the most recent timezone (http://b/8270865).
|
||||
static int __bionic_tzload_cached(const char* name, struct state* const sp, const int doextend) {
|
||||
lock();
|
||||
|
||||
// Our single-item cache.
|
||||
static char* g_cached_time_zone_name;
|
||||
static struct state g_cached_time_zone;
|
||||
|
||||
// Do we already have this timezone cached?
|
||||
if (g_cached_time_zone_name != NULL && strcmp(name, g_cached_time_zone_name) == 0) {
|
||||
*sp = g_cached_time_zone;
|
||||
unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Can we load it?
|
||||
int rc = tzload(name, sp, doextend);
|
||||
if (rc == 0) {
|
||||
// Update the cache.
|
||||
free(g_cached_time_zone_name);
|
||||
g_cached_time_zone_name = strdup(name);
|
||||
g_cached_time_zone = *sp;
|
||||
}
|
||||
|
||||
unlock();
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Non-standard API: mktime(3) but with an explicit timezone parameter.
|
||||
// This can't actually be hidden/removed until we fix MtpUtils.cpp
|
||||
__attribute__((visibility("default"))) time_t mktime_tz(struct tm* const tmp, const char* tz) {
|
||||
struct state* st = malloc(sizeof(*st));
|
||||
time_t return_value;
|
||||
|
||||
if (st == NULL)
|
||||
return 0;
|
||||
if (__bionic_tzload_cached(tz, st, true) != 0) {
|
||||
// TODO: not sure what's best here, but for now, we fall back to gmt.
|
||||
gmtload(st);
|
||||
}
|
||||
|
||||
return_value = time1(tmp, localsub, st, 0L);
|
||||
free(st);
|
||||
return return_value;
|
||||
}
|
||||
|
||||
// END android-added
|
||||
|
@ -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],
|
||||
|
@ -4822,8 +4822,13 @@ void* dlcalloc(size_t n_elements, size_t elem_size) {
|
||||
req = MAX_SIZE_T; /* force downstream failure on overflow */
|
||||
}
|
||||
mem = dlmalloc(req);
|
||||
if (mem != 0 && calloc_must_clear(mem2chunk(mem)))
|
||||
memset(mem, 0, req);
|
||||
if (mem != 0) {
|
||||
mchunkptr p = mem2chunk(mem);
|
||||
if (calloc_must_clear(p)) {
|
||||
/* Make sure to clear all of the buffer, not just the requested size. */
|
||||
memset(mem, 0, chunksize(p) - overhead_for(p));
|
||||
}
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
|
||||
|
@ -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,17 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_N {
|
||||
global:
|
||||
android_init_namespaces;
|
||||
android_create_namespace;
|
||||
dlvsym;
|
||||
} 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,17 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_N {
|
||||
global:
|
||||
android_init_namespaces;
|
||||
android_create_namespace;
|
||||
dlvsym;
|
||||
} 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;
|
||||
|
@ -24,21 +24,48 @@
|
||||
// in the dynamic linker and hijacked at runtime.
|
||||
|
||||
void* dlopen(const char* filename __unused, int flag __unused) { return 0; }
|
||||
|
||||
const char* dlerror(void) { return 0; }
|
||||
|
||||
void* dlsym(void* handle __unused, const char* symbol __unused) { return 0; }
|
||||
|
||||
void* dlvsym(void* handle __unused, const char* symbol __unused, const char* version __unused) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dladdr(const void* addr __unused, Dl_info* info __unused) { return 0; }
|
||||
|
||||
int dlclose(void* handle __unused) { return 0; }
|
||||
|
||||
#if defined(__arm__)
|
||||
_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,
|
||||
uint64_t type __unused,
|
||||
const char* permitted_when_isolated_path __unused) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -28,10 +28,17 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_N {
|
||||
global:
|
||||
android_init_namespaces;
|
||||
android_create_namespace;
|
||||
dlvsym;
|
||||
} 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,17 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_N {
|
||||
global:
|
||||
android_init_namespaces;
|
||||
android_create_namespace;
|
||||
dlvsym;
|
||||
} 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,17 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_N {
|
||||
global:
|
||||
android_init_namespaces;
|
||||
android_create_namespace;
|
||||
dlvsym;
|
||||
} 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,17 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_N {
|
||||
global:
|
||||
android_init_namespaces;
|
||||
android_create_namespace;
|
||||
dlvsym;
|
||||
} 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,17 @@ LIBC {
|
||||
*;
|
||||
};
|
||||
|
||||
LIBC_N {
|
||||
global:
|
||||
android_init_namespaces;
|
||||
android_create_namespace;
|
||||
dlvsym;
|
||||
} 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 \
|
||||
|
||||
|
124
linker/dlfcn.cpp
124
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,32 @@ void* dlopen(const char* filename, int flags) {
|
||||
return dlopen_ext(filename, flags, nullptr, caller_addr);
|
||||
}
|
||||
|
||||
void* dlsym(void* handle, const char* symbol) {
|
||||
extern android_namespace_t* g_anonymous_namespace;
|
||||
|
||||
void* dlsym_impl(void* handle, const char* symbol, const char* version, void* caller_addr) {
|
||||
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);
|
||||
void* result;
|
||||
if (!do_dlsym(handle, symbol, version, caller_addr, &result)) {
|
||||
__bionic_format_dlerror(linker_get_error_buffer(), nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
soinfo* found = nullptr;
|
||||
const ElfW(Sym)* sym = nullptr;
|
||||
return result;
|
||||
}
|
||||
|
||||
void* dlsym(void* handle, const char* symbol) {
|
||||
void* caller_addr = __builtin_return_address(0);
|
||||
soinfo* caller = find_containing_library(caller_addr);
|
||||
return dlsym_impl(handle, symbol, nullptr, 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);
|
||||
return nullptr;
|
||||
}
|
||||
void* dlvsym(void* handle, const char* symbol, const char* version) {
|
||||
void* caller_addr = __builtin_return_address(0);
|
||||
return dlsym_impl(handle, symbol, version, caller_addr);
|
||||
}
|
||||
|
||||
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 +136,34 @@ 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, uint64_t type,
|
||||
const char* permitted_when_isolated_path) {
|
||||
void* caller_addr = __builtin_return_address(0);
|
||||
ScopedPthreadMutexLocker locker(&g_dl_mutex);
|
||||
|
||||
android_namespace_t* result = create_namespace(caller_addr, name, ld_library_path,
|
||||
default_library_path, type,
|
||||
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 +190,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 6666677
|
||||
// 0123456789012345 678901234567890123456789 0123456789012345678901234 5678901
|
||||
"get_sdk_version\0android_init_namespaces\0android_create_namespace\0dlvsym\0"
|
||||
#if defined(__arm__)
|
||||
// 216
|
||||
// 272
|
||||
"dl_unwind_find_exidx\0"
|
||||
#endif
|
||||
;
|
||||
@ -229,8 +216,11 @@ 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),
|
||||
ELFW(SYM_INITIALIZER)(265, &dlvsym, 1),
|
||||
#if defined(__arm__)
|
||||
ELFW(SYM_INITIALIZER)(216, &dl_unwind_find_exidx, 1),
|
||||
ELFW(SYM_INITIALIZER)(272, &dl_unwind_find_exidx, 1),
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -247,18 +237,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, 15, 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, 14, 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) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user