diff --git a/ChangeLog b/ChangeLog
index c66e67122128..f03b3ab82e40 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2007-08-18  Paul Brook  <paul@codesourcery.com>
+            Joseph Myers  <joseph@codesourcery.com>
+
+	* Makefile.tpl (DEBUG_PREFIX_CFLAGS_FOR_TARGET): New.
+	(CFLAGS_FOR_TARGET, CXXFLAGS_FOR_TARGET): Include it.
+	* Makefile.in: Regenerate.
+	* configure.ac (--with-debug-prefix-map): New.
+	* configure: Regenerate.
+
 2007-08-17  Richard Sandiford  <richard@codesourcery.com>
 	    Nigel Stephens  <nigel@mips.com>
 
diff --git a/Makefile.in b/Makefile.in
index a91ee163d1bd..80b2474686a0 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -366,9 +366,12 @@ COMPILER_NM_FOR_TARGET=@COMPILER_NM_FOR_TARGET@
 # CFLAGS will be just -g.  We want to ensure that TARGET libraries
 # (which we know are built with gcc) are built with optimizations so
 # prepend -O2 when setting CFLAGS_FOR_TARGET.
-CFLAGS_FOR_TARGET = -O2 $(CFLAGS) $(SYSROOT_CFLAGS_FOR_TARGET)
+CFLAGS_FOR_TARGET = -O2 $(CFLAGS) $(SYSROOT_CFLAGS_FOR_TARGET) \
+	$(DEBUG_PREFIX_CFLAGS_FOR_TARGET)
 SYSROOT_CFLAGS_FOR_TARGET = @SYSROOT_CFLAGS_FOR_TARGET@
-CXXFLAGS_FOR_TARGET = $(CXXFLAGS) $(SYSROOT_CFLAGS_FOR_TARGET)
+DEBUG_PREFIX_CFLAGS_FOR_TARGET = @DEBUG_PREFIX_CFLAGS_FOR_TARGET@
+CXXFLAGS_FOR_TARGET = $(CXXFLAGS) $(SYSROOT_CFLAGS_FOR_TARGET) \
+	$(DEBUG_PREFIX_CFLAGS_FOR_TARGET)
 LIBCFLAGS_FOR_TARGET = $(CFLAGS_FOR_TARGET)
 LIBCXXFLAGS_FOR_TARGET = $(CXXFLAGS_FOR_TARGET) -fno-implicit-templates
 LDFLAGS_FOR_TARGET = 
diff --git a/Makefile.tpl b/Makefile.tpl
index 8cb7f7d177f4..cf9796166361 100644
--- a/Makefile.tpl
+++ b/Makefile.tpl
@@ -369,9 +369,12 @@ COMPILER_NM_FOR_TARGET=@COMPILER_NM_FOR_TARGET@
 # CFLAGS will be just -g.  We want to ensure that TARGET libraries
 # (which we know are built with gcc) are built with optimizations so
 # prepend -O2 when setting CFLAGS_FOR_TARGET.
-CFLAGS_FOR_TARGET = -O2 $(CFLAGS) $(SYSROOT_CFLAGS_FOR_TARGET)
+CFLAGS_FOR_TARGET = -O2 $(CFLAGS) $(SYSROOT_CFLAGS_FOR_TARGET) \
+	$(DEBUG_PREFIX_CFLAGS_FOR_TARGET)
 SYSROOT_CFLAGS_FOR_TARGET = @SYSROOT_CFLAGS_FOR_TARGET@
-CXXFLAGS_FOR_TARGET = $(CXXFLAGS) $(SYSROOT_CFLAGS_FOR_TARGET)
+DEBUG_PREFIX_CFLAGS_FOR_TARGET = @DEBUG_PREFIX_CFLAGS_FOR_TARGET@
+CXXFLAGS_FOR_TARGET = $(CXXFLAGS) $(SYSROOT_CFLAGS_FOR_TARGET) \
+	$(DEBUG_PREFIX_CFLAGS_FOR_TARGET)
 LIBCFLAGS_FOR_TARGET = $(CFLAGS_FOR_TARGET)
 LIBCXXFLAGS_FOR_TARGET = $(CXXFLAGS_FOR_TARGET) -fno-implicit-templates
 LDFLAGS_FOR_TARGET = 
diff --git a/config/ChangeLog b/config/ChangeLog
index ffa8a92cd741..3df146fbd9c4 100644
--- a/config/ChangeLog
+++ b/config/ChangeLog
@@ -1,3 +1,9 @@
+2007-08-18  Paul Brook  <paul@codesourcery.com>
+            Joseph Myers  <joseph@codesourcery.com>
+
+	* mt-gnu (CXXFLAGS_FOR_TARGET): Add
+	$(DEBUG_PREFIX_CFLAGS_FOR_TARGET).
+
 2007-07-06  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* tls.m4 (GCC_CHECK_CC_TLS): New.
diff --git a/config/mt-gnu b/config/mt-gnu
index f05c4f92f665..2400fa44e55f 100644
--- a/config/mt-gnu
+++ b/config/mt-gnu
@@ -1 +1,2 @@
-CXXFLAGS_FOR_TARGET = $(CXXFLAGS) $(SYSROOT_CFLAGS_FOR_TARGET) -D_GNU_SOURCE
+CXXFLAGS_FOR_TARGET = $(CXXFLAGS) $(SYSROOT_CFLAGS_FOR_TARGET) \
+	$(DEBUG_PREFIX_CFLAGS_FOR_TARGET) -D_GNU_SOURCE
diff --git a/configure b/configure
index ac3eeb1d92ea..1a37bfd6b33d 100755
--- a/configure
+++ b/configure
@@ -272,7 +272,7 @@ PACKAGE_STRING=
 PACKAGE_BUGREPORT=
 
 ac_unique_file="move-if-change"
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os build_noncanonical host_noncanonical target_noncanonical host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN LN_S TOPLEVEL_CONFIGURE_ARGUMENTS build_libsubdir build_subdir host_subdir target_subdir CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX GNATBIND ac_ct_GNATBIND GNATMAKE ac_ct_GNATMAKE do_compare gmplibs gmpinc stage1_languages SYSROOT_CFLAGS_FOR_TARGET RPATH_ENVVAR tooldir build_tooldir CONFIGURE_GDB_TK GDB_TK INSTALL_GDB_TK build_configargs build_configdirs host_configargs configdirs target_configargs CC_FOR_BUILD config_shell YACC BISON M4 LEX FLEX MAKEINFO EXPECT RUNTEST AR AS DLLTOOL LD LIPO NM RANLIB STRIP WINDRES WINDMC OBJCOPY OBJDUMP CFLAGS_FOR_BUILD CC_FOR_TARGET CXX_FOR_TARGET GCC_FOR_TARGET GCJ_FOR_TARGET GFORTRAN_FOR_TARGET AR_FOR_TARGET AS_FOR_TARGET DLLTOOL_FOR_TARGET LD_FOR_TARGET LIPO_FOR_TARGET NM_FOR_TARGET OBJDUMP_FOR_TARGET RANLIB_FOR_TARGET STRIP_FOR_TARGET WINDRES_FOR_TARGET WINDMC_FOR_TARGET RAW_CXX_FOR_TARGET FLAGS_FOR_TARGET COMPILER_AS_FOR_TARGET COMPILER_LD_FOR_TARGET COMPILER_NM_FOR_TARGET MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT stage1_cflags stage1_checking stage2_werror_flag datarootdir docdir pdfdir htmldir LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os build_noncanonical host_noncanonical target_noncanonical host host_cpu host_vendor host_os target target_cpu target_vendor target_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN LN_S TOPLEVEL_CONFIGURE_ARGUMENTS build_libsubdir build_subdir host_subdir target_subdir CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX GNATBIND ac_ct_GNATBIND GNATMAKE ac_ct_GNATMAKE do_compare gmplibs gmpinc stage1_languages SYSROOT_CFLAGS_FOR_TARGET DEBUG_PREFIX_CFLAGS_FOR_TARGET RPATH_ENVVAR tooldir build_tooldir CONFIGURE_GDB_TK GDB_TK INSTALL_GDB_TK build_configargs build_configdirs host_configargs configdirs target_configargs CC_FOR_BUILD config_shell YACC BISON M4 LEX FLEX MAKEINFO EXPECT RUNTEST AR AS DLLTOOL LD LIPO NM RANLIB STRIP WINDRES WINDMC OBJCOPY OBJDUMP CFLAGS_FOR_BUILD CC_FOR_TARGET CXX_FOR_TARGET GCC_FOR_TARGET GCJ_FOR_TARGET GFORTRAN_FOR_TARGET AR_FOR_TARGET AS_FOR_TARGET DLLTOOL_FOR_TARGET LD_FOR_TARGET LIPO_FOR_TARGET NM_FOR_TARGET OBJDUMP_FOR_TARGET RANLIB_FOR_TARGET STRIP_FOR_TARGET WINDRES_FOR_TARGET WINDMC_FOR_TARGET RAW_CXX_FOR_TARGET FLAGS_FOR_TARGET COMPILER_AS_FOR_TARGET COMPILER_LD_FOR_TARGET COMPILER_NM_FOR_TARGET MAINTAINER_MODE_TRUE MAINTAINER_MODE_FALSE MAINT stage1_cflags stage1_checking stage2_werror_flag datarootdir docdir pdfdir htmldir LIBOBJS LTLIBOBJS'
 ac_subst_files='serialization_dependencies host_makefile_frag target_makefile_frag alphaieee_frag ospace_frag'
 
 # Initialize some variables set by options.
@@ -965,6 +965,8 @@ Optional Packages:
   --with-gmp-lib=PATH     specify directory for the installed GMP library
   --with-build-sysroot=SYSROOT
                           use sysroot as the system root during the build
+  --with-debug-prefix-map='A=B C=D ...'
+                             map A to B, C to D ... in debug information
   --with-build-time-tools=PATH
                           use given path to find target tools during the build
   --with-datarootdir      use datarootdir as the data root directory.
@@ -5069,6 +5071,21 @@ else
 fi;
 
 
+
+# Check whether --with-debug-prefix-map or --without-debug-prefix-map was given.
+if test "${with_debug_prefix_map+set}" = set; then
+  withval="$with_debug_prefix_map"
+  if test x"$withval" != x; then
+     DEBUG_PREFIX_CFLAGS_FOR_TARGET=
+     for debug_map in $withval; do
+       DEBUG_PREFIX_CFLAGS_FOR_TARGET="$DEBUG_PREFIX_CFLAGS_FOR_TARGET -fdebug-prefix-map=$debug_map"
+     done
+   fi
+else
+  DEBUG_PREFIX_CFLAGS_FOR_TARGET=
+fi;
+
+
 # Handle --with-headers=XXX.  If the value is not "yes", the contents of
 # the named directory are copied to $(tooldir)/sys-include.
 if test x"${with_headers}" != x && test x"${with_headers}" != xno ; then
@@ -12723,6 +12740,7 @@ s,@gmplibs@,$gmplibs,;t t
 s,@gmpinc@,$gmpinc,;t t
 s,@stage1_languages@,$stage1_languages,;t t
 s,@SYSROOT_CFLAGS_FOR_TARGET@,$SYSROOT_CFLAGS_FOR_TARGET,;t t
+s,@DEBUG_PREFIX_CFLAGS_FOR_TARGET@,$DEBUG_PREFIX_CFLAGS_FOR_TARGET,;t t
 s,@RPATH_ENVVAR@,$RPATH_ENVVAR,;t t
 s,@tooldir@,$tooldir,;t t
 s,@build_tooldir@,$build_tooldir,;t t
diff --git a/configure.ac b/configure.ac
index 9e0efc32c7c7..2486049cf18b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1593,6 +1593,18 @@ AC_ARG_WITH([build-sysroot],
   [SYSROOT_CFLAGS_FOR_TARGET=])
 AC_SUBST(SYSROOT_CFLAGS_FOR_TARGET)
 
+AC_ARG_WITH([debug-prefix-map],
+  [  --with-debug-prefix-map='A=B C=D ...'
+                             map A to B, C to D ... in debug information],
+  [if test x"$withval" != x; then
+     DEBUG_PREFIX_CFLAGS_FOR_TARGET=
+     for debug_map in $withval; do
+       DEBUG_PREFIX_CFLAGS_FOR_TARGET="$DEBUG_PREFIX_CFLAGS_FOR_TARGET -fdebug-prefix-map=$debug_map"
+     done
+   fi],
+  [DEBUG_PREFIX_CFLAGS_FOR_TARGET=])
+AC_SUBST(DEBUG_PREFIX_CFLAGS_FOR_TARGET)
+
 # Handle --with-headers=XXX.  If the value is not "yes", the contents of
 # the named directory are copied to $(tooldir)/sys-include.
 if test x"${with_headers}" != x && test x"${with_headers}" != xno ; then
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 39e912c56192..0af10bdebb75 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,30 @@
+2007-08-18  Paul Brook  <paul@codesourcery.com>
+            Joseph Myers  <joseph@codesourcery.com>
+
+	* common.opt (-fdebug-prefix-map=): New option.
+	* opts.c: Include debug.h.
+	(common_handle_option): Handle -fdebug-prefix-map.
+	* final.c: Include ggc.h.
+	(struct debug_prefix_map, debug_prefix_maps, add_debug_prefix_map,
+	remap_debug_filename): New.
+	* Makefile.in (final.o, opts.o): Update dependencies.
+	* debug.h (remap_debug_filename, add_debug_prefix_map): Declare.
+	* configure.ac: Check for assembler --debug-prefix-map support.
+	* configure, config.in: Regenerate.
+	* gcc.c (ASM_MAP): Define conditional on HAVE_AS_DEBUG_PREFIX_MAP.
+	(ASM_DEBUG_SPEC): Include ASM_MAP.
+	* doc/install.texi (--with-debug-prefix-map): Document.
+	* doc/invoke.texi (-fdebug-prefix-map): Document.
+	* dbxout.c (dbxout_init, dbxout_start_source_file,
+	dbxout_source_file): Call remap_debug_filename.
+	* dwarf2out.c (add_comp_dir_attribute, maybe_emit_file,
+	dwarf2out_start_source_file, dwarf2out_finish): Call
+	remap_debug_filename.
+	(file_table_relative_p): Do not check d->emitted_number.
+	* toplev.c (output_file_directive): Call remap_debug_filename.
+	* vmsdbgout.c (write_srccorr): Call remap_debug_filename.
+	* xcoffout.c (xcoffout_source_file): Call remap_debug_filename.
+
 2007-08-17  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
 	* loop-invariant.c (find_invariants_to_move): Add missing macro
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 190ff69a7c4e..597e2468fceb 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -2295,7 +2295,7 @@ diagnostic.o : diagnostic.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
 opts.o : opts.c opts.h options.h toplev.h $(CONFIG_H) $(SYSTEM_H) \
    coretypes.h $(TREE_H) $(TM_H) langhooks.h $(GGC_H) $(RTL_H) \
    output.h $(DIAGNOSTIC_H) $(TM_P_H) $(INSN_ATTR_H) intl.h $(TARGET_H) \
-   $(FLAGS_H) $(PARAMS_H) tree-pass.h $(DBGCNT_H)
+   $(FLAGS_H) $(PARAMS_H) tree-pass.h $(DBGCNT_H) debug.h
 opts-common.o : opts-common.c opts.h $(CONFIG_H) $(SYSTEM_H) \
    coretypes.h intl.h
 targhooks.o : targhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
@@ -2785,7 +2785,7 @@ final.o : final.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    insn-config.h $(INSN_ATTR_H) $(FUNCTION_H) output.h hard-reg-set.h \
    except.h debug.h xcoffout.h toplev.h reload.h dwarf2out.h tree-pass.h \
    $(BASIC_BLOCK_H) $(TM_P_H) $(TARGET_H) $(EXPR_H) $(CFGLAYOUT_H) dbxout.h \
-   $(TIMEVAR_H) $(CGRAPH_H) $(COVERAGE_H) $(REAL_H) $(DF_H) vecprim.h
+   $(TIMEVAR_H) $(CGRAPH_H) $(COVERAGE_H) $(REAL_H) $(DF_H) vecprim.h $(GGC_H)
 recog.o : recog.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    $(FUNCTION_H) $(BASIC_BLOCK_H) $(REGS_H) $(RECOG_H) $(EXPR_H) \
    $(FLAGS_H) insn-config.h $(INSN_ATTR_H) toplev.h output.h reload.h \
diff --git a/gcc/common.opt b/gcc/common.opt
index 6d277eac86a4..d9894a98844d 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -399,6 +399,10 @@ fdbg-cnt=
 Common RejectNegative Joined
 -fdbg-cnt=<counter>:<limit>[,<counter>:<limit>,...]    Set the debug counter limit.   
 
+fdebug-prefix-map=
+Common Joined RejectNegative
+Map one directory name to another in debug information
+
 ; Nonzero for -fdefer-pop: don't pop args after each function call
 ; instead save them up to pop many calls' args with one insns.
 fdefer-pop
diff --git a/gcc/config.in b/gcc/config.in
index 80f0dac7b23e..42748868bf32 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -186,6 +186,12 @@
 #endif
 
 
+/* Define if your assembler supports the --debug-prefix-map option. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_AS_DEBUG_PREFIX_MAP
+#endif
+
+
 /* Define if your assembler supports DFP instructions. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_AS_DFP
diff --git a/gcc/configure b/gcc/configure
index 31bfc400c6e6..ac5f49a6120d 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -16178,6 +16178,43 @@ cat >>confdefs.h <<\_ACEOF
 #define HAVE_AS_GSTABS_DEBUG_FLAG 1
 _ACEOF
 
+fi
+
+ echo "$as_me:$LINENO: checking assembler for --debug-prefix-map option" >&5
+echo $ECHO_N "checking assembler for --debug-prefix-map option... $ECHO_C" >&6
+if test "${gcc_cv_as_debug_prefix_map_flag+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  gcc_cv_as_debug_prefix_map_flag=no
+    if test $in_tree_gas = yes; then
+    if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 0`
+  then gcc_cv_as_debug_prefix_map_flag=yes
+fi
+  elif test x$gcc_cv_as != x; then
+    echo "$insn" > conftest.s
+    if { ac_try='$gcc_cv_as --debug-prefix-map /a=/b -o conftest.o conftest.s >&5'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }
+    then
+	gcc_cv_as_debug_prefix_map_flag=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_as_debug_prefix_map_flag" >&5
+echo "${ECHO_T}$gcc_cv_as_debug_prefix_map_flag" >&6
+if test $gcc_cv_as_debug_prefix_map_flag = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_AS_DEBUG_PREFIX_MAP 1
+_ACEOF
+
 fi
 fi
 
diff --git a/gcc/configure.ac b/gcc/configure.ac
index e1dc518a2a76..8bb9fc6b170e 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3068,6 +3068,12 @@ if test x"$insn" != x; then
    fi],
   [AC_DEFINE(HAVE_AS_GSTABS_DEBUG_FLAG, 1,
 [Define if your assembler supports the --gstabs option.])])
+
+ gcc_GAS_CHECK_FEATURE([--debug-prefix-map option],
+  gcc_cv_as_debug_prefix_map_flag,
+  [2,19,0], [--debug-prefix-map /a=/b], [$insn],,
+  [AC_DEFINE(HAVE_AS_DEBUG_PREFIX_MAP, 1,
+[Define if your assembler supports the --debug-prefix-map option.])])
 fi
 
 AC_CACHE_CHECK([assembler for tolerance to line number 0],
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index 9657120b29b2..8c6a72e05ff9 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -983,6 +983,7 @@ dbxout_init (const char *input_file_name)
   char ltext_label_name[100];
   bool used_ltext_label_name = false;
   tree syms = lang_hooks.decls.getdecls ();
+  const char *mapped_name;
 
   typevec_len = 100;
   typevec = ggc_calloc (typevec_len, sizeof typevec[0]);
@@ -1008,6 +1009,7 @@ dbxout_init (const char *input_file_name)
 	    cwd = "/";
 	  else if (!IS_DIR_SEPARATOR (cwd[strlen (cwd) - 1]))
 	    cwd = concat (cwd, "/", NULL);
+	  cwd = remap_debug_filename (cwd);
 	}
 #ifdef DBX_OUTPUT_MAIN_SOURCE_DIRECTORY
       DBX_OUTPUT_MAIN_SOURCE_DIRECTORY (asm_out_file, cwd);
@@ -1018,10 +1020,11 @@ dbxout_init (const char *input_file_name)
 #endif /* no DBX_OUTPUT_MAIN_SOURCE_DIRECTORY */
     }
 
+  mapped_name = remap_debug_filename (input_file_name);
 #ifdef DBX_OUTPUT_MAIN_SOURCE_FILENAME
-  DBX_OUTPUT_MAIN_SOURCE_FILENAME (asm_out_file, input_file_name);
+  DBX_OUTPUT_MAIN_SOURCE_FILENAME (asm_out_file, mapped_name);
 #else
-  dbxout_begin_simple_stabs_desc (input_file_name, N_SO, get_lang_number ());
+  dbxout_begin_simple_stabs_desc (mapped_name, N_SO, get_lang_number ());
   dbxout_stab_value_label (ltext_label_name);
   used_ltext_label_name = true;
 #endif
@@ -1163,7 +1166,7 @@ dbxout_start_source_file (unsigned int line ATTRIBUTE_UNUSED,
   n->prev = NULL;
   current_file->prev = n;
   n->bincl_status = BINCL_PENDING;
-  n->pending_bincl_name = filename;
+  n->pending_bincl_name = remap_debug_filename (filename);
   pending_bincls = 1;
   current_file = n;
 #endif
@@ -1229,7 +1232,7 @@ dbxout_source_file (const char *filename)
       if (current_function_decl == NULL_TREE)
 	switch_to_section (text_section);
 
-      dbxout_begin_simple_stabs (filename, N_SOL);
+      dbxout_begin_simple_stabs (remap_debug_filename (filename), N_SOL);
       dbxout_stab_value_internal_label ("Ltext", &source_label_number);
       lastfile = filename;
     }
diff --git a/gcc/debug.h b/gcc/debug.h
index 90076fca819b..d1431f5c7ad9 100644
--- a/gcc/debug.h
+++ b/gcc/debug.h
@@ -167,4 +167,7 @@ extern void debug_free_queue (void);
 extern int debug_nesting;
 extern int symbol_queue_index;
 
+const char *remap_debug_filename (const char *);
+void add_debug_prefix_map (const char *);
+
 #endif /* !GCC_DEBUG_H  */
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index ec2826e8edab..bf017761d0ee 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -1345,6 +1345,11 @@ GCC, you can explicitly specify the directory where they are installed
 shorthand assumptions are not correct, you can use the explicit
 include and lib options directly.
 
+@item --with-debug-prefix-map=@var{map}
+Convert source directory names using @option{-fdebug-prefix-map} when
+building runtime libraries.  @samp{@var{map}} is a space-separated
+list of maps of the form @samp{@var{old}=@var{new}}.
+
 @end table
 
 @subheading Cross-Compiler-Specific Options
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index eed4f10b5067..3815e593e058 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -303,6 +303,7 @@ Objective-C and Objective-C++ Dialects}.
 -ftest-coverage  -ftime-report -fvar-tracking @gol
 -g  -g@var{level}  -gcoff -gdwarf-2 @gol
 -ggdb  -gstabs  -gstabs+  -gvms  -gxcoff  -gxcoff+ @gol
+-fdebug-prefix-map=@var{old}=@var{new} @gol
 -femit-struct-debug-baseonly -femit-struct-debug-reduced @gol
 -femit-struct-debug-detailed@r{[}=@var{spec-list}@r{]} @gol
 -p  -pg  -print-file-name=@var{library}  -print-libgcc-file-name @gol
@@ -4144,6 +4145,11 @@ The default is @samp{-femit-struct-debug-detailed=all}.
 
 This option works only with DWARF 2.
 
+@item -fdebug-prefix-map=@var{old}=@var{new}
+@opindex fdebug-prefix-map
+When compiling files in directory @file{@var{old}}, record debugging
+information describing them as in @file{@var{new}} instead.
+
 @cindex @command{prof}
 @item -p
 @opindex p
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index dc352b1e5b49..bfeb5447c79d 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -10906,7 +10906,7 @@ add_comp_dir_attribute (dw_die_ref die)
 {
   const char *wd = get_src_pwd ();
   if (wd != NULL)
-    add_AT_string (die, DW_AT_comp_dir, wd);
+    add_AT_string (die, DW_AT_comp_dir, remap_debug_filename (wd));
 }
 
 /* Given a tree node describing an array bound (either lower or upper) output
@@ -14000,7 +14000,8 @@ maybe_emit_file (struct dwarf_file_data * fd)
       if (DWARF2_ASM_LINE_DEBUG_INFO)
 	{
 	  fprintf (asm_out_file, "\t.file %u ", fd->emitted_number);
-	  output_quoted_string (asm_out_file, fd->filename);
+	  output_quoted_string (asm_out_file,
+				remap_debug_filename (fd->filename));
 	  fputc ('\n', asm_out_file);
 	}
     }
@@ -14167,7 +14168,7 @@ dwarf2out_start_source_file (unsigned int lineno, const char *filename)
       dw_die_ref bincl_die;
 
       bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die, NULL);
-      add_AT_string (bincl_die, DW_AT_name, filename);
+      add_AT_string (bincl_die, DW_AT_name, remap_debug_filename (filename));
     }
 
   if (debug_info_level >= DINFO_LEVEL_VERBOSE)
@@ -14626,7 +14627,7 @@ file_table_relative_p (void ** slot, void *param)
 {
   bool *p = param;
   struct dwarf_file_data *d = *slot;
-  if (d->emitted_number && !IS_ABSOLUTE_PATH (d->filename))
+  if (!IS_ABSOLUTE_PATH (d->filename))
     {
       *p = true;
       return 0;
@@ -14645,7 +14646,7 @@ dwarf2out_finish (const char *filename)
 
   /* Add the name for the main input file now.  We delayed this from
      dwarf2out_init to avoid complications with PCH.  */
-  add_name_attribute (comp_unit_die, filename);
+  add_name_attribute (comp_unit_die, remap_debug_filename (filename));
   if (!IS_ABSOLUTE_PATH (filename))
     add_comp_dir_attribute (comp_unit_die);
   else if (get_AT (comp_unit_die, DW_AT_comp_dir) == NULL)
diff --git a/gcc/final.c b/gcc/final.c
index 759bf101d7bd..008a773ca23b 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -77,6 +77,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "coverage.h"
 #include "df.h"
 #include "vecprim.h"
+#include "ggc.h"
 
 #ifdef XCOFF_DEBUGGING_INFO
 #include "xcoffout.h"		/* Needed for external data
@@ -1350,6 +1351,72 @@ asm_insn_count (rtx body)
 }
 #endif
 
+/* ??? This is probably the wrong place for these.  */
+/* Structure recording the mapping from source file and directory
+   names at compile time to those to be embedded in debug
+   information.  */
+typedef struct debug_prefix_map
+{
+  const char *old_prefix;
+  const char *new_prefix;
+  size_t old_len;
+  size_t new_len;
+  struct debug_prefix_map *next;
+} debug_prefix_map;
+
+/* Linked list of such structures.  */
+debug_prefix_map *debug_prefix_maps;
+
+
+/* Record a debug file prefix mapping.  ARG is the argument to
+   -fdebug-prefix-map and must be of the form OLD=NEW.  */
+
+void
+add_debug_prefix_map (const char *arg)
+{
+  debug_prefix_map *map;
+  const char *p;
+
+  p = strchr (arg, '=');
+  if (!p)
+    {
+      error ("invalid argument %qs to -fdebug-prefix-map", arg);
+      return;
+    }
+  map = XNEW (debug_prefix_map);
+  map->old_prefix = ggc_alloc_string (arg, p - arg);
+  map->old_len = p - arg;
+  p++;
+  map->new_prefix = ggc_strdup (p);
+  map->new_len = strlen (p);
+  map->next = debug_prefix_maps;
+  debug_prefix_maps = map;
+}
+
+/* Perform user-specified mapping of debug filename prefixes.  Return
+   the new name corresponding to FILENAME.  */
+
+const char *
+remap_debug_filename (const char *filename)
+{
+  debug_prefix_map *map;
+  char *s;
+  const char *name;
+  size_t name_len;
+
+  for (map = debug_prefix_maps; map; map = map->next)
+    if (strncmp (filename, map->old_prefix, map->old_len) == 0)
+      break;
+  if (!map)
+    return filename;
+  name = filename + map->old_len;
+  name_len = strlen (name) + 1;
+  s = (char *) alloca (name_len + map->new_len);
+  memcpy (s, map->new_prefix, map->new_len);
+  memcpy (s + map->new_len, name, name_len);
+  return ggc_strdup (s);
+}
+
 /* Output assembler code for the start of a function,
    and initialize some of the variables in this file
    for the new function.  The label for the function and associated
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 02c365b4b5c6..9546ff9c703e 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -655,21 +655,27 @@ proper position among the other output files.  */
 #define LINKER_NAME "collect2"
 #endif
 
+#ifdef HAVE_AS_DEBUG_PREFIX_MAP
+#define ASM_MAP " %{fdebug-prefix-map=*:--debug-prefix-map %*}"
+#else
+#define ASM_MAP ""
+#endif
+
 /* Define ASM_DEBUG_SPEC to be a spec suitable for translating '-g'
    to the assembler.  */
 #ifndef ASM_DEBUG_SPEC
 # if defined(DBX_DEBUGGING_INFO) && defined(DWARF2_DEBUGGING_INFO) \
      && defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
-#  define ASM_DEBUG_SPEC					\
-      (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG			\
-       ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}"	\
-       : "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}")
+#  define ASM_DEBUG_SPEC						\
+      (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG				\
+       ? "%{gdwarf-2*:--gdwarf2}%{!gdwarf-2*:%{g*:--gstabs}}" ASM_MAP	\
+       : "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}" ASM_MAP)
 # else
 #  if defined(DBX_DEBUGGING_INFO) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
-#   define ASM_DEBUG_SPEC "%{g*:--gstabs}"
+#   define ASM_DEBUG_SPEC "%{g*:--gstabs}" ASM_MAP
 #  endif
 #  if defined(DWARF2_DEBUGGING_INFO) && defined(HAVE_AS_GDWARF2_DEBUG_FLAG)
-#   define ASM_DEBUG_SPEC "%{g*:--gdwarf2}"
+#   define ASM_DEBUG_SPEC "%{g*:--gdwarf2}" ASM_MAP
 #  endif
 # endif
 #endif
diff --git a/gcc/opts.c b/gcc/opts.c
index 21491fa4f598..dc5a26d24830 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -40,6 +40,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "target.h"
 #include "tree-pass.h"
 #include "dbgcnt.h"
+#include "debug.h"
 
 /* Value of the -G xx switch, and whether it was passed or not.  */
 unsigned HOST_WIDE_INT g_switch_value;
@@ -1531,6 +1532,10 @@ common_handle_option (size_t scode, const char *arg, int value,
       dbg_cnt_list_all_counters ();
       break;
 
+    case OPT_fdebug_prefix_map_:
+      add_debug_prefix_map (arg);
+      break;
+
     case OPT_fdiagnostics_show_location_:
       if (!strcmp (arg, "once"))
 	diagnostic_prefixing_rule (global_dc) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 288866d13933..440b4474e92a 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -694,6 +694,8 @@ output_file_directive (FILE *asm_file, const char *input_name)
 
   if (input_name == NULL)
     input_name = "<stdin>";
+  else
+    input_name = remap_debug_filename (input_name);
 
   len = strlen (input_name);
   na = input_name + len;
diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c
index 768e90d24121..e865eb14297d 100644
--- a/gcc/vmsdbgout.c
+++ b/gcc/vmsdbgout.c
@@ -1150,7 +1150,8 @@ write_srccorr (int fileid, dst_file_info_entry file_info_entry,
     (src_command.dst_a_src_cmd_fields.dst_a_src_decl_src.dst_b_src_df_filename,
      "source_corr (filename length)", dosizeonly);
 
-  totsize += write_debug_string (file_info_entry.file_name,
+  totsize += write_debug_string (remap_debug_filename (
+				    file_info_entry.file_name),
 				 "source file name", dosizeonly);
   totsize += write_debug_data1 (src_cmdtrlr.dst_b_src_df_libmodname,
 				"source_corr (libmodname)", dosizeonly);
diff --git a/gcc/xcoffout.c b/gcc/xcoffout.c
index 4bf29a0a582d..d1dc5a3a4dbd 100644
--- a/gcc/xcoffout.c
+++ b/gcc/xcoffout.c
@@ -300,7 +300,8 @@ xcoffout_source_file (FILE *file, const char *filename, int inline_p)
       if (xcoff_current_include_file)
 	{
 	  fprintf (file, "\t.ei\t");
-	  output_quoted_string (file, xcoff_current_include_file);
+	  output_quoted_string (file,
+	      remap_debug_filename (xcoff_current_include_file));
 	  fprintf (file, "\n");
 	  xcoff_current_include_file = NULL;
 	}
@@ -308,7 +309,7 @@ xcoffout_source_file (FILE *file, const char *filename, int inline_p)
       if (strcmp (main_input_filename, filename) || inline_p)
 	{
 	  fprintf (file, "\t.bi\t");
-	  output_quoted_string (file, filename);
+	  output_quoted_string (file, remap_debug_filename (filename));
 	  fprintf (file, "\n");
 	  xcoff_current_include_file = filename;
 	}