From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp.tuxdriver.com (charlotte.tuxdriver.com [70.61.120.58]) by dpdk.org (Postfix) with ESMTP id 9D685AA38 for ; Mon, 16 May 2016 22:42:03 +0200 (CEST) Received: from hmsreliant.think-freely.org ([2001:470:8:a08:7aac:c0ff:fec2:933b] helo=localhost) by smtp.tuxdriver.com with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.63) (envelope-from ) id 1b2PKk-0004Oy-A5; Mon, 16 May 2016 16:41:55 -0400 From: Neil Horman To: dev@dpdk.org Cc: Neil Horman , Bruce Richardson , Thomas Monjalon , Stephen Hemminger , Panu Matilainen Date: Mon, 16 May 2016 16:41:24 -0400 Message-Id: <1463431287-4551-2-git-send-email-nhorman@tuxdriver.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1463431287-4551-1-git-send-email-nhorman@tuxdriver.com> References: <1463431287-4551-1-git-send-email-nhorman@tuxdriver.com> X-Spam-Score: -1.0 (-) X-Spam-Status: No Subject: [dpdk-dev] [PATCH 1/4] pmdinfo: Add buildtools and pmdinfo utility X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 16 May 2016 20:42:04 -0000 pmdinfo is a tool used to parse object files and build json strings for use in later determining hardware support in a dso or application binary. pmdinfo looks for the non-exported symbol names this_pmd_name and this_pmd_tbl (where n is a integer counter). It records the name of each of these tuples, using the later to find the symbolic name of the pci_table for physical devices that the object supports. With this information, it outputs a C file with a single line of the form: static char *_driver_info[] __attribute__((used)) = " \ PMD_DRIVER_INFO="; Where is the arbitrary name of the pmd, and is the json encoded string that hold relevant pmd information, including the pmd name, type and optional array of pci device/vendor ids that the driver supports. This c file is suitable for compiling to object code, then relocatably linking into the parent file from which the C was generated. This creates an entry in the string table of the object that can inform a later tool about hardware support. Signed-off-by: Neil Horman CC: Bruce Richardson CC: Thomas Monjalon CC: Stephen Hemminger CC: Panu Matilainen --- GNUmakefile | 2 +- buildtools/Makefile | 36 ++++ buildtools/pmdinfo/Makefile | 48 +++++ buildtools/pmdinfo/pmdinfo.c | 435 +++++++++++++++++++++++++++++++++++++++++++ buildtools/pmdinfo/pmdinfo.h | 210 +++++++++++++++++++++ mk/rte.buildtools.mk | 148 +++++++++++++++ mk/rte.sdkbuild.mk | 3 +- 7 files changed, 880 insertions(+), 2 deletions(-) create mode 100644 buildtools/Makefile create mode 100644 buildtools/pmdinfo/Makefile create mode 100644 buildtools/pmdinfo/pmdinfo.c create mode 100644 buildtools/pmdinfo/pmdinfo.h create mode 100644 mk/rte.buildtools.mk diff --git a/GNUmakefile b/GNUmakefile index b59e4b6..00fe0db 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -40,6 +40,6 @@ export RTE_SDK # directory list # -ROOTDIRS-y := lib drivers app +ROOTDIRS-y := buildtools lib drivers app include $(RTE_SDK)/mk/rte.sdkroot.mk diff --git a/buildtools/Makefile b/buildtools/Makefile new file mode 100644 index 0000000..0f15d58 --- /dev/null +++ b/buildtools/Makefile @@ -0,0 +1,36 @@ +# BSD LICENSE +# +# Copyright(c) 2010-2014 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +DIRS-y += pmdinfo + +include $(RTE_SDK)/mk/rte.subdir.mk diff --git a/buildtools/pmdinfo/Makefile b/buildtools/pmdinfo/Makefile new file mode 100644 index 0000000..3dea68b --- /dev/null +++ b/buildtools/pmdinfo/Makefile @@ -0,0 +1,48 @@ +# BSD LICENSE +# +# Copyright(c) 2010-2015 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# +# library name +# +APP = pmdinfo + +# +# all sources are stored in SRCS-y +# +SRCS-y += pmdinfo.c + +#CFLAGS += $(WERROR_FLAGS) -g +CFLAGS += -g + +include $(RTE_SDK)/mk/rte.buildtools.mk + diff --git a/buildtools/pmdinfo/pmdinfo.c b/buildtools/pmdinfo/pmdinfo.c new file mode 100644 index 0000000..5e705ab --- /dev/null +++ b/buildtools/pmdinfo/pmdinfo.c @@ -0,0 +1,435 @@ +/* Postprocess pmd object files to export hw support + * + * Copyright 2016 Neil Horman + * Based in part on modpost.c from the linux kernel + * + * This software may be used and distributed according to the terms + * of the GNU General Public License V2, incorporated herein by reference. + * + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include "pmdinfo.h" + + +static const char *sym_name(struct elf_info *elf, Elf_Sym *sym) +{ + if (sym) + return elf->strtab + sym->st_name; + else + return "(unknown)"; +} + +void *grab_file(const char *filename, unsigned long *size) +{ + struct stat st; + void *map = MAP_FAILED; + int fd; + + fd = open(filename, O_RDONLY); + if (fd < 0) + return NULL; + if (fstat(fd, &st)) + goto failed; + + *size = st.st_size; + map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0); + +failed: + close(fd); + if (map == MAP_FAILED) + return NULL; + return map; +} + +/** + * Return a copy of the next line in a mmap'ed file. + * spaces in the beginning of the line is trimmed away. + * Return a pointer to a static buffer. + **/ +char *get_next_line(unsigned long *pos, void *file, unsigned long size) +{ + static char line[4096]; + int skip = 1; + size_t len = 0; + signed char *p = (signed char *)file + *pos; + char *s = line; + + for (; *pos < size ; (*pos)++) { + if (skip && isspace(*p)) { + p++; + continue; + } + skip = 0; + if (*p != '\n' && (*pos < size)) { + len++; + *s++ = *p++; + if (len > 4095) + break; /* Too long, stop */ + } else { + /* End of string */ + *s = '\0'; + return line; + } + } + /* End of buffer */ + return NULL; +} + +void release_file(void *file, unsigned long size) +{ + munmap(file, size); +} + + +static void *get_sym_value(struct elf_info *info, const Elf_Sym *sym) +{ + void *ptr = (void *)info->hdr + info->sechdrs[sym->st_shndx].sh_offset; + + return (void *)(ptr + sym->st_value); +} + +static Elf_Sym *find_sym_in_symtab(struct elf_info *info, + const char *name, Elf_Sym *last) +{ + Elf_Sym *idx; + if (last) + idx = last+1; + else + idx = info->symtab_start; + + for(; idx < info->symtab_stop; idx++) { + const char *n = sym_name(info, idx); + if (!strncmp(n, name, strlen(name))) + return idx; + } + return NULL; +} + +static int parse_elf(struct elf_info *info, const char *filename) +{ + unsigned int i; + Elf_Ehdr *hdr; + Elf_Shdr *sechdrs; + Elf_Sym *sym; + const char *secstrings; + unsigned int symtab_idx = ~0U, symtab_shndx_idx = ~0U; + + hdr = grab_file(filename, &info->size); + if (!hdr) { + perror(filename); + exit(1); + } + info->hdr = hdr; + if (info->size < sizeof(*hdr)) { + /* file too small, assume this is an empty .o file */ + return 0; + } + /* Is this a valid ELF file? */ + if ((hdr->e_ident[EI_MAG0] != ELFMAG0) || + (hdr->e_ident[EI_MAG1] != ELFMAG1) || + (hdr->e_ident[EI_MAG2] != ELFMAG2) || + (hdr->e_ident[EI_MAG3] != ELFMAG3)) { + /* Not an ELF file - silently ignore it */ + return 0; + } + /* Fix endianness in ELF header */ + hdr->e_type = TO_NATIVE(hdr->e_type); + hdr->e_machine = TO_NATIVE(hdr->e_machine); + hdr->e_version = TO_NATIVE(hdr->e_version); + hdr->e_entry = TO_NATIVE(hdr->e_entry); + hdr->e_phoff = TO_NATIVE(hdr->e_phoff); + hdr->e_shoff = TO_NATIVE(hdr->e_shoff); + hdr->e_flags = TO_NATIVE(hdr->e_flags); + hdr->e_ehsize = TO_NATIVE(hdr->e_ehsize); + hdr->e_phentsize = TO_NATIVE(hdr->e_phentsize); + hdr->e_phnum = TO_NATIVE(hdr->e_phnum); + hdr->e_shentsize = TO_NATIVE(hdr->e_shentsize); + hdr->e_shnum = TO_NATIVE(hdr->e_shnum); + hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx); + sechdrs = (void *)hdr + hdr->e_shoff; + info->sechdrs = sechdrs; + + /* Check if file offset is correct */ + if (hdr->e_shoff > info->size) { + fprintf(stderr, "section header offset=%lu in file '%s' is bigger than " + "filesize=%lu\n", (unsigned long)hdr->e_shoff, + filename, info->size); + return 0; + } + + if (hdr->e_shnum == SHN_UNDEF) { + /* + * There are more than 64k sections, + * read count from .sh_size. + */ + info->num_sections = TO_NATIVE(sechdrs[0].sh_size); + } + else { + info->num_sections = hdr->e_shnum; + } + if (hdr->e_shstrndx == SHN_XINDEX) { + info->secindex_strings = TO_NATIVE(sechdrs[0].sh_link); + } + else { + info->secindex_strings = hdr->e_shstrndx; + } + + /* Fix endianness in section headers */ + for (i = 0; i < info->num_sections; i++) { + sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name); + sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type); + sechdrs[i].sh_flags = TO_NATIVE(sechdrs[i].sh_flags); + sechdrs[i].sh_addr = TO_NATIVE(sechdrs[i].sh_addr); + sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset); + sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); + sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); + sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info); + sechdrs[i].sh_addralign = TO_NATIVE(sechdrs[i].sh_addralign); + sechdrs[i].sh_entsize = TO_NATIVE(sechdrs[i].sh_entsize); + } + /* Find symbol table. */ + secstrings = (void *)hdr + sechdrs[info->secindex_strings].sh_offset; + for (i = 1; i < info->num_sections; i++) { + const char *secname; + int nobits = sechdrs[i].sh_type == SHT_NOBITS; + + if (!nobits && sechdrs[i].sh_offset > info->size) { + fprintf(stderr, "%s is truncated. sechdrs[i].sh_offset=%lu > " + "sizeof(*hrd)=%zu\n", filename, + (unsigned long)sechdrs[i].sh_offset, + sizeof(*hdr)); + return 0; + } + secname = secstrings + sechdrs[i].sh_name; + if (strcmp(secname, ".modinfo") == 0) { + if (nobits) + fprintf(stderr, "%s has NOBITS .modinfo\n", filename); + info->modinfo = (void *)hdr + sechdrs[i].sh_offset; + info->modinfo_len = sechdrs[i].sh_size; + } else if (strcmp(secname, "__ksymtab") == 0) + info->export_sec = i; + else if (strcmp(secname, "__ksymtab_unused") == 0) + info->export_unused_sec = i; + else if (strcmp(secname, "__ksymtab_gpl") == 0) + info->export_gpl_sec = i; + else if (strcmp(secname, "__ksymtab_unused_gpl") == 0) + info->export_unused_gpl_sec = i; + else if (strcmp(secname, "__ksymtab_gpl_future") == 0) + info->export_gpl_future_sec = i; + + if (sechdrs[i].sh_type == SHT_SYMTAB) { + unsigned int sh_link_idx; + symtab_idx = i; + info->symtab_start = (void *)hdr + + sechdrs[i].sh_offset; + info->symtab_stop = (void *)hdr + + sechdrs[i].sh_offset + sechdrs[i].sh_size; + sh_link_idx = sechdrs[i].sh_link; + info->strtab = (void *)hdr + + sechdrs[sh_link_idx].sh_offset; + } + + /* 32bit section no. table? ("more than 64k sections") */ + if (sechdrs[i].sh_type == SHT_SYMTAB_SHNDX) { + symtab_shndx_idx = i; + info->symtab_shndx_start = (void *)hdr + + sechdrs[i].sh_offset; + info->symtab_shndx_stop = (void *)hdr + + sechdrs[i].sh_offset + sechdrs[i].sh_size; + } + } + if (!info->symtab_start) + fprintf(stderr, "%s has no symtab?\n", filename); + + /* Fix endianness in symbols */ + for (sym = info->symtab_start; sym < info->symtab_stop; sym++) { + sym->st_shndx = TO_NATIVE(sym->st_shndx); + sym->st_name = TO_NATIVE(sym->st_name); + sym->st_value = TO_NATIVE(sym->st_value); + sym->st_size = TO_NATIVE(sym->st_size); + } + + if (symtab_shndx_idx != ~0U) { + Elf32_Word *p; + if (symtab_idx != sechdrs[symtab_shndx_idx].sh_link) + fprintf(stderr, "%s: SYMTAB_SHNDX has bad sh_link: %u!=%u\n", + filename, sechdrs[symtab_shndx_idx].sh_link, + symtab_idx); + /* Fix endianness */ + for (p = info->symtab_shndx_start; p < info->symtab_shndx_stop; + p++) + *p = TO_NATIVE(*p); + } + + return 1; +} + +static void parse_elf_finish(struct elf_info *info) +{ + struct pmd_driver *tmp, *idx = info->drivers; + release_file(info->hdr, info->size); + while (idx) { + tmp = idx->next; + free(idx); + idx = tmp; + } +} + +static const char *sec_name(struct elf_info *elf, int secindex) +{ + Elf_Shdr *sechdrs = elf->sechdrs; + return (void *)elf->hdr + + elf->sechdrs[elf->secindex_strings].sh_offset + + sechdrs[secindex].sh_name; +} + +static int get_symbol_index(struct elf_info *info, Elf64_Sym *sym) +{ + const char *name = sym_name(info, sym); + const char *idx; + + idx = name; + while (idx) { + if (isdigit(*idx)) + return atoi(idx); + idx++; + } + return -1; +} + +static int complete_pmd_entry(struct elf_info *info, struct pmd_driver *drv) +{ + const char *tname; + int i = get_symbol_index(info, drv->name_sym); + char drvsym[128]; + + if (i == -1) + return -ENOENT; + + drv->name = get_sym_value(info, drv->name_sym); + + sprintf(drvsym, "this_pmd_driver%d", i); + + drv->driver = find_sym_in_symtab(info, drvsym, NULL); + + /* + * If this returns NULL, then this is a PMD_VDEV, because + * it has no pci table reference + */ + if (!drv->driver) { + drv->pci_tbl = NULL; + return 0; + } + + tname = get_sym_value(info, drv->driver); + drv->pci_tbl_sym = find_sym_in_symtab(info, tname, NULL); + + if (!drv->pci_tbl_sym) + return -ENOENT; + + drv->pci_tbl = (struct rte_pci_id *)get_sym_value(info, drv->pci_tbl_sym); + if (!drv->pci_tbl) + return -ENOENT; + + + return 0; + +} + +static int locate_pmd_entries(struct elf_info *info) +{ + Elf_Sym *last = NULL; + struct pmd_driver *new; + + info->drivers = NULL; + + do { + new = malloc(sizeof(struct pmd_driver)); + new->name_sym = find_sym_in_symtab(info, "this_pmd_name", last); + last = new->name_sym; + if (!new->name_sym) + free(new); + else { + if (complete_pmd_entry(info, new)) { + fprintf(stderr, "Failed to complete pmd entry\n"); + free(new); + } else { + new->next = info->drivers; + info->drivers = new; + } + } + } while (last); +} + +static void output_pmd_info_string(struct elf_info *info, char *outfile) +{ + FILE *ofd; + struct pmd_driver *drv; + struct rte_pci_id *pci_ids; + int idx = 0; + + ofd = fopen(outfile, "w+"); + if (!ofd) { + fprintf(stderr, "Unable to open output file\n"); + return; + } + + drv = info->drivers; + + while (drv) { + fprintf(ofd, "const char %s_pmd_info[] __attribute__((used)) = \"PMD_INFO_STRING= {", + drv->name); + fprintf(ofd,"\\\"name\\\" : \\\"%s\\\", ", drv->name); + fprintf(ofd,"\\\"type\\\" : \\\"%s\\\", ", drv->pci_tbl ? "PMD_PDEV" : "PMD_VDEV"); + + pci_ids = drv->pci_tbl; + fprintf(ofd, "\\\"pci_ids\\\" : ["); + + while (pci_ids && pci_ids->device_id) { + fprintf(ofd, "[%d, %d, %d, %d]", + pci_ids->vendor_id, pci_ids->device_id, + pci_ids->subsystem_vendor_id, + pci_ids->subsystem_device_id); + pci_ids++; + if (pci_ids->device_id) + fprintf(ofd, ","); + else + fprintf(ofd, " "); + } + fprintf(ofd, "]}\";"); + drv = drv->next; + } + + fclose(ofd); +} + +int main(int argc, char **argv) +{ + struct elf_info info; + int rc = 1; + + if (argc < 3) { + fprintf(stderr, "usage: pmdinfo \n"); + exit(127); + } + parse_elf(&info, argv[1]); + + locate_pmd_entries(&info); + + if (info.drivers) { + output_pmd_info_string(&info, argv[2]); + rc = 0; + } else { + fprintf(stderr, "Hmm, Appears to be a driver but no drivers registered\n"); + } + + parse_elf_finish(&info); + exit(rc); +} diff --git a/buildtools/pmdinfo/pmdinfo.h b/buildtools/pmdinfo/pmdinfo.h new file mode 100644 index 0000000..5dafb67 --- /dev/null +++ b/buildtools/pmdinfo/pmdinfo.h @@ -0,0 +1,210 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* On BSD-alike OSes elf.h defines these according to host's word size */ +#undef ELF_ST_BIND +#undef ELF_ST_TYPE +#undef ELF_R_SYM +#undef ELF_R_TYPE + +#if 0 + +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Shdr Elf32_Shdr +#define Elf_Sym Elf32_Sym +#define Elf_Addr Elf32_Addr +#define Elf_Sword Elf64_Sword +#define Elf_Section Elf32_Half +#define ELF_ST_BIND ELF32_ST_BIND +#define ELF_ST_TYPE ELF32_ST_TYPE + +#define Elf_Rel Elf32_Rel +#define Elf_Rela Elf32_Rela +#define ELF_R_SYM ELF32_R_SYM +#define ELF_R_TYPE ELF32_R_TYPE +#else + +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Shdr Elf64_Shdr +#define Elf_Sym Elf64_Sym +#define Elf_Addr Elf64_Addr +#define Elf_Sword Elf64_Sxword +#define Elf_Section Elf64_Half +#define ELF_ST_BIND ELF64_ST_BIND +#define ELF_ST_TYPE ELF64_ST_TYPE + +#define Elf_Rel Elf64_Rel +#define Elf_Rela Elf64_Rela +#define ELF_R_SYM ELF64_R_SYM +#define ELF_R_TYPE ELF64_R_TYPE +#endif + +/* The 64-bit MIPS ELF ABI uses an unusual reloc format. */ +typedef struct +{ + Elf32_Word r_sym; /* Symbol index */ + unsigned char r_ssym; /* Special symbol for 2nd relocation */ + unsigned char r_type3; /* 3rd relocation type */ + unsigned char r_type2; /* 2nd relocation type */ + unsigned char r_type1; /* 1st relocation type */ +} _Elf64_Mips_R_Info; + +typedef union +{ + Elf64_Xword r_info_number; + _Elf64_Mips_R_Info r_info_fields; +} _Elf64_Mips_R_Info_union; + +#define ELF64_MIPS_R_SYM(i) \ + ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_sym) + +#define ELF64_MIPS_R_TYPE(i) \ + ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_type1) + +#if 0 + +static inline void __endian(const void *src, void *dest, unsigned int size) +{ + unsigned int i; + for (i = 0; i < size; i++) + ((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1]; +} + +#define TO_NATIVE(x) \ +({ \ + typeof(x) __x; \ + __endian(&(x), &(__x), sizeof(__x)); \ + __x; \ +}) + +#else /* endianness matches */ + +#define TO_NATIVE(x) (x) + +#endif + +#define NOFAIL(ptr) do_nofail((ptr), #ptr) +void *do_nofail(void *ptr, const char *expr); + +struct buffer { + char *p; + int pos; + int size; +}; + +void __attribute__((format(printf, 2, 3))) +buf_printf(struct buffer *buf, const char *fmt, ...); + +void +buf_write(struct buffer *buf, const char *s, int len); + +struct module { + struct module *next; + const char *name; + int gpl_compatible; + struct symbol *unres; + int seen; + int skip; + int has_init; + int has_cleanup; + struct buffer dev_table_buf; + char srcversion[25]; + int is_dot_o; +}; + +struct rte_pci_id { + uint16_t vendor_id; /**< Vendor ID or PCI_ANY_ID. */ + uint16_t device_id; /**< Device ID or PCI_ANY_ID. */ + uint16_t subsystem_vendor_id; /**< Subsystem vendor ID or PCI_ANY_ID. */ + uint16_t subsystem_device_id; /**< Subsystem device ID or PCI_ANY_ID. */ +}; + +struct pmd_driver { + Elf_Sym *driver; + Elf_Sym *pci_tbl_sym; + Elf_Sym *name_sym; + struct rte_pci_id *pci_tbl; + struct pmd_driver *next; + const char *name; +}; + +struct elf_info { + unsigned long size; + Elf_Ehdr *hdr; + Elf_Shdr *sechdrs; + Elf_Sym *symtab_start; + Elf_Sym *symtab_stop; + Elf_Section export_sec; + Elf_Section export_unused_sec; + Elf_Section export_gpl_sec; + Elf_Section export_unused_gpl_sec; + Elf_Section export_gpl_future_sec; + char *strtab; + char *modinfo; + unsigned int modinfo_len; + + /* support for 32bit section numbers */ + + unsigned int num_sections; /* max_secindex + 1 */ + unsigned int secindex_strings; + /* if Nth symbol table entry has .st_shndx = SHN_XINDEX, + * take shndx from symtab_shndx_start[N] instead */ + Elf32_Word *symtab_shndx_start; + Elf32_Word *symtab_shndx_stop; + + struct pmd_driver *drivers; +}; + +static inline int is_shndx_special(unsigned int i) +{ + return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE; +} + +/* + * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of + * the way to -256..-1, to avoid conflicting with real section + * indices. + */ +#define SPECIAL(i) ((i) - (SHN_HIRESERVE + 1)) + +/* Accessor for sym->st_shndx, hides ugliness of "64k sections" */ +static inline unsigned int get_secindex(const struct elf_info *info, + const Elf_Sym *sym) +{ + if (is_shndx_special(sym->st_shndx)) + return SPECIAL(sym->st_shndx); + if (sym->st_shndx != SHN_XINDEX) + return sym->st_shndx; + return info->symtab_shndx_start[sym - info->symtab_start]; +} + +/* file2alias.c */ +extern unsigned int cross_build; +void handle_moddevtable(struct module *mod, struct elf_info *info, + Elf_Sym *sym, const char *symname); +void add_moddevtable(struct buffer *buf, struct module *mod); + +/* sumversion.c */ +void maybe_frob_rcs_version(const char *modfilename, + char *version, + void *modinfo, + unsigned long modinfo_offset); +void get_src_version(const char *modname, char sum[], unsigned sumlen); + +/* from modpost.c */ +void *grab_file(const char *filename, unsigned long *size); +char* get_next_line(unsigned long *pos, void *file, unsigned long size); +void release_file(void *file, unsigned long size); + +void fatal(const char *fmt, ...); +void warn(const char *fmt, ...); +void merror(const char *fmt, ...); diff --git a/mk/rte.buildtools.mk b/mk/rte.buildtools.mk new file mode 100644 index 0000000..e8bfcef --- /dev/null +++ b/mk/rte.buildtools.mk @@ -0,0 +1,148 @@ +# BSD LICENSE +# +# Copyright(c) 2010-2016 Intel Corporation. All rights reserved. +# Copyright(c) 2014-2015 6WIND S.A. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/internal/rte.compile-pre.mk +include $(RTE_SDK)/mk/internal/rte.install-pre.mk +include $(RTE_SDK)/mk/internal/rte.clean-pre.mk +include $(RTE_SDK)/mk/internal/rte.build-pre.mk +include $(RTE_SDK)/mk/internal/rte.depdirs-pre.mk + +# VPATH contains at least SRCDIR +VPATH += $(SRCDIR) + +_BUILD = $(APP) +_INSTALL = $(INSTALL-FILES-y) $(SYMLINK-FILES-y) +_INSTALL += $(RTE_OUTPUT)/buildtools/$(APP) $(RTE_OUTPUT)/buildtools/$(APP).map +POSTINSTALL += target-appinstall +_CLEAN = doclean +POSTCLEAN += target-appclean + +.PHONY: all +all: install + +.PHONY: install +install: build _postinstall + +_postinstall: build + +.PHONY: build +build: _postbuild + +exe2cmd = $(strip $(call dotfile,$(patsubst %,%.cmd,$(1)))) + +ifeq ($(LINK_USING_CC),1) +override EXTRA_LDFLAGS := $(call linkerprefix,$(EXTRA_LDFLAGS)) +O_TO_EXE = $(CC) $(CFLAGS) $(LDFLAGS_$(@)) \ + -Wl,-Map=$(@).map,--cref -o $@ $(OBJS-y) $(call linkerprefix,$(LDFLAGS)) \ + $(EXTRA_LDFLAGS) $(call linkerprefix,$(LDLIBS)) +else +O_TO_EXE = $(LD) $(LDFLAGS) $(LDFLAGS_$(@)) $(EXTRA_LDFLAGS) \ + -Map=$(@).map --cref -o $@ $(OBJS-y) $(LDLIBS) +endif +O_TO_EXE_STR = $(subst ','\'',$(O_TO_EXE)) #'# fix syntax highlight +O_TO_EXE_DISP = $(if $(V),"$(O_TO_EXE_STR)"," LD $(@)") +O_TO_EXE_CMD = "cmd_$@ = $(O_TO_EXE_STR)" +O_TO_EXE_DO = @set -e; \ + echo $(O_TO_EXE_DISP); \ + $(O_TO_EXE) && \ + echo $(O_TO_EXE_CMD) > $(call exe2cmd,$(@)) + +-include .$(APP).cmd + +# path where libraries are retrieved +LDLIBS_PATH := $(subst -Wl$(comma)-L,,$(filter -Wl$(comma)-L%,$(LDLIBS))) +LDLIBS_PATH += $(subst -L,,$(filter -L%,$(LDLIBS))) + +# list of .a files that are linked to this application +LDLIBS_NAMES := $(patsubst -l%,lib%.a,$(filter -l%,$(LDLIBS))) +LDLIBS_NAMES += $(patsubst -Wl$(comma)-l%,lib%.a,$(filter -Wl$(comma)-l%,$(LDLIBS))) + +# list of found libraries files (useful for deps). If not found, the +# library is silently ignored and dep won't be checked +LDLIBS_FILES := $(wildcard $(foreach dir,$(LDLIBS_PATH),\ + $(addprefix $(dir)/,$(LDLIBS_NAMES)))) + +# +# Compile executable file if needed +# +$(APP): $(OBJS-y) $(LDLIBS_FILES) $(DEP_$(APP)) $(LDSCRIPT) FORCE + @[ -d $(dir $@) ] || mkdir -p $(dir $@) + $(if $(D),\ + @echo -n "$< -> $@ " ; \ + echo -n "file_missing=$(call boolean,$(file_missing)) " ; \ + echo -n "cmdline_changed=$(call boolean,$(call cmdline_changed,$(O_TO_EXE_STR))) " ; \ + echo -n "depfile_missing=$(call boolean,$(depfile_missing)) " ; \ + echo "depfile_newer=$(call boolean,$(depfile_newer)) ") + $(if $(or \ + $(file_missing),\ + $(call cmdline_changed,$(O_TO_EXE_STR)),\ + $(depfile_missing),\ + $(depfile_newer)),\ + $(O_TO_EXE_DO)) + +# +# install app in $(RTE_OUTPUT)/app +# +$(RTE_OUTPUT)/buildtools/$(APP): $(APP) + @echo " INSTALL-APP $(APP)" + @[ -d $(RTE_OUTPUT)/buildtools ] || mkdir -p $(RTE_OUTPUT)/buildtools + $(Q)cp -f $(APP) $(RTE_OUTPUT)/buildtools + +# +# install app map file in $(RTE_OUTPUT)/app +# +$(RTE_OUTPUT)/buildtools/$(APP).map: $(APP) + @echo " INSTALL-MAP $(APP).map" + @[ -d $(RTE_OUTPUT)/buildtools ] || mkdir -p $(RTE_OUTPUT)/buildtools + $(Q)cp -f $(APP).map $(RTE_OUTPUT)/buildtools + +# +# Clean all generated files +# +.PHONY: clean +clean: _postclean + $(Q)rm -f $(_BUILD_TARGETS) $(_INSTALL_TARGETS) $(_CLEAN_TARGETS) + +.PHONY: doclean +doclean: + $(Q)rm -rf $(APP) $(OBJS-all) $(DEPS-all) $(DEPSTMP-all) \ + $(CMDS-all) $(INSTALL-FILES-all) .$(APP).cmd + + +include $(RTE_SDK)/mk/internal/rte.compile-post.mk +include $(RTE_SDK)/mk/internal/rte.install-post.mk +include $(RTE_SDK)/mk/internal/rte.clean-post.mk +include $(RTE_SDK)/mk/internal/rte.build-post.mk +include $(RTE_SDK)/mk/internal/rte.depdirs-post.mk + +.PHONY: FORCE +FORCE: diff --git a/mk/rte.sdkbuild.mk b/mk/rte.sdkbuild.mk index eec5241..fb68af2 100644 --- a/mk/rte.sdkbuild.mk +++ b/mk/rte.sdkbuild.mk @@ -64,7 +64,8 @@ build: $(ROOTDIRS-y) clean: $(CLEANDIRS) @rm -rf $(RTE_OUTPUT)/include $(RTE_OUTPUT)/app \ $(RTE_OUTPUT)/hostapp $(RTE_OUTPUT)/lib \ - $(RTE_OUTPUT)/hostlib $(RTE_OUTPUT)/kmod + $(RTE_OUTPUT)/hostlib $(RTE_OUTPUT)/kmod \ + $(RTE_OUTPUT)/buildtools @[ -d $(RTE_OUTPUT)/include ] || mkdir -p $(RTE_OUTPUT)/include @$(RTE_SDK)/scripts/gen-config-h.sh $(RTE_OUTPUT)/.config \ > $(RTE_OUTPUT)/include/rte_config.h -- 2.5.5