summaryrefslogtreecommitdiffstats
path: root/tools/dpdk-pmdinfo.py
diff options
context:
space:
mode:
authorChristian Ehrhardt <christian.ehrhardt@canonical.com>2017-05-16 14:51:32 +0200
committerChristian Ehrhardt <christian.ehrhardt@canonical.com>2017-05-16 16:20:45 +0200
commit7595afa4d30097c1177b69257118d8ad89a539be (patch)
tree4bfeadc905c977e45e54a90c42330553b8942e4e /tools/dpdk-pmdinfo.py
parentce3d555e43e3795b5d9507fcfc76b7a0a92fd0d6 (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-xtools/dpdk-pmdinfo.py636
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()