#ifndef _SYS_LINKER_H_
#define _SYS_LINKER_H_
#ifdef _KERNEL
#include <machine/elf.h>
#include <sys/kobj.h>
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_LINKER);
#endif
struct mod_depend;
typedef struct linker_file* linker_file_t;
typedef TAILQ_HEAD(, linker_file) linker_file_list_t;
typedef caddr_t linker_sym_t;
typedef c_caddr_t c_linker_sym_t;
typedef int (*linker_function_name_callback_t)(const char *, void *);
typedef struct linker_symval {
const char* name;
caddr_t value;
size_t size;
} linker_symval_t;
typedef int (*linker_function_nameval_callback_t)(linker_file_t, int, linker_symval_t *, void *);
struct common_symbol {
STAILQ_ENTRY(common_symbol) link;
char* name;
caddr_t address;
};
struct linker_file {
KOBJ_FIELDS;
int refs;
int userrefs;
int flags;
#define LINKER_FILE_LINKED 0x1
TAILQ_ENTRY(linker_file) link;
char* filename;
char* pathname;
int id;
caddr_t address;
size_t size;
caddr_t ctors_addr;
size_t ctors_size;
int ndeps;
linker_file_t* deps;
STAILQ_HEAD(, common_symbol) common;
TAILQ_HEAD(, module) modules;
TAILQ_ENTRY(linker_file) loaded;
int loadcnt;
int nenabled;
int fbt_nentries;
};
typedef struct linker_class *linker_class_t;
typedef TAILQ_HEAD(, linker_class) linker_class_list_t;
struct linker_class {
KOBJ_CLASS_FIELDS;
TAILQ_ENTRY(linker_class) link;
};
typedef int linker_predicate_t(linker_file_t, void *);
extern linker_file_t linker_kernel_file;
int linker_reference_module(const char* _modname, struct mod_depend *_verinfo,
linker_file_t* _result);
int linker_release_module(const char *_modname, struct mod_depend *_verinfo,
linker_file_t _file);
int linker_file_foreach(linker_predicate_t *_predicate, void *_context);
caddr_t linker_file_lookup_symbol(linker_file_t _file, const char* _name,
int _deps);
int linker_file_lookup_set(linker_file_t _file, const char *_name,
void *_start, void *_stop, int *_count);
int linker_file_function_listall(linker_file_t,
linker_function_nameval_callback_t, void *);
int linker_add_class(linker_class_t _cls);
int linker_file_unload(linker_file_t _file, int flags);
int linker_load_dependencies(linker_file_t _lf);
linker_file_t linker_make_file(const char* _filename, linker_class_t _cls);
int linker_ddb_lookup(const char *_symstr, c_linker_sym_t *_sym);
int linker_ddb_search_symbol(caddr_t _value, c_linker_sym_t *_sym,
long *_diffp);
int linker_ddb_symbol_values(c_linker_sym_t _sym, linker_symval_t *_symval);
int linker_ddb_search_symbol_name(caddr_t value, char *buf, u_int buflen,
long *offset);
int linker_search_symbol_name(caddr_t value, char *buf, u_int buflen,
long *offset);
void *linker_hwpmc_list_objects(void);
#endif
#define MODINFO_END 0x0000
#define MODINFO_NAME 0x0001
#define MODINFO_TYPE 0x0002
#define MODINFO_ADDR 0x0003
#define MODINFO_SIZE 0x0004
#define MODINFO_EMPTY 0x0005
#define MODINFO_ARGS 0x0006
#define MODINFO_METADATA 0x8000
#define MODINFOMD_AOUTEXEC 0x0001
#define MODINFOMD_ELFHDR 0x0002
#define MODINFOMD_SSYM 0x0003
#define MODINFOMD_ESYM 0x0004
#define MODINFOMD_DYNAMIC 0x0005
#if !defined(__sparc64__) && !defined(__powerpc__)
#define MODINFOMD_ENVP 0x0006
#define MODINFOMD_HOWTO 0x0007
#define MODINFOMD_KERNEND 0x0008
#endif
#define MODINFOMD_SHDR 0x0009
#define MODINFOMD_CTORS_ADDR 0x000a
#define MODINFOMD_CTORS_SIZE 0x000b
#define MODINFOMD_FW_HANDLE 0x000c
#define MODINFOMD_NOCOPY 0x8000
#define MODINFOMD_DEPLIST (0x4001 | MODINFOMD_NOCOPY)
#ifdef _KERNEL
#define MD_FETCH(mdp, info, type) ({ \
type *__p; \
__p = (type *)preload_search_info((mdp), MODINFO_METADATA | (info)); \
__p ? *__p : 0; \
})
#endif
#define LINKER_HINTS_VERSION 1
#define LINKER_HINTS_MAX (1 << 20)
#ifdef _KERNEL
extern vm_offset_t preload_addr_relocate;
extern caddr_t preload_metadata;
extern void * preload_fetch_addr(caddr_t _mod);
extern size_t preload_fetch_size(caddr_t _mod);
extern caddr_t preload_search_by_name(const char *_name);
extern caddr_t preload_search_by_type(const char *_type);
extern caddr_t preload_search_next_name(caddr_t _base);
extern caddr_t preload_search_info(caddr_t _mod, int _inf);
extern void preload_delete_name(const char *_name);
extern void preload_bootstrap_relocate(vm_offset_t _offset);
#ifdef KLD_DEBUG
extern int kld_debug;
#define KLD_DEBUG_FILE 1
#define KLD_DEBUG_SYM 2
#define KLD_DPF(cat, args) \
do { \
if (kld_debug & KLD_DEBUG_##cat) printf args; \
} while (0)
#else
#define KLD_DPF(cat, args)
#endif
typedef int elf_lookup_fn(linker_file_t, Elf_Size, int, Elf_Addr *);
int elf_reloc(linker_file_t _lf, Elf_Addr base, const void *_rel, int _type, elf_lookup_fn _lu);
int elf_reloc_local(linker_file_t _lf, Elf_Addr base, const void *_rel, int _type, elf_lookup_fn _lu);
Elf_Addr elf_relocaddr(linker_file_t _lf, Elf_Addr addr);
const Elf_Sym *elf_get_sym(linker_file_t _lf, Elf_Size _symidx);
const char *elf_get_symname(linker_file_t _lf, Elf_Size _symidx);
typedef struct linker_ctf {
const uint8_t *ctftab;
int ctfcnt;
const Elf_Sym *symtab;
int nsym;
const char *strtab;
int strcnt;
uint32_t **ctfoffp;
uint32_t **typoffp;
long *typlenp;
} linker_ctf_t;
int linker_ctf_get(linker_file_t, linker_ctf_t *);
int elf_cpu_load_file(linker_file_t);
int elf_cpu_unload_file(linker_file_t);
#define ELF_RELOC_REL 1
#define ELF_RELOC_RELA 2
struct kld_file_stat_1 {
int version;
char name[MAXPATHLEN];
int refs;
int id;
caddr_t address;
size_t size;
};
#endif
struct kld_file_stat {
int version;
char name[MAXPATHLEN];
int refs;
int id;
caddr_t address;
size_t size;
char pathname[MAXPATHLEN];
};
struct kld_sym_lookup {
int version;
char *symname;
u_long symvalue;
size_t symsize;
};
#define KLDSYM_LOOKUP 1
#define LINKER_UNLOAD_NORMAL 0
#define LINKER_UNLOAD_FORCE 1
#ifndef _KERNEL
#include <sys/cdefs.h>
__BEGIN_DECLS
int kldload(const char* _file);
int kldunload(int _fileid);
int kldunloadf(int _fileid, int flags);
int kldfind(const char* _file);
int kldnext(int _fileid);
int kldstat(int _fileid, struct kld_file_stat* _stat);
int kldfirstmod(int _fileid);
int kldsym(int _fileid, int _cmd, void *_data);
__END_DECLS
#endif
#endif