HardenedBSD/lib/libkldelf/kldelf.h
Ka Ho Ng 72e15f76a1 libkldelf: add see_local parameter to elf_lookup_symbol
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
2024-10-25 16:20:16 +00:00

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_*/