get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/12886/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 12886,
    "url": "http://patches.dpdk.org/api/patches/12886/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1463605687-649-2-git-send-email-nhorman@tuxdriver.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1463605687-649-2-git-send-email-nhorman@tuxdriver.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1463605687-649-2-git-send-email-nhorman@tuxdriver.com",
    "date": "2016-05-18T21:08:04",
    "name": "[dpdk-dev,PATCHv2,1/4] pmdinfogen: Add buildtools and pmdinfogen utility",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "ff88ab9839c371726890986a55c900b8681d204c",
    "submitter": {
        "id": 32,
        "url": "http://patches.dpdk.org/api/people/32/?format=api",
        "name": "Neil Horman",
        "email": "nhorman@tuxdriver.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1463605687-649-2-git-send-email-nhorman@tuxdriver.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/12886/comments/",
    "check": "pending",
    "checks": "http://patches.dpdk.org/api/patches/12886/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 5D7BB95D3;\n\tWed, 18 May 2016 23:08:39 +0200 (CEST)",
            "from smtp.tuxdriver.com (charlotte.tuxdriver.com [70.61.120.58])\n\tby dpdk.org (Postfix) with ESMTP id 1441B68FC\n\tfor <dev@dpdk.org>; Wed, 18 May 2016 23:08:38 +0200 (CEST)",
            "from hmsreliant.think-freely.org\n\t([2001:470:8:a08:7aac:c0ff:fec2:933b] helo=localhost)\n\tby smtp.tuxdriver.com with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.63)\n\t(envelope-from <nhorman@tuxdriver.com>)\n\tid 1b38hh-0001IQ-Me; Wed, 18 May 2016 17:08:35 -0400"
        ],
        "From": "Neil Horman <nhorman@tuxdriver.com>",
        "To": "dev@dpdk.org",
        "Cc": "Neil Horman <nhorman@tuxdriver.com>,\n\tBruce Richardson <bruce.richardson@intel.com>,\n\tThomas Monjalon <thomas.monjalon@6wind.com>,\n\tStephen Hemminger <stephen@networkplumber.org>,\n\tPanu Matilainen <pmatilai@redhat.com>",
        "Date": "Wed, 18 May 2016 17:08:04 -0400",
        "Message-Id": "<1463605687-649-2-git-send-email-nhorman@tuxdriver.com>",
        "X-Mailer": "git-send-email 2.5.5",
        "In-Reply-To": "<1463605687-649-1-git-send-email-nhorman@tuxdriver.com>",
        "References": "<1463431287-4551-1-git-send-email-nhorman@tuxdriver.com>\n\t<1463605687-649-1-git-send-email-nhorman@tuxdriver.com>",
        "X-Spam-Score": "-1.0 (-)",
        "X-Spam-Status": "No",
        "Subject": "[dpdk-dev] [PATCHv2 1/4] pmdinfogen: Add buildtools and pmdinfogen\n\tutility",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "pmdinfogen is a tool used to parse object files and build json strings for use in\nlater determining hardware support in a dso or application binary.  pmdinfo\nlooks for the non-exported symbol names this_pmd_name<n> and this_pmd_tbl<n>\n(where n is a integer counter).  It records the name of each of these tuples,\nusing the later to find the symbolic name of the pci_table for physical devices\nthat the object supports.  With this information, it outputs a C file with a\nsingle line of the form:\n\nstatic char *<pmd_name>_driver_info[] __attribute__((used)) = \" \\\n\tPMD_DRIVER_INFO=<json string>\";\n\nWhere <pmd_name> is the arbitrary name of the pmd, and <json_string> is the json\nencoded string that hold relevant pmd information, including the pmd name, type\nand optional array of pci device/vendor ids that the driver supports.\n\nThis c file is suitable for compiling to object code, then relocatably linking\ninto the parent file from which the C was generated.  This creates an entry in\nthe string table of the object that can inform a later tool about hardware\nsupport.\n\nSigned-off-by: Neil Horman <nhorman@tuxdriver.com>\nCC: Bruce Richardson <bruce.richardson@intel.com>\nCC: Thomas Monjalon <thomas.monjalon@6wind.com>\nCC: Stephen Hemminger <stephen@networkplumber.org>\nCC: Panu Matilainen <pmatilai@redhat.com>\n---\n GNUmakefile                        |   2 +-\n buildtools/Makefile                |  36 ++++\n buildtools/pmdinfogen/Makefile     |  48 +++++\n buildtools/pmdinfogen/pmdinfogen.c | 430 +++++++++++++++++++++++++++++++++++++\n buildtools/pmdinfogen/pmdinfogen.h |  83 +++++++\n mk/rte.buildtools.mk               | 148 +++++++++++++\n mk/rte.sdkbuild.mk                 |   3 +-\n 7 files changed, 748 insertions(+), 2 deletions(-)\n create mode 100644 buildtools/Makefile\n create mode 100644 buildtools/pmdinfogen/Makefile\n create mode 100644 buildtools/pmdinfogen/pmdinfogen.c\n create mode 100644 buildtools/pmdinfogen/pmdinfogen.h\n create mode 100644 mk/rte.buildtools.mk",
    "diff": "diff --git a/GNUmakefile b/GNUmakefile\nindex b59e4b6..00fe0db 100644\n--- a/GNUmakefile\n+++ b/GNUmakefile\n@@ -40,6 +40,6 @@ export RTE_SDK\n # directory list\n #\n \n-ROOTDIRS-y := lib drivers app\n+ROOTDIRS-y := buildtools lib drivers app\n \n include $(RTE_SDK)/mk/rte.sdkroot.mk\ndiff --git a/buildtools/Makefile b/buildtools/Makefile\nnew file mode 100644\nindex 0000000..eb565eb\n--- /dev/null\n+++ b/buildtools/Makefile\n@@ -0,0 +1,36 @@\n+#   BSD LICENSE\n+#\n+#   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+#   All rights reserved.\n+#\n+#   Redistribution and use in source and binary forms, with or without\n+#   modification, are permitted provided that the following conditions\n+#   are met:\n+#\n+#     * Redistributions of source code must retain the above copyright\n+#       notice, this list of conditions and the following disclaimer.\n+#     * Redistributions in binary form must reproduce the above copyright\n+#       notice, this list of conditions and the following disclaimer in\n+#       the documentation and/or other materials provided with the\n+#       distribution.\n+#     * Neither the name of Intel Corporation nor the names of its\n+#       contributors may be used to endorse or promote products derived\n+#       from this software without specific prior written permission.\n+#\n+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+#   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+\n+DIRS-y += pmdinfogen\n+\n+include $(RTE_SDK)/mk/rte.subdir.mk\ndiff --git a/buildtools/pmdinfogen/Makefile b/buildtools/pmdinfogen/Makefile\nnew file mode 100644\nindex 0000000..4de9506\n--- /dev/null\n+++ b/buildtools/pmdinfogen/Makefile\n@@ -0,0 +1,48 @@\n+#   BSD LICENSE\n+#\n+#   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.\n+#   All rights reserved.\n+#\n+#   Redistribution and use in source and binary forms, with or without\n+#   modification, are permitted provided that the following conditions\n+#   are met:\n+#\n+#     * Redistributions of source code must retain the above copyright\n+#       notice, this list of conditions and the following disclaimer.\n+#     * Redistributions in binary form must reproduce the above copyright\n+#       notice, this list of conditions and the following disclaimer in\n+#       the documentation and/or other materials provided with the\n+#       distribution.\n+#     * Neither the name of Intel Corporation nor the names of its\n+#       contributors may be used to endorse or promote products derived\n+#       from this software without specific prior written permission.\n+#\n+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+#   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+\n+#\n+# library name\n+#\n+APP = pmdinfogen\n+\n+#\n+# all sources are stored in SRCS-y\n+#\n+SRCS-y += pmdinfogen.c\n+\n+#CFLAGS += $(WERROR_FLAGS) -g\n+CFLAGS += -g\n+\n+include $(RTE_SDK)/mk/rte.buildtools.mk\n+\ndiff --git a/buildtools/pmdinfogen/pmdinfogen.c b/buildtools/pmdinfogen/pmdinfogen.c\nnew file mode 100644\nindex 0000000..9183937\n--- /dev/null\n+++ b/buildtools/pmdinfogen/pmdinfogen.c\n@@ -0,0 +1,430 @@\n+/* Postprocess pmd object files to export hw support \n+ *\n+ * Copyright 2016 Neil Horman <nhorman@tuxdriver.com>\n+ * Based in part on modpost.c from the linux kernel\n+ *\n+ * This software may be used and distributed according to the terms\n+ * of the GNU General Public License V2, incorporated herein by reference.\n+ *\n+ */\n+\n+#define _GNU_SOURCE\n+#include <stdio.h>\n+#include <ctype.h>\n+#include <string.h>\n+#include <limits.h>\n+#include <stdbool.h>\n+#include <errno.h>\n+#include \"pmdinfogen.h\"\n+\n+\n+static const char *sym_name(struct elf_info *elf, Elf_Sym *sym)\n+{\n+\tif (sym)\n+\t\treturn elf->strtab + sym->st_name;\n+\telse\n+\t\treturn \"(unknown)\";\n+}\n+\n+void *grab_file(const char *filename, unsigned long *size)\n+{\n+\tstruct stat st;\n+\tvoid *map = MAP_FAILED;\n+\tint fd;\n+\n+\tfd = open(filename, O_RDONLY);\n+\tif (fd < 0)\n+\t\treturn NULL;\n+\tif (fstat(fd, &st))\n+\t\tgoto failed;\n+\n+\t*size = st.st_size;\n+\tmap = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);\n+\n+failed:\n+\tclose(fd);\n+\tif (map == MAP_FAILED)\n+\t\treturn NULL;\n+\treturn map;\n+}\n+\n+/**\n+  * Return a copy of the next line in a mmap'ed file.\n+  * spaces in the beginning of the line is trimmed away.\n+  * Return a pointer to a static buffer.\n+  **/\n+void release_file(void *file, unsigned long size)\n+{\n+\tmunmap(file, size);\n+}\n+\n+\n+static void *get_sym_value(struct elf_info *info, const Elf_Sym *sym)\n+{\n+\tvoid *ptr = (void *)info->hdr + info->sechdrs[sym->st_shndx].sh_offset;\n+\n+\treturn (void *)(ptr + sym->st_value);\n+}\n+\n+static Elf_Sym *find_sym_in_symtab(struct elf_info *info, \n+\t\t\t\t   const char *name, Elf_Sym *last)\n+{\n+\tElf_Sym *idx;\n+\tif (last)\n+\t\tidx = last+1;\n+\telse\n+\t\tidx = info->symtab_start;\n+\n+\tfor(; idx < info->symtab_stop; idx++) {\n+\t\tconst char *n = sym_name(info, idx);\n+\t\tif (!strncmp(n, name, strlen(name)))\n+\t\t\treturn idx;\n+\t}\n+\treturn NULL;\n+}\n+\n+static int parse_elf(struct elf_info *info, const char *filename)\n+{\n+\tunsigned int i;\n+\tElf_Ehdr *hdr;\n+\tElf_Shdr *sechdrs;\n+\tElf_Sym  *sym;\n+\tconst char *secstrings;\n+\tunsigned int symtab_idx = ~0U, symtab_shndx_idx = ~0U;\n+\n+\thdr = grab_file(filename, &info->size);\n+\tif (!hdr) {\n+\t\tperror(filename);\n+\t\texit(1);\n+\t}\n+\tinfo->hdr = hdr;\n+\tif (info->size < sizeof(*hdr)) {\n+\t\t/* file too small, assume this is an empty .o file */\n+\t\treturn 0;\n+\t}\n+\t/* Is this a valid ELF file? */\n+\tif ((hdr->e_ident[EI_MAG0] != ELFMAG0) ||\n+\t    (hdr->e_ident[EI_MAG1] != ELFMAG1) ||\n+\t    (hdr->e_ident[EI_MAG2] != ELFMAG2) ||\n+\t    (hdr->e_ident[EI_MAG3] != ELFMAG3)) {\n+\t\t/* Not an ELF file - silently ignore it */\n+\t\treturn 0;\n+\t}\n+\t/* Fix endianness in ELF header */\n+\thdr->e_type      = TO_NATIVE(hdr->e_type);\n+\thdr->e_machine   = TO_NATIVE(hdr->e_machine);\n+\thdr->e_version   = TO_NATIVE(hdr->e_version);\n+\thdr->e_entry     = TO_NATIVE(hdr->e_entry);\n+\thdr->e_phoff     = TO_NATIVE(hdr->e_phoff);\n+\thdr->e_shoff     = TO_NATIVE(hdr->e_shoff);\n+\thdr->e_flags     = TO_NATIVE(hdr->e_flags);\n+\thdr->e_ehsize    = TO_NATIVE(hdr->e_ehsize);\n+\thdr->e_phentsize = TO_NATIVE(hdr->e_phentsize);\n+\thdr->e_phnum     = TO_NATIVE(hdr->e_phnum);\n+\thdr->e_shentsize = TO_NATIVE(hdr->e_shentsize);\n+\thdr->e_shnum     = TO_NATIVE(hdr->e_shnum);\n+\thdr->e_shstrndx  = TO_NATIVE(hdr->e_shstrndx);\n+\tsechdrs = (void *)hdr + hdr->e_shoff;\n+\tinfo->sechdrs = sechdrs;\n+\n+\t/* Check if file offset is correct */\n+\tif (hdr->e_shoff > info->size) {\n+\t\tfprintf(stderr, \"section header offset=%lu in file '%s' is bigger than \"\n+\t\t      \"filesize=%lu\\n\", (unsigned long)hdr->e_shoff,\n+\t\t      filename, info->size);\n+\t\treturn 0;\n+\t}\n+\n+\tif (hdr->e_shnum == SHN_UNDEF) {\n+\t\t/*\n+\t\t * There are more than 64k sections,\n+\t\t * read count from .sh_size.\n+\t\t */\n+\t\tinfo->num_sections = TO_NATIVE(sechdrs[0].sh_size);\n+\t}\n+\telse {\n+\t\tinfo->num_sections = hdr->e_shnum;\n+\t}\n+\tif (hdr->e_shstrndx == SHN_XINDEX) {\n+\t\tinfo->secindex_strings = TO_NATIVE(sechdrs[0].sh_link);\n+\t}\n+\telse {\n+\t\tinfo->secindex_strings = hdr->e_shstrndx;\n+\t}\n+\n+\t/* Fix endianness in section headers */\n+\tfor (i = 0; i < info->num_sections; i++) {\n+\t\tsechdrs[i].sh_name      = TO_NATIVE(sechdrs[i].sh_name);\n+\t\tsechdrs[i].sh_type      = TO_NATIVE(sechdrs[i].sh_type);\n+\t\tsechdrs[i].sh_flags     = TO_NATIVE(sechdrs[i].sh_flags);\n+\t\tsechdrs[i].sh_addr      = TO_NATIVE(sechdrs[i].sh_addr);\n+\t\tsechdrs[i].sh_offset    = TO_NATIVE(sechdrs[i].sh_offset);\n+\t\tsechdrs[i].sh_size      = TO_NATIVE(sechdrs[i].sh_size);\n+\t\tsechdrs[i].sh_link      = TO_NATIVE(sechdrs[i].sh_link);\n+\t\tsechdrs[i].sh_info      = TO_NATIVE(sechdrs[i].sh_info);\n+\t\tsechdrs[i].sh_addralign = TO_NATIVE(sechdrs[i].sh_addralign);\n+\t\tsechdrs[i].sh_entsize   = TO_NATIVE(sechdrs[i].sh_entsize);\n+\t}\n+\t/* Find symbol table. */\n+\tsecstrings = (void *)hdr + sechdrs[info->secindex_strings].sh_offset;\n+\tfor (i = 1; i < info->num_sections; i++) {\n+\t\tconst char *secname;\n+\t\tint nobits = sechdrs[i].sh_type == SHT_NOBITS;\n+\n+\t\tif (!nobits && sechdrs[i].sh_offset > info->size) {\n+\t\t\tfprintf(stderr, \"%s is truncated. sechdrs[i].sh_offset=%lu > \"\n+\t\t\t      \"sizeof(*hrd)=%zu\\n\", filename,\n+\t\t\t      (unsigned long)sechdrs[i].sh_offset,\n+\t\t\t      sizeof(*hdr));\n+\t\t\treturn 0;\n+\t\t}\n+\t\tsecname = secstrings + sechdrs[i].sh_name;\n+\t\tif (strcmp(secname, \".modinfo\") == 0) {\n+\t\t\tif (nobits)\n+\t\t\t\tfprintf(stderr, \"%s has NOBITS .modinfo\\n\", filename);\n+\t\t\tinfo->modinfo = (void *)hdr + sechdrs[i].sh_offset;\n+\t\t\tinfo->modinfo_len = sechdrs[i].sh_size;\n+\t\t} else if (strcmp(secname, \"__ksymtab\") == 0)\n+\t\t\tinfo->export_sec = i;\n+\t\telse if (strcmp(secname, \"__ksymtab_unused\") == 0)\n+\t\t\tinfo->export_unused_sec = i;\n+\t\telse if (strcmp(secname, \"__ksymtab_gpl\") == 0)\n+\t\t\tinfo->export_gpl_sec = i;\n+\t\telse if (strcmp(secname, \"__ksymtab_unused_gpl\") == 0)\n+\t\t\tinfo->export_unused_gpl_sec = i;\n+\t\telse if (strcmp(secname, \"__ksymtab_gpl_future\") == 0)\n+\t\t\tinfo->export_gpl_future_sec = i;\n+\n+\t\tif (sechdrs[i].sh_type == SHT_SYMTAB) {\n+\t\t\tunsigned int sh_link_idx;\n+\t\t\tsymtab_idx = i;\n+\t\t\tinfo->symtab_start = (void *)hdr +\n+\t\t\t    sechdrs[i].sh_offset;\n+\t\t\tinfo->symtab_stop  = (void *)hdr +\n+\t\t\t    sechdrs[i].sh_offset + sechdrs[i].sh_size;\n+\t\t\tsh_link_idx = sechdrs[i].sh_link;\n+\t\t\tinfo->strtab       = (void *)hdr +\n+\t\t\t    sechdrs[sh_link_idx].sh_offset;\n+\t\t}\n+\n+\t\t/* 32bit section no. table? (\"more than 64k sections\") */\n+\t\tif (sechdrs[i].sh_type == SHT_SYMTAB_SHNDX) {\n+\t\t\tsymtab_shndx_idx = i;\n+\t\t\tinfo->symtab_shndx_start = (void *)hdr +\n+\t\t\t    sechdrs[i].sh_offset;\n+\t\t\tinfo->symtab_shndx_stop  = (void *)hdr +\n+\t\t\t    sechdrs[i].sh_offset + sechdrs[i].sh_size;\n+\t\t}\n+\t}\n+\tif (!info->symtab_start)\n+\t\tfprintf(stderr, \"%s has no symtab?\\n\", filename);\n+\n+\t/* Fix endianness in symbols */\n+\tfor (sym = info->symtab_start; sym < info->symtab_stop; sym++) {\n+\t\tsym->st_shndx = TO_NATIVE(sym->st_shndx);\n+\t\tsym->st_name  = TO_NATIVE(sym->st_name);\n+\t\tsym->st_value = TO_NATIVE(sym->st_value);\n+\t\tsym->st_size  = TO_NATIVE(sym->st_size);\n+\t}\n+\n+\tif (symtab_shndx_idx != ~0U) {\n+\t\tElf32_Word *p;\n+\t\tif (symtab_idx != sechdrs[symtab_shndx_idx].sh_link)\n+\t\t\tfprintf(stderr, \"%s: SYMTAB_SHNDX has bad sh_link: %u!=%u\\n\",\n+\t\t\t      filename, sechdrs[symtab_shndx_idx].sh_link,\n+\t\t\t      symtab_idx);\n+\t\t/* Fix endianness */\n+\t\tfor (p = info->symtab_shndx_start; p < info->symtab_shndx_stop;\n+\t\t     p++)\n+\t\t\t*p = TO_NATIVE(*p);\n+\t}\n+\n+\treturn 1;\n+}\n+\n+static void parse_elf_finish(struct elf_info *info)\n+{\n+\tstruct pmd_driver *tmp, *idx = info->drivers;\n+\trelease_file(info->hdr, info->size);\n+\twhile (idx) {\n+\t\ttmp = idx->next;\n+\t\tfree(idx);\n+\t\tidx = tmp;\n+\t}\n+}\n+\n+static const char *sec_name(struct elf_info *elf, int secindex)\n+{\n+\tElf_Shdr *sechdrs = elf->sechdrs;\n+\treturn (void *)elf->hdr +\n+\t\telf->sechdrs[elf->secindex_strings].sh_offset +\n+\t\tsechdrs[secindex].sh_name;\n+}\n+\n+static int get_symbol_index(struct elf_info *info, Elf64_Sym *sym)\n+{\n+\tconst char *name =  sym_name(info, sym);\n+\tconst char *idx;\n+\n+\tidx = name;\n+\twhile (idx) {\n+\t\tif (isdigit(*idx))\n+\t\t\treturn atoi(idx);\n+\t\tidx++;\n+\t}\n+\treturn -1;\n+}\n+\n+struct opt_tag {\n+\tconst char* suffix;\n+\tconst char* json_id;\n+};\n+\n+static const struct opt_tag opt_tags[] = {\n+\t{\"_param_string_export\", \"params\"},\n+};\n+\n+static int complete_pmd_entry(struct elf_info *info, struct pmd_driver *drv)\n+{\n+\tconst char *tname;\n+\tint i;\n+\tchar tmpsymname[128];\n+\tElf_Sym *tmpsym;\n+\t\n+\n+\tdrv->name = get_sym_value(info, drv->name_sym);\n+\n+\tfor (i=0; i<PMD_OPT_MAX; i++) {\n+\t\tmemset(tmpsymname, 0, 128);\n+\t\tsprintf(tmpsymname, \"%s%s\", drv->name, opt_tags[i].suffix);\n+\t\ttmpsym = find_sym_in_symtab(info, tmpsymname, NULL);\n+\t\tif (!tmpsym)\n+\t\t\tcontinue;\n+\t\tdrv->opt_vals[i] = get_sym_value(info, tmpsym);\n+\t}\n+\n+\tmemset(tmpsymname, 0, 128);\n+\tsprintf(tmpsymname, \"%s_pci_tbl_export\", drv->name);\n+\n+\ttmpsym = find_sym_in_symtab(info, tmpsymname, NULL);\n+\n+\n+\t/*\n+ \t * If this returns NULL, then this is a PMD_VDEV, because\n+ \t * it has no pci table reference\n+ \t */\n+\tif (!tmpsym) {\n+\t\tdrv->pci_tbl = NULL;\n+\t\treturn 0;\n+\t}\n+\n+\ttname = get_sym_value(info, tmpsym);\n+\ttmpsym = find_sym_in_symtab(info, tname, NULL);\n+\tif (!tmpsym)\n+\t\treturn -ENOENT;\n+\n+\tdrv->pci_tbl = (struct rte_pci_id *)get_sym_value(info, tmpsym);\n+\tif (!drv->pci_tbl)\n+\t\treturn -ENOENT;\n+\n+\n+\treturn 0;\n+\t\n+}\n+\n+static int locate_pmd_entries(struct elf_info *info)\n+{\n+\tElf_Sym *last = NULL;\n+\tstruct pmd_driver *new;\n+\n+\tinfo->drivers = NULL;\n+\n+\tdo {\n+\t\tnew = calloc(sizeof(struct pmd_driver), 1);\n+\t\tnew->name_sym = find_sym_in_symtab(info, \"this_pmd_name\", last);\n+\t\tlast = new->name_sym;\n+\t\tif (!new->name_sym)\n+\t\t\tfree(new);\n+\t\telse {\n+\t\t\tif (complete_pmd_entry(info, new)) {\n+\t\t\t\tfprintf(stderr, \"Failed to complete pmd entry\\n\");\n+\t\t\t\tfree(new);\n+\t\t\t} else {\n+\t\t\t\tnew->next = info->drivers;\n+\t\t\t\tinfo->drivers = new;\n+\t\t\t}\n+\t\t}\n+\t} while (last);\n+}\n+\n+static void output_pmd_info_string(struct elf_info *info, char *outfile)\n+{\n+\tFILE *ofd;\n+\tstruct pmd_driver *drv;\n+\tstruct rte_pci_id *pci_ids;\n+\tint idx = 0;\n+\n+\tofd = fopen(outfile, \"w+\");\n+\tif (!ofd) {\n+\t\tfprintf(stderr, \"Unable to open output file\\n\");\n+\t\treturn;\n+\t}\n+\n+\tdrv = info->drivers;\n+\n+\twhile (drv) {\n+\t\tfprintf(ofd, \"const char %s_pmd_info[] __attribute__((used)) = \\\"PMD_INFO_STRING= {\",\n+\t\t\tdrv->name);\n+\t\tfprintf(ofd,\"\\\\\\\"name\\\\\\\" : \\\\\\\"%s\\\\\\\", \", drv->name);\n+\t\tfprintf(ofd,\"\\\\\\\"type\\\\\\\" : \\\\\\\"%s\\\\\\\", \", drv->pci_tbl ? \"PMD_PDEV\" : \"PMD_VDEV\");\n+\n+\t\tfor(idx=0; idx<PMD_OPT_MAX; idx++) {\n+\t\t\tif (drv->opt_vals[idx])\n+\t\t\t\tfprintf(ofd,\"\\\\\\\"%s\\\\\\\" : \\\\\\\"%s\\\\\\\", \", opt_tags[idx].json_id,\n+\t\t\t\t\tdrv->opt_vals[idx]);\n+\t\t}\n+\n+\t\tpci_ids = drv->pci_tbl;\n+\t\tfprintf(ofd, \"\\\\\\\"pci_ids\\\\\\\" : [\");\n+\n+\t\twhile (pci_ids && pci_ids->device_id) {\n+\t\t\tfprintf(ofd, \"[%d, %d, %d, %d]\",\n+\t\t\t\tpci_ids->vendor_id, pci_ids->device_id,\n+\t\t\t\tpci_ids->subsystem_vendor_id,\n+\t\t\t\tpci_ids->subsystem_device_id);\n+\t\t\tpci_ids++;\n+\t\t\tif (pci_ids->device_id)\n+\t\t\t\tfprintf(ofd, \",\");\n+\t\t\telse\n+\t\t\t\tfprintf(ofd, \" \");\n+\t\t}\n+\t\tfprintf(ofd, \"]}\\\";\");\n+\t\tdrv = drv->next;\n+\t}\n+\n+\tfclose(ofd);\n+}\n+\n+int main(int argc, char **argv)\n+{\n+\tstruct elf_info info;\n+\tint rc = 1;\n+\n+\tif (argc < 3) {\n+\t\tfprintf(stderr, \"usage: pmdinfo <object file> <c output file>\\n\");\n+\t\texit(127);\n+\t}\n+\tparse_elf(&info, argv[1]);\n+\n+\tlocate_pmd_entries(&info);\n+\n+\tif (info.drivers) {\n+\t\toutput_pmd_info_string(&info, argv[2]);\n+\t\trc = 0;\n+\t} else {\n+\t\tfprintf(stderr, \"Hmm, Appears to be a driver but no drivers registered\\n\");\n+\t}\n+\n+\tparse_elf_finish(&info);\n+\texit(rc);\n+}\ndiff --git a/buildtools/pmdinfogen/pmdinfogen.h b/buildtools/pmdinfogen/pmdinfogen.h\nnew file mode 100644\nindex 0000000..580ed9f\n--- /dev/null\n+++ b/buildtools/pmdinfogen/pmdinfogen.h\n@@ -0,0 +1,83 @@\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <stdarg.h>\n+#include <string.h>\n+#include <sys/types.h>\n+#include <sys/stat.h>\n+#include <sys/mman.h>\n+#include <fcntl.h>\n+#include <unistd.h>\n+#include <elf.h>\n+\n+\n+/* On BSD-alike OSes elf.h defines these according to host's word size */\n+#undef ELF_ST_BIND\n+#undef ELF_ST_TYPE\n+#undef ELF_R_SYM\n+#undef ELF_R_TYPE\n+\n+#define Elf_Ehdr    Elf64_Ehdr\n+#define Elf_Shdr    Elf64_Shdr\n+#define Elf_Sym     Elf64_Sym\n+#define Elf_Addr    Elf64_Addr\n+#define Elf_Sword   Elf64_Sxword\n+#define Elf_Section Elf64_Half\n+#define ELF_ST_BIND ELF64_ST_BIND\n+#define ELF_ST_TYPE ELF64_ST_TYPE\n+\n+#define Elf_Rel     Elf64_Rel\n+#define Elf_Rela    Elf64_Rela\n+#define ELF_R_SYM   ELF64_R_SYM\n+#define ELF_R_TYPE  ELF64_R_TYPE\n+\n+#define TO_NATIVE(x) (x)\n+\n+\n+struct rte_pci_id {\n+\tuint16_t vendor_id;           /**< Vendor ID or PCI_ANY_ID. */\n+\tuint16_t device_id;           /**< Device ID or PCI_ANY_ID. */\n+\tuint16_t subsystem_vendor_id; /**< Subsystem vendor ID or PCI_ANY_ID. */\n+\tuint16_t subsystem_device_id; /**< Subsystem device ID or PCI_ANY_ID. */\n+};\n+\n+enum opt_params {\n+\tPMD_PARAM_STRING = 0,\n+\tPMD_OPT_MAX\n+};\n+\n+struct pmd_driver {\n+\tElf_Sym *name_sym;\n+\tconst char *name;\n+\tstruct rte_pci_id *pci_tbl;\n+\tstruct pmd_driver *next;\n+\n+\tconst char* opt_vals[PMD_OPT_MAX];\n+};\n+\n+struct elf_info {\n+\tunsigned long size;\n+\tElf_Ehdr     *hdr;\n+\tElf_Shdr     *sechdrs;\n+\tElf_Sym      *symtab_start;\n+\tElf_Sym      *symtab_stop;\n+\tElf_Section  export_sec;\n+\tElf_Section  export_unused_sec;\n+\tElf_Section  export_gpl_sec;\n+\tElf_Section  export_unused_gpl_sec;\n+\tElf_Section  export_gpl_future_sec;\n+\tchar         *strtab;\n+\tchar\t     *modinfo;\n+\tunsigned int modinfo_len;\n+\n+\t/* support for 32bit section numbers */\n+\n+\tunsigned int num_sections; /* max_secindex + 1 */\n+\tunsigned int secindex_strings;\n+\t/* if Nth symbol table entry has .st_shndx = SHN_XINDEX,\n+\t * take shndx from symtab_shndx_start[N] instead */\n+\tElf32_Word   *symtab_shndx_start;\n+\tElf32_Word   *symtab_shndx_stop;\n+\n+\tstruct pmd_driver *drivers;\n+};\n+\ndiff --git a/mk/rte.buildtools.mk b/mk/rte.buildtools.mk\nnew file mode 100644\nindex 0000000..e8bfcef\n--- /dev/null\n+++ b/mk/rte.buildtools.mk\n@@ -0,0 +1,148 @@\n+#   BSD LICENSE\n+#\n+#   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.\n+#   Copyright(c) 2014-2015 6WIND S.A.\n+#   All rights reserved.\n+#\n+#   Redistribution and use in source and binary forms, with or without\n+#   modification, are permitted provided that the following conditions\n+#   are met:\n+#\n+#     * Redistributions of source code must retain the above copyright\n+#       notice, this list of conditions and the following disclaimer.\n+#     * Redistributions in binary form must reproduce the above copyright\n+#       notice, this list of conditions and the following disclaimer in\n+#       the documentation and/or other materials provided with the\n+#       distribution.\n+#     * Neither the name of Intel Corporation nor the names of its\n+#       contributors may be used to endorse or promote products derived\n+#       from this software without specific prior written permission.\n+#\n+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+#   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+\n+include $(RTE_SDK)/mk/internal/rte.compile-pre.mk\n+include $(RTE_SDK)/mk/internal/rte.install-pre.mk\n+include $(RTE_SDK)/mk/internal/rte.clean-pre.mk\n+include $(RTE_SDK)/mk/internal/rte.build-pre.mk\n+include $(RTE_SDK)/mk/internal/rte.depdirs-pre.mk\n+\n+# VPATH contains at least SRCDIR\n+VPATH += $(SRCDIR)\n+\n+_BUILD = $(APP)\n+_INSTALL = $(INSTALL-FILES-y) $(SYMLINK-FILES-y)\n+_INSTALL += $(RTE_OUTPUT)/buildtools/$(APP) $(RTE_OUTPUT)/buildtools/$(APP).map\n+POSTINSTALL += target-appinstall\n+_CLEAN = doclean\n+POSTCLEAN += target-appclean\n+\n+.PHONY: all\n+all: install\n+\n+.PHONY: install\n+install: build _postinstall\n+\n+_postinstall: build\n+\n+.PHONY: build\n+build: _postbuild\n+\n+exe2cmd = $(strip $(call dotfile,$(patsubst %,%.cmd,$(1))))\n+\n+ifeq ($(LINK_USING_CC),1)\n+override EXTRA_LDFLAGS := $(call linkerprefix,$(EXTRA_LDFLAGS))\n+O_TO_EXE = $(CC) $(CFLAGS) $(LDFLAGS_$(@)) \\\n+\t-Wl,-Map=$(@).map,--cref -o $@ $(OBJS-y) $(call linkerprefix,$(LDFLAGS)) \\\n+\t$(EXTRA_LDFLAGS) $(call linkerprefix,$(LDLIBS))\n+else\n+O_TO_EXE = $(LD) $(LDFLAGS) $(LDFLAGS_$(@)) $(EXTRA_LDFLAGS) \\\n+\t-Map=$(@).map --cref -o $@ $(OBJS-y) $(LDLIBS)\n+endif\n+O_TO_EXE_STR = $(subst ','\\'',$(O_TO_EXE)) #'# fix syntax highlight\n+O_TO_EXE_DISP = $(if $(V),\"$(O_TO_EXE_STR)\",\"  LD $(@)\")\n+O_TO_EXE_CMD = \"cmd_$@ = $(O_TO_EXE_STR)\"\n+O_TO_EXE_DO = @set -e; \\\n+\techo $(O_TO_EXE_DISP); \\\n+\t$(O_TO_EXE) && \\\n+\techo $(O_TO_EXE_CMD) > $(call exe2cmd,$(@))\n+\n+-include .$(APP).cmd\n+\n+# path where libraries are retrieved\n+LDLIBS_PATH := $(subst -Wl$(comma)-L,,$(filter -Wl$(comma)-L%,$(LDLIBS)))\n+LDLIBS_PATH += $(subst -L,,$(filter -L%,$(LDLIBS)))\n+\n+# list of .a files that are linked to this application\n+LDLIBS_NAMES := $(patsubst -l%,lib%.a,$(filter -l%,$(LDLIBS)))\n+LDLIBS_NAMES += $(patsubst -Wl$(comma)-l%,lib%.a,$(filter -Wl$(comma)-l%,$(LDLIBS)))\n+\n+# list of found libraries files (useful for deps). If not found, the\n+# library is silently ignored and dep won't be checked\n+LDLIBS_FILES := $(wildcard $(foreach dir,$(LDLIBS_PATH),\\\n+\t$(addprefix $(dir)/,$(LDLIBS_NAMES))))\n+\n+#\n+# Compile executable file if needed\n+#\n+$(APP): $(OBJS-y) $(LDLIBS_FILES) $(DEP_$(APP)) $(LDSCRIPT) FORCE\n+\t@[ -d $(dir $@) ] || mkdir -p $(dir $@)\n+\t$(if $(D),\\\n+\t\t@echo -n \"$< -> $@ \" ; \\\n+\t\techo -n \"file_missing=$(call boolean,$(file_missing)) \" ; \\\n+\t\techo -n \"cmdline_changed=$(call boolean,$(call cmdline_changed,$(O_TO_EXE_STR))) \" ; \\\n+\t\techo -n \"depfile_missing=$(call boolean,$(depfile_missing)) \" ; \\\n+\t\techo \"depfile_newer=$(call boolean,$(depfile_newer)) \")\n+\t$(if $(or \\\n+\t\t$(file_missing),\\\n+\t\t$(call cmdline_changed,$(O_TO_EXE_STR)),\\\n+\t\t$(depfile_missing),\\\n+\t\t$(depfile_newer)),\\\n+\t\t$(O_TO_EXE_DO))\n+\n+#\n+# install app in $(RTE_OUTPUT)/app\n+#\n+$(RTE_OUTPUT)/buildtools/$(APP): $(APP)\n+\t@echo \"  INSTALL-APP $(APP)\"\n+\t@[ -d $(RTE_OUTPUT)/buildtools ] || mkdir -p $(RTE_OUTPUT)/buildtools\n+\t$(Q)cp -f $(APP) $(RTE_OUTPUT)/buildtools\n+\n+#\n+# install app map file in $(RTE_OUTPUT)/app\n+#\n+$(RTE_OUTPUT)/buildtools/$(APP).map: $(APP)\n+\t@echo \"  INSTALL-MAP $(APP).map\"\n+\t@[ -d $(RTE_OUTPUT)/buildtools ] || mkdir -p $(RTE_OUTPUT)/buildtools\n+\t$(Q)cp -f $(APP).map $(RTE_OUTPUT)/buildtools\n+\n+#\n+# Clean all generated files\n+#\n+.PHONY: clean\n+clean: _postclean\n+\t$(Q)rm -f $(_BUILD_TARGETS) $(_INSTALL_TARGETS) $(_CLEAN_TARGETS)\n+\n+.PHONY: doclean\n+doclean:\n+\t$(Q)rm -rf $(APP) $(OBJS-all) $(DEPS-all) $(DEPSTMP-all) \\\n+\t  $(CMDS-all) $(INSTALL-FILES-all) .$(APP).cmd\n+\n+\n+include $(RTE_SDK)/mk/internal/rte.compile-post.mk\n+include $(RTE_SDK)/mk/internal/rte.install-post.mk\n+include $(RTE_SDK)/mk/internal/rte.clean-post.mk\n+include $(RTE_SDK)/mk/internal/rte.build-post.mk\n+include $(RTE_SDK)/mk/internal/rte.depdirs-post.mk\n+\n+.PHONY: FORCE\n+FORCE:\ndiff --git a/mk/rte.sdkbuild.mk b/mk/rte.sdkbuild.mk\nindex eec5241..fb68af2 100644\n--- a/mk/rte.sdkbuild.mk\n+++ b/mk/rte.sdkbuild.mk\n@@ -64,7 +64,8 @@ build: $(ROOTDIRS-y)\n clean: $(CLEANDIRS)\n \t@rm -rf $(RTE_OUTPUT)/include $(RTE_OUTPUT)/app \\\n \t\t$(RTE_OUTPUT)/hostapp $(RTE_OUTPUT)/lib \\\n-\t\t$(RTE_OUTPUT)/hostlib $(RTE_OUTPUT)/kmod\n+\t\t$(RTE_OUTPUT)/hostlib $(RTE_OUTPUT)/kmod \\\n+\t\t$(RTE_OUTPUT)/buildtools\n \t@[ -d $(RTE_OUTPUT)/include ] || mkdir -p $(RTE_OUTPUT)/include\n \t@$(RTE_SDK)/scripts/gen-config-h.sh $(RTE_OUTPUT)/.config \\\n \t\t> $(RTE_OUTPUT)/include/rte_config.h\n",
    "prefixes": [
        "dpdk-dev",
        "PATCHv2",
        "1/4"
    ]
}