diff options
author | Anthony G. Basile <blueness@gentoo.org> | 2012-12-23 20:54:10 -0500 |
---|---|---|
committer | Anthony G. Basile <blueness@gentoo.org> | 2012-12-24 05:57:57 -0500 |
commit | bbed69289001490eb792727262035ff696c8fc44 (patch) | |
tree | 6c6dca53f51df3308a4efc47e95f3efc1c4805ae | |
parent | src/paxctl-ng.c: fix flag logic under various --{en,dis}able-{pt,xt}pax (diff) | |
download | elfix-bbed69289001490eb792727262035ff696c8fc44.tar.gz elfix-bbed69289001490eb792727262035ff696c8fc44.tar.bz2 elfix-bbed69289001490eb792727262035ff696c8fc44.zip |
misc/link_maps{,_portage}: compare reading /var/db/pkg directly and via portage
-rwxr-xr-x | misc/link_maps | 60 | ||||
-rwxr-xr-x | misc/link_maps_portage | 184 |
2 files changed, 199 insertions, 45 deletions
diff --git a/misc/link_maps b/misc/link_maps index a6adacd..3e4e3cb 100755 --- a/misc/link_maps +++ b/misc/link_maps @@ -168,57 +168,27 @@ def main(): 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 out all ELF objects and the NEEDED sonames and full library paths """ + for elf in object_linkings: + sonames = object_linkings[elf] print("%s" % elf) - for soname in sorted(object_needed[elf]): + for soname in sorted(object_linkings[elf]): try: print("\t%s\t=> %s" % (soname, soname2library[soname])) except KeyError: - print("\t%s\t=> ****" % soname) + print("%s\t=>%s " % (soname, '***')) + print("\n\n") + + """ Print out all ELF objects and the NEEDED sonames and full library paths """ + for soname in object_reverse_linkings: + try: + print("%s\t=> %s" % (soname, soname2library[soname])) + except KeyError: + print("%s\t=>%s " % (soname, '***')) + for elf in sorted(object_reverse_linkings[soname]): + print("\t%s" % elf) 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() diff --git a/misc/link_maps_portage b/misc/link_maps_portage new file mode 100755 index 0000000..bf5b447 --- /dev/null +++ b/misc/link_maps_portage @@ -0,0 +1,184 @@ +#!/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 +import portage + + +""" +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(): + + vardb = portage.db[portage.root]["vartree"].dbapi + + object_needed = {} + + for pkg in vardb.cpv_all(): + needs = vardb.aux_get(pkg, ['NEEDED.ELF.2'])[0].strip() + if not needs: #skip empty lines + continue + lines = re.split('\n', needs) + for line in lines: + link = re.split(';', line) + elf = link[1] + sonames = re.split(',', link[4]) + object_needed[elf] = sonames + + 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(): + + vardb = portage.db[portage.root]["vartree"].dbapi + + library2soname = {} + soname2library = {} + + for pkg in vardb.cpv_all(): + needs = vardb.aux_get(pkg, ['NEEDED.ELF.2'])[0].strip() + if not needs: #skip empty lines + continue + lines = re.split('\n', needs) + for line in lines: + link = re.split(';', line) + elf = link[1] + soname = link[2] + if soname: #no soname => executable + library2soname[elf] = soname + soname2library[soname] = elf + + 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 the NEEDED sonames and full library paths """ + for elf in object_linkings: + sonames = object_linkings[elf] + print("%s" % elf) + for soname in sorted(object_linkings[elf]): + try: + print("\t%s\t=> %s" % (soname, soname2library[soname])) + except KeyError: + print("%s\t=>%s " % (soname, '***')) + print("\n\n") + + """ Print out all ELF objects and the NEEDED sonames and full library paths """ + for soname in object_reverse_linkings: + try: + print("%s\t=> %s" % (soname, soname2library[soname])) + except KeyError: + print("%s\t=>%s " % (soname, '***')) + for elf in sorted(object_reverse_linkings[soname]): + print("\t%s" % elf) + print("\n\n") + + +if __name__ == '__main__': + main() |