mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-11-25 18:12:57 +01:00
72e15f76a1
This gives the function the ability to return only global symbols. Sponsored by: Juniper Networks, Inc. Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D47206
328 lines
11 KiB
C
328 lines
11 KiB
C
/*-
|
|
* 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_*/
|