1*199767f8SToomas Soome /*- 2*199767f8SToomas Soome * Copyright (c) 1997-2000 Doug Rabson 3*199767f8SToomas Soome * All rights reserved. 4*199767f8SToomas Soome * 5*199767f8SToomas Soome * Redistribution and use in source and binary forms, with or without 6*199767f8SToomas Soome * modification, are permitted provided that the following conditions 7*199767f8SToomas Soome * are met: 8*199767f8SToomas Soome * 1. Redistributions of source code must retain the above copyright 9*199767f8SToomas Soome * notice, this list of conditions and the following disclaimer. 10*199767f8SToomas Soome * 2. Redistributions in binary form must reproduce the above copyright 11*199767f8SToomas Soome * notice, this list of conditions and the following disclaimer in the 12*199767f8SToomas Soome * documentation and/or other materials provided with the distribution. 13*199767f8SToomas Soome * 14*199767f8SToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*199767f8SToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*199767f8SToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*199767f8SToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*199767f8SToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*199767f8SToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*199767f8SToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*199767f8SToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*199767f8SToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*199767f8SToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*199767f8SToomas Soome * SUCH DAMAGE. 25*199767f8SToomas Soome * 26*199767f8SToomas Soome * $FreeBSD$ 27*199767f8SToomas Soome */ 28*199767f8SToomas Soome 29*199767f8SToomas Soome #ifndef _SYS_LINKER_H_ 30*199767f8SToomas Soome #define _SYS_LINKER_H_ 31*199767f8SToomas Soome 32*199767f8SToomas Soome #ifdef _KERNEL 33*199767f8SToomas Soome 34*199767f8SToomas Soome #include <machine/elf.h> 35*199767f8SToomas Soome #include <sys/kobj.h> 36*199767f8SToomas Soome 37*199767f8SToomas Soome #ifdef MALLOC_DECLARE 38*199767f8SToomas Soome MALLOC_DECLARE(M_LINKER); 39*199767f8SToomas Soome #endif 40*199767f8SToomas Soome 41*199767f8SToomas Soome struct mod_depend; 42*199767f8SToomas Soome 43*199767f8SToomas Soome /* 44*199767f8SToomas Soome * Object representing a file which has been loaded by the linker. 45*199767f8SToomas Soome */ 46*199767f8SToomas Soome typedef struct linker_file* linker_file_t; 47*199767f8SToomas Soome typedef TAILQ_HEAD(, linker_file) linker_file_list_t; 48*199767f8SToomas Soome 49*199767f8SToomas Soome typedef caddr_t linker_sym_t; /* opaque symbol */ 50*199767f8SToomas Soome typedef c_caddr_t c_linker_sym_t; /* const opaque symbol */ 51*199767f8SToomas Soome typedef int (*linker_function_name_callback_t)(const char *, void *); 52*199767f8SToomas Soome 53*199767f8SToomas Soome /* 54*199767f8SToomas Soome * expanded out linker_sym_t 55*199767f8SToomas Soome */ 56*199767f8SToomas Soome typedef struct linker_symval { 57*199767f8SToomas Soome const char* name; 58*199767f8SToomas Soome caddr_t value; 59*199767f8SToomas Soome size_t size; 60*199767f8SToomas Soome } linker_symval_t; 61*199767f8SToomas Soome 62*199767f8SToomas Soome typedef int (*linker_function_nameval_callback_t)(linker_file_t, int, linker_symval_t *, void *); 63*199767f8SToomas Soome 64*199767f8SToomas Soome struct common_symbol { 65*199767f8SToomas Soome STAILQ_ENTRY(common_symbol) link; 66*199767f8SToomas Soome char* name; 67*199767f8SToomas Soome caddr_t address; 68*199767f8SToomas Soome }; 69*199767f8SToomas Soome 70*199767f8SToomas Soome struct linker_file { 71*199767f8SToomas Soome KOBJ_FIELDS; 72*199767f8SToomas Soome int refs; /* reference count */ 73*199767f8SToomas Soome int userrefs; /* kldload(2) count */ 74*199767f8SToomas Soome int flags; 75*199767f8SToomas Soome #define LINKER_FILE_LINKED 0x1 /* file has been fully linked */ 76*199767f8SToomas Soome TAILQ_ENTRY(linker_file) link; /* list of all loaded files */ 77*199767f8SToomas Soome char* filename; /* file which was loaded */ 78*199767f8SToomas Soome char* pathname; /* file name with full path */ 79*199767f8SToomas Soome int id; /* unique id */ 80*199767f8SToomas Soome caddr_t address; /* load address */ 81*199767f8SToomas Soome size_t size; /* size of file */ 82*199767f8SToomas Soome caddr_t ctors_addr; /* address of .ctors */ 83*199767f8SToomas Soome size_t ctors_size; /* size of .ctors */ 84*199767f8SToomas Soome int ndeps; /* number of dependencies */ 85*199767f8SToomas Soome linker_file_t* deps; /* list of dependencies */ 86*199767f8SToomas Soome STAILQ_HEAD(, common_symbol) common; /* list of common symbols */ 87*199767f8SToomas Soome TAILQ_HEAD(, module) modules; /* modules in this file */ 88*199767f8SToomas Soome TAILQ_ENTRY(linker_file) loaded; /* preload dependency support */ 89*199767f8SToomas Soome int loadcnt; /* load counter value */ 90*199767f8SToomas Soome 91*199767f8SToomas Soome /* 92*199767f8SToomas Soome * Function Boundary Tracing (FBT) or Statically Defined Tracing (SDT) 93*199767f8SToomas Soome * fields. 94*199767f8SToomas Soome */ 95*199767f8SToomas Soome int nenabled; /* number of enabled probes. */ 96*199767f8SToomas Soome int fbt_nentries; /* number of fbt entries created. */ 97*199767f8SToomas Soome }; 98*199767f8SToomas Soome 99*199767f8SToomas Soome /* 100*199767f8SToomas Soome * Object implementing a class of file (a.out, elf, etc.) 101*199767f8SToomas Soome */ 102*199767f8SToomas Soome typedef struct linker_class *linker_class_t; 103*199767f8SToomas Soome typedef TAILQ_HEAD(, linker_class) linker_class_list_t; 104*199767f8SToomas Soome 105*199767f8SToomas Soome struct linker_class { 106*199767f8SToomas Soome KOBJ_CLASS_FIELDS; 107*199767f8SToomas Soome TAILQ_ENTRY(linker_class) link; /* list of all file classes */ 108*199767f8SToomas Soome }; 109*199767f8SToomas Soome 110*199767f8SToomas Soome /* 111*199767f8SToomas Soome * Function type used when iterating over the list of linker files. 112*199767f8SToomas Soome */ 113*199767f8SToomas Soome typedef int linker_predicate_t(linker_file_t, void *); 114*199767f8SToomas Soome 115*199767f8SToomas Soome /* 116*199767f8SToomas Soome * The "file" for the kernel. 117*199767f8SToomas Soome */ 118*199767f8SToomas Soome extern linker_file_t linker_kernel_file; 119*199767f8SToomas Soome 120*199767f8SToomas Soome /* 121*199767f8SToomas Soome * Obtain a reference to a module, loading it if required. 122*199767f8SToomas Soome */ 123*199767f8SToomas Soome int linker_reference_module(const char* _modname, struct mod_depend *_verinfo, 124*199767f8SToomas Soome linker_file_t* _result); 125*199767f8SToomas Soome 126*199767f8SToomas Soome /* 127*199767f8SToomas Soome * Release a reference to a module, unloading it if there are no more 128*199767f8SToomas Soome * references. Note that one should either provide a module name and 129*199767f8SToomas Soome * optional version info or a linker file, but not both. 130*199767f8SToomas Soome */ 131*199767f8SToomas Soome int linker_release_module(const char *_modname, struct mod_depend *_verinfo, 132*199767f8SToomas Soome linker_file_t _file); 133*199767f8SToomas Soome 134*199767f8SToomas Soome /* 135*199767f8SToomas Soome * Iterate over all of the currently loaded linker files calling the 136*199767f8SToomas Soome * predicate function while the function returns 0. Returns the value 137*199767f8SToomas Soome * returned by the last predicate function. 138*199767f8SToomas Soome */ 139*199767f8SToomas Soome int linker_file_foreach(linker_predicate_t *_predicate, void *_context); 140*199767f8SToomas Soome 141*199767f8SToomas Soome /* 142*199767f8SToomas Soome * Lookup a symbol in a file. If deps is TRUE, look in dependencies 143*199767f8SToomas Soome * if not found in file. 144*199767f8SToomas Soome */ 145*199767f8SToomas Soome caddr_t linker_file_lookup_symbol(linker_file_t _file, const char* _name, 146*199767f8SToomas Soome int _deps); 147*199767f8SToomas Soome 148*199767f8SToomas Soome /* 149*199767f8SToomas Soome * Lookup a linker set in a file. Return pointers to the first entry, 150*199767f8SToomas Soome * last + 1, and count of entries. Use: for (p = start; p < stop; p++) {} 151*199767f8SToomas Soome * void *start is really: "struct yoursetmember ***start;" 152*199767f8SToomas Soome */ 153*199767f8SToomas Soome int linker_file_lookup_set(linker_file_t _file, const char *_name, 154*199767f8SToomas Soome void *_start, void *_stop, int *_count); 155*199767f8SToomas Soome 156*199767f8SToomas Soome /* 157*199767f8SToomas Soome * List all functions in a file. 158*199767f8SToomas Soome */ 159*199767f8SToomas Soome int linker_file_function_listall(linker_file_t, 160*199767f8SToomas Soome linker_function_nameval_callback_t, void *); 161*199767f8SToomas Soome 162*199767f8SToomas Soome /* 163*199767f8SToomas Soome * Functions soley for use by the linker class handlers. 164*199767f8SToomas Soome */ 165*199767f8SToomas Soome int linker_add_class(linker_class_t _cls); 166*199767f8SToomas Soome int linker_file_unload(linker_file_t _file, int flags); 167*199767f8SToomas Soome int linker_load_dependencies(linker_file_t _lf); 168*199767f8SToomas Soome linker_file_t linker_make_file(const char* _filename, linker_class_t _cls); 169*199767f8SToomas Soome 170*199767f8SToomas Soome /* 171*199767f8SToomas Soome * DDB Helpers, tuned specifically for ddb/db_kld.c 172*199767f8SToomas Soome */ 173*199767f8SToomas Soome int linker_ddb_lookup(const char *_symstr, c_linker_sym_t *_sym); 174*199767f8SToomas Soome int linker_ddb_search_symbol(caddr_t _value, c_linker_sym_t *_sym, 175*199767f8SToomas Soome long *_diffp); 176*199767f8SToomas Soome int linker_ddb_symbol_values(c_linker_sym_t _sym, linker_symval_t *_symval); 177*199767f8SToomas Soome int linker_ddb_search_symbol_name(caddr_t value, char *buf, u_int buflen, 178*199767f8SToomas Soome long *offset); 179*199767f8SToomas Soome 180*199767f8SToomas Soome /* 181*199767f8SToomas Soome * stack(9) helper for situations where kernel locking is required. 182*199767f8SToomas Soome */ 183*199767f8SToomas Soome int linker_search_symbol_name(caddr_t value, char *buf, u_int buflen, 184*199767f8SToomas Soome long *offset); 185*199767f8SToomas Soome 186*199767f8SToomas Soome 187*199767f8SToomas Soome /* HWPMC helper */ 188*199767f8SToomas Soome void *linker_hwpmc_list_objects(void); 189*199767f8SToomas Soome 190*199767f8SToomas Soome #endif /* _KERNEL */ 191*199767f8SToomas Soome 192*199767f8SToomas Soome /* 193*199767f8SToomas Soome * Module information subtypes 194*199767f8SToomas Soome */ 195*199767f8SToomas Soome #define MODINFO_END 0x0000 /* End of list */ 196*199767f8SToomas Soome #define MODINFO_NAME 0x0001 /* Name of module (string) */ 197*199767f8SToomas Soome #define MODINFO_TYPE 0x0002 /* Type of module (string) */ 198*199767f8SToomas Soome #define MODINFO_ADDR 0x0003 /* Loaded address */ 199*199767f8SToomas Soome #define MODINFO_SIZE 0x0004 /* Size of module */ 200*199767f8SToomas Soome #define MODINFO_EMPTY 0x0005 /* Has been deleted */ 201*199767f8SToomas Soome #define MODINFO_ARGS 0x0006 /* Parameters string */ 202*199767f8SToomas Soome #define MODINFO_METADATA 0x8000 /* Module-specfic */ 203*199767f8SToomas Soome 204*199767f8SToomas Soome #define MODINFOMD_AOUTEXEC 0x0001 /* a.out exec header */ 205*199767f8SToomas Soome #define MODINFOMD_ELFHDR 0x0002 /* ELF header */ 206*199767f8SToomas Soome #define MODINFOMD_SSYM 0x0003 /* start of symbols */ 207*199767f8SToomas Soome #define MODINFOMD_ESYM 0x0004 /* end of symbols */ 208*199767f8SToomas Soome #define MODINFOMD_DYNAMIC 0x0005 /* _DYNAMIC pointer */ 209*199767f8SToomas Soome /* These values are MD on these two platforms */ 210*199767f8SToomas Soome #if !defined(__sparc64__) && !defined(__powerpc__) 211*199767f8SToomas Soome #define MODINFOMD_ENVP 0x0006 /* envp[] */ 212*199767f8SToomas Soome #define MODINFOMD_HOWTO 0x0007 /* boothowto */ 213*199767f8SToomas Soome #define MODINFOMD_KERNEND 0x0008 /* kernend */ 214*199767f8SToomas Soome #endif 215*199767f8SToomas Soome #define MODINFOMD_SHDR 0x0009 /* section header table */ 216*199767f8SToomas Soome #define MODINFOMD_CTORS_ADDR 0x000a /* address of .ctors */ 217*199767f8SToomas Soome #define MODINFOMD_CTORS_SIZE 0x000b /* size of .ctors */ 218*199767f8SToomas Soome #define MODINFOMD_FW_HANDLE 0x000c /* Firmware dependent handle */ 219*199767f8SToomas Soome #define MODINFOMD_NOCOPY 0x8000 /* don't copy this metadata to the kernel */ 220*199767f8SToomas Soome 221*199767f8SToomas Soome #define MODINFOMD_DEPLIST (0x4001 | MODINFOMD_NOCOPY) /* depends on */ 222*199767f8SToomas Soome 223*199767f8SToomas Soome #ifdef _KERNEL 224*199767f8SToomas Soome #define MD_FETCH(mdp, info, type) ({ \ 225*199767f8SToomas Soome type *__p; \ 226*199767f8SToomas Soome __p = (type *)preload_search_info((mdp), MODINFO_METADATA | (info)); \ 227*199767f8SToomas Soome __p ? *__p : 0; \ 228*199767f8SToomas Soome }) 229*199767f8SToomas Soome #endif 230*199767f8SToomas Soome 231*199767f8SToomas Soome #define LINKER_HINTS_VERSION 1 /* linker.hints file version */ 232*199767f8SToomas Soome #define LINKER_HINTS_MAX (1 << 20) /* Allow at most 1MB for linker.hints */ 233*199767f8SToomas Soome 234*199767f8SToomas Soome #ifdef _KERNEL 235*199767f8SToomas Soome 236*199767f8SToomas Soome /* 237*199767f8SToomas Soome * Module lookup 238*199767f8SToomas Soome */ 239*199767f8SToomas Soome extern vm_offset_t preload_addr_relocate; 240*199767f8SToomas Soome extern caddr_t preload_metadata; 241*199767f8SToomas Soome 242*199767f8SToomas Soome extern void * preload_fetch_addr(caddr_t _mod); 243*199767f8SToomas Soome extern size_t preload_fetch_size(caddr_t _mod); 244*199767f8SToomas Soome extern caddr_t preload_search_by_name(const char *_name); 245*199767f8SToomas Soome extern caddr_t preload_search_by_type(const char *_type); 246*199767f8SToomas Soome extern caddr_t preload_search_next_name(caddr_t _base); 247*199767f8SToomas Soome extern caddr_t preload_search_info(caddr_t _mod, int _inf); 248*199767f8SToomas Soome extern void preload_delete_name(const char *_name); 249*199767f8SToomas Soome extern void preload_bootstrap_relocate(vm_offset_t _offset); 250*199767f8SToomas Soome 251*199767f8SToomas Soome #ifdef KLD_DEBUG 252*199767f8SToomas Soome 253*199767f8SToomas Soome extern int kld_debug; 254*199767f8SToomas Soome #define KLD_DEBUG_FILE 1 /* file load/unload */ 255*199767f8SToomas Soome #define KLD_DEBUG_SYM 2 /* symbol lookup */ 256*199767f8SToomas Soome 257*199767f8SToomas Soome #define KLD_DPF(cat, args) \ 258*199767f8SToomas Soome do { \ 259*199767f8SToomas Soome if (kld_debug & KLD_DEBUG_##cat) printf args; \ 260*199767f8SToomas Soome } while (0) 261*199767f8SToomas Soome 262*199767f8SToomas Soome #else 263*199767f8SToomas Soome 264*199767f8SToomas Soome #define KLD_DPF(cat, args) 265*199767f8SToomas Soome 266*199767f8SToomas Soome #endif 267*199767f8SToomas Soome 268*199767f8SToomas Soome typedef int elf_lookup_fn(linker_file_t, Elf_Size, int, Elf_Addr *); 269*199767f8SToomas Soome 270*199767f8SToomas Soome /* Support functions */ 271*199767f8SToomas Soome int elf_reloc(linker_file_t _lf, Elf_Addr base, const void *_rel, int _type, elf_lookup_fn _lu); 272*199767f8SToomas Soome int elf_reloc_local(linker_file_t _lf, Elf_Addr base, const void *_rel, int _type, elf_lookup_fn _lu); 273*199767f8SToomas Soome Elf_Addr elf_relocaddr(linker_file_t _lf, Elf_Addr addr); 274*199767f8SToomas Soome const Elf_Sym *elf_get_sym(linker_file_t _lf, Elf_Size _symidx); 275*199767f8SToomas Soome const char *elf_get_symname(linker_file_t _lf, Elf_Size _symidx); 276*199767f8SToomas Soome 277*199767f8SToomas Soome typedef struct linker_ctf { 278*199767f8SToomas Soome const uint8_t *ctftab; /* Decompressed CTF data. */ 279*199767f8SToomas Soome int ctfcnt; /* Number of CTF data bytes. */ 280*199767f8SToomas Soome const Elf_Sym *symtab; /* Ptr to the symbol table. */ 281*199767f8SToomas Soome int nsym; /* Number of symbols. */ 282*199767f8SToomas Soome const char *strtab; /* Ptr to the string table. */ 283*199767f8SToomas Soome int strcnt; /* Number of string bytes. */ 284*199767f8SToomas Soome uint32_t **ctfoffp; /* Ptr to array of obj/fnc offsets. */ 285*199767f8SToomas Soome uint32_t **typoffp; /* Ptr to array of type offsets. */ 286*199767f8SToomas Soome long *typlenp; /* Ptr to number of type data entries. */ 287*199767f8SToomas Soome } linker_ctf_t; 288*199767f8SToomas Soome 289*199767f8SToomas Soome int linker_ctf_get(linker_file_t, linker_ctf_t *); 290*199767f8SToomas Soome 291*199767f8SToomas Soome int elf_cpu_load_file(linker_file_t); 292*199767f8SToomas Soome int elf_cpu_unload_file(linker_file_t); 293*199767f8SToomas Soome 294*199767f8SToomas Soome /* values for type */ 295*199767f8SToomas Soome #define ELF_RELOC_REL 1 296*199767f8SToomas Soome #define ELF_RELOC_RELA 2 297*199767f8SToomas Soome 298*199767f8SToomas Soome /* 299*199767f8SToomas Soome * This is version 1 of the KLD file status structure. It is identified 300*199767f8SToomas Soome * by its _size_ in the version field. 301*199767f8SToomas Soome */ 302*199767f8SToomas Soome struct kld_file_stat_1 { 303*199767f8SToomas Soome int version; /* set to sizeof(struct kld_file_stat_1) */ 304*199767f8SToomas Soome char name[MAXPATHLEN]; 305*199767f8SToomas Soome int refs; 306*199767f8SToomas Soome int id; 307*199767f8SToomas Soome caddr_t address; /* load address */ 308*199767f8SToomas Soome size_t size; /* size in bytes */ 309*199767f8SToomas Soome }; 310*199767f8SToomas Soome #endif /* _KERNEL */ 311*199767f8SToomas Soome 312*199767f8SToomas Soome struct kld_file_stat { 313*199767f8SToomas Soome int version; /* set to sizeof(struct kld_file_stat) */ 314*199767f8SToomas Soome char name[MAXPATHLEN]; 315*199767f8SToomas Soome int refs; 316*199767f8SToomas Soome int id; 317*199767f8SToomas Soome caddr_t address; /* load address */ 318*199767f8SToomas Soome size_t size; /* size in bytes */ 319*199767f8SToomas Soome char pathname[MAXPATHLEN]; 320*199767f8SToomas Soome }; 321*199767f8SToomas Soome 322*199767f8SToomas Soome struct kld_sym_lookup { 323*199767f8SToomas Soome int version; /* set to sizeof(struct kld_sym_lookup) */ 324*199767f8SToomas Soome char *symname; /* Symbol name we are looking up */ 325*199767f8SToomas Soome u_long symvalue; 326*199767f8SToomas Soome size_t symsize; 327*199767f8SToomas Soome }; 328*199767f8SToomas Soome #define KLDSYM_LOOKUP 1 329*199767f8SToomas Soome 330*199767f8SToomas Soome /* 331*199767f8SToomas Soome * Flags for kldunloadf() and linker_file_unload() 332*199767f8SToomas Soome */ 333*199767f8SToomas Soome #define LINKER_UNLOAD_NORMAL 0 334*199767f8SToomas Soome #define LINKER_UNLOAD_FORCE 1 335*199767f8SToomas Soome 336*199767f8SToomas Soome #ifndef _KERNEL 337*199767f8SToomas Soome 338*199767f8SToomas Soome #include <sys/cdefs.h> 339*199767f8SToomas Soome 340*199767f8SToomas Soome __BEGIN_DECLS 341*199767f8SToomas Soome int kldload(const char* _file); 342*199767f8SToomas Soome int kldunload(int _fileid); 343*199767f8SToomas Soome int kldunloadf(int _fileid, int flags); 344*199767f8SToomas Soome int kldfind(const char* _file); 345*199767f8SToomas Soome int kldnext(int _fileid); 346*199767f8SToomas Soome int kldstat(int _fileid, struct kld_file_stat* _stat); 347*199767f8SToomas Soome int kldfirstmod(int _fileid); 348*199767f8SToomas Soome int kldsym(int _fileid, int _cmd, void *_data); 349*199767f8SToomas Soome __END_DECLS 350*199767f8SToomas Soome 351*199767f8SToomas Soome #endif 352*199767f8SToomas Soome 353*199767f8SToomas Soome #endif /* !_SYS_LINKER_H_ */ 354