aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2017-04-13 23:27:40 +0300
committerJussi Pakkanen <jpakkane@gmail.com>2017-04-17 12:48:54 +0300
commit0e47e74a77447575cbabd71315481c6dd9632601 (patch)
tree368de0c60806fdb1d1109aabdc7dc8abae0b9c6c
parent0e45134dee09b12005c028aee066b04ff86228e5 (diff)
downloadmeson-0e47e74a77447575cbabd71315481c6dd9632601.zip
meson-0e47e74a77447575cbabd71315481c6dd9632601.tar.gz
meson-0e47e74a77447575cbabd71315481c6dd9632601.tar.bz2
Do not obliterate old rpath because it might be used due to read only data sharing. Closes #1619.
-rw-r--r--mesonbuild/scripts/depfixer.py15
-rwxr-xr-xrun_unittests.py22
-rw-r--r--test cases/unit/7 run installed/foo/foo.c3
-rw-r--r--test cases/unit/7 run installed/foo/meson.build7
-rw-r--r--test cases/unit/7 run installed/meson.build9
-rw-r--r--test cases/unit/7 run installed/prog.c5
6 files changed, 58 insertions, 3 deletions
diff --git a/mesonbuild/scripts/depfixer.py b/mesonbuild/scripts/depfixer.py
index 1404619..16050d7 100644
--- a/mesonbuild/scripts/depfixer.py
+++ b/mesonbuild/scripts/depfixer.py
@@ -297,11 +297,20 @@ class Elf(DataSizes):
old_rpath = self.read_str()
if len(old_rpath) < len(new_rpath):
sys.exit("New rpath must not be longer than the old one.")
- self.bf.seek(rp_off)
- self.bf.write(new_rpath)
- self.bf.write(b'\0' * (len(old_rpath) - len(new_rpath) + 1))
+ # The linker does read-only string deduplication. If there is a
+ # string that shares a suffix with the rpath, they might get
+ # dedupped. This means changing the rpath string might break something
+ # completely unrelated. This has already happened once with X.org.
+ # Thus we want to keep this change as small as possible to minimize
+ # the chance of obliterating other strings. It might still happen
+ # but our behaviour is identical to what chrpath does and it has
+ # been in use for ages so based on that this should be rare.
if len(new_rpath) == 0:
self.remove_rpath_entry(entrynum)
+ else:
+ self.bf.seek(rp_off)
+ self.bf.write(new_rpath)
+ self.bf.write(b'\0')
def remove_rpath_entry(self, entrynum):
sec = self.find_section(b'.dynamic')
diff --git a/run_unittests.py b/run_unittests.py
index e8ecbb2..3e98c21 100755
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -1460,6 +1460,28 @@ class LinuxlikeTests(BasePlatformTests):
self.assertIn('-Werror', plain_comp)
self.assertNotIn('-Werror', c03_comp)
+ def test_run_installed(self):
+ testdir = os.path.join(self.unit_test_dir, '7 run installed')
+ self.init(testdir)
+ self.build()
+ self.install()
+ installed_exe = os.path.join(self.installdir, 'usr/bin/prog')
+ installed_libdir = os.path.join(self.installdir, 'usr/foo')
+ installed_lib = os.path.join(installed_libdir, 'libfoo.so')
+ self.assertTrue(os.path.isfile(installed_exe))
+ self.assertTrue(os.path.isdir(installed_libdir))
+ self.assertTrue(os.path.isfile(installed_lib))
+ # Must fail when run without LD_LIBRARY_PATH to ensure that
+ # rpath has been properly stripped rather than pointing to the builddir.
+ self.assertNotEqual(subprocess.call(installed_exe, stderr=subprocess.DEVNULL), 0)
+ # When LD_LIBRARY_PATH is set it should start working.
+ # For some reason setting LD_LIBRARY_PATH in os.environ fails
+ # when all tests are run (but works when only this test is run),
+ # but doing this explicitly works.
+ env = os.environ.copy()
+ env['LD_LIBRARY_PATH'] = installed_libdir
+ self.assertEqual(subprocess.call(installed_exe, env=env), 0)
+
class RewriterTests(unittest.TestCase):
def setUp(self):
diff --git a/test cases/unit/7 run installed/foo/foo.c b/test cases/unit/7 run installed/foo/foo.c
new file mode 100644
index 0000000..402c895
--- /dev/null
+++ b/test cases/unit/7 run installed/foo/foo.c
@@ -0,0 +1,3 @@
+int foo() {
+ return 0;
+}
diff --git a/test cases/unit/7 run installed/foo/meson.build b/test cases/unit/7 run installed/foo/meson.build
new file mode 100644
index 0000000..082f985
--- /dev/null
+++ b/test cases/unit/7 run installed/foo/meson.build
@@ -0,0 +1,7 @@
+# Try to invoke linker constant string deduplication,
+# to ensure we are not clobbering shared strings.
+# Name everything possible just as "foo".
+foolib = shared_library('foo', 'foo.c',
+ install_dir : 'foo',
+ install : true)
+
diff --git a/test cases/unit/7 run installed/meson.build b/test cases/unit/7 run installed/meson.build
new file mode 100644
index 0000000..46236fa
--- /dev/null
+++ b/test cases/unit/7 run installed/meson.build
@@ -0,0 +1,9 @@
+project('foo', 'c',
+ default_options : 'libdir=lib')
+
+subdir('foo')
+
+executable('prog', 'prog.c',
+ link_with : foolib,
+ install : true)
+
diff --git a/test cases/unit/7 run installed/prog.c b/test cases/unit/7 run installed/prog.c
new file mode 100644
index 0000000..8e61e6e
--- /dev/null
+++ b/test cases/unit/7 run installed/prog.c
@@ -0,0 +1,5 @@
+int foo();
+
+int main(int argc, char **argv) {
+ return foo();
+}