#ifndef _SYS_LINKER_H_
#define _SYS_LINKER_H_
#ifndef _SYS_TYPES_H_
#include <sys/types.h>
#endif
#ifndef _SYS_PARAM_H_
#include <sys/param.h>
#endif
#ifdef _KERNEL
#ifndef _SYS_QUEUE_H_
#include <sys/queue.h>
#endif
#include <machine/elf.h>
#include <sys/module.h>
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_LINKER);
#endif
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 struct linker_symval {
const char* name;
caddr_t value;
size_t size;
} linker_symval_t;
struct linker_file_ops {
int (*lookup_symbol)(linker_file_t, const char* name,
c_linker_sym_t* sym);
int (*symbol_values)(linker_file_t, c_linker_sym_t,
linker_symval_t*);
int (*search_symbol)(linker_file_t, caddr_t value,
c_linker_sym_t* sym, long* diffp);
int (*preload_finish)(linker_file_t);
void (*unload)(linker_file_t);
int (*lookup_set)(linker_file_t, const char *name,
void ***firstp, void ***lastp, int *countp);
};
struct common_symbol {
STAILQ_ENTRY(common_symbol) link;
char* name;
caddr_t address;
};
struct linker_file {
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;
int ndeps;
linker_file_t* deps;
STAILQ_HEAD(, common_symbol) common;
TAILQ_HEAD(, module) modules;
TAILQ_ENTRY(linker_file) loaded;
void* priv;
struct linker_file_ops* ops;
};
typedef struct linker_class *linker_class_t;
typedef TAILQ_HEAD(, linker_class) linker_class_list_t;
struct linker_class_ops {
int (*load_file)(const char *filename, linker_file_t *result);
int (*preload_file)(const char *filename, linker_file_t *result);
};
struct linker_class {
TAILQ_ENTRY(linker_class) link;
const char* desc;
void* priv;
struct linker_class_ops *ops;
};
typedef int linker_predicate_t(linker_file_t, void *);
extern linker_file_t linker_current_file;
extern linker_file_t linker_kernel_file;
int linker_add_class(const char* _desc, void* _priv,
struct linker_class_ops* _ops);
int linker_load_file(const char *_filename, linker_file_t *_result);
linker_file_t linker_find_file_by_name(const char* _filename);
linker_file_t linker_find_file_by_id(int _fileid);
linker_file_t linker_make_file(const char* _filename, void* _priv,
struct linker_file_ops* _ops);
int linker_file_unload(linker_file_t _file);
void linker_file_add_dependancy(linker_file_t _file, linker_file_t _dep);
int linker_load_dependencies(linker_file_t lf);
int linker_file_foreach(linker_predicate_t *_predicate, void *_context);
int linker_file_lookup_symbol(linker_file_t _file, const char* _name,
int _deps, caddr_t *);
int linker_file_lookup_set(linker_file_t _file, const char *_name,
void *_start, void *_stop, int *_count);
char *linker_search_path(const char *_filename);
int linker_reference_module(const char *modname, struct mod_depend *verinfo,
linker_file_t *retult);
int linker_release_module(const char *modname, struct mod_depend *verinfo,
linker_file_t lf);
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);
#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
#define MODINFOMD_ENVP 0x0006
#define MODINFOMD_HOWTO 0x0007
#define MODINFOMD_KERNEND 0x0008
#define MODINFOMD_SHDR 0x0009
#define MODINFOMD_FW_HANDLE 0x000a
#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
#ifdef _KERNEL
extern caddr_t preload_metadata;
caddr_t preload_search_by_name(const char *);
caddr_t preload_search_by_type(const char *);
caddr_t preload_search_next_name(caddr_t);
caddr_t preload_search_info(caddr_t, int);
void preload_delete_name(const char *);
void preload_bootstrap_relocate(vm_offset_t);
extern struct mod_metadata *find_mod_metadata(const char *);
#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) kprintf 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, Elf_Addr, const void *, int, elf_lookup_fn);
int elf_reloc_local(linker_file_t, Elf_Addr, const void *, int, elf_lookup_fn);
Elf_Addr elf_relocaddr(linker_file_t, Elf_Addr);
#define ELF_RELOC_REL 1
#define ELF_RELOC_RELA 2
#endif
struct kld_file_stat {
int version;
char name[MAXPATHLEN];
char pathname[MAXPATHLEN];
int refs;
int id;
caddr_t address;
size_t size;
};
struct kld_sym_lookup {
int version;
const char *symname;
u_long symvalue;
size_t symsize;
};
#define KLDSYM_LOOKUP 1
#ifndef _KERNEL
#ifndef _SYS_CDEFS_H_
#include <sys/cdefs.h>
#endif
__BEGIN_DECLS
int kldload(const char *);
int kldunload(int);
int kldfind(const char *);
int kldnext(int);
int kldstat(int, struct kld_file_stat *);
int kldfirstmod(int);
int kldsym(int, int, void *);
__END_DECLS
#endif
#endif