mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-12-01 17:56:10 +03:00
Compare commits
No commits in common. "12a6ba324f8bc147f3f7ba299e9264e68d2d1a25" and "0efdd5d766d82fc319aed5028eb3fb0c149ea4a9" have entirely different histories.
12a6ba324f
...
0efdd5d766
@ -1 +1 @@
|
|||||||
111.0.5563.64
|
112.0.5615.49
|
||||||
|
10
src/AUTHORS
10
src/AUTHORS
@ -126,6 +126,7 @@ Anton Obzhirov <a.obzhirov@samsung.com>
|
|||||||
Antonin Hildebrand <antonin.hildebrand@gmail.com>
|
Antonin Hildebrand <antonin.hildebrand@gmail.com>
|
||||||
Antonio Gomes <a1.gomes@sisa.samsung.com>
|
Antonio Gomes <a1.gomes@sisa.samsung.com>
|
||||||
Anuj Kumar Sharma <anujk.sharma@samsung.com>
|
Anuj Kumar Sharma <anujk.sharma@samsung.com>
|
||||||
|
Ao Hui <aohui.wan@gmail.com>
|
||||||
Ao Sun <ntusunao@gmail.com>
|
Ao Sun <ntusunao@gmail.com>
|
||||||
Ao Wang <wangao.james@bytedance.com>
|
Ao Wang <wangao.james@bytedance.com>
|
||||||
Aquibuzzaman Md. Sayem <md.sayem@samsung.com>
|
Aquibuzzaman Md. Sayem <md.sayem@samsung.com>
|
||||||
@ -277,6 +278,7 @@ Daniel Waxweiler <daniel.waxweiler@gmail.com>
|
|||||||
Dániel Bátyai <dbatyai@inf.u-szeged.hu>
|
Dániel Bátyai <dbatyai@inf.u-szeged.hu>
|
||||||
Dániel Vince <vinced@inf.u-szeged.hu>
|
Dániel Vince <vinced@inf.u-szeged.hu>
|
||||||
Daniil Suvorov <severecloud@gmail.com>
|
Daniil Suvorov <severecloud@gmail.com>
|
||||||
|
Danny Weiss <danny.weiss.fr@gmail.com>
|
||||||
Daoming Qiu <daoming.qiu@intel.com>
|
Daoming Qiu <daoming.qiu@intel.com>
|
||||||
Darik Harter <darik.harter@gmail.com>
|
Darik Harter <darik.harter@gmail.com>
|
||||||
Darshan Sen <raisinten@gmail.com>
|
Darshan Sen <raisinten@gmail.com>
|
||||||
@ -376,6 +378,7 @@ Feifei Wang <alexswang@tencent.com>
|
|||||||
Felipe Erias Morandeira <felipeerias@gmail.com>
|
Felipe Erias Morandeira <felipeerias@gmail.com>
|
||||||
Felix H. Dahlke <fhd@ubercode.de>
|
Felix H. Dahlke <fhd@ubercode.de>
|
||||||
Felix Weilbach <feweilbach@gmail.com>
|
Felix Weilbach <feweilbach@gmail.com>
|
||||||
|
Feng Shengyuan <fengshengyuan@agora.io>
|
||||||
Feng Yu <f3n67u@gmail.com>
|
Feng Yu <f3n67u@gmail.com>
|
||||||
Fengrong Fang <fr.fang@samsung.com>
|
Fengrong Fang <fr.fang@samsung.com>
|
||||||
Fernando Jiménez Moreno <ferjmoreno@gmail.com>
|
Fernando Jiménez Moreno <ferjmoreno@gmail.com>
|
||||||
@ -605,6 +608,7 @@ John Kleinschmidt <kleinschmidtorama@gmail.com>
|
|||||||
John Yani <vanuan@gmail.com>
|
John Yani <vanuan@gmail.com>
|
||||||
John Yoo <nearbyh13@gmail.com>
|
John Yoo <nearbyh13@gmail.com>
|
||||||
Johnson Lin <johnson.lin@intel.com>
|
Johnson Lin <johnson.lin@intel.com>
|
||||||
|
Jon Jensen <jonj@netflix.com>
|
||||||
Jonathan Frazer <listedegarde@gmail.com>
|
Jonathan Frazer <listedegarde@gmail.com>
|
||||||
Jonathan Garbee <jonathan@garbee.me>
|
Jonathan Garbee <jonathan@garbee.me>
|
||||||
Jonathan Hacker <jhacker@arcanefour.com>
|
Jonathan Hacker <jhacker@arcanefour.com>
|
||||||
@ -640,6 +644,7 @@ Julien Isorce <j.isorce@samsung.com>
|
|||||||
Julien Racle <jracle@logitech.com>
|
Julien Racle <jracle@logitech.com>
|
||||||
Jun Fang <jun_fang@foxitsoftware.com>
|
Jun Fang <jun_fang@foxitsoftware.com>
|
||||||
Jun Jiang <jun.a.jiang@intel.com>
|
Jun Jiang <jun.a.jiang@intel.com>
|
||||||
|
Junbong Eom <jb.eom@samsung.com>
|
||||||
Jungchang Park <valley84265@gmail.com>
|
Jungchang Park <valley84265@gmail.com>
|
||||||
Junchao Han <junchao.han@intel.com>
|
Junchao Han <junchao.han@intel.com>
|
||||||
Junghoon Lee <sjh836@gmail.com>
|
Junghoon Lee <sjh836@gmail.com>
|
||||||
@ -740,6 +745,7 @@ Li Yanbo <liyanbo.monster@bytedance.com>
|
|||||||
Li Yin <li.yin@intel.com>
|
Li Yin <li.yin@intel.com>
|
||||||
Lidwine Genevet <lgenevet@cisco.com>
|
Lidwine Genevet <lgenevet@cisco.com>
|
||||||
Lin Sun <lin.sun@intel.com>
|
Lin Sun <lin.sun@intel.com>
|
||||||
|
Lin Peng <penglin220@gmail.com>
|
||||||
Lin Peng <penglin22@huawei.com>
|
Lin Peng <penglin22@huawei.com>
|
||||||
Lingqi Chi <someway.bit@gmail.com>
|
Lingqi Chi <someway.bit@gmail.com>
|
||||||
Lingyun Cai <lingyun.cai@intel.com>
|
Lingyun Cai <lingyun.cai@intel.com>
|
||||||
@ -762,7 +768,7 @@ Luke Seunghoe Gu <gulukesh@gmail.com>
|
|||||||
Luke Zarko <lukezarko@gmail.com>
|
Luke Zarko <lukezarko@gmail.com>
|
||||||
Luoxi Pan <l.panpax@gmail.com>
|
Luoxi Pan <l.panpax@gmail.com>
|
||||||
Lu Yahan <yahan@iscas.ac.cn>
|
Lu Yahan <yahan@iscas.ac.cn>
|
||||||
Ma Aiguo <maaiguo@uniontech.com>
|
Ma Aiguo <imaiguo@gmail.com>
|
||||||
Maarten Lankhorst <m.b.lankhorst@gmail.com>
|
Maarten Lankhorst <m.b.lankhorst@gmail.com>
|
||||||
Maciej Pawlowski <m.pawlowski@eyeo.com>
|
Maciej Pawlowski <m.pawlowski@eyeo.com>
|
||||||
Magnus Danielsson <fuzzac@gmail.com>
|
Magnus Danielsson <fuzzac@gmail.com>
|
||||||
@ -915,6 +921,7 @@ Noj Vek <nojvek@gmail.com>
|
|||||||
Nolan Cao <nolan.robin.cao@gmail.com>
|
Nolan Cao <nolan.robin.cao@gmail.com>
|
||||||
Oleksii Kadurin <ovkadurin@gmail.com>
|
Oleksii Kadurin <ovkadurin@gmail.com>
|
||||||
Oliver Dunk <oliver@oliverdunk.com>
|
Oliver Dunk <oliver@oliverdunk.com>
|
||||||
|
Olivier Tilloy <olivier+chromium@tilloy.net>
|
||||||
Olli Raula (Old name Olli Syrjälä) <olli.raula@intel.com>
|
Olli Raula (Old name Olli Syrjälä) <olli.raula@intel.com>
|
||||||
Omar Sandoval <osandov@osandov.com>
|
Omar Sandoval <osandov@osandov.com>
|
||||||
Owen Yuwono <owenyuwono@gmail.com>
|
Owen Yuwono <owenyuwono@gmail.com>
|
||||||
@ -1199,6 +1206,7 @@ Suyash Nayan <suyashnyn1@gmail.com>
|
|||||||
Suyash Sengar <suyash.s@samsung.com>
|
Suyash Sengar <suyash.s@samsung.com>
|
||||||
Swarali Raut <swarali.sr@samsung.com>
|
Swarali Raut <swarali.sr@samsung.com>
|
||||||
Swati Jaiswal <swa.jaiswal@samsung.com>
|
Swati Jaiswal <swa.jaiswal@samsung.com>
|
||||||
|
Syed Wajid <syed.wajid@samsung.com>
|
||||||
Sylvain Zimmer <sylvinus@gmail.com>
|
Sylvain Zimmer <sylvinus@gmail.com>
|
||||||
Sylvestre Ledru <sylvestre.ledru@gmail.com>
|
Sylvestre Ledru <sylvestre.ledru@gmail.com>
|
||||||
Synthia Islam <synthia.is@samsung.com>
|
Synthia Islam <synthia.is@samsung.com>
|
||||||
|
358
src/DEPS
358
src/DEPS
@ -229,7 +229,7 @@ vars = {
|
|||||||
#
|
#
|
||||||
# CQ_INCLUDE_TRYBOTS=luci.chrome.try:lacros-amd64-generic-chrome-skylab
|
# CQ_INCLUDE_TRYBOTS=luci.chrome.try:lacros-amd64-generic-chrome-skylab
|
||||||
# CQ_INCLUDE_TRYBOTS=luci.chrome.try:lacros-arm-generic-chrome-skylab
|
# CQ_INCLUDE_TRYBOTS=luci.chrome.try:lacros-arm-generic-chrome-skylab
|
||||||
'lacros_sdk_version': '15326.0.0',
|
'lacros_sdk_version': '15357.0.0',
|
||||||
|
|
||||||
# Generate location tag metadata to include in tests result data uploaded
|
# Generate location tag metadata to include in tests result data uploaded
|
||||||
# to ResultDB. This isn't needed on some configs and the tool that generates
|
# to ResultDB. This isn't needed on some configs and the tool that generates
|
||||||
@ -241,7 +241,7 @@ vars = {
|
|||||||
# luci-go CIPD package version.
|
# luci-go CIPD package version.
|
||||||
# Make sure the revision is uploaded by infra-packagers builder.
|
# Make sure the revision is uploaded by infra-packagers builder.
|
||||||
# https://ci.chromium.org/p/infra-internal/g/infra-packagers/console
|
# https://ci.chromium.org/p/infra-internal/g/infra-packagers/console
|
||||||
'luci_go': 'git_revision:221383f749a2c5b8587449d3d2e4982857daa9e7',
|
'luci_go': 'git_revision:8a8b4f2ea65c7ff5fde8a0c522008aed78d42d9d',
|
||||||
|
|
||||||
# This can be overridden, e.g. with custom_vars, to build clang from HEAD
|
# This can be overridden, e.g. with custom_vars, to build clang from HEAD
|
||||||
# instead of downloading the prebuilt pinned revision.
|
# instead of downloading the prebuilt pinned revision.
|
||||||
@ -286,11 +286,6 @@ vars = {
|
|||||||
# Rust toolchain.
|
# Rust toolchain.
|
||||||
'checkout_rust_toolchain_deps': False,
|
'checkout_rust_toolchain_deps': False,
|
||||||
|
|
||||||
# The Rust toolchain sources. It is a version tag from an instance of the
|
|
||||||
# CIPD `chromium/third_party/rust_src` package. This field is written by
|
|
||||||
# //tools/clang/scripts/upload_revision.py and shouldn't be updated by hand.
|
|
||||||
'rust_toolchain_version': 'version:2@2022-12-09',
|
|
||||||
|
|
||||||
'android_git': 'https://android.googlesource.com',
|
'android_git': 'https://android.googlesource.com',
|
||||||
'aomedia_git': 'https://aomedia.googlesource.com',
|
'aomedia_git': 'https://aomedia.googlesource.com',
|
||||||
'boringssl_git': 'https://boringssl.googlesource.com',
|
'boringssl_git': 'https://boringssl.googlesource.com',
|
||||||
@ -304,34 +299,34 @@ vars = {
|
|||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling Skia
|
# the commit queue can handle CLs rolling Skia
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'skia_revision': '59932b057f281ddaeb0926ecfac55486270f8c51',
|
'skia_revision': 'f5fefe5245098be43cb608eace5e14d67cdc09e6',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling V8
|
# the commit queue can handle CLs rolling V8
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'v8_revision': '1cee747760b14aa78503a22ba1a3ab97b968fa28',
|
'v8_revision': '96fed67922e5f54a027aed80259e5083769e33e2',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling ANGLE
|
# the commit queue can handle CLs rolling ANGLE
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'angle_revision': 'cd45d155bf4cf7404061f37e974a048914ca4610',
|
'angle_revision': '293db5ce4d0766cb3ba7711057a00f0a5bddb00d',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling SwiftShader
|
# the commit queue can handle CLs rolling SwiftShader
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'swiftshader_revision': 'aae98adc2222dcada4aa952cccad48ab08e34004',
|
'swiftshader_revision': '3575b5479af54e471ea6750a8585e2c9bc87801c',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling PDFium
|
# the commit queue can handle CLs rolling PDFium
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'pdfium_revision': 'd087df316170b2d8757487b1015244384624478e',
|
'pdfium_revision': '4090d4c0f9873f5f50b630c26c2439b5297a6e49',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling BoringSSL
|
# the commit queue can handle CLs rolling BoringSSL
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
#
|
#
|
||||||
# Note this revision should be updated with
|
# Note this revision should be updated with
|
||||||
# third_party/boringssl/roll_boringssl.py, not roll-dep.
|
# third_party/boringssl/roll_boringssl.py, not roll-dep.
|
||||||
'boringssl_revision': '45b8d7bbd771cbf7e116db2ba1f1cc7af959497e',
|
'boringssl_revision': 'ca1690e221677cea3fb946f324eb89d846ec53f2',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling Fuchsia sdk
|
# the commit queue can handle CLs rolling Fuchsia sdk
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'fuchsia_version': 'version:11.20230126.1.1',
|
'fuchsia_version': 'version:11.20230223.1.1',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling google-toolbox-for-mac
|
# the commit queue can handle CLs rolling google-toolbox-for-mac
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
@ -351,11 +346,11 @@ vars = {
|
|||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling NaCl
|
# the commit queue can handle CLs rolling NaCl
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'nacl_revision': '5b530a9ffd34be8541037262cf47cf3924bfc973',
|
'nacl_revision': '417b413dbe94a861ee050d42daf945cca02dba11',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling freetype
|
# the commit queue can handle CLs rolling freetype
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'freetype_revision': '82ce172669f132839debe6e50a3a53fe88db9e31',
|
'freetype_revision': '3f01161ff22c84c371b6dc3b5e0351e0d6e8e771',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling freetype
|
# the commit queue can handle CLs rolling freetype
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
@ -375,15 +370,23 @@ vars = {
|
|||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling catapult
|
# the commit queue can handle CLs rolling catapult
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'catapult_revision': 'abaad53f0c4e104ab630b314af2902ad83b82c8c',
|
'catapult_revision': '4274fe29dac91b7713244daebb6f1d2364d97193',
|
||||||
|
# Three lines of non-changing comments so that
|
||||||
|
# the commit queue can handle CLs rolling CrossBench
|
||||||
|
# and whatever else without interference from each other.
|
||||||
|
'crossbench_revision': '27639d495e1cec411073bc82ba1fe368ce0ca89a',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling libFuzzer
|
# the commit queue can handle CLs rolling libFuzzer
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'libfuzzer_revision': 'debe7d2d1982e540fbd6bd78604bf001753f9e74',
|
'libfuzzer_revision': 'debe7d2d1982e540fbd6bd78604bf001753f9e74',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
|
# the commit queue can handle CLs rolling centipede
|
||||||
|
# and whatever else without interference from each other.
|
||||||
|
'centipede_revision': '63ed43d2bfa2c04e291e81d643a5581c9be90c53',
|
||||||
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling devtools-frontend
|
# the commit queue can handle CLs rolling devtools-frontend
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'devtools_frontend_revision': 'f0bf0ece4aae3192fa2f0f2859f668cb343791be',
|
'devtools_frontend_revision': '2436ae2c5444ba8008a9f092301209a87aef0483',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling libprotobuf-mutator
|
# the commit queue can handle CLs rolling libprotobuf-mutator
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
@ -411,6 +414,10 @@ vars = {
|
|||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling android_sdk_platforms_version
|
# the commit queue can handle CLs rolling android_sdk_platforms_version
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
|
'android_sdk_platforms_preview_version': 'YWMYkzyxGBgVsty0GhXL1oxbY0pGXQIgFc0Rh7ZMRPYC',
|
||||||
|
# Three lines of non-changing comments so that
|
||||||
|
# the commit queue can handle CLs rolling android_sdk_platforms_version
|
||||||
|
# and whatever else without interference from each other.
|
||||||
'android_sdk_platforms_version': 'eo5KvW6UVor92LwZai8Zulc624BQZoCu-yn7wa1z_YcC',
|
'android_sdk_platforms_version': 'eo5KvW6UVor92LwZai8Zulc624BQZoCu-yn7wa1z_YcC',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling android_sdk_sources_version
|
# the commit queue can handle CLs rolling android_sdk_sources_version
|
||||||
@ -419,11 +426,11 @@ vars = {
|
|||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling feed
|
# the commit queue can handle CLs rolling feed
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'dawn_revision': 'e5193f1ffd232ebf7adfd403114edde08d162663',
|
'dawn_revision': 'de24841411c4cfb13662238327f2e456c82d26f6',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling feed
|
# the commit queue can handle CLs rolling feed
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'quiche_revision': '566b33c9fa5b1723db04be3d40dcaf102344c323',
|
'quiche_revision': '40c87d454d762f3daaeca334cd2dc962f0476b13',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling ios_webkit
|
# the commit queue can handle CLs rolling ios_webkit
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
@ -443,7 +450,7 @@ vars = {
|
|||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling nearby
|
# the commit queue can handle CLs rolling nearby
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'nearby_revision': '26973fada5175060db140d7e1157cce6b604dc6a',
|
'nearby_revision': 'd260feced56cfdea53f941883c250d635ed6064d',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling securemessage
|
# the commit queue can handle CLs rolling securemessage
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
@ -455,19 +462,19 @@ vars = {
|
|||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling feed
|
# the commit queue can handle CLs rolling feed
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'cros_components_revision': '5e449ecf7311cba83cdcfc1b2ae449f40d22f29e',
|
'cros_components_revision': 'fb2448fc618b4e3634c8c4097b4a84fcfa34c540',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling feed
|
# the commit queue can handle CLs rolling feed
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'resultdb_version': 'git_revision:ac21cf9883af7d1bf6d60e8a7448918eb3b6aa18',
|
'resultdb_version': 'git_revision:ebc74d10fa0d64057daa6f128e89f3672eeeec95',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling feed
|
# the commit queue can handle CLs rolling feed
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'libcxxabi_revision': 'd520d582aa710cc0a4635620c02c5dbc187deb4f',
|
'libcxxabi_revision': '87d8fe050bedb143f232b9ff99a0a46897640e5d',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling feed
|
# the commit queue can handle CLs rolling feed
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'libunwind_revision': 'e95b94b74d26f8387d4fb03a687a2fab0ed8e91c',
|
'libunwind_revision': 'c5e861c7b48ee121d3719b7b5c14175c47ec5cc9',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling feed
|
# the commit queue can handle CLs rolling feed
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
@ -475,18 +482,18 @@ vars = {
|
|||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling feed
|
# the commit queue can handle CLs rolling feed
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'highway_revision': '8ae5b88670fb918f815b717c7c13d38a9b0eb4bb',
|
'highway_revision': '58746ca5b9f9444a2a3549704602ecc6239f8f41',
|
||||||
# Three lines of non-changing comments so that
|
# Three lines of non-changing comments so that
|
||||||
# the commit queue can handle CLs rolling ffmpeg
|
# the commit queue can handle CLs rolling ffmpeg
|
||||||
# and whatever else without interference from each other.
|
# and whatever else without interference from each other.
|
||||||
'ffmpeg_revision': 'a249b21db6516234e5456716ae074fbb00176b3f',
|
'ffmpeg_revision': 'ee0c52d52036ecadfd38affec86c04937480bedb',
|
||||||
|
|
||||||
# If you change this, also update the libc++ revision in
|
# If you change this, also update the libc++ revision in
|
||||||
# //buildtools/deps_revisions.gni.
|
# //buildtools/deps_revisions.gni.
|
||||||
'libcxx_revision': '1127c78cf90cf253be614a1e1d3645da57edbeb4',
|
'libcxx_revision': 'e136ec5032a5e5d97e988ce66e8c269a80ff54c4',
|
||||||
|
|
||||||
# GN CIPD package version.
|
# GN CIPD package version.
|
||||||
'gn_version': 'git_revision:5e19d2fb166fbd4f6f32147fbb2f497091a54ad8',
|
'gn_version': 'git_revision:b25a2f8c2d33f02082f0f258350f5e22c0973108',
|
||||||
|
|
||||||
# ninja CIPD package version.
|
# ninja CIPD package version.
|
||||||
# https://chrome-infra-packages.appspot.com/p/infra/3pp/tools/ninja
|
# https://chrome-infra-packages.appspot.com/p/infra/3pp/tools/ninja
|
||||||
@ -579,19 +586,6 @@ deps = {
|
|||||||
'condition': 'host_os == "linux"',
|
'condition': 'host_os == "linux"',
|
||||||
},
|
},
|
||||||
|
|
||||||
# Rust sources are used to build the Rust standard library, and on toolchain
|
|
||||||
# build bots, to build the Rust toolchain.
|
|
||||||
'src/third_party/rust_src/src': {
|
|
||||||
'packages': [
|
|
||||||
{
|
|
||||||
'package': 'chromium/third_party/rust_src',
|
|
||||||
'version': Var('rust_toolchain_version'),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'dep_type': 'cipd',
|
|
||||||
'condition': 'checkout_rust_toolchain_deps or use_rust',
|
|
||||||
},
|
|
||||||
|
|
||||||
# We don't know target_cpu at deps time. At least until there's a universal
|
# We don't know target_cpu at deps time. At least until there's a universal
|
||||||
# binary of httpd-php, pull both intel and arm versions in DEPS and then pick
|
# binary of httpd-php, pull both intel and arm versions in DEPS and then pick
|
||||||
# the right one at runtime.
|
# the right one at runtime.
|
||||||
@ -631,7 +625,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/android_webview/tools/cts_archive',
|
'package': 'chromium/android_webview/tools/cts_archive',
|
||||||
'version': 'C4m9-gZKvvtS0-KQ9cMRi6wEfZH_TeWSiXEgsgtGtsMC',
|
'version': 'APYMYksv9eNAkU6osFvNXN38pMO1Q1kScjeecePr7NgC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
@ -654,7 +648,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/updater/chrome_mac_universal',
|
'package': 'chromium/third_party/updater/chrome_mac_universal',
|
||||||
'version': '1c74wqdugvZKRLfu6oY7wkYQ_VpIAObl_7TDwLQw8w4C',
|
'version': 'u1XGTm7703jO-Ax33P8j-x_KijOeHd36aBA6SO8V3a8C',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
@ -665,7 +659,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/updater/chrome_mac_universal_prod',
|
'package': 'chromium/third_party/updater/chrome_mac_universal_prod',
|
||||||
'version': 'aFiR8jLJBXsy6aYQhQp8cd9yBEmqa_cJZwx0ltJbKT4C',
|
'version': 'qDhUmRj82uhWqE2eVqt12e1eJKWKgRpRjgQrBSrdyP4C',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -676,7 +670,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/updater/chrome_win_x86',
|
'package': 'chromium/third_party/updater/chrome_win_x86',
|
||||||
'version': 'G5yIDMjjCL2TyjU-EmLubZkkb1sLM0XdZ5zB1XmviQkC',
|
'version': 'RmZn_R0BOPSbruD15DEq9pfu5IhhtjoJX6z-ufrWnD4C',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -687,7 +681,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/updater/chrome_win_x86_64',
|
'package': 'chromium/third_party/updater/chrome_win_x86_64',
|
||||||
'version': 'LHw1kjfI3H94qB22t7YsgnMQyXBBgxCgtub5F-GxSCEC',
|
'version': 'AAes70A2b8-CLhU1h9Sh1x2K-N3WjG7j2Tlp6VOgmnQC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -699,7 +693,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/updater/chromium_mac_amd64',
|
'package': 'chromium/third_party/updater/chromium_mac_amd64',
|
||||||
'version': 'Rd4fkayO0xqiXgM-WjFwSTh1YECDXF5ZfcSLW_odlz0C',
|
'version': '5ui7_fqpvI7a8omWqM8iyD0PZFPJpYKoMHkAb6xA_TkC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -711,7 +705,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/updater/chromium_mac_arm64',
|
'package': 'chromium/third_party/updater/chromium_mac_arm64',
|
||||||
'version': 'UoyUoEkFS37BkNrD1mNVfqdDlPujDLGwaGBdWz7bPakC',
|
'version': '0KnizXQ2_n_V3aEHR240LqMKw7b0-Pm9VBUmVuQh0cAC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -722,7 +716,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/updater/chromium_win_x86',
|
'package': 'chromium/third_party/updater/chromium_win_x86',
|
||||||
'version': 'Sl2g34_swdY9lIDQA6pTzPSTM5tec284DtwYekj9BIwC',
|
'version': 'g_24x4tVzQIoveectPGIXIGc2ptYDTnOodXieF_OG_4C',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@ -733,18 +727,18 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/updater/chromium_win_x86_64',
|
'package': 'chromium/third_party/updater/chromium_win_x86_64',
|
||||||
'version': 'vnZtwC2H42TkFgDMIYizwAUGFXTMOm00-yjnB6gnXigC',
|
'version': 's6U9lpJZsILIKkP5bCc_QqvJjPW2MwMWg5IoCBt_YEYC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
'src/chrome/test/data/autofill/captured_sites': {
|
'src/chrome/test/data/autofill/captured_sites/artifacts': {
|
||||||
'url': 'https://chrome-internal.googlesource.com/chrome/test/captured_sites/autofill.git' + '@' + '58a7920c173397b57d8d7be95cb93c2b43d02e26',
|
'url': 'https://chrome-internal.googlesource.com/chrome/test/captured_sites/autofill.git' + '@' + 'a38d810c87a18582e986b94650d9cfa4b67be12c',
|
||||||
'condition': 'checkout_chromium_autofill_test_dependencies',
|
'condition': 'checkout_chromium_autofill_test_dependencies',
|
||||||
},
|
},
|
||||||
|
|
||||||
'src/chrome/test/data/password/captured_sites': {
|
'src/chrome/test/data/password/captured_sites/artifacts': {
|
||||||
'url': 'https://chrome-internal.googlesource.com/chrome/test/captured_sites/password.git' + '@' + '93dfc8b7199a285a2ed832e607b0e68c5544273a',
|
'url': 'https://chrome-internal.googlesource.com/chrome/test/captured_sites/password.git' + '@' + '04b3ea663adf745c52831650e2426b54bc94e65d',
|
||||||
'condition': 'checkout_chromium_password_manager_test_dependencies',
|
'condition': 'checkout_chromium_password_manager_test_dependencies',
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -770,21 +764,21 @@ deps = {
|
|||||||
|
|
||||||
'src/clank': {
|
'src/clank': {
|
||||||
'url': 'https://chrome-internal.googlesource.com/clank/internal/apps.git' + '@' +
|
'url': 'https://chrome-internal.googlesource.com/clank/internal/apps.git' + '@' +
|
||||||
'7d4e93f3d1693f1dfe471527e93a8e729ce149a3',
|
'd83811f32343245218e742319cec89aaefb94657',
|
||||||
'condition': 'checkout_android and checkout_src_internal',
|
'condition': 'checkout_android and checkout_src_internal',
|
||||||
},
|
},
|
||||||
|
|
||||||
'src/docs/website': {
|
'src/docs/website': {
|
||||||
'url': Var('chromium_git') + '/website.git' + '@' + '7e351332addd1fca691bb524c976a56f17e3eb95',
|
'url': Var('chromium_git') + '/website.git' + '@' + '182a630499559e1403237d14e2bc6302d384ed39',
|
||||||
},
|
},
|
||||||
|
|
||||||
'src/ios/third_party/earl_grey2/src': {
|
'src/ios/third_party/earl_grey2/src': {
|
||||||
'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '99ba3b6ed7b8489899f06a0d602e84fc657e8338',
|
'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '8ac47627cb9ba09bf4bc3489b7aff5d77cd6eb88',
|
||||||
'condition': 'checkout_ios',
|
'condition': 'checkout_ios',
|
||||||
},
|
},
|
||||||
|
|
||||||
'src/ios/third_party/edo/src': {
|
'src/ios/third_party/edo/src': {
|
||||||
'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + 'd4d6f7da76f34b87b7b953176ef9e08eda83afb1',
|
'url': Var('chromium_git') + '/external/github.com/google/eDistantObject.git' + '@' + '51058a369f943064dc6db4f38dca32263d584ea5',
|
||||||
'condition': 'checkout_ios',
|
'condition': 'checkout_ios',
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -799,7 +793,7 @@ deps = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
'src/ios/third_party/material_components_ios/src': {
|
'src/ios/third_party/material_components_ios/src': {
|
||||||
'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '2cdac2db582f6067b014aa66a3846588352361a1',
|
'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'a407ef3ac3220882732e701804613c44704ebf78',
|
||||||
'condition': 'checkout_ios',
|
'condition': 'checkout_ios',
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -869,7 +863,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/rts/model/linux-amd64',
|
'package': 'chromium/rts/model/linux-amd64',
|
||||||
'version': 'bCwganuATTWjTe2ahjxynn8rnTuSw900jtLOYmi3kV4C',
|
'version': 'E7vzLhZk6xAJnnioidm0-d5a4cz1OxOr0LJUsCkKKJ0C',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'dep_type': 'cipd',
|
'dep_type': 'cipd',
|
||||||
@ -880,7 +874,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/rts/model/mac-amd64',
|
'package': 'chromium/rts/model/mac-amd64',
|
||||||
'version': 'ms15aJhiLzrF61zOZxq2jcESbsF3FFYtCS8R290t8JsC',
|
'version': '4wYh3p2y6ATe5OeiGmtl-G9thdrKGoX5DHzaP8V_tecC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'dep_type': 'cipd',
|
'dep_type': 'cipd',
|
||||||
@ -891,7 +885,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/rts/model/windows-amd64',
|
'package': 'chromium/rts/model/windows-amd64',
|
||||||
'version': 'xILgcx3FOZDE8fCy3EXmw76GOIrdmlVb3aQ5dUSq8x8C',
|
'version': 'E5Y3kcrVZt1PybXoGxTDRb_KmswZX_5jBphOaHwm2fQC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'dep_type': 'cipd',
|
'dep_type': 'cipd',
|
||||||
@ -959,7 +953,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/androidx',
|
'package': 'chromium/third_party/androidx',
|
||||||
'version': '8KUWsjmvRQJlzdaro14SgP8nok3-kHY2h00BEjXLJqQC',
|
'version': 'zEg6hTXAR6Mcqyfh8gHDzD9fmyy1xwz4swj6pkENIYsC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
@ -997,7 +991,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/android_build_tools/aapt2',
|
'package': 'chromium/third_party/android_build_tools/aapt2',
|
||||||
'version': 'cbNG7g8Sinh-lsT8hWsU-RyXqLT_uh4jIb1fjCdhrzIC',
|
'version': '36NqCian2RIwuM6SFfizdUgKoXyZhy3q6pFfsws0szYC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
@ -1019,7 +1013,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/android_build_tools/bundletool',
|
'package': 'chromium/third_party/android_build_tools/bundletool',
|
||||||
'version': 'XIPSJgFHEHN1ogOJqWVktlbl8PTfLZdNf_G2h4GcnrYC',
|
'version': 'TpDdbF-PPgwL0iOVsdLM07L-DUp2DV3hgzCMmPd2_GUC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
@ -1030,7 +1024,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/android_build_tools/lint',
|
'package': 'chromium/third_party/android_build_tools/lint',
|
||||||
'version': 'EPj7vnLteKz9kMQ6x4ZPaM5E20Bt4I0wTdrxdBpruZMC',
|
'version': 'MSpv-kFDDSPO0SY0dLdHegUJcJT1Yy8cL9r3vlAZ9vkC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
@ -1041,7 +1035,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/android_build_tools/manifest_merger',
|
'package': 'chromium/third_party/android_build_tools/manifest_merger',
|
||||||
'version': '5Zw4RYBL86koJro2O-jjcZYxOOdEW-hJDYykae8efQAC',
|
'version': 'EbRaK62t9grqlZqL-JTd_zwM4t1u9fm1x4c2rLE0cqQC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
@ -1075,6 +1069,10 @@ deps = {
|
|||||||
'package': 'chromium/third_party/android_sdk/public/platforms/android-33',
|
'package': 'chromium/third_party/android_sdk/public/platforms/android-33',
|
||||||
'version': Var('android_sdk_platforms_version'),
|
'version': Var('android_sdk_platforms_version'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'package': 'chromium/third_party/android_sdk/public/platforms/android-tiramisuprivacysandbox',
|
||||||
|
'version': Var('android_sdk_platforms_preview_version'),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/android_sdk/public/sources/android-31',
|
'package': 'chromium/third_party/android_sdk/public/sources/android-31',
|
||||||
'version': Var('android_sdk_sources_version'),
|
'version': Var('android_sdk_sources_version'),
|
||||||
@ -1122,7 +1120,7 @@ deps = {
|
|||||||
Var('boringssl_git') + '/boringssl.git' + '@' + Var('boringssl_revision'),
|
Var('boringssl_git') + '/boringssl.git' + '@' + Var('boringssl_revision'),
|
||||||
|
|
||||||
'src/third_party/breakpad/breakpad':
|
'src/third_party/breakpad/breakpad':
|
||||||
Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '79326ebe9446add03e76b4422ff8036e812224d2',
|
Var('chromium_git') + '/breakpad/breakpad.git' + '@' + 'abb105db21e962eda5b7d9b7a0ac8dd701e0b987',
|
||||||
|
|
||||||
'src/third_party/byte_buddy': {
|
'src/third_party/byte_buddy': {
|
||||||
'packages': [
|
'packages': [
|
||||||
@ -1147,7 +1145,7 @@ deps = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
'src/third_party/cast_core/public/src':
|
'src/third_party/cast_core/public/src':
|
||||||
Var('chromium_git') + '/cast_core/public' + '@' + 'f4628fda1b370eb238ae69545024d256ca62d719',
|
Var('chromium_git') + '/cast_core/public' + '@' + 'e42ef68aa05ac0c163805f60b9b19284f3c2dee3',
|
||||||
|
|
||||||
'src/third_party/catapult':
|
'src/third_party/catapult':
|
||||||
Var('chromium_git') + '/catapult.git' + '@' + Var('catapult_revision'),
|
Var('chromium_git') + '/catapult.git' + '@' + Var('catapult_revision'),
|
||||||
@ -1176,7 +1174,7 @@ deps = {
|
|||||||
# Tools used when building Chrome for Chrome OS. This affects both the Simple
|
# Tools used when building Chrome for Chrome OS. This affects both the Simple
|
||||||
# Chrome workflow, as well as the chromeos-chrome ebuild.
|
# Chrome workflow, as well as the chromeos-chrome ebuild.
|
||||||
'src/third_party/chromite': {
|
'src/third_party/chromite': {
|
||||||
'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd60807b98527df86e516532b8e2a62a1cb44c128',
|
'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '52efbfdc210624f1895d5994149f53c3a4457f29',
|
||||||
'condition': 'checkout_chromeos',
|
'condition': 'checkout_chromeos',
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1194,23 +1192,27 @@ deps = {
|
|||||||
|
|
||||||
# For Linux and Chromium OS.
|
# For Linux and Chromium OS.
|
||||||
'src/third_party/cros_system_api': {
|
'src/third_party/cros_system_api': {
|
||||||
'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'e0bfd3d75917adfa22e401805f9f9793cec82559',
|
'url': Var('chromium_git') + '/chromiumos/platform2/system_api.git' + '@' + 'ffb88930c81ef7f7026a2433c424d8b3658580d4',
|
||||||
'condition': 'checkout_linux',
|
'condition': 'checkout_linux',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'src/third_party/crossbench':
|
||||||
|
Var('chromium_git') + '/crossbench.git' + '@' + Var('crossbench_revision'),
|
||||||
|
|
||||||
|
|
||||||
'src/third_party/crubit/src': {
|
'src/third_party/crubit/src': {
|
||||||
'url': Var('chromium_git') + '/external/github.com/google/crubit.git' + '@' + Var('crubit_revision'),
|
'url': Var('chromium_git') + '/external/github.com/google/crubit.git' + '@' + Var('crubit_revision'),
|
||||||
'condition': 'checkout_crubit',
|
'condition': 'checkout_crubit',
|
||||||
},
|
},
|
||||||
|
|
||||||
'src/third_party/depot_tools':
|
'src/third_party/depot_tools':
|
||||||
Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'c023a6302fc665bae743a5833dea350fd3d0749f',
|
Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'a6898e71abf374d699ebaa121312e89bad8f100a',
|
||||||
|
|
||||||
'src/third_party/devtools-frontend/src':
|
'src/third_party/devtools-frontend/src':
|
||||||
Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
|
Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
|
||||||
|
|
||||||
'src/third_party/devtools-frontend-internal': {
|
'src/third_party/devtools-frontend-internal': {
|
||||||
'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + '4c3517346586ea020e5859cf51488e534a90d15e',
|
'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + '2ac32de43d557d678de46fb7cfc850187f3379fd',
|
||||||
'condition': 'checkout_src_internal',
|
'condition': 'checkout_src_internal',
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1218,7 +1220,7 @@ deps = {
|
|||||||
Var('chromium_git') + '/chromium/dom-distiller/dist.git' + '@' + '199de96b345ada7c6e7e6ba3d2fa7a6911b8767d',
|
Var('chromium_git') + '/chromium/dom-distiller/dist.git' + '@' + '199de96b345ada7c6e7e6ba3d2fa7a6911b8767d',
|
||||||
|
|
||||||
'src/third_party/eigen3/src':
|
'src/third_party/eigen3/src':
|
||||||
Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + '6156797016164b87b3e360e02d0e4107f7f66fbc',
|
Var('chromium_git') + '/external/gitlab.com/libeigen/eigen.git' + '@' + '3460f3558e7b469efb8a225894e21929c8c77629',
|
||||||
|
|
||||||
'src/third_party/emoji-metadata/src': {
|
'src/third_party/emoji-metadata/src': {
|
||||||
'url': Var('chromium_git') + '/external/github.com/googlefonts/emoji-metadata' + '@' + '045f146fca682a836e01cd265171312bfb300e06',
|
'url': Var('chromium_git') + '/external/github.com/googlefonts/emoji-metadata' + '@' + '045f146fca682a836e01cd265171312bfb300e06',
|
||||||
@ -1246,11 +1248,11 @@ deps = {
|
|||||||
Var('chromium_git') + '/chromium/deps/flac.git' + '@' + '689da3a7ed50af7448c3f1961d1791c7c1d9c85c',
|
Var('chromium_git') + '/chromium/deps/flac.git' + '@' + '689da3a7ed50af7448c3f1961d1791c7c1d9c85c',
|
||||||
|
|
||||||
'src/third_party/flatbuffers/src':
|
'src/third_party/flatbuffers/src':
|
||||||
Var('chromium_git') + '/external/github.com/google/flatbuffers.git' + '@' + 'b47ba1d5ffae3bd4d5eaad615e33d7cc5c1e3d4a',
|
Var('chromium_git') + '/external/github.com/google/flatbuffers.git' + '@' + 'a56f9ec50e908362e20254fcef28e62a2f148d91',
|
||||||
|
|
||||||
# Used for embedded builds. CrOS & Linux use the system version.
|
# Used for embedded builds. CrOS & Linux use the system version.
|
||||||
'src/third_party/fontconfig/src': {
|
'src/third_party/fontconfig/src': {
|
||||||
'url': Var('chromium_git') + '/external/fontconfig.git' + '@' + '452be8125f0e2a18a7dfef469e05d19374d36307',
|
'url': Var('chromium_git') + '/external/fontconfig.git' + '@' + '06929a556fdc39c8fe12965b69070c8df520a33e',
|
||||||
'condition': 'checkout_linux',
|
'condition': 'checkout_linux',
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1370,7 +1372,7 @@ deps = {
|
|||||||
Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + '41cdffd71c9948f63c7ad36e1fb0ff519aa7a37e',
|
Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + '41cdffd71c9948f63c7ad36e1fb0ff519aa7a37e',
|
||||||
|
|
||||||
'src/third_party/icu':
|
'src/third_party/icu':
|
||||||
Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '4e100720a20a471ca5ceff3b15a87596b694ada4',
|
Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'faf22e66ceafad90f5cafbd6707055c24646adcc',
|
||||||
|
|
||||||
'src/third_party/icu4j': {
|
'src/third_party/icu4j': {
|
||||||
'packages': [
|
'packages': [
|
||||||
@ -1433,11 +1435,22 @@ deps = {
|
|||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'src/third_party/kotlin_stdlib': {
|
||||||
|
'packages': [
|
||||||
|
{
|
||||||
|
'package': 'chromium/third_party/kotlin_stdlib',
|
||||||
|
'version': 'Mg7371mEUwDQH4_z29HdWqYWVlXN6t2dXX0kIutg_SwC',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'condition': 'checkout_android',
|
||||||
|
'dep_type': 'cipd',
|
||||||
|
},
|
||||||
|
|
||||||
'src/third_party/kotlinc/current': {
|
'src/third_party/kotlinc/current': {
|
||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/kotlinc',
|
'package': 'chromium/third_party/kotlinc',
|
||||||
'version': 'F-v9Yy4tNQtjGB7TtAWc2J-3qhx9Q6ixZJyuGixVH08C',
|
'version': 'bCZedwoM-hb1pP1QKzA3P5aR4zjZltqLj4JQpmQsHuUC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
@ -1450,11 +1463,14 @@ deps = {
|
|||||||
'src/third_party/libFuzzer/src':
|
'src/third_party/libFuzzer/src':
|
||||||
Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git' + '@' + Var('libfuzzer_revision'),
|
Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git' + '@' + Var('libfuzzer_revision'),
|
||||||
|
|
||||||
|
'src/third_party/centipede/src':
|
||||||
|
Var('chromium_git') + '/external/github.com/google/centipede.git' + '@' + Var('centipede_revision'),
|
||||||
|
|
||||||
'src/third_party/libaddressinput/src':
|
'src/third_party/libaddressinput/src':
|
||||||
Var('chromium_git') + '/external/libaddressinput.git' + '@' + 'e8712e415627f22d0b00ebee8db99547077f39bd',
|
Var('chromium_git') + '/external/libaddressinput.git' + '@' + 'e8712e415627f22d0b00ebee8db99547077f39bd',
|
||||||
|
|
||||||
'src/third_party/libaom/source/libaom':
|
'src/third_party/libaom/source/libaom':
|
||||||
Var('aomedia_git') + '/aom.git' + '@' + '74d61ae86f20bc9fb707347bfe618425024f3865',
|
Var('aomedia_git') + '/aom.git' + '@' + '70b12695e1967d9589dd15b345a039e575e8f429',
|
||||||
|
|
||||||
'src/third_party/libavif/src':
|
'src/third_party/libavif/src':
|
||||||
Var('chromium_git') + '/external/github.com/AOMediaCodec/libavif.git' + '@' + Var('libavif_revision'),
|
Var('chromium_git') + '/external/github.com/AOMediaCodec/libavif.git' + '@' + Var('libavif_revision'),
|
||||||
@ -1487,7 +1503,7 @@ deps = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
'src/third_party/libjpeg_turbo':
|
'src/third_party/libjpeg_turbo':
|
||||||
Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + 'ed683925e4897a84b3bffc5c1414c85b97a129a3',
|
Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + '0b6e6a152242c2fa30ffb29633d1b7d7b229b46b',
|
||||||
|
|
||||||
'src/third_party/liblouis/src': {
|
'src/third_party/liblouis/src': {
|
||||||
'url': Var('chromium_git') + '/external/liblouis-github.git' + '@' + '9700847afb92cb35969bdfcbbfbbb74b9c7b3376',
|
'url': Var('chromium_git') + '/external/liblouis-github.git' + '@' + '9700847afb92cb35969bdfcbbfbbb74b9c7b3376',
|
||||||
@ -1515,16 +1531,16 @@ deps = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
'src/third_party/libvpx/source/libvpx':
|
'src/third_party/libvpx/source/libvpx':
|
||||||
Var('chromium_git') + '/webm/libvpx.git' + '@' + 'b7c22b3a9584d7d9c0a7b9b37a52bc595113b398',
|
Var('chromium_git') + '/webm/libvpx.git' + '@' + 'db69ce6aea278bee88668fd9cc2af2e544516fdb',
|
||||||
|
|
||||||
'src/third_party/libwebm/source':
|
'src/third_party/libwebm/source':
|
||||||
Var('chromium_git') + '/webm/libwebm.git' + '@' + 'e4fbea0c9751ae8aa86629b197a28d8276a2b0da',
|
Var('chromium_git') + '/webm/libwebm.git' + '@' + 'e4fbea0c9751ae8aa86629b197a28d8276a2b0da',
|
||||||
|
|
||||||
'src/third_party/libwebp/src':
|
'src/third_party/libwebp/src':
|
||||||
Var('chromium_git') + '/webm/libwebp.git' + '@' + '603e8d7adb0ccc35237419c2938194623b60e9be',
|
Var('chromium_git') + '/webm/libwebp.git' + '@' + 'fd7b5d48464475408d32d2611bdb6947d4246b97',
|
||||||
|
|
||||||
'src/third_party/libyuv':
|
'src/third_party/libyuv':
|
||||||
Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '6e4b0acb4b3d5858c77a044aad46132998ac4a76',
|
Var('chromium_git') + '/libyuv/libyuv.git' + '@' + '2bdc210be9eb11ded16bf3ef1f6cadb0d4dcb0c2',
|
||||||
|
|
||||||
'src/third_party/lighttpd': {
|
'src/third_party/lighttpd': {
|
||||||
'url': Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'),
|
'url': Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'),
|
||||||
@ -1651,7 +1667,7 @@ deps = {
|
|||||||
Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + 'db956674bbdfbaab5acdd3fdb4117c2fef5527e9',
|
Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + 'db956674bbdfbaab5acdd3fdb4117c2fef5527e9',
|
||||||
|
|
||||||
'src/third_party/openscreen/src':
|
'src/third_party/openscreen/src':
|
||||||
Var('chromium_git') + '/openscreen' + '@' + 'eca304d29cee3f9d045fd0dd36f147a91a367c75',
|
Var('chromium_git') + '/openscreen' + '@' + '5d694418bc76f66463f06ce141c375062b0ba3b0',
|
||||||
|
|
||||||
'src/third_party/openxr/src': {
|
'src/third_party/openxr/src': {
|
||||||
'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + 'bf21ccb1007bb531b45d9978919a56ea5059c245',
|
'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + 'bf21ccb1007bb531b45d9978919a56ea5059c245',
|
||||||
@ -1668,7 +1684,7 @@ deps = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
'src/third_party/perfetto':
|
'src/third_party/perfetto':
|
||||||
Var('android_git') + '/platform/external/perfetto.git' + '@' + '3aa2acd9af48d097ad94cf778c2228031e6c4dfa',
|
Var('android_git') + '/platform/external/perfetto.git' + '@' + '4bda78645d1d23a98473b793bc532a3ebff6c7f9',
|
||||||
|
|
||||||
'src/third_party/perl': {
|
'src/third_party/perl': {
|
||||||
'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
|
'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
|
||||||
@ -1702,13 +1718,13 @@ deps = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
'src/third_party/re2/src':
|
'src/third_party/re2/src':
|
||||||
Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '8afcf7fcc481692197e33612446d69e8f5777c54',
|
Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '3a8436ac436124a57a4e22d5c8713a2d42b381d7',
|
||||||
|
|
||||||
'src/third_party/r8': {
|
'src/third_party/r8': {
|
||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/r8',
|
'package': 'chromium/third_party/r8',
|
||||||
'version': 'lhnuNLpWpWBVM6efX0iIg5i9ztfW8VKpMvkyfWCxfr0C',
|
'version': 'HGbnG0_a1HHQtwgKBlFRLuC0-AVyYhHpcTol560MvlUC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
@ -1722,7 +1738,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/r8',
|
'package': 'chromium/third_party/r8',
|
||||||
'version': 'qGtBu6TtxyR5XNy4cmsslb7c946YtkZF5_QCjVP-wc8C',
|
'version': 'PwglNZFRNPkBBXdnY9NfrZFk2ULWDTRxhV9rl2kvkpUC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
@ -1746,7 +1762,7 @@ deps = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
'src/third_party/ruy/src':
|
'src/third_party/ruy/src':
|
||||||
Var('chromium_git') + '/external/github.com/google/ruy.git' + '@' + '3168a5c8f4c447fd8cea94078121ee2e2cd87df0',
|
Var('chromium_git') + '/external/github.com/google/ruy.git' + '@' + '21a85fef159f9942f636a43b14c64b481c2a05b2',
|
||||||
|
|
||||||
'src/third_party/skia':
|
'src/third_party/skia':
|
||||||
Var('skia_git') + '/skia.git' + '@' + Var('skia_revision'),
|
Var('skia_git') + '/skia.git' + '@' + Var('skia_revision'),
|
||||||
@ -1758,7 +1774,7 @@ deps = {
|
|||||||
Var('chromium_git') + '/external/github.com/google/snappy.git' + '@' + '65dc7b383985eb4f63cd3e752136db8d9b4be8c0',
|
Var('chromium_git') + '/external/github.com/google/snappy.git' + '@' + '65dc7b383985eb4f63cd3e752136db8d9b4be8c0',
|
||||||
|
|
||||||
'src/third_party/sqlite/src':
|
'src/third_party/sqlite/src':
|
||||||
Var('chromium_git') + '/chromium/deps/sqlite.git' + '@' + '469aae8118e18b7354607f8ef09780cf8f3e54aa',
|
Var('chromium_git') + '/chromium/deps/sqlite.git' + '@' + '88742a54683bcdec9a0d0c14462621da8b6f841e',
|
||||||
|
|
||||||
'src/third_party/sqlite4java': {
|
'src/third_party/sqlite4java': {
|
||||||
'packages': [
|
'packages': [
|
||||||
@ -1800,20 +1816,20 @@ deps = {
|
|||||||
Var('chromium_git') + '/external/github.com/GoogleChromeLabs/text-fragments-polyfill.git' + '@' + 'c036420683f672d685e27415de0a5f5e85bdc23f',
|
Var('chromium_git') + '/external/github.com/GoogleChromeLabs/text-fragments-polyfill.git' + '@' + 'c036420683f672d685e27415de0a5f5e85bdc23f',
|
||||||
|
|
||||||
'src/third_party/tflite/src':
|
'src/third_party/tflite/src':
|
||||||
Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + 'ef70dc999eee784e3f505e89c798f8b9cc894e52',
|
Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + '60ec371de65a63d588bcfce7a99482847ad1312e',
|
||||||
|
|
||||||
'src/third_party/turbine': {
|
'src/third_party/turbine': {
|
||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/turbine',
|
'package': 'chromium/third_party/turbine',
|
||||||
'version': 't0TeGgk2CZr3B0HtEqBb60BSRwVPRJm9066izhJwzz0C',
|
'version': 'YQC-btuan_DTe9V9dv_e1LxgYSWeOoDfrd-VSqzIvHkC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
'dep_type': 'cipd',
|
'dep_type': 'cipd',
|
||||||
},
|
},
|
||||||
|
|
||||||
'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@243deb3abd84f442957dc5394745d25482ff791b',
|
'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@3c1556cc73226c2895c1de9a925dc5fe623c8752',
|
||||||
|
|
||||||
'src/third_party/vulkan_memory_allocator':
|
'src/third_party/vulkan_memory_allocator':
|
||||||
Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907',
|
Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907',
|
||||||
@ -1850,10 +1866,10 @@ deps = {
|
|||||||
Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'd1b65aa5a88f6efd900604dfcda840154e9f16e2',
|
Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'd1b65aa5a88f6efd900604dfcda840154e9f16e2',
|
||||||
|
|
||||||
'src/third_party/webgpu-cts/src':
|
'src/third_party/webgpu-cts/src':
|
||||||
Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'a7e54e7b964d08901cba6418ca00ffec501bc867',
|
Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '6c8361e98f1daba65902f5e2fc1297893ac14b67',
|
||||||
|
|
||||||
'src/third_party/webrtc':
|
'src/third_party/webrtc':
|
||||||
Var('webrtc_git') + '/src.git' + '@' + 'b6b9b1fc761c039195faa033cb8fdde4ed8ba0a9',
|
Var('webrtc_git') + '/src.git' + '@' + 'd75b9e9ff07ee42841b4e416629c9fbd4b058905',
|
||||||
|
|
||||||
# Wuffs' canonical repository is at github.com/google/wuffs, but we use
|
# Wuffs' canonical repository is at github.com/google/wuffs, but we use
|
||||||
# Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file.
|
# Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file.
|
||||||
@ -1871,7 +1887,7 @@ deps = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
'src/third_party/xnnpack/src':
|
'src/third_party/xnnpack/src':
|
||||||
Var('chromium_git') + '/external/github.com/google/XNNPACK.git' + '@' + 'a50369c0fdd15f0f35b1a91c964644327a88d480',
|
Var('chromium_git') + '/external/github.com/google/XNNPACK.git' + '@' + '659147817805d17c7be2d60bd7bbca7e780f9c82',
|
||||||
|
|
||||||
'src/tools/page_cycler/acid3':
|
'src/tools/page_cycler/acid3':
|
||||||
Var('chromium_git') + '/chromium/deps/acid3.git' + '@' + '6be0a66a1ebd7ebc5abc1b2f405a945f6d871521',
|
Var('chromium_git') + '/chromium/deps/acid3.git' + '@' + '6be0a66a1ebd7ebc5abc1b2f405a945f6d871521',
|
||||||
@ -1880,7 +1896,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'skia/tools/goldctl/linux-amd64',
|
'package': 'skia/tools/goldctl/linux-amd64',
|
||||||
'version': 'PZOpm-VdLUuaVE8seo910YRCnqv7Y2BkPcrmUs13RMAC',
|
'version': '-G9gUusEGDPsbf_GULdyJo9DYyeNBuqD8gHfdxCvIbYC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'dep_type': 'cipd',
|
'dep_type': 'cipd',
|
||||||
@ -1890,7 +1906,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'skia/tools/goldctl/windows-amd64',
|
'package': 'skia/tools/goldctl/windows-amd64',
|
||||||
'version': 'qp3u_bn43vFlG3HHG61Co9eOeo52m6SWIw099mHqt9EC',
|
'version': 'BZ0EL-KSkwCzJciJf9MbwmZAJPRhlKOp0LEYiTV6lWIC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'dep_type': 'cipd',
|
'dep_type': 'cipd',
|
||||||
@ -1901,7 +1917,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'skia/tools/goldctl/mac-amd64',
|
'package': 'skia/tools/goldctl/mac-amd64',
|
||||||
'version': 'aZ8KYJUPYrRq4f7-Td3nt0et_16S06A0vovOn2c85tIC',
|
'version': '0GVvuvDBNt6KJ7UzxBRUW5ShTWCliifyzaCkudNzmrkC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'dep_type': 'cipd',
|
'dep_type': 'cipd',
|
||||||
@ -1912,7 +1928,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'skia/tools/goldctl/mac-arm64',
|
'package': 'skia/tools/goldctl/mac-arm64',
|
||||||
'version': 'JtcfJFsvsUuaaIajqvwETn8j5hxOSC_YLDszV96Ukn8C',
|
'version': '8vKG1ZGA0f7asv5AHh_7yBxVD2h-I-yR2oY4TOjwo6kC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'dep_type': 'cipd',
|
'dep_type': 'cipd',
|
||||||
@ -1923,7 +1939,7 @@ deps = {
|
|||||||
Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'),
|
Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'),
|
||||||
|
|
||||||
'src-internal': {
|
'src-internal': {
|
||||||
'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f1d52b8c1ec0769ac006917d1fe42e99a4dba6c3',
|
'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@67c8cac0a84ad86b64ecf3f4af23a928fb605313',
|
||||||
'condition': 'checkout_src_internal',
|
'condition': 'checkout_src_internal',
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1942,7 +1958,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromeos_internal/apps/eche_app/app',
|
'package': 'chromeos_internal/apps/eche_app/app',
|
||||||
'version': 'Y9Vb3-WAI0IRjTRTVDtPP86MNNpZItvfey3JuYZXXeYC',
|
'version': 'WyNqAPOj-HR5fZBbkHIXf7YeyCvf0GpXuhdv6EqzNJsC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_chromeos and checkout_src_internal',
|
'condition': 'checkout_chromeos and checkout_src_internal',
|
||||||
@ -1953,7 +1969,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromeos_internal/apps/help_app/app',
|
'package': 'chromeos_internal/apps/help_app/app',
|
||||||
'version': 'J19Uq07iO__IsduQFotOfHNdiRWoyIQc4UgK1HpMFU8C',
|
'version': 'hF_ZkOgJWb6Tl-9h6WAmpF4VcZggBH4rjoP_hBr2ddUC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_chromeos and checkout_src_internal',
|
'condition': 'checkout_chromeos and checkout_src_internal',
|
||||||
@ -1964,7 +1980,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromeos_internal/apps/media_app/app',
|
'package': 'chromeos_internal/apps/media_app/app',
|
||||||
'version': 'CHpgn1-7IChFiK96I1-giMbXe-Cl9XQiwH3aHwCGzYwC',
|
'version': 'EXosTZG9iiyjnqmWKjS04Tf9dvSUjbHqqhGv1SQW0ycC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_chromeos and checkout_src_internal',
|
'condition': 'checkout_chromeos and checkout_src_internal',
|
||||||
@ -1975,7 +1991,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromeos_internal/apps/projector_app/app',
|
'package': 'chromeos_internal/apps/projector_app/app',
|
||||||
'version': 'ufJ9DwqTBE76l81FUQQ2JOIG1ely5QRDFuwz3ccJIRIC',
|
'version': 'zmInwk2DIsJlzZbF9Fw29hmN6rQTpzqIgzzMAgwl2PkC',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_chromeos and checkout_src_internal',
|
'condition': 'checkout_chromeos and checkout_src_internal',
|
||||||
@ -1994,7 +2010,7 @@ deps = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
'src/third_party/android_prebuilts/build_tools': {
|
'src/third_party/android_prebuilts/build_tools': {
|
||||||
'url': Var('android_git') + '/platform/prebuilts/build-tools.git' + '@' + '5794e96eb8bae47bb48feee915d99583573b3887',
|
'url': Var('android_git') + '/platform/prebuilts/build-tools.git' + '@' + '673c20b524a83b662d8c1057fd3eec8fd0f93f9d',
|
||||||
'condition': 'checkout_android_prebuilts_build_tools',
|
'condition': 'checkout_android_prebuilts_build_tools',
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -2569,7 +2585,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_basement',
|
'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_basement',
|
||||||
'version': 'version:2@18.0.1.cr1',
|
'version': 'version:2@18.1.0.cr1',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
@ -2723,7 +2739,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_tasks',
|
'package': 'chromium/third_party/android_deps/libs/com_google_android_gms_play_services_tasks',
|
||||||
'version': 'version:2@18.0.1.cr1',
|
'version': 'version:2@18.0.2.cr1',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
@ -2763,11 +2779,22 @@ deps = {
|
|||||||
'dep_type': 'cipd',
|
'dep_type': 'cipd',
|
||||||
},
|
},
|
||||||
|
|
||||||
'src/third_party/android_deps/libs/com_google_android_play_core': {
|
'src/third_party/android_deps/libs/com_google_android_play_core_common': {
|
||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/android_deps/libs/com_google_android_play_core',
|
'package': 'chromium/third_party/android_deps/libs/com_google_android_play_core_common',
|
||||||
'version': 'version:2@1.10.0.cr1',
|
'version': 'version:2@2.0.2.cr1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'condition': 'checkout_android',
|
||||||
|
'dep_type': 'cipd',
|
||||||
|
},
|
||||||
|
|
||||||
|
'src/third_party/android_deps/libs/com_google_android_play_feature_delivery': {
|
||||||
|
'packages': [
|
||||||
|
{
|
||||||
|
'package': 'chromium/third_party/android_deps/libs/com_google_android_play_feature_delivery',
|
||||||
|
'version': 'version:2@2.0.1.cr1',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
@ -3328,7 +3355,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/android_deps/libs/net_bytebuddy_byte_buddy',
|
'package': 'chromium/third_party/android_deps/libs/net_bytebuddy_byte_buddy',
|
||||||
'version': 'version:2@1.12.13.cr1',
|
'version': 'version:2@1.12.22.cr1',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
@ -3339,7 +3366,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/android_deps/libs/net_bytebuddy_byte_buddy_agent',
|
'package': 'chromium/third_party/android_deps/libs/net_bytebuddy_byte_buddy_agent',
|
||||||
'version': 'version:2@1.12.13.cr1',
|
'version': 'version:2@1.12.22.cr1',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
@ -3478,39 +3505,6 @@ deps = {
|
|||||||
'dep_type': 'cipd',
|
'dep_type': 'cipd',
|
||||||
},
|
},
|
||||||
|
|
||||||
'src/third_party/android_deps/libs/org_jetbrains_annotations': {
|
|
||||||
'packages': [
|
|
||||||
{
|
|
||||||
'package': 'chromium/third_party/android_deps/libs/org_jetbrains_annotations',
|
|
||||||
'version': 'version:2@13.0.cr1',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'condition': 'checkout_android',
|
|
||||||
'dep_type': 'cipd',
|
|
||||||
},
|
|
||||||
|
|
||||||
'src/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib': {
|
|
||||||
'packages': [
|
|
||||||
{
|
|
||||||
'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib',
|
|
||||||
'version': 'version:2@1.8.0.cr1',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'condition': 'checkout_android',
|
|
||||||
'dep_type': 'cipd',
|
|
||||||
},
|
|
||||||
|
|
||||||
'src/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common': {
|
|
||||||
'packages': [
|
|
||||||
{
|
|
||||||
'package': 'chromium/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_common',
|
|
||||||
'version': 'version:2@1.8.0.cr1',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'condition': 'checkout_android',
|
|
||||||
'dep_type': 'cipd',
|
|
||||||
},
|
|
||||||
|
|
||||||
'src/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_jdk7': {
|
'src/third_party/android_deps/libs/org_jetbrains_kotlin_kotlin_stdlib_jdk7': {
|
||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
@ -3581,7 +3575,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/android_deps/libs/org_mockito_mockito_core',
|
'package': 'chromium/third_party/android_deps/libs/org_mockito_mockito_core',
|
||||||
'version': 'version:2@4.7.0.cr1',
|
'version': 'version:2@5.1.1.cr1',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
@ -3592,7 +3586,7 @@ deps = {
|
|||||||
'packages': [
|
'packages': [
|
||||||
{
|
{
|
||||||
'package': 'chromium/third_party/android_deps/libs/org_objenesis_objenesis',
|
'package': 'chromium/third_party/android_deps/libs/org_objenesis_objenesis',
|
||||||
'version': 'version:2@3.2.cr1',
|
'version': 'version:2@3.3.cr1',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
'condition': 'checkout_android',
|
'condition': 'checkout_android',
|
||||||
@ -3876,16 +3870,26 @@ include_rules = [
|
|||||||
'+third_party/icu/source/i18n/unicode',
|
'+third_party/icu/source/i18n/unicode',
|
||||||
'+url',
|
'+url',
|
||||||
|
|
||||||
# Abseil features are allowlisted explicitly. See
|
# Abseil is allowed by default, but some features are banned. See
|
||||||
# //styleguide/c++/c++-features.md.
|
# //styleguide/c++/c++-features.md.
|
||||||
'-absl',
|
'+third_party/abseil-cpp',
|
||||||
'-third_party/abseil-cpp',
|
'-third_party/abseil-cpp/absl/algorithm/container.h',
|
||||||
'+third_party/abseil-cpp/absl/base/attributes.h',
|
'-third_party/abseil-cpp/absl/container',
|
||||||
'+third_party/abseil-cpp/absl/cleanup/cleanup.h',
|
'-third_party/abseil-cpp/absl/crc',
|
||||||
'+third_party/abseil-cpp/absl/numeric/int128.h',
|
'-third_party/abseil-cpp/absl/flags',
|
||||||
'+third_party/abseil-cpp/absl/types/optional.h',
|
'-third_party/abseil-cpp/absl/functional/any_invocable.h',
|
||||||
'+third_party/abseil-cpp/absl/types/variant.h',
|
'-third_party/abseil-cpp/absl/functional/bind_front.h',
|
||||||
'+third_party/abseil-cpp/absl/utility/utility.h',
|
'-third_party/abseil-cpp/absl/functional/function_ref.h',
|
||||||
|
'-third_party/abseil-cpp/absl/hash',
|
||||||
|
'-third_party/abseil-cpp/absl/log',
|
||||||
|
'-third_party/abseil-cpp/absl/random',
|
||||||
|
'-third_party/abseil-cpp/absl/status/statusor.h',
|
||||||
|
'-third_party/abseil-cpp/absl/strings',
|
||||||
|
'+third_party/abseil-cpp/absl/strings/cord.h',
|
||||||
|
'-third_party/abseil-cpp/absl/synchronization',
|
||||||
|
'-third_party/abseil-cpp/absl/time',
|
||||||
|
'-third_party/abseil-cpp/absl/types/any.h',
|
||||||
|
'-third_party/abseil-cpp/absl/types/span.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@ -4353,30 +4357,6 @@ hooks = [
|
|||||||
'-s', 'src/third_party/instrumented_libraries/binaries/msan-no-origins-focal.tgz.sha1',
|
'-s', 'src/third_party/instrumented_libraries/binaries/msan-no-origins-focal.tgz.sha1',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
'name': 'msan_chained_origins_xenial',
|
|
||||||
'pattern': '.',
|
|
||||||
'condition': 'checkout_instrumented_libraries',
|
|
||||||
'action': [ 'python3',
|
|
||||||
'src/third_party/depot_tools/download_from_google_storage.py',
|
|
||||||
'--no_resume',
|
|
||||||
'--no_auth',
|
|
||||||
'--bucket', 'chromium-instrumented-libraries',
|
|
||||||
'-s', 'src/third_party/instrumented_libraries/binaries/msan-chained-origins-xenial.tgz.sha1',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'name': 'msan_no_origins_xenial',
|
|
||||||
'pattern': '.',
|
|
||||||
'condition': 'checkout_instrumented_libraries',
|
|
||||||
'action': [ 'python3',
|
|
||||||
'src/third_party/depot_tools/download_from_google_storage.py',
|
|
||||||
'--no_resume',
|
|
||||||
'--no_auth',
|
|
||||||
'--bucket', 'chromium-instrumented-libraries',
|
|
||||||
'-s', 'src/third_party/instrumented_libraries/binaries/msan-no-origins-xenial.tgz.sha1',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
'name': 'wasm_fuzzer',
|
'name': 'wasm_fuzzer',
|
||||||
'pattern': '.',
|
'pattern': '.',
|
||||||
@ -4572,7 +4552,7 @@ hooks = [
|
|||||||
{
|
{
|
||||||
'name': 'Fetch Android AFDO profile',
|
'name': 'Fetch Android AFDO profile',
|
||||||
'pattern': '.',
|
'pattern': '.',
|
||||||
'condition': 'checkout_android or checkout_linux',
|
'condition': 'checkout_android',
|
||||||
'action': [ 'python3',
|
'action': [ 'python3',
|
||||||
'src/tools/download_optimization_profile.py',
|
'src/tools/download_optimization_profile.py',
|
||||||
'--newest_state=src/chrome/android/profiles/newest.txt',
|
'--newest_state=src/chrome/android/profiles/newest.txt',
|
||||||
@ -4581,6 +4561,18 @@ hooks = [
|
|||||||
'--gs_url_base=chromeos-prebuilt/afdo-job/llvm',
|
'--gs_url_base=chromeos-prebuilt/afdo-job/llvm',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'name': 'Fetch Android Arm AFDO profile',
|
||||||
|
'pattern': '.',
|
||||||
|
'condition': 'checkout_android',
|
||||||
|
'action': [ 'python3',
|
||||||
|
'src/tools/download_optimization_profile.py',
|
||||||
|
'--newest_state=src/chrome/android/profiles/arm.newest.txt',
|
||||||
|
'--local_state=src/chrome/android/profiles/arm.local.txt',
|
||||||
|
'--output_name=src/chrome/android/profiles/arm.afdo.prof',
|
||||||
|
'--gs_url_base=chromeos-prebuilt/afdo-job/llvm',
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
'name': 'gvr_static_shim_android',
|
'name': 'gvr_static_shim_android',
|
||||||
'pattern': '\\.sha1',
|
'pattern': '\\.sha1',
|
||||||
|
1181
src/base/BUILD.gn
1181
src/base/BUILD.gn
File diff suppressed because it is too large
Load Diff
@ -207,7 +207,7 @@ AllocatorDispatch g_allocator_dispatch = {&AllocFn,
|
|||||||
} // namespace base::allocator::dispatcher::allocator_shim_details
|
} // namespace base::allocator::dispatcher::allocator_shim_details
|
||||||
#endif // BUILDFLAG(USE_ALLOCATOR_SHIM)
|
#endif // BUILDFLAG(USE_ALLOCATOR_SHIM)
|
||||||
|
|
||||||
#if BUILDFLAG(USE_PARTITION_ALLOC) && !BUILDFLAG(IS_NACL)
|
#if BUILDFLAG(USE_PARTITION_ALLOC)
|
||||||
namespace base::allocator::dispatcher::partition_allocator_details {
|
namespace base::allocator::dispatcher::partition_allocator_details {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -222,7 +222,7 @@ void PartitionFreeHook(void* address) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace base::allocator::dispatcher::partition_allocator_details
|
} // namespace base::allocator::dispatcher::partition_allocator_details
|
||||||
#endif // BUILDFLAG(USE_PARTITION_ALLOC) && !BUILDFLAG(IS_NACL)
|
#endif // BUILDFLAG(USE_PARTITION_ALLOC)
|
||||||
|
|
||||||
namespace base::allocator::dispatcher {
|
namespace base::allocator::dispatcher {
|
||||||
|
|
||||||
@ -236,11 +236,11 @@ void InstallStandardAllocatorHooks() {
|
|||||||
// happen for tests.
|
// happen for tests.
|
||||||
#endif // BUILDFLAG(USE_ALLOCATOR_SHIM)
|
#endif // BUILDFLAG(USE_ALLOCATOR_SHIM)
|
||||||
|
|
||||||
#if BUILDFLAG(USE_PARTITION_ALLOC) && !BUILDFLAG(IS_NACL)
|
#if BUILDFLAG(USE_PARTITION_ALLOC)
|
||||||
partition_alloc::PartitionAllocHooks::SetObserverHooks(
|
partition_alloc::PartitionAllocHooks::SetObserverHooks(
|
||||||
&partition_allocator_details::PartitionAllocHook,
|
&partition_allocator_details::PartitionAllocHook,
|
||||||
&partition_allocator_details::PartitionFreeHook);
|
&partition_allocator_details::PartitionFreeHook);
|
||||||
#endif // BUILDFLAG(USE_PARTITION_ALLOC) && !BUILDFLAG(IS_NACL)
|
#endif // BUILDFLAG(USE_PARTITION_ALLOC)
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace base::allocator::dispatcher
|
} // namespace base::allocator::dispatcher
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include "base/check.h"
|
#include "base/check.h"
|
||||||
#include "base/compiler_specific.h"
|
#include "base/compiler_specific.h"
|
||||||
|
#include "base/debug/crash_logging.h"
|
||||||
|
#include "base/strings/string_number_conversions.h"
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
|
||||||
#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_ANDROID)
|
#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_ANDROID)
|
||||||
@ -15,15 +17,25 @@
|
|||||||
namespace base::allocator::dispatcher {
|
namespace base::allocator::dispatcher {
|
||||||
|
|
||||||
#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_ANDROID)
|
#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_ANDROID)
|
||||||
pthread_key_t ReentryGuard::entered_key_ = 0;
|
// pthread_key_t has different signedness on Mac and Android. Store the null
|
||||||
|
// value in a strongly-typed constant to avoid "comparison of integers of
|
||||||
|
// different signs" warnings when comparing with 0.
|
||||||
|
constexpr pthread_key_t kNullKey = 0;
|
||||||
|
|
||||||
|
pthread_key_t ReentryGuard::entered_key_ = kNullKey;
|
||||||
|
|
||||||
void ReentryGuard::InitTLSSlot() {
|
void ReentryGuard::InitTLSSlot() {
|
||||||
if (entered_key_ == 0) {
|
if (entered_key_ == kNullKey) {
|
||||||
int error = pthread_key_create(&entered_key_, nullptr);
|
int error = pthread_key_create(&entered_key_, nullptr);
|
||||||
CHECK(!error);
|
CHECK(!error);
|
||||||
|
// Touch the TLS slot immediately to force any allocations.
|
||||||
|
// TODO(https://crbug.com/1411454): Use this technique to avoid allocations
|
||||||
|
// in PoissonAllocationSampler::ScopedMuteThreadSamples, which will make
|
||||||
|
// ReentryGuard redundant.
|
||||||
|
pthread_setspecific(entered_key_, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
DCHECK(entered_key_ != 0);
|
DCHECK_NE(entered_key_, kNullKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -31,4 +43,19 @@ void ReentryGuard::InitTLSSlot() {
|
|||||||
void ReentryGuard::InitTLSSlot() {}
|
void ReentryGuard::InitTLSSlot() {}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void ReentryGuard::RecordTLSSlotToCrashKey() {
|
||||||
|
// Record the key in crash dumps to detect when it's higher than 32
|
||||||
|
// (PTHREAD_KEY_2NDLEVEL_SIZE).
|
||||||
|
// TODO(crbug.com/1411454): Remove this after diagnosing reentry crashes.
|
||||||
|
static auto* const crash_key = base::debug::AllocateCrashKeyString(
|
||||||
|
"reentry_guard_tls_slot", base::debug::CrashKeySize::Size32);
|
||||||
|
|
||||||
|
#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_ANDROID)
|
||||||
|
base::debug::SetCrashKeyString(crash_key, base::NumberToString(entered_key_));
|
||||||
|
#else
|
||||||
|
base::debug::SetCrashKeyString(crash_key, "unused");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace base::allocator::dispatcher
|
} // namespace base::allocator::dispatcher
|
||||||
|
@ -23,8 +23,10 @@ namespace base::allocator::dispatcher {
|
|||||||
// twice. The scoped guard allows us to detect that.
|
// twice. The scoped guard allows us to detect that.
|
||||||
//
|
//
|
||||||
// Besides that the implementations of thread_local on macOS and Android
|
// Besides that the implementations of thread_local on macOS and Android
|
||||||
// seem to allocate memory lazily on the first access to thread_local variables.
|
// seem to allocate memory lazily on the first access to thread_local variables
|
||||||
// Make use of pthread TLS instead of C++ thread_local there.
|
// (and on Android at least thread_local is implemented on top of pthread so is
|
||||||
|
// strictly worse for performance). Make use of pthread TLS instead of C++
|
||||||
|
// thread_local there.
|
||||||
struct BASE_EXPORT ReentryGuard {
|
struct BASE_EXPORT ReentryGuard {
|
||||||
ReentryGuard() : allowed_(!pthread_getspecific(entered_key_)) {
|
ReentryGuard() : allowed_(!pthread_getspecific(entered_key_)) {
|
||||||
pthread_setspecific(entered_key_, reinterpret_cast<void*>(true));
|
pthread_setspecific(entered_key_, reinterpret_cast<void*>(true));
|
||||||
@ -37,12 +39,19 @@ struct BASE_EXPORT ReentryGuard {
|
|||||||
|
|
||||||
explicit operator bool() const noexcept { return allowed_; }
|
explicit operator bool() const noexcept { return allowed_; }
|
||||||
|
|
||||||
// This function must be called in very early of the process start-up in
|
// This function must be called before installing any allocator hooks because
|
||||||
// order to acquire a low TLS slot number because glibc TLS implementation
|
// some TLS implementations may allocate (eg. glibc will require a malloc call
|
||||||
// will require a malloc call to allocate storage for a higher slot number
|
// to allocate storage for a higher slot number (>= PTHREAD_KEY_2NDLEVEL_SIZE
|
||||||
// (>= PTHREAD_KEY_2NDLEVEL_SIZE == 32). c.f. heap_profiling::InitTLSSlot.
|
// == 32). This touches the thread-local storage so that any malloc happens
|
||||||
|
// before installing the hooks.
|
||||||
static void InitTLSSlot();
|
static void InitTLSSlot();
|
||||||
|
|
||||||
|
// InitTLSSlot() is called before crash keys are available. At some point
|
||||||
|
// after SetCrashKeyImplementation() is called, this function should be
|
||||||
|
// called to record `entered_key_` to a crash key for debugging. This may
|
||||||
|
// allocate so it must not be called from inside an allocator hook.
|
||||||
|
static void RecordTLSSlotToCrashKey();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static pthread_key_t entered_key_;
|
static pthread_key_t entered_key_;
|
||||||
const bool allowed_;
|
const bool allowed_;
|
||||||
@ -56,6 +65,7 @@ struct [[maybe_unused]] BASE_EXPORT ReentryGuard {
|
|||||||
constexpr explicit operator bool() const noexcept { return true; }
|
constexpr explicit operator bool() const noexcept { return true; }
|
||||||
|
|
||||||
static void InitTLSSlot();
|
static void InitTLSSlot();
|
||||||
|
static void RecordTLSSlotToCrashKey();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,10 +32,16 @@ const base::FeatureParam<UnretainedDanglingPtrMode>
|
|||||||
|
|
||||||
BASE_FEATURE(kPartitionAllocDanglingPtr,
|
BASE_FEATURE(kPartitionAllocDanglingPtr,
|
||||||
"PartitionAllocDanglingPtr",
|
"PartitionAllocDanglingPtr",
|
||||||
FEATURE_DISABLED_BY_DEFAULT);
|
#if BUILDFLAG(ENABLE_DANGLING_RAW_PTR_FEATURE_FLAGS_FOR_BOTS)
|
||||||
|
FEATURE_ENABLED_BY_DEFAULT
|
||||||
|
#else
|
||||||
|
FEATURE_DISABLED_BY_DEFAULT
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
constexpr FeatureParam<DanglingPtrMode>::Option kDanglingPtrModeOption[] = {
|
constexpr FeatureParam<DanglingPtrMode>::Option kDanglingPtrModeOption[] = {
|
||||||
{DanglingPtrMode::kCrash, "crash"},
|
{DanglingPtrMode::kCrash, "crash"},
|
||||||
{DanglingPtrMode::kLogSignature, "log_signature"},
|
{DanglingPtrMode::kLogOnly, "log_only"},
|
||||||
};
|
};
|
||||||
const base::FeatureParam<DanglingPtrMode> kDanglingPtrModeParam{
|
const base::FeatureParam<DanglingPtrMode> kDanglingPtrModeParam{
|
||||||
&kPartitionAllocDanglingPtr,
|
&kPartitionAllocDanglingPtr,
|
||||||
@ -43,14 +49,24 @@ const base::FeatureParam<DanglingPtrMode> kDanglingPtrModeParam{
|
|||||||
DanglingPtrMode::kCrash,
|
DanglingPtrMode::kCrash,
|
||||||
&kDanglingPtrModeOption,
|
&kDanglingPtrModeOption,
|
||||||
};
|
};
|
||||||
|
constexpr FeatureParam<DanglingPtrType>::Option kDanglingPtrTypeOption[] = {
|
||||||
|
{DanglingPtrType::kAll, "all"},
|
||||||
|
{DanglingPtrType::kCrossTask, "cross_task"},
|
||||||
|
};
|
||||||
|
const base::FeatureParam<DanglingPtrType> kDanglingPtrTypeParam{
|
||||||
|
&kPartitionAllocDanglingPtr,
|
||||||
|
"type",
|
||||||
|
DanglingPtrType::kAll,
|
||||||
|
&kDanglingPtrTypeOption,
|
||||||
|
};
|
||||||
|
|
||||||
#if PA_CONFIG(ALLOW_PCSCAN)
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
// If enabled, PCScan is turned on by default for all partitions that don't
|
// If enabled, PCScan is turned on by default for all partitions that don't
|
||||||
// disable it explicitly.
|
// disable it explicitly.
|
||||||
BASE_FEATURE(kPartitionAllocPCScan,
|
BASE_FEATURE(kPartitionAllocPCScan,
|
||||||
"PartitionAllocPCScan",
|
"PartitionAllocPCScan",
|
||||||
FEATURE_DISABLED_BY_DEFAULT);
|
FEATURE_DISABLED_BY_DEFAULT);
|
||||||
#endif // PA_CONFIG(ALLOW_PCSCAN)
|
#endif // BUILDFLAG(USE_STARSCAN)
|
||||||
|
|
||||||
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
||||||
// If enabled, PCScan is turned on only for the browser's malloc partition.
|
// If enabled, PCScan is turned on only for the browser's malloc partition.
|
||||||
@ -88,7 +104,8 @@ BASE_FEATURE(kPartitionAllocLargeEmptySlotSpanRing,
|
|||||||
|
|
||||||
BASE_FEATURE(kPartitionAllocBackupRefPtr,
|
BASE_FEATURE(kPartitionAllocBackupRefPtr,
|
||||||
"PartitionAllocBackupRefPtr",
|
"PartitionAllocBackupRefPtr",
|
||||||
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) || \
|
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN) || \
|
||||||
|
BUILDFLAG(ENABLE_DANGLING_RAW_PTR_FEATURE_FLAGS_FOR_BOTS) || \
|
||||||
(BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) && BUILDFLAG(IS_LINUX))
|
(BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) && BUILDFLAG(IS_LINUX))
|
||||||
FEATURE_ENABLED_BY_DEFAULT
|
FEATURE_ENABLED_BY_DEFAULT
|
||||||
#else
|
#else
|
||||||
@ -183,11 +200,11 @@ BASE_FEATURE(kPartitionAllocPCScanEagerClearing,
|
|||||||
// In addition to heap, scan also the stack of the current mutator.
|
// In addition to heap, scan also the stack of the current mutator.
|
||||||
BASE_FEATURE(kPartitionAllocPCScanStackScanning,
|
BASE_FEATURE(kPartitionAllocPCScanStackScanning,
|
||||||
"PartitionAllocPCScanStackScanning",
|
"PartitionAllocPCScanStackScanning",
|
||||||
#if defined(PA_PCSCAN_STACK_SUPPORTED)
|
#if BUILDFLAG(PCSCAN_STACK_SUPPORTED)
|
||||||
FEATURE_ENABLED_BY_DEFAULT
|
FEATURE_ENABLED_BY_DEFAULT
|
||||||
#else
|
#else
|
||||||
FEATURE_DISABLED_BY_DEFAULT
|
FEATURE_DISABLED_BY_DEFAULT
|
||||||
#endif // defined(PA_PCSCAN_STACK_SUPPORTED)
|
#endif // BUILDFLAG(PCSCAN_STACK_SUPPORTED)
|
||||||
);
|
);
|
||||||
|
|
||||||
BASE_FEATURE(kPartitionAllocDCScan,
|
BASE_FEATURE(kPartitionAllocDCScan,
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#define BASE_ALLOCATOR_PARTITION_ALLOC_FEATURES_H_
|
#define BASE_ALLOCATOR_PARTITION_ALLOC_FEATURES_H_
|
||||||
|
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
|
||||||
#include "base/base_export.h"
|
#include "base/base_export.h"
|
||||||
#include "base/compiler_specific.h"
|
#include "base/compiler_specific.h"
|
||||||
#include "base/feature_list.h"
|
#include "base/feature_list.h"
|
||||||
@ -25,10 +24,6 @@ extern const BASE_EXPORT base::FeatureParam<UnretainedDanglingPtrMode>
|
|||||||
kUnretainedDanglingPtrModeParam;
|
kUnretainedDanglingPtrModeParam;
|
||||||
|
|
||||||
// See /docs/dangling_ptr.md
|
// See /docs/dangling_ptr.md
|
||||||
//
|
|
||||||
// Usage:
|
|
||||||
// --enable-features=PartitionAllocDanglingPtr:mode/crash
|
|
||||||
// --enable-features=PartitionAllocDanglingPtr:mode/log_signature
|
|
||||||
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocDanglingPtr);
|
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocDanglingPtr);
|
||||||
enum class DanglingPtrMode {
|
enum class DanglingPtrMode {
|
||||||
// Crash immediately after detecting a dangling raw_ptr.
|
// Crash immediately after detecting a dangling raw_ptr.
|
||||||
@ -36,19 +31,33 @@ enum class DanglingPtrMode {
|
|||||||
|
|
||||||
// Log the signature of every occurrences without crashing. It is used by
|
// Log the signature of every occurrences without crashing. It is used by
|
||||||
// bots.
|
// bots.
|
||||||
// Format "[DanglingSignature]\t<1>\t<2>"
|
// Format "[DanglingSignature]\t<1>\t<2>\t<3>\t<4>"
|
||||||
// 1. The function who freed the memory while it was still referenced.
|
// 1. The function which freed the memory while it was still referenced.
|
||||||
// 2. The function who released the raw_ptr reference.
|
// 2. The task in which the memory was freed.
|
||||||
kLogSignature,
|
// 3. The function which released the raw_ptr reference.
|
||||||
|
// 4. The task in which the raw_ptr was released.
|
||||||
|
kLogOnly,
|
||||||
|
|
||||||
// Note: This will be extended with a single shot DumpWithoutCrashing.
|
// Note: This will be extended with a single shot DumpWithoutCrashing.
|
||||||
};
|
};
|
||||||
extern const BASE_EXPORT base::FeatureParam<DanglingPtrMode>
|
extern const BASE_EXPORT base::FeatureParam<DanglingPtrMode>
|
||||||
kDanglingPtrModeParam;
|
kDanglingPtrModeParam;
|
||||||
|
enum class DanglingPtrType {
|
||||||
|
// Act on any dangling raw_ptr released after being freed.
|
||||||
|
kAll, // (default)
|
||||||
|
|
||||||
#if PA_CONFIG(ALLOW_PCSCAN)
|
// Detect when freeing memory and releasing the dangling raw_ptr happens in
|
||||||
|
// a different task. Those are more likely to cause use after free.
|
||||||
|
kCrossTask,
|
||||||
|
|
||||||
|
// Note: This will be extended with LongLived
|
||||||
|
};
|
||||||
|
extern const BASE_EXPORT base::FeatureParam<DanglingPtrType>
|
||||||
|
kDanglingPtrTypeParam;
|
||||||
|
|
||||||
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocPCScan);
|
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocPCScan);
|
||||||
#endif // PA_CONFIG(ALLOW_PCSCAN)
|
#endif
|
||||||
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
||||||
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocPCScanBrowserOnly);
|
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocPCScanBrowserOnly);
|
||||||
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocPCScanRendererOnly);
|
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocPCScanRendererOnly);
|
||||||
|
@ -48,14 +48,14 @@
|
|||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||||
|
|
||||||
#if PA_CONFIG(ALLOW_PCSCAN)
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
#include "base/allocator/partition_allocator/starscan/pcscan.h"
|
#include "base/allocator/partition_allocator/starscan/pcscan.h"
|
||||||
#include "base/allocator/partition_allocator/starscan/pcscan_scheduling.h"
|
#include "base/allocator/partition_allocator/starscan/pcscan_scheduling.h"
|
||||||
#include "base/allocator/partition_allocator/starscan/stack/stack.h"
|
#include "base/allocator/partition_allocator/starscan/stack/stack.h"
|
||||||
#include "base/allocator/partition_allocator/starscan/stats_collector.h"
|
#include "base/allocator/partition_allocator/starscan/stats_collector.h"
|
||||||
#include "base/allocator/partition_allocator/starscan/stats_reporter.h"
|
#include "base/allocator/partition_allocator/starscan/stats_reporter.h"
|
||||||
#include "base/memory/nonscannable_memory.h"
|
#include "base/memory/nonscannable_memory.h"
|
||||||
#endif // PA_CONFIG(ALLOW_PCSCAN)
|
#endif // BUILDFLAG(USE_STARSCAN)
|
||||||
|
|
||||||
#if BUILDFLAG(IS_ANDROID)
|
#if BUILDFLAG(IS_ANDROID)
|
||||||
#include "base/system/sys_info.h"
|
#include "base/system/sys_info.h"
|
||||||
@ -74,13 +74,13 @@ namespace {
|
|||||||
namespace switches {
|
namespace switches {
|
||||||
[[maybe_unused]] constexpr char kRendererProcess[] = "renderer";
|
[[maybe_unused]] constexpr char kRendererProcess[] = "renderer";
|
||||||
constexpr char kZygoteProcess[] = "zygote";
|
constexpr char kZygoteProcess[] = "zygote";
|
||||||
#if PA_CONFIG(ALLOW_PCSCAN)
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
constexpr char kGpuProcess[] = "gpu-process";
|
constexpr char kGpuProcess[] = "gpu-process";
|
||||||
constexpr char kUtilityProcess[] = "utility";
|
constexpr char kUtilityProcess[] = "utility";
|
||||||
#endif
|
#endif
|
||||||
} // namespace switches
|
} // namespace switches
|
||||||
|
|
||||||
#if PA_CONFIG(ALLOW_PCSCAN)
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
|
|
||||||
#if BUILDFLAG(ENABLE_BASE_TRACING)
|
#if BUILDFLAG(ENABLE_BASE_TRACING)
|
||||||
constexpr const char* ScannerIdToTracingString(
|
constexpr const char* ScannerIdToTracingString(
|
||||||
@ -181,11 +181,11 @@ class StatsReporterImpl final : public partition_alloc::StatsReporter {
|
|||||||
static constexpr char kTraceCategory[] = "partition_alloc";
|
static constexpr char kTraceCategory[] = "partition_alloc";
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PA_CONFIG(ALLOW_PCSCAN)
|
#endif // BUILDFLAG(USE_STARSCAN)
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#if PA_CONFIG(ALLOW_PCSCAN)
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
void RegisterPCScanStatsReporter() {
|
void RegisterPCScanStatsReporter() {
|
||||||
static StatsReporterImpl s_reporter;
|
static StatsReporterImpl s_reporter;
|
||||||
static bool registered = false;
|
static bool registered = false;
|
||||||
@ -195,7 +195,7 @@ void RegisterPCScanStatsReporter() {
|
|||||||
partition_alloc::internal::PCScan::RegisterStatsReporter(&s_reporter);
|
partition_alloc::internal::PCScan::RegisterStatsReporter(&s_reporter);
|
||||||
registered = true;
|
registered = true;
|
||||||
}
|
}
|
||||||
#endif // PA_CONFIG(ALLOW_PCSCAN)
|
#endif // BUILDFLAG(USE_STARSCAN)
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -302,7 +302,7 @@ std::map<std::string, std::string> ProposeSyntheticFinchTrials() {
|
|||||||
}
|
}
|
||||||
#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
||||||
[[maybe_unused]] bool pcscan_enabled =
|
[[maybe_unused]] bool pcscan_enabled =
|
||||||
#if PA_CONFIG(ALLOW_PCSCAN)
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
FeatureList::IsEnabled(features::kPartitionAllocPCScanBrowserOnly);
|
FeatureList::IsEnabled(features::kPartitionAllocPCScanBrowserOnly);
|
||||||
#else
|
#else
|
||||||
false;
|
false;
|
||||||
@ -378,7 +378,7 @@ std::map<std::string, std::string> ProposeSyntheticFinchTrials() {
|
|||||||
// fully controlled by Finch and thus have identical population sizes.
|
// fully controlled by Finch and thus have identical population sizes.
|
||||||
std::string pcscan_group_name = "Unavailable";
|
std::string pcscan_group_name = "Unavailable";
|
||||||
std::string pcscan_group_name_fallback = "Unavailable";
|
std::string pcscan_group_name_fallback = "Unavailable";
|
||||||
#if PA_CONFIG(ALLOW_PCSCAN)
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
if (brp_truly_enabled) {
|
if (brp_truly_enabled) {
|
||||||
// If BRP protection is enabled, just ignore the population. Check
|
// If BRP protection is enabled, just ignore the population. Check
|
||||||
// brp_truly_enabled, not brp_finch_enabled, because there are certain modes
|
// brp_truly_enabled, not brp_finch_enabled, because there are certain modes
|
||||||
@ -395,7 +395,7 @@ std::map<std::string, std::string> ProposeSyntheticFinchTrials() {
|
|||||||
} else {
|
} else {
|
||||||
pcscan_group_name_fallback = (pcscan_enabled ? "Enabled" : "Disabled");
|
pcscan_group_name_fallback = (pcscan_enabled ? "Enabled" : "Disabled");
|
||||||
}
|
}
|
||||||
#endif // PA_CONFIG(ALLOW_PCSCAN)
|
#endif // BUILDFLAG(USE_STARSCAN)
|
||||||
trials.emplace("PCScan_Effective", pcscan_group_name);
|
trials.emplace("PCScan_Effective", pcscan_group_name);
|
||||||
trials.emplace("PCScan_Effective_Fallback", pcscan_group_name_fallback);
|
trials.emplace("PCScan_Effective_Fallback", pcscan_group_name_fallback);
|
||||||
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
||||||
@ -415,11 +415,13 @@ namespace {
|
|||||||
|
|
||||||
internal::PartitionLock g_stack_trace_buffer_lock;
|
internal::PartitionLock g_stack_trace_buffer_lock;
|
||||||
|
|
||||||
struct StackTraceWithID {
|
struct DanglingPointerFreeInfo {
|
||||||
debug::StackTrace stack_trace;
|
debug::StackTrace stack_trace;
|
||||||
|
debug::TaskTrace task_trace;
|
||||||
uintptr_t id = 0;
|
uintptr_t id = 0;
|
||||||
};
|
};
|
||||||
using DanglingRawPtrBuffer = std::array<absl::optional<StackTraceWithID>, 32>;
|
using DanglingRawPtrBuffer =
|
||||||
|
std::array<absl::optional<DanglingPointerFreeInfo>, 32>;
|
||||||
DanglingRawPtrBuffer g_stack_trace_buffer GUARDED_BY(g_stack_trace_buffer_lock);
|
DanglingRawPtrBuffer g_stack_trace_buffer GUARDED_BY(g_stack_trace_buffer_lock);
|
||||||
|
|
||||||
void DanglingRawPtrDetected(uintptr_t id) {
|
void DanglingRawPtrDetected(uintptr_t id) {
|
||||||
@ -428,14 +430,14 @@ void DanglingRawPtrDetected(uintptr_t id) {
|
|||||||
internal::PartitionAutoLock guard(g_stack_trace_buffer_lock);
|
internal::PartitionAutoLock guard(g_stack_trace_buffer_lock);
|
||||||
|
|
||||||
#if DCHECK_IS_ON()
|
#if DCHECK_IS_ON()
|
||||||
for (absl::optional<StackTraceWithID>& entry : g_stack_trace_buffer) {
|
for (absl::optional<DanglingPointerFreeInfo>& entry : g_stack_trace_buffer) {
|
||||||
PA_DCHECK(!entry || entry->id != id);
|
PA_DCHECK(!entry || entry->id != id);
|
||||||
}
|
}
|
||||||
#endif // DCHECK_IS_ON()
|
#endif // DCHECK_IS_ON()
|
||||||
|
|
||||||
for (absl::optional<StackTraceWithID>& entry : g_stack_trace_buffer) {
|
for (absl::optional<DanglingPointerFreeInfo>& entry : g_stack_trace_buffer) {
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
entry = {debug::StackTrace(), id};
|
entry = {debug::StackTrace(), debug::TaskTrace(), id};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -444,15 +446,16 @@ void DanglingRawPtrDetected(uintptr_t id) {
|
|||||||
// enough.
|
// enough.
|
||||||
}
|
}
|
||||||
|
|
||||||
// From the StackTrace recorded in |DanglingRawPtrDetected|, extract the one
|
// From the traces recorded in |DanglingRawPtrDetected|, extract the one
|
||||||
// whose id match |id|. Return nullopt if not found.
|
// whose id match |id|. Return nullopt if not found.
|
||||||
absl::optional<debug::StackTrace> TakeStackTrace(uintptr_t id) {
|
absl::optional<DanglingPointerFreeInfo> TakeDanglingPointerFreeInfo(
|
||||||
|
uintptr_t id) {
|
||||||
internal::PartitionAutoLock guard(g_stack_trace_buffer_lock);
|
internal::PartitionAutoLock guard(g_stack_trace_buffer_lock);
|
||||||
for (absl::optional<StackTraceWithID>& entry : g_stack_trace_buffer) {
|
for (absl::optional<DanglingPointerFreeInfo>& entry : g_stack_trace_buffer) {
|
||||||
if (entry && entry->id == id) {
|
if (entry && entry->id == id) {
|
||||||
debug::StackTrace stack_trace = std::move(entry->stack_trace);
|
absl::optional<DanglingPointerFreeInfo> result(entry);
|
||||||
entry = absl::nullopt;
|
entry = absl::nullopt;
|
||||||
return stack_trace;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return absl::nullopt;
|
return absl::nullopt;
|
||||||
@ -463,14 +466,31 @@ absl::optional<debug::StackTrace> TakeStackTrace(uintptr_t id) {
|
|||||||
// are all the dangling raw_ptr occurrences in a table.
|
// are all the dangling raw_ptr occurrences in a table.
|
||||||
std::string ExtractDanglingPtrSignature(std::string stacktrace) {
|
std::string ExtractDanglingPtrSignature(std::string stacktrace) {
|
||||||
std::vector<StringPiece> lines = SplitStringPiece(
|
std::vector<StringPiece> lines = SplitStringPiece(
|
||||||
stacktrace, "\r\n", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
|
stacktrace, "\r\n", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY);
|
||||||
|
|
||||||
// We are looking for the callers of the function releasing the raw_ptr and
|
// We are looking for the callers of the function releasing the raw_ptr and
|
||||||
// freeing memory:
|
// freeing memory:
|
||||||
const StringPiece callees[] = {
|
const StringPiece callees[] = {
|
||||||
|
// Common signatures
|
||||||
|
"internal::PartitionFree",
|
||||||
|
"base::(anonymous namespace)::FreeFn",
|
||||||
|
|
||||||
|
// Linux signatures
|
||||||
"internal::RawPtrBackupRefImpl<>::ReleaseInternal()",
|
"internal::RawPtrBackupRefImpl<>::ReleaseInternal()",
|
||||||
"internal::PartitionFree()",
|
"base::RefCountedThreadSafe<>::Release()",
|
||||||
"base::(anonymous namespace)::FreeFn()",
|
|
||||||
|
// Windows signatures
|
||||||
|
"internal::RawPtrBackupRefImpl<0>::ReleaseInternal",
|
||||||
|
"_free_base",
|
||||||
|
// Windows stack traces are prefixed with "Backtrace:"
|
||||||
|
"Backtrace:",
|
||||||
|
|
||||||
|
// Mac signatures
|
||||||
|
"internal::RawPtrBackupRefImpl<false>::ReleaseInternal",
|
||||||
|
|
||||||
|
// Task traces are prefixed with "Task trace:" in
|
||||||
|
// |TaskTrace::OutputToStream|
|
||||||
|
"Task trace:",
|
||||||
};
|
};
|
||||||
size_t caller_index = 0;
|
size_t caller_index = 0;
|
||||||
for (size_t i = 0; i < lines.size(); ++i) {
|
for (size_t i = 0; i < lines.size(); ++i) {
|
||||||
@ -481,78 +501,142 @@ std::string ExtractDanglingPtrSignature(std::string stacktrace) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (caller_index >= lines.size()) {
|
if (caller_index >= lines.size()) {
|
||||||
return "undefined";
|
return "no_callee_match";
|
||||||
}
|
}
|
||||||
StringPiece caller = lines[caller_index];
|
StringPiece caller = lines[caller_index];
|
||||||
|
|
||||||
// |callers| follows the following format:
|
if (caller.empty()) {
|
||||||
|
return "invalid_format";
|
||||||
|
}
|
||||||
|
|
||||||
|
// On Posix platforms |callers| follows the following format:
|
||||||
//
|
//
|
||||||
// #4 0x56051fe3404b content::GeneratedCodeCache::DidCreateBackend()
|
// #<index> <address> <symbol>
|
||||||
// -- -------------- -----------------------------------------------
|
//
|
||||||
// Depth Address Function
|
// See https://crsrc.org/c/base/debug/stack_trace_posix.cc
|
||||||
|
if (caller[0] == '#') {
|
||||||
|
const size_t address_start = caller.find(' ');
|
||||||
|
const size_t function_start = caller.find(' ', address_start + 1);
|
||||||
|
|
||||||
size_t address_start = caller.find(' ');
|
if (address_start == caller.npos || function_start == caller.npos) {
|
||||||
size_t function_start = caller.find(' ', address_start + 1);
|
return "invalid_format";
|
||||||
|
}
|
||||||
|
|
||||||
if (address_start == caller.npos || function_start == caller.npos) {
|
return std::string(caller.substr(function_start + 1));
|
||||||
return "undefined";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::string(caller.substr(function_start + 1));
|
// On Windows platforms |callers| follows the following format:
|
||||||
}
|
//
|
||||||
|
// \t<symbol> [0x<address>]+<displacement>(<filename>:<line>)
|
||||||
void DanglingRawPtrReleasedLogSignature(uintptr_t id) {
|
//
|
||||||
// This is called from raw_ptr<>'s release operation. Making allocations is
|
// See https://crsrc.org/c/base/debug/stack_trace_win.cc
|
||||||
// allowed. In particular, symbolizing and printing the StackTraces may
|
if (caller[0] == '\t') {
|
||||||
// allocate memory.
|
const size_t symbol_start = 1;
|
||||||
|
const size_t symbol_end = caller.find(' ');
|
||||||
debug::StackTrace stack_trace_release;
|
if (symbol_end == caller.npos) {
|
||||||
absl::optional<debug::StackTrace> stack_trace_free = TakeStackTrace(id);
|
return "invalid_format";
|
||||||
|
}
|
||||||
if (stack_trace_free) {
|
return std::string(caller.substr(symbol_start, symbol_end - symbol_start));
|
||||||
LOG(ERROR) << StringPrintf(
|
|
||||||
"[DanglingSignature]\t%s\t%s",
|
|
||||||
ExtractDanglingPtrSignature(stack_trace_release.ToString()).c_str(),
|
|
||||||
ExtractDanglingPtrSignature(stack_trace_free->ToString()).c_str());
|
|
||||||
} else {
|
|
||||||
LOG(ERROR) << StringPrintf(
|
|
||||||
"[DanglingSignature]\t%s\tmissing-stacktrace",
|
|
||||||
ExtractDanglingPtrSignature(stack_trace_release.ToString()).c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// On Mac platforms |callers| follows the following format:
|
||||||
|
//
|
||||||
|
// <index> <library> 0x<address> <symbol> + <line>
|
||||||
|
//
|
||||||
|
// See https://crsrc.org/c/base/debug/stack_trace_posix.cc
|
||||||
|
if (caller[0] >= '0' && caller[0] <= '9') {
|
||||||
|
const size_t address_start = caller.find("0x");
|
||||||
|
const size_t symbol_start = caller.find(' ', address_start + 1) + 1;
|
||||||
|
const size_t symbol_end = caller.find(' ', symbol_start);
|
||||||
|
if (symbol_start == caller.npos || symbol_end == caller.npos) {
|
||||||
|
return "invalid_format";
|
||||||
|
}
|
||||||
|
return std::string(caller.substr(symbol_start, symbol_end - symbol_start));
|
||||||
|
}
|
||||||
|
|
||||||
|
return "invalid_format";
|
||||||
}
|
}
|
||||||
|
|
||||||
void DanglingRawPtrReleasedCrash(uintptr_t id) {
|
std::string ExtractDanglingPtrSignature(debug::TaskTrace task_trace) {
|
||||||
|
if (task_trace.empty()) {
|
||||||
|
return "No active task";
|
||||||
|
}
|
||||||
|
return ExtractDanglingPtrSignature(task_trace.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ExtractDanglingPtrSignature(
|
||||||
|
absl::optional<DanglingPointerFreeInfo> free_info,
|
||||||
|
debug::StackTrace release_stack_trace,
|
||||||
|
debug::TaskTrace release_task_trace) {
|
||||||
|
if (free_info) {
|
||||||
|
return StringPrintf(
|
||||||
|
"[DanglingSignature]\t%s\t%s\t%s\t%s",
|
||||||
|
ExtractDanglingPtrSignature(free_info->stack_trace.ToString()).c_str(),
|
||||||
|
ExtractDanglingPtrSignature(free_info->task_trace).c_str(),
|
||||||
|
ExtractDanglingPtrSignature(release_stack_trace.ToString()).c_str(),
|
||||||
|
ExtractDanglingPtrSignature(release_task_trace).c_str());
|
||||||
|
}
|
||||||
|
return StringPrintf(
|
||||||
|
"[DanglingSignature]\t%s\t%s\t%s\t%s", "missing", "missing",
|
||||||
|
ExtractDanglingPtrSignature(release_stack_trace.ToString()).c_str(),
|
||||||
|
ExtractDanglingPtrSignature(release_task_trace).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <features::DanglingPtrMode dangling_pointer_mode,
|
||||||
|
features::DanglingPtrType dangling_pointer_type>
|
||||||
|
void DanglingRawPtrReleased(uintptr_t id) {
|
||||||
// This is called from raw_ptr<>'s release operation. Making allocations is
|
// This is called from raw_ptr<>'s release operation. Making allocations is
|
||||||
// allowed. In particular, symbolizing and printing the StackTraces may
|
// allowed. In particular, symbolizing and printing the StackTraces may
|
||||||
// allocate memory.
|
// allocate memory.
|
||||||
debug::StackTrace stack_trace_release;
|
debug::StackTrace stack_trace_release;
|
||||||
debug::TaskTrace task_trace_release;
|
debug::TaskTrace task_trace_release;
|
||||||
absl::optional<debug::StackTrace> stack_trace_free = TakeStackTrace(id);
|
absl::optional<DanglingPointerFreeInfo> free_info =
|
||||||
|
TakeDanglingPointerFreeInfo(id);
|
||||||
|
|
||||||
|
if constexpr (dangling_pointer_type ==
|
||||||
|
features::DanglingPtrType::kCrossTask) {
|
||||||
|
if (!free_info) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (task_trace_release.ToString() == free_info->task_trace.ToString()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string dangling_signature = ExtractDanglingPtrSignature(
|
||||||
|
free_info, stack_trace_release, task_trace_release);
|
||||||
static const char dangling_ptr_footer[] =
|
static const char dangling_ptr_footer[] =
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Please check for more information on:\n"
|
"Please check for more information on:\n"
|
||||||
"https://chromium.googlesource.com/chromium/src/+/main/docs/"
|
"https://chromium.googlesource.com/chromium/src/+/main/docs/"
|
||||||
"dangling_ptr_guide.md\n";
|
"dangling_ptr_guide.md\n"
|
||||||
|
"\n"
|
||||||
if (stack_trace_free) {
|
"Googlers: Please give us your feedback about the dangling pointer\n"
|
||||||
|
" detector at:\n"
|
||||||
|
" http://go/dangling-ptr-cq-survey\n";
|
||||||
|
if (free_info) {
|
||||||
LOG(ERROR) << "Detected dangling raw_ptr with id="
|
LOG(ERROR) << "Detected dangling raw_ptr with id="
|
||||||
<< StringPrintf("0x%016" PRIxPTR, id) << ":\n\n"
|
<< StringPrintf("0x%016" PRIxPTR, id) << ":\n"
|
||||||
|
<< dangling_signature << "\n\n"
|
||||||
<< "The memory was freed at:\n"
|
<< "The memory was freed at:\n"
|
||||||
<< *stack_trace_free << "\n"
|
<< free_info->stack_trace << free_info->task_trace << "\n"
|
||||||
<< "The dangling raw_ptr was released at:\n"
|
<< "The dangling raw_ptr was released at:\n"
|
||||||
<< stack_trace_release << task_trace_release
|
<< stack_trace_release << task_trace_release
|
||||||
<< dangling_ptr_footer;
|
<< dangling_ptr_footer;
|
||||||
} else {
|
} else {
|
||||||
LOG(ERROR) << "Detected dangling raw_ptr with id="
|
LOG(ERROR) << "Detected dangling raw_ptr with id="
|
||||||
<< StringPrintf("0x%016" PRIxPTR, id) << ":\n\n"
|
<< StringPrintf("0x%016" PRIxPTR, id) << ":\n\n"
|
||||||
|
<< dangling_signature << "\n\n"
|
||||||
<< "It was not recorded where the memory was freed.\n\n"
|
<< "It was not recorded where the memory was freed.\n\n"
|
||||||
<< "The dangling raw_ptr was released at:\n"
|
<< "The dangling raw_ptr was released at:\n"
|
||||||
<< stack_trace_release << task_trace_release
|
<< stack_trace_release << task_trace_release
|
||||||
<< dangling_ptr_footer;
|
<< dangling_ptr_footer;
|
||||||
}
|
}
|
||||||
ImmediateCrash();
|
|
||||||
|
if constexpr (dangling_pointer_mode == features::DanglingPtrMode::kCrash) {
|
||||||
|
ImmediateCrash();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClearDanglingRawPtrBuffer() {
|
void ClearDanglingRawPtrBuffer() {
|
||||||
@ -573,16 +657,35 @@ void InstallDanglingRawPtrChecks() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
partition_alloc::SetDanglingRawPtrDetectedFn(&DanglingRawPtrDetected);
|
||||||
switch (features::kDanglingPtrModeParam.Get()) {
|
switch (features::kDanglingPtrModeParam.Get()) {
|
||||||
case features::DanglingPtrMode::kCrash:
|
case features::DanglingPtrMode::kCrash:
|
||||||
partition_alloc::SetDanglingRawPtrDetectedFn(DanglingRawPtrDetected);
|
switch (features::kDanglingPtrTypeParam.Get()) {
|
||||||
partition_alloc::SetDanglingRawPtrReleasedFn(DanglingRawPtrReleasedCrash);
|
case features::DanglingPtrType::kAll:
|
||||||
|
partition_alloc::SetDanglingRawPtrReleasedFn(
|
||||||
|
&DanglingRawPtrReleased<features::DanglingPtrMode::kCrash,
|
||||||
|
features::DanglingPtrType::kAll>);
|
||||||
|
break;
|
||||||
|
case features::DanglingPtrType::kCrossTask:
|
||||||
|
partition_alloc::SetDanglingRawPtrReleasedFn(
|
||||||
|
&DanglingRawPtrReleased<features::DanglingPtrMode::kCrash,
|
||||||
|
features::DanglingPtrType::kCrossTask>);
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
case features::DanglingPtrMode::kLogOnly:
|
||||||
case features::DanglingPtrMode::kLogSignature:
|
switch (features::kDanglingPtrTypeParam.Get()) {
|
||||||
partition_alloc::SetDanglingRawPtrDetectedFn(DanglingRawPtrDetected);
|
case features::DanglingPtrType::kAll:
|
||||||
partition_alloc::SetDanglingRawPtrReleasedFn(
|
partition_alloc::SetDanglingRawPtrReleasedFn(
|
||||||
DanglingRawPtrReleasedLogSignature);
|
&DanglingRawPtrReleased<features::DanglingPtrMode::kLogOnly,
|
||||||
|
features::DanglingPtrType::kAll>);
|
||||||
|
break;
|
||||||
|
case features::DanglingPtrType::kCrossTask:
|
||||||
|
partition_alloc::SetDanglingRawPtrReleasedFn(
|
||||||
|
&DanglingRawPtrReleased<features::DanglingPtrMode::kLogOnly,
|
||||||
|
features::DanglingPtrType::kCrossTask>);
|
||||||
|
break;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -632,7 +735,7 @@ void InstallUnretainedDanglingRawPtrChecks() {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
#if PA_CONFIG(ALLOW_PCSCAN)
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
void SetProcessNameForPCScan(const std::string& process_type) {
|
void SetProcessNameForPCScan(const std::string& process_type) {
|
||||||
const char* name = [&process_type] {
|
const char* name = [&process_type] {
|
||||||
if (process_type.empty()) {
|
if (process_type.empty()) {
|
||||||
@ -713,7 +816,7 @@ bool EnablePCScanForMallocPartitionsInRendererProcessIfNeeded() {
|
|||||||
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif // PA_CONFIG(ALLOW_PCSCAN)
|
#endif // BUILDFLAG(USE_STARSCAN)
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
@ -929,7 +1032,7 @@ void PartitionAllocSupport::ReconfigureAfterFeatureListInit(
|
|||||||
|
|
||||||
// If BRP is not enabled, check if any of PCScan flags is enabled.
|
// If BRP is not enabled, check if any of PCScan flags is enabled.
|
||||||
[[maybe_unused]] bool scan_enabled = false;
|
[[maybe_unused]] bool scan_enabled = false;
|
||||||
#if PA_CONFIG(ALLOW_PCSCAN)
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
if (!enable_brp) {
|
if (!enable_brp) {
|
||||||
scan_enabled = EnablePCScanForMallocPartitionsIfNeeded();
|
scan_enabled = EnablePCScanForMallocPartitionsIfNeeded();
|
||||||
// No specified process type means this is the Browser process.
|
// No specified process type means this is the Browser process.
|
||||||
@ -963,10 +1066,10 @@ void PartitionAllocSupport::ReconfigureAfterFeatureListInit(
|
|||||||
SetProcessNameForPCScan(process_type);
|
SetProcessNameForPCScan(process_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // PA_CONFIG(ALLOW_PCSCAN)
|
#endif // BUILDFLAG(USE_STARSCAN)
|
||||||
|
|
||||||
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
||||||
#if PA_CONFIG(ALLOW_PCSCAN)
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
// Non-quarantinable partition is dealing with hot V8's zone allocations.
|
// Non-quarantinable partition is dealing with hot V8's zone allocations.
|
||||||
// In case PCScan is enabled in Renderer, enable thread cache on this
|
// In case PCScan is enabled in Renderer, enable thread cache on this
|
||||||
// partition. At the same time, thread cache on the main(malloc) partition
|
// partition. At the same time, thread cache on the main(malloc) partition
|
||||||
@ -976,7 +1079,7 @@ void PartitionAllocSupport::ReconfigureAfterFeatureListInit(
|
|||||||
.root()
|
.root()
|
||||||
->EnableThreadCacheIfSupported();
|
->EnableThreadCacheIfSupported();
|
||||||
} else
|
} else
|
||||||
#endif // PA_CONFIG(ALLOW_PCSCAN)
|
#endif // BUILDFLAG(USE_STARSCAN)
|
||||||
{
|
{
|
||||||
allocator_shim::internal::PartitionAllocMalloc::Allocator()
|
allocator_shim::internal::PartitionAllocMalloc::Allocator()
|
||||||
->EnableThreadCacheIfSupported();
|
->EnableThreadCacheIfSupported();
|
||||||
@ -1058,7 +1161,7 @@ void PartitionAllocSupport::ReconfigureAfterTaskRunnerInit(
|
|||||||
#endif // PA_CONFIG(THREAD_CACHE_SUPPORTED) &&
|
#endif // PA_CONFIG(THREAD_CACHE_SUPPORTED) &&
|
||||||
// BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
// BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
||||||
|
|
||||||
#if PA_CONFIG(ALLOW_PCSCAN)
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
if (base::FeatureList::IsEnabled(
|
if (base::FeatureList::IsEnabled(
|
||||||
base::features::kPartitionAllocPCScanMUAwareScheduler)) {
|
base::features::kPartitionAllocPCScanMUAwareScheduler)) {
|
||||||
// Assign PCScan a task-based scheduling backend.
|
// Assign PCScan a task-based scheduling backend.
|
||||||
@ -1070,7 +1173,7 @@ void PartitionAllocSupport::ReconfigureAfterTaskRunnerInit(
|
|||||||
partition_alloc::internal::PCScan::scheduler().SetNewSchedulingBackend(
|
partition_alloc::internal::PCScan::scheduler().SetNewSchedulingBackend(
|
||||||
*mu_aware_task_based_backend.get());
|
*mu_aware_task_based_backend.get());
|
||||||
}
|
}
|
||||||
#endif // PA_CONFIG(ALLOW_PCSCAN)
|
#endif // BUILDFLAG(USE_STARSCAN)
|
||||||
|
|
||||||
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
||||||
base::allocator::StartMemoryReclaimer(
|
base::allocator::StartMemoryReclaimer(
|
||||||
@ -1136,4 +1239,11 @@ void PartitionAllocSupport::OnBackgrounded() {
|
|||||||
// BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
// BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if BUILDFLAG(ENABLE_DANGLING_RAW_PTR_CHECKS)
|
||||||
|
std::string PartitionAllocSupport::ExtractDanglingPtrSignatureForTests(
|
||||||
|
std::string stacktrace) {
|
||||||
|
return ExtractDanglingPtrSignature(stacktrace);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace base::allocator
|
} // namespace base::allocator
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
namespace base::allocator {
|
namespace base::allocator {
|
||||||
|
|
||||||
#if PA_CONFIG(ALLOW_PCSCAN)
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
BASE_EXPORT void RegisterPCScanStatsReporter();
|
BASE_EXPORT void RegisterPCScanStatsReporter();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -75,6 +75,11 @@ class BASE_EXPORT PartitionAllocSupport {
|
|||||||
void OnForegrounded(bool has_main_frame);
|
void OnForegrounded(bool has_main_frame);
|
||||||
void OnBackgrounded();
|
void OnBackgrounded();
|
||||||
|
|
||||||
|
#if BUILDFLAG(ENABLE_DANGLING_RAW_PTR_CHECKS)
|
||||||
|
static std::string ExtractDanglingPtrSignatureForTests(
|
||||||
|
std::string stacktrace);
|
||||||
|
#endif
|
||||||
|
|
||||||
static PartitionAllocSupport* Get() {
|
static PartitionAllocSupport* Get() {
|
||||||
static auto* singleton = new PartitionAllocSupport();
|
static auto* singleton = new PartitionAllocSupport();
|
||||||
return singleton;
|
return singleton;
|
||||||
|
@ -289,19 +289,20 @@ component("partition_alloc") {
|
|||||||
}
|
}
|
||||||
if (use_starscan) {
|
if (use_starscan) {
|
||||||
if (current_cpu == "x64") {
|
if (current_cpu == "x64") {
|
||||||
defines += [ "PA_PCSCAN_STACK_SUPPORTED" ]
|
assert(pcscan_stack_supported)
|
||||||
sources += [ "starscan/stack/asm/x64/push_registers_asm.cc" ]
|
sources += [ "starscan/stack/asm/x64/push_registers_asm.cc" ]
|
||||||
} else if (current_cpu == "x86") {
|
} else if (current_cpu == "x86") {
|
||||||
defines += [ "PA_PCSCAN_STACK_SUPPORTED" ]
|
assert(pcscan_stack_supported)
|
||||||
sources += [ "starscan/stack/asm/x86/push_registers_asm.cc" ]
|
sources += [ "starscan/stack/asm/x86/push_registers_asm.cc" ]
|
||||||
} else if (current_cpu == "arm") {
|
} else if (current_cpu == "arm") {
|
||||||
defines += [ "PA_PCSCAN_STACK_SUPPORTED" ]
|
assert(pcscan_stack_supported)
|
||||||
sources += [ "starscan/stack/asm/arm/push_registers_asm.cc" ]
|
sources += [ "starscan/stack/asm/arm/push_registers_asm.cc" ]
|
||||||
} else if (current_cpu == "arm64") {
|
} else if (current_cpu == "arm64") {
|
||||||
defines += [ "PA_PCSCAN_STACK_SUPPORTED" ]
|
assert(pcscan_stack_supported)
|
||||||
sources += [ "starscan/stack/asm/arm64/push_registers_asm.cc" ]
|
sources += [ "starscan/stack/asm/arm64/push_registers_asm.cc" ]
|
||||||
} else {
|
} else {
|
||||||
# To support a trampoline for another arch, please refer to v8/src/heap/base.
|
# To support a trampoline for another arch, please refer to v8/src/heap/base.
|
||||||
|
assert(!pcscan_stack_supported)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public_deps = [
|
public_deps = [
|
||||||
@ -397,6 +398,12 @@ source_set("raw_ptr") {
|
|||||||
|
|
||||||
# See also: `partition_alloc_base/component_export.h`
|
# See also: `partition_alloc_base/component_export.h`
|
||||||
defines = [ "IS_RAW_PTR_IMPL" ]
|
defines = [ "IS_RAW_PTR_IMPL" ]
|
||||||
|
|
||||||
|
# When built inside Chromium, although this cannot directly be made a
|
||||||
|
# component, we expect `//base` to provide the only GN-level access.
|
||||||
|
if (build_with_chromium) {
|
||||||
|
visibility = [ "//base" ]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildflag_header("partition_alloc_buildflags") {
|
buildflag_header("partition_alloc_buildflags") {
|
||||||
@ -415,12 +422,15 @@ buildflag_header("partition_alloc_buildflags") {
|
|||||||
# defines and partition alloc includes the header file. For chrome,
|
# defines and partition alloc includes the header file. For chrome,
|
||||||
# gen/base/allocator/buildflags.h defines and chrome includes.
|
# gen/base/allocator/buildflags.h defines and chrome includes.
|
||||||
flags = [
|
flags = [
|
||||||
|
"HAS_64_BIT_POINTERS=$has_64_bit_pointers",
|
||||||
|
|
||||||
"USE_PARTITION_ALLOC=$use_partition_alloc",
|
"USE_PARTITION_ALLOC=$use_partition_alloc",
|
||||||
"USE_PARTITION_ALLOC_AS_MALLOC=$use_partition_alloc_as_malloc",
|
"USE_PARTITION_ALLOC_AS_MALLOC=$use_partition_alloc_as_malloc",
|
||||||
|
|
||||||
"ENABLE_BACKUP_REF_PTR_SUPPORT=$enable_backup_ref_ptr_support",
|
"ENABLE_BACKUP_REF_PTR_SUPPORT=$enable_backup_ref_ptr_support",
|
||||||
"ENABLE_BACKUP_REF_PTR_SLOW_CHECKS=$enable_backup_ref_ptr_slow_checks",
|
"ENABLE_BACKUP_REF_PTR_SLOW_CHECKS=$enable_backup_ref_ptr_slow_checks",
|
||||||
"ENABLE_DANGLING_RAW_PTR_CHECKS=$enable_dangling_raw_ptr_checks",
|
"ENABLE_DANGLING_RAW_PTR_CHECKS=$enable_dangling_raw_ptr_checks",
|
||||||
|
"ENABLE_DANGLING_RAW_PTR_FEATURE_FLAGS_FOR_BOTS=$enable_dangling_raw_ptr_feature_flags_for_bots",
|
||||||
"ENABLE_DANGLING_RAW_PTR_PERF_EXPERIMENT=$enable_dangling_raw_ptr_perf_experiment",
|
"ENABLE_DANGLING_RAW_PTR_PERF_EXPERIMENT=$enable_dangling_raw_ptr_perf_experiment",
|
||||||
"BACKUP_REF_PTR_POISON_OOB_PTR=$backup_ref_ptr_poison_oob_ptr",
|
"BACKUP_REF_PTR_POISON_OOB_PTR=$backup_ref_ptr_poison_oob_ptr",
|
||||||
"PUT_REF_COUNT_IN_PREVIOUS_SLOT=$put_ref_count_in_previous_slot",
|
"PUT_REF_COUNT_IN_PREVIOUS_SLOT=$put_ref_count_in_previous_slot",
|
||||||
@ -442,9 +452,17 @@ buildflag_header("partition_alloc_buildflags") {
|
|||||||
"ENABLE_SHADOW_METADATA_FOR_64_BITS_POINTERS=$enable_shadow_metadata",
|
"ENABLE_SHADOW_METADATA_FOR_64_BITS_POINTERS=$enable_shadow_metadata",
|
||||||
|
|
||||||
"USE_STARSCAN=$use_starscan",
|
"USE_STARSCAN=$use_starscan",
|
||||||
|
"PCSCAN_STACK_SUPPORTED=$pcscan_stack_supported",
|
||||||
|
|
||||||
"ENABLE_PKEYS=$enable_pkeys",
|
"ENABLE_PKEYS=$enable_pkeys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if (is_apple) {
|
||||||
|
# TODO(crbug.com/1414153): once TimeTicks::Now behavior is unified on iOS,
|
||||||
|
# this should be removed.
|
||||||
|
flags += [ "PARTITION_ALLOC_ENABLE_MACH_ABSOLUTE_TIME_TICKS=" +
|
||||||
|
"$partition_alloc_enable_mach_absolute_time_ticks" ]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buildflag_header("chromecast_buildflags") {
|
buildflag_header("chromecast_buildflags") {
|
||||||
|
@ -158,5 +158,9 @@ specific_include_rules = {
|
|||||||
"+base",
|
"+base",
|
||||||
"+third_party/abseil-cpp/absl/types/optional.h",
|
"+third_party/abseil-cpp/absl/types/optional.h",
|
||||||
"+third_party/abseil-cpp/absl/types/variant.h",
|
"+third_party/abseil-cpp/absl/types/variant.h",
|
||||||
|
],
|
||||||
|
"raw_ptr_test_support\.h$": [
|
||||||
|
"+testing/gmock/include/gmock/gmock.h",
|
||||||
|
"+third_party/abseil-cpp/absl/types/optional.h",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ AddressPoolManager& AddressPoolManager::GetInstance() {
|
|||||||
return singleton_;
|
return singleton_;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -77,8 +77,9 @@ uintptr_t AddressPoolManager::GetPoolBaseAddress(pool_handle handle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AddressPoolManager::ResetForTesting() {
|
void AddressPoolManager::ResetForTesting() {
|
||||||
for (pool_handle i = 0; i < std::size(aligned_pools_.pools_); ++i)
|
for (size_t i = 0; i < std::size(aligned_pools_.pools_); ++i) {
|
||||||
aligned_pools_.pools_[i].Reset();
|
aligned_pools_.pools_[i].Reset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddressPoolManager::Remove(pool_handle handle) {
|
void AddressPoolManager::Remove(pool_handle handle) {
|
||||||
@ -102,7 +103,7 @@ uintptr_t AddressPoolManager::Reserve(pool_handle handle,
|
|||||||
void AddressPoolManager::UnreserveAndDecommit(pool_handle handle,
|
void AddressPoolManager::UnreserveAndDecommit(pool_handle handle,
|
||||||
uintptr_t address,
|
uintptr_t address,
|
||||||
size_t length) {
|
size_t length) {
|
||||||
PA_DCHECK(0 < handle && handle <= kNumPools);
|
PA_DCHECK(kNullPoolHandle < handle && handle <= kNumPools);
|
||||||
Pool* pool = GetPool(handle);
|
Pool* pool = GetPool(handle);
|
||||||
PA_DCHECK(pool->IsInitialized());
|
PA_DCHECK(pool->IsInitialized());
|
||||||
DecommitPages(address, length);
|
DecommitPages(address, length);
|
||||||
@ -299,7 +300,7 @@ bool AddressPoolManager::GetStats(AddressSpaceStats* stats) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#else // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
static_assert(
|
static_assert(
|
||||||
kSuperPageSize % AddressPoolManagerBitmap::kBytesPer1BitOfBRPPoolBitmap ==
|
kSuperPageSize % AddressPoolManagerBitmap::kBytesPer1BitOfBRPPoolBitmap ==
|
||||||
@ -531,7 +532,7 @@ bool AddressPoolManager::GetStats(AddressSpaceStats* stats) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
void AddressPoolManager::DumpStats(AddressSpaceStatsDumper* dumper) {
|
void AddressPoolManager::DumpStats(AddressSpaceStatsDumper* dumper) {
|
||||||
AddressSpaceStats stats{};
|
AddressSpaceStats stats{};
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/thread_annotations.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/thread_annotations.h"
|
||||||
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
||||||
#include "base/allocator/partition_allocator/partition_lock.h"
|
#include "base/allocator/partition_allocator/partition_lock.h"
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
@ -53,7 +53,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) AddressPoolManager {
|
|||||||
AddressPoolManager(const AddressPoolManager&) = delete;
|
AddressPoolManager(const AddressPoolManager&) = delete;
|
||||||
AddressPoolManager& operator=(const AddressPoolManager&) = delete;
|
AddressPoolManager& operator=(const AddressPoolManager&) = delete;
|
||||||
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
void Add(pool_handle handle, uintptr_t address, size_t length);
|
void Add(pool_handle handle, uintptr_t address, size_t length);
|
||||||
void Remove(pool_handle handle);
|
void Remove(pool_handle handle);
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) AddressPoolManager {
|
|||||||
|
|
||||||
// Return the base address of a pool.
|
// Return the base address of a pool.
|
||||||
uintptr_t GetPoolBaseAddress(pool_handle handle);
|
uintptr_t GetPoolBaseAddress(pool_handle handle);
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
// Reserves address space from the pool.
|
// Reserves address space from the pool.
|
||||||
uintptr_t Reserve(pool_handle handle,
|
uintptr_t Reserve(pool_handle handle,
|
||||||
@ -76,7 +76,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) AddressPoolManager {
|
|||||||
size_t length);
|
size_t length);
|
||||||
void ResetForTesting();
|
void ResetForTesting();
|
||||||
|
|
||||||
#if !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
void MarkUsed(pool_handle handle, uintptr_t address, size_t size);
|
void MarkUsed(pool_handle handle, uintptr_t address, size_t size);
|
||||||
void MarkUnused(pool_handle handle, uintptr_t address, size_t size);
|
void MarkUnused(pool_handle handle, uintptr_t address, size_t size);
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) AddressPoolManager {
|
|||||||
static bool IsManagedByBRPPool(uintptr_t address) {
|
static bool IsManagedByBRPPool(uintptr_t address) {
|
||||||
return AddressPoolManagerBitmap::IsManagedByBRPPool(address);
|
return AddressPoolManagerBitmap::IsManagedByBRPPool(address);
|
||||||
}
|
}
|
||||||
#endif // !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif // !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
void DumpStats(AddressSpaceStatsDumper* dumper);
|
void DumpStats(AddressSpaceStatsDumper* dumper);
|
||||||
|
|
||||||
@ -107,7 +107,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) AddressPoolManager {
|
|||||||
// if PartitionAlloc is wholly unused in this process.)
|
// if PartitionAlloc is wholly unused in this process.)
|
||||||
bool GetStats(AddressSpaceStats* stats);
|
bool GetStats(AddressSpaceStats* stats);
|
||||||
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
class Pool {
|
class Pool {
|
||||||
public:
|
public:
|
||||||
constexpr Pool() = default;
|
constexpr Pool() = default;
|
||||||
@ -151,7 +151,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) AddressPoolManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
PA_ALWAYS_INLINE Pool* GetPool(pool_handle handle) {
|
PA_ALWAYS_INLINE Pool* GetPool(pool_handle handle) {
|
||||||
PA_DCHECK(0 < handle && handle <= kNumPools);
|
PA_DCHECK(kNullPoolHandle < handle && handle <= kNumPools);
|
||||||
return &aligned_pools_.pools_[handle - 1];
|
return &aligned_pools_.pools_[handle - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,7 +168,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) AddressPoolManager {
|
|||||||
char pad_after_[PA_PKEY_FILL_PAGE_SZ(sizeof(Pool))] = {};
|
char pad_after_[PA_PKEY_FILL_PAGE_SZ(sizeof(Pool))] = {};
|
||||||
} aligned_pools_ PA_PKEY_ALIGN;
|
} aligned_pools_ PA_PKEY_ALIGN;
|
||||||
|
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
static PA_CONSTINIT AddressPoolManager singleton_;
|
static PA_CONSTINIT AddressPoolManager singleton_;
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
||||||
|
|
||||||
#if !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
namespace partition_alloc::internal {
|
namespace partition_alloc::internal {
|
||||||
|
|
||||||
@ -34,4 +34,4 @@ std::atomic_size_t AddressPoolManagerBitmap::blocklist_hit_count_;
|
|||||||
|
|
||||||
} // namespace partition_alloc::internal
|
} // namespace partition_alloc::internal
|
||||||
|
|
||||||
#endif // !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif // !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
@ -14,12 +14,11 @@
|
|||||||
#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
||||||
#include "base/allocator/partition_allocator/partition_lock.h"
|
#include "base/allocator/partition_allocator/partition_lock.h"
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
|
||||||
#if !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
namespace partition_alloc {
|
namespace partition_alloc {
|
||||||
|
|
||||||
@ -185,6 +184,6 @@ PA_ALWAYS_INLINE bool IsConfigurablePoolAvailable() {
|
|||||||
|
|
||||||
} // namespace partition_alloc
|
} // namespace partition_alloc
|
||||||
|
|
||||||
#endif // !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif // !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_ADDRESS_POOL_MANAGER_BITMAP_H_
|
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_ADDRESS_POOL_MANAGER_BITMAP_H_
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
namespace partition_alloc::internal {
|
namespace partition_alloc::internal {
|
||||||
|
|
||||||
using pool_handle = unsigned;
|
enum pool_handle : unsigned;
|
||||||
|
|
||||||
} // namespace partition_alloc::internal
|
} // namespace partition_alloc::internal
|
||||||
|
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
#include "base/allocator/partition_allocator/address_space_randomization.h"
|
#include "base/allocator/partition_allocator/address_space_randomization.h"
|
||||||
|
|
||||||
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
|
||||||
#include "base/allocator/partition_allocator/random.h"
|
#include "base/allocator/partition_allocator/random.h"
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ namespace partition_alloc {
|
|||||||
uintptr_t GetRandomPageBase() {
|
uintptr_t GetRandomPageBase() {
|
||||||
uintptr_t random = static_cast<uintptr_t>(internal::RandomValue());
|
uintptr_t random = static_cast<uintptr_t>(internal::RandomValue());
|
||||||
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
random <<= 32ULL;
|
random <<= 32ULL;
|
||||||
random |= static_cast<uintptr_t>(internal::RandomValue());
|
random |= static_cast<uintptr_t>(internal::RandomValue());
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ uintptr_t GetRandomPageBase() {
|
|||||||
// OS and build configuration.
|
// OS and build configuration.
|
||||||
random &= internal::ASLRMask();
|
random &= internal::ASLRMask();
|
||||||
random += internal::ASLROffset();
|
random += internal::ASLROffset();
|
||||||
#else // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#else // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
#if BUILDFLAG(IS_WIN)
|
#if BUILDFLAG(IS_WIN)
|
||||||
// On win32 host systems the randomization plus huge alignment causes
|
// On win32 host systems the randomization plus huge alignment causes
|
||||||
// excessive fragmentation. Plus most of these systems lack ASLR, so the
|
// excessive fragmentation. Plus most of these systems lack ASLR, so the
|
||||||
@ -40,7 +40,7 @@ uintptr_t GetRandomPageBase() {
|
|||||||
#endif // BUILDFLAG(IS_WIN)
|
#endif // BUILDFLAG(IS_WIN)
|
||||||
random &= internal::ASLRMask();
|
random &= internal::ASLRMask();
|
||||||
random += internal::ASLROffset();
|
random += internal::ASLROffset();
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
PA_DCHECK(!(random & internal::PageAllocationGranularityOffsetMask()));
|
PA_DCHECK(!(random & internal::PageAllocationGranularityOffsetMask()));
|
||||||
return random;
|
return random;
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
|
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
|
||||||
|
|
||||||
namespace partition_alloc {
|
namespace partition_alloc {
|
||||||
|
|
||||||
@ -20,9 +19,9 @@ struct PoolStats {
|
|||||||
// On 32-bit, pools are mainly logical entities, intermingled with
|
// On 32-bit, pools are mainly logical entities, intermingled with
|
||||||
// allocations not managed by PartitionAlloc. The "largest available
|
// allocations not managed by PartitionAlloc. The "largest available
|
||||||
// reservation" is not possible to measure in that case.
|
// reservation" is not possible to measure in that case.
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
size_t largest_available_reservation = 0;
|
size_t largest_available_reservation = 0;
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AddressSpaceStats {
|
struct AddressSpaceStats {
|
||||||
@ -30,14 +29,14 @@ struct AddressSpaceStats {
|
|||||||
#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
||||||
PoolStats brp_pool_stats;
|
PoolStats brp_pool_stats;
|
||||||
#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
PoolStats configurable_pool_stats;
|
PoolStats configurable_pool_stats;
|
||||||
#else
|
#else
|
||||||
#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
||||||
size_t blocklist_size; // measured in super pages
|
size_t blocklist_size; // measured in super pages
|
||||||
size_t blocklist_hit_count;
|
size_t blocklist_hit_count;
|
||||||
#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
#if BUILDFLAG(ENABLE_PKEYS)
|
#if BUILDFLAG(ENABLE_PKEYS)
|
||||||
PoolStats pkey_pool_stats;
|
PoolStats pkey_pool_stats;
|
||||||
#endif
|
#endif
|
||||||
|
@ -14,6 +14,6 @@ use_partition_alloc_as_malloc_default = false
|
|||||||
use_allocator_shim_default = false
|
use_allocator_shim_default = false
|
||||||
enable_backup_ref_ptr_support_default = false
|
enable_backup_ref_ptr_support_default = false
|
||||||
enable_mte_checked_ptr_support_default = false
|
enable_mte_checked_ptr_support_default = false
|
||||||
put_ref_count_in_previous_slot_default = false
|
put_ref_count_in_previous_slot_default = true
|
||||||
enable_backup_ref_ptr_slow_checks_default = false
|
enable_backup_ref_ptr_slow_checks_default = false
|
||||||
enable_dangling_raw_ptr_checks_default = false
|
enable_dangling_raw_ptr_checks_default = false
|
||||||
|
@ -6,20 +6,9 @@ standalone repository for PartitionAlloc is hosted
|
|||||||
|
|
||||||
## GN Args
|
## GN Args
|
||||||
|
|
||||||
External clients mainly need to set these six GN args:
|
External clients should examine the args described in
|
||||||
|
`build_overrides/partition_alloc.gni` and add them in their own source
|
||||||
``` none
|
tree. PartitionAlloc's build will expect them at
|
||||||
# These are blocked on PA-E and `raw_ptr.h` and can never be true until
|
|
||||||
# we make them part of the standalone PA distribution.
|
|
||||||
use_partition_alloc_as_malloc_default = false
|
|
||||||
enable_mte_checked_ptr_support_default = false
|
|
||||||
enable_backup_ref_ptr_support_default = false
|
|
||||||
put_ref_count_in_previous_slot_default = false
|
|
||||||
enable_backup_ref_ptr_slow_checks_default = false
|
|
||||||
enable_dangling_raw_ptr_checks_default = false
|
|
||||||
```
|
|
||||||
|
|
||||||
PartitionAlloc's build will expect them at
|
|
||||||
`//build_overrides/partition_alloc.gni`.
|
`//build_overrides/partition_alloc.gni`.
|
||||||
|
|
||||||
In addition, something must provide `build_with_chromium = false` to
|
In addition, something must provide `build_with_chromium = false` to
|
||||||
|
@ -136,8 +136,18 @@ bool UseMapJit() {
|
|||||||
return base::mac::CFCast<CFBooleanRef>(jit_entitlement.get()) ==
|
return base::mac::CFCast<CFBooleanRef>(jit_entitlement.get()) ==
|
||||||
kCFBooleanTrue;
|
kCFBooleanTrue;
|
||||||
}
|
}
|
||||||
#endif // BUILDFLAG(IS_MAC)
|
#elif BUILDFLAG(IS_IOS)
|
||||||
|
bool UseMapJit() {
|
||||||
|
// Always enable MAP_JIT in simulator as it is supported unconditionally.
|
||||||
|
#if TARGET_IPHONE_SIMULATOR
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
// TODO(https://crbug.com/1413818): Fill this out when the API it is
|
||||||
|
// available.
|
||||||
|
return false;
|
||||||
|
#endif // TARGET_IPHONE_SIMULATOR
|
||||||
|
}
|
||||||
|
#endif // BUILDFLAG(IS_IOS)
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
// |mmap| uses a nearby address if the hint address is blocked.
|
// |mmap| uses a nearby address if the hint address is blocked.
|
||||||
@ -166,7 +176,7 @@ uintptr_t SystemAllocPagesInternal(uintptr_t hint,
|
|||||||
int access_flag = GetAccessFlags(accessibility);
|
int access_flag = GetAccessFlags(accessibility);
|
||||||
int map_flags = MAP_ANONYMOUS | MAP_PRIVATE;
|
int map_flags = MAP_ANONYMOUS | MAP_PRIVATE;
|
||||||
|
|
||||||
#if BUILDFLAG(IS_MAC)
|
#if BUILDFLAG(IS_APPLE)
|
||||||
// On macOS 10.14 and higher, executables that are code signed with the
|
// On macOS 10.14 and higher, executables that are code signed with the
|
||||||
// "runtime" option cannot execute writable memory by default. They can opt
|
// "runtime" option cannot execute writable memory by default. They can opt
|
||||||
// into this capability by specifying the "com.apple.security.cs.allow-jit"
|
// into this capability by specifying the "com.apple.security.cs.allow-jit"
|
||||||
@ -369,7 +379,6 @@ bool TryRecommitSystemPagesInternal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DiscardSystemPagesInternal(uintptr_t address, size_t length) {
|
void DiscardSystemPagesInternal(uintptr_t address, size_t length) {
|
||||||
#if !BUILDFLAG(IS_NACL)
|
|
||||||
void* ptr = reinterpret_cast<void*>(address);
|
void* ptr = reinterpret_cast<void*>(address);
|
||||||
#if BUILDFLAG(IS_APPLE)
|
#if BUILDFLAG(IS_APPLE)
|
||||||
int ret = madvise(ptr, length, MADV_FREE_REUSABLE);
|
int ret = madvise(ptr, length, MADV_FREE_REUSABLE);
|
||||||
@ -378,7 +387,7 @@ void DiscardSystemPagesInternal(uintptr_t address, size_t length) {
|
|||||||
ret = madvise(ptr, length, MADV_DONTNEED);
|
ret = madvise(ptr, length, MADV_DONTNEED);
|
||||||
}
|
}
|
||||||
PA_PCHECK(ret == 0);
|
PA_PCHECK(ret == 0);
|
||||||
#else
|
#else // BUILDFLAG(IS_APPLE)
|
||||||
// We have experimented with other flags, but with suboptimal results.
|
// We have experimented with other flags, but with suboptimal results.
|
||||||
//
|
//
|
||||||
// MADV_FREE (Linux): Makes our memory measurements less predictable;
|
// MADV_FREE (Linux): Makes our memory measurements less predictable;
|
||||||
@ -391,8 +400,7 @@ void DiscardSystemPagesInternal(uintptr_t address, size_t length) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PA_PCHECK(ret == 0);
|
PA_PCHECK(ret == 0);
|
||||||
#endif
|
#endif // BUILDFLAG(IS_APPLE)
|
||||||
#endif // !BUILDFLAG(IS_NACL)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace partition_alloc::internal
|
} // namespace partition_alloc::internal
|
||||||
|
@ -10,8 +10,8 @@
|
|||||||
#include "base/allocator/partition_allocator/oom.h"
|
#include "base/allocator/partition_allocator/oom.h"
|
||||||
#include "base/allocator/partition_allocator/page_allocator.h"
|
#include "base/allocator/partition_allocator/page_allocator.h"
|
||||||
#include "base/allocator/partition_allocator/page_allocator_internal.h"
|
#include "base/allocator/partition_allocator/page_allocator_internal.h"
|
||||||
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_notreached.h"
|
#include "base/allocator/partition_allocator/partition_alloc_notreached.h"
|
||||||
|
|
||||||
namespace partition_alloc::internal {
|
namespace partition_alloc::internal {
|
||||||
@ -28,7 +28,7 @@ bool IsOutOfMemory(DWORD error) {
|
|||||||
case ERROR_COMMITMENT_MINIMUM:
|
case ERROR_COMMITMENT_MINIMUM:
|
||||||
// Page file is too small.
|
// Page file is too small.
|
||||||
case ERROR_COMMITMENT_LIMIT:
|
case ERROR_COMMITMENT_LIMIT:
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
// Not enough memory resources are available to process this command.
|
// Not enough memory resources are available to process this command.
|
||||||
//
|
//
|
||||||
// It is not entirely clear whether this error pertains to out of address
|
// It is not entirely clear whether this error pertains to out of address
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "base/allocator/partition_allocator/partition_alloc_base/bits.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/bits.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/debug/alias.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/debug/alias.h"
|
||||||
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
||||||
@ -36,7 +37,7 @@
|
|||||||
|
|
||||||
namespace partition_alloc::internal {
|
namespace partition_alloc::internal {
|
||||||
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -422,6 +423,6 @@ PageCharacteristics page_characteristics;
|
|||||||
|
|
||||||
#endif // BUILDFLAG(IS_LINUX) && defined(ARCH_CPU_ARM64)
|
#endif // BUILDFLAG(IS_LINUX) && defined(ARCH_CPU_ARM64)
|
||||||
|
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
} // namespace partition_alloc::internal
|
} // namespace partition_alloc::internal
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
|
||||||
// The feature is not applicable to 32-bit address space.
|
// The feature is not applicable to 32-bit address space.
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
namespace partition_alloc {
|
namespace partition_alloc {
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionAddressSpace {
|
|||||||
#if !BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
#if !BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
||||||
PA_DCHECK(!IsInBRPPool(address));
|
PA_DCHECK(!IsInBRPPool(address));
|
||||||
#endif
|
#endif
|
||||||
pool_handle pool = 0;
|
pool_handle pool = kNullPoolHandle;
|
||||||
uintptr_t base = 0;
|
uintptr_t base = 0;
|
||||||
if (IsInRegularPool(address)) {
|
if (IsInRegularPool(address)) {
|
||||||
pool = kRegularPoolHandle;
|
pool = kRegularPoolHandle;
|
||||||
@ -475,6 +475,6 @@ PA_ALWAYS_INLINE bool IsConfigurablePoolAvailable() {
|
|||||||
|
|
||||||
} // namespace partition_alloc
|
} // namespace partition_alloc
|
||||||
|
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ADDRESS_SPACE_H_
|
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ADDRESS_SPACE_H_
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
#include "base/allocator/partition_allocator/partition_address_space.h"
|
#include "base/allocator/partition_allocator/partition_address_space.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_hooks.h"
|
#include "base/allocator/partition_allocator/partition_alloc_hooks.h"
|
||||||
#include "base/allocator/partition_allocator/partition_direct_map_extent.h"
|
#include "base/allocator/partition_allocator/partition_direct_map_extent.h"
|
||||||
#include "base/allocator/partition_allocator/partition_oom.h"
|
#include "base/allocator/partition_allocator/partition_oom.h"
|
||||||
@ -105,16 +104,6 @@ void PartitionAllocGlobalUninitForTesting() {
|
|||||||
#if BUILDFLAG(ENABLE_PKEYS)
|
#if BUILDFLAG(ENABLE_PKEYS)
|
||||||
internal::PartitionAddressSpace::UninitPkeyPoolForTesting();
|
internal::PartitionAddressSpace::UninitPkeyPoolForTesting();
|
||||||
#endif
|
#endif
|
||||||
#if BUILDFLAG(USE_STARSCAN)
|
|
||||||
internal::PCScan::UninitForTesting(); // IN-TEST
|
|
||||||
#endif
|
|
||||||
#if !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
|
||||||
internal::PartitionAddressSpace::UninitForTesting();
|
|
||||||
#else
|
|
||||||
internal::AddressPoolManager::GetInstance().ResetForTesting();
|
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS)
|
|
||||||
#endif // !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
|
||||||
internal::g_oom_handling_function = nullptr;
|
internal::g_oom_handling_function = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,23 @@
|
|||||||
import("//build/config/sanitizers/sanitizers.gni")
|
import("//build/config/sanitizers/sanitizers.gni")
|
||||||
import("//build_overrides/partition_alloc.gni")
|
import("//build_overrides/partition_alloc.gni")
|
||||||
|
|
||||||
|
if (is_apple) {
|
||||||
|
import("//build/config/features.gni")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Whether 64-bit pointers are used.
|
||||||
|
# A static_assert in partition_alloc_config.h verifies that.
|
||||||
|
if (is_nacl) {
|
||||||
|
# NaCl targets don't use 64-bit pointers.
|
||||||
|
has_64_bit_pointers = false
|
||||||
|
} else if (current_cpu == "x64" || current_cpu == "arm64" || current_cpu == "mips64el") {
|
||||||
|
has_64_bit_pointers = true
|
||||||
|
} else if (current_cpu == "x86" || current_cpu == "arm" || current_cpu == "mipsel") {
|
||||||
|
has_64_bit_pointers = false
|
||||||
|
} else {
|
||||||
|
assert(false, "Unknown CPU: $current_cpu")
|
||||||
|
}
|
||||||
|
|
||||||
if (use_partition_alloc_as_malloc_default) {
|
if (use_partition_alloc_as_malloc_default) {
|
||||||
_default_allocator = "partition"
|
_default_allocator = "partition"
|
||||||
} else {
|
} else {
|
||||||
@ -119,6 +136,14 @@ declare_args() {
|
|||||||
enable_dangling_raw_ptr_checks =
|
enable_dangling_raw_ptr_checks =
|
||||||
enable_dangling_raw_ptr_checks_default && enable_backup_ref_ptr_support
|
enable_dangling_raw_ptr_checks_default && enable_backup_ref_ptr_support
|
||||||
|
|
||||||
|
# Enable the feature flags required to check for dangling pointers. That is to
|
||||||
|
# say `PartitionAllocBackupRefPtr` and `PartitionAllocDanglingPtr`.
|
||||||
|
#
|
||||||
|
# This is meant to be used on bots only. It is much easier to override the
|
||||||
|
# feature flags using a binary flag instead of updating multiple bots's
|
||||||
|
# scripts to pass command line arguments.
|
||||||
|
enable_dangling_raw_ptr_feature_flags_for_bots = false
|
||||||
|
|
||||||
# Enables the dangling raw_ptr checks feature for the performance experiment.
|
# Enables the dangling raw_ptr checks feature for the performance experiment.
|
||||||
# Not every dangling pointers have been fixed or annotated yet. To avoid
|
# Not every dangling pointers have been fixed or annotated yet. To avoid
|
||||||
# accounting for the cost of calling the PA's embedder's callbacks when a
|
# accounting for the cost of calling the PA's embedder's callbacks when a
|
||||||
@ -136,10 +161,20 @@ declare_args() {
|
|||||||
# Shadow metadata is still under development and only supports Linux
|
# Shadow metadata is still under development and only supports Linux
|
||||||
# for now.
|
# for now.
|
||||||
enable_shadow_metadata = false
|
enable_shadow_metadata = false
|
||||||
|
|
||||||
|
if (is_apple) {
|
||||||
|
# use_blink currently assumes mach absolute ticks (eg, to ensure trace
|
||||||
|
# events cohere).
|
||||||
|
partition_alloc_enable_mach_absolute_time_ticks = is_mac || use_blink
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# *Scan is currently only used by Chromium.
|
# *Scan is currently only used by Chromium, and supports only 64-bit.
|
||||||
use_starscan = build_with_chromium
|
use_starscan = build_with_chromium && has_64_bit_pointers
|
||||||
|
|
||||||
|
pcscan_stack_supported =
|
||||||
|
use_starscan && (current_cpu == "x64" || current_cpu == "x86" ||
|
||||||
|
current_cpu == "arm" || current_cpu == "arm64")
|
||||||
|
|
||||||
# We want to provide assertions that guard against inconsistent build
|
# We want to provide assertions that guard against inconsistent build
|
||||||
# args, but there is no point in having them fire if we're not building
|
# args, but there is no point in having them fire if we're not building
|
||||||
@ -223,6 +258,14 @@ assert(!use_asan_backup_ref_ptr || is_asan,
|
|||||||
assert(!use_asan_unowned_ptr || is_asan,
|
assert(!use_asan_unowned_ptr || is_asan,
|
||||||
"AsanUnownedPtr requires AddressSanitizer")
|
"AsanUnownedPtr requires AddressSanitizer")
|
||||||
|
|
||||||
|
if (is_apple) {
|
||||||
|
assert(!use_blink || partition_alloc_enable_mach_absolute_time_ticks,
|
||||||
|
"use_blink requires partition_alloc_enable_mach_absolute_time_ticks")
|
||||||
|
|
||||||
|
assert(!is_mac || partition_alloc_enable_mach_absolute_time_ticks,
|
||||||
|
"mac requires partition_alloc_enable_mach_absolute_time_ticks")
|
||||||
|
}
|
||||||
|
|
||||||
# AsanBackupRefPtr is not supported outside Chromium. The implementation is
|
# AsanBackupRefPtr is not supported outside Chromium. The implementation is
|
||||||
# entangled with `//base`. The code is only physically located with the
|
# entangled with `//base`. The code is only physically located with the
|
||||||
# rest of `raw_ptr` to keep it together.
|
# rest of `raw_ptr` to keep it together.
|
||||||
|
@ -137,7 +137,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// MemorySanitizer annotations.
|
// MemorySanitizer annotations.
|
||||||
#if defined(MEMORY_SANITIZER) && !BUILDFLAG(IS_NACL)
|
#if defined(MEMORY_SANITIZER)
|
||||||
#include <sanitizer/msan_interface.h>
|
#include <sanitizer/msan_interface.h>
|
||||||
|
|
||||||
// Mark a memory region fully initialized.
|
// Mark a memory region fully initialized.
|
||||||
|
@ -41,13 +41,7 @@
|
|||||||
|
|
||||||
#if defined(COMPILER_GCC)
|
#if defined(COMPILER_GCC)
|
||||||
|
|
||||||
#if BUILDFLAG(IS_NACL)
|
#if defined(ARCH_CPU_X86_FAMILY)
|
||||||
|
|
||||||
// Crash report accuracy is not guaranteed on NaCl.
|
|
||||||
#define PA_TRAP_SEQUENCE1_() __builtin_trap()
|
|
||||||
#define PA_TRAP_SEQUENCE2_() asm volatile("")
|
|
||||||
|
|
||||||
#elif defined(ARCH_CPU_X86_FAMILY)
|
|
||||||
|
|
||||||
// TODO(https://crbug.com/958675): In theory, it should be possible to use just
|
// TODO(https://crbug.com/958675): In theory, it should be possible to use just
|
||||||
// int3. However, there are a number of crashes with SIGILL as the exception
|
// int3. However, there are a number of crashes with SIGILL as the exception
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
namespace partition_alloc::internal::base {
|
namespace partition_alloc::internal::base {
|
||||||
|
|
||||||
#if defined(__GLIBC__) || BUILDFLAG(IS_NACL)
|
#if defined(__GLIBC__)
|
||||||
#define USE_HISTORICAL_STRERROR_R 1
|
#define USE_HISTORICAL_STRERROR_R 1
|
||||||
// Post-L versions of bionic define the GNU-specific strerror_r if _GNU_SOURCE
|
// Post-L versions of bionic define the GNU-specific strerror_r if _GNU_SOURCE
|
||||||
// is defined, but the symbol is renamed to __gnu_strerror_r which only exists
|
// is defined, but the symbol is renamed to __gnu_strerror_r which only exists
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
|
||||||
#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && !BUILDFLAG(IS_NACL)
|
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
|
||||||
#include "third_party/lss/linux_syscall_support.h"
|
#include "third_party/lss/linux_syscall_support.h"
|
||||||
#elif BUILDFLAG(IS_MAC)
|
#elif BUILDFLAG(IS_MAC)
|
||||||
// TODO(crbug.com/995996): Waiting for this header to appear in the iOS SDK.
|
// TODO(crbug.com/995996): Waiting for this header to appear in the iOS SDK.
|
||||||
@ -68,7 +68,7 @@ namespace partition_alloc::internal::base {
|
|||||||
// (https://chromium-review.googlesource.com/c/chromium/src/+/1545096) and land
|
// (https://chromium-review.googlesource.com/c/chromium/src/+/1545096) and land
|
||||||
// it or some form of it.
|
// it or some form of it.
|
||||||
void RandBytes(void* output, size_t output_length) {
|
void RandBytes(void* output, size_t output_length) {
|
||||||
#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && !BUILDFLAG(IS_NACL)
|
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
|
||||||
// We have to call `getrandom` via Linux Syscall Support, rather than through
|
// We have to call `getrandom` via Linux Syscall Support, rather than through
|
||||||
// the libc wrapper, because we might not have an up-to-date libc (e.g. on
|
// the libc wrapper, because we might not have an up-to-date libc (e.g. on
|
||||||
// some bots).
|
// some bots).
|
||||||
|
@ -116,11 +116,6 @@ PlatformThreadId PlatformThread::CurrentId() {
|
|||||||
return zx_thread_self();
|
return zx_thread_self();
|
||||||
#elif BUILDFLAG(IS_SOLARIS) || BUILDFLAG(IS_QNX)
|
#elif BUILDFLAG(IS_SOLARIS) || BUILDFLAG(IS_QNX)
|
||||||
return pthread_self();
|
return pthread_self();
|
||||||
#elif BUILDFLAG(IS_NACL) && defined(__GLIBC__)
|
|
||||||
return pthread_self();
|
|
||||||
#elif BUILDFLAG(IS_NACL) && !defined(__GLIBC__)
|
|
||||||
// Pointers are 32-bits in NaCl.
|
|
||||||
return reinterpret_cast<int32_t>(pthread_self());
|
|
||||||
#elif BUILDFLAG(IS_POSIX) && BUILDFLAG(IS_AIX)
|
#elif BUILDFLAG(IS_POSIX) && BUILDFLAG(IS_AIX)
|
||||||
return pthread_self();
|
return pthread_self();
|
||||||
#elif BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_AIX)
|
#elif BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_AIX)
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && BUILDFLAG(USE_STARSCAN)
|
||||||
#include "base/allocator/partition_allocator/starscan/pcscan.h"
|
#include "base/allocator/partition_allocator/starscan/pcscan.h"
|
||||||
#include "base/allocator/partition_allocator/starscan/stack/stack.h"
|
#include "base/allocator/partition_allocator/starscan/stack/stack.h"
|
||||||
#endif
|
#endif
|
||||||
@ -52,16 +52,14 @@ void* ThreadFunc(void* params) {
|
|||||||
|
|
||||||
delegate = thread_params->delegate;
|
delegate = thread_params->delegate;
|
||||||
|
|
||||||
#if !BUILDFLAG(IS_NACL)
|
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && BUILDFLAG(USE_STARSCAN)
|
||||||
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
|
||||||
PCScan::NotifyThreadCreated(GetStackPointer());
|
PCScan::NotifyThreadCreated(GetStackPointer());
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
delegate->ThreadMain();
|
delegate->ThreadMain();
|
||||||
|
|
||||||
#if !BUILDFLAG(IS_NACL) && BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && BUILDFLAG(USE_STARSCAN)
|
||||||
PCScan::NotifyThreadDestroyed();
|
PCScan::NotifyThreadDestroyed();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && BUILDFLAG(USE_STARSCAN)
|
||||||
#include "base/allocator/partition_allocator/starscan/pcscan.h"
|
#include "base/allocator/partition_allocator/starscan/pcscan.h"
|
||||||
#include "base/allocator/partition_allocator/starscan/stack/stack.h"
|
#include "base/allocator/partition_allocator/starscan/stack/stack.h"
|
||||||
#endif
|
#endif
|
||||||
@ -62,7 +62,7 @@ DWORD __stdcall ThreadFunc(void* params) {
|
|||||||
GetCurrentProcess(), &platform_handle, 0,
|
GetCurrentProcess(), &platform_handle, 0,
|
||||||
FALSE, DUPLICATE_SAME_ACCESS);
|
FALSE, DUPLICATE_SAME_ACCESS);
|
||||||
|
|
||||||
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && BUILDFLAG(USE_STARSCAN)
|
||||||
PCScan::NotifyThreadCreated(GetStackPointer());
|
PCScan::NotifyThreadCreated(GetStackPointer());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ DWORD __stdcall ThreadFunc(void* params) {
|
|||||||
delete thread_params;
|
delete thread_params;
|
||||||
delegate->ThreadMain();
|
delegate->ThreadMain();
|
||||||
|
|
||||||
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && BUILDFLAG(USE_STARSCAN)
|
||||||
PCScan::NotifyThreadDestroyed();
|
PCScan::NotifyThreadDestroyed();
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -75,6 +75,10 @@
|
|||||||
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
|
||||||
|
#if BUILDFLAG(IS_APPLE)
|
||||||
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
|
#endif // BUILDFLAG(IS_APPLE)
|
||||||
|
|
||||||
#if BUILDFLAG(IS_FUCHSIA)
|
#if BUILDFLAG(IS_FUCHSIA)
|
||||||
#include <zircon/types.h>
|
#include <zircon/types.h>
|
||||||
#endif
|
#endif
|
||||||
@ -136,9 +140,11 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) TimeDelta {
|
|||||||
#if BUILDFLAG(IS_FUCHSIA)
|
#if BUILDFLAG(IS_FUCHSIA)
|
||||||
static TimeDelta FromZxDuration(zx_duration_t nanos);
|
static TimeDelta FromZxDuration(zx_duration_t nanos);
|
||||||
#endif
|
#endif
|
||||||
#if BUILDFLAG(IS_MAC)
|
#if BUILDFLAG(IS_APPLE)
|
||||||
|
#if BUILDFLAG(PARTITION_ALLOC_ENABLE_MACH_ABSOLUTE_TIME_TICKS)
|
||||||
static TimeDelta FromMachTime(uint64_t mach_time);
|
static TimeDelta FromMachTime(uint64_t mach_time);
|
||||||
#endif // BUILDFLAG(IS_MAC)
|
#endif // BUILDFLAG(PARTITION_ALLOC_ENABLE_MACH_ABSOLUTE_TIME_TICKS)
|
||||||
|
#endif // BUILDFLAG(IS_APPLE)
|
||||||
|
|
||||||
// Converts an integer value representing TimeDelta to a class. This is used
|
// Converts an integer value representing TimeDelta to a class. This is used
|
||||||
// when deserializing a |TimeDelta| structure, using a value known to be
|
// when deserializing a |TimeDelta| structure, using a value known to be
|
||||||
@ -879,14 +885,16 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) TimeTicks
|
|||||||
static TimeTicks FromQPCValue(LONGLONG qpc_value);
|
static TimeTicks FromQPCValue(LONGLONG qpc_value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BUILDFLAG(IS_MAC)
|
#if BUILDFLAG(IS_APPLE)
|
||||||
|
#if BUILDFLAG(PARTITION_ALLOC_ENABLE_MACH_ABSOLUTE_TIME_TICKS)
|
||||||
static TimeTicks FromMachAbsoluteTime(uint64_t mach_absolute_time);
|
static TimeTicks FromMachAbsoluteTime(uint64_t mach_absolute_time);
|
||||||
|
|
||||||
// Sets the current Mach timebase to `timebase`. Returns the old timebase.
|
// Sets the current Mach timebase to `timebase`. Returns the old timebase.
|
||||||
static mach_timebase_info_data_t SetMachTimebaseInfoForTesting(
|
static mach_timebase_info_data_t SetMachTimebaseInfoForTesting(
|
||||||
mach_timebase_info_data_t timebase);
|
mach_timebase_info_data_t timebase);
|
||||||
|
|
||||||
#endif // BUILDFLAG(IS_MAC)
|
#endif // BUILDFLAG(PARTITION_ALLOC_ENABLE_MACH_ABSOLUTE_TIME_TICKS)
|
||||||
|
#endif // BUILDFLAG(IS_APPLE)
|
||||||
|
|
||||||
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(PA_IS_CHROMEOS_ASH)
|
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(PA_IS_CHROMEOS_ASH)
|
||||||
// Converts to TimeTicks the value obtained from SystemClock.uptimeMillis().
|
// Converts to TimeTicks the value obtained from SystemClock.uptimeMillis().
|
||||||
@ -979,7 +987,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) ThreadTicks
|
|||||||
// Returns true if ThreadTicks::Now() is supported on this system.
|
// Returns true if ThreadTicks::Now() is supported on this system.
|
||||||
[[nodiscard]] static bool IsSupported() {
|
[[nodiscard]] static bool IsSupported() {
|
||||||
#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
|
#if (defined(_POSIX_THREAD_CPUTIME) && (_POSIX_THREAD_CPUTIME >= 0)) || \
|
||||||
BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
|
BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA)
|
||||||
return true;
|
return true;
|
||||||
#elif BUILDFLAG(IS_WIN)
|
#elif BUILDFLAG(IS_WIN)
|
||||||
return IsSupportedWin();
|
return IsSupportedWin();
|
||||||
|
@ -14,18 +14,21 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#if BUILDFLAG(IS_IOS)
|
||||||
|
#include <errno.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/logging.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/logging.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/numerics/safe_conversions.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/numerics/safe_conversions.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/time/time_override.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/time/time_override.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_notreached.h"
|
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
|
||||||
namespace partition_alloc::internal::base {
|
namespace partition_alloc::internal::base {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
#if BUILDFLAG(IS_MAC)
|
#if BUILDFLAG(PARTITION_ALLOC_ENABLE_MACH_ABSOLUTE_TIME_TICKS)
|
||||||
// Returns a pointer to the initialized Mach timebase info struct.
|
// Returns a pointer to the initialized Mach timebase info struct.
|
||||||
mach_timebase_info_data_t* MachTimebaseInfo() {
|
mach_timebase_info_data_t* MachTimebaseInfo() {
|
||||||
static mach_timebase_info_data_t timebase_info = []() {
|
static mach_timebase_info_data_t timebase_info = []() {
|
||||||
@ -78,48 +81,32 @@ int64_t MachTimeToMicroseconds(uint64_t mach_time) {
|
|||||||
// 9223372036854775807 / (1e6 * 60 * 60 * 24 * 365.2425) = 292,277).
|
// 9223372036854775807 / (1e6 * 60 * 60 * 24 * 365.2425) = 292,277).
|
||||||
return checked_cast<int64_t>(microseconds);
|
return checked_cast<int64_t>(microseconds);
|
||||||
}
|
}
|
||||||
#endif // BUILDFLAG(IS_MAC)
|
#endif // BUILDFLAG(PARTITION_ALLOC_ENABLE_MACH_ABSOLUTE_TIME_TICKS)
|
||||||
|
|
||||||
// Returns monotonically growing number of ticks in microseconds since some
|
// Returns monotonically growing number of ticks in microseconds since some
|
||||||
// unspecified starting point.
|
// unspecified starting point.
|
||||||
int64_t ComputeCurrentTicks() {
|
int64_t ComputeCurrentTicks() {
|
||||||
#if BUILDFLAG(IS_IOS)
|
#if !BUILDFLAG(PARTITION_ALLOC_ENABLE_MACH_ABSOLUTE_TIME_TICKS)
|
||||||
// iOS 10 supports clock_gettime(CLOCK_MONOTONIC, ...), which is
|
struct timespec tp;
|
||||||
// around 15 times faster than sysctl() call. Use it if possible;
|
// clock_gettime() returns 0 on success and -1 on failure. Failure can only
|
||||||
// otherwise, fall back to sysctl().
|
// happen because of bad arguments (unsupported clock type or timespec
|
||||||
if (__builtin_available(iOS 10, *)) {
|
// pointer out of accessible address space). Here it is known that neither
|
||||||
struct timespec tp;
|
// can happen since the timespec parameter is stack allocated right above and
|
||||||
if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0) {
|
// `CLOCK_MONOTONIC` is supported on all versions of iOS that Chrome is
|
||||||
return (int64_t)tp.tv_sec * 1000000 + tp.tv_nsec / 1000;
|
// supported on.
|
||||||
}
|
int res = clock_gettime(CLOCK_MONOTONIC, &tp);
|
||||||
}
|
PA_DCHECK(0 == res) << "Failed clock_gettime, errno: " << errno;
|
||||||
|
|
||||||
// On iOS mach_absolute_time stops while the device is sleeping. Instead use
|
return (int64_t)tp.tv_sec * 1000000 + tp.tv_nsec / 1000;
|
||||||
// now - KERN_BOOTTIME to get a time difference that is not impacted by clock
|
|
||||||
// changes. KERN_BOOTTIME will be updated by the system whenever the system
|
|
||||||
// clock change.
|
|
||||||
struct timeval boottime;
|
|
||||||
int mib[2] = {CTL_KERN, KERN_BOOTTIME};
|
|
||||||
size_t size = sizeof(boottime);
|
|
||||||
int kr = sysctl(mib, std::size(mib), &boottime, &size, nullptr, 0);
|
|
||||||
PA_DCHECK(KERN_SUCCESS == kr);
|
|
||||||
TimeDelta time_difference =
|
|
||||||
subtle::TimeNowIgnoringOverride() -
|
|
||||||
(Time::FromTimeT(boottime.tv_sec) + Microseconds(boottime.tv_usec));
|
|
||||||
return time_difference.InMicroseconds();
|
|
||||||
#else
|
#else
|
||||||
// mach_absolute_time is it when it comes to ticks on the Mac. Other calls
|
// mach_absolute_time is it when it comes to ticks on the Mac. Other calls
|
||||||
// with less precision (such as TickCount) just call through to
|
// with less precision (such as TickCount) just call through to
|
||||||
// mach_absolute_time.
|
// mach_absolute_time.
|
||||||
return MachTimeToMicroseconds(mach_absolute_time());
|
return MachTimeToMicroseconds(mach_absolute_time());
|
||||||
#endif // BUILDFLAG(IS_IOS)
|
#endif // !BUILDFLAG(PARTITION_ALLOC_ENABLE_MACH_ABSOLUTE_TIME_TICKS)
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t ComputeThreadTicks() {
|
int64_t ComputeThreadTicks() {
|
||||||
#if BUILDFLAG(IS_IOS)
|
|
||||||
PA_NOTREACHED();
|
|
||||||
return 0;
|
|
||||||
#else
|
|
||||||
// The pthreads library keeps a cached reference to the thread port, which
|
// The pthreads library keeps a cached reference to the thread port, which
|
||||||
// does not have to be released like mach_thread_self() does.
|
// does not have to be released like mach_thread_self() does.
|
||||||
mach_port_t thread_port = pthread_mach_thread_np(pthread_self());
|
mach_port_t thread_port = pthread_mach_thread_np(pthread_self());
|
||||||
@ -142,7 +129,6 @@ int64_t ComputeThreadTicks() {
|
|||||||
absolute_micros += (thread_info_data.user_time.microseconds +
|
absolute_micros += (thread_info_data.user_time.microseconds +
|
||||||
thread_info_data.system_time.microseconds);
|
thread_info_data.system_time.microseconds);
|
||||||
return absolute_micros.ValueOrDie();
|
return absolute_micros.ValueOrDie();
|
||||||
#endif // BUILDFLAG(IS_IOS)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -200,12 +186,12 @@ NSDate* Time::ToNSDate() const {
|
|||||||
|
|
||||||
// TimeDelta ------------------------------------------------------------------
|
// TimeDelta ------------------------------------------------------------------
|
||||||
|
|
||||||
#if BUILDFLAG(IS_MAC)
|
#if BUILDFLAG(PARTITION_ALLOC_ENABLE_MACH_ABSOLUTE_TIME_TICKS)
|
||||||
// static
|
// static
|
||||||
TimeDelta TimeDelta::FromMachTime(uint64_t mach_time) {
|
TimeDelta TimeDelta::FromMachTime(uint64_t mach_time) {
|
||||||
return Microseconds(MachTimeToMicroseconds(mach_time));
|
return Microseconds(MachTimeToMicroseconds(mach_time));
|
||||||
}
|
}
|
||||||
#endif // BUILDFLAG(IS_MAC)
|
#endif // BUILDFLAG(PARTITION_ALLOC_ENABLE_MACH_ABSOLUTE_TIME_TICKS)
|
||||||
|
|
||||||
// TimeTicks ------------------------------------------------------------------
|
// TimeTicks ------------------------------------------------------------------
|
||||||
|
|
||||||
@ -225,7 +211,7 @@ bool TimeTicks::IsConsistentAcrossProcesses() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if BUILDFLAG(IS_MAC)
|
#if BUILDFLAG(PARTITION_ALLOC_ENABLE_MACH_ABSOLUTE_TIME_TICKS)
|
||||||
// static
|
// static
|
||||||
TimeTicks TimeTicks::FromMachAbsoluteTime(uint64_t mach_absolute_time) {
|
TimeTicks TimeTicks::FromMachAbsoluteTime(uint64_t mach_absolute_time) {
|
||||||
return TimeTicks(MachTimeToMicroseconds(mach_absolute_time));
|
return TimeTicks(MachTimeToMicroseconds(mach_absolute_time));
|
||||||
@ -241,15 +227,15 @@ mach_timebase_info_data_t TimeTicks::SetMachTimebaseInfoForTesting(
|
|||||||
return orig_timebase;
|
return orig_timebase;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // BUILDFLAG(IS_MAC)
|
#endif // BUILDFLAG(PARTITION_ALLOC_ENABLE_MACH_ABSOLUTE_TIME_TICKS)
|
||||||
|
|
||||||
// static
|
// static
|
||||||
TimeTicks::Clock TimeTicks::GetClock() {
|
TimeTicks::Clock TimeTicks::GetClock() {
|
||||||
#if BUILDFLAG(IS_IOS)
|
#if !BUILDFLAG(PARTITION_ALLOC_ENABLE_MACH_ABSOLUTE_TIME_TICKS)
|
||||||
return Clock::IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME;
|
return Clock::IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME;
|
||||||
#else
|
#else
|
||||||
return Clock::MAC_MACH_ABSOLUTE_TIME;
|
return Clock::MAC_MACH_ABSOLUTE_TIME;
|
||||||
#endif // BUILDFLAG(IS_IOS)
|
#endif // !BUILDFLAG(PARTITION_ALLOC_ENABLE_MACH_ABSOLUTE_TIME_TICKS)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ThreadTicks ----------------------------------------------------------------
|
// ThreadTicks ----------------------------------------------------------------
|
||||||
|
@ -23,37 +23,25 @@
|
|||||||
// 4. Do not use PA_CONFIG() when defining config macros, or it will lead to
|
// 4. Do not use PA_CONFIG() when defining config macros, or it will lead to
|
||||||
// recursion. Either use #if/#else, or PA_CONFIG_MY_SETTING() directly.
|
// recursion. Either use #if/#else, or PA_CONFIG_MY_SETTING() directly.
|
||||||
// 5. Try to use constexpr instead of macros wherever possible.
|
// 5. Try to use constexpr instead of macros wherever possible.
|
||||||
// TODO(bartekn): Convert macros to constexpr as much as possible.
|
// TODO(bartekn): Convert macros to constexpr or BUILDFLAG as much as possible.
|
||||||
#define PA_CONFIG(flag) (PA_CONFIG_##flag())
|
#define PA_CONFIG(flag) (PA_CONFIG_##flag())
|
||||||
|
|
||||||
// ARCH_CPU_64_BITS implies 64-bit instruction set, but not necessarily 64-bit
|
// Assert that the heuristic in partition_alloc.gni is accurate on supported
|
||||||
// address space. The only known case where address space is 32-bit is NaCl, so
|
// configurations.
|
||||||
// eliminate it explicitly. static_assert below ensures that others won't slip
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
// through.
|
|
||||||
#define PA_CONFIG_HAS_64_BITS_POINTERS() \
|
|
||||||
(defined(ARCH_CPU_64_BITS) && !BUILDFLAG(IS_NACL))
|
|
||||||
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
|
||||||
static_assert(sizeof(void*) == 8, "");
|
static_assert(sizeof(void*) == 8, "");
|
||||||
#else
|
#else
|
||||||
static_assert(sizeof(void*) != 8, "");
|
static_assert(sizeof(void*) != 8, "");
|
||||||
#endif
|
#endif // PA_CONFIG(HAS_64_BITS_POINTERS)
|
||||||
|
|
||||||
// PCScan supports 64 bits only and is disabled outside Chromium.
|
#if BUILDFLAG(HAS_64_BIT_POINTERS) && \
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS) && BUILDFLAG(USE_STARSCAN)
|
|
||||||
#define PA_CONFIG_ALLOW_PCSCAN() 1
|
|
||||||
#else
|
|
||||||
#define PA_CONFIG_ALLOW_PCSCAN() 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS) && \
|
|
||||||
(defined(__ARM_NEON) || defined(__ARM_NEON__)) && defined(__ARM_FP)
|
(defined(__ARM_NEON) || defined(__ARM_NEON__)) && defined(__ARM_FP)
|
||||||
#define PA_CONFIG_STARSCAN_NEON_SUPPORTED() 1
|
#define PA_CONFIG_STARSCAN_NEON_SUPPORTED() 1
|
||||||
#else
|
#else
|
||||||
#define PA_CONFIG_STARSCAN_NEON_SUPPORTED() 0
|
#define PA_CONFIG_STARSCAN_NEON_SUPPORTED() 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS) && BUILDFLAG(IS_IOS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS) && BUILDFLAG(IS_IOS)
|
||||||
// Allow PA to select an alternate pool size at run-time before initialization,
|
// Allow PA to select an alternate pool size at run-time before initialization,
|
||||||
// rather than using a single constexpr value.
|
// rather than using a single constexpr value.
|
||||||
//
|
//
|
||||||
@ -64,19 +52,19 @@ static_assert(sizeof(void*) != 8, "");
|
|||||||
#define PA_CONFIG_DYNAMICALLY_SELECT_POOL_SIZE() 1
|
#define PA_CONFIG_DYNAMICALLY_SELECT_POOL_SIZE() 1
|
||||||
#else
|
#else
|
||||||
#define PA_CONFIG_DYNAMICALLY_SELECT_POOL_SIZE() 0
|
#define PA_CONFIG_DYNAMICALLY_SELECT_POOL_SIZE() 0
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS) && BUILDFLAG(IS_IOS)
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS) && BUILDFLAG(IS_IOS)
|
||||||
|
|
||||||
// Puts the regular and BRP pools right next to each other, so that we can
|
// Puts the regular and BRP pools right next to each other, so that we can
|
||||||
// check "belongs to one of the two pools" with a single bitmask operation.
|
// check "belongs to one of the two pools" with a single bitmask operation.
|
||||||
//
|
//
|
||||||
// This setting is specific to 64-bit, as 32-bit has a different implementation.
|
// This setting is specific to 64-bit, as 32-bit has a different implementation.
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS) && BUILDFLAG(GLUE_CORE_POOLS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS) && BUILDFLAG(GLUE_CORE_POOLS)
|
||||||
#define PA_CONFIG_GLUE_CORE_POOLS() 1
|
#define PA_CONFIG_GLUE_CORE_POOLS() 1
|
||||||
#else
|
#else
|
||||||
#define PA_CONFIG_GLUE_CORE_POOLS() 0
|
#define PA_CONFIG_GLUE_CORE_POOLS() 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS) && \
|
#if BUILDFLAG(HAS_64_BIT_POINTERS) && \
|
||||||
(BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID))
|
(BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID))
|
||||||
#include <linux/version.h>
|
#include <linux/version.h>
|
||||||
// TODO(bikineev): Enable for ChromeOS.
|
// TODO(bikineev): Enable for ChromeOS.
|
||||||
@ -84,10 +72,10 @@ static_assert(sizeof(void*) != 8, "");
|
|||||||
(LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0))
|
(LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0))
|
||||||
#else
|
#else
|
||||||
#define PA_CONFIG_STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED() 0
|
#define PA_CONFIG_STARSCAN_UFFD_WRITE_PROTECTOR_SUPPORTED() 0
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS) &&
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS) &&
|
||||||
// (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID))
|
// (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID))
|
||||||
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS) && BUILDFLAG(USE_STARSCAN)
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
// Use card table to avoid races for PCScan configuration without safepoints.
|
// Use card table to avoid races for PCScan configuration without safepoints.
|
||||||
// The card table provides the guaranteee that for a marked card the underling
|
// The card table provides the guaranteee that for a marked card the underling
|
||||||
// super-page is fully initialized.
|
// super-page is fully initialized.
|
||||||
@ -95,11 +83,7 @@ static_assert(sizeof(void*) != 8, "");
|
|||||||
#else
|
#else
|
||||||
// The card table is permanently disabled for 32-bit.
|
// The card table is permanently disabled for 32-bit.
|
||||||
#define PA_CONFIG_STARSCAN_USE_CARD_TABLE() 0
|
#define PA_CONFIG_STARSCAN_USE_CARD_TABLE() 0
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS) && BUILDFLAG(USE_STARSCAN)
|
#endif // BUILDFLAG(USE_STARSCAN)
|
||||||
|
|
||||||
#if PA_CONFIG(STARSCAN_USE_CARD_TABLE) && !PA_CONFIG(ALLOW_PCSCAN)
|
|
||||||
#error "Card table can only be used when *Scan is allowed"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Use batched freeing when sweeping pages. This builds up a freelist in the
|
// Use batched freeing when sweeping pages. This builds up a freelist in the
|
||||||
// scanner thread and appends to the slot-span's freelist only once.
|
// scanner thread and appends to the slot-span's freelist only once.
|
||||||
@ -184,7 +168,7 @@ static_assert(sizeof(void*) != 8, "");
|
|||||||
static_assert(sizeof(void*) == 8);
|
static_assert(sizeof(void*) == 8);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS) && BUILDFLAG(BACKUP_REF_PTR_POISON_OOB_PTR)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS) && BUILDFLAG(BACKUP_REF_PTR_POISON_OOB_PTR)
|
||||||
#define PA_CONFIG_USE_OOB_POISON() 1
|
#define PA_CONFIG_USE_OOB_POISON() 1
|
||||||
#else
|
#else
|
||||||
#define PA_CONFIG_USE_OOB_POISON() 0
|
#define PA_CONFIG_USE_OOB_POISON() 0
|
||||||
@ -195,7 +179,7 @@ static_assert(sizeof(void*) == 8);
|
|||||||
// Only applicable to code with 64-bit pointers. Currently conflicts with true
|
// Only applicable to code with 64-bit pointers. Currently conflicts with true
|
||||||
// hardware MTE.
|
// hardware MTE.
|
||||||
#if BUILDFLAG(ENABLE_MTE_CHECKED_PTR_SUPPORT) && \
|
#if BUILDFLAG(ENABLE_MTE_CHECKED_PTR_SUPPORT) && \
|
||||||
PA_CONFIG(HAS_64_BITS_POINTERS) && !PA_CONFIG(HAS_MEMORY_TAGGING)
|
BUILDFLAG(HAS_64_BIT_POINTERS) && !PA_CONFIG(HAS_MEMORY_TAGGING)
|
||||||
static_assert(sizeof(void*) == 8);
|
static_assert(sizeof(void*) == 8);
|
||||||
#define PA_CONFIG_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS() 1
|
#define PA_CONFIG_ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS() 1
|
||||||
#else
|
#else
|
||||||
@ -321,7 +305,7 @@ constexpr bool kUseLazyCommit = false;
|
|||||||
// This feature is only enabled with 64-bit environment because pools work
|
// This feature is only enabled with 64-bit environment because pools work
|
||||||
// differently with 32-bits pointers (see glossary).
|
// differently with 32-bits pointers (see glossary).
|
||||||
#if BUILDFLAG(ENABLE_SHADOW_METADATA_FOR_64_BITS_POINTERS) && \
|
#if BUILDFLAG(ENABLE_SHADOW_METADATA_FOR_64_BITS_POINTERS) && \
|
||||||
PA_CONFIG(HAS_64_BITS_POINTERS)
|
BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
#define PA_CONFIG_ENABLE_SHADOW_METADATA() 1
|
#define PA_CONFIG_ENABLE_SHADOW_METADATA() 1
|
||||||
#else
|
#else
|
||||||
#define PA_CONFIG_ENABLE_SHADOW_METADATA() 0
|
#define PA_CONFIG_ENABLE_SHADOW_METADATA() 0
|
||||||
@ -340,7 +324,7 @@ constexpr bool kUseLazyCommit = false;
|
|||||||
|
|
||||||
// Enables compressed (4-byte) pointers that can point within the core pools
|
// Enables compressed (4-byte) pointers that can point within the core pools
|
||||||
// (Regular + BRP).
|
// (Regular + BRP).
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS) && BUILDFLAG(ENABLE_POINTER_COMPRESSION)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS) && BUILDFLAG(ENABLE_POINTER_COMPRESSION)
|
||||||
#define PA_CONFIG_POINTER_COMPRESSION() 1
|
#define PA_CONFIG_POINTER_COMPRESSION() 1
|
||||||
|
|
||||||
#if !PA_CONFIG(GLUE_CORE_POOLS)
|
#if !PA_CONFIG(GLUE_CORE_POOLS)
|
||||||
@ -354,7 +338,7 @@ constexpr bool kUseLazyCommit = false;
|
|||||||
// TODO(1376980): Address MTE once it's enabled.
|
// TODO(1376980): Address MTE once it's enabled.
|
||||||
#error "Compressed pointers don't support tag in the upper bits"
|
#error "Compressed pointers don't support tag in the upper bits"
|
||||||
#endif
|
#endif
|
||||||
#else // PA_CONFIG(HAS_64_BITS_POINTERS) &&
|
#else // BUILDFLAG(HAS_64_BIT_POINTERS) &&
|
||||||
// BUILDFLAG(ENABLE_POINTER_COMPRESSION)
|
// BUILDFLAG(ENABLE_POINTER_COMPRESSION)
|
||||||
#define PA_CONFIG_POINTER_COMPRESSION() 0
|
#define PA_CONFIG_POINTER_COMPRESSION() 0
|
||||||
#endif
|
#endif
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "base/allocator/partition_allocator/address_pool_manager_types.h"
|
#include "base/allocator/partition_allocator/address_pool_manager_types.h"
|
||||||
#include "base/allocator/partition_allocator/page_allocator_constants.h"
|
#include "base/allocator/partition_allocator/page_allocator_constants.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
|
||||||
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_forward.h"
|
#include "base/allocator/partition_allocator/partition_alloc_forward.h"
|
||||||
#include "base/allocator/partition_allocator/tagging.h"
|
#include "base/allocator/partition_allocator/tagging.h"
|
||||||
@ -260,12 +261,29 @@ constexpr size_t kSuperPageOffsetMask = kSuperPageAlignment - 1;
|
|||||||
constexpr size_t kSuperPageBaseMask = ~kSuperPageOffsetMask;
|
constexpr size_t kSuperPageBaseMask = ~kSuperPageOffsetMask;
|
||||||
|
|
||||||
// PartitionAlloc's address space is split into pools. See `glossary.md`.
|
// PartitionAlloc's address space is split into pools. See `glossary.md`.
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
|
||||||
#if BUILDFLAG(ENABLE_PKEYS)
|
enum pool_handle : unsigned {
|
||||||
constexpr size_t kNumPools = 4;
|
kNullPoolHandle = 0u,
|
||||||
#else
|
|
||||||
constexpr size_t kNumPools = 3;
|
kRegularPoolHandle,
|
||||||
|
kBRPPoolHandle,
|
||||||
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
kConfigurablePoolHandle,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// New pool_handles will be added here.
|
||||||
|
|
||||||
|
#if BUILDFLAG(ENABLE_PKEYS)
|
||||||
|
// The pkey pool must come last since we pkey_mprotect its entry in the
|
||||||
|
// metadata tables, e.g. AddressPoolManager::aligned_pools_
|
||||||
|
kPkeyPoolHandle,
|
||||||
|
#endif
|
||||||
|
kMaxPoolHandle
|
||||||
|
};
|
||||||
|
|
||||||
|
// kNullPoolHandle doesn't have metadata, hence - 1
|
||||||
|
constexpr size_t kNumPools = kMaxPoolHandle - 1;
|
||||||
|
|
||||||
// Maximum pool size. With exception of Configurable Pool, it is also
|
// Maximum pool size. With exception of Configurable Pool, it is also
|
||||||
// the actual size, unless PA_DYNAMICALLY_SELECT_POOL_SIZE is set, which
|
// the actual size, unless PA_DYNAMICALLY_SELECT_POOL_SIZE is set, which
|
||||||
// allows to choose a different size at initialization time for certain
|
// allows to choose a different size at initialization time for certain
|
||||||
@ -277,22 +295,18 @@ constexpr size_t kNumPools = 3;
|
|||||||
//
|
//
|
||||||
// When pointer compression is enabled, we cannot use large pools (at most
|
// When pointer compression is enabled, we cannot use large pools (at most
|
||||||
// 8GB for each of the glued pools).
|
// 8GB for each of the glued pools).
|
||||||
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) || PA_CONFIG(POINTER_COMPRESSION)
|
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) || PA_CONFIG(POINTER_COMPRESSION)
|
||||||
constexpr size_t kPoolMaxSize = 8 * kGiB;
|
constexpr size_t kPoolMaxSize = 8 * kGiB;
|
||||||
#else
|
#else
|
||||||
constexpr size_t kPoolMaxSize = 16 * kGiB;
|
constexpr size_t kPoolMaxSize = 16 * kGiB;
|
||||||
#endif
|
#endif
|
||||||
#else // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#else // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
constexpr size_t kNumPools = 2;
|
|
||||||
constexpr size_t kPoolMaxSize = 4 * kGiB;
|
constexpr size_t kPoolMaxSize = 4 * kGiB;
|
||||||
#endif
|
#endif
|
||||||
constexpr size_t kMaxSuperPagesInPool = kPoolMaxSize / kSuperPageSize;
|
constexpr size_t kMaxSuperPagesInPool = kPoolMaxSize / kSuperPageSize;
|
||||||
|
|
||||||
static constexpr pool_handle kRegularPoolHandle = 1;
|
|
||||||
static constexpr pool_handle kBRPPoolHandle = 2;
|
|
||||||
static constexpr pool_handle kConfigurablePoolHandle = 3;
|
|
||||||
#if BUILDFLAG(ENABLE_PKEYS)
|
#if BUILDFLAG(ENABLE_PKEYS)
|
||||||
static constexpr pool_handle kPkeyPoolHandle = 4;
|
|
||||||
static_assert(
|
static_assert(
|
||||||
kPkeyPoolHandle == kNumPools,
|
kPkeyPoolHandle == kNumPools,
|
||||||
"The pkey pool must come last since we pkey_mprotect its metadata.");
|
"The pkey pool must come last since we pkey_mprotect its metadata.");
|
||||||
@ -327,7 +341,7 @@ constexpr PA_ALWAYS_INLINE size_t MaxSuperPagesInPool() {
|
|||||||
return kMaxSuperPagesInPool;
|
return kMaxSuperPagesInPool;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
// In 64-bit mode, the direct map allocation granularity is super page size,
|
// In 64-bit mode, the direct map allocation granularity is super page size,
|
||||||
// because this is the reservation granularity of the pools.
|
// because this is the reservation granularity of the pools.
|
||||||
constexpr PA_ALWAYS_INLINE size_t DirectMapAllocationGranularity() {
|
constexpr PA_ALWAYS_INLINE size_t DirectMapAllocationGranularity() {
|
||||||
@ -337,7 +351,7 @@ constexpr PA_ALWAYS_INLINE size_t DirectMapAllocationGranularity() {
|
|||||||
constexpr PA_ALWAYS_INLINE size_t DirectMapAllocationGranularityShift() {
|
constexpr PA_ALWAYS_INLINE size_t DirectMapAllocationGranularityShift() {
|
||||||
return kSuperPageShift;
|
return kSuperPageShift;
|
||||||
}
|
}
|
||||||
#else // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#else // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
// In 32-bit mode, address space is space is a scarce resource. Use the system
|
// In 32-bit mode, address space is space is a scarce resource. Use the system
|
||||||
// allocation granularity, which is the lowest possible address space allocation
|
// allocation granularity, which is the lowest possible address space allocation
|
||||||
// unit. However, don't go below partition page size, so that pool bitmaps
|
// unit. However, don't go below partition page size, so that pool bitmaps
|
||||||
@ -351,7 +365,7 @@ PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR PA_ALWAYS_INLINE size_t
|
|||||||
DirectMapAllocationGranularityShift() {
|
DirectMapAllocationGranularityShift() {
|
||||||
return std::max(PageAllocationGranularityShift(), PartitionPageShift());
|
return std::max(PageAllocationGranularityShift(), PartitionPageShift());
|
||||||
}
|
}
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR PA_ALWAYS_INLINE size_t
|
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR PA_ALWAYS_INLINE size_t
|
||||||
DirectMapAllocationGranularityOffsetMask() {
|
DirectMapAllocationGranularityOffsetMask() {
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
// Copyright 2023 The Chromium Authors
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_FOR_TESTING_H_
|
||||||
|
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_FOR_TESTING_H_
|
||||||
|
|
||||||
|
#include "base/allocator/partition_allocator/partition_alloc.h"
|
||||||
|
|
||||||
|
namespace partition_alloc {
|
||||||
|
namespace internal {
|
||||||
|
|
||||||
|
constexpr bool AllowLeaks = true;
|
||||||
|
constexpr bool DisallowLeaks = false;
|
||||||
|
|
||||||
|
// A subclass of PartitionAllocator for testing. It will free all resources,
|
||||||
|
// i.e. allocated memory, memory inside freelist, and so on, when destructing
|
||||||
|
// it or when manually invoking reset().
|
||||||
|
// If need to check if there are any memory allocated but not freed yet,
|
||||||
|
// use allow_leaks=false. We will see CHECK failure inside reset() if any
|
||||||
|
// leak is detected. Otherwise (e.g. intentional leaks), use allow_leaks=true.
|
||||||
|
template <bool thread_safe, bool allow_leaks>
|
||||||
|
struct PartitionAllocatorForTesting : public PartitionAllocator<thread_safe> {
|
||||||
|
PartitionAllocatorForTesting() : PartitionAllocator<thread_safe>() {}
|
||||||
|
|
||||||
|
explicit PartitionAllocatorForTesting(PartitionOptions opts)
|
||||||
|
: PartitionAllocator<thread_safe>() {
|
||||||
|
PartitionAllocator<thread_safe>::init(opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
~PartitionAllocatorForTesting() { reset(); }
|
||||||
|
|
||||||
|
PA_ALWAYS_INLINE void reset() {
|
||||||
|
PartitionAllocator<thread_safe>::root()->ResetForTesting(allow_leaks);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
|
using PartitionAllocatorForTesting =
|
||||||
|
internal::PartitionAllocatorForTesting<internal::ThreadSafe,
|
||||||
|
internal::DisallowLeaks>;
|
||||||
|
|
||||||
|
using PartitionAllocatorAllowLeaksForTesting =
|
||||||
|
internal::PartitionAllocatorForTesting<internal::ThreadSafe,
|
||||||
|
internal::AllowLeaks>;
|
||||||
|
|
||||||
|
} // namespace partition_alloc
|
||||||
|
|
||||||
|
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_FOR_TESTING_H_
|
@ -32,6 +32,8 @@ std::atomic<PartitionAllocHooks::FreeOverrideHook*>
|
|||||||
PartitionAllocHooks::free_override_hook_(nullptr);
|
PartitionAllocHooks::free_override_hook_(nullptr);
|
||||||
std::atomic<PartitionAllocHooks::ReallocOverrideHook*>
|
std::atomic<PartitionAllocHooks::ReallocOverrideHook*>
|
||||||
PartitionAllocHooks::realloc_override_hook_(nullptr);
|
PartitionAllocHooks::realloc_override_hook_(nullptr);
|
||||||
|
std::atomic<PartitionAllocHooks::QuarantineOverrideHook*>
|
||||||
|
PartitionAllocHooks::quarantine_override_hook_(nullptr);
|
||||||
|
|
||||||
void PartitionAllocHooks::SetObserverHooks(AllocationObserverHook* alloc_hook,
|
void PartitionAllocHooks::SetObserverHooks(AllocationObserverHook* alloc_hook,
|
||||||
FreeObserverHook* free_hook) {
|
FreeObserverHook* free_hook) {
|
||||||
@ -118,4 +120,9 @@ bool PartitionAllocHooks::ReallocOverrideHookIfEnabled(size_t* out,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PartitionAllocHooks::SetQuarantineOverrideHook(
|
||||||
|
QuarantineOverrideHook* hook) {
|
||||||
|
quarantine_override_hook_.store(hook, std::memory_order_release);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace partition_alloc
|
} // namespace partition_alloc
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
|
||||||
|
|
||||||
namespace partition_alloc {
|
namespace partition_alloc {
|
||||||
@ -34,6 +35,12 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionAllocHooks {
|
|||||||
// the size of the underlying allocation.
|
// the size of the underlying allocation.
|
||||||
typedef bool ReallocOverrideHook(size_t* out, void* address);
|
typedef bool ReallocOverrideHook(size_t* out, void* address);
|
||||||
|
|
||||||
|
// Special hook type, independent of the rest. Triggered when `free()` detects
|
||||||
|
// outstanding references to the allocation.
|
||||||
|
// IMPORTANT: Make sure the hook always overwrites `[address, address + size)`
|
||||||
|
// with a bit pattern that cannot be interpreted as a valid memory address.
|
||||||
|
typedef void QuarantineOverrideHook(void* address, size_t size);
|
||||||
|
|
||||||
// To unhook, call Set*Hooks with nullptrs.
|
// To unhook, call Set*Hooks with nullptrs.
|
||||||
static void SetObserverHooks(AllocationObserverHook* alloc_hook,
|
static void SetObserverHooks(AllocationObserverHook* alloc_hook,
|
||||||
FreeObserverHook* free_hook);
|
FreeObserverHook* free_hook);
|
||||||
@ -65,6 +72,12 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionAllocHooks {
|
|||||||
const char* type_name);
|
const char* type_name);
|
||||||
static bool ReallocOverrideHookIfEnabled(size_t* out, void* address);
|
static bool ReallocOverrideHookIfEnabled(size_t* out, void* address);
|
||||||
|
|
||||||
|
PA_ALWAYS_INLINE static QuarantineOverrideHook* GetQuarantineOverrideHook() {
|
||||||
|
return quarantine_override_hook_.load(std::memory_order_acquire);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetQuarantineOverrideHook(QuarantineOverrideHook* hook);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Single bool that is used to indicate whether observer or allocation hooks
|
// Single bool that is used to indicate whether observer or allocation hooks
|
||||||
// are set to reduce the numbers of loads required to check whether hooking is
|
// are set to reduce the numbers of loads required to check whether hooking is
|
||||||
@ -78,6 +91,8 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionAllocHooks {
|
|||||||
static std::atomic<AllocationOverrideHook*> allocation_override_hook_;
|
static std::atomic<AllocationOverrideHook*> allocation_override_hook_;
|
||||||
static std::atomic<FreeOverrideHook*> free_override_hook_;
|
static std::atomic<FreeOverrideHook*> free_override_hook_;
|
||||||
static std::atomic<ReallocOverrideHook*> realloc_override_hook_;
|
static std::atomic<ReallocOverrideHook*> realloc_override_hook_;
|
||||||
|
|
||||||
|
static std::atomic<QuarantineOverrideHook*> quarantine_override_hook_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace partition_alloc
|
} // namespace partition_alloc
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
|
||||||
#if BUILDFLAG(USE_STARSCAN)
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
#include "base/allocator/partition_allocator/starscan/state_bitmap.h"
|
#include "base/allocator/partition_allocator/starscan/pcscan.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace partition_alloc::internal {
|
namespace partition_alloc::internal {
|
||||||
@ -74,7 +74,7 @@ template <bool thread_safe>
|
|||||||
PA_IMMEDIATE_CRASH(); // Not required, kept as documentation.
|
PA_IMMEDIATE_CRASH(); // Not required, kept as documentation.
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !PA_CONFIG(HAS_64_BITS_POINTERS) && BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
#if !BUILDFLAG(HAS_64_BIT_POINTERS) && BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
||||||
// |start| has to be aligned to kSuperPageSize, but |end| doesn't. This means
|
// |start| has to be aligned to kSuperPageSize, but |end| doesn't. This means
|
||||||
// that a partial super page is allowed at the end. Since the block list uses
|
// that a partial super page is allowed at the end. Since the block list uses
|
||||||
// kSuperPageSize granularity, a partial super page is considered blocked if
|
// kSuperPageSize granularity, a partial super page is considered blocked if
|
||||||
@ -93,7 +93,7 @@ bool AreAllowedSuperPagesForBRPPool(uintptr_t start, uintptr_t end) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif // !PA_CONFIG(HAS_64_BITS_POINTERS) &&
|
#endif // !BUILDFLAG(HAS_64_BIT_POINTERS) &&
|
||||||
// BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
// BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
||||||
|
|
||||||
// Reserves |requested_size| worth of super pages from the specified pool.
|
// Reserves |requested_size| worth of super pages from the specified pool.
|
||||||
@ -123,7 +123,7 @@ uintptr_t ReserveMemoryFromPool(pool_handle pool,
|
|||||||
|
|
||||||
// In 32-bit mode, when allocating from BRP pool, verify that the requested
|
// In 32-bit mode, when allocating from BRP pool, verify that the requested
|
||||||
// allocation honors the block list. Find a better address otherwise.
|
// allocation honors the block list. Find a better address otherwise.
|
||||||
#if !PA_CONFIG(HAS_64_BITS_POINTERS) && BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
#if !BUILDFLAG(HAS_64_BIT_POINTERS) && BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
||||||
if (pool == kBRPPoolHandle) {
|
if (pool == kBRPPoolHandle) {
|
||||||
constexpr int kMaxRandomAddressTries = 10;
|
constexpr int kMaxRandomAddressTries = 10;
|
||||||
for (int i = 0; i < kMaxRandomAddressTries; ++i) {
|
for (int i = 0; i < kMaxRandomAddressTries; ++i) {
|
||||||
@ -172,10 +172,10 @@ uintptr_t ReserveMemoryFromPool(pool_handle pool,
|
|||||||
reserved_address = 0;
|
reserved_address = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // !PA_CONFIG(HAS_64_BITS_POINTERS) &&
|
#endif // !BUILDFLAG(HAS_64_BIT_POINTERS) &&
|
||||||
// BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
// BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
||||||
|
|
||||||
#if !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
// Only mark the region as belonging to the pool after it has passed the
|
// Only mark the region as belonging to the pool after it has passed the
|
||||||
// blocklist check in order to avoid a potential race with destructing a
|
// blocklist check in order to avoid a potential race with destructing a
|
||||||
// raw_ptr<T> object that points to non-PA memory in another thread.
|
// raw_ptr<T> object that points to non-PA memory in another thread.
|
||||||
@ -284,7 +284,7 @@ SlotSpanMetadata<thread_safe>* PartitionDirectMap(
|
|||||||
{
|
{
|
||||||
// Reserving memory from the pool is actually not a syscall on 64 bit
|
// Reserving memory from the pool is actually not a syscall on 64 bit
|
||||||
// platforms.
|
// platforms.
|
||||||
#if !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
ScopedSyscallTimer timer{root};
|
ScopedSyscallTimer timer{root};
|
||||||
#endif
|
#endif
|
||||||
reservation_start = ReserveMemoryFromPool(pool, 0, reservation_size);
|
reservation_start = ReserveMemoryFromPool(pool, 0, reservation_size);
|
||||||
@ -434,7 +434,7 @@ SlotSpanMetadata<thread_safe>* PartitionDirectMap(
|
|||||||
|
|
||||||
{
|
{
|
||||||
ScopedSyscallTimer timer{root};
|
ScopedSyscallTimer timer{root};
|
||||||
#if !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
AddressPoolManager::GetInstance().MarkUnused(pool, reservation_start,
|
AddressPoolManager::GetInstance().MarkUnused(pool, reservation_start,
|
||||||
reservation_size);
|
reservation_size);
|
||||||
#endif
|
#endif
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/bits.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/bits.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
|
||||||
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
||||||
|
|
||||||
namespace partition_alloc::internal {
|
namespace partition_alloc::internal {
|
||||||
@ -39,13 +39,13 @@ constexpr size_t OrderSubIndexMask(uint8_t order) {
|
|||||||
(kNumBucketsPerOrderBits + 1);
|
(kNumBucketsPerOrderBits + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
#define PA_BITS_PER_SIZE_T 64
|
#define PA_BITS_PER_SIZE_T 64
|
||||||
static_assert(kBitsPerSizeT == 64, "");
|
static_assert(kBitsPerSizeT == 64, "");
|
||||||
#else
|
#else
|
||||||
#define PA_BITS_PER_SIZE_T 32
|
#define PA_BITS_PER_SIZE_T 32
|
||||||
static_assert(kBitsPerSizeT == 32, "");
|
static_assert(kBitsPerSizeT == 32, "");
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
inline constexpr uint8_t kOrderIndexShift[PA_BITS_PER_SIZE_T + 1] = {
|
inline constexpr uint8_t kOrderIndexShift[PA_BITS_PER_SIZE_T + 1] = {
|
||||||
OrderIndexShift(0), OrderIndexShift(1), OrderIndexShift(2),
|
OrderIndexShift(0), OrderIndexShift(1), OrderIndexShift(2),
|
||||||
|
@ -249,9 +249,7 @@ class PartitionFreelistEntry {
|
|||||||
(next_address & kSuperPageBaseMask);
|
(next_address & kSuperPageBaseMask);
|
||||||
#if BUILDFLAG(USE_FREESLOT_BITMAP)
|
#if BUILDFLAG(USE_FREESLOT_BITMAP)
|
||||||
bool marked_as_free_in_bitmap =
|
bool marked_as_free_in_bitmap =
|
||||||
for_thread_cache
|
for_thread_cache ? true : !FreeSlotBitmapSlotIsUsed(next_address);
|
||||||
? true
|
|
||||||
: !FreeSlotBitmapSlotIsUsed(reinterpret_cast<uintptr_t>(next));
|
|
||||||
#else
|
#else
|
||||||
bool marked_as_free_in_bitmap = true;
|
bool marked_as_free_in_bitmap = true;
|
||||||
#endif
|
#endif
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#include "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_forward.h"
|
#include "base/allocator/partition_allocator/partition_alloc_forward.h"
|
||||||
#include "base/allocator/partition_allocator/partition_direct_map_extent.h"
|
#include "base/allocator/partition_allocator/partition_direct_map_extent.h"
|
||||||
@ -323,23 +322,26 @@ void UnmapNow(uintptr_t reservation_start,
|
|||||||
// In 32-bit mode, the beginning of a reservation may be excluded from the
|
// In 32-bit mode, the beginning of a reservation may be excluded from the
|
||||||
// BRP pool, so shift the pointer. Other pools don't have this logic.
|
// BRP pool, so shift the pointer. Other pools don't have this logic.
|
||||||
PA_DCHECK(IsManagedByPartitionAllocBRPPool(
|
PA_DCHECK(IsManagedByPartitionAllocBRPPool(
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
reservation_start
|
reservation_start
|
||||||
#else
|
#else
|
||||||
reservation_start +
|
reservation_start +
|
||||||
AddressPoolManagerBitmap::kBytesPer1BitOfBRPPoolBitmap *
|
AddressPoolManagerBitmap::kBytesPer1BitOfBRPPoolBitmap *
|
||||||
AddressPoolManagerBitmap::kGuardOffsetOfBRPPoolBitmap
|
AddressPoolManagerBitmap::kGuardOffsetOfBRPPoolBitmap
|
||||||
#endif
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
));
|
));
|
||||||
} else
|
} else
|
||||||
#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
||||||
{
|
{
|
||||||
PA_DCHECK(
|
PA_DCHECK(pool == kRegularPoolHandle
|
||||||
pool == kRegularPoolHandle
|
|
||||||
#if BUILDFLAG(ENABLE_PKEYS)
|
#if BUILDFLAG(ENABLE_PKEYS)
|
||||||
|| pool == kPkeyPoolHandle
|
|| pool == kPkeyPoolHandle
|
||||||
#endif
|
#endif
|
||||||
|| (IsConfigurablePoolAvailable() && pool == kConfigurablePoolHandle));
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
||
|
||||||
|
(IsConfigurablePoolAvailable() && pool == kConfigurablePoolHandle)
|
||||||
|
#endif
|
||||||
|
);
|
||||||
// Non-BRP pools don't need adjustment that BRP needs in 32-bit mode.
|
// Non-BRP pools don't need adjustment that BRP needs in 32-bit mode.
|
||||||
PA_DCHECK(IsManagedByPartitionAllocRegularPool(reservation_start) ||
|
PA_DCHECK(IsManagedByPartitionAllocRegularPool(reservation_start) ||
|
||||||
#if BUILDFLAG(ENABLE_PKEYS)
|
#if BUILDFLAG(ENABLE_PKEYS)
|
||||||
@ -365,7 +367,7 @@ void UnmapNow(uintptr_t reservation_start,
|
|||||||
*offset_ptr++ = kOffsetTagNotAllocated;
|
*offset_ptr++ = kOffsetTagNotAllocated;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
AddressPoolManager::GetInstance().MarkUnused(pool, reservation_start,
|
AddressPoolManager::GetInstance().MarkUnused(pool, reservation_start,
|
||||||
reservation_size);
|
reservation_size);
|
||||||
#endif
|
#endif
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
#include "base/allocator/partition_allocator/partition_alloc_base/thread_annotations.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/thread_annotations.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_forward.h"
|
#include "base/allocator/partition_allocator/partition_alloc_forward.h"
|
||||||
#include "base/allocator/partition_allocator/partition_bucket.h"
|
#include "base/allocator/partition_allocator/partition_bucket.h"
|
||||||
@ -138,7 +137,7 @@ struct SlotSpanMetadata {
|
|||||||
PartitionBucket<thread_safe>* const bucket = nullptr;
|
PartitionBucket<thread_safe>* const bucket = nullptr;
|
||||||
|
|
||||||
// CHECK()ed in AllocNewSlotSpan().
|
// CHECK()ed in AllocNewSlotSpan().
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS) && BUILDFLAG(IS_APPLE)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS) && BUILDFLAG(IS_APPLE)
|
||||||
// System page size is not a constant on Apple OSes, but is either 4 or 16kiB
|
// System page size is not a constant on Apple OSes, but is either 4 or 16kiB
|
||||||
// (1 << 12 or 1 << 14), as checked in PartitionRoot::Init(). And
|
// (1 << 12 or 1 << 14), as checked in PartitionRoot::Init(). And
|
||||||
// PartitionPageSize() is 4 times the OS page size.
|
// PartitionPageSize() is 4 times the OS page size.
|
||||||
@ -155,7 +154,7 @@ struct SlotSpanMetadata {
|
|||||||
// larger, so it doesn't have as many slots.
|
// larger, so it doesn't have as many slots.
|
||||||
static constexpr size_t kMaxSlotsPerSlotSpan =
|
static constexpr size_t kMaxSlotsPerSlotSpan =
|
||||||
PartitionPageSize() / kSmallestBucket;
|
PartitionPageSize() / kSmallestBucket;
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS) && BUILDFLAG(IS_APPLE)
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS) && BUILDFLAG(IS_APPLE)
|
||||||
// The maximum number of bits needed to cover all currently supported OSes.
|
// The maximum number of bits needed to cover all currently supported OSes.
|
||||||
static constexpr size_t kMaxSlotsPerSlotSpanBits = 13;
|
static constexpr size_t kMaxSlotsPerSlotSpanBits = 13;
|
||||||
static_assert(kMaxSlotsPerSlotSpan < (1 << kMaxSlotsPerSlotSpanBits), "");
|
static_assert(kMaxSlotsPerSlotSpan < (1 << kMaxSlotsPerSlotSpanBits), "");
|
||||||
@ -482,7 +481,8 @@ PA_ALWAYS_INLINE AllocationStateMap* SuperPageStateBitmap(
|
|||||||
return reinterpret_cast<AllocationStateMap*>(
|
return reinterpret_cast<AllocationStateMap*>(
|
||||||
SuperPageStateBitmapAddr(super_page));
|
SuperPageStateBitmapAddr(super_page));
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
|
#else // BUILDFLAG(USE_STARSCAN)
|
||||||
|
|
||||||
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR PA_ALWAYS_INLINE size_t
|
PAGE_ALLOCATOR_CONSTANTS_DECLARE_CONSTEXPR PA_ALWAYS_INLINE size_t
|
||||||
ReservedStateBitmapSize() {
|
ReservedStateBitmapSize() {
|
||||||
|
@ -736,13 +736,24 @@ void PartitionRoot<thread_safe>::DestructForTesting() {
|
|||||||
// this function on PartitionRoots without a thread cache.
|
// this function on PartitionRoots without a thread cache.
|
||||||
PA_CHECK(!flags.with_thread_cache);
|
PA_CHECK(!flags.with_thread_cache);
|
||||||
auto pool_handle = ChoosePool();
|
auto pool_handle = ChoosePool();
|
||||||
|
#if BUILDFLAG(ENABLE_PKEYS)
|
||||||
|
// The pages managed by pkey will be free-ed at UninitPKeyForTesting().
|
||||||
|
// Don't invoke FreePages() for the pages.
|
||||||
|
if (pool_handle == internal::kPkeyPoolHandle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PA_DCHECK(pool_handle < internal::kNumPools);
|
||||||
|
#else
|
||||||
|
PA_DCHECK(pool_handle <= internal::kNumPools);
|
||||||
|
#endif
|
||||||
|
|
||||||
auto* curr = first_extent;
|
auto* curr = first_extent;
|
||||||
while (curr != nullptr) {
|
while (curr != nullptr) {
|
||||||
auto* next = curr->next;
|
auto* next = curr->next;
|
||||||
uintptr_t address = SuperPagesBeginFromExtent(curr);
|
uintptr_t address = SuperPagesBeginFromExtent(curr);
|
||||||
size_t size =
|
size_t size =
|
||||||
internal::kSuperPageSize * curr->number_of_consecutive_super_pages;
|
internal::kSuperPageSize * curr->number_of_consecutive_super_pages;
|
||||||
#if !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
internal::AddressPoolManager::GetInstance().MarkUnused(pool_handle, address,
|
internal::AddressPoolManager::GetInstance().MarkUnused(pool_handle, address,
|
||||||
size);
|
size);
|
||||||
#endif
|
#endif
|
||||||
@ -759,7 +770,7 @@ void PartitionRoot<thread_safe>::EnableMac11MallocSizeHackForTesting() {
|
|||||||
}
|
}
|
||||||
#endif // PA_CONFIG(ENABLE_MAC11_MALLOC_SIZE_HACK)
|
#endif // PA_CONFIG(ENABLE_MAC11_MALLOC_SIZE_HACK)
|
||||||
|
|
||||||
#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) && !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) && !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
namespace {
|
namespace {
|
||||||
std::atomic<bool> g_reserve_brp_guard_region_called;
|
std::atomic<bool> g_reserve_brp_guard_region_called;
|
||||||
// An address constructed by repeating `kQuarantinedByte` shouldn't never point
|
// An address constructed by repeating `kQuarantinedByte` shouldn't never point
|
||||||
@ -795,7 +806,7 @@ void ReserveBackupRefPtrGuardRegionIfNeeded() {
|
|||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) &&
|
#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) &&
|
||||||
// !PA_CONFIG(HAS_64_BITS_POINTERS)
|
// !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
template <bool thread_safe>
|
template <bool thread_safe>
|
||||||
void PartitionRoot<thread_safe>::Init(PartitionOptions opts) {
|
void PartitionRoot<thread_safe>::Init(PartitionOptions opts) {
|
||||||
@ -824,12 +835,12 @@ void PartitionRoot<thread_safe>::Init(PartitionOptions opts) {
|
|||||||
// running on the right hardware.
|
// running on the right hardware.
|
||||||
::partition_alloc::internal::InitializeMTESupportIfNeeded();
|
::partition_alloc::internal::InitializeMTESupportIfNeeded();
|
||||||
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
// Reserve address space for partition alloc.
|
// Reserve address space for partition alloc.
|
||||||
internal::PartitionAddressSpace::Init();
|
internal::PartitionAddressSpace::Init();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) && !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) && !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
ReserveBackupRefPtrGuardRegionIfNeeded();
|
ReserveBackupRefPtrGuardRegionIfNeeded();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1499,6 +1510,73 @@ void PartitionRoot<thread_safe>::DeleteForTesting(
|
|||||||
delete partition_root;
|
delete partition_root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <bool thread_safe>
|
||||||
|
void PartitionRoot<thread_safe>::ResetForTesting(bool allow_leaks) {
|
||||||
|
if (flags.with_thread_cache) {
|
||||||
|
ThreadCache::SwapForTesting(nullptr);
|
||||||
|
flags.with_thread_cache = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
::partition_alloc::internal::ScopedGuard guard(lock_);
|
||||||
|
|
||||||
|
#if BUILDFLAG(PA_DCHECK_IS_ON)
|
||||||
|
if (!allow_leaks) {
|
||||||
|
unsigned num_allocated_slots = 0;
|
||||||
|
for (Bucket& bucket : buckets) {
|
||||||
|
if (bucket.active_slot_spans_head !=
|
||||||
|
internal::SlotSpanMetadata<thread_safe>::get_sentinel_slot_span()) {
|
||||||
|
for (internal::SlotSpanMetadata<thread_safe>* slot_span =
|
||||||
|
bucket.active_slot_spans_head;
|
||||||
|
slot_span; slot_span = slot_span->next_slot_span) {
|
||||||
|
num_allocated_slots += slot_span->num_allocated_slots;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Full slot spans are nowhere. Need to see bucket.num_full_slot_spans
|
||||||
|
// to count the number of full slot spans' slots.
|
||||||
|
if (bucket.num_full_slot_spans) {
|
||||||
|
num_allocated_slots +=
|
||||||
|
bucket.num_full_slot_spans * bucket.get_slots_per_span();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PA_DCHECK(num_allocated_slots == 0);
|
||||||
|
|
||||||
|
// Check for direct-mapped allocations.
|
||||||
|
PA_DCHECK(!direct_map_list);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DestructForTesting(); // IN-TEST
|
||||||
|
|
||||||
|
#if PA_CONFIG(USE_PARTITION_ROOT_ENUMERATOR)
|
||||||
|
if (initialized) {
|
||||||
|
internal::PartitionRootEnumerator::Instance().Unregister(this);
|
||||||
|
}
|
||||||
|
#endif // PA_CONFIG(USE_PARTITION_ROOT_ENUMERATOR)
|
||||||
|
|
||||||
|
for (Bucket& bucket : buckets) {
|
||||||
|
bucket.active_slot_spans_head =
|
||||||
|
SlotSpan::get_sentinel_slot_span_non_const();
|
||||||
|
bucket.empty_slot_spans_head = nullptr;
|
||||||
|
bucket.decommitted_slot_spans_head = nullptr;
|
||||||
|
bucket.num_full_slot_spans = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
next_super_page = 0;
|
||||||
|
next_partition_page = 0;
|
||||||
|
next_partition_page_end = 0;
|
||||||
|
current_extent = nullptr;
|
||||||
|
first_extent = nullptr;
|
||||||
|
|
||||||
|
direct_map_list = nullptr;
|
||||||
|
for (auto& entity : global_empty_slot_span_ring) {
|
||||||
|
entity = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
global_empty_slot_span_ring_index = 0;
|
||||||
|
global_empty_slot_span_ring_size = internal::kDefaultEmptySlotSpanRingSize;
|
||||||
|
initialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
template <bool thread_safe>
|
template <bool thread_safe>
|
||||||
void PartitionRoot<thread_safe>::ResetBookkeepingForTesting() {
|
void PartitionRoot<thread_safe>::ResetBookkeepingForTesting() {
|
||||||
::partition_alloc::internal::ScopedGuard guard{lock_};
|
::partition_alloc::internal::ScopedGuard guard{lock_};
|
||||||
|
@ -74,7 +74,6 @@
|
|||||||
|
|
||||||
#if BUILDFLAG(USE_STARSCAN)
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
#include "base/allocator/partition_allocator/starscan/pcscan.h"
|
#include "base/allocator/partition_allocator/starscan/pcscan.h"
|
||||||
#include "base/allocator/partition_allocator/starscan/state_bitmap.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// We use this to make MEMORY_TOOL_REPLACES_ALLOCATOR behave the same for max
|
// We use this to make MEMORY_TOOL_REPLACES_ALLOCATOR behave the same for max
|
||||||
@ -406,6 +405,8 @@ struct PA_ALIGNAS(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot {
|
|||||||
PartitionRoot()
|
PartitionRoot()
|
||||||
: flags{QuarantineMode::kAlwaysDisabled, ScanMode::kDisabled} {}
|
: flags{QuarantineMode::kAlwaysDisabled, ScanMode::kDisabled} {}
|
||||||
explicit PartitionRoot(PartitionOptions opts) : flags() { Init(opts); }
|
explicit PartitionRoot(PartitionOptions opts) : flags() { Init(opts); }
|
||||||
|
// TODO(tasak): remove ~PartitionRoot() after confirming all tests
|
||||||
|
// don't need ~PartitionRoot().
|
||||||
~PartitionRoot();
|
~PartitionRoot();
|
||||||
|
|
||||||
// This will unreserve any space in the pool that the PartitionRoot is
|
// This will unreserve any space in the pool that the PartitionRoot is
|
||||||
@ -585,6 +586,7 @@ struct PA_ALIGNAS(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot {
|
|||||||
PartitionStatsDumper* partition_stats_dumper);
|
PartitionStatsDumper* partition_stats_dumper);
|
||||||
|
|
||||||
static void DeleteForTesting(PartitionRoot* partition_root);
|
static void DeleteForTesting(PartitionRoot* partition_root);
|
||||||
|
void ResetForTesting(bool allow_leaks);
|
||||||
void ResetBookkeepingForTesting();
|
void ResetBookkeepingForTesting();
|
||||||
|
|
||||||
PA_ALWAYS_INLINE BucketDistribution GetBucketDistribution() const {
|
PA_ALWAYS_INLINE BucketDistribution GetBucketDistribution() const {
|
||||||
@ -653,10 +655,12 @@ struct PA_ALIGNAS(64) PA_COMPONENT_EXPORT(PARTITION_ALLOC) PartitionRoot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal::pool_handle ChoosePool() const {
|
internal::pool_handle ChoosePool() const {
|
||||||
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
if (flags.use_configurable_pool) {
|
if (flags.use_configurable_pool) {
|
||||||
PA_DCHECK(IsConfigurablePoolAvailable());
|
PA_DCHECK(IsConfigurablePoolAvailable());
|
||||||
return internal::kConfigurablePoolHandle;
|
return internal::kConfigurablePoolHandle;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#if BUILDFLAG(ENABLE_PKEYS)
|
#if BUILDFLAG(ENABLE_PKEYS)
|
||||||
if (flags.pkey != internal::kDefaultPkey) {
|
if (flags.pkey != internal::kDefaultPkey) {
|
||||||
return internal::kPkeyPoolHandle;
|
return internal::kPkeyPoolHandle;
|
||||||
@ -962,13 +966,13 @@ class ScopedSyscallTimer {
|
|||||||
PA_ALWAYS_INLINE uintptr_t
|
PA_ALWAYS_INLINE uintptr_t
|
||||||
PartitionAllocGetDirectMapSlotStartInBRPPool(uintptr_t address) {
|
PartitionAllocGetDirectMapSlotStartInBRPPool(uintptr_t address) {
|
||||||
PA_DCHECK(IsManagedByPartitionAllocBRPPool(address));
|
PA_DCHECK(IsManagedByPartitionAllocBRPPool(address));
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
// Use this variant of GetDirectMapReservationStart as it has better
|
// Use this variant of GetDirectMapReservationStart as it has better
|
||||||
// performance.
|
// performance.
|
||||||
uintptr_t offset = OffsetInBRPPool(address);
|
uintptr_t offset = OffsetInBRPPool(address);
|
||||||
uintptr_t reservation_start =
|
uintptr_t reservation_start =
|
||||||
GetDirectMapReservationStart(address, kBRPPoolHandle, offset);
|
GetDirectMapReservationStart(address, kBRPPoolHandle, offset);
|
||||||
#else
|
#else // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
uintptr_t reservation_start = GetDirectMapReservationStart(address);
|
uintptr_t reservation_start = GetDirectMapReservationStart(address);
|
||||||
#endif
|
#endif
|
||||||
if (!reservation_start) {
|
if (!reservation_start) {
|
||||||
@ -1396,8 +1400,13 @@ PA_ALWAYS_INLINE void PartitionRoot<thread_safe>::FreeNoHooksImmediate(
|
|||||||
// potential use-after-free issues into unexploitable crashes.
|
// potential use-after-free issues into unexploitable crashes.
|
||||||
if (PA_UNLIKELY(!ref_count->IsAliveWithNoKnownRefs() &&
|
if (PA_UNLIKELY(!ref_count->IsAliveWithNoKnownRefs() &&
|
||||||
brp_zapping_enabled())) {
|
brp_zapping_enabled())) {
|
||||||
internal::SecureMemset(object, internal::kQuarantinedByte,
|
auto usable_size = slot_span->GetUsableSize(this);
|
||||||
slot_span->GetUsableSize(this));
|
auto hook = PartitionAllocHooks::GetQuarantineOverrideHook();
|
||||||
|
if (PA_UNLIKELY(hook)) {
|
||||||
|
hook(object, usable_size);
|
||||||
|
} else {
|
||||||
|
internal::SecureMemset(object, internal::kQuarantinedByte, usable_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PA_UNLIKELY(!(ref_count->ReleaseFromAllocator()))) {
|
if (PA_UNLIKELY(!(ref_count->ReleaseFromAllocator()))) {
|
||||||
|
@ -11,12 +11,12 @@
|
|||||||
|
|
||||||
#include "base/allocator/partition_allocator/page_allocator_constants.h"
|
#include "base/allocator/partition_allocator/page_allocator_constants.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h"
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#if !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
#error "pkey support requires 64 bit pointers"
|
#error "pkey support requires 64 bit pointers"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -85,130 +85,90 @@ namespace base {
|
|||||||
// NOTE: All methods should be `PA_ALWAYS_INLINE`. raw_ptr is meant to be a
|
// NOTE: All methods should be `PA_ALWAYS_INLINE`. raw_ptr is meant to be a
|
||||||
// lightweight replacement of a raw pointer, hence performance is critical.
|
// lightweight replacement of a raw pointer, hence performance is critical.
|
||||||
|
|
||||||
|
// This is a bitfield representing the different flags that can be applied to a
|
||||||
|
// raw_ptr.
|
||||||
|
//
|
||||||
|
// Internal use only: Developers shouldn't use those values directly.
|
||||||
|
//
|
||||||
|
// Housekeeping rules: Try not to change trait values, so that numeric trait
|
||||||
|
// values stay constant across builds (could be useful e.g. when analyzing stack
|
||||||
|
// traces). A reasonable exception to this rule are `*ForTest` traits. As a
|
||||||
|
// matter of fact, we propose that new non-test traits are added before the
|
||||||
|
// `*ForTest` traits.
|
||||||
|
enum class RawPtrTraits : unsigned {
|
||||||
|
kEmpty = 0,
|
||||||
|
|
||||||
|
// Disables dangling pointer detection, but keeps other raw_ptr protections.
|
||||||
|
//
|
||||||
|
// Don't use directly, use DisableDanglingPtrDetection or DanglingUntriaged
|
||||||
|
// instead.
|
||||||
|
kMayDangle = (1 << 0),
|
||||||
|
|
||||||
|
#if PA_CONFIG(ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
|
||||||
|
// Disables any protections when MTECheckedPtrImpl is requested, by
|
||||||
|
// switching to NoOpImpl in that case.
|
||||||
|
//
|
||||||
|
// Don't use directly, use DegradeToNoOpWhenMTE instead.
|
||||||
|
kDisableMTECheckedPtr = (1 << 1),
|
||||||
|
#else
|
||||||
|
kDisableMTECheckedPtr = kEmpty,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
|
||||||
|
// Disables any hooks, by switching to NoOpImpl in that case.
|
||||||
|
//
|
||||||
|
// Internal use only.
|
||||||
|
kDisableHooks = (1 << 2),
|
||||||
|
#else
|
||||||
|
kDisableHooks = kEmpty,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Pointer arithmetic is discouraged and disabled by default.
|
||||||
|
//
|
||||||
|
// Don't use directly, use AllowPtrArithmetic instead.
|
||||||
|
kAllowPtrArithmetic = (1 << 3),
|
||||||
|
|
||||||
|
// Adds accounting, on top of the chosen implementation, for test purposes.
|
||||||
|
// raw_ptr/raw_ref with this trait perform extra bookkeeping, e.g. to track
|
||||||
|
// the number of times the raw_ptr is wrapped, unwrapped, etc.
|
||||||
|
//
|
||||||
|
// Test only.
|
||||||
|
kUseCountingWrapperForTest = (1 << 4),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Used to combine RawPtrTraits:
|
||||||
|
constexpr RawPtrTraits operator|(RawPtrTraits a, RawPtrTraits b) {
|
||||||
|
return static_cast<RawPtrTraits>(static_cast<unsigned>(a) |
|
||||||
|
static_cast<unsigned>(b));
|
||||||
|
}
|
||||||
|
constexpr RawPtrTraits operator&(RawPtrTraits a, RawPtrTraits b) {
|
||||||
|
return static_cast<RawPtrTraits>(static_cast<unsigned>(a) &
|
||||||
|
static_cast<unsigned>(b));
|
||||||
|
}
|
||||||
|
constexpr RawPtrTraits operator~(RawPtrTraits a) {
|
||||||
|
return static_cast<RawPtrTraits>(~static_cast<unsigned>(a));
|
||||||
|
}
|
||||||
|
|
||||||
namespace raw_ptr_traits {
|
namespace raw_ptr_traits {
|
||||||
|
|
||||||
// Disables dangling pointer detection, but keeps other raw_ptr protections.
|
constexpr bool Contains(RawPtrTraits a, RawPtrTraits b) {
|
||||||
// Don't use directly, use DisableDanglingPtrDetection or DanglingUntriaged
|
return (a & b) != RawPtrTraits::kEmpty;
|
||||||
// instead.
|
}
|
||||||
struct MayDangle {};
|
|
||||||
// Disables any protections when MTECheckedPtrImpl is requested, by switching to
|
|
||||||
// NoOpImpl in that case.
|
|
||||||
// Don't use directly, use DegradeToNoOpWhenMTE instead.
|
|
||||||
struct DisableMTECheckedPtr {};
|
|
||||||
// Disables any hooks, by switching to NoOpImpl in that case.
|
|
||||||
// Internal use only.
|
|
||||||
struct DisableHooks {};
|
|
||||||
// Adds accounting, on top of the chosen implementation, for test purposes.
|
|
||||||
// raw_ptr/raw_ref with this trait perform extra bookkeeping, e.g. to track the
|
|
||||||
// number of times the raw_ptr is wrapped, unrwapped, etc.
|
|
||||||
// Test only.
|
|
||||||
struct UseCountingWrapperForTest {};
|
|
||||||
// Very internal use only.
|
|
||||||
using EmptyTrait = void;
|
|
||||||
|
|
||||||
template <typename Trait>
|
constexpr RawPtrTraits Remove(RawPtrTraits a, RawPtrTraits b) {
|
||||||
inline constexpr bool IsValidTraitV =
|
return a & ~b;
|
||||||
std::is_same_v<Trait, MayDangle> ||
|
}
|
||||||
std::is_same_v<Trait, DisableMTECheckedPtr> ||
|
|
||||||
std::is_same_v<Trait, DisableHooks> ||
|
|
||||||
std::is_same_v<Trait, UseCountingWrapperForTest> ||
|
|
||||||
std::is_same_v<Trait, EmptyTrait>;
|
|
||||||
|
|
||||||
template <typename... Traits>
|
constexpr bool AreValid(RawPtrTraits traits) {
|
||||||
struct TraitPack {
|
return Remove(traits, RawPtrTraits::kMayDangle |
|
||||||
static_assert((IsValidTraitV<Traits> && ...), "Unknown raw_ptr trait");
|
RawPtrTraits::kDisableMTECheckedPtr |
|
||||||
|
RawPtrTraits::kDisableHooks |
|
||||||
|
RawPtrTraits::kAllowPtrArithmetic |
|
||||||
|
RawPtrTraits::kUseCountingWrapperForTest) ==
|
||||||
|
RawPtrTraits::kEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename TraitToSearch>
|
template <RawPtrTraits Traits>
|
||||||
static inline constexpr bool HasV =
|
|
||||||
(std::is_same_v<TraitToSearch, Traits> || ...);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Replaces an unwanted trait with EmptyTrait.
|
|
||||||
template <typename TraitToExclude>
|
|
||||||
struct ExcludeTrait {
|
|
||||||
template <typename Trait>
|
|
||||||
using Filter = std::
|
|
||||||
conditional_t<std::is_same_v<TraitToExclude, Trait>, EmptyTrait, Trait>;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Use TraitBundle alias, instead of TraitBundleInt, so that traits in different
|
|
||||||
// order and duplicates resolve to the same underlying type. For example,
|
|
||||||
// TraitBundle<A,B> is the same C++ type as TraitBundle<B,A,B,A>. This also
|
|
||||||
// allows to entirely ignore a trait under some build configurations, to prevent
|
|
||||||
// it from turning TraitBundle into a different C++ type.
|
|
||||||
//
|
|
||||||
// It'd be easier to just pass bools into TraitBundleInt, instead of echo'ing
|
|
||||||
// the trait, but that would lead to less readable compiler messages that spit
|
|
||||||
// out the type. TraitBundleInt<MayDangle,EmptyTrait,DisableHooks,EmptyTrait> is
|
|
||||||
// more readable than TraitBundleInt<true,false,true,false>.
|
|
||||||
template <typename... Traits>
|
|
||||||
struct TraitBundleInt;
|
|
||||||
template <typename... Traits>
|
|
||||||
using TraitBundle = TraitBundleInt<
|
|
||||||
std::conditional_t<TraitPack<Traits...>::template HasV<MayDangle>,
|
|
||||||
MayDangle,
|
|
||||||
EmptyTrait>,
|
|
||||||
#if PA_CONFIG(ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
|
|
||||||
std::conditional_t<
|
|
||||||
TraitPack<Traits...>::template HasV<DisableMTECheckedPtr>,
|
|
||||||
DisableMTECheckedPtr,
|
|
||||||
EmptyTrait>,
|
|
||||||
#else
|
|
||||||
// Entirely ignore DisableMTECheckedPtr on non-MTECheckedPtr builds, so that
|
|
||||||
// TraitBundle (and thus raw_ptr/raw_ref) with that trait is considered
|
|
||||||
// exactly the same type as without it. This matches the long standing
|
|
||||||
// behavior prior to crrev.com/c/4113514.
|
|
||||||
EmptyTrait,
|
|
||||||
#endif // PA_CONFIG(ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
|
|
||||||
#if BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
|
|
||||||
std::conditional_t<TraitPack<Traits...>::template HasV<DisableHooks>,
|
|
||||||
DisableHooks,
|
|
||||||
EmptyTrait>,
|
|
||||||
#else
|
|
||||||
// Entirely ignore DisableHooks on non-ASanBRP builds, so that
|
|
||||||
// TraitBundle (and thus raw_ptr/raw_ref) with that trait is considered
|
|
||||||
// exactly the same type as without it. This matches the long standing
|
|
||||||
// behavior prior to crrev.com/c/4113514.
|
|
||||||
EmptyTrait,
|
|
||||||
#endif // BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
|
|
||||||
std::conditional_t<
|
|
||||||
TraitPack<Traits...>::template HasV<UseCountingWrapperForTest>,
|
|
||||||
UseCountingWrapperForTest,
|
|
||||||
EmptyTrait>>;
|
|
||||||
|
|
||||||
template <typename... Traits>
|
|
||||||
struct TraitBundleInt {
|
|
||||||
static constexpr bool kMayDangle =
|
|
||||||
TraitPack<Traits...>::template HasV<MayDangle>;
|
|
||||||
static constexpr bool kDisableMTECheckedPtr =
|
|
||||||
TraitPack<Traits...>::template HasV<DisableMTECheckedPtr>;
|
|
||||||
static constexpr bool kDisableHooks =
|
|
||||||
TraitPack<Traits...>::template HasV<DisableHooks>;
|
|
||||||
static constexpr bool kUseCountingWrapperForTest =
|
|
||||||
TraitPack<Traits...>::template HasV<UseCountingWrapperForTest>;
|
|
||||||
|
|
||||||
// Assert that on certain build configurations, the related traits are not
|
|
||||||
// even used. If they were, they'd result in a different C++ type, and would
|
|
||||||
// trigger more costly cross-type raw_ptr/raw_ref conversions.
|
|
||||||
#if !PA_CONFIG(ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
|
|
||||||
static_assert(!kDisableMTECheckedPtr);
|
|
||||||
#endif
|
|
||||||
#if !BUILDFLAG(USE_ASAN_BACKUP_REF_PTR)
|
|
||||||
static_assert(!kDisableHooks);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Use TraitBundle, instead of TraitBundleInt, to re-normalize trait list
|
|
||||||
// (i.e. order canonically and remove duplicates).
|
|
||||||
template <typename TraitToAdd>
|
|
||||||
using AddTraitT = TraitBundle<Traits..., TraitToAdd>;
|
|
||||||
// Unlike AddTraitT, no need to re-normalize because ExcludeTrait preserves
|
|
||||||
// the trait list structure.
|
|
||||||
template <typename TraitToRemove>
|
|
||||||
using RemoveTraitT = TraitBundleInt<
|
|
||||||
typename ExcludeTrait<TraitToRemove>::template Filter<Traits>...>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename TraitBundle>
|
|
||||||
struct TraitsToImpl;
|
struct TraitsToImpl;
|
||||||
|
|
||||||
} // namespace raw_ptr_traits
|
} // namespace raw_ptr_traits
|
||||||
@ -346,17 +306,33 @@ struct MTECheckedPtrImpl {
|
|||||||
// Wraps a pointer, and returns its uintptr_t representation.
|
// Wraps a pointer, and returns its uintptr_t representation.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
|
static PA_ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
|
||||||
|
// Catch the obviously unsupported cases, e.g. `nullptr` or `-1ull`.
|
||||||
|
//
|
||||||
|
// `ExtractPtr(ptr)` should be functionally identical to `ptr` for
|
||||||
|
// the purposes of `EnabledForPtr()`, since we assert that `ptr` is
|
||||||
|
// an untagged raw pointer (there are no tag bits provided by
|
||||||
|
// MTECheckedPtr to strip off). However, something like `-1ull`
|
||||||
|
// looks identical to a fully tagged-up pointer. We'll add a check
|
||||||
|
// here just to make sure there's no difference in the support check
|
||||||
|
// whether extracted or not.
|
||||||
|
const bool extracted_supported =
|
||||||
|
PartitionAllocSupport::EnabledForPtr(ExtractPtr(ptr));
|
||||||
|
const bool raw_supported = PartitionAllocSupport::EnabledForPtr(ptr);
|
||||||
|
PA_BASE_DCHECK(extracted_supported == raw_supported);
|
||||||
|
|
||||||
|
// At the expense of consistency, we use the `raw_supported`
|
||||||
|
// condition. When wrapping a raw pointer, we assert that having set
|
||||||
|
// bits conflatable with the MTECheckedPtr tag disqualifies `ptr`
|
||||||
|
// from support.
|
||||||
|
if (!raw_supported) {
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Disambiguation: UntagPtr removes the hardware MTE tag, whereas this
|
// Disambiguation: UntagPtr removes the hardware MTE tag, whereas this
|
||||||
// function is responsible for adding the software MTE tag.
|
// function is responsible for adding the software MTE tag.
|
||||||
uintptr_t addr = partition_alloc::UntagPtr(ptr);
|
uintptr_t addr = partition_alloc::UntagPtr(ptr);
|
||||||
PA_BASE_DCHECK(ExtractTag(addr) == 0ull);
|
PA_BASE_DCHECK(ExtractTag(addr) == 0ull);
|
||||||
|
|
||||||
// Return a not-wrapped |addr|, if it's either nullptr or if the protection
|
|
||||||
// for this pointer is disabled.
|
|
||||||
if (!PartitionAllocSupport::EnabledForPtr(ptr)) {
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the tag and place it in the top bits of the address.
|
// Read the tag and place it in the top bits of the address.
|
||||||
// Even if PartitionAlloc's tag has less than kTagBits, we'll read
|
// Even if PartitionAlloc's tag has less than kTagBits, we'll read
|
||||||
// what's given and pad the rest with 0s.
|
// what's given and pad the rest with 0s.
|
||||||
@ -407,19 +383,30 @@ struct MTECheckedPtrImpl {
|
|||||||
return wrapped_ptr;
|
return wrapped_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unwraps the pointer's uintptr_t representation, while asserting that memory
|
// Unwraps the pointer as a T*, without making an assertion on whether
|
||||||
// hasn't been freed. The function must handle nullptr gracefully.
|
// memory was freed or not.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
|
static PA_ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
|
||||||
// SafelyUnwrapPtrForDereference handles nullptr case well.
|
// Return `wrapped_ptr` straightaway if protection is disabled, e.g.
|
||||||
return SafelyUnwrapPtrForDereference(wrapped_ptr);
|
// when `ptr` is `nullptr` or `uintptr_t{-1ull}`.
|
||||||
|
T* extracted_ptr = ExtractPtr(wrapped_ptr);
|
||||||
|
if (!PartitionAllocSupport::EnabledForPtr(extracted_ptr)) {
|
||||||
|
return wrapped_ptr;
|
||||||
|
}
|
||||||
|
return extracted_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unwraps the pointer's uintptr_t representation, without making an assertion
|
// Unwraps the pointer's uintptr_t representation, without making an assertion
|
||||||
// on whether memory was freed or not.
|
// on whether memory was freed or not.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
|
static PA_ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
|
||||||
return ExtractPtr(wrapped_ptr);
|
// Return `wrapped_ptr` straightaway if protection is disabled, e.g.
|
||||||
|
// when `ptr` is `nullptr` or `uintptr_t{-1ull}`.
|
||||||
|
T* extracted_ptr = ExtractPtr(wrapped_ptr);
|
||||||
|
if (!PartitionAllocSupport::EnabledForPtr(extracted_ptr)) {
|
||||||
|
return wrapped_ptr;
|
||||||
|
}
|
||||||
|
return extracted_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Upcasts the wrapped pointer.
|
// Upcasts the wrapped pointer.
|
||||||
@ -522,10 +509,12 @@ struct MTECheckedPtrImpl {
|
|||||||
// wrapped, unrwapped, etc.
|
// wrapped, unrwapped, etc.
|
||||||
//
|
//
|
||||||
// Test only.
|
// Test only.
|
||||||
template <typename Traits>
|
template <RawPtrTraits Traits>
|
||||||
struct RawPtrCountingImplWrapperForTest
|
struct RawPtrCountingImplWrapperForTest
|
||||||
: public raw_ptr_traits::TraitsToImpl<Traits>::Impl {
|
: public raw_ptr_traits::TraitsToImpl<Traits>::Impl {
|
||||||
static_assert(!Traits::kUseCountingWrapperForTest);
|
static_assert(
|
||||||
|
!raw_ptr_traits::Contains(Traits,
|
||||||
|
RawPtrTraits::kUseCountingWrapperForTest));
|
||||||
|
|
||||||
using SuperImpl = typename raw_ptr_traits::TraitsToImpl<Traits>::Impl;
|
using SuperImpl = typename raw_ptr_traits::TraitsToImpl<Traits>::Impl;
|
||||||
|
|
||||||
@ -685,31 +674,36 @@ struct IsSupportedType<T,
|
|||||||
#undef PA_WINDOWS_HANDLE_TYPE
|
#undef PA_WINDOWS_HANDLE_TYPE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template <typename Traits>
|
template <RawPtrTraits Traits>
|
||||||
struct TraitsToImpl {
|
struct TraitsToImpl {
|
||||||
|
static_assert(AreValid(Traits), "Unknown raw_ptr trait(s)");
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// UnderlyingImpl is the struct that provides the implementation of the
|
// UnderlyingImpl is the struct that provides the implementation of the
|
||||||
// protections related to raw_ptr.
|
// protections related to raw_ptr.
|
||||||
#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
|
||||||
using UnderlyingImpl = internal::RawPtrBackupRefImpl<
|
using UnderlyingImpl = internal::RawPtrBackupRefImpl<
|
||||||
/*AllowDangling=*/Traits::kMayDangle>;
|
/*allow_dangling=*/Contains(Traits, RawPtrTraits::kMayDangle)>;
|
||||||
|
|
||||||
#elif BUILDFLAG(USE_ASAN_UNOWNED_PTR)
|
#elif BUILDFLAG(USE_ASAN_UNOWNED_PTR)
|
||||||
using UnderlyingImpl =
|
using UnderlyingImpl = std::conditional_t<
|
||||||
std::conditional_t<Traits::kMayDangle,
|
Contains(Traits, RawPtrTraits::kMayDangle),
|
||||||
// No special bookkeeping required for this case,
|
// No special bookkeeping required for this case,
|
||||||
// just treat these as ordinary pointers.
|
// just treat these as ordinary pointers.
|
||||||
internal::RawPtrNoOpImpl,
|
internal::RawPtrNoOpImpl,
|
||||||
internal::RawPtrAsanUnownedImpl>;
|
internal::RawPtrAsanUnownedImpl<
|
||||||
|
Contains(Traits, RawPtrTraits::kAllowPtrArithmetic)>>;
|
||||||
#elif PA_CONFIG(ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
|
#elif PA_CONFIG(ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
|
||||||
using UnderlyingImpl =
|
using UnderlyingImpl =
|
||||||
std::conditional_t<Traits::kDisableMTECheckedPtr,
|
std::conditional_t<Contains(Traits, RawPtrTraits::kDisableMTECheckedPtr),
|
||||||
internal::RawPtrNoOpImpl,
|
internal::RawPtrNoOpImpl,
|
||||||
internal::MTECheckedPtrImpl<
|
internal::MTECheckedPtrImpl<
|
||||||
internal::MTECheckedPtrImplPartitionAllocSupport>>;
|
internal::MTECheckedPtrImplPartitionAllocSupport>>;
|
||||||
#elif BUILDFLAG(USE_HOOKABLE_RAW_PTR)
|
#elif BUILDFLAG(USE_HOOKABLE_RAW_PTR)
|
||||||
using UnderlyingImpl = std::conditional_t<Traits::kDisableHooks,
|
using UnderlyingImpl =
|
||||||
internal::RawPtrNoOpImpl,
|
std::conditional_t<Contains(Traits, RawPtrTraits::kDisableHooks),
|
||||||
internal::RawPtrHookableImpl>;
|
internal::RawPtrNoOpImpl,
|
||||||
|
internal::RawPtrHookableImpl>;
|
||||||
#else
|
#else
|
||||||
using UnderlyingImpl = internal::RawPtrNoOpImpl;
|
using UnderlyingImpl = internal::RawPtrNoOpImpl;
|
||||||
#endif
|
#endif
|
||||||
@ -720,9 +714,9 @@ struct TraitsToImpl {
|
|||||||
// Impl may be different from UnderlyingImpl, because it may include a
|
// Impl may be different from UnderlyingImpl, because it may include a
|
||||||
// wrapper.
|
// wrapper.
|
||||||
using Impl = std::conditional_t<
|
using Impl = std::conditional_t<
|
||||||
Traits::kUseCountingWrapperForTest,
|
Contains(Traits, RawPtrTraits::kUseCountingWrapperForTest),
|
||||||
internal::RawPtrCountingImplWrapperForTest<
|
internal::RawPtrCountingImplWrapperForTest<
|
||||||
typename Traits::template RemoveTraitT<UseCountingWrapperForTest>>,
|
Remove(Traits, RawPtrTraits::kUseCountingWrapperForTest)>,
|
||||||
UnderlyingImpl>;
|
UnderlyingImpl>;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -754,13 +748,11 @@ struct TraitsToImpl {
|
|||||||
// non-default move constructor/assignment. Thus, it's possible to get an error
|
// non-default move constructor/assignment. Thus, it's possible to get an error
|
||||||
// where the pointer is not actually dangling, and have to work around the
|
// where the pointer is not actually dangling, and have to work around the
|
||||||
// compiler. We have not managed to construct such an example in Chromium yet.
|
// compiler. We have not managed to construct such an example in Chromium yet.
|
||||||
template <typename T, typename Traits = raw_ptr_traits::TraitBundle<>>
|
template <typename T, RawPtrTraits Traits = RawPtrTraits::kEmpty>
|
||||||
class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ptr {
|
class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ptr {
|
||||||
// Type to return from ExtractAsDangling(), which is identical except
|
// Type to return from ExtractAsDangling(), which is identical except
|
||||||
// MayDangle trait is added (if one isn't there already).
|
// kMayDangle trait is added (if one isn't there already).
|
||||||
using DanglingRawPtrType =
|
using DanglingRawPtrType = raw_ptr<T, Traits | RawPtrTraits::kMayDangle>;
|
||||||
raw_ptr<T,
|
|
||||||
typename Traits::template AddTraitT<raw_ptr_traits::MayDangle>>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Impl = typename raw_ptr_traits::TraitsToImpl<Traits>::Impl;
|
using Impl = typename raw_ptr_traits::TraitsToImpl<Traits>::Impl;
|
||||||
@ -842,17 +834,15 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ptr {
|
|||||||
#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) ||
|
#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) ||
|
||||||
// BUILDFLAG(USE_ASAN_UNOWNED_PTR)
|
// BUILDFLAG(USE_ASAN_UNOWNED_PTR)
|
||||||
|
|
||||||
template <
|
template <RawPtrTraits PassedTraits,
|
||||||
typename PassedTraits,
|
typename Unused = std::enable_if_t<Traits != PassedTraits>>
|
||||||
typename Unused = std::enable_if_t<!std::is_same_v<Traits, PassedTraits>>>
|
|
||||||
PA_ALWAYS_INLINE explicit raw_ptr(const raw_ptr<T, PassedTraits>& p) noexcept
|
PA_ALWAYS_INLINE explicit raw_ptr(const raw_ptr<T, PassedTraits>& p) noexcept
|
||||||
: wrapped_ptr_(Impl::WrapRawPtrForDuplication(
|
: wrapped_ptr_(Impl::WrapRawPtrForDuplication(
|
||||||
raw_ptr_traits::TraitsToImpl<PassedTraits>::Impl::
|
raw_ptr_traits::TraitsToImpl<PassedTraits>::Impl::
|
||||||
UnsafelyUnwrapPtrForDuplication(p.wrapped_ptr_))) {}
|
UnsafelyUnwrapPtrForDuplication(p.wrapped_ptr_))) {}
|
||||||
|
|
||||||
template <
|
template <RawPtrTraits PassedTraits,
|
||||||
typename PassedTraits,
|
typename Unused = std::enable_if_t<Traits != PassedTraits>>
|
||||||
typename Unused = std::enable_if_t<!std::is_same_v<Traits, PassedTraits>>>
|
|
||||||
PA_ALWAYS_INLINE raw_ptr& operator=(
|
PA_ALWAYS_INLINE raw_ptr& operator=(
|
||||||
const raw_ptr<T, PassedTraits>& p) noexcept {
|
const raw_ptr<T, PassedTraits>& p) noexcept {
|
||||||
Impl::ReleaseWrappedPtr(wrapped_ptr_);
|
Impl::ReleaseWrappedPtr(wrapped_ptr_);
|
||||||
@ -1004,20 +994,23 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ptr {
|
|||||||
return *this += -delta_elems;
|
return *this += -delta_elems;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
// Do not disable operator+() and operator-().
|
||||||
typename Z,
|
// They provide OOB checks. Keep them enabled, which may be blocked later when
|
||||||
typename = std::enable_if_t<partition_alloc::internal::offset_type<Z>>>
|
// attempting to apply the += or -= operation, when disabled. In the absence
|
||||||
|
// of operators +/-, the compiler is free to implicitly convert to the
|
||||||
|
// underlying T* representation and perform ordinary pointer arithmetic, thus
|
||||||
|
// invalidating the purpose behind disabling them.
|
||||||
|
template <typename Z>
|
||||||
friend PA_ALWAYS_INLINE raw_ptr operator+(const raw_ptr& p, Z delta_elems) {
|
friend PA_ALWAYS_INLINE raw_ptr operator+(const raw_ptr& p, Z delta_elems) {
|
||||||
raw_ptr result = p;
|
raw_ptr result = p;
|
||||||
return result += delta_elems;
|
return result += delta_elems;
|
||||||
}
|
}
|
||||||
template <
|
template <typename Z>
|
||||||
typename Z,
|
|
||||||
typename = std::enable_if_t<partition_alloc::internal::offset_type<Z>>>
|
|
||||||
friend PA_ALWAYS_INLINE raw_ptr operator-(const raw_ptr& p, Z delta_elems) {
|
friend PA_ALWAYS_INLINE raw_ptr operator-(const raw_ptr& p, Z delta_elems) {
|
||||||
raw_ptr result = p;
|
raw_ptr result = p;
|
||||||
return result -= delta_elems;
|
return result -= delta_elems;
|
||||||
}
|
}
|
||||||
|
|
||||||
friend PA_ALWAYS_INLINE ptrdiff_t operator-(const raw_ptr& p1,
|
friend PA_ALWAYS_INLINE ptrdiff_t operator-(const raw_ptr& p1,
|
||||||
const raw_ptr& p2) {
|
const raw_ptr& p2) {
|
||||||
return Impl::GetDeltaElems(p1.wrapped_ptr_, p2.wrapped_ptr_);
|
return Impl::GetDeltaElems(p1.wrapped_ptr_, p2.wrapped_ptr_);
|
||||||
@ -1086,22 +1079,22 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ptr {
|
|||||||
// `raw_ptr` and `raw_ptr<U>` in the friend declaration itself does not work,
|
// `raw_ptr` and `raw_ptr<U>` in the friend declaration itself does not work,
|
||||||
// because a comparison operator defined inline would not be allowed to call
|
// because a comparison operator defined inline would not be allowed to call
|
||||||
// `raw_ptr<U>`'s private `GetForComparison()` method.
|
// `raw_ptr<U>`'s private `GetForComparison()` method.
|
||||||
template <typename U, typename V, typename R1, typename R2>
|
template <typename U, typename V, RawPtrTraits R1, RawPtrTraits R2>
|
||||||
friend PA_ALWAYS_INLINE bool operator==(const raw_ptr<U, R1>& lhs,
|
friend PA_ALWAYS_INLINE bool operator==(const raw_ptr<U, R1>& lhs,
|
||||||
const raw_ptr<V, R2>& rhs);
|
const raw_ptr<V, R2>& rhs);
|
||||||
template <typename U, typename V, typename R1, typename R2>
|
template <typename U, typename V, RawPtrTraits R1, RawPtrTraits R2>
|
||||||
friend PA_ALWAYS_INLINE bool operator!=(const raw_ptr<U, R1>& lhs,
|
friend PA_ALWAYS_INLINE bool operator!=(const raw_ptr<U, R1>& lhs,
|
||||||
const raw_ptr<V, R2>& rhs);
|
const raw_ptr<V, R2>& rhs);
|
||||||
template <typename U, typename V, typename R1, typename R2>
|
template <typename U, typename V, RawPtrTraits R1, RawPtrTraits R2>
|
||||||
friend PA_ALWAYS_INLINE bool operator<(const raw_ptr<U, R1>& lhs,
|
friend PA_ALWAYS_INLINE bool operator<(const raw_ptr<U, R1>& lhs,
|
||||||
const raw_ptr<V, R2>& rhs);
|
const raw_ptr<V, R2>& rhs);
|
||||||
template <typename U, typename V, typename R1, typename R2>
|
template <typename U, typename V, RawPtrTraits R1, RawPtrTraits R2>
|
||||||
friend PA_ALWAYS_INLINE bool operator>(const raw_ptr<U, R1>& lhs,
|
friend PA_ALWAYS_INLINE bool operator>(const raw_ptr<U, R1>& lhs,
|
||||||
const raw_ptr<V, R2>& rhs);
|
const raw_ptr<V, R2>& rhs);
|
||||||
template <typename U, typename V, typename R1, typename R2>
|
template <typename U, typename V, RawPtrTraits R1, RawPtrTraits R2>
|
||||||
friend PA_ALWAYS_INLINE bool operator<=(const raw_ptr<U, R1>& lhs,
|
friend PA_ALWAYS_INLINE bool operator<=(const raw_ptr<U, R1>& lhs,
|
||||||
const raw_ptr<V, R2>& rhs);
|
const raw_ptr<V, R2>& rhs);
|
||||||
template <typename U, typename V, typename R1, typename R2>
|
template <typename U, typename V, RawPtrTraits R1, RawPtrTraits R2>
|
||||||
friend PA_ALWAYS_INLINE bool operator>=(const raw_ptr<U, R1>& lhs,
|
friend PA_ALWAYS_INLINE bool operator>=(const raw_ptr<U, R1>& lhs,
|
||||||
const raw_ptr<V, R2>& rhs);
|
const raw_ptr<V, R2>& rhs);
|
||||||
|
|
||||||
@ -1211,41 +1204,41 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ptr {
|
|||||||
// #union, #global-scope, #constexpr-ctor-field-initializer
|
// #union, #global-scope, #constexpr-ctor-field-initializer
|
||||||
RAW_PTR_EXCLUSION T* wrapped_ptr_;
|
RAW_PTR_EXCLUSION T* wrapped_ptr_;
|
||||||
|
|
||||||
template <typename U, typename R>
|
template <typename U, base::RawPtrTraits R>
|
||||||
friend class raw_ptr;
|
friend class raw_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename U, typename V, typename Traits1, typename Traits2>
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
PA_ALWAYS_INLINE bool operator==(const raw_ptr<U, Traits1>& lhs,
|
PA_ALWAYS_INLINE bool operator==(const raw_ptr<U, Traits1>& lhs,
|
||||||
const raw_ptr<V, Traits2>& rhs) {
|
const raw_ptr<V, Traits2>& rhs) {
|
||||||
return lhs.GetForComparison() == rhs.GetForComparison();
|
return lhs.GetForComparison() == rhs.GetForComparison();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U, typename V, typename Traits1, typename Traits2>
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
PA_ALWAYS_INLINE bool operator!=(const raw_ptr<U, Traits1>& lhs,
|
PA_ALWAYS_INLINE bool operator!=(const raw_ptr<U, Traits1>& lhs,
|
||||||
const raw_ptr<V, Traits2>& rhs) {
|
const raw_ptr<V, Traits2>& rhs) {
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U, typename V, typename Traits1, typename Traits2>
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
PA_ALWAYS_INLINE bool operator<(const raw_ptr<U, Traits1>& lhs,
|
PA_ALWAYS_INLINE bool operator<(const raw_ptr<U, Traits1>& lhs,
|
||||||
const raw_ptr<V, Traits2>& rhs) {
|
const raw_ptr<V, Traits2>& rhs) {
|
||||||
return lhs.GetForComparison() < rhs.GetForComparison();
|
return lhs.GetForComparison() < rhs.GetForComparison();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U, typename V, typename Traits1, typename Traits2>
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
PA_ALWAYS_INLINE bool operator>(const raw_ptr<U, Traits1>& lhs,
|
PA_ALWAYS_INLINE bool operator>(const raw_ptr<U, Traits1>& lhs,
|
||||||
const raw_ptr<V, Traits2>& rhs) {
|
const raw_ptr<V, Traits2>& rhs) {
|
||||||
return lhs.GetForComparison() > rhs.GetForComparison();
|
return lhs.GetForComparison() > rhs.GetForComparison();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U, typename V, typename Traits1, typename Traits2>
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
PA_ALWAYS_INLINE bool operator<=(const raw_ptr<U, Traits1>& lhs,
|
PA_ALWAYS_INLINE bool operator<=(const raw_ptr<U, Traits1>& lhs,
|
||||||
const raw_ptr<V, Traits2>& rhs) {
|
const raw_ptr<V, Traits2>& rhs) {
|
||||||
return lhs.GetForComparison() <= rhs.GetForComparison();
|
return lhs.GetForComparison() <= rhs.GetForComparison();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename U, typename V, typename Traits1, typename Traits2>
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
PA_ALWAYS_INLINE bool operator>=(const raw_ptr<U, Traits1>& lhs,
|
PA_ALWAYS_INLINE bool operator>=(const raw_ptr<U, Traits1>& lhs,
|
||||||
const raw_ptr<V, Traits2>& rhs) {
|
const raw_ptr<V, Traits2>& rhs) {
|
||||||
return lhs.GetForComparison() >= rhs.GetForComparison();
|
return lhs.GetForComparison() >= rhs.GetForComparison();
|
||||||
@ -1254,7 +1247,7 @@ PA_ALWAYS_INLINE bool operator>=(const raw_ptr<U, Traits1>& lhs,
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct IsRawPtr : std::false_type {};
|
struct IsRawPtr : std::false_type {};
|
||||||
|
|
||||||
template <typename T, typename Traits>
|
template <typename T, RawPtrTraits Traits>
|
||||||
struct IsRawPtr<raw_ptr<T, Traits>> : std::true_type {};
|
struct IsRawPtr<raw_ptr<T, Traits>> : std::true_type {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -1263,9 +1256,9 @@ inline constexpr bool IsRawPtrV = IsRawPtr<T>::value;
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
inline constexpr bool IsRawPtrMayDangleV = false;
|
inline constexpr bool IsRawPtrMayDangleV = false;
|
||||||
|
|
||||||
template <typename T, typename Traits>
|
template <typename T, RawPtrTraits Traits>
|
||||||
inline constexpr bool IsRawPtrMayDangleV<raw_ptr<T, Traits>> =
|
inline constexpr bool IsRawPtrMayDangleV<raw_ptr<T, Traits>> =
|
||||||
Traits::kMayDangle;
|
raw_ptr_traits::Contains(Traits, RawPtrTraits::kMayDangle);
|
||||||
|
|
||||||
// Template helpers for working with T* or raw_ptr<T>.
|
// Template helpers for working with T* or raw_ptr<T>.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -1274,7 +1267,7 @@ struct IsPointer : std::false_type {};
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct IsPointer<T*> : std::true_type {};
|
struct IsPointer<T*> : std::true_type {};
|
||||||
|
|
||||||
template <typename T, typename Traits>
|
template <typename T, RawPtrTraits Traits>
|
||||||
struct IsPointer<raw_ptr<T, Traits>> : std::true_type {};
|
struct IsPointer<raw_ptr<T, Traits>> : std::true_type {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -1290,7 +1283,7 @@ struct RemovePointer<T*> {
|
|||||||
using type = T;
|
using type = T;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename Traits>
|
template <typename T, RawPtrTraits Traits>
|
||||||
struct RemovePointer<raw_ptr<T, Traits>> {
|
struct RemovePointer<raw_ptr<T, Traits>> {
|
||||||
using type = T;
|
using type = T;
|
||||||
};
|
};
|
||||||
@ -1311,23 +1304,19 @@ using base::raw_ptr;
|
|||||||
//
|
//
|
||||||
// When using it, please provide a justification about what guarantees that it
|
// When using it, please provide a justification about what guarantees that it
|
||||||
// will never be dereferenced after becoming dangling.
|
// will never be dereferenced after becoming dangling.
|
||||||
using DisableDanglingPtrDetection =
|
constexpr auto DisableDanglingPtrDetection = base::RawPtrTraits::kMayDangle;
|
||||||
base::raw_ptr_traits::TraitBundle<base::raw_ptr_traits::MayDangle>;
|
|
||||||
|
|
||||||
// See `docs/dangling_ptr.md`
|
// See `docs/dangling_ptr.md`
|
||||||
// Annotates known dangling raw_ptr. Those haven't been triaged yet. All the
|
// Annotates known dangling raw_ptr. Those haven't been triaged yet. All the
|
||||||
// occurrences are meant to be removed. See https://crbug.com/1291138.
|
// occurrences are meant to be removed. See https://crbug.com/1291138.
|
||||||
using DanglingUntriaged =
|
constexpr auto DanglingUntriaged = base::RawPtrTraits::kMayDangle;
|
||||||
base::raw_ptr_traits::TraitBundle<base::raw_ptr_traits::MayDangle>;
|
|
||||||
|
|
||||||
// This type is to be used in callbacks arguments when it is known that they
|
// This type is to be used in callbacks arguments when it is known that they
|
||||||
// might receive dangling pointers. In any other cases, please use one of:
|
// might receive dangling pointers. In any other cases, please use one of:
|
||||||
// - raw_ptr<T, DanglingUntriaged>
|
// - raw_ptr<T, DanglingUntriaged>
|
||||||
// - raw_ptr<T, DisableDanglingPtrDetection>
|
// - raw_ptr<T, DisableDanglingPtrDetection>
|
||||||
template <typename T>
|
template <typename T, base::RawPtrTraits Traits = base::RawPtrTraits::kEmpty>
|
||||||
using MayBeDangling = base::raw_ptr<
|
using MayBeDangling = base::raw_ptr<T, Traits | base::RawPtrTraits::kMayDangle>;
|
||||||
T,
|
|
||||||
base::raw_ptr_traits::TraitBundle<base::raw_ptr_traits::MayDangle>>;
|
|
||||||
|
|
||||||
// The following template parameters are only meaningful when `raw_ptr`
|
// The following template parameters are only meaningful when `raw_ptr`
|
||||||
// is `MTECheckedPtr` (never the case unless a particular GN arg is set
|
// is `MTECheckedPtr` (never the case unless a particular GN arg is set
|
||||||
@ -1342,25 +1331,18 @@ using MayBeDangling = base::raw_ptr<
|
|||||||
// See `base/memory/raw_ptr_mtecheckedptr.md`
|
// See `base/memory/raw_ptr_mtecheckedptr.md`
|
||||||
|
|
||||||
// Direct pass-through to no-op implementation.
|
// Direct pass-through to no-op implementation.
|
||||||
using DegradeToNoOpWhenMTE = base::raw_ptr_traits::TraitBundle<
|
constexpr auto DegradeToNoOpWhenMTE = base::RawPtrTraits::kDisableMTECheckedPtr;
|
||||||
base::raw_ptr_traits::DisableMTECheckedPtr>;
|
|
||||||
|
|
||||||
// As above, but with the "untriaged dangling" annotation.
|
// The use of pointer arithmetic with raw_ptr is strongly discouraged and
|
||||||
using DanglingUntriagedDegradeToNoOpWhenMTE = base::raw_ptr_traits::TraitBundle<
|
// disabled by default. Usually a container like span<> should be used
|
||||||
base::raw_ptr_traits::MayDangle,
|
// instead of the raw_ptr.
|
||||||
base::raw_ptr_traits::DisableMTECheckedPtr>;
|
constexpr auto AllowPtrArithmetic = base::RawPtrTraits::kAllowPtrArithmetic;
|
||||||
|
|
||||||
// As above, but with the "explicitly disable protection" annotation.
|
|
||||||
using DisableDanglingPtrDetectionDegradeToNoOpWhenMTE =
|
|
||||||
base::raw_ptr_traits::TraitBundle<
|
|
||||||
base::raw_ptr_traits::MayDangle,
|
|
||||||
base::raw_ptr_traits::DisableMTECheckedPtr>;
|
|
||||||
|
|
||||||
namespace std {
|
namespace std {
|
||||||
|
|
||||||
// Override so set/map lookups do not create extra raw_ptr. This also allows
|
// Override so set/map lookups do not create extra raw_ptr. This also allows
|
||||||
// dangling pointers to be used for lookup.
|
// dangling pointers to be used for lookup.
|
||||||
template <typename T, typename Traits>
|
template <typename T, base::RawPtrTraits Traits>
|
||||||
struct less<raw_ptr<T, Traits>> {
|
struct less<raw_ptr<T, Traits>> {
|
||||||
using Impl = typename raw_ptr<T, Traits>::Impl;
|
using Impl = typename raw_ptr<T, Traits>::Impl;
|
||||||
using is_transparent = void;
|
using is_transparent = void;
|
||||||
@ -1385,7 +1367,7 @@ struct less<raw_ptr<T, Traits>> {
|
|||||||
// Define for cases where raw_ptr<T> holds a pointer to an array of type T.
|
// Define for cases where raw_ptr<T> holds a pointer to an array of type T.
|
||||||
// This is consistent with definition of std::iterator_traits<T*>.
|
// This is consistent with definition of std::iterator_traits<T*>.
|
||||||
// Algorithms like std::binary_search need that.
|
// Algorithms like std::binary_search need that.
|
||||||
template <typename T, typename Traits>
|
template <typename T, base::RawPtrTraits Traits>
|
||||||
struct iterator_traits<raw_ptr<T, Traits>> {
|
struct iterator_traits<raw_ptr<T, Traits>> {
|
||||||
using difference_type = ptrdiff_t;
|
using difference_type = ptrdiff_t;
|
||||||
using value_type = std::remove_cv_t<T>;
|
using value_type = std::remove_cv_t<T>;
|
||||||
@ -1394,6 +1376,33 @@ struct iterator_traits<raw_ptr<T, Traits>> {
|
|||||||
using iterator_category = std::random_access_iterator_tag;
|
using iterator_category = std::random_access_iterator_tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(_LIBCPP_VERSION)
|
||||||
|
// Specialize std::pointer_traits. The latter is required to obtain the
|
||||||
|
// underlying raw pointer in the std::to_address(pointer) overload.
|
||||||
|
// Implementing the pointer_traits is the standard blessed way to customize
|
||||||
|
// `std::to_address(pointer)` in C++20 [3].
|
||||||
|
//
|
||||||
|
// [1] https://wg21.link/pointer.traits.optmem
|
||||||
|
|
||||||
|
template <typename T, ::base::RawPtrTraits Traits>
|
||||||
|
struct pointer_traits<::raw_ptr<T, Traits>> {
|
||||||
|
using pointer = ::raw_ptr<T, Traits>;
|
||||||
|
using element_type = T;
|
||||||
|
using difference_type = ptrdiff_t;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
using rebind = ::raw_ptr<U, Traits>;
|
||||||
|
|
||||||
|
static constexpr pointer pointer_to(element_type& r) noexcept {
|
||||||
|
return pointer(&r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr element_type* to_address(pointer p) noexcept {
|
||||||
|
return p.get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif // defined(_LIBCPP_VERSION)
|
||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_PTR_H_
|
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_PTR_H_
|
||||||
|
@ -12,13 +12,34 @@
|
|||||||
namespace base::internal {
|
namespace base::internal {
|
||||||
|
|
||||||
PA_NO_SANITIZE("address")
|
PA_NO_SANITIZE("address")
|
||||||
bool RawPtrAsanUnownedImpl::EndOfAliveAllocation(const volatile void* ptr) {
|
bool EndOfAliveAllocation(const volatile void* ptr, bool is_adjustable_ptr) {
|
||||||
uintptr_t address = reinterpret_cast<uintptr_t>(ptr);
|
uintptr_t address = reinterpret_cast<uintptr_t>(ptr);
|
||||||
return __asan_region_is_poisoned(reinterpret_cast<void*>(address), 1) &&
|
|
||||||
|
// Normally, we probe the first byte of an object, but in cases of pointer
|
||||||
|
// arithmetic, we may be probing subsequent bytes, including the legal
|
||||||
|
// "end + 1" position.
|
||||||
|
//
|
||||||
|
// Alas, ASAN will claim an unmapped page is unpoisoned, so willfully ignore
|
||||||
|
// the fist address of a page, since "end + 1" of an object allocated exactly
|
||||||
|
// up to a page boundary will SEGV on probe. This will cause false negatives
|
||||||
|
// for pointers that happen to be page aligned, which is undesirable but
|
||||||
|
// necessary for now.
|
||||||
|
//
|
||||||
|
// We minimize the consequences by using the pointer arithmetic flag in
|
||||||
|
// higher levels to conditionalize this suppression.
|
||||||
|
//
|
||||||
|
// TODO(tsepez): this may still fail for a non-accessible but non-null
|
||||||
|
// return from, say, malloc(0) which happens to be page-aligned.
|
||||||
|
//
|
||||||
|
// TODO(tsepez): enforce the pointer arithmetic flag. Until then, we
|
||||||
|
// may fail here if a pointer requires the flag but is lacking it.
|
||||||
|
return is_adjustable_ptr &&
|
||||||
|
((address & 0x0fff) == 0 ||
|
||||||
|
__asan_region_is_poisoned(reinterpret_cast<void*>(address), 1)) &&
|
||||||
!__asan_region_is_poisoned(reinterpret_cast<void*>(address - 1), 1);
|
!__asan_region_is_poisoned(reinterpret_cast<void*>(address - 1), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RawPtrAsanUnownedImpl::LikelySmuggledScalar(const volatile void* ptr) {
|
bool LikelySmuggledScalar(const volatile void* ptr) {
|
||||||
intptr_t address = reinterpret_cast<intptr_t>(ptr);
|
intptr_t address = reinterpret_cast<intptr_t>(ptr);
|
||||||
return address < 0x4000; // Negative or small positive.
|
return address < 0x4000; // Negative or small positive.
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,10 @@
|
|||||||
|
|
||||||
namespace base::internal {
|
namespace base::internal {
|
||||||
|
|
||||||
|
bool EndOfAliveAllocation(const volatile void* ptr, bool is_adjustable_ptr);
|
||||||
|
bool LikelySmuggledScalar(const volatile void* ptr);
|
||||||
|
|
||||||
|
template <bool IsAdjustablePtr>
|
||||||
struct RawPtrAsanUnownedImpl {
|
struct RawPtrAsanUnownedImpl {
|
||||||
// Wraps a pointer.
|
// Wraps a pointer.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -91,14 +95,11 @@ struct RawPtrAsanUnownedImpl {
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
static void ProbeForLowSeverityLifetimeIssue(T* wrapped_ptr) {
|
static void ProbeForLowSeverityLifetimeIssue(T* wrapped_ptr) {
|
||||||
if (wrapped_ptr && !LikelySmuggledScalar(wrapped_ptr) &&
|
if (wrapped_ptr && !LikelySmuggledScalar(wrapped_ptr) &&
|
||||||
!EndOfAliveAllocation(wrapped_ptr)) {
|
!EndOfAliveAllocation(wrapped_ptr, IsAdjustablePtr)) {
|
||||||
reinterpret_cast<const volatile uint8_t*>(wrapped_ptr)[0];
|
reinterpret_cast<const volatile uint8_t*>(wrapped_ptr)[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool EndOfAliveAllocation(const volatile void* ptr);
|
|
||||||
static bool LikelySmuggledScalar(const volatile void* ptr);
|
|
||||||
|
|
||||||
// `WrapRawPtrForDuplication` and `UnsafelyUnwrapPtrForDuplication` are used
|
// `WrapRawPtrForDuplication` and `UnsafelyUnwrapPtrForDuplication` are used
|
||||||
// to create a new raw_ptr<T> from another raw_ptr<T> of a different flavor.
|
// to create a new raw_ptr<T> from another raw_ptr<T> of a different flavor.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "base/allocator/partition_allocator/partition_address_space.h"
|
#include "base/allocator/partition_allocator/partition_address_space.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/component_export.h"
|
||||||
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_forward.h"
|
#include "base/allocator/partition_allocator/partition_alloc_forward.h"
|
||||||
@ -133,7 +134,7 @@ struct RawPtrBackupRefImpl {
|
|||||||
#endif
|
#endif
|
||||||
AcquireInternal(address);
|
AcquireInternal(address);
|
||||||
} else {
|
} else {
|
||||||
#if !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
#if PA_HAS_BUILTIN(__builtin_constant_p)
|
#if PA_HAS_BUILTIN(__builtin_constant_p)
|
||||||
// Similarly to `IsSupportedAndNotNull` above, elide the
|
// Similarly to `IsSupportedAndNotNull` above, elide the
|
||||||
// `BanSuperPageFromBRPPool` call if the compiler can prove that `address`
|
// `BanSuperPageFromBRPPool` call if the compiler can prove that `address`
|
||||||
@ -148,7 +149,7 @@ struct RawPtrBackupRefImpl {
|
|||||||
partition_alloc::internal::AddressPoolManagerBitmap::
|
partition_alloc::internal::AddressPoolManagerBitmap::
|
||||||
BanSuperPageFromBRPPool(address);
|
BanSuperPageFromBRPPool(address);
|
||||||
}
|
}
|
||||||
#endif // !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif // !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
}
|
}
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
// Copyright 2023 The Chromium Authors
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_PTR_TEST_SUPPORT_H_
|
||||||
|
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_PTR_TEST_SUPPORT_H_
|
||||||
|
|
||||||
|
#include "testing/gmock/include/gmock/gmock.h"
|
||||||
|
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||||
|
|
||||||
|
// Struct intended to be used with designated initializers and passed
|
||||||
|
// to the `CountersMatch()` matcher.
|
||||||
|
//
|
||||||
|
// `CountingImplType` isn't used directly; it tells the `CountersMatch`
|
||||||
|
// matcher which impl's static members should be checked.
|
||||||
|
template <typename CountingImplType>
|
||||||
|
struct CountingRawPtrExpectations {
|
||||||
|
absl::optional<int> wrap_raw_ptr_cnt;
|
||||||
|
absl::optional<int> release_wrapped_ptr_cnt;
|
||||||
|
absl::optional<int> get_for_dereference_cnt;
|
||||||
|
absl::optional<int> get_for_extraction_cnt;
|
||||||
|
absl::optional<int> get_for_comparison_cnt;
|
||||||
|
absl::optional<int> wrapped_ptr_swap_cnt;
|
||||||
|
absl::optional<int> wrapped_ptr_less_cnt;
|
||||||
|
absl::optional<int> pointer_to_member_operator_cnt;
|
||||||
|
absl::optional<int> wrap_raw_ptr_for_dup_cnt;
|
||||||
|
absl::optional<int> get_for_duplication_cnt;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define REPORT_UNEQUAL_RAW_PTR_COUNTER(member_name, CounterClassImpl) \
|
||||||
|
{ \
|
||||||
|
if (arg.member_name.has_value() && \
|
||||||
|
arg.member_name.value() != CounterClassImpl::member_name) { \
|
||||||
|
*result_listener << "Expected `" #member_name "` to be " \
|
||||||
|
<< arg.member_name.value() << " but got " \
|
||||||
|
<< CounterClassImpl::member_name << "; "; \
|
||||||
|
result = false; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#define REPORT_UNEQUAL_RAW_PTR_COUNTERS(result, CounterClassImpl) \
|
||||||
|
{ \
|
||||||
|
result = true; \
|
||||||
|
REPORT_UNEQUAL_RAW_PTR_COUNTER(wrap_raw_ptr_cnt, CounterClassImpl) \
|
||||||
|
REPORT_UNEQUAL_RAW_PTR_COUNTER(release_wrapped_ptr_cnt, CounterClassImpl) \
|
||||||
|
REPORT_UNEQUAL_RAW_PTR_COUNTER(get_for_dereference_cnt, CounterClassImpl) \
|
||||||
|
REPORT_UNEQUAL_RAW_PTR_COUNTER(get_for_extraction_cnt, CounterClassImpl) \
|
||||||
|
REPORT_UNEQUAL_RAW_PTR_COUNTER(get_for_comparison_cnt, CounterClassImpl) \
|
||||||
|
REPORT_UNEQUAL_RAW_PTR_COUNTER(wrapped_ptr_swap_cnt, CounterClassImpl) \
|
||||||
|
REPORT_UNEQUAL_RAW_PTR_COUNTER(wrapped_ptr_less_cnt, CounterClassImpl) \
|
||||||
|
REPORT_UNEQUAL_RAW_PTR_COUNTER(pointer_to_member_operator_cnt, \
|
||||||
|
CounterClassImpl) \
|
||||||
|
REPORT_UNEQUAL_RAW_PTR_COUNTER(wrap_raw_ptr_for_dup_cnt, CounterClassImpl) \
|
||||||
|
REPORT_UNEQUAL_RAW_PTR_COUNTER(get_for_duplication_cnt, CounterClassImpl) \
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matcher used with `CountingRawPtr`. Provides slightly shorter
|
||||||
|
// boilerplate for verifying counts. This inner function is detached
|
||||||
|
// from the `MATCHER` to isolate the templating.
|
||||||
|
template <typename CountingImplType>
|
||||||
|
bool CountersMatchImpl(const CountingRawPtrExpectations<CountingImplType>& arg,
|
||||||
|
testing::MatchResultListener* result_listener) {
|
||||||
|
bool result = true;
|
||||||
|
REPORT_UNEQUAL_RAW_PTR_COUNTERS(result, CountingImplType);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implicit `arg` has type `CountingRawPtrExpectations`, specialized for
|
||||||
|
// the specific counting impl.
|
||||||
|
MATCHER(CountersMatch, "counting impl has specified counters") {
|
||||||
|
return CountersMatchImpl(arg, result_listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef REPORT_UNEQUAL_RAW_PTR_COUNTERS
|
||||||
|
#undef REPORT_UNEQUAL_RAW_PTR_COUNTER
|
||||||
|
|
||||||
|
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_PTR_TEST_SUPPORT_H_
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
|
|
||||||
template <class T, typename Traits>
|
template <class T, RawPtrTraits Traits>
|
||||||
class raw_ref;
|
class raw_ref;
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
@ -25,7 +25,7 @@ namespace internal {
|
|||||||
template <class T>
|
template <class T>
|
||||||
struct is_raw_ref : std::false_type {};
|
struct is_raw_ref : std::false_type {};
|
||||||
|
|
||||||
template <class T, typename Traits>
|
template <class T, RawPtrTraits Traits>
|
||||||
struct is_raw_ref<::base::raw_ref<T, Traits>> : std::true_type {};
|
struct is_raw_ref<::base::raw_ref<T, Traits>> : std::true_type {};
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
@ -53,7 +53,7 @@ constexpr inline bool is_raw_ref_v = is_raw_ref<T>::value;
|
|||||||
// Unlike a native `T&` reference, a mutable `raw_ref<T>` can be changed
|
// Unlike a native `T&` reference, a mutable `raw_ref<T>` can be changed
|
||||||
// independent of the underlying `T`, similar to `std::reference_wrapper`. That
|
// independent of the underlying `T`, similar to `std::reference_wrapper`. That
|
||||||
// means the reference inside it can be moved and reassigned.
|
// means the reference inside it can be moved and reassigned.
|
||||||
template <class T, typename Traits = raw_ptr_traits::TraitBundle<>>
|
template <class T, RawPtrTraits Traits = RawPtrTraits::kEmpty>
|
||||||
class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ref {
|
class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ref {
|
||||||
// operator* is used with the expectation of GetForExtraction semantics:
|
// operator* is used with the expectation of GetForExtraction semantics:
|
||||||
//
|
//
|
||||||
@ -63,9 +63,7 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ref {
|
|||||||
// The implementation of operator* provides GetForDereference semantics, and
|
// The implementation of operator* provides GetForDereference semantics, and
|
||||||
// this results in spurious crashes in BRP-ASan builds, so we need to disable
|
// this results in spurious crashes in BRP-ASan builds, so we need to disable
|
||||||
// hooks that provide BRP-ASan instrumentation for raw_ref.
|
// hooks that provide BRP-ASan instrumentation for raw_ref.
|
||||||
using Inner = raw_ptr<
|
using Inner = raw_ptr<T, Traits | RawPtrTraits::kDisableHooks>;
|
||||||
T,
|
|
||||||
typename Traits::template AddTraitT<raw_ptr_traits::DisableHooks>>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Impl = typename Inner::Impl;
|
using Impl = typename Inner::Impl;
|
||||||
@ -81,7 +79,8 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ref {
|
|||||||
internal::MTECheckedPtrImplPartitionAllocSupport>> ||
|
internal::MTECheckedPtrImplPartitionAllocSupport>> ||
|
||||||
#endif // PA_CONFIG(ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
|
#endif // PA_CONFIG(ENABLE_MTE_CHECKED_PTR_SUPPORT_WITH_64_BITS_POINTERS)
|
||||||
#if BUILDFLAG(USE_ASAN_UNOWNED_PTR)
|
#if BUILDFLAG(USE_ASAN_UNOWNED_PTR)
|
||||||
std::is_same_v<Impl, internal::RawPtrAsanUnownedImpl> ||
|
std::is_same_v<Impl, internal::RawPtrAsanUnownedImpl<true>> ||
|
||||||
|
std::is_same_v<Impl, internal::RawPtrAsanUnownedImpl<false>> ||
|
||||||
#endif // BUILDFLAG(USE_ASAN_UNOWNED_PTR)
|
#endif // BUILDFLAG(USE_ASAN_UNOWNED_PTR)
|
||||||
std::is_same_v<Impl, internal::RawPtrNoOpImpl>;
|
std::is_same_v<Impl, internal::RawPtrNoOpImpl>;
|
||||||
|
|
||||||
@ -98,24 +97,24 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ref {
|
|||||||
raw_ref& operator=(const T&& p) = delete;
|
raw_ref& operator=(const T&& p) = delete;
|
||||||
|
|
||||||
PA_ALWAYS_INLINE raw_ref(const raw_ref& p) noexcept : inner_(p.inner_) {
|
PA_ALWAYS_INLINE raw_ref(const raw_ref& p) noexcept : inner_(p.inner_) {
|
||||||
PA_RAW_PTR_CHECK(inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(inner_); // Catch use-after-move.
|
||||||
}
|
}
|
||||||
|
|
||||||
PA_ALWAYS_INLINE raw_ref(raw_ref&& p) noexcept : inner_(std::move(p.inner_)) {
|
PA_ALWAYS_INLINE raw_ref(raw_ref&& p) noexcept : inner_(std::move(p.inner_)) {
|
||||||
PA_RAW_PTR_CHECK(inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(inner_); // Catch use-after-move.
|
||||||
if constexpr (need_clear_after_move) {
|
if constexpr (need_clear_after_move) {
|
||||||
p.inner_ = nullptr;
|
p.inner_ = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PA_ALWAYS_INLINE raw_ref& operator=(const raw_ref& p) noexcept {
|
PA_ALWAYS_INLINE raw_ref& operator=(const raw_ref& p) noexcept {
|
||||||
PA_RAW_PTR_CHECK(p.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(p.inner_); // Catch use-after-move.
|
||||||
inner_.operator=(p.inner_);
|
inner_.operator=(p.inner_);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
PA_ALWAYS_INLINE raw_ref& operator=(raw_ref&& p) noexcept {
|
PA_ALWAYS_INLINE raw_ref& operator=(raw_ref&& p) noexcept {
|
||||||
PA_RAW_PTR_CHECK(p.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(p.inner_); // Catch use-after-move.
|
||||||
inner_.operator=(std::move(p.inner_));
|
inner_.operator=(std::move(p.inner_));
|
||||||
if constexpr (need_clear_after_move) {
|
if constexpr (need_clear_after_move) {
|
||||||
p.inner_ = nullptr;
|
p.inner_ = nullptr;
|
||||||
@ -128,14 +127,14 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ref {
|
|||||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
PA_ALWAYS_INLINE raw_ref(const raw_ref<U, Traits>& p) noexcept
|
PA_ALWAYS_INLINE raw_ref(const raw_ref<U, Traits>& p) noexcept
|
||||||
: inner_(p.inner_) {
|
: inner_(p.inner_) {
|
||||||
PA_RAW_PTR_CHECK(inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(inner_); // Catch use-after-move.
|
||||||
}
|
}
|
||||||
// Deliberately implicit in order to support implicit upcast.
|
// Deliberately implicit in order to support implicit upcast.
|
||||||
template <class U, class = std::enable_if_t<std::is_convertible_v<U&, T&>>>
|
template <class U, class = std::enable_if_t<std::is_convertible_v<U&, T&>>>
|
||||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||||
PA_ALWAYS_INLINE raw_ref(raw_ref<U, Traits>&& p) noexcept
|
PA_ALWAYS_INLINE raw_ref(raw_ref<U, Traits>&& p) noexcept
|
||||||
: inner_(std::move(p.inner_)) {
|
: inner_(std::move(p.inner_)) {
|
||||||
PA_RAW_PTR_CHECK(inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(inner_); // Catch use-after-move.
|
||||||
if constexpr (need_clear_after_move) {
|
if constexpr (need_clear_after_move) {
|
||||||
p.inner_ = nullptr;
|
p.inner_ = nullptr;
|
||||||
}
|
}
|
||||||
@ -149,13 +148,13 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ref {
|
|||||||
// Upcast assignment
|
// Upcast assignment
|
||||||
template <class U, class = std::enable_if_t<std::is_convertible_v<U&, T&>>>
|
template <class U, class = std::enable_if_t<std::is_convertible_v<U&, T&>>>
|
||||||
PA_ALWAYS_INLINE raw_ref& operator=(const raw_ref<U, Traits>& p) noexcept {
|
PA_ALWAYS_INLINE raw_ref& operator=(const raw_ref<U, Traits>& p) noexcept {
|
||||||
PA_RAW_PTR_CHECK(p.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(p.inner_); // Catch use-after-move.
|
||||||
inner_.operator=(p.inner_);
|
inner_.operator=(p.inner_);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
template <class U, class = std::enable_if_t<std::is_convertible_v<U&, T&>>>
|
template <class U, class = std::enable_if_t<std::is_convertible_v<U&, T&>>>
|
||||||
PA_ALWAYS_INLINE raw_ref& operator=(raw_ref<U, Traits>&& p) noexcept {
|
PA_ALWAYS_INLINE raw_ref& operator=(raw_ref<U, Traits>&& p) noexcept {
|
||||||
PA_RAW_PTR_CHECK(p.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(p.inner_); // Catch use-after-move.
|
||||||
inner_.operator=(std::move(p.inner_));
|
inner_.operator=(std::move(p.inner_));
|
||||||
if constexpr (need_clear_after_move) {
|
if constexpr (need_clear_after_move) {
|
||||||
p.inner_ = nullptr;
|
p.inner_ = nullptr;
|
||||||
@ -164,7 +163,7 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ref {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PA_ALWAYS_INLINE T& operator*() const {
|
PA_ALWAYS_INLINE T& operator*() const {
|
||||||
PA_RAW_PTR_CHECK(inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(inner_); // Catch use-after-move.
|
||||||
return inner_.operator*();
|
return inner_.operator*();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,12 +172,12 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ref {
|
|||||||
// used in place of operator*() when the memory referred to by the reference
|
// used in place of operator*() when the memory referred to by the reference
|
||||||
// is not immediately going to be accessed.
|
// is not immediately going to be accessed.
|
||||||
PA_ALWAYS_INLINE T& get() const {
|
PA_ALWAYS_INLINE T& get() const {
|
||||||
PA_RAW_PTR_CHECK(inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(inner_); // Catch use-after-move.
|
||||||
return *inner_.get();
|
return *inner_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
PA_ALWAYS_INLINE T* operator->() const PA_ATTRIBUTE_RETURNS_NONNULL {
|
PA_ALWAYS_INLINE T* operator->() const PA_ATTRIBUTE_RETURNS_NONNULL {
|
||||||
PA_RAW_PTR_CHECK(inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(inner_); // Catch use-after-move.
|
||||||
return inner_.operator->();
|
return inner_.operator->();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,123 +190,142 @@ class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ref {
|
|||||||
}
|
}
|
||||||
|
|
||||||
friend PA_ALWAYS_INLINE void swap(raw_ref& lhs, raw_ref& rhs) noexcept {
|
friend PA_ALWAYS_INLINE void swap(raw_ref& lhs, raw_ref& rhs) noexcept {
|
||||||
PA_RAW_PTR_CHECK(lhs.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
|
||||||
PA_RAW_PTR_CHECK(rhs.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
|
||||||
swap(lhs.inner_, rhs.inner_);
|
swap(lhs.inner_, rhs.inner_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class U>
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
friend PA_ALWAYS_INLINE bool operator==(const raw_ref& lhs,
|
friend PA_ALWAYS_INLINE bool operator==(const raw_ref<U, Traits1>& lhs,
|
||||||
const raw_ref<U, Traits>& rhs) {
|
const raw_ref<V, Traits2>& rhs);
|
||||||
PA_RAW_PTR_CHECK(lhs.inner_.get()); // Catch use-after-move.
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
PA_RAW_PTR_CHECK(rhs.inner_.get()); // Catch use-after-move.
|
friend PA_ALWAYS_INLINE bool operator!=(const raw_ref<U, Traits1>& lhs,
|
||||||
return lhs.inner_ == rhs.inner_;
|
const raw_ref<V, Traits2>& rhs);
|
||||||
}
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
template <class U>
|
friend PA_ALWAYS_INLINE bool operator<(const raw_ref<U, Traits1>& lhs,
|
||||||
friend PA_ALWAYS_INLINE bool operator!=(const raw_ref& lhs,
|
const raw_ref<V, Traits2>& rhs);
|
||||||
const raw_ref<U, Traits>& rhs) {
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
PA_RAW_PTR_CHECK(lhs.inner_.get()); // Catch use-after-move.
|
friend PA_ALWAYS_INLINE bool operator>(const raw_ref<U, Traits1>& lhs,
|
||||||
PA_RAW_PTR_CHECK(rhs.inner_.get()); // Catch use-after-move.
|
const raw_ref<V, Traits2>& rhs);
|
||||||
return lhs.inner_ != rhs.inner_;
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
}
|
friend PA_ALWAYS_INLINE bool operator<=(const raw_ref<U, Traits1>& lhs,
|
||||||
template <class U>
|
const raw_ref<V, Traits2>& rhs);
|
||||||
friend PA_ALWAYS_INLINE bool operator<(const raw_ref& lhs,
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
const raw_ref<U, Traits>& rhs) {
|
friend PA_ALWAYS_INLINE bool operator>=(const raw_ref<U, Traits1>& lhs,
|
||||||
PA_RAW_PTR_CHECK(lhs.inner_.get()); // Catch use-after-move.
|
const raw_ref<V, Traits2>& rhs);
|
||||||
PA_RAW_PTR_CHECK(rhs.inner_.get()); // Catch use-after-move.
|
|
||||||
return lhs.inner_ < rhs.inner_;
|
|
||||||
}
|
|
||||||
template <class U>
|
|
||||||
friend PA_ALWAYS_INLINE bool operator>(const raw_ref& lhs,
|
|
||||||
const raw_ref<U, Traits>& rhs) {
|
|
||||||
PA_RAW_PTR_CHECK(lhs.inner_.get()); // Catch use-after-move.
|
|
||||||
PA_RAW_PTR_CHECK(rhs.inner_.get()); // Catch use-after-move.
|
|
||||||
return lhs.inner_ > rhs.inner_;
|
|
||||||
}
|
|
||||||
template <class U>
|
|
||||||
friend PA_ALWAYS_INLINE bool operator<=(const raw_ref& lhs,
|
|
||||||
const raw_ref<U, Traits>& rhs) {
|
|
||||||
PA_RAW_PTR_CHECK(lhs.inner_.get()); // Catch use-after-move.
|
|
||||||
PA_RAW_PTR_CHECK(rhs.inner_.get()); // Catch use-after-move.
|
|
||||||
return lhs.inner_ <= rhs.inner_;
|
|
||||||
}
|
|
||||||
template <class U>
|
|
||||||
friend PA_ALWAYS_INLINE bool operator>=(const raw_ref& lhs,
|
|
||||||
const raw_ref<U, Traits>& rhs) {
|
|
||||||
PA_RAW_PTR_CHECK(lhs.inner_.get()); // Catch use-after-move.
|
|
||||||
PA_RAW_PTR_CHECK(rhs.inner_.get()); // Catch use-after-move.
|
|
||||||
return lhs.inner_ >= rhs.inner_;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
||||||
friend PA_ALWAYS_INLINE bool operator==(const raw_ref& lhs, const U& rhs) {
|
friend PA_ALWAYS_INLINE bool operator==(const raw_ref& lhs, const U& rhs) {
|
||||||
PA_RAW_PTR_CHECK(lhs.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
|
||||||
return lhs.inner_ == &rhs;
|
return lhs.inner_ == &rhs;
|
||||||
}
|
}
|
||||||
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
||||||
friend PA_ALWAYS_INLINE bool operator!=(const raw_ref& lhs, const U& rhs) {
|
friend PA_ALWAYS_INLINE bool operator!=(const raw_ref& lhs, const U& rhs) {
|
||||||
PA_RAW_PTR_CHECK(lhs.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
|
||||||
return lhs.inner_ != &rhs;
|
return lhs.inner_ != &rhs;
|
||||||
}
|
}
|
||||||
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
||||||
friend PA_ALWAYS_INLINE bool operator<(const raw_ref& lhs, const U& rhs) {
|
friend PA_ALWAYS_INLINE bool operator<(const raw_ref& lhs, const U& rhs) {
|
||||||
PA_RAW_PTR_CHECK(lhs.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
|
||||||
return lhs.inner_ < &rhs;
|
return lhs.inner_ < &rhs;
|
||||||
}
|
}
|
||||||
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
||||||
friend PA_ALWAYS_INLINE bool operator>(const raw_ref& lhs, const U& rhs) {
|
friend PA_ALWAYS_INLINE bool operator>(const raw_ref& lhs, const U& rhs) {
|
||||||
PA_RAW_PTR_CHECK(lhs.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
|
||||||
return lhs.inner_ > &rhs;
|
return lhs.inner_ > &rhs;
|
||||||
}
|
}
|
||||||
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
||||||
friend PA_ALWAYS_INLINE bool operator<=(const raw_ref& lhs, const U& rhs) {
|
friend PA_ALWAYS_INLINE bool operator<=(const raw_ref& lhs, const U& rhs) {
|
||||||
PA_RAW_PTR_CHECK(lhs.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
|
||||||
return lhs.inner_ <= &rhs;
|
return lhs.inner_ <= &rhs;
|
||||||
}
|
}
|
||||||
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
||||||
friend PA_ALWAYS_INLINE bool operator>=(const raw_ref& lhs, const U& rhs) {
|
friend PA_ALWAYS_INLINE bool operator>=(const raw_ref& lhs, const U& rhs) {
|
||||||
PA_RAW_PTR_CHECK(lhs.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
|
||||||
return lhs.inner_ >= &rhs;
|
return lhs.inner_ >= &rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
||||||
friend PA_ALWAYS_INLINE bool operator==(const U& lhs, const raw_ref& rhs) {
|
friend PA_ALWAYS_INLINE bool operator==(const U& lhs, const raw_ref& rhs) {
|
||||||
PA_RAW_PTR_CHECK(rhs.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
|
||||||
return &lhs == rhs.inner_;
|
return &lhs == rhs.inner_;
|
||||||
}
|
}
|
||||||
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
||||||
friend PA_ALWAYS_INLINE bool operator!=(const U& lhs, const raw_ref& rhs) {
|
friend PA_ALWAYS_INLINE bool operator!=(const U& lhs, const raw_ref& rhs) {
|
||||||
PA_RAW_PTR_CHECK(rhs.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
|
||||||
return &lhs != rhs.inner_;
|
return &lhs != rhs.inner_;
|
||||||
}
|
}
|
||||||
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
||||||
friend PA_ALWAYS_INLINE bool operator<(const U& lhs, const raw_ref& rhs) {
|
friend PA_ALWAYS_INLINE bool operator<(const U& lhs, const raw_ref& rhs) {
|
||||||
PA_RAW_PTR_CHECK(rhs.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
|
||||||
return &lhs < rhs.inner_;
|
return &lhs < rhs.inner_;
|
||||||
}
|
}
|
||||||
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
||||||
friend PA_ALWAYS_INLINE bool operator>(const U& lhs, const raw_ref& rhs) {
|
friend PA_ALWAYS_INLINE bool operator>(const U& lhs, const raw_ref& rhs) {
|
||||||
PA_RAW_PTR_CHECK(rhs.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
|
||||||
return &lhs > rhs.inner_;
|
return &lhs > rhs.inner_;
|
||||||
}
|
}
|
||||||
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
||||||
friend PA_ALWAYS_INLINE bool operator<=(const U& lhs, const raw_ref& rhs) {
|
friend PA_ALWAYS_INLINE bool operator<=(const U& lhs, const raw_ref& rhs) {
|
||||||
PA_RAW_PTR_CHECK(rhs.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
|
||||||
return &lhs <= rhs.inner_;
|
return &lhs <= rhs.inner_;
|
||||||
}
|
}
|
||||||
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
template <class U, class = std::enable_if_t<!internal::is_raw_ref_v<U>, void>>
|
||||||
friend PA_ALWAYS_INLINE bool operator>=(const U& lhs, const raw_ref& rhs) {
|
friend PA_ALWAYS_INLINE bool operator>=(const U& lhs, const raw_ref& rhs) {
|
||||||
PA_RAW_PTR_CHECK(rhs.inner_.get()); // Catch use-after-move.
|
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
|
||||||
return &lhs >= rhs.inner_;
|
return &lhs >= rhs.inner_;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class U, typename R>
|
template <class U, RawPtrTraits R>
|
||||||
friend class raw_ref;
|
friend class raw_ref;
|
||||||
|
|
||||||
Inner inner_;
|
Inner inner_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
|
PA_ALWAYS_INLINE bool operator==(const raw_ref<U, Traits1>& lhs,
|
||||||
|
const raw_ref<V, Traits2>& rhs) {
|
||||||
|
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
|
||||||
|
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
|
||||||
|
return lhs.inner_ == rhs.inner_;
|
||||||
|
}
|
||||||
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
|
PA_ALWAYS_INLINE bool operator!=(const raw_ref<U, Traits1>& lhs,
|
||||||
|
const raw_ref<V, Traits2>& rhs) {
|
||||||
|
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
|
||||||
|
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
|
||||||
|
return lhs.inner_ != rhs.inner_;
|
||||||
|
}
|
||||||
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
|
PA_ALWAYS_INLINE bool operator<(const raw_ref<U, Traits1>& lhs,
|
||||||
|
const raw_ref<V, Traits2>& rhs) {
|
||||||
|
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
|
||||||
|
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
|
||||||
|
return lhs.inner_ < rhs.inner_;
|
||||||
|
}
|
||||||
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
|
PA_ALWAYS_INLINE bool operator>(const raw_ref<U, Traits1>& lhs,
|
||||||
|
const raw_ref<V, Traits2>& rhs) {
|
||||||
|
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
|
||||||
|
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
|
||||||
|
return lhs.inner_ > rhs.inner_;
|
||||||
|
}
|
||||||
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
|
PA_ALWAYS_INLINE bool operator<=(const raw_ref<U, Traits1>& lhs,
|
||||||
|
const raw_ref<V, Traits2>& rhs) {
|
||||||
|
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
|
||||||
|
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
|
||||||
|
return lhs.inner_ <= rhs.inner_;
|
||||||
|
}
|
||||||
|
template <typename U, typename V, RawPtrTraits Traits1, RawPtrTraits Traits2>
|
||||||
|
PA_ALWAYS_INLINE bool operator>=(const raw_ref<U, Traits1>& lhs,
|
||||||
|
const raw_ref<V, Traits2>& rhs) {
|
||||||
|
PA_RAW_PTR_CHECK(lhs.inner_); // Catch use-after-move.
|
||||||
|
PA_RAW_PTR_CHECK(rhs.inner_); // Catch use-after-move.
|
||||||
|
return lhs.inner_ >= rhs.inner_;
|
||||||
|
}
|
||||||
|
|
||||||
// CTAD deduction guide.
|
// CTAD deduction guide.
|
||||||
template <class T>
|
template <class T>
|
||||||
raw_ref(T&) -> raw_ref<T>;
|
raw_ref(T&) -> raw_ref<T>;
|
||||||
@ -318,7 +336,7 @@ raw_ref(const T&) -> raw_ref<const T>;
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
struct IsRawRef : std::false_type {};
|
struct IsRawRef : std::false_type {};
|
||||||
|
|
||||||
template <typename T, typename Traits>
|
template <typename T, RawPtrTraits Traits>
|
||||||
struct IsRawRef<raw_ref<T, Traits>> : std::true_type {};
|
struct IsRawRef<raw_ref<T, Traits>> : std::true_type {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -329,7 +347,7 @@ struct RemoveRawRef {
|
|||||||
using type = T;
|
using type = T;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename Traits>
|
template <typename T, RawPtrTraits Traits>
|
||||||
struct RemoveRawRef<raw_ref<T, Traits>> {
|
struct RemoveRawRef<raw_ref<T, Traits>> {
|
||||||
using type = T;
|
using type = T;
|
||||||
};
|
};
|
||||||
@ -345,7 +363,7 @@ namespace std {
|
|||||||
|
|
||||||
// Override so set/map lookups do not create extra raw_ref. This also
|
// Override so set/map lookups do not create extra raw_ref. This also
|
||||||
// allows C++ references to be used for lookup.
|
// allows C++ references to be used for lookup.
|
||||||
template <typename T, typename Traits>
|
template <typename T, base::RawPtrTraits Traits>
|
||||||
struct less<raw_ref<T, Traits>> {
|
struct less<raw_ref<T, Traits>> {
|
||||||
using Impl = typename raw_ref<T, Traits>::Impl;
|
using Impl = typename raw_ref<T, Traits>::Impl;
|
||||||
using is_transparent = void;
|
using is_transparent = void;
|
||||||
@ -367,6 +385,37 @@ struct less<raw_ref<T, Traits>> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(_LIBCPP_VERSION)
|
||||||
|
// Specialize std::pointer_traits. The latter is required to obtain the
|
||||||
|
// underlying raw pointer in the std::to_address(pointer) overload.
|
||||||
|
// Implementing the pointer_traits is the standard blessed way to customize
|
||||||
|
// `std::to_address(pointer)` in C++20 [3].
|
||||||
|
//
|
||||||
|
// [1] https://wg21.link/pointer.traits.optmem
|
||||||
|
|
||||||
|
template <typename T, ::base::RawPtrTraits Traits>
|
||||||
|
struct pointer_traits<::raw_ref<T, Traits>> {
|
||||||
|
using pointer = ::raw_ref<T, Traits>;
|
||||||
|
using element_type = T;
|
||||||
|
using difference_type = ptrdiff_t;
|
||||||
|
|
||||||
|
template <typename U>
|
||||||
|
using rebind = ::raw_ref<U, Traits>;
|
||||||
|
|
||||||
|
static constexpr pointer pointer_to(element_type& r) noexcept {
|
||||||
|
return pointer(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr element_type* to_address(pointer p) noexcept {
|
||||||
|
// `raw_ref::get` is used instead of raw_ref::operator*`. It provides
|
||||||
|
// GetForExtraction rather rather than GetForDereference semantics (see
|
||||||
|
// raw_ptr.h). This should be used when we we don't know the memory will be
|
||||||
|
// accessed.
|
||||||
|
return &(p.get());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif // defined(_LIBCPP_VERSION)
|
||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_REF_H_
|
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_POINTERS_RAW_REF_H_
|
||||||
|
@ -4,14 +4,16 @@
|
|||||||
|
|
||||||
#include "base/allocator/partition_allocator/reservation_offset_table.h"
|
#include "base/allocator/partition_allocator/reservation_offset_table.h"
|
||||||
|
|
||||||
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
|
|
||||||
namespace partition_alloc::internal {
|
namespace partition_alloc::internal {
|
||||||
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
ReservationOffsetTable::_PaddedReservationOffsetTables
|
ReservationOffsetTable::_PaddedReservationOffsetTables
|
||||||
ReservationOffsetTable::padded_reservation_offset_tables_ PA_PKEY_ALIGN;
|
ReservationOffsetTable::padded_reservation_offset_tables_ PA_PKEY_ALIGN;
|
||||||
#else
|
#else
|
||||||
ReservationOffsetTable::_ReservationOffsetTable
|
ReservationOffsetTable::_ReservationOffsetTable
|
||||||
ReservationOffsetTable::reservation_offset_table_;
|
ReservationOffsetTable::reservation_offset_table_;
|
||||||
#endif
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
} // namespace partition_alloc::internal
|
} // namespace partition_alloc::internal
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#include "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/debug/debugging_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
||||||
#include "base/allocator/partition_allocator/pkey.h"
|
#include "base/allocator/partition_allocator/pkey.h"
|
||||||
#include "base/allocator/partition_allocator/tagging.h"
|
#include "base/allocator/partition_allocator/tagging.h"
|
||||||
@ -67,7 +66,7 @@ static constexpr uint16_t kOffsetTagNormalBuckets =
|
|||||||
// granularity is kSuperPageSize.
|
// granularity is kSuperPageSize.
|
||||||
class PA_COMPONENT_EXPORT(PARTITION_ALLOC) ReservationOffsetTable {
|
class PA_COMPONENT_EXPORT(PARTITION_ALLOC) ReservationOffsetTable {
|
||||||
public:
|
public:
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
// There is one reservation offset table per Pool in 64-bit mode.
|
// There is one reservation offset table per Pool in 64-bit mode.
|
||||||
static constexpr size_t kReservationOffsetTableCoverage = kPoolMaxSize;
|
static constexpr size_t kReservationOffsetTableCoverage = kPoolMaxSize;
|
||||||
static constexpr size_t kReservationOffsetTableLength =
|
static constexpr size_t kReservationOffsetTableLength =
|
||||||
@ -78,7 +77,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) ReservationOffsetTable {
|
|||||||
static constexpr uint64_t kGiB = 1024 * 1024 * 1024ull;
|
static constexpr uint64_t kGiB = 1024 * 1024 * 1024ull;
|
||||||
static constexpr size_t kReservationOffsetTableLength =
|
static constexpr size_t kReservationOffsetTableLength =
|
||||||
4 * kGiB / kSuperPageSize;
|
4 * kGiB / kSuperPageSize;
|
||||||
#endif
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
static_assert(kReservationOffsetTableLength < kOffsetTagNormalBuckets,
|
static_assert(kReservationOffsetTableLength < kOffsetTagNormalBuckets,
|
||||||
"Offsets should be smaller than kOffsetTagNormalBuckets.");
|
"Offsets should be smaller than kOffsetTagNormalBuckets.");
|
||||||
|
|
||||||
@ -95,7 +94,7 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) ReservationOffsetTable {
|
|||||||
offset = kOffsetTagNotAllocated;
|
offset = kOffsetTagNotAllocated;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
// If pkey support is enabled, we need to pkey-tag the tables of the pkey
|
// If pkey support is enabled, we need to pkey-tag the tables of the pkey
|
||||||
// pool. For this, we need to pad the tables so that the pkey ones start on a
|
// pool. For this, we need to pad the tables so that the pkey ones start on a
|
||||||
// page boundary.
|
// page boundary.
|
||||||
@ -109,12 +108,12 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) ReservationOffsetTable {
|
|||||||
#else
|
#else
|
||||||
// A single table for the entire 32-bit address space.
|
// A single table for the entire 32-bit address space.
|
||||||
static PA_CONSTINIT struct _ReservationOffsetTable reservation_offset_table_;
|
static PA_CONSTINIT struct _ReservationOffsetTable reservation_offset_table_;
|
||||||
#endif
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
};
|
};
|
||||||
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
PA_ALWAYS_INLINE uint16_t* GetReservationOffsetTable(pool_handle handle) {
|
PA_ALWAYS_INLINE uint16_t* GetReservationOffsetTable(pool_handle handle) {
|
||||||
PA_DCHECK(0 < handle && handle <= kNumPools);
|
PA_DCHECK(kNullPoolHandle < handle && handle <= kNumPools);
|
||||||
return ReservationOffsetTable::padded_reservation_offset_tables_
|
return ReservationOffsetTable::padded_reservation_offset_tables_
|
||||||
.tables[handle - 1]
|
.tables[handle - 1]
|
||||||
.offsets;
|
.offsets;
|
||||||
@ -144,7 +143,7 @@ PA_ALWAYS_INLINE uint16_t* ReservationOffsetPointer(pool_handle pool,
|
|||||||
ReservationOffsetTable::kReservationOffsetTableLength);
|
ReservationOffsetTable::kReservationOffsetTableLength);
|
||||||
return GetReservationOffsetTable(pool) + table_index;
|
return GetReservationOffsetTable(pool) + table_index;
|
||||||
}
|
}
|
||||||
#else
|
#else // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
PA_ALWAYS_INLINE uint16_t* GetReservationOffsetTable(uintptr_t address) {
|
PA_ALWAYS_INLINE uint16_t* GetReservationOffsetTable(uintptr_t address) {
|
||||||
return ReservationOffsetTable::reservation_offset_table_.offsets;
|
return ReservationOffsetTable::reservation_offset_table_.offsets;
|
||||||
}
|
}
|
||||||
@ -154,10 +153,10 @@ PA_ALWAYS_INLINE const uint16_t* GetReservationOffsetTableEnd(
|
|||||||
return ReservationOffsetTable::reservation_offset_table_.offsets +
|
return ReservationOffsetTable::reservation_offset_table_.offsets +
|
||||||
ReservationOffsetTable::kReservationOffsetTableLength;
|
ReservationOffsetTable::kReservationOffsetTableLength;
|
||||||
}
|
}
|
||||||
#endif
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
PA_ALWAYS_INLINE uint16_t* ReservationOffsetPointer(uintptr_t address) {
|
PA_ALWAYS_INLINE uint16_t* ReservationOffsetPointer(uintptr_t address) {
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
// In 64-bit mode, find the owning Pool and compute the offset from its base.
|
// In 64-bit mode, find the owning Pool and compute the offset from its base.
|
||||||
auto [pool, offset] = GetPoolAndOffset(address);
|
auto [pool, offset] = GetPoolAndOffset(address);
|
||||||
return ReservationOffsetPointer(pool, offset);
|
return ReservationOffsetPointer(pool, offset);
|
||||||
@ -200,13 +199,13 @@ PA_ALWAYS_INLINE uintptr_t GetDirectMapReservationStart(uintptr_t address) {
|
|||||||
#if BUILDFLAG(PA_DCHECK_IS_ON)
|
#if BUILDFLAG(PA_DCHECK_IS_ON)
|
||||||
// MSVC workaround: the preprocessor seems to choke on an `#if` embedded
|
// MSVC workaround: the preprocessor seems to choke on an `#if` embedded
|
||||||
// inside another macro (PA_DCHECK).
|
// inside another macro (PA_DCHECK).
|
||||||
#if !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
constexpr size_t kBRPOffset =
|
constexpr size_t kBRPOffset =
|
||||||
AddressPoolManagerBitmap::kBytesPer1BitOfBRPPoolBitmap *
|
AddressPoolManagerBitmap::kBytesPer1BitOfBRPPoolBitmap *
|
||||||
AddressPoolManagerBitmap::kGuardOffsetOfBRPPoolBitmap;
|
AddressPoolManagerBitmap::kGuardOffsetOfBRPPoolBitmap;
|
||||||
#else
|
#else
|
||||||
constexpr size_t kBRPOffset = 0ull;
|
constexpr size_t kBRPOffset = 0ull;
|
||||||
#endif // !PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif // !BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
// Make sure the reservation start is in the same pool as |address|.
|
// Make sure the reservation start is in the same pool as |address|.
|
||||||
// In the 32-bit mode, the beginning of a reservation may be excluded
|
// In the 32-bit mode, the beginning of a reservation may be excluded
|
||||||
// from the BRP pool, so shift the pointer. The other pools don't have
|
// from the BRP pool, so shift the pointer. The other pools don't have
|
||||||
@ -227,7 +226,7 @@ PA_ALWAYS_INLINE uintptr_t GetDirectMapReservationStart(uintptr_t address) {
|
|||||||
return reservation_start;
|
return reservation_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
// If the given address doesn't point to direct-map allocated memory,
|
// If the given address doesn't point to direct-map allocated memory,
|
||||||
// returns 0.
|
// returns 0.
|
||||||
// This variant has better performance than the regular one on 64-bit builds if
|
// This variant has better performance than the regular one on 64-bit builds if
|
||||||
@ -247,7 +246,7 @@ GetDirectMapReservationStart(uintptr_t address,
|
|||||||
PA_DCHECK(*ReservationOffsetPointer(reservation_start) == 0);
|
PA_DCHECK(*ReservationOffsetPointer(reservation_start) == 0);
|
||||||
return reservation_start;
|
return reservation_start;
|
||||||
}
|
}
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
// Returns true if |address| is the beginning of the first super page of a
|
// Returns true if |address| is the beginning of the first super page of a
|
||||||
// reservation, i.e. either a normal bucket super page, or the first super page
|
// reservation, i.e. either a normal bucket super page, or the first super page
|
||||||
|
@ -10,12 +10,11 @@
|
|||||||
|
|
||||||
#include "base/allocator/partition_alloc_features.h"
|
#include "base/allocator/partition_alloc_features.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
|
||||||
#include "base/base_export.h"
|
#include "base/base_export.h"
|
||||||
#include "base/types/strong_alias.h"
|
#include "base/types/strong_alias.h"
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
|
||||||
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && PA_CONFIG(ALLOW_PCSCAN)
|
#if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && BUILDFLAG(USE_STARSCAN)
|
||||||
#include "base/allocator/partition_allocator/starscan/pcscan.h"
|
#include "base/allocator/partition_allocator/starscan/pcscan.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -208,7 +207,7 @@ BASE_EXPORT void ConfigurePartitions(
|
|||||||
AddDummyRefCount add_dummy_ref_count,
|
AddDummyRefCount add_dummy_ref_count,
|
||||||
AlternateBucketDistribution use_alternate_bucket_distribution);
|
AlternateBucketDistribution use_alternate_bucket_distribution);
|
||||||
|
|
||||||
#if PA_CONFIG(ALLOW_PCSCAN)
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
BASE_EXPORT void EnablePCScan(partition_alloc::internal::PCScan::InitConfig);
|
BASE_EXPORT void EnablePCScan(partition_alloc::internal::PCScan::InitConfig);
|
||||||
#endif
|
#endif
|
||||||
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
#include "base/allocator/partition_allocator/partition_alloc_base/threading/platform_thread.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/threading/platform_thread.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
||||||
#include "base/allocator/partition_allocator/partition_root.h"
|
#include "base/allocator/partition_allocator/partition_root.h"
|
||||||
#include "base/allocator/partition_allocator/partition_stats.h"
|
#include "base/allocator/partition_allocator/partition_stats.h"
|
||||||
@ -713,7 +712,7 @@ void ConfigurePartitions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PA_CONFIG(ALLOW_PCSCAN)
|
#if BUILDFLAG(USE_STARSCAN)
|
||||||
void EnablePCScan(partition_alloc::internal::PCScan::InitConfig config) {
|
void EnablePCScan(partition_alloc::internal::PCScan::InitConfig config) {
|
||||||
partition_alloc::internal::base::PlatformThread::SetThreadNameHook(
|
partition_alloc::internal::base::PlatformThread::SetThreadNameHook(
|
||||||
&::base::PlatformThread::SetName);
|
&::base::PlatformThread::SetName);
|
||||||
@ -730,7 +729,7 @@ void EnablePCScan(partition_alloc::internal::PCScan::InitConfig config) {
|
|||||||
base::internal::NonScannableAllocator::Instance().NotifyPCScanEnabled();
|
base::internal::NonScannableAllocator::Instance().NotifyPCScanEnabled();
|
||||||
base::internal::NonQuarantinableAllocator::Instance().NotifyPCScanEnabled();
|
base::internal::NonQuarantinableAllocator::Instance().NotifyPCScanEnabled();
|
||||||
}
|
}
|
||||||
#endif // PA_CONFIG(ALLOW_PCSCAN)
|
#endif // BUILDFLAG(USE_STARSCAN)
|
||||||
|
|
||||||
#if BUILDFLAG(IS_WIN)
|
#if BUILDFLAG(IS_WIN)
|
||||||
// Call this as soon as possible during startup.
|
// Call this as soon as possible during startup.
|
||||||
|
@ -30,13 +30,14 @@ ThreadSafePartitionRoot& PCScanMetadataAllocator() {
|
|||||||
return *allocator;
|
return *allocator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(tasak): investigate whether PartitionAlloc tests really need this
|
||||||
|
// function or not. If we found no tests need, remove it.
|
||||||
void ReinitPCScanMetadataAllocatorForTesting() {
|
void ReinitPCScanMetadataAllocatorForTesting() {
|
||||||
// First, purge memory owned by PCScanMetadataAllocator.
|
// First, purge memory owned by PCScanMetadataAllocator.
|
||||||
PCScanMetadataAllocator().PurgeMemory(PurgeFlags::kDecommitEmptySlotSpans |
|
PCScanMetadataAllocator().PurgeMemory(PurgeFlags::kDecommitEmptySlotSpans |
|
||||||
PurgeFlags::kDiscardUnusedSystemPages);
|
PurgeFlags::kDiscardUnusedSystemPages);
|
||||||
// Then, reinit the allocator.
|
// Then, reinit the allocator.
|
||||||
PCScanMetadataAllocator().~PartitionRoot();
|
PCScanMetadataAllocator().ResetForTesting(true); // IN-TEST
|
||||||
memset(&PCScanMetadataAllocator(), 0, sizeof(PCScanMetadataAllocator()));
|
|
||||||
PCScanMetadataAllocator().Init(kConfig);
|
PCScanMetadataAllocator().Init(kConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "base/allocator/partition_allocator/partition_alloc_base/no_destructor.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/no_destructor.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/threading/platform_thread.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/threading/platform_thread.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/time/time.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/time/time.h"
|
||||||
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
#include "base/allocator/partition_allocator/partition_alloc_constants.h"
|
||||||
@ -613,14 +614,14 @@ PA_SCAN_INLINE AllocationStateMap* PCScanTask::TryFindScannerBitmapForPointer(
|
|||||||
PA_SCAN_DCHECK(IsManagedByPartitionAllocRegularPool(maybe_ptr));
|
PA_SCAN_DCHECK(IsManagedByPartitionAllocRegularPool(maybe_ptr));
|
||||||
// First, check if |maybe_ptr| points to a valid super page or a quarantined
|
// First, check if |maybe_ptr| points to a valid super page or a quarantined
|
||||||
// card.
|
// card.
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
#if PA_CONFIG(STARSCAN_USE_CARD_TABLE)
|
#if PA_CONFIG(STARSCAN_USE_CARD_TABLE)
|
||||||
// Check if |maybe_ptr| points to a quarantined card.
|
// Check if |maybe_ptr| points to a quarantined card.
|
||||||
if (PA_LIKELY(
|
if (PA_LIKELY(
|
||||||
!QuarantineCardTable::GetFrom(maybe_ptr).IsQuarantined(maybe_ptr))) {
|
!QuarantineCardTable::GetFrom(maybe_ptr).IsQuarantined(maybe_ptr))) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
#else
|
#else // PA_CONFIG(STARSCAN_USE_CARD_TABLE)
|
||||||
// Without the card table, use the reservation offset table to check if
|
// Without the card table, use the reservation offset table to check if
|
||||||
// |maybe_ptr| points to a valid super-page. It's not as precise (meaning that
|
// |maybe_ptr| points to a valid super-page. It's not as precise (meaning that
|
||||||
// we may have hit the slow path more frequently), but reduces the memory
|
// we may have hit the slow path more frequently), but reduces the memory
|
||||||
@ -634,11 +635,11 @@ PA_SCAN_INLINE AllocationStateMap* PCScanTask::TryFindScannerBitmapForPointer(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
#endif // PA_CONFIG(STARSCAN_USE_CARD_TABLE)
|
#endif // PA_CONFIG(STARSCAN_USE_CARD_TABLE)
|
||||||
#else // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#else // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
if (PA_LIKELY(!IsManagedByPartitionAllocRegularPool(maybe_ptr))) {
|
if (PA_LIKELY(!IsManagedByPartitionAllocRegularPool(maybe_ptr))) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
// We are certain here that |maybe_ptr| points to an allocated super-page.
|
// We are certain here that |maybe_ptr| points to an allocated super-page.
|
||||||
return StateBitmapFromAddr(maybe_ptr);
|
return StateBitmapFromAddr(maybe_ptr);
|
||||||
@ -777,14 +778,14 @@ class PCScanScanLoop final : public ScanLoop<PCScanScanLoop> {
|
|||||||
size_t quarantine_size() const { return quarantine_size_; }
|
size_t quarantine_size() const { return quarantine_size_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
PA_ALWAYS_INLINE static uintptr_t RegularPoolBase() {
|
PA_ALWAYS_INLINE static uintptr_t RegularPoolBase() {
|
||||||
return PartitionAddressSpace::RegularPoolBase();
|
return PartitionAddressSpace::RegularPoolBase();
|
||||||
}
|
}
|
||||||
PA_ALWAYS_INLINE static uintptr_t RegularPoolMask() {
|
PA_ALWAYS_INLINE static uintptr_t RegularPoolMask() {
|
||||||
return PartitionAddressSpace::RegularPoolBaseMask();
|
return PartitionAddressSpace::RegularPoolBaseMask();
|
||||||
}
|
}
|
||||||
#endif // PA_CONFIG(HAS_64_BITS_POINTERS)
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
PA_SCAN_INLINE void CheckPointer(uintptr_t maybe_ptr_maybe_tagged) {
|
PA_SCAN_INLINE void CheckPointer(uintptr_t maybe_ptr_maybe_tagged) {
|
||||||
// |maybe_ptr| may have an MTE tag, so remove it first.
|
// |maybe_ptr| may have an MTE tag, so remove it first.
|
||||||
@ -1289,7 +1290,7 @@ PCScanInternal::~PCScanInternal() = default;
|
|||||||
|
|
||||||
void PCScanInternal::Initialize(PCScan::InitConfig config) {
|
void PCScanInternal::Initialize(PCScan::InitConfig config) {
|
||||||
PA_DCHECK(!is_initialized_);
|
PA_DCHECK(!is_initialized_);
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
// Make sure that pools are initialized.
|
// Make sure that pools are initialized.
|
||||||
PartitionAddressSpace::Init();
|
PartitionAddressSpace::Init();
|
||||||
#endif
|
#endif
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
|
||||||
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
#include "base/allocator/partition_allocator/partition_alloc_config.h"
|
||||||
#include "base/allocator/partition_allocator/starscan/starscan_fwd.h"
|
#include "base/allocator/partition_allocator/starscan/starscan_fwd.h"
|
||||||
@ -93,12 +94,12 @@ template <typename Derived>
|
|||||||
void ScanLoop<Derived>::RunUnvectorized(uintptr_t begin, uintptr_t end) {
|
void ScanLoop<Derived>::RunUnvectorized(uintptr_t begin, uintptr_t end) {
|
||||||
PA_SCAN_DCHECK(!(begin % sizeof(uintptr_t)));
|
PA_SCAN_DCHECK(!(begin % sizeof(uintptr_t)));
|
||||||
PA_SCAN_DCHECK(!(end % sizeof(uintptr_t)));
|
PA_SCAN_DCHECK(!(end % sizeof(uintptr_t)));
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
// If the read value is a pointer into the PA region, it's likely
|
// If the read value is a pointer into the PA region, it's likely
|
||||||
// MTE-tagged. Piggyback on |mask| to untag, for efficiency.
|
// MTE-tagged. Piggyback on |mask| to untag, for efficiency.
|
||||||
const uintptr_t mask = Derived::RegularPoolMask() & kPtrUntagMask;
|
const uintptr_t mask = Derived::RegularPoolMask() & kPtrUntagMask;
|
||||||
const uintptr_t base = Derived::RegularPoolBase();
|
const uintptr_t base = Derived::RegularPoolBase();
|
||||||
#endif
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
for (; begin < end; begin += sizeof(uintptr_t)) {
|
for (; begin < end; begin += sizeof(uintptr_t)) {
|
||||||
// Read the region word-by-word. Everything that we read is a potential
|
// Read the region word-by-word. Everything that we read is a potential
|
||||||
// pointer to or inside an object on heap. Such an object should be
|
// pointer to or inside an object on heap. Such an object should be
|
||||||
@ -106,13 +107,13 @@ void ScanLoop<Derived>::RunUnvectorized(uintptr_t begin, uintptr_t end) {
|
|||||||
//
|
//
|
||||||
// Keep it MTE-untagged. See DisableMTEScope for details.
|
// Keep it MTE-untagged. See DisableMTEScope for details.
|
||||||
const uintptr_t maybe_ptr = *reinterpret_cast<uintptr_t*>(begin);
|
const uintptr_t maybe_ptr = *reinterpret_cast<uintptr_t*>(begin);
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
if (PA_LIKELY((maybe_ptr & mask) != base))
|
if (PA_LIKELY((maybe_ptr & mask) != base))
|
||||||
continue;
|
continue;
|
||||||
#else
|
#else
|
||||||
if (!maybe_ptr)
|
if (!maybe_ptr)
|
||||||
continue;
|
continue;
|
||||||
#endif
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
derived().CheckPointer(maybe_ptr);
|
derived().CheckPointer(maybe_ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
|
#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h"
|
||||||
|
#include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
|
||||||
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
#include "base/allocator/partition_allocator/partition_alloc_check.h"
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
|
||||||
@ -135,12 +136,12 @@ namespace {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void Stack::IteratePointers(StackVisitor* visitor) const {
|
void Stack::IteratePointers(StackVisitor* visitor) const {
|
||||||
#if defined(PA_PCSCAN_STACK_SUPPORTED)
|
#if BUILDFLAG(PCSCAN_STACK_SUPPORTED)
|
||||||
PAPushAllRegistersAndIterateStack(this, visitor, &IteratePointersImpl);
|
PAPushAllRegistersAndIterateStack(this, visitor, &IteratePointersImpl);
|
||||||
// No need to deal with callee-saved registers as they will be kept alive by
|
// No need to deal with callee-saved registers as they will be kept alive by
|
||||||
// the regular conservative stack iteration.
|
// the regular conservative stack iteration.
|
||||||
IterateSafeStackIfNecessary(visitor);
|
IterateSafeStackIfNecessary(visitor);
|
||||||
#endif
|
#endif // BUILDFLAG(PCSCAN_STACK_SUPPORTED)
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace partition_alloc::internal
|
} // namespace partition_alloc::internal
|
||||||
|
@ -355,7 +355,7 @@ void ThreadCache::RemoveTombstoneForTesting() {
|
|||||||
// static
|
// static
|
||||||
void ThreadCache::Init(PartitionRoot<>* root) {
|
void ThreadCache::Init(PartitionRoot<>* root) {
|
||||||
#if BUILDFLAG(IS_NACL)
|
#if BUILDFLAG(IS_NACL)
|
||||||
PA_IMMEDIATE_CRASH();
|
static_assert(false, "PartitionAlloc isn't supported for NaCl");
|
||||||
#endif
|
#endif
|
||||||
PA_CHECK(root->buckets[kBucketCount - 1].slot_size ==
|
PA_CHECK(root->buckets[kBucketCount - 1].slot_size ==
|
||||||
ThreadCache::kLargeSizeThreshold);
|
ThreadCache::kLargeSizeThreshold);
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#include "base/allocator/partition_allocator/partition_tls.h"
|
#include "base/allocator/partition_allocator/partition_tls.h"
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
|
||||||
#if defined(ARCH_CPU_X86_64) && PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if defined(ARCH_CPU_X86_64) && BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -43,13 +43,13 @@ namespace tools {
|
|||||||
//
|
//
|
||||||
// These two values were chosen randomly, and in particular neither is a valid
|
// These two values were chosen randomly, and in particular neither is a valid
|
||||||
// pointer on most 64 bit architectures.
|
// pointer on most 64 bit architectures.
|
||||||
#if PA_CONFIG(HAS_64_BITS_POINTERS)
|
#if BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
constexpr uintptr_t kNeedle1 = 0xe69e32f3ad9ea63;
|
constexpr uintptr_t kNeedle1 = 0xe69e32f3ad9ea63;
|
||||||
constexpr uintptr_t kNeedle2 = 0x9615ee1c5eb14caf;
|
constexpr uintptr_t kNeedle2 = 0x9615ee1c5eb14caf;
|
||||||
#else
|
#else
|
||||||
constexpr uintptr_t kNeedle1 = 0xe69e32f3;
|
constexpr uintptr_t kNeedle1 = 0xe69e32f3;
|
||||||
constexpr uintptr_t kNeedle2 = 0x9615ee1c;
|
constexpr uintptr_t kNeedle2 = 0x9615ee1c;
|
||||||
#endif
|
#endif // BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
// This array contains, in order:
|
// This array contains, in order:
|
||||||
// - kNeedle1
|
// - kNeedle1
|
||||||
@ -161,14 +161,8 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) ThreadCacheRegistry {
|
|||||||
internal::base::TimeDelta periodic_purge_next_interval_ =
|
internal::base::TimeDelta periodic_purge_next_interval_ =
|
||||||
kDefaultPurgeInterval;
|
kDefaultPurgeInterval;
|
||||||
|
|
||||||
#if BUILDFLAG(IS_NACL)
|
|
||||||
// The thread cache is never used with NaCl, but its compiler doesn't
|
|
||||||
// understand enough constexpr to handle the code below.
|
|
||||||
uint8_t largest_active_bucket_index_ = 1;
|
|
||||||
#else
|
|
||||||
uint8_t largest_active_bucket_index_ = internal::BucketIndexLookup::GetIndex(
|
uint8_t largest_active_bucket_index_ = internal::BucketIndexLookup::GetIndex(
|
||||||
ThreadCacheLimits::kDefaultSizeThreshold);
|
ThreadCacheLimits::kDefaultSizeThreshold);
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr ThreadCacheRegistry::ThreadCacheRegistry() = default;
|
constexpr ThreadCacheRegistry::ThreadCacheRegistry() = default;
|
||||||
@ -392,15 +386,9 @@ class PA_COMPONENT_EXPORT(PARTITION_ALLOC) ThreadCache {
|
|||||||
void FreeAfter(internal::PartitionFreelistEntry* head, size_t slot_size);
|
void FreeAfter(internal::PartitionFreelistEntry* head, size_t slot_size);
|
||||||
static void SetGlobalLimits(PartitionRoot<>* root, float multiplier);
|
static void SetGlobalLimits(PartitionRoot<>* root, float multiplier);
|
||||||
|
|
||||||
#if BUILDFLAG(IS_NACL)
|
|
||||||
// The thread cache is never used with NaCl, but its compiler doesn't
|
|
||||||
// understand enough constexpr to handle the code below.
|
|
||||||
static constexpr uint16_t kBucketCount = 1;
|
|
||||||
#else
|
|
||||||
static constexpr uint16_t kBucketCount =
|
static constexpr uint16_t kBucketCount =
|
||||||
internal::BucketIndexLookup::GetIndex(ThreadCache::kLargeSizeThreshold) +
|
internal::BucketIndexLookup::GetIndex(ThreadCache::kLargeSizeThreshold) +
|
||||||
1;
|
1;
|
||||||
#endif
|
|
||||||
static_assert(
|
static_assert(
|
||||||
kBucketCount < internal::kNumBuckets,
|
kBucketCount < internal::kNumBuckets,
|
||||||
"Cannot have more cached buckets than what the allocator supports");
|
"Cannot have more cached buckets than what the allocator supports");
|
||||||
@ -547,7 +535,7 @@ PA_ALWAYS_INLINE uintptr_t ThreadCache::GetFromCache(size_t bucket_index,
|
|||||||
internal::PartitionFreelistEntry* entry = bucket.freelist_head;
|
internal::PartitionFreelistEntry* entry = bucket.freelist_head;
|
||||||
// TODO(lizeb): Consider removing once crbug.com/1382658 is fixed.
|
// TODO(lizeb): Consider removing once crbug.com/1382658 is fixed.
|
||||||
#if BUILDFLAG(IS_CHROMEOS) && defined(ARCH_CPU_X86_64) && \
|
#if BUILDFLAG(IS_CHROMEOS) && defined(ARCH_CPU_X86_64) && \
|
||||||
PA_CONFIG(HAS_64_BITS_POINTERS)
|
BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
// x86_64 architecture now supports 57 bits of address space, as of Ice Lake
|
// x86_64 architecture now supports 57 bits of address space, as of Ice Lake
|
||||||
// for Intel. However Chrome OS systems do not ship with kernel support for
|
// for Intel. However Chrome OS systems do not ship with kernel support for
|
||||||
// it, but with 48 bits, so all canonical addresses have the upper 16 bits
|
// it, but with 48 bits, so all canonical addresses have the upper 16 bits
|
||||||
@ -555,7 +543,8 @@ PA_ALWAYS_INLINE uintptr_t ThreadCache::GetFromCache(size_t bucket_index,
|
|||||||
// by the kernel).
|
// by the kernel).
|
||||||
constexpr uintptr_t kCanonicalPointerMask = (1ULL << 48) - 1;
|
constexpr uintptr_t kCanonicalPointerMask = (1ULL << 48) - 1;
|
||||||
PA_CHECK(!(reinterpret_cast<uintptr_t>(entry) & ~kCanonicalPointerMask));
|
PA_CHECK(!(reinterpret_cast<uintptr_t>(entry) & ~kCanonicalPointerMask));
|
||||||
#endif
|
#endif // BUILDFLAG(IS_CHROMEOS) && defined(ARCH_CPU_X86_64) &&
|
||||||
|
// BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
// Passes the bucket size to |GetNext()|, so that in case of freelist
|
// Passes the bucket size to |GetNext()|, so that in case of freelist
|
||||||
// corruption, we know the bucket size that lead to the crash, helping to
|
// corruption, we know the bucket size that lead to the crash, helping to
|
||||||
@ -578,7 +567,7 @@ PA_ALWAYS_INLINE uintptr_t ThreadCache::GetFromCache(size_t bucket_index,
|
|||||||
PA_ALWAYS_INLINE void ThreadCache::PutInBucket(Bucket& bucket,
|
PA_ALWAYS_INLINE void ThreadCache::PutInBucket(Bucket& bucket,
|
||||||
uintptr_t slot_start) {
|
uintptr_t slot_start) {
|
||||||
#if PA_CONFIG(HAS_FREELIST_SHADOW_ENTRY) && defined(ARCH_CPU_X86_64) && \
|
#if PA_CONFIG(HAS_FREELIST_SHADOW_ENTRY) && defined(ARCH_CPU_X86_64) && \
|
||||||
PA_CONFIG(HAS_64_BITS_POINTERS)
|
BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
// We see freelist corruption crashes happening in the wild. These are likely
|
// We see freelist corruption crashes happening in the wild. These are likely
|
||||||
// due to out-of-bounds accesses in the previous slot, or to a Use-After-Free
|
// due to out-of-bounds accesses in the previous slot, or to a Use-After-Free
|
||||||
// somewhere in the code.
|
// somewhere in the code.
|
||||||
@ -630,7 +619,7 @@ PA_ALWAYS_INLINE void ThreadCache::PutInBucket(Bucket& bucket,
|
|||||||
address_aligned += 4;
|
address_aligned += 4;
|
||||||
}
|
}
|
||||||
#endif // PA_CONFIG(HAS_FREELIST_SHADOW_ENTRY) && defined(ARCH_CPU_X86_64) &&
|
#endif // PA_CONFIG(HAS_FREELIST_SHADOW_ENTRY) && defined(ARCH_CPU_X86_64) &&
|
||||||
// PA_CONFIG(HAS_64_BITS_POINTERS)
|
// BUILDFLAG(HAS_64_BIT_POINTERS)
|
||||||
|
|
||||||
auto* entry = internal::PartitionFreelistEntry::EmplaceAndInitForThreadCache(
|
auto* entry = internal::PartitionFreelistEntry::EmplaceAndInitForThreadCache(
|
||||||
slot_start, bucket.freelist_head);
|
slot_start, bucket.freelist_head);
|
||||||
|
@ -14,13 +14,12 @@
|
|||||||
// other hyper-thread on this core. See the following for context:
|
// other hyper-thread on this core. See the following for context:
|
||||||
// https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops
|
// https://software.intel.com/en-us/articles/benefitting-power-and-performance-sleep-loops
|
||||||
|
|
||||||
#if BUILDFLAG(IS_NACL)
|
#if PA_CONFIG(IS_NONCLANG_MSVC)
|
||||||
// Inline assembly not allowed.
|
|
||||||
#define PA_YIELD_PROCESSOR ((void)0)
|
|
||||||
#elif PA_CONFIG(IS_NONCLANG_MSVC)
|
|
||||||
// MSVC is in its own assemblyless world (crbug.com/1351310#c6).
|
// MSVC is in its own assemblyless world (crbug.com/1351310#c6).
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#define PA_YIELD_PROCESSOR (YieldProcessor())
|
#define PA_YIELD_PROCESSOR (YieldProcessor())
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#if defined(ARCH_CPU_X86_64) || defined(ARCH_CPU_X86)
|
#if defined(ARCH_CPU_X86_64) || defined(ARCH_CPU_X86)
|
||||||
@ -47,6 +46,6 @@
|
|||||||
#define PA_YIELD_PROCESSOR ((void)0)
|
#define PA_YIELD_PROCESSOR ((void)0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // BUILDFLAG(IS_NACL)
|
#endif // PA_CONFIG(IS_NONCLANG_MSVC)
|
||||||
|
|
||||||
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_YIELD_PROCESSOR_H_
|
#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_YIELD_PROCESSOR_H_
|
||||||
|
@ -48,12 +48,17 @@ source_set("jni_sample_native_side") {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generate_jni_registration("jni_registration") {
|
||||||
|
targets = [ ":jni_sample_java" ]
|
||||||
|
manual_jni_registration = true
|
||||||
|
}
|
||||||
|
|
||||||
shared_library("jni_sample_lib") {
|
shared_library("jni_sample_lib") {
|
||||||
sources = [ "sample_entry_point.cc" ]
|
sources = [ "sample_entry_point.cc" ]
|
||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
|
":jni_registration",
|
||||||
":jni_sample_native_side",
|
":jni_sample_native_side",
|
||||||
":sample_jni_apk__final_jni", # For registration_header
|
|
||||||
"//base",
|
"//base",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -63,7 +68,6 @@ android_apk("sample_jni_apk") {
|
|||||||
android_manifest = "AndroidManifest.xml"
|
android_manifest = "AndroidManifest.xml"
|
||||||
deps = [ ":jni_sample_java" ]
|
deps = [ ":jni_sample_java" ]
|
||||||
shared_libraries = [ ":jni_sample_lib" ]
|
shared_libraries = [ ":jni_sample_lib" ]
|
||||||
manual_jni_registration = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Serves to test that generated bindings compile properly.
|
# Serves to test that generated bindings compile properly.
|
||||||
|
@ -175,6 +175,16 @@ public class AnimationFrameTimeHistogramTest {
|
|||||||
If a native method is called without setting a mock in a unit test, an
|
If a native method is called without setting a mock in a unit test, an
|
||||||
`UnsupportedOperationException` will be thrown.
|
`UnsupportedOperationException` will be thrown.
|
||||||
|
|
||||||
|
#### Special case: DFMs
|
||||||
|
DFMs have their own generated `GEN_JNI`s, which are `<module_name>_GEN_JNI`. In
|
||||||
|
order to get your DFM's JNI to use the `<module_name>` prefix, you must add your
|
||||||
|
module name into the argument of the `@NativeMethods` annotation.
|
||||||
|
|
||||||
|
So, for example, say your module was named `test_module`. You would annotate
|
||||||
|
your `Natives` interface with `@NativeMethods("test_module")`, and this would
|
||||||
|
result in `test_module_GEN_JNI`.
|
||||||
|
|
||||||
|
|
||||||
### Testing for readiness: use `get()`
|
### Testing for readiness: use `get()`
|
||||||
|
|
||||||
JNI Generator automatically produces checks that verify that the Natives interface can be safely
|
JNI Generator automatically produces checks that verify that the Natives interface can be safely
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# Copyright 2012 The Chromium Authors
|
# Copyright 2012 The Chromium Authors
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
# found in the LICENSE file.
|
# found in the LICENSE file.
|
||||||
|
|
||||||
"""Extracts native methods from a Java file and generates the JNI bindings.
|
"""Extracts native methods from a Java file and generates the JNI bindings.
|
||||||
If you change this, please run and update the tests."""
|
If you change this, please run and update the tests."""
|
||||||
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import base64
|
import base64
|
||||||
import collections
|
import collections
|
||||||
@ -62,7 +59,7 @@ _EXTRACT_METHODS_REGEX = re.compile(
|
|||||||
flags=re.DOTALL)
|
flags=re.DOTALL)
|
||||||
|
|
||||||
_NATIVE_PROXY_EXTRACTION_REGEX = re.compile(
|
_NATIVE_PROXY_EXTRACTION_REGEX = re.compile(
|
||||||
r'@NativeMethods[\S\s]+?interface\s*'
|
r'@NativeMethods(?:\(\s*"(?P<module_name>\w+)"\s*\))?[\S\s]+?interface\s*'
|
||||||
r'(?P<interface_name>\w*)\s*(?P<interface_body>{(\s*.*)+?\s*})')
|
r'(?P<interface_name>\w*)\s*(?P<interface_body>{(\s*.*)+?\s*})')
|
||||||
|
|
||||||
# Use 100 columns rather than 80 because it makes many lines more readable.
|
# Use 100 columns rather than 80 because it makes many lines more readable.
|
||||||
@ -842,9 +839,12 @@ class JNIFromJavaP(object):
|
|||||||
self.constant_fields.append(
|
self.constant_fields.append(
|
||||||
ConstantField(name=match.group('name'), value=value.group('value')))
|
ConstantField(name=match.group('name'), value=value.group('value')))
|
||||||
|
|
||||||
|
# We pass in an empty string for the module (which will make the JNI use the
|
||||||
|
# base module's files) for all javap-derived JNI. There may be a way to get
|
||||||
|
# the module from a jar file, but it's not needed right now.
|
||||||
self.inl_header_file_generator = InlHeaderFileGenerator(
|
self.inl_header_file_generator = InlHeaderFileGenerator(
|
||||||
self.namespace, self.fully_qualified_class, [], self.called_by_natives,
|
'', self.namespace, self.fully_qualified_class, [],
|
||||||
self.constant_fields, self.jni_params, options)
|
self.called_by_natives, self.constant_fields, self.jni_params, options)
|
||||||
|
|
||||||
def GetContent(self):
|
def GetContent(self):
|
||||||
return self.inl_header_file_generator.GetContent()
|
return self.inl_header_file_generator.GetContent()
|
||||||
@ -875,17 +875,21 @@ class ProxyHelpers(object):
|
|||||||
MAX_CHARS_FOR_HASHED_NATIVE_METHODS = 8
|
MAX_CHARS_FOR_HASHED_NATIVE_METHODS = 8
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def GetClass(use_hash):
|
def GetClass(short_name, name_prefix=None):
|
||||||
return 'N' if use_hash else 'GEN_JNI'
|
if not name_prefix:
|
||||||
|
name_prefix = ''
|
||||||
|
else:
|
||||||
|
name_prefix += '_'
|
||||||
|
return name_prefix + ('N' if short_name else 'GEN_JNI')
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def GetPackage(use_hash):
|
def GetPackage(short_name):
|
||||||
return 'J' if use_hash else 'org/chromium/base/natives'
|
return 'J' if short_name else 'org/chromium/base/natives'
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def GetQualifiedClass(use_hash):
|
def GetQualifiedClass(short_name, name_prefix=None):
|
||||||
return '%s/%s' % (ProxyHelpers.GetPackage(use_hash),
|
return '%s/%s' % (ProxyHelpers.GetPackage(short_name),
|
||||||
ProxyHelpers.GetClass(use_hash))
|
ProxyHelpers.GetClass(short_name, name_prefix))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def CreateHashedMethodName(fully_qualified_class_name, method_name):
|
def CreateHashedMethodName(fully_qualified_class_name, method_name):
|
||||||
@ -934,8 +938,18 @@ class ProxyHelpers(object):
|
|||||||
ptr_type,
|
ptr_type,
|
||||||
include_test_only=True):
|
include_test_only=True):
|
||||||
methods = []
|
methods = []
|
||||||
|
first_match = True
|
||||||
|
module_name = None
|
||||||
for match in _NATIVE_PROXY_EXTRACTION_REGEX.finditer(contents):
|
for match in _NATIVE_PROXY_EXTRACTION_REGEX.finditer(contents):
|
||||||
interface_body = match.group('interface_body')
|
interface_body = match.group('interface_body')
|
||||||
|
if first_match:
|
||||||
|
module_name = match.group('module_name')
|
||||||
|
first_match = False
|
||||||
|
else:
|
||||||
|
assert module_name == match.group(
|
||||||
|
'module_name'
|
||||||
|
), 'JNI cannot belong to two modules in one file {} and {}'.format(
|
||||||
|
module_name, match.group('module_name'))
|
||||||
for method in _EXTRACT_METHODS_REGEX.finditer(interface_body):
|
for method in _EXTRACT_METHODS_REGEX.finditer(interface_body):
|
||||||
name = method.group('name')
|
name = method.group('name')
|
||||||
if not include_test_only and _NameIsTestOnly(name):
|
if not include_test_only and _NameIsTestOnly(name):
|
||||||
@ -961,7 +975,9 @@ class ProxyHelpers(object):
|
|||||||
ptr_type=ptr_type)
|
ptr_type=ptr_type)
|
||||||
methods.append(native)
|
methods.append(native)
|
||||||
|
|
||||||
return methods
|
if not module_name:
|
||||||
|
module_name = ''
|
||||||
|
return methods, module_name
|
||||||
|
|
||||||
|
|
||||||
class JNIFromJavaSource(object):
|
class JNIFromJavaSource(object):
|
||||||
@ -972,20 +988,19 @@ class JNIFromJavaSource(object):
|
|||||||
self.jni_params = JniParams(fully_qualified_class)
|
self.jni_params = JniParams(fully_qualified_class)
|
||||||
self.jni_params.ExtractImportsAndInnerClasses(contents)
|
self.jni_params.ExtractImportsAndInnerClasses(contents)
|
||||||
jni_namespace = ExtractJNINamespace(contents) or options.namespace
|
jni_namespace = ExtractJNINamespace(contents) or options.namespace
|
||||||
natives = ExtractNatives(contents, options.ptr_type)
|
|
||||||
called_by_natives = ExtractCalledByNatives(self.jni_params, contents,
|
called_by_natives = ExtractCalledByNatives(self.jni_params, contents,
|
||||||
options.always_mangle)
|
options.always_mangle)
|
||||||
|
|
||||||
natives += ProxyHelpers.ExtractStaticProxyNatives(fully_qualified_class,
|
natives, module_name = ProxyHelpers.ExtractStaticProxyNatives(
|
||||||
contents,
|
fully_qualified_class, contents, options.ptr_type)
|
||||||
options.ptr_type)
|
natives += ExtractNatives(contents, options.ptr_type)
|
||||||
|
|
||||||
if len(natives) == 0 and len(called_by_natives) == 0:
|
if len(natives) == 0 and len(called_by_natives) == 0:
|
||||||
raise SyntaxError(
|
raise SyntaxError(
|
||||||
'Unable to find any JNI methods for %s.' % fully_qualified_class)
|
'Unable to find any JNI methods for %s.' % fully_qualified_class)
|
||||||
inl_header_file_generator = InlHeaderFileGenerator(
|
inl_header_file_generator = InlHeaderFileGenerator(
|
||||||
jni_namespace, fully_qualified_class, natives, called_by_natives, [],
|
module_name, jni_namespace, fully_qualified_class, natives,
|
||||||
self.jni_params, options)
|
called_by_natives, [], self.jni_params, options)
|
||||||
self.content = inl_header_file_generator.GetContent()
|
self.content = inl_header_file_generator.GetContent()
|
||||||
|
|
||||||
def GetContent(self):
|
def GetContent(self):
|
||||||
@ -1005,11 +1020,13 @@ class HeaderFileGeneratorHelper(object):
|
|||||||
|
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
class_name,
|
class_name,
|
||||||
|
module_name,
|
||||||
fully_qualified_class,
|
fully_qualified_class,
|
||||||
use_proxy_hash,
|
use_proxy_hash,
|
||||||
split_name=None,
|
split_name=None,
|
||||||
enable_jni_multiplexing=False):
|
enable_jni_multiplexing=False):
|
||||||
self.class_name = class_name
|
self.class_name = class_name
|
||||||
|
self.module_name = module_name
|
||||||
self.fully_qualified_class = fully_qualified_class
|
self.fully_qualified_class = fully_qualified_class
|
||||||
self.use_proxy_hash = use_proxy_hash
|
self.use_proxy_hash = use_proxy_hash
|
||||||
self.split_name = split_name
|
self.split_name = split_name
|
||||||
@ -1031,8 +1048,8 @@ class HeaderFileGeneratorHelper(object):
|
|||||||
method_name = EscapeClassName(native.proxy_name)
|
method_name = EscapeClassName(native.proxy_name)
|
||||||
return 'Java_%s_%s' % (EscapeClassName(
|
return 'Java_%s_%s' % (EscapeClassName(
|
||||||
ProxyHelpers.GetQualifiedClass(
|
ProxyHelpers.GetQualifiedClass(
|
||||||
self.use_proxy_hash
|
self.use_proxy_hash or self.enable_jni_multiplexing,
|
||||||
or self.enable_jni_multiplexing)), method_name)
|
self.module_name)), method_name)
|
||||||
|
|
||||||
template = Template('Java_${JAVA_NAME}_native${NAME}')
|
template = Template('Java_${JAVA_NAME}_native${NAME}')
|
||||||
|
|
||||||
@ -1047,9 +1064,9 @@ class HeaderFileGeneratorHelper(object):
|
|||||||
ret = collections.OrderedDict()
|
ret = collections.OrderedDict()
|
||||||
for entry in origin:
|
for entry in origin:
|
||||||
if isinstance(entry, NativeMethod) and entry.is_proxy:
|
if isinstance(entry, NativeMethod) and entry.is_proxy:
|
||||||
use_hash = self.use_proxy_hash or self.enable_jni_multiplexing
|
short_name = self.use_proxy_hash or self.enable_jni_multiplexing
|
||||||
ret[ProxyHelpers.GetClass(use_hash)] \
|
ret[ProxyHelpers.GetClass(short_name, self.module_name)] \
|
||||||
= ProxyHelpers.GetQualifiedClass(use_hash)
|
= ProxyHelpers.GetQualifiedClass(short_name, self.module_name)
|
||||||
continue
|
continue
|
||||||
ret[self.class_name] = self.fully_qualified_class
|
ret[self.class_name] = self.fully_qualified_class
|
||||||
|
|
||||||
@ -1083,7 +1100,8 @@ const char kClassPath_${JAVA_CLASS}[] = \
|
|||||||
# Since all proxy methods use the same class, defining this in every
|
# Since all proxy methods use the same class, defining this in every
|
||||||
# header file would result in duplicated extern initializations.
|
# header file would result in duplicated extern initializations.
|
||||||
if full_clazz != ProxyHelpers.GetQualifiedClass(
|
if full_clazz != ProxyHelpers.GetQualifiedClass(
|
||||||
self.use_proxy_hash or self.enable_jni_multiplexing):
|
self.use_proxy_hash or self.enable_jni_multiplexing,
|
||||||
|
self.module_name):
|
||||||
ret += [template.substitute(values)]
|
ret += [template.substitute(values)]
|
||||||
|
|
||||||
class_getter = """\
|
class_getter = """\
|
||||||
@ -1115,7 +1133,8 @@ JNI_REGISTRATION_EXPORT std::atomic<jclass> g_${JAVA_CLASS}_clazz(nullptr);
|
|||||||
# Since all proxy methods use the same class, defining this in every
|
# Since all proxy methods use the same class, defining this in every
|
||||||
# header file would result in duplicated extern initializations.
|
# header file would result in duplicated extern initializations.
|
||||||
if full_clazz != ProxyHelpers.GetQualifiedClass(
|
if full_clazz != ProxyHelpers.GetQualifiedClass(
|
||||||
self.use_proxy_hash or self.enable_jni_multiplexing):
|
self.use_proxy_hash or self.enable_jni_multiplexing,
|
||||||
|
self.module_name):
|
||||||
ret += [template.substitute(values)]
|
ret += [template.substitute(values)]
|
||||||
|
|
||||||
return ''.join(ret)
|
return ''.join(ret)
|
||||||
@ -1124,7 +1143,7 @@ JNI_REGISTRATION_EXPORT std::atomic<jclass> g_${JAVA_CLASS}_clazz(nullptr);
|
|||||||
class InlHeaderFileGenerator(object):
|
class InlHeaderFileGenerator(object):
|
||||||
"""Generates an inline header file for JNI integration."""
|
"""Generates an inline header file for JNI integration."""
|
||||||
|
|
||||||
def __init__(self, namespace, fully_qualified_class, natives,
|
def __init__(self, module_name, namespace, fully_qualified_class, natives,
|
||||||
called_by_natives, constant_fields, jni_params, options):
|
called_by_natives, constant_fields, jni_params, options):
|
||||||
self.namespace = namespace
|
self.namespace = namespace
|
||||||
self.fully_qualified_class = fully_qualified_class
|
self.fully_qualified_class = fully_qualified_class
|
||||||
@ -1137,6 +1156,7 @@ class InlHeaderFileGenerator(object):
|
|||||||
self.options = options
|
self.options = options
|
||||||
self.helper = HeaderFileGeneratorHelper(
|
self.helper = HeaderFileGeneratorHelper(
|
||||||
self.class_name,
|
self.class_name,
|
||||||
|
module_name,
|
||||||
fully_qualified_class,
|
fully_qualified_class,
|
||||||
self.options.use_proxy_hash,
|
self.options.use_proxy_hash,
|
||||||
split_name=self.options.split_name,
|
split_name=self.options.split_name,
|
||||||
|
@ -12,14 +12,17 @@ file.
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
|
import copy
|
||||||
import difflib
|
import difflib
|
||||||
import inspect
|
import inspect
|
||||||
import optparse
|
import optparse
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import tempfile
|
||||||
import unittest
|
import unittest
|
||||||
import jni_generator
|
import jni_generator
|
||||||
import jni_registration_generator
|
import jni_registration_generator
|
||||||
|
import zipfile
|
||||||
from jni_generator import CalledByNative
|
from jni_generator import CalledByNative
|
||||||
from jni_generator import IsMainDexJavaClass
|
from jni_generator import IsMainDexJavaClass
|
||||||
from jni_generator import NativeMethod
|
from jni_generator import NativeMethod
|
||||||
@ -44,7 +47,7 @@ def _RemoveHashedNames(natives):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class TestOptions(object):
|
class JniGeneratorOptions(object):
|
||||||
"""The mock options object which is passed to the jni_generator.py script."""
|
"""The mock options object which is passed to the jni_generator.py script."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@ -54,7 +57,6 @@ class TestOptions(object):
|
|||||||
self.ptr_type = 'long'
|
self.ptr_type = 'long'
|
||||||
self.cpp = 'cpp'
|
self.cpp = 'cpp'
|
||||||
self.javap = 'mock-javap'
|
self.javap = 'mock-javap'
|
||||||
self.native_exports_optional = True
|
|
||||||
self.enable_profiling = False
|
self.enable_profiling = False
|
||||||
self.enable_tracing = False
|
self.enable_tracing = False
|
||||||
self.use_proxy_hash = False
|
self.use_proxy_hash = False
|
||||||
@ -65,6 +67,21 @@ class TestOptions(object):
|
|||||||
self.include_test_only = True
|
self.include_test_only = True
|
||||||
|
|
||||||
|
|
||||||
|
class JniRegistrationGeneratorOptions(object):
|
||||||
|
"""The mock options object which is passed to the jni_generator.py script."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.sources_exclusions = []
|
||||||
|
self.namespace = None
|
||||||
|
self.enable_proxy_mocks = False
|
||||||
|
self.require_mocks = False
|
||||||
|
self.use_proxy_hash = False
|
||||||
|
self.enable_jni_multiplexing = False
|
||||||
|
self.manual_jni_registration = False
|
||||||
|
self.include_test_only = False
|
||||||
|
self.header_path = None
|
||||||
|
|
||||||
|
|
||||||
class BaseTest(unittest.TestCase):
|
class BaseTest(unittest.TestCase):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@ -100,10 +117,42 @@ class BaseTest(unittest.TestCase):
|
|||||||
signature_to_cases[signature].extend(cases)
|
signature_to_cases[signature].extend(cases)
|
||||||
combined_dict[
|
combined_dict[
|
||||||
'FORWARDING_CALLS'] = jni_registration_generator._AddForwardingCalls(
|
'FORWARDING_CALLS'] = jni_registration_generator._AddForwardingCalls(
|
||||||
signature_to_cases, namespace)
|
signature_to_cases, '')
|
||||||
|
|
||||||
return combined_dict
|
return combined_dict
|
||||||
|
|
||||||
|
def _TestEndToEndRegistration(self,
|
||||||
|
input_java_src_files,
|
||||||
|
options,
|
||||||
|
name_to_goldens,
|
||||||
|
header_golden=None):
|
||||||
|
with tempfile.TemporaryDirectory() as tdir:
|
||||||
|
options.srcjar_path = os.path.join(tdir, 'srcjar.jar')
|
||||||
|
if header_golden:
|
||||||
|
options.header_path = os.path.join(tdir, 'header.h')
|
||||||
|
|
||||||
|
input_java_paths = [
|
||||||
|
self._JoinScriptDir(os.path.join(_JAVA_SRC_DIR, f))
|
||||||
|
for f in input_java_src_files
|
||||||
|
]
|
||||||
|
|
||||||
|
jni_registration_generator._Generate(options, input_java_paths)
|
||||||
|
with zipfile.ZipFile(options.srcjar_path, 'r') as srcjar:
|
||||||
|
for name in srcjar.namelist():
|
||||||
|
self.assertTrue(
|
||||||
|
name in name_to_goldens,
|
||||||
|
f'Found {name} output, but not present in name_to_goldens map.')
|
||||||
|
contents = srcjar.read(name).decode('utf-8')
|
||||||
|
self.AssertGoldenTextEquals(contents,
|
||||||
|
golden_file=name_to_goldens[name])
|
||||||
|
if header_golden:
|
||||||
|
with open(options.header_path, 'r') as f:
|
||||||
|
# Temp directory will cause some diffs each time we run if we don't
|
||||||
|
# normalize.
|
||||||
|
contents = f.read().replace(
|
||||||
|
tdir.replace('/', '_').upper(), 'TEMP_DIR')
|
||||||
|
self.AssertGoldenTextEquals(contents, golden_file=header_golden)
|
||||||
|
|
||||||
def _JoinScriptDir(self, path):
|
def _JoinScriptDir(self, path):
|
||||||
script_dir = os.path.dirname(sys.argv[0])
|
script_dir = os.path.dirname(sys.argv[0])
|
||||||
return os.path.join(script_dir, path)
|
return os.path.join(script_dir, path)
|
||||||
@ -123,7 +172,7 @@ class BaseTest(unittest.TestCase):
|
|||||||
content = f.read()
|
content = f.read()
|
||||||
opts = options
|
opts = options
|
||||||
if opts is None:
|
if opts is None:
|
||||||
opts = TestOptions()
|
opts = JniGeneratorOptions()
|
||||||
|
|
||||||
jni_from_java = jni_generator.JNIFromJavaSource(content, qualified_clazz,
|
jni_from_java = jni_generator.JNIFromJavaSource(content, qualified_clazz,
|
||||||
opts)
|
opts)
|
||||||
@ -192,8 +241,8 @@ class BaseTest(unittest.TestCase):
|
|||||||
if golden_file is None:
|
if golden_file is None:
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
caller.startswith('test'),
|
caller.startswith('test'),
|
||||||
'AssertGoldenTextEquals can only be called from a '
|
'AssertGoldenTextEquals can only be called without at golden file '
|
||||||
'test* method, not %s' % caller)
|
'from a test* method, not %s' % caller)
|
||||||
golden_file = '%s%s.golden' % (caller, suffix)
|
golden_file = '%s%s.golden' % (caller, suffix)
|
||||||
golden_text = self._ReadGoldenFile(golden_file)
|
golden_text = self._ReadGoldenFile(golden_file)
|
||||||
if os.environ.get(_REBASELINE_ENV):
|
if os.environ.get(_REBASELINE_ENV):
|
||||||
@ -209,6 +258,7 @@ class BaseTest(unittest.TestCase):
|
|||||||
self.AssertTextEquals(golden_text, generated_text)
|
self.AssertTextEquals(golden_text, generated_text)
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(os.name == 'nt', 'Not intended to work on Windows')
|
||||||
class TestGenerator(BaseTest):
|
class TestGenerator(BaseTest):
|
||||||
|
|
||||||
def testInspectCaller(self):
|
def testInspectCaller(self):
|
||||||
@ -375,21 +425,21 @@ class TestGenerator(BaseTest):
|
|||||||
java_class_name=None)
|
java_class_name=None)
|
||||||
]
|
]
|
||||||
self.AssertListEquals(golden_natives, natives)
|
self.AssertListEquals(golden_natives, natives)
|
||||||
h1 = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
|
h1 = jni_generator.InlHeaderFileGenerator('', '', 'org/chromium/TestJni',
|
||||||
natives, [], [], jni_params,
|
natives, [], [], jni_params,
|
||||||
TestOptions())
|
JniGeneratorOptions())
|
||||||
self.AssertGoldenTextEquals(h1.GetContent())
|
self.AssertGoldenTextEquals(h1.GetContent())
|
||||||
h2 = jni_registration_generator.HeaderGenerator('',
|
h2 = jni_registration_generator.DictionaryGenerator(JniGeneratorOptions(),
|
||||||
'',
|
'', '',
|
||||||
'org/chromium/TestJni',
|
'org/chromium/TestJni',
|
||||||
natives,
|
natives, jni_params,
|
||||||
jni_params,
|
True)
|
||||||
True,
|
|
||||||
use_proxy_hash=False)
|
|
||||||
content = TestGenerator._MergeRegistrationForTests([h2.Generate()])
|
content = TestGenerator._MergeRegistrationForTests([h2.Generate()])
|
||||||
|
|
||||||
|
reg_options = JniRegistrationGeneratorOptions()
|
||||||
|
reg_options.manual_jni_registration = True
|
||||||
self.AssertGoldenTextEquals(jni_registration_generator.CreateFromDict(
|
self.AssertGoldenTextEquals(jni_registration_generator.CreateFromDict(
|
||||||
content, use_hash=False, manual_jni_registration=True),
|
reg_options, '', content),
|
||||||
suffix='Registrations')
|
suffix='Registrations')
|
||||||
|
|
||||||
def testInnerClassNatives(self):
|
def testInnerClassNatives(self):
|
||||||
@ -410,9 +460,9 @@ class TestGenerator(BaseTest):
|
|||||||
]
|
]
|
||||||
self.AssertListEquals(golden_natives, natives)
|
self.AssertListEquals(golden_natives, natives)
|
||||||
jni_params = jni_generator.JniParams('')
|
jni_params = jni_generator.JniParams('')
|
||||||
h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
|
h = jni_generator.InlHeaderFileGenerator('', '', 'org/chromium/TestJni',
|
||||||
natives, [], [], jni_params,
|
natives, [], [], jni_params,
|
||||||
TestOptions())
|
JniGeneratorOptions())
|
||||||
self.AssertGoldenTextEquals(h.GetContent())
|
self.AssertGoldenTextEquals(h.GetContent())
|
||||||
|
|
||||||
def testInnerClassNativesMultiple(self):
|
def testInnerClassNativesMultiple(self):
|
||||||
@ -443,9 +493,9 @@ class TestGenerator(BaseTest):
|
|||||||
]
|
]
|
||||||
self.AssertListEquals(golden_natives, natives)
|
self.AssertListEquals(golden_natives, natives)
|
||||||
jni_params = jni_generator.JniParams('')
|
jni_params = jni_generator.JniParams('')
|
||||||
h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
|
h = jni_generator.InlHeaderFileGenerator('', '', 'org/chromium/TestJni',
|
||||||
natives, [], [], jni_params,
|
natives, [], [], jni_params,
|
||||||
TestOptions())
|
JniGeneratorOptions())
|
||||||
self.AssertGoldenTextEquals(h.GetContent())
|
self.AssertGoldenTextEquals(h.GetContent())
|
||||||
|
|
||||||
def testInnerClassNativesBothInnerAndOuter(self):
|
def testInnerClassNativesBothInnerAndOuter(self):
|
||||||
@ -475,22 +525,22 @@ class TestGenerator(BaseTest):
|
|||||||
]
|
]
|
||||||
self.AssertListEquals(golden_natives, natives)
|
self.AssertListEquals(golden_natives, natives)
|
||||||
jni_params = jni_generator.JniParams('')
|
jni_params = jni_generator.JniParams('')
|
||||||
h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
|
h = jni_generator.InlHeaderFileGenerator('', '', 'org/chromium/TestJni',
|
||||||
natives, [], [], jni_params,
|
natives, [], [], jni_params,
|
||||||
TestOptions())
|
JniGeneratorOptions())
|
||||||
self.AssertGoldenTextEquals(h.GetContent())
|
self.AssertGoldenTextEquals(h.GetContent())
|
||||||
|
|
||||||
h2 = jni_registration_generator.HeaderGenerator('',
|
h2 = jni_registration_generator.DictionaryGenerator(JniGeneratorOptions(),
|
||||||
'',
|
'', '',
|
||||||
'org/chromium/TestJni',
|
'org/chromium/TestJni',
|
||||||
natives,
|
natives, jni_params,
|
||||||
jni_params,
|
True)
|
||||||
True,
|
|
||||||
use_proxy_hash=False)
|
|
||||||
content = TestGenerator._MergeRegistrationForTests([h2.Generate()])
|
content = TestGenerator._MergeRegistrationForTests([h2.Generate()])
|
||||||
|
|
||||||
|
reg_options = JniRegistrationGeneratorOptions()
|
||||||
|
reg_options.manual_jni_registration = True
|
||||||
self.AssertGoldenTextEquals(jni_registration_generator.CreateFromDict(
|
self.AssertGoldenTextEquals(jni_registration_generator.CreateFromDict(
|
||||||
content, use_hash=False, manual_jni_registration=True),
|
reg_options, '', content),
|
||||||
suffix='Registrations')
|
suffix='Registrations')
|
||||||
|
|
||||||
def testCalledByNatives(self):
|
def testCalledByNatives(self):
|
||||||
@ -839,9 +889,9 @@ class TestGenerator(BaseTest):
|
|||||||
),
|
),
|
||||||
]
|
]
|
||||||
self.AssertListEquals(golden_called_by_natives, called_by_natives)
|
self.AssertListEquals(golden_called_by_natives, called_by_natives)
|
||||||
h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni', [],
|
h = jni_generator.InlHeaderFileGenerator('', '', 'org/chromium/TestJni', [],
|
||||||
called_by_natives, [], jni_params,
|
called_by_natives, [], jni_params,
|
||||||
TestOptions())
|
JniGeneratorOptions())
|
||||||
self.AssertGoldenTextEquals(h.GetContent())
|
self.AssertGoldenTextEquals(h.GetContent())
|
||||||
|
|
||||||
def testCalledByNativeParseError(self):
|
def testCalledByNativeParseError(self):
|
||||||
@ -938,8 +988,8 @@ public abstract class java.util.HashSet<T> extends java.util.AbstractSet<E>
|
|||||||
Signature: ([Landroid/icu/text/DisplayContext;)V
|
Signature: ([Landroid/icu/text/DisplayContext;)V
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
jni_from_javap = jni_generator.JNIFromJavaP(
|
jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'),
|
||||||
contents.split('\n'), TestOptions())
|
JniGeneratorOptions())
|
||||||
self.AssertGoldenTextEquals(jni_from_javap.GetContent())
|
self.AssertGoldenTextEquals(jni_from_javap.GetContent())
|
||||||
|
|
||||||
def testSnippnetJavap6_7_8(self):
|
def testSnippnetJavap6_7_8(self):
|
||||||
@ -964,12 +1014,12 @@ public class java.util.HashSet {
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
jni_from_javap6 = jni_generator.JNIFromJavaP(
|
jni_from_javap6 = jni_generator.JNIFromJavaP(content_javap6.split('\n'),
|
||||||
content_javap6.split('\n'), TestOptions())
|
JniGeneratorOptions())
|
||||||
jni_from_javap7 = jni_generator.JNIFromJavaP(
|
jni_from_javap7 = jni_generator.JNIFromJavaP(content_javap7.split('\n'),
|
||||||
content_javap7.split('\n'), TestOptions())
|
JniGeneratorOptions())
|
||||||
jni_from_javap8 = jni_generator.JNIFromJavaP(
|
jni_from_javap8 = jni_generator.JNIFromJavaP(content_javap8.split('\n'),
|
||||||
content_javap8.split('\n'), TestOptions())
|
JniGeneratorOptions())
|
||||||
self.assertTrue(jni_from_javap6.GetContent())
|
self.assertTrue(jni_from_javap6.GetContent())
|
||||||
self.assertTrue(jni_from_javap7.GetContent())
|
self.assertTrue(jni_from_javap7.GetContent())
|
||||||
self.assertTrue(jni_from_javap8.GetContent())
|
self.assertTrue(jni_from_javap8.GetContent())
|
||||||
@ -983,16 +1033,16 @@ public class java.util.HashSet {
|
|||||||
|
|
||||||
def testFromJavaP(self):
|
def testFromJavaP(self):
|
||||||
contents = self._ReadGoldenFile('testInputStream.javap')
|
contents = self._ReadGoldenFile('testInputStream.javap')
|
||||||
jni_from_javap = jni_generator.JNIFromJavaP(
|
jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'),
|
||||||
contents.split('\n'), TestOptions())
|
JniGeneratorOptions())
|
||||||
self.assertEqual(10, len(jni_from_javap.called_by_natives))
|
self.assertEqual(10, len(jni_from_javap.called_by_natives))
|
||||||
self.AssertGoldenTextEquals(jni_from_javap.GetContent())
|
self.AssertGoldenTextEquals(jni_from_javap.GetContent())
|
||||||
|
|
||||||
def testConstantsFromJavaP(self):
|
def testConstantsFromJavaP(self):
|
||||||
for f in ['testMotionEvent.javap', 'testMotionEvent.javap7']:
|
for f in ['testMotionEvent.javap', 'testMotionEvent.javap7']:
|
||||||
contents = self._ReadGoldenFile(f)
|
contents = self._ReadGoldenFile(f)
|
||||||
jni_from_javap = jni_generator.JNIFromJavaP(
|
jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'),
|
||||||
contents.split('\n'), TestOptions())
|
JniGeneratorOptions())
|
||||||
self.assertEqual(86, len(jni_from_javap.called_by_natives))
|
self.assertEqual(86, len(jni_from_javap.called_by_natives))
|
||||||
self.AssertGoldenTextEquals(jni_from_javap.GetContent())
|
self.AssertGoldenTextEquals(jni_from_javap.GetContent())
|
||||||
|
|
||||||
@ -1013,8 +1063,8 @@ public class java.util.HashSet {
|
|||||||
private native void nativeSyncSetupEnded(
|
private native void nativeSyncSetupEnded(
|
||||||
int nativeAndroidSyncSetupFlowHandler);
|
int nativeAndroidSyncSetupFlowHandler);
|
||||||
"""
|
"""
|
||||||
jni_from_java = jni_generator.JNIFromJavaSource(
|
jni_from_java = jni_generator.JNIFromJavaSource(test_data, 'foo/bar',
|
||||||
test_data, 'foo/bar', TestOptions())
|
JniGeneratorOptions())
|
||||||
self.AssertGoldenTextEquals(jni_from_java.GetContent())
|
self.AssertGoldenTextEquals(jni_from_java.GetContent())
|
||||||
|
|
||||||
def testRaisesOnNonJNIMethod(self):
|
def testRaisesOnNonJNIMethod(self):
|
||||||
@ -1025,7 +1075,7 @@ public class java.util.HashSet {
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
self.assertRaises(SyntaxError, jni_generator.JNIFromJavaSource, test_data,
|
self.assertRaises(SyntaxError, jni_generator.JNIFromJavaSource, test_data,
|
||||||
'foo/bar', TestOptions())
|
'foo/bar', JniGeneratorOptions())
|
||||||
|
|
||||||
def testJniSelfDocumentingExample(self):
|
def testJniSelfDocumentingExample(self):
|
||||||
generated_text = self._CreateJniHeaderFromFile(
|
generated_text = self._CreateJniHeaderFromFile(
|
||||||
@ -1045,7 +1095,7 @@ public class java.util.HashSet {
|
|||||||
jni_from_java = jni_generator.JNIFromJavaSource(
|
jni_from_java = jni_generator.JNIFromJavaSource(
|
||||||
test_data, ('com/google/lookhowextremelylongiam/snarf/'
|
test_data, ('com/google/lookhowextremelylongiam/snarf/'
|
||||||
'icankeepthisupallday/ReallyLongClassNamesAreAllTheRage'),
|
'icankeepthisupallday/ReallyLongClassNamesAreAllTheRage'),
|
||||||
TestOptions())
|
JniGeneratorOptions())
|
||||||
jni_lines = jni_from_java.GetContent().split('\n')
|
jni_lines = jni_from_java.GetContent().split('\n')
|
||||||
line = next(
|
line = next(
|
||||||
line for line in jni_lines if line.lstrip().startswith('#ifndef'))
|
line for line in jni_lines if line.lstrip().startswith('#ifndef'))
|
||||||
@ -1113,7 +1163,7 @@ class Foo {
|
|||||||
jni_params.JavaToJni('java/nio/ByteBuffer[]'))
|
jni_params.JavaToJni('java/nio/ByteBuffer[]'))
|
||||||
|
|
||||||
def testNativesLong(self):
|
def testNativesLong(self):
|
||||||
test_options = TestOptions()
|
test_options = JniGeneratorOptions()
|
||||||
test_options.ptr_type = 'long'
|
test_options.ptr_type = 'long'
|
||||||
test_data = """"
|
test_data = """"
|
||||||
private native void nativeDestroy(long nativeChromeBrowserProvider);
|
private native void nativeDestroy(long nativeChromeBrowserProvider);
|
||||||
@ -1131,8 +1181,9 @@ class Foo {
|
|||||||
ptr_type=test_options.ptr_type),
|
ptr_type=test_options.ptr_type),
|
||||||
]
|
]
|
||||||
self.AssertListEquals(golden_natives, natives)
|
self.AssertListEquals(golden_natives, natives)
|
||||||
h = jni_generator.InlHeaderFileGenerator(
|
h = jni_generator.InlHeaderFileGenerator('', '', 'org/chromium/TestJni',
|
||||||
'', 'org/chromium/TestJni', natives, [], [], jni_params, test_options)
|
natives, [], [], jni_params,
|
||||||
|
test_options)
|
||||||
self.AssertGoldenTextEquals(h.GetContent())
|
self.AssertGoldenTextEquals(h.GetContent())
|
||||||
|
|
||||||
def testMainDexAnnotation(self):
|
def testMainDexAnnotation(self):
|
||||||
@ -1210,8 +1261,7 @@ class Foo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
options = TestOptions()
|
options = JniGeneratorOptions()
|
||||||
options.native_exports_optional = False
|
|
||||||
jni_from_java = jni_generator.JNIFromJavaSource(
|
jni_from_java = jni_generator.JNIFromJavaSource(
|
||||||
test_data, 'org/chromium/example/jni_generator/SampleForTests', options)
|
test_data, 'org/chromium/example/jni_generator/SampleForTests', options)
|
||||||
self.AssertGoldenTextEquals(jni_from_java.GetContent())
|
self.AssertGoldenTextEquals(jni_from_java.GetContent())
|
||||||
@ -1229,7 +1279,7 @@ class Foo {
|
|||||||
def willRaise():
|
def willRaise():
|
||||||
jni_generator.JNIFromJavaSource(test_data,
|
jni_generator.JNIFromJavaSource(test_data,
|
||||||
'org/chromium/media/VideoCaptureFactory',
|
'org/chromium/media/VideoCaptureFactory',
|
||||||
TestOptions())
|
JniGeneratorOptions())
|
||||||
|
|
||||||
self.assertRaises(SyntaxError, willRaise)
|
self.assertRaises(SyntaxError, willRaise)
|
||||||
|
|
||||||
@ -1249,7 +1299,7 @@ class Foo {
|
|||||||
"""
|
"""
|
||||||
jni_from_java = jni_generator.JNIFromJavaSource(test_data,
|
jni_from_java = jni_generator.JNIFromJavaSource(test_data,
|
||||||
'org/chromium/foo/Foo',
|
'org/chromium/foo/Foo',
|
||||||
TestOptions())
|
JniGeneratorOptions())
|
||||||
self.AssertGoldenTextEquals(jni_from_java.GetContent())
|
self.AssertGoldenTextEquals(jni_from_java.GetContent())
|
||||||
|
|
||||||
def testMultipleJNIAdditionalImport(self):
|
def testMultipleJNIAdditionalImport(self):
|
||||||
@ -1270,7 +1320,7 @@ class Foo {
|
|||||||
"""
|
"""
|
||||||
jni_from_java = jni_generator.JNIFromJavaSource(test_data,
|
jni_from_java = jni_generator.JNIFromJavaSource(test_data,
|
||||||
'org/chromium/foo/Foo',
|
'org/chromium/foo/Foo',
|
||||||
TestOptions())
|
JniGeneratorOptions())
|
||||||
self.AssertGoldenTextEquals(jni_from_java.GetContent())
|
self.AssertGoldenTextEquals(jni_from_java.GetContent())
|
||||||
|
|
||||||
def testTracing(self):
|
def testTracing(self):
|
||||||
@ -1291,7 +1341,7 @@ class Foo {
|
|||||||
static native void nativeStaticMethod();
|
static native void nativeStaticMethod();
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
options_with_tracing = TestOptions()
|
options_with_tracing = JniGeneratorOptions()
|
||||||
options_with_tracing.enable_tracing = True
|
options_with_tracing.enable_tracing = True
|
||||||
jni_from_java = jni_generator.JNIFromJavaSource(
|
jni_from_java = jni_generator.JNIFromJavaSource(
|
||||||
test_data, 'org/chromium/foo/Foo', options_with_tracing)
|
test_data, 'org/chromium/foo/Foo', options_with_tracing)
|
||||||
@ -1314,11 +1364,11 @@ class Foo {
|
|||||||
|
|
||||||
jni_from_java = jni_generator.JNIFromJavaSource(test_data,
|
jni_from_java = jni_generator.JNIFromJavaSource(test_data,
|
||||||
'org/chromium/foo/Foo',
|
'org/chromium/foo/Foo',
|
||||||
TestOptions())
|
JniGeneratorOptions())
|
||||||
self.AssertGoldenTextEquals(jni_from_java.GetContent())
|
self.AssertGoldenTextEquals(jni_from_java.GetContent())
|
||||||
|
|
||||||
def testSplitNameExample(self):
|
def testSplitNameExample(self):
|
||||||
opts = TestOptions()
|
opts = JniGeneratorOptions()
|
||||||
opts.split_name = "sample"
|
opts.split_name = "sample"
|
||||||
generated_text = self._CreateJniHeaderFromFile(
|
generated_text = self._CreateJniHeaderFromFile(
|
||||||
os.path.join(_JAVA_SRC_DIR, 'SampleForTests.java'),
|
os.path.join(_JAVA_SRC_DIR, 'SampleForTests.java'),
|
||||||
@ -1327,19 +1377,58 @@ class Foo {
|
|||||||
generated_text, golden_file='SampleForTestsWithSplit_jni.golden')
|
generated_text, golden_file='SampleForTestsWithSplit_jni.golden')
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(os.name == 'nt', 'Not intended to work on Windows')
|
||||||
class ProxyTestGenerator(BaseTest):
|
class ProxyTestGenerator(BaseTest):
|
||||||
|
|
||||||
def _BuildRegDictFromSample(self, options=None):
|
def _BuildRegDictFromSample(self):
|
||||||
if options is None:
|
|
||||||
options = TestOptions()
|
|
||||||
|
|
||||||
path = self._JoinScriptDir(
|
path = self._JoinScriptDir(
|
||||||
os.path.join(_JAVA_SRC_DIR, 'SampleForAnnotationProcessor.java'))
|
os.path.join(_JAVA_SRC_DIR, 'SampleForAnnotationProcessor.java'))
|
||||||
reg_dict = jni_registration_generator._DictForPath(path)
|
reg_dict = jni_registration_generator._DictForPath(
|
||||||
|
JniRegistrationGeneratorOptions(), path)
|
||||||
reg_dict = self._MergeRegistrationForTests([reg_dict])
|
reg_dict = self._MergeRegistrationForTests([reg_dict])
|
||||||
|
|
||||||
return reg_dict
|
return reg_dict
|
||||||
|
|
||||||
|
def testEndToEndProxyHashed(self):
|
||||||
|
input_java_files = ['SampleForAnnotationProcessor.java']
|
||||||
|
options = JniRegistrationGeneratorOptions()
|
||||||
|
options.use_proxy_hash = True
|
||||||
|
name_to_goldens = {
|
||||||
|
'org/chromium/base/natives/GEN_JNI.java':
|
||||||
|
'HashedSampleForAnnotationProcessorGenJni.2.golden',
|
||||||
|
'J/N.java': 'HashedSampleForAnnotationProcessorGenJni.golden'
|
||||||
|
}
|
||||||
|
self._TestEndToEndRegistration(input_java_files, options, name_to_goldens)
|
||||||
|
|
||||||
|
def testEndToEndManualRegistration(self):
|
||||||
|
input_java_files = ['SampleForAnnotationProcessor.java']
|
||||||
|
options = JniRegistrationGeneratorOptions()
|
||||||
|
options.manual_jni_registration = True
|
||||||
|
name_to_goldens = {
|
||||||
|
'org/chromium/base/natives/GEN_JNI.java':
|
||||||
|
'SampleForAnnotationProcessorGenJni.golden'
|
||||||
|
}
|
||||||
|
self._TestEndToEndRegistration(
|
||||||
|
input_java_files,
|
||||||
|
options,
|
||||||
|
name_to_goldens,
|
||||||
|
header_golden='SampleForAnnotationProcessorManualJni.golden')
|
||||||
|
|
||||||
|
def testEndToEndProxyJniWithModules(self):
|
||||||
|
input_java_files = [
|
||||||
|
'SampleForAnnotationProcessor.java', 'SampleModule.java'
|
||||||
|
]
|
||||||
|
options = JniRegistrationGeneratorOptions()
|
||||||
|
options.use_proxy_hash = True
|
||||||
|
name_to_goldens = {
|
||||||
|
'org/chromium/base/natives/GEN_JNI.java':
|
||||||
|
'HashedSampleForAnnotationProcessorGenJni.2.golden',
|
||||||
|
'J/N.java': 'HashedSampleForAnnotationProcessorGenJni.golden',
|
||||||
|
'org/chromium/base/natives/module_GEN_JNI.java': 'ModuleGenJni.golden',
|
||||||
|
'J/module_N.java': 'ModuleJN.golden'
|
||||||
|
}
|
||||||
|
self._TestEndToEndRegistration(input_java_files, options, name_to_goldens)
|
||||||
|
|
||||||
def testProxyNativesWithNatives(self):
|
def testProxyNativesWithNatives(self):
|
||||||
test_data = """
|
test_data = """
|
||||||
package org.chromium.foo;
|
package org.chromium.foo;
|
||||||
@ -1362,7 +1451,7 @@ class ProxyTestGenerator(BaseTest):
|
|||||||
|
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
options_with_tracing = TestOptions()
|
options_with_tracing = JniGeneratorOptions()
|
||||||
options_with_tracing.enable_tracing = True
|
options_with_tracing.enable_tracing = True
|
||||||
jni_from_java = jni_generator.JNIFromJavaSource(
|
jni_from_java = jni_generator.JNIFromJavaSource(
|
||||||
test_data, 'org/chromium/foo/Foo', options_with_tracing)
|
test_data, 'org/chromium/foo/Foo', options_with_tracing)
|
||||||
@ -1380,7 +1469,7 @@ class ProxyTestGenerator(BaseTest):
|
|||||||
"""
|
"""
|
||||||
qualified_clazz = 'org/chromium/example/SampleProxyJni'
|
qualified_clazz = 'org/chromium/example/SampleProxyJni'
|
||||||
|
|
||||||
natives = jni_generator.ProxyHelpers.ExtractStaticProxyNatives(
|
natives, _ = jni_generator.ProxyHelpers.ExtractStaticProxyNatives(
|
||||||
qualified_clazz, test_data, 'long')
|
qualified_clazz, test_data, 'long')
|
||||||
|
|
||||||
golden_natives = [
|
golden_natives = [
|
||||||
@ -1416,7 +1505,7 @@ class ProxyTestGenerator(BaseTest):
|
|||||||
"""
|
"""
|
||||||
qualified_clazz = 'org/chromium/example/SampleProxyJni'
|
qualified_clazz = 'org/chromium/example/SampleProxyJni'
|
||||||
|
|
||||||
natives = jni_generator.ProxyHelpers.ExtractStaticProxyNatives(
|
natives, _ = jni_generator.ProxyHelpers.ExtractStaticProxyNatives(
|
||||||
qualified_clazz, test_data, 'long', True)
|
qualified_clazz, test_data, 'long', True)
|
||||||
|
|
||||||
golden_natives = [
|
golden_natives = [
|
||||||
@ -1452,7 +1541,7 @@ class ProxyTestGenerator(BaseTest):
|
|||||||
"""
|
"""
|
||||||
qualified_clazz = 'org/chromium/example/SampleProxyJni'
|
qualified_clazz = 'org/chromium/example/SampleProxyJni'
|
||||||
|
|
||||||
natives = jni_generator.ProxyHelpers.ExtractStaticProxyNatives(
|
natives, _ = jni_generator.ProxyHelpers.ExtractStaticProxyNatives(
|
||||||
qualified_clazz, test_data, 'long', False)
|
qualified_clazz, test_data, 'long', False)
|
||||||
|
|
||||||
self.AssertListEquals(_RemoveHashedNames(natives), [])
|
self.AssertListEquals(_RemoveHashedNames(natives), [])
|
||||||
@ -1481,9 +1570,10 @@ class ProxyTestGenerator(BaseTest):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
qualified_clazz = 'test/foo/Foo'
|
qualified_clazz = 'test/foo/Foo'
|
||||||
jni_params = TestOptions()
|
options = JniRegistrationGeneratorOptions()
|
||||||
|
options.manual_jni_registration = True
|
||||||
|
|
||||||
natives = jni_generator.ProxyHelpers.ExtractStaticProxyNatives(
|
natives, _ = jni_generator.ProxyHelpers.ExtractStaticProxyNatives(
|
||||||
qualified_clazz, test_data, 'long')
|
qualified_clazz, test_data, 'long')
|
||||||
|
|
||||||
golden_natives = [
|
golden_natives = [
|
||||||
@ -1500,42 +1590,33 @@ class ProxyTestGenerator(BaseTest):
|
|||||||
self.AssertListEquals(_RemoveHashedNames(natives), golden_natives)
|
self.AssertListEquals(_RemoveHashedNames(natives), golden_natives)
|
||||||
|
|
||||||
jni_params = jni_generator.JniParams(qualified_clazz)
|
jni_params = jni_generator.JniParams(qualified_clazz)
|
||||||
main_dex_header = jni_registration_generator.HeaderGenerator(
|
main_dex_header = jni_registration_generator.DictionaryGenerator(
|
||||||
'',
|
options, '', '', qualified_clazz, natives, jni_params,
|
||||||
'',
|
main_dex=True).Generate()
|
||||||
qualified_clazz,
|
|
||||||
natives,
|
|
||||||
jni_params,
|
|
||||||
main_dex=True,
|
|
||||||
use_proxy_hash=False).Generate()
|
|
||||||
content = TestGenerator._MergeRegistrationForTests([main_dex_header])
|
content = TestGenerator._MergeRegistrationForTests([main_dex_header])
|
||||||
|
|
||||||
self.AssertGoldenTextEquals(
|
self.AssertGoldenTextEquals(
|
||||||
jni_registration_generator.CreateFromDict(content,
|
jni_registration_generator.CreateFromDict(options, '', content))
|
||||||
use_hash=False,
|
|
||||||
manual_jni_registration=True))
|
|
||||||
|
|
||||||
other_qualified_clazz = 'test/foo/Bar'
|
other_qualified_clazz = 'test/foo/Bar'
|
||||||
other_natives = jni_generator.ProxyHelpers.ExtractStaticProxyNatives(
|
other_natives, _ = jni_generator.ProxyHelpers.ExtractStaticProxyNatives(
|
||||||
other_qualified_clazz, non_main_dex_test_data, 'long')
|
other_qualified_clazz, non_main_dex_test_data, 'long')
|
||||||
|
|
||||||
jni_params = jni_generator.JniParams(other_qualified_clazz)
|
jni_params = jni_generator.JniParams(other_qualified_clazz)
|
||||||
non_main_dex_header = jni_registration_generator.HeaderGenerator(
|
non_main_dex_header = jni_registration_generator.DictionaryGenerator(
|
||||||
|
options,
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
other_qualified_clazz,
|
other_qualified_clazz,
|
||||||
other_natives,
|
other_natives,
|
||||||
jni_params,
|
jni_params,
|
||||||
main_dex=False,
|
main_dex=False).Generate()
|
||||||
use_proxy_hash=False).Generate()
|
|
||||||
|
|
||||||
content = TestGenerator._MergeRegistrationForTests([main_dex_header] +
|
content = TestGenerator._MergeRegistrationForTests([main_dex_header] +
|
||||||
[non_main_dex_header])
|
[non_main_dex_header])
|
||||||
|
|
||||||
self.AssertGoldenTextEquals(
|
self.AssertGoldenTextEquals(
|
||||||
jni_registration_generator.CreateFromDict(content,
|
jni_registration_generator.CreateFromDict(options, '', content),
|
||||||
use_hash=False,
|
|
||||||
manual_jni_registration=True),
|
|
||||||
'AndNonMainDex')
|
'AndNonMainDex')
|
||||||
|
|
||||||
def testProxyNatives(self):
|
def testProxyNatives(self):
|
||||||
@ -1575,9 +1656,9 @@ class ProxyTestGenerator(BaseTest):
|
|||||||
|
|
||||||
qualified_clazz = 'org/chromium/example/SampleProxyJni'
|
qualified_clazz = 'org/chromium/example/SampleProxyJni'
|
||||||
|
|
||||||
natives = jni_generator.ProxyHelpers.ExtractStaticProxyNatives(
|
natives, _ = jni_generator.ProxyHelpers.ExtractStaticProxyNatives(
|
||||||
qualified_clazz, test_data, 'long')
|
qualified_clazz, test_data, 'long')
|
||||||
bad_spacing_natives = jni_generator.ProxyHelpers \
|
bad_spacing_natives, _ = jni_generator.ProxyHelpers \
|
||||||
.ExtractStaticProxyNatives(qualified_clazz, bad_spaced_test_data, 'long')
|
.ExtractStaticProxyNatives(qualified_clazz, bad_spaced_test_data, 'long')
|
||||||
golden_natives = [
|
golden_natives = [
|
||||||
NativeMethod(
|
NativeMethod(
|
||||||
@ -1616,34 +1697,32 @@ class ProxyTestGenerator(BaseTest):
|
|||||||
self.AssertListEquals(golden_natives, _RemoveHashedNames(natives))
|
self.AssertListEquals(golden_natives, _RemoveHashedNames(natives))
|
||||||
self.AssertListEquals(golden_natives,
|
self.AssertListEquals(golden_natives,
|
||||||
_RemoveHashedNames(bad_spacing_natives))
|
_RemoveHashedNames(bad_spacing_natives))
|
||||||
|
options = JniGeneratorOptions()
|
||||||
|
reg_options = JniRegistrationGeneratorOptions()
|
||||||
|
reg_options.manual_jni_registration = True
|
||||||
|
|
||||||
jni_params = jni_generator.JniParams(qualified_clazz)
|
jni_params = jni_generator.JniParams(qualified_clazz)
|
||||||
h1 = jni_generator.InlHeaderFileGenerator('', qualified_clazz, natives, [],
|
h1 = jni_generator.InlHeaderFileGenerator('', '', qualified_clazz, natives,
|
||||||
[], jni_params, TestOptions())
|
[], [], jni_params, options)
|
||||||
self.AssertGoldenTextEquals(h1.GetContent())
|
self.AssertGoldenTextEquals(h1.GetContent())
|
||||||
h2 = jni_registration_generator.HeaderGenerator('',
|
h2 = jni_registration_generator.DictionaryGenerator(reg_options, '', '',
|
||||||
'',
|
qualified_clazz,
|
||||||
qualified_clazz,
|
natives, jni_params,
|
||||||
natives,
|
False)
|
||||||
jni_params,
|
|
||||||
False,
|
|
||||||
use_proxy_hash=False)
|
|
||||||
content = TestGenerator._MergeRegistrationForTests([h2.Generate()])
|
content = TestGenerator._MergeRegistrationForTests([h2.Generate()])
|
||||||
|
|
||||||
proxy_opts = jni_registration_generator.ProxyOptions(
|
|
||||||
manual_jni_registration=True)
|
|
||||||
self.AssertGoldenTextEquals(
|
self.AssertGoldenTextEquals(
|
||||||
jni_registration_generator.CreateProxyJavaFromDict(content, proxy_opts),
|
jni_registration_generator.CreateProxyJavaFromDict(
|
||||||
|
reg_options, '', content),
|
||||||
suffix='Java')
|
suffix='Java')
|
||||||
|
|
||||||
self.AssertGoldenTextEquals(jni_registration_generator.CreateFromDict(
|
self.AssertGoldenTextEquals(jni_registration_generator.CreateFromDict(
|
||||||
content,
|
reg_options, '', content),
|
||||||
proxy_opts.use_hash,
|
|
||||||
manual_jni_registration=proxy_opts.manual_jni_registration),
|
|
||||||
suffix='Registrations')
|
suffix='Registrations')
|
||||||
|
|
||||||
def testProxyHashedExample(self):
|
def testProxyHashedExample(self):
|
||||||
opts = TestOptions()
|
opts = JniGeneratorOptions()
|
||||||
opts.use_proxy_hash = True
|
opts.use_proxy_hash = True
|
||||||
path = os.path.join(_JAVA_SRC_DIR, 'SampleForAnnotationProcessor.java')
|
path = os.path.join(_JAVA_SRC_DIR, 'SampleForAnnotationProcessor.java')
|
||||||
|
|
||||||
@ -1654,20 +1733,6 @@ class ProxyTestGenerator(BaseTest):
|
|||||||
generated_text,
|
generated_text,
|
||||||
golden_file='HashedSampleForAnnotationProcessor_jni.golden')
|
golden_file='HashedSampleForAnnotationProcessor_jni.golden')
|
||||||
|
|
||||||
reg_dict = jni_registration_generator._DictForPath(
|
|
||||||
self._JoinScriptDir(path), use_proxy_hash=True)
|
|
||||||
reg_dict = self._MergeRegistrationForTests([reg_dict])
|
|
||||||
|
|
||||||
proxy_opts = jni_registration_generator.ProxyOptions(use_hash=True)
|
|
||||||
self.AssertGoldenTextEquals(
|
|
||||||
jni_registration_generator.CreateProxyJavaFromDict(
|
|
||||||
reg_dict, proxy_opts),
|
|
||||||
golden_file='HashedSampleForAnnotationProcessorGenJni.golden')
|
|
||||||
self.AssertGoldenTextEquals(
|
|
||||||
jni_registration_generator.CreateProxyJavaFromDict(
|
|
||||||
reg_dict, proxy_opts, forwarding=True),
|
|
||||||
golden_file='HashedSampleForAnnotationProcessorGenJni.2.golden')
|
|
||||||
|
|
||||||
def testProxyJniExample(self):
|
def testProxyJniExample(self):
|
||||||
generated_text = self._CreateJniHeaderFromFile(
|
generated_text = self._CreateJniHeaderFromFile(
|
||||||
os.path.join(_JAVA_SRC_DIR, 'SampleForAnnotationProcessor.java'),
|
os.path.join(_JAVA_SRC_DIR, 'SampleForAnnotationProcessor.java'),
|
||||||
@ -1676,21 +1741,20 @@ class ProxyTestGenerator(BaseTest):
|
|||||||
generated_text, golden_file='SampleForAnnotationProcessor_jni.golden')
|
generated_text, golden_file='SampleForAnnotationProcessor_jni.golden')
|
||||||
|
|
||||||
def testGenJniFlags(self):
|
def testGenJniFlags(self):
|
||||||
|
options = JniRegistrationGeneratorOptions()
|
||||||
reg_dict = self._BuildRegDictFromSample()
|
reg_dict = self._BuildRegDictFromSample()
|
||||||
proxy_options = jni_registration_generator.ProxyOptions()
|
|
||||||
content = jni_registration_generator.CreateProxyJavaFromDict(
|
content = jni_registration_generator.CreateProxyJavaFromDict(
|
||||||
reg_dict, proxy_options)
|
options, '', reg_dict)
|
||||||
self.AssertGoldenTextEquals(content, 'Disabled')
|
self.AssertGoldenTextEquals(content, 'Disabled')
|
||||||
|
|
||||||
proxy_options = jni_registration_generator.ProxyOptions(enable_mocks=True)
|
options.enable_proxy_mocks = True
|
||||||
content = jni_registration_generator.CreateProxyJavaFromDict(
|
content = jni_registration_generator.CreateProxyJavaFromDict(
|
||||||
reg_dict, proxy_options)
|
options, '', reg_dict)
|
||||||
self.AssertGoldenTextEquals(content, 'MocksEnabled')
|
self.AssertGoldenTextEquals(content, 'MocksEnabled')
|
||||||
|
|
||||||
proxy_options = jni_registration_generator.ProxyOptions(
|
options.require_mocks = True
|
||||||
enable_mocks=True, require_mocks=True)
|
|
||||||
content = jni_registration_generator.CreateProxyJavaFromDict(
|
content = jni_registration_generator.CreateProxyJavaFromDict(
|
||||||
reg_dict, proxy_options)
|
options, '', reg_dict)
|
||||||
self.AssertGoldenTextEquals(content, 'MocksRequired')
|
self.AssertGoldenTextEquals(content, 'MocksRequired')
|
||||||
|
|
||||||
def testProxyTypeInfoPreserved(self):
|
def testProxyTypeInfoPreserved(self):
|
||||||
@ -1708,8 +1772,8 @@ class ProxyTestGenerator(BaseTest):
|
|||||||
SomeJavaType[][] someObjects);
|
SomeJavaType[][] someObjects);
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
natives = ProxyHelpers.ExtractStaticProxyNatives('org/chromium/foo/FooJni',
|
natives, _ = ProxyHelpers.ExtractStaticProxyNatives(
|
||||||
test_data, 'long')
|
'org/chromium/foo/FooJni', test_data, 'long')
|
||||||
golden_natives = [
|
golden_natives = [
|
||||||
NativeMethod(
|
NativeMethod(
|
||||||
static=True,
|
static=True,
|
||||||
@ -1758,63 +1822,53 @@ class ProxyTestGenerator(BaseTest):
|
|||||||
self.AssertListEquals(golden_natives, _RemoveHashedNames(natives))
|
self.AssertListEquals(golden_natives, _RemoveHashedNames(natives))
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipIf(os.name == 'nt', 'Not intended to work on Windows')
|
||||||
class MultiplexTestGenerator(BaseTest):
|
class MultiplexTestGenerator(BaseTest):
|
||||||
|
options = JniRegistrationGeneratorOptions()
|
||||||
|
options.enable_jni_multiplexing = True
|
||||||
|
|
||||||
def testProxyMultiplexGenJni(self):
|
def testProxyMultiplexGenJni(self):
|
||||||
path = os.path.join(_JAVA_SRC_DIR, 'SampleForAnnotationProcessor.java')
|
path = os.path.join(_JAVA_SRC_DIR, 'SampleForAnnotationProcessor.java')
|
||||||
reg_dict = jni_registration_generator._DictForPath(
|
reg_dict = jni_registration_generator._DictForPath(
|
||||||
self._JoinScriptDir(path),
|
self.options, self._JoinScriptDir(path))
|
||||||
enable_jni_multiplexing=True,
|
|
||||||
namespace='test')
|
|
||||||
reg_dict = self._MergeRegistrationForTests([reg_dict],
|
reg_dict = self._MergeRegistrationForTests([reg_dict],
|
||||||
enable_jni_multiplexing=True)
|
enable_jni_multiplexing=True)
|
||||||
|
|
||||||
proxy_opts = jni_registration_generator.ProxyOptions(
|
|
||||||
enable_jni_multiplexing=True)
|
|
||||||
self.AssertGoldenTextEquals(
|
self.AssertGoldenTextEquals(
|
||||||
jni_registration_generator.CreateProxyJavaFromDict(
|
jni_registration_generator.CreateProxyJavaFromDict(
|
||||||
reg_dict, proxy_opts),
|
self.options, '', reg_dict),
|
||||||
golden_file='testProxyMultiplexGenJni.golden')
|
golden_file='testProxyMultiplexGenJni.golden')
|
||||||
|
|
||||||
self.AssertGoldenTextEquals(
|
self.AssertGoldenTextEquals(
|
||||||
jni_registration_generator.CreateProxyJavaFromDict(reg_dict,
|
jni_registration_generator.CreateProxyJavaFromDict(self.options,
|
||||||
proxy_opts,
|
'',
|
||||||
|
reg_dict,
|
||||||
forwarding=True),
|
forwarding=True),
|
||||||
golden_file='testProxyMultiplexGenJni.2.golden')
|
golden_file='testProxyMultiplexGenJni.2.golden')
|
||||||
|
|
||||||
def testProxyMultiplexNatives(self):
|
def testProxyMultiplexNatives(self):
|
||||||
path = os.path.join(_JAVA_SRC_DIR, 'SampleForAnnotationProcessor.java')
|
path = os.path.join(_JAVA_SRC_DIR, 'SampleForAnnotationProcessor.java')
|
||||||
reg_dict = jni_registration_generator._DictForPath(
|
reg_dict = jni_registration_generator._DictForPath(
|
||||||
self._JoinScriptDir(path),
|
self.options, self._JoinScriptDir(path))
|
||||||
enable_jni_multiplexing=True,
|
|
||||||
namespace='test')
|
|
||||||
reg_dict = self._MergeRegistrationForTests([reg_dict],
|
reg_dict = self._MergeRegistrationForTests([reg_dict],
|
||||||
enable_jni_multiplexing=True)
|
enable_jni_multiplexing=True)
|
||||||
|
|
||||||
proxy_opts = jni_registration_generator.ProxyOptions(
|
|
||||||
enable_jni_multiplexing=True)
|
|
||||||
self.AssertGoldenTextEquals(jni_registration_generator.CreateFromDict(
|
self.AssertGoldenTextEquals(jni_registration_generator.CreateFromDict(
|
||||||
reg_dict,
|
self.options, '', reg_dict),
|
||||||
proxy_opts.use_hash,
|
|
||||||
enable_jni_multiplexing=proxy_opts.enable_jni_multiplexing),
|
|
||||||
golden_file='testProxyMultiplexNatives.golden')
|
golden_file='testProxyMultiplexNatives.golden')
|
||||||
|
|
||||||
def testProxyMultiplexNativesRegistration(self):
|
def testProxyMultiplexNativesRegistration(self):
|
||||||
path = os.path.join(_JAVA_SRC_DIR, 'SampleForAnnotationProcessor.java')
|
path = os.path.join(_JAVA_SRC_DIR, 'SampleForAnnotationProcessor.java')
|
||||||
reg_dict_for_registration = jni_registration_generator._DictForPath(
|
reg_dict_for_registration = jni_registration_generator._DictForPath(
|
||||||
self._JoinScriptDir(path),
|
self.options, self._JoinScriptDir(path))
|
||||||
enable_jni_multiplexing=True,
|
|
||||||
namespace='test')
|
|
||||||
reg_dict_for_registration = self._MergeRegistrationForTests(
|
reg_dict_for_registration = self._MergeRegistrationForTests(
|
||||||
[reg_dict_for_registration], enable_jni_multiplexing=True)
|
[reg_dict_for_registration], enable_jni_multiplexing=True)
|
||||||
|
|
||||||
proxy_opts = jni_registration_generator.ProxyOptions(
|
new_options = copy.copy(self.options)
|
||||||
enable_jni_multiplexing=True)
|
new_options.manual_jni_registration = True
|
||||||
self.AssertGoldenTextEquals(
|
self.AssertGoldenTextEquals(
|
||||||
jni_registration_generator.CreateFromDict(
|
jni_registration_generator.CreateFromDict(new_options, '',
|
||||||
reg_dict_for_registration,
|
reg_dict_for_registration),
|
||||||
proxy_opts.use_hash,
|
|
||||||
enable_jni_multiplexing=proxy_opts.enable_jni_multiplexing,
|
|
||||||
manual_jni_registration=True),
|
|
||||||
golden_file='testProxyMultiplexNativesRegistration.golden')
|
golden_file='testProxyMultiplexNativesRegistration.golden')
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
# Copyright 2017 The Chromium Authors
|
# Copyright 2017 The Chromium Authors
|
||||||
# Use of this source code is governed by a BSD-style license that can be
|
# Use of this source code is governed by a BSD-style license that can be
|
||||||
# found in the LICENSE file.
|
# found in the LICENSE file.
|
||||||
@ -37,12 +37,7 @@ MERGEABLE_KEYS = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def _Generate(java_file_paths,
|
def _Generate(options, java_file_paths):
|
||||||
srcjar_path,
|
|
||||||
proxy_opts,
|
|
||||||
header_path=None,
|
|
||||||
namespace='',
|
|
||||||
include_test_only=True):
|
|
||||||
"""Generates files required to perform JNI registration.
|
"""Generates files required to perform JNI registration.
|
||||||
|
|
||||||
Generates a srcjar containing a single class, GEN_JNI, that contains all
|
Generates a srcjar containing a single class, GEN_JNI, that contains all
|
||||||
@ -53,92 +48,92 @@ def _Generate(java_file_paths,
|
|||||||
JNI registration.
|
JNI registration.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
options: arguments from the command line
|
||||||
java_file_paths: A list of java file paths.
|
java_file_paths: A list of java file paths.
|
||||||
srcjar_path: Path to the GEN_JNI srcjar.
|
|
||||||
header_path: If specified, generates a header file in this location.
|
|
||||||
namespace: If specified, sets the namespace for the generated header file.
|
|
||||||
"""
|
"""
|
||||||
# Without multiprocessing, script takes ~13 seconds for chrome_public_apk
|
# Without multiprocessing, script takes ~13 seconds for chrome_public_apk
|
||||||
# on a z620. With multiprocessing, takes ~2 seconds.
|
# on a z620. With multiprocessing, takes ~2 seconds.
|
||||||
results = []
|
results = collections.defaultdict(list)
|
||||||
with multiprocessing.Pool() as pool:
|
with multiprocessing.Pool() as pool:
|
||||||
for d in pool.imap_unordered(
|
for d in pool.imap_unordered(functools.partial(_DictForPath, options),
|
||||||
functools.partial(
|
java_file_paths):
|
||||||
_DictForPath,
|
|
||||||
use_proxy_hash=proxy_opts.use_hash,
|
|
||||||
enable_jni_multiplexing=proxy_opts.enable_jni_multiplexing,
|
|
||||||
namespace=namespace,
|
|
||||||
include_test_only=include_test_only), java_file_paths):
|
|
||||||
if d:
|
if d:
|
||||||
results.append(d)
|
results[d['MODULE_NAME']].append(d)
|
||||||
|
|
||||||
# Sort to make output deterministic.
|
combined_dicts = collections.defaultdict(dict)
|
||||||
results.sort(key=lambda d: d['FULL_CLASS_NAME'])
|
for module_name, module_results in results.items():
|
||||||
|
# Sort to make output deterministic.
|
||||||
|
module_results.sort(key=lambda d: d['FULL_CLASS_NAME'])
|
||||||
|
combined_dict = combined_dicts[module_name]
|
||||||
|
for key in MERGEABLE_KEYS:
|
||||||
|
combined_dict[key] = ''.join(d.get(key, '') for d in module_results)
|
||||||
|
|
||||||
combined_dict = {}
|
# PROXY_NATIVE_SIGNATURES and PROXY_NATIVE_METHOD_ARRAY_MAIN_DEX will have
|
||||||
for key in MERGEABLE_KEYS:
|
# duplicates for JNI multiplexing since all native methods with similar
|
||||||
combined_dict[key] = ''.join(d.get(key, '') for d in results)
|
# signatures map to the same proxy. Similarly, there may be multiple switch
|
||||||
# PROXY_NATIVE_SIGNATURES and PROXY_NATIVE_METHOD_ARRAY_MAIN_DEX will have
|
# case entries for the same proxy signatures.
|
||||||
# duplicates for JNI multiplexing since all native methods with similar
|
if options.enable_jni_multiplexing:
|
||||||
# signatures map to the same proxy. Similarly, there may be multiple switch
|
proxy_signatures_list = sorted(
|
||||||
# case entries for the same proxy signatures.
|
set(combined_dict['PROXY_NATIVE_SIGNATURES'].split('\n')))
|
||||||
if proxy_opts.enable_jni_multiplexing:
|
combined_dict['PROXY_NATIVE_SIGNATURES'] = '\n'.join(
|
||||||
proxy_signatures_list = sorted(
|
signature for signature in proxy_signatures_list)
|
||||||
set(combined_dict['PROXY_NATIVE_SIGNATURES'].split('\n')))
|
|
||||||
combined_dict['PROXY_NATIVE_SIGNATURES'] = '\n'.join(
|
|
||||||
signature for signature in proxy_signatures_list)
|
|
||||||
|
|
||||||
proxy_native_array_list = sorted(
|
proxy_native_array_list = sorted(
|
||||||
set(combined_dict['PROXY_NATIVE_METHOD_ARRAY_MAIN_DEX'].split('},\n')))
|
set(combined_dict['PROXY_NATIVE_METHOD_ARRAY_MAIN_DEX'].split(
|
||||||
combined_dict['PROXY_NATIVE_METHOD_ARRAY_MAIN_DEX'] = '},\n'.join(
|
'},\n')))
|
||||||
p for p in proxy_native_array_list if p != '') + '}'
|
combined_dict['PROXY_NATIVE_METHOD_ARRAY_MAIN_DEX'] = '},\n'.join(
|
||||||
|
p for p in proxy_native_array_list if p != '') + '}'
|
||||||
|
|
||||||
signature_to_cases = collections.defaultdict(list)
|
signature_to_cases = collections.defaultdict(list)
|
||||||
for d in results:
|
for d in module_results:
|
||||||
for signature, cases in d['SIGNATURE_TO_CASES'].items():
|
for signature, cases in d['SIGNATURE_TO_CASES'].items():
|
||||||
signature_to_cases[signature].extend(cases)
|
signature_to_cases[signature].extend(cases)
|
||||||
combined_dict['FORWARDING_CALLS'] = _AddForwardingCalls(
|
combined_dict['FORWARDING_CALLS'] = _AddForwardingCalls(
|
||||||
signature_to_cases, namespace)
|
signature_to_cases, module_name)
|
||||||
|
|
||||||
|
if options.header_path:
|
||||||
|
assert len(
|
||||||
|
combined_dicts) == 1, 'Cannot output a header for multiple modules'
|
||||||
|
module_name = next(iter(combined_dicts))
|
||||||
|
combined_dict = combined_dicts[module_name]
|
||||||
|
|
||||||
if header_path:
|
|
||||||
combined_dict['HEADER_GUARD'] = \
|
combined_dict['HEADER_GUARD'] = \
|
||||||
os.path.splitext(header_path)[0].replace('/', '_').upper() + '_'
|
os.path.splitext(options.header_path)[0].replace('/', '_').replace('.', '_').upper() + '_'
|
||||||
combined_dict['NAMESPACE'] = namespace
|
combined_dict['NAMESPACE'] = options.namespace
|
||||||
header_content = CreateFromDict(
|
header_content = CreateFromDict(options, module_name, combined_dict)
|
||||||
combined_dict,
|
with build_utils.AtomicOutput(options.header_path, mode='w') as f:
|
||||||
proxy_opts.use_hash,
|
|
||||||
enable_jni_multiplexing=proxy_opts.enable_jni_multiplexing,
|
|
||||||
manual_jni_registration=proxy_opts.manual_jni_registration)
|
|
||||||
with build_utils.AtomicOutput(header_path, mode='w') as f:
|
|
||||||
f.write(header_content)
|
f.write(header_content)
|
||||||
|
|
||||||
with build_utils.AtomicOutput(srcjar_path) as f:
|
with build_utils.AtomicOutput(options.srcjar_path) as f:
|
||||||
with zipfile.ZipFile(f, 'w') as srcjar:
|
with zipfile.ZipFile(f, 'w') as srcjar:
|
||||||
if proxy_opts.use_hash or proxy_opts.enable_jni_multiplexing:
|
for module_name, combined_dict in combined_dicts.items():
|
||||||
# J/N.java
|
|
||||||
build_utils.AddToZipHermetic(
|
if options.use_proxy_hash or options.enable_jni_multiplexing:
|
||||||
srcjar,
|
# J/N.java
|
||||||
'%s.java' % jni_generator.ProxyHelpers.GetQualifiedClass(True),
|
build_utils.AddToZipHermetic(
|
||||||
data=CreateProxyJavaFromDict(combined_dict, proxy_opts))
|
srcjar,
|
||||||
# org/chromium/base/natives/GEN_JNI.java
|
'%s.java' %
|
||||||
build_utils.AddToZipHermetic(
|
jni_generator.ProxyHelpers.GetQualifiedClass(True, module_name),
|
||||||
srcjar,
|
data=CreateProxyJavaFromDict(options, module_name, combined_dict))
|
||||||
'%s.java' % jni_generator.ProxyHelpers.GetQualifiedClass(False),
|
# org/chromium/base/natives/GEN_JNI.java
|
||||||
data=CreateProxyJavaFromDict(
|
build_utils.AddToZipHermetic(
|
||||||
combined_dict, proxy_opts, forwarding=True))
|
srcjar,
|
||||||
else:
|
'%s.java' %
|
||||||
# org/chromium/base/natives/GEN_JNI.java
|
jni_generator.ProxyHelpers.GetQualifiedClass(False, module_name),
|
||||||
build_utils.AddToZipHermetic(
|
data=CreateProxyJavaFromDict(options,
|
||||||
srcjar,
|
module_name,
|
||||||
'%s.java' % jni_generator.ProxyHelpers.GetQualifiedClass(False),
|
combined_dict,
|
||||||
data=CreateProxyJavaFromDict(combined_dict, proxy_opts))
|
forwarding=True))
|
||||||
|
else:
|
||||||
|
# org/chromium/base/natives/GEN_JNI.java
|
||||||
|
build_utils.AddToZipHermetic(
|
||||||
|
srcjar,
|
||||||
|
'%s.java' %
|
||||||
|
jni_generator.ProxyHelpers.GetQualifiedClass(False, module_name),
|
||||||
|
data=CreateProxyJavaFromDict(options, module_name, combined_dict))
|
||||||
|
|
||||||
|
|
||||||
def _DictForPath(path,
|
def _DictForPath(options, path):
|
||||||
use_proxy_hash=False,
|
|
||||||
enable_jni_multiplexing=False,
|
|
||||||
namespace='',
|
|
||||||
include_test_only=True):
|
|
||||||
with open(path) as f:
|
with open(path) as f:
|
||||||
contents = jni_generator.RemoveComments(f.read())
|
contents = jni_generator.RemoveComments(f.read())
|
||||||
if '@JniIgnoreNatives' in contents:
|
if '@JniIgnoreNatives' in contents:
|
||||||
@ -146,13 +141,14 @@ def _DictForPath(path,
|
|||||||
|
|
||||||
fully_qualified_class = jni_generator.ExtractFullyQualifiedJavaClassName(
|
fully_qualified_class = jni_generator.ExtractFullyQualifiedJavaClassName(
|
||||||
path, contents)
|
path, contents)
|
||||||
natives = jni_generator.ExtractNatives(contents, 'long')
|
|
||||||
|
|
||||||
natives += jni_generator.ProxyHelpers.ExtractStaticProxyNatives(
|
natives, module_name = jni_generator.ProxyHelpers.ExtractStaticProxyNatives(
|
||||||
fully_qualified_class=fully_qualified_class,
|
fully_qualified_class=fully_qualified_class,
|
||||||
contents=contents,
|
contents=contents,
|
||||||
ptr_type='long',
|
ptr_type='long',
|
||||||
include_test_only=include_test_only)
|
include_test_only=options.include_test_only)
|
||||||
|
natives += jni_generator.ExtractNatives(contents, 'long')
|
||||||
|
|
||||||
if len(natives) == 0:
|
if len(natives) == 0:
|
||||||
return None
|
return None
|
||||||
# The namespace for the content is separate from the namespace for the
|
# The namespace for the content is separate from the namespace for the
|
||||||
@ -161,19 +157,13 @@ def _DictForPath(path,
|
|||||||
jni_params = jni_generator.JniParams(fully_qualified_class)
|
jni_params = jni_generator.JniParams(fully_qualified_class)
|
||||||
jni_params.ExtractImportsAndInnerClasses(contents)
|
jni_params.ExtractImportsAndInnerClasses(contents)
|
||||||
is_main_dex = jni_generator.IsMainDexJavaClass(contents)
|
is_main_dex = jni_generator.IsMainDexJavaClass(contents)
|
||||||
header_generator = HeaderGenerator(
|
dict_generator = DictionaryGenerator(options, module_name, content_namespace,
|
||||||
namespace,
|
fully_qualified_class, natives,
|
||||||
content_namespace,
|
jni_params, is_main_dex)
|
||||||
fully_qualified_class,
|
return dict_generator.Generate()
|
||||||
natives,
|
|
||||||
jni_params,
|
|
||||||
is_main_dex,
|
|
||||||
use_proxy_hash,
|
|
||||||
enable_jni_multiplexing=enable_jni_multiplexing)
|
|
||||||
return header_generator.Generate()
|
|
||||||
|
|
||||||
|
|
||||||
def _AddForwardingCalls(signature_to_cases, namespace):
|
def _AddForwardingCalls(signature_to_cases, module_name):
|
||||||
template = string.Template("""
|
template = string.Template("""
|
||||||
JNI_GENERATOR_EXPORT ${RETURN} Java_${CLASS_NAME}_${PROXY_SIGNATURE}(
|
JNI_GENERATOR_EXPORT ${RETURN} Java_${CLASS_NAME}_${PROXY_SIGNATURE}(
|
||||||
JNIEnv* env,
|
JNIEnv* env,
|
||||||
@ -199,7 +189,8 @@ ${CLASS_NAME}_${PROXY_SIGNATURE} was called with an invalid switch number: "\
|
|||||||
jni_generator.JavaDataTypeToC(return_type),
|
jni_generator.JavaDataTypeToC(return_type),
|
||||||
'CLASS_NAME':
|
'CLASS_NAME':
|
||||||
jni_generator.EscapeClassName(
|
jni_generator.EscapeClassName(
|
||||||
jni_generator.ProxyHelpers.GetQualifiedClass(True) + namespace),
|
jni_generator.ProxyHelpers.GetQualifiedClass(True,
|
||||||
|
module_name)),
|
||||||
'PROXY_SIGNATURE':
|
'PROXY_SIGNATURE':
|
||||||
jni_generator.EscapeClassName(
|
jni_generator.EscapeClassName(
|
||||||
_GetMultiplexProxyName(return_type, params_list)),
|
_GetMultiplexProxyName(return_type, params_list)),
|
||||||
@ -214,9 +205,7 @@ ${CLASS_NAME}_${PROXY_SIGNATURE} was called with an invalid switch number: "\
|
|||||||
return ''.join(s for s in switch_statements)
|
return ''.join(s for s in switch_statements)
|
||||||
|
|
||||||
|
|
||||||
def _SetProxyRegistrationFields(registration_dict, use_hash,
|
def _SetProxyRegistrationFields(options, module_name, registration_dict):
|
||||||
enable_jni_multiplexing,
|
|
||||||
manual_jni_registration):
|
|
||||||
registration_template = string.Template("""\
|
registration_template = string.Template("""\
|
||||||
|
|
||||||
static const JNINativeMethod kMethods_${ESCAPED_PROXY_CLASS}[] = {
|
static const JNINativeMethod kMethods_${ESCAPED_PROXY_CLASS}[] = {
|
||||||
@ -279,20 +268,20 @@ ${REGISTER_NON_MAIN_DEX_NATIVES}
|
|||||||
} // namespace ${NAMESPACE}
|
} // namespace ${NAMESPACE}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
short_name = options.use_proxy_hash or options.enable_jni_multiplexing
|
||||||
sub_dict = {
|
sub_dict = {
|
||||||
'ESCAPED_PROXY_CLASS':
|
'ESCAPED_PROXY_CLASS':
|
||||||
jni_generator.EscapeClassName(
|
jni_generator.EscapeClassName(
|
||||||
jni_generator.ProxyHelpers.GetQualifiedClass(
|
jni_generator.ProxyHelpers.GetQualifiedClass(short_name,
|
||||||
use_hash or enable_jni_multiplexing)),
|
module_name)),
|
||||||
'PROXY_CLASS':
|
'PROXY_CLASS':
|
||||||
jni_generator.ProxyHelpers.GetQualifiedClass(use_hash
|
jni_generator.ProxyHelpers.GetQualifiedClass(short_name, module_name),
|
||||||
or enable_jni_multiplexing),
|
|
||||||
'KMETHODS':
|
'KMETHODS':
|
||||||
registration_dict['PROXY_NATIVE_METHOD_ARRAY'],
|
registration_dict['PROXY_NATIVE_METHOD_ARRAY'],
|
||||||
'REGISTRATION_NAME':
|
'REGISTRATION_NAME':
|
||||||
jni_generator.GetRegistrationFunctionName(
|
jni_generator.GetRegistrationFunctionName(
|
||||||
jni_generator.ProxyHelpers.GetQualifiedClass(
|
jni_generator.ProxyHelpers.GetQualifiedClass(short_name,
|
||||||
use_hash or enable_jni_multiplexing)),
|
module_name)),
|
||||||
}
|
}
|
||||||
|
|
||||||
if registration_dict['PROXY_NATIVE_METHOD_ARRAY']:
|
if registration_dict['PROXY_NATIVE_METHOD_ARRAY']:
|
||||||
@ -316,14 +305,17 @@ ${REGISTER_NON_MAIN_DEX_NATIVES}
|
|||||||
registration_dict['REGISTER_PROXY_NATIVES'] = proxy_natives_registration
|
registration_dict['REGISTER_PROXY_NATIVES'] = proxy_natives_registration
|
||||||
registration_dict['REGISTER_MAIN_DEX_PROXY_NATIVES'] = main_dex_call
|
registration_dict['REGISTER_MAIN_DEX_PROXY_NATIVES'] = main_dex_call
|
||||||
|
|
||||||
if manual_jni_registration:
|
if options.manual_jni_registration:
|
||||||
registration_dict['MANUAL_REGISTRATION'] = manual_registration.substitute(
|
registration_dict['MANUAL_REGISTRATION'] = manual_registration.substitute(
|
||||||
registration_dict)
|
registration_dict)
|
||||||
else:
|
else:
|
||||||
registration_dict['MANUAL_REGISTRATION'] = ''
|
registration_dict['MANUAL_REGISTRATION'] = ''
|
||||||
|
|
||||||
|
|
||||||
def CreateProxyJavaFromDict(registration_dict, proxy_opts, forwarding=False):
|
def CreateProxyJavaFromDict(options,
|
||||||
|
module_name,
|
||||||
|
registration_dict,
|
||||||
|
forwarding=False):
|
||||||
template = string.Template("""\
|
template = string.Template("""\
|
||||||
// Copyright 2018 The Chromium Authors
|
// Copyright 2018 The Chromium Authors
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
@ -341,19 +333,20 @@ ${METHODS}
|
|||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
|
|
||||||
is_natives_class = not forwarding and (proxy_opts.use_hash
|
is_natives_class = not forwarding and (options.use_proxy_hash
|
||||||
or proxy_opts.enable_jni_multiplexing)
|
or options.enable_jni_multiplexing)
|
||||||
class_name = jni_generator.ProxyHelpers.GetClass(is_natives_class)
|
class_name = jni_generator.ProxyHelpers.GetClass(is_natives_class,
|
||||||
|
module_name)
|
||||||
package = jni_generator.ProxyHelpers.GetPackage(is_natives_class)
|
package = jni_generator.ProxyHelpers.GetPackage(is_natives_class)
|
||||||
|
|
||||||
if forwarding or not (proxy_opts.use_hash
|
if forwarding or not (options.use_proxy_hash
|
||||||
or proxy_opts.enable_jni_multiplexing):
|
or options.enable_jni_multiplexing):
|
||||||
fields = string.Template("""\
|
fields = string.Template("""\
|
||||||
public static final boolean TESTING_ENABLED = ${TESTING_ENABLED};
|
public static final boolean TESTING_ENABLED = ${TESTING_ENABLED};
|
||||||
public static final boolean REQUIRE_MOCK = ${REQUIRE_MOCK};
|
public static final boolean REQUIRE_MOCK = ${REQUIRE_MOCK};
|
||||||
""").substitute({
|
""").substitute({
|
||||||
'TESTING_ENABLED': str(proxy_opts.enable_mocks).lower(),
|
'TESTING_ENABLED': str(options.enable_proxy_mocks).lower(),
|
||||||
'REQUIRE_MOCK': str(proxy_opts.require_mocks).lower(),
|
'REQUIRE_MOCK': str(options.require_mocks).lower(),
|
||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
fields = ''
|
fields = ''
|
||||||
@ -371,10 +364,7 @@ ${METHODS}
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
def CreateFromDict(registration_dict,
|
def CreateFromDict(options, module_name, registration_dict):
|
||||||
use_hash,
|
|
||||||
enable_jni_multiplexing=False,
|
|
||||||
manual_jni_registration=False):
|
|
||||||
"""Returns the content of the header file."""
|
"""Returns the content of the header file."""
|
||||||
|
|
||||||
template = string.Template("""\
|
template = string.Template("""\
|
||||||
@ -408,9 +398,8 @@ ${FORWARDING_CALLS}
|
|||||||
${MANUAL_REGISTRATION}
|
${MANUAL_REGISTRATION}
|
||||||
#endif // ${HEADER_GUARD}
|
#endif // ${HEADER_GUARD}
|
||||||
""")
|
""")
|
||||||
_SetProxyRegistrationFields(registration_dict, use_hash,
|
_SetProxyRegistrationFields(options, module_name, registration_dict)
|
||||||
enable_jni_multiplexing, manual_jni_registration)
|
if not options.enable_jni_multiplexing:
|
||||||
if not enable_jni_multiplexing:
|
|
||||||
registration_dict['FORWARDING_CALLS'] = ''
|
registration_dict['FORWARDING_CALLS'] = ''
|
||||||
if len(registration_dict['FORWARD_DECLARATIONS']) == 0:
|
if len(registration_dict['FORWARD_DECLARATIONS']) == 0:
|
||||||
return ''
|
return ''
|
||||||
@ -436,19 +425,13 @@ def _GetJavaToNativeParamsList(params_list):
|
|||||||
return 'jlong switch_num, ' + ', '.join(params_in_stub)
|
return 'jlong switch_num, ' + ', '.join(params_in_stub)
|
||||||
|
|
||||||
|
|
||||||
class HeaderGenerator(object):
|
class DictionaryGenerator(object):
|
||||||
"""Generates an inline header file for JNI registration."""
|
"""Generates an inline header file for JNI registration."""
|
||||||
|
|
||||||
def __init__(self,
|
def __init__(self, options, module_name, content_namespace,
|
||||||
namespace,
|
fully_qualified_class, natives, jni_params, main_dex):
|
||||||
content_namespace,
|
self.options = options
|
||||||
fully_qualified_class,
|
self.module_name = module_name
|
||||||
natives,
|
|
||||||
jni_params,
|
|
||||||
main_dex,
|
|
||||||
use_proxy_hash,
|
|
||||||
enable_jni_multiplexing=False):
|
|
||||||
self.namespace = namespace
|
|
||||||
self.content_namespace = content_namespace
|
self.content_namespace = content_namespace
|
||||||
self.natives = natives
|
self.natives = natives
|
||||||
self.proxy_natives = [n for n in natives if n.is_proxy]
|
self.proxy_natives = [n for n in natives if n.is_proxy]
|
||||||
@ -459,15 +442,17 @@ class HeaderGenerator(object):
|
|||||||
self.main_dex = main_dex
|
self.main_dex = main_dex
|
||||||
self.helper = jni_generator.HeaderFileGeneratorHelper(
|
self.helper = jni_generator.HeaderFileGeneratorHelper(
|
||||||
self.class_name,
|
self.class_name,
|
||||||
|
self.module_name,
|
||||||
fully_qualified_class,
|
fully_qualified_class,
|
||||||
use_proxy_hash,
|
options.use_proxy_hash,
|
||||||
enable_jni_multiplexing=enable_jni_multiplexing)
|
enable_jni_multiplexing=options.enable_jni_multiplexing)
|
||||||
self.use_proxy_hash = use_proxy_hash
|
|
||||||
self.enable_jni_multiplexing = enable_jni_multiplexing
|
|
||||||
self.registration_dict = None
|
self.registration_dict = None
|
||||||
|
|
||||||
def Generate(self):
|
def Generate(self):
|
||||||
self.registration_dict = {'FULL_CLASS_NAME': self.fully_qualified_class}
|
self.registration_dict = {
|
||||||
|
'FULL_CLASS_NAME': self.fully_qualified_class,
|
||||||
|
'MODULE_NAME': self.module_name
|
||||||
|
}
|
||||||
self._AddClassPathDeclarations()
|
self._AddClassPathDeclarations()
|
||||||
self._AddForwardDeclaration()
|
self._AddForwardDeclaration()
|
||||||
self._AddJNINativeMethodsArrays()
|
self._AddJNINativeMethodsArrays()
|
||||||
@ -476,19 +461,16 @@ class HeaderGenerator(object):
|
|||||||
self._AddRegisterNativesFunctions()
|
self._AddRegisterNativesFunctions()
|
||||||
|
|
||||||
self.registration_dict['PROXY_NATIVE_SIGNATURES'] = (''.join(
|
self.registration_dict['PROXY_NATIVE_SIGNATURES'] = (''.join(
|
||||||
_MakeProxySignature(
|
_MakeProxySignature(self.options, native)
|
||||||
native,
|
|
||||||
self.use_proxy_hash,
|
|
||||||
enable_jni_multiplexing=self.enable_jni_multiplexing)
|
|
||||||
for native in self.proxy_natives))
|
for native in self.proxy_natives))
|
||||||
if self.enable_jni_multiplexing:
|
|
||||||
|
if self.options.enable_jni_multiplexing:
|
||||||
self._AssignSwitchNumberToNatives()
|
self._AssignSwitchNumberToNatives()
|
||||||
self._AddCases()
|
self._AddCases()
|
||||||
|
|
||||||
if self.use_proxy_hash or self.enable_jni_multiplexing:
|
if self.options.use_proxy_hash or self.options.enable_jni_multiplexing:
|
||||||
self.registration_dict['FORWARDING_PROXY_METHODS'] = ('\n'.join(
|
self.registration_dict['FORWARDING_PROXY_METHODS'] = ('\n'.join(
|
||||||
_MakeForwardingProxy(
|
_MakeForwardingProxy(self.options, self.module_name, native)
|
||||||
native, enable_jni_multiplexing=self.enable_jni_multiplexing)
|
|
||||||
for native in self.proxy_natives))
|
for native in self.proxy_natives))
|
||||||
|
|
||||||
return self.registration_dict
|
return self.registration_dict
|
||||||
@ -582,10 +564,11 @@ ${KMETHODS}
|
|||||||
if native.is_proxy:
|
if native.is_proxy:
|
||||||
# Literal name of the native method in the class that contains the actual
|
# Literal name of the native method in the class that contains the actual
|
||||||
# native declaration.
|
# native declaration.
|
||||||
if self.enable_jni_multiplexing:
|
if self.options.enable_jni_multiplexing:
|
||||||
return_type, params_list = native.return_and_signature
|
return_type, params_list = native.return_and_signature
|
||||||
class_name = jni_generator.EscapeClassName(
|
class_name = jni_generator.EscapeClassName(
|
||||||
jni_generator.ProxyHelpers.GetQualifiedClass(True) + self.namespace)
|
jni_generator.ProxyHelpers.GetQualifiedClass(
|
||||||
|
True, self.module_name))
|
||||||
proxy_signature = jni_generator.EscapeClassName(
|
proxy_signature = jni_generator.EscapeClassName(
|
||||||
_GetMultiplexProxyName(return_type, params_list))
|
_GetMultiplexProxyName(return_type, params_list))
|
||||||
|
|
||||||
@ -594,7 +577,7 @@ ${KMETHODS}
|
|||||||
[jni_generator.Param(datatype='long', name='switch_num')] +
|
[jni_generator.Param(datatype='long', name='switch_num')] +
|
||||||
native.params, native.return_type)
|
native.params, native.return_type)
|
||||||
stub_name = 'Java_' + class_name + '_' + proxy_signature
|
stub_name = 'Java_' + class_name + '_' + proxy_signature
|
||||||
elif self.use_proxy_hash:
|
elif self.options.use_proxy_hash:
|
||||||
name = native.hashed_proxy_name
|
name = native.hashed_proxy_name
|
||||||
else:
|
else:
|
||||||
name = native.proxy_name
|
name = native.proxy_name
|
||||||
@ -608,7 +591,7 @@ ${KMETHODS}
|
|||||||
def _AddProxyNativeMethodKStrings(self):
|
def _AddProxyNativeMethodKStrings(self):
|
||||||
"""Returns KMethodString for wrapped native methods in all_classes """
|
"""Returns KMethodString for wrapped native methods in all_classes """
|
||||||
|
|
||||||
if self.main_dex or self.enable_jni_multiplexing:
|
if self.main_dex or self.options.enable_jni_multiplexing:
|
||||||
key = 'PROXY_NATIVE_METHOD_ARRAY_MAIN_DEX'
|
key = 'PROXY_NATIVE_METHOD_ARRAY_MAIN_DEX'
|
||||||
else:
|
else:
|
||||||
key = 'PROXY_NATIVE_METHOD_ARRAY'
|
key = 'PROXY_NATIVE_METHOD_ARRAY'
|
||||||
@ -618,7 +601,7 @@ ${KMETHODS}
|
|||||||
|
|
||||||
self._SetDictValue(key, proxy_k_strings)
|
self._SetDictValue(key, proxy_k_strings)
|
||||||
|
|
||||||
def _SubstituteNativeMethods(self, template, sub_proxy=False):
|
def _SubstituteNativeMethods(self, template):
|
||||||
"""Substitutes NAMESPACE, JAVA_CLASS and KMETHODS in the provided
|
"""Substitutes NAMESPACE, JAVA_CLASS and KMETHODS in the provided
|
||||||
template."""
|
template."""
|
||||||
ret = []
|
ret = []
|
||||||
@ -626,10 +609,10 @@ ${KMETHODS}
|
|||||||
all_classes[self.class_name] = self.fully_qualified_class
|
all_classes[self.class_name] = self.fully_qualified_class
|
||||||
|
|
||||||
for clazz, full_clazz in all_classes.items():
|
for clazz, full_clazz in all_classes.items():
|
||||||
if not sub_proxy:
|
if clazz == jni_generator.ProxyHelpers.GetClass(
|
||||||
if clazz == jni_generator.ProxyHelpers.GetClass(
|
self.options.use_proxy_hash or self.options.enable_jni_multiplexing,
|
||||||
self.use_proxy_hash or self.enable_jni_multiplexing):
|
self.module_name):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
kmethods = self._GetKMethodsString(clazz)
|
kmethods = self._GetKMethodsString(clazz)
|
||||||
namespace_str = ''
|
namespace_str = ''
|
||||||
@ -723,6 +706,8 @@ ${NATIVES}\
|
|||||||
params = _GetParamsListForMultiplex(signature[1], with_types=False)
|
params = _GetParamsListForMultiplex(signature[1], with_types=False)
|
||||||
values = {
|
values = {
|
||||||
'SWITCH_NUM': native.switch_num,
|
'SWITCH_NUM': native.switch_num,
|
||||||
|
# We are forced to call the generated stub instead of the impl because
|
||||||
|
# the impl is not guaranteed to have a globally unique name.
|
||||||
'STUB_NAME': self.helper.GetStubName(native),
|
'STUB_NAME': self.helper.GetStubName(native),
|
||||||
'PARAMS': params,
|
'PARAMS': params,
|
||||||
}
|
}
|
||||||
@ -778,7 +763,7 @@ def _GetMultiplexProxyName(return_type, params_list):
|
|||||||
return 'resolve_for_' + return_type.replace('[]', '_array').lower() + params
|
return 'resolve_for_' + return_type.replace('[]', '_array').lower() + params
|
||||||
|
|
||||||
|
|
||||||
def _MakeForwardingProxy(proxy_native, enable_jni_multiplexing=False):
|
def _MakeForwardingProxy(options, module_name, proxy_native):
|
||||||
template = string.Template("""
|
template = string.Template("""
|
||||||
public static ${RETURN_TYPE} ${METHOD_NAME}(${PARAMS_WITH_TYPES}) {
|
public static ${RETURN_TYPE} ${METHOD_NAME}(${PARAMS_WITH_TYPES}) {
|
||||||
${MAYBE_RETURN}${PROXY_CLASS}.${PROXY_METHOD_NAME}(${PARAM_NAMES});
|
${MAYBE_RETURN}${PROXY_CLASS}.${PROXY_METHOD_NAME}(${PARAM_NAMES});
|
||||||
@ -787,9 +772,9 @@ def _MakeForwardingProxy(proxy_native, enable_jni_multiplexing=False):
|
|||||||
params_with_types = ', '.join(
|
params_with_types = ', '.join(
|
||||||
'%s %s' % (p.datatype, p.name) for p in proxy_native.params)
|
'%s %s' % (p.datatype, p.name) for p in proxy_native.params)
|
||||||
param_names = ', '.join(p.name for p in proxy_native.params)
|
param_names = ', '.join(p.name for p in proxy_native.params)
|
||||||
proxy_class = jni_generator.ProxyHelpers.GetQualifiedClass(True)
|
proxy_class = jni_generator.ProxyHelpers.GetQualifiedClass(True, module_name)
|
||||||
|
|
||||||
if enable_jni_multiplexing:
|
if options.enable_jni_multiplexing:
|
||||||
if not param_names:
|
if not param_names:
|
||||||
param_names = proxy_native.switch_num + 'L'
|
param_names = proxy_native.switch_num + 'L'
|
||||||
else:
|
else:
|
||||||
@ -817,15 +802,13 @@ def _MakeForwardingProxy(proxy_native, enable_jni_multiplexing=False):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
def _MakeProxySignature(proxy_native,
|
def _MakeProxySignature(options, proxy_native):
|
||||||
use_proxy_hash,
|
|
||||||
enable_jni_multiplexing=False):
|
|
||||||
params_with_types = ', '.join('%s %s' % (p.datatype, p.name)
|
params_with_types = ', '.join('%s %s' % (p.datatype, p.name)
|
||||||
for p in proxy_native.params)
|
for p in proxy_native.params)
|
||||||
native_method_line = """
|
native_method_line = """
|
||||||
public static native ${RETURN} ${PROXY_NAME}(${PARAMS_WITH_TYPES});"""
|
public static native ${RETURN} ${PROXY_NAME}(${PARAMS_WITH_TYPES});"""
|
||||||
|
|
||||||
if enable_jni_multiplexing:
|
if options.enable_jni_multiplexing:
|
||||||
# This has to be only one line and without comments because all the proxy
|
# This has to be only one line and without comments because all the proxy
|
||||||
# signatures will be joined, then split on new lines with duplicates removed
|
# signatures will be joined, then split on new lines with duplicates removed
|
||||||
# since multiple |proxy_native|s map to the same multiplexed signature.
|
# since multiple |proxy_native|s map to the same multiplexed signature.
|
||||||
@ -836,7 +819,7 @@ def _MakeProxySignature(proxy_native,
|
|||||||
proxy_name = _GetMultiplexProxyName(return_type, params_list)
|
proxy_name = _GetMultiplexProxyName(return_type, params_list)
|
||||||
params_with_types = 'long switch_num' + _GetParamsListForMultiplex(
|
params_with_types = 'long switch_num' + _GetParamsListForMultiplex(
|
||||||
params_list, with_types=True)
|
params_list, with_types=True)
|
||||||
elif use_proxy_hash:
|
elif options.use_proxy_hash:
|
||||||
signature_template = string.Template("""
|
signature_template = string.Template("""
|
||||||
// Original name: ${ALT_NAME}""" + native_method_line)
|
// Original name: ${ALT_NAME}""" + native_method_line)
|
||||||
|
|
||||||
@ -859,18 +842,6 @@ def _MakeProxySignature(proxy_native,
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class ProxyOptions:
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
|
||||||
self.use_hash = kwargs.get('use_hash', False)
|
|
||||||
self.enable_jni_multiplexing = kwargs.get('enable_jni_multiplexing', False)
|
|
||||||
self.manual_jni_registration = kwargs.get('manual_jni_registration', False)
|
|
||||||
self.enable_mocks = kwargs.get('enable_mocks', False)
|
|
||||||
self.require_mocks = kwargs.get('require_mocks', False)
|
|
||||||
# Can never require and disable.
|
|
||||||
assert self.enable_mocks or not self.require_mocks
|
|
||||||
|
|
||||||
|
|
||||||
def main(argv):
|
def main(argv):
|
||||||
arg_parser = argparse.ArgumentParser()
|
arg_parser = argparse.ArgumentParser()
|
||||||
build_utils.AddDepfileOption(arg_parser)
|
build_utils.AddDepfileOption(arg_parser)
|
||||||
@ -888,64 +859,56 @@ def main(argv):
|
|||||||
required=True,
|
required=True,
|
||||||
help='Path to output srcjar for GEN_JNI.java (and J/N.java if proxy'
|
help='Path to output srcjar for GEN_JNI.java (and J/N.java if proxy'
|
||||||
' hash is enabled).')
|
' hash is enabled).')
|
||||||
arg_parser.add_argument(
|
arg_parser.add_argument('--file-exclusions',
|
||||||
'--sources-exclusions',
|
default=[],
|
||||||
default=[],
|
help='A list of Java files which should be ignored '
|
||||||
help='A list of Java files which should be ignored '
|
'by the parser.')
|
||||||
'by the parser.')
|
|
||||||
arg_parser.add_argument(
|
arg_parser.add_argument(
|
||||||
'--namespace',
|
'--namespace',
|
||||||
default='',
|
default='',
|
||||||
help='Namespace to wrap the registration functions '
|
help='Native namespace to wrap the registration functions '
|
||||||
'into.')
|
'into.')
|
||||||
# TODO(crbug.com/898261) hook these flags up to the build config to enable
|
# TODO(crbug.com/898261) hook these flags up to the build config to enable
|
||||||
# mocking in instrumentation tests
|
# mocking in instrumentation tests
|
||||||
arg_parser.add_argument(
|
arg_parser.add_argument(
|
||||||
'--enable_proxy_mocks',
|
'--enable-proxy-mocks',
|
||||||
default=False,
|
default=False,
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Allows proxy native impls to be mocked through Java.')
|
help='Allows proxy native impls to be mocked through Java.')
|
||||||
arg_parser.add_argument(
|
arg_parser.add_argument(
|
||||||
'--require_mocks',
|
'--require-mocks',
|
||||||
default=False,
|
default=False,
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Requires all used native implementations to have a mock set when '
|
help='Requires all used native implementations to have a mock set when '
|
||||||
'called. Otherwise an exception will be thrown.')
|
'called. Otherwise an exception will be thrown.')
|
||||||
arg_parser.add_argument(
|
arg_parser.add_argument(
|
||||||
'--use_proxy_hash',
|
'--use-proxy-hash',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Enables hashing of the native declaration for methods in '
|
help='Enables hashing of the native declaration for methods in '
|
||||||
'an @JniNatives interface')
|
'an @JniNatives interface')
|
||||||
arg_parser.add_argument(
|
arg_parser.add_argument(
|
||||||
'--enable_jni_multiplexing',
|
'--enable-jni-multiplexing',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Enables JNI multiplexing for Java native methods')
|
help='Enables JNI multiplexing for Java native methods')
|
||||||
arg_parser.add_argument(
|
arg_parser.add_argument(
|
||||||
'--manual_jni_registration',
|
'--manual-jni-registration',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Manually do JNI registration - required for crazy linker')
|
help='Manually do JNI registration - required for crazy linker')
|
||||||
arg_parser.add_argument('--include_test_only',
|
arg_parser.add_argument('--include-test-only',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Whether to maintain ForTesting JNI methods.')
|
help='Whether to maintain ForTesting JNI methods.')
|
||||||
args = arg_parser.parse_args(build_utils.ExpandFileArgs(argv[1:]))
|
args = arg_parser.parse_args(build_utils.ExpandFileArgs(argv[1:]))
|
||||||
|
|
||||||
if not args.enable_proxy_mocks and args.require_mocks:
|
if not args.enable_proxy_mocks and args.require_mocks:
|
||||||
arg_parser.error(
|
arg_parser.error(
|
||||||
'Invalid arguments: --require_mocks without --enable_proxy_mocks. '
|
'Invalid arguments: --require-mocks without --enable-proxy-mocks. '
|
||||||
'Cannot require mocks if they are not enabled.')
|
'Cannot require mocks if they are not enabled.')
|
||||||
|
|
||||||
if not args.header_path and args.manual_jni_registration:
|
if not args.header_path and args.manual_jni_registration:
|
||||||
arg_parser.error(
|
arg_parser.error(
|
||||||
'Invalid arguments: --manual_jni_registration without --header-path. '
|
'Invalid arguments: --manual-jni-registration without --header-path. '
|
||||||
'Cannot manually register JNI if there is no output header file.')
|
'Cannot manually register JNI if there is no output header file.')
|
||||||
|
|
||||||
sources_files = sorted(set(build_utils.ParseGnList(args.sources_files)))
|
sources_files = sorted(set(build_utils.ParseGnList(args.sources_files)))
|
||||||
proxy_opts = ProxyOptions(
|
|
||||||
use_hash=args.use_proxy_hash,
|
|
||||||
enable_jni_multiplexing=args.enable_jni_multiplexing,
|
|
||||||
manual_jni_registration=args.manual_jni_registration,
|
|
||||||
require_mocks=args.require_mocks,
|
|
||||||
enable_mocks=args.enable_proxy_mocks)
|
|
||||||
|
|
||||||
java_file_paths = []
|
java_file_paths = []
|
||||||
for f in sources_files:
|
for f in sources_files:
|
||||||
@ -953,13 +916,8 @@ def main(argv):
|
|||||||
# skip Kotlin files as they are not supported by JNI generation.
|
# skip Kotlin files as they are not supported by JNI generation.
|
||||||
java_file_paths.extend(
|
java_file_paths.extend(
|
||||||
p for p in build_utils.ReadSourcesList(f) if p.startswith('..')
|
p for p in build_utils.ReadSourcesList(f) if p.startswith('..')
|
||||||
and p not in args.sources_exclusions and not p.endswith('.kt'))
|
and p not in args.file_exclusions and not p.endswith('.kt'))
|
||||||
_Generate(java_file_paths,
|
_Generate(args, java_file_paths)
|
||||||
args.srcjar_path,
|
|
||||||
proxy_opts=proxy_opts,
|
|
||||||
header_path=args.header_path,
|
|
||||||
namespace=args.namespace,
|
|
||||||
include_test_only=args.include_test_only)
|
|
||||||
|
|
||||||
if args.depfile:
|
if args.depfile:
|
||||||
build_utils.WriteDepfile(args.depfile, args.srcjar_path,
|
build_utils.WriteDepfile(args.depfile, args.srcjar_path,
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "base/android/jni_android.h"
|
#include "base/android/jni_android.h"
|
||||||
#include "base/android/jni_generator/sample_jni_apk__final_jni_generated.h"
|
#include "base/android/jni_generator/jni_registration_generated.h"
|
||||||
#include "base/android/jni_utils.h"
|
#include "base/android/jni_utils.h"
|
||||||
|
|
||||||
// This is called by the VM when the shared library is first loaded.
|
// This is called by the VM when the shared library is first loaded.
|
||||||
|
105
src/base/android/meminfo_dump_provider.cc
Normal file
105
src/base/android/meminfo_dump_provider.cc
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
// Copyright 2023 The Chromium Authors
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#include "base/android/meminfo_dump_provider.h"
|
||||||
|
#include <jni.h>
|
||||||
|
#include "base/android/jni_android.h"
|
||||||
|
#include "base/logging.h"
|
||||||
|
#include "base/time/time.h"
|
||||||
|
#include "base/trace_event/base_tracing.h"
|
||||||
|
|
||||||
|
#if BUILDFLAG(ENABLE_BASE_TRACING)
|
||||||
|
#include "base/base_jni_headers/MemoryInfoBridge_jni.h"
|
||||||
|
#endif // BUILDFLAG(ENABLE_BASE_TRACING)
|
||||||
|
|
||||||
|
namespace base::android {
|
||||||
|
|
||||||
|
MeminfoDumpProvider::MeminfoDumpProvider() {
|
||||||
|
#if BUILDFLAG(ENABLE_BASE_TRACING)
|
||||||
|
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
|
||||||
|
this, kDumpProviderName, nullptr);
|
||||||
|
#endif // BUILDFLAG(ENABLE_BASE_TRACING)
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
MeminfoDumpProvider& MeminfoDumpProvider::Initialize() {
|
||||||
|
static base::NoDestructor<MeminfoDumpProvider> instance;
|
||||||
|
return *instance.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MeminfoDumpProvider::OnMemoryDump(
|
||||||
|
const base::trace_event::MemoryDumpArgs& args,
|
||||||
|
base::trace_event::ProcessMemoryDump* pmd) {
|
||||||
|
#if BUILDFLAG(ENABLE_BASE_TRACING)
|
||||||
|
// This is best-effort, and will be wrong if there are other callers of
|
||||||
|
// ActivityManager#getProcessMemoryInfo(), either in this process or from
|
||||||
|
// another process which is allowed to do so (typically, adb).
|
||||||
|
//
|
||||||
|
// However, since the framework doesn't document throttling in any non-vague
|
||||||
|
// terms and the results are not timestamped, this is the best we can do. The
|
||||||
|
// delay and the rest of the assumptions here come from
|
||||||
|
// https://android.googlesource.com/platform/frameworks/base/+/refs/heads/android13-dev/services/core/java/com/android/server/am/ActivityManagerService.java#4093.
|
||||||
|
//
|
||||||
|
// We could always report the value on pre-Q devices, but that would skew
|
||||||
|
// reported data. Also, some OEMs may have cherry-picked the Q change, meaning
|
||||||
|
// that it's safer and more accurate to not report likely-stale data on all
|
||||||
|
// Android releases.
|
||||||
|
base::TimeTicks now = base::TimeTicks::Now();
|
||||||
|
bool stale_data = (now - last_collection_time_) < base::Minutes(5);
|
||||||
|
|
||||||
|
// Background data dumps (as in the BACKGROUND level of detail, not the
|
||||||
|
// application being in background) should not include stale data, since it
|
||||||
|
// would confuse data in UMA. In particular, the background/foreground session
|
||||||
|
// filter would no longer be accurate.
|
||||||
|
if (stale_data && args.level_of_detail !=
|
||||||
|
base::trace_event::MemoryDumpLevelOfDetail::DETAILED) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
base::trace_event::MemoryAllocatorDump* dump =
|
||||||
|
pmd->CreateAllocatorDump(kDumpName);
|
||||||
|
// Data is either expected to be fresh, or this is a manually requested dump,
|
||||||
|
// and we should still report data, but note that it is stale.
|
||||||
|
dump->AddScalar(kIsStaleName, "bool", stale_data);
|
||||||
|
|
||||||
|
last_collection_time_ = now;
|
||||||
|
JNIEnv* env = AttachCurrentThread();
|
||||||
|
ScopedJavaLocalRef<jobject> memory_info =
|
||||||
|
Java_MemoryInfoBridge_getActivityManagerMemoryInfoForSelf(env);
|
||||||
|
// Tell the manager that collection failed. Since this is likely not a
|
||||||
|
// transient failure, don't return an empty dump, and let the manager exclude
|
||||||
|
// this provider from the next dump.
|
||||||
|
if (memory_info.is_null()) {
|
||||||
|
LOG(WARNING) << "Got a null value";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedJavaLocalRef<jclass> clazz{env, env->GetObjectClass(memory_info.obj())};
|
||||||
|
|
||||||
|
jfieldID other_private_dirty_id =
|
||||||
|
env->GetFieldID(clazz.obj(), "otherPrivateDirty", "I");
|
||||||
|
jfieldID other_pss_id = env->GetFieldID(clazz.obj(), "otherPss", "I");
|
||||||
|
|
||||||
|
int other_private_dirty_kb =
|
||||||
|
env->GetIntField(memory_info.obj(), other_private_dirty_id);
|
||||||
|
int other_pss_kb = env->GetIntField(memory_info.obj(), other_pss_id);
|
||||||
|
|
||||||
|
// What "other" covers is not documented in Debug#MemoryInfo, nor in
|
||||||
|
// ActivityManager#getProcessMemoryInfo. However, it calls
|
||||||
|
// Debug#getMemoryInfo(), which ends up summing all the heaps in the range
|
||||||
|
// [HEAP_DALVIK_OTHER, HEAP_OTHER_MEMTRACK]. See the definitions in
|
||||||
|
// https://android.googlesource.com/platform/frameworks/base/+/0b7c1774ba42daef7c80bf2f00fe1c0327e756ae/core/jni/android_os_Debug.cpp#60,
|
||||||
|
// and the code in android_os_Debug_getDirtyPagesPid() in the same file.
|
||||||
|
dump->AddScalar(kPrivateDirtyMetricName, "bytes",
|
||||||
|
static_cast<uint64_t>(other_private_dirty_kb) * 1024);
|
||||||
|
dump->AddScalar(kPssMetricName, "bytes",
|
||||||
|
static_cast<uint64_t>(other_pss_kb) * 1024);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
#else // BUILDFLAG(ENABLE_BASE_TRACING)
|
||||||
|
return false;
|
||||||
|
#endif // BUILDFLAG(ENABLE_BASE_TRACING)
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace base::android
|
38
src/base/android/meminfo_dump_provider.h
Normal file
38
src/base/android/meminfo_dump_provider.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2023 The Chromium Authors
|
||||||
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#ifndef BASE_ANDROID_MEMINFO_DUMP_PROVIDER_H_
|
||||||
|
#define BASE_ANDROID_MEMINFO_DUMP_PROVIDER_H_
|
||||||
|
|
||||||
|
#include "base/base_export.h"
|
||||||
|
#include "base/no_destructor.h"
|
||||||
|
#include "base/time/time.h"
|
||||||
|
#include "base/trace_event/base_tracing.h"
|
||||||
|
|
||||||
|
namespace base::android {
|
||||||
|
|
||||||
|
class BASE_EXPORT MeminfoDumpProvider
|
||||||
|
: public base::trace_event::MemoryDumpProvider {
|
||||||
|
public:
|
||||||
|
// Returns the instance for testing.
|
||||||
|
static MeminfoDumpProvider& Initialize();
|
||||||
|
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
|
||||||
|
base::trace_event::ProcessMemoryDump* pmd) override;
|
||||||
|
|
||||||
|
static constexpr char kDumpProviderName[] = "android_meminfo";
|
||||||
|
static constexpr char kDumpName[] = "meminfo";
|
||||||
|
static constexpr char kIsStaleName[] = "is_stale";
|
||||||
|
static constexpr char kPssMetricName[] = "other_pss";
|
||||||
|
static constexpr char kPrivateDirtyMetricName[] = "other_private_dirty";
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class base::NoDestructor<MeminfoDumpProvider>;
|
||||||
|
MeminfoDumpProvider();
|
||||||
|
|
||||||
|
base::TimeTicks last_collection_time_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace base::android
|
||||||
|
|
||||||
|
#endif // BASE_ANDROID_MEMINFO_DUMP_PROVIDER_H_
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "base/android/callback_android.h"
|
#include "base/android/callback_android.h"
|
||||||
#include "base/android/jni_android.h"
|
#include "base/android/jni_android.h"
|
||||||
|
#include "base/android/jni_array.h"
|
||||||
#include "base/android/jni_string.h"
|
#include "base/android/jni_string.h"
|
||||||
#include "base/base_jni_headers/NativeUmaRecorder_jni.h"
|
#include "base/base_jni_headers/NativeUmaRecorder_jni.h"
|
||||||
#include "base/format_macros.h"
|
#include "base/format_macros.h"
|
||||||
@ -264,6 +265,36 @@ jint JNI_NativeUmaRecorder_GetHistogramTotalCountForTesting(
|
|||||||
return actual_count;
|
return actual_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns an array with 3 entries for each bucket, representing (min, max,
|
||||||
|
// count).
|
||||||
|
ScopedJavaLocalRef<jlongArray>
|
||||||
|
JNI_NativeUmaRecorder_GetHistogramSamplesForTesting(
|
||||||
|
JNIEnv* env,
|
||||||
|
const JavaParamRef<jstring>& histogram_name) {
|
||||||
|
std::string name = android::ConvertJavaStringToUTF8(env, histogram_name);
|
||||||
|
HistogramBase* histogram = StatisticsRecorder::FindHistogram(name);
|
||||||
|
std::vector<int64_t> buckets;
|
||||||
|
|
||||||
|
if (histogram == nullptr) {
|
||||||
|
// No samples have been recorded for this histogram.
|
||||||
|
return base::android::ToJavaLongArray(env, buckets);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
|
||||||
|
for (auto sampleCountIterator = samples->Iterator();
|
||||||
|
!sampleCountIterator->Done(); sampleCountIterator->Next()) {
|
||||||
|
HistogramBase::Sample min;
|
||||||
|
int64_t max;
|
||||||
|
HistogramBase::Count count;
|
||||||
|
sampleCountIterator->Get(&min, &max, &count);
|
||||||
|
buckets.push_back(min);
|
||||||
|
buckets.push_back(max);
|
||||||
|
buckets.push_back(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
return base::android::ToJavaLongArray(env, buckets);
|
||||||
|
}
|
||||||
|
|
||||||
jlong JNI_NativeUmaRecorder_CreateHistogramSnapshotForTesting(JNIEnv* env) {
|
jlong JNI_NativeUmaRecorder_CreateHistogramSnapshotForTesting(JNIEnv* env) {
|
||||||
HistogramsSnapshot* snapshot = new HistogramsSnapshot();
|
HistogramsSnapshot* snapshot = new HistogramsSnapshot();
|
||||||
for (const auto* const histogram : StatisticsRecorder::GetHistograms()) {
|
for (const auto* const histogram : StatisticsRecorder::GetHistograms()) {
|
||||||
|
@ -240,7 +240,7 @@ NO_INSTRUMENT_FUNCTION bool DumpToFile(const base::FilePath& path) {
|
|||||||
|
|
||||||
// This can get very large as it constructs the whole data structure in
|
// This can get very large as it constructs the whole data structure in
|
||||||
// memory before dumping it to the file.
|
// memory before dumping it to the file.
|
||||||
Value root(Value::Type::DICTIONARY);
|
Value root(Value::Type::DICT);
|
||||||
uint32_t total_calls_count = g_calls_count.load(std::memory_order_relaxed);
|
uint32_t total_calls_count = g_calls_count.load(std::memory_order_relaxed);
|
||||||
root.SetStringKey("total_calls_count",
|
root.SetStringKey("total_calls_count",
|
||||||
base::StringPrintf("%" PRIu32, total_calls_count));
|
base::StringPrintf("%" PRIu32, total_calls_count));
|
||||||
@ -252,7 +252,7 @@ NO_INSTRUMENT_FUNCTION bool DumpToFile(const base::FilePath& path) {
|
|||||||
// This callee was never called.
|
// This callee was never called.
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Value callee_element(Value::Type::DICTIONARY);
|
Value callee_element(Value::Type::DICT);
|
||||||
uint32_t callee_offset = i * 4;
|
uint32_t callee_offset = i * 4;
|
||||||
callee_element.SetStringKey("index",
|
callee_element.SetStringKey("index",
|
||||||
base::StringPrintf("%" PRIuS, caller_index));
|
base::StringPrintf("%" PRIuS, caller_index));
|
||||||
@ -278,7 +278,7 @@ NO_INSTRUMENT_FUNCTION bool DumpToFile(const base::FilePath& path) {
|
|||||||
// No misses.
|
// No misses.
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Value caller_count(Value::Type::DICTIONARY);
|
Value caller_count(Value::Type::DICT);
|
||||||
caller_count.SetStringKey("caller_offset",
|
caller_count.SetStringKey("caller_offset",
|
||||||
base::StringPrintf("%" PRIu32, caller_offset));
|
base::StringPrintf("%" PRIu32, caller_offset));
|
||||||
caller_count.SetStringKey("count", base::StringPrintf("%" PRIu32, count));
|
caller_count.SetStringKey("count", base::StringPrintf("%" PRIu32, count));
|
||||||
|
@ -2,6 +2,21 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
// IMPORTANT NOTE: deprecated. Use std::atomic instead.
|
||||||
|
//
|
||||||
|
// Rationale:
|
||||||
|
// - Uniformity: most of the code uses std::atomic, and the underlying
|
||||||
|
// implementation is the same. Use the STL one.
|
||||||
|
// - Clearer code: return values from some operations (e.g. CompareAndSwap)
|
||||||
|
// differ from the equivalent ones in std::atomic, leading to confusion.
|
||||||
|
// - Richer semantics: can use actual types, rather than e.g. Atomic32 for a
|
||||||
|
// boolean flag, or AtomicWord for T*. Bitwise operations (e.g. fetch_or())
|
||||||
|
// are only in std::atomic.
|
||||||
|
// - Harder to misuse: base::subtle::Atomic32 is just an int, making it possible
|
||||||
|
// to accidentally manipulate, not realizing that there are no atomic
|
||||||
|
// semantics attached to it. For instance, "Atomic32 a; a++;" is almost
|
||||||
|
// certainly incorrect.
|
||||||
|
|
||||||
// For atomic operations on reference counts, see atomic_refcount.h.
|
// For atomic operations on reference counts, see atomic_refcount.h.
|
||||||
// For atomic operations on sequence numbers, see atomic_sequence_num.h.
|
// For atomic operations on sequence numbers, see atomic_sequence_num.h.
|
||||||
|
|
||||||
|
@ -137,9 +137,8 @@ class BASE_EXPORT BigEndianWriter {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
bool Write(T v);
|
bool Write(T v);
|
||||||
|
|
||||||
// TODO(crbug.com/1298696): Breaks net_unittests.
|
raw_ptr<char, DanglingUntriaged | AllowPtrArithmetic> ptr_;
|
||||||
raw_ptr<char, DanglingUntriagedDegradeToNoOpWhenMTE> ptr_;
|
raw_ptr<char, DanglingUntriaged | AllowPtrArithmetic> end_;
|
||||||
raw_ptr<char, DanglingUntriagedDegradeToNoOpWhenMTE> end_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace base
|
} // namespace base
|
||||||
|
@ -180,10 +180,24 @@ std::ostream& CheckError::stream() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CheckError::~CheckError() {
|
CheckError::~CheckError() {
|
||||||
|
// TODO(crbug.com/1409729): Consider splitting out CHECK from DCHECK so that
|
||||||
|
// the destructor can be marked [[noreturn]] and we don't need to check
|
||||||
|
// severity in the destructor.
|
||||||
|
const bool is_fatal = log_message_->severity() == LOGGING_FATAL;
|
||||||
// Note: This function ends up in crash stack traces. If its full name
|
// Note: This function ends up in crash stack traces. If its full name
|
||||||
// changes, the crash server's magic signature logic needs to be updated.
|
// changes, the crash server's magic signature logic needs to be updated.
|
||||||
// See cl/306632920.
|
// See cl/306632920.
|
||||||
delete log_message_;
|
delete log_message_;
|
||||||
|
|
||||||
|
// Make sure we crash even if LOG(FATAL) has been overridden.
|
||||||
|
// TODO(crbug.com/1409729): Include Windows here too. This is done in steps to
|
||||||
|
// prevent backsliding on platforms where this goes through CQ.
|
||||||
|
// Windows is blocked by:
|
||||||
|
// * All/RenderProcessHostWriteableFileDeathTest.
|
||||||
|
// PassUnsafeWriteableExecutableFile/2
|
||||||
|
if (is_fatal && !BUILDFLAG(IS_WIN)) {
|
||||||
|
base::ImmediateCrash();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NotReachedError NotReachedError::NotReached(const char* file, int line) {
|
NotReachedError NotReachedError::NotReached(const char* file, int line) {
|
||||||
@ -198,13 +212,47 @@ NotReachedError NotReachedError::NotReached(const char* file, int line) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NotReachedError::TriggerNotReached() {
|
void NotReachedError::TriggerNotReached() {
|
||||||
// TODO(pbos): Add back NotReachedError("", -1) here asap. This was removed to
|
// This triggers a NOTREACHED() error as the returned NotReachedError goes out
|
||||||
// disable NOTREACHED() reports temporarily for M111 and should be added
|
// of scope.
|
||||||
// back once this change has merged to M111.
|
NotReached("", -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
NotReachedError::~NotReachedError() = default;
|
NotReachedError::~NotReachedError() = default;
|
||||||
|
|
||||||
|
NotReachedNoreturnError::NotReachedNoreturnError(const char* file, int line)
|
||||||
|
: CheckError([file, line]() {
|
||||||
|
auto* const log_message = new LogMessage(file, line, LOGGING_FATAL);
|
||||||
|
log_message->stream() << "NOTREACHED hit. ";
|
||||||
|
return log_message;
|
||||||
|
}()) {}
|
||||||
|
|
||||||
|
// Note: This function ends up in crash stack traces. If its full name changes,
|
||||||
|
// the crash server's magic signature logic needs to be updated. See
|
||||||
|
// cl/306632920.
|
||||||
|
NotReachedNoreturnError::~NotReachedNoreturnError() {
|
||||||
|
delete log_message_;
|
||||||
|
|
||||||
|
// Make sure we die if we haven't. LOG(FATAL) is not yet [[noreturn]] as of
|
||||||
|
// writing this.
|
||||||
|
base::ImmediateCrash();
|
||||||
|
}
|
||||||
|
|
||||||
|
LogMessage* CheckOpResult::CreateLogMessage(bool is_dcheck,
|
||||||
|
const char* file,
|
||||||
|
int line,
|
||||||
|
const char* expr_str,
|
||||||
|
char* v1_str,
|
||||||
|
char* v2_str) {
|
||||||
|
LogMessage* const log_message =
|
||||||
|
is_dcheck ? new DCheckLogMessage(file, line, LOGGING_DCHECK)
|
||||||
|
: new LogMessage(file, line, LOGGING_FATAL);
|
||||||
|
log_message->stream() << "Check failed: " << expr_str << " (" << v1_str
|
||||||
|
<< " vs. " << v2_str << ")";
|
||||||
|
free(v1_str);
|
||||||
|
free(v2_str);
|
||||||
|
return log_message;
|
||||||
|
}
|
||||||
|
|
||||||
void RawCheck(const char* message) {
|
void RawCheck(const char* message) {
|
||||||
RawLog(LOGGING_FATAL, message);
|
RawLog(LOGGING_FATAL, message);
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ class BASE_EXPORT CheckError {
|
|||||||
return stream() << streamed_type;
|
return stream() << streamed_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
LogMessage* const log_message_;
|
LogMessage* const log_message_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -113,6 +113,15 @@ class BASE_EXPORT NotReachedError : public CheckError {
|
|||||||
using CheckError::CheckError;
|
using CheckError::CheckError;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO(crbug.com/851128): This should take the name of the above class once all
|
||||||
|
// callers of NOTREACHED() have migrated to the CHECK-fatal version.
|
||||||
|
class BASE_EXPORT NotReachedNoreturnError : public CheckError {
|
||||||
|
public:
|
||||||
|
NotReachedNoreturnError(const char* file, int line);
|
||||||
|
|
||||||
|
[[noreturn]] NOMERGE NOINLINE NOT_TAIL_CALLED ~NotReachedNoreturnError();
|
||||||
|
};
|
||||||
|
|
||||||
// The 'switch' is used to prevent the 'else' from being ambiguous when the
|
// The 'switch' is used to prevent the 'else' from being ambiguous when the
|
||||||
// macro is used in an 'if' clause such as:
|
// macro is used in an 'if' clause such as:
|
||||||
// if (a == 1)
|
// if (a == 1)
|
||||||
|
@ -76,19 +76,4 @@ char* StreamValToStr(const void* v,
|
|||||||
return strdup(ss.str().c_str());
|
return strdup(ss.str().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
LogMessage* CheckOpResult::CreateLogMessage(bool is_dcheck,
|
|
||||||
const char* file,
|
|
||||||
int line,
|
|
||||||
const char* expr_str,
|
|
||||||
char* v1_str,
|
|
||||||
char* v2_str) {
|
|
||||||
LogMessage* const log_message =
|
|
||||||
new LogMessage(file, line, is_dcheck ? LOGGING_DCHECK : LOGGING_FATAL);
|
|
||||||
log_message->stream() << "Check failed: " << expr_str << " (" << v1_str
|
|
||||||
<< " vs. " << v2_str << ")";
|
|
||||||
free(v1_str);
|
|
||||||
free(v2_str);
|
|
||||||
return log_message;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace logging
|
} // namespace logging
|
||||||
|
@ -64,7 +64,7 @@
|
|||||||
// folding of multiple identical caller functions into a single signature. To
|
// folding of multiple identical caller functions into a single signature. To
|
||||||
// prevent code folding, see NO_CODE_FOLDING() in base/debug/alias.h.
|
// prevent code folding, see NO_CODE_FOLDING() in base/debug/alias.h.
|
||||||
// Use like:
|
// Use like:
|
||||||
// void NOT_TAIL_CALLED FooBar();
|
// NOT_TAIL_CALLED void FooBar();
|
||||||
#if defined(__clang__) && HAS_ATTRIBUTE(not_tail_called)
|
#if defined(__clang__) && HAS_ATTRIBUTE(not_tail_called)
|
||||||
#define NOT_TAIL_CALLED __attribute__((not_tail_called))
|
#define NOT_TAIL_CALLED __attribute__((not_tail_called))
|
||||||
#else
|
#else
|
||||||
|
@ -253,6 +253,15 @@ class EnumSet {
|
|||||||
// Removes all values from our set.
|
// Removes all values from our set.
|
||||||
void Clear() { enums_.reset(); }
|
void Clear() { enums_.reset(); }
|
||||||
|
|
||||||
|
// Conditionally puts or removes `value`, based on `should_be_present`.
|
||||||
|
void PutOrRemove(E value, bool should_be_present) {
|
||||||
|
if (should_be_present) {
|
||||||
|
Put(value);
|
||||||
|
} else {
|
||||||
|
Remove(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true iff the given value is in range and a member of our set.
|
// Returns true iff the given value is in range and a member of our set.
|
||||||
constexpr bool Has(E value) const {
|
constexpr bool Has(E value) const {
|
||||||
return InRange(value) && enums_[ToIndex(value)];
|
return InRange(value) && enums_[ToIndex(value)];
|
||||||
|
@ -250,7 +250,7 @@ class small_map {
|
|||||||
inline explicit iterator(const typename NormalMap::iterator& init)
|
inline explicit iterator(const typename NormalMap::iterator& init)
|
||||||
: array_iter_(nullptr), map_iter_(init) {}
|
: array_iter_(nullptr), map_iter_(init) {}
|
||||||
|
|
||||||
raw_ptr<value_type> array_iter_;
|
raw_ptr<value_type, AllowPtrArithmetic> array_iter_;
|
||||||
typename NormalMap::iterator map_iter_;
|
typename NormalMap::iterator map_iter_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -327,7 +327,7 @@ class small_map {
|
|||||||
const typename NormalMap::const_iterator& init)
|
const typename NormalMap::const_iterator& init)
|
||||||
: array_iter_(nullptr), map_iter_(init) {}
|
: array_iter_(nullptr), map_iter_(init) {}
|
||||||
|
|
||||||
raw_ptr<const value_type> array_iter_;
|
raw_ptr<const value_type, AllowPtrArithmetic> array_iter_;
|
||||||
typename NormalMap::const_iterator map_iter_;
|
typename NormalMap::const_iterator map_iter_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "base/containers/checked_iterators.h"
|
#include "base/containers/checked_iterators.h"
|
||||||
#include "base/containers/contiguous_iterator.h"
|
#include "base/containers/contiguous_iterator.h"
|
||||||
#include "base/cxx20_to_address.h"
|
#include "base/cxx20_to_address.h"
|
||||||
|
#include "base/numerics/safe_math.h"
|
||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
|
|
||||||
@ -256,16 +257,16 @@ class GSL_POINTER span : public internal::ExtentStorage<Extent> {
|
|||||||
|
|
||||||
template <typename It,
|
template <typename It,
|
||||||
typename = internal::EnableIfCompatibleContiguousIterator<It, T>>
|
typename = internal::EnableIfCompatibleContiguousIterator<It, T>>
|
||||||
constexpr span(It first, size_t count) noexcept
|
constexpr span(It first, StrictNumeric<size_t> count) noexcept
|
||||||
: ExtentStorage(count),
|
: ExtentStorage(count),
|
||||||
// The use of to_address() here is to handle the case where the iterator
|
// The use of to_address() here is to handle the case where the iterator
|
||||||
// `first` is pointing to the container's `end()`. In that case we can
|
// `first` is pointing to the container's `end()`. In that case we can
|
||||||
// not use the address returned from the iterator, or dereference it
|
// not use the address returned from the iterator, or dereference it
|
||||||
// through the iterator's `operator*`, but we can store it. We must assume
|
// through the iterator's `operator*`, but we can store it. We must
|
||||||
// in this case that `count` is 0, since the iterator does not point to
|
// assume in this case that `count` is 0, since the iterator does not
|
||||||
// valid data. Future hardening of iterators may disallow pulling the
|
// point to valid data. Future hardening of iterators may disallow
|
||||||
// address from `end()`, as demonstrated by asserts() in libstdc++:
|
// pulling the address from `end()`, as demonstrated by asserts() in
|
||||||
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93960.
|
// libstdc++: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93960.
|
||||||
//
|
//
|
||||||
// The span API dictates that the `data()` is accessible when size is 0,
|
// The span API dictates that the `data()` is accessible when size is 0,
|
||||||
// since the pointer may be valid, so we cannot prevent storing and
|
// since the pointer may be valid, so we cannot prevent storing and
|
||||||
@ -473,7 +474,7 @@ as_writable_bytes(span<T, X> s) noexcept {
|
|||||||
|
|
||||||
// Type-deducing helpers for constructing a span.
|
// Type-deducing helpers for constructing a span.
|
||||||
template <int&... ExplicitArgumentBarrier, typename It>
|
template <int&... ExplicitArgumentBarrier, typename It>
|
||||||
constexpr auto make_span(It it, size_t size) noexcept {
|
constexpr auto make_span(It it, StrictNumeric<size_t> size) noexcept {
|
||||||
using T = std::remove_reference_t<iter_reference_t<It>>;
|
using T = std::remove_reference_t<iter_reference_t<It>>;
|
||||||
return span<T>(it, size);
|
return span<T>(it, size);
|
||||||
}
|
}
|
||||||
@ -508,7 +509,7 @@ constexpr auto make_span(Container&& container) noexcept {
|
|||||||
//
|
//
|
||||||
// Usage: auto static_span = base::make_span<N>(...);
|
// Usage: auto static_span = base::make_span<N>(...);
|
||||||
template <size_t N, int&... ExplicitArgumentBarrier, typename It>
|
template <size_t N, int&... ExplicitArgumentBarrier, typename It>
|
||||||
constexpr auto make_span(It it, size_t size) noexcept {
|
constexpr auto make_span(It it, StrictNumeric<size_t> size) noexcept {
|
||||||
using T = std::remove_reference_t<iter_reference_t<It>>;
|
using T = std::remove_reference_t<iter_reference_t<It>>;
|
||||||
return span<T, N>(it, size);
|
return span<T, N>(it, size);
|
||||||
}
|
}
|
||||||
|
@ -5,27 +5,13 @@
|
|||||||
#ifndef BASE_CXX17_BACKPORTS_H_
|
#ifndef BASE_CXX17_BACKPORTS_H_
|
||||||
#define BASE_CXX17_BACKPORTS_H_
|
#define BASE_CXX17_BACKPORTS_H_
|
||||||
|
|
||||||
#include <functional>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "base/check.h"
|
|
||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
|
|
||||||
// C++14 implementation of C++17's std::clamp():
|
// TODO(crbug.com/1373621): Rewrite all uses of base::clamp as std::clamp and
|
||||||
// https://en.cppreference.com/w/cpp/algorithm/clamp
|
// remove this file.
|
||||||
// Please note that the C++ spec makes it undefined behavior to call std::clamp
|
using std::clamp;
|
||||||
// with a value of `lo` that compares greater than the value of `hi`. This
|
|
||||||
// implementation uses a CHECK to enforce this as a hard restriction.
|
|
||||||
template <typename T, typename Compare>
|
|
||||||
constexpr const T& clamp(const T& v, const T& lo, const T& hi, Compare comp) {
|
|
||||||
CHECK(!comp(hi, lo));
|
|
||||||
return comp(v, lo) ? lo : comp(hi, v) ? hi : v;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
constexpr const T& clamp(const T& v, const T& lo, const T& hi) {
|
|
||||||
return base::clamp(v, lo, hi, std::less<T>{});
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace base
|
} // namespace base
|
||||||
|
|
||||||
|
@ -1,5 +1,2 @@
|
|||||||
# For activity tracking:
|
|
||||||
per-file activity_*=bcwhite@chromium.org
|
|
||||||
|
|
||||||
# For ASan integration:
|
# For ASan integration:
|
||||||
per-file asan_service*=file://base/memory/MIRACLE_PTR_OWNERS
|
per-file asan_service*=file://base/memory/MIRACLE_PTR_OWNERS
|
||||||
|
@ -1,407 +0,0 @@
|
|||||||
// Copyright 2016 The Chromium Authors
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#include "base/debug/activity_analyzer.h"
|
|
||||||
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "base/check_op.h"
|
|
||||||
#include "base/containers/contains.h"
|
|
||||||
#include "base/files/file.h"
|
|
||||||
#include "base/files/file_path.h"
|
|
||||||
#include "base/files/memory_mapped_file.h"
|
|
||||||
#include "base/metrics/histogram_functions.h"
|
|
||||||
#include "base/metrics/histogram_macros.h"
|
|
||||||
#include "base/no_destructor.h"
|
|
||||||
#include "base/ranges/algorithm.h"
|
|
||||||
#include "base/strings/string_util.h"
|
|
||||||
#include "build/build_config.h"
|
|
||||||
|
|
||||||
namespace base {
|
|
||||||
namespace debug {
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
const ActivityUserData::Snapshot& GetEmptyUserDataSnapshot() {
|
|
||||||
// An empty snapshot that can be returned when there otherwise is none.
|
|
||||||
static const NoDestructor<ActivityUserData::Snapshot> empty_snapshot;
|
|
||||||
return *empty_snapshot;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DO NOT CHANGE VALUES. This is logged persistently in a histogram.
|
|
||||||
enum AnalyzerCreationError {
|
|
||||||
kInvalidMemoryMappedFile,
|
|
||||||
kPmaBadFile,
|
|
||||||
kPmaUninitialized,
|
|
||||||
kPmaDeleted,
|
|
||||||
kPmaCorrupt,
|
|
||||||
kAnalyzerCreationErrorMax // Keep this last.
|
|
||||||
};
|
|
||||||
|
|
||||||
void LogAnalyzerCreationError(AnalyzerCreationError error) {
|
|
||||||
UmaHistogramEnumeration("ActivityTracker.Collect.AnalyzerCreationError",
|
|
||||||
error, kAnalyzerCreationErrorMax);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
ThreadActivityAnalyzer::Snapshot::Snapshot() = default;
|
|
||||||
ThreadActivityAnalyzer::Snapshot::~Snapshot() = default;
|
|
||||||
|
|
||||||
ThreadActivityAnalyzer::ThreadActivityAnalyzer(
|
|
||||||
const ThreadActivityTracker& tracker)
|
|
||||||
: activity_snapshot_valid_(tracker.CreateSnapshot(&activity_snapshot_)) {}
|
|
||||||
|
|
||||||
ThreadActivityAnalyzer::ThreadActivityAnalyzer(void* base, size_t size)
|
|
||||||
: ThreadActivityAnalyzer(ThreadActivityTracker(base, size)) {}
|
|
||||||
|
|
||||||
ThreadActivityAnalyzer::ThreadActivityAnalyzer(
|
|
||||||
PersistentMemoryAllocator* allocator,
|
|
||||||
PersistentMemoryAllocator::Reference reference)
|
|
||||||
: ThreadActivityAnalyzer(allocator->GetAsArray<char>(
|
|
||||||
reference,
|
|
||||||
GlobalActivityTracker::kTypeIdActivityTracker,
|
|
||||||
PersistentMemoryAllocator::kSizeAny),
|
|
||||||
allocator->GetAllocSize(reference)) {}
|
|
||||||
|
|
||||||
ThreadActivityAnalyzer::~ThreadActivityAnalyzer() = default;
|
|
||||||
|
|
||||||
void ThreadActivityAnalyzer::AddGlobalInformation(
|
|
||||||
GlobalActivityAnalyzer* global) {
|
|
||||||
if (!IsValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// User-data is held at the global scope even though it's referenced at the
|
|
||||||
// thread scope.
|
|
||||||
activity_snapshot_.user_data_stack.clear();
|
|
||||||
for (auto& activity : activity_snapshot_.activity_stack) {
|
|
||||||
// The global GetUserDataSnapshot will return an empty snapshot if the ref
|
|
||||||
// or id is not valid.
|
|
||||||
activity_snapshot_.user_data_stack.push_back(global->GetUserDataSnapshot(
|
|
||||||
activity_snapshot_.process_id, activity.user_data_ref,
|
|
||||||
activity.user_data_id));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GlobalActivityAnalyzer::GlobalActivityAnalyzer(
|
|
||||||
std::unique_ptr<PersistentMemoryAllocator> allocator)
|
|
||||||
: allocator_(std::move(allocator)),
|
|
||||||
analysis_stamp_(0LL),
|
|
||||||
allocator_iterator_(allocator_.get()) {
|
|
||||||
DCHECK(allocator_);
|
|
||||||
}
|
|
||||||
|
|
||||||
GlobalActivityAnalyzer::~GlobalActivityAnalyzer() = default;
|
|
||||||
|
|
||||||
// static
|
|
||||||
std::unique_ptr<GlobalActivityAnalyzer>
|
|
||||||
GlobalActivityAnalyzer::CreateWithAllocator(
|
|
||||||
std::unique_ptr<PersistentMemoryAllocator> allocator) {
|
|
||||||
if (allocator->GetMemoryState() ==
|
|
||||||
PersistentMemoryAllocator::MEMORY_UNINITIALIZED) {
|
|
||||||
LogAnalyzerCreationError(kPmaUninitialized);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (allocator->GetMemoryState() ==
|
|
||||||
PersistentMemoryAllocator::MEMORY_DELETED) {
|
|
||||||
LogAnalyzerCreationError(kPmaDeleted);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (allocator->IsCorrupt()) {
|
|
||||||
LogAnalyzerCreationError(kPmaCorrupt);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::make_unique<GlobalActivityAnalyzer>(std::move(allocator));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !BUILDFLAG(IS_NACL)
|
|
||||||
// static
|
|
||||||
std::unique_ptr<GlobalActivityAnalyzer> GlobalActivityAnalyzer::CreateWithFile(
|
|
||||||
const FilePath& file_path) {
|
|
||||||
// Map the file read-write so it can guarantee consistency between
|
|
||||||
// the analyzer and any trackers that my still be active.
|
|
||||||
std::unique_ptr<MemoryMappedFile> mmfile(new MemoryMappedFile());
|
|
||||||
if (!mmfile->Initialize(file_path, MemoryMappedFile::READ_WRITE)) {
|
|
||||||
LogAnalyzerCreationError(kInvalidMemoryMappedFile);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile, true)) {
|
|
||||||
LogAnalyzerCreationError(kPmaBadFile);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CreateWithAllocator(std::make_unique<FilePersistentMemoryAllocator>(
|
|
||||||
std::move(mmfile), 0, 0, StringPiece(), /*readonly=*/true));
|
|
||||||
}
|
|
||||||
#endif // !BUILDFLAG(IS_NACL)
|
|
||||||
|
|
||||||
// static
|
|
||||||
std::unique_ptr<GlobalActivityAnalyzer>
|
|
||||||
GlobalActivityAnalyzer::CreateWithSharedMemory(
|
|
||||||
base::ReadOnlySharedMemoryMapping mapping) {
|
|
||||||
if (!mapping.IsValid() ||
|
|
||||||
!ReadOnlySharedPersistentMemoryAllocator::IsSharedMemoryAcceptable(
|
|
||||||
mapping)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
return CreateWithAllocator(
|
|
||||||
std::make_unique<ReadOnlySharedPersistentMemoryAllocator>(
|
|
||||||
std::move(mapping), 0, StringPiece()));
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessId GlobalActivityAnalyzer::GetFirstProcess() {
|
|
||||||
PrepareAllAnalyzers();
|
|
||||||
return GetNextProcess();
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessId GlobalActivityAnalyzer::GetNextProcess() {
|
|
||||||
if (process_ids_.empty())
|
|
||||||
return 0;
|
|
||||||
ProcessId pid = process_ids_.back();
|
|
||||||
process_ids_.pop_back();
|
|
||||||
return pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetFirstAnalyzer(
|
|
||||||
ProcessId pid) {
|
|
||||||
analyzers_iterator_ = analyzers_.begin();
|
|
||||||
analyzers_iterator_pid_ = pid;
|
|
||||||
if (analyzers_iterator_ == analyzers_.end())
|
|
||||||
return nullptr;
|
|
||||||
int64_t create_stamp;
|
|
||||||
if (analyzers_iterator_->second->GetProcessId(&create_stamp) == pid &&
|
|
||||||
create_stamp <= analysis_stamp_) {
|
|
||||||
return analyzers_iterator_->second.get();
|
|
||||||
}
|
|
||||||
return GetNextAnalyzer();
|
|
||||||
}
|
|
||||||
|
|
||||||
ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetNextAnalyzer() {
|
|
||||||
DCHECK(analyzers_iterator_ != analyzers_.end());
|
|
||||||
int64_t create_stamp;
|
|
||||||
do {
|
|
||||||
++analyzers_iterator_;
|
|
||||||
if (analyzers_iterator_ == analyzers_.end())
|
|
||||||
return nullptr;
|
|
||||||
} while (analyzers_iterator_->second->GetProcessId(&create_stamp) !=
|
|
||||||
analyzers_iterator_pid_ ||
|
|
||||||
create_stamp > analysis_stamp_);
|
|
||||||
return analyzers_iterator_->second.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetAnalyzerForThread(
|
|
||||||
const ThreadKey& key) {
|
|
||||||
auto found = analyzers_.find(key);
|
|
||||||
if (found == analyzers_.end())
|
|
||||||
return nullptr;
|
|
||||||
return found->second.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
ActivityUserData::Snapshot GlobalActivityAnalyzer::GetUserDataSnapshot(
|
|
||||||
ProcessId pid,
|
|
||||||
uint32_t ref,
|
|
||||||
uint32_t id) {
|
|
||||||
ActivityUserData::Snapshot snapshot;
|
|
||||||
|
|
||||||
void* memory = allocator_->GetAsArray<char>(
|
|
||||||
ref, GlobalActivityTracker::kTypeIdUserDataRecord,
|
|
||||||
PersistentMemoryAllocator::kSizeAny);
|
|
||||||
if (memory) {
|
|
||||||
size_t size = allocator_->GetAllocSize(ref);
|
|
||||||
const ActivityUserData user_data(memory, size);
|
|
||||||
user_data.CreateSnapshot(&snapshot);
|
|
||||||
ProcessId process_id;
|
|
||||||
int64_t create_stamp;
|
|
||||||
if (!ActivityUserData::GetOwningProcessId(memory, &process_id,
|
|
||||||
&create_stamp) ||
|
|
||||||
process_id != pid || user_data.id() != id) {
|
|
||||||
// This allocation has been overwritten since it was created. Return an
|
|
||||||
// empty snapshot because whatever was captured is incorrect.
|
|
||||||
snapshot.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return snapshot;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ActivityUserData::Snapshot&
|
|
||||||
GlobalActivityAnalyzer::GetProcessDataSnapshot(ProcessId pid) {
|
|
||||||
auto iter = process_data_.find(pid);
|
|
||||||
if (iter == process_data_.end())
|
|
||||||
return GetEmptyUserDataSnapshot();
|
|
||||||
if (iter->second.create_stamp > analysis_stamp_)
|
|
||||||
return GetEmptyUserDataSnapshot();
|
|
||||||
DCHECK_EQ(pid, iter->second.process_id);
|
|
||||||
return iter->second.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> GlobalActivityAnalyzer::GetLogMessages() {
|
|
||||||
std::vector<std::string> messages;
|
|
||||||
PersistentMemoryAllocator::Reference ref;
|
|
||||||
|
|
||||||
PersistentMemoryAllocator::Iterator iter(allocator_.get());
|
|
||||||
while ((ref = iter.GetNextOfType(
|
|
||||||
GlobalActivityTracker::kTypeIdGlobalLogMessage)) != 0) {
|
|
||||||
const char* message = allocator_->GetAsArray<char>(
|
|
||||||
ref, GlobalActivityTracker::kTypeIdGlobalLogMessage,
|
|
||||||
PersistentMemoryAllocator::kSizeAny);
|
|
||||||
if (message)
|
|
||||||
messages.push_back(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
return messages;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<GlobalActivityTracker::ModuleInfo>
|
|
||||||
GlobalActivityAnalyzer::GetModules(ProcessId pid) {
|
|
||||||
std::vector<GlobalActivityTracker::ModuleInfo> modules;
|
|
||||||
|
|
||||||
PersistentMemoryAllocator::Iterator iter(allocator_.get());
|
|
||||||
const GlobalActivityTracker::ModuleInfoRecord* record;
|
|
||||||
while (
|
|
||||||
(record =
|
|
||||||
iter.GetNextOfObject<GlobalActivityTracker::ModuleInfoRecord>()) !=
|
|
||||||
nullptr) {
|
|
||||||
ProcessId process_id;
|
|
||||||
int64_t create_stamp;
|
|
||||||
if (!OwningProcess::GetOwningProcessId(&record->owner, &process_id,
|
|
||||||
&create_stamp) ||
|
|
||||||
pid != process_id || create_stamp > analysis_stamp_) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
GlobalActivityTracker::ModuleInfo info;
|
|
||||||
if (record->DecodeTo(&info, allocator_->GetAllocSize(
|
|
||||||
allocator_->GetAsReference(record)))) {
|
|
||||||
modules.push_back(std::move(info));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return modules;
|
|
||||||
}
|
|
||||||
|
|
||||||
GlobalActivityAnalyzer::ProgramLocation
|
|
||||||
GlobalActivityAnalyzer::GetProgramLocationFromAddress(uint64_t address) {
|
|
||||||
// This should be implemented but it's never been a priority.
|
|
||||||
return { 0, 0 };
|
|
||||||
}
|
|
||||||
|
|
||||||
bool GlobalActivityAnalyzer::IsDataComplete() const {
|
|
||||||
DCHECK(allocator_);
|
|
||||||
return !allocator_->IsFull();
|
|
||||||
}
|
|
||||||
|
|
||||||
GlobalActivityAnalyzer::UserDataSnapshot::UserDataSnapshot() = default;
|
|
||||||
GlobalActivityAnalyzer::UserDataSnapshot::UserDataSnapshot(
|
|
||||||
const UserDataSnapshot& rhs) = default;
|
|
||||||
GlobalActivityAnalyzer::UserDataSnapshot::UserDataSnapshot(
|
|
||||||
UserDataSnapshot&& rhs) = default;
|
|
||||||
GlobalActivityAnalyzer::UserDataSnapshot::~UserDataSnapshot() = default;
|
|
||||||
|
|
||||||
void GlobalActivityAnalyzer::PrepareAllAnalyzers() {
|
|
||||||
// Record the time when analysis started.
|
|
||||||
analysis_stamp_ = base::Time::Now().ToInternalValue();
|
|
||||||
|
|
||||||
// Fetch all the records. This will retrieve only ones created since the
|
|
||||||
// last run since the PMA iterator will continue from where it left off.
|
|
||||||
uint32_t type;
|
|
||||||
PersistentMemoryAllocator::Reference ref;
|
|
||||||
while ((ref = allocator_iterator_.GetNext(&type)) != 0) {
|
|
||||||
switch (type) {
|
|
||||||
case GlobalActivityTracker::kTypeIdActivityTracker:
|
|
||||||
case GlobalActivityTracker::kTypeIdActivityTrackerFree:
|
|
||||||
case GlobalActivityTracker::kTypeIdProcessDataRecord:
|
|
||||||
case GlobalActivityTracker::kTypeIdProcessDataRecordFree:
|
|
||||||
case PersistentMemoryAllocator::kTypeIdTransitioning:
|
|
||||||
// Active, free, or transitioning: add it to the list of references
|
|
||||||
// for later analysis.
|
|
||||||
memory_references_.insert(ref);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clear out any old information.
|
|
||||||
analyzers_.clear();
|
|
||||||
process_data_.clear();
|
|
||||||
process_ids_.clear();
|
|
||||||
std::set<ProcessId> seen_pids;
|
|
||||||
|
|
||||||
// Go through all the known references and create objects for them with
|
|
||||||
// snapshots of the current state.
|
|
||||||
for (PersistentMemoryAllocator::Reference memory_ref : memory_references_) {
|
|
||||||
// Get the actual data segment for the tracker. Any type will do since it
|
|
||||||
// is checked below.
|
|
||||||
void* const base = allocator_->GetAsArray<char>(
|
|
||||||
memory_ref, PersistentMemoryAllocator::kTypeIdAny,
|
|
||||||
PersistentMemoryAllocator::kSizeAny);
|
|
||||||
const size_t size = allocator_->GetAllocSize(memory_ref);
|
|
||||||
if (!base)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch (allocator_->GetType(memory_ref)) {
|
|
||||||
case GlobalActivityTracker::kTypeIdActivityTracker: {
|
|
||||||
// Create the analyzer on the data. This will capture a snapshot of the
|
|
||||||
// tracker state. This can fail if the tracker is somehow corrupted or
|
|
||||||
// is in the process of shutting down.
|
|
||||||
std::unique_ptr<ThreadActivityAnalyzer> analyzer(
|
|
||||||
new ThreadActivityAnalyzer(base, size));
|
|
||||||
if (!analyzer->IsValid())
|
|
||||||
continue;
|
|
||||||
analyzer->AddGlobalInformation(this);
|
|
||||||
|
|
||||||
// Track PIDs.
|
|
||||||
ProcessId pid = analyzer->GetProcessId();
|
|
||||||
if (seen_pids.find(pid) == seen_pids.end()) {
|
|
||||||
process_ids_.push_back(pid);
|
|
||||||
seen_pids.insert(pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add this analyzer to the map of known ones, indexed by a unique
|
|
||||||
// thread
|
|
||||||
// identifier.
|
|
||||||
DCHECK(!base::Contains(analyzers_, analyzer->GetThreadKey()));
|
|
||||||
analyzer->allocator_reference_ = ref;
|
|
||||||
analyzers_[analyzer->GetThreadKey()] = std::move(analyzer);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case GlobalActivityTracker::kTypeIdProcessDataRecord: {
|
|
||||||
// Get the PID associated with this data record.
|
|
||||||
ProcessId process_id;
|
|
||||||
int64_t create_stamp;
|
|
||||||
ActivityUserData::GetOwningProcessId(base, &process_id, &create_stamp);
|
|
||||||
DCHECK(!base::Contains(process_data_, process_id));
|
|
||||||
|
|
||||||
// Create a snapshot of the data. This can fail if the data is somehow
|
|
||||||
// corrupted or the process shutdown and the memory being released.
|
|
||||||
UserDataSnapshot& snapshot = process_data_[process_id];
|
|
||||||
snapshot.process_id = process_id;
|
|
||||||
snapshot.create_stamp = create_stamp;
|
|
||||||
const ActivityUserData process_data(base, size);
|
|
||||||
if (!process_data.CreateSnapshot(&snapshot.data))
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Check that nothing changed. If it did, forget what was recorded.
|
|
||||||
ActivityUserData::GetOwningProcessId(base, &process_id, &create_stamp);
|
|
||||||
if (process_id != snapshot.process_id ||
|
|
||||||
create_stamp != snapshot.create_stamp) {
|
|
||||||
process_data_.erase(process_id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Track PIDs.
|
|
||||||
if (seen_pids.find(process_id) == seen_pids.end()) {
|
|
||||||
process_ids_.push_back(process_id);
|
|
||||||
seen_pids.insert(process_id);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reverse the list of PIDs so that they get popped in the order found.
|
|
||||||
ranges::reverse(process_ids_);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace debug
|
|
||||||
} // namespace base
|
|
@ -1,260 +0,0 @@
|
|||||||
// Copyright 2016 The Chromium Authors
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
#ifndef BASE_DEBUG_ACTIVITY_ANALYZER_H_
|
|
||||||
#define BASE_DEBUG_ACTIVITY_ANALYZER_H_
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <memory>
|
|
||||||
#include <set>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include "base/base_export.h"
|
|
||||||
#include "base/debug/activity_tracker.h"
|
|
||||||
#include "base/memory/shared_memory_mapping.h"
|
|
||||||
#include "build/build_config.h"
|
|
||||||
|
|
||||||
namespace base {
|
|
||||||
namespace debug {
|
|
||||||
|
|
||||||
class GlobalActivityAnalyzer;
|
|
||||||
|
|
||||||
// This class provides analysis of data captured from a ThreadActivityTracker.
|
|
||||||
// When created, it takes a snapshot of the data held by the tracker and
|
|
||||||
// makes that information available to other code.
|
|
||||||
class BASE_EXPORT ThreadActivityAnalyzer {
|
|
||||||
public:
|
|
||||||
struct BASE_EXPORT Snapshot : ThreadActivityTracker::Snapshot {
|
|
||||||
Snapshot();
|
|
||||||
~Snapshot();
|
|
||||||
|
|
||||||
// The user-data snapshot for an activity, matching the |activity_stack|
|
|
||||||
// of ThreadActivityTracker::Snapshot, if any.
|
|
||||||
std::vector<ActivityUserData::Snapshot> user_data_stack;
|
|
||||||
};
|
|
||||||
|
|
||||||
// This class provides keys that uniquely identify a thread, even across
|
|
||||||
// multiple processes.
|
|
||||||
class ThreadKey {
|
|
||||||
public:
|
|
||||||
ThreadKey(ProcessId pid, int64_t tid) : pid_(pid), tid_(tid) {}
|
|
||||||
|
|
||||||
bool operator<(const ThreadKey& rhs) const {
|
|
||||||
if (pid_ != rhs.pid_)
|
|
||||||
return pid_ < rhs.pid_;
|
|
||||||
return tid_ < rhs.tid_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(const ThreadKey& rhs) const {
|
|
||||||
return (pid_ == rhs.pid_ && tid_ == rhs.tid_);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
ProcessId pid_;
|
|
||||||
int64_t tid_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Creates an analyzer for an existing activity |tracker|. A snapshot is taken
|
|
||||||
// immediately and the tracker is not referenced again.
|
|
||||||
explicit ThreadActivityAnalyzer(const ThreadActivityTracker& tracker);
|
|
||||||
|
|
||||||
// Creates an analyzer for a block of memory currently or previously in-use
|
|
||||||
// by an activity-tracker. A snapshot is taken immediately and the memory
|
|
||||||
// is not referenced again.
|
|
||||||
ThreadActivityAnalyzer(void* base, size_t size);
|
|
||||||
|
|
||||||
// Creates an analyzer for a block of memory held within a persistent-memory
|
|
||||||
// |allocator| at the given |reference|. A snapshot is taken immediately and
|
|
||||||
// the memory is not referenced again.
|
|
||||||
ThreadActivityAnalyzer(PersistentMemoryAllocator* allocator,
|
|
||||||
PersistentMemoryAllocator::Reference reference);
|
|
||||||
|
|
||||||
ThreadActivityAnalyzer(const ThreadActivityAnalyzer&) = delete;
|
|
||||||
ThreadActivityAnalyzer& operator=(const ThreadActivityAnalyzer&) = delete;
|
|
||||||
|
|
||||||
~ThreadActivityAnalyzer();
|
|
||||||
|
|
||||||
// Adds information from the global analyzer.
|
|
||||||
void AddGlobalInformation(GlobalActivityAnalyzer* global);
|
|
||||||
|
|
||||||
// Returns true iff the contained data is valid. Results from all other
|
|
||||||
// methods are undefined if this returns false.
|
|
||||||
bool IsValid() { return activity_snapshot_valid_; }
|
|
||||||
|
|
||||||
// Gets the process id and its creation stamp.
|
|
||||||
ProcessId GetProcessId(int64_t* out_stamp = nullptr) {
|
|
||||||
if (out_stamp)
|
|
||||||
*out_stamp = activity_snapshot_.create_stamp;
|
|
||||||
return activity_snapshot_.process_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the name of the thread.
|
|
||||||
const std::string& GetThreadName() {
|
|
||||||
return activity_snapshot_.thread_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the TheadKey for this thread.
|
|
||||||
ThreadKey GetThreadKey() {
|
|
||||||
return ThreadKey(activity_snapshot_.process_id,
|
|
||||||
activity_snapshot_.thread_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Snapshot& activity_snapshot() { return activity_snapshot_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class GlobalActivityAnalyzer;
|
|
||||||
|
|
||||||
// The snapshot of the activity tracker taken at the moment of construction.
|
|
||||||
Snapshot activity_snapshot_;
|
|
||||||
|
|
||||||
// Flag indicating if the snapshot data is valid.
|
|
||||||
bool activity_snapshot_valid_;
|
|
||||||
|
|
||||||
// A reference into a persistent memory allocator, used by the global
|
|
||||||
// analyzer to know where this tracker came from.
|
|
||||||
PersistentMemoryAllocator::Reference allocator_reference_ = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// This class manages analyzers for all known processes and threads as stored
|
|
||||||
// in a persistent memory allocator. It supports retrieval of them through
|
|
||||||
// iteration and directly using a ThreadKey, which allows for cross-references
|
|
||||||
// to be resolved.
|
|
||||||
// Note that though atomic snapshots are used and everything has its snapshot
|
|
||||||
// taken at the same time, the multi-snapshot itself is not atomic and thus may
|
|
||||||
// show small inconsistencies between threads if attempted on a live system.
|
|
||||||
class BASE_EXPORT GlobalActivityAnalyzer {
|
|
||||||
public:
|
|
||||||
struct ProgramLocation {
|
|
||||||
int module;
|
|
||||||
uintptr_t offset;
|
|
||||||
};
|
|
||||||
|
|
||||||
using ThreadKey = ThreadActivityAnalyzer::ThreadKey;
|
|
||||||
|
|
||||||
// Creates a global analyzer from a persistent memory allocator.
|
|
||||||
explicit GlobalActivityAnalyzer(
|
|
||||||
std::unique_ptr<PersistentMemoryAllocator> allocator);
|
|
||||||
|
|
||||||
GlobalActivityAnalyzer(const GlobalActivityAnalyzer&) = delete;
|
|
||||||
GlobalActivityAnalyzer& operator=(const GlobalActivityAnalyzer&) = delete;
|
|
||||||
|
|
||||||
~GlobalActivityAnalyzer();
|
|
||||||
|
|
||||||
// Creates a global analyzer using a given persistent-memory |allocator|.
|
|
||||||
static std::unique_ptr<GlobalActivityAnalyzer> CreateWithAllocator(
|
|
||||||
std::unique_ptr<PersistentMemoryAllocator> allocator);
|
|
||||||
|
|
||||||
#if !BUILDFLAG(IS_NACL)
|
|
||||||
// Creates a global analyzer using the contents of a file given in
|
|
||||||
// |file_path|.
|
|
||||||
static std::unique_ptr<GlobalActivityAnalyzer> CreateWithFile(
|
|
||||||
const FilePath& file_path);
|
|
||||||
#endif // !BUILDFLAG(IS_NACL)
|
|
||||||
|
|
||||||
// Like above but accesses an allocator in a mapped shared-memory segment.
|
|
||||||
static std::unique_ptr<GlobalActivityAnalyzer> CreateWithSharedMemory(
|
|
||||||
base::ReadOnlySharedMemoryMapping mapping);
|
|
||||||
|
|
||||||
// Iterates over all known valid processes and returns their PIDs or zero
|
|
||||||
// if there are no more. Calls to GetFirstProcess() will perform a global
|
|
||||||
// snapshot in order to provide a relatively consistent state across the
|
|
||||||
// future calls to GetNextProcess() and GetFirst/NextAnalyzer(). PIDs are
|
|
||||||
// returned in the order they're found meaning that a first-launched
|
|
||||||
// controlling process will be found first. Note, however, that space
|
|
||||||
// freed by an exiting process may be re-used by a later process.
|
|
||||||
ProcessId GetFirstProcess();
|
|
||||||
ProcessId GetNextProcess();
|
|
||||||
|
|
||||||
// Iterates over all known valid analyzers for the a given process or returns
|
|
||||||
// null if there are no more.
|
|
||||||
//
|
|
||||||
// GetFirstProcess() must be called first in order to capture a global
|
|
||||||
// snapshot! Ownership stays with the global analyzer object and all existing
|
|
||||||
// analyzer pointers are invalidated when GetFirstProcess() is called.
|
|
||||||
ThreadActivityAnalyzer* GetFirstAnalyzer(ProcessId pid);
|
|
||||||
ThreadActivityAnalyzer* GetNextAnalyzer();
|
|
||||||
|
|
||||||
// Gets the analyzer for a specific thread or null if there is none.
|
|
||||||
// Ownership stays with the global analyzer object.
|
|
||||||
ThreadActivityAnalyzer* GetAnalyzerForThread(const ThreadKey& key);
|
|
||||||
|
|
||||||
// Extract user data based on a reference and its identifier.
|
|
||||||
ActivityUserData::Snapshot GetUserDataSnapshot(ProcessId pid,
|
|
||||||
uint32_t ref,
|
|
||||||
uint32_t id);
|
|
||||||
|
|
||||||
// Extract the data for a specific process. An empty snapshot will be
|
|
||||||
// returned if the process is not known.
|
|
||||||
const ActivityUserData::Snapshot& GetProcessDataSnapshot(ProcessId pid);
|
|
||||||
|
|
||||||
// Gets all log messages stored within.
|
|
||||||
std::vector<std::string> GetLogMessages();
|
|
||||||
|
|
||||||
// Gets modules corresponding to a pid. This pid must come from a call to
|
|
||||||
// GetFirst/NextProcess. Only modules that were first registered prior to
|
|
||||||
// GetFirstProcess's snapshot are returned.
|
|
||||||
std::vector<GlobalActivityTracker::ModuleInfo> GetModules(ProcessId pid);
|
|
||||||
|
|
||||||
// Gets the corresponding "program location" for a given "program counter".
|
|
||||||
// This will return {0,0} if no mapping could be found.
|
|
||||||
ProgramLocation GetProgramLocationFromAddress(uint64_t address);
|
|
||||||
|
|
||||||
// Returns whether the data is complete. Data can be incomplete if the
|
|
||||||
// recording size quota is hit.
|
|
||||||
bool IsDataComplete() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
using AnalyzerMap =
|
|
||||||
std::map<ThreadKey, std::unique_ptr<ThreadActivityAnalyzer>>;
|
|
||||||
|
|
||||||
struct UserDataSnapshot {
|
|
||||||
// Complex class needs out-of-line ctor/dtor.
|
|
||||||
UserDataSnapshot();
|
|
||||||
UserDataSnapshot(const UserDataSnapshot& rhs);
|
|
||||||
UserDataSnapshot(UserDataSnapshot&& rhs);
|
|
||||||
~UserDataSnapshot();
|
|
||||||
|
|
||||||
ProcessId process_id;
|
|
||||||
int64_t create_stamp;
|
|
||||||
ActivityUserData::Snapshot data;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Finds, creates, and indexes analyzers for all known processes and threads.
|
|
||||||
void PrepareAllAnalyzers();
|
|
||||||
|
|
||||||
// The persistent memory allocator holding all tracking data.
|
|
||||||
std::unique_ptr<PersistentMemoryAllocator> allocator_;
|
|
||||||
|
|
||||||
// The time stamp when analysis began. This is used to prevent looking into
|
|
||||||
// process IDs that get reused when analyzing a live system.
|
|
||||||
int64_t analysis_stamp_;
|
|
||||||
|
|
||||||
// The iterator for finding tracking information in the allocator.
|
|
||||||
PersistentMemoryAllocator::Iterator allocator_iterator_;
|
|
||||||
|
|
||||||
// A set of all interesting memory references found within the allocator.
|
|
||||||
std::set<PersistentMemoryAllocator::Reference> memory_references_;
|
|
||||||
|
|
||||||
// A set of all process-data memory references found within the allocator.
|
|
||||||
std::map<ProcessId, UserDataSnapshot> process_data_;
|
|
||||||
|
|
||||||
// A set of all process IDs collected during PrepareAllAnalyzers. These are
|
|
||||||
// popped and returned one-by-one with calls to GetFirst/NextProcess().
|
|
||||||
std::vector<ProcessId> process_ids_;
|
|
||||||
|
|
||||||
// A map, keyed by ThreadKey, of all valid activity analyzers.
|
|
||||||
AnalyzerMap analyzers_;
|
|
||||||
|
|
||||||
// The iterator within the analyzers_ map for returning analyzers through
|
|
||||||
// first/next iteration.
|
|
||||||
AnalyzerMap::iterator analyzers_iterator_;
|
|
||||||
ProcessId analyzers_iterator_pid_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace debug
|
|
||||||
} // namespace base
|
|
||||||
|
|
||||||
#endif // BASE_DEBUG_ACTIVITY_ANALYZER_H_
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -300,6 +301,27 @@ void PrintToStderr(const char* output) {
|
|||||||
std::ignore = HANDLE_EINTR(write(STDERR_FILENO, output, strlen(output)));
|
std::ignore = HANDLE_EINTR(write(STDERR_FILENO, output, strlen(output)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if BUILDFLAG(IS_LINUX)
|
||||||
|
void AlarmSignalHandler(int signal, siginfo_t* info, void* void_context) {
|
||||||
|
// We have seen rare cases on AMD linux where the default signal handler
|
||||||
|
// either does not run or a thread (Probably an AMD driver thread) prevents
|
||||||
|
// the termination of the gpu process. We catch this case when the alarm fires
|
||||||
|
// and then call exit_group() to kill all threads of the process. This has
|
||||||
|
// resolved the zombie gpu process issues we have seen on our context lost
|
||||||
|
// test.
|
||||||
|
// Note that many different calls were tried to kill the process when it is in
|
||||||
|
// this state. Only 'exit_group' was found to cause termination and it is
|
||||||
|
// speculated that only this works because only this exit kills all threads in
|
||||||
|
// the process (not simply the current thread).
|
||||||
|
// See: http://crbug.com/1396451.
|
||||||
|
PrintToStderr(
|
||||||
|
"Warning: Default signal handler failed to terminate process.\n");
|
||||||
|
PrintToStderr("Calling exit_group() directly to prevent timeout.\n");
|
||||||
|
// See: https://man7.org/linux/man-pages/man2/exit_group.2.html
|
||||||
|
syscall(SYS_exit_group, EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
#endif // BUILDFLAG(IS_LINUX)
|
||||||
|
|
||||||
void StackDumpSignalHandler(int signal, siginfo_t* info, void* void_context) {
|
void StackDumpSignalHandler(int signal, siginfo_t* info, void* void_context) {
|
||||||
// NOTE: This code MUST be async-signal safe.
|
// NOTE: This code MUST be async-signal safe.
|
||||||
// NO malloc or stdio is allowed here.
|
// NO malloc or stdio is allowed here.
|
||||||
@ -520,11 +542,27 @@ void StackDumpSignalHandler(int signal, siginfo_t* info, void* void_context) {
|
|||||||
PrintToStderr(
|
PrintToStderr(
|
||||||
"Calling _exit(EXIT_FAILURE). Core file will not be generated.\n");
|
"Calling _exit(EXIT_FAILURE). Core file will not be generated.\n");
|
||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
#endif // !BUILDFLAG(IS_LINUX)
|
#else // BUILDFLAG(IS_LINUX)
|
||||||
|
|
||||||
// After leaving this handler control flow returns to the point where the
|
// After leaving this handler control flow returns to the point where the
|
||||||
// signal was raised, raising the current signal once again but executing the
|
// signal was raised, raising the current signal once again but executing the
|
||||||
// default handler instead of this one.
|
// default handler instead of this one.
|
||||||
|
|
||||||
|
// Set an alarm to trigger in case the default handler does not terminate
|
||||||
|
// the process. See 'AlarmSignalHandler' for more details.
|
||||||
|
struct sigaction action;
|
||||||
|
memset(&action, 0, sizeof(action));
|
||||||
|
action.sa_flags = static_cast<int>(SA_RESETHAND);
|
||||||
|
action.sa_sigaction = &AlarmSignalHandler;
|
||||||
|
sigemptyset(&action.sa_mask);
|
||||||
|
sigaction(SIGALRM, &action, nullptr);
|
||||||
|
// 'alarm' function is signal handler safe.
|
||||||
|
// https://man7.org/linux/man-pages/man7/signal-safety.7.html
|
||||||
|
// This delay is set to be long enough for the real signal handler to fire but
|
||||||
|
// shorter than chrome's process watchdog timer.
|
||||||
|
constexpr unsigned int kAlarmSignalDelaySeconds = 5;
|
||||||
|
alarm(kAlarmSignalDelaySeconds);
|
||||||
|
#endif // !BUILDFLAG(IS_LINUX)
|
||||||
}
|
}
|
||||||
|
|
||||||
class PrintBacktraceOutputHandler : public BacktraceOutputHandler {
|
class PrintBacktraceOutputHandler : public BacktraceOutputHandler {
|
||||||
|
@ -668,7 +668,12 @@ FeatureList::OverrideState FeatureList::GetOverrideState(
|
|||||||
const Feature& feature) const {
|
const Feature& feature) const {
|
||||||
DCHECK(initialized_);
|
DCHECK(initialized_);
|
||||||
DCHECK(IsValidFeatureOrFieldTrialName(feature.name)) << feature.name;
|
DCHECK(IsValidFeatureOrFieldTrialName(feature.name)) << feature.name;
|
||||||
DCHECK(CheckFeatureIdentity(feature)) << feature.name;
|
DCHECK(CheckFeatureIdentity(feature))
|
||||||
|
<< feature.name
|
||||||
|
<< " has multiple definitions. Either it is defined more than once in "
|
||||||
|
"code or (for component builds) the code is built into multiple "
|
||||||
|
"components (shared libraries) without a corresponding export "
|
||||||
|
"statement";
|
||||||
|
|
||||||
// If caching is disabled, always perform the full lookup.
|
// If caching is disabled, always perform the full lookup.
|
||||||
if (!g_cache_override_state)
|
if (!g_cache_override_state)
|
||||||
|
@ -13,7 +13,7 @@ namespace base::features {
|
|||||||
// backed by executable files.
|
// backed by executable files.
|
||||||
BASE_FEATURE(kEnforceNoExecutableFileHandles,
|
BASE_FEATURE(kEnforceNoExecutableFileHandles,
|
||||||
"EnforceNoExecutableFileHandles",
|
"EnforceNoExecutableFileHandles",
|
||||||
FEATURE_DISABLED_BY_DEFAULT);
|
FEATURE_ENABLED_BY_DEFAULT);
|
||||||
|
|
||||||
// Optimizes parsing and loading of data: URLs.
|
// Optimizes parsing and loading of data: URLs.
|
||||||
BASE_FEATURE(kOptimizeDataUrls, "OptimizeDataUrls", FEATURE_ENABLED_BY_DEFAULT);
|
BASE_FEATURE(kOptimizeDataUrls, "OptimizeDataUrls", FEATURE_ENABLED_BY_DEFAULT);
|
||||||
|
@ -75,9 +75,7 @@ class BASE_EXPORT FileDescriptorWatcher {
|
|||||||
// Controller is deleted, ownership of |watcher_| is transfered to a delete
|
// Controller is deleted, ownership of |watcher_| is transfered to a delete
|
||||||
// task posted to the MessageLoopForIO. This ensures that |watcher_| isn't
|
// task posted to the MessageLoopForIO. This ensures that |watcher_| isn't
|
||||||
// deleted while it is being used by the MessageLoopForIO.
|
// deleted while it is being used by the MessageLoopForIO.
|
||||||
//
|
raw_ptr<Watcher, DanglingUntriaged> watcher_;
|
||||||
// TODO(crbug.com/1298696): Breaks base_unittests.
|
|
||||||
raw_ptr<Watcher, DanglingUntriagedDegradeToNoOpWhenMTE> watcher_;
|
|
||||||
|
|
||||||
// An event for the watcher to notify controller that it's destroyed.
|
// An event for the watcher to notify controller that it's destroyed.
|
||||||
// As the |watcher_| is owned by Controller, always outlives the Watcher.
|
// As the |watcher_| is owned by Controller, always outlives the Watcher.
|
||||||
|
@ -350,9 +350,9 @@ class BASE_EXPORT FilePath {
|
|||||||
// Returns a FilePath by appending a separator and the supplied path
|
// Returns a FilePath by appending a separator and the supplied path
|
||||||
// component to this object's path. Append takes care to avoid adding
|
// component to this object's path. Append takes care to avoid adding
|
||||||
// excessive separators if this object's path already ends with a separator.
|
// excessive separators if this object's path already ends with a separator.
|
||||||
// If this object's path is kCurrentDirectory, a new FilePath corresponding
|
// If this object's path is kCurrentDirectory ('.'), a new FilePath
|
||||||
// only to |component| is returned. |component| must be a relative path;
|
// corresponding only to |component| is returned. |component| must be a
|
||||||
// it is an error to pass an absolute path.
|
// relative path; it is an error to pass an absolute path.
|
||||||
[[nodiscard]] FilePath Append(StringPieceType component) const;
|
[[nodiscard]] FilePath Append(StringPieceType component) const;
|
||||||
[[nodiscard]] FilePath Append(const FilePath& component) const;
|
[[nodiscard]] FilePath Append(const FilePath& component) const;
|
||||||
[[nodiscard]] FilePath Append(const SafeBaseName& component) const;
|
[[nodiscard]] FilePath Append(const SafeBaseName& component) const;
|
||||||
|
@ -46,11 +46,11 @@ class BASE_EXPORT FilePathWatcher {
|
|||||||
// within the directory are watched.
|
// within the directory are watched.
|
||||||
kRecursive,
|
kRecursive,
|
||||||
|
|
||||||
#if BUILDFLAG(IS_MAC)
|
#if BUILDFLAG(IS_APPLE)
|
||||||
// Indicates that the watcher should watch the given path only (neither
|
// Indicates that the watcher should watch the given path only (neither
|
||||||
// ancestors nor descendants). The watch fails if the path does not exist.
|
// ancestors nor descendants). The watch fails if the path does not exist.
|
||||||
kTrivial,
|
kTrivial,
|
||||||
#endif // BUILDFLAG(IS_MAC)
|
#endif // BUILDFLAG(IS_APPLE)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flags are a generalization of |Type|. They are used in the new
|
// Flags are a generalization of |Type|. They are used in the new
|
||||||
|
@ -390,14 +390,24 @@ bool IsPathSafeToSetAclOn(const FilePath& path) {
|
|||||||
if (g_extra_allowed_path_for_no_execute) {
|
if (g_extra_allowed_path_for_no_execute) {
|
||||||
valid_paths.push_back(g_extra_allowed_path_for_no_execute);
|
valid_paths.push_back(g_extra_allowed_path_for_no_execute);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MakeLongFilePath is needed here because temp files can have an 8.3 path
|
||||||
|
// under certain conditions. See comments in base::MakeLongFilePath.
|
||||||
|
base::FilePath long_path = base::MakeLongFilePath(path);
|
||||||
|
DCHECK(!long_path.empty()) << "Cannot get long path for " << path;
|
||||||
|
|
||||||
for (const auto path_type : valid_paths) {
|
for (const auto path_type : valid_paths) {
|
||||||
base::FilePath valid_path;
|
base::FilePath valid_path;
|
||||||
if (base::PathService::Get(path_type, &valid_path)) {
|
if (!base::PathService::Get(path_type, &valid_path)) {
|
||||||
// Temp files can sometimes have an 8.3 path. See comments in
|
DLOG(FATAL) << "Cannot get path for pathservice key " << path_type;
|
||||||
// base::MakeLongFilePath.
|
continue;
|
||||||
if (base::MakeLongFilePath(valid_path).IsParent(path)) {
|
}
|
||||||
return true;
|
// Temp files can sometimes have an 8.3 path. See comments in
|
||||||
}
|
// base::MakeLongFilePath.
|
||||||
|
base::FilePath full_path = base::MakeLongFilePath(valid_path);
|
||||||
|
DCHECK(!full_path.empty()) << "Cannot get long path for " << valid_path;
|
||||||
|
if (full_path.IsParent(long_path)) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1100,9 +1110,7 @@ bool PreventExecuteMapping(const FilePath& path) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeLongFilePath is needed here because temp files can have an 8.3 path
|
bool is_path_safe = IsPathSafeToSetAclOn(path);
|
||||||
// under certain conditions. See comments in base::MakeLongFilePath.
|
|
||||||
bool is_path_safe = IsPathSafeToSetAclOn(base::MakeLongFilePath(path));
|
|
||||||
|
|
||||||
if (!is_path_safe) {
|
if (!is_path_safe) {
|
||||||
// To mitigate the effect of past OS bugs where attackers are able to use
|
// To mitigate the effect of past OS bugs where attackers are able to use
|
||||||
@ -1137,7 +1145,7 @@ bool PreventExecuteMapping(const FilePath& path) {
|
|||||||
// dangerous path is being passed to a renderer, which is inherently unsafe.
|
// dangerous path is being passed to a renderer, which is inherently unsafe.
|
||||||
//
|
//
|
||||||
// If this check hits, please do not ignore it but consult security team.
|
// If this check hits, please do not ignore it but consult security team.
|
||||||
NOTREACHED() << "Unsafe to deny execute access to path : " << path;
|
DLOG(FATAL) << "Unsafe to deny execute access to path : " << path;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -457,6 +457,16 @@ void File::DoInitialize(const FilePath& path, uint32_t flags) {
|
|||||||
else if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE))
|
else if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE))
|
||||||
created_ = true;
|
created_ = true;
|
||||||
if (flags & FLAG_WIN_NO_EXECUTE) {
|
if (flags & FLAG_WIN_NO_EXECUTE) {
|
||||||
|
// These two DCHECKs make sure that no callers are trying to remove
|
||||||
|
// execute permission from a file that might need to be mapped executable
|
||||||
|
// later. If they hit in code then the file should not have
|
||||||
|
// FLAG_WIN_NO_EXECUTE flag, but this will mean that the file cannot be
|
||||||
|
// passed to renderers.
|
||||||
|
DCHECK(!base::FilePath::CompareEqualIgnoreCase(FILE_PATH_LITERAL(".exe"),
|
||||||
|
path.Extension()));
|
||||||
|
DCHECK(!base::FilePath::CompareEqualIgnoreCase(FILE_PATH_LITERAL(".dll"),
|
||||||
|
path.Extension()));
|
||||||
|
|
||||||
// It is possible that the ACE could not be added if the file was created
|
// It is possible that the ACE could not be added if the file was created
|
||||||
// in a path for which the caller does not have WRITE_DAC access. In this
|
// in a path for which the caller does not have WRITE_DAC access. In this
|
||||||
// case, ignore the error since if this is occurring then it's likely the
|
// case, ignore the error since if this is occurring then it's likely the
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user