summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/external_resources/ymake/public.resources.json10
-rw-r--r--build/external_resources/ymake/resources.json10
-rw-r--r--build/mapping.conf.json10
-rw-r--r--build/platform/mold/mold.json16
-rw-r--r--build/platform/mold/ya.make13
-rw-r--r--build/plugins/_dart_fields.py36
-rw-r--r--build/plugins/lib/test_const/__init__.py1
-rw-r--r--build/plugins/ytest.py1
-rw-r--r--build/sysincl/darwin.yml1
-rw-r--r--build/ymake.core.conf33
-rw-r--r--contrib/libs/clang14-rt/lib/asan/ya.make2
-rw-r--r--contrib/libs/clang14-rt/lib/asan_cxx/ya.make2
-rw-r--r--contrib/libs/clang14-rt/lib/asan_static/ya.make2
-rw-r--r--contrib/libs/clang14-rt/lib/msan/ya.make2
-rw-r--r--contrib/libs/clang14-rt/lib/msan_cxx/ya.make2
-rw-r--r--contrib/libs/clang14-rt/lib/tsan/ya.make2
-rw-r--r--contrib/libs/clang14-rt/lib/tsan_cxx/ya.make2
-rw-r--r--contrib/libs/clang18-rt/lib/asan/ya.make2
-rw-r--r--contrib/libs/clang18-rt/lib/asan_cxx/ya.make2
-rw-r--r--contrib/libs/clang18-rt/lib/asan_static/ya.make2
-rw-r--r--contrib/libs/clang18-rt/lib/msan/ya.make2
-rw-r--r--contrib/libs/clang18-rt/lib/msan_cxx/ya.make2
-rw-r--r--contrib/libs/clang18-rt/lib/profile/ya.make2
-rw-r--r--contrib/libs/clang18-rt/lib/tsan/ya.make2
-rw-r--r--contrib/libs/clang18-rt/lib/tsan_cxx/ya.make2
-rw-r--r--contrib/libs/cxxsupp/builtins/.yandex_meta/build.ym2
-rw-r--r--contrib/libs/cxxsupp/builtins/.yandex_meta/devtools.licenses.report20
-rw-r--r--contrib/libs/cxxsupp/builtins/CODE_OWNERS.TXT8
-rw-r--r--contrib/libs/cxxsupp/builtins/README.txt5
-rw-r--r--contrib/libs/cxxsupp/builtins/aarch64/sme-abi-vg.c21
-rw-r--r--contrib/libs/cxxsupp/builtins/aarch64/sme-abi.S78
-rw-r--r--contrib/libs/cxxsupp/builtins/aarch64/sme-libc-mem-routines.S352
-rw-r--r--contrib/libs/cxxsupp/builtins/aarch64/sme-libc-routines.c77
-rw-r--r--contrib/libs/cxxsupp/builtins/atomic.c14
-rw-r--r--contrib/libs/cxxsupp/builtins/cpu_model/AArch64CPUFeatures.inc91
-rw-r--r--contrib/libs/cxxsupp/builtins/cpu_model/aarch64.c70
-rw-r--r--contrib/libs/cxxsupp/builtins/cpu_model/aarch64.h21
-rw-r--r--contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/android.inc4
-rw-r--r--contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/apple.inc174
-rw-r--r--contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/freebsd.inc4
-rw-r--r--contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/fuchsia.inc8
-rw-r--r--contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/mrs.inc135
-rw-r--r--contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/sysauxv.inc4
-rw-r--r--contrib/libs/cxxsupp/builtins/cpu_model/aarch64/hwcap.inc6
-rw-r--r--contrib/libs/cxxsupp/builtins/cpu_model/x86.c296
-rw-r--r--contrib/libs/cxxsupp/builtins/divtc3.c2
-rw-r--r--contrib/libs/cxxsupp/builtins/extendbfsf2.c13
-rw-r--r--contrib/libs/cxxsupp/builtins/fp_add_impl.inc2
-rw-r--r--contrib/libs/cxxsupp/builtins/fp_extend.h26
-rw-r--r--contrib/libs/cxxsupp/builtins/fp_fixint_impl.inc4
-rw-r--r--contrib/libs/cxxsupp/builtins/fp_lib.h17
-rw-r--r--contrib/libs/cxxsupp/builtins/int_types.h4
-rw-r--r--contrib/libs/cxxsupp/builtins/multc3.c2
-rw-r--r--contrib/libs/cxxsupp/builtins/os_version_check.c4
-rw-r--r--contrib/libs/cxxsupp/builtins/riscv/restore.S4
-rw-r--r--contrib/libs/cxxsupp/builtins/riscv/save.S4
-rw-r--r--contrib/libs/cxxsupp/builtins/trampoline_setup.c42
-rw-r--r--contrib/libs/cxxsupp/builtins/ya.make9
-rw-r--r--contrib/libs/cxxsupp/libcxxrt/exception.cc6
-rw-r--r--contrib/libs/cxxsupp/libsan/ya.make2
-rw-r--r--contrib/restricted/aws/aws-c-auth/.yandex_meta/__init__.py14
-rw-r--r--contrib/restricted/aws/aws-c-auth/.yandex_meta/devtools.copyrights.report6
-rw-r--r--contrib/restricted/aws/aws-c-auth/.yandex_meta/devtools.licenses.report6
-rw-r--r--contrib/restricted/aws/aws-c-auth/.yandex_meta/override.nix4
-rw-r--r--contrib/restricted/aws/aws-c-auth/include/aws/auth/auth.h4
-rw-r--r--contrib/restricted/aws/aws-c-auth/include/aws/auth/credentials.h68
-rw-r--r--contrib/restricted/aws/aws-c-auth/include/aws/auth/private/credentials_utils.h12
-rw-r--r--contrib/restricted/aws/aws-c-auth/include/aws/auth/private/sso_token_providers.h112
-rw-r--r--contrib/restricted/aws/aws-c-auth/include/aws/auth/private/sso_token_utils.h58
-rw-r--r--contrib/restricted/aws/aws-c-auth/source/auth.c12
-rw-r--r--contrib/restricted/aws/aws-c-auth/source/aws_imds_client.c2
-rw-r--r--contrib/restricted/aws/aws-c-auth/source/credentials.c184
-rw-r--r--contrib/restricted/aws/aws-c-auth/source/credentials_provider_ecs.c2
-rw-r--r--contrib/restricted/aws/aws-c-auth/source/credentials_provider_process.c4
-rw-r--r--contrib/restricted/aws/aws-c-auth/source/credentials_provider_sso.c851
-rw-r--r--contrib/restricted/aws/aws-c-auth/source/credentials_utils.c71
-rw-r--r--contrib/restricted/aws/aws-c-auth/source/sso_token_utils.c160
-rw-r--r--contrib/restricted/aws/aws-c-auth/source/token_provider_sso_profile.c186
-rw-r--r--contrib/restricted/aws/aws-c-auth/source/token_provider_sso_session.c251
-rw-r--r--contrib/restricted/aws/aws-c-auth/ya.make14
-rw-r--r--library/cpp/netliba/socket/creators.cpp2
-rw-r--r--library/cpp/sanitizer/address/static/ya.make2
-rw-r--r--library/cpp/sanitizer/memory/static/ya.make2
-rw-r--r--library/cpp/sanitizer/thread/static/ya.make2
-rw-r--r--library/cpp/testing/dump_clang_coverage/write_profile_data.cpp125
-rw-r--r--library/cpp/testing/dump_clang_coverage/ya.make13
-rw-r--r--ydb/ci/rightlib.txt2
-rw-r--r--yql/essentials/tests/sql/sql2yql/canondata/result.json12
-rw-r--r--yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_hor_join-yql19332_aux_cols_/formatted.sql20
-rw-r--r--yql/essentials/tests/sql/suites/hor_join/yql19332_aux_cols.cfg3
-rw-r--r--yql/essentials/tests/sql/suites/hor_join/yql19332_aux_cols.sql9
-rw-r--r--yt/yql/providers/yt/provider/yql_yt_horizontal_join.cpp2
-rw-r--r--yt/yql/providers/yt/provider/yql_yt_physical_finalizing.cpp7
-rw-r--r--yt/yt/core/misc/proc.cpp31
-rw-r--r--yt/yt/core/misc/proc.h3
-rw-r--r--yt/yt/core/net/connection.cpp9
-rw-r--r--yt/yt/core/ytree/unittests/yson_struct_ut.cpp70
-rw-r--r--yt/yt/core/ytree/yson_struct-inl.h5
-rw-r--r--yt/yt/core/ytree/yson_struct.h2
-rw-r--r--yt/yt/core/ytree/yson_struct_detail-inl.h71
-rw-r--r--yt/yt/core/ytree/yson_struct_detail.h8
-rw-r--r--yt/yt/library/process/unittests/pipes_ut.cpp20
102 files changed, 3597 insertions, 536 deletions
diff --git a/build/external_resources/ymake/public.resources.json b/build/external_resources/ymake/public.resources.json
index da903b8c73a..a8a76e1b078 100644
--- a/build/external_resources/ymake/public.resources.json
+++ b/build/external_resources/ymake/public.resources.json
@@ -1,19 +1,19 @@
{
"by_platform": {
"darwin": {
- "uri": "sbr:7522713648"
+ "uri": "sbr:7570915389"
},
"darwin-arm64": {
- "uri": "sbr:7522713246"
+ "uri": "sbr:7570915039"
},
"linux": {
- "uri": "sbr:7522714449"
+ "uri": "sbr:7570916388"
},
"linux-aarch64": {
- "uri": "sbr:7522712750"
+ "uri": "sbr:7570914495"
},
"win32-clang-cl": {
- "uri": "sbr:7522714072"
+ "uri": "sbr:7570915900"
}
}
}
diff --git a/build/external_resources/ymake/resources.json b/build/external_resources/ymake/resources.json
index a3ccd61239e..de7de32951a 100644
--- a/build/external_resources/ymake/resources.json
+++ b/build/external_resources/ymake/resources.json
@@ -1,19 +1,19 @@
{
"by_platform": {
"darwin": {
- "uri": "sbr:7522728679"
+ "uri": "sbr:7570909413"
},
"darwin-arm64": {
- "uri": "sbr:7522728262"
+ "uri": "sbr:7570909172"
},
"linux": {
- "uri": "sbr:7522729575"
+ "uri": "sbr:7570910246"
},
"linux-aarch64": {
- "uri": "sbr:7522727825"
+ "uri": "sbr:7570908880"
},
"win32-clang-cl": {
- "uri": "sbr:7522729138"
+ "uri": "sbr:7570909765"
}
}
}
diff --git a/build/mapping.conf.json b/build/mapping.conf.json
index f555d8c72cf..e0f4f906c7e 100644
--- a/build/mapping.conf.json
+++ b/build/mapping.conf.json
@@ -624,6 +624,7 @@
"7448914799": "https://devtools-registry.s3.yandex.net/7448914799",
"7478218557": "https://devtools-registry.s3.yandex.net/7478218557",
"7522713648": "https://devtools-registry.s3.yandex.net/7522713648",
+ "7570915389": "https://devtools-registry.s3.yandex.net/7570915389",
"5766171800": "https://devtools-registry.s3.yandex.net/5766171800",
"5805430761": "https://devtools-registry.s3.yandex.net/5805430761",
"5829025456": "https://devtools-registry.s3.yandex.net/5829025456",
@@ -677,6 +678,7 @@
"7448913101": "https://devtools-registry.s3.yandex.net/7448913101",
"7478218228": "https://devtools-registry.s3.yandex.net/7478218228",
"7522713246": "https://devtools-registry.s3.yandex.net/7522713246",
+ "7570915039": "https://devtools-registry.s3.yandex.net/7570915039",
"5766173070": "https://devtools-registry.s3.yandex.net/5766173070",
"5805432830": "https://devtools-registry.s3.yandex.net/5805432830",
"5829031598": "https://devtools-registry.s3.yandex.net/5829031598",
@@ -730,6 +732,7 @@
"7448917907": "https://devtools-registry.s3.yandex.net/7448917907",
"7478219259": "https://devtools-registry.s3.yandex.net/7478219259",
"7522714449": "https://devtools-registry.s3.yandex.net/7522714449",
+ "7570916388": "https://devtools-registry.s3.yandex.net/7570916388",
"5766171341": "https://devtools-registry.s3.yandex.net/5766171341",
"5805430188": "https://devtools-registry.s3.yandex.net/5805430188",
"5829023352": "https://devtools-registry.s3.yandex.net/5829023352",
@@ -783,6 +786,7 @@
"7448911598": "https://devtools-registry.s3.yandex.net/7448911598",
"7478218007": "https://devtools-registry.s3.yandex.net/7478218007",
"7522712750": "https://devtools-registry.s3.yandex.net/7522712750",
+ "7570914495": "https://devtools-registry.s3.yandex.net/7570914495",
"5766172695": "https://devtools-registry.s3.yandex.net/5766172695",
"5805432230": "https://devtools-registry.s3.yandex.net/5805432230",
"5829029743": "https://devtools-registry.s3.yandex.net/5829029743",
@@ -836,6 +840,7 @@
"7448916360": "https://devtools-registry.s3.yandex.net/7448916360",
"7478218861": "https://devtools-registry.s3.yandex.net/7478218861",
"7522714072": "https://devtools-registry.s3.yandex.net/7522714072",
+ "7570915900": "https://devtools-registry.s3.yandex.net/7570915900",
"4307890075": "https://devtools-registry.s3.yandex.net/4307890075",
"5517245192": "https://devtools-registry.s3.yandex.net/5517245192",
"4307901240": "https://devtools-registry.s3.yandex.net/4307901240",
@@ -1690,6 +1695,7 @@
"7448914799": "devtools/ymake/bin/ymake for darwin",
"7478218557": "devtools/ymake/bin/ymake for darwin",
"7522713648": "devtools/ymake/bin/ymake for darwin",
+ "7570915389": "devtools/ymake/bin/ymake for darwin",
"5766171800": "devtools/ymake/bin/ymake for darwin-arm64",
"5805430761": "devtools/ymake/bin/ymake for darwin-arm64",
"5829025456": "devtools/ymake/bin/ymake for darwin-arm64",
@@ -1743,6 +1749,7 @@
"7448913101": "devtools/ymake/bin/ymake for darwin-arm64",
"7478218228": "devtools/ymake/bin/ymake for darwin-arm64",
"7522713246": "devtools/ymake/bin/ymake for darwin-arm64",
+ "7570915039": "devtools/ymake/bin/ymake for darwin-arm64",
"5766173070": "devtools/ymake/bin/ymake for linux",
"5805432830": "devtools/ymake/bin/ymake for linux",
"5829031598": "devtools/ymake/bin/ymake for linux",
@@ -1796,6 +1803,7 @@
"7448917907": "devtools/ymake/bin/ymake for linux",
"7478219259": "devtools/ymake/bin/ymake for linux",
"7522714449": "devtools/ymake/bin/ymake for linux",
+ "7570916388": "devtools/ymake/bin/ymake for linux",
"5766171341": "devtools/ymake/bin/ymake for linux-aarch64",
"5805430188": "devtools/ymake/bin/ymake for linux-aarch64",
"5829023352": "devtools/ymake/bin/ymake for linux-aarch64",
@@ -1849,6 +1857,7 @@
"7448911598": "devtools/ymake/bin/ymake for linux-aarch64",
"7478218007": "devtools/ymake/bin/ymake for linux-aarch64",
"7522712750": "devtools/ymake/bin/ymake for linux-aarch64",
+ "7570914495": "devtools/ymake/bin/ymake for linux-aarch64",
"5766172695": "devtools/ymake/bin/ymake for win32-clang-cl",
"5805432230": "devtools/ymake/bin/ymake for win32-clang-cl",
"5829029743": "devtools/ymake/bin/ymake for win32-clang-cl",
@@ -1902,6 +1911,7 @@
"7448916360": "devtools/ymake/bin/ymake for win32-clang-cl",
"7478218861": "devtools/ymake/bin/ymake for win32-clang-cl",
"7522714072": "devtools/ymake/bin/ymake for win32-clang-cl",
+ "7570915900": "devtools/ymake/bin/ymake for win32-clang-cl",
"4307890075": "flake8_linter for linux",
"5517245192": "flake8_linter for linux",
"4307901240": "flake8_linter for linux-aarch64",
diff --git a/build/platform/mold/mold.json b/build/platform/mold/mold.json
new file mode 100644
index 00000000000..ee314b2a2e0
--- /dev/null
+++ b/build/platform/mold/mold.json
@@ -0,0 +1,16 @@
+{
+ "by_platform": {
+ "darwin-arm64": {
+ "uri": "sbr:7421008516"
+ },
+ "darwin-x86_64": {
+ "uri": "sbr:7421180051"
+ },
+ "linux-aarch64": {
+ "uri": "sbr:7421207790"
+ },
+ "linux-x86_64": {
+ "uri": "sbr:7421606584"
+ }
+ }
+}
diff --git a/build/platform/mold/ya.make b/build/platform/mold/ya.make
new file mode 100644
index 00000000000..2d5f8cde455
--- /dev/null
+++ b/build/platform/mold/ya.make
@@ -0,0 +1,13 @@
+RESOURCES_LIBRARY()
+
+TOOLCHAIN(mold)
+VERSION(2.34.1)
+
+DECLARE_EXTERNAL_HOST_RESOURCES_BUNDLE_BY_JSON(MOLD_ROOT mold.json)
+
+LDFLAGS(
+ -fuse-ld=mold
+ --ld-path=${MOLD_ROOT_RESOURCE_GLOBAL}/bin/ld.mold
+)
+
+END()
diff --git a/build/plugins/_dart_fields.py b/build/plugins/_dart_fields.py
index aa1b5d9a161..eb5a0baa759 100644
--- a/build/plugins/_dart_fields.py
+++ b/build/plugins/_dart_fields.py
@@ -611,15 +611,37 @@ class LintConfigs:
def cpp_configs(cls, unit, flat_args, spec_args):
custom_config = spec_args.get('CUSTOM_CONFIG')
if custom_config:
+ # TODO delete CUSTOM_CONFIG, it's used only by arc
config = custom_config[0]
assert_file_exists(unit, config)
- else:
- # file with default configs
- config = spec_args.get('CONFIGS')[0]
- assert_file_exists(unit, config)
- name = spec_args['NAME'][0]
- config = get_linter_configs(unit, config)[name]
- assert_file_exists(unit, config)
+ return {cls.KEY: serialize_list([config])}
+ linter_name = spec_args['NAME'][0]
+ if config_type := spec_args.get('CONFIG_TYPE'):
+ config_type = config_type[0]
+ if config_type not in consts.LINTER_CONFIG_TYPES[linter_name]:
+ message = "Unknown CPP linter config type: {}. Allowed types: {}".format(
+ config_type, ', '.join(consts.LINTER_CONFIG_TYPES[linter_name])
+ )
+ ymake.report_configure_error(message)
+ raise DartValueError()
+ if common_configs_dir := unit.get('MODULE_COMMON_CONFIGS_DIR'):
+ config = os.path.join(common_configs_dir, config_type)
+ path = unit.resolve(config)
+ if os.path.exists(path):
+ config = _common.strip_roots(config)
+ return {cls.KEY: serialize_list([config])}
+ message = "File not found: {}".format(path)
+ ymake.report_configure_error(message)
+ raise DartValueError()
+ else:
+ message = "Config type specifier is only allowed with autoincludes"
+ ymake.report_configure_error(message)
+ raise DartValueError()
+ # default config
+ config = spec_args.get('CONFIGS')[0]
+ assert_file_exists(unit, config)
+ config = get_linter_configs(unit, config)[linter_name]
+ assert_file_exists(unit, config)
return {cls.KEY: serialize_list([config])}
diff --git a/build/plugins/lib/test_const/__init__.py b/build/plugins/lib/test_const/__init__.py
index 02c3c5313ad..cc2536d6fed 100644
--- a/build/plugins/lib/test_const/__init__.py
+++ b/build/plugins/lib/test_const/__init__.py
@@ -437,6 +437,7 @@ class ServiceTags(Enum):
AnyTag = "ya:anytag"
+# Linter names must match `NAME` set in `_ADD_*_LINTER_CHECK`
class PythonLinterName(Enum):
Black = "black"
DummyLinter = "dummy_linter"
diff --git a/build/plugins/ytest.py b/build/plugins/ytest.py
index 33eeac4403f..dd540baf829 100644
--- a/build/plugins/ytest.py
+++ b/build/plugins/ytest.py
@@ -1014,6 +1014,7 @@ def on_add_cpp_linter_check(fields, unit, *args):
"GLOBAL_RESOURCES": unlimited,
"FILE_PROCESSING_TIME": 1,
"EXTRA_PARAMS": unlimited,
+ "CONFIG_TYPE": 1,
}
_, spec_args = _common.sort_by_keywords(keywords, args)
diff --git a/build/sysincl/darwin.yml b/build/sysincl/darwin.yml
index 06eaa50480f..d583225dfad 100644
--- a/build/sysincl/darwin.yml
+++ b/build/sysincl/darwin.yml
@@ -37,6 +37,7 @@
- MacTypes.h
- TargetConditionals.h
- architecture/byte_order.h
+ - arm/cpu_capabilities_public.h
- asl.h
- copyfile.h
- crt_externs.h
diff --git a/build/ymake.core.conf b/build/ymake.core.conf
index 3fe44f55fe8..a2fa9450cca 100644
--- a/build/ymake.core.conf
+++ b/build/ymake.core.conf
@@ -2358,7 +2358,7 @@ multimodule PACKAGE {
.USE_PEERS_LATE_OUTS=yes
.PEERDIR_POLICY=as_build_from
.FINAL_TARGET=yes
- SET(PEERDIR_TAGS CPP_PROTO CPP_PROTO_FROM_SCHEMA CPP_FBS PY2 PY3 PY2_NATIVE PY3_NATIVE YQL_UDF_SHARED __EMPTY__ RESOURCE_LIB DOCSBOOK JAR_RUNNABLE PY3_BIN PY3TEST_PROGRAM DLL GO_PROGRAM PACKAGE_UNION)
+ SET(PEERDIR_TAGS CPP_PROTO CPP_PROTO_FROM_SCHEMA CPP_FBS PY2 PY3 PY2_NATIVE PY3_NATIVE YQL_UDF_SHARED __EMPTY__ RESOURCE_LIB DOCSBOOK JAR_RUNNABLE PY3_BIN PY3TEST_PROGRAM DLL GO_PROGRAM TS PACKAGE_UNION)
SET(MODULE_SUFFIX .final.pkg.fake)
SET(DONT_RESOLVE_INCLUDES yes)
@@ -2376,7 +2376,7 @@ multimodule PACKAGE {
.IGNORED=VCS_INFO_FILE
SET(MODULE_SUFFIX .pkg.fake)
- SET(PEERDIR_TAGS CPP_PROTO CPP_PROTO_FROM_SCHEMA CPP_FBS PY2 PY3 PY2_NATIVE PY3_NATIVE YQL_UDF_SHARED __EMPTY__ RESOURCE_LIB DOCSBOOK JAR_RUNNABLE PY3_BIN PY3TEST_PROGRAM DLL GO_PROGRAM PACKAGE_UNION)
+ SET(PEERDIR_TAGS CPP_PROTO CPP_PROTO_FROM_SCHEMA CPP_FBS PY2 PY3 PY2_NATIVE PY3_NATIVE YQL_UDF_SHARED __EMPTY__ RESOURCE_LIB DOCSBOOK JAR_RUNNABLE PY3_BIN PY3TEST_PROGRAM DLL GO_PROGRAM TS PACKAGE_UNION)
DISABLE(START_TARGET)
SET(_COPY_FILE_CONTEXT TEXT)
@@ -2423,7 +2423,7 @@ module UNION: _BASE_UNIT {
SET(MODULE_SUFFIX .pkg.fake)
SET(DONT_RESOLVE_INCLUDES yes)
SET(NEED_PLATFORM_PEERDIRS no)
- PEERDIR_TAGS=CPP_PROTO CPP_PROTO_FROM_SCHEMA CPP_FBS PY2 PY2_NATIVE PY3_NATIVE YQL_UDF_SHARED __EMPTY__ RESOURCE_LIB DOCSBOOK JAR_RUNNABLE PY3_BIN DLL PACKAGE_UNION
+ PEERDIR_TAGS=CPP_PROTO CPP_PROTO_FROM_SCHEMA CPP_FBS PY2 PY2_NATIVE PY3_NATIVE YQL_UDF_SHARED __EMPTY__ RESOURCE_LIB DOCSBOOK JAR_RUNNABLE PY3_BIN DLL TS PACKAGE_UNION
UNION_OUTS=${hide;late_out:AUTO_INPUT}
when ($_UNION_EXPLICIT_OUTPUTS) {
@@ -3125,9 +3125,26 @@ macro _SRC("ssqls", SRC, SRCFLAGS...) {
.CMD=${tool:"metrika/core/tools/ssqls"} ${input;notransformbuilddir:SRC} -S $ARCADIA_ROOT -B $ARCADIA_BUILD_ROOT $SRCFLAGS ${output;noext;hide:SRC.cpp} ${output;noext;hide:SRC.h} ${hide;kv:"p SS"} ${hide;kv:"pc yellow"}
}
+macro _SRC_f_new(SRC, SRCFLAGS...) {
+ .CMD=${tool:"build/platform/flang"} -c ${input:SRC} -o ${output:SRC.o} ${hide;kv:"p FL"} ${hide;kv:"pc light-green"}
+}
+
+macro _SRC_f_old(SRC, SRCFLAGS...) {
+ .CMD=$YMAKE_PYTHON ${input:"build/scripts/f2c.py"} -t ${tool:"contrib/tools/f2c"} -c ${input:SRC} -o ${output:SRC.c} ${hide;output_include:"f2c.h"} ${hide;kv:"p FT"} ${hide;kv:"pc light-green"}
+}
+
+USE_FLANG=no
+
+when ($USE_FLANG == "yes") {
+ _SRC_FLANG=$_SRC_f_new($SRC, $SRCFLAGS)
+}
+otherwise {
+ _SRC_FLANG=$_SRC_f_old($SRC, $SRCFLAGS)
+}
+
# tag:src-processing
macro _SRC("f", SRC, SRCFLAGS...) {
- .CMD=$YMAKE_PYTHON ${input:"build/scripts/f2c.py"} -t ${tool:"contrib/tools/f2c"} -c ${input:SRC} -o ${output:SRC.c} ${hide;output_include:"f2c.h"} ${hide;kv:"p FT"} ${hide;kv:"pc light-green"}
+ .CMD=$_SRC_FLANG
.PEERDIR=contrib/libs/libf2c
.ADDINCL=contrib/libs/libf2c
}
@@ -5837,7 +5854,7 @@ macro _STYLE_CPP(CONFIG...) {
}
# tag:internal
-### @usage: _ADD_CPP_LINTER_CHECK(NAME name LINTER linter [DEPENDS deps] CONFIGS configs_file [GLOBAL_RESOURCES gr] [FILE_PROCESSING_TIME fpt] [EXTRA_PARAMS params] [CUSTOM_CONFIG cc])
+### @usage: _ADD_CPP_LINTER_CHECK(NAME name LINTER linter [DEPENDS deps] CONFIGS configs_file [GLOBAL_RESOURCES gr] [FILE_PROCESSING_TIME fpt] [EXTRA_PARAMS params] [CUSTOM_CONFIG cc] [CONFIG_TYPE ct])
###
### Triggers respective plugin
macro _ADD_CPP_LINTER_CHECK(Args...) {
@@ -5847,12 +5864,12 @@ macro _ADD_CPP_LINTER_CHECK(Args...) {
}
# tag:test
-### @usage STYLE_CPP()
+### @usage STYLE_CPP([CONFIG_TYPE config_type])
###
### Run 'ya tool clang-format' test on all cpp sources and headers of the current module
-macro STYLE_CPP() {
+macro STYLE_CPP(CONFIG_TYPE="") {
.ALLOWED_IN_COMMON=yes
- _ADD_CPP_LINTER_CHECK(NAME clang_format LINTER tools/cpp_style_checker/cpp_style_checker GLOBAL_RESOURCES build/platform/clang/clang-format CONFIGS $CPP_LINTERS_DEFAULT_CONFIGS)
+ _ADD_CPP_LINTER_CHECK(NAME clang_format LINTER tools/cpp_style_checker/cpp_style_checker GLOBAL_RESOURCES build/platform/clang/clang-format CONFIGS $CPP_LINTERS_DEFAULT_CONFIGS CONFIG_TYPE $CONFIG_TYPE)
}
### @usage: HEADERS(<Dirs...> [EXCLUDE patterns...])
diff --git a/contrib/libs/clang14-rt/lib/asan/ya.make b/contrib/libs/clang14-rt/lib/asan/ya.make
index 981e911a745..c3cd19e360f 100644
--- a/contrib/libs/clang14-rt/lib/asan/ya.make
+++ b/contrib/libs/clang14-rt/lib/asan/ya.make
@@ -15,8 +15,6 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-SUBSCRIBER(g:cpp-contrib)
-
ADDINCL(
contrib/libs/clang14-rt/lib
)
diff --git a/contrib/libs/clang14-rt/lib/asan_cxx/ya.make b/contrib/libs/clang14-rt/lib/asan_cxx/ya.make
index 9dad0117181..0d46e10dfe8 100644
--- a/contrib/libs/clang14-rt/lib/asan_cxx/ya.make
+++ b/contrib/libs/clang14-rt/lib/asan_cxx/ya.make
@@ -15,8 +15,6 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-SUBSCRIBER(g:cpp-contrib)
-
ADDINCL(
contrib/libs/clang14-rt/lib
)
diff --git a/contrib/libs/clang14-rt/lib/asan_static/ya.make b/contrib/libs/clang14-rt/lib/asan_static/ya.make
index f721a6a6e30..6339dbec829 100644
--- a/contrib/libs/clang14-rt/lib/asan_static/ya.make
+++ b/contrib/libs/clang14-rt/lib/asan_static/ya.make
@@ -15,8 +15,6 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-SUBSCRIBER(g:cpp-contrib)
-
ADDINCL(
contrib/libs/clang14-rt/lib
)
diff --git a/contrib/libs/clang14-rt/lib/msan/ya.make b/contrib/libs/clang14-rt/lib/msan/ya.make
index 67938fa41c0..25dfe3000e1 100644
--- a/contrib/libs/clang14-rt/lib/msan/ya.make
+++ b/contrib/libs/clang14-rt/lib/msan/ya.make
@@ -15,8 +15,6 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-SUBSCRIBER(g:cpp-contrib)
-
ADDINCL(
contrib/libs/clang14-rt/lib
)
diff --git a/contrib/libs/clang14-rt/lib/msan_cxx/ya.make b/contrib/libs/clang14-rt/lib/msan_cxx/ya.make
index af50884296f..ef8af1073f2 100644
--- a/contrib/libs/clang14-rt/lib/msan_cxx/ya.make
+++ b/contrib/libs/clang14-rt/lib/msan_cxx/ya.make
@@ -15,8 +15,6 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-SUBSCRIBER(g:cpp-contrib)
-
ADDINCL(
contrib/libs/clang14-rt/lib
)
diff --git a/contrib/libs/clang14-rt/lib/tsan/ya.make b/contrib/libs/clang14-rt/lib/tsan/ya.make
index 488aa06f7ac..f999fab5763 100644
--- a/contrib/libs/clang14-rt/lib/tsan/ya.make
+++ b/contrib/libs/clang14-rt/lib/tsan/ya.make
@@ -15,8 +15,6 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-SUBSCRIBER(g:cpp-contrib)
-
ADDINCL(
contrib/libs/clang14-rt/lib
)
diff --git a/contrib/libs/clang14-rt/lib/tsan_cxx/ya.make b/contrib/libs/clang14-rt/lib/tsan_cxx/ya.make
index 362b60067c3..d34ca6e4405 100644
--- a/contrib/libs/clang14-rt/lib/tsan_cxx/ya.make
+++ b/contrib/libs/clang14-rt/lib/tsan_cxx/ya.make
@@ -15,8 +15,6 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-SUBSCRIBER(g:cpp-contrib)
-
ADDINCL(
contrib/libs/clang14-rt/lib
)
diff --git a/contrib/libs/clang18-rt/lib/asan/ya.make b/contrib/libs/clang18-rt/lib/asan/ya.make
index df9c2230d8b..b73b1c80816 100644
--- a/contrib/libs/clang18-rt/lib/asan/ya.make
+++ b/contrib/libs/clang18-rt/lib/asan/ya.make
@@ -13,8 +13,6 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-SUBSCRIBER(g:cpp-contrib)
-
VERSION(18.1.8)
ADDINCL(
diff --git a/contrib/libs/clang18-rt/lib/asan_cxx/ya.make b/contrib/libs/clang18-rt/lib/asan_cxx/ya.make
index c3905d6faf0..08e0825cf1a 100644
--- a/contrib/libs/clang18-rt/lib/asan_cxx/ya.make
+++ b/contrib/libs/clang18-rt/lib/asan_cxx/ya.make
@@ -13,8 +13,6 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-SUBSCRIBER(g:cpp-contrib)
-
VERSION(18.1.8)
ADDINCL(
diff --git a/contrib/libs/clang18-rt/lib/asan_static/ya.make b/contrib/libs/clang18-rt/lib/asan_static/ya.make
index 89daf049d96..6187b6e8a78 100644
--- a/contrib/libs/clang18-rt/lib/asan_static/ya.make
+++ b/contrib/libs/clang18-rt/lib/asan_static/ya.make
@@ -13,8 +13,6 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-SUBSCRIBER(g:cpp-contrib)
-
VERSION(18.1.8)
ADDINCL(
diff --git a/contrib/libs/clang18-rt/lib/msan/ya.make b/contrib/libs/clang18-rt/lib/msan/ya.make
index 8089773feb2..54b50bfca3d 100644
--- a/contrib/libs/clang18-rt/lib/msan/ya.make
+++ b/contrib/libs/clang18-rt/lib/msan/ya.make
@@ -13,8 +13,6 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-SUBSCRIBER(g:cpp-contrib)
-
VERSION(18.1.8)
ADDINCL(
diff --git a/contrib/libs/clang18-rt/lib/msan_cxx/ya.make b/contrib/libs/clang18-rt/lib/msan_cxx/ya.make
index bc9beb80ec0..06bbcad52a3 100644
--- a/contrib/libs/clang18-rt/lib/msan_cxx/ya.make
+++ b/contrib/libs/clang18-rt/lib/msan_cxx/ya.make
@@ -13,8 +13,6 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-SUBSCRIBER(g:cpp-contrib)
-
VERSION(18.1.8)
ADDINCL(
diff --git a/contrib/libs/clang18-rt/lib/profile/ya.make b/contrib/libs/clang18-rt/lib/profile/ya.make
index 63ecb242140..685644c6804 100644
--- a/contrib/libs/clang18-rt/lib/profile/ya.make
+++ b/contrib/libs/clang18-rt/lib/profile/ya.make
@@ -13,8 +13,6 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-SUBSCRIBER(g:cpp-contrib)
-
VERSION(18.1.8)
ADDINCL(
diff --git a/contrib/libs/clang18-rt/lib/tsan/ya.make b/contrib/libs/clang18-rt/lib/tsan/ya.make
index 92ce585becd..6900ab53022 100644
--- a/contrib/libs/clang18-rt/lib/tsan/ya.make
+++ b/contrib/libs/clang18-rt/lib/tsan/ya.make
@@ -13,8 +13,6 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-SUBSCRIBER(g:cpp-contrib)
-
VERSION(18.1.8)
ADDINCL(
diff --git a/contrib/libs/clang18-rt/lib/tsan_cxx/ya.make b/contrib/libs/clang18-rt/lib/tsan_cxx/ya.make
index a752c10fb42..6739560227e 100644
--- a/contrib/libs/clang18-rt/lib/tsan_cxx/ya.make
+++ b/contrib/libs/clang18-rt/lib/tsan_cxx/ya.make
@@ -13,8 +13,6 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-SUBSCRIBER(g:cpp-contrib)
-
VERSION(18.1.8)
ADDINCL(
diff --git a/contrib/libs/cxxsupp/builtins/.yandex_meta/build.ym b/contrib/libs/cxxsupp/builtins/.yandex_meta/build.ym
index 20967507889..e454ac162ac 100644
--- a/contrib/libs/cxxsupp/builtins/.yandex_meta/build.ym
+++ b/contrib/libs/cxxsupp/builtins/.yandex_meta/build.ym
@@ -1,6 +1,6 @@
{% extends '//builtin/bag.ym' %}
-{% block current_version %}18.1.8{% endblock %}
+{% block current_version %}19.1.3{% endblock %}
{% block current_url %}
https://github.com/llvm/llvm-project/releases/download/llvmorg-{{self.version().strip()}}/compiler-rt-{{self.version().strip()}}.src.tar.xz
diff --git a/contrib/libs/cxxsupp/builtins/.yandex_meta/devtools.licenses.report b/contrib/libs/cxxsupp/builtins/.yandex_meta/devtools.licenses.report
index ce8fb1f4bb7..874c592edd9 100644
--- a/contrib/libs/cxxsupp/builtins/.yandex_meta/devtools.licenses.report
+++ b/contrib/libs/cxxsupp/builtins/.yandex_meta/devtools.licenses.report
@@ -103,7 +103,9 @@ BELONGS ya.make
aarch64/chkstk.S [1:2]
aarch64/fp_mode.c [3:4]
aarch64/sme-abi-init.c [1:2]
+ aarch64/sme-abi-vg.c [1:2]
aarch64/sme-abi.S [1:2]
+ aarch64/sme-libc-mem-routines.S [1:2]
absvdi2.c [3:4]
absvsi2.c [3:4]
absvti2.c [3:4]
@@ -237,7 +239,9 @@ BELONGS ya.make
comparedf2.c [3:4]
comparesf2.c [3:4]
comparetf2.c [3:4]
+ cpu_model/AArch64CPUFeatures.inc [3:4]
cpu_model/aarch64.c [3:4]
+ cpu_model/aarch64.h [3:4]
cpu_model/cpu_model.h [3:4]
cpu_model/x86.c [3:4]
crtbegin.c [3:4]
@@ -261,6 +265,7 @@ BELONGS ya.make
emutls.c [3:4]
enable_execute_stack.c [3:4]
eprintf.c [3:4]
+ extendbfsf2.c [3:4]
extenddftf2.c [3:4]
extendhfsf2.c [3:4]
extendsfdf2.c [3:4]
@@ -486,7 +491,9 @@ BELONGS ya.make
aarch64/chkstk.S [1:2]
aarch64/fp_mode.c [3:4]
aarch64/sme-abi-init.c [1:2]
+ aarch64/sme-abi-vg.c [1:2]
aarch64/sme-abi.S [1:2]
+ aarch64/sme-libc-mem-routines.S [1:2]
absvdi2.c [3:4]
absvsi2.c [3:4]
absvti2.c [3:4]
@@ -620,7 +627,9 @@ BELONGS ya.make
comparedf2.c [3:4]
comparesf2.c [3:4]
comparetf2.c [3:4]
+ cpu_model/AArch64CPUFeatures.inc [3:4]
cpu_model/aarch64.c [3:4]
+ cpu_model/aarch64.h [3:4]
cpu_model/cpu_model.h [3:4]
cpu_model/x86.c [3:4]
crtbegin.c [3:4]
@@ -644,6 +653,7 @@ BELONGS ya.make
emutls.c [3:4]
enable_execute_stack.c [3:4]
eprintf.c [3:4]
+ extendbfsf2.c [3:4]
extenddftf2.c [3:4]
extendhfsf2.c [3:4]
extendsfdf2.c [3:4]
@@ -927,7 +937,9 @@ BELONGS ya.make
aarch64/chkstk.S [3:3]
aarch64/fp_mode.c [5:5]
aarch64/sme-abi-init.c [3:3]
+ aarch64/sme-abi-vg.c [3:3]
aarch64/sme-abi.S [3:3]
+ aarch64/sme-libc-mem-routines.S [3:3]
absvdi2.c [5:5]
absvsi2.c [5:5]
absvti2.c [5:5]
@@ -1061,7 +1073,9 @@ BELONGS ya.make
comparedf2.c [5:5]
comparesf2.c [5:5]
comparetf2.c [5:5]
+ cpu_model/AArch64CPUFeatures.inc [5:5]
cpu_model/aarch64.c [5:5]
+ cpu_model/aarch64.h [5:5]
cpu_model/cpu_model.h [5:5]
cpu_model/x86.c [5:5]
crtbegin.c [5:5]
@@ -1085,6 +1099,7 @@ BELONGS ya.make
emutls.c [5:5]
enable_execute_stack.c [5:5]
eprintf.c [5:5]
+ extendbfsf2.c [5:5]
extenddftf2.c [5:5]
extendhfsf2.c [5:5]
extendsfdf2.c [5:5]
@@ -1310,7 +1325,9 @@ BELONGS ya.make
aarch64/chkstk.S [3:3]
aarch64/fp_mode.c [5:5]
aarch64/sme-abi-init.c [3:3]
+ aarch64/sme-abi-vg.c [3:3]
aarch64/sme-abi.S [3:3]
+ aarch64/sme-libc-mem-routines.S [3:3]
absvdi2.c [5:5]
absvsi2.c [5:5]
absvti2.c [5:5]
@@ -1444,7 +1461,9 @@ BELONGS ya.make
comparedf2.c [5:5]
comparesf2.c [5:5]
comparetf2.c [5:5]
+ cpu_model/AArch64CPUFeatures.inc [5:5]
cpu_model/aarch64.c [5:5]
+ cpu_model/aarch64.h [5:5]
cpu_model/cpu_model.h [5:5]
cpu_model/x86.c [5:5]
crtbegin.c [5:5]
@@ -1468,6 +1487,7 @@ BELONGS ya.make
emutls.c [5:5]
enable_execute_stack.c [5:5]
eprintf.c [5:5]
+ extendbfsf2.c [5:5]
extenddftf2.c [5:5]
extendhfsf2.c [5:5]
extendsfdf2.c [5:5]
diff --git a/contrib/libs/cxxsupp/builtins/CODE_OWNERS.TXT b/contrib/libs/cxxsupp/builtins/CODE_OWNERS.TXT
index ad136edf967..bd51a1073cc 100644
--- a/contrib/libs/cxxsupp/builtins/CODE_OWNERS.TXT
+++ b/contrib/libs/cxxsupp/builtins/CODE_OWNERS.TXT
@@ -67,3 +67,11 @@ D: ThreadSanitizer
N: Bill Wendling
D: Profile runtime library
+
+N: Christopher Apple, David Trevelyan
+D: Realtime Sanitizer (RTSan)
+
+N: Alexander Shaposhnikov
+D: Numerical Sanitizer (NSAN)
diff --git a/contrib/libs/cxxsupp/builtins/README.txt b/contrib/libs/cxxsupp/builtins/README.txt
index 2d213d95f33..19f26c92a0f 100644
--- a/contrib/libs/cxxsupp/builtins/README.txt
+++ b/contrib/libs/cxxsupp/builtins/README.txt
@@ -272,6 +272,11 @@ switch32
switch8
switchu8
+// This function generates a custom trampoline function with the specific
+// realFunc and localsPtr values.
+void __trampoline_setup(uint32_t* trampOnStack, int trampSizeAllocated,
+ const void* realFunc, void* localsPtr);
+
// There is no C interface to the *_vfp_d8_d15_regs functions. There are
// called in the prolog and epilog of Thumb1 functions. When the C++ ABI use
// SJLJ for exceptions, each function with a catch clause or destructors needs
diff --git a/contrib/libs/cxxsupp/builtins/aarch64/sme-abi-vg.c b/contrib/libs/cxxsupp/builtins/aarch64/sme-abi-vg.c
new file mode 100644
index 00000000000..20061012e16
--- /dev/null
+++ b/contrib/libs/cxxsupp/builtins/aarch64/sme-abi-vg.c
@@ -0,0 +1,21 @@
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+#include "../cpu_model/aarch64.h"
+
+struct FEATURES {
+ unsigned long long features;
+};
+
+extern struct FEATURES __aarch64_cpu_features;
+
+#if __GNUC__ >= 9
+#pragma GCC diagnostic ignored "-Wprio-ctor-dtor"
+#endif
+__attribute__((constructor(90))) static void get_aarch64_cpu_features(void) {
+ if (__atomic_load_n(&__aarch64_cpu_features.features, __ATOMIC_RELAXED))
+ return;
+
+ __init_cpu_features();
+}
diff --git a/contrib/libs/cxxsupp/builtins/aarch64/sme-abi.S b/contrib/libs/cxxsupp/builtins/aarch64/sme-abi.S
index d470ecaf7aa..cd8153f6067 100644
--- a/contrib/libs/cxxsupp/builtins/aarch64/sme-abi.S
+++ b/contrib/libs/cxxsupp/builtins/aarch64/sme-abi.S
@@ -12,11 +12,15 @@
#if !defined(__APPLE__)
#define TPIDR2_SYMBOL SYMBOL_NAME(__aarch64_has_sme_and_tpidr2_el0)
#define TPIDR2_SYMBOL_OFFSET :lo12:SYMBOL_NAME(__aarch64_has_sme_and_tpidr2_el0)
+#define CPU_FEATS_SYMBOL SYMBOL_NAME(__aarch64_cpu_features)
+#define CPU_FEATS_SYMBOL_OFFSET :lo12:SYMBOL_NAME(__aarch64_cpu_features)
#else
// MachO requires @page/@pageoff directives because the global is defined
// in a different file. Otherwise this file may fail to build.
#define TPIDR2_SYMBOL SYMBOL_NAME(__aarch64_has_sme_and_tpidr2_el0)@page
#define TPIDR2_SYMBOL_OFFSET SYMBOL_NAME(__aarch64_has_sme_and_tpidr2_el0)@pageoff
+#define CPU_FEATS_SYMBOL SYMBOL_NAME(__aarch64_cpu_features)@page
+#define CPU_FEATS_SYMBOL_OFFSET SYMBOL_NAME(__aarch64_cpu_features)@pageoff
#endif
.arch armv9-a+sme
@@ -26,9 +30,10 @@
// abort(). Note that there is no need to preserve any state before the call,
// because the function does not return.
DEFINE_COMPILERRT_PRIVATE_FUNCTION(do_abort)
-.cfi_startproc
- .variant_pcs SYMBOL_NAME(do_abort)
- stp x29, x30, [sp, #-32]!
+ .cfi_startproc
+ .variant_pcs SYMBOL_NAME(do_abort)
+ BTI_C
+ stp x29, x30, [sp, #-32]!
cntd x0
// Store VG to a stack location that we describe with .cfi_offset
str x0, [sp, #16]
@@ -36,22 +41,23 @@ DEFINE_COMPILERRT_PRIVATE_FUNCTION(do_abort)
.cfi_offset w30, -24
.cfi_offset w29, -32
.cfi_offset 46, -16
- bl __arm_sme_state
- tbz x0, #0, 2f
+ bl __arm_sme_state
+ tbz x0, #0, 2f
1:
- smstop sm
+ smstop sm
2:
// We can't make this into a tail-call because the unwinder would
// need to restore the value of VG.
- bl SYMBOL_NAME(abort)
-.cfi_endproc
+ bl SYMBOL_NAME(abort)
+ .cfi_endproc
END_COMPILERRT_FUNCTION(do_abort)
// __arm_sme_state fills the result registers based on a local
// that is set as part of the compiler-rt startup code.
// __aarch64_has_sme_and_tpidr2_el0
DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_sme_state)
- .variant_pcs __arm_sme_state
+ .variant_pcs __arm_sme_state
+ BTI_C
mov x0, xzr
mov x1, xzr
@@ -68,7 +74,8 @@ DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_sme_state)
END_COMPILERRT_OUTLINE_FUNCTION(__arm_sme_state)
DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_tpidr2_restore)
- .variant_pcs __arm_tpidr2_restore
+ .variant_pcs __arm_tpidr2_restore
+ BTI_C
// If TPIDR2_EL0 is nonnull, the subroutine aborts in some platform-specific
// manner.
mrs x14, TPIDR2_EL0
@@ -103,7 +110,8 @@ DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_tpidr2_restore)
END_COMPILERRT_OUTLINE_FUNCTION(__arm_tpidr2_restore)
DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_tpidr2_save)
- .variant_pcs __arm_tpidr2_restore
+ .variant_pcs __arm_tpidr2_restore
+ BTI_C
// If the current thread does not have access to TPIDR2_EL0, the subroutine
// does nothing.
adrp x14, TPIDR2_SYMBOL
@@ -143,7 +151,8 @@ DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_tpidr2_save)
END_COMPILERRT_OUTLINE_FUNCTION(__arm_tpidr2_save)
DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_za_disable)
- .variant_pcs __arm_tpidr2_restore
+ .variant_pcs __arm_tpidr2_restore
+ BTI_C
// If the current thread does not have access to SME, the subroutine does
// nothing.
adrp x14, TPIDR2_SYMBOL
@@ -174,3 +183,48 @@ DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_za_disable)
0:
ret
END_COMPILERRT_OUTLINE_FUNCTION(__arm_za_disable)
+
+DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_get_current_vg)
+ .variant_pcs __arm_get_current_vg
+ BTI_C
+
+ stp x29, x30, [sp, #-16]!
+ .cfi_def_cfa_offset 16
+ mov x29, sp
+ .cfi_def_cfa w29, 16
+ .cfi_offset w30, -8
+ .cfi_offset w29, -16
+ adrp x17, CPU_FEATS_SYMBOL
+ ldr w17, [x17, CPU_FEATS_SYMBOL_OFFSET]
+ tbnz w17, #30, 0f
+ adrp x16, TPIDR2_SYMBOL
+ ldrb w16, [x16, TPIDR2_SYMBOL_OFFSET]
+ cbz w16, 1f
+0:
+ mov x18, x1
+ bl __arm_sme_state
+ mov x1, x18
+ and x17, x17, #0x40000000
+ bfxil x17, x0, #0, #1
+ cbz x17, 1f
+ cntd x0
+ .cfi_def_cfa wsp, 16
+ ldp x29, x30, [sp], #16
+ .cfi_def_cfa_offset 0
+ .cfi_restore w30
+ .cfi_restore w29
+ ret
+1:
+ mov x0, xzr
+ .cfi_def_cfa wsp, 16
+ ldp x29, x30, [sp], #16
+ .cfi_def_cfa_offset 0
+ .cfi_restore w30
+ .cfi_restore w29
+ ret
+END_COMPILERRT_OUTLINE_FUNCTION(__arm_get_current_vg)
+
+NO_EXEC_STACK_DIRECTIVE
+
+// GNU property note for BTI and PAC
+GNU_PROPERTY_BTI_PAC
diff --git a/contrib/libs/cxxsupp/builtins/aarch64/sme-libc-mem-routines.S b/contrib/libs/cxxsupp/builtins/aarch64/sme-libc-mem-routines.S
new file mode 100644
index 00000000000..0318d9a6f1e
--- /dev/null
+++ b/contrib/libs/cxxsupp/builtins/aarch64/sme-libc-mem-routines.S
@@ -0,0 +1,352 @@
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// Routines taken from libc/AOR_v20.02/string/aarch64
+
+#include "../assembly.h"
+
+#ifdef __aarch64__
+
+#define L(l) .L ## l
+
+//
+// __arm_sc_memcpy / __arm_sc_memmove
+//
+
+#define dstin x0
+#define src x1
+#define count x2
+#define dst x3
+#define srcend1 x4
+#define dstend1 x5
+#define A_l x6
+#define A_lw w6
+#define A_h x7
+#define B_l x8
+#define B_lw w8
+#define B_h x9
+#define C_l x10
+#define C_lw w10
+#define C_h x11
+#define D_l x12
+#define D_h x13
+#define E_l x14
+#define E_h x15
+#define F_l x16
+#define F_h x17
+#define G_l count
+#define G_h dst
+#define H_l src
+#define H_h srcend1
+#define tmp1 x14
+
+/* This implementation handles overlaps and supports both memcpy and memmove
+ from a single entry point. It uses unaligned accesses and branchless
+ sequences to keep the code small, simple and improve performance.
+
+ Copies are split into 3 main cases: small copies of up to 32 bytes, medium
+ copies of up to 128 bytes, and large copies. The overhead of the overlap
+ check is negligible since it is only required for large copies.
+
+ Large copies use a software pipelined loop processing 64 bytes per iteration.
+ The destination pointer is 16-byte aligned to minimize unaligned accesses.
+ The loop tail is handled by always copying 64 bytes from the end.
+*/
+
+DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_sc_memcpy)
+ add srcend1, src, count
+ add dstend1, dstin, count
+ cmp count, 128
+ b.hi L(copy_long)
+ cmp count, 32
+ b.hi L(copy32_128)
+
+ /* Small copies: 0..32 bytes. */
+ cmp count, 16
+ b.lo L(copy16)
+ ldp A_l, A_h, [src]
+ ldp D_l, D_h, [srcend1, -16]
+ stp A_l, A_h, [dstin]
+ stp D_l, D_h, [dstend1, -16]
+ ret
+
+ /* Copy 8-15 bytes. */
+L(copy16):
+ tbz count, 3, L(copy8)
+ ldr A_l, [src]
+ ldr A_h, [srcend1, -8]
+ str A_l, [dstin]
+ str A_h, [dstend1, -8]
+ ret
+
+ .p2align 3
+ /* Copy 4-7 bytes. */
+L(copy8):
+ tbz count, 2, L(copy4)
+ ldr A_lw, [src]
+ ldr B_lw, [srcend1, -4]
+ str A_lw, [dstin]
+ str B_lw, [dstend1, -4]
+ ret
+
+ /* Copy 0..3 bytes using a branchless sequence. */
+L(copy4):
+ cbz count, L(copy0)
+ lsr tmp1, count, 1
+ ldrb A_lw, [src]
+ ldrb C_lw, [srcend1, -1]
+ ldrb B_lw, [src, tmp1]
+ strb A_lw, [dstin]
+ strb B_lw, [dstin, tmp1]
+ strb C_lw, [dstend1, -1]
+L(copy0):
+ ret
+
+ .p2align 4
+ /* Medium copies: 33..128 bytes. */
+L(copy32_128):
+ ldp A_l, A_h, [src]
+ ldp B_l, B_h, [src, 16]
+ ldp C_l, C_h, [srcend1, -32]
+ ldp D_l, D_h, [srcend1, -16]
+ cmp count, 64
+ b.hi L(copy128)
+ stp A_l, A_h, [dstin]
+ stp B_l, B_h, [dstin, 16]
+ stp C_l, C_h, [dstend1, -32]
+ stp D_l, D_h, [dstend1, -16]
+ ret
+
+ .p2align 4
+ /* Copy 65..128 bytes. */
+L(copy128):
+ ldp E_l, E_h, [src, 32]
+ ldp F_l, F_h, [src, 48]
+ cmp count, 96
+ b.ls L(copy96)
+ ldp G_l, G_h, [srcend1, -64]
+ ldp H_l, H_h, [srcend1, -48]
+ stp G_l, G_h, [dstend1, -64]
+ stp H_l, H_h, [dstend1, -48]
+L(copy96):
+ stp A_l, A_h, [dstin]
+ stp B_l, B_h, [dstin, 16]
+ stp E_l, E_h, [dstin, 32]
+ stp F_l, F_h, [dstin, 48]
+ stp C_l, C_h, [dstend1, -32]
+ stp D_l, D_h, [dstend1, -16]
+ ret
+
+ .p2align 4
+ /* Copy more than 128 bytes. */
+L(copy_long):
+ /* Use backwards copy if there is an overlap. */
+ sub tmp1, dstin, src
+ cbz tmp1, L(copy0)
+ cmp tmp1, count
+ b.lo L(copy_long_backwards)
+
+ /* Copy 16 bytes and then align dst to 16-byte alignment. */
+
+ ldp D_l, D_h, [src]
+ and tmp1, dstin, 15
+ bic dst, dstin, 15
+ sub src, src, tmp1
+ add count, count, tmp1 /* Count is now 16 too large. */
+ ldp A_l, A_h, [src, 16]
+ stp D_l, D_h, [dstin]
+ ldp B_l, B_h, [src, 32]
+ ldp C_l, C_h, [src, 48]
+ ldp D_l, D_h, [src, 64]!
+ subs count, count, 128 + 16 /* Test and readjust count. */
+ b.ls L(copy64_from_end)
+L(loop64):
+ stp A_l, A_h, [dst, 16]
+ ldp A_l, A_h, [src, 16]
+ stp B_l, B_h, [dst, 32]
+ ldp B_l, B_h, [src, 32]
+ stp C_l, C_h, [dst, 48]
+ ldp C_l, C_h, [src, 48]
+ stp D_l, D_h, [dst, 64]!
+ ldp D_l, D_h, [src, 64]!
+ subs count, count, 64
+ b.hi L(loop64)
+
+ /* Write the last iteration and copy 64 bytes from the end. */
+L(copy64_from_end):
+ ldp E_l, E_h, [srcend1, -64]
+ stp A_l, A_h, [dst, 16]
+ ldp A_l, A_h, [srcend1, -48]
+ stp B_l, B_h, [dst, 32]
+ ldp B_l, B_h, [srcend1, -32]
+ stp C_l, C_h, [dst, 48]
+ ldp C_l, C_h, [srcend1, -16]
+ stp D_l, D_h, [dst, 64]
+ stp E_l, E_h, [dstend1, -64]
+ stp A_l, A_h, [dstend1, -48]
+ stp B_l, B_h, [dstend1, -32]
+ stp C_l, C_h, [dstend1, -16]
+ ret
+
+ .p2align 4
+
+ /* Large backwards copy for overlapping copies.
+ Copy 16 bytes and then align dst to 16-byte alignment. */
+L(copy_long_backwards):
+ ldp D_l, D_h, [srcend1, -16]
+ and tmp1, dstend1, 15
+ sub srcend1, srcend1, tmp1
+ sub count, count, tmp1
+ ldp A_l, A_h, [srcend1, -16]
+ stp D_l, D_h, [dstend1, -16]
+ ldp B_l, B_h, [srcend1, -32]
+ ldp C_l, C_h, [srcend1, -48]
+ ldp D_l, D_h, [srcend1, -64]!
+ sub dstend1, dstend1, tmp1
+ subs count, count, 128
+ b.ls L(copy64_from_start)
+
+L(loop64_backwards):
+ stp A_l, A_h, [dstend1, -16]
+ ldp A_l, A_h, [srcend1, -16]
+ stp B_l, B_h, [dstend1, -32]
+ ldp B_l, B_h, [srcend1, -32]
+ stp C_l, C_h, [dstend1, -48]
+ ldp C_l, C_h, [srcend1, -48]
+ stp D_l, D_h, [dstend1, -64]!
+ ldp D_l, D_h, [srcend1, -64]!
+ subs count, count, 64
+ b.hi L(loop64_backwards)
+
+ /* Write the last iteration and copy 64 bytes from the start. */
+L(copy64_from_start):
+ ldp G_l, G_h, [src, 48]
+ stp A_l, A_h, [dstend1, -16]
+ ldp A_l, A_h, [src, 32]
+ stp B_l, B_h, [dstend1, -32]
+ ldp B_l, B_h, [src, 16]
+ stp C_l, C_h, [dstend1, -48]
+ ldp C_l, C_h, [src]
+ stp D_l, D_h, [dstend1, -64]
+ stp G_l, G_h, [dstin, 48]
+ stp A_l, A_h, [dstin, 32]
+ stp B_l, B_h, [dstin, 16]
+ stp C_l, C_h, [dstin]
+ ret
+END_COMPILERRT_OUTLINE_FUNCTION(__arm_sc_memcpy)
+
+DEFINE_COMPILERRT_FUNCTION_ALIAS(__arm_sc_memmove, __arm_sc_memcpy)
+
+
+//
+// __arm_sc_memset
+//
+
+#define dstin x0
+#define val x1
+#define valw w1
+#define count x2
+#define dst x3
+#define dstend2 x4
+#define zva_val x5
+
+DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_sc_memset)
+#ifdef __ARM_FEATURE_SVE
+ mov z0.b, valw
+#else
+ bfi valw, valw, #8, #8
+ bfi valw, valw, #16, #16
+ bfi val, val, #32, #32
+ fmov d0, val
+ fmov v0.d[1], val
+#endif
+ add dstend2, dstin, count
+
+ cmp count, 96
+ b.hi L(set_long)
+ cmp count, 16
+ b.hs L(set_medium)
+ mov val, v0.D[0]
+
+ /* Set 0..15 bytes. */
+ tbz count, 3, 1f
+ str val, [dstin]
+ str val, [dstend2, -8]
+ ret
+ nop
+1: tbz count, 2, 2f
+ str valw, [dstin]
+ str valw, [dstend2, -4]
+ ret
+2: cbz count, 3f
+ strb valw, [dstin]
+ tbz count, 1, 3f
+ strh valw, [dstend2, -2]
+3: ret
+
+ /* Set 17..96 bytes. */
+L(set_medium):
+ str q0, [dstin]
+ tbnz count, 6, L(set96)
+ str q0, [dstend2, -16]
+ tbz count, 5, 1f
+ str q0, [dstin, 16]
+ str q0, [dstend2, -32]
+1: ret
+
+ .p2align 4
+ /* Set 64..96 bytes. Write 64 bytes from the start and
+ 32 bytes from the end. */
+L(set96):
+ str q0, [dstin, 16]
+ stp q0, q0, [dstin, 32]
+ stp q0, q0, [dstend2, -32]
+ ret
+
+ .p2align 4
+L(set_long):
+ and valw, valw, 255
+ bic dst, dstin, 15
+ str q0, [dstin]
+ cmp count, 160
+ ccmp valw, 0, 0, hs
+ b.ne L(no_zva)
+
+#ifndef SKIP_ZVA_CHECK
+ mrs zva_val, dczid_el0
+ and zva_val, zva_val, 31
+ cmp zva_val, 4 /* ZVA size is 64 bytes. */
+ b.ne L(no_zva)
+#endif
+ str q0, [dst, 16]
+ stp q0, q0, [dst, 32]
+ bic dst, dst, 63
+ sub count, dstend2, dst /* Count is now 64 too large. */
+ sub count, count, 128 /* Adjust count and bias for loop. */
+
+ .p2align 4
+L(zva_loop):
+ add dst, dst, 64
+ dc zva, dst
+ subs count, count, 64
+ b.hi L(zva_loop)
+ stp q0, q0, [dstend2, -64]
+ stp q0, q0, [dstend2, -32]
+ ret
+
+L(no_zva):
+ sub count, dstend2, dst /* Count is 16 too large. */
+ sub dst, dst, 16 /* Dst is biased by -32. */
+ sub count, count, 64 + 16 /* Adjust count and bias for loop. */
+L(no_zva_loop):
+ stp q0, q0, [dst, 32]
+ stp q0, q0, [dst, 64]!
+ subs count, count, 64
+ b.hi L(no_zva_loop)
+ stp q0, q0, [dstend2, -64]
+ stp q0, q0, [dstend2, -32]
+ ret
+END_COMPILERRT_OUTLINE_FUNCTION(__arm_sc_memset)
+
+#endif // __aarch64__
diff --git a/contrib/libs/cxxsupp/builtins/aarch64/sme-libc-routines.c b/contrib/libs/cxxsupp/builtins/aarch64/sme-libc-routines.c
index cd73025a19c..315490e73ea 100644
--- a/contrib/libs/cxxsupp/builtins/aarch64/sme-libc-routines.c
+++ b/contrib/libs/cxxsupp/builtins/aarch64/sme-libc-routines.c
@@ -1,79 +1,4 @@
-#include <stdlib.h>
-
-// WARNING: When building the scalar versions of these functions you need to
-// use the compiler flag "-mllvm -disable-loop-idiom-all" to prevent clang
-// from recognising a loop idiom and planting calls to memcpy!
-
-static void *__arm_sc_memcpy_fwd(void *dest, const void *src,
- size_t n) __arm_streaming_compatible {
- unsigned char *destp = (unsigned char *)dest;
- const unsigned char *srcp = (const unsigned char *)src;
- for (size_t i = 0; i < n; ++i)
- destp[i] = srcp[i];
-
- return dest;
-}
-
-// If dest and src overlap then behaviour is undefined, hence we can add the
-// restrict keywords here. This also matches the definition of the libc memcpy
-// according to the man page.
-void *__arm_sc_memcpy(void *__restrict__ dest, const void *__restrict__ src,
- size_t n) __arm_streaming_compatible {
- return __arm_sc_memcpy_fwd(dest, src, n);
-}
-
-void *__arm_sc_memset(void *dest, int c, size_t n) __arm_streaming_compatible {
- unsigned char *destp = (unsigned char *)dest;
- unsigned char c8 = (unsigned char)c;
- for (size_t i = 0; i < n; ++i)
- destp[i] = c8;
-
- return dest;
-}
-
-static void *__arm_sc_memcpy_rev(void *dest, const void *src,
- size_t n) __arm_streaming_compatible {
- unsigned char *destp = (unsigned char *)dest;
- const unsigned char *srcp = (const unsigned char *)src;
- // TODO: Improve performance by copying larger chunks in reverse, or by
- // using SVE.
- while (n > 0) {
- --n;
- destp[n] = srcp[n];
- }
- return dest;
-}
-
-// Semantically a memmove is equivalent to the following:
-// 1. Copy the entire contents of src to a temporary array that does not
-// overlap with src or dest.
-// 2. Copy the contents of the temporary array into dest.
-void *__arm_sc_memmove(void *dest, const void *src,
- size_t n) __arm_streaming_compatible {
- unsigned char *destp = (unsigned char *)dest;
- const unsigned char *srcp = (const unsigned char *)src;
-
- // If src and dest don't overlap then just invoke memcpy
- if ((srcp > (destp + n)) || (destp > (srcp + n)))
- return __arm_sc_memcpy_fwd(dest, src, n);
-
- // Overlap case 1:
- // src: Low | -> | High
- // dest: Low | -> | High
- // Here src is always ahead of dest at a higher addres. If we first read a
- // chunk of data from src we can safely write the same chunk to dest without
- // corrupting future reads of src.
- if (srcp > destp)
- return __arm_sc_memcpy_fwd(dest, src, n);
-
- // Overlap case 2:
- // src: Low | -> | High
- // dest: Low | -> | High
- // While we're in the overlap region we're always corrupting future reads of
- // src when writing to dest. An efficient way to do this is to copy the data
- // in reverse by starting at the highest address.
- return __arm_sc_memcpy_rev(dest, src, n);
-}
+#include <stddef.h>
const void *__arm_sc_memchr(const void *src, int c,
size_t n) __arm_streaming_compatible {
diff --git a/contrib/libs/cxxsupp/builtins/atomic.c b/contrib/libs/cxxsupp/builtins/atomic.c
index 852bb20f086..aded25d9baa 100644
--- a/contrib/libs/cxxsupp/builtins/atomic.c
+++ b/contrib/libs/cxxsupp/builtins/atomic.c
@@ -12,7 +12,7 @@
//
// 1) This code must work with C programs that do not link to anything
// (including pthreads) and so it should not depend on any pthread
-// functions.
+// functions. If the user wishes to opt into using pthreads, they may do so.
// 2) Atomic operations, rather than explicit mutexes, are most commonly used
// on code where contended operations are rate.
//
@@ -56,7 +56,17 @@ static const long SPINLOCK_MASK = SPINLOCK_COUNT - 1;
// defined. Each platform should define the Lock type, and corresponding
// lock() and unlock() functions.
////////////////////////////////////////////////////////////////////////////////
-#if defined(__FreeBSD__) || defined(__DragonFly__)
+#if defined(_LIBATOMIC_USE_PTHREAD)
+#include <pthread.h>
+typedef pthread_mutex_t Lock;
+/// Unlock a lock. This is a release operation.
+__inline static void unlock(Lock *l) { pthread_mutex_unlock(l); }
+/// Locks a lock.
+__inline static void lock(Lock *l) { pthread_mutex_lock(l); }
+/// locks for atomic operations
+static Lock locks[SPINLOCK_COUNT];
+
+#elif defined(__FreeBSD__) || defined(__DragonFly__)
#include <errno.h>
// clang-format off
#include <sys/types.h>
diff --git a/contrib/libs/cxxsupp/builtins/cpu_model/AArch64CPUFeatures.inc b/contrib/libs/cxxsupp/builtins/cpu_model/AArch64CPUFeatures.inc
new file mode 100644
index 00000000000..e78bb88cfed
--- /dev/null
+++ b/contrib/libs/cxxsupp/builtins/cpu_model/AArch64CPUFeatures.inc
@@ -0,0 +1,91 @@
+//===- AArch64CPUFeatures.inc - AArch64 CPU Features enum -------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the CPUFeatures enum for AArch64 to facilitate better
+// testing of this code between LLVM and compiler-rt, primarily that the files
+// are an exact match.
+//
+// This file has two identical copies. The primary copy lives in LLVM and
+// the other one sits in compiler-rt/lib/builtins/cpu_model directory. To make
+// changes in this file, first modify the primary copy and copy it over to
+// compiler-rt. compiler-rt tests will fail if the two files are not synced up.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef AARCH64_CPU_FEATURS_INC_H
+#define AARCH64_CPU_FEATURS_INC_H
+
+// Function Multi Versioning CPU features.
+enum CPUFeatures {
+ FEAT_RNG,
+ FEAT_FLAGM,
+ FEAT_FLAGM2,
+ FEAT_FP16FML,
+ FEAT_DOTPROD,
+ FEAT_SM4,
+ FEAT_RDM,
+ FEAT_LSE,
+ FEAT_FP,
+ FEAT_SIMD,
+ FEAT_CRC,
+ FEAT_SHA1,
+ FEAT_SHA2,
+ FEAT_SHA3,
+ FEAT_AES,
+ FEAT_PMULL,
+ FEAT_FP16,
+ FEAT_DIT,
+ FEAT_DPB,
+ FEAT_DPB2,
+ FEAT_JSCVT,
+ FEAT_FCMA,
+ FEAT_RCPC,
+ FEAT_RCPC2,
+ FEAT_FRINTTS,
+ FEAT_DGH,
+ FEAT_I8MM,
+ FEAT_BF16,
+ FEAT_EBF16,
+ FEAT_RPRES,
+ FEAT_SVE,
+ FEAT_SVE_BF16,
+ FEAT_SVE_EBF16,
+ FEAT_SVE_I8MM,
+ FEAT_SVE_F32MM,
+ FEAT_SVE_F64MM,
+ FEAT_SVE2,
+ FEAT_SVE_AES,
+ FEAT_SVE_PMULL128,
+ FEAT_SVE_BITPERM,
+ FEAT_SVE_SHA3,
+ FEAT_SVE_SM4,
+ FEAT_SME,
+ FEAT_MEMTAG,
+ FEAT_MEMTAG2,
+ FEAT_MEMTAG3,
+ FEAT_SB,
+ FEAT_PREDRES,
+ FEAT_SSBS,
+ FEAT_SSBS2,
+ FEAT_BTI,
+ FEAT_LS64,
+ FEAT_LS64_V,
+ FEAT_LS64_ACCDATA,
+ FEAT_WFXT,
+ FEAT_SME_F64,
+ FEAT_SME_I64,
+ FEAT_SME2,
+ FEAT_RCPC3,
+ FEAT_MOPS,
+ FEAT_MAX,
+ FEAT_EXT = 62, // Reserved to indicate presence of additional features field
+ // in __aarch64_cpu_features
+ FEAT_INIT // Used as flag of features initialization completion
+};
+
+#endif
diff --git a/contrib/libs/cxxsupp/builtins/cpu_model/aarch64.c b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64.c
index 17bddfca46f..b868caa991b 100644
--- a/contrib/libs/cxxsupp/builtins/cpu_model/aarch64.c
+++ b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64.c
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "cpu_model.h"
+#include "aarch64.h"
#if !defined(__aarch64__)
#error This file is intended only for aarch64-based targets
@@ -53,74 +53,6 @@ _Bool __aarch64_have_lse_atomics
#endif
#if !defined(DISABLE_AARCH64_FMV)
-// CPUFeatures must correspond to the same AArch64 features in
-// AArch64TargetParser.h
-enum CPUFeatures {
- FEAT_RNG,
- FEAT_FLAGM,
- FEAT_FLAGM2,
- FEAT_FP16FML,
- FEAT_DOTPROD,
- FEAT_SM4,
- FEAT_RDM,
- FEAT_LSE,
- FEAT_FP,
- FEAT_SIMD,
- FEAT_CRC,
- FEAT_SHA1,
- FEAT_SHA2,
- FEAT_SHA3,
- FEAT_AES,
- FEAT_PMULL,
- FEAT_FP16,
- FEAT_DIT,
- FEAT_DPB,
- FEAT_DPB2,
- FEAT_JSCVT,
- FEAT_FCMA,
- FEAT_RCPC,
- FEAT_RCPC2,
- FEAT_FRINTTS,
- FEAT_DGH,
- FEAT_I8MM,
- FEAT_BF16,
- FEAT_EBF16,
- FEAT_RPRES,
- FEAT_SVE,
- FEAT_SVE_BF16,
- FEAT_SVE_EBF16,
- FEAT_SVE_I8MM,
- FEAT_SVE_F32MM,
- FEAT_SVE_F64MM,
- FEAT_SVE2,
- FEAT_SVE_AES,
- FEAT_SVE_PMULL128,
- FEAT_SVE_BITPERM,
- FEAT_SVE_SHA3,
- FEAT_SVE_SM4,
- FEAT_SME,
- FEAT_MEMTAG,
- FEAT_MEMTAG2,
- FEAT_MEMTAG3,
- FEAT_SB,
- FEAT_PREDRES,
- FEAT_SSBS,
- FEAT_SSBS2,
- FEAT_BTI,
- FEAT_LS64,
- FEAT_LS64_V,
- FEAT_LS64_ACCDATA,
- FEAT_WFXT,
- FEAT_SME_F64,
- FEAT_SME_I64,
- FEAT_SME2,
- FEAT_RCPC3,
- FEAT_MOPS,
- FEAT_MAX,
- FEAT_EXT = 62, // Reserved to indicate presence of additional features field
- // in __aarch64_cpu_features
- FEAT_INIT // Used as flag of features initialization completion
-};
// Architecture features used
// in Function Multi Versioning
diff --git a/contrib/libs/cxxsupp/builtins/cpu_model/aarch64.h b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64.h
new file mode 100644
index 00000000000..f6cbf75d582
--- /dev/null
+++ b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64.h
@@ -0,0 +1,21 @@
+//===-- cpu_model/aarch64.h --------------------------------------------- -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "cpu_model.h"
+
+#if !defined(__aarch64__)
+#error This file is intended only for aarch64-based targets
+#endif
+
+#if !defined(DISABLE_AARCH64_FMV)
+
+#include "AArch64CPUFeatures.inc"
+
+void __init_cpu_features(void);
+
+#endif // !defined(DISABLE_AARCH64_FMV)
diff --git a/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/android.inc b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/android.inc
index f711431489c..a9e3594e93c 100644
--- a/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/android.inc
+++ b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/android.inc
@@ -1,6 +1,6 @@
void __init_cpu_features_resolver(unsigned long hwcap,
const __ifunc_arg_t *arg) {
- if (__aarch64_cpu_features.features)
+ if (__atomic_load_n(&__aarch64_cpu_features.features, __ATOMIC_RELAXED))
return;
// ifunc resolvers don't have hwcaps in arguments on Android API lower
@@ -17,7 +17,7 @@ void __init_cpu_features_resolver(unsigned long hwcap,
void CONSTRUCTOR_ATTRIBUTE __init_cpu_features(void) {
// CPU features already initialized.
- if (__aarch64_cpu_features.features)
+ if (__atomic_load_n(&__aarch64_cpu_features.features, __ATOMIC_RELAXED))
return;
// Don't set any CPU features,
diff --git a/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/apple.inc b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/apple.inc
index 0bb755f4b30..f0694900f23 100644
--- a/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/apple.inc
+++ b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/apple.inc
@@ -1,8 +1,27 @@
#include <TargetConditionals.h>
#if TARGET_OS_OSX || TARGET_OS_IPHONE
-#include <dispatch/dispatch.h>
#include <sys/sysctl.h>
+#if __has_include(<arm/cpu_capabilities_public.h>)
+#include <arm/cpu_capabilities_public.h>
+#define HAS_CPU_CAPABILITIES_PUBLIC_H 1
+
+// FB13964283 - A few of these didn't make it into the public SDK yet.
+#ifndef CAP_BIT_FEAT_SME
+#define CAP_BIT_FEAT_SME 40
+#endif
+#ifndef CAP_BIT_FEAT_SME2
+#define CAP_BIT_FEAT_SME2 41
+#endif
+#ifndef CAP_BIT_FEAT_SME_F64F64
+#define CAP_BIT_FEAT_SME_F64F64 42
+#endif
+#ifndef CAP_BIT_FEAT_SME_I16I64
+#define CAP_BIT_FEAT_SME_I16I64 43
+#endif
+
+#endif
+
static bool isKnownAndSupported(const char *name) {
int32_t val = 0;
size_t size = sizeof(val);
@@ -11,61 +30,130 @@ static bool isKnownAndSupported(const char *name) {
return val;
}
+static uint64_t deriveImplicitFeatures(uint64_t features) {
+ // FEAT_SSBS2 implies FEAT_SSBS
+ if ((1ULL << FEAT_SSBS2) & features)
+ features |= (1ULL << FEAT_SSBS);
+
+ // FEAT_FP is always enabled
+ features |= (1ULL << FEAT_FP);
+
+ features |= (1ULL << FEAT_INIT);
+
+ return features;
+}
+
void __init_cpu_features_resolver(void) {
// On Darwin platforms, this may be called concurrently by multiple threads
// because the resolvers that use it are called lazily at runtime (unlike on
// ELF platforms, where IFuncs are resolved serially at load time). This
// function's effect on __aarch64_cpu_features must be idempotent.
- if (!__atomic_load_n(&__aarch64_cpu_features.features, __ATOMIC_RELAXED)) {
- uint64_t features = 0;
+ if (__atomic_load_n(&__aarch64_cpu_features.features, __ATOMIC_RELAXED))
+ return;
+
+ uint64_t features = 0;
- // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics
- static const struct {
- const char *sysctl_name;
- enum CPUFeatures feature;
- } feature_checks[] = {
- {"hw.optional.arm.FEAT_FlagM", FEAT_FLAGM},
- {"hw.optional.arm.FEAT_FlagM2", FEAT_FLAGM2},
- {"hw.optional.arm.FEAT_FHM", FEAT_FP16FML},
- {"hw.optional.arm.FEAT_DotProd", FEAT_DOTPROD},
- {"hw.optional.arm.FEAT_RDM", FEAT_RDM},
- {"hw.optional.arm.FEAT_LSE", FEAT_LSE},
- {"hw.optional.floatingpoint", FEAT_FP},
- {"hw.optional.AdvSIMD", FEAT_SIMD},
- {"hw.optional.armv8_crc32", FEAT_CRC},
- {"hw.optional.arm.FEAT_SHA1", FEAT_SHA1},
- {"hw.optional.arm.FEAT_SHA256", FEAT_SHA2},
- {"hw.optional.arm.FEAT_SHA3", FEAT_SHA3},
- {"hw.optional.arm.FEAT_AES", FEAT_AES},
- {"hw.optional.arm.FEAT_PMULL", FEAT_PMULL},
- {"hw.optional.arm.FEAT_FP16", FEAT_FP16},
- {"hw.optional.arm.FEAT_DIT", FEAT_DIT},
- {"hw.optional.arm.FEAT_DPB", FEAT_DPB},
- {"hw.optional.arm.FEAT_DPB2", FEAT_DPB2},
- {"hw.optional.arm.FEAT_JSCVT", FEAT_JSCVT},
- {"hw.optional.arm.FEAT_FCMA", FEAT_FCMA},
- {"hw.optional.arm.FEAT_LRCPC", FEAT_RCPC},
- {"hw.optional.arm.FEAT_LRCPC2", FEAT_RCPC2},
- {"hw.optional.arm.FEAT_FRINTTS", FEAT_FRINTTS},
- {"hw.optional.arm.FEAT_I8MM", FEAT_I8MM},
- {"hw.optional.arm.FEAT_BF16", FEAT_BF16},
- {"hw.optional.arm.FEAT_SB", FEAT_SB},
- {"hw.optional.arm.FEAT_SPECRES", FEAT_PREDRES},
- {"hw.optional.arm.FEAT_SSBS", FEAT_SSBS2},
- {"hw.optional.arm.FEAT_BTI", FEAT_BTI},
- };
+#ifdef HAS_CPU_CAPABILITIES_PUBLIC_H
+ uint8_t feats_bitvec[(CAP_BIT_NB + 7) / 8] = {0};
+ size_t len = sizeof(feats_bitvec);
+ // When hw.optional.arm.feats is available (macOS 15.0+, iOS 18.0+), use the
+ // fast path to get all the feature bits, otherwise fall back to the slow
+ // ~20-something sysctls path.
+ if (!sysctlbyname("hw.optional.arm.caps", &feats_bitvec, &len, 0, 0)) {
- for (size_t I = 0, E = sizeof(feature_checks) / sizeof(feature_checks[0]);
- I != E; ++I)
- if (isKnownAndSupported(feature_checks[I].sysctl_name))
- features |= (1ULL << feature_checks[I].feature);
+#define CHECK_BIT(FROM, TO) \
+ do { \
+ if (feats_bitvec[FROM / 8] & (1u << ((FROM) & 7))) { \
+ features |= (1ULL << TO); \
+ } \
+ } while (0)
- features |= (1ULL << FEAT_INIT);
+ CHECK_BIT(CAP_BIT_FEAT_FlagM, FEAT_FLAGM);
+ CHECK_BIT(CAP_BIT_FEAT_FlagM2, FEAT_FLAGM2);
+ CHECK_BIT(CAP_BIT_FEAT_FHM, FEAT_FP16FML);
+ CHECK_BIT(CAP_BIT_FEAT_DotProd, FEAT_DOTPROD);
+ CHECK_BIT(CAP_BIT_FEAT_SHA3, FEAT_SHA3);
+ CHECK_BIT(CAP_BIT_FEAT_RDM, FEAT_RDM);
+ CHECK_BIT(CAP_BIT_FEAT_LSE, FEAT_LSE);
+ CHECK_BIT(CAP_BIT_FEAT_SHA256, FEAT_SHA2);
+ CHECK_BIT(CAP_BIT_FEAT_SHA1, FEAT_SHA1);
+ CHECK_BIT(CAP_BIT_FEAT_AES, FEAT_AES);
+ CHECK_BIT(CAP_BIT_FEAT_PMULL, FEAT_PMULL);
+ CHECK_BIT(CAP_BIT_FEAT_SPECRES, FEAT_PREDRES);
+ CHECK_BIT(CAP_BIT_FEAT_SB, FEAT_SB);
+ CHECK_BIT(CAP_BIT_FEAT_FRINTTS, FEAT_FRINTTS);
+ CHECK_BIT(CAP_BIT_FEAT_LRCPC, FEAT_RCPC);
+ CHECK_BIT(CAP_BIT_FEAT_LRCPC2, FEAT_RCPC2);
+ CHECK_BIT(CAP_BIT_FEAT_FCMA, FEAT_FCMA);
+ CHECK_BIT(CAP_BIT_FEAT_JSCVT, FEAT_JSCVT);
+ CHECK_BIT(CAP_BIT_FEAT_DPB, FEAT_DPB);
+ CHECK_BIT(CAP_BIT_FEAT_DPB2, FEAT_DPB2);
+ CHECK_BIT(CAP_BIT_FEAT_BF16, FEAT_BF16);
+ CHECK_BIT(CAP_BIT_FEAT_I8MM, FEAT_I8MM);
+ CHECK_BIT(CAP_BIT_FEAT_DIT, FEAT_DIT);
+ CHECK_BIT(CAP_BIT_FEAT_FP16, FEAT_FP16);
+ CHECK_BIT(CAP_BIT_FEAT_SSBS, FEAT_SSBS2);
+ CHECK_BIT(CAP_BIT_FEAT_BTI, FEAT_BTI);
+ CHECK_BIT(CAP_BIT_AdvSIMD, FEAT_SIMD);
+ CHECK_BIT(CAP_BIT_CRC32, FEAT_CRC);
+ CHECK_BIT(CAP_BIT_FEAT_SME, FEAT_SME);
+ CHECK_BIT(CAP_BIT_FEAT_SME2, FEAT_SME2);
+ CHECK_BIT(CAP_BIT_FEAT_SME_F64F64, FEAT_SME_F64);
+ CHECK_BIT(CAP_BIT_FEAT_SME_I16I64, FEAT_SME_I64);
+
+ features = deriveImplicitFeatures(features);
__atomic_store(&__aarch64_cpu_features.features, &features,
__ATOMIC_RELAXED);
+ return;
}
+#endif
+
+ // https://developer.apple.com/documentation/kernel/1387446-sysctlbyname/determining_instruction_set_characteristics
+ static const struct {
+ const char *sysctl_name;
+ enum CPUFeatures feature;
+ } feature_checks[] = {
+ {"hw.optional.arm.FEAT_FlagM", FEAT_FLAGM},
+ {"hw.optional.arm.FEAT_FlagM2", FEAT_FLAGM2},
+ {"hw.optional.arm.FEAT_FHM", FEAT_FP16FML},
+ {"hw.optional.arm.FEAT_DotProd", FEAT_DOTPROD},
+ {"hw.optional.arm.FEAT_RDM", FEAT_RDM},
+ {"hw.optional.arm.FEAT_LSE", FEAT_LSE},
+ {"hw.optional.AdvSIMD", FEAT_SIMD},
+ {"hw.optional.armv8_crc32", FEAT_CRC},
+ {"hw.optional.arm.FEAT_SHA1", FEAT_SHA1},
+ {"hw.optional.arm.FEAT_SHA256", FEAT_SHA2},
+ {"hw.optional.arm.FEAT_SHA3", FEAT_SHA3},
+ {"hw.optional.arm.FEAT_AES", FEAT_AES},
+ {"hw.optional.arm.FEAT_PMULL", FEAT_PMULL},
+ {"hw.optional.arm.FEAT_FP16", FEAT_FP16},
+ {"hw.optional.arm.FEAT_DIT", FEAT_DIT},
+ {"hw.optional.arm.FEAT_DPB", FEAT_DPB},
+ {"hw.optional.arm.FEAT_DPB2", FEAT_DPB2},
+ {"hw.optional.arm.FEAT_JSCVT", FEAT_JSCVT},
+ {"hw.optional.arm.FEAT_FCMA", FEAT_FCMA},
+ {"hw.optional.arm.FEAT_LRCPC", FEAT_RCPC},
+ {"hw.optional.arm.FEAT_LRCPC2", FEAT_RCPC2},
+ {"hw.optional.arm.FEAT_FRINTTS", FEAT_FRINTTS},
+ {"hw.optional.arm.FEAT_I8MM", FEAT_I8MM},
+ {"hw.optional.arm.FEAT_BF16", FEAT_BF16},
+ {"hw.optional.arm.FEAT_SB", FEAT_SB},
+ {"hw.optional.arm.FEAT_SPECRES", FEAT_PREDRES},
+ {"hw.optional.arm.FEAT_SSBS", FEAT_SSBS2},
+ {"hw.optional.arm.FEAT_BTI", FEAT_BTI},
+ };
+
+ for (size_t I = 0, E = sizeof(feature_checks) / sizeof(feature_checks[0]);
+ I != E; ++I)
+ if (isKnownAndSupported(feature_checks[I].sysctl_name))
+ features |= (1ULL << feature_checks[I].feature);
+
+ features = deriveImplicitFeatures(features);
+
+ __atomic_store(&__aarch64_cpu_features.features, &features,
+ __ATOMIC_RELAXED);
}
#endif // TARGET_OS_OSX || TARGET_OS_IPHONE
diff --git a/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/freebsd.inc b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/freebsd.inc
index 793adef44b9..aa975dc854f 100644
--- a/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/freebsd.inc
+++ b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/freebsd.inc
@@ -1,6 +1,6 @@
void __init_cpu_features_resolver(unsigned long hwcap,
const __ifunc_arg_t *arg) {
- if (__aarch64_cpu_features.features)
+ if (__atomic_load_n(&__aarch64_cpu_features.features, __ATOMIC_RELAXED))
return;
__init_cpu_features_constructor(hwcap, arg);
@@ -10,7 +10,7 @@ void CONSTRUCTOR_ATTRIBUTE __init_cpu_features(void) {
unsigned long hwcap = 0;
unsigned long hwcap2 = 0;
// CPU features already initialized.
- if (__aarch64_cpu_features.features)
+ if (__atomic_load_n(&__aarch64_cpu_features.features, __ATOMIC_RELAXED))
return;
int res = 0;
diff --git a/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/fuchsia.inc b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/fuchsia.inc
index 329b6b43a8a..fd0800dd11e 100644
--- a/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/fuchsia.inc
+++ b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/fuchsia.inc
@@ -2,7 +2,7 @@
#include <zircon/syscalls.h>
void __init_cpu_features_resolver() {
- if (__aarch64_cpu_features.features)
+ if (__atomic_load_n(&__aarch64_cpu_features.features, __ATOMIC_RELAXED))
return;
// This ensures the vDSO is a direct link-time dependency of anything that
@@ -13,8 +13,8 @@ void __init_cpu_features_resolver() {
if (status != ZX_OK)
return;
-#define setCPUFeature(cpu_feature) \
- __aarch64_cpu_features.features |= 1ULL << cpu_feature
+ unsigned long long feat = 0;
+#define setCPUFeature(cpu_feature) feat |= 1ULL << cpu_feature
if (features & ZX_ARM64_FEATURE_ISA_FP)
setCPUFeature(FEAT_FP);
@@ -48,4 +48,6 @@ void __init_cpu_features_resolver() {
setCPUFeature(FEAT_SVE);
setCPUFeature(FEAT_INIT);
+
+ __atomic_store_n(&__aarch64_cpu_features.features, feat, __ATOMIC_RELAXED);
}
diff --git a/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/mrs.inc b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/mrs.inc
index 32a21a2fba9..e4d5e7f2bd7 100644
--- a/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/mrs.inc
+++ b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/mrs.inc
@@ -3,11 +3,10 @@
#define HAVE_SYS_AUXV_H
#endif
-
-
static void __init_cpu_features_constructor(unsigned long hwcap,
const __ifunc_arg_t *arg) {
-#define setCPUFeature(F) __aarch64_cpu_features.features |= 1ULL << F
+ unsigned long long feat = 0;
+#define setCPUFeature(F) feat |= 1ULL << F
#define getCPUFeature(id, ftr) __asm__("mrs %0, " #id : "=r"(ftr))
#define extractBits(val, start, number) \
(val & ((1ULL << number) - 1ULL) << start) >> start
@@ -20,26 +19,20 @@ static void __init_cpu_features_constructor(unsigned long hwcap,
setCPUFeature(FEAT_PMULL);
if (hwcap & HWCAP_FLAGM)
setCPUFeature(FEAT_FLAGM);
- if (hwcap2 & HWCAP2_FLAGM2) {
- setCPUFeature(FEAT_FLAGM);
+ if (hwcap2 & HWCAP2_FLAGM2)
setCPUFeature(FEAT_FLAGM2);
- }
- if (hwcap & HWCAP_SM3 && hwcap & HWCAP_SM4)
+ if (hwcap & HWCAP_SM4)
setCPUFeature(FEAT_SM4);
if (hwcap & HWCAP_ASIMDDP)
setCPUFeature(FEAT_DOTPROD);
if (hwcap & HWCAP_ASIMDFHM)
setCPUFeature(FEAT_FP16FML);
- if (hwcap & HWCAP_FPHP) {
+ if (hwcap & HWCAP_FPHP)
setCPUFeature(FEAT_FP16);
- setCPUFeature(FEAT_FP);
- }
if (hwcap & HWCAP_DIT)
setCPUFeature(FEAT_DIT);
if (hwcap & HWCAP_ASIMDRDM)
setCPUFeature(FEAT_RDM);
- if (hwcap & HWCAP_ILRCPC)
- setCPUFeature(FEAT_RCPC2);
if (hwcap & HWCAP_AES)
setCPUFeature(FEAT_AES);
if (hwcap & HWCAP_SHA1)
@@ -52,23 +45,20 @@ static void __init_cpu_features_constructor(unsigned long hwcap,
setCPUFeature(FEAT_FCMA);
if (hwcap & HWCAP_SB)
setCPUFeature(FEAT_SB);
- if (hwcap & HWCAP_SSBS)
+ if (hwcap & HWCAP_SSBS) {
+ setCPUFeature(FEAT_SSBS);
setCPUFeature(FEAT_SSBS2);
+ }
if (hwcap2 & HWCAP2_MTE) {
setCPUFeature(FEAT_MEMTAG);
setCPUFeature(FEAT_MEMTAG2);
}
- if (hwcap2 & HWCAP2_MTE3) {
- setCPUFeature(FEAT_MEMTAG);
- setCPUFeature(FEAT_MEMTAG2);
+ if (hwcap2 & HWCAP2_MTE3)
setCPUFeature(FEAT_MEMTAG3);
- }
if (hwcap2 & HWCAP2_SVEAES)
setCPUFeature(FEAT_SVE_AES);
- if (hwcap2 & HWCAP2_SVEPMULL) {
- setCPUFeature(FEAT_SVE_AES);
+ if (hwcap2 & HWCAP2_SVEPMULL)
setCPUFeature(FEAT_SVE_PMULL128);
- }
if (hwcap2 & HWCAP2_SVEBITPERM)
setCPUFeature(FEAT_SVE_BITPERM);
if (hwcap2 & HWCAP2_SVESHA3)
@@ -105,6 +95,8 @@ static void __init_cpu_features_constructor(unsigned long hwcap,
setCPUFeature(FEAT_WFXT);
if (hwcap2 & HWCAP2_SME)
setCPUFeature(FEAT_SME);
+ if (hwcap2 & HWCAP2_SME2)
+ setCPUFeature(FEAT_SME2);
if (hwcap2 & HWCAP2_SME_I16I64)
setCPUFeature(FEAT_SME_I64);
if (hwcap2 & HWCAP2_SME_F64F64)
@@ -113,86 +105,45 @@ static void __init_cpu_features_constructor(unsigned long hwcap,
setCPUFeature(FEAT_MOPS);
if (hwcap & HWCAP_CPUID) {
unsigned long ftr;
- getCPUFeature(ID_AA64PFR1_EL1, ftr);
- // ID_AA64PFR1_EL1.MTE >= 0b0001
- if (extractBits(ftr, 8, 4) >= 0x1)
- setCPUFeature(FEAT_MEMTAG);
- // ID_AA64PFR1_EL1.SSBS == 0b0001
- if (extractBits(ftr, 4, 4) == 0x1)
- setCPUFeature(FEAT_SSBS);
- // ID_AA64PFR1_EL1.SME == 0b0010
- if (extractBits(ftr, 24, 4) == 0x2)
- setCPUFeature(FEAT_SME2);
- getCPUFeature(ID_AA64PFR0_EL1, ftr);
- // ID_AA64PFR0_EL1.FP != 0b1111
- if (extractBits(ftr, 16, 4) != 0xF) {
- setCPUFeature(FEAT_FP);
- // ID_AA64PFR0_EL1.AdvSIMD has the same value as ID_AA64PFR0_EL1.FP
- setCPUFeature(FEAT_SIMD);
- }
- // ID_AA64PFR0_EL1.SVE != 0b0000
- if (extractBits(ftr, 32, 4) != 0x0) {
- // get ID_AA64ZFR0_EL1, that name supported
- // if sve enabled only
- getCPUFeature(S3_0_C0_C4_4, ftr);
- // ID_AA64ZFR0_EL1.SVEver == 0b0000
- if (extractBits(ftr, 0, 4) == 0x0)
- setCPUFeature(FEAT_SVE);
- // ID_AA64ZFR0_EL1.SVEver == 0b0001
- if (extractBits(ftr, 0, 4) == 0x1)
- setCPUFeature(FEAT_SVE2);
- // ID_AA64ZFR0_EL1.BF16 != 0b0000
- if (extractBits(ftr, 20, 4) != 0x0)
- setCPUFeature(FEAT_SVE_BF16);
- }
- getCPUFeature(ID_AA64ISAR0_EL1, ftr);
- // ID_AA64ISAR0_EL1.SHA3 != 0b0000
- if (extractBits(ftr, 32, 4) != 0x0)
- setCPUFeature(FEAT_SHA3);
+
getCPUFeature(ID_AA64ISAR1_EL1, ftr);
- // ID_AA64ISAR1_EL1.DPB >= 0b0001
- if (extractBits(ftr, 0, 4) >= 0x1)
- setCPUFeature(FEAT_DPB);
- // ID_AA64ISAR1_EL1.LRCPC != 0b0000
- if (extractBits(ftr, 20, 4) != 0x0)
- setCPUFeature(FEAT_RCPC);
- // ID_AA64ISAR1_EL1.LRCPC == 0b0011
- if (extractBits(ftr, 20, 4) == 0x3)
- setCPUFeature(FEAT_RCPC3);
- // ID_AA64ISAR1_EL1.SPECRES == 0b0001
- if (extractBits(ftr, 40, 4) == 0x2)
+ /* ID_AA64ISAR1_EL1.SPECRES >= 0b0001 */
+ if (extractBits(ftr, 40, 4) >= 0x1)
setCPUFeature(FEAT_PREDRES);
- // ID_AA64ISAR1_EL1.BF16 != 0b0000
- if (extractBits(ftr, 44, 4) != 0x0)
- setCPUFeature(FEAT_BF16);
- // ID_AA64ISAR1_EL1.LS64 >= 0b0001
+ /* ID_AA64ISAR1_EL1.LS64 >= 0b0001 */
if (extractBits(ftr, 60, 4) >= 0x1)
setCPUFeature(FEAT_LS64);
- // ID_AA64ISAR1_EL1.LS64 >= 0b0010
+ /* ID_AA64ISAR1_EL1.LS64 >= 0b0010 */
if (extractBits(ftr, 60, 4) >= 0x2)
setCPUFeature(FEAT_LS64_V);
- // ID_AA64ISAR1_EL1.LS64 >= 0b0011
+ /* ID_AA64ISAR1_EL1.LS64 >= 0b0011 */
if (extractBits(ftr, 60, 4) >= 0x3)
setCPUFeature(FEAT_LS64_ACCDATA);
- } else {
- // Set some features in case of no CPUID support
- if (hwcap & (HWCAP_FP | HWCAP_FPHP)) {
- setCPUFeature(FEAT_FP);
- // FP and AdvSIMD fields have the same value
- setCPUFeature(FEAT_SIMD);
- }
- if (hwcap & HWCAP_DCPOP || hwcap2 & HWCAP2_DCPODP)
- setCPUFeature(FEAT_DPB);
- if (hwcap & HWCAP_LRCPC || hwcap & HWCAP_ILRCPC)
- setCPUFeature(FEAT_RCPC);
- if (hwcap2 & HWCAP2_BF16 || hwcap2 & HWCAP2_EBF16)
- setCPUFeature(FEAT_BF16);
- if (hwcap2 & HWCAP2_SVEBF16)
- setCPUFeature(FEAT_SVE_BF16);
- if (hwcap2 & HWCAP2_SVE2 && hwcap & HWCAP_SVE)
- setCPUFeature(FEAT_SVE2);
- if (hwcap & HWCAP_SHA3)
- setCPUFeature(FEAT_SHA3);
}
+ if (hwcap & HWCAP_FP) {
+ setCPUFeature(FEAT_FP);
+ // FP and AdvSIMD fields have the same value
+ setCPUFeature(FEAT_SIMD);
+ }
+ if (hwcap & HWCAP_DCPOP)
+ setCPUFeature(FEAT_DPB);
+ if (hwcap & HWCAP_LRCPC)
+ setCPUFeature(FEAT_RCPC);
+ if (hwcap & HWCAP_ILRCPC)
+ setCPUFeature(FEAT_RCPC2);
+ if (hwcap2 & HWCAP2_LRCPC3)
+ setCPUFeature(FEAT_RCPC3);
+ if (hwcap2 & HWCAP2_BF16)
+ setCPUFeature(FEAT_BF16);
+ if (hwcap2 & HWCAP2_SVEBF16)
+ setCPUFeature(FEAT_SVE_BF16);
+ if (hwcap & HWCAP_SVE)
+ setCPUFeature(FEAT_SVE);
+ if (hwcap2 & HWCAP2_SVE2)
+ setCPUFeature(FEAT_SVE2);
+ if (hwcap & HWCAP_SHA3)
+ setCPUFeature(FEAT_SHA3);
setCPUFeature(FEAT_INIT);
+
+ __atomic_store_n(&__aarch64_cpu_features.features, feat, __ATOMIC_RELAXED);
}
diff --git a/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/sysauxv.inc b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/sysauxv.inc
index fb5722c4306..486f77a1e4d 100644
--- a/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/sysauxv.inc
+++ b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/fmv/sysauxv.inc
@@ -1,13 +1,13 @@
void __init_cpu_features_resolver(unsigned long hwcap,
const __ifunc_arg_t *arg) {
- if (__aarch64_cpu_features.features)
+ if (__atomic_load_n(&__aarch64_cpu_features.features, __ATOMIC_RELAXED))
return;
__init_cpu_features_constructor(hwcap, arg);
}
void CONSTRUCTOR_ATTRIBUTE __init_cpu_features(void) {
// CPU features already initialized.
- if (__aarch64_cpu_features.features)
+ if (__atomic_load_n(&__aarch64_cpu_features.features, __ATOMIC_RELAXED))
return;
unsigned long hwcap = getauxval(AT_HWCAP);
diff --git a/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/hwcap.inc b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/hwcap.inc
index 7ddc125b26d..41aba82ef95 100644
--- a/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/hwcap.inc
+++ b/contrib/libs/cxxsupp/builtins/cpu_model/aarch64/hwcap.inc
@@ -178,6 +178,12 @@
#ifndef HWCAP2_SVE_EBF16
#define HWCAP2_SVE_EBF16 (1ULL << 33)
#endif
+#ifndef HWCAP2_SME2
+#define HWCAP2_SME2 (1UL << 37)
+#endif
#ifndef HWCAP2_MOPS
#define HWCAP2_MOPS (1ULL << 43)
#endif
+#ifndef HWCAP2_LRCPC3
+#define HWCAP2_LRCPC3 (1UL << 46)
+#endif
diff --git a/contrib/libs/cxxsupp/builtins/cpu_model/x86.c b/contrib/libs/cxxsupp/builtins/cpu_model/x86.c
index 0750e29f989..b1c4abd9d11 100644
--- a/contrib/libs/cxxsupp/builtins/cpu_model/x86.c
+++ b/contrib/libs/cxxsupp/builtins/cpu_model/x86.c
@@ -59,6 +59,7 @@ enum ProcessorTypes {
INTEL_SIERRAFOREST,
INTEL_GRANDRIDGE,
INTEL_CLEARWATERFOREST,
+ AMDFAM1AH,
CPU_TYPE_MAX
};
@@ -97,6 +98,7 @@ enum ProcessorSubtypes {
INTEL_COREI7_ARROWLAKE,
INTEL_COREI7_ARROWLAKE_S,
INTEL_COREI7_PANTHERLAKE,
+ AMDFAM1AH_ZNVER5,
CPU_SUBTYPE_MAX
};
@@ -139,20 +141,88 @@ enum ProcessorFeatures {
FEATURE_AVX512BITALG,
FEATURE_AVX512BF16,
FEATURE_AVX512VP2INTERSECT,
-
- FEATURE_CMPXCHG16B = 46,
- FEATURE_F16C = 49,
+ // FIXME: Below Features has some missings comparing to gcc, it's because gcc
+ // has some not one-to-one mapped in llvm.
+ // FEATURE_3DNOW,
+ // FEATURE_3DNOWP,
+ FEATURE_ADX = 40,
+ // FEATURE_ABM,
+ FEATURE_CLDEMOTE = 42,
+ FEATURE_CLFLUSHOPT,
+ FEATURE_CLWB,
+ FEATURE_CLZERO,
+ FEATURE_CMPXCHG16B,
+ // FIXME: Not adding FEATURE_CMPXCHG8B is a workaround to make 'generic' as
+ // a cpu string with no X86_FEATURE_COMPAT features, which is required in
+ // current implementantion of cpu_specific/cpu_dispatch FMV feature.
+ // FEATURE_CMPXCHG8B,
+ FEATURE_ENQCMD = 48,
+ FEATURE_F16C,
+ FEATURE_FSGSBASE,
+ // FEATURE_FXSAVE,
+ // FEATURE_HLE,
+ // FEATURE_IBT,
FEATURE_LAHF_LM = 54,
FEATURE_LM,
- FEATURE_WP,
+ FEATURE_LWP,
FEATURE_LZCNT,
FEATURE_MOVBE,
-
- FEATURE_AVX512FP16 = 94,
+ FEATURE_MOVDIR64B,
+ FEATURE_MOVDIRI,
+ FEATURE_MWAITX,
+ // FEATURE_OSXSAVE,
+ FEATURE_PCONFIG = 63,
+ FEATURE_PKU,
+ FEATURE_PREFETCHWT1,
+ FEATURE_PRFCHW,
+ FEATURE_PTWRITE,
+ FEATURE_RDPID,
+ FEATURE_RDRND,
+ FEATURE_RDSEED,
+ FEATURE_RTM,
+ FEATURE_SERIALIZE,
+ FEATURE_SGX,
+ FEATURE_SHA,
+ FEATURE_SHSTK,
+ FEATURE_TBM,
+ FEATURE_TSXLDTRK,
+ FEATURE_VAES,
+ FEATURE_WAITPKG,
+ FEATURE_WBNOINVD,
+ FEATURE_XSAVE,
+ FEATURE_XSAVEC,
+ FEATURE_XSAVEOPT,
+ FEATURE_XSAVES,
+ FEATURE_AMX_TILE,
+ FEATURE_AMX_INT8,
+ FEATURE_AMX_BF16,
+ FEATURE_UINTR,
+ FEATURE_HRESET,
+ FEATURE_KL,
+ // FEATURE_AESKLE,
+ FEATURE_WIDEKL = 92,
+ FEATURE_AVXVNNI,
+ FEATURE_AVX512FP16,
FEATURE_X86_64_BASELINE,
FEATURE_X86_64_V2,
FEATURE_X86_64_V3,
FEATURE_X86_64_V4,
+ FEATURE_AVXIFMA,
+ FEATURE_AVXVNNIINT8,
+ FEATURE_AVXNECONVERT,
+ FEATURE_CMPCCXADD,
+ FEATURE_AMX_FP16,
+ FEATURE_PREFETCHI,
+ FEATURE_RAOINT,
+ FEATURE_AMX_COMPLEX,
+ FEATURE_AVXVNNIINT16,
+ FEATURE_SM3,
+ FEATURE_SHA512,
+ FEATURE_SM4,
+ FEATURE_APXF,
+ FEATURE_USERMSR,
+ FEATURE_AVX10_1_256,
+ FEATURE_AVX10_1_512,
CPU_FEATURE_MAX
};
@@ -299,13 +369,13 @@ static void detectX86FamilyModel(unsigned EAX, unsigned *Family,
}
}
+#define testFeature(F) (Features[F / 32] & (1 << (F % 32))) != 0
+
static const char *getIntelProcessorTypeAndSubtype(unsigned Family,
unsigned Model,
const unsigned *Features,
unsigned *Type,
unsigned *Subtype) {
-#define testFeature(F) (Features[F / 32] & (1 << (F % 32))) != 0
-
// We select CPU strings to match the code in Host.cpp, but we don't use them
// in compiler-rt.
const char *CPU = 0;
@@ -594,14 +664,48 @@ static const char *getAMDProcessorTypeAndSubtype(unsigned Family,
const unsigned *Features,
unsigned *Type,
unsigned *Subtype) {
- // We select CPU strings to match the code in Host.cpp, but we don't use them
- // in compiler-rt.
const char *CPU = 0;
switch (Family) {
+ case 4:
+ CPU = "i486";
+ break;
+ case 5:
+ CPU = "pentium";
+ switch (Model) {
+ case 6:
+ case 7:
+ CPU = "k6";
+ break;
+ case 8:
+ CPU = "k6-2";
+ break;
+ case 9:
+ case 13:
+ CPU = "k6-3";
+ break;
+ case 10:
+ CPU = "geode";
+ break;
+ }
+ break;
+ case 6:
+ if (testFeature(FEATURE_SSE)) {
+ CPU = "athlon-xp";
+ break;
+ }
+ CPU = "athlon";
+ break;
+ case 15:
+ if (testFeature(FEATURE_SSE3)) {
+ CPU = "k8-sse3";
+ break;
+ }
+ CPU = "k8";
+ break;
case 16:
CPU = "amdfam10";
- *Type = AMDFAM10H;
+ *Type = AMDFAM10H; // "amdfam10"
switch (Model) {
case 2:
*Subtype = AMDFAM10H_BARCELONA;
@@ -677,7 +781,7 @@ static const char *getAMDProcessorTypeAndSubtype(unsigned Family,
case 25:
CPU = "znver3";
*Type = AMDFAM19H;
- if ((Model <= 0x0f) || (Model >= 0x20 && Model <= 0x2f) ||
+ if (Model <= 0x0f || (Model >= 0x20 && Model <= 0x2f) ||
(Model >= 0x30 && Model <= 0x3f) || (Model >= 0x40 && Model <= 0x4f) ||
(Model >= 0x50 && Model <= 0x5f)) {
// Family 19h Models 00h-0Fh (Genesis, Chagall) Zen 3
@@ -701,6 +805,24 @@ static const char *getAMDProcessorTypeAndSubtype(unsigned Family,
break; // "znver4"
}
break; // family 19h
+ case 26:
+ CPU = "znver5";
+ *Type = AMDFAM1AH;
+ if (Model <= 0x77) {
+ // Models 00h-0Fh (Breithorn).
+ // Models 10h-1Fh (Breithorn-Dense).
+ // Models 20h-2Fh (Strix 1).
+ // Models 30h-37h (Strix 2).
+ // Models 38h-3Fh (Strix 3).
+ // Models 40h-4Fh (Granite Ridge).
+ // Models 50h-5Fh (Weisshorn).
+ // Models 60h-6Fh (Krackan1).
+ // Models 70h-77h (Sarlak).
+ CPU = "znver5";
+ *Subtype = AMDFAM1AH_ZNVER5;
+ break; // "znver5"
+ }
+ break;
default:
break; // Unknown AMD CPU.
}
@@ -708,6 +830,8 @@ static const char *getAMDProcessorTypeAndSubtype(unsigned Family,
return CPU;
}
+#undef testFeature
+
static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
unsigned *Features) {
unsigned EAX = 0, EBX = 0;
@@ -746,13 +870,15 @@ static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
setFeature(FEATURE_AES);
if ((ECX >> 29) & 1)
setFeature(FEATURE_F16C);
+ if ((ECX >> 30) & 1)
+ setFeature(FEATURE_RDRND);
// If CPUID indicates support for XSAVE, XRESTORE and AVX, and XGETBV
// indicates that the AVX registers will be saved and restored on context
// switch, then we have full AVX support.
const unsigned AVXBits = (1 << 27) | (1 << 28);
- bool HasAVX = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&
- ((EAX & 0x6) == 0x6);
+ bool HasAVXSave = ((ECX & AVXBits) == AVXBits) && !getX86XCR0(&EAX, &EDX) &&
+ ((EAX & 0x6) == 0x6);
#if defined(__APPLE__)
// Darwin lazily saves the AVX512 context on first use: trust that the OS will
// save the AVX512 context if we use AVX512 instructions, even the bit is not
@@ -760,45 +886,76 @@ static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
bool HasAVX512Save = true;
#else
// AVX512 requires additional context to be saved by the OS.
- bool HasAVX512Save = HasAVX && ((EAX & 0xe0) == 0xe0);
+ bool HasAVX512Save = HasAVXSave && ((EAX & 0xe0) == 0xe0);
#endif
+ // AMX requires additional context to be saved by the OS.
+ const unsigned AMXBits = (1 << 17) | (1 << 18);
+ bool HasXSave = ((ECX >> 27) & 1) && !getX86XCR0(&EAX, &EDX);
+ bool HasAMXSave = HasXSave && ((EAX & AMXBits) == AMXBits);
- if (HasAVX)
+ if (HasAVXSave)
setFeature(FEATURE_AVX);
+ if (((ECX >> 26) & 1) && HasAVXSave)
+ setFeature(FEATURE_XSAVE);
+
bool HasLeaf7 =
MaxLeaf >= 0x7 && !getX86CpuIDAndInfoEx(0x7, 0x0, &EAX, &EBX, &ECX, &EDX);
+ if (HasLeaf7 && ((EBX >> 0) & 1))
+ setFeature(FEATURE_FSGSBASE);
+ if (HasLeaf7 && ((EBX >> 2) & 1))
+ setFeature(FEATURE_SGX);
if (HasLeaf7 && ((EBX >> 3) & 1))
setFeature(FEATURE_BMI);
- if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX)
+ if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVXSave)
setFeature(FEATURE_AVX2);
if (HasLeaf7 && ((EBX >> 8) & 1))
setFeature(FEATURE_BMI2);
+ if (HasLeaf7 && ((EBX >> 11) & 1))
+ setFeature(FEATURE_RTM);
if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512F);
if (HasLeaf7 && ((EBX >> 17) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512DQ);
+ if (HasLeaf7 && ((EBX >> 18) & 1))
+ setFeature(FEATURE_RDSEED);
+ if (HasLeaf7 && ((EBX >> 19) & 1))
+ setFeature(FEATURE_ADX);
if (HasLeaf7 && ((EBX >> 21) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512IFMA);
+ if (HasLeaf7 && ((EBX >> 24) & 1))
+ setFeature(FEATURE_CLWB);
if (HasLeaf7 && ((EBX >> 26) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512PF);
if (HasLeaf7 && ((EBX >> 27) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512ER);
if (HasLeaf7 && ((EBX >> 28) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512CD);
+ if (HasLeaf7 && ((EBX >> 29) & 1))
+ setFeature(FEATURE_SHA);
if (HasLeaf7 && ((EBX >> 30) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512BW);
if (HasLeaf7 && ((EBX >> 31) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512VL);
+ if (HasLeaf7 && ((ECX >> 0) & 1))
+ setFeature(FEATURE_PREFETCHWT1);
if (HasLeaf7 && ((ECX >> 1) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512VBMI);
+ if (HasLeaf7 && ((ECX >> 4) & 1))
+ setFeature(FEATURE_PKU);
+ if (HasLeaf7 && ((ECX >> 5) & 1))
+ setFeature(FEATURE_WAITPKG);
if (HasLeaf7 && ((ECX >> 6) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512VBMI2);
+ if (HasLeaf7 && ((ECX >> 7) & 1))
+ setFeature(FEATURE_SHSTK);
if (HasLeaf7 && ((ECX >> 8) & 1))
setFeature(FEATURE_GFNI);
- if (HasLeaf7 && ((ECX >> 10) & 1) && HasAVX)
+ if (HasLeaf7 && ((ECX >> 9) & 1) && HasAVXSave)
+ setFeature(FEATURE_VAES);
+ if (HasLeaf7 && ((ECX >> 10) & 1) && HasAVXSave)
setFeature(FEATURE_VPCLMULQDQ);
if (HasLeaf7 && ((ECX >> 11) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512VNNI);
@@ -806,23 +963,100 @@ static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
setFeature(FEATURE_AVX512BITALG);
if (HasLeaf7 && ((ECX >> 14) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512VPOPCNTDQ);
+ if (HasLeaf7 && ((ECX >> 22) & 1))
+ setFeature(FEATURE_RDPID);
+ if (HasLeaf7 && ((ECX >> 23) & 1))
+ setFeature(FEATURE_KL);
+ if (HasLeaf7 && ((ECX >> 25) & 1))
+ setFeature(FEATURE_CLDEMOTE);
+ if (HasLeaf7 && ((ECX >> 27) & 1))
+ setFeature(FEATURE_MOVDIRI);
+ if (HasLeaf7 && ((ECX >> 28) & 1))
+ setFeature(FEATURE_MOVDIR64B);
+ if (HasLeaf7 && ((ECX >> 29) & 1))
+ setFeature(FEATURE_ENQCMD);
if (HasLeaf7 && ((EDX >> 2) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX5124VNNIW);
if (HasLeaf7 && ((EDX >> 3) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX5124FMAPS);
+ if (HasLeaf7 && ((EDX >> 5) & 1))
+ setFeature(FEATURE_UINTR);
if (HasLeaf7 && ((EDX >> 8) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512VP2INTERSECT);
+ if (HasLeaf7 && ((EDX >> 14) & 1))
+ setFeature(FEATURE_SERIALIZE);
+ if (HasLeaf7 && ((EDX >> 16) & 1))
+ setFeature(FEATURE_TSXLDTRK);
+ if (HasLeaf7 && ((EDX >> 18) & 1))
+ setFeature(FEATURE_PCONFIG);
+ if (HasLeaf7 && ((EDX >> 22) & 1) && HasAMXSave)
+ setFeature(FEATURE_AMX_BF16);
if (HasLeaf7 && ((EDX >> 23) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512FP16);
+ if (HasLeaf7 && ((EDX >> 24) & 1) && HasAMXSave)
+ setFeature(FEATURE_AMX_TILE);
+ if (HasLeaf7 && ((EDX >> 25) & 1) && HasAMXSave)
+ setFeature(FEATURE_AMX_INT8);
// EAX from subleaf 0 is the maximum subleaf supported. Some CPUs don't
// return all 0s for invalid subleaves so check the limit.
bool HasLeaf7Subleaf1 =
HasLeaf7 && EAX >= 1 &&
!getX86CpuIDAndInfoEx(0x7, 0x1, &EAX, &EBX, &ECX, &EDX);
+ if (HasLeaf7Subleaf1 && ((EAX >> 0) & 1))
+ setFeature(FEATURE_SHA512);
+ if (HasLeaf7Subleaf1 && ((EAX >> 1) & 1))
+ setFeature(FEATURE_SM3);
+ if (HasLeaf7Subleaf1 && ((EAX >> 2) & 1))
+ setFeature(FEATURE_SM4);
+ if (HasLeaf7Subleaf1 && ((EAX >> 3) & 1))
+ setFeature(FEATURE_RAOINT);
+ if (HasLeaf7Subleaf1 && ((EAX >> 4) & 1) && HasAVXSave)
+ setFeature(FEATURE_AVXVNNI);
if (HasLeaf7Subleaf1 && ((EAX >> 5) & 1) && HasAVX512Save)
setFeature(FEATURE_AVX512BF16);
+ if (HasLeaf7Subleaf1 && ((EAX >> 7) & 1))
+ setFeature(FEATURE_CMPCCXADD);
+ if (HasLeaf7Subleaf1 && ((EAX >> 21) & 1) && HasAMXSave)
+ setFeature(FEATURE_AMX_FP16);
+ if (HasLeaf7Subleaf1 && ((EAX >> 22) & 1))
+ setFeature(FEATURE_HRESET);
+ if (HasLeaf7Subleaf1 && ((EAX >> 23) & 1) && HasAVXSave)
+ setFeature(FEATURE_AVXIFMA);
+
+ if (HasLeaf7Subleaf1 && ((EDX >> 4) & 1) && HasAVXSave)
+ setFeature(FEATURE_AVXVNNIINT8);
+ if (HasLeaf7Subleaf1 && ((EDX >> 5) & 1) && HasAVXSave)
+ setFeature(FEATURE_AVXNECONVERT);
+ if (HasLeaf7Subleaf1 && ((EDX >> 8) & 1) && HasAMXSave)
+ setFeature(FEATURE_AMX_COMPLEX);
+ if (HasLeaf7Subleaf1 && ((EDX >> 10) & 1) && HasAVXSave)
+ setFeature(FEATURE_AVXVNNIINT16);
+ if (HasLeaf7Subleaf1 && ((EDX >> 14) & 1))
+ setFeature(FEATURE_PREFETCHI);
+ if (HasLeaf7Subleaf1 && ((EDX >> 15) & 1))
+ setFeature(FEATURE_USERMSR);
+ if (HasLeaf7Subleaf1 && ((EDX >> 19) & 1))
+ setFeature(FEATURE_AVX10_1_256);
+ if (HasLeaf7Subleaf1 && ((EDX >> 21) & 1))
+ setFeature(FEATURE_APXF);
+
+ unsigned MaxLevel;
+ getX86CpuIDAndInfo(0, &MaxLevel, &EBX, &ECX, &EDX);
+ bool HasLeafD = MaxLevel >= 0xd &&
+ !getX86CpuIDAndInfoEx(0xd, 0x1, &EAX, &EBX, &ECX, &EDX);
+ if (HasLeafD && ((EAX >> 0) & 1) && HasAVXSave)
+ setFeature(FEATURE_XSAVEOPT);
+ if (HasLeafD && ((EAX >> 1) & 1) && HasAVXSave)
+ setFeature(FEATURE_XSAVEC);
+ if (HasLeafD && ((EAX >> 3) & 1) && HasAVXSave)
+ setFeature(FEATURE_XSAVES);
+
+ bool HasLeaf24 =
+ MaxLevel >= 0x24 && !getX86CpuIDAndInfo(0x24, &EAX, &EBX, &ECX, &EDX);
+ if (HasLeaf7Subleaf1 && ((EDX >> 19) & 1) && HasLeaf24 && ((EBX >> 18) & 1))
+ setFeature(FEATURE_AVX10_1_512);
unsigned MaxExtLevel;
getX86CpuIDAndInfo(0x80000000, &MaxExtLevel, &EBX, &ECX, &EDX);
@@ -836,14 +1070,40 @@ static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
setFeature(FEATURE_LZCNT);
if (((ECX >> 6) & 1))
setFeature(FEATURE_SSE4_A);
+ if (((ECX >> 8) & 1))
+ setFeature(FEATURE_PRFCHW);
if (((ECX >> 11) & 1))
setFeature(FEATURE_XOP);
+ if (((ECX >> 15) & 1))
+ setFeature(FEATURE_LWP);
if (((ECX >> 16) & 1))
setFeature(FEATURE_FMA4);
+ if (((ECX >> 21) & 1))
+ setFeature(FEATURE_TBM);
+ if (((ECX >> 29) & 1))
+ setFeature(FEATURE_MWAITX);
+
if (((EDX >> 29) & 1))
setFeature(FEATURE_LM);
}
+ bool HasExtLeaf8 = MaxExtLevel >= 0x80000008 &&
+ !getX86CpuIDAndInfo(0x80000008, &EAX, &EBX, &ECX, &EDX);
+ if (HasExtLeaf8 && ((EBX >> 0) & 1))
+ setFeature(FEATURE_CLZERO);
+ if (HasExtLeaf8 && ((EBX >> 9) & 1))
+ setFeature(FEATURE_WBNOINVD);
+
+ bool HasLeaf14 = MaxLevel >= 0x14 &&
+ !getX86CpuIDAndInfoEx(0x14, 0x0, &EAX, &EBX, &ECX, &EDX);
+ if (HasLeaf14 && ((EBX >> 4) & 1))
+ setFeature(FEATURE_PTWRITE);
+
+ bool HasLeaf19 =
+ MaxLevel >= 0x19 && !getX86CpuIDAndInfo(0x19, &EAX, &EBX, &ECX, &EDX);
+ if (HasLeaf7 && HasLeaf19 && ((EBX >> 2) & 1))
+ setFeature(FEATURE_WIDEKL);
+
if (hasFeature(FEATURE_LM) && hasFeature(FEATURE_SSE2)) {
setFeature(FEATURE_X86_64_BASELINE);
if (hasFeature(FEATURE_CMPXCHG16B) && hasFeature(FEATURE_POPCNT) &&
diff --git a/contrib/libs/cxxsupp/builtins/divtc3.c b/contrib/libs/cxxsupp/builtins/divtc3.c
index 099de5802da..c393de81533 100644
--- a/contrib/libs/cxxsupp/builtins/divtc3.c
+++ b/contrib/libs/cxxsupp/builtins/divtc3.c
@@ -13,7 +13,7 @@
#define QUAD_PRECISION
#include "fp_lib.h"
-#if defined(CRT_HAS_F128)
+#if defined(CRT_HAS_128BIT) && defined(CRT_HAS_F128)
// Returns: the quotient of (a + ib) / (c + id)
diff --git a/contrib/libs/cxxsupp/builtins/extendbfsf2.c b/contrib/libs/cxxsupp/builtins/extendbfsf2.c
new file mode 100644
index 00000000000..e159d7997f6
--- /dev/null
+++ b/contrib/libs/cxxsupp/builtins/extendbfsf2.c
@@ -0,0 +1,13 @@
+//===-- lib/extendbfsf2.c - bfloat -> single conversion -----------*- C -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#define SRC_BFLOAT16
+#define DST_SINGLE
+#include "fp_extend_impl.inc"
+
+COMPILER_RT_ABI float __extendbfsf2(src_t a) { return __extendXfYf2__(a); }
diff --git a/contrib/libs/cxxsupp/builtins/fp_add_impl.inc b/contrib/libs/cxxsupp/builtins/fp_add_impl.inc
index 7133358df9b..d20599921e7 100644
--- a/contrib/libs/cxxsupp/builtins/fp_add_impl.inc
+++ b/contrib/libs/cxxsupp/builtins/fp_add_impl.inc
@@ -91,7 +91,7 @@ static __inline fp_t __addXf3__(fp_t a, fp_t b) {
// Shift the significand of b by the difference in exponents, with a sticky
// bottom bit to get rounding correct.
- const unsigned int align = aExponent - bExponent;
+ const unsigned int align = (unsigned int)(aExponent - bExponent);
if (align) {
if (align < typeWidth) {
const bool sticky = (bSignificand << (typeWidth - align)) != 0;
diff --git a/contrib/libs/cxxsupp/builtins/fp_extend.h b/contrib/libs/cxxsupp/builtins/fp_extend.h
index 95ea2a7ac4b..22bf2b2514e 100644
--- a/contrib/libs/cxxsupp/builtins/fp_extend.h
+++ b/contrib/libs/cxxsupp/builtins/fp_extend.h
@@ -37,16 +37,7 @@ static const int srcSigFracBits = 52;
// srcBits - srcSigFracBits - 1
static const int srcExpBits = 11;
-static inline int src_rep_t_clz_impl(src_rep_t a) {
-#if defined __LP64__
- return __builtin_clzl(a);
-#else
- if (a & REP_C(0xffffffff00000000))
- return clzsi(a >> 32);
- else
- return 32 + clzsi(a & REP_C(0xffffffff));
-#endif
-}
+static inline int src_rep_t_clz_impl(src_rep_t a) { return __builtin_clzll(a); }
#define src_rep_t_clz src_rep_t_clz_impl
#elif defined SRC_80
@@ -81,6 +72,21 @@ static inline int src_rep_t_clz_impl(src_rep_t a) {
#define src_rep_t_clz src_rep_t_clz_impl
+#elif defined SRC_BFLOAT16
+#ifdef COMPILER_RT_HAS_BFLOAT16
+typedef __bf16 src_t;
+#else
+typedef uint16_t src_t;
+#endif
+typedef uint16_t src_rep_t;
+#define SRC_REP_C UINT16_C
+static const int srcBits = sizeof(src_t) * CHAR_BIT;
+static const int srcSigFracBits = 7;
+// -1 accounts for the sign bit.
+// srcBits - srcSigFracBits - 1
+static const int srcExpBits = 8;
+#define src_rep_t_clz __builtin_clz
+
#else
#error Source should be half, single, or double precision!
#endif // end source precision
diff --git a/contrib/libs/cxxsupp/builtins/fp_fixint_impl.inc b/contrib/libs/cxxsupp/builtins/fp_fixint_impl.inc
index 3556bad9990..2f2f77ce781 100644
--- a/contrib/libs/cxxsupp/builtins/fp_fixint_impl.inc
+++ b/contrib/libs/cxxsupp/builtins/fp_fixint_impl.inc
@@ -34,7 +34,7 @@ static __inline fixint_t __fixint(fp_t a) {
// If 0 <= exponent < significandBits, right shift to get the result.
// Otherwise, shift left.
if (exponent < significandBits)
- return sign * (significand >> (significandBits - exponent));
+ return (fixint_t)(sign * (significand >> (significandBits - exponent)));
else
- return sign * ((fixuint_t)significand << (exponent - significandBits));
+ return (fixint_t)(sign * ((fixuint_t)significand << (exponent - significandBits)));
}
diff --git a/contrib/libs/cxxsupp/builtins/fp_lib.h b/contrib/libs/cxxsupp/builtins/fp_lib.h
index c4f0a5b9587..b2a89506135 100644
--- a/contrib/libs/cxxsupp/builtins/fp_lib.h
+++ b/contrib/libs/cxxsupp/builtins/fp_lib.h
@@ -43,8 +43,8 @@ static __inline int rep_clz(rep_t a) { return clzsi(a); }
// 32x32 --> 64 bit multiply
static __inline void wideMultiply(rep_t a, rep_t b, rep_t *hi, rep_t *lo) {
const uint64_t product = (uint64_t)a * b;
- *hi = product >> 32;
- *lo = product;
+ *hi = (rep_t)(product >> 32);
+ *lo = (rep_t)product;
}
COMPILER_RT_ABI fp_t __addsf3(fp_t a, fp_t b);
@@ -58,16 +58,7 @@ typedef double fp_t;
#define REP_C UINT64_C
#define significandBits 52
-static __inline int rep_clz(rep_t a) {
-#if defined __LP64__
- return __builtin_clzl(a);
-#else
- if (a & REP_C(0xffffffff00000000))
- return clzsi(a >> 32);
- else
- return 32 + clzsi(a & REP_C(0xffffffff));
-#endif
-}
+static inline int rep_clz(rep_t a) { return __builtin_clzll(a); }
#define loWord(a) (a & 0xffffffffU)
#define hiWord(a) (a >> 32)
@@ -239,7 +230,7 @@ static __inline int normalize(rep_t *significand) {
return 1 - shift;
}
-static __inline void wideLeftShift(rep_t *hi, rep_t *lo, int count) {
+static __inline void wideLeftShift(rep_t *hi, rep_t *lo, unsigned int count) {
*hi = *hi << count | *lo >> (typeWidth - count);
*lo = *lo << count;
}
diff --git a/contrib/libs/cxxsupp/builtins/int_types.h b/contrib/libs/cxxsupp/builtins/int_types.h
index ca97391fc28..48862f36421 100644
--- a/contrib/libs/cxxsupp/builtins/int_types.h
+++ b/contrib/libs/cxxsupp/builtins/int_types.h
@@ -107,8 +107,8 @@ typedef union {
static __inline ti_int make_ti(di_int h, di_int l) {
twords r;
- r.s.high = h;
- r.s.low = l;
+ r.s.high = (du_int)h;
+ r.s.low = (du_int)l;
return r.all;
}
diff --git a/contrib/libs/cxxsupp/builtins/multc3.c b/contrib/libs/cxxsupp/builtins/multc3.c
index 61a3f45e472..a89832f0e88 100644
--- a/contrib/libs/cxxsupp/builtins/multc3.c
+++ b/contrib/libs/cxxsupp/builtins/multc3.c
@@ -15,7 +15,7 @@
#include "int_lib.h"
#include "int_math.h"
-#if defined(CRT_HAS_F128)
+#if defined(CRT_HAS_128BIT) && defined(CRT_HAS_F128)
// Returns: the product of a + ib and c + id
diff --git a/contrib/libs/cxxsupp/builtins/os_version_check.c b/contrib/libs/cxxsupp/builtins/os_version_check.c
index 182eabe7a6a..01fae834ab2 100644
--- a/contrib/libs/cxxsupp/builtins/os_version_check.c
+++ b/contrib/libs/cxxsupp/builtins/os_version_check.c
@@ -316,8 +316,8 @@ int32_t __isOSVersionAtLeast(int32_t Major, int32_t Minor, int32_t Subminor) {
static pthread_once_t once = PTHREAD_ONCE_INIT;
pthread_once(&once, readSystemProperties);
- return SdkVersion >= Major ||
- (IsPreRelease && Major == __ANDROID_API_FUTURE__);
+ // Allow all on pre-release. Note that we still rely on compile-time checks.
+ return SdkVersion >= Major || IsPreRelease;
}
#else
diff --git a/contrib/libs/cxxsupp/builtins/riscv/restore.S b/contrib/libs/cxxsupp/builtins/riscv/restore.S
index 6f43842c8ca..d87dfc1ac71 100644
--- a/contrib/libs/cxxsupp/builtins/riscv/restore.S
+++ b/contrib/libs/cxxsupp/builtins/riscv/restore.S
@@ -22,7 +22,7 @@
#if __riscv_xlen == 32
-#ifndef __riscv_32e
+#ifndef __riscv_abi_rve
.globl __riscv_restore_12
.type __riscv_restore_12,@function
@@ -109,7 +109,7 @@ __riscv_restore_0:
#elif __riscv_xlen == 64
-#ifndef __riscv_64e
+#ifndef __riscv_abi_rve
.globl __riscv_restore_12
.type __riscv_restore_12,@function
diff --git a/contrib/libs/cxxsupp/builtins/riscv/save.S b/contrib/libs/cxxsupp/builtins/riscv/save.S
index 3e044179ff7..6324e05e971 100644
--- a/contrib/libs/cxxsupp/builtins/riscv/save.S
+++ b/contrib/libs/cxxsupp/builtins/riscv/save.S
@@ -18,7 +18,7 @@
#if __riscv_xlen == 32
-#ifndef __riscv_32e
+#ifndef __riscv_abi_rve
.globl __riscv_save_12
.type __riscv_save_12,@function
@@ -115,7 +115,7 @@ __riscv_save_0:
#elif __riscv_xlen == 64
-#ifndef __riscv_64e
+#ifndef __riscv_abi_rve
.globl __riscv_save_12
.type __riscv_save_12,@function
diff --git a/contrib/libs/cxxsupp/builtins/trampoline_setup.c b/contrib/libs/cxxsupp/builtins/trampoline_setup.c
index 844eb279441..830e25e4c03 100644
--- a/contrib/libs/cxxsupp/builtins/trampoline_setup.c
+++ b/contrib/libs/cxxsupp/builtins/trampoline_setup.c
@@ -41,3 +41,45 @@ COMPILER_RT_ABI void __trampoline_setup(uint32_t *trampOnStack,
__clear_cache(trampOnStack, &trampOnStack[10]);
}
#endif // __powerpc__ && !defined(__powerpc64__)
+
+// The AArch64 compiler generates calls to __trampoline_setup() when creating
+// trampoline functions on the stack for use with nested functions.
+// This function creates a custom 36-byte trampoline function on the stack
+// which loads x18 with a pointer to the outer function's locals
+// and then jumps to the target nested function.
+// Note: x18 is a reserved platform register on Windows and macOS.
+
+#if defined(__aarch64__) && defined(__ELF__)
+COMPILER_RT_ABI void __trampoline_setup(uint32_t *trampOnStack,
+ int trampSizeAllocated,
+ const void *realFunc, void *localsPtr) {
+ // This should never happen, but if compiler did not allocate
+ // enough space on stack for the trampoline, abort.
+ if (trampSizeAllocated < 36)
+ compilerrt_abort();
+
+ // create trampoline
+ // Load realFunc into x17. mov/movk 16 bits at a time.
+ trampOnStack[0] =
+ 0xd2800000u | ((((uint64_t)realFunc >> 0) & 0xffffu) << 5) | 0x11;
+ trampOnStack[1] =
+ 0xf2a00000u | ((((uint64_t)realFunc >> 16) & 0xffffu) << 5) | 0x11;
+ trampOnStack[2] =
+ 0xf2c00000u | ((((uint64_t)realFunc >> 32) & 0xffffu) << 5) | 0x11;
+ trampOnStack[3] =
+ 0xf2e00000u | ((((uint64_t)realFunc >> 48) & 0xffffu) << 5) | 0x11;
+ // Load localsPtr into x18
+ trampOnStack[4] =
+ 0xd2800000u | ((((uint64_t)localsPtr >> 0) & 0xffffu) << 5) | 0x12;
+ trampOnStack[5] =
+ 0xf2a00000u | ((((uint64_t)localsPtr >> 16) & 0xffffu) << 5) | 0x12;
+ trampOnStack[6] =
+ 0xf2c00000u | ((((uint64_t)localsPtr >> 32) & 0xffffu) << 5) | 0x12;
+ trampOnStack[7] =
+ 0xf2e00000u | ((((uint64_t)localsPtr >> 48) & 0xffffu) << 5) | 0x12;
+ trampOnStack[8] = 0xd61f0220; // br x17
+
+ // Clear instruction cache.
+ __clear_cache(trampOnStack, &trampOnStack[9]);
+}
+#endif // defined(__aarch64__) && !defined(__APPLE__) && !defined(_WIN64)
diff --git a/contrib/libs/cxxsupp/builtins/ya.make b/contrib/libs/cxxsupp/builtins/ya.make
index 5f9c60552aa..ae250c5db79 100644
--- a/contrib/libs/cxxsupp/builtins/ya.make
+++ b/contrib/libs/cxxsupp/builtins/ya.make
@@ -12,9 +12,9 @@ LICENSE(
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-VERSION(18.1.8)
+VERSION(19.1.3)
-ORIGINAL_SOURCE(https://github.com/llvm/llvm-project/releases/download/llvmorg-18.1.8/compiler-rt-18.1.8.src.tar.xz)
+ORIGINAL_SOURCE(https://github.com/llvm/llvm-project/releases/download/llvmorg-19.1.3/compiler-rt-19.1.3.src.tar.xz)
NO_COMPILER_WARNINGS()
@@ -65,7 +65,9 @@ IF (ARCH_AARCH64)
aarch64/chkstk.S
aarch64/fp_mode.c
aarch64/sme-abi-init.c
+ aarch64/sme-abi-vg.c
aarch64/sme-abi.S
+ aarch64/sme-libc-mem-routines.S
absvdi2.c
absvsi2.c
absvti2.c
@@ -117,6 +119,7 @@ IF (ARCH_AARCH64)
emutls.c
enable_execute_stack.c
eprintf.c
+ extendbfsf2.c
extenddftf2.c
extendhfsf2.c
extendhftf2.c
@@ -284,6 +287,7 @@ ELSEIF (ARCH_X86_64)
emutls.c
enable_execute_stack.c
eprintf.c
+ extendbfsf2.c
extenddftf2.c
extendhfsf2.c
extendhftf2.c
@@ -467,6 +471,7 @@ ELSE()
emutls.c
enable_execute_stack.c
eprintf.c
+ extendbfsf2.c
extenddftf2.c
extendhfsf2.c
extendhftf2.c
diff --git a/contrib/libs/cxxsupp/libcxxrt/exception.cc b/contrib/libs/cxxsupp/libcxxrt/exception.cc
index 2fe90c3e1c6..97f499f882c 100644
--- a/contrib/libs/cxxsupp/libcxxrt/exception.cc
+++ b/contrib/libs/cxxsupp/libcxxrt/exception.cc
@@ -811,7 +811,7 @@ static void report_failure(_Unwind_Reason_Code err, __cxa_exception *thrown_exce
case _URC_END_OF_STACK:
__cxa_begin_catch (&(thrown_exception->unwindHeader));
std::terminate();
- fprintf(stderr, "uncaught exception:\n address -> %p\n",
+ fprintf(stderr, "Terminating due to uncaught exception %p",
static_cast<void*>(thrown_exception));
thrown_exception = realExceptionFromException(thrown_exception);
static const __class_type_info *e_ti =
@@ -825,7 +825,7 @@ static void report_failure(_Unwind_Reason_Code err, __cxa_exception *thrown_exce
throw_ti));
if (e)
{
- fprintf(stderr, " what() -> \"%s\"\n", e->what());
+ fprintf(stderr, " '%s'", e->what());
}
}
@@ -834,7 +834,7 @@ static void report_failure(_Unwind_Reason_Code err, __cxa_exception *thrown_exce
const char *mangled = thrown_exception->exceptionType->name();
int status;
demangled = __cxa_demangle(mangled, demangled, &bufferSize, &status);
- fprintf(stderr, " type -> %s\n",
+ fprintf(stderr, " of type %s\n",
status == 0 ? demangled : mangled);
if (status == 0) { free(demangled); }
// Print a back trace if no handler is found.
diff --git a/contrib/libs/cxxsupp/libsan/ya.make b/contrib/libs/cxxsupp/libsan/ya.make
index e770d0ac3df..016fa270d29 100644
--- a/contrib/libs/cxxsupp/libsan/ya.make
+++ b/contrib/libs/cxxsupp/libsan/ya.make
@@ -12,8 +12,6 @@ NO_SANITIZE()
NO_SANITIZE_COVERAGE()
-SUBSCRIBER(somov)
-
RUN_PYTHON3(
generate_symbolizer.py ${CXX_COMPILER}
STDOUT symbolizer.c
diff --git a/contrib/restricted/aws/aws-c-auth/.yandex_meta/__init__.py b/contrib/restricted/aws/aws-c-auth/.yandex_meta/__init__.py
index 11284abdb3c..17cf7612e10 100644
--- a/contrib/restricted/aws/aws-c-auth/.yandex_meta/__init__.py
+++ b/contrib/restricted/aws/aws-c-auth/.yandex_meta/__init__.py
@@ -1,7 +1,21 @@
+from devtools.yamaker.modules import Linkable, Switch
from devtools.yamaker.project import CMakeNinjaNixProject
+def post_install(self):
+ with self.yamakes["."] as m:
+ m.after(
+ "CFLAGS",
+ Switch(
+ OS_WINDOWS=Linkable(
+ CFLAGS=["-DAWS_AUTH_EXPORTS"],
+ ),
+ ),
+ )
+
+
aws_c_auth = CMakeNinjaNixProject(
arcdir="contrib/restricted/aws/aws-c-auth",
nixattr="aws-c-auth",
+ post_install=post_install,
)
diff --git a/contrib/restricted/aws/aws-c-auth/.yandex_meta/devtools.copyrights.report b/contrib/restricted/aws/aws-c-auth/.yandex_meta/devtools.copyrights.report
index 18eebfd75d7..6870cbe6c1c 100644
--- a/contrib/restricted/aws/aws-c-auth/.yandex_meta/devtools.copyrights.report
+++ b/contrib/restricted/aws/aws-c-auth/.yandex_meta/devtools.copyrights.report
@@ -53,6 +53,8 @@ BELONGS ya.make
include/aws/auth/private/credentials_utils.h [5:5]
include/aws/auth/private/key_derivation.h [5:5]
include/aws/auth/private/sigv4_http_request.h [5:5]
+ include/aws/auth/private/sso_token_providers.h [5:5]
+ include/aws/auth/private/sso_token_utils.h [5:5]
include/aws/auth/signing.h [5:5]
include/aws/auth/signing_config.h [5:5]
include/aws/auth/signing_result.h [5:5]
@@ -72,6 +74,7 @@ BELONGS ya.make
source/credentials_provider_imds.c [2:2]
source/credentials_provider_process.c [2:2]
source/credentials_provider_profile.c [2:2]
+ source/credentials_provider_sso.c [2:2]
source/credentials_provider_static.c [2:2]
source/credentials_provider_sts.c [2:2]
source/credentials_provider_sts_web_identity.c [2:2]
@@ -86,3 +89,6 @@ BELONGS ya.make
source/signing_config.c [2:2]
source/signing_result.c [2:2]
source/sigv4_http_request.c [2:2]
+ source/sso_token_utils.c [2:2]
+ source/token_provider_sso_profile.c [2:2]
+ source/token_provider_sso_session.c [2:2]
diff --git a/contrib/restricted/aws/aws-c-auth/.yandex_meta/devtools.licenses.report b/contrib/restricted/aws/aws-c-auth/.yandex_meta/devtools.licenses.report
index 72747329987..3e77c3fc299 100644
--- a/contrib/restricted/aws/aws-c-auth/.yandex_meta/devtools.licenses.report
+++ b/contrib/restricted/aws/aws-c-auth/.yandex_meta/devtools.licenses.report
@@ -101,6 +101,8 @@ BELONGS ya.make
include/aws/auth/private/credentials_utils.h [6:6]
include/aws/auth/private/key_derivation.h [6:6]
include/aws/auth/private/sigv4_http_request.h [6:6]
+ include/aws/auth/private/sso_token_providers.h [6:6]
+ include/aws/auth/private/sso_token_utils.h [6:6]
include/aws/auth/signing.h [6:6]
include/aws/auth/signing_config.h [6:6]
include/aws/auth/signing_result.h [6:6]
@@ -120,6 +122,7 @@ BELONGS ya.make
source/credentials_provider_imds.c [3:3]
source/credentials_provider_process.c [3:3]
source/credentials_provider_profile.c [3:3]
+ source/credentials_provider_sso.c [3:3]
source/credentials_provider_static.c [3:3]
source/credentials_provider_sts.c [3:3]
source/credentials_provider_sts_web_identity.c [3:3]
@@ -134,6 +137,9 @@ BELONGS ya.make
source/signing_config.c [3:3]
source/signing_result.c [3:3]
source/sigv4_http_request.c [3:3]
+ source/sso_token_utils.c [3:3]
+ source/token_provider_sso_profile.c [3:3]
+ source/token_provider_sso_session.c [3:3]
SKIP LicenseRef-scancode-generic-cla ee24fdc60600747c7d12c32055b0011d
BELONGS ya.make
diff --git a/contrib/restricted/aws/aws-c-auth/.yandex_meta/override.nix b/contrib/restricted/aws/aws-c-auth/.yandex_meta/override.nix
index d770242b9a3..6a964efc618 100644
--- a/contrib/restricted/aws/aws-c-auth/.yandex_meta/override.nix
+++ b/contrib/restricted/aws/aws-c-auth/.yandex_meta/override.nix
@@ -1,10 +1,10 @@
pkgs: attrs: with pkgs; with attrs; rec {
- version = "0.6.26";
+ version = "0.6.27";
src = fetchFromGitHub {
owner = "awslabs";
repo = "aws-c-auth";
rev = "v${version}";
- hash = "sha256-PvdkTw5JydJT0TbXLB2C9tk4T+ho+fAbaw4jU9m5KuU=";
+ hash = "sha256-rjluBj8C4GjE67Os0+1CKKI/2V9RnkbYKhpdqQBryik=";
};
}
diff --git a/contrib/restricted/aws/aws-c-auth/include/aws/auth/auth.h b/contrib/restricted/aws/aws-c-auth/include/aws/auth/auth.h
index 4411d8ff253..b00928372fc 100644
--- a/contrib/restricted/aws/aws-c-auth/include/aws/auth/auth.h
+++ b/contrib/restricted/aws/aws-c-auth/include/aws/auth/auth.h
@@ -43,6 +43,10 @@ enum aws_auth_errors {
AWS_AUTH_SIGV4A_SIGNATURE_VALIDATION_FAILURE,
AWS_AUTH_CREDENTIALS_PROVIDER_COGNITO_SOURCE_FAILURE,
AWS_AUTH_CREDENTIALS_PROVIDER_DELEGATE_FAILURE,
+ AWS_AUTH_SSO_TOKEN_PROVIDER_SOURCE_FAILURE,
+ AWS_AUTH_SSO_TOKEN_INVALID,
+ AWS_AUTH_SSO_TOKEN_EXPIRED,
+ AWS_AUTH_CREDENTIALS_PROVIDER_SSO_SOURCE_FAILURE,
AWS_AUTH_ERROR_END_RANGE = AWS_ERROR_ENUM_END_RANGE(AWS_C_AUTH_PACKAGE_ID)
};
diff --git a/contrib/restricted/aws/aws-c-auth/include/aws/auth/credentials.h b/contrib/restricted/aws/aws-c-auth/include/aws/auth/credentials.h
index 3fa13911f63..2a92f42caba 100644
--- a/contrib/restricted/aws/aws-c-auth/include/aws/auth/credentials.h
+++ b/contrib/restricted/aws/aws-c-auth/include/aws/auth/credentials.h
@@ -90,8 +90,8 @@ struct aws_credentials_provider_environment_options {
};
/**
- * Configuration options for a provider that sources credentials from the aws profile and credentials files
- * (by default ~/.aws/profile and ~/.aws/credentials)
+ * Configuration options for a provider that sources credentials from the aws config and credentials files
+ * (by default ~/.aws/config and ~/.aws/credentials)
*/
struct aws_credentials_provider_profile_options {
struct aws_credentials_provider_shutdown_options shutdown_options;
@@ -114,7 +114,7 @@ struct aws_credentials_provider_profile_options {
/**
* (Optional)
* Use a cached merged profile collection. A merge collection has both config file
- * (~/.aws/profile) and credentials file based profile collection (~/.aws/credentials) using
+ * (~/.aws/config) and credentials file based profile collection (~/.aws/credentials) using
* `aws_profile_collection_new_from_merge`.
* If this option is provided, `config_file_name_override` and `credentials_file_name_override` will be ignored.
*/
@@ -355,6 +355,49 @@ struct aws_credentials_provider_sts_web_identity_options {
struct aws_auth_http_system_vtable *function_table;
};
+/*
+ * Configuration for the SSOCredentialsProvider that sends a GetRoleCredentialsRequest to the AWS Single
+ * Sign-On Service to maintain short-lived sessions to use for authentication.
+ *
+ * https://docs.aws.amazon.com/sdkref/latest/guide/feature-sso-credentials.html
+ */
+struct aws_credentials_provider_sso_options {
+ struct aws_credentials_provider_shutdown_options shutdown_options;
+
+ /*
+ * Override of what profile to use to source credentials from ('default' by default)
+ */
+ struct aws_byte_cursor profile_name_override;
+
+ /*
+ * Override path to the profile config file (~/.aws/config by default)
+ */
+ struct aws_byte_cursor config_file_name_override;
+
+ /**
+ * (Optional)
+ * Use a cached config profile collection. You can also pass a merged collection.
+ * config_file_name_override will be ignored if this option is provided.
+ */
+ struct aws_profile_collection *config_file_cached;
+
+ /*
+ * Connection bootstrap to use for any network connections made while sourcing credentials
+ * Required.
+ */
+ struct aws_client_bootstrap *bootstrap;
+
+ /*
+ * Client TLS context to use when querying SSO provider.
+ * Required.
+ */
+ struct aws_tls_ctx *tls_ctx;
+
+ /* For mocking, leave NULL otherwise */
+ struct aws_auth_http_system_vtable *function_table;
+ aws_io_clock_fn *system_clock_fn;
+};
+
/**
* Configuration options for the STS credentials provider
*/
@@ -457,7 +500,7 @@ struct aws_credentials_provider_chain_default_options {
/**
* (Optional)
* Use a cached merged profile collection. A merge collection has both config file
- * (~/.aws/profile) and credentials file based profile collection (~/.aws/credentials) using
+ * (~/.aws/config) and credentials file based profile collection (~/.aws/credentials) using
* `aws_profile_collection_new_from_merge`.
* If this option is provided, `config_file_name_override` and `credentials_file_name_override` will be ignored.
*/
@@ -733,7 +776,7 @@ struct aws_ecc_key_pair *aws_ecc_key_pair_new_ecdsa_p256_key_from_aws_credential
/**
* Release a reference to a credentials provider
*
- * @param provider provider to increment the ref count on
+ * @param provider provider to decrement the ref count on
*/
AWS_AUTH_API
struct aws_credentials_provider *aws_credentials_provider_release(struct aws_credentials_provider *provider);
@@ -741,7 +784,7 @@ struct aws_credentials_provider *aws_credentials_provider_release(struct aws_cre
/*
* Add a reference to a credentials provider
*
- * @param provider provider to decrement the ref count on
+ * @param provider provider to increment the ref count on
*/
AWS_AUTH_API
struct aws_credentials_provider *aws_credentials_provider_acquire(struct aws_credentials_provider *provider);
@@ -927,6 +970,19 @@ struct aws_credentials_provider *aws_credentials_provider_new_sts_web_identity(
struct aws_allocator *allocator,
const struct aws_credentials_provider_sts_web_identity_options *options);
+/**
+ * Creates a provider that sources credentials from SSO using a SSOToken.
+ *
+ * @param allocator memory allocator to use for all memory allocation
+ * @param options provider-specific configuration options
+ *
+ * @return the newly-constructed credentials provider, or NULL if an error occurred.
+ */
+AWS_AUTH_API
+struct aws_credentials_provider *aws_credentials_provider_new_sso(
+ struct aws_allocator *allocator,
+ const struct aws_credentials_provider_sso_options *options);
+
/*
* Creates a provider that sources credentials from running an external command or process
*
diff --git a/contrib/restricted/aws/aws-c-auth/include/aws/auth/private/credentials_utils.h b/contrib/restricted/aws/aws-c-auth/include/aws/auth/private/credentials_utils.h
index 7bba24331ef..598c3ba0626 100644
--- a/contrib/restricted/aws/aws-c-auth/include/aws/auth/private/credentials_utils.h
+++ b/contrib/restricted/aws/aws-c-auth/include/aws/auth/private/credentials_utils.h
@@ -73,6 +73,7 @@ struct aws_auth_http_system_vtable {
enum aws_parse_credentials_expiration_format {
AWS_PCEF_STRING_ISO_8601_DATE,
AWS_PCEF_NUMBER_UNIX_EPOCH,
+ AWS_PCEF_NUMBER_UNIX_EPOCH_MS,
};
struct aws_parse_credentials_from_json_doc_options {
@@ -80,6 +81,7 @@ struct aws_parse_credentials_from_json_doc_options {
const char *secret_access_key_name;
const char *token_name;
const char *expiration_name;
+ const char *top_level_object_name;
enum aws_parse_credentials_expiration_format expiration_format;
bool token_required;
bool expiration_required;
@@ -154,12 +156,20 @@ struct aws_credentials *aws_parse_credentials_from_aws_json_object(
AWS_AUTH_API
struct aws_credentials *aws_parse_credentials_from_json_document(
struct aws_allocator *allocator,
- const char *json_document,
+ struct aws_byte_cursor json_document,
const struct aws_parse_credentials_from_json_doc_options *options);
AWS_AUTH_API
enum aws_retry_error_type aws_credentials_provider_compute_retry_error_type(int response_code, int error_code);
+/*
+ * Loads an aws config profile collection
+ */
+AWS_AUTH_API
+struct aws_profile_collection *aws_load_profile_collection_from_config_file(
+ struct aws_allocator *allocator,
+ struct aws_byte_cursor config_file_name_override);
+
AWS_EXTERN_C_END
#endif /* AWS_AUTH_CREDENTIALS_PRIVATE_H */
diff --git a/contrib/restricted/aws/aws-c-auth/include/aws/auth/private/sso_token_providers.h b/contrib/restricted/aws/aws-c-auth/include/aws/auth/private/sso_token_providers.h
new file mode 100644
index 00000000000..a9f93079426
--- /dev/null
+++ b/contrib/restricted/aws/aws-c-auth/include/aws/auth/private/sso_token_providers.h
@@ -0,0 +1,112 @@
+#ifndef AWS_AUTH_TOKEN_PROVIDERS_PRIVATE_H
+#define AWS_AUTH_TOKEN_PROVIDERS_PRIVATE_H
+
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/auth/auth.h>
+#include <aws/auth/credentials.h>
+
+/**
+ * Configuration options for a provider that sources sso token information from the aws profile (by default
+ * ~/.aws/config) and token from ~/.aws/sso/cache/<sha1 of start url>.json.
+ */
+struct aws_token_provider_sso_profile_options {
+ struct aws_credentials_provider_shutdown_options shutdown_options;
+
+ /*
+ * Override of what profile to use to source credentials from ('default' by default)
+ */
+ struct aws_byte_cursor profile_name_override;
+
+ /*
+ * Override path to the profile config file (~/.aws/config by default)
+ */
+ struct aws_byte_cursor config_file_name_override;
+
+ /**
+ * (Optional)
+ * Use a cached config profile collection. You can also pass a merged collection.
+ * config_file_name_override will be ignored if this option is provided.
+ */
+ struct aws_profile_collection *config_file_cached;
+
+ /* For mocking, leave NULL otherwise */
+ aws_io_clock_fn *system_clock_fn;
+};
+
+/**
+ * Configuration options for a provider that sources sso token information from the aws profile (by default
+ * ~/.aws/config) and token from ~/.aws/sso/cache/<sha1 of session name>.json.
+ */
+struct aws_token_provider_sso_session_options {
+ struct aws_credentials_provider_shutdown_options shutdown_options;
+
+ /*
+ * Override of what profile to use to source credentials from ('default' by default)
+ */
+ struct aws_byte_cursor profile_name_override;
+
+ /*
+ * Override path to the profile config file (~/.aws/config by default)
+ */
+ struct aws_byte_cursor config_file_name_override;
+
+ /**
+ * (Optional)
+ * Use a cached config profile collection. You can also pass a merged collection.
+ * config_file_name_override will be ignored if this option is provided.
+ */
+ struct aws_profile_collection *config_file_cached;
+
+ /*
+ * Connection bootstrap to use for any network connections made
+ */
+ struct aws_client_bootstrap *bootstrap;
+
+ /*
+ * Client TLS context to use for any network connections made.
+ */
+ struct aws_tls_ctx *tls_ctx;
+
+ /* For mocking, leave NULL otherwise */
+ aws_io_clock_fn *system_clock_fn;
+};
+
+AWS_EXTERN_C_BEGIN
+
+/**
+ * Creates a provider that sources sso token based credentials from key-value profiles loaded from the aws
+ * config("~/.aws/config" by default) and ~/.aws/sso/cache/<sha1 of start url>.json
+ * This is the legacy way which doesn't support refreshing credentials.
+ *
+ * @param allocator memory allocator to use for all memory allocation
+ * @param options provider-specific configuration options
+ *
+ * @return the newly-constructed credentials provider, or NULL if an error occurred.
+ */
+AWS_AUTH_API
+struct aws_credentials_provider *aws_token_provider_new_sso_profile(
+ struct aws_allocator *allocator,
+ const struct aws_token_provider_sso_profile_options *options);
+
+/**
+ * Creates a provider that sources sso token based credentials from key-value profiles loaded from the aws
+ * config("~/.aws/config" by default) and ~/.aws/sso/cache/<sha1 of session name>.json
+ * Note: Token refresh is not currently supported
+ *
+ * @param allocator memory allocator to use for all memory allocation
+ * @param options provider-specific configuration options
+ *
+ * @return the newly-constructed credentials provider, or NULL if an error occurred.
+ */
+AWS_AUTH_API
+struct aws_credentials_provider *aws_token_provider_new_sso_session(
+ struct aws_allocator *allocator,
+ const struct aws_token_provider_sso_session_options *options);
+
+AWS_EXTERN_C_END
+
+#endif /* AWS_AUTH_TOKEN_PROVIDERS_PRIVATE_H */
diff --git a/contrib/restricted/aws/aws-c-auth/include/aws/auth/private/sso_token_utils.h b/contrib/restricted/aws/aws-c-auth/include/aws/auth/private/sso_token_utils.h
new file mode 100644
index 00000000000..42c5c2bfe48
--- /dev/null
+++ b/contrib/restricted/aws/aws-c-auth/include/aws/auth/private/sso_token_utils.h
@@ -0,0 +1,58 @@
+#ifndef AWS_AUTH_TOKEN_PRIVATE_H
+#define AWS_AUTH_TOKEN_PRIVATE_H
+
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/auth/auth.h>
+#include <aws/common/date_time.h>
+
+/* structure to represent a parsed sso token */
+struct aws_sso_token {
+ struct aws_allocator *allocator;
+
+ struct aws_string *access_token;
+ struct aws_date_time expiration;
+};
+
+AWS_EXTERN_C_BEGIN
+
+/* Construct token path which is ~/.aws/sso/cache/<hex encoded sha1 of input>.json */
+AWS_AUTH_API
+struct aws_string *aws_construct_sso_token_path(struct aws_allocator *allocator, const struct aws_string *input);
+
+AWS_AUTH_API
+void aws_sso_token_destroy(struct aws_sso_token *token);
+
+/* Parse `aws_sso_token` from the give file path */
+AWS_AUTH_API
+struct aws_sso_token *aws_sso_token_new_from_file(struct aws_allocator *allocator, const struct aws_string *file_path);
+
+/**
+ * Creates a set of AWS credentials based on a token with expiration.
+ *
+ * @param allocator memory allocator to use for all memory allocation
+ * @param token token for the credentials
+ * @param expiration_timepoint_in_seconds time at which these credentials expire
+ * @return a new pair of AWS credentials, or NULL
+ */
+AWS_AUTH_API
+struct aws_credentials *aws_credentials_new_token(
+ struct aws_allocator *allocator,
+ struct aws_byte_cursor token,
+ uint64_t expiration_timepoint_in_seconds);
+
+/**
+ * Get the token from a set of AWS credentials
+ *
+ * @param credentials credentials to get the token from
+ * @return a byte cursor to the token or an empty byte cursor if there is no token
+ */
+AWS_AUTH_API
+struct aws_byte_cursor aws_credentials_get_token(const struct aws_credentials *credentials);
+
+AWS_EXTERN_C_END
+
+#endif /* AWS_AUTH_TOKEN_PRIVATE_H */
diff --git a/contrib/restricted/aws/aws-c-auth/source/auth.c b/contrib/restricted/aws/aws-c-auth/source/auth.c
index b3fb4d3f5c1..5a0fbc8ca6d 100644
--- a/contrib/restricted/aws/aws-c-auth/source/auth.c
+++ b/contrib/restricted/aws/aws-c-auth/source/auth.c
@@ -91,6 +91,18 @@ static struct aws_error_info s_errors[] = {
AWS_DEFINE_ERROR_INFO_AUTH(
AWS_AUTH_CREDENTIALS_PROVIDER_DELEGATE_FAILURE,
"Valid credentials could not be sourced by the delegate provider"),
+ AWS_DEFINE_ERROR_INFO_AUTH(
+ AWS_AUTH_SSO_TOKEN_PROVIDER_SOURCE_FAILURE,
+ "Valid token could not be sourced by the sso token provider"),
+ AWS_DEFINE_ERROR_INFO_AUTH(
+ AWS_AUTH_SSO_TOKEN_INVALID,
+ "Token sourced by the sso token provider is invalid."),
+ AWS_DEFINE_ERROR_INFO_AUTH(
+ AWS_AUTH_SSO_TOKEN_EXPIRED,
+ "Token sourced by the sso token provider is expired."),
+ AWS_DEFINE_ERROR_INFO_AUTH(
+ AWS_AUTH_CREDENTIALS_PROVIDER_SSO_SOURCE_FAILURE,
+ "Valid credentials could not be sourced by the sso credentials provider"),
};
/* clang-format on */
diff --git a/contrib/restricted/aws/aws-c-auth/source/aws_imds_client.c b/contrib/restricted/aws/aws-c-auth/source/aws_imds_client.c
index d5e7352dd00..5ef16bc408d 100644
--- a/contrib/restricted/aws/aws-c-auth/source/aws_imds_client.c
+++ b/contrib/restricted/aws/aws-c-auth/source/aws_imds_client.c
@@ -1039,7 +1039,7 @@ static void s_process_credentials_resource(const struct aws_byte_buf *resource,
};
credentials = aws_parse_credentials_from_json_document(
- wrapped_user_data->allocator, (const char *)json_data.buffer, &parse_options);
+ wrapped_user_data->allocator, aws_byte_cursor_from_buf(&json_data), &parse_options);
on_finish:
wrapped_user_data->callback(credentials, error_code, wrapped_user_data->user_data);
diff --git a/contrib/restricted/aws/aws-c-auth/source/credentials.c b/contrib/restricted/aws/aws-c-auth/source/credentials.c
index f838c3e17ee..3340663dc51 100644
--- a/contrib/restricted/aws/aws-c-auth/source/credentials.c
+++ b/contrib/restricted/aws/aws-c-auth/source/credentials.c
@@ -5,22 +5,45 @@
#include <aws/auth/credentials.h>
+#include <aws/auth/private/sso_token_utils.h>
#include <aws/cal/ecc.h>
#include <aws/common/environment.h>
#include <aws/common/string.h>
+/* aws ecc identity which contains the data needed to sign a Sigv4a AWS request */
+struct aws_ecc_identity {
+ struct aws_string *access_key_id;
+ struct aws_string *session_token;
+ struct aws_ecc_key_pair *ecc_key;
+};
+
+/* aws credentials identity which contains the data needed to sign an authenticated AWS request */
+struct aws_credentials_identity {
+ struct aws_string *access_key_id;
+ struct aws_string *secret_access_key;
+ struct aws_string *session_token;
+};
+
+/* aws_token identity contains only a token to represent token only identities like a bearer token. */
+struct aws_token_identity {
+ struct aws_string *token;
+};
+
+enum aws_identity_type {
+ AWS_CREDENTIALS_IDENTITY,
+ TOKEN_IDENTITY,
+ ANONYMOUS_IDENTITY,
+ ECC_IDENTITY,
+};
+
/*
- * A structure that wraps the public/private data needed to sign an authenticated AWS request
+ * A structure that wraps the different types of credentials that the customer can provider to establish their
+ * identity.
*/
struct aws_credentials {
struct aws_allocator *allocator;
struct aws_atomic_var ref_count;
-
- struct aws_string *access_key_id;
- struct aws_string *secret_access_key;
- struct aws_string *session_token;
-
/*
* A timepoint, in seconds since epoch, at which the credentials should no longer be used because they
* will have expired.
@@ -51,7 +74,12 @@ struct aws_credentials {
*/
uint64_t expiration_timepoint_seconds;
- struct aws_ecc_key_pair *ecc_key;
+ enum aws_identity_type identity_type;
+ union {
+ struct aws_credentials_identity credentials_identity;
+ struct aws_token_identity token_identity;
+ struct aws_ecc_identity ecc_identity;
+ } identity;
};
/*
@@ -83,23 +111,24 @@ struct aws_credentials *aws_credentials_new(
credentials->allocator = allocator;
aws_atomic_init_int(&credentials->ref_count, 1);
-
- credentials->access_key_id =
+ credentials->identity_type = AWS_CREDENTIALS_IDENTITY;
+ struct aws_credentials_identity *credentials_identity = &credentials->identity.credentials_identity;
+ credentials_identity->access_key_id =
aws_string_new_from_array(allocator, access_key_id_cursor.ptr, access_key_id_cursor.len);
- if (credentials->access_key_id == NULL) {
+ if (credentials_identity->access_key_id == NULL) {
goto error;
}
- credentials->secret_access_key =
+ credentials_identity->secret_access_key =
aws_string_new_from_array(allocator, secret_access_key_cursor.ptr, secret_access_key_cursor.len);
- if (credentials->secret_access_key == NULL) {
+ if (credentials_identity->secret_access_key == NULL) {
goto error;
}
if (session_token_cursor.ptr != NULL && session_token_cursor.len > 0) {
- credentials->session_token =
+ credentials_identity->session_token =
aws_string_new_from_array(allocator, session_token_cursor.ptr, session_token_cursor.len);
- if (credentials->session_token == NULL) {
+ if (credentials_identity->session_token == NULL) {
goto error;
}
}
@@ -120,6 +149,7 @@ struct aws_credentials *aws_credentials_new_anonymous(struct aws_allocator *allo
struct aws_credentials *credentials = aws_mem_calloc(allocator, 1, sizeof(struct aws_credentials));
credentials->allocator = allocator;
+ credentials->identity_type = ANONYMOUS_IDENTITY;
aws_atomic_init_int(&credentials->ref_count, 1);
credentials->expiration_timepoint_seconds = UINT64_MAX;
@@ -131,21 +161,24 @@ static void s_aws_credentials_destroy(struct aws_credentials *credentials) {
if (credentials == NULL) {
return;
}
-
- if (credentials->access_key_id != NULL) {
- aws_string_destroy(credentials->access_key_id);
- }
-
- if (credentials->secret_access_key != NULL) {
- aws_string_destroy_secure(credentials->secret_access_key);
+ switch (credentials->identity_type) {
+ case AWS_CREDENTIALS_IDENTITY:
+ aws_string_destroy(credentials->identity.credentials_identity.access_key_id);
+ aws_string_destroy_secure(credentials->identity.credentials_identity.secret_access_key);
+ aws_string_destroy_secure(credentials->identity.credentials_identity.session_token);
+ break;
+ case ECC_IDENTITY:
+ aws_string_destroy(credentials->identity.ecc_identity.access_key_id);
+ aws_string_destroy_secure(credentials->identity.ecc_identity.session_token);
+ aws_ecc_key_pair_release(credentials->identity.ecc_identity.ecc_key);
+ break;
+ case TOKEN_IDENTITY:
+ aws_string_destroy_secure(credentials->identity.token_identity.token);
+ break;
+ case ANONYMOUS_IDENTITY:
+ break;
}
- if (credentials->session_token != NULL) {
- aws_string_destroy_secure(credentials->session_token);
- }
-
- aws_ecc_key_pair_release(credentials->ecc_key);
-
aws_mem_release(credentials->allocator, credentials);
}
@@ -174,26 +207,64 @@ static struct aws_byte_cursor s_empty_token_cursor = {
};
struct aws_byte_cursor aws_credentials_get_access_key_id(const struct aws_credentials *credentials) {
- if (credentials->access_key_id == NULL) {
- return s_empty_token_cursor;
+ switch (credentials->identity_type) {
+ case AWS_CREDENTIALS_IDENTITY:
+ if (credentials->identity.credentials_identity.access_key_id != NULL) {
+ return aws_byte_cursor_from_string(credentials->identity.credentials_identity.access_key_id);
+ }
+ break;
+ case ECC_IDENTITY:
+ if (credentials->identity.ecc_identity.access_key_id != NULL) {
+ return aws_byte_cursor_from_string(credentials->identity.ecc_identity.access_key_id);
+ }
+ break;
+ default:
+ break;
}
-
- return aws_byte_cursor_from_string(credentials->access_key_id);
+ return s_empty_token_cursor;
}
struct aws_byte_cursor aws_credentials_get_secret_access_key(const struct aws_credentials *credentials) {
- if (credentials->secret_access_key == NULL) {
- return s_empty_token_cursor;
+ switch (credentials->identity_type) {
+ case AWS_CREDENTIALS_IDENTITY:
+ if (credentials->identity.credentials_identity.secret_access_key != NULL) {
+ return aws_byte_cursor_from_string(credentials->identity.credentials_identity.secret_access_key);
+ }
+ break;
+ default:
+ break;
}
-
- return aws_byte_cursor_from_string(credentials->secret_access_key);
+ return s_empty_token_cursor;
}
struct aws_byte_cursor aws_credentials_get_session_token(const struct aws_credentials *credentials) {
- if (credentials->session_token != NULL) {
- return aws_byte_cursor_from_string(credentials->session_token);
+ switch (credentials->identity_type) {
+ case AWS_CREDENTIALS_IDENTITY:
+ if (credentials->identity.credentials_identity.session_token != NULL) {
+ return aws_byte_cursor_from_string(credentials->identity.credentials_identity.session_token);
+ }
+ break;
+ case ECC_IDENTITY:
+ if (credentials->identity.ecc_identity.session_token != NULL) {
+ return aws_byte_cursor_from_string(credentials->identity.ecc_identity.session_token);
+ }
+ break;
+ default:
+ break;
}
+ return s_empty_token_cursor;
+}
+struct aws_byte_cursor aws_credentials_get_token(const struct aws_credentials *credentials) {
+ switch (credentials->identity_type) {
+ case TOKEN_IDENTITY:
+ if (credentials->identity.token_identity.token != NULL) {
+ return aws_byte_cursor_from_string(credentials->identity.token_identity.token);
+ }
+ break;
+ default:
+ break;
+ }
return s_empty_token_cursor;
}
@@ -202,12 +273,15 @@ uint64_t aws_credentials_get_expiration_timepoint_seconds(const struct aws_crede
}
struct aws_ecc_key_pair *aws_credentials_get_ecc_key_pair(const struct aws_credentials *credentials) {
- return credentials->ecc_key;
+ if (credentials->identity_type == ECC_IDENTITY) {
+ return credentials->identity.ecc_identity.ecc_key;
+ }
+ return NULL;
}
bool aws_credentials_is_anonymous(const struct aws_credentials *credentials) {
AWS_PRECONDITION(credentials);
- return credentials->access_key_id == NULL && credentials->secret_access_key == NULL;
+ return credentials->identity_type == ANONYMOUS_IDENTITY;
}
struct aws_credentials *aws_credentials_new_from_string(
@@ -250,16 +324,19 @@ struct aws_credentials *aws_credentials_new_ecc(
credentials->expiration_timepoint_seconds = expiration_timepoint_in_seconds;
aws_atomic_init_int(&credentials->ref_count, 1);
aws_ecc_key_pair_acquire(ecc_key);
- credentials->ecc_key = ecc_key;
+ credentials->identity_type = ECC_IDENTITY;
+ credentials->identity.ecc_identity.ecc_key = ecc_key;
- credentials->access_key_id = aws_string_new_from_array(allocator, access_key_id.ptr, access_key_id.len);
- if (credentials->access_key_id == NULL) {
+ credentials->identity.ecc_identity.access_key_id =
+ aws_string_new_from_array(allocator, access_key_id.ptr, access_key_id.len);
+ if (credentials->identity.ecc_identity.access_key_id == NULL) {
goto on_error;
}
if (session_token.ptr != NULL && session_token.len > 0) {
- credentials->session_token = aws_string_new_from_array(allocator, session_token.ptr, session_token.len);
- if (credentials->session_token == NULL) {
+ credentials->identity.ecc_identity.session_token =
+ aws_string_new_from_array(allocator, session_token.ptr, session_token.len);
+ if (credentials->identity.ecc_identity.session_token == NULL) {
goto on_error;
}
}
@@ -295,6 +372,25 @@ struct aws_credentials *aws_credentials_new_ecc_from_aws_credentials(
return ecc_credentials;
}
+struct aws_credentials *aws_credentials_new_token(
+ struct aws_allocator *allocator,
+ struct aws_byte_cursor token,
+ uint64_t expiration_timepoint_in_seconds) {
+ if (token.ptr == NULL || token.len == 0) {
+ aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
+ return NULL;
+ }
+ struct aws_credentials *credentials = aws_mem_calloc(allocator, 1, sizeof(struct aws_credentials));
+
+ credentials->allocator = allocator;
+ aws_atomic_init_int(&credentials->ref_count, 1);
+ credentials->identity_type = TOKEN_IDENTITY;
+ struct aws_token_identity *token_identity = &credentials->identity.token_identity;
+ token_identity->token = aws_string_new_from_array(allocator, token.ptr, token.len);
+ credentials->expiration_timepoint_seconds = expiration_timepoint_in_seconds;
+ return credentials;
+}
+
/*
* global credentials provider APIs
*/
diff --git a/contrib/restricted/aws/aws-c-auth/source/credentials_provider_ecs.c b/contrib/restricted/aws/aws-c-auth/source/credentials_provider_ecs.c
index 91c74f0852e..7d96cf3a243 100644
--- a/contrib/restricted/aws/aws-c-auth/source/credentials_provider_ecs.c
+++ b/contrib/restricted/aws/aws-c-auth/source/credentials_provider_ecs.c
@@ -145,7 +145,7 @@ static void s_ecs_finalize_get_credentials_query(struct aws_credentials_provider
};
if (aws_byte_buf_append_null_terminator(&ecs_user_data->current_result) == AWS_OP_SUCCESS) {
credentials = aws_parse_credentials_from_json_document(
- ecs_user_data->allocator, (const char *)ecs_user_data->current_result.buffer, &parse_options);
+ ecs_user_data->allocator, aws_byte_cursor_from_buf(&ecs_user_data->current_result), &parse_options);
} else {
AWS_LOGF_ERROR(
AWS_LS_AUTH_CREDENTIALS_PROVIDER,
diff --git a/contrib/restricted/aws/aws-c-auth/source/credentials_provider_process.c b/contrib/restricted/aws/aws-c-auth/source/credentials_provider_process.c
index 29f99d09280..e1c0bfbf00a 100644
--- a/contrib/restricted/aws/aws-c-auth/source/credentials_provider_process.c
+++ b/contrib/restricted/aws/aws-c-auth/source/credentials_provider_process.c
@@ -56,8 +56,8 @@ static int s_get_credentials_from_process(
.expiration_required = false,
};
- credentials =
- aws_parse_credentials_from_json_document(provider->allocator, aws_string_c_str(result.std_out), &parse_options);
+ credentials = aws_parse_credentials_from_json_document(
+ provider->allocator, aws_byte_cursor_from_string(result.std_out), &parse_options);
if (!credentials) {
AWS_LOGF_INFO(
AWS_LS_AUTH_CREDENTIALS_PROVIDER,
diff --git a/contrib/restricted/aws/aws-c-auth/source/credentials_provider_sso.c b/contrib/restricted/aws/aws-c-auth/source/credentials_provider_sso.c
new file mode 100644
index 00000000000..e7c39e75d5a
--- /dev/null
+++ b/contrib/restricted/aws/aws-c-auth/source/credentials_provider_sso.c
@@ -0,0 +1,851 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/auth/credentials.h>
+
+#include <aws/auth/private/aws_profile.h>
+#include <aws/auth/private/credentials_utils.h>
+#include <aws/auth/private/sso_token_providers.h>
+#include <aws/auth/private/sso_token_utils.h>
+
+#include <aws/common/clock.h>
+#include <aws/http/connection_manager.h>
+#include <aws/http/request_response.h>
+#include <aws/http/status_code.h>
+#include <aws/io/channel_bootstrap.h>
+#include <aws/io/socket.h>
+#include <aws/io/tls_channel_handler.h>
+#include <aws/io/uri.h>
+
+#if defined(_MSC_VER)
+# pragma warning(disable : 4204)
+#endif /* _MSC_VER */
+
+#define SSO_RESPONSE_SIZE_INITIAL 2048
+#define SSO_RESPONSE_SIZE_LIMIT 10000
+#define SSO_CONNECT_TIMEOUT_DEFAULT_IN_SECONDS 2
+#define SSO_MAX_ATTEMPTS 3
+#define SSO_RETRY_TIMEOUT_MS 100
+
+struct aws_credentials_provider_sso_impl {
+ struct aws_http_connection_manager *connection_manager;
+ const struct aws_auth_http_system_vtable *function_table;
+ struct aws_string *endpoint;
+ struct aws_string *sso_account_id;
+ struct aws_string *sso_role_name;
+ struct aws_credentials_provider *token_provider;
+ struct aws_retry_strategy *retry_strategy;
+};
+
+/**
+ * aws_sso_query_context - context for each outstanding SSO query.
+ */
+struct aws_sso_query_context {
+ /* immutable post-creation */
+ struct aws_allocator *allocator;
+ struct aws_credentials_provider *provider;
+ aws_on_get_credentials_callback_fn *original_callback;
+ void *original_user_data;
+
+ /* mutable */
+ struct aws_http_connection *connection;
+ struct aws_http_message *request;
+ struct aws_byte_buf payload;
+ struct aws_retry_token *retry_token;
+ struct aws_byte_buf path_and_query;
+ struct aws_string *token;
+
+ int status_code;
+ int error_code;
+};
+
+/* called in between retries. */
+static void s_sso_query_context_reset_request_specific_data(struct aws_sso_query_context *sso_query_context) {
+ if (sso_query_context->request) {
+ aws_http_message_release(sso_query_context->request);
+ sso_query_context->request = NULL;
+ }
+ if (sso_query_context->connection) {
+ struct aws_credentials_provider_sso_impl *provider_impl = sso_query_context->provider->impl;
+ int result = provider_impl->function_table->aws_http_connection_manager_release_connection(
+ provider_impl->connection_manager, sso_query_context->connection);
+ (void)result;
+ AWS_ASSERT(result == AWS_OP_SUCCESS);
+ sso_query_context->connection = NULL;
+ }
+ if (sso_query_context->token) {
+ aws_string_destroy_secure(sso_query_context->token);
+ sso_query_context->token = NULL;
+ }
+ sso_query_context->status_code = 0;
+ sso_query_context->error_code = 0;
+}
+
+static void s_sso_query_context_destroy(struct aws_sso_query_context *sso_query_context) {
+ if (sso_query_context == NULL) {
+ return;
+ }
+
+ s_sso_query_context_reset_request_specific_data(sso_query_context);
+ aws_byte_buf_clean_up(&sso_query_context->payload);
+ aws_byte_buf_clean_up(&sso_query_context->path_and_query);
+ aws_credentials_provider_release(sso_query_context->provider);
+ aws_retry_token_release(sso_query_context->retry_token);
+ aws_mem_release(sso_query_context->allocator, sso_query_context);
+}
+
+static struct aws_sso_query_context *s_sso_query_context_new(
+ struct aws_credentials_provider *provider,
+ aws_on_get_credentials_callback_fn callback,
+ void *user_data) {
+ struct aws_credentials_provider_sso_impl *impl = provider->impl;
+
+ struct aws_sso_query_context *sso_query_context =
+ aws_mem_calloc(provider->allocator, 1, sizeof(struct aws_sso_query_context));
+ sso_query_context->allocator = provider->allocator;
+ sso_query_context->provider = aws_credentials_provider_acquire(provider);
+ sso_query_context->original_user_data = user_data;
+ sso_query_context->original_callback = callback;
+
+ /* construct path and query */
+ struct aws_byte_cursor account_id_cursor = aws_byte_cursor_from_string(impl->sso_account_id);
+ struct aws_byte_cursor role_name_cursor = aws_byte_cursor_from_string(impl->sso_role_name);
+ struct aws_byte_cursor path_cursor = aws_byte_cursor_from_c_str("/federation/credentials?account_id=");
+ struct aws_byte_cursor role_name_param_cursor = aws_byte_cursor_from_c_str("&role_name=");
+
+ if (aws_byte_buf_init_copy_from_cursor(&sso_query_context->path_and_query, provider->allocator, path_cursor) ||
+ aws_byte_buf_append_encoding_uri_param(&sso_query_context->path_and_query, &account_id_cursor) ||
+ aws_byte_buf_append_dynamic(&sso_query_context->path_and_query, &role_name_param_cursor) ||
+ aws_byte_buf_append_encoding_uri_param(&sso_query_context->path_and_query, &role_name_cursor)) {
+ goto on_error;
+ }
+
+ if (aws_byte_buf_init(&sso_query_context->payload, provider->allocator, SSO_RESPONSE_SIZE_INITIAL)) {
+ goto on_error;
+ }
+
+ return sso_query_context;
+
+on_error:
+ s_sso_query_context_destroy(sso_query_context);
+
+ return NULL;
+}
+
+/*
+ * No matter the result, this always gets called assuming that sso_query_context is successfully allocated
+ */
+static void s_finalize_get_credentials_query(struct aws_sso_query_context *sso_query_context) {
+ struct aws_credentials *credentials = NULL;
+
+ if (sso_query_context->error_code == AWS_ERROR_SUCCESS) {
+ /* parse credentials */
+ struct aws_parse_credentials_from_json_doc_options parse_options = {
+ .access_key_id_name = "accessKeyId",
+ .secret_access_key_name = "secretAccessKey",
+ .token_name = "sessionToken",
+ .expiration_name = "expiration",
+ .top_level_object_name = "roleCredentials",
+ .token_required = true,
+ .expiration_required = true,
+ .expiration_format = AWS_PCEF_NUMBER_UNIX_EPOCH_MS,
+ };
+
+ credentials = aws_parse_credentials_from_json_document(
+ sso_query_context->allocator, aws_byte_cursor_from_buf(&sso_query_context->payload), &parse_options);
+ }
+
+ if (credentials) {
+ AWS_LOGF_INFO(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p) successfully queried credentials",
+ (void *)sso_query_context->provider);
+ } else {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p) failed to query credentials",
+ (void *)sso_query_context->provider);
+
+ if (sso_query_context->error_code == AWS_ERROR_SUCCESS) {
+ sso_query_context->error_code = AWS_AUTH_CREDENTIALS_PROVIDER_SSO_SOURCE_FAILURE;
+ }
+ }
+
+ /* pass the credentials back */
+ sso_query_context->original_callback(
+ credentials, sso_query_context->error_code, sso_query_context->original_user_data);
+
+ /* clean up */
+ s_sso_query_context_destroy(sso_query_context);
+ aws_credentials_release(credentials);
+}
+static void s_on_retry_ready(struct aws_retry_token *token, int error_code, void *user_data);
+
+static void s_on_stream_complete_fn(struct aws_http_stream *stream, int error_code, void *user_data) {
+ struct aws_sso_query_context *sso_query_context = user_data;
+
+ struct aws_credentials_provider_sso_impl *impl = sso_query_context->provider->impl;
+ impl->function_table->aws_http_stream_release(stream);
+
+ /* set error code */
+ sso_query_context->error_code = error_code;
+ impl->function_table->aws_http_stream_get_incoming_response_status(stream, &sso_query_context->status_code);
+ if (error_code == AWS_OP_SUCCESS && sso_query_context->status_code != AWS_HTTP_STATUS_CODE_200_OK) {
+ sso_query_context->error_code = AWS_AUTH_CREDENTIALS_PROVIDER_HTTP_STATUS_FAILURE;
+ }
+
+ /*
+ * If we can retry the request based on error response or http status code failure, retry it, otherwise, call the
+ * finalize function.
+ */
+ if (error_code || sso_query_context->status_code != AWS_HTTP_STATUS_CODE_200_OK) {
+ enum aws_retry_error_type error_type =
+ aws_credentials_provider_compute_retry_error_type(sso_query_context->status_code, error_code);
+
+ /* don't retry client errors at all. */
+ if (error_type != AWS_RETRY_ERROR_TYPE_CLIENT_ERROR) {
+ if (aws_retry_strategy_schedule_retry(
+ sso_query_context->retry_token, error_type, s_on_retry_ready, sso_query_context) ==
+ AWS_OP_SUCCESS) {
+ AWS_LOGF_INFO(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p): successfully scheduled a retry",
+ (void *)sso_query_context->provider);
+ return;
+ }
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p): failed to schedule retry: %s",
+ (void *)sso_query_context->provider,
+ aws_error_str(aws_last_error()));
+ sso_query_context->error_code = aws_last_error();
+ }
+ } else {
+ int result = aws_retry_token_record_success(sso_query_context->retry_token);
+ (void)result;
+ AWS_ASSERT(result == AWS_ERROR_SUCCESS);
+ }
+
+ s_finalize_get_credentials_query(sso_query_context);
+}
+
+static int s_on_incoming_body_fn(struct aws_http_stream *stream, const struct aws_byte_cursor *body, void *user_data) {
+
+ (void)stream;
+
+ struct aws_sso_query_context *sso_query_context = user_data;
+
+ AWS_LOGF_TRACE(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p) received %zu response bytes",
+ (void *)sso_query_context->provider,
+ body->len);
+
+ if (body->len + sso_query_context->payload.len > SSO_RESPONSE_SIZE_LIMIT) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p) response exceeded maximum allowed length",
+ (void *)sso_query_context->provider);
+
+ return aws_raise_error(AWS_ERROR_SHORT_BUFFER);
+ }
+
+ if (aws_byte_buf_append_dynamic(&sso_query_context->payload, body)) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p) error appending response payload: %s",
+ (void *)sso_query_context->provider,
+ aws_error_str(aws_last_error()));
+
+ return AWS_OP_ERR;
+ }
+
+ return AWS_OP_SUCCESS;
+}
+
+/* Request headers. */
+AWS_STATIC_STRING_FROM_LITERAL(s_sso_token_header, "x-amz-sso_bearer_token");
+AWS_STATIC_STRING_FROM_LITERAL(s_sso_user_agent_header, "User-Agent");
+AWS_STATIC_STRING_FROM_LITERAL(s_sso_user_agent_header_value, "aws-sdk-crt/sso-credentials-provider");
+
+static void s_query_credentials(struct aws_sso_query_context *sso_query_context) {
+ AWS_FATAL_ASSERT(sso_query_context->connection);
+ struct aws_http_stream *stream = NULL;
+ struct aws_credentials_provider_sso_impl *impl = sso_query_context->provider->impl;
+
+ sso_query_context->request = aws_http_message_new_request(sso_query_context->allocator);
+ if (sso_query_context->request == NULL) {
+ goto on_error;
+ }
+
+ struct aws_http_header auth_header = {
+ .name = aws_byte_cursor_from_string(s_sso_token_header),
+ .value = aws_byte_cursor_from_string(sso_query_context->token),
+ };
+ struct aws_http_header host_header = {
+ .name = AWS_BYTE_CUR_INIT_FROM_STRING_LITERAL("Host"),
+ .value = aws_byte_cursor_from_string(impl->endpoint),
+ };
+ struct aws_http_header user_agent_header = {
+ .name = aws_byte_cursor_from_string(s_sso_user_agent_header),
+ .value = aws_byte_cursor_from_string(s_sso_user_agent_header_value),
+ };
+
+ if (aws_http_message_add_header(sso_query_context->request, auth_header) ||
+ aws_http_message_add_header(sso_query_context->request, host_header) ||
+ aws_http_message_add_header(sso_query_context->request, user_agent_header)) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p) failed to add http header with error: %s",
+ (void *)sso_query_context->provider,
+ aws_error_debug_str(aws_last_error()));
+ goto on_error;
+ }
+
+ if (aws_http_message_set_request_method(sso_query_context->request, aws_http_method_get)) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p) failed to set request method with error: %s",
+ (void *)sso_query_context->provider,
+ aws_error_debug_str(aws_last_error()));
+ goto on_error;
+ }
+
+ if (aws_http_message_set_request_path(
+ sso_query_context->request, aws_byte_cursor_from_buf(&sso_query_context->path_and_query))) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p) failed to set request path with error: %s",
+ (void *)sso_query_context->provider,
+ aws_error_debug_str(aws_last_error()));
+ goto on_error;
+ }
+
+ struct aws_http_make_request_options request_options = {
+ .self_size = sizeof(request_options),
+ .on_response_headers = NULL,
+ .on_response_header_block_done = NULL,
+ .on_response_body = s_on_incoming_body_fn,
+ .on_complete = s_on_stream_complete_fn,
+ .user_data = sso_query_context,
+ .request = sso_query_context->request,
+ };
+
+ stream = impl->function_table->aws_http_connection_make_request(sso_query_context->connection, &request_options);
+ if (!stream) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p) failed to make request with error: %s",
+ (void *)sso_query_context->provider,
+ aws_error_debug_str(aws_last_error()));
+ goto on_error;
+ }
+
+ if (impl->function_table->aws_http_stream_activate(stream)) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p) failed to activate the stream with error: %s",
+ (void *)sso_query_context->provider,
+ aws_error_debug_str(aws_last_error()));
+ goto on_error;
+ }
+
+ return;
+
+on_error:
+ sso_query_context->error_code = aws_last_error();
+ impl->function_table->aws_http_stream_release(stream);
+ s_finalize_get_credentials_query(sso_query_context);
+}
+
+static void s_on_get_token_callback(struct aws_credentials *credentials, int error_code, void *user_data) {
+ struct aws_sso_query_context *sso_query_context = user_data;
+
+ if (error_code) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "id=%p: failed to acquire a token, error code %d(%s)",
+ (void *)sso_query_context->provider,
+ error_code,
+ aws_error_str(error_code));
+ sso_query_context->error_code = error_code;
+ s_finalize_get_credentials_query(sso_query_context);
+ return;
+ }
+
+ struct aws_byte_cursor token = aws_credentials_get_token(credentials);
+ AWS_LOGF_INFO(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p): successfully accquired a token",
+ (void *)sso_query_context->provider);
+
+ sso_query_context->token = aws_string_new_from_cursor(sso_query_context->allocator, &token);
+ s_query_credentials(sso_query_context);
+}
+
+static void s_on_acquire_connection(struct aws_http_connection *connection, int error_code, void *user_data) {
+ struct aws_sso_query_context *sso_query_context = user_data;
+
+ if (error_code) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "id=%p: failed to acquire a connection, error code %d(%s)",
+ (void *)sso_query_context->provider,
+ error_code,
+ aws_error_str(error_code));
+ sso_query_context->error_code = error_code;
+ s_finalize_get_credentials_query(sso_query_context);
+ return;
+ }
+ AWS_LOGF_INFO(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p): successfully accquired a connection",
+ (void *)sso_query_context->provider);
+ sso_query_context->connection = connection;
+
+ struct aws_credentials_provider_sso_impl *impl = sso_query_context->provider->impl;
+ if (aws_credentials_provider_get_credentials(impl->token_provider, s_on_get_token_callback, user_data)) {
+ int last_error_code = aws_last_error();
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "id=%p: failed to get a token, error code %d(%s)",
+ (void *)sso_query_context->provider,
+ last_error_code,
+ aws_error_str(last_error_code));
+
+ sso_query_context->error_code = last_error_code;
+ s_finalize_get_credentials_query(sso_query_context);
+ }
+}
+
+/* called for each retry. */
+static void s_on_retry_ready(struct aws_retry_token *token, int error_code, void *user_data) {
+ (void)token;
+ struct aws_sso_query_context *sso_query_context = user_data;
+ struct aws_credentials_provider_sso_impl *impl = sso_query_context->provider->impl;
+
+ if (error_code) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p): failed to schedule retry with error: %s",
+ (void *)sso_query_context->provider,
+ aws_error_debug_str(error_code));
+ sso_query_context->error_code = error_code;
+ s_finalize_get_credentials_query(sso_query_context);
+ return;
+ }
+
+ /* clear the result from previous attempt */
+ s_sso_query_context_reset_request_specific_data(sso_query_context);
+
+ impl->function_table->aws_http_connection_manager_acquire_connection(
+ impl->connection_manager, s_on_acquire_connection, sso_query_context);
+}
+
+static void s_on_retry_token_acquired(
+ struct aws_retry_strategy *strategy,
+ int error_code,
+ struct aws_retry_token *token,
+ void *user_data) {
+ struct aws_sso_query_context *sso_query_context = user_data;
+ (void)strategy;
+
+ if (error_code) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p): failed to acquire retry token: %s",
+ (void *)sso_query_context->provider,
+ aws_error_debug_str(error_code));
+ sso_query_context->error_code = error_code;
+ s_finalize_get_credentials_query(sso_query_context);
+ return;
+ }
+
+ sso_query_context->retry_token = token;
+ struct aws_credentials_provider_sso_impl *impl = sso_query_context->provider->impl;
+ impl->function_table->aws_http_connection_manager_acquire_connection(
+ impl->connection_manager, s_on_acquire_connection, user_data);
+}
+
+static int s_credentials_provider_sso_get_credentials(
+ struct aws_credentials_provider *provider,
+ aws_on_get_credentials_callback_fn callback,
+ void *user_data) {
+
+ struct aws_credentials_provider_sso_impl *impl = provider->impl;
+
+ struct aws_sso_query_context *sso_query_context = s_sso_query_context_new(provider, callback, user_data);
+ if (sso_query_context == NULL) {
+ return AWS_OP_ERR;
+ }
+
+ if (aws_retry_strategy_acquire_retry_token(
+ impl->retry_strategy, NULL, s_on_retry_token_acquired, sso_query_context, SSO_RETRY_TIMEOUT_MS)) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p): failed to acquire retry token: %s",
+ (void *)provider,
+ aws_error_debug_str(aws_last_error()));
+ goto on_error;
+ }
+
+ return AWS_OP_SUCCESS;
+
+on_error:
+ s_sso_query_context_destroy(sso_query_context);
+ return AWS_OP_ERR;
+}
+
+static void s_on_connection_manager_shutdown(void *user_data) {
+ struct aws_credentials_provider *provider = user_data;
+
+ aws_credentials_provider_invoke_shutdown_callback(provider);
+ aws_mem_release(provider->allocator, provider);
+}
+
+static void s_credentials_provider_sso_destroy(struct aws_credentials_provider *provider) {
+
+ struct aws_credentials_provider_sso_impl *impl = provider->impl;
+ if (impl == NULL) {
+ return;
+ }
+ aws_string_destroy(impl->endpoint);
+ aws_string_destroy(impl->sso_account_id);
+ aws_string_destroy(impl->sso_role_name);
+ aws_retry_strategy_release(impl->retry_strategy);
+ aws_credentials_provider_release(impl->token_provider);
+
+ /* aws_http_connection_manager_release will eventually leads to call of s_on_connection_manager_shutdown,
+ * which will do memory release for provider and impl. So We should be freeing impl
+ * related memory first, then call aws_http_connection_manager_release.
+ */
+ if (impl->connection_manager) {
+ impl->function_table->aws_http_connection_manager_release(impl->connection_manager);
+ } else {
+ /* If provider setup failed halfway through, connection_manager might not exist.
+ * In this case invoke shutdown completion callback directly to finish cleanup */
+ s_on_connection_manager_shutdown(provider);
+ }
+}
+
+static struct aws_credentials_provider_vtable s_aws_credentials_provider_sso_vtable = {
+ .get_credentials = s_credentials_provider_sso_get_credentials,
+ .destroy = s_credentials_provider_sso_destroy,
+};
+
+static int s_construct_sso_portal_endpoint(
+ struct aws_allocator *allocator,
+ struct aws_byte_buf *out_endpoint,
+ const struct aws_string *region) {
+ AWS_PRECONDITION(allocator);
+ AWS_PRECONDITION(out_endpoint);
+
+ if (!region) {
+ return aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
+ }
+ aws_byte_buf_clean_up(out_endpoint);
+ struct aws_byte_cursor sso_prefix = aws_byte_cursor_from_c_str("portal.sso.");
+ struct aws_byte_cursor region_cursor = aws_byte_cursor_from_string(region);
+ struct aws_byte_cursor amazonaws_cursor = aws_byte_cursor_from_c_str(".amazonaws.com");
+ struct aws_byte_cursor cn_cursor = aws_byte_cursor_from_c_str(".cn");
+
+ if (aws_byte_buf_init_copy_from_cursor(out_endpoint, allocator, sso_prefix) ||
+ aws_byte_buf_append_dynamic(out_endpoint, &region_cursor) ||
+ aws_byte_buf_append_dynamic(out_endpoint, &amazonaws_cursor)) {
+ goto on_error;
+ }
+
+ if (aws_string_eq_c_str_ignore_case(region, "cn-north-1") ||
+ aws_string_eq_c_str_ignore_case(region, "cn-northwest-1")) {
+ if (aws_byte_buf_append_dynamic(out_endpoint, &cn_cursor)) {
+ goto on_error;
+ }
+ }
+ return AWS_OP_SUCCESS;
+
+on_error:
+ aws_byte_buf_clean_up(out_endpoint);
+ return AWS_OP_ERR;
+}
+
+AWS_STATIC_STRING_FROM_LITERAL(s_sso_account_id, "sso_account_id");
+AWS_STATIC_STRING_FROM_LITERAL(s_sso_region, "sso_region");
+AWS_STATIC_STRING_FROM_LITERAL(s_sso_role_name, "sso_role_name");
+AWS_STATIC_STRING_FROM_LITERAL(s_sso_session, "sso_session");
+
+struct sso_parameters {
+ struct aws_allocator *allocator;
+ struct aws_byte_buf endpoint;
+ struct aws_string *sso_account_id;
+ struct aws_string *sso_role_name;
+ struct aws_credentials_provider *token_provider;
+};
+
+static void s_parameters_destroy(struct sso_parameters *parameters) {
+ if (!parameters) {
+ return;
+ }
+ aws_byte_buf_clean_up(&parameters->endpoint);
+ aws_string_destroy(parameters->sso_account_id);
+ aws_string_destroy(parameters->sso_role_name);
+ aws_credentials_provider_release(parameters->token_provider);
+ aws_mem_release(parameters->allocator, parameters);
+}
+
+/**
+ * Read the config file and construct profile or sso_session token provider based on sso_session property.
+ *
+ * If the profile contains sso_session property, a valid config example is as follow.
+ * [profile sso-profile]
+ * sso_session = dev
+ * sso_account_id = 012345678901
+ * sso_role_name = SampleRole
+ *
+ * [sso-session dev]
+ * sso_region = us-east-1
+ * sso_start_url = https://d-abc123.awsapps.com/start
+ *
+ * If the profile does't contains sso_session, the legacy valid config example is as follow.
+ * [profile sso-profile]
+ * sso_account_id = 012345678901
+ * sso_region = us-east-1
+ * sso_role_name = SampleRole
+ * sso_start_url = https://d-abc123.awsapps.com/start-beta
+ */
+static struct sso_parameters *s_parameters_new(
+ struct aws_allocator *allocator,
+ const struct aws_credentials_provider_sso_options *options) {
+
+ struct sso_parameters *parameters = aws_mem_calloc(allocator, 1, sizeof(struct sso_parameters));
+ parameters->allocator = allocator;
+
+ struct aws_profile_collection *config_profile_collection = NULL;
+ struct aws_string *profile_name = NULL;
+ bool success = false;
+
+ profile_name = aws_get_profile_name(allocator, &options->profile_name_override);
+ if (!profile_name) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "sso: failed to resolve profile name");
+ goto on_finish;
+ }
+ if (options->config_file_cached) {
+ /* Use cached config file */
+ config_profile_collection = aws_profile_collection_acquire(options->config_file_cached);
+ } else {
+ /* load config file */
+ config_profile_collection =
+ aws_load_profile_collection_from_config_file(allocator, options->config_file_name_override);
+ }
+
+ if (!config_profile_collection) {
+ goto on_finish;
+ }
+
+ const struct aws_profile *profile = aws_profile_collection_get_profile(config_profile_collection, profile_name);
+ if (!profile) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER, "sso: failed to load \"%s\" profile", aws_string_c_str(profile_name));
+ goto on_finish;
+ }
+
+ const struct aws_profile_property *sso_account_id = aws_profile_get_property(profile, s_sso_account_id);
+ const struct aws_profile_property *sso_role_name = aws_profile_get_property(profile, s_sso_role_name);
+ const struct aws_profile_property *sso_region = NULL;
+
+ if (!sso_account_id) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "sso: sso_account_id is missing");
+ aws_raise_error(AWS_AUTH_CREDENTIALS_PROVIDER_SSO_SOURCE_FAILURE);
+ goto on_finish;
+ }
+ if (!sso_role_name) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "sso: sso_role_name is missing");
+ aws_raise_error(AWS_AUTH_CREDENTIALS_PROVIDER_SSO_SOURCE_FAILURE);
+ goto on_finish;
+ }
+
+ const struct aws_profile_property *sso_session_property = aws_profile_get_property(profile, s_sso_session);
+ /* create the appropriate token provider based on sso_session property is available or not */
+ if (sso_session_property) {
+ /* construct sso_session token provider */
+ struct aws_token_provider_sso_session_options token_provider_options = {
+ .config_file_name_override = options->config_file_name_override,
+ .config_file_cached = config_profile_collection,
+ .profile_name_override = options->profile_name_override,
+ .bootstrap = options->bootstrap,
+ .tls_ctx = options->tls_ctx,
+ .system_clock_fn = options->system_clock_fn,
+ };
+ parameters->token_provider = aws_token_provider_new_sso_session(allocator, &token_provider_options);
+ if (!parameters->token_provider) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "sso: unable to create a sso token provider");
+ aws_raise_error(AWS_AUTH_CREDENTIALS_PROVIDER_SSO_SOURCE_FAILURE);
+ goto on_finish;
+ }
+ sso_region = aws_profile_get_property(
+ aws_profile_collection_get_section(
+ config_profile_collection,
+ AWS_PROFILE_SECTION_TYPE_SSO_SESSION,
+ aws_profile_property_get_value(sso_session_property)),
+ s_sso_region);
+ } else {
+ /* construct profile token provider */
+ struct aws_token_provider_sso_profile_options token_provider_options = {
+ .config_file_name_override = options->config_file_name_override,
+ .config_file_cached = config_profile_collection,
+ .profile_name_override = options->profile_name_override,
+ .system_clock_fn = options->system_clock_fn,
+ };
+
+ parameters->token_provider = aws_token_provider_new_sso_profile(allocator, &token_provider_options);
+ if (!parameters->token_provider) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "sso: unable to create a profile token provider");
+ aws_raise_error(AWS_AUTH_CREDENTIALS_PROVIDER_SSO_SOURCE_FAILURE);
+ goto on_finish;
+ }
+ sso_region = aws_profile_get_property(profile, s_sso_region);
+ }
+
+ if (!sso_region) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "sso: sso_region is missing");
+ aws_raise_error(AWS_AUTH_CREDENTIALS_PROVIDER_SSO_SOURCE_FAILURE);
+ goto on_finish;
+ }
+
+ parameters->sso_account_id = aws_string_new_from_string(allocator, aws_profile_property_get_value(sso_account_id));
+ parameters->sso_role_name = aws_string_new_from_string(allocator, aws_profile_property_get_value(sso_role_name));
+ /* determine endpoint */
+ if (s_construct_sso_portal_endpoint(allocator, &parameters->endpoint, aws_profile_property_get_value(sso_region))) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "Failed to construct sso endpoint");
+ goto on_finish;
+ }
+ AWS_LOGF_DEBUG(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER, "Successfully loaded all required parameters for sso credentials provider.");
+ success = true;
+
+on_finish:
+ if (!success) {
+ s_parameters_destroy(parameters);
+ parameters = NULL;
+ }
+ aws_string_destroy(profile_name);
+ aws_profile_collection_release(config_profile_collection);
+
+ return parameters;
+}
+
+struct aws_credentials_provider *aws_credentials_provider_new_sso(
+ struct aws_allocator *allocator,
+ const struct aws_credentials_provider_sso_options *options) {
+
+ struct sso_parameters *parameters = s_parameters_new(allocator, options);
+ if (!parameters) {
+ return NULL;
+ }
+
+ struct aws_credentials_provider *provider = NULL;
+ struct aws_credentials_provider_sso_impl *impl = NULL;
+ struct aws_tls_connection_options tls_connection_options;
+
+ aws_mem_acquire_many(
+ allocator,
+ 2,
+ &provider,
+ sizeof(struct aws_credentials_provider),
+ &impl,
+ sizeof(struct aws_credentials_provider_sso_impl));
+
+ AWS_ZERO_STRUCT(*provider);
+ AWS_ZERO_STRUCT(*impl);
+ AWS_ZERO_STRUCT(tls_connection_options);
+
+ aws_credentials_provider_init_base(provider, allocator, &s_aws_credentials_provider_sso_vtable, impl);
+
+ if (!options->tls_ctx) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "(id=%p): a TLS context must be provided", (void *)provider);
+ aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
+ goto on_error;
+ }
+
+ if (!options->bootstrap) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER, "(id=%p): a bootstrap instance must be provided", (void *)provider);
+ aws_raise_error(AWS_ERROR_INVALID_ARGUMENT);
+ goto on_error;
+ }
+
+ aws_tls_connection_options_init_from_ctx(&tls_connection_options, options->tls_ctx);
+ struct aws_byte_cursor host = aws_byte_cursor_from_buf(&parameters->endpoint);
+ if (aws_tls_connection_options_set_server_name(&tls_connection_options, allocator, &host)) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p): failed to create a tls connection options with error %s",
+ (void *)provider,
+ aws_error_str(aws_last_error()));
+ goto on_error;
+ }
+
+ struct aws_socket_options socket_options;
+ AWS_ZERO_STRUCT(socket_options);
+ socket_options.type = AWS_SOCKET_STREAM;
+ socket_options.domain = AWS_SOCKET_IPV4;
+ socket_options.connect_timeout_ms = (uint32_t)aws_timestamp_convert(
+ SSO_CONNECT_TIMEOUT_DEFAULT_IN_SECONDS, AWS_TIMESTAMP_SECS, AWS_TIMESTAMP_MILLIS, NULL);
+
+ struct aws_http_connection_manager_options manager_options;
+ AWS_ZERO_STRUCT(manager_options);
+ manager_options.bootstrap = options->bootstrap;
+ manager_options.initial_window_size = SSO_RESPONSE_SIZE_LIMIT;
+ manager_options.socket_options = &socket_options;
+ manager_options.host = host;
+ manager_options.port = 443;
+ manager_options.max_connections = 2;
+ manager_options.shutdown_complete_callback = s_on_connection_manager_shutdown;
+ manager_options.shutdown_complete_user_data = provider;
+ manager_options.tls_connection_options = &tls_connection_options;
+
+ impl->function_table = options->function_table;
+ if (impl->function_table == NULL) {
+ impl->function_table = g_aws_credentials_provider_http_function_table;
+ }
+
+ impl->connection_manager = impl->function_table->aws_http_connection_manager_new(allocator, &manager_options);
+ if (impl->connection_manager == NULL) {
+ goto on_error;
+ }
+
+ impl->token_provider = aws_credentials_provider_acquire(parameters->token_provider);
+ impl->endpoint = aws_string_new_from_buf(allocator, &parameters->endpoint);
+ impl->sso_account_id = aws_string_new_from_string(allocator, parameters->sso_account_id);
+ impl->sso_role_name = aws_string_new_from_string(allocator, parameters->sso_role_name);
+
+ provider->shutdown_options = options->shutdown_options;
+
+ struct aws_standard_retry_options retry_options = {
+ .backoff_retry_options =
+ {
+ .el_group = options->bootstrap->event_loop_group,
+ .max_retries = SSO_MAX_ATTEMPTS,
+ },
+ };
+ impl->retry_strategy = aws_retry_strategy_new_standard(allocator, &retry_options);
+ if (!impl->retry_strategy) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "(id=%p): failed to create a retry strategy with error %s",
+ (void *)provider,
+ aws_error_debug_str(aws_last_error()));
+ goto on_error;
+ }
+
+ s_parameters_destroy(parameters);
+ aws_tls_connection_options_clean_up(&tls_connection_options);
+ return provider;
+
+on_error:
+ aws_credentials_provider_destroy(provider);
+ s_parameters_destroy(parameters);
+ aws_tls_connection_options_clean_up(&tls_connection_options);
+ return NULL;
+}
diff --git a/contrib/restricted/aws/aws-c-auth/source/credentials_utils.c b/contrib/restricted/aws/aws-c-auth/source/credentials_utils.c
index 2cb61d65473..a1ee268c379 100644
--- a/contrib/restricted/aws/aws-c-auth/source/credentials_utils.c
+++ b/contrib/restricted/aws/aws-c-auth/source/credentials_utils.c
@@ -5,6 +5,7 @@
#include <aws/auth/private/credentials_utils.h>
+#include <aws/common/clock.h>
#include <aws/common/date_time.h>
#include <aws/common/json.h>
#include <aws/common/string.h>
@@ -12,6 +13,7 @@
#include <aws/http/connection.h>
#include <aws/http/request_response.h>
#include <aws/http/status_code.h>
+#include <aws/sdkutils/aws_profile.h>
#if defined(_MSC_VER)
# pragma warning(disable : 4232)
@@ -127,6 +129,20 @@ static bool s_parse_expiration_value_from_json_object(
return true;
}
+ case AWS_PCEF_NUMBER_UNIX_EPOCH_MS: {
+ double expiration_value_ms = 0;
+ if (aws_json_value_get_number(value, &expiration_value_ms)) {
+ AWS_LOGF_INFO(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "Unabled to extract credentials Expiration field from Json document.");
+ return false;
+ }
+
+ *expiration_timepoint_in_seconds =
+ aws_timestamp_convert((uint64_t)expiration_value_ms, AWS_TIMESTAMP_MILLIS, AWS_TIMESTAMP_SECS, NULL);
+ return true;
+ }
+
default:
return false;
}
@@ -251,16 +267,29 @@ done:
struct aws_credentials *aws_parse_credentials_from_json_document(
struct aws_allocator *allocator,
- const char *document,
+ struct aws_byte_cursor document,
const struct aws_parse_credentials_from_json_doc_options *options) {
+ struct aws_credentials *credentials = NULL;
- struct aws_json_value *document_root =
- aws_json_value_new_from_string(allocator, aws_byte_cursor_from_c_str(document));
+ struct aws_json_value *document_root = aws_json_value_new_from_string(allocator, document);
if (document_root == NULL) {
AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "Failed to parse document as Json document.");
return NULL;
}
- struct aws_credentials *credentials = aws_parse_credentials_from_aws_json_object(allocator, document_root, options);
+
+ struct aws_json_value *top_level_object = NULL;
+ if (options->top_level_object_name) {
+ top_level_object =
+ aws_json_value_get_from_object(document_root, aws_byte_cursor_from_c_str(options->top_level_object_name));
+ if (!top_level_object) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "failed to parse top level object in json document.");
+ goto done;
+ }
+ }
+
+ credentials = aws_parse_credentials_from_aws_json_object(
+ allocator, top_level_object ? top_level_object : document_root, options);
+done:
aws_json_value_destroy(document_root);
return credentials;
}
@@ -292,3 +321,37 @@ enum aws_retry_error_type aws_credentials_provider_compute_retry_error_type(int
return error_type;
}
+
+struct aws_profile_collection *aws_load_profile_collection_from_config_file(
+ struct aws_allocator *allocator,
+ struct aws_byte_cursor config_file_name_override) {
+
+ struct aws_profile_collection *config_profiles = NULL;
+ struct aws_string *config_file_path = NULL;
+
+ config_file_path = aws_get_config_file_path(allocator, &config_file_name_override);
+ if (!config_file_path) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "Failed to resolve config file path: %s",
+ aws_error_str(aws_last_error()));
+ return NULL;
+ }
+
+ config_profiles = aws_profile_collection_new_from_file(allocator, config_file_path, AWS_PST_CONFIG);
+ if (config_profiles != NULL) {
+ AWS_LOGF_DEBUG(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "Successfully built config profile collection from file at (%s)",
+ aws_string_c_str(config_file_path));
+ } else {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "Failed to build config profile collection from file at (%s) : %s",
+ aws_string_c_str(config_file_path),
+ aws_error_str(aws_last_error()));
+ }
+
+ aws_string_destroy(config_file_path);
+ return config_profiles;
+}
diff --git a/contrib/restricted/aws/aws-c-auth/source/sso_token_utils.c b/contrib/restricted/aws/aws-c-auth/source/sso_token_utils.c
new file mode 100644
index 00000000000..7b90ef43ed2
--- /dev/null
+++ b/contrib/restricted/aws/aws-c-auth/source/sso_token_utils.c
@@ -0,0 +1,160 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/auth/private/sso_token_utils.h>
+#include <aws/cal/hash.h>
+#include <aws/common/encoding.h>
+#include <aws/common/file.h>
+#include <aws/common/json.h>
+
+#if defined(_MSC_VER)
+# pragma warning(disable : 4232)
+#endif /* _MSC_VER */
+
+struct aws_string *aws_construct_sso_token_path(struct aws_allocator *allocator, const struct aws_string *input) {
+ AWS_PRECONDITION(input);
+
+ struct aws_string *sso_token_path_str = NULL;
+
+ struct aws_string *home_directory = aws_get_home_directory(allocator);
+ if (!home_directory) {
+ return NULL;
+ }
+
+ struct aws_byte_cursor home_dir_cursor = aws_byte_cursor_from_string(home_directory);
+ struct aws_byte_cursor input_cursor = aws_byte_cursor_from_string(input);
+ struct aws_byte_cursor json_cursor = aws_byte_cursor_from_c_str(".json");
+
+ struct aws_byte_buf sso_token_path_buf;
+ AWS_ZERO_STRUCT(sso_token_path_buf);
+ struct aws_byte_buf sha1_buf;
+ AWS_ZERO_STRUCT(sha1_buf);
+
+ /* append home directory */
+ if (aws_byte_buf_init_copy_from_cursor(&sso_token_path_buf, allocator, home_dir_cursor)) {
+ goto cleanup;
+ }
+
+ /* append sso cache directory */
+ struct aws_byte_cursor sso_cache_dir_cursor = aws_byte_cursor_from_c_str("/.aws/sso/cache/");
+ if (aws_byte_buf_append_dynamic(&sso_token_path_buf, &sso_cache_dir_cursor)) {
+ goto cleanup;
+ }
+
+ /* append hex encoded sha1 of input */
+ if (aws_byte_buf_init(&sha1_buf, allocator, AWS_SHA1_LEN) ||
+ aws_sha1_compute(allocator, &input_cursor, &sha1_buf, 0)) {
+ goto cleanup;
+ }
+ struct aws_byte_cursor sha1_cursor = aws_byte_cursor_from_buf(&sha1_buf);
+ if (aws_hex_encode_append_dynamic(&sha1_cursor, &sso_token_path_buf)) {
+ goto cleanup;
+ }
+
+ /* append .json */
+ if (aws_byte_buf_append_dynamic(&sso_token_path_buf, &json_cursor)) {
+ goto cleanup;
+ }
+
+ /* use platform-specific directory separator. */
+ aws_normalize_directory_separator(&sso_token_path_buf);
+
+ sso_token_path_str = aws_string_new_from_buf(allocator, &sso_token_path_buf);
+ AWS_LOGF_INFO(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "successfully constructed token path: %s",
+ aws_string_c_str(sso_token_path_str));
+cleanup:
+ aws_byte_buf_clean_up(&sso_token_path_buf);
+ aws_byte_buf_clean_up(&sha1_buf);
+ aws_string_destroy(home_directory);
+ return sso_token_path_str;
+}
+
+void aws_sso_token_destroy(struct aws_sso_token *sso_token) {
+ if (sso_token == NULL) {
+ return;
+ }
+
+ aws_string_destroy(sso_token->access_token);
+ aws_mem_release(sso_token->allocator, sso_token);
+}
+
+struct aws_sso_token *aws_sso_token_new_from_file(struct aws_allocator *allocator, const struct aws_string *file_path) {
+ AWS_PRECONDITION(allocator);
+ AWS_PRECONDITION(file_path);
+
+ bool success = false;
+
+ struct aws_sso_token *token = aws_mem_calloc(allocator, 1, sizeof(struct aws_sso_token));
+ token->allocator = allocator;
+ struct aws_byte_buf file_contents_buf;
+ AWS_ZERO_STRUCT(file_contents_buf);
+ struct aws_json_value *document_root = NULL;
+
+ if (aws_byte_buf_init_from_file(&file_contents_buf, allocator, aws_string_c_str(file_path))) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER, "sso token: failed to load token file %s", aws_string_c_str(file_path));
+ goto cleanup;
+ }
+
+ struct aws_byte_cursor document_cursor = aws_byte_cursor_from_buf(&file_contents_buf);
+ document_root = aws_json_value_new_from_string(allocator, document_cursor);
+ if (document_root == NULL) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "sso token: failed to parse sso token file %s",
+ aws_string_c_str(file_path));
+ aws_raise_error(AWS_AUTH_SSO_TOKEN_INVALID);
+ goto cleanup;
+ }
+
+ struct aws_byte_cursor access_token_cursor;
+ struct aws_json_value *access_token =
+ aws_json_value_get_from_object(document_root, aws_byte_cursor_from_c_str("accessToken"));
+ if (!aws_json_value_is_string(access_token) || aws_json_value_get_string(access_token, &access_token_cursor)) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "sso token: failed to parse accessToken from %s",
+ aws_string_c_str(file_path));
+ aws_raise_error(AWS_AUTH_SSO_TOKEN_INVALID);
+ goto cleanup;
+ }
+
+ struct aws_byte_cursor expires_at_cursor;
+ struct aws_json_value *expires_at =
+ aws_json_value_get_from_object(document_root, aws_byte_cursor_from_c_str("expiresAt"));
+ if (!aws_json_value_is_string(expires_at) || aws_json_value_get_string(expires_at, &expires_at_cursor)) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "sso token: failed to parse expiresAt from %s",
+ aws_string_c_str(file_path));
+ aws_raise_error(AWS_AUTH_SSO_TOKEN_INVALID);
+ goto cleanup;
+ }
+ struct aws_date_time expiration;
+ if (aws_date_time_init_from_str_cursor(&expiration, &expires_at_cursor, AWS_DATE_FORMAT_ISO_8601)) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "sso token: expiresAt '" PRInSTR "' in %s is not a valid ISO-8601 date string",
+ AWS_BYTE_CURSOR_PRI(expires_at_cursor),
+ aws_string_c_str(file_path));
+ aws_raise_error(AWS_AUTH_SSO_TOKEN_INVALID);
+ goto cleanup;
+ }
+ token->access_token = aws_string_new_from_cursor(allocator, &access_token_cursor);
+ token->expiration = expiration;
+
+ success = true;
+
+cleanup:
+ aws_json_value_destroy(document_root);
+ aws_byte_buf_clean_up(&file_contents_buf);
+ if (!success) {
+ aws_sso_token_destroy(token);
+ token = NULL;
+ }
+ return token;
+}
diff --git a/contrib/restricted/aws/aws-c-auth/source/token_provider_sso_profile.c b/contrib/restricted/aws/aws-c-auth/source/token_provider_sso_profile.c
new file mode 100644
index 00000000000..6e2a3521f72
--- /dev/null
+++ b/contrib/restricted/aws/aws-c-auth/source/token_provider_sso_profile.c
@@ -0,0 +1,186 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/auth/credentials.h>
+
+#include <aws/auth/private/aws_profile.h>
+#include <aws/auth/private/credentials_utils.h>
+#include <aws/auth/private/sso_token_providers.h>
+#include <aws/auth/private/sso_token_utils.h>
+#include <aws/common/clock.h>
+
+#ifdef _MSC_VER
+/* allow non-constant declared initializers. */
+# pragma warning(disable : 4204)
+#endif
+
+/*
+ * sso-token profile provider implementation
+ */
+struct aws_token_provider_profile_impl {
+ struct aws_string *sso_token_file_path;
+
+ aws_io_clock_fn *system_clock_fn;
+};
+
+static int s_token_provider_profile_get_token(
+ struct aws_credentials_provider *provider,
+ aws_on_get_credentials_callback_fn callback,
+ void *user_data) {
+ struct aws_token_provider_profile_impl *impl = provider->impl;
+
+ struct aws_sso_token *sso_token = NULL;
+ struct aws_credentials *credentials = NULL;
+ int result = AWS_OP_ERR;
+ sso_token = aws_sso_token_new_from_file(provider->allocator, impl->sso_token_file_path);
+ if (!sso_token) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "(id=%p) failed to get sso token from file", (void *)provider);
+ goto done;
+ }
+
+ /* check token expiration. */
+ uint64_t now_ns = UINT64_MAX;
+ if (impl->system_clock_fn(&now_ns) != AWS_OP_SUCCESS) {
+ goto done;
+ }
+
+ if (aws_date_time_as_nanos(&sso_token->expiration) <= now_ns) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "(id=%p) cached sso token is expired.", (void *)provider);
+ aws_raise_error(AWS_AUTH_SSO_TOKEN_EXPIRED);
+ goto done;
+ }
+
+ credentials = aws_credentials_new_token(
+ provider->allocator,
+ aws_byte_cursor_from_string(sso_token->access_token),
+ (uint64_t)aws_date_time_as_epoch_secs(&sso_token->expiration));
+ if (!credentials) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "(id=%p) Unable to construct credentials.", (void *)provider);
+ goto done;
+ }
+
+ callback(credentials, AWS_OP_SUCCESS, user_data);
+ result = AWS_OP_SUCCESS;
+
+done:
+ aws_sso_token_destroy(sso_token);
+ aws_credentials_release(credentials);
+ return result;
+}
+
+static void s_token_provider_profile_destroy(struct aws_credentials_provider *provider) {
+ struct aws_token_provider_profile_impl *impl = provider->impl;
+ if (impl == NULL) {
+ return;
+ }
+
+ aws_string_destroy(impl->sso_token_file_path);
+
+ aws_credentials_provider_invoke_shutdown_callback(provider);
+ aws_mem_release(provider->allocator, provider);
+}
+
+static struct aws_credentials_provider_vtable s_aws_token_provider_profile_vtable = {
+ .get_credentials = s_token_provider_profile_get_token,
+ .destroy = s_token_provider_profile_destroy,
+};
+
+AWS_STRING_FROM_LITERAL(s_profile_sso_start_url_name, "sso_start_url");
+
+static struct aws_string *s_construct_profile_sso_token_path(
+ struct aws_allocator *allocator,
+ const struct aws_token_provider_sso_profile_options *options) {
+
+ struct aws_profile_collection *config_collection = NULL;
+ struct aws_string *profile_name = NULL;
+ struct aws_string *sso_token_path = NULL;
+
+ profile_name = aws_get_profile_name(allocator, &options->profile_name_override);
+ if (!profile_name) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "token-provider-sso-profile: failed to resolve profile name");
+ aws_raise_error(AWS_AUTH_SSO_TOKEN_PROVIDER_SOURCE_FAILURE);
+ goto cleanup;
+ }
+ if (options->config_file_cached) {
+ /* Use cached config file */
+ config_collection = aws_profile_collection_acquire(options->config_file_cached);
+ } else {
+ /* load config file */
+ config_collection = aws_load_profile_collection_from_config_file(allocator, options->config_file_name_override);
+ }
+
+ if (!config_collection) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "token-provider-sso-profile: could not load or parse"
+ " a config file.");
+ aws_raise_error(AWS_AUTH_SSO_TOKEN_PROVIDER_SOURCE_FAILURE);
+ goto cleanup;
+ }
+
+ const struct aws_profile *profile = aws_profile_collection_get_profile(config_collection, profile_name);
+
+ if (!profile) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "token-provider-sso-profile: could not load"
+ " a profile at %s.",
+ aws_string_c_str(profile_name));
+ aws_raise_error(AWS_AUTH_SSO_TOKEN_PROVIDER_SOURCE_FAILURE);
+ goto cleanup;
+ }
+
+ const struct aws_profile_property *sso_start_url_property =
+ aws_profile_get_property(profile, s_profile_sso_start_url_name);
+
+ if (!sso_start_url_property) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "token-provider-sso-profile: failed to find sso_start_url");
+ aws_raise_error(AWS_AUTH_SSO_TOKEN_PROVIDER_SOURCE_FAILURE);
+ goto cleanup;
+ }
+
+ sso_token_path = aws_construct_sso_token_path(allocator, aws_profile_property_get_value(sso_start_url_property));
+ if (!sso_token_path) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "token-provider-sso-profile: failed to construct token path");
+ goto cleanup;
+ }
+
+cleanup:
+ aws_string_destroy(profile_name);
+ aws_profile_collection_release(config_collection);
+ return sso_token_path;
+}
+
+struct aws_credentials_provider *aws_token_provider_new_sso_profile(
+ struct aws_allocator *allocator,
+ const struct aws_token_provider_sso_profile_options *options) {
+ struct aws_string *token_path = s_construct_profile_sso_token_path(allocator, options);
+ if (!token_path) {
+ return NULL;
+ }
+ struct aws_credentials_provider *provider = NULL;
+ struct aws_token_provider_profile_impl *impl = NULL;
+
+ aws_mem_acquire_many(
+ allocator,
+ 2,
+ &provider,
+ sizeof(struct aws_credentials_provider),
+ &impl,
+ sizeof(struct aws_token_provider_profile_impl));
+ AWS_ZERO_STRUCT(*provider);
+ AWS_ZERO_STRUCT(*impl);
+ aws_credentials_provider_init_base(provider, allocator, &s_aws_token_provider_profile_vtable, impl);
+ impl->sso_token_file_path = aws_string_new_from_string(allocator, token_path);
+ provider->shutdown_options = options->shutdown_options;
+ if (options->system_clock_fn) {
+ impl->system_clock_fn = options->system_clock_fn;
+ } else {
+ impl->system_clock_fn = aws_sys_clock_get_ticks;
+ }
+
+ aws_string_destroy(token_path);
+ return provider;
+}
diff --git a/contrib/restricted/aws/aws-c-auth/source/token_provider_sso_session.c b/contrib/restricted/aws/aws-c-auth/source/token_provider_sso_session.c
new file mode 100644
index 00000000000..e3a17b7f5bc
--- /dev/null
+++ b/contrib/restricted/aws/aws-c-auth/source/token_provider_sso_session.c
@@ -0,0 +1,251 @@
+/**
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0.
+ */
+
+#include <aws/auth/credentials.h>
+
+#include <aws/auth/private/aws_profile.h>
+#include <aws/auth/private/credentials_utils.h>
+#include <aws/auth/private/sso_token_providers.h>
+#include <aws/auth/private/sso_token_utils.h>
+#include <aws/common/clock.h>
+
+#ifdef _MSC_VER
+/* allow non-constant declared initializers. */
+# pragma warning(disable : 4204)
+#endif
+
+/*
+ * sso-session token provider implementation
+ */
+struct aws_token_provider_sso_session_impl {
+ struct aws_string *sso_token_file_path;
+ aws_io_clock_fn *system_clock_fn;
+};
+
+static int s_token_provider_sso_session_get_token(
+ struct aws_credentials_provider *provider,
+ aws_on_get_credentials_callback_fn callback,
+ void *user_data) {
+
+ struct aws_token_provider_sso_session_impl *impl = provider->impl;
+ struct aws_sso_token *sso_token = NULL;
+ struct aws_credentials *credentials = NULL;
+ int result = AWS_OP_ERR;
+
+ sso_token = aws_sso_token_new_from_file(provider->allocator, impl->sso_token_file_path);
+ if (!sso_token) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER, "(id=%p) failed to get sso token from file.", (void *)provider);
+ goto done;
+ }
+
+ /* check token expiration. */
+ uint64_t now_ns = UINT64_MAX;
+ if (impl->system_clock_fn(&now_ns) != AWS_OP_SUCCESS) {
+ goto done;
+ }
+
+ if (aws_date_time_as_nanos(&sso_token->expiration) <= now_ns) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "(id=%p) cached sso token is expired.", (void *)provider);
+ aws_raise_error(AWS_AUTH_SSO_TOKEN_EXPIRED);
+ goto done;
+ }
+
+ /* TODO: Refresh token if it is within refresh window and refreshable */
+
+ credentials = aws_credentials_new_token(
+ provider->allocator,
+ aws_byte_cursor_from_string(sso_token->access_token),
+ (uint64_t)aws_date_time_as_epoch_secs(&sso_token->expiration));
+ if (!credentials) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "(id=%p) Unable to construct credentials.", (void *)provider);
+ goto done;
+ }
+ callback(credentials, AWS_OP_SUCCESS, user_data);
+ result = AWS_OP_SUCCESS;
+
+done:
+ aws_sso_token_destroy(sso_token);
+ aws_credentials_release(credentials);
+ return result;
+}
+
+static void s_token_provider_sso_session_destroy(struct aws_credentials_provider *provider) {
+ struct aws_token_provider_sso_session_impl *impl = provider->impl;
+ if (impl == NULL) {
+ return;
+ }
+
+ aws_string_destroy(impl->sso_token_file_path);
+
+ aws_credentials_provider_invoke_shutdown_callback(provider);
+ aws_mem_release(provider->allocator, provider);
+}
+
+static struct aws_credentials_provider_vtable s_aws_token_provider_sso_session_vtable = {
+ .get_credentials = s_token_provider_sso_session_get_token,
+ .destroy = s_token_provider_sso_session_destroy,
+};
+
+AWS_STRING_FROM_LITERAL(s_sso_session_name, "sso_session");
+AWS_STRING_FROM_LITERAL(s_sso_region_name, "sso_region");
+AWS_STRING_FROM_LITERAL(s_sso_start_url_name, "sso_start_url");
+
+/**
+ * Parses the config file to validate and construct a token path. A valid profile with sso session is as follow
+ * [profile sso-profile]
+ * sso_session = dev
+ * sso_account_id = 012345678901
+ * sso_role_name = SampleRole
+ *
+ * [sso-session dev]
+ * sso_region = us-east-1
+ * sso_start_url = https://d-abc123.awsapps.com/start
+ */
+static struct aws_string *s_verify_config_and_construct_sso_token_path(
+ struct aws_allocator *allocator,
+ const struct aws_token_provider_sso_session_options *options) {
+ struct aws_profile_collection *config_collection = NULL;
+ struct aws_string *profile_name = NULL;
+ struct aws_string *sso_token_path = NULL;
+
+ profile_name = aws_get_profile_name(allocator, &options->profile_name_override);
+ if (!profile_name) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "sso-session: token provider failed to resolve profile name");
+ goto cleanup;
+ }
+ if (options->config_file_cached) {
+ /* Use cached config file */
+ config_collection = aws_profile_collection_acquire(options->config_file_cached);
+ } else {
+ /* load config file */
+ config_collection = aws_load_profile_collection_from_config_file(allocator, options->config_file_name_override);
+ }
+ if (!config_collection) {
+ goto cleanup;
+ }
+
+ const struct aws_profile *profile = aws_profile_collection_get_profile(config_collection, profile_name);
+
+ if (!profile) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "sso-session: token provider could not load"
+ " a profile at %s.",
+ aws_string_c_str(profile_name));
+ goto cleanup;
+ }
+
+ const struct aws_profile_property *sso_session_property = aws_profile_get_property(profile, s_sso_session_name);
+ if (!sso_session_property) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "token-provider-sso-session: token provider could not find an sso-session at profile %s",
+ aws_string_c_str(profile_name));
+ aws_raise_error(AWS_AUTH_SSO_TOKEN_PROVIDER_SOURCE_FAILURE);
+ goto cleanup;
+ }
+ const struct aws_string *sso_session_name = aws_profile_property_get_value(sso_session_property);
+
+ /* parse sso_session */
+ const struct aws_profile *session_profile =
+ aws_profile_collection_get_section(config_collection, AWS_PROFILE_SECTION_TYPE_SSO_SESSION, sso_session_name);
+ if (!session_profile) {
+ AWS_LOGF_ERROR(AWS_LS_AUTH_CREDENTIALS_PROVIDER, "token-provider-sso-session: failed to find an sso-session");
+ aws_raise_error(AWS_AUTH_SSO_TOKEN_PROVIDER_SOURCE_FAILURE);
+ goto cleanup;
+ }
+
+ const struct aws_profile_property *sso_region_property =
+ aws_profile_get_property(session_profile, s_sso_region_name);
+ const struct aws_profile_property *sso_start_url_property =
+ aws_profile_get_property(session_profile, s_sso_start_url_name);
+
+ if (!sso_region_property) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER, "token-provider-sso-session: failed to find sso_region in sso-session");
+ aws_raise_error(AWS_AUTH_SSO_TOKEN_PROVIDER_SOURCE_FAILURE);
+ goto cleanup;
+ }
+
+ if (!sso_start_url_property) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "token-provider-sso-session: failed to find sso_start_url in sso-session");
+ aws_raise_error(AWS_AUTH_SSO_TOKEN_PROVIDER_SOURCE_FAILURE);
+ goto cleanup;
+ }
+
+ /* Verify sso_region & start_url are the same in profile section if they exist */
+ const struct aws_string *sso_region = aws_profile_property_get_value(sso_region_property);
+ const struct aws_string *sso_start_url = aws_profile_property_get_value(sso_start_url_property);
+
+ const struct aws_profile_property *profile_sso_region_property =
+ aws_profile_get_property(profile, s_sso_region_name);
+ const struct aws_profile_property *profile_sso_start_url_property =
+ aws_profile_get_property(profile, s_sso_start_url_name);
+
+ if (profile_sso_region_property &&
+ !aws_string_eq(sso_region, aws_profile_property_get_value(profile_sso_region_property))) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "token-provider-sso-session: profile & sso-session have different value for sso_region");
+ aws_raise_error(AWS_AUTH_SSO_TOKEN_PROVIDER_SOURCE_FAILURE);
+ goto cleanup;
+ }
+
+ if (profile_sso_start_url_property &&
+ !aws_string_eq(sso_start_url, aws_profile_property_get_value(profile_sso_start_url_property))) {
+ AWS_LOGF_ERROR(
+ AWS_LS_AUTH_CREDENTIALS_PROVIDER,
+ "token-provider-sso-session: profile & sso-session have different value for sso_start_url");
+ aws_raise_error(AWS_AUTH_SSO_TOKEN_PROVIDER_SOURCE_FAILURE);
+ goto cleanup;
+ }
+
+ sso_token_path = aws_construct_sso_token_path(allocator, sso_session_name);
+
+cleanup:
+ aws_string_destroy(profile_name);
+ aws_profile_collection_release(config_collection);
+ return sso_token_path;
+}
+
+struct aws_credentials_provider *aws_token_provider_new_sso_session(
+ struct aws_allocator *allocator,
+ const struct aws_token_provider_sso_session_options *options) {
+
+ /* Currently, they are not used but they will be required when we implement the refresh token functionality. */
+ AWS_ASSERT(options->bootstrap);
+ AWS_ASSERT(options->tls_ctx);
+
+ struct aws_string *token_path = s_verify_config_and_construct_sso_token_path(allocator, options);
+ if (!token_path) {
+ return NULL;
+ }
+ struct aws_credentials_provider *provider = NULL;
+ struct aws_token_provider_sso_session_impl *impl = NULL;
+
+ aws_mem_acquire_many(
+ allocator,
+ 2,
+ &provider,
+ sizeof(struct aws_credentials_provider),
+ &impl,
+ sizeof(struct aws_token_provider_sso_session_impl));
+ AWS_ZERO_STRUCT(*provider);
+ AWS_ZERO_STRUCT(*impl);
+ aws_credentials_provider_init_base(provider, allocator, &s_aws_token_provider_sso_session_vtable, impl);
+ impl->sso_token_file_path = aws_string_new_from_string(allocator, token_path);
+ provider->shutdown_options = options->shutdown_options;
+ if (options->system_clock_fn) {
+ impl->system_clock_fn = options->system_clock_fn;
+ } else {
+ impl->system_clock_fn = aws_sys_clock_get_ticks;
+ }
+
+ aws_string_destroy(token_path);
+ return provider;
+}
diff --git a/contrib/restricted/aws/aws-c-auth/ya.make b/contrib/restricted/aws/aws-c-auth/ya.make
index a0f2151cee7..ef7a8fc1530 100644
--- a/contrib/restricted/aws/aws-c-auth/ya.make
+++ b/contrib/restricted/aws/aws-c-auth/ya.make
@@ -6,9 +6,9 @@ LICENSE(Apache-2.0)
LICENSE_TEXTS(.yandex_meta/licenses.list.txt)
-VERSION(0.6.26)
+VERSION(0.6.27)
-ORIGINAL_SOURCE(https://github.com/awslabs/aws-c-auth/archive/v0.6.26.tar.gz)
+ORIGINAL_SOURCE(https://github.com/awslabs/aws-c-auth/archive/v0.6.27.tar.gz)
PEERDIR(
contrib/restricted/aws/aws-c-cal
@@ -51,6 +51,12 @@ CFLAGS(
-DS2N___RESTRICT__SUPPORTED
)
+IF (OS_WINDOWS)
+ CFLAGS(
+ -DAWS_AUTH_EXPORTS
+ )
+ENDIF()
+
SRCS(
source/auth.c
source/aws_imds_client.c
@@ -68,6 +74,7 @@ SRCS(
source/credentials_provider_imds.c
source/credentials_provider_process.c
source/credentials_provider_profile.c
+ source/credentials_provider_sso.c
source/credentials_provider_static.c
source/credentials_provider_sts.c
source/credentials_provider_sts_web_identity.c
@@ -82,6 +89,9 @@ SRCS(
source/signing_config.c
source/signing_result.c
source/sigv4_http_request.c
+ source/sso_token_utils.c
+ source/token_provider_sso_profile.c
+ source/token_provider_sso_session.c
)
END()
diff --git a/library/cpp/netliba/socket/creators.cpp b/library/cpp/netliba/socket/creators.cpp
index 3821bf55b96..f9a3b9830c4 100644
--- a/library/cpp/netliba/socket/creators.cpp
+++ b/library/cpp/netliba/socket/creators.cpp
@@ -61,7 +61,7 @@ namespace NNetlibaSocket {
*(ui8*)CMSG_DATA(cmsgTos) = tos;
#endif
- if (*(ui64*)myAddr.sin6_addr.s6_addr != 0u) {
+ if (((ui64*)myAddr.sin6_addr.s6_addr)[0] != 0u || ((ui64*)myAddr.sin6_addr.s6_addr)[1] != 0u) {
in6_pktinfo* pktInfo;
#ifdef _cygwin_
cmsghdr* cmsgAddr = CMSG_FIRSTHDR(header);
diff --git a/library/cpp/sanitizer/address/static/ya.make b/library/cpp/sanitizer/address/static/ya.make
index d8cf24a8487..7210cbced90 100644
--- a/library/cpp/sanitizer/address/static/ya.make
+++ b/library/cpp/sanitizer/address/static/ya.make
@@ -1,7 +1,5 @@
LIBRARY()
-SUBSCRIBER(g:devtools-contrib)
-
NO_UTIL()
PEERDIR(
diff --git a/library/cpp/sanitizer/memory/static/ya.make b/library/cpp/sanitizer/memory/static/ya.make
index ab10fb9c88d..0955ec62d8c 100644
--- a/library/cpp/sanitizer/memory/static/ya.make
+++ b/library/cpp/sanitizer/memory/static/ya.make
@@ -1,7 +1,5 @@
LIBRARY()
-SUBSCRIBER(g:devtools-contrib)
-
NO_UTIL()
PEERDIR(
diff --git a/library/cpp/sanitizer/thread/static/ya.make b/library/cpp/sanitizer/thread/static/ya.make
index 0a09b0098cc..7cbd7b9fd5e 100644
--- a/library/cpp/sanitizer/thread/static/ya.make
+++ b/library/cpp/sanitizer/thread/static/ya.make
@@ -1,7 +1,5 @@
LIBRARY()
-SUBSCRIBER(g:devtools-contrib)
-
NO_UTIL()
PEERDIR(
diff --git a/library/cpp/testing/dump_clang_coverage/write_profile_data.cpp b/library/cpp/testing/dump_clang_coverage/write_profile_data.cpp
new file mode 100644
index 00000000000..8b13474cc8f
--- /dev/null
+++ b/library/cpp/testing/dump_clang_coverage/write_profile_data.cpp
@@ -0,0 +1,125 @@
+#include <dlfcn.h>
+#include <linux/limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+extern "C" {
+ void __llvm_profile_initialize_file(void);
+ int __llvm_profile_write_file(void);
+ void __llvm_profile_set_filename(const char* filename_pattern);
+
+ // there might no llmv rt, for example for the targets from contrib
+ __attribute__((weak)) int __llvm_profile_write_file(void) {
+ return 0;
+ }
+ __attribute__((weak)) void __llvm_profile_initialize_file(void) {
+ }
+ __attribute__((weak)) void __llvm_profile_set_filename(const char*) {
+ }
+}
+
+namespace {
+ void dummy() {
+ }
+}
+
+bool getSoName(char* buff, size_t size) {
+ // returns so name for shared objects and exe_name for binaries
+ Dl_info dl_info = {0, 0, 0, 0};
+ if (dladdr((void*)(intptr_t)dummy, &dl_info) != 0) {
+ if (dl_info.dli_fname) {
+ const char* name = dl_info.dli_fname;
+ char real_path[PATH_MAX];
+ const char* resolved = realpath(name, real_path);
+ if (resolved != NULL)
+ name = real_path;
+ const char* lastSlash = strrchr(name, '/');
+ if (!!lastSlash) {
+ name = lastSlash + 1;
+ }
+ strncpy(buff, name, size);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool getExeName(char* buff, size_t size) {
+ ssize_t len = readlink("/proc/self/exe", buff, size);
+ if (len <= 0) {
+ return false;
+ }
+
+ buff[len] = '\0';
+ char* lastSlash = strrchr(buff, '/');
+ if (!!lastSlash) {
+ strncpy(buff, lastSlash + 1, size);
+ buff[(buff + len) - lastSlash] = '\0';
+ }
+ return true;
+}
+
+bool getSelfName(char* buff, size_t size) {
+#if defined(_musl_)
+ return getExeName(buff, size);
+#else
+ return getSoName(buff, size);
+#endif
+}
+
+void replaceFirst(char* data, size_t dsize, const char* pat, size_t psize, const char* repl, size_t rsize) {
+ char* patPtr = strstr(data, pat);
+ if (!patPtr) {
+ return;
+ }
+
+ char tmp[PATH_MAX] = {0};
+ char* tmpPtr = &tmp[0];
+
+ strcpy(tmpPtr, patPtr + psize);
+ strcpy(patPtr, repl);
+ strcpy(patPtr + rsize, tmpPtr);
+ data[dsize - psize + rsize] = '\0';
+}
+
+// Adds support of the specifier '%e' (executable filename (without path prefix)) to the LLVM_PROFILE_FILE
+void parseAndSetFilename() {
+ const char* profile_file = getenv("LLVM_PROFILE_FILE");
+ if (!profile_file)
+ return;
+
+ // __llvm_profile_set_filename doesn't copy name, so it must remain valid
+ static char pattern[PATH_MAX] = {0};
+ char* patternPtr = &pattern[0];
+
+ strncpy(patternPtr, profile_file, PATH_MAX - 1);
+
+ if (!!strstr(patternPtr, "%e")) {
+ char buff[PATH_MAX] = {0};
+ char* buffPtr = &buff[0];
+
+ if (getSelfName(buffPtr, PATH_MAX)) {
+ size_t patternSize = strlen(patternPtr);
+ size_t buffSize = strlen(buffPtr);
+
+ if (patternSize + buffSize >= PATH_MAX) {
+ abort();
+ }
+ replaceFirst(patternPtr, patternSize, "%e", 2, buffPtr, buffSize);
+ }
+ }
+
+ __llvm_profile_set_filename(patternPtr);
+}
+
+void __attribute__((constructor)) premain() {
+ parseAndSetFilename();
+ if (getenv("YA_COVERAGE_DUMP_PROFILE_AND_EXIT")) {
+ __llvm_profile_initialize_file();
+ int rc = __llvm_profile_write_file();
+ if (!rc && getenv("YA_COVERAGE_DUMP_PROFILE_EXIT_CODE"))
+ rc = atoi(getenv("YA_COVERAGE_DUMP_PROFILE_EXIT_CODE"));
+ exit(rc);
+ }
+}
diff --git a/library/cpp/testing/dump_clang_coverage/ya.make b/library/cpp/testing/dump_clang_coverage/ya.make
new file mode 100644
index 00000000000..26eb36048c2
--- /dev/null
+++ b/library/cpp/testing/dump_clang_coverage/ya.make
@@ -0,0 +1,13 @@
+LIBRARY()
+
+NO_CLANG_COVERAGE()
+
+NO_RUNTIME()
+
+IF (OS_LINUX)
+ SRCS(
+ GLOBAL write_profile_data.cpp
+ )
+ENDIF()
+
+END()
diff --git a/ydb/ci/rightlib.txt b/ydb/ci/rightlib.txt
index 51edbdc360c..fda17fed09c 100644
--- a/ydb/ci/rightlib.txt
+++ b/ydb/ci/rightlib.txt
@@ -1 +1 @@
-24211947581091f2f54c8e50e3427e6621dfec3d
+b0c2229a8d320931b2a986503a39f0f805956f11
diff --git a/yql/essentials/tests/sql/sql2yql/canondata/result.json b/yql/essentials/tests/sql/sql2yql/canondata/result.json
index dac11c7bd37..ad1c6773945 100644
--- a/yql/essentials/tests/sql/sql2yql/canondata/result.json
+++ b/yql/essentials/tests/sql/sql2yql/canondata/result.json
@@ -7559,6 +7559,13 @@
"uri": "https://{canondata_backend}/1936273/4a1b39013e1bae40e722cff8ccef8829784964e2/resource.tar.gz#test_sql2yql.test_hor_join-yql-6477_table_path_/sql.yql"
}
],
+ "test_sql2yql.test[hor_join-yql19332_aux_cols]": [
+ {
+ "checksum": "195e1068ca8926582b211c2b2eb5bfbf",
+ "size": 3144,
+ "uri": "https://{canondata_backend}/1784117/39173fc32d12059e969bfcf094e71dd92d4acaeb/resource.tar.gz#test_sql2yql.test_hor_join-yql19332_aux_cols_/sql.yql"
+ }
+ ],
"test_sql2yql.test[in-basic_in]": [
{
"checksum": "d65b144596eb506f4cc5f1f191a89832",
@@ -25272,6 +25279,11 @@
"uri": "file://test_sql_format.test_hor_join-yql-6477_table_path_/formatted.sql"
}
],
+ "test_sql_format.test[hor_join-yql19332_aux_cols]": [
+ {
+ "uri": "file://test_sql_format.test_hor_join-yql19332_aux_cols_/formatted.sql"
+ }
+ ],
"test_sql_format.test[in-basic_in]": [
{
"uri": "file://test_sql_format.test_in-basic_in_/formatted.sql"
diff --git a/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_hor_join-yql19332_aux_cols_/formatted.sql b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_hor_join-yql19332_aux_cols_/formatted.sql
new file mode 100644
index 00000000000..e5628f6d894
--- /dev/null
+++ b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_hor_join-yql19332_aux_cols_/formatted.sql
@@ -0,0 +1,20 @@
+-- ignore runonopt plan diff
+USE plato;
+PRAGMA DisableSimpleColumns;
+PRAGMA yt.JoinMergeTablesLimit = "10";
+
+$i =
+ SELECT
+ *
+ FROM concat(Input2, Input3)
+ WHERE value != "1";
+
+SELECT
+ b.key,
+ b.subkey,
+ a.value
+FROM Input1
+ AS a
+JOIN $i
+ AS b
+ON (a.key, a.subkey) == (b.key, b.subkey);
diff --git a/yql/essentials/tests/sql/suites/hor_join/yql19332_aux_cols.cfg b/yql/essentials/tests/sql/suites/hor_join/yql19332_aux_cols.cfg
new file mode 100644
index 00000000000..3eb7660ec93
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/hor_join/yql19332_aux_cols.cfg
@@ -0,0 +1,3 @@
+in Input1 sorted.txt
+in Input2 sorted.txt
+in Input3 sorted.txt
diff --git a/yql/essentials/tests/sql/suites/hor_join/yql19332_aux_cols.sql b/yql/essentials/tests/sql/suites/hor_join/yql19332_aux_cols.sql
new file mode 100644
index 00000000000..c84769777c1
--- /dev/null
+++ b/yql/essentials/tests/sql/suites/hor_join/yql19332_aux_cols.sql
@@ -0,0 +1,9 @@
+-- ignore runonopt plan diff
+USE plato;
+pragma DisableSimpleColumns;
+pragma yt.JoinMergeTablesLimit="10";
+
+$i = select * from concat(Input2, Input3) where value != "1";
+
+select b.key, b.subkey, a.value from Input1 as a
+join $i as b on (a.key, a.subkey) == (b.key, b.subkey)
diff --git a/yt/yql/providers/yt/provider/yql_yt_horizontal_join.cpp b/yt/yql/providers/yt/provider/yql_yt_horizontal_join.cpp
index b35f82aca04..f680d995686 100644
--- a/yt/yql/providers/yt/provider/yql_yt_horizontal_join.cpp
+++ b/yt/yql/providers/yt/provider/yql_yt_horizontal_join.cpp
@@ -999,7 +999,7 @@ bool THorizontalJoinOptimizer::MakeJoinedMap(TPositionHandle pos, TExprContext&
else if (nextNewOutIndex < outRemap.size()) {
TVector<TExprBase> tupleTypes;
for (auto out: joinedMapOuts) {
- auto itemType = out.Ref().GetTypeAnn()->Cast<TListExprType>()->GetItemType();
+ auto itemType = TYqlRowSpecInfo(out.RowSpec()).GetExtendedType(ctx);
tupleTypes.push_back(TExprBase(ExpandType(pos, *itemType, ctx)));
}
TExprBase varType = Build<TCoVariantType>(ctx, pos)
diff --git a/yt/yql/providers/yt/provider/yql_yt_physical_finalizing.cpp b/yt/yql/providers/yt/provider/yql_yt_physical_finalizing.cpp
index 01cf4708e7f..1ebcfcc1e12 100644
--- a/yt/yql/providers/yt/provider/yql_yt_physical_finalizing.cpp
+++ b/yt/yql/providers/yt/provider/yql_yt_physical_finalizing.cpp
@@ -1026,10 +1026,12 @@ private:
bool changedOutSort = false;
TVector<TYtOutTable> outTables;
TExprNode::TListType filterColumns(op.Output().Size());
+ TTypeAnnotationNode::TListType varItemTypes(op.Output().Size());
for (size_t i = 0; i < op.Output().Size(); ++i) {
auto out = op.Output().Item(i);
+ auto rowSpec = TYtTableBaseInfo::GetRowSpec(out);
+ varItemTypes[i] = rowSpec->GetExtendedType(ctx);
if (unorderedOuts.Test(i)) {
- auto rowSpec = TYtTableBaseInfo::GetRowSpec(out);
YQL_ENSURE(rowSpec);
if (rowSpec->IsSorted()) {
if (rowSpec->HasAuxColumns()) {
@@ -1038,6 +1040,7 @@ private:
columns.emplace_back(item->GetName());
}
filterColumns[i] = ToAtomList(columns, node.Pos(), ctx);
+ varItemTypes[i] = rowSpec->GetType();
}
rowSpec->ClearSortness(ctx);
outTables.push_back(TYtOutTable(ctx.ChangeChild(out.Ref(), TYtOutTable::idx_RowSpec, rowSpec->ToExprNode(ctx, out.Pos()).Ptr())));
@@ -1156,7 +1159,7 @@ private:
.Build()
.Done().Ptr();
} else {
- auto varType = ExpandType(lambda->Pos(), *GetSeqItemType(node.Child(lambdaIdx)->GetTypeAnn()), ctx);
+ auto varType = ExpandType(lambda->Pos(), *ctx.MakeType<TVariantExprType>(ctx.MakeType<TTupleExprType>(varItemTypes)), ctx);
TVector<TExprBase> visitArgs;
for (size_t i = 0; i < op.Output().Size(); ++i) {
visitArgs.push_back(Build<TCoAtom>(ctx, lambda->Pos()).Value(ToString(i)).Done());
diff --git a/yt/yt/core/misc/proc.cpp b/yt/yt/core/misc/proc.cpp
index 363549b4bf9..e25dd22cc08 100644
--- a/yt/yt/core/misc/proc.cpp
+++ b/yt/yt/core/misc/proc.cpp
@@ -42,6 +42,7 @@
#include <unistd.h>
#endif
#ifdef _linux_
+ #include <fcntl.h>
#include <pty.h>
#include <pwd.h>
#include <grp.h>
@@ -951,6 +952,36 @@ void SafeSetPipeCapacity(int fd, int capacity)
}
}
+bool TryEnableEmptyPipeEpollEvent(TFileDescriptor fd)
+{
+// TODO(arkady-e1ppa): To not waste gpu we swallow an error
+// resulting in a potentially broken behavior.
+// if F_SET_PIPE_WAKE_WRITER is not defined and/or properly
+// implemented we should return false.
+#if defined(_linux_) && defined(F_SET_PIPE_WAKE_WRITER)
+ int res = ::fcntl(fd, F_SET_PIPE_WAKE_WRITER, 1);
+
+ // TODO(arkady-e1ppa): Once kernel version is fresh enough
+ // remove this branch altogether.
+ if (res == -1) {
+ return errno == EINVAL;
+ }
+
+ return res != -1;
+#else
+ Y_UNUSED(fd);
+ return true;
+#endif
+}
+
+void SafeEnableEmptyPipeEpollEvent(TFileDescriptor fd)
+{
+ if (!TryEnableEmptyPipeEpollEvent(fd)) {
+ THROW_ERROR_EXCEPTION("Failed to enable empty pipe epoll event for descriptor %v", fd)
+ << TError::FromSystem();
+ }
+}
+
bool TrySetUid(int uid)
{
#ifdef _linux_
diff --git a/yt/yt/core/misc/proc.h b/yt/yt/core/misc/proc.h
index 36d9ce8bc6a..86d8ad42232 100644
--- a/yt/yt/core/misc/proc.h
+++ b/yt/yt/core/misc/proc.h
@@ -166,6 +166,9 @@ void SafeMakeNonblocking(TFileDescriptor fd);
bool TrySetPipeCapacity(TFileDescriptor fd, int capacity);
void SafeSetPipeCapacity(TFileDescriptor fd, int capacity);
+bool TryEnableEmptyPipeEpollEvent(TFileDescriptor fd);
+void SafeEnableEmptyPipeEpollEvent(TFileDescriptor fd);
+
bool TrySetUid(int uid);
void SafeSetUid(int uid);
diff --git a/yt/yt/core/net/connection.cpp b/yt/yt/core/net/connection.cpp
index a8435fbf5a0..458d4e6b1a4 100644
--- a/yt/yt/core/net/connection.cpp
+++ b/yt/yt/core/net/connection.cpp
@@ -1305,7 +1305,8 @@ namespace {
TFileDescriptor CreateWriteFDForConnection(
const TString& pipePath,
- std::optional<int> capacity)
+ std::optional<int> capacity,
+ bool useDeliveryFence)
{
#ifdef _unix_
int flags = O_WRONLY | O_CLOEXEC;
@@ -1321,6 +1322,10 @@ TFileDescriptor CreateWriteFDForConnection(
SafeSetPipeCapacity(fd, *capacity);
}
+ if (useDeliveryFence) {
+ SafeEnableEmptyPipeEpollEvent(fd);
+ }
+
SafeMakeNonblocking(fd);
} catch (...) {
SafeClose(fd, false);
@@ -1421,7 +1426,7 @@ IConnectionWriterPtr CreateOutputConnectionFromPath(
bool useDeliveryFence)
{
return New<TFDConnection>(
- CreateWriteFDForConnection(pipePath, capacity),
+ CreateWriteFDForConnection(pipePath, capacity, useDeliveryFence),
std::move(pipePath),
std::move(poller),
pipeHolder,
diff --git a/yt/yt/core/ytree/unittests/yson_struct_ut.cpp b/yt/yt/core/ytree/unittests/yson_struct_ut.cpp
index 615fef5a325..614810de56b 100644
--- a/yt/yt/core/ytree/unittests/yson_struct_ut.cpp
+++ b/yt/yt/core/ytree/unittests/yson_struct_ut.cpp
@@ -3645,5 +3645,75 @@ TEST(TYsonStructTest, OverrideWithComparisonFromTemplatedFunction)
////////////////////////////////////////////////////////////////////////////////
+struct THasFieldWithDefaultedStrategy
+ : public TYsonStructLite
+{
+ TIntrusivePtr<TConfigWithOneLevelNesting> Field;
+
+ REGISTER_YSON_STRUCT_LITE(THasFieldWithDefaultedStrategy);
+
+ static void Register(TRegistrar registrar)
+ {
+ registrar.Parameter("field", &TThis::Field)
+ .Default()
+ .DefaultUnrecognizedStrategy(EUnrecognizedStrategy::Throw);
+ }
+};
+
+struct THasFieldWithDefaultedStrategyAndOwnRecursiveStrategy
+ : public TYsonStructLite
+{
+ TIntrusivePtr<TConfigWithOneLevelNesting> Field;
+
+ REGISTER_YSON_STRUCT_LITE(THasFieldWithDefaultedStrategyAndOwnRecursiveStrategy);
+
+ static void Register(TRegistrar registrar)
+ {
+ registrar.UnrecognizedStrategy(EUnrecognizedStrategy::KeepRecursive);
+
+ registrar.Parameter("field", &TThis::Field)
+ .Default()
+ .DefaultUnrecognizedStrategy(EUnrecognizedStrategy::Throw)
+ .EnforceDefaultUnrecognizedStrategy();
+ }
+};
+
+TEST(TYsonStructTest, DefaultUnrecognizedStrategy1)
+{
+ auto source = BuildYsonNodeFluently().BeginMap()
+ .Item("field").BeginMap()
+ .Item("unrecognized").Value(42)
+ .EndMap()
+ .EndMap();
+
+ THasFieldWithDefaultedStrategy yson = {};
+ EXPECT_ANY_THROW(Deserialize(yson, source->AsMap()));
+}
+
+TEST(TYsonStructTest, DefaultUnrecognizedStrategy2)
+{
+ auto source = BuildYsonNodeFluently().BeginMap()
+ .Item("field").BeginMap()
+ .Item("sub").BeginMap()
+ .EndMap()
+ .EndMap()
+ .EndMap();
+
+ THasFieldWithDefaultedStrategy yson = {};
+ Deserialize(yson, source->AsMap());
+}
+
+TEST(TYsonStructTest, DefaultUnrecognizedStrategy3)
+{
+ auto source = BuildYsonNodeFluently().BeginMap()
+ .Item("field").BeginMap()
+ .Item("unrecognized").Value(42)
+ .EndMap()
+ .EndMap();
+
+ THasFieldWithDefaultedStrategyAndOwnRecursiveStrategy yson = {};
+ EXPECT_ANY_THROW(Deserialize(yson, source->AsMap()));
+}
+
} // namespace
} // namespace NYT::NYTree
diff --git a/yt/yt/core/ytree/yson_struct-inl.h b/yt/yt/core/ytree/yson_struct-inl.h
index 6e9bdb2d961..34103976daf 100644
--- a/yt/yt/core/ytree/yson_struct-inl.h
+++ b/yt/yt/core/ytree/yson_struct-inl.h
@@ -288,11 +288,14 @@ void Serialize(const T& value, NYson::IYsonConsumer* consumer)
}
template <CExternallySerializable T, CYsonStructSource TSource>
-void Deserialize(T& value, TSource source, bool postprocess, bool setDefaults)
+void Deserialize(T& value, TSource source, bool postprocess, bool setDefaults, std::optional<EUnrecognizedStrategy> strategy)
{
using TTraits = TGetExternalizedYsonStructTraits<T>;
using TSerializer = typename TTraits::TExternalSerializer;
auto serializer = TSerializer::template CreateWritable<T, TSerializer>(value, setDefaults);
+ if (strategy) {
+ serializer.SetUnrecognizedStrategy(*strategy);
+ }
serializer.Load(std::move(source), postprocess, setDefaults);
}
diff --git a/yt/yt/core/ytree/yson_struct.h b/yt/yt/core/ytree/yson_struct.h
index 4fd373e49c8..24eb811a88b 100644
--- a/yt/yt/core/ytree/yson_struct.h
+++ b/yt/yt/core/ytree/yson_struct.h
@@ -393,7 +393,7 @@ void Deserialize(TYsonStructBase& value, NYson::TYsonPullParserCursor* cursor);
template <CExternallySerializable T>
void Serialize(const T& value, NYson::IYsonConsumer* consumer);
template <CExternallySerializable T, CYsonStructSource TSource>
-void Deserialize(T& value, TSource source, bool postprocess = true, bool setDefaults = true);
+void Deserialize(T& value, TSource source, bool postprocess = true, bool setDefaults = true, std::optional<EUnrecognizedStrategy> strategy = {});
template <class T>
TIntrusivePtr<T> UpdateYsonStruct(
diff --git a/yt/yt/core/ytree/yson_struct_detail-inl.h b/yt/yt/core/ytree/yson_struct_detail-inl.h
index bc7dbdb1300..3a4cdea34fa 100644
--- a/yt/yt/core/ytree/yson_struct_detail-inl.h
+++ b/yt/yt/core/ytree/yson_struct_detail-inl.h
@@ -189,7 +189,7 @@ void LoadFromSource(
std::optional<T>& parameter,
TSource source,
const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy);
+ std::optional<EUnrecognizedStrategy> unrecognizedStrategy);
// std::vector
template <CYsonStructSource TSource, CStdVector TVector>
@@ -197,7 +197,7 @@ void LoadFromSource(
TVector& parameter,
TSource source,
const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy);
+ std::optional<EUnrecognizedStrategy> unrecognizedStrategy);
// any map.
template <CYsonStructSource TSource, CAnyMap TMap>
@@ -205,7 +205,7 @@ void LoadFromSource(
TMap& parameter,
TSource source,
const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy);
+ std::optional<EUnrecognizedStrategy> unrecognizedStrategy);
////////////////////////////////////////////////////////////////////////////////
@@ -274,14 +274,14 @@ void LoadFromSource(
TIntrusivePtr<T>& parameter,
TSource source,
const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy)
+ std::optional<EUnrecognizedStrategy> unrecognizedStrategy)
{
if (!parameter) {
parameter = New<T>();
}
- if (recursiveUnrecognizedStrategy) {
- parameter->SetUnrecognizedStrategy(*recursiveUnrecognizedStrategy);
+ if (unrecognizedStrategy) {
+ parameter->SetUnrecognizedStrategy(*unrecognizedStrategy);
}
parameter->Load(std::move(source), /*postprocess*/ false, /*setDefaults*/ false, path);
@@ -293,9 +293,12 @@ void LoadFromSource(
T& parameter,
TSource source,
const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> /*ignored*/)
+ std::optional<EUnrecognizedStrategy> unrecognizedStrategy)
{
try {
+ if (unrecognizedStrategy) {
+ parameter.SetUnrecognizedStrategy(*unrecognizedStrategy);
+ }
parameter.Load(std::move(source), /*postprocess*/ false, /*setDefaults*/ false, path);
} catch (const std::exception& ex) {
THROW_ERROR_EXCEPTION("Error reading parameter %v", path)
@@ -309,10 +312,10 @@ void LoadFromSource(
T& parameter,
TSource source,
const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> /*ignored*/)
+ std::optional<EUnrecognizedStrategy> unrecognizedStrategy)
{
try {
- Deserialize(parameter, std::move(source), /*postprocess*/ false, /*setDefaults*/ false);
+ Deserialize(parameter, std::move(source), /*postprocess*/ false, /*setDefaults*/ false, unrecognizedStrategy);
} catch (const std::exception& ex) {
THROW_ERROR_EXCEPTION("Error reading parameter %v", path)
<< ex;
@@ -328,7 +331,7 @@ void LoadFromSource(
TExtension& parameter,
TSource source,
const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy)
+ std::optional<EUnrecognizedStrategy> unrecognizedStrategy)
{
static_assert(CYsonStructFieldFor<TExtension, TSource>, "You must add alias TImplementsYsonStructField");
@@ -338,7 +341,7 @@ void LoadFromSource(
/*postprocess*/ false,
/*setDefaults*/ false,
path,
- recursiveUnrecognizedStrategy);
+ unrecognizedStrategy);
} catch (const std::exception& ex) {
THROW_ERROR_EXCEPTION("Error loading parameter %v", path)
<< ex;
@@ -351,7 +354,7 @@ void LoadFromSource(
std::optional<T>& parameter,
TSource source,
const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy)
+ std::optional<EUnrecognizedStrategy> unrecognizedStrategy)
{
using TTraits = TYsonSourceTraits<TSource>;
@@ -363,12 +366,12 @@ void LoadFromSource(
}
if (parameter.has_value()) {
- LoadFromSource(*parameter, std::move(source), path, recursiveUnrecognizedStrategy);
+ LoadFromSource(*parameter, std::move(source), path, unrecognizedStrategy);
return;
}
T value;
- LoadFromSource(value, std::move(source), path, recursiveUnrecognizedStrategy);
+ LoadFromSource(value, std::move(source), path, unrecognizedStrategy);
parameter = std::move(value);
} catch (const std::exception& ex) {
@@ -383,7 +386,7 @@ void LoadFromSource(
TVector& parameter,
TSource source,
const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy)
+ std::optional<EUnrecognizedStrategy> unrecognizedStrategy)
{
using TTraits = TYsonSourceTraits<TSource>;
@@ -396,7 +399,7 @@ void LoadFromSource(
vector.emplace_back(),
elementSource,
path + "/" + NYPath::ToYPathLiteral(index),
- recursiveUnrecognizedStrategy);
+ unrecognizedStrategy);
++index;
});
} catch (const std::exception& ex) {
@@ -411,7 +414,7 @@ void LoadFromSource(
TMap& parameter,
TSource source,
const NYPath::TYPath& path,
- std::optional<EUnrecognizedStrategy> recursiveUnrecognizedStrategy)
+ std::optional<EUnrecognizedStrategy> unrecognizedStrategy)
{
using TTraits = TYsonSourceTraits<TSource>;
// TODO(arkady-e1ppa): Remove "typename" when clang-14 is abolished.
@@ -425,7 +428,7 @@ void LoadFromSource(
value,
childSource,
path + "/" + NYPath::ToYPathLiteral(key),
- recursiveUnrecognizedStrategy);
+ unrecognizedStrategy);
map[DeserializeMapKey<TKey>(key)] = std::move(value);
});
} catch (const std::exception& ex) {
@@ -751,6 +754,13 @@ void TYsonStructParameter<TValue>::Load(
const TLoadParameterOptions& options)
{
if (node) {
+ auto unrecognizedStrategy = options.RecursiveUnrecognizedRecursively;
+ if (EnforceDefaultUnrecognizedStrategy_) {
+ unrecognizedStrategy.reset();
+ }
+ if (!unrecognizedStrategy) {
+ unrecognizedStrategy = DefaultUnrecognizedStrategy_;
+ }
if (ResetOnLoad_) {
NPrivate::ResetOnLoad(FieldAccessor_->GetValue(self));
}
@@ -758,7 +768,7 @@ void TYsonStructParameter<TValue>::Load(
FieldAccessor_->GetValue(self),
std::move(node),
options.Path,
- options.RecursiveUnrecognizedRecursively);
+ unrecognizedStrategy);
if (auto* bitmap = self->GetSetFieldsBitmap()) {
bitmap->Set(FieldIndex_);
@@ -776,6 +786,13 @@ void TYsonStructParameter<TValue>::Load(
const TLoadParameterOptions& options)
{
if (cursor) {
+ auto unrecognizedStrategy = options.RecursiveUnrecognizedRecursively;
+ if (EnforceDefaultUnrecognizedStrategy_) {
+ unrecognizedStrategy.reset();
+ }
+ if (!unrecognizedStrategy) {
+ unrecognizedStrategy = DefaultUnrecognizedStrategy_;
+ }
if (ResetOnLoad_) {
NPrivate::ResetOnLoad(FieldAccessor_->GetValue(self));
}
@@ -783,7 +800,7 @@ void TYsonStructParameter<TValue>::Load(
FieldAccessor_->GetValue(self),
cursor,
options.Path,
- options.RecursiveUnrecognizedRecursively);
+ unrecognizedStrategy);
if (auto* bitmap = self->GetSetFieldsBitmap()) {
bitmap->Set(FieldIndex_);
@@ -893,6 +910,20 @@ TYsonStructParameter<TValue>& TYsonStructParameter<TValue>::ResetOnLoad()
}
template <class TValue>
+TYsonStructParameter<TValue>& TYsonStructParameter<TValue>::DefaultUnrecognizedStrategy(EUnrecognizedStrategy strategy)
+{
+ DefaultUnrecognizedStrategy_.emplace(strategy);
+ return *this;
+}
+
+template <class TValue>
+TYsonStructParameter<TValue>& TYsonStructParameter<TValue>::EnforceDefaultUnrecognizedStrategy()
+{
+ EnforceDefaultUnrecognizedStrategy_ = true;
+ return *this;
+}
+
+template <class TValue>
const std::vector<TString>& TYsonStructParameter<TValue>::GetAliases() const
{
return Aliases_;
diff --git a/yt/yt/core/ytree/yson_struct_detail.h b/yt/yt/core/ytree/yson_struct_detail.h
index bd9f3b1917e..3ed99df7ec2 100644
--- a/yt/yt/core/ytree/yson_struct_detail.h
+++ b/yt/yt/core/ytree/yson_struct_detail.h
@@ -317,6 +317,12 @@ public:
TYsonStructParameter& Alias(const TString& name);
// Set field to T() (or suitable analogue) before deserializations.
TYsonStructParameter& ResetOnLoad();
+ // Uses given unrecognized strategy in |Load| if there was no strategy supplied.
+ TYsonStructParameter& DefaultUnrecognizedStrategy(EUnrecognizedStrategy strategy);
+ // Forces given parameter to ignore unrecognized strategy even if it set to
+ // some recursive version. Combination with |DefaultUnrecognizedStrategy| enables
+ // behavior which ensures selected default strategy for all fields below.
+ TYsonStructParameter& EnforceDefaultUnrecognizedStrategy();
// Register constructor with parameters as initializer of default value for ref-counted class.
template <class... TArgs>
@@ -333,6 +339,8 @@ private:
bool TriviallyInitializedIntrusivePtr_ = false;
bool Optional_ = false;
bool ResetOnLoad_ = false;
+ std::optional<EUnrecognizedStrategy> DefaultUnrecognizedStrategy_;
+ bool EnforceDefaultUnrecognizedStrategy_ = false;
const int FieldIndex_ = -1;
};
diff --git a/yt/yt/library/process/unittests/pipes_ut.cpp b/yt/yt/library/process/unittests/pipes_ut.cpp
index b41b7fc5957..6d088d3e3ad 100644
--- a/yt/yt/library/process/unittests/pipes_ut.cpp
+++ b/yt/yt/library/process/unittests/pipes_ut.cpp
@@ -350,9 +350,9 @@ TEST_F(TNamedPipeReadWriteTest, CapacityDontDiscardSurplus)
EXPECT_TRUE(writeFuture.Get().IsOK());
}
-#ifdef _linux_
+#if defined(_linux_) && defined(F_SET_PIPE_WAKE_WRITER)
-TEST_F(TNamedPipeReadWriteTest, SyncWriteJustWorks)
+TEST_F(TNamedPipeReadWriteTest, DeliveryFencedWriteJustWorks)
{
SetUpWithDeliveryFence();
@@ -374,22 +374,6 @@ TEST_F(TNamedPipeReadWriteTest, SyncWriteJustWorks)
EXPECT_TRUE(writeFuture.Get().IsOK());
}
-#else
-
-TEST_F(TNamedPipeReadWriteTest, SyncWriteUnsupportedPlatform)
-{
- SetUpWithDeliveryFence();
-
- TString text("aabbb");
- auto writeBuffer = TSharedRef::FromString(text);
- auto writeFuture = Writer->Write(writeBuffer);
-
- // Future is set with error because platform is not supported
- auto error = writeFuture.Get();
- EXPECT_FALSE(error.IsOK());
- EXPECT_TRUE(error.GetMessage().Contains("Delivery fenced write failed: FIONDREAD is not supported on your platform"));
-}
-
#endif
////////////////////////////////////////////////////////////////////////////////