diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index f6631b66f5b65..b409515c5ea05 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -463,7 +463,9 @@ fn run_test(
     // Run the code!
     let mut cmd;
 
+    let output_file = make_maybe_absolute_path(output_file);
     if let Some(tool) = runtool {
+        let tool = make_maybe_absolute_path(tool.into());
         cmd = Command::new(tool);
         cmd.args(runtool_args);
         cmd.arg(output_file);
@@ -497,6 +499,20 @@ fn run_test(
     Ok(())
 }
 
+/// Converts a path intended to use as a command to absolute if it is
+/// relative, and not a single component.
+///
+/// This is needed to deal with relative paths interacting with
+/// `Command::current_dir` in a platform-specific way.
+fn make_maybe_absolute_path(path: PathBuf) -> PathBuf {
+    if path.components().count() == 1 {
+        // Look up process via PATH.
+        path
+    } else {
+        std::env::current_dir().map(|c| c.join(&path)).unwrap_or_else(|_| path)
+    }
+}
+
 /// Transforms a test into code that can be compiled into a Rust binary, and returns the number of
 /// lines before the test code begins as well as if the output stream supports colors or not.
 pub(crate) fn make_test(
diff --git a/tests/run-make/doctests-keep-binaries/Makefile b/tests/run-make/doctests-keep-binaries/Makefile
index 6254e93d3334f..2c647851ad0b7 100644
--- a/tests/run-make/doctests-keep-binaries/Makefile
+++ b/tests/run-make/doctests-keep-binaries/Makefile
@@ -3,7 +3,9 @@ include ../tools.mk
 
 # Check that valid binaries are persisted by running them, regardless of whether the --run or --no-run option is used.
 
-all: run no_run
+MY_SRC_DIR := ${CURDIR}
+
+all: run no_run test_run_directory
 
 run:
 	mkdir -p $(TMPDIR)/doctests
@@ -20,3 +22,12 @@ no_run:
 	$(TMPDIR)/doctests/t_rs_2_0/rust_out
 	$(TMPDIR)/doctests/t_rs_8_0/rust_out
 	rm -rf $(TMPDIR)/doctests
+
+# Behavior with --test-run-directory with relative paths.
+test_run_directory:
+	mkdir -p $(TMPDIR)/doctests
+	mkdir -p $(TMPDIR)/rundir
+	$(RUSTC) --crate-type rlib t.rs
+	( cd $(TMPDIR); \
+		$(RUSTDOC) -Zunstable-options --test --persist-doctests doctests --test-run-directory rundir --extern t=libt.rlib $(MY_SRC_DIR)/t.rs )
+	rm -rf $(TMPDIR)/doctests $(TMPDIR)/rundir
diff --git a/tests/run-make/doctests-runtool/Makefile b/tests/run-make/doctests-runtool/Makefile
new file mode 100644
index 0000000000000..7d5df1e307fb8
--- /dev/null
+++ b/tests/run-make/doctests-runtool/Makefile
@@ -0,0 +1,20 @@
+# ignore-cross-compile
+include ../tools.mk
+
+# Tests behavior of rustdoc --runtool
+
+MY_SRC_DIR := ${CURDIR}
+
+all: with_test_run_directory
+
+# Behavior with --runtool with relative paths and --test-run-directory.
+with_test_run_directory:
+	mkdir -p $(TMPDIR)/rundir
+	mkdir -p $(TMPDIR)/runtool
+	$(RUSTC) --crate-type rlib t.rs
+	$(RUSTC) runtool.rs -o $(TMPDIR)/runtool/runtool
+	( cd $(TMPDIR); \
+		$(RUSTDOC) -Zunstable-options --test --test-run-directory rundir \
+			--runtool runtool/runtool --extern t=libt.rlib $(MY_SRC_DIR)/t.rs \
+	)
+	rm -rf $(TMPDIR)/rundir $(TMPDIR)/runtool
diff --git a/tests/run-make/doctests-runtool/runtool.rs b/tests/run-make/doctests-runtool/runtool.rs
new file mode 100644
index 0000000000000..f5e3afdf212e2
--- /dev/null
+++ b/tests/run-make/doctests-runtool/runtool.rs
@@ -0,0 +1,3 @@
+fn main() {
+    eprintln!("{:?}", std::env::args().collect::<Vec<_>>());
+}
diff --git a/tests/run-make/doctests-runtool/t.rs b/tests/run-make/doctests-runtool/t.rs
new file mode 100644
index 0000000000000..c38cf0a0b25d4
--- /dev/null
+++ b/tests/run-make/doctests-runtool/t.rs
@@ -0,0 +1,11 @@
+/// Fungle the foople.
+/// ```
+/// t::foople();
+/// ```
+pub fn foople() {}
+
+/// Flomble the florp
+/// ```
+/// t::florp();
+/// ```
+pub fn florp() {}