[go: nahoru, domu]

Revert "Reland "Add toolchains without PartitionAlloc-Everywhere for dump_syms et al""

This reverts commit 818e126f4350095dd0a54566ded107f0a5065f6f.

Reason for revert: This brakes the following official builds.
https://ci.chromium.org/ui/p/chrome/builders/official/mac64/8407/overview
https://ci.chromium.org/ui/p/chrome/builders/official/win-clang/8618/overview

`symupload` disappeared from those builds.

Repro steps:
```
./tools/mb/mb gen -m official.chrome -b mac64 --config-file ./internal/tools/mb/mb_config.pyl out/mac64-official
ninja -C out/mac64-official clang_arm64/symupload
[0/1] Regenerating ninja files
ninja: error: unknown target 'clang_arm64/symupload'
```

Original change's description:
> Reland "Add toolchains without PartitionAlloc-Everywhere for dump_syms et al"
>
> This is a reland of commit 38c00784bc98a5dc885b06f5a0e738386c5f7df7
>
> MSAN is disabled in the toolchain with the system allocator as we only
> support MSAN in the default toolchain. If another toolchain has MSAN
> enabled it will try to also generate the MSAN instrumented libraries
> in the default toolchain's directory and they collide.
>
> This is similar to the rust host build tools toolchain, but there we
> disable all sanitizers. For the system allocator toolchain, we disable
> MSAN but retain the ability to build these tools with ASAN or UBSAN if
> needed.
>
> Original change's description:
> > Add toolchains without PartitionAlloc-Everywhere for dump_syms et al
> >
> > When PartitionAlloc is linked into an executable, it takes over the
> > system allocator (malloc, new, etc), which is called PartitionAlloc-
> > Everywhere (or PA-E). When this occurs in dump_syms, we see that PA
> > hits OOM and causes dump_syms to crash while generating the symbols
> > for chrome. It's not at all clear why PA hits OOM but the system
> > allocator does not, it occurs during construction of a std::string (on
> > my machine anyway when I am running it in gdb, maybe elsewhere on bots).
> > This happens on all platforms that we run dump_syms on as part of the
> > official build: on linux and on mac, building for at least linux,
> > android, chromeos, and mac. See also crbug.com/345514993.
> >
> > So we want to build dump_syms and other breakpad executables in a way
> > that uses the system allocator. To do that we need to disable the
> > use_partition_alloc_as_malloc GN variable. As this variable is global,
> > we need a separate toolchain in order to disable it.
> >
> > We introduce a new toolchain with the suffix `_with_system_allocator`
> > that can be used for this purpose. Initially we intended to use the
> > Rust host build tools toolchain for this purpose, however we require
> > careful naming to avoid toolchain collisions. For instance if building
> > on a Linux x64 machine with an Other x64 target, we can have two
> > toolchains:
> > - default_toolchain: //build/toolchain/other:clang_x64
> > - host_toolchain: //build/toolchain/other:clang_x64
> >
> > While these have different labels, it is the name at the end that is
> > used as their output directory (this is hardcoded in GN). But they
> > avoid colliding because the default toolchain is not placed in a
> > subdirectory and uses the `root_build_dir`. However when we add another
> > toolchain with them, they both get subdirs and collide:
> > - for target: //build/toolchain/other:clang_x64_with_system_allocator
> > - for host: //build/toolchain/linux:clang_x64_with_system_allocator
> >
> > Now both toolchains try to write to the clang_x64_with_system_allocator
> > directory which causes errors. To avoid this, we actually make two
> > toolchains per toolchain, one with a `host_` tag inside it.
> > - target:  //build/toolchain/other:clang_x64_with_system_allocator
> > - unused:  //build/toolchain/linux:clang_x64_with_system_allocator
> > - unused:  //build/toolchain/other:clang_x64_host_with_system_allocator
> > - host:    //build/toolchain/linux:clang_x64_host_with_system_allocator
> >
> > Then, when building for the host we choose the `host_` variety, which
> > is specified in the `host_system_allocator_toolchain variable`. And
> > when building for default target, we choose the non-`host_` one, which
> > is specified in the `default_system_allocator_toolchain` variable.
> >
> > More clever strategies that try to avoid creating the unused toolchains
> > above do not seem possible. Inside the toolchain-creating template,
> > it is not clear how to determine which toolchain is being created, as
> > the get_label_info() function on `target_name` does not produce
> > anything that matches exactly with the string in `default_toolchain` or
> > `host_toolchain`. We also tried using the current_cpu and current_os,
> > however the `toolchain_args.current_os` is not actually set correctly in
> > the default toolchain when targeting ChromeOS. The current_os variable
> > is "chromeos" but inside the toolchain_args, it is "linux". So we just
> > make extra toolchains (which can't be used or they'd make build errors)
> > and we don't refer to them from the `host_system_allocator_toolchain`
> > and `default_system_allocator_toolchain` variables, which makes them
> > effectively inaccessible.
> >
> > In the process we learnt many things about how the breakpad executables
> > are built. When you build them for the default toolchain, such as by
> > building `//third_party/breakpad:dump_syms`, it redirects to the *host*
> > toolchain on many platforms, but not on all platforms. This ends up
> > putting a binary that may not work on the target machine in the
> > `root_build_dir` which is highly unusual, but it is required by our
> > testing scripts/infra.
> >
> > The key insight added here is that the toolchain that it should be
> > built with is the platform from where the tests on the target will be
> > *launched*. On Android, iOS, and ChromeOS, the tests are launched from
> > the host machine and that's where the breakpad executables are run. We
> > encode this explicitly in the breakpad GN file.
> >
> > One additional exception is that the breakpad tools do not build on
> > Windows ARM, so when building on Windows x64 for Windows ARM, while
> > the tests are launched from the ARM machine, we target the host x64
> > machine still. This relies on the ARM machine being able to run the
> > x64 binaries through emulation.
> >
> > There's no change here in how the breakpad binaries are built, but it
> > is now more explicitly encoded and documented. What did change is that
> > since we use a separate toolchain for building these tools, we also
> > turn off component build in them. This allows us to replace the use
> > of symlinks with copying (or hardlinking) the binaries from the
> > toolchain's root directory up to the root_build_dir. This enables
> > support for building these tools in the default_toolchain on Windows,
> > something which was not possible before.
> >
> > Bug: 345514993, b/342251590
> > Change-Id: Ic2d1d356452791b8916d6876f3d8d1855a6566b6
> > Cq-Include-Trybots: luci.chromium.try:linux-official,android-official,win-official,mac-official
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5609092
> > Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
> > Reviewed-by: Nico Weber <thakis@chromium.org>
> > Owners-Override: danakj <danakj@chromium.org>
> > Reviewed-by: Avi Drissman <avi@chromium.org>
> > Commit-Queue: danakj <danakj@chromium.org>
> > Reviewed-by: Mark Mentovai <mark@chromium.org>
> > Cr-Commit-Position: refs/heads/main@{#1316523}
>
> Bug: 345514993, b/342251590
> Change-Id: Ieef03911ad484b234845a6df3f47c4f77136ca6a
> Cq-Include-Trybots: luci.chromium.try:linux-official,android-official,win-official,mac-official
> Cq-Include-Trybots: luci.chromium.try:linux_chromium_msan_rel_ng
> Cq-Include-Trybots: luci.chromium.try:linux_chromium_asan_rel_ng
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5639356
> Owners-Override: danakj <danakj@chromium.org>
> Reviewed-by: Nico Weber <thakis@chromium.org>
> Commit-Queue: danakj <danakj@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#1316723}

Bug: 345514993, b/342251590
Change-Id: Id1b999a68902755c06f908a3ab6777720a4dd27e
Cq-Include-Trybots: luci.chromium.try:linux-official,android-official,win-official,mac-official
Cq-Include-Trybots: luci.chromium.try:linux_chromium_msan_rel_ng
Cq-Include-Trybots: luci.chromium.try:linux_chromium_asan_rel_ng
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5641925
Commit-Queue: Junji Watanabe <jwata@google.com>
Owners-Override: Prudhvikumar Bommana <pbommana@google.com>
Commit-Queue: Prudhvikumar Bommana <pbommana@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/heads/main@{#1317267}
diff --git a/BUILD.gn b/BUILD.gn
index a8a6ada..eaae83b 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -603,10 +603,10 @@
         "//mojo:mojo_perftests",
         "//services/service_manager/public/cpp",
         "//testing/gmock:gmock_main",
-        "//third_party/breakpad:dump_syms($host_system_allocator_toolchain)",
-        "//third_party/breakpad:microdump_stackwalk($host_system_allocator_toolchain)",
-        "//third_party/breakpad:minidump_dump($host_system_allocator_toolchain)",
-        "//third_party/breakpad:minidump_stackwalk($host_system_allocator_toolchain)",
+        "//third_party/breakpad:dump_syms($host_toolchain)",
+        "//third_party/breakpad:microdump_stackwalk($host_toolchain)",
+        "//third_party/breakpad:minidump_dump($host_toolchain)",
+        "//third_party/breakpad:minidump_stackwalk($host_toolchain)",
       ]
     }
 
@@ -628,7 +628,7 @@
 
     if (is_mac) {
       deps += [
-        "//third_party/breakpad:dump_syms($host_system_allocator_toolchain)",
+        "//third_party/breakpad:dump_syms",
 
         # The following are accessibility API tools.
         "//tools/accessibility/inspect:ax_dump_events",
@@ -672,10 +672,8 @@
           host_os == "win") {
         deps += [ "//chrome/test/mini_installer:mini_installer_tests" ]
       }
-    } else if (!is_android && !is_fuchsia) {
-      deps += [
-        "//third_party/breakpad:symupload($host_system_allocator_toolchain)",
-      ]
+    } else if (!is_android && !is_ios && !is_fuchsia) {
+      deps += [ "//third_party/breakpad:symupload($host_toolchain)" ]
     }
 
     if (is_cast_android || is_castos || (is_fuchsia && enable_cast_receiver)) {
@@ -980,7 +978,7 @@
       "//net:net_unittests",
       "//printing:printing_unittests",
       "//sql:sql_unittests",
-      "//third_party/breakpad:symupload($host_system_allocator_toolchain)",
+      "//third_party/breakpad:symupload($host_toolchain)",
       "//ui/base:ui_base_unittests",
       "//ui/gfx:gfx_unittests",
       "//ui/touch_selection:ui_touch_selection_unittests",
@@ -1008,7 +1006,7 @@
       "//media/capture:capture_unittests",
       "//sandbox/linux:chrome_sandbox",
       "//sandbox/linux:sandbox_linux_unittests",
-      "//third_party/breakpad:minidump_stackwalk($host_system_allocator_toolchain)",
+      "//third_party/breakpad:minidump_stackwalk($host_toolchain)",
       "//third_party/dawn/src/dawn/tests:dawn_end2end_tests",
       "//third_party/dawn/src/dawn/tests:dawn_unittests",
       "//ui/ozone:ozone_integration_tests",
@@ -1182,40 +1180,28 @@
     if (is_android) {
       data_deps += [
         "//third_party/breakpad:breakpad_unittests",
-        "//tools/android/forwarder2",
-
-        # Using the target toolchain for this tool, as it's run during tests not
-        # during the build. This places a symlink in the root_build_dir for
-        # scrips to use.
         "//third_party/breakpad:dump_syms",
         "//third_party/breakpad:microdump_stackwalk",
         "//third_party/breakpad:minidump_dump",
         "//third_party/breakpad:minidump_stackwalk",
         "//third_party/breakpad:symupload",
+        "//tools/android/forwarder2",
       ]
     } else {
       data_deps += [ "//content/web_test:web_test_common_mojom_js_data_deps" ]
     }
 
     if (!is_win && !is_android) {
-      # Using the default toolchain for this tool, as it's run during tests not
-      # during the build. This places a symlink in the root_build_dir for scrips
-      # to use.
-      data_deps += [ "//third_party/breakpad:minidump_stackwalk" ]
+      data_deps +=
+          [ "//third_party/breakpad:minidump_stackwalk($host_toolchain)" ]
     }
 
     if (is_mac) {
-      # Using the default toolchain for this tool, as it's run during tests not
-      # during the build, and on Mac we support cross-building from a different
-      # architecture.
-      data_deps += [ "//third_party/breakpad:dump_syms" ]
+      data_deps += [ "//third_party/breakpad:dump_syms($host_toolchain)" ]
     }
 
     if (is_linux || is_chromeos) {
-      # Using the default toolchain for this tool, as it's run during tests not
-      # during the build. This places a symlink in the root_build_dir for scrips
-      # to use.
-      data_deps += [ "//third_party/breakpad:dump_syms" ]
+      data_deps += [ "//third_party/breakpad:dump_syms($host_toolchain)" ]
     }
 
     if (is_fuchsia) {
@@ -1679,7 +1665,8 @@
     }
 
     if (!is_win) {
-      data_deps += [ "//third_party/breakpad:minidump_stackwalk($host_system_allocator_toolchain)" ]
+      data_deps +=
+          [ "//third_party/breakpad:minidump_stackwalk($host_toolchain)" ]
     }
   }
 
diff --git a/build/config/android/create_unwind_table.gni b/build/config/android/create_unwind_table.gni
index 59cb024..92b7427 100644
--- a/build/config/android/create_unwind_table.gni
+++ b/build/config/android/create_unwind_table.gni
@@ -6,8 +6,7 @@
 
 unwind_table_asset_v2_filename = "unwind_cfi_32_v2"
 
-_dump_syms_target =
-    "//third_party/breakpad:dump_syms($host_system_allocator_toolchain)"
+_dump_syms_target = "//third_party/breakpad:dump_syms($host_toolchain)"
 _dump_syms = get_label_info(_dump_syms_target, "root_out_dir") + "/dump_syms"
 _readobj_path = "$clang_base_path/bin/llvm-readobj"
 
diff --git a/build/config/android/extract_unwind_tables.gni b/build/config/android/extract_unwind_tables.gni
index 6518a2d..d4daa6a 100644
--- a/build/config/android/extract_unwind_tables.gni
+++ b/build/config/android/extract_unwind_tables.gni
@@ -6,8 +6,7 @@
 
 unwind_table_asset_v1_filename = "unwind_cfi_32"
 
-_dump_syms_target =
-    "//third_party/breakpad:dump_syms($host_system_allocator_toolchain)"
+_dump_syms_target = "//third_party/breakpad:dump_syms($host_toolchain)"
 _dump_syms = get_label_info(_dump_syms_target, "root_out_dir") + "/dump_syms"
 
 template("unwind_table_v1") {
diff --git a/build/config/sanitizers/BUILD.gn b/build/config/sanitizers/BUILD.gn
index a1cb043..837bfbc 100644
--- a/build/config/sanitizers/BUILD.gn
+++ b/build/config/sanitizers/BUILD.gn
@@ -25,7 +25,6 @@
 # shared_libraries.
 group("deps") {
   deps = []
-  data = []
   if (using_sanitizer) {
     public_configs = [
       # Even when a target removes default_sanitizer_flags, it may be depending
@@ -39,7 +38,7 @@
       } else {
         exe = ""
       }
-      data += [
+      data = [
         "//tools/valgrind/asan/",
         "$clang_base_path/bin/llvm-symbolizer${exe}",
       ]
diff --git a/build/linux/extract_symbols.gni b/build/linux/extract_symbols.gni
index 26426c8..8fef131 100644
--- a/build/linux/extract_symbols.gni
+++ b/build/linux/extract_symbols.gni
@@ -18,8 +18,7 @@
                            "testonly",
                          ])
   action("${target_name}") {
-    dump_syms_label =
-        "//third_party/breakpad:dump_syms($host_system_allocator_toolchain)"
+    dump_syms_label = "//third_party/breakpad:dump_syms($host_toolchain)"
     dump_syms_binary =
         get_label_info(dump_syms_label, "root_out_dir") + "/" + "dump_syms"
 
diff --git a/build/toolchain/apple/toolchain.gni b/build/toolchain/apple/toolchain.gni
index 31f0316..9e138aa 100644
--- a/build/toolchain/apple/toolchain.gni
+++ b/build/toolchain/apple/toolchain.gni
@@ -792,68 +792,6 @@
   }
 }
 
-# Make an additional toolchain which is used for making tools that are run
-# on the host machine as part of the build process (such as proc macros
-# and Cargo build scripts). This toolchain uses the prebuilt stdlib that
-# comes with the compiler, so it doesn't have to wait for the stdlib to be
-# built before building other stuff. And this ensures its proc macro
-# outputs have the right ABI to be loaded by the compiler, and it can be
-# used to compile build scripts that are part of the stdlib that is built
-# for the default toolchain.
-template("apple_rust_host_build_tools_toolchain") {
-  single_apple_toolchain(target_name) {
-    assert(defined(invoker.toolchain_args),
-           "Toolchains must declare toolchain_args")
-    forward_variables_from(invoker,
-                           "*",
-                           TESTONLY_AND_VISIBILITY + [ "toolchain_args" ])
-    toolchain_args = {
-      # Populate toolchain args from the invoker.
-      forward_variables_from(invoker.toolchain_args, "*")
-      toolchain_for_rust_host_build_tools = true
-
-      # The host build tools are static release builds to make the Chromium
-      # build faster. They do not need PGO etc, so no official builds.
-      is_debug = false
-      is_component_build = false
-      is_official_build = false
-      use_clang_coverage = false
-      use_sanitizer_coverage = false
-      generate_linker_map = false
-      use_thin_lto = false
-    }
-  }
-}
-
-# If PartitionAlloc is part of the build (even as a transitive dependency), then
-# it replaces the system allocator. If this toolchain is used, that will be
-# overridden and the system allocator will be used regardless. This is important
-# in some third-party binaries outside of Chrome.
-template("apple_system_allocator_toolchain") {
-  single_apple_toolchain(target_name) {
-    assert(defined(invoker.toolchain_args),
-           "Toolchains must declare toolchain_args")
-    forward_variables_from(invoker,
-                           "*",
-                           TESTONLY_AND_VISIBILITY + [ "toolchain_args" ])
-    toolchain_args = {
-      # Populate toolchain args from the invoker.
-      forward_variables_from(invoker.toolchain_args, "*")
-      use_partition_alloc_as_malloc = false
-
-      # Disable component build so that we can copy the exes to the
-      # root_build_dir and support the default_toolchain redirection on Windows.
-      # See also the comment in //build/symlink.gni.
-      is_component_build = false
-
-      # Only one toolchain can be configured with MSAN support with our current
-      # GN setup, or they all try to make the instrumented libraries and
-      # collide.
-      is_msan = false
-    }
-  }
-}
-
 # Makes an Apple toolchain for the target, and an equivalent toolchain with the
 # prebuilt Rust stdlib for building proc macros (and other for-build-use
 # artifacts).
@@ -861,28 +799,51 @@
   single_apple_toolchain(target_name) {
     assert(defined(invoker.toolchain_args),
            "Toolchains must declare toolchain_args")
-    forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
+    forward_variables_from(invoker,
+                           "*",
+                           [
+                             "visibility",
+                             "test_only",
+                           ])
 
     # No need to forward visibility and test_only as they apply to targets not
     # toolchains, but presubmit checks require that we explicitly exclude them
   }
 
-  apple_rust_host_build_tools_toolchain(
-      "${target_name}_for_rust_host_build_tools") {
-    assert(defined(invoker.toolchain_args),
-           "Toolchains must declare toolchain_args")
-    forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
-  }
+  if (enable_rust && current_toolchain == default_toolchain) {
+    # Make an additional toolchain which is used for making tools that are run
+    # on the host machine as part of the build process (such as proc macros
+    # and Cargo build scripts). This toolchain uses the prebuilt stdlib that
+    # comes with the compiler, so it doesn't have to wait for the stdlib to be
+    # built before building other stuff. And this ensures its proc macro
+    # outputs have the right ABI to be loaded by the compiler, and it can be
+    # used to compile build scripts that are part of the stdlib that is built
+    # for the default toolchain.
+    single_apple_toolchain("${target_name}_for_rust_host_build_tools") {
+      assert(defined(invoker.toolchain_args),
+             "Toolchains must declare toolchain_args")
+      forward_variables_from(invoker,
+                             "*",
+                             [
+                               "toolchain_args",
+                               "visibility",
+                               "test_only",
+                             ])
+      toolchain_args = {
+        # Populate toolchain args from the invoker.
+        forward_variables_from(invoker.toolchain_args, "*")
+        toolchain_for_rust_host_build_tools = true
 
-  apple_system_allocator_toolchain(
-      "${target_name}_host_with_system_allocator") {
-    assert(defined(invoker.toolchain_args),
-           "Toolchains must declare toolchain_args")
-    forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
-  }
-  apple_system_allocator_toolchain("${target_name}_with_system_allocator") {
-    assert(defined(invoker.toolchain_args),
-           "Toolchains must declare toolchain_args")
-    forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
+        # The host build tools are static release builds to make the Chromium
+        # build faster. They do not need PGO etc, so no official builds.
+        is_debug = false
+        is_component_build = false
+        is_official_build = false
+        use_clang_coverage = false
+        use_sanitizer_coverage = false
+        generate_linker_map = false
+        use_thin_lto = false
+      }
+    }
   }
 }
diff --git a/build/toolchain/gcc_toolchain.gni b/build/toolchain/gcc_toolchain.gni
index 6e8ab87..09f1f39 100644
--- a/build/toolchain/gcc_toolchain.gni
+++ b/build/toolchain/gcc_toolchain.gni
@@ -141,10 +141,8 @@
            "toolchain_args must specify a current_os")
 
     # use_reclient is default to use_remoteexec
-    if (!defined(invoker_toolchain_args.use_reclient) &&
-        defined(invoker_toolchain_args.use_remoteexec)) {
-      invoker_toolchain_args.use_reclient =
-          invoker_toolchain_args.use_remoteexec
+    if (!defined(invoker_toolchain_args.use_reclient) && defined(invoker_toolchain_args.use_remoteexec)) {
+      invoker_toolchain_args.use_reclient = invoker_toolchain_args.use_remoteexec
     }
 
     # When invoking this toolchain not as the default one, these args will be
@@ -798,72 +796,6 @@
   }
 }
 
-# Make an additional toolchain which is used for making tools that are run
-# on the host machine as part of the build process (such as proc macros
-# and Cargo build scripts). This toolchain uses the prebuilt stdlib that
-# comes with the compiler, so it doesn't have to wait for the stdlib to be
-# built before building other stuff. And this ensures its proc macro
-# outputs have the right ABI to be loaded by the compiler, and it can be
-# used to compile build scripts that are part of the stdlib that is built
-# for the default toolchain.
-template("gcc_rust_host_build_tools_toolchain") {
-  single_gcc_toolchain(target_name) {
-    assert(defined(invoker.toolchain_args),
-           "Toolchains must declare toolchain_args")
-    forward_variables_from(invoker,
-                           "*",
-                           TESTONLY_AND_VISIBILITY + [ "toolchain_args" ])
-    toolchain_args = {
-      # Populate toolchain args from the invoker.
-      forward_variables_from(invoker.toolchain_args, "*")
-      toolchain_for_rust_host_build_tools = true
-
-      # The host build tools are static release builds to make the Chromium
-      # build faster.
-      is_debug = false
-      is_component_build = false
-      is_official_build = false
-      use_clang_coverage = false
-      use_sanitizer_coverage = false
-      generate_linker_map = false
-      use_thin_lto = false
-    }
-
-    # When cross-compiling we don't want to use the target platform's file
-    # extensions.
-    shlib_extension = host_shlib_extension
-  }
-}
-
-# If PartitionAlloc is part of the build (even as a transitive dependency), then
-# it replaces the system allocator. If this toolchain is used, that will be
-# overridden and the system allocator will be used regardless. This is important
-# in some third-party binaries outside of Chrome.
-template("gcc_system_allocator_toolchain") {
-  single_gcc_toolchain(target_name) {
-    assert(defined(invoker.toolchain_args),
-           "Toolchains must declare toolchain_args")
-    forward_variables_from(invoker,
-                           "*",
-                           TESTONLY_AND_VISIBILITY + [ "toolchain_args" ])
-    toolchain_args = {
-      # Populate toolchain args from the invoker.
-      forward_variables_from(invoker.toolchain_args, "*")
-      use_partition_alloc_as_malloc = false
-
-      # Disable component build so that we can copy the exes to the
-      # root_build_dir and support the default_toolchain redirection on Windows.
-      # See also the comment in //build/symlink.gni.
-      is_component_build = false
-
-      # Only one toolchain can be configured with MSAN support with our current
-      # GN setup, or they all try to make the instrumented libraries and
-      # collide.
-      is_msan = false
-    }
-  }
-}
-
 # Makes a GCC toolchain for the target, and an equivalent toolchain with the
 # prebuilt Rust stdlib for building proc macros (and other for-build-use
 # artifacts).
@@ -871,28 +803,56 @@
   single_gcc_toolchain(target_name) {
     assert(defined(invoker.toolchain_args),
            "Toolchains must declare toolchain_args")
-    forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
+    forward_variables_from(invoker,
+                           "*",
+                           [
+                             "visibility",
+                             "test_only",
+                           ])
 
     # No need to forward visibility and test_only as they apply to targets not
     # toolchains, but presubmit checks require that we explicitly exclude them
   }
 
-  gcc_rust_host_build_tools_toolchain(
-      "${target_name}_for_rust_host_build_tools") {
-    assert(defined(invoker.toolchain_args),
-           "Toolchains must declare toolchain_args")
-    forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
-  }
+  if (enable_rust && current_toolchain == default_toolchain) {
+    # Make an additional toolchain which is used for making tools that are run
+    # on the host machine as part of the build process (such as proc macros
+    # and Cargo build scripts). This toolchain uses the prebuilt stdlib that
+    # comes with the compiler, so it doesn't have to wait for the stdlib to be
+    # built before building other stuff. And this ensures its proc macro
+    # outputs have the right ABI to be loaded by the compiler, and it can be
+    # used to compile build scripts that are part of the stdlib that is built
+    # for the default toolchain.
+    single_gcc_toolchain("${target_name}_for_rust_host_build_tools") {
+      assert(defined(invoker.toolchain_args),
+             "Toolchains must declare toolchain_args")
+      forward_variables_from(invoker,
+                             "*",
+                             [
+                               "toolchain_args",
+                               "visibility",
+                               "test_only",
+                             ])
+      toolchain_args = {
+        # Populate toolchain args from the invoker.
+        forward_variables_from(invoker.toolchain_args, "*")
+        toolchain_for_rust_host_build_tools = true
 
-  gcc_system_allocator_toolchain("${target_name}_host_with_system_allocator") {
-    assert(defined(invoker.toolchain_args),
-           "Toolchains must declare toolchain_args")
-    forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
-  }
-  gcc_system_allocator_toolchain("${target_name}_with_system_allocator") {
-    assert(defined(invoker.toolchain_args),
-           "Toolchains must declare toolchain_args")
-    forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY)
+        # The host build tools are static release builds to make the Chromium
+        # build faster.
+        is_debug = false
+        is_component_build = false
+        is_official_build = false
+        use_clang_coverage = false
+        use_sanitizer_coverage = false
+        generate_linker_map = false
+        use_thin_lto = false
+      }
+
+      # When cross-compiling we don't want to use the target platform's file
+      # extensions.
+      shlib_extension = host_shlib_extension
+    }
   }
 }
 
diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni
index 60ba6d8..14aa5f7 100644
--- a/build/toolchain/toolchain.gni
+++ b/build/toolchain/toolchain.gni
@@ -116,15 +116,3 @@
 is_a_target_toolchain =
     (current_toolchain != host_toolchain ||
      default_toolchain == host_toolchain) && current_os == target_os
-
-# A toolchain for building tools that run on the host machine and need to use
-# the system allocator. This toolchain does not use PartitionAlloc-Everywhere by
-# design. We use a name with `_host` injected into it to avoid colliding with
-# toolchains of the same name (but different path) between different OSes.
-host_system_allocator_toolchain = "${host_toolchain}_host_with_system_allocator"
-
-# A toolchain for building tools that run on the default target machine and need
-# to use the system allocator. This toolchain does not use
-# PartitionAlloc-Everywhere by design.
-default_system_allocator_toolchain =
-    "${default_toolchain}_with_system_allocator"
diff --git a/build/toolchain/win/toolchain.gni b/build/toolchain/win/toolchain.gni
index 30a65eb68..c2d8d3a 100644
--- a/build/toolchain/win/toolchain.gni
+++ b/build/toolchain/win/toolchain.gni
@@ -589,71 +589,36 @@
   }
 }
 
-# Make an additional toolchain which is used for making tools that are run
-# on the host machine as part of the build process (such as proc macros
-# and Cargo build scripts). This toolchain uses the prebuilt stdlib that
-# comes with the compiler, so it doesn't have to wait for the stdlib to be
-# built before building other stuff. And this ensures its proc macro
-# outputs have the right ABI to be loaded by the compiler, and it can be
-# used to compile build scripts that are part of the stdlib that is built
-# for the default toolchain.
 template("msvc_rust_host_build_tools_toolchain") {
-  msvc_toolchain(target_name) {
-    assert(defined(invoker.toolchain_args))
-    forward_variables_from(invoker,
-                           "*",
-                           [
-                             "toolchain_args",
-                             "visibility",
-                             "testonly",
-                           ])
-    toolchain_args = {
-      # Populate toolchain args from the invoker.
-      forward_variables_from(invoker.toolchain_args, "*")
-      toolchain_for_rust_host_build_tools = true
+  assert(defined(invoker.toolchain_args))
+  if (enable_rust) {
+    msvc_toolchain("${target_name}_for_rust_host_build_tools") {
+      forward_variables_from(invoker,
+                             "*",
+                             [
+                               "toolchain_args",
+                               "visibility",
+                               "testonly",
+                             ])
+      toolchain_args = {
+        # Populate toolchain args from the invoker.
+        forward_variables_from(invoker.toolchain_args, "*")
+        toolchain_for_rust_host_build_tools = true
 
-      # The host build tools are static release builds to make the Chromium
-      # build faster. They do not need PGO etc, so no official builds.
-      is_debug = false
-      is_component_build = false
-      is_official_build = false
-      use_clang_coverage = false
-      use_sanitizer_coverage = false
-      generate_linker_map = false
-      use_thin_lto = false
+        # The host build tools are static release builds to make the Chromium
+        # build faster. They do not need PGO etc, so no official builds.
+        is_debug = false
+        is_component_build = false
+        is_official_build = false
+        use_clang_coverage = false
+        use_sanitizer_coverage = false
+        generate_linker_map = false
+        use_thin_lto = false
+      }
     }
-  }
-}
-
-# If PartitionAlloc is part of the build (even as a transitive dependency), then
-# it replaces the system allocator. If this toolchain is used, that will be
-# overridden and the system allocator will be used regardless. This is important
-# in some third-party binaries outside of Chrome.
-template("msvc_system_allocator_toolchain") {
-  msvc_toolchain(target_name) {
-    assert(defined(invoker.toolchain_args))
-    forward_variables_from(invoker,
-                           "*",
-                           [
-                             "toolchain_args",
-                             "visibility",
-                             "testonly",
-                           ])
-    toolchain_args = {
-      # Populate toolchain args from the invoker.
-      forward_variables_from(invoker.toolchain_args, "*")
-      use_partition_alloc_as_malloc = false
-
-      # Disable component build so that we can copy the exes to the
-      # root_build_dir and support the default_toolchain redirection on Windows.
-      # See also the comment in //build/symlink.gni.
-      is_component_build = false
-
-      # Only one toolchain can be configured with MSAN support with our current
-      # GN setup, or they all try to make the instrumented libraries and
-      # collide.
-      is_msan = false
-    }
+  } else {
+    not_needed(invoker, "*")
+    not_needed([ "target_name" ])
   }
 }
 
@@ -663,12 +628,12 @@
   # //build/config/BUILDCONFIG.gn). But the prebuilt stdlib does not
   # exist for Windows x86 and it's exceedingly difficult to get it
   # built from a single build_rust.py invocation. So we just don't follow
-  # along in the `build_tools_toolchain` toolchains, and always use the host
-  # cpu type (which will be x64 in that case). Things built with these
-  # toolchains are never built for the target_cpu anyhow, so the optimization
-  # there does not benefit them.
+  # along in the `msvc_rust_host_build_tools_toolchain` toolchains, and
+  # always use the host cpu type (which will be x64 in that case). Things
+  # built with these toolchains are never built for the target_cpu anyhow,
+  # so the optimization there does not benefit them.
   #
-  # Thus, in build_tools_toolchain, for the host machine:
+  # Thus, in msvc_rust_host_build_tools_toolchain:
   # * Use `rust_host_toolchain_arch` instead of `toolchain_arch`.
   # * Use `rust_host_win_toolchain_data` instead of `win_toolchain_data`.
 
@@ -687,7 +652,7 @@
     error("Unsupported toolchain_arch, add it to win_toolchain_data.gni")
   }
 
-  # The toolchain data for `build_tools_toolchain` for the host machine.
+  # The toolchain data for `msvc_rust_host_build_tools_toolchain()`.
   if (rust_host_toolchain_arch == "x86") {
     rust_host_win_toolchain_data = win_toolchain_data_x86
   } else if (rust_host_toolchain_arch == "x64") {
@@ -722,38 +687,7 @@
         current_cpu = toolchain_arch
       }
     }
-    msvc_system_allocator_toolchain(
-        cl_toolchain_prefix + target_name + "_host_with_system_allocator") {
-      environment = "environment." + toolchain_arch
-      cl = "\"${win_toolchain_data.vc_bin_dir}/cl.exe\""
-
-      toolchain_args = {
-        if (defined(invoker.toolchain_args)) {
-          forward_variables_from(invoker.toolchain_args, "*")
-        }
-        is_clang = false
-        use_clang_coverage = false
-        current_os = "win"
-        current_cpu = toolchain_arch
-      }
-    }
-    msvc_system_allocator_toolchain(
-        cl_toolchain_prefix + target_name + "_with_system_allocator") {
-      environment = "environment." + toolchain_arch
-      cl = "\"${win_toolchain_data.vc_bin_dir}/cl.exe\""
-
-      toolchain_args = {
-        if (defined(invoker.toolchain_args)) {
-          forward_variables_from(invoker.toolchain_args, "*")
-        }
-        is_clang = false
-        use_clang_coverage = false
-        current_os = "win"
-        current_cpu = toolchain_arch
-      }
-    }
-    msvc_rust_host_build_tools_toolchain(
-        cl_toolchain_prefix + target_name + "_for_rust_host_build_tools") {
+    msvc_rust_host_build_tools_toolchain(cl_toolchain_prefix + target_name) {
       environment = "environment." + rust_host_toolchain_arch
       cl = "\"${rust_host_win_toolchain_data.vc_bin_dir}/cl.exe\""
 
@@ -802,48 +736,7 @@
       current_cpu = toolchain_arch
     }
   }
-  msvc_system_allocator_toolchain(
-      clang_toolchain_prefix + target_name + "_host_with_system_allocator") {
-    environment = "environment." + toolchain_arch
-    cl = "${_clang_bin_path}/clang-cl${_exe}"
-
-    sys_include_flags = "${win_toolchain_data.include_flags_imsvc}"
-    if (use_lld) {
-      sys_lib_flags = "-libpath:$_clang_lib_dir " +
-                      "${win_toolchain_data.libpath_lldlink_flags}"
-    }
-
-    toolchain_args = {
-      if (defined(invoker.toolchain_args)) {
-        forward_variables_from(invoker.toolchain_args, "*")
-      }
-      is_clang = true
-      current_os = "win"
-      current_cpu = toolchain_arch
-    }
-  }
-  msvc_system_allocator_toolchain(
-      clang_toolchain_prefix + target_name + "_with_system_allocator") {
-    environment = "environment." + toolchain_arch
-    cl = "${_clang_bin_path}/clang-cl${_exe}"
-
-    sys_include_flags = "${win_toolchain_data.include_flags_imsvc}"
-    if (use_lld) {
-      sys_lib_flags = "-libpath:$_clang_lib_dir " +
-                      "${win_toolchain_data.libpath_lldlink_flags}"
-    }
-
-    toolchain_args = {
-      if (defined(invoker.toolchain_args)) {
-        forward_variables_from(invoker.toolchain_args, "*")
-      }
-      is_clang = true
-      current_os = "win"
-      current_cpu = toolchain_arch
-    }
-  }
-  msvc_rust_host_build_tools_toolchain(
-      clang_toolchain_prefix + target_name + "_for_rust_host_build_tools") {
+  msvc_rust_host_build_tools_toolchain(clang_toolchain_prefix + target_name) {
     environment = "environment." + rust_host_toolchain_arch
     cl = "${_clang_bin_path}/clang-cl${_exe}"
 
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index 6dd5533..6e3f0a1 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -1319,8 +1319,7 @@
       outputs =
           [ "$root_out_dir/{{source_file_part}}-$chrome_version_full.breakpad" ]
 
-      dump_syms =
-          "//third_party/breakpad:dump_syms($host_system_allocator_toolchain)"
+      dump_syms = "//third_party/breakpad:dump_syms($host_toolchain)"
       args = rebase_path(outputs, root_build_dir) + [
                rebase_path(get_label_info(dump_syms, "root_out_dir") + "/" +
                                get_label_info(dump_syms, "name"),
diff --git a/chrome/updater/mac/BUILD.gn b/chrome/updater/mac/BUILD.gn
index ec4c538..0b4f9ed 100644
--- a/chrome/updater/mac/BUILD.gn
+++ b/chrome/updater/mac/BUILD.gn
@@ -537,8 +537,7 @@
   action_foreach("syms") {
     script = "//build/redirect_stdout.py"
     sources = _symbols_sources
-    dump_syms =
-        "//third_party/breakpad:dump_syms($host_system_allocator_toolchain)"
+    dump_syms = "//third_party/breakpad:dump_syms($host_toolchain)"
     public_deps = [
       ":updater_bundle",
       dump_syms,
diff --git a/ios/BUILD.gn b/ios/BUILD.gn
index e32b1c8..8fadc0bc 100644
--- a/ios/BUILD.gn
+++ b/ios/BUILD.gn
@@ -43,5 +43,8 @@
     deps = []
   }
 
+  # Force dependency on symupload needed by official builder.
+  deps += [ "//third_party/breakpad:symupload" ]
+
   deps += [ "//ios/intents/app:intents" ]
 }
diff --git a/native_client_sdk/src/BUILD.gn b/native_client_sdk/src/BUILD.gn
index cc1e68f..ee813b1e 100644
--- a/native_client_sdk/src/BUILD.gn
+++ b/native_client_sdk/src/BUILD.gn
@@ -2,7 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//build/toolchain/toolchain.gni")
 import("//components/nacl/features.gni")
 
 declare_args() {
@@ -54,9 +53,9 @@
     # http://crbug.com/245456
     if (!is_win && target_cpu == "x64") {
       deps += [
-        "//third_party/breakpad:dump_syms($host_system_allocator_toolchain)",
-        "//third_party/breakpad:minidump_dump($host_system_allocator_toolchain)",
-        "//third_party/breakpad:minidump_stackwalk($host_system_allocator_toolchain)",
+        "//third_party/breakpad:dump_syms($host_toolchain)",
+        "//third_party/breakpad:minidump_dump($host_toolchain)",
+        "//third_party/breakpad:minidump_stackwalk($host_toolchain)",
       ]
     }
   }
diff --git a/third_party/breakpad/BUILD.gn b/third_party/breakpad/BUILD.gn
index 110bfca..5fab2687 100644
--- a/third_party/breakpad/BUILD.gn
+++ b/third_party/breakpad/BUILD.gn
@@ -5,7 +5,6 @@
 import("//build/config/chromeos/ui_mode.gni")
 import("//build/config/rust.gni")
 import("//build/symlink.gni")
-import("//build/toolchain/toolchain.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 import("//testing/test.gni")
 
@@ -13,62 +12,6 @@
   import("//build/config/win/visual_studio_version.gni")
 }
 
-# Breakpad executables are only built with the system allocator toolchains,
-# because when built with PartitionAlloc-Everywhere enabled, we see that they
-# OOM and crash: https://crbug.com/345514993.
-#
-# IMPORTANT: The executables here may almost all be built for the *host*
-# machine, not the target machine. However they are still built into the
-# root_build_dir where normally you'd find the outputs of the default_toolchain
-# which are meant to run on the *target* machine. This is quite abnormal, but
-# our GN dependencies and test scripts expect the binary to be in the
-# root_build_dir, and expect to run it on the host machine any time the tests
-# are run in a VM or on a device (such as IOS, Android, and ChromeOS). In other
-# cases, where the test launcher is the same as the target (such as any desktop
-# platform), we expect to run it on the target machine.
-#
-# As such, if the executables are built for the default toolchain, they will be
-# built with the host or the default toolchain's settings depending on if we
-# expect the tests to be launched from the target machine or from a host
-# machine. Then they are copied up to the `root_out_dir` of the
-# `default_toolchain.
-#
-# There is no support for building these on host A, launching tests on host B,
-# and running tests on target C, where A and B are different machine types.
-if (is_ios || is_android || is_chromeos ||
-    # The breakpad exes do not compile successfully for Windows ARM.
-    (is_win && (current_cpu == "arm" || current_cpu == "arm64"))) {
-  # We build Windows ARM executables as Windows x64, targeting the host machine
-  # because they will run on the Arm machine still (through emulation) and
-  # because the code does not compile when targeting Windows ARM. This doesn't
-  # work for other hosts obviously.
-  assert(!is_win || host_os == "win")
-  _tests_launcher_toolchain = host_system_allocator_toolchain
-} else {
-  _tests_launcher_toolchain = default_system_allocator_toolchain
-}
-
-# Copies an executable target to the root directory of the current toolchain.
-# Used to copy from another toolchain. This requires that the executable is
-# built without component build enabled (see comment in //build/symlink.gni),
-# which is true for the `host_system_allocator_toolchain` and
-# `default_system_allocator_toolchain` toolchains in order to support this use
-# case.
-template("copy_exe") {
-  copy(target_name) {
-    forward_variables_from(invoker, TESTONLY_AND_VISIBILITY + [ "public_deps" ])
-    public_deps = [ invoker.target ]
-    if (is_win) {
-      _exe = ".exe"
-    } else {
-      _exe = ""
-    }
-    sources = [ get_label_info(invoker.target, "root_out_dir") + "/" +
-                get_label_info(invoker.target, "name") + _exe ]
-    outputs = [ "$root_out_dir/{{source_file_part}}" ]
-  }
-}
-
 config("tools_config") {
   include_dirs = [
     "breakpad/src",
@@ -137,8 +80,7 @@
 # {micro,mini}dump_stackwalk and minidump_dump are tool-type executables
 # that do not build on Windows.
 if (!is_win) {
-  if (current_toolchain == host_system_allocator_toolchain ||
-      current_toolchain == default_system_allocator_toolchain) {
+  if (current_toolchain == host_toolchain || target_os == "mac") {
     # Contains the code shared by both {micro,mini}dump_stackwalk.
     static_library("stackwalk_common") {
       # Binaries that use this library are not debugged frequently and
@@ -354,17 +296,16 @@
       configs -= [ "//build/config/compiler:chromium_code" ]
       configs += [ "//build/config/compiler:no_chromium_code" ]
     }
-  } else if (current_toolchain == default_toolchain) {
-    # The default toolchain builds the system-allocator binaries, which are
-    # placed in the output dir of the default toolchain.
-    copy_exe("microdump_stackwalk") {
-      target = ":$target_name($_tests_launcher_toolchain)"
+  } else {
+    # Aliases for convenience.
+    binary_symlink("microdump_stackwalk") {
+      binary_label = ":$target_name($host_toolchain)"
     }
-    copy_exe("minidump_stackwalk") {
-      target = ":$target_name($_tests_launcher_toolchain)"
+    binary_symlink("minidump_stackwalk") {
+      binary_label = ":$target_name($host_toolchain)"
     }
-    copy_exe("minidump_dump") {
-      target = ":$target_name($_tests_launcher_toolchain)"
+    binary_symlink("minidump_dump") {
+      binary_label = ":$target_name($host_toolchain)"
     }
   }
 }
@@ -372,8 +313,7 @@
 # Mac --------------------------------------------------------------------------
 
 if (is_mac) {
-  if (current_toolchain == host_system_allocator_toolchain ||
-      current_toolchain == default_system_allocator_toolchain) {
+  if (current_toolchain == host_toolchain || target_os != "ios") {
     source_set("common") {
       sources = [
         "breakpad/src/common/dwarf/bytereader.cc",
@@ -512,32 +452,27 @@
              ] + [ "-go_src" ] + rebase_path(_go_sources, root_build_dir) +
              [ "-extra" ] + rebase_path(_extra_sources, root_build_dir)
     }
-  } else if (current_toolchain == default_toolchain) {
-    # The default toolchain builds the system-allocator binaries, which are
-    # placed in the output dir of the default toolchain.
-    copy_exe("dump_syms") {
-      target = ":$target_name($_tests_launcher_toolchain)"
+  } else {
+    binary_symlink("dump_syms") {
+      binary_label = ":$target_name($host_toolchain)"
     }
-    copy_exe("symupload") {
-      target = ":$target_name($_tests_launcher_toolchain)"
+    binary_symlink("symupload") {
+      binary_label = ":$target_name($host_toolchain)"
     }
   }
 }
 
 if (is_ios) {
-  if (current_toolchain == default_toolchain) {
-    copy_exe("dump_syms") {
-      target = ":$target_name($_tests_launcher_toolchain)"
-    }
-    copy_exe("symupload") {
-      target = ":$target_name($_tests_launcher_toolchain)"
-    }
+  binary_symlink("dump_syms") {
+    binary_label = ":$target_name($host_toolchain)"
+  }
+  binary_symlink("symupload") {
+    binary_label = ":$target_name($host_toolchain)"
   }
 }
 
 if (is_linux || is_chromeos || is_android) {
-  if (current_toolchain == host_system_allocator_toolchain ||
-      current_toolchain == default_system_allocator_toolchain) {
+  if (current_toolchain == host_toolchain) {
     executable("symupload") {
       sources = [
         "breakpad/src/common/linux/http_upload.cc",
@@ -638,14 +573,13 @@
 
       libs = [ "z" ]
     }
-  } else if (current_toolchain == default_toolchain) {
-    # The default toolchain builds the system-allocator binaries, which are
-    # placed in the output dir of the default toolchain.
-    copy_exe("dump_syms") {
-      target = ":$target_name($_tests_launcher_toolchain)"
+  } else {
+    # Aliases for convenience.
+    binary_symlink("dump_syms") {
+      binary_label = ":dump_syms($host_toolchain)"
     }
-    copy_exe("symupload") {
-      target = ":$target_name($_tests_launcher_toolchain)"
+    binary_symlink("symupload") {
+      binary_label = ":symupload($host_toolchain)"
     }
   }
 
@@ -836,90 +770,85 @@
     configs += [ ":breakpad_unittest_config" ]
   }
 
-  if (current_toolchain == host_system_allocator_toolchain ||
-      current_toolchain == default_system_allocator_toolchain) {
-    executable("linux_dumper_unittest_helper") {
-      testonly = true
-      sources = [ "breakpad/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc" ]
-      deps = [ ":processor_support" ]
+  executable("linux_dumper_unittest_helper") {
+    testonly = true
+    sources = [ "breakpad/src/client/linux/minidump_writer/linux_dumper_unittest_helper.cc" ]
+    deps = [ ":processor_support" ]
 
-      configs += [ ":client_config" ]
+    configs += [ ":client_config" ]
 
-      if (is_component_build) {
-        ldflags = [ "-Wl,-rpath,\$ORIGIN" ]
-      }
+    if (is_component_build) {
+      ldflags = [ "-Wl,-rpath,\$ORIGIN" ]
     }
+  }
 
-    executable("generate_test_dump") {
-      testonly = true
-      sources = [ "linux/generate-test-dump.cc" ]
+  executable("generate_test_dump") {
+    testonly = true
+    sources = [ "linux/generate-test-dump.cc" ]
 
-      # This file has an unused variable warning.
-      configs -= [ "//build/config/compiler:chromium_code" ]
-      configs += [
-        ":client_config",
-        "//build/config/compiler:no_chromium_code",
-      ]
+    # This file has an unused variable warning.
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [
+      ":client_config",
+      "//build/config/compiler:no_chromium_code",
+    ]
 
-      deps = [ ":client" ]
+    deps = [ ":client" ]
 
-      if (is_android) {
-        libs = [ "log" ]
-      }
+    if (is_android) {
+      libs = [ "log" ]
     }
+  }
 
-    executable("minidump-2-core") {
-      sources = [
-        "breakpad/src/common/path_helper.cc",
-        "breakpad/src/common/path_helper.h",
-        "breakpad/src/tools/linux/md2core/minidump-2-core.cc",
-        "breakpad/src/tools/linux/md2core/minidump_memory_range.h",
-      ]
+  executable("minidump-2-core") {
+    sources = [
+      "breakpad/src/common/path_helper.cc",
+      "breakpad/src/common/path_helper.h",
+      "breakpad/src/tools/linux/md2core/minidump-2-core.cc",
+      "breakpad/src/tools/linux/md2core/minidump_memory_range.h",
+    ]
 
-      include_dirs = [ "breakpad/src" ]
+    include_dirs = [ "breakpad/src" ]
 
-      deps = [ ":client" ]
-    }
+    deps = [ ":client" ]
+  }
 
-    executable("core-2-minidump") {
-      sources = [
-        "breakpad/src/common/path_helper.cc",
-        "breakpad/src/common/path_helper.h",
-        "breakpad/src/tools/linux/core2md/core2md.cc",
-      ]
+  executable("core-2-minidump") {
+    sources = [
+      "breakpad/src/common/path_helper.cc",
+      "breakpad/src/common/path_helper.h",
+      "breakpad/src/tools/linux/core2md/core2md.cc",
+    ]
 
-      deps = [ ":client" ]
+    deps = [ ":client" ]
 
-      include_dirs = [ "breakpad/src" ]
-    }
-  } else if (current_toolchain == default_toolchain) {
-    # The default toolchain builds the system-allocator binaries, which are
-    # linked from the output dir of the default toolchain.
-
-    # Most breakpad binaries are only built for the `_tests_launcher_toolchain`.
-    # This is different, as it's used _inside_ a test, and thus needs to be
-    # built for the target machine, not the test-launcher machine.
-    copy_exe("linux_dumper_unittest_helper") {
-      testonly = true
-      target = ":$target_name($default_system_allocator_toolchain)"
-    }
-
-    copy_exe("generate_test_dump") {
-      testonly = true
-      target = ":$target_name($_tests_launcher_toolchain)"
-    }
-    copy_exe("minidump-2-core") {
-      target = ":$target_name($_tests_launcher_toolchain)"
-    }
-    copy_exe("core-2-minidump") {
-      target = ":$target_name($_tests_launcher_toolchain)"
-    }
+    include_dirs = [ "breakpad/src" ]
   }
 }
 
 if (is_win) {
-  if (current_toolchain == host_system_allocator_toolchain ||
-      current_toolchain == default_system_allocator_toolchain) {
+  # Force a native symupload, since Chrome tries to be "helpful" and not really
+  # differentiate target vs. host for x86/x64 builds.
+  #
+  # Normally, this would just use the (current_toolchain == host_toolchain)
+  # condition, which would cause these targets to only be compiled for the host
+  # CPU (i.e. to only build "native" binaries), but the Chrome Windows build
+  # will "always use the target CPU for host builds for x86/x64":
+  # https://crrev.com/3258ed4d9d755a3564d98bef8707bbdb5f8a7974/config/BUILDCONFIG.gn#199
+  # This means that host_toolchain will be x86 (32-bit) if the target is x86,
+  # even when the host is actually x64 (64-bit), which causes this to create
+  # 32-bit binaries, despite wanting native, 64-bit binaries.
+  #
+  # Adding the second condition enables this block for the "true" host
+  # toolchain as well, which allows creating 64-bit binaries even when the host
+  # toolchain is redefined to a 32-bit target.
+  if (is_clang) {
+    symupload_toolchain = "//build/toolchain/win:win_clang_$host_cpu"
+  } else {
+    symupload_toolchain = "//build/toolchain/win:$host_cpu"
+  }
+  if (current_toolchain == host_toolchain ||
+      current_toolchain == symupload_toolchain) {
     static_library("common_windows") {
       include_dirs = [
         "$visual_studio_path/DIA SDK/include",
@@ -997,15 +926,38 @@
       }
     }
 
-    executable("symupload") {
+    group("symupload") {
+      deps = [ ":symupload_win($symupload_toolchain)" ]
+    }
+    executable("symupload_win") {
       include_dirs = [
         "$visual_studio_path/DIA SDK/include",
         "breakpad/src",
       ]
       output_name = "symupload"
+
+      # Invert the normal logic which puts binaries built with the default
+      # (target) toolchain into the root output directory, and other toolchain
+      # binaries into subdirs. This gives preference to the native symupload,
+      # which is what's wanted in most situations. The cross-compiled binary
+      # can still be created (by building "symupload_win" instead of
+      # "symupload") and found in the corresponding toolchain subdir (e.g.
+      # //out/Release/win_clang_x86/ when cross-compiling to x86).
+      if (current_toolchain == symupload_toolchain) {
+        output_dir = "$root_build_dir"
+      } else {
+        output_name = "symupload_$target_cpu"
+        toolchain_parts =
+            string_split(get_path_info(current_toolchain, "name"), ":")
+        output_dir = "$root_out_dir/" + toolchain_parts[1]
+      }
+
       sources = [ "breakpad/src/tools/windows/symupload/symupload.cc" ]
+
       deps = [ "//third_party/breakpad:common_windows" ]
+
       ldflags = [ "/LARGEADDRESSAWARE" ]
+
       lib_dirs = []
       if (current_cpu == "x64") {
         lib_dirs += [ "$visual_studio_path/DIA SDK/lib/amd64" ]
@@ -1070,18 +1022,9 @@
         cflags = [ "-Wno-microsoft-goto" ]
       }
     }
-  } else if (current_toolchain == default_toolchain) {
-    # The default toolchain builds the system-allocator binaries, which are
-    # placed in the output dir of the default toolchain.
-    copy_exe("google_converter") {
-      target = ":$target_name($_tests_launcher_toolchain)"
-    }
-    copy_exe("symupload") {
-      target = ":$target_name($_tests_launcher_toolchain)"
-    }
-    copy_exe("dump_syms") {
-      target = ":$target_name($_tests_launcher_toolchain)"
-    }
+  } else {
+    # handle dump_syms appropriately for Windows cross build when necessary,
+    # such as symlinking.
   }
 }
 
diff --git a/tools/perf/chrome_telemetry_build/BUILD.gn b/tools/perf/chrome_telemetry_build/BUILD.gn
index 760386e..8a33f5dc 100644
--- a/tools/perf/chrome_telemetry_build/BUILD.gn
+++ b/tools/perf/chrome_telemetry_build/BUILD.gn
@@ -48,7 +48,7 @@
   }
 
   if (is_linux || is_chromeos) {
-    data_deps += [ "//third_party/breakpad:dump_syms" ]
+    data_deps += [ "//third_party/breakpad:dump_syms($host_toolchain)" ]
 
     # CrOS currently has issues with the locally compiled version of
     # crashpad_database_util, so only include it on traditional Linux