aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'misc/link_maps')
-rwxr-xr-xmisc/link_maps224
1 files changed, 224 insertions, 0 deletions
diff --git a/misc/link_maps b/misc/link_maps
new file mode 100755
index 0000000..a6adacd
--- /dev/null
+++ b/misc/link_maps
@@ -0,0 +1,224 @@
+#!/usr/bin/env python
+
+#
+# Note: This alternative way of doing revdep-pax only
+# works on Gentoo systems where NEEDED.ELF.2 all the
+# information we need generated by scanelf during emerge.
+#
+# See /usr/lib/portage/bin/misc-functions.sh ~line 520
+# echo "${arch:3};${obj};${soname};${rpath};${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.ELF.2
+#
+
+import os
+import sys
+import re
+import pax
+
+
+"""
+Return object_needed dictionary which has structure
+
+ { full_path_to_ELF_object : [ soname1, soname2, ... ], ... }
+
+Here the sonames were obtained from the ELF object by scanelf -nm
+(like readelf -d) during emerge.
+"""
+def get_object_needed():
+
+ var_db_pkg = '/var/db/pkg'
+
+ object_needed = {}
+ for cat in os.listdir(var_db_pkg):
+ catdir = '%s/%s' % (var_db_pkg, cat)
+ for pkg in os.listdir(catdir):
+ pkgdir = '%s/%s' % (catdir, pkg)
+ need = '%s/%s' % (pkgdir, 'NEEDED.ELF.2')
+ try:
+ g = open(need, 'r')
+ needs = g.readlines()
+ for line in needs:
+ line = line.strip()
+ link = re.split(';', line)
+ elf = link[1]
+ sonames = re.split(',', link[4])
+ object_needed[elf] = sonames
+ except IOError:
+ continue #File probably doesn't exist, which is okay
+
+ return object_needed
+
+
+"""
+Return library2soname dictionary which has structure
+
+ { full_path_to_library : soname, ... }
+
+and its inverse which has structure
+
+ { soname : full_path_to_library, ... }
+"""
+def get_libraries():
+
+ var_db_pkg = '/var/db/pkg'
+
+ library2soname = {}
+ soname2library = {}
+
+ for cat in os.listdir(var_db_pkg):
+ catdir = '%s/%s' % (var_db_pkg, cat)
+ for pkg in os.listdir(catdir):
+ pkgdir = '%s/%s' % (catdir, pkg)
+ need = '%s/%s' % (pkgdir, 'NEEDED.ELF.2')
+ try:
+ g = open(need, 'r')
+ needs = g.readlines()
+ for line in needs:
+ line = line.strip()
+ link = re.split(';', line)
+ elf = link[1]
+ soname = link[2]
+ if soname: #no soname => executable
+ library2soname[elf] = soname
+ soname2library[soname] = elf
+ except IOError:
+ continue #File probably doesn't exist, which is okay
+
+ return ( library2soname, soname2library )
+
+
+"""
+Return get_soname_needed dictionary which has structure:
+
+ { soname : [ soname1, soname2, ... ], .... }
+
+Here the soname1, soname2,... were obtained from soname's corresponding
+ELF object by scanelf -n during emerge.
+"""
+def get_soname_needed( object_needed, library2soname ):
+
+ soname_needed = {}
+
+ for elf in object_needed:
+ try:
+ soname = library2soname[elf]
+ soname_needed[soname] = object_needed[elf]
+ #soname_needed[soname] = copy(object_needed[elf]) #copy the list
+ except KeyError:
+ continue # no soname, its probably an executable
+
+ return soname_needed
+
+
+def get_soname_linkings( soname_needed, soname2library ):
+ for soname in soname_needed:
+ while True:
+ count = 0
+ for s in soname_needed[soname]:
+ try:
+ for sf in soname_needed[s]:
+ if sf in soname_needed[soname]: # Skip it if we already included it
+ continue
+ if not sf in soname2library: #Skip if its a vdso
+ continue
+ # This appends to the object_needed and soname_needed list.
+ # No copy was done so its the same list in memory for both.
+ soname_needed[soname].append(sf)
+ count = 1
+ except KeyError:
+ continue
+
+ if count == 0:
+ break
+ return
+
+
+def get_object_reverse_linkings( object_linkings ):
+ object_reverse_linkings = {}
+
+ for elf in object_linkings:
+ for soname in object_linkings[elf]:
+ object_reverse_linkings.setdefault(soname,[]).append(elf)
+
+ return object_reverse_linkings
+
+
+def main():
+
+ # Run as root to be able to real all files
+ uid = os.getuid()
+ if uid != 0:
+ print('RUN AS ROOT: cannot read all flags')
+ sys.exit(0)
+
+ object_needed = get_object_needed()
+ ( library2soname, soname2library ) = get_libraries()
+ soname_needed = get_soname_needed( object_needed, library2soname )
+
+ # After the appending to needed in get_soname_linkings(), forward_needed
+ # and soname_needed have been extended through the entire chain of linking.
+ # If we want to keep only the object_needed and soname_needed, then do
+ # a copy before calling get_soname_linkings().
+ get_soname_linkings( soname_needed, soname2library )
+
+ object_linkings = object_needed
+ object_needed = None
+
+ soname_linkings = soname_needed
+ soname_needed = None
+
+ object_reverse_linkings = get_object_reverse_linkings( object_linkings )
+
+ """ Print out all ELF objects and their PaX flags
+ for elf in object_needed:
+ try:
+ flags = pax.getflags(elf)[0]
+ if flags:
+ print("%s %s" % (flags, elf))
+ else:
+ print("NONE: %s" % elf)
+ except pax.error:
+ print("CANT: %s" % elf)
+
+ """
+
+ """ Print out all sonames and their library paths
+ for soname in sorted(soname2library):
+ elf = soname2library[soname]
+ print("%s : %s" % ( soname, elf ))
+ """
+
+
+ """ Print out all ELF objects and the NEEDED sonames and full library paths
+ for elf in object_needed:
+ sonames = object_needed[elf]
+ print("%s" % elf)
+ for soname in sorted(object_needed[elf]):
+ try:
+ print("\t%s\t=> %s" % (soname, soname2library[soname]))
+ except KeyError:
+ print("\t%s\t=> ****" % soname)
+ print("\n\n")
+ """
+
+ """ Print out all the soname to soname NEEDED
+ for soname in soname_needed:
+ print("%s" % soname)
+ for s in soname_needed[soname]:
+ print("\t%s" % s )
+ print('')
+ """
+
+
+ """ Print out all the soname to soname linkings
+ for soname in soname_linkings:
+ print("%s => %s" % (soname, soname2library[soname]))
+ for s in soname_linkings[soname]:
+ if s in soname2library:
+ print("\t%s => %s" % (s, soname2library[s]))
+ else:
+ print("\t%s => ****" %s )
+ print('')
+ """
+
+if __name__ == '__main__':
+ main()