1cea6c86cSDoug Rabson /*- 2cea6c86cSDoug Rabson * Copyright (c) 1997 Doug Rabson 3cea6c86cSDoug Rabson * All rights reserved. 4cea6c86cSDoug Rabson * 5cea6c86cSDoug Rabson * Redistribution and use in source and binary forms, with or without 6cea6c86cSDoug Rabson * modification, are permitted provided that the following conditions 7cea6c86cSDoug Rabson * are met: 8cea6c86cSDoug Rabson * 1. Redistributions of source code must retain the above copyright 9cea6c86cSDoug Rabson * notice, this list of conditions and the following disclaimer. 10cea6c86cSDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright 11cea6c86cSDoug Rabson * notice, this list of conditions and the following disclaimer in the 12cea6c86cSDoug Rabson * documentation and/or other materials provided with the distribution. 13cea6c86cSDoug Rabson * 14cea6c86cSDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15cea6c86cSDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16cea6c86cSDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17cea6c86cSDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18cea6c86cSDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19cea6c86cSDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20cea6c86cSDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21cea6c86cSDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22cea6c86cSDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23cea6c86cSDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24cea6c86cSDoug Rabson * SUCH DAMAGE. 25cea6c86cSDoug Rabson * 26fe08c21aSMatthew Dillon * $Id: linker.h,v 1.13 1999/01/27 21:50:00 dillon Exp $ 27cea6c86cSDoug Rabson */ 28cea6c86cSDoug Rabson 29cea6c86cSDoug Rabson #ifndef _SYS_LINKER_H_ 30cea6c86cSDoug Rabson #define _SYS_LINKER_H_ 31cea6c86cSDoug Rabson 32cea6c86cSDoug Rabson #ifdef KERNEL 33cea6c86cSDoug Rabson 3481450045SPeter Wemm #include <machine/elf.h> 3581450045SPeter Wemm 36452ed6dcSBruce Evans #ifdef MALLOC_DECLARE 37452ed6dcSBruce Evans MALLOC_DECLARE(M_LINKER); 38452ed6dcSBruce Evans #endif 39cea6c86cSDoug Rabson 40cea6c86cSDoug Rabson /* 41cea6c86cSDoug Rabson * Object representing a file which has been loaded by the linker. 42cea6c86cSDoug Rabson */ 43cea6c86cSDoug Rabson typedef struct linker_file* linker_file_t; 44cea6c86cSDoug Rabson typedef TAILQ_HEAD(, linker_file) linker_file_list_t; 45cea6c86cSDoug Rabson 46a2c99e3eSDoug Rabson typedef caddr_t linker_sym_t; /* opaque symbol */ 47d254af07SMatthew Dillon typedef c_caddr_t c_linker_sym_t; /* const opaque symbol */ 48a2c99e3eSDoug Rabson 49a2c99e3eSDoug Rabson /* 50a2c99e3eSDoug Rabson * expanded out linker_sym_t 51a2c99e3eSDoug Rabson */ 52a2c99e3eSDoug Rabson typedef struct linker_symval { 53a2c99e3eSDoug Rabson const char* name; 54a2c99e3eSDoug Rabson caddr_t value; 55a2c99e3eSDoug Rabson size_t size; 56a2c99e3eSDoug Rabson } linker_symval_t; 57a2c99e3eSDoug Rabson 58cea6c86cSDoug Rabson struct linker_file_ops { 59cea6c86cSDoug Rabson /* 60cea6c86cSDoug Rabson * Lookup a symbol in the file's symbol table. If the symbol is 61cea6c86cSDoug Rabson * not found then return ENOENT, otherwise zero. If the symbol 62cea6c86cSDoug Rabson * found is a common symbol, return with *address set to zero and 63cea6c86cSDoug Rabson * *size set to the size of the common space required. Otherwise 64cea6c86cSDoug Rabson * set *address the value of the symbol. 65cea6c86cSDoug Rabson */ 66cea6c86cSDoug Rabson int (*lookup_symbol)(linker_file_t, const char* name, 67fe08c21aSMatthew Dillon c_linker_sym_t* sym); 68a2c99e3eSDoug Rabson 69fe08c21aSMatthew Dillon int (*symbol_values)(linker_file_t, c_linker_sym_t, 70a2c99e3eSDoug Rabson linker_symval_t*); 71a2c99e3eSDoug Rabson 72a2c99e3eSDoug Rabson int (*search_symbol)(linker_file_t, caddr_t value, 73fe08c21aSMatthew Dillon c_linker_sym_t* sym, long* diffp); 74cea6c86cSDoug Rabson 75cea6c86cSDoug Rabson /* 76cea6c86cSDoug Rabson * Unload a file, releasing dependancies and freeing storage. 77cea6c86cSDoug Rabson */ 78cea6c86cSDoug Rabson void (*unload)(linker_file_t); 79cea6c86cSDoug Rabson }; 80cea6c86cSDoug Rabson 81cea6c86cSDoug Rabson struct common_symbol { 82cea6c86cSDoug Rabson STAILQ_ENTRY(common_symbol) link; 83cea6c86cSDoug Rabson char* name; 84cea6c86cSDoug Rabson caddr_t address; 85cea6c86cSDoug Rabson }; 86cea6c86cSDoug Rabson 87cea6c86cSDoug Rabson struct linker_file { 88cea6c86cSDoug Rabson int refs; /* reference count */ 8981450045SPeter Wemm int userrefs; /* kldload(2) count */ 90149a155cSDoug Rabson int flags; 91149a155cSDoug Rabson #define LINKER_FILE_LINKED 0x1 /* file has been fully linked */ 92cea6c86cSDoug Rabson TAILQ_ENTRY(linker_file) link; /* list of all loaded files */ 93cea6c86cSDoug Rabson char* filename; /* file which was loaded */ 94cea6c86cSDoug Rabson int id; /* unique id */ 95cea6c86cSDoug Rabson caddr_t address; /* load address */ 96cea6c86cSDoug Rabson size_t size; /* size of file */ 97cea6c86cSDoug Rabson int ndeps; /* number of dependancies */ 98cea6c86cSDoug Rabson linker_file_t* deps; /* list of dependancies */ 99cea6c86cSDoug Rabson STAILQ_HEAD(, common_symbol) common; /* list of common symbols */ 100cea6c86cSDoug Rabson TAILQ_HEAD(, module) modules; /* modules in this file */ 101cea6c86cSDoug Rabson void* priv; /* implementation data */ 102cea6c86cSDoug Rabson 103cea6c86cSDoug Rabson struct linker_file_ops* ops; 104cea6c86cSDoug Rabson }; 105cea6c86cSDoug Rabson 106cea6c86cSDoug Rabson /* 107cea6c86cSDoug Rabson * Object implementing a class of file (a.out, elf, etc.) 108cea6c86cSDoug Rabson */ 109cea6c86cSDoug Rabson typedef struct linker_class *linker_class_t; 110cea6c86cSDoug Rabson typedef TAILQ_HEAD(, linker_class) linker_class_list_t; 111cea6c86cSDoug Rabson 112cea6c86cSDoug Rabson struct linker_class_ops { 113cea6c86cSDoug Rabson /* 114cea6c86cSDoug Rabson * Load a file, returning the new linker_file_t in *result. If 115cea6c86cSDoug Rabson * the class does not recognise the file type, zero should be 116cea6c86cSDoug Rabson * returned, without modifying *result. If the file is 117cea6c86cSDoug Rabson * recognised, the file should be loaded, *result set to the new 118cea6c86cSDoug Rabson * file and zero returned. If some other error is detected an 119cea6c86cSDoug Rabson * appropriate errno should be returned. 120cea6c86cSDoug Rabson */ 121cea6c86cSDoug Rabson int (*load_file)(const char* filename, linker_file_t* result); 122cea6c86cSDoug Rabson }; 123cea6c86cSDoug Rabson 124cea6c86cSDoug Rabson struct linker_class { 125cea6c86cSDoug Rabson TAILQ_ENTRY(linker_class) link; /* list of all file classes */ 126cea6c86cSDoug Rabson const char* desc; /* description (e.g. "a.out") */ 127cea6c86cSDoug Rabson void* priv; /* implementation data */ 128cea6c86cSDoug Rabson 129cea6c86cSDoug Rabson struct linker_class_ops *ops; 130cea6c86cSDoug Rabson }; 131cea6c86cSDoug Rabson 132cea6c86cSDoug Rabson /* 133cea6c86cSDoug Rabson * The file which is currently loading. Used to register modules with 134cea6c86cSDoug Rabson * the files which contain them. 135cea6c86cSDoug Rabson */ 136d73424aaSBruce Evans extern linker_file_t linker_current_file; 137cea6c86cSDoug Rabson 138cea6c86cSDoug Rabson /* 13984e40f56SPeter Wemm * The "file" for the kernel. 14084e40f56SPeter Wemm */ 14184e40f56SPeter Wemm extern linker_file_t linker_kernel_file; 14284e40f56SPeter Wemm 14384e40f56SPeter Wemm /* 144cea6c86cSDoug Rabson * Add a new file class to the linker. 145cea6c86cSDoug Rabson */ 146cea6c86cSDoug Rabson int linker_add_class(const char* desc, void* priv, 147cea6c86cSDoug Rabson struct linker_class_ops* ops); 148cea6c86cSDoug Rabson 149cea6c86cSDoug Rabson /* 150cea6c86cSDoug Rabson * Load a file, trying each file class until one succeeds. 151cea6c86cSDoug Rabson */ 152cea6c86cSDoug Rabson int linker_load_file(const char* filename, linker_file_t* result); 153cea6c86cSDoug Rabson 154cea6c86cSDoug Rabson /* 155cea6c86cSDoug Rabson * Find a currently loaded file given its filename. 156cea6c86cSDoug Rabson */ 157cea6c86cSDoug Rabson linker_file_t linker_find_file_by_name(const char* filename); 158cea6c86cSDoug Rabson 159cea6c86cSDoug Rabson /* 160cea6c86cSDoug Rabson * Find a currently loaded file given its file id. 161cea6c86cSDoug Rabson */ 162cea6c86cSDoug Rabson linker_file_t linker_find_file_by_id(int fileid); 163cea6c86cSDoug Rabson 164cea6c86cSDoug Rabson /* 165cea6c86cSDoug Rabson * Called from a class handler when a file is laoded. 166cea6c86cSDoug Rabson */ 167cea6c86cSDoug Rabson linker_file_t linker_make_file(const char* filename, void* priv, 168cea6c86cSDoug Rabson struct linker_file_ops* ops); 169cea6c86cSDoug Rabson 170cea6c86cSDoug Rabson /* 171cea6c86cSDoug Rabson * Unload a file, freeing up memory. 172cea6c86cSDoug Rabson */ 173cea6c86cSDoug Rabson int linker_file_unload(linker_file_t file); 174cea6c86cSDoug Rabson 175cea6c86cSDoug Rabson /* 176cea6c86cSDoug Rabson * Add a dependancy to a file. 177cea6c86cSDoug Rabson */ 178cea6c86cSDoug Rabson int linker_file_add_dependancy(linker_file_t file, linker_file_t dep); 179cea6c86cSDoug Rabson 180cea6c86cSDoug Rabson /* 181cea6c86cSDoug Rabson * Lookup a symbol in a file. If deps is TRUE, look in dependancies 182cea6c86cSDoug Rabson * if not found in file. 183cea6c86cSDoug Rabson */ 184cea6c86cSDoug Rabson caddr_t linker_file_lookup_symbol(linker_file_t file, const char* name, 185cea6c86cSDoug Rabson int deps); 186cea6c86cSDoug Rabson 1877ec76718SMike Smith /* 18881450045SPeter Wemm * Search the linker path for the module. Return the full pathname in 18981450045SPeter Wemm * a malloc'ed buffer. 19081450045SPeter Wemm */ 19181450045SPeter Wemm char *linker_search_path(const char *filename); 19281450045SPeter Wemm 19381450045SPeter Wemm /* 19481450045SPeter Wemm * DDB Helpers, tuned specifically for ddb/db_kld.c 19581450045SPeter Wemm */ 196fe08c21aSMatthew Dillon int linker_ddb_lookup(const char *symstr, c_linker_sym_t *sym); 197fe08c21aSMatthew Dillon int linker_ddb_search_symbol(caddr_t value, c_linker_sym_t *sym, long *diffp); 198fe08c21aSMatthew Dillon int linker_ddb_symbol_values(c_linker_sym_t sym, linker_symval_t *symval); 19981450045SPeter Wemm 20081450045SPeter Wemm 20181450045SPeter Wemm #endif /* KERNEL */ 20281450045SPeter Wemm 20381450045SPeter Wemm /* 2047ec76718SMike Smith * Module information subtypes 2057ec76718SMike Smith */ 20681450045SPeter Wemm #define MODINFO_END 0x0000 /* End of list */ 20781450045SPeter Wemm #define MODINFO_NAME 0x0001 /* Name of module (string) */ 20881450045SPeter Wemm #define MODINFO_TYPE 0x0002 /* Type of module (string) */ 20981450045SPeter Wemm #define MODINFO_ADDR 0x0003 /* Loaded address */ 21081450045SPeter Wemm #define MODINFO_SIZE 0x0004 /* Size of module */ 21181450045SPeter Wemm #define MODINFO_EMPTY 0x0005 /* Has been deleted */ 21281450045SPeter Wemm #define MODINFO_METADATA 0x8000 /* Module-specfic */ 2137ec76718SMike Smith 2147ec76718SMike Smith #define MODINFOMD_AOUTEXEC 0x0001 /* a.out exec header */ 2157ec76718SMike Smith #define MODINFOMD_ELFHDR 0x0002 /* ELF header */ 21681450045SPeter Wemm #define MODINFOMD_SSYM 0x0003 /* start of symbols */ 21781450045SPeter Wemm #define MODINFOMD_ESYM 0x0004 /* end of symbols */ 21881450045SPeter Wemm #define MODINFOMD_DYNAMIC 0x0005 /* _DYNAMIC pointer */ 2197ec76718SMike Smith #define MODINFOMD_NOCOPY 0x8000 /* don't copy this metadata to the kernel */ 2207ec76718SMike Smith 22181450045SPeter Wemm #define MODINFOMD_DEPLIST (0x4001 | MODINFOMD_NOCOPY) /* depends on */ 22281450045SPeter Wemm 22381450045SPeter Wemm #ifdef KERNEL 2247ec76718SMike Smith 2251d13be33SMike Smith /* 2261d13be33SMike Smith * Module lookup 2271d13be33SMike Smith */ 22881450045SPeter Wemm extern caddr_t preload_metadata; 22981450045SPeter Wemm extern caddr_t preload_search_by_name(const char *name); 23081450045SPeter Wemm extern caddr_t preload_search_by_type(const char *type); 23181450045SPeter Wemm extern caddr_t preload_search_next_name(caddr_t base); 23281450045SPeter Wemm extern caddr_t preload_search_info(caddr_t mod, int inf); 23381450045SPeter Wemm extern void preload_delete_name(const char *name); 23481450045SPeter Wemm extern void preload_bootstrap_relocate(vm_offset_t offset); 2351d13be33SMike Smith 236cea6c86cSDoug Rabson #ifdef KLD_DEBUG 237cea6c86cSDoug Rabson 238cea6c86cSDoug Rabson extern int kld_debug; 239cea6c86cSDoug Rabson #define KLD_DEBUG_FILE 1 /* file load/unload */ 240cea6c86cSDoug Rabson #define KLD_DEBUG_SYM 2 /* symbol lookup */ 241cea6c86cSDoug Rabson 242cea6c86cSDoug Rabson #define KLD_DPF(cat, args) \ 243cea6c86cSDoug Rabson do { \ 24481450045SPeter Wemm if (kld_debug & KLD_DEBUG_##cat) printf args; \ 245cea6c86cSDoug Rabson } while (0) 246cea6c86cSDoug Rabson 247cea6c86cSDoug Rabson #else 248cea6c86cSDoug Rabson 249cea6c86cSDoug Rabson #define KLD_DPF(cat, args) 250cea6c86cSDoug Rabson 251cea6c86cSDoug Rabson #endif 252cea6c86cSDoug Rabson 25381450045SPeter Wemm /* Support functions */ 254aa855a59SPeter Wemm int elf_reloc(linker_file_t lf, const void *rel, int type, const char *sym); 255aa855a59SPeter Wemm /* values for type */ 256aa855a59SPeter Wemm #define ELF_RELOC_REL 1 257aa855a59SPeter Wemm #define ELF_RELOC_RELA 2 25881450045SPeter Wemm 259cea6c86cSDoug Rabson #endif /* KERNEL */ 260cea6c86cSDoug Rabson 261cea6c86cSDoug Rabson struct kld_file_stat { 262cea6c86cSDoug Rabson int version; /* set to sizeof(linker_file_stat) */ 263cea6c86cSDoug Rabson char name[MAXPATHLEN]; 264cea6c86cSDoug Rabson int refs; 265cea6c86cSDoug Rabson int id; 266cea6c86cSDoug Rabson caddr_t address; /* load address */ 267cea6c86cSDoug Rabson size_t size; /* size in bytes */ 268cea6c86cSDoug Rabson }; 269cea6c86cSDoug Rabson 270ba031106SPeter Wemm struct kld_sym_lookup { 271ba031106SPeter Wemm int version; /* set to sizeof(struct kld_sym_lookup) */ 272ba031106SPeter Wemm char *symname; /* Symbol name we are looking up */ 273ba031106SPeter Wemm u_long symvalue; 274ba031106SPeter Wemm size_t symsize; 275ba031106SPeter Wemm }; 276ba031106SPeter Wemm #define KLDSYM_LOOKUP 1 277ba031106SPeter Wemm 278cea6c86cSDoug Rabson #ifndef KERNEL 279cea6c86cSDoug Rabson 280cea6c86cSDoug Rabson #include <sys/cdefs.h> 281cea6c86cSDoug Rabson 282cea6c86cSDoug Rabson __BEGIN_DECLS 283cea6c86cSDoug Rabson int kldload(const char* file); 284cea6c86cSDoug Rabson int kldunload(int fileid); 285cea6c86cSDoug Rabson int kldfind(const char* file); 286cea6c86cSDoug Rabson int kldnext(int fileid); 287cea6c86cSDoug Rabson int kldstat(int fileid, struct kld_file_stat* stat); 288cea6c86cSDoug Rabson int kldfirstmod(int fileid); 289ba031106SPeter Wemm int kldsym(int _fileid, int _cmd, void *_data); 290cea6c86cSDoug Rabson __END_DECLS 291cea6c86cSDoug Rabson 292cea6c86cSDoug Rabson #endif 293cea6c86cSDoug Rabson 294452ed6dcSBruce Evans #endif /* !_SYS_LINKER_H_ */ 295