diff --git a/contrib/oid2name/oid2name.c b/contrib/oid2name/oid2name.c
index a666731e727b3faf5d27f98045494fc00533566d..d8ed06f42020dd31c08883be21f2ab3d9a846957 100644
--- a/contrib/oid2name/oid2name.c
+++ b/contrib/oid2name/oid2name.c
@@ -50,9 +50,6 @@ struct options
 /* function prototypes */
 static void help(const char *progname);
 void		get_opts(int, char **, struct options *);
-void	   *pg_malloc(size_t size);
-void	   *pg_realloc(void *ptr, size_t size);
-char	   *pg_strdup(const char *str);
 void		add_one_elt(char *eltname, eary *eary);
 char	   *get_comma_elts(eary *eary);
 PGconn	   *sql_conn(struct options *);
@@ -201,53 +198,6 @@ help(const char *progname)
 		   progname, progname);
 }
 
-void *
-pg_malloc(size_t size)
-{
-	void	   *ptr;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	ptr = malloc(size);
-	if (!ptr)
-	{
-		fprintf(stderr, "out of memory\n");
-		exit(1);
-	}
-	return ptr;
-}
-
-void *
-pg_realloc(void *ptr, size_t size)
-{
-	void	   *result;
-
-	/* Avoid unportable behavior of realloc(NULL, 0) */
-	if (ptr == NULL && size == 0)
-		size = 1;
-	result = realloc(ptr, size);
-	if (!result)
-	{
-		fprintf(stderr, "out of memory\n");
-		exit(1);
-	}
-	return result;
-}
-
-char *
-pg_strdup(const char *str)
-{
-	char	   *result = strdup(str);
-
-	if (!result)
-	{
-		fprintf(stderr, "out of memory\n");
-		exit(1);
-	}
-	return result;
-}
-
 /*
  * add_one_elt
  *
diff --git a/contrib/pg_upgrade/check.c b/contrib/pg_upgrade/check.c
index 818864346ea416a648e5f0a330320b7357d87d50..a7d4a68ce3caa1fa761cc33d79edce88b604f622 100644
--- a/contrib/pg_upgrade/check.c
+++ b/contrib/pg_upgrade/check.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/check.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/controldata.c b/contrib/pg_upgrade/controldata.c
index 01c66776e44fab9b02dd7b5b27fb5e1603ba6000..0d9a64c967f5ff95bd93af79f3891678aef68e26 100644
--- a/contrib/pg_upgrade/controldata.c
+++ b/contrib/pg_upgrade/controldata.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/controldata.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/dump.c b/contrib/pg_upgrade/dump.c
index 9c6c2773bb88af821bffb845fb52e64f4adab425..66d4846eae583b1deaee9e44a43f1cbd7705daa1 100644
--- a/contrib/pg_upgrade/dump.c
+++ b/contrib/pg_upgrade/dump.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/dump.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/exec.c b/contrib/pg_upgrade/exec.c
index 44dafc36a9159933a9fc034d755c3f81d42fd87c..af752a66d0067428a956fcee39e4952f82335d7a 100644
--- a/contrib/pg_upgrade/exec.c
+++ b/contrib/pg_upgrade/exec.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/exec.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/file.c b/contrib/pg_upgrade/file.c
index f76dcb668250bfa0a4a0ae5c86311b24a4e99f41..62e8deb69b503bf5a86bd09504dd168495a4adfd 100644
--- a/contrib/pg_upgrade/file.c
+++ b/contrib/pg_upgrade/file.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/file.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/function.c b/contrib/pg_upgrade/function.c
index 7bb5f915f62ddf3b5c0bd4a54818841be58e48ae..b24e43eebad71afe7a673a5c807066621d8b3197 100644
--- a/contrib/pg_upgrade/function.c
+++ b/contrib/pg_upgrade/function.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/function.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/info.c b/contrib/pg_upgrade/info.c
index 7fd4584dff073888a2f692d67b7dc8a82c779b96..1905c4399d9022ccc598264c267865e111237500 100644
--- a/contrib/pg_upgrade/info.c
+++ b/contrib/pg_upgrade/info.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/info.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/option.c b/contrib/pg_upgrade/option.c
index d5d94c70970048e5b4640369ffd264795f0c7806..aee8d3d15374ed15ec45a1aa93d3ec5f862d0f85 100644
--- a/contrib/pg_upgrade/option.c
+++ b/contrib/pg_upgrade/option.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/option.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "miscadmin.h"
 
diff --git a/contrib/pg_upgrade/page.c b/contrib/pg_upgrade/page.c
index d11d227fa930fd9d958311e2cc7f688606220d78..fb044d1b62c9f603c8d9b83d232bde2d34aca047 100644
--- a/contrib/pg_upgrade/page.c
+++ b/contrib/pg_upgrade/page.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/page.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/parallel.c b/contrib/pg_upgrade/parallel.c
index d157511781ea49f705abc7384877cd1e10bf1489..688a53112c2f8a884282fab5ef46bbf62aec94f6 100644
--- a/contrib/pg_upgrade/parallel.c
+++ b/contrib/pg_upgrade/parallel.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/parallel.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/pg_upgrade.c b/contrib/pg_upgrade/pg_upgrade.c
index 55155d22e287ed2c79b544feaae6b3993e8b71d8..3089a72fe52998c52082fbb2f5dfa40c3cdffc0e 100644
--- a/contrib/pg_upgrade/pg_upgrade.c
+++ b/contrib/pg_upgrade/pg_upgrade.c
@@ -35,7 +35,7 @@
 
 
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/pg_upgrade.h b/contrib/pg_upgrade/pg_upgrade.h
index 69b9c6030b71fe1cb6810c6db84669bd4b69e6af..c110e45c3602a59bb00e37001bb754c477f02989 100644
--- a/contrib/pg_upgrade/pg_upgrade.h
+++ b/contrib/pg_upgrade/pg_upgrade.h
@@ -451,10 +451,6 @@ void
 prep_status(const char *fmt,...)
 __attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
 void		check_ok(void);
-char	   *pg_strdup(const char *s);
-void	   *pg_malloc(size_t size);
-void	   *pg_realloc(void *ptr, size_t size);
-void		pg_free(void *ptr);
 const char *getErrorText(int errNum);
 unsigned int str2uint(const char *str);
 void		pg_putenv(const char *var, const char *val);
diff --git a/contrib/pg_upgrade/relfilenode.c b/contrib/pg_upgrade/relfilenode.c
index 552f2033c2f139574650fe860b06a0979f3b83f1..56c702e258162bb6e6c7fc9b3004f7dcae0f0b74 100644
--- a/contrib/pg_upgrade/relfilenode.c
+++ b/contrib/pg_upgrade/relfilenode.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/relfilenode.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/server.c b/contrib/pg_upgrade/server.c
index d1a3f76eff377a8ce51d3d05666bf3fd48420882..ed6775935bc0e743e86d3e648a82bb98a5253643 100644
--- a/contrib/pg_upgrade/server.c
+++ b/contrib/pg_upgrade/server.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/server.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/tablespace.c b/contrib/pg_upgrade/tablespace.c
index 321738dabc7764cd313597b4d0ff9b61c01e85e9..805e402d4a7f10197160f101baaf533c00e12272 100644
--- a/contrib/pg_upgrade/tablespace.c
+++ b/contrib/pg_upgrade/tablespace.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/tablespace.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/util.c b/contrib/pg_upgrade/util.c
index c91003a46db363a1267366d9e8530bb95ad73a88..4e51ed72e9837071cc2d0800a875687d8983db83 100644
--- a/contrib/pg_upgrade/util.c
+++ b/contrib/pg_upgrade/util.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/util.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
@@ -213,55 +213,6 @@ get_user_info(char **user_name)
 }
 
 
-void *
-pg_malloc(size_t size)
-{
-	void	   *p;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	p = malloc(size);
-	if (p == NULL)
-		pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
-	return p;
-}
-
-void *
-pg_realloc(void *ptr, size_t size)
-{
-	void	   *p;
-
-	/* Avoid unportable behavior of realloc(NULL, 0) */
-	if (ptr == NULL && size == 0)
-		size = 1;
-	p = realloc(ptr, size);
-	if (p == NULL)
-		pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
-	return p;
-}
-
-
-void
-pg_free(void *ptr)
-{
-	if (ptr != NULL)
-		free(ptr);
-}
-
-
-char *
-pg_strdup(const char *s)
-{
-	char	   *result = strdup(s);
-
-	if (result == NULL)
-		pg_log(PG_FATAL, "%s: out of memory\n", os_info.progname);
-
-	return result;
-}
-
-
 /*
  * getErrorText()
  *
diff --git a/contrib/pg_upgrade/version.c b/contrib/pg_upgrade/version.c
index 80383cd1a627c11bcb3c068ba681b5d4bd75b582..5fe7ec45202a8167b26e149802e9a4ddb1f1e123 100644
--- a/contrib/pg_upgrade/version.c
+++ b/contrib/pg_upgrade/version.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/version.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pg_upgrade/version_old_8_3.c b/contrib/pg_upgrade/version_old_8_3.c
index a224be1ab8fd1003e9b8271167c2ae32e3379b43..4551d68ba48d9b9330c22da1f27fad948663fb7c 100644
--- a/contrib/pg_upgrade/version_old_8_3.c
+++ b/contrib/pg_upgrade/version_old_8_3.c
@@ -7,7 +7,7 @@
  *	contrib/pg_upgrade/version_old_8_3.c
  */
 
-#include "postgres.h"
+#include "postgres_fe.h"
 
 #include "pg_upgrade.h"
 
diff --git a/contrib/pgbench/pgbench.c b/contrib/pgbench/pgbench.c
index 11c006209facf2aad8ec6c9e946243a7f7e35883..d5f8f73190d116857dec5233a027ca8d9420661b 100644
--- a/contrib/pgbench/pgbench.c
+++ b/contrib/pgbench/pgbench.c
@@ -320,59 +320,6 @@ static char *select_only = {
 static void setalarm(int seconds);
 static void *threadRun(void *arg);
 
-
-/*
- * routines to check mem allocations and fail noisily.
- */
-static void *
-pg_malloc(size_t size)
-{
-	void	   *result;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	result = malloc(size);
-	if (!result)
-	{
-		fprintf(stderr, "out of memory\n");
-		exit(1);
-	}
-	return result;
-}
-
-static void *
-pg_realloc(void *ptr, size_t size)
-{
-	void	   *result;
-
-	/* Avoid unportable behavior of realloc(NULL, 0) */
-	if (ptr == NULL && size == 0)
-		size = 1;
-	result = realloc(ptr, size);
-	if (!result)
-	{
-		fprintf(stderr, "out of memory\n");
-		exit(1);
-	}
-	return result;
-}
-
-static char *
-pg_strdup(const char *s)
-{
-	char	   *result;
-
-	result = strdup(s);
-	if (!result)
-	{
-		fprintf(stderr, "out of memory\n");
-		exit(1);
-	}
-	return result;
-}
-
-
 static void
 usage(void)
 {
diff --git a/src/Makefile b/src/Makefile
index a0460342e8adb005aa8ee5018c0ee72cdf9ab95f..e859826dc4fd66888f3f0f49e01f4d48ce4bd68b 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -13,6 +13,7 @@ top_builddir = ..
 include Makefile.global
 
 SUBDIRS = \
+	common \
 	port \
 	timezone \
 	backend \
diff --git a/src/Makefile.global.in b/src/Makefile.global.in
index ecfb80147f5cea58a69761299c5a1fb560de6ebd..1077e0b98ab6a07524b7ec9cbb9b56b6104965d1 100644
--- a/src/Makefile.global.in
+++ b/src/Makefile.global.in
@@ -243,14 +243,15 @@ LD = @LD@
 with_gnu_ld = @with_gnu_ld@
 ld_R_works = @ld_R_works@
 
-# We want -L for libpgport.a to be first in LDFLAGS.  We also need LDFLAGS
-# to be a "recursively expanded" variable, else adjustments to rpathdir
-# don't work right.  So we must NOT do LDFLAGS := something, meaning this has
-# to be done first and elsewhere we must only do LDFLAGS += something.
+# We want -L for libpgport.a and libpgcommon.a to be first in LDFLAGS.  We
+# also need LDFLAGS to be a "recursively expanded" variable, else adjustments
+# to rpathdir don't work right.  So we must NOT do LDFLAGS := something,
+# meaning this has to be done first and elsewhere we must only do LDFLAGS +=
+# something.
 ifdef PGXS
   LDFLAGS = -L$(libdir)
 else
-  LDFLAGS = -L$(top_builddir)/src/port
+  LDFLAGS = -L$(top_builddir)/src/port -L$(top_builddir)/src/common
 endif
 LDFLAGS += @LDFLAGS@
 
@@ -400,16 +401,17 @@ endif
 libpq = -L$(libpq_builddir) -lpq
 
 # This macro is for use by client executables (not libraries) that use libpq.
-# We force clients to pull symbols from the non-shared library libpgport
-# rather than pulling some libpgport symbols from libpq just because
-# libpq uses those functions too.  This makes applications less
+# We force clients to pull symbols from the non-shared libraries libpgport
+# and libpgcommon rather than pulling some libpgport symbols from libpq just
+# because libpq uses those functions too.  This makes applications less
 # dependent on changes in libpq's usage of pgport.  To do this we link to
 # pgport before libpq.  This does cause duplicate -lpgport's to appear
 # on client link lines.
 ifdef PGXS
-libpq_pgport = -L$(libdir) -lpgport $(libpq)
+libpq_pgport = -L$(libdir) -lpgport -lpgcommon $(libpq)
 else
-libpq_pgport = -L$(top_builddir)/src/port -lpgport $(libpq)
+libpq_pgport = -L$(top_builddir)/src/port -lpgport \
+			   -L$(top_builddir)/src/common -lpgcommon $(libpq)
 endif
 
 
@@ -418,6 +420,7 @@ submake-libpq:
 
 submake-libpgport:
 	$(MAKE) -C $(top_builddir)/src/port all
+	$(MAKE) -C $(top_builddir)/src/common all
 
 .PHONY: submake-libpq submake-libpgport
 
@@ -496,7 +499,7 @@ endif
 
 LIBOBJS = @LIBOBJS@
 
-LIBS := -lpgport $(LIBS)
+LIBS := -lpgport -lpgcommon $(LIBS)
 
 # to make ws2_32.lib the last library, and always link with shfolder,
 # so SHGetFolderName isn't picked up from shell32.dll
diff --git a/src/backend/storage/file/copydir.c b/src/backend/storage/file/copydir.c
index 017f862dc05b93c6709e8d81b7d19301e979e2c8..391359cdd92bf502120318487f8d5bdfb805b0b5 100644
--- a/src/backend/storage/file/copydir.c
+++ b/src/backend/storage/file/copydir.c
@@ -26,17 +26,6 @@
 #include "storage/fd.h"
 #include "miscadmin.h"
 
-/*
- *	On Windows, call non-macro versions of palloc; we can't reference
- *	CurrentMemoryContext in this file because of PGDLLIMPORT conflict.
- */
-#if defined(WIN32) || defined(__CYGWIN__)
-#undef palloc
-#undef pstrdup
-#define palloc(sz)		pgport_palloc(sz)
-#define pstrdup(str)	pgport_pstrdup(str)
-#endif
-
 
 static void fsync_fname(char *fname, bool isdir);
 
diff --git a/src/backend/utils/mmgr/mcxt.c b/src/backend/utils/mmgr/mcxt.c
index d71f206dee4f7f89548b64455f45fba2f7be8a24..8dd3cf488964afaa3801b7b64c4b1ac1f9fa1157 100644
--- a/src/backend/utils/mmgr/mcxt.c
+++ b/src/backend/utils/mmgr/mcxt.c
@@ -634,6 +634,42 @@ MemoryContextAllocZeroAligned(MemoryContext context, Size size)
 	return ret;
 }
 
+void *
+palloc(Size size)
+{
+	/* duplicates MemoryContextAlloc to avoid increased overhead */
+	AssertArg(MemoryContextIsValid(CurrentMemoryContext));
+
+	if (!AllocSizeIsValid(size))
+		elog(ERROR, "invalid memory alloc request size %lu",
+			 (unsigned long) size);
+
+	CurrentMemoryContext->isReset = false;
+
+	return (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
+}
+
+void *
+palloc0(Size size)
+{
+	/* duplicates MemoryContextAllocZero to avoid increased overhead */
+	void	   *ret;
+
+	AssertArg(MemoryContextIsValid(CurrentMemoryContext));
+
+	if (!AllocSizeIsValid(size))
+		elog(ERROR, "invalid memory alloc request size %lu",
+			 (unsigned long) size);
+
+	CurrentMemoryContext->isReset = false;
+
+	ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
+
+	MemSetAligned(ret, 0, size);
+
+	return ret;
+}
+
 /*
  * pfree
  *		Release an allocated chunk.
@@ -715,6 +751,12 @@ MemoryContextStrdup(MemoryContext context, const char *string)
 	return nstr;
 }
 
+char *
+pstrdup(const char *in)
+{
+	return MemoryContextStrdup(CurrentMemoryContext, in);
+}
+
 /*
  * pnstrdup
  *		Like pstrdup(), but append null byte to a
@@ -729,39 +771,3 @@ pnstrdup(const char *in, Size len)
 	out[len] = '\0';
 	return out;
 }
-
-
-#if defined(WIN32) || defined(__CYGWIN__)
-/*
- *	Memory support routines for libpgport on Win32
- *
- *	Win32 can't load a library that PGDLLIMPORTs a variable
- *	if the link object files also PGDLLIMPORT the same variable.
- *	For this reason, libpgport can't reference CurrentMemoryContext
- *	in the palloc macro calls.
- *
- *	To fix this, we create several functions here that allow us to
- *	manage memory without doing the inline in libpgport.
- */
-void *
-pgport_palloc(Size sz)
-{
-	return palloc(sz);
-}
-
-
-char *
-pgport_pstrdup(const char *str)
-{
-	return pstrdup(str);
-}
-
-
-/* Doesn't reference a PGDLLIMPORT variable, but here for completeness. */
-void
-pgport_pfree(void *pointer)
-{
-	pfree(pointer);
-}
-
-#endif
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index b75d9768561ed25a6620cd02060c989cb158f9b8..2ea3f6ed02bebb7d2040fd7769b0db52b23f98fa 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -200,8 +200,6 @@ const char *subdirs[] = {
 static char bin_path[MAXPGPATH];
 static char backend_exec[MAXPGPATH];
 
-static void *pg_malloc(size_t size);
-static char *pg_strdup(const char *s);
 static char **replace_token(char **lines,
 			  const char *token, const char *replacement);
 
@@ -317,43 +315,6 @@ do { \
 #define DIR_SEP "\\"
 #endif
 
-/*
- * routines to check mem allocations and fail noisily.
- *
- * Note that we can't call exit_nicely() on a memory failure, as it calls
- * rmtree() which needs memory allocation. So we just exit with a bang.
- */
-static void *
-pg_malloc(size_t size)
-{
-	void	   *result;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	result = malloc(size);
-	if (!result)
-	{
-		fprintf(stderr, _("%s: out of memory\n"), progname);
-		exit(1);
-	}
-	return result;
-}
-
-static char *
-pg_strdup(const char *s)
-{
-	char	   *result;
-
-	result = strdup(s);
-	if (!result)
-	{
-		fprintf(stderr, _("%s: out of memory\n"), progname);
-		exit(1);
-	}
-	return result;
-}
-
 static char *
 escape_quotes(const char *src)
 {
diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c
index 71abbfa9de9a9afa7df192b468562f68e96e4a42..8a43c4bad1dd3a33230634132a8abec4e746afa2 100644
--- a/src/bin/pg_basebackup/streamutil.c
+++ b/src/bin/pg_basebackup/streamutil.c
@@ -25,43 +25,6 @@ int			dbgetpassword = 0;	/* 0=auto, -1=never, 1=always */
 static char *dbpassword = NULL;
 PGconn	   *conn = NULL;
 
-/*
- * strdup() and malloc() replacements that print an error and exit
- * if something goes wrong. Can never return NULL.
- */
-char *
-pg_strdup(const char *s)
-{
-	char	   *result;
-
-	result = strdup(s);
-	if (!result)
-	{
-		fprintf(stderr, _("%s: out of memory\n"), progname);
-		exit(1);
-	}
-	return result;
-}
-
-void *
-pg_malloc0(size_t size)
-{
-	void	   *result;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	result = malloc(size);
-	if (!result)
-	{
-		fprintf(stderr, _("%s: out of memory\n"), progname);
-		exit(1);
-	}
-	MemSet(result, 0, size);
-	return result;
-}
-
-
 /*
  * Connect to the server. Returns a valid PGconn pointer if connected,
  * or NULL on non-permanent error. On permanent error, the function will
diff --git a/src/bin/pg_basebackup/streamutil.h b/src/bin/pg_basebackup/streamutil.h
index fdf36418616f2919e50e33b9259635810eba7ae6..4f5ff914e23fd807cfaa461f0b5905a029429a5b 100644
--- a/src/bin/pg_basebackup/streamutil.h
+++ b/src/bin/pg_basebackup/streamutil.h
@@ -15,8 +15,4 @@ extern PGconn *conn;
 	exit(code);									\
 	}
 
-
-extern char *pg_strdup(const char *s);
-extern void *pg_malloc0(size_t size);
-
 extern PGconn *GetConnection(void);
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index e086b1244cc1f3552bc9c123c7aed17982246b3b..04de977e3f93ecf201e3e445920942c9ad3048cd 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -118,8 +118,6 @@ write_stderr(const char *fmt,...)
 /* This extension allows gcc to check the format string for consistency with
    the supplied arguments. */
 __attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2)));
-static void *pg_malloc(size_t size);
-static char *pg_strdup(const char *s);
 static void do_advice(void);
 static void do_help(void);
 static void set_mode(char *modeopt);
@@ -225,42 +223,6 @@ write_stderr(const char *fmt,...)
 	va_end(ap);
 }
 
-/*
- * routines to check memory allocations and fail noisily.
- */
-
-static void *
-pg_malloc(size_t size)
-{
-	void	   *result;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	result = malloc(size);
-	if (!result)
-	{
-		write_stderr(_("%s: out of memory\n"), progname);
-		exit(1);
-	}
-	return result;
-}
-
-
-static char *
-pg_strdup(const char *s)
-{
-	char	   *result;
-
-	result = strdup(s);
-	if (!result)
-	{
-		write_stderr(_("%s: out of memory\n"), progname);
-		exit(1);
-	}
-	return result;
-}
-
 /*
  * Given an already-localized string, print it to stdout unless the
  * user has specified that no messages should be printed.
diff --git a/src/bin/pg_dump/Makefile b/src/bin/pg_dump/Makefile
index 57aea6f8130f04ab5f4cda9c1347d03f9ac6f265..a6ab39d34782f02246a60f79d7d8884b43e3d67c 100644
--- a/src/bin/pg_dump/Makefile
+++ b/src/bin/pg_dump/Makefile
@@ -20,7 +20,7 @@ override CPPFLAGS := -I$(libpq_srcdir) $(CPPFLAGS)
 
 OBJS=	pg_backup_archiver.o pg_backup_db.o pg_backup_custom.o \
 	pg_backup_null.o pg_backup_tar.o \
-	pg_backup_directory.o dumpmem.o dumputils.o compress_io.o $(WIN32RES)
+	pg_backup_directory.o dumputils.o compress_io.o $(WIN32RES)
 
 KEYWRDOBJS = keywords.o kwlookup.o
 
@@ -35,8 +35,8 @@ pg_dump: pg_dump.o common.o pg_dump_sort.o $(OBJS) $(KEYWRDOBJS) | submake-libpq
 pg_restore: pg_restore.o $(OBJS) $(KEYWRDOBJS) | submake-libpq submake-libpgport
 	$(CC) $(CFLAGS) pg_restore.o $(KEYWRDOBJS) $(OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
-pg_dumpall: pg_dumpall.o dumputils.o dumpmem.o $(KEYWRDOBJS) | submake-libpq submake-libpgport
-	$(CC) $(CFLAGS) pg_dumpall.o dumputils.o dumpmem.o $(KEYWRDOBJS) $(WIN32RES) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
+pg_dumpall: pg_dumpall.o dumputils.o $(KEYWRDOBJS) | submake-libpq submake-libpgport
+	$(CC) $(CFLAGS) pg_dumpall.o dumputils.o $(KEYWRDOBJS) $(WIN32RES) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
 
 install: all installdirs
 	$(INSTALL_PROGRAM) pg_dump$(X) '$(DESTDIR)$(bindir)'/pg_dump$(X)
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 706b9a75e3b00caf4f9fa6f216a0195c124ab17a..01739ab717c9ca1c50df9223dcb02e8a631c7dd0 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -18,8 +18,6 @@
 #include <ctype.h>
 
 #include "catalog/pg_class.h"
-#include "dumpmem.h"
-#include "dumputils.h"
 
 
 /*
diff --git a/src/bin/pg_dump/compress_io.c b/src/bin/pg_dump/compress_io.c
index aac991bd10f12cfaf5e22ffe9c8d03ad72e92d9e..768b923ae5fd73ae61956850795c1436c85852ef 100644
--- a/src/bin/pg_dump/compress_io.c
+++ b/src/bin/pg_dump/compress_io.c
@@ -53,7 +53,6 @@
  */
 
 #include "compress_io.h"
-#include "dumpmem.h"
 #include "dumputils.h"
 
 /*----------------------
diff --git a/src/bin/pg_dump/dumpmem.c b/src/bin/pg_dump/dumpmem.c
deleted file mode 100644
index d96655e7f4e74d070dbcad646869aa11220c1dfc..0000000000000000000000000000000000000000
--- a/src/bin/pg_dump/dumpmem.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * dumpmem.c
- *	  Memory allocation routines used by pg_dump, pg_dumpall, and pg_restore
- *
- * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *	  src/bin/pg_dump/dumpmem.c
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres_fe.h"
-
-#include "dumputils.h"
-#include "dumpmem.h"
-
-
-/*
- * Safer versions of some standard C library functions. If an
- * out-of-memory condition occurs, these functions will bail out via exit();
- *therefore, their return value is guaranteed to be non-NULL.
- */
-
-char *
-pg_strdup(const char *string)
-{
-	char	   *tmp;
-
-	if (!string)
-		exit_horribly(NULL, "cannot duplicate null pointer\n");
-	tmp = strdup(string);
-	if (!tmp)
-		exit_horribly(NULL, "out of memory\n");
-	return tmp;
-}
-
-void *
-pg_malloc(size_t size)
-{
-	void	   *tmp;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	tmp = malloc(size);
-	if (!tmp)
-		exit_horribly(NULL, "out of memory\n");
-	return tmp;
-}
-
-void *
-pg_malloc0(size_t size)
-{
-	void	   *tmp;
-
-	tmp = pg_malloc(size);
-	MemSet(tmp, 0, size);
-	return tmp;
-}
-
-void *
-pg_realloc(void *ptr, size_t size)
-{
-	void	   *tmp;
-
-	/* Avoid unportable behavior of realloc(NULL, 0) */
-	if (ptr == NULL && size == 0)
-		size = 1;
-	tmp = realloc(ptr, size);
-	if (!tmp)
-		exit_horribly(NULL, "out of memory\n");
-	return tmp;
-}
diff --git a/src/bin/pg_dump/dumpmem.h b/src/bin/pg_dump/dumpmem.h
deleted file mode 100644
index 0a4ab1bed37d14d27ab9c3e8c0e61d78bcd0aa60..0000000000000000000000000000000000000000
--- a/src/bin/pg_dump/dumpmem.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * dumpmem.h
- *	  Memory allocation routines used by pg_dump, pg_dumpall, and pg_restore
- *
- * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/bin/pg_dump/dumpmem.h
- *
- *-------------------------------------------------------------------------
- */
-
-#ifndef DUMPMEM_H
-#define DUMPMEM_H
-
-extern char *pg_strdup(const char *string);
-extern void *pg_malloc(size_t size);
-extern void *pg_malloc0(size_t size);
-extern void *pg_realloc(void *ptr, size_t size);
-
-#endif   /* DUMPMEM_H */
diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c
index 7ca0c60f3e50332ffdfbe3410de5bb0326f62633..0a09882f5dc44cc39347bf99fce08682a4b24b33 100644
--- a/src/bin/pg_dump/dumputils.c
+++ b/src/bin/pg_dump/dumputils.c
@@ -17,7 +17,6 @@
 #include <ctype.h>
 
 #include "dumputils.h"
-#include "dumpmem.h"
 
 #include "parser/keywords.h"
 
diff --git a/src/bin/pg_dump/nls.mk b/src/bin/pg_dump/nls.mk
index 8bf6ec9b5e8f232d9db3213c9f78401a5032ce6b..84486003d08738bac02b9802dcc51d6d41c6c8b7 100644
--- a/src/bin/pg_dump/nls.mk
+++ b/src/bin/pg_dump/nls.mk
@@ -3,7 +3,7 @@ CATALOG_NAME     = pg_dump
 AVAIL_LANGUAGES  = de es fr it ja ko pt_BR sv tr zh_CN zh_TW
 GETTEXT_FILES    = pg_backup_archiver.c pg_backup_db.c pg_backup_custom.c \
                    pg_backup_null.c pg_backup_tar.c \
-                   pg_backup_directory.c dumpmem.c dumputils.c compress_io.c \
+                   pg_backup_directory.c dumputils.c compress_io.c \
                    pg_dump.c common.c pg_dump_sort.c \
                    pg_restore.c pg_dumpall.c \
                    ../../port/exec.c
diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index a810efd3bb9c192aba7c98a9e9ca490859b498e5..1c663cd14f8d96ac3bcd59ee3d19d8282bce9b9d 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -21,7 +21,6 @@
  */
 
 #include "pg_backup_db.h"
-#include "dumpmem.h"
 #include "dumputils.h"
 
 #include <ctype.h>
diff --git a/src/bin/pg_dump/pg_backup_custom.c b/src/bin/pg_dump/pg_backup_custom.c
index c9adc6f82feb204f48990b72dc562438465e33d4..7081598baaaa63514beca620d81b8e21aa2412f1 100644
--- a/src/bin/pg_dump/pg_backup_custom.c
+++ b/src/bin/pg_dump/pg_backup_custom.c
@@ -26,7 +26,6 @@
 
 #include "compress_io.h"
 #include "dumputils.h"
-#include "dumpmem.h"
 
 /*--------
  * Routines in the format interface
diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c
index c295fc5ddd2078978f9851ff554fadc7aaad456d..21c203e8e7b903732eadb69eb75e9b71a571bcca 100644
--- a/src/bin/pg_dump/pg_backup_db.c
+++ b/src/bin/pg_dump/pg_backup_db.c
@@ -11,7 +11,6 @@
  */
 
 #include "pg_backup_db.h"
-#include "dumpmem.h"
 #include "dumputils.h"
 
 #include <unistd.h>
diff --git a/src/bin/pg_dump/pg_backup_directory.c b/src/bin/pg_dump/pg_backup_directory.c
index 2dcf7be80da5a42a651aeba05451233d15add838..5b71ebaeebc20bedc5185fc3bea0c9dd274a5863 100644
--- a/src/bin/pg_dump/pg_backup_directory.c
+++ b/src/bin/pg_dump/pg_backup_directory.c
@@ -34,7 +34,6 @@
  */
 
 #include "compress_io.h"
-#include "dumpmem.h"
 #include "dumputils.h"
 
 #include <dirent.h>
diff --git a/src/bin/pg_dump/pg_backup_null.c b/src/bin/pg_dump/pg_backup_null.c
index ba1e461af45576d86427e39cf35f52a42767ceba..6ac81982b8d852ce91e506de4b200a7ce26e4f04 100644
--- a/src/bin/pg_dump/pg_backup_null.c
+++ b/src/bin/pg_dump/pg_backup_null.c
@@ -23,7 +23,6 @@
  */
 
 #include "pg_backup_archiver.h"
-#include "dumpmem.h"
 #include "dumputils.h"
 
 #include <unistd.h>				/* for dup */
diff --git a/src/bin/pg_dump/pg_backup_tar.c b/src/bin/pg_dump/pg_backup_tar.c
index d090612d0f3772cc443058206455f6b16aa7217f..03ae4f82bcead174415d30066ddb260380724d7a 100644
--- a/src/bin/pg_dump/pg_backup_tar.c
+++ b/src/bin/pg_dump/pg_backup_tar.c
@@ -31,7 +31,6 @@
 #include "pg_backup.h"
 #include "pg_backup_archiver.h"
 #include "pg_backup_tar.h"
-#include "dumpmem.h"
 #include "dumputils.h"
 #include "pgtar.h"
 
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 9f1ef32b15867b5006b3f8132ab8a38fd1dfbc9a..43d571ca5bbe234644f2896b6a7e586b84dbc8f1 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -59,7 +59,6 @@
 
 #include "pg_backup_archiver.h"
 #include "pg_backup_db.h"
-#include "dumpmem.h"
 #include "dumputils.h"
 
 extern char *optarg;
diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c
index f828a45800c77f5504f27b51606ae54f20c55a34..955c231b1a8a8f31e414f0b7bb34d62e71961099 100644
--- a/src/bin/pg_dump/pg_dump_sort.c
+++ b/src/bin/pg_dump/pg_dump_sort.c
@@ -15,7 +15,6 @@
  */
 #include "pg_backup_archiver.h"
 #include "dumputils.h"
-#include "dumpmem.h"
 
 /* translator: this is a module name */
 static const char *modulename = gettext_noop("sorter");
diff --git a/src/bin/pg_dump/pg_dumpall.c b/src/bin/pg_dump/pg_dumpall.c
index 0662bc206958d3f3310bd14aff3f7e7170a728e7..9afbab4b07b2a180acb6d8833090657846625287 100644
--- a/src/bin/pg_dump/pg_dumpall.c
+++ b/src/bin/pg_dump/pg_dumpall.c
@@ -25,7 +25,6 @@
 #include "getopt_long.h"
 
 #include "dumputils.h"
-#include "dumpmem.h"
 #include "pg_backup.h"
 
 /* version string we expect back from pg_dump */
diff --git a/src/bin/pg_dump/pg_restore.c b/src/bin/pg_dump/pg_restore.c
index 45b8b587e410a0e1deca9bee96144f0229c92c15..5dbe98f7145766b1a5af7e3905e49172c045bea5 100644
--- a/src/bin/pg_dump/pg_restore.c
+++ b/src/bin/pg_dump/pg_restore.c
@@ -41,7 +41,6 @@
 
 #include "pg_backup_archiver.h"
 
-#include "dumpmem.h"
 #include "dumputils.h"
 
 #include <ctype.h>
diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c
index 317d8606a0bb176f71a807e8bc0effe6e1ce14a5..f075b6e9323c0736b525985acd26dfc9ae1eb954 100644
--- a/src/bin/pg_resetxlog/pg_resetxlog.c
+++ b/src/bin/pg_resetxlog/pg_resetxlog.c
@@ -54,6 +54,7 @@
 #include "access/xlog_internal.h"
 #include "catalog/catversion.h"
 #include "catalog/pg_control.h"
+#include "common/fe_memutils.h"
 
 extern int	optind;
 extern char *optarg;
@@ -420,7 +421,7 @@ ReadControlFile(void)
 	}
 
 	/* Use malloc to ensure we have a maxaligned buffer */
-	buffer = (char *) malloc(PG_CONTROL_SIZE);
+	buffer = (char *) pg_malloc(PG_CONTROL_SIZE);
 
 	len = read(fd, buffer, PG_CONTROL_SIZE);
 	if (len < 0)
@@ -942,7 +943,7 @@ WriteEmptyXLOG(void)
 	int			nbytes;
 
 	/* Use malloc() to ensure buffer is MAXALIGNED */
-	buffer = (char *) malloc(XLOG_BLCKSZ);
+	buffer = (char *) pg_malloc(XLOG_BLCKSZ);
 	page = (XLogPageHeader) buffer;
 	memset(buffer, 0, XLOG_BLCKSZ);
 
diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c
index a8aa1a2df1b430c24ee3a931c03025a78efb6b65..dd183cacc142ee06c6d0390bd5c7535cb1bc3a05 100644
--- a/src/bin/psql/common.c
+++ b/src/bin/psql/common.c
@@ -32,56 +32,6 @@ static bool ExecQueryUsingCursor(const char *query, double *elapsed_msec);
 static bool command_no_begin(const char *query);
 static bool is_select_command(const char *query);
 
-/*
- * "Safe" wrapper around strdup()
- */
-char *
-pg_strdup(const char *string)
-{
-	char	   *tmp;
-
-	if (!string)
-	{
-		psql_error("%s: pg_strdup: cannot duplicate null pointer (internal error)\n",
-				   pset.progname);
-		exit(EXIT_FAILURE);
-	}
-	tmp = strdup(string);
-	if (!tmp)
-	{
-		psql_error("out of memory\n");
-		exit(EXIT_FAILURE);
-	}
-	return tmp;
-}
-
-void *
-pg_malloc(size_t size)
-{
-	void	   *tmp;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	tmp = malloc(size);
-	if (!tmp)
-	{
-		psql_error("out of memory\n");
-		exit(EXIT_FAILURE);
-	}
-	return tmp;
-}
-
-void *
-pg_malloc0(size_t size)
-{
-	void	   *tmp;
-
-	tmp = pg_malloc(size);
-	MemSet(tmp, 0, size);
-	return tmp;
-}
-
 /*
  * setQFout
  * -- handler for -o command line option and \o command
diff --git a/src/bin/psql/common.h b/src/bin/psql/common.h
index f9f3b1f3c844d98abcbc0d4bc93e9d296a3b4c24..d8bb0930b415bb58caa158533568a50c5ba07456 100644
--- a/src/bin/psql/common.h
+++ b/src/bin/psql/common.h
@@ -14,15 +14,6 @@
 
 #define atooid(x)  ((Oid) strtoul((x), NULL, 10))
 
-/*
- * Safer versions of some standard C library functions. If an
- * out-of-memory condition occurs, these functions will bail out
- * safely; therefore, their return value is guaranteed to be non-NULL.
- */
-extern char *pg_strdup(const char *string);
-extern void *pg_malloc(size_t size);
-extern void *pg_malloc0(size_t size);
-
 extern bool setQFout(const char *fname);
 
 extern void
diff --git a/src/bin/scripts/common.c b/src/bin/scripts/common.c
index c7cc04aea4b7cc78e143d90f63f83bd779365374..03193b6fcdc78c3a7a49273008a9eec7f21aba24 100644
--- a/src/bin/scripts/common.c
+++ b/src/bin/scripts/common.c
@@ -277,55 +277,6 @@ executeMaintenanceCommand(PGconn *conn, const char *query, bool echo)
 	return r;
 }
 
-/*
- * "Safe" wrapper around strdup().	Pulled from psql/common.c
- */
-char *
-pg_strdup(const char *string)
-{
-	char	   *tmp;
-
-	if (!string)
-	{
-		fprintf(stderr, _("pg_strdup: cannot duplicate null pointer (internal error)\n"));
-		exit(EXIT_FAILURE);
-	}
-	tmp = strdup(string);
-	if (!tmp)
-	{
-		fprintf(stderr, _("out of memory\n"));
-		exit(EXIT_FAILURE);
-	}
-	return tmp;
-}
-
-void *
-pg_malloc(size_t size)
-{
-	void	   *tmp;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	tmp = malloc(size);
-	if (!tmp)
-	{
-		fprintf(stderr, _("out of memory\n"));
-		exit(EXIT_FAILURE);
-	}
-	return tmp;
-}
-
-void *
-pg_malloc0(size_t size)
-{
-	void	   *tmp;
-
-	tmp = pg_malloc(size);
-	MemSet(tmp, 0, size);
-	return tmp;
-}
-
 /*
  * Check yes/no answer in a localized way.	1=yes, 0=no, -1=neither.
  */
diff --git a/src/bin/scripts/common.h b/src/bin/scripts/common.h
index a174da79b05346c9bfe00f5c9c8c8f87192b9462..6cf490f7484588269aea2fca6be614c6de1376ac 100644
--- a/src/bin/scripts/common.h
+++ b/src/bin/scripts/common.h
@@ -50,8 +50,4 @@ extern bool yesno_prompt(const char *question);
 
 extern void setup_cancel_handler(void);
 
-extern char *pg_strdup(const char *string);
-extern void *pg_malloc(size_t size);
-extern void *pg_malloc0(size_t size);
-
 #endif   /* COMMON_H */
diff --git a/src/common/Makefile b/src/common/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..3aa6e70322f622d640d727cc8ff60dab48089540
--- /dev/null
+++ b/src/common/Makefile
@@ -0,0 +1,64 @@
+#-------------------------------------------------------------------------
+#
+# Makefile
+#    Makefile for src/common
+#
+# This makefile generates two outputs:
+#
+#	libpgcommon.a - contains object files with FRONTEND defined,
+#		for use by client application and libraries
+#
+#	libpgcommon_srv.a - contains object files without FRONTEND defined,
+#		for use only by the backend binaries
+#
+# IDENTIFICATION
+#    src/common/Makefile
+#
+#-------------------------------------------------------------------------
+
+subdir = src/common
+top_builddir = ../..
+include $(top_builddir)/src/Makefile.global
+
+override CPPFLAGS := -DFRONTEND $(CPPFLAGS)
+LIBS += $(PTHREAD_LIBS)
+
+OBJS_COMMON =
+
+OBJS_FRONTEND = $(OBJS_COMMON) fe_memutils.o
+
+OBJS_SRV = $(OBJS_COMMON:%.o=%_srv.o)
+
+all: libpgcommon.a libpgcommon_srv.a
+
+# libpgcommon is needed by some contrib
+install: all installdirs
+	$(INSTALL_STLIB) libpgcommon.a '$(DESTDIR)$(libdir)/libpgcommon.a'
+
+installdirs:
+	$(MKDIR_P) '$(DESTDIR)$(libdir)'
+
+uninstall:
+	rm -f '$(DESTDIR)$(libdir)/libpgcommon.a'
+
+libpgcommon.a: $(OBJS_FRONTEND)
+	$(AR) $(AROPT) $@ $^
+
+#
+# Server versions of object files
+#
+
+libpgcommon_srv.a: $(OBJS_SRV)
+	$(AR) $(AROPT) $@ $^
+
+# Because this uses its own compilation rule, it doesn't use the
+# dependency tracking logic from Makefile.global.  To make sure that
+# dependency tracking works anyway for the *_srv.o files, depend on
+# their *.o siblings as well, which do have proper dependencies.  It's
+# a hack that might fail someday if there is a *_srv.o without a
+# corresponding *.o, but it works for now.
+%_srv.o: %.c %.o
+	$(CC) $(CFLAGS) $(subst -DFRONTEND,, $(CPPFLAGS)) -c $< -o $@
+
+clean distclean maintainer-clean:
+	rm -f libpgcommon.a libpgcommon_srv.a $(OBJS_FRONTEND) $(OBJS_SRV)
diff --git a/src/common/fe_memutils.c b/src/common/fe_memutils.c
new file mode 100644
index 0000000000000000000000000000000000000000..7d4d99eefd53f93a8e90dff8231eafc45833d8d9
--- /dev/null
+++ b/src/common/fe_memutils.c
@@ -0,0 +1,128 @@
+/*-------------------------------------------------------------------------
+ *
+ * fe_memutils.c
+ *	  memory management support for frontend code
+ *
+ * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  src/common/fe_memutils.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef FRONTEND
+#error "This file is not expected to be compiled for backend code"
+#endif
+
+#include "postgres_fe.h"
+
+void *
+pg_malloc(size_t size)
+{
+	void	   *tmp;
+
+	/* Avoid unportable behavior of malloc(0) */
+	if (size == 0)
+		size = 1;
+	tmp = malloc(size);
+	if (!tmp)
+	{
+		fprintf(stderr, _("out of memory\n"));
+		exit(EXIT_FAILURE);
+	}
+	return tmp;
+}
+
+void *
+pg_malloc0(size_t size)
+{
+	void	   *tmp;
+
+	tmp = pg_malloc(size);
+	MemSet(tmp, 0, size);
+	return tmp;
+}
+
+void *
+pg_realloc(void *ptr, size_t size)
+{
+   void       *tmp;
+
+   /* Avoid unportable behavior of realloc(NULL, 0) */
+   if (ptr == NULL && size == 0)
+       size = 1;
+   tmp = realloc(ptr, size);
+   if (!tmp)
+   {
+		fprintf(stderr, _("out of memory\n"));
+		exit(EXIT_FAILURE);
+   }
+   return tmp;
+}
+
+/*
+ * "Safe" wrapper around strdup().
+ */
+char *
+pg_strdup(const char *string)
+{
+	char	   *tmp;
+
+	if (!string)
+	{
+		fprintf(stderr,
+				_("cannot duplicate null pointer (internal error)\n"));
+		exit(EXIT_FAILURE);
+	}
+	tmp = strdup(string);
+	if (!tmp)
+	{
+		fprintf(stderr, _("out of memory\n"));
+		exit(EXIT_FAILURE);
+	}
+	return tmp;
+}
+
+void
+pg_free(void *ptr)
+{
+	if (ptr != NULL)
+		free(ptr);
+}
+
+/*
+ * Frontend emulation of backend memory management functions.  Useful for
+ * programs that compile backend files.
+ */
+void *
+palloc(Size size)
+{
+	return pg_malloc(size);
+}
+
+void *
+palloc0(Size size)
+{
+	return pg_malloc0(size);
+}
+
+void
+pfree(void *pointer)
+{
+	pg_free(pointer);
+}
+
+char *
+pstrdup(const char *string)
+{
+	return pg_strdup(string);
+}
+
+void *
+repalloc(void *pointer, Size size)
+{
+	return pg_realloc(pointer, size);
+}
diff --git a/src/include/common/fe_memutils.h b/src/include/common/fe_memutils.h
new file mode 100644
index 0000000000000000000000000000000000000000..cefa7ecedc8c8b11788086be44aa03a1b74295f5
--- /dev/null
+++ b/src/include/common/fe_memutils.h
@@ -0,0 +1,20 @@
+/*
+ *	fe_memutils.h
+ *		memory management support for frontend code
+ *
+ *	Copyright (c) 2003-2013, PostgreSQL Global Development Group
+ *
+ *	src/include/common/fe_memutils.h
+ */
+#ifndef FE_MEMUTILS_H
+#define FE_MEMUTILS_H
+
+extern char *pg_strdup(const char *string);
+extern void *pg_malloc(size_t size);
+extern void *pg_malloc0(size_t size);
+extern void *pg_realloc(void *pointer, size_t size);
+extern void  pg_free(void *pointer);
+
+#include "utils/palloc.h"
+
+#endif   /* FE_MEMUTILS_H */
diff --git a/src/include/postgres_fe.h b/src/include/postgres_fe.h
index 0f35eccc7489fbe8e95dbf44123385e157067372..6798b4c05ce0f7ef6bf81035751eff06723e0ee4 100644
--- a/src/include/postgres_fe.h
+++ b/src/include/postgres_fe.h
@@ -24,4 +24,6 @@
 
 #include "c.h"
 
+#include "common/fe_memutils.h"
+
 #endif   /* POSTGRES_FE_H */
diff --git a/src/include/utils/palloc.h b/src/include/utils/palloc.h
index d86558e417f65250c73849c258e13a1a771bf934..7fc7ccc3b520dc0b63e6db3119fcdbbb4dd5c94d 100644
--- a/src/include/utils/palloc.h
+++ b/src/include/utils/palloc.h
@@ -28,6 +28,8 @@
 #ifndef PALLOC_H
 #define PALLOC_H
 
+#ifndef FRONTEND
+
 /*
  * Type MemoryContextData is declared in nodes/memnodes.h.	Most users
  * of memory allocation should just treat it as an abstract type, so we
@@ -49,10 +51,6 @@ extern void *MemoryContextAlloc(MemoryContext context, Size size);
 extern void *MemoryContextAllocZero(MemoryContext context, Size size);
 extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size);
 
-#define palloc(sz)	MemoryContextAlloc(CurrentMemoryContext, (sz))
-
-#define palloc0(sz) MemoryContextAllocZero(CurrentMemoryContext, (sz))
-
 /*
  * The result of palloc() is always word-aligned, so we can skip testing
  * alignment of the pointer when deciding which MemSet variant to use.
@@ -66,20 +64,11 @@ extern void *MemoryContextAllocZeroAligned(MemoryContext context, Size size);
 		MemoryContextAllocZeroAligned(CurrentMemoryContext, sz) : \
 		MemoryContextAllocZero(CurrentMemoryContext, sz) )
 
-extern void pfree(void *pointer);
-
-extern void *repalloc(void *pointer, Size size);
-
 /*
  * MemoryContextSwitchTo can't be a macro in standard C compilers.
  * But we can make it an inline function if the compiler supports it.
  * See STATIC_IF_INLINE in c.h.
- *
- * This file has to be includable by some non-backend code such as
- * pg_resetxlog, so don't expose the CurrentMemoryContext reference
- * if FRONTEND is defined.
  */
-#ifndef FRONTEND
 
 #ifndef PG_USE_INLINE
 extern MemoryContext MemoryContextSwitchTo(MemoryContext context);
@@ -94,22 +83,19 @@ MemoryContextSwitchTo(MemoryContext context)
 	return old;
 }
 #endif   /* PG_USE_INLINE || MCXT_INCLUDE_DEFINITIONS */
-#endif   /* !FRONTEND */
 
 /*
  * These are like standard strdup() except the copied string is
  * allocated in a context, not with malloc().
  */
 extern char *MemoryContextStrdup(MemoryContext context, const char *string);
+#endif /* !FRONTEND */
 
-#define pstrdup(str)  MemoryContextStrdup(CurrentMemoryContext, (str))
-
+extern char *pstrdup(const char *in);
 extern char *pnstrdup(const char *in, Size len);
-
-#if defined(WIN32) || defined(__CYGWIN__)
-extern void *pgport_palloc(Size sz);
-extern char *pgport_pstrdup(const char *str);
-extern void pgport_pfree(void *pointer);
-#endif
+extern void *palloc(Size size);
+extern void *palloc0(Size size);
+extern void pfree(void *pointer);
+extern void *repalloc(void *pointer, Size size);
 
 #endif   /* PALLOC_H */
diff --git a/src/port/dirmod.c b/src/port/dirmod.c
index e7ff1f0d27191b25c758982447228c5fc427b4df..5dd0983a2de5c2223766f4ce38e5a78c6772b4e7 100644
--- a/src/port/dirmod.c
+++ b/src/port/dirmod.c
@@ -40,80 +40,6 @@
 #endif
 #endif
 
-
-#ifndef FRONTEND
-
-/*
- *	On Windows, call non-macro versions of palloc; we can't reference
- *	CurrentMemoryContext in this file because of PGDLLIMPORT conflict.
- */
-#if defined(WIN32) || defined(__CYGWIN__)
-#undef palloc
-#undef pstrdup
-#define palloc(sz)		pgport_palloc(sz)
-#define pstrdup(str)	pgport_pstrdup(str)
-#endif
-#else							/* FRONTEND */
-
-/*
- *	In frontend, fake palloc behavior with these
- */
-#undef palloc
-#undef pstrdup
-#define palloc(sz)		fe_palloc(sz)
-#define pstrdup(str)	fe_pstrdup(str)
-#define repalloc(pointer,sz)	fe_repalloc(pointer,sz)
-#define pfree(pointer)	free(pointer)
-
-static void *
-fe_palloc(Size size)
-{
-	void	   *res;
-
-	/* Avoid unportable behavior of malloc(0) */
-	if (size == 0)
-		size = 1;
-	res = malloc(size);
-	if (res == NULL)
-	{
-		fprintf(stderr, _("out of memory\n"));
-		exit(1);
-	}
-	return res;
-}
-
-static char *
-fe_pstrdup(const char *string)
-{
-	char	   *res;
-
-	if ((res = strdup(string)) == NULL)
-	{
-		fprintf(stderr, _("out of memory\n"));
-		exit(1);
-	}
-	return res;
-}
-
-static void *
-fe_repalloc(void *pointer, Size size)
-{
-	void	   *res;
-
-	/* Avoid unportable behavior of realloc(NULL, 0) */
-	if (pointer == NULL && size == 0)
-		size = 1;
-	res = realloc(pointer, size);
-	if (res == NULL)
-	{
-		fprintf(stderr, _("out of memory\n"));
-		exit(1);
-	}
-	return res;
-}
-#endif   /* FRONTEND */
-
-
 #if defined(WIN32) || defined(__CYGWIN__)
 
 /*
diff --git a/src/tools/msvc/Install.pm b/src/tools/msvc/Install.pm
index e92354e6213d31050544f0970c7e025f40c091d0..0d0c46e18bbb6e3b78d38cf28bf7ac741163bd06 100644
--- a/src/tools/msvc/Install.pm
+++ b/src/tools/msvc/Install.pm
@@ -86,6 +86,7 @@ sub Install
 		'Import libraries',         $target . '/lib/',
 		"$conf\\",                  "postgres\\postgres.lib",
 		"libpq\\libpq.lib",         "libecpg\\libecpg.lib",
+		"libpgcommon\\libpgcommon.lib",
 		"libpgport\\libpgport.lib", "libpgtypes\\libpgtypes.lib",
 		"libecpg_compat\\libecpg_compat.lib");
 	CopySetOfFiles(
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index d587365437ce3e161718f766b971b8299c3add8f..75e7e4173f88ebd70585310d7d7f7bcd6c0cca58 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -24,6 +24,7 @@ our (@ISA, @EXPORT_OK);
 
 my $solution;
 my $libpgport;
+my $libpgcommon;
 my $postgres;
 my $libpq;
 
@@ -35,6 +36,11 @@ my @contrib_uselibpgport = (
 	'pg_standby',    'pg_archivecleanup',
 	'pg_test_fsync', 'pg_test_timing',
 	'pg_upgrade',    'vacuumlo');
+my @contrib_uselibpgcommon = (
+	'oid2name',      'pgbench',
+	'pg_standby',    'pg_archivecleanup',
+	'pg_test_fsync', 'pg_test_timing',
+	'pg_upgrade',    'vacuumlo');
 my $contrib_extralibs = { 'pgbench' => ['wsock32.lib'] };
 my $contrib_extraincludes =
   { 'tsearch2' => ['contrib/tsearch2'], 'dblink' => ['src/backend'] };
@@ -63,10 +69,19 @@ sub mkvcbuild
 	  sprompt.c tar.c thread.c getopt.c getopt_long.c dirent.c rint.c win32env.c
 	  win32error.c win32setlocale.c);
 
+	our @pgcommonfiles = qw(
+		fe_memutils.c);
+
+	our @pgcommonbkndfiles = qw();
+
 	$libpgport = $solution->AddProject('libpgport', 'lib', 'misc');
 	$libpgport->AddDefine('FRONTEND');
 	$libpgport->AddFiles('src\port', @pgportfiles);
 
+	$libpgcommon = $solution->AddProject('libpgcommon', 'lib', 'misc');
+	$libpgcommon->AddDefine('FRONTEND');
+	$libpgcommon->AddFiles('src\common', @pgcommonfiles);
+
 	$postgres = $solution->AddProject('postgres', 'exe', '', 'src\backend');
 	$postgres->AddIncludeDir('src\backend');
 	$postgres->AddDir('src\backend\port\win32');
@@ -81,6 +96,7 @@ sub mkvcbuild
 	$postgres->ReplaceFile('src\backend\port\pg_latch.c',
 		'src\backend\port\win32_latch.c');
 	$postgres->AddFiles('src\port', @pgportfiles);
+	$postgres->AddFiles('src\common', @pgcommonbkndfiles);
 	$postgres->AddDir('src\timezone');
 	$postgres->AddFiles('src\backend\parser', 'scan.l', 'gram.y');
 	$postgres->AddFiles('src\backend\bootstrap', 'bootscanner.l',
@@ -297,7 +313,7 @@ sub mkvcbuild
 	$ecpg->AddDefine('MINOR_VERSION=9');
 	$ecpg->AddDefine('PATCHLEVEL=0');
 	$ecpg->AddDefine('ECPG_COMPILE');
-	$ecpg->AddReference($libpgport);
+	$ecpg->AddReference($libpgport, $libpgcommon);
 
 	my $pgregress_ecpg =
 	  $solution->AddProject('pg_regress_ecpg', 'exe', 'misc');
@@ -307,7 +323,7 @@ sub mkvcbuild
 	$pgregress_ecpg->AddIncludeDir('src\test\regress');
 	$pgregress_ecpg->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
 	$pgregress_ecpg->AddDefine('FRONTEND');
-	$pgregress_ecpg->AddReference($libpgport);
+	$pgregress_ecpg->AddReference($libpgport, $libpgcommon);
 
 	my $isolation_tester =
 	  $solution->AddProject('isolationtester', 'exe', 'misc');
@@ -332,7 +348,7 @@ sub mkvcbuild
 	$pgregress_isolation->AddIncludeDir('src\test\regress');
 	$pgregress_isolation->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
 	$pgregress_isolation->AddDefine('FRONTEND');
-	$pgregress_isolation->AddReference($libpgport);
+	$pgregress_isolation->AddReference($libpgport, $libpgcommon);
 
 	# src/bin
 	my $initdb = AddSimpleFrontend('initdb');
@@ -393,7 +409,6 @@ sub mkvcbuild
 	$pgdumpall->AddIncludeDir('src\backend');
 	$pgdumpall->AddFile('src\bin\pg_dump\pg_dumpall.c');
 	$pgdumpall->AddFile('src\bin\pg_dump\dumputils.c');
-	$pgdumpall->AddFile('src\bin\pg_dump\dumpmem.c');
 	$pgdumpall->AddFile('src\bin\pg_dump\keywords.c');
 	$pgdumpall->AddFile('src\backend\parser\kwlookup.c');
 
@@ -407,7 +422,7 @@ sub mkvcbuild
 	my $zic = $solution->AddProject('zic', 'exe', 'utils');
 	$zic->AddFiles('src\timezone', 'zic.c', 'ialloc.c', 'scheck.c',
 		'localtime.c');
-	$zic->AddReference($libpgport);
+	$zic->AddReference($libpgport, $libpgcommon);
 
 	if ($solution->{options}->{xml})
 	{
@@ -547,7 +562,7 @@ sub mkvcbuild
 		$proj->AddIncludeDir('src\interfaces\libpq');
 		$proj->AddIncludeDir('src\bin\pg_dump');
 		$proj->AddIncludeDir('src\bin\psql');
-		$proj->AddReference($libpq, $libpgport);
+		$proj->AddReference($libpq, $libpgport, $libpgcommon);
 		$proj->AddResourceFile('src\bin\scripts', 'PostgreSQL Utility');
 	}
 
@@ -561,7 +576,7 @@ sub mkvcbuild
 	$pgregress->AddFile('src\test\regress\pg_regress_main.c');
 	$pgregress->AddIncludeDir('src\port');
 	$pgregress->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
-	$pgregress->AddReference($libpgport);
+	$pgregress->AddReference($libpgport, $libpgcommon);
 
 	$solution->Save();
 	return $solution->{vcver};
@@ -579,7 +594,7 @@ sub AddSimpleFrontend
 
 	my $p = $solution->AddProject($n, 'exe', 'bin');
 	$p->AddDir('src\bin\\' . $n);
-	$p->AddReference($libpgport);
+	$p->AddReference($libpgport, $libpgcommon);
 	if ($uselibpq)
 	{
 		$p->AddIncludeDir('src\interfaces\libpq');
@@ -730,6 +745,10 @@ sub AdjustContribProj
 	{
 		$proj->AddReference($libpgport);
 	}
+	if (grep { /^$n$/ } @contrib_uselibpgcommon)
+	{
+		$proj->AddReference($libpgcommon);
+	}
 	if ($contrib_extralibs->{$n})
 	{
 		foreach my $l (@{ $contrib_extralibs->{$n} })
diff --git a/src/tools/msvc/Project.pm b/src/tools/msvc/Project.pm
index 0a47e40942fc5efb433f4dbe43eaa3bd924e5c01..4182871e88ec9ec976c6018c62716fef63e908a3 100644
--- a/src/tools/msvc/Project.pm
+++ b/src/tools/msvc/Project.pm
@@ -225,7 +225,7 @@ sub AddDir
 
 				if ($filter eq "LIBOBJS")
 				{
-					if (grep(/$p/, @main::pgportfiles) == 1)
+					if (grep(/$p/, @main::pgportfiles, @main::pgcommonfiles) == 1)
 					{
 						$p =~ s/\.c/\.o/;
 						$matches .= $p . " ";