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