125537Sdfr/*- 259603Sdfr * Copyright (c) 1997-2000 Doug Rabson 325537Sdfr * All rights reserved. 425537Sdfr * 525537Sdfr * Redistribution and use in source and binary forms, with or without 625537Sdfr * modification, are permitted provided that the following conditions 725537Sdfr * are met: 825537Sdfr * 1. Redistributions of source code must retain the above copyright 925537Sdfr * notice, this list of conditions and the following disclaimer. 1025537Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1125537Sdfr * notice, this list of conditions and the following disclaimer in the 1225537Sdfr * documentation and/or other materials provided with the distribution. 1325537Sdfr * 1425537Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1525537Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1625537Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1725537Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1825537Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1925537Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2025537Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2125537Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2225537Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2325537Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2425537Sdfr * SUCH DAMAGE. 2525537Sdfr * 2650477Speter * $FreeBSD$ 2725537Sdfr */ 2825537Sdfr 2925537Sdfr#ifndef _SYS_LINKER_H_ 3025537Sdfr#define _SYS_LINKER_H_ 3125537Sdfr 3255205Speter#ifdef _KERNEL 3325537Sdfr 3440138Speter#include <machine/elf.h> 3559603Sdfr#include <sys/kobj.h> 3640138Speter 3732152Sbde#ifdef MALLOC_DECLARE 3832152SbdeMALLOC_DECLARE(M_LINKER); 3932152Sbde#endif 4025537Sdfr 4194321Sbrianstruct mod_depend; 4294321Sbrian 4325537Sdfr/* 4425537Sdfr * Object representing a file which has been loaded by the linker. 4525537Sdfr */ 4625537Sdfrtypedef struct linker_file* linker_file_t; 4760938Sjaketypedef TAILQ_HEAD(, linker_file) linker_file_list_t; 4825537Sdfr 4943301Sdillontypedef caddr_t linker_sym_t; /* opaque symbol */ 5043301Sdillontypedef c_caddr_t c_linker_sym_t; /* const opaque symbol */ 5185736Sgreentypedef int (*linker_function_name_callback_t)(const char *, void *); 5238275Sdfr 5338275Sdfr/* 5438275Sdfr * expanded out linker_sym_t 5538275Sdfr */ 5638275Sdfrtypedef struct linker_symval { 5738275Sdfr const char* name; 5838275Sdfr caddr_t value; 5938275Sdfr size_t size; 6038275Sdfr} linker_symval_t; 6138275Sdfr 62179223Sjbtypedef int (*linker_function_nameval_callback_t)(linker_file_t, int, linker_symval_t *, void *); 63173714Sjb 6425537Sdfrstruct common_symbol { 6560938Sjake STAILQ_ENTRY(common_symbol) link; 6625537Sdfr char* name; 6725537Sdfr caddr_t address; 6825537Sdfr}; 6925537Sdfr 7025537Sdfrstruct linker_file { 7159603Sdfr KOBJ_FIELDS; 7225537Sdfr int refs; /* reference count */ 7340138Speter int userrefs; /* kldload(2) count */ 7443185Sdfr int flags; 7543185Sdfr#define LINKER_FILE_LINKED 0x1 /* file has been fully linked */ 7660938Sjake TAILQ_ENTRY(linker_file) link; /* list of all loaded files */ 7725537Sdfr char* filename; /* file which was loaded */ 78172862Sjb char* pathname; /* file name with full path */ 7925537Sdfr int id; /* unique id */ 8025537Sdfr caddr_t address; /* load address */ 8125537Sdfr size_t size; /* size of file */ 8286469Siedowse int ndeps; /* number of dependencies */ 8386469Siedowse linker_file_t* deps; /* list of dependencies */ 8460938Sjake STAILQ_HEAD(, common_symbol) common; /* list of common symbols */ 8560938Sjake TAILQ_HEAD(, module) modules; /* modules in this file */ 8660938Sjake TAILQ_ENTRY(linker_file) loaded; /* preload dependency support */ 87172862Sjb int loadcnt; /* load counter value */ 88172862Sjb 89172862Sjb /* 90172862Sjb * Function Boundary Tracing (FBT) or Statically Defined Tracing (SDT) 91172862Sjb * fields. 92172862Sjb */ 93172862Sjb int nenabled; /* number of enabled probes. */ 94172862Sjb int fbt_nentries; /* number of fbt entries created. */ 9525537Sdfr}; 9625537Sdfr 9725537Sdfr/* 9825537Sdfr * Object implementing a class of file (a.out, elf, etc.) 9925537Sdfr */ 10025537Sdfrtypedef struct linker_class *linker_class_t; 10160938Sjaketypedef TAILQ_HEAD(, linker_class) linker_class_list_t; 10225537Sdfr 10325537Sdfrstruct linker_class { 10459603Sdfr KOBJ_CLASS_FIELDS; 10560938Sjake TAILQ_ENTRY(linker_class) link; /* list of all file classes */ 10625537Sdfr}; 10725537Sdfr 10825537Sdfr/* 109159797Sjhb * Function type used when iterating over the list of linker files. 110159797Sjhb */ 111159797Sjhbtypedef int linker_predicate_t(linker_file_t, void *); 112159797Sjhb 113159797Sjhb/* 11440906Speter * The "file" for the kernel. 11540906Speter */ 11640906Speterextern linker_file_t linker_kernel_file; 11740906Speter 11840906Speter/* 11978413Sbrian * Obtain a reference to a module, loading it if required. 12078413Sbrian */ 12194321Sbrianint linker_reference_module(const char* _modname, struct mod_depend *_verinfo, 12294321Sbrian linker_file_t* _result); 12378413Sbrian 12478413Sbrian/* 125159804Sjhb * Release a reference to a module, unloading it if there are no more 126159804Sjhb * references. Note that one should either provide a module name and 127159804Sjhb * optional version info or a linker file, but not both. 128159804Sjhb */ 129159804Sjhbint linker_release_module(const char *_modname, struct mod_depend *_verinfo, 130159804Sjhb linker_file_t _file); 131159804Sjhb 132159804Sjhb/* 133159797Sjhb * Iterate over all of the currently loaded linker files calling the 134159797Sjhb * predicate function while the function returns 0. Returns the value 135159797Sjhb * returned by the last predicate function. 136159797Sjhb */ 137159797Sjhbint linker_file_foreach(linker_predicate_t *_predicate, void *_context); 138159797Sjhb 139159797Sjhb/* 14086469Siedowse * Lookup a symbol in a file. If deps is TRUE, look in dependencies 14125537Sdfr * if not found in file. 14225537Sdfr */ 14363858Sjhbcaddr_t linker_file_lookup_symbol(linker_file_t _file, const char* _name, 14463858Sjhb int _deps); 14525537Sdfr 14639179Smsmith/* 14778161Speter * Lookup a linker set in a file. Return pointers to the first entry, 14878161Speter * last + 1, and count of entries. Use: for (p = start; p < stop; p++) {} 14978161Speter * void *start is really: "struct yoursetmember ***start;" 15078161Speter */ 15178161Speterint linker_file_lookup_set(linker_file_t _file, const char *_name, 15278161Speter void *_start, void *_stop, int *_count); 15378161Speter 15478161Speter/* 155173714Sjb * List all functions in a file. 156173714Sjb */ 157179223Sjbint linker_file_function_listall(linker_file_t, 158179223Sjb linker_function_nameval_callback_t, void *); 159173714Sjb 160173714Sjb/* 161159805Sjhb * Functions soley for use by the linker class handlers. 16240138Speter */ 163159805Sjhbint linker_add_class(linker_class_t _cls); 164159805Sjhbint linker_file_unload(linker_file_t _file, int flags); 16586469Siedowseint linker_load_dependencies(linker_file_t _lf); 166159805Sjhblinker_file_t linker_make_file(const char* _filename, linker_class_t _cls); 16740138Speter 16840138Speter/* 16940138Speter * DDB Helpers, tuned specifically for ddb/db_kld.c 17040138Speter */ 17163858Sjhbint linker_ddb_lookup(const char *_symstr, c_linker_sym_t *_sym); 17263858Sjhbint linker_ddb_search_symbol(caddr_t _value, c_linker_sym_t *_sym, 17363858Sjhb long *_diffp); 17463858Sjhbint linker_ddb_symbol_values(c_linker_sym_t _sym, linker_symval_t *_symval); 175174132Srwatsonint linker_ddb_search_symbol_name(caddr_t value, char *buf, u_int buflen, 176174132Srwatson long *offset); 17740138Speter 178174132Srwatson/* 179174132Srwatson * stack(9) helper for situations where kernel locking is required. 180174132Srwatson */ 181174132Srwatsonint linker_search_symbol_name(caddr_t value, char *buf, u_int buflen, 182174132Srwatson long *offset); 18340138Speter 184174132Srwatson 185157144Sjkoshy/* HWPMC helper */ 186157144Sjkoshyvoid *linker_hwpmc_list_objects(void); 187157144Sjkoshy 18855205Speter#endif /* _KERNEL */ 18940138Speter 19040138Speter/* 19139179Smsmith * Module information subtypes 19239179Smsmith */ 19340138Speter#define MODINFO_END 0x0000 /* End of list */ 19440138Speter#define MODINFO_NAME 0x0001 /* Name of module (string) */ 19540138Speter#define MODINFO_TYPE 0x0002 /* Type of module (string) */ 19640138Speter#define MODINFO_ADDR 0x0003 /* Loaded address */ 19740138Speter#define MODINFO_SIZE 0x0004 /* Size of module */ 19840138Speter#define MODINFO_EMPTY 0x0005 /* Has been deleted */ 19944572Sdcs#define MODINFO_ARGS 0x0006 /* Parameters string */ 20040138Speter#define MODINFO_METADATA 0x8000 /* Module-specfic */ 20139179Smsmith 20239179Smsmith#define MODINFOMD_AOUTEXEC 0x0001 /* a.out exec header */ 20339179Smsmith#define MODINFOMD_ELFHDR 0x0002 /* ELF header */ 20440138Speter#define MODINFOMD_SSYM 0x0003 /* start of symbols */ 20540138Speter#define MODINFOMD_ESYM 0x0004 /* end of symbols */ 20640138Speter#define MODINFOMD_DYNAMIC 0x0005 /* _DYNAMIC pointer */ 207114373Speter/* These values are MD on these two platforms */ 208114373Speter#if !defined(__sparc64__) && !defined(__powerpc__) 209114373Speter#define MODINFOMD_ENVP 0x0006 /* envp[] */ 210114373Speter#define MODINFOMD_HOWTO 0x0007 /* boothowto */ 211114373Speter#define MODINFOMD_KERNEND 0x0008 /* kernend */ 212114373Speter#endif 213134363Siedowse#define MODINFOMD_SHDR 0x0009 /* section header table */ 21439179Smsmith#define MODINFOMD_NOCOPY 0x8000 /* don't copy this metadata to the kernel */ 21539179Smsmith 21640138Speter#define MODINFOMD_DEPLIST (0x4001 | MODINFOMD_NOCOPY) /* depends on */ 21739179Smsmith 218114373Speter#ifdef _KERNEL 219114373Speter#define MD_FETCH(mdp, info, type) ({ \ 220114373Speter type *__p; \ 221114373Speter __p = (type *)preload_search_info((mdp), MODINFO_METADATA | (info)); \ 222114373Speter __p ? *__p : 0; \ 223114373Speter}) 224114373Speter#endif 225114373Speter 22683321Speter#define LINKER_HINTS_VERSION 1 /* linker.hints file version */ 22783321Speter 22855205Speter#ifdef _KERNEL 22940138Speter 23040096Smsmith/* 23140096Smsmith * Module lookup 23240096Smsmith */ 233218494Smarcelextern vm_offset_t preload_addr_relocate; 23440138Speterextern caddr_t preload_metadata; 235218494Smarcel 236218494Smarcelextern void * preload_fetch_addr(caddr_t _mod); 237218494Smarcelextern size_t preload_fetch_size(caddr_t _mod); 23863858Sjhbextern caddr_t preload_search_by_name(const char *_name); 23963858Sjhbextern caddr_t preload_search_by_type(const char *_type); 24063858Sjhbextern caddr_t preload_search_next_name(caddr_t _base); 24163858Sjhbextern caddr_t preload_search_info(caddr_t _mod, int _inf); 24263858Sjhbextern void preload_delete_name(const char *_name); 24363858Sjhbextern void preload_bootstrap_relocate(vm_offset_t _offset); 24440096Smsmith 24525537Sdfr#ifdef KLD_DEBUG 24625537Sdfr 24725537Sdfrextern int kld_debug; 24825537Sdfr#define KLD_DEBUG_FILE 1 /* file load/unload */ 24925537Sdfr#define KLD_DEBUG_SYM 2 /* symbol lookup */ 25025537Sdfr 25125537Sdfr#define KLD_DPF(cat, args) \ 25225537Sdfr do { \ 25340138Speter if (kld_debug & KLD_DEBUG_##cat) printf args; \ 25425537Sdfr } while (0) 25525537Sdfr 25625537Sdfr#else 25725537Sdfr 25825537Sdfr#define KLD_DPF(cat, args) 25925537Sdfr 26025537Sdfr#endif 26125537Sdfr 262153504Smarceltypedef Elf_Addr elf_lookup_fn(linker_file_t, Elf_Size, int); 263129282Speter 26440138Speter/* Support functions */ 265129282Speterint elf_reloc(linker_file_t _lf, Elf_Addr base, const void *_rel, int _type, elf_lookup_fn _lu); 266129282Speterint elf_reloc_local(linker_file_t _lf, Elf_Addr base, const void *_rel, int _type, elf_lookup_fn _lu); 267194784SjeffElf_Addr elf_relocaddr(linker_file_t _lf, Elf_Addr addr); 268153504Smarcelconst Elf_Sym *elf_get_sym(linker_file_t _lf, Elf_Size _symidx); 269153504Smarcelconst char *elf_get_symname(linker_file_t _lf, Elf_Size _symidx); 27095410Smarcel 271179223Sjbtypedef struct linker_ctf { 272179223Sjb const uint8_t *ctftab; /* Decompressed CTF data. */ 273179223Sjb int ctfcnt; /* Number of CTF data bytes. */ 274179223Sjb const Elf_Sym *symtab; /* Ptr to the symbol table. */ 275179223Sjb int nsym; /* Number of symbols. */ 276179223Sjb const char *strtab; /* Ptr to the string table. */ 277179223Sjb int strcnt; /* Number of string bytes. */ 278179223Sjb uint32_t **ctfoffp; /* Ptr to array of obj/fnc offsets. */ 279179223Sjb uint32_t **typoffp; /* Ptr to array of type offsets. */ 280179223Sjb long *typlenp; /* Ptr to number of type data entries. */ 281179223Sjb} linker_ctf_t; 282179223Sjb 283179223Sjbint linker_ctf_get(linker_file_t, linker_ctf_t *); 284179223Sjb 285105469Smarcelint elf_cpu_load_file(linker_file_t); 286105469Smarcelint elf_cpu_unload_file(linker_file_t); 287105469Smarcel 28840435Speter/* values for type */ 28940435Speter#define ELF_RELOC_REL 1 29040435Speter#define ELF_RELOC_RELA 2 29140138Speter 292172862Sjb/* 293172862Sjb * This is version 1 of the KLD file status structure. It is identified 294173841Sru * by its _size_ in the version field. 295172862Sjb */ 296172862Sjbstruct kld_file_stat_1 { 297173841Sru int version; /* set to sizeof(struct kld_file_stat_1) */ 298172862Sjb char name[MAXPATHLEN]; 299172862Sjb int refs; 300172862Sjb int id; 301172862Sjb caddr_t address; /* load address */ 302172862Sjb size_t size; /* size in bytes */ 303172862Sjb}; 30455205Speter#endif /* _KERNEL */ 30525537Sdfr 30625537Sdfrstruct kld_file_stat { 307173841Sru int version; /* set to sizeof(struct kld_file_stat) */ 30825537Sdfr char name[MAXPATHLEN]; 30925537Sdfr int refs; 31025537Sdfr int id; 31125537Sdfr caddr_t address; /* load address */ 31225537Sdfr size_t size; /* size in bytes */ 313172862Sjb char pathname[MAXPATHLEN]; 31425537Sdfr}; 31525537Sdfr 31641090Speterstruct kld_sym_lookup { 31741090Speter int version; /* set to sizeof(struct kld_sym_lookup) */ 31841090Speter char *symname; /* Symbol name we are looking up */ 31941090Speter u_long symvalue; 32041090Speter size_t symsize; 32141090Speter}; 32241090Speter#define KLDSYM_LOOKUP 1 32341090Speter 324132117Sphk/* 325132117Sphk * Flags for kldunloadf() and linker_file_unload() 326132117Sphk */ 327132117Sphk#define LINKER_UNLOAD_NORMAL 0 328132117Sphk#define LINKER_UNLOAD_FORCE 1 329132117Sphk 33055205Speter#ifndef _KERNEL 33125537Sdfr 33225537Sdfr#include <sys/cdefs.h> 33325537Sdfr 33425537Sdfr__BEGIN_DECLS 33563858Sjhbint kldload(const char* _file); 33663858Sjhbint kldunload(int _fileid); 337132117Sphkint kldunloadf(int _fileid, int flags); 33863858Sjhbint kldfind(const char* _file); 33963858Sjhbint kldnext(int _fileid); 34063858Sjhbint kldstat(int _fileid, struct kld_file_stat* _stat); 34163858Sjhbint kldfirstmod(int _fileid); 34241090Speterint kldsym(int _fileid, int _cmd, void *_data); 34325537Sdfr__END_DECLS 34425537Sdfr 34525537Sdfr#endif 34625537Sdfr 34732152Sbde#endif /* !_SYS_LINKER_H_ */ 348