From: "Anthony G. Basile" <blueness@gentoo.org>
To: gentoo-commits@lists.gentoo.org
Subject: [gentoo-commits] proj/elfix:master commit in: misc/
Date: Wed, 26 Dec 2012 21:23:22 +0000 (UTC) [thread overview]
Message-ID: <1356556989.beacfc74b3af09d5a87ea60edba019a8d7f51f6a.blueness@gentoo> (raw)
commit: beacfc74b3af09d5a87ea60edba019a8d7f51f6a
Author: Anthony G. Basile <blueness <AT> gentoo <DOT> org>
AuthorDate: Wed Dec 26 21:23:09 2012 +0000
Commit: Anthony G. Basile <blueness <AT> gentoo <DOT> org>
CommitDate: Wed Dec 26 21:23:09 2012 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/elfix.git;a=commit;h=beacfc74
misc/link_maps: encapsulate all logic in class LinkMap
---
misc/link_maps | 302 +++++++++++++++++++++++++++++---------------------------
1 files changed, 156 insertions(+), 146 deletions(-)
diff --git a/misc/link_maps b/misc/link_maps
index 3707298..508af24 100755
--- a/misc/link_maps
+++ b/misc/link_maps
@@ -1,14 +1,5 @@
#!/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
@@ -16,147 +7,181 @@ import pax
import portage
-def get_object_needed():
- """ Return object_needed dictionary which has structure
+class LinkMap:
- {
- abi1 : { full_path_to_ELF_object : [ soname1, soname2, ... ], ... },
- abi2 : { full_path_to_ELF_object : [ soname1, soname2, ... ], ... },
- ....
- }
+ def __init__(self):
+ """ Put all the NEEDED.ELF.2 files for all installed packages
+ into a dictionary of the form
- Here the sonames were obtained from the ELF object by scanelf -nm
- (like readelf -d) during emerge.
- """
+ { pkg : line_from_NEEDED.ELF.2, ... }
- vardb = portage.db[portage.root]["vartree"].dbapi
+ where the line has the following form:
- object_needed = {}
+ echo "${arch:3};${obj};${soname};${rpath};${needed}" >> \
+ "${PORTAGE_BUILDDIR}"/build-info/NEEDED.ELF.2
- 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)
- abi = link[0]
- elf = link[1]
- sonames = re.split(',', link[4])
- object_needed.setdefault(abi,{}).update({elf:sonames})
+ See /usr/lib/portage/bin/misc-functions.sh ~line 520
+ """
+ vardb = portage.db[portage.root]["vartree"].dbapi
- return object_needed
+ self.pkgs = []
+ self.pkgs_needed = {}
+ for pkg in vardb.cpv_all():
+ needed = vardb.aux_get(pkg, ['NEEDED.ELF.2'])[0].strip()
+ if needed: # Some packages have no NEEDED.ELF.2
+ self.pkgs.append(pkg)
+ for line in re.split('\n', needed):
+ self.pkgs_needed.setdefault(pkg,[]).append(re.split(';', line))
-def get_libraries():
- """ Return library2soname dictionary which has structure
- { full_path_to_library : (soname, abi), ... }
+ def get_object_needed(self):
+ """ Return object_needed dictionary which has structure
- and its inverse which has structure
+ {
+ abi1 : { full_path_to_ELF_object : [ soname1, soname2, ... ], ... },
+ abi2 : { full_path_to_ELF_object : [ soname1, soname2, ... ], ... },
+ ....
+ }
- { (soname, abi) : full_path_to_library, ... }
- """
+ Here the sonames were obtained from the ELF object by scanelf -nm
+ (like readelf -d) during emerge.
+ """
+ object_needed = {}
- vardb = portage.db[portage.root]["vartree"].dbapi
+ for pkg in self.pkgs:
+ for link in self.pkgs_needed[pkg]:
+ abi = link[0]
+ elf = link[1]
+ sonames = re.split(',', link[4])
+ object_needed.setdefault(abi,{}).update({elf:sonames})
- library2soname = {}
- soname2library = {}
+ return 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)
- abi = link[0]
- elf = link[1]
- soname = link[2]
- if soname: #no soname => executable
- library2soname[elf] = (soname,abi)
- soname2library[(soname,abi)] = elf
- return ( library2soname, soname2library )
+ def get_libraries(self):
+ """ Return library2soname dictionary which has structure
+ { full_path_to_library : (soname, abi), ... }
-def get_soname_needed( object_needed, library2soname ):
- """ Return soname_needed dictionary which has structure:
+ and its inverse which has structure
- {
- abi1: { soname: [ soname1, soname2, ... ], .... },
- abi2: { soname: [ soname1, soname2, ... ], .... },
- }
+ { (soname, abi) : full_path_to_library, ... }
+ """
+ library2soname = {}
+ soname2library = {}
- Here the soname1, soname2,... were obtained from soname's corresponding
- ELF object by scanelf -n during emerge.
- """
+ for pkg in self.pkgs:
+ for link in self.pkgs_needed[pkg]:
+ abi = link[0]
+ elf = link[1]
+ soname = link[2]
+ if soname: #no soname => executable
+ library2soname[elf] = (soname,abi)
+ soname2library[(soname,abi)] = elf
- soname_needed = {}
+ return ( library2soname, soname2library )
- for abi in object_needed:
- for elf in object_needed[abi]:
- try:
- (soname, abi_check) = library2soname[elf]
- if abi != abi_check:
- print('This should never happen!')
- sys.exit(1)
- soname_needed.setdefault(abi,{}).update({soname:object_needed[abi][elf]})
- except KeyError:
- continue # no soname, its probably an executable
-
- return soname_needed
-
-
-def expand_linkings( object_needed, soname2library ):
- """ Expands the object_needed dictionary which has structure
-
- {
- abi1 : { full_path_to_ELF_object : [ soname1, soname2, ... ], ... },
- abi2 : { full_path_to_ELF_object : [ soname1, soname2, ... ], ... },
- ....
- }
-
- such that the soname's are traced all the way to the end of
- the link chain. Here the sonames should be the same as those
- obtained from the ELF object by ldd.
- """
-
- for abi in object_needed:
- for elf in object_needed[abi]:
- while True:
- found_new_soname = False
- for so in object_needed[abi][elf]: # For all the first links ...
- try:
- for sn in object_needed[abi][soname2library[(so,abi)]]: # go to the next links ...
- if sn in object_needed[abi][elf]: # skip if already included ...
- continue
- if not (sn,abi) in soname2library: # skip if vdso ...
- continue
- # This appends to the object_needed
- # and soname_needed lists. No copy
- # was done so its the same lists in
- # memory for both, and its modified
- # for both.
- object_needed[abi][elf].append(sn) # otherwise collapse it back into
- found_new_soname = True # first links of the chain.
-
- except KeyError: # Not all nodes in the chain have a next node
- continue
-
- if not found_new_soname: # We're done, that last iteration found
- break # no new nodes
-
-
-def get_object_reverse_linkings( object_linkings ):
- object_reverse_linkings = {}
- for abi in object_linkings:
- for elf in object_linkings[abi]:
- for soname in object_linkings[abi][elf]:
- object_reverse_linkings.setdefault(abi,{}).setdefault(soname,[]).append(elf)
+ def get_soname_needed(self, object_needed, library2soname ):
+ """ Return soname_needed dictionary which has structure:
+
+ {
+ abi1: { soname: [ soname1, soname2, ... ], .... },
+ abi2: { soname: [ soname1, soname2, ... ], .... },
+ }
+
+ Here the soname1, soname2,... were obtained from soname's corresponding
+ ELF object by scanelf -n during emerge.
+ """
+ soname_needed = {}
+
+ for abi in object_needed:
+ for elf in object_needed[abi]:
+ try:
+ (soname, abi_check) = library2soname[elf]
+ assert abi == abi_check # We should get the same abi associated with the soname
+ soname_needed.setdefault(abi,{}).update({soname:object_needed[abi][elf]})
+ except KeyError:
+ continue # no soname, its probably an executable
+
+ return soname_needed
+
+
+ def expand_linkings(self, object_needed, soname2library):
+ """ Expands the object_needed dictionary which has structure
+
+ {
+ abi1 : { full_path_to_ELF_object : [ soname1, soname2, ... ], ... },
+ abi2 : { full_path_to_ELF_object : [ soname1, soname2, ... ], ... },
+ ....
+ }
+
+ such that the soname's are traced all the way to the end of
+ the link chain. Here the sonames should be the same as those
+ obtained from the ELF object by ldd.
+ """
+ for abi in object_needed:
+ for elf in object_needed[abi]:
+ while True:
+ found_new_soname = False
+ for so in object_needed[abi][elf]: # For all the first links ...
+ try:
+ for sn in object_needed[abi][soname2library[(so,abi)]]: # go to the next links ...
+ if sn in object_needed[abi][elf]: # skip if already included ...
+ continue
+ if not (sn,abi) in soname2library: # skip if vdso ...
+ continue
+
+ # This appends to the object_needed and soname_needed lists. No copy was
+ # done so its the same lists in memory for both, and its modified for both.
+
+ object_needed[abi][elf].append(sn) # otherwise collapse it back into
+ found_new_soname = True # first links of the chain.
- return object_reverse_linkings
+ except KeyError: # Not all nodes in the chain have a next node
+ continue
+
+ if not found_new_soname: # We're done, that last iteration found
+ break # no new nodes
+
+
+ def get_object_reverse_linkings(self, object_linkings):
+ """ Return object_reverse_linkings dictionary which has structure
+
+ {
+ abi1 : { soname : [ path_to_elf1, path_to_elf2, ... ], ... },
+ abi2 : { soname : [ path_to_elf3, path_to_elf4, ... ], ... },
+ ....
+ }
+ """
+ object_reverse_linkings = {}
+
+ for abi in object_linkings:
+ for elf in object_linkings[abi]:
+ for soname in object_linkings[abi][elf]:
+ object_reverse_linkings.setdefault(abi,{}).setdefault(soname,[]).append(elf)
+
+ return object_reverse_linkings
+
+
+ def get_maps(self):
+ """ Generate the full forward and reverse links using the above functions """
+
+ # After get_object_needed() and get_soname_needed(), both object_linkings and
+ # soname_linkings are only one step into the entire link chain.
+
+ object_linkings = self.get_object_needed()
+ ( library2soname, soname2library ) = self.get_libraries()
+ soname_linkings = self.get_soname_needed( object_linkings, library2soname )
+
+ # After the appending in expand_linkings(), forward_linkings and soname_linkings
+ # have been extended through the entire chain of linking. expand_linkings() is
+ # a "side-effect" function, so we note it here.
+ self.expand_linkings( soname_linkings, soname2library )
+ object_reverse_linkings = self.get_object_reverse_linkings( object_linkings )
+
+ return ( object_linkings, object_reverse_linkings, library2soname, soname2library )
def main():
@@ -167,27 +192,12 @@ def main():
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 expand_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 expand_linkings().
- expand_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 )
+ link_maps = LinkMap()
+ ( object_linkings, object_reverse_linkings, library2soname, soname2library ) = link_maps.get_maps()
layout = "{0:<30} => {1:<30}"
- """ Print out all ELF objects and the NEEDED sonames and full library paths """
+ #Print out all ELF objects and the NEEDED sonames and full library paths
for abi in object_linkings:
for elf in object_linkings[abi]:
sonames = object_linkings[abi][elf]
@@ -199,7 +209,7 @@ def main():
print('\t%s' % layout.format(soname, '***' ))
print('')
- """ Print out all ELF objects and the NEEDED sonames and full library paths """
+ # Print out all ELF objects and the NEEDED sonames and full library paths
for abi in object_linkings:
for soname in object_reverse_linkings[abi]:
try:
next reply other threads:[~2012-12-26 21:23 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-12-26 21:23 Anthony G. Basile [this message]
-- strict thread matches above, loose matches on Subject: below --
2016-02-13 21:38 [gentoo-commits] proj/elfix:master commit in: misc/ Anthony G. Basile
2014-02-13 19:07 Anthony G. Basile
2013-05-21 15:21 Anthony G. Basile
2013-02-09 21:50 Anthony G. Basile
2012-12-27 3:11 Anthony G. Basile
2012-12-26 21:43 Anthony G. Basile
2012-12-26 3:42 Anthony G. Basile
2012-12-25 14:22 Anthony G. Basile
2012-12-24 23:26 Anthony G. Basile
2012-12-24 21:44 Anthony G. Basile
2012-12-24 21:08 Anthony G. Basile
2012-12-24 2:18 Anthony G. Basile
2012-12-24 1:54 Anthony G. Basile
2012-12-23 11:51 Anthony G. Basile
2012-12-23 4:53 Anthony G. Basile
2012-12-23 3:49 Anthony G. Basile
2012-12-23 3:49 Anthony G. Basile
2012-12-23 3:49 Anthony G. Basile
2012-12-23 3:47 Anthony G. Basile
2012-12-23 2:36 Anthony G. Basile
2012-12-23 2:36 Anthony G. Basile
2012-12-23 2:34 Anthony G. Basile
2012-12-23 1:02 Anthony G. Basile
2012-12-22 14:44 Anthony G. Basile
2012-12-22 4:21 Anthony G. Basile
2012-12-22 3:58 Anthony G. Basile
2012-12-22 1:06 Anthony G. Basile
2012-12-19 3:52 Anthony G. Basile
2011-07-08 1:32 Anthony G. Basile
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1356556989.beacfc74b3af09d5a87ea60edba019a8d7f51f6a.blueness@gentoo \
--to=blueness@gentoo.org \
--cc=gentoo-commits@lists.gentoo.org \
--cc=gentoo-dev@lists.gentoo.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox