aboutsummaryrefslogtreecommitdiff
path: root/lib/libkldelf/kldelf.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libkldelf/kldelf.h')
-rw-r--r--lib/libkldelf/kldelf.h327
1 files changed, 327 insertions, 0 deletions
diff --git a/lib/libkldelf/kldelf.h b/lib/libkldelf/kldelf.h
new file mode 100644
index 000000000000..4fb5fcc5f5aa
--- /dev/null
+++ b/lib/libkldelf/kldelf.h
@@ -0,0 +1,327 @@
+/*-
+ * SPDX-License-Identifier: BSD-4-Clause
+ *
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ */
+
+#ifndef _KLDELF_H_
+#define _KLDELF_H_
+
+#include <sys/linker_set.h>
+#include <stdbool.h>
+
+#define EF_CLOSE(ef) \
+ (ef)->ef_ops->close((ef)->ef_ef)
+#define EF_SEG_READ_REL(ef, address, len, dest) \
+ (ef)->ef_ops->seg_read_rel((ef)->ef_ef, address, len, dest)
+#define EF_SEG_READ_STRING(ef, address, len, dest) \
+ (ef)->ef_ops->seg_read_string((ef)->ef_ef, address, len, dest)
+#define EF_SYMADDR(ef, symidx) \
+ (ef)->ef_ops->symaddr((ef)->ef_ef, symidx)
+#define EF_LOOKUP_SET(ef, name, startp, stopp, countp) \
+ (ef)->ef_ops->lookup_set((ef)->ef_ef, name, startp, stopp, countp)
+#define EF_LOOKUP_SYMBOL(ef, name, sym, see_local) \
+ (ef)->ef_ops->lookup_symbol((ef)->ef_ef, name, sym, see_local)
+
+/* XXX, should have a different name. */
+typedef struct ef_file *elf_file_t;
+
+/* FreeBSD's headers define additional typedef's for ELF structures. */
+typedef Elf64_Size GElf_Size;
+typedef Elf64_Hashelt GElf_Hashelt;
+
+struct elf_file;
+
+struct elf_file_ops {
+ void (*close)(elf_file_t ef);
+ int (*seg_read_rel)(elf_file_t ef, GElf_Addr address, size_t len,
+ void *dest);
+ int (*seg_read_string)(elf_file_t ef, GElf_Addr address, size_t len,
+ char *dest);
+ GElf_Addr (*symaddr)(elf_file_t ef, GElf_Size symidx);
+ int (*lookup_set)(elf_file_t ef, const char *name, GElf_Addr *startp,
+ GElf_Addr *stopp, long *countp);
+ int (*lookup_symbol)(elf_file_t ef, const char *name, GElf_Sym **sym,
+ bool see_local);
+};
+
+typedef int (elf_reloc_t)(struct elf_file *ef, const void *reldata,
+ Elf_Type reltype, GElf_Addr relbase, GElf_Addr dataoff, size_t len,
+ void *dest);
+
+struct elf_reloc_data {
+ unsigned char class;
+ unsigned char data;
+ GElf_Half machine;
+ elf_reloc_t *reloc;
+};
+
+#define ELF_RELOC(_class, _data, _machine, _reloc) \
+ static struct elf_reloc_data __CONCAT(elf_reloc_data_, __LINE__) = { \
+ .class = (_class), \
+ .data = (_data), \
+ .machine = (_machine), \
+ .reloc = (_reloc) \
+ }; \
+ DATA_SET(elf_reloc, __CONCAT(elf_reloc_data_, __LINE__))
+
+struct elf_file {
+ elf_file_t ef_ef;
+ struct elf_file_ops *ef_ops;
+ const char *ef_filename;
+ Elf *ef_elf;
+ elf_reloc_t *ef_reloc;
+ GElf_Ehdr ef_hdr;
+ size_t ef_pointer_size;
+ int ef_fd;
+};
+
+#define elf_machine(ef) ((ef)->ef_hdr.e_machine)
+#define elf_class(ef) ((ef)->ef_hdr.e_ident[EI_CLASS])
+#define elf_encoding(ef) ((ef)->ef_hdr.e_ident[EI_DATA])
+
+/*
+ * "Generic" versions of module metadata structures.
+ */
+struct Gmod_depend {
+ int md_ver_minimum;
+ int md_ver_preferred;
+ int md_ver_maximum;
+};
+
+struct Gmod_version {
+ int mv_version;
+};
+
+struct Gmod_metadata {
+ int md_version; /* structure version MDTV_* */
+ int md_type; /* type of entry MDT_* */
+ GElf_Addr md_data; /* specific data */
+ GElf_Addr md_cval; /* common string label */
+};
+
+struct Gmod_pnp_match_info
+{
+ GElf_Addr descr; /* Description of the table */
+ GElf_Addr bus; /* Name of the bus for this table */
+ GElf_Addr table; /* Pointer to pnp table */
+ int entry_len; /* Length of each entry in the table (may be */
+ /* longer than descr describes). */
+ int num_entry; /* Number of entries in the table */
+};
+
+__BEGIN_DECLS
+
+/*
+ * Attempt to parse an open ELF file as either an executable or DSO
+ * (ef_open) or an object file (ef_obj_open). On success, these
+ * routines initialize the 'ef_ef' and 'ef_ops' members of 'ef'.
+ */
+int ef_open(struct elf_file *ef, int verbose);
+int ef_obj_open(struct elf_file *ef, int verbose);
+
+/*
+ * Direct operations on an ELF file regardless of type. Many of these
+ * use libelf.
+ */
+
+/*
+ * Open an ELF file with libelf. Populates fields other than ef_ef
+ * and ef_ops in '*efile'.
+ */
+int elf_open_file(struct elf_file *efile, const char *filename,
+ int verbose);
+
+/* Close an ELF file. */
+void elf_close_file(struct elf_file *efile);
+
+/* Is an ELF file the same architecture as hdr? */
+bool elf_compatible(struct elf_file *efile, const GElf_Ehdr *hdr);
+
+/* The size of a single object of 'type'. */
+size_t elf_object_size(struct elf_file *efile, Elf_Type type);
+
+/* The size of a pointer in architecture of 'efile'. */
+size_t elf_pointer_size(struct elf_file *efile);
+
+/*
+ * Read and convert an array of a data type from an ELF file. This is
+ * a wrapper around gelf_xlatetom() which reads an array of raw ELF
+ * objects from the file and converts them into host structures using
+ * native endianness. The data is returned in a dynamically-allocated
+ * buffer.
+ */
+int elf_read_data(struct elf_file *efile, Elf_Type type, off_t offset,
+ size_t len, void **out);
+
+/* Reads "raw" data from an ELF file without any translation. */
+int elf_read_raw_data(struct elf_file *efile, off_t offset, void *dst,
+ size_t len);
+
+/*
+ * A wrapper around elf_read_raw_data which returns the data in a
+ * dynamically-allocated buffer.
+ */
+int elf_read_raw_data_alloc(struct elf_file *efile, off_t offset,
+ size_t len, void **out);
+
+/* Reads a single string at the given offset from an ELF file. */
+int elf_read_raw_string(struct elf_file *efile, off_t offset, char *dst,
+ size_t len);
+
+/*
+ * Read relocated data from an ELF file and return it in a
+ * dynamically-allocated buffer. Note that no translation
+ * (byte-swapping for endianness, 32-vs-64) is performed on the
+ * returned data, but any ELF relocations which affect the contents
+ * are applied to the returned data. The address parameter gives the
+ * address of the data buffer if the ELF file were loaded into memory
+ * rather than a direct file offset.
+ */
+int elf_read_relocated_data(struct elf_file *efile, GElf_Addr address,
+ size_t len, void **buf);
+
+/*
+ * Read the program headers from an ELF file and return them in a
+ * dynamically-allocated array of GElf_Phdr objects.
+ */
+int elf_read_phdrs(struct elf_file *efile, size_t *nphdrp,
+ GElf_Phdr **phdrp);
+
+/*
+ * Read the section headers from an ELF file and return them in a
+ * dynamically-allocated array of GElf_Shdr objects.
+ */
+int elf_read_shdrs(struct elf_file *efile, size_t *nshdrp,
+ GElf_Shdr **shdrp);
+
+/*
+ * Read the dynamic table from a section of an ELF file into a
+ * dynamically-allocated array of GElf_Dyn objects.
+ */
+int elf_read_dynamic(struct elf_file *efile, int section_index, size_t *ndynp,
+ GElf_Dyn **dynp);
+
+/*
+ * Read a symbol table from a section of an ELF file into a
+ * dynamically-allocated array of GElf_Sym objects.
+ */
+int elf_read_symbols(struct elf_file *efile, int section_index,
+ size_t *nsymp, GElf_Sym **symp);
+
+/*
+ * Read a string table described by a section header of an ELF file
+ * into a dynamically-allocated buffer.
+ */
+int elf_read_string_table(struct elf_file *efile, const GElf_Shdr *shdr,
+ long *strcnt, char **strtab);
+
+/*
+ * Read a table of relocation objects from a section of an ELF file
+ * into a dynamically-allocated array of GElf_Rel objects.
+ */
+int elf_read_rel(struct elf_file *efile, int section_index, long *nrelp,
+ GElf_Rel **relp);
+
+/*
+ * Read a table of relocation-with-addend objects from a section of an
+ * ELF file into a dynamically-allocated array of GElf_Rela objects.
+ */
+int elf_read_rela(struct elf_file *efile, int section_index, long *nrelap,
+ GElf_Rela **relap);
+
+/*
+ * Read a string from an ELF file and return it in the provided
+ * buffer. If the string is longer than the buffer, this fails with
+ * EFAULT. The address parameter gives the address of the data buffer
+ * if the ELF file were loaded into memory rather than a direct file
+ * offset.
+ */
+int elf_read_string(struct elf_file *efile, GElf_Addr address, void *dst,
+ size_t len);
+
+/* Return the address extracted from a target pointer stored at 'p'. */
+GElf_Addr elf_address_from_pointer(struct elf_file *efile, const void *p);
+
+/*
+ * Read a linker set and return an array of addresses extracted from the
+ * relocated pointers in the linker set.
+ */
+int elf_read_linker_set(struct elf_file *efile, const char *name,
+ GElf_Addr **buf, long *countp);
+
+/*
+ * Read and convert a target 'struct mod_depend' into a host
+ * 'struct Gmod_depend'.
+ */
+int elf_read_mod_depend(struct elf_file *efile, GElf_Addr addr,
+ struct Gmod_depend *mdp);
+
+/*
+ * Read and convert a target 'struct mod_version' into a host
+ * 'struct Gmod_version'.
+ */
+int elf_read_mod_version(struct elf_file *efile, GElf_Addr addr,
+ struct Gmod_version *mdv);
+
+/*
+ * Read and convert a target 'struct mod_metadata' into a host
+ * 'struct Gmod_metadata'.
+ */
+int elf_read_mod_metadata(struct elf_file *efile, GElf_Addr addr,
+ struct Gmod_metadata *md);
+
+/*
+ * Read and convert a target 'struct mod_pnp_match_info' into a host
+ * 'struct Gmod_pnp_match_info'.
+ */
+int elf_read_mod_pnp_match_info(struct elf_file *efile, GElf_Addr addr,
+ struct Gmod_pnp_match_info *pnp);
+
+/*
+ * Apply relocations to the values obtained from the file. `relbase' is the
+ * target relocation address of the section, and `dataoff/len' is the region
+ * that is to be relocated, and has been copied to *dest
+ */
+int elf_reloc(struct elf_file *ef, const void *reldata, Elf_Type reltype,
+ GElf_Addr relbase, GElf_Addr dataoff, size_t len, void *dest);
+
+/*
+ * Find the symbol with the specified symbol name 'name' within the given
+ * 'efile'. 0 is returned when such a symbol is found, otherwise ENOENT is
+ * returned.
+ */
+int elf_lookup_symbol(struct elf_file *efile, const char *name,
+ GElf_Sym **sym, bool see_local);
+
+__END_DECLS
+
+#endif /* _KLDELF_H_*/