mk: build with _GNU_SOURCE defined by default
[dpdk.git] / buildtools / pmdinfogen / pmdinfogen.c
index 0947dc6..dc0b6d5 100644 (file)
@@ -8,13 +8,15 @@
  *
  */
 
-#define _GNU_SOURCE
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
 #include <limits.h>
 #include <stdbool.h>
 #include <errno.h>
+#include <libgen.h>
+
+#include <rte_common.h>
 #include "pmdinfogen.h"
 
 #ifdef RTE_ARCH_64
@@ -23,6 +25,7 @@
 #define ADDR_SIZE 32
 #endif
 
+static int use_stdin, use_stdout;
 
 static const char *sym_name(struct elf_info *elf, Elf_Sym *sym)
 {
@@ -32,15 +35,40 @@ static const char *sym_name(struct elf_info *elf, Elf_Sym *sym)
                return "(unknown)";
 }
 
-void *grab_file(const char *filename, unsigned long *size)
+static void *grab_file(const char *filename, unsigned long *size)
 {
        struct stat st;
        void *map = MAP_FAILED;
-       int fd;
+       int fd = -1;
+
+       if (!use_stdin) {
+               fd = open(filename, O_RDONLY);
+               if (fd < 0)
+                       return NULL;
+       } else {
+               /* from stdin, use a temporary file to mmap */
+               FILE *infile;
+               char buffer[1024];
+               int n;
+
+               infile = tmpfile();
+               if (infile == NULL) {
+                       perror("tmpfile");
+                       return NULL;
+               }
+               fd = dup(fileno(infile));
+               fclose(infile);
+               if (fd < 0)
+                       return NULL;
+
+               n = read(STDIN_FILENO, buffer, sizeof(buffer));
+               while (n > 0) {
+                       if (write(fd, buffer, n) != n)
+                               goto failed;
+                       n = read(STDIN_FILENO, buffer, sizeof(buffer));
+               }
+       }
 
-       fd = open(filename, O_RDONLY);
-       if (fd < 0)
-               return NULL;
        if (fstat(fd, &st))
                goto failed;
 
@@ -59,7 +87,7 @@ failed:
   * spaces in the beginning of the line is trimmed away.
   * Return a pointer to a static buffer.
   **/
-void release_file(void *file, unsigned long size)
+static void release_file(void *file, unsigned long size)
 {
        munmap(file, size);
 }
@@ -67,9 +95,8 @@ void release_file(void *file, unsigned long 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);
+       return RTE_PTR_ADD(info->hdr,
+               info->sechdrs[sym->st_shndx].sh_offset + sym->st_value);
 }
 
 static Elf_Sym *find_sym_in_symtab(struct elf_info *info,
@@ -95,7 +122,6 @@ static int parse_elf(struct elf_info *info, const char *filename)
        Elf_Ehdr *hdr;
        Elf_Shdr *sechdrs;
        Elf_Sym  *sym;
-       const char *secstrings;
        int endian;
        unsigned int symtab_idx = ~0U, symtab_shndx_idx = ~0U;
 
@@ -140,7 +166,7 @@ static int parse_elf(struct elf_info *info, const char *filename)
        hdr->e_shnum     = TO_NATIVE(endian, 16, hdr->e_shnum);
        hdr->e_shstrndx  = TO_NATIVE(endian, 16, hdr->e_shstrndx);
 
-       sechdrs = (void *)hdr + hdr->e_shoff;
+       sechdrs = RTE_PTR_ADD(hdr, hdr->e_shoff);
        info->sechdrs = sechdrs;
 
        /* Check if file offset is correct */
@@ -157,7 +183,8 @@ static int parse_elf(struct elf_info *info, const char *filename)
                 * There are more than 64k sections,
                 * read count from .sh_size.
                 */
-               info->num_sections = TO_NATIVE(endian, 32, sechdrs[0].sh_size);
+               info->num_sections =
+                       TO_NATIVE(endian, ADDR_SIZE, sechdrs[0].sh_size);
        } else {
                info->num_sections = hdr->e_shnum;
        }
@@ -180,7 +207,7 @@ static int parse_elf(struct elf_info *info, const char *filename)
                sechdrs[i].sh_offset    =
                        TO_NATIVE(endian, ADDR_SIZE, sechdrs[i].sh_offset);
                sechdrs[i].sh_size      =
-                       TO_NATIVE(endian, 32, sechdrs[i].sh_size);
+                       TO_NATIVE(endian, ADDR_SIZE, sechdrs[i].sh_size);
                sechdrs[i].sh_link      =
                        TO_NATIVE(endian, 32, sechdrs[i].sh_link);
                sechdrs[i].sh_info      =
@@ -191,7 +218,6 @@ static int parse_elf(struct elf_info *info, const char *filename)
                        TO_NATIVE(endian, ADDR_SIZE, sechdrs[i].sh_entsize);
        }
        /* Find symbol table. */
-       secstrings = (void *)hdr + sechdrs[info->secindex_strings].sh_offset;
        for (i = 1; i < info->num_sections; i++) {
                int nobits = sechdrs[i].sh_type == SHT_NOBITS;
 
@@ -206,33 +232,34 @@ static int parse_elf(struct elf_info *info, const char *filename)
                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;
+                       info->symtab_start = RTE_PTR_ADD(hdr,
+                               sechdrs[i].sh_offset);
+                       info->symtab_stop  = RTE_PTR_ADD(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;
+                       info->strtab       = RTE_PTR_ADD(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;
+                       info->symtab_shndx_start = RTE_PTR_ADD(hdr,
+                               sechdrs[i].sh_offset);
+                       info->symtab_shndx_stop  = RTE_PTR_ADD(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(endian, 16, sym->st_shndx);
-               sym->st_name  = TO_NATIVE(endian, 32, sym->st_name);
-               sym->st_value = TO_NATIVE(endian, ADDR_SIZE, sym->st_value);
-               sym->st_size  = TO_NATIVE(endian, ADDR_SIZE, sym->st_size);
+       else {
+               /* Fix endianness in symbols */
+               for (sym = info->symtab_start; sym < info->symtab_stop; sym++) {
+                       sym->st_shndx = TO_NATIVE(endian, 16, sym->st_shndx);
+                       sym->st_name  = TO_NATIVE(endian, 32, sym->st_name);
+                       sym->st_value = TO_NATIVE(endian, ADDR_SIZE, sym->st_value);
+                       sym->st_size  = TO_NATIVE(endian, ADDR_SIZE, sym->st_size);
+               }
        }
 
        if (symtab_shndx_idx != ~0U) {
@@ -262,28 +289,6 @@ static void parse_elf_finish(struct elf_info *info)
        }
 }
 
-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, Elf_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;
-}
-
 struct opt_tag {
        const char *suffix;
        const char *json_id;
@@ -291,6 +296,7 @@ struct opt_tag {
 
 static const struct opt_tag opt_tags[] = {
        {"_param_string_export", "params"},
+       {"_kmod_dep_export", "kmod"},
 };
 
 static int complete_pmd_entry(struct elf_info *info, struct pmd_driver *drv)
@@ -347,6 +353,10 @@ static int locate_pmd_entries(struct elf_info *info)
 
        do {
                new = calloc(sizeof(struct pmd_driver), 1);
+               if (new == NULL) {
+                       fprintf(stderr, "Failed to calloc memory\n");
+                       return -1;
+               }
                new->name_sym = find_sym_in_symtab(info, "this_pmd_name", last);
                last = new->name_sym;
                if (!new->name_sym)
@@ -362,6 +372,8 @@ static int locate_pmd_entries(struct elf_info *info)
                        }
                }
        } while (last);
+
+       return 0;
 }
 
 static void output_pmd_info_string(struct elf_info *info, char *outfile)
@@ -371,10 +383,14 @@ static void output_pmd_info_string(struct elf_info *info, char *outfile)
        struct rte_pci_id *pci_ids;
        int idx = 0;
 
-       ofd = fopen(outfile, "w+");
-       if (!ofd) {
-               fprintf(stderr, "Unable to open output file\n");
-               return;
+       if (use_stdout)
+               ofd = stdout;
+       else {
+               ofd = fopen(outfile, "w+");
+               if (!ofd) {
+                       fprintf(stderr, "Unable to open output file\n");
+                       return;
+               }
        }
 
        drv = info->drivers;
@@ -406,7 +422,7 @@ static void output_pmd_info_string(struct elf_info *info, char *outfile)
                        else
                                fprintf(ofd, " ");
                }
-               fprintf(ofd, "]}\";");
+               fprintf(ofd, "]}\";\n");
                drv = drv->next;
        }
 
@@ -415,17 +431,21 @@ static void output_pmd_info_string(struct elf_info *info, char *outfile)
 
 int main(int argc, char **argv)
 {
-       struct elf_info info;
+       struct elf_info info = {0};
        int rc = 1;
 
        if (argc < 3) {
                fprintf(stderr,
-                       "usage: pmdinfo <object file> <c output file>\n");
+                       "usage: %s <object file> <c output file>\n",
+                       basename(argv[0]));
                exit(127);
        }
+       use_stdin = !strcmp(argv[1], "-");
+       use_stdout = !strcmp(argv[2], "-");
        parse_elf(&info, argv[1]);
 
-       locate_pmd_entries(&info);
+       if (locate_pmd_entries(&info) < 0)
+               exit(1);
 
        if (info.drivers) {
                output_pmd_info_string(&info, argv[2]);