7c0489
commit eb447b7b4bd6177f876ba9420ad9e048c27bae91
7c0489
Author: David Kilroy <David.Kilroy@arm.com>
7c0489
Date:   Wed Feb 12 14:28:15 2020 -0300
7c0489
7c0489
    elf: Allow dlopen of filter object to work [BZ #16272]
7c0489
    
7c0489
    There are two fixes that are needed to be able to dlopen filter
7c0489
    objects. First _dl_map_object_deps cannot assume that map will be at
7c0489
    the beginning of l_searchlist.r_list[], as filtees are inserted before
7c0489
    map. Secondly dl_open_worker needs to ensure that filtees get
7c0489
    relocated.
7c0489
    
7c0489
    In _dl_map_object_deps:
7c0489
    
7c0489
    * avoiding removing relocation dependencies of map by setting
7c0489
      l_reserved to 0 and otherwise processing the rest of the search
7c0489
      list.
7c0489
    
7c0489
    * ensure that map remains at the beginning of l_initfini - the list
7c0489
      of things that need initialisation (and destruction). Do this by
7c0489
      splitting the copy up. This may not be required, but matches the
7c0489
      initialization order without dlopen.
7c0489
    
7c0489
    Modify dl_open_worker to relocate the objects in new->l_inifini.
7c0489
    new->l_initfini is constructed in _dl_map_object_deps, and lists the
7c0489
    objects that need initialization and destruction. Originally the list
7c0489
    of objects in new->l_next are relocated. All of these objects should
7c0489
    also be included in new->l_initfini (both lists are populated with
7c0489
    dependencies in _dl_map_object_deps). We can't use new->l_prev to pick
7c0489
    up filtees, as during a recursive dlopen from an interposed malloc
7c0489
    call, l->prev can contain objects that are not ready for relocation.
7c0489
    
7c0489
    Add tests to verify that symbols resolve to the filtee implementation
7c0489
    when auxiliary and filter objects are used, both as a normal link and
7c0489
    when dlopen'd.
7c0489
    
7c0489
    Tested by running the testsuite on x86_64.
7c0489
7c0489
# Conflicts:
7c0489
#	elf/Makefile
7c0489
7c0489
diff --git a/elf/Makefile b/elf/Makefile
7c0489
index a52d9b1f6a4364a7..b4b618ce62a9e6df 100644
7c0489
--- a/elf/Makefile
7c0489
+++ b/elf/Makefile
7c0489
@@ -192,7 +192,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
7c0489
 	 tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
7c0489
 	 tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
7c0489
 	 tst-sonamemove-link tst-sonamemove-dlopen tst-initfinilazyfail \
7c0489
-	 tst-dlopenfail tst-dlopenfail-2
7c0489
+	 tst-dlopenfail tst-dlopenfail-2 \
7c0489
+	 tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen
7c0489
 #	 reldep9
7c0489
 tests-internal += loadtest unload unload2 circleload1 \
7c0489
 	 neededtest neededtest2 neededtest3 neededtest4 \
7c0489
@@ -302,7 +303,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
7c0489
 		tst-sonamemove-runmod1 tst-sonamemove-runmod2 \
7c0489
 		tst-initlazyfailmod tst-finilazyfailmod \
7c0489
 		tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \
7c0489
-		tst-dlopenfailmod3
7c0489
+		tst-dlopenfailmod3 \
7c0489
+		tst-filterobj-flt tst-filterobj-aux tst-filterobj-filtee
7c0489
 
7c0489
 ifeq (yes,$(have-mtls-dialect-gnu2))
7c0489
 tests += tst-gnu2-tls1
7c0489
@@ -1626,3 +1628,15 @@ $(objpfx)tst-dlopen-nodelete-reloc-mod17.so: \
7c0489
   $(objpfx)tst-dlopen-nodelete-reloc-mod15.so \
7c0489
   $(objpfx)tst-dlopen-nodelete-reloc-mod16.so
7c0489
 LDFLAGS-tst-dlopen-nodelete-reloc-mod17.so = -Wl,--no-as-needed
7c0489
+
7c0489
+LDFLAGS-tst-filterobj-flt.so = -Wl,--filter=$(objpfx)tst-filterobj-filtee.so
7c0489
+$(objpfx)tst-filterobj: $(objpfx)tst-filterobj-flt.so
7c0489
+$(objpfx)tst-filterobj-dlopen: $(libdl)
7c0489
+$(objpfx)tst-filterobj.out: $(objpfx)tst-filterobj-filtee.so
7c0489
+$(objpfx)tst-filterobj-dlopen.out: $(objpfx)tst-filterobj-filtee.so
7c0489
+
7c0489
+LDFLAGS-tst-filterobj-aux.so = -Wl,--auxiliary=$(objpfx)tst-filterobj-filtee.so
7c0489
+$(objpfx)tst-auxobj: $(objpfx)tst-filterobj-aux.so
7c0489
+$(objpfx)tst-auxobj-dlopen: $(libdl)
7c0489
+$(objpfx)tst-auxobj.out: $(objpfx)tst-filterobj-filtee.so
7c0489
+$(objpfx)tst-auxobj-dlopen.out: $(objpfx)tst-filterobj-filtee.so
7c0489
diff --git a/elf/dl-deps.c b/elf/dl-deps.c
7c0489
index 9d9b1ba7f244348a..50f053a1586efdc3 100644
7c0489
--- a/elf/dl-deps.c
7c0489
+++ b/elf/dl-deps.c
7c0489
@@ -485,14 +485,18 @@ _dl_map_object_deps (struct link_map *map,
7c0489
 
7c0489
   map->l_searchlist.r_list = &l_initfini[nlist + 1];
7c0489
   map->l_searchlist.r_nlist = nlist;
7c0489
+  unsigned int map_index = UINT_MAX;
7c0489
 
7c0489
   for (nlist = 0, runp = known; runp; runp = runp->next)
7c0489
     {
7c0489
       if (__builtin_expect (trace_mode, 0) && runp->map->l_faked)
7c0489
 	/* This can happen when we trace the loading.  */
7c0489
 	--map->l_searchlist.r_nlist;
7c0489
-      else
7c0489
+      else {
7c0489
+	if (runp->map == map)
7c0489
+	  map_index = nlist;
7c0489
 	map->l_searchlist.r_list[nlist++] = runp->map;
7c0489
+      }
7c0489
 
7c0489
       /* Now clear all the mark bits we set in the objects on the search list
7c0489
 	 to avoid duplicates, so the next call starts fresh.  */
7c0489
@@ -550,13 +554,14 @@ Filters not supported with LD_TRACE_PRELINKING"));
7c0489
     }
7c0489
 
7c0489
   /* Maybe we can remove some relocation dependencies now.  */
7c0489
-  assert (map->l_searchlist.r_list[0] == map);
7c0489
   struct link_map_reldeps *l_reldeps = NULL;
7c0489
   if (map->l_reldeps != NULL)
7c0489
     {
7c0489
-      for (i = 1; i < nlist; ++i)
7c0489
+      for (i = 0; i < nlist; ++i)
7c0489
 	map->l_searchlist.r_list[i]->l_reserved = 1;
7c0489
 
7c0489
+      /* Avoid removing relocation dependencies of the main binary.  */
7c0489
+      map->l_reserved = 0;
7c0489
       struct link_map **list = &map->l_reldeps->list[0];
7c0489
       for (i = 0; i < map->l_reldeps->act; ++i)
7c0489
 	if (list[i]->l_reserved)
7c0489
@@ -581,16 +586,30 @@ Filters not supported with LD_TRACE_PRELINKING"));
7c0489
 	      }
7c0489
 	  }
7c0489
 
7c0489
-      for (i = 1; i < nlist; ++i)
7c0489
+      for (i = 0; i < nlist; ++i)
7c0489
 	map->l_searchlist.r_list[i]->l_reserved = 0;
7c0489
     }
7c0489
 
7c0489
-  /* Sort the initializer list to take dependencies into account.  The binary
7c0489
-     itself will always be initialize last.  */
7c0489
-  memcpy (l_initfini, map->l_searchlist.r_list,
7c0489
-	  nlist * sizeof (struct link_map *));
7c0489
-  /* We can skip looking for the binary itself which is at the front of
7c0489
-     the search list.  */
7c0489
+  /* Sort the initializer list to take dependencies into account.  Always
7c0489
+     initialize the binary itself last.  */
7c0489
+  assert (map_index < nlist);
7c0489
+  if (map_index > 0)
7c0489
+    {
7c0489
+      /* Copy the binary into position 0.  */
7c0489
+      l_initfini[0] = map->l_searchlist.r_list[map_index];
7c0489
+
7c0489
+      /* Copy the filtees.  */
7c0489
+      for (i = 0; i < map_index; ++i)
7c0489
+	l_initfini[i+1] = map->l_searchlist.r_list[i];
7c0489
+
7c0489
+      /* Copy the remainder.  */
7c0489
+      for (i = map_index + 1; i < nlist; ++i)
7c0489
+	l_initfini[i] = map->l_searchlist.r_list[i];
7c0489
+    }
7c0489
+  else
7c0489
+    memcpy (l_initfini, map->l_searchlist.r_list,
7c0489
+	    nlist * sizeof (struct link_map *));
7c0489
+
7c0489
   _dl_sort_maps (&l_initfini[1], nlist - 1, NULL, false);
7c0489
 
7c0489
   /* Terminate the list of dependencies.  */
7c0489
diff --git a/elf/dl-open.c b/elf/dl-open.c
7c0489
index d834b89754d2b073..d31356f7e17dfb14 100644
7c0489
--- a/elf/dl-open.c
7c0489
+++ b/elf/dl-open.c
7c0489
@@ -618,22 +618,25 @@ dl_open_worker (void *a)
7c0489
      allows IFUNC relocations to work and it also means copy
7c0489
      relocation of dependencies are if necessary overwritten.  */
7c0489
   unsigned int nmaps = 0;
7c0489
-  struct link_map *l = new;
7c0489
+  unsigned int j = 0;
7c0489
+  struct link_map *l = new->l_initfini[0];
7c0489
   do
7c0489
     {
7c0489
       if (! l->l_real->l_relocated)
7c0489
 	++nmaps;
7c0489
-      l = l->l_next;
7c0489
+      l = new->l_initfini[++j];
7c0489
     }
7c0489
   while (l != NULL);
7c0489
+  /* Stack allocation is limited by the number of loaded objects.  */
7c0489
   struct link_map *maps[nmaps];
7c0489
   nmaps = 0;
7c0489
-  l = new;
7c0489
+  j = 0;
7c0489
+  l = new->l_initfini[0];
7c0489
   do
7c0489
     {
7c0489
       if (! l->l_real->l_relocated)
7c0489
 	maps[nmaps++] = l;
7c0489
-      l = l->l_next;
7c0489
+      l = new->l_initfini[++j];
7c0489
     }
7c0489
   while (l != NULL);
7c0489
   _dl_sort_maps (maps, nmaps, NULL, false);
7c0489
diff --git a/elf/tst-auxobj-dlopen.c b/elf/tst-auxobj-dlopen.c
7c0489
new file mode 100644
7c0489
index 0000000000000000..cb54aba19470a1fe
7c0489
--- /dev/null
7c0489
+++ b/elf/tst-auxobj-dlopen.c
7c0489
@@ -0,0 +1,47 @@
7c0489
+/* Test for BZ#16272, dlopen'ing an auxiliary filter object.
7c0489
+   Ensure that symbols from the resolve correctly.
7c0489
+
7c0489
+   Copyright (C) 2020 Free Software Foundation, Inc.
7c0489
+   This file is part of the GNU C Library.
7c0489
+
7c0489
+   The GNU C Library is free software; you can redistribute it and/or
7c0489
+   modify it under the terms of the GNU Lesser General Public
7c0489
+   License as published by the Free Software Foundation; either
7c0489
+   version 2.1 of the License, or (at your option) any later version.
7c0489
+
7c0489
+   The GNU C Library is distributed in the hope that it will be useful,
7c0489
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
7c0489
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
7c0489
+   Lesser General Public License for more details.
7c0489
+
7c0489
+   You should have received a copy of the GNU Lesser General Public
7c0489
+   License along with the GNU C Library; if not, see
7c0489
+   <https://www.gnu.org/licenses/>.  */
7c0489
+
7c0489
+#include <stdio.h>
7c0489
+#include <support/check.h>
7c0489
+#include <support/xdlfcn.h>
7c0489
+
7c0489
+static int do_test (void)
7c0489
+{
7c0489
+  void *lib = xdlopen ("tst-filterobj-aux.so", RTLD_LAZY);
7c0489
+  char *(*fn)(void) = xdlsym (lib, "get_text");
7c0489
+  const char* text = fn ();
7c0489
+
7c0489
+  printf ("%s\n", text);
7c0489
+
7c0489
+  /* Verify the text matches what we expect from the filtee */
7c0489
+  TEST_COMPARE_STRING (text, "Hello from filtee (PASS)");
7c0489
+
7c0489
+  fn = xdlsym (lib, "get_text2");
7c0489
+  text = fn ();
7c0489
+
7c0489
+  printf ("%s\n", text);
7c0489
+
7c0489
+  /* Verify the text matches what we expect from the auxiliary object */
7c0489
+  TEST_COMPARE_STRING (text, "Hello from auxiliary filter object (PASS)");
7c0489
+
7c0489
+  return 0;
7c0489
+}
7c0489
+
7c0489
+#include <support/test-driver.c>
7c0489
diff --git a/elf/tst-auxobj.c b/elf/tst-auxobj.c
7c0489
new file mode 100644
7c0489
index 0000000000000000..bdc7713b04b4a79b
7c0489
--- /dev/null
7c0489
+++ b/elf/tst-auxobj.c
7c0489
@@ -0,0 +1,42 @@
7c0489
+/* Test that symbols from auxiliary filter objects are resolved to the
7c0489
+   filtee.
7c0489
+
7c0489
+   Copyright (C) 2020 Free Software Foundation, Inc.
7c0489
+   This file is part of the GNU C Library.
7c0489
+
7c0489
+   The GNU C Library is free software; you can redistribute it and/or
7c0489
+   modify it under the terms of the GNU Lesser General Public
7c0489
+   License as published by the Free Software Foundation; either
7c0489
+   version 2.1 of the License, or (at your option) any later version.
7c0489
+
7c0489
+   The GNU C Library is distributed in the hope that it will be useful,
7c0489
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
7c0489
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
7c0489
+   Lesser General Public License for more details.
7c0489
+
7c0489
+   You should have received a copy of the GNU Lesser General Public
7c0489
+   License along with the GNU C Library; if not, see
7c0489
+   <https://www.gnu.org/licenses/>.  */
7c0489
+
7c0489
+#include <stdio.h>
7c0489
+#include <support/check.h>
7c0489
+#include "tst-filterobj-filtee.h"
7c0489
+
7c0489
+static int do_test (void)
7c0489
+{
7c0489
+  const char* text = get_text ();
7c0489
+  printf ("%s\n", text);
7c0489
+
7c0489
+  /* Verify the text matches what we expect from the filtee */
7c0489
+  TEST_COMPARE_STRING (text, "Hello from filtee (PASS)");
7c0489
+
7c0489
+  text = get_text2 ();
7c0489
+  printf ("%s\n", text);
7c0489
+
7c0489
+  /* Verify the text matches what we expect from the auxiliary object */
7c0489
+  TEST_COMPARE_STRING (text, "Hello from auxiliary filter object (PASS)");
7c0489
+
7c0489
+  return 0;
7c0489
+}
7c0489
+
7c0489
+#include <support/test-driver.c>
7c0489
diff --git a/elf/tst-filterobj-aux.c b/elf/tst-filterobj-aux.c
7c0489
new file mode 100644
7c0489
index 0000000000000000..0b732f2fb3a69a7f
7c0489
--- /dev/null
7c0489
+++ b/elf/tst-filterobj-aux.c
7c0489
@@ -0,0 +1,33 @@
7c0489
+/* Auxiliary filter object.
7c0489
+   Contains symbols to be resolved in filtee, and one which doesn't.
7c0489
+
7c0489
+   Copyright (C) 2020 Free Software Foundation, Inc.
7c0489
+   This file is part of the GNU C Library.
7c0489
+
7c0489
+   The GNU C Library is free software; you can redistribute it and/or
7c0489
+   modify it under the terms of the GNU Lesser General Public
7c0489
+   License as published by the Free Software Foundation; either
7c0489
+   version 2.1 of the License, or (at your option) any later version.
7c0489
+
7c0489
+   The GNU C Library is distributed in the hope that it will be useful,
7c0489
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
7c0489
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
7c0489
+   Lesser General Public License for more details.
7c0489
+
7c0489
+   You should have received a copy of the GNU Lesser General Public
7c0489
+   License along with the GNU C Library; if not, see
7c0489
+   <https://www.gnu.org/licenses/>.  */
7c0489
+
7c0489
+#include "tst-filterobj-filtee.h"
7c0489
+
7c0489
+/* We never want to see the output of the auxiliary object.  */
7c0489
+const char *get_text (void)
7c0489
+{
7c0489
+  return "Hello from auxiliary filter object (FAIL)";
7c0489
+}
7c0489
+
7c0489
+/* The filtee doesn't implement this symbol, so this should resolve.  */
7c0489
+const char *get_text2 (void)
7c0489
+{
7c0489
+  return "Hello from auxiliary filter object (PASS)";
7c0489
+}
7c0489
diff --git a/elf/tst-filterobj-dlopen.c b/elf/tst-filterobj-dlopen.c
7c0489
new file mode 100644
7c0489
index 0000000000000000..c5b5072979802b98
7c0489
--- /dev/null
7c0489
+++ b/elf/tst-filterobj-dlopen.c
7c0489
@@ -0,0 +1,39 @@
7c0489
+/* Test for BZ#16272, dlopen'ing a filter object.
7c0489
+   Ensure that symbols from the filter object resolve to the filtee.
7c0489
+
7c0489
+   Copyright (C) 2020 Free Software Foundation, Inc.
7c0489
+   This file is part of the GNU C Library.
7c0489
+
7c0489
+   The GNU C Library is free software; you can redistribute it and/or
7c0489
+   modify it under the terms of the GNU Lesser General Public
7c0489
+   License as published by the Free Software Foundation; either
7c0489
+   version 2.1 of the License, or (at your option) any later version.
7c0489
+
7c0489
+   The GNU C Library is distributed in the hope that it will be useful,
7c0489
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
7c0489
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
7c0489
+   Lesser General Public License for more details.
7c0489
+
7c0489
+   You should have received a copy of the GNU Lesser General Public
7c0489
+   License along with the GNU C Library; if not, see
7c0489
+   <https://www.gnu.org/licenses/>.  */
7c0489
+
7c0489
+#include <stdio.h>
7c0489
+#include <support/check.h>
7c0489
+#include <support/xdlfcn.h>
7c0489
+
7c0489
+static int do_test (void)
7c0489
+{
7c0489
+  void *lib = xdlopen ("tst-filterobj-flt.so", RTLD_LAZY);
7c0489
+  char *(*fn)(void) = xdlsym (lib, "get_text");
7c0489
+  const char* text = fn ();
7c0489
+
7c0489
+  printf ("%s\n", text);
7c0489
+
7c0489
+  /* Verify the text matches what we expect from the filtee */
7c0489
+  TEST_COMPARE_STRING (text, "Hello from filtee (PASS)");
7c0489
+
7c0489
+  return 0;
7c0489
+}
7c0489
+
7c0489
+#include <support/test-driver.c>
7c0489
diff --git a/elf/tst-filterobj-filtee.c b/elf/tst-filterobj-filtee.c
7c0489
new file mode 100644
7c0489
index 0000000000000000..8fa557cbd251f53c
7c0489
--- /dev/null
7c0489
+++ b/elf/tst-filterobj-filtee.c
7c0489
@@ -0,0 +1,27 @@
7c0489
+/* Filtee for BZ#16272 test.
7c0489
+   Contains desired symbol implementations.
7c0489
+
7c0489
+   Copyright (C) 2020 Free Software Foundation, Inc.
7c0489
+   This file is part of the GNU C Library.
7c0489
+
7c0489
+   The GNU C Library is free software; you can redistribute it and/or
7c0489
+   modify it under the terms of the GNU Lesser General Public
7c0489
+   License as published by the Free Software Foundation; either
7c0489
+   version 2.1 of the License, or (at your option) any later version.
7c0489
+
7c0489
+   The GNU C Library is distributed in the hope that it will be useful,
7c0489
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
7c0489
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
7c0489
+   Lesser General Public License for more details.
7c0489
+
7c0489
+   You should have received a copy of the GNU Lesser General Public
7c0489
+   License along with the GNU C Library; if not, see
7c0489
+   <https://www.gnu.org/licenses/>.  */
7c0489
+
7c0489
+#include "tst-filterobj-filtee.h"
7c0489
+
7c0489
+/* This is the real implementation that wants to be called */
7c0489
+const char *get_text (void)
7c0489
+{
7c0489
+  return "Hello from filtee (PASS)";
7c0489
+}
7c0489
diff --git a/elf/tst-filterobj-filtee.h b/elf/tst-filterobj-filtee.h
7c0489
new file mode 100644
7c0489
index 0000000000000000..46aee28178b88a77
7c0489
--- /dev/null
7c0489
+++ b/elf/tst-filterobj-filtee.h
7c0489
@@ -0,0 +1,24 @@
7c0489
+/* Filtee header for BZ#16272 test.
7c0489
+   Contains prototypes for symbols implemented in the filtee.
7c0489
+
7c0489
+   Copyright (C) 2020 Free Software Foundation, Inc.
7c0489
+   This file is part of the GNU C Library.
7c0489
+
7c0489
+   The GNU C Library is free software; you can redistribute it and/or
7c0489
+   modify it under the terms of the GNU Lesser General Public
7c0489
+   License as published by the Free Software Foundation; either
7c0489
+   version 2.1 of the License, or (at your option) any later version.
7c0489
+
7c0489
+   The GNU C Library is distributed in the hope that it will be useful,
7c0489
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
7c0489
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
7c0489
+   Lesser General Public License for more details.
7c0489
+
7c0489
+   You should have received a copy of the GNU Lesser General Public
7c0489
+   License along with the GNU C Library; if not, see
7c0489
+   <https://www.gnu.org/licenses/>.  */
7c0489
+
7c0489
+const char *get_text (void);
7c0489
+
7c0489
+/* For testing auxiliary filter object.  */
7c0489
+const char *get_text2 (void);
7c0489
diff --git a/elf/tst-filterobj-flt.c b/elf/tst-filterobj-flt.c
7c0489
new file mode 100644
7c0489
index 0000000000000000..5062654be6f14a80
7c0489
--- /dev/null
7c0489
+++ b/elf/tst-filterobj-flt.c
7c0489
@@ -0,0 +1,27 @@
7c0489
+/* Filter object for BZ#16272 test.
7c0489
+   Contains symbols to be resolved in filtee.
7c0489
+
7c0489
+   Copyright (C) 2020 Free Software Foundation, Inc.
7c0489
+   This file is part of the GNU C Library.
7c0489
+
7c0489
+   The GNU C Library is free software; you can redistribute it and/or
7c0489
+   modify it under the terms of the GNU Lesser General Public
7c0489
+   License as published by the Free Software Foundation; either
7c0489
+   version 2.1 of the License, or (at your option) any later version.
7c0489
+
7c0489
+   The GNU C Library is distributed in the hope that it will be useful,
7c0489
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
7c0489
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
7c0489
+   Lesser General Public License for more details.
7c0489
+
7c0489
+   You should have received a copy of the GNU Lesser General Public
7c0489
+   License along with the GNU C Library; if not, see
7c0489
+   <https://www.gnu.org/licenses/>.  */
7c0489
+
7c0489
+#include "tst-filterobj-filtee.h"
7c0489
+
7c0489
+/* We never want to see the output of the filter object */
7c0489
+const char *get_text (void)
7c0489
+{
7c0489
+  return "Hello from filter object (FAIL)";
7c0489
+}
7c0489
diff --git a/elf/tst-filterobj.c b/elf/tst-filterobj.c
7c0489
new file mode 100644
7c0489
index 0000000000000000..96bfae019ea670bc
7c0489
--- /dev/null
7c0489
+++ b/elf/tst-filterobj.c
7c0489
@@ -0,0 +1,36 @@
7c0489
+/* Test that symbols from filter objects are resolved to the filtee.
7c0489
+
7c0489
+   Copyright (C) 2020 Free Software Foundation, Inc.
7c0489
+   This file is part of the GNU C Library.
7c0489
+
7c0489
+   The GNU C Library is free software; you can redistribute it and/or
7c0489
+   modify it under the terms of the GNU Lesser General Public
7c0489
+   License as published by the Free Software Foundation; either
7c0489
+   version 2.1 of the License, or (at your option) any later version.
7c0489
+
7c0489
+   The GNU C Library is distributed in the hope that it will be useful,
7c0489
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
7c0489
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
7c0489
+   Lesser General Public License for more details.
7c0489
+
7c0489
+   You should have received a copy of the GNU Lesser General Public
7c0489
+   License along with the GNU C Library; if not, see
7c0489
+   <https://www.gnu.org/licenses/>.  */
7c0489
+
7c0489
+#include <stdio.h>
7c0489
+#include <support/check.h>
7c0489
+#include "tst-filterobj-filtee.h"
7c0489
+
7c0489
+static int do_test (void)
7c0489
+{
7c0489
+  const char* text = get_text ();
7c0489
+
7c0489
+  printf ("%s\n", text);
7c0489
+
7c0489
+  /* Verify the text matches what we expect from the filtee */
7c0489
+  TEST_COMPARE_STRING (text, "Hello from filtee (PASS)");
7c0489
+
7c0489
+  return 0;
7c0489
+}
7c0489
+
7c0489
+#include <support/test-driver.c>