Index: gcc/config/aarch64/aarch64.h
===================================================================
--- gcc/config/aarch64/aarch64.h	(revision 198662)
+++ gcc/config/aarch64/aarch64.h	(working copy)
@@ -760,9 +760,23 @@
 #define PRINT_OPERAND_ADDRESS(STREAM, X) \
   aarch64_print_operand_address (STREAM, X)
 
-#define FUNCTION_PROFILER(STREAM, LABELNO) \
-  aarch64_function_profiler (STREAM, LABELNO)
+#define MCOUNT_NAME "_mcount"
 
+#define NO_PROFILE_COUNTERS 1
+
+/* Emit rtl for profiling.
+   Output assembler code to FILE to call "_mcount"
+   for profiling a function entry. */
+#define PROFILE_HOOK(LABEL)                         \
+{                                                   \
+  rtx fun;                                          \
+  fun = gen_rtx_SYMBOL_REF (Pmode, MCOUNT_NAME);    \
+  emit_library_call (fun, LCT_NORMAL, VOIDmode, 0); \
+}                                                   \
+
+/* All the work done in PROFILE_HOOK, but still required. */
+#define FUNCTION_PROFILER(FILE, LABELNO) do { } while (0)
+
 /* For some reason, the Linux headers think they know how to define
    these macros.  They don't!!!  */
 #undef ASM_APP_ON
Index: gcc/config/aarch64/aarch64.c
===================================================================
--- gcc/config/aarch64/aarch64.c	(revision 198662)
+++ gcc/config/aarch64/aarch64.c	(working copy)
@@ -1485,6 +1485,12 @@
   if (cfun->calls_alloca)
     return true;
 
+  /* If function is compiled for profiling via -pg, we need to
+     use the frame pointer to access the return address by going back
+     to the frame of the caller. */
+  if (crtl->profile)
+    return true;
+
   /* We may have turned flag_omit_frame_pointer on in order to have this
      function called; if we did, we also set the 'faked_omit_frame_pointer' flag
      and we'll check it here.
@@ -3646,13 +3652,6 @@
   output_addr_const (f, x);
 }
 
-void
-aarch64_function_profiler (FILE *f ATTRIBUTE_UNUSED,
-			   int labelno ATTRIBUTE_UNUSED)
-{
-  sorry ("function profiling");
-}
-
 bool
 aarch64_label_mentioned_p (rtx x)
 {
@@ -3937,18 +3936,25 @@
 }
 
 
-/* Implement RETURN_ADDR_RTX.  We do not support moving back to a
-   previous frame.  */
-
+/* Implement RETURN_ADDR_RTX.  As per Aarch64 ABI return address
+   is stored at an offset 8 from the frame pointer of a function. */
 rtx
-aarch64_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
+aarch64_return_addr (int count, rtx frame)
 {
-  if (count != 0)
-    return const0_rtx;
-  return get_hard_reg_initial_val (Pmode, LR_REGNUM);
+  if(count != 0)
+    {
+	rtx mem_lr;
+
+	mem_lr =  gen_frame_mem (DImode,
+				 plus_constant (Pmode,
+				 		frame,
+				 		UNITS_PER_WORD));
+	return mem_lr;
+   }
+  else
+    return get_hard_reg_initial_val (Pmode, LR_REGNUM);
 }
 
-
 static void
 aarch64_asm_trampoline_template (FILE *f)
 {
Index: gcc/testsuite/lib/target-supports.exp
===================================================================
--- gcc/testsuite/lib/target-supports.exp	(revision 198662)
+++ gcc/testsuite/lib/target-supports.exp	(working copy)
@@ -487,11 +487,10 @@
 	return 0
     }
 
-    # We don't yet support profiling for AArch64.
-    if { [istarget aarch64*-*-*]
-	 && ([lindex $test_what 1] == "-p"
-	     || [lindex $test_what 1] == "-pg") } {
-	return 0
+    # We support profiling for AArch64 linux target.
+    if { [istarget aarch64*-linux-*]
+	 && ($test_what == "-p" || $test_what == "-pg") } {
+	return 1
     }
 
     # cygwin does not support -p.
