1 /* SPDX-License-Identifier: GPL-2.0
2  * Postprocess pmd object files to export hw support
3  *
4  * Copyright 2016 Neil Horman <[email protected]>
5  * Based in part on modpost.c from the linux kernel
6  */
7 
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdarg.h>
11 #include <string.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <sys/mman.h>
15 #ifdef __linux__
16 #include <endian.h>
17 #else
18 #include <sys/endian.h>
19 #endif
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <elf.h>
23 #include <rte_pci.h>
24 
25 /* On BSD-alike OSes elf.h defines these according to host's word size */
26 #undef ELF_ST_BIND
27 #undef ELF_ST_TYPE
28 #undef ELF_R_SYM
29 #undef ELF_R_TYPE
30 
31 /*
32  * Define ELF64_* to ELF_*, the latter being defined in both 32 and 64 bit
33  * flavors in elf.h.  This makes our code a bit more generic between arches
34  * and allows us to support 32 bit code in the future should we ever want to
35  */
36 #ifdef RTE_ARCH_64
37 #define Elf_Ehdr    Elf64_Ehdr
38 #define Elf_Shdr    Elf64_Shdr
39 #define Elf_Sym     Elf64_Sym
40 #define Elf_Addr    Elf64_Addr
41 #define Elf_Sword   Elf64_Sxword
42 #define Elf_Section Elf64_Half
43 #define ELF_ST_BIND ELF64_ST_BIND
44 #define ELF_ST_TYPE ELF64_ST_TYPE
45 
46 #define Elf_Rel     Elf64_Rel
47 #define Elf_Rela    Elf64_Rela
48 #define ELF_R_SYM   ELF64_R_SYM
49 #define ELF_R_TYPE  ELF64_R_TYPE
50 #else
51 #define Elf_Ehdr    Elf32_Ehdr
52 #define Elf_Shdr    Elf32_Shdr
53 #define Elf_Sym     Elf32_Sym
54 #define Elf_Addr    Elf32_Addr
55 #define Elf_Sword   Elf32_Sxword
56 #define Elf_Section Elf32_Half
57 #define ELF_ST_BIND ELF32_ST_BIND
58 #define ELF_ST_TYPE ELF32_ST_TYPE
59 
60 #define Elf_Rel     Elf32_Rel
61 #define Elf_Rela    Elf32_Rela
62 #define ELF_R_SYM   ELF32_R_SYM
63 #define ELF_R_TYPE  ELF32_R_TYPE
64 #endif
65 
66 
67 /*
68  * Note, it seems odd that we have both a CONVERT_NATIVE and a TO_NATIVE macro
69  * below.  We do this because the values passed to TO_NATIVE may themselves be
70  * macros and need both macros here to get expanded.  Specifically its the width
71  * variable we are concerned with, because it needs to get expanded prior to
72  * string concatenation
73  */
74 #define CONVERT_NATIVE(fend, width, x) ({ \
75 typeof(x) ___x; \
76 if ((fend) == ELFDATA2LSB) \
77 	___x = le##width##toh(x); \
78 else \
79 	___x = be##width##toh(x); \
80 ___x; \
81 })
82 
83 #define TO_NATIVE(fend, width, x) CONVERT_NATIVE(fend, width, x)
84 
85 enum opt_params {
86 	PMD_PARAM_STRING = 0,
87 	PMD_KMOD_DEP,
88 	PMD_OPT_MAX
89 };
90 
91 struct pmd_driver {
92 	Elf_Sym *name_sym;
93 	const char *name;
94 	struct rte_pci_id *pci_tbl;
95 	struct pmd_driver *next;
96 
97 	const char *opt_vals[PMD_OPT_MAX];
98 };
99 
100 struct elf_info {
101 	unsigned long size;
102 	Elf_Ehdr     *hdr;
103 	Elf_Shdr     *sechdrs;
104 	Elf_Sym      *symtab_start;
105 	Elf_Sym      *symtab_stop;
106 	char         *strtab;
107 
108 	/* support for 32bit section numbers */
109 
110 	unsigned int num_sections; /* max_secindex + 1 */
111 	unsigned int secindex_strings;
112 	/* if Nth symbol table entry has .st_shndx = SHN_XINDEX,
113 	 * take shndx from symtab_shndx_start[N] instead
114 	 */
115 	Elf32_Word   *symtab_shndx_start;
116 	Elf32_Word   *symtab_shndx_stop;
117 
118 	struct pmd_driver *drivers;
119 };
120