Norm Jacobs
2018-01-29 df98988a54b3cf2cc02eff2eecf98b0781d4e40d
tools/userland-mangler
@@ -31,6 +31,9 @@
import os
import sys
import re
import subprocess
import shutil
import pkg.fmri
import pkg.manifest
@@ -194,12 +197,70 @@
   return result
#
# mangler.elf.strip = (true|false)
# mangler.elf.strip_runpath = (true|false)
#
def mangle_elf(manifest, action, src, dest):
   pass
   strip_elf_runpath = action.attrs.pop('mangler.elf.strip_runpath', 'true')
   if strip_elf_runpath is 'false':
      return
   #
   # Strip any runtime linker default search path elements from the file
   #
   ELFEDIT = '/usr/bin/elfedit'
   # runtime linker default search path elements + /64 link
   rtld_default_dirs = [ '/lib', '/usr/lib',
               '/lib/64', '/usr/lib/64',
               '/lib/amd64', '/usr/lib/amd64',
               '/lib/sparcv9', '/usr/lib/sparcv9' ]
   runpath_re = re.compile('.+\s(RPATH|RUNPATH)\s+\S+\s+(\S+)')
   # Retreive the search path from the object file.  Use elfedit(1) because pkg.elf only
   # retrieves the RUNPATH.  Note that dyn:rpath and dyn:runpath return both values.
   # Both RPATH and RUNPATH are expected to be the same, but in an overabundand of caution,
   # process each element found separately.
   result = subprocess.Popen([ELFEDIT, '-re', 'dyn:runpath', src ],
              stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        result.wait()
   if result.returncode != 0:   # no RUNPATH or RPATH to potentially strip
      return
   for line in result.stdout:
      result = runpath_re.match(line)
      if result != None:
         element = result.group(1)
         original_dirs = result.group(2).split(":")
         keep_dirs = []
         matched_dirs = []
         for dir in original_dirs:
            if dir not in rtld_default_dirs:
               keep_dirs.append(dir)
            else:
               matched_dirs.append(dir)
         if len(matched_dirs) != 0:
            # Emit an "Error" message in case someone wants to look at the build log
            # and fix the component build so that this is a NOP.
            print >>sys.stderr, "Stripping %s from %s in %s" % (":".join(matched_dirs), element, src)
            # Make sure that there is a destdir to copy the file into for mangling.
            destdir = os.path.dirname(dest)
            if not os.path.exists(destdir):
               os.makedirs(destdir)
            # Create a copy to mangle if it doesn't exist yet.
            if os.path.isfile(dest) == False:
               shutil.copy2(src, dest)
            # Mangle the copy by deleting the tag if there is nothing left to keep
            # or replacing the value if there is something left.
            elfcmd = "dyn:delete %s" % element.lower()
            if len(keep_dirs) > 0:
               elfcmd = "dyn:%s '%s'" % (element.lower(), ":".join(keep_dirs))
            subprocess.call([ELFEDIT, '-e', elfcmd, dest])
#
# mangler.script.file-magic =