diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index 90601521b19f1..847b5b81d5adc 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -1519,17 +1519,25 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
     // for the current implementation of the standard library.
     let mut group_end = None;
     let mut group_start = None;
-    let mut end_with = FxHashSet::default();
+    // Crates available for linking thus far.
+    let mut available = FxHashSet::default();
+    // Crates required to satisfy dependencies discovered so far.
+    let mut required = FxHashSet::default();
+
     let info = &codegen_results.crate_info;
     for &(cnum, _) in deps.iter().rev() {
         if let Some(missing) = info.missing_lang_items.get(&cnum) {
-            end_with.extend(missing.iter().cloned());
-            if !end_with.is_empty() && group_end.is_none() {
-                group_end = Some(cnum);
-            }
+            let missing_crates = missing.iter().map(|i| info.lang_item_to_crate.get(i).copied());
+            required.extend(missing_crates);
+        }
+
+        required.insert(Some(cnum));
+        available.insert(Some(cnum));
+
+        if required.len() > available.len() && group_end.is_none() {
+            group_end = Some(cnum);
         }
-        end_with.retain(|item| info.lang_item_to_crate.get(item) != Some(&cnum));
-        if end_with.is_empty() && group_end.is_some() {
+        if required.len() == available.len() && group_end.is_some() {
             group_start = Some(cnum);
             break;
         }
diff --git a/src/test/run-make-fulldeps/issue-69368/Makefile b/src/test/run-make-fulldeps/issue-69368/Makefile
new file mode 100644
index 0000000000000..dbb044d8f5d46
--- /dev/null
+++ b/src/test/run-make-fulldeps/issue-69368/Makefile
@@ -0,0 +1,18 @@
+-include ../tools.mk
+
+# Test that previously triggered a linker failure with root cause
+# similar to one found in the issue #69368.
+#
+# The crate that provides oom lang item is missing some other lang
+# items. Necessary to prevent the use of start-group / end-group.
+#
+# The weak lang items are defined in a separate compilation units,
+# so that linker could omit them if not used.
+#
+# The crates that need those weak lang items are dependencies of
+# crates that provide them.
+
+all:
+	$(RUSTC) a.rs
+	$(RUSTC) b.rs
+	$(RUSTC) c.rs
diff --git a/src/test/run-make-fulldeps/issue-69368/a.rs b/src/test/run-make-fulldeps/issue-69368/a.rs
new file mode 100644
index 0000000000000..726db8746371e
--- /dev/null
+++ b/src/test/run-make-fulldeps/issue-69368/a.rs
@@ -0,0 +1,16 @@
+#![crate_type = "rlib"]
+#![feature(lang_items)]
+#![feature(panic_unwind)]
+#![no_std]
+
+extern crate panic_unwind;
+
+#[panic_handler]
+pub fn panic_handler(_: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
+
+#[no_mangle]
+extern "C" fn __rust_drop_panic() -> ! {
+    loop {}
+}
diff --git a/src/test/run-make-fulldeps/issue-69368/b.rs b/src/test/run-make-fulldeps/issue-69368/b.rs
new file mode 100644
index 0000000000000..4d6af0266563b
--- /dev/null
+++ b/src/test/run-make-fulldeps/issue-69368/b.rs
@@ -0,0 +1,8 @@
+#![crate_type = "rlib"]
+#![feature(alloc_error_handler)]
+#![no_std]
+
+#[alloc_error_handler]
+pub fn error_handler(_: core::alloc::Layout) -> ! {
+    panic!();
+}
diff --git a/src/test/run-make-fulldeps/issue-69368/c.rs b/src/test/run-make-fulldeps/issue-69368/c.rs
new file mode 100644
index 0000000000000..729c4249a053a
--- /dev/null
+++ b/src/test/run-make-fulldeps/issue-69368/c.rs
@@ -0,0 +1,34 @@
+#![crate_type = "bin"]
+#![feature(start)]
+#![no_std]
+
+extern crate alloc;
+extern crate a;
+extern crate b;
+
+use alloc::vec::Vec;
+use core::alloc::*;
+
+struct Allocator;
+
+unsafe impl GlobalAlloc for Allocator {
+    unsafe fn alloc(&self, _: Layout) -> *mut u8 {
+        loop {}
+    }
+
+    unsafe fn dealloc(&self, _: *mut u8, _: Layout) {
+        loop {}
+    }
+}
+
+#[global_allocator]
+static ALLOCATOR: Allocator = Allocator;
+
+#[start]
+fn main(argc: isize, _argv: *const *const u8) -> isize {
+    let mut v = Vec::new();
+    for i in 0..argc {
+        v.push(i);
+    }
+    v.iter().sum()
+}