xref: /freebsd/lib/libkldelf/kldelf.h (revision 92cd5abb64dd70c305535c9504c6a2b73552147f)
1 /*-
2  * SPDX-License-Identifier: BSD-4-Clause
3  *
4  * Copyright (c) 2000, Boris Popov
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *    This product includes software developed by Boris Popov.
18  * 4. Neither the name of the author nor the names of any co-contributors
19  *    may be used to endorse or promote products derived from this software
20  *    without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #ifndef _KLDELF_H_
36 #define _KLDELF_H_
37 
38 #include <sys/linker_set.h>
39 #include <stdbool.h>
40 
41 #define EF_CLOSE(ef) \
42     (ef)->ef_ops->close((ef)->ef_ef)
43 #define EF_SEG_READ_REL(ef, address, len, dest) \
44     (ef)->ef_ops->seg_read_rel((ef)->ef_ef, address, len, dest)
45 #define EF_SEG_READ_STRING(ef, address, len, dest) \
46     (ef)->ef_ops->seg_read_string((ef)->ef_ef, address, len, dest)
47 #define EF_SYMADDR(ef, symidx) \
48     (ef)->ef_ops->symaddr((ef)->ef_ef, symidx)
49 #define EF_LOOKUP_SET(ef, name, startp, stopp, countp) \
50     (ef)->ef_ops->lookup_set((ef)->ef_ef, name, startp, stopp, countp)
51 #define EF_LOOKUP_SYMBOL(ef, name, sym) \
52     (ef)->ef_ops->lookup_symbol((ef)->ef_ef, name, sym)
53 
54 /* XXX, should have a different name. */
55 typedef struct ef_file *elf_file_t;
56 
57 /* FreeBSD's headers define additional typedef's for ELF structures. */
58 typedef Elf64_Size GElf_Size;
59 typedef Elf64_Hashelt GElf_Hashelt;
60 
61 struct elf_file;
62 
63 struct elf_file_ops {
64 	void (*close)(elf_file_t ef);
65 	int (*seg_read_rel)(elf_file_t ef, GElf_Addr address, size_t len,
66 	    void *dest);
67 	int (*seg_read_string)(elf_file_t ef, GElf_Addr address, size_t len,
68 	    char *dest);
69 	GElf_Addr (*symaddr)(elf_file_t ef, GElf_Size symidx);
70 	int (*lookup_set)(elf_file_t ef, const char *name, GElf_Addr *startp,
71 	    GElf_Addr *stopp, long *countp);
72 	int (*lookup_symbol)(elf_file_t ef, const char *name, GElf_Sym **sym);
73 };
74 
75 typedef int (elf_reloc_t)(struct elf_file *ef, const void *reldata,
76     Elf_Type reltype, GElf_Addr relbase, GElf_Addr dataoff, size_t len,
77     void *dest);
78 
79 struct elf_reloc_data {
80 	unsigned char class;
81 	unsigned char data;
82 	GElf_Half machine;
83 	elf_reloc_t *reloc;
84 };
85 
86 #define	ELF_RELOC(_class, _data, _machine, _reloc)			\
87 	static struct elf_reloc_data __CONCAT(elf_reloc_data_, __LINE__) = { \
88 	    .class = (_class),						\
89 	    .data = (_data),						\
90 	    .machine = (_machine),					\
91 	    .reloc = (_reloc)						\
92 	};								\
93 	DATA_SET(elf_reloc, __CONCAT(elf_reloc_data_, __LINE__))
94 
95 struct elf_file {
96 	elf_file_t ef_ef;
97 	struct elf_file_ops *ef_ops;
98 	const char *ef_filename;
99 	Elf *ef_elf;
100 	elf_reloc_t *ef_reloc;
101 	GElf_Ehdr ef_hdr;
102 	size_t ef_pointer_size;
103 	int ef_fd;
104 };
105 
106 #define	elf_machine(ef)		((ef)->ef_hdr.e_machine)
107 #define	elf_class(ef)		((ef)->ef_hdr.e_ident[EI_CLASS])
108 #define	elf_encoding(ef)	((ef)->ef_hdr.e_ident[EI_DATA])
109 
110 /*
111  * "Generic" versions of module metadata structures.
112  */
113 struct Gmod_depend {
114 	int	md_ver_minimum;
115 	int	md_ver_preferred;
116 	int	md_ver_maximum;
117 };
118 
119 struct Gmod_version {
120 	int	mv_version;
121 };
122 
123 struct Gmod_metadata {
124 	int		md_version;	/* structure version MDTV_* */
125 	int		md_type;	/* type of entry MDT_* */
126 	GElf_Addr	md_data;	/* specific data */
127 	GElf_Addr	md_cval;	/* common string label */
128 };
129 
130 struct Gmod_pnp_match_info
131 {
132 	GElf_Addr	descr;	/* Description of the table */
133 	GElf_Addr	bus;	/* Name of the bus for this table */
134 	GElf_Addr	table;	/* Pointer to pnp table */
135 	int entry_len;		/* Length of each entry in the table (may be */
136 				/*   longer than descr describes). */
137 	int num_entry;		/* Number of entries in the table */
138 };
139 
140 __BEGIN_DECLS
141 
142 /*
143  * Attempt to parse an open ELF file as either an executable or DSO
144  * (ef_open) or an object file (ef_obj_open).  On success, these
145  * routines initialize the 'ef_ef' and 'ef_ops' members of 'ef'.
146  */
147 int ef_open(struct elf_file *ef, int verbose);
148 int ef_obj_open(struct elf_file *ef, int verbose);
149 
150 /*
151  * Direct operations on an ELF file regardless of type.  Many of these
152  * use libelf.
153  */
154 
155 /*
156  * Open an ELF file with libelf.  Populates fields other than ef_ef
157  * and ef_ops in '*efile'.
158  */
159 int	elf_open_file(struct elf_file *efile, const char *filename,
160     int verbose);
161 
162 /* Close an ELF file. */
163 void	elf_close_file(struct elf_file *efile);
164 
165 /* Is an ELF file the same architecture as hdr? */
166 bool	elf_compatible(struct elf_file *efile, const GElf_Ehdr *hdr);
167 
168 /* The size of a single object of 'type'. */
169 size_t	elf_object_size(struct elf_file *efile, Elf_Type type);
170 
171 /* The size of a pointer in architecture of 'efile'. */
172 size_t	elf_pointer_size(struct elf_file *efile);
173 
174 /*
175  * Read and convert an array of a data type from an ELF file.  This is
176  * a wrapper around gelf_xlatetom() which reads an array of raw ELF
177  * objects from the file and converts them into host structures using
178  * native endianness.  The data is returned in a dynamically-allocated
179  * buffer.
180  */
181 int	elf_read_data(struct elf_file *efile, Elf_Type type, off_t offset,
182     size_t len, void **out);
183 
184 /* Reads "raw" data from an ELF file without any translation. */
185 int	elf_read_raw_data(struct elf_file *efile, off_t offset, void *dst,
186     size_t len);
187 
188 /*
189  * A wrapper around elf_read_raw_data which returns the data in a
190  * dynamically-allocated buffer.
191  */
192 int	elf_read_raw_data_alloc(struct elf_file *efile, off_t offset,
193     size_t len, void **out);
194 
195 /* Reads a single string at the given offset from an ELF file. */
196 int	elf_read_raw_string(struct elf_file *efile, off_t offset, char *dst,
197     size_t len);
198 
199 /*
200  * Read relocated data from an ELF file and return it in a
201  * dynamically-allocated buffer.  Note that no translation
202  * (byte-swapping for endianness, 32-vs-64) is performed on the
203  * returned data, but any ELF relocations which affect the contents
204  * are applied to the returned data.  The address parameter gives the
205  * address of the data buffer if the ELF file were loaded into memory
206  * rather than a direct file offset.
207  */
208 int	elf_read_relocated_data(struct elf_file *efile, GElf_Addr address,
209     size_t len, void **buf);
210 
211 /*
212  * Read the program headers from an ELF file and return them in a
213  * dynamically-allocated array of GElf_Phdr objects.
214  */
215 int	elf_read_phdrs(struct elf_file *efile, size_t *nphdrp,
216     GElf_Phdr **phdrp);
217 
218 /*
219  * Read the section headers from an ELF file and return them in a
220  * dynamically-allocated array of GElf_Shdr objects.
221  */
222 int	elf_read_shdrs(struct elf_file *efile, size_t *nshdrp,
223     GElf_Shdr **shdrp);
224 
225 /*
226  * Read the dynamic table from a section of an ELF file into a
227  * dynamically-allocated array of GElf_Dyn objects.
228  */
229 int	elf_read_dynamic(struct elf_file *efile, int section_index, size_t *ndynp,
230     GElf_Dyn **dynp);
231 
232 /*
233  * Read a symbol table from a section of an ELF file into a
234  * dynamically-allocated array of GElf_Sym objects.
235  */
236 int	elf_read_symbols(struct elf_file *efile, int section_index,
237     size_t *nsymp, GElf_Sym **symp);
238 
239 /*
240  * Read a string table described by a section header of an ELF file
241  * into a dynamically-allocated buffer.
242  */
243 int	elf_read_string_table(struct elf_file *efile, const GElf_Shdr *shdr,
244     long *strcnt, char **strtab);
245 
246 /*
247  * Read a table of relocation objects from a section of an ELF file
248  * into a dynamically-allocated array of GElf_Rel objects.
249  */
250 int	elf_read_rel(struct elf_file *efile, int section_index, long *nrelp,
251     GElf_Rel **relp);
252 
253 /*
254  * Read a table of relocation-with-addend objects from a section of an
255  * ELF file into a dynamically-allocated array of GElf_Rela objects.
256  */
257 int	elf_read_rela(struct elf_file *efile, int section_index, long *nrelap,
258     GElf_Rela **relap);
259 
260 /*
261  * Read a string from an ELF file and return it in the provided
262  * buffer.  If the string is longer than the buffer, this fails with
263  * EFAULT.  The address parameter gives the address of the data buffer
264  * if the ELF file were loaded into memory rather than a direct file
265  * offset.
266  */
267 int	elf_read_string(struct elf_file *efile, GElf_Addr address, void *dst,
268     size_t len);
269 
270 /* Return the address extracted from a target pointer stored at 'p'. */
271 GElf_Addr elf_address_from_pointer(struct elf_file *efile, const void *p);
272 
273 /*
274  * Read a linker set and return an array of addresses extracted from the
275  * relocated pointers in the linker set.
276  */
277 int	elf_read_linker_set(struct elf_file *efile, const char *name,
278     GElf_Addr **buf, long *countp);
279 
280 /*
281  * Read and convert a target 'struct mod_depend' into a host
282  * 'struct Gmod_depend'.
283  */
284 int	elf_read_mod_depend(struct elf_file *efile, GElf_Addr addr,
285     struct Gmod_depend *mdp);
286 
287 /*
288  * Read and convert a target 'struct mod_version' into a host
289  * 'struct Gmod_version'.
290  */
291 int	elf_read_mod_version(struct elf_file *efile, GElf_Addr addr,
292     struct Gmod_version *mdv);
293 
294 /*
295  * Read and convert a target 'struct mod_metadata' into a host
296  * 'struct Gmod_metadata'.
297  */
298 int	elf_read_mod_metadata(struct elf_file *efile, GElf_Addr addr,
299     struct Gmod_metadata *md);
300 
301 /*
302  * Read and convert a target 'struct mod_pnp_match_info' into a host
303  * 'struct Gmod_pnp_match_info'.
304  */
305 int	elf_read_mod_pnp_match_info(struct elf_file *efile, GElf_Addr addr,
306     struct Gmod_pnp_match_info *pnp);
307 
308 /*
309  * Apply relocations to the values obtained from the file. `relbase' is the
310  * target relocation address of the section, and `dataoff/len' is the region
311  * that is to be relocated, and has been copied to *dest
312  */
313 int	elf_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
314     GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest);
315 
316 /*
317  * Find the symbol with the specified symbol name 'name' within the given
318  * 'efile'. 0 is returned when such a symbol is found, otherwise ENOENT is
319  * returned.
320  *
321  * XXX: This only return the first symbol being found when traversing symtab.
322  */
323 int	elf_lookup_symbol(struct elf_file *efile, const char *name,
324     GElf_Sym **sym);
325 
326 __END_DECLS
327 
328 #endif /* _KLDELF_H_*/
329