diff options
author | Christian Ehrhardt <christian.ehrhardt@canonical.com> | 2017-05-16 14:51:32 +0200 |
---|---|---|
committer | Christian Ehrhardt <christian.ehrhardt@canonical.com> | 2017-05-16 16:20:45 +0200 |
commit | 7595afa4d30097c1177b69257118d8ad89a539be (patch) | |
tree | 4bfeadc905c977e45e54a90c42330553b8942e4e /tools/dpdk-pmdinfo.py | |
parent | ce3d555e43e3795b5d9507fcfc76b7a0a92fd0d6 (diff) |
Imported Upstream version 17.05
Change-Id: Id1e419c5a214e4a18739663b91f0f9a549f1fdc6
Signed-off-by: Christian Ehrhardt <christian.ehrhardt@canonical.com>
Diffstat (limited to 'tools/dpdk-pmdinfo.py')
-rwxr-xr-x | tools/dpdk-pmdinfo.py | 636 |
1 files changed, 0 insertions, 636 deletions
diff --git a/tools/dpdk-pmdinfo.py b/tools/dpdk-pmdinfo.py deleted file mode 100755 index 3db9819c..00000000 --- a/tools/dpdk-pmdinfo.py +++ /dev/null @@ -1,636 +0,0 @@ -#!/usr/bin/env python -# ------------------------------------------------------------------------- -# -# Utility to dump PMD_INFO_STRING support from an object file -# -# ------------------------------------------------------------------------- -import os -import sys -from optparse import OptionParser -import string -import json -import platform - -# For running from development directory. It should take precedence over the -# installed pyelftools. -sys.path.insert(0, '.') - - -from elftools import __version__ -from elftools.common.exceptions import ELFError -from elftools.common.py3compat import ( - ifilter, byte2int, bytes2str, itervalues, str2bytes) -from elftools.elf.elffile import ELFFile -from elftools.elf.dynamic import DynamicSection, DynamicSegment -from elftools.elf.enums import ENUM_D_TAG -from elftools.elf.segments import InterpSegment -from elftools.elf.sections import SymbolTableSection -from elftools.elf.gnuversions import ( - GNUVerSymSection, GNUVerDefSection, - GNUVerNeedSection, -) -from elftools.elf.relocation import RelocationSection -from elftools.elf.descriptions import ( - describe_ei_class, describe_ei_data, describe_ei_version, - describe_ei_osabi, describe_e_type, describe_e_machine, - describe_e_version_numeric, describe_p_type, describe_p_flags, - describe_sh_type, describe_sh_flags, - describe_symbol_type, describe_symbol_bind, describe_symbol_visibility, - describe_symbol_shndx, describe_reloc_type, describe_dyn_tag, - describe_ver_flags, -) -from elftools.elf.constants import E_FLAGS -from elftools.dwarf.dwarfinfo import DWARFInfo -from elftools.dwarf.descriptions import ( - describe_reg_name, describe_attr_value, set_global_machine_arch, - describe_CFI_instructions, describe_CFI_register_rule, - describe_CFI_CFA_rule, -) -from elftools.dwarf.constants import ( - DW_LNS_copy, DW_LNS_set_file, DW_LNE_define_file) -from elftools.dwarf.callframe import CIE, FDE - -raw_output = False -pcidb = None - -# =========================================== - - -class Vendor: - """ - Class for vendors. This is the top level class - for the devices belong to a specific vendor. - self.devices is the device dictionary - subdevices are in each device. - """ - - def __init__(self, vendorStr): - """ - Class initializes with the raw line from pci.ids - Parsing takes place inside __init__ - """ - self.ID = vendorStr.split()[0] - self.name = vendorStr.replace("%s " % self.ID, "").rstrip() - self.devices = {} - - def addDevice(self, deviceStr): - """ - Adds a device to self.devices - takes the raw line from pci.ids - """ - s = deviceStr.strip() - devID = s.split()[0] - if devID in self.devices: - pass - else: - self.devices[devID] = Device(deviceStr) - - def report(self): - print self.ID, self.name - for id, dev in self.devices.items(): - dev.report() - - def find_device(self, devid): - # convert to a hex string and remove 0x - devid = hex(devid)[2:] - try: - return self.devices[devid] - except: - return Device("%s Unknown Device" % devid) - - -class Device: - - def __init__(self, deviceStr): - """ - Class for each device. - Each vendor has its own devices dictionary. - """ - s = deviceStr.strip() - self.ID = s.split()[0] - self.name = s.replace("%s " % self.ID, "") - self.subdevices = {} - - def report(self): - print "\t%s\t%s" % (self.ID, self.name) - for subID, subdev in self.subdevices.items(): - subdev.report() - - def addSubDevice(self, subDeviceStr): - """ - Adds a subvendor, subdevice to device. - Uses raw line from pci.ids - """ - s = subDeviceStr.strip() - spl = s.split() - subVendorID = spl[0] - subDeviceID = spl[1] - subDeviceName = s.split(" ")[-1] - devID = "%s:%s" % (subVendorID, subDeviceID) - self.subdevices[devID] = SubDevice( - subVendorID, subDeviceID, subDeviceName) - - def find_subid(self, subven, subdev): - subven = hex(subven)[2:] - subdev = hex(subdev)[2:] - devid = "%s:%s" % (subven, subdev) - - try: - return self.subdevices[devid] - except: - if (subven == "ffff" and subdev == "ffff"): - return SubDevice("ffff", "ffff", "(All Subdevices)") - else: - return SubDevice(subven, subdev, "(Unknown Subdevice)") - - -class SubDevice: - """ - Class for subdevices. - """ - - def __init__(self, vendor, device, name): - """ - Class initializes with vendorid, deviceid and name - """ - self.vendorID = vendor - self.deviceID = device - self.name = name - - def report(self): - print "\t\t%s\t%s\t%s" % (self.vendorID, self.deviceID, self.name) - - -class PCIIds: - """ - Top class for all pci.ids entries. - All queries will be asked to this class. - PCIIds.vendors["0e11"].devices["0046"].\ - subdevices["0e11:4091"].name = "Smart Array 6i" - """ - - def __init__(self, filename): - """ - Prepares the directories. - Checks local data file. - Tries to load from local, if not found, downloads from web - """ - self.version = "" - self.date = "" - self.vendors = {} - self.contents = None - self.readLocal(filename) - self.parse() - - def reportVendors(self): - """Reports the vendors - """ - for vid, v in self.vendors.items(): - print v.ID, v.name - - def report(self, vendor=None): - """ - Reports everything for all vendors or a specific vendor - PCIIds.report() reports everything - PCIIDs.report("0e11") reports only "Compaq Computer Corporation" - """ - if vendor is not None: - self.vendors[vendor].report() - else: - for vID, v in self.vendors.items(): - v.report() - - def find_vendor(self, vid): - # convert vid to a hex string and remove the 0x - vid = hex(vid)[2:] - - try: - return self.vendors[vid] - except: - return Vendor("%s Unknown Vendor" % (vid)) - - def findDate(self, content): - for l in content: - if l.find("Date:") > -1: - return l.split()[-2].replace("-", "") - return None - - def parse(self): - if len(self.contents) < 1: - print "data/%s-pci.ids not found" % self.date - else: - vendorID = "" - deviceID = "" - for l in self.contents: - if l[0] == "#": - continue - elif len(l.strip()) == 0: - continue - else: - if l.find("\t\t") == 0: - self.vendors[vendorID].devices[ - deviceID].addSubDevice(l) - elif l.find("\t") == 0: - deviceID = l.strip().split()[0] - self.vendors[vendorID].addDevice(l) - else: - vendorID = l.split()[0] - self.vendors[vendorID] = Vendor(l) - - def readLocal(self, filename): - """ - Reads the local file - """ - self.contents = open(filename).readlines() - self.date = self.findDate(self.contents) - - def loadLocal(self): - """ - Loads database from local. If there is no file, - it creates a new one from web - """ - self.date = idsfile[0].split("/")[1].split("-")[0] - self.readLocal() - - -# ======================================= - -def search_file(filename, search_path): - """ Given a search path, find file with requested name """ - for path in string.split(search_path, ":"): - candidate = os.path.join(path, filename) - if os.path.exists(candidate): - return os.path.abspath(candidate) - return None - - -class ReadElf(object): - """ display_* methods are used to emit output into the output stream - """ - - def __init__(self, file, output): - """ file: - stream object with the ELF file to read - - output: - output stream to write to - """ - self.elffile = ELFFile(file) - self.output = output - - # Lazily initialized if a debug dump is requested - self._dwarfinfo = None - - self._versioninfo = None - - def _section_from_spec(self, spec): - """ Retrieve a section given a "spec" (either number or name). - Return None if no such section exists in the file. - """ - try: - num = int(spec) - if num < self.elffile.num_sections(): - return self.elffile.get_section(num) - else: - return None - except ValueError: - # Not a number. Must be a name then - return self.elffile.get_section_by_name(str2bytes(spec)) - - def pretty_print_pmdinfo(self, pmdinfo): - global pcidb - - for i in pmdinfo["pci_ids"]: - vendor = pcidb.find_vendor(i[0]) - device = vendor.find_device(i[1]) - subdev = device.find_subid(i[2], i[3]) - print("%s (%s) : %s (%s) %s" % - (vendor.name, vendor.ID, device.name, - device.ID, subdev.name)) - - def parse_pmd_info_string(self, mystring): - global raw_output - global pcidb - - optional_pmd_info = [{'id': 'params', 'tag': 'PMD PARAMETERS'}] - - i = mystring.index("=") - mystring = mystring[i + 2:] - pmdinfo = json.loads(mystring) - - if raw_output: - print(json.dumps(pmdinfo)) - return - - print("PMD NAME: " + pmdinfo["name"]) - for i in optional_pmd_info: - try: - print("%s: %s" % (i['tag'], pmdinfo[i['id']])) - except KeyError as e: - continue - - if (len(pmdinfo["pci_ids"]) != 0): - print("PMD HW SUPPORT:") - if pcidb is not None: - self.pretty_print_pmdinfo(pmdinfo) - else: - print("VENDOR\t DEVICE\t SUBVENDOR\t SUBDEVICE") - for i in pmdinfo["pci_ids"]: - print("0x%04x\t 0x%04x\t 0x%04x\t\t 0x%04x" % - (i[0], i[1], i[2], i[3])) - - print("") - - def display_pmd_info_strings(self, section_spec): - """ Display a strings dump of a section. section_spec is either a - section number or a name. - """ - section = self._section_from_spec(section_spec) - if section is None: - return - - data = section.data() - dataptr = 0 - - while dataptr < len(data): - while (dataptr < len(data) and - not (32 <= byte2int(data[dataptr]) <= 127)): - dataptr += 1 - - if dataptr >= len(data): - break - - endptr = dataptr - while endptr < len(data) and byte2int(data[endptr]) != 0: - endptr += 1 - - mystring = bytes2str(data[dataptr:endptr]) - rc = mystring.find("PMD_INFO_STRING") - if (rc != -1): - self.parse_pmd_info_string(mystring) - - dataptr = endptr - - def find_librte_eal(self, section): - for tag in section.iter_tags(): - if tag.entry.d_tag == 'DT_NEEDED': - if "librte_eal" in tag.needed: - return tag.needed - return None - - def search_for_autoload_path(self): - scanelf = self - scanfile = None - library = None - - section = self._section_from_spec(".dynamic") - try: - eallib = self.find_librte_eal(section) - if eallib is not None: - ldlibpath = os.environ.get('LD_LIBRARY_PATH') - if ldlibpath is None: - ldlibpath = "" - dtr = self.get_dt_runpath(section) - library = search_file(eallib, - dtr + ":" + ldlibpath + - ":/usr/lib64:/lib64:/usr/lib:/lib") - if library is None: - return (None, None) - if raw_output is False: - print("Scanning for autoload path in %s" % library) - scanfile = open(library, 'rb') - scanelf = ReadElf(scanfile, sys.stdout) - except AttributeError: - # Not a dynamic binary - pass - except ELFError: - scanfile.close() - return (None, None) - - section = scanelf._section_from_spec(".rodata") - if section is None: - if scanfile is not None: - scanfile.close() - return (None, None) - - data = section.data() - dataptr = 0 - - while dataptr < len(data): - while (dataptr < len(data) and - not (32 <= byte2int(data[dataptr]) <= 127)): - dataptr += 1 - - if dataptr >= len(data): - break - - endptr = dataptr - while endptr < len(data) and byte2int(data[endptr]) != 0: - endptr += 1 - - mystring = bytes2str(data[dataptr:endptr]) - rc = mystring.find("DPDK_PLUGIN_PATH") - if (rc != -1): - rc = mystring.find("=") - return (mystring[rc + 1:], library) - - dataptr = endptr - if scanfile is not None: - scanfile.close() - return (None, None) - - def get_dt_runpath(self, dynsec): - for tag in dynsec.iter_tags(): - if tag.entry.d_tag == 'DT_RUNPATH': - return tag.runpath - return "" - - def process_dt_needed_entries(self): - """ Look to see if there are any DT_NEEDED entries in the binary - And process those if there are - """ - global raw_output - runpath = "" - ldlibpath = os.environ.get('LD_LIBRARY_PATH') - if ldlibpath is None: - ldlibpath = "" - - dynsec = self._section_from_spec(".dynamic") - try: - runpath = self.get_dt_runpath(dynsec) - except AttributeError: - # dynsec is None, just return - return - - for tag in dynsec.iter_tags(): - if tag.entry.d_tag == 'DT_NEEDED': - rc = tag.needed.find("librte_pmd") - if (rc != -1): - library = search_file(tag.needed, - runpath + ":" + ldlibpath + - ":/usr/lib64:/lib64:/usr/lib:/lib") - if library is not None: - if raw_output is False: - print("Scanning %s for pmd information" % library) - with open(library, 'rb') as file: - try: - libelf = ReadElf(file, sys.stdout) - except ELFError as e: - print("%s is no an ELF file" % library) - continue - libelf.process_dt_needed_entries() - libelf.display_pmd_info_strings(".rodata") - file.close() - - -def scan_autoload_path(autoload_path): - global raw_output - - if os.path.exists(autoload_path) is False: - return - - try: - dirs = os.listdir(autoload_path) - except OSError as e: - # Couldn't read the directory, give up - return - - for d in dirs: - dpath = os.path.join(autoload_path, d) - if os.path.isdir(dpath): - scan_autoload_path(dpath) - if os.path.isfile(dpath): - try: - file = open(dpath, 'rb') - readelf = ReadElf(file, sys.stdout) - except ELFError as e: - # this is likely not an elf file, skip it - continue - except IOError as e: - # No permission to read the file, skip it - continue - - if raw_output is False: - print("Hw Support for library %s" % d) - readelf.display_pmd_info_strings(".rodata") - file.close() - - -def scan_for_autoload_pmds(dpdk_path): - """ - search the specified application or path for a pmd autoload path - then scan said path for pmds and report hw support - """ - global raw_output - - if (os.path.isfile(dpdk_path) is False): - if raw_output is False: - print("Must specify a file name") - return - - file = open(dpdk_path, 'rb') - try: - readelf = ReadElf(file, sys.stdout) - except ElfError as e: - if raw_output is False: - print("Unable to parse %s" % file) - return - - (autoload_path, scannedfile) = readelf.search_for_autoload_path() - if (autoload_path is None or autoload_path is ""): - if (raw_output is False): - print("No autoload path configured in %s" % dpdk_path) - return - if (raw_output is False): - if (scannedfile is None): - scannedfile = dpdk_path - print("Found autoload path %s in %s" % (autoload_path, scannedfile)) - - file.close() - if (raw_output is False): - print("Discovered Autoload HW Support:") - scan_autoload_path(autoload_path) - return - - -def main(stream=None): - global raw_output - global pcidb - - pcifile_default = "./pci.ids" # for unknown OS's assume local file - if platform.system() == 'Linux': - pcifile_default = "/usr/share/hwdata/pci.ids" - elif platform.system() == 'FreeBSD': - pcifile_default = "/usr/local/share/pciids/pci.ids" - if not os.path.exists(pcifile_default): - pcifile_default = "/usr/share/misc/pci_vendors" - - optparser = OptionParser( - usage='usage: %prog [-hrtp] [-d <pci id file] <elf-file>', - description="Dump pmd hardware support info", - add_help_option=True) - optparser.add_option('-r', '--raw', - action='store_true', dest='raw_output', - help='Dump raw json strings') - optparser.add_option("-d", "--pcidb", dest="pcifile", - help="specify a pci database " - "to get vendor names from", - default=pcifile_default, metavar="FILE") - optparser.add_option("-t", "--table", dest="tblout", - help="output information on hw support as a hex table", - action='store_true') - optparser.add_option("-p", "--plugindir", dest="pdir", - help="scan dpdk for autoload plugins", - action='store_true') - - options, args = optparser.parse_args() - - if options.raw_output: - raw_output = True - - if options.pcifile: - pcidb = PCIIds(options.pcifile) - if pcidb is None: - print("Pci DB file not found") - exit(1) - - if options.tblout: - options.pcifile = None - pcidb = None - - if (len(args) == 0): - optparser.print_usage() - exit(1) - - if options.pdir is True: - exit(scan_for_autoload_pmds(args[0])) - - ldlibpath = os.environ.get('LD_LIBRARY_PATH') - if (ldlibpath is None): - ldlibpath = "" - - if (os.path.exists(args[0]) is True): - myelffile = args[0] - else: - myelffile = search_file( - args[0], ldlibpath + ":/usr/lib64:/lib64:/usr/lib:/lib") - - if (myelffile is None): - print("File not found") - sys.exit(1) - - with open(myelffile, 'rb') as file: - try: - readelf = ReadElf(file, sys.stdout) - readelf.process_dt_needed_entries() - readelf.display_pmd_info_strings(".rodata") - sys.exit(0) - - except ELFError as ex: - sys.stderr.write('ELF error: %s\n' % ex) - sys.exit(1) - - -# ------------------------------------------------------------------------- -if __name__ == '__main__': - main() |