diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index 3d524c9..795dd4c 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -34,6 +34,7 @@
 #include "breakpoint.h"
 #include "auxv.h"
 #include "xml-syscall.h"
+#include "objfiles.h"
 
 #include "arm-tdep.h"
 #include "arm-linux-tdep.h"
@@ -1351,6 +1352,69 @@ arm_linux_syscall_record (struct regcache *regcache, unsigned long svc_number)
   return 0;
 }
 
+/* This is used to skip the arm entry points in thumb shared library.
+   GNU ld adds the stub for the armv4t thumb shared library.  If we call
+   'foo' from a shared library, 'foo' becomes the stub and '__real_foo' is
+   the real function.
+
+   0x75c <__real_foo>: foo function
+
+   0x7b4 <foo>:   ldr     r12, [pc, #4]   ; 0x7c0 <pendfunc1+12>
+   0x7b8 <foo+4>: add     r12, r12, pc
+   0x7bc <foo+8>: bx      r12             ; branch to __real_foo.
+
+   When ADDR is foo's address, this function is to adjust the address to
+   __real_foo's, the address of the function foo.  */
+
+static CORE_ADDR
+arm_linux_skip_armv4t_thumb_shlib_stub (struct gdbarch *gdbarch,
+					CORE_ADDR addr)
+{
+  struct bound_minimal_symbol msym = lookup_minimal_symbol_by_pc (addr);
+
+  if (msym.minsym != NULL
+      && BMSYMBOL_VALUE_ADDRESS (msym) == addr
+      && MSYMBOL_LINKAGE_NAME (msym.minsym) != NULL)
+    {
+      const char *name = MSYMBOL_LINKAGE_NAME (msym.minsym);
+      char *real = xmalloc (strlen (name) + sizeof "__real_");
+
+      strcpy (real, "__real_");
+      strcpy (real + sizeof "__real_" - 1, name);
+
+      /* Look for __real_foo within the same objfile.  */
+      msym = lookup_minimal_symbol (real, NULL, msym.objfile);
+
+      xfree (real);
+      if (msym.minsym != NULL)
+	{
+	  int i;
+	  static const unsigned int stub_code[] =
+	  {
+	    0xe59fc004,	/* ldr     r12, [pc, #4] */
+	    0xe08cc00f,	/* add     r12, r12, pc  */
+	    0xe12fff1c,	/* bx      r12           */
+	    0
+	  };
+
+	  for (i = 0; stub_code[i] != 0; i++)
+	    {
+	      unsigned int insn;
+	      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+
+	      insn = read_memory_integer (addr + (i * 4), 4, byte_order);
+	      if (insn != stub_code[i])
+		return addr;
+	    }
+
+	  /* Return the address of __real_foo if it is found.  */
+	  return BMSYMBOL_VALUE_ADDRESS (msym);
+	}
+    }
+
+  return addr;
+}
+
 /* Implement the skip_trampoline_code gdbarch method.  */
 
 static CORE_ADDR
@@ -1364,6 +1428,16 @@ arm_linux_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
   return find_solib_trampoline_target (frame, pc);
 }
 
+/* Implement the convert_from_func_ptr_addr gdbarch method.  */
+
+static CORE_ADDR
+arm_linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch,
+				      CORE_ADDR addr,
+				      struct target_ops *targ)
+{
+  return arm_linux_skip_armv4t_thumb_shlib_stub (gdbarch, addr);
+}
+
 static void
 arm_linux_init_abi (struct gdbarch_info info,
 		    struct gdbarch *gdbarch)
@@ -1431,6 +1505,8 @@ arm_linux_init_abi (struct gdbarch_info info,
   /* Shared library handling.  */
   set_gdbarch_skip_trampoline_code (gdbarch, arm_linux_skip_trampoline_code);
   set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
+  set_gdbarch_convert_from_func_ptr_addr
+    (gdbarch, arm_linux_convert_from_func_ptr_addr);
 
   /* Enable TLS support.  */
   set_gdbarch_fetch_tls_load_module_address (gdbarch,
diff --git a/gdb/testsuite/gdb.base/solib-weak.exp b/gdb/testsuite/gdb.base/solib-weak.exp
index 27f07e7..63144f5 100644
--- a/gdb/testsuite/gdb.base/solib-weak.exp
+++ b/gdb/testsuite/gdb.base/solib-weak.exp
@@ -100,7 +100,31 @@ proc do_test { lib1opts lib2opts lib1first } {
 
     gdb_breakpoint "bar"
 
-    gdb_test "continue" "Breakpoint .* \\.?bar .*${expected_file}\\..*" \
+    set pattern "\\.?bar"
+
+    global gdb_prompt hex
+    set test "p __real_bar"
+    # Test symbol __real_bar exists or not.
+    gdb_test_multiple $test $test {
+	-re "<text variable, no debug info>.*$gdb_prompt $" {
+	    # If the first appeared library doesn't have debug info,
+	    # the minimal symbol is used.  The address is resolved
+	    # to __real_bar.
+	    if {$lib1first} {
+		if {$lib1opts == ""} {
+		    set pattern "__real_bar"
+		}
+	    } else {
+		if {$lib2opts == ""} {
+		    set pattern "__real_bar"
+		}
+	    }
+	}
+	-re "$gdb_prompt $" {
+	}
+    }
+
+    gdb_test "continue" "Breakpoint .* $pattern .*${expected_file}\\..*" \
 	"run to breakpoint - $testopts"
 }
 
