1From e3a1797dbab3eaa1c808d53215b32c8759d27ac7 Mon Sep 17 00:00:00 2001
2From: Collin Baker <collinbaker@chromium.org>
3Date: Fri, 4 Apr 2025 14:08:18 -0700
4Subject: [PATCH] Reland "Use #[global_allocator] to provide Rust allocator
5 implementation"
6MIME-Version: 1.0
7Content-Type: text/plain; charset=UTF-8
8Content-Transfer-Encoding: 8bit
9
10This is a reland of commit cfa3beef52625e03ba6ce2b2ac98e1b89dde5cdb
11
12Original was reverted due to a cronet gn2bp failure. The script
13filtered out GN rules in //build/rust/std, but this caused an exception
14when //build/rust/std:allocator was referenced later.
15
16Moving the rules to //build/rust/allocator sidesteps the issue.
17
18Original change's description:
19> Use #[global_allocator] to provide Rust allocator implementation
20>
21> The allocator shim hack we have been using no longer works with
22> upstream Rust. Replace it with a less-unsupported method: provide a
23> https://github.com/rust-lang/rust/issues/123015, which still requires
24> us to provide a few symbol definitions.
25>
26> Bug: 408221149, 407024458
27> Change-Id: If1808ca24b12dc80ead35a25521313a3d2e148d5
28>
29> Cq-Include-Trybots: luci.chromium.try:android-rust-arm32-rel,android-rust-arm64-dbg,android-rust-arm64-rel,linux-rust-x64-dbg,linux-rust-x64-rel,mac-rust-x64-dbg,win-rust-x64-dbg,win-rust-x64-rel
30> Change-Id: If1808ca24b12dc80ead35a25521313a3d2e148d5
31> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6427855
32> Reviewed-by: Alan Zhao <ayzhao@google.com>
33> Reviewed-by: Lei Zhang <thestig@chromium.org>
34> Reviewed-by: Łukasz Anforowicz <lukasza@chromium.org>
35> Commit-Queue: Collin Baker <collinbaker@chromium.org>
36> Auto-Submit: Collin Baker <collinbaker@chromium.org>
37> Cr-Commit-Position: refs/heads/main@{#1442472}
38
39Bug: 408221149, 407024458
40Cq-Include-Trybots: luci.chromium.try:android-rust-arm32-rel,android-rust-arm64-dbg,android-rust-arm64-rel,linux-rust-x64-dbg,linux-rust-x64-rel,mac-rust-x64-dbg,win-rust-x64-dbg,win-rust-x64-rel
41Change-Id: I36fef217297bfe64ae81519be24b8c653f6fdfa1
42Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6432410
43Reviewed-by: Mohannad Farrag <aymanm@google.com>
44Reviewed-by: Łukasz Anforowicz <lukasza@chromium.org>
45Auto-Submit: Collin Baker <collinbaker@chromium.org>
46Commit-Queue: Łukasz Anforowicz <lukasza@chromium.org>
47Cr-Commit-Position: refs/heads/main@{#1442922}
48---
49 build/rust/allocator/BUILD.gn | 90 ++++++++++++++++
50 build/rust/{std => allocator}/alias.cc | 4 +-
51 build/rust/{std => allocator}/alias.h | 6 +-
52 .../allocator_impls.cc} | 100 ++++++++----------
53 build/rust/allocator/allocator_impls.h | 25 +++++
54 .../allocator/allocator_shim_definitions.cc | 30 ++++++
55 .../{std => allocator}/compiler_specific.h | 6 +-
56 .../rust/{std => allocator}/immediate_crash.h | 6 +-
57 build/rust/allocator/lib.rs | 48 +++++++++
58 build/rust/cargo_crate.gni | 9 ++
59 build/rust/rust_macro.gni | 3 +
60 build/rust/rust_target.gni | 4 +
61 build/rust/std/BUILD.gn | 41 -------
62 components/cronet/android/dependencies.txt | 1 +
63 third_party/breakpad/BUILD.gn | 10 +-
64 15 files changed, 272 insertions(+), 111 deletions(-)
65 create mode 100644 build/rust/allocator/BUILD.gn
66 rename build/rust/{std => allocator}/alias.cc (87%)
67 rename build/rust/{std => allocator}/alias.h (91%)
68 rename build/rust/{std/remap_alloc.cc => allocator/allocator_impls.cc} (67%)
69 create mode 100644 build/rust/allocator/allocator_impls.h
70 create mode 100644 build/rust/allocator/allocator_shim_definitions.cc
71 rename build/rust/{std => allocator}/compiler_specific.h (87%)
72 rename build/rust/{std => allocator}/immediate_crash.h (97%)
73 create mode 100644 build/rust/allocator/lib.rs
74
75diff --git a/build/rust/allocator/BUILD.gn b/build/rust/allocator/BUILD.gn
76new file mode 100644
77index 00000000000000..06aa47f097c9c4
78--- /dev/null
79+++ b/build/rust/allocator/BUILD.gn
80@@ -0,0 +1,90 @@
81+# Copyright 2025 The Chromium Authors
82+# Use of this source code is governed by a BSD-style license that can be
83+# found in the LICENSE file.
84+
85+import("//build/buildflag_header.gni")
86+import("//build/config/rust.gni")
87+import("//build/rust/rust_static_library.gni")
88+
89+rust_allocator_uses_partition_alloc = false
90+if (build_with_chromium) {
91+ import("//base/allocator/partition_allocator/partition_alloc.gni")
92+ rust_allocator_uses_partition_alloc = use_partition_alloc_as_malloc
93+}
94+
95+buildflag_header("buildflags") {
96+ header = "buildflags.h"
97+ flags = [
98+ "RUST_ALLOCATOR_USES_PARTITION_ALLOC=$rust_allocator_uses_partition_alloc",
99+ ]
100+ visibility = [ ":*" ]
101+}
102+
103+if (toolchain_has_rust) {
104+ # All targets which depend on Rust code but are not linked by rustc must
105+ # depend on this. Usually, this dependency will come from the rust_target() GN
106+ # template. However, cargo_crate() does *not* include this dependency so any
107+ # C++ targets which directly depend on a cargo_crate() must depend on this.
108+ rust_static_library("allocator") {
109+ sources = [ "lib.rs" ]
110+ crate_root = "lib.rs"
111+ cxx_bindings = [ "lib.rs" ]
112+
113+ deps = [
114+ ":allocator_impls",
115+ ":allocator_shim_definitions",
116+ ]
117+
118+ no_chromium_prelude = true
119+ no_allocator_crate = true
120+ allow_unsafe = true
121+ }
122+
123+ static_library("allocator_impls") {
124+ public_deps = []
125+ if (rust_allocator_uses_partition_alloc) {
126+ public_deps += [ "//base/allocator/partition_allocator:partition_alloc" ]
127+ }
128+
129+ sources = [
130+ "allocator_impls.cc",
131+ "allocator_impls.h",
132+ ]
133+
134+ deps = [
135+ ":allocator_cpp_shared",
136+ ":buildflags",
137+
138+ # TODO(crbug.com/408221149): remove the C++ -> Rust dependency for the
139+ # default allocator.
140+ "//build/rust/std",
141+ ]
142+
143+ visibility = [ ":*" ]
144+ }
145+
146+ source_set("allocator_shim_definitions") {
147+ sources = [ "allocator_shim_definitions.cc" ]
148+
149+ deps = [ ":allocator_cpp_shared" ]
150+
151+ visibility = [ ":*" ]
152+ }
153+
154+ source_set("allocator_cpp_shared") {
155+ sources = [
156+ # `alias.*`, `compiler_specific.h`, and `immediate_crash.*` have been
157+ # copied from `//base`.
158+ # TODO(crbug.com/40279749): Avoid duplication / reuse code.
159+ "alias.cc",
160+ "alias.h",
161+ "compiler_specific.h",
162+ "immediate_crash.h",
163+ ]
164+
165+ visibility = [
166+ ":allocator_impls",
167+ ":allocator_shim_definitions",
168+ ]
169+ }
170+}
171diff --git a/build/rust/std/alias.cc b/build/rust/allocator/alias.cc
172similarity index 87%
173rename from build/rust/std/alias.cc
174rename to build/rust/allocator/alias.cc
175index 42febac3ed1fc5..ca20986f8ed496 100644
176--- a/build/rust/std/alias.cc
177+++ b/build/rust/allocator/alias.cc
178@@ -7,9 +7,9 @@
179 //
180 // TODO(crbug.com/40279749): Avoid code duplication / reuse code.
181
182-#include "build/rust/std/alias.h"
183+#include "build/rust/allocator/alias.h"
184
185-#include "build/rust/std/compiler_specific.h"
186+#include "build/rust/allocator/compiler_specific.h"
187
188 namespace build_rust_std {
189 namespace debug {
190diff --git a/build/rust/std/alias.h b/build/rust/allocator/alias.h
191similarity index 91%
192rename from build/rust/std/alias.h
193rename to build/rust/allocator/alias.h
194index 0eaba6766148fa..80995ecfb045e3 100644
195--- a/build/rust/std/alias.h
196+++ b/build/rust/allocator/alias.h
197@@ -8,8 +8,8 @@
198 //
199 // TODO(crbug.com/40279749): Avoid code duplication / reuse code.
200
201-#ifndef BUILD_RUST_STD_ALIAS_H_
202-#define BUILD_RUST_STD_ALIAS_H_
203+#ifndef BUILD_RUST_ALLOCATOR_ALIAS_H_
204+#define BUILD_RUST_ALLOCATOR_ALIAS_H_
205
206 #include <stddef.h>
207
208@@ -34,4 +34,4 @@ void Alias(const void* var);
209 const int line_number = __LINE__; \
210 build_rust_std::debug::Alias(&line_number)
211
212-#endif // BUILD_RUST_STD_ALIAS_H_
213+#endif // BUILD_RUST_ALLOCATOR_ALIAS_H_
214diff --git a/build/rust/std/remap_alloc.cc b/build/rust/allocator/allocator_impls.cc
215similarity index 67%
216rename from build/rust/std/remap_alloc.cc
217rename to build/rust/allocator/allocator_impls.cc
218index a443b11ec513df..1fde98f23cd124 100644
219--- a/build/rust/std/remap_alloc.cc
220+++ b/build/rust/allocator/allocator_impls.cc
221@@ -2,6 +2,8 @@
222 // Use of this source code is governed by a BSD-style license that can be
223 // found in the LICENSE file.
224
225+#include "build/rust/allocator/allocator_impls.h"
226+
227 #ifdef UNSAFE_BUFFERS_BUILD
228 // TODO(crbug.com/390223051): Remove C-library calls to fix the errors.
229 #pragma allow_unsafe_libc_calls
230@@ -11,9 +13,9 @@
231 #include <cstring>
232
233 #include "build/build_config.h"
234-#include "build/rust/std/alias.h"
235-#include "build/rust/std/buildflags.h"
236-#include "build/rust/std/immediate_crash.h"
237+#include "build/rust/allocator/alias.h"
238+#include "build/rust/allocator/buildflags.h"
239+#include "build/rust/allocator/immediate_crash.h"
240
241 #if BUILDFLAG(RUST_ALLOCATOR_USES_PARTITION_ALLOC)
242 #include "partition_alloc/partition_alloc_constants.h" // nogncheck
243@@ -22,6 +24,11 @@
244 #include <cstdlib>
245 #endif
246
247+// NOTE: this documentation is outdated.
248+//
249+// TODO(crbug.com/408221149): update this documentation, or replace it with docs
250+// in the Rust allocator implementation.
251+//
252 // When linking a final binary, rustc has to pick between either:
253 // * The default Rust allocator
254 // * Any #[global_allocator] defined in *any rlib in its dependency tree*
255@@ -87,19 +94,6 @@
256 // enabling it breaks Win32 APIs like CreateProcess:
257 // https://issues.chromium.org/u/1/issues/368070343#comment29
258
259-extern "C" {
260-
261-#ifdef COMPONENT_BUILD
262-#if BUILDFLAG(IS_WIN)
263-#define REMAP_ALLOC_ATTRIBUTES __declspec(dllexport) __attribute__((weak))
264-#else
265-#define REMAP_ALLOC_ATTRIBUTES \
266- __attribute__((visibility("default"))) __attribute__((weak))
267-#endif
268-#else
269-#define REMAP_ALLOC_ATTRIBUTES __attribute__((weak))
270-#endif // COMPONENT_BUILD
271-
272 #if !BUILDFLAG(RUST_ALLOCATOR_USES_PARTITION_ALLOC) && BUILDFLAG(IS_WIN) && \
273 defined(ADDRESS_SANITIZER)
274 #define USE_WIN_ALIGNED_MALLOC 1
275@@ -107,17 +101,19 @@ extern "C" {
276 #define USE_WIN_ALIGNED_MALLOC 0
277 #endif
278
279-// This must exist as the stdlib depends on it to prove that we know the
280-// alloc shims below are unstable. In the future we may be required to replace
281-// them with a #[global_allocator] crate (see file comment above for more).
282-//
283-// Marked as weak as when Rust drives linking it includes this symbol itself,
284-// and we don't want a collision due to C++ being in the same link target, where
285-// C++ causes us to explicitly link in the stdlib and this symbol here.
286-[[maybe_unused]]
287-__attribute__((weak)) unsigned char __rust_no_alloc_shim_is_unstable;
288+// The default allocator functions provided by the Rust standard library.
289+extern "C" void* __rdl_alloc(size_t size, size_t align);
290+extern "C" void __rdl_dealloc(void* p, size_t size, size_t align);
291+extern "C" void* __rdl_realloc(void* p,
292+ size_t old_size,
293+ size_t align,
294+ size_t new_size);
295+
296+extern "C" void* __rdl_alloc_zeroed(size_t size, size_t align);
297+
298+namespace rust_allocator_internal {
299
300-REMAP_ALLOC_ATTRIBUTES void* __rust_alloc(size_t size, size_t align) {
301+unsigned char* alloc(size_t size, size_t align) {
302 #if BUILDFLAG(RUST_ALLOCATOR_USES_PARTITION_ALLOC)
303 // PartitionAlloc will crash if given an alignment larger than this.
304 if (align > partition_alloc::internal::kMaxSupportedAlignment) {
305@@ -125,19 +121,19 @@ REMAP_ALLOC_ATTRIBUTES void* __rust_alloc(size_t size, size_t align) {
306 }
307
308 if (align <= alignof(std::max_align_t)) {
309- return allocator_shim::UncheckedAlloc(size);
310+ return static_cast<unsigned char*>(allocator_shim::UncheckedAlloc(size));
311 } else {
312- return allocator_shim::UncheckedAlignedAlloc(size, align);
313+ return static_cast<unsigned char*>(
314+ allocator_shim::UncheckedAlignedAlloc(size, align));
315 }
316 #elif USE_WIN_ALIGNED_MALLOC
317- return _aligned_malloc(size, align);
318+ return static_cast<unsigned char*>(_aligned_malloc(size, align));
319 #else
320- extern void* __rdl_alloc(size_t size, size_t align);
321- return __rdl_alloc(size, align);
322+ return static_cast<unsigned char*>(__rdl_alloc(size, align));
323 #endif
324 }
325
326-REMAP_ALLOC_ATTRIBUTES void __rust_dealloc(void* p, size_t size, size_t align) {
327+void dealloc(unsigned char* p, size_t size, size_t align) {
328 #if BUILDFLAG(RUST_ALLOCATOR_USES_PARTITION_ALLOC)
329 if (align <= alignof(std::max_align_t)) {
330 allocator_shim::UncheckedFree(p);
331@@ -147,54 +143,44 @@ REMAP_ALLOC_ATTRIBUTES void __rust_dealloc(void* p, size_t size, size_t align) {
332 #elif USE_WIN_ALIGNED_MALLOC
333 return _aligned_free(p);
334 #else
335- extern void __rdl_dealloc(void* p, size_t size, size_t align);
336 __rdl_dealloc(p, size, align);
337 #endif
338 }
339
340-REMAP_ALLOC_ATTRIBUTES void* __rust_realloc(void* p,
341- size_t old_size,
342- size_t align,
343- size_t new_size) {
344+unsigned char* realloc(unsigned char* p,
345+ size_t old_size,
346+ size_t align,
347+ size_t new_size) {
348 #if BUILDFLAG(RUST_ALLOCATOR_USES_PARTITION_ALLOC)
349 if (align <= alignof(std::max_align_t)) {
350- return allocator_shim::UncheckedRealloc(p, new_size);
351+ return static_cast<unsigned char*>(
352+ allocator_shim::UncheckedRealloc(p, new_size));
353 } else {
354- return allocator_shim::UncheckedAlignedRealloc(p, new_size, align);
355+ return static_cast<unsigned char*>(
356+ allocator_shim::UncheckedAlignedRealloc(p, new_size, align));
357 }
358 #elif USE_WIN_ALIGNED_MALLOC
359- return _aligned_realloc(p, new_size, align);
360+ return static_cast<unsigned char*>(_aligned_realloc(p, new_size, align));
361 #else
362- extern void* __rdl_realloc(void* p, size_t old_size, size_t align,
363- size_t new_size);
364- return __rdl_realloc(p, old_size, align, new_size);
365+ return static_cast<unsigned char*>(
366+ __rdl_realloc(p, old_size, align, new_size));
367 #endif
368 }
369
370-REMAP_ALLOC_ATTRIBUTES void* __rust_alloc_zeroed(size_t size, size_t align) {
371+unsigned char* alloc_zeroed(size_t size, size_t align) {
372 #if BUILDFLAG(RUST_ALLOCATOR_USES_PARTITION_ALLOC) || USE_WIN_ALIGNED_MALLOC
373 // TODO(danakj): When RUST_ALLOCATOR_USES_PARTITION_ALLOC is true, it's
374 // possible that a partition_alloc::UncheckedAllocZeroed() call would perform
375 // better than partition_alloc::UncheckedAlloc() + memset. But there is no
376 // such API today. See b/342251590.
377- void* p = __rust_alloc(size, align);
378+ unsigned char* p = alloc(size, align);
379 if (p) {
380 memset(p, 0, size);
381 }
382 return p;
383 #else
384- extern void* __rdl_alloc_zeroed(size_t size, size_t align);
385- return __rdl_alloc_zeroed(size, align);
386+ return static_cast<unsigned char*>(__rdl_alloc_zeroed(size, align));
387 #endif
388 }
389
390-REMAP_ALLOC_ATTRIBUTES void __rust_alloc_error_handler(size_t size,
391- size_t align) {
392- NO_CODE_FOLDING();
393- IMMEDIATE_CRASH();
394-}
395-
396-REMAP_ALLOC_ATTRIBUTES extern const unsigned char
397- __rust_alloc_error_handler_should_panic = 0;
398-
399-} // extern "C"
400+} // namespace rust_allocator_internal
401diff --git a/build/rust/allocator/allocator_impls.h b/build/rust/allocator/allocator_impls.h
402new file mode 100644
403index 00000000000000..afb335412faf9c
404--- /dev/null
405+++ b/build/rust/allocator/allocator_impls.h
406@@ -0,0 +1,25 @@
407+// Copyright 2025 The Chromium Authors
408+// Use of this source code is governed by a BSD-style license that can be
409+// found in the LICENSE file.
410+
411+#ifndef BUILD_RUST_ALLOCATOR_ALLOCATOR_IMPLS_H_
412+#define BUILD_RUST_ALLOCATOR_ALLOCATOR_IMPLS_H_
413+
414+#include <cstddef>
415+
416+#include "build/build_config.h"
417+#include "build/rust/allocator/buildflags.h"
418+
419+namespace rust_allocator_internal {
420+
421+unsigned char* alloc(size_t size, size_t align);
422+void dealloc(unsigned char* p, size_t size, size_t align);
423+unsigned char* realloc(unsigned char* p,
424+ size_t old_size,
425+ size_t align,
426+ size_t new_size);
427+unsigned char* alloc_zeroed(size_t size, size_t align);
428+
429+} // namespace rust_allocator_internal
430+
431+#endif // BUILD_RUST_ALLOCATOR_ALLOCATOR_IMPLS_H_
432diff --git a/build/rust/allocator/allocator_shim_definitions.cc b/build/rust/allocator/allocator_shim_definitions.cc
433new file mode 100644
434index 00000000000000..a4d1bd77b7016e
435--- /dev/null
436+++ b/build/rust/allocator/allocator_shim_definitions.cc
437@@ -0,0 +1,30 @@
438+// Copyright 2025 The Chromium Authors
439+// Use of this source code is governed by a BSD-style license that can be
440+// found in the LICENSE file.
441+
442+#include <cstddef>
443+
444+#include "build/rust/allocator/alias.h"
445+#include "build/rust/allocator/immediate_crash.h"
446+
447+extern "C" {
448+
449+// As part of rustc's contract for using `#[global_allocator]` without
450+// rustc-generated shims we must define this symbol, since we are opting in to
451+// unstable functionality. See https://github.com/rust-lang/rust/issues/123015
452+//
453+// Mark it weak since rustc will generate it when it drives linking.
454+[[maybe_unused]]
455+__attribute__((weak)) unsigned char __rust_no_alloc_shim_is_unstable;
456+
457+__attribute__((weak)) void __rust_alloc_error_handler(size_t size,
458+ size_t align) {
459+ NO_CODE_FOLDING();
460+ IMMEDIATE_CRASH();
461+}
462+
463+__attribute__((
464+ weak)) extern const unsigned char __rust_alloc_error_handler_should_panic =
465+ 0;
466+
467+} // extern "C"
468diff --git a/build/rust/std/compiler_specific.h b/build/rust/allocator/compiler_specific.h
469similarity index 87%
470rename from build/rust/std/compiler_specific.h
471rename to build/rust/allocator/compiler_specific.h
472index ea79a7a8dc2842..f9079679a3e9af 100644
473--- a/build/rust/std/compiler_specific.h
474+++ b/build/rust/allocator/compiler_specific.h
475@@ -7,8 +7,8 @@
476 //
477 // TODO(crbug.com/40279749): Avoid code duplication / reuse code.
478
479-#ifndef BUILD_RUST_STD_COMPILER_SPECIFIC_H_
480-#define BUILD_RUST_STD_COMPILER_SPECIFIC_H_
481+#ifndef BUILD_RUST_ALLOCATOR_COMPILER_SPECIFIC_H_
482+#define BUILD_RUST_ALLOCATOR_COMPILER_SPECIFIC_H_
483
484 #include "build/build_config.h"
485
486@@ -35,4 +35,4 @@
487 #define NOINLINE
488 #endif
489
490-#endif // BUILD_RUST_STD_COMPILER_SPECIFIC_H_
491+#endif // BUILD_RUST_ALLOCATOR_COMPILER_SPECIFIC_H_
492diff --git a/build/rust/std/immediate_crash.h b/build/rust/allocator/immediate_crash.h
493similarity index 97%
494rename from build/rust/std/immediate_crash.h
495rename to build/rust/allocator/immediate_crash.h
496index e4fd5a09d9379f..9cbf9fd65f3e09 100644
497--- a/build/rust/std/immediate_crash.h
498+++ b/build/rust/allocator/immediate_crash.h
499@@ -5,8 +5,8 @@
500 // This file has been copied from //base/immediate_crash.h.
501 // TODO(crbug.com/40279749): Avoid code duplication / reuse code.
502
503-#ifndef BUILD_RUST_STD_IMMEDIATE_CRASH_H_
504-#define BUILD_RUST_STD_IMMEDIATE_CRASH_H_
505+#ifndef BUILD_RUST_ALLOCATOR_IMMEDIATE_CRASH_H_
506+#define BUILD_RUST_ALLOCATOR_IMMEDIATE_CRASH_H_
507
508 #include "build/build_config.h"
509
510@@ -168,4 +168,4 @@
511
512 #endif // defined(__clang__) || defined(COMPILER_GCC)
513
514-#endif // BUILD_RUST_STD_IMMEDIATE_CRASH_H_
515+#endif // BUILD_RUST_ALLOCATOR_IMMEDIATE_CRASH_H_
516diff --git a/build/rust/allocator/lib.rs b/build/rust/allocator/lib.rs
517new file mode 100644
518index 00000000000000..7f4a0fc2456942
519--- /dev/null
520+++ b/build/rust/allocator/lib.rs
521@@ -0,0 +1,48 @@
522+// Copyright 2025 The Chromium Authors
523+// Use of this source code is governed by a BSD-style license that can be
524+// found in the LICENSE file.
525+
526+//! Define the allocator that Rust code in Chrome should use.
527+//!
528+//! Any final artifact that depends on this crate, even transitively, will use
529+//! the allocator defined here. Currently this is a thin wrapper around
530+//! allocator_impls.cc's functions; see the documentation there.
531+
532+use std::alloc::{GlobalAlloc, Layout};
533+
534+struct Allocator;
535+
536+unsafe impl GlobalAlloc for Allocator {
537+ unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
538+ unsafe { ffi::alloc(layout.size(), layout.align()) }
539+ }
540+
541+ unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
542+ unsafe {
543+ ffi::dealloc(ptr, layout.size(), layout.align());
544+ }
545+ }
546+
547+ unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
548+ unsafe { ffi::alloc_zeroed(layout.size(), layout.align()) }
549+ }
550+
551+ unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
552+ unsafe { ffi::realloc(ptr, layout.size(), layout.align(), new_size) }
553+ }
554+}
555+
556+#[global_allocator]
557+static GLOBAL: Allocator = Allocator;
558+
559+#[cxx::bridge(namespace = "rust_allocator_internal")]
560+mod ffi {
561+ extern "C++" {
562+ include!("build/rust/allocator/allocator_impls.h");
563+
564+ unsafe fn alloc(size: usize, align: usize) -> *mut u8;
565+ unsafe fn dealloc(p: *mut u8, size: usize, align: usize);
566+ unsafe fn realloc(p: *mut u8, old_size: usize, align: usize, new_size: usize) -> *mut u8;
567+ unsafe fn alloc_zeroed(size: usize, align: usize) -> *mut u8;
568+ }
569+}
570diff --git a/build/rust/cargo_crate.gni b/build/rust/cargo_crate.gni
571index 6d11c538bf4d5a..d9912722b4ecdb 100644
572--- a/build/rust/cargo_crate.gni
573+++ b/build/rust/cargo_crate.gni
574@@ -259,6 +259,12 @@ template("cargo_crate") {
575 # Don't import the `chromium` crate into third-party code.
576 no_chromium_prelude = true
577
578+ # Don't depend on the chrome-specific #[global_allocator] crate from
579+ # third-party code. This avoids some dependency cycle issues. The allocator
580+ # crate will still be used if it exists anywhere in the dependency graph for
581+ # a given linked artifact.
582+ no_allocator_crate = true
583+
584 rustc_metadata = _rustc_metadata
585
586 # TODO(crbug.com/40259764): don't default to true. This requires changes to
587@@ -483,6 +489,9 @@ template("cargo_crate") {
588 # Don't import the `chromium` crate into third-party code.
589 no_chromium_prelude = true
590
591+ # Build scripts do not need to link to chrome's allocator.
592+ no_allocator_crate = true
593+
594 # The ${_build_script_name}_output target looks for the exe in this
595 # location. Due to how the Windows component build works, this has to
596 # be $root_out_dir for all EXEs. In component build, C++ links to the
597diff --git a/build/rust/rust_macro.gni b/build/rust/rust_macro.gni
598index bcbb30ed441115..41d857632ccdc9 100644
599--- a/build/rust/rust_macro.gni
600+++ b/build/rust/rust_macro.gni
601@@ -16,6 +16,9 @@ template("rust_macro") {
602 forward_variables_from(invoker, TESTONLY_AND_VISIBILITY)
603 proc_macro_configs = invoker.configs
604 target_type = "rust_proc_macro"
605+
606+ # Macros are loaded by rustc and shouldn't use chrome's allocation routines.
607+ no_allocator_crate = true
608 }
609 }
610
611diff --git a/build/rust/rust_target.gni b/build/rust/rust_target.gni
612index 1a2f96337d4361..1003a7b678352d 100644
613--- a/build/rust/rust_target.gni
614+++ b/build/rust/rust_target.gni
615@@ -339,6 +339,10 @@ template("rust_target") {
616 _rust_deps += [ "//build/rust/std" ]
617 }
618
619+ if (!defined(invoker.no_allocator_crate) || !invoker.no_allocator_crate) {
620+ _rust_deps += [ "//build/rust/allocator" ]
621+ }
622+
623 if (_build_unit_tests) {
624 _unit_test_target = "${_target_name}_unittests"
625 if (defined(invoker.unit_test_target)) {
626diff --git a/build/rust/std/BUILD.gn b/build/rust/std/BUILD.gn
627index 6b996aa1fe3865..25db126076b2fa 100644
628--- a/build/rust/std/BUILD.gn
629+++ b/build/rust/std/BUILD.gn
630@@ -15,51 +15,12 @@
631 # allocator functions to PartitionAlloc when `use_partition_alloc_as_malloc` is
632 # true, so that Rust and C++ use the same allocator backend.
633
634-import("//build/buildflag_header.gni")
635 import("//build/config/compiler/compiler.gni")
636 import("//build/config/coverage/coverage.gni")
637 import("//build/config/rust.gni")
638 import("//build/config/sanitizers/sanitizers.gni")
639
640-rust_allocator_uses_partition_alloc = false
641-if (build_with_chromium) {
642- import("//base/allocator/partition_allocator/partition_alloc.gni")
643- rust_allocator_uses_partition_alloc = use_partition_alloc_as_malloc
644-}
645-
646-buildflag_header("buildflags") {
647- header = "buildflags.h"
648- flags = [
649- "RUST_ALLOCATOR_USES_PARTITION_ALLOC=$rust_allocator_uses_partition_alloc",
650- ]
651- visibility = [ ":*" ]
652-}
653-
654 if (toolchain_has_rust) {
655- # If clang performs the link step, we need to provide the allocator symbols
656- # that are normally injected by rustc during linking.
657- #
658- # We also "happen to" use this to redirect allocations to PartitionAlloc,
659- # though that would be better done through a #[global_allocator] crate (see
660- # above).
661- source_set("remap_alloc") {
662- public_deps = []
663- if (rust_allocator_uses_partition_alloc) {
664- public_deps += [ "//base/allocator/partition_allocator:partition_alloc" ]
665- }
666- deps = [ ":buildflags" ]
667- sources = [
668- # `alias.*`, `compiler_specific.h`, and `immediate_crash.*` have been
669- # copied from `//base`.
670- # TODO(crbug.com/40279749): Avoid duplication / reuse code.
671- "alias.cc",
672- "alias.h",
673- "compiler_specific.h",
674- "immediate_crash.h",
675- "remap_alloc.cc",
676- ]
677- }
678-
679 # List of Rust stdlib rlibs which are present in the official Rust toolchain
680 # we are using from the Android team. This is usually a version or two behind
681 # nightly. Generally this matches the toolchain we build ourselves, but if
682@@ -269,8 +230,6 @@ if (toolchain_has_rust) {
683 foreach(libname, stdlib_files + skip_stdlib_files) {
684 deps += [ "rules:$libname" ]
685 }
686-
687- public_deps = [ ":remap_alloc" ]
688 }
689 } else {
690 action("find_stdlib") {
691diff --git a/components/cronet/android/dependencies.txt b/components/cronet/android/dependencies.txt
692index bf56bc45ed41f7..c0e41ef7c6766a 100644
693--- a/components/cronet/android/dependencies.txt
694+++ b/components/cronet/android/dependencies.txt
695@@ -14,6 +14,7 @@
696 //build/config
697 //build/config/compiler
698 //build/rust
699+//build/rust/allocator
700 //build/rust/chromium_prelude
701 //build/rust/std
702 //build/rust/std/rules
703diff --git a/third_party/breakpad/BUILD.gn b/third_party/breakpad/BUILD.gn
704index 2f4e1ab0156609..e140ecbedcc9a0 100644
705--- a/third_party/breakpad/BUILD.gn
706+++ b/third_party/breakpad/BUILD.gn
707@@ -495,7 +495,10 @@ if (is_mac) {
708 defines = [ "HAVE_MACH_O_NLIST_H" ]
709
710 # Rust demangle support.
711- deps = [ "//third_party/rust/rustc_demangle_capi/v0_1:lib" ]
712+ deps = [
713+ "//build/rust/allocator",
714+ "//third_party/rust/rustc_demangle_capi/v0_1:lib",
715+ ]
716 defines += [ "HAVE_RUSTC_DEMANGLE" ]
717 include_dirs += [ "//third_party/rust/chromium_crates_io/vendor/rustc-demangle-capi-v0_1/include" ]
718 sources += [ "//third_party/rust/chromium_crates_io/vendor/rustc-demangle-capi-v0_1/include/rustc_demangle.h" ]
719@@ -743,7 +746,10 @@ if (is_linux || is_chromeos || is_android) {
720 include_dirs = [ "breakpad/src" ]
721
722 # Rust demangle support.
723- deps = [ "//third_party/rust/rustc_demangle_capi/v0_1:lib" ]
724+ deps = [
725+ "//build/rust/allocator",
726+ "//third_party/rust/rustc_demangle_capi/v0_1:lib",
727+ ]
728 defines += [ "HAVE_RUSTC_DEMANGLE" ]
729 include_dirs += [ "//third_party/rust/chromium_crates_io/vendor/rustc-demangle-capi-v0_1/include" ]
730 sources += [ "//third_party/rust/chromium_crates_io/vendor/rustc-demangle-capi-v0_1/include/rustc_demangle.h" ]