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 * 2684e40f56SPeter Wemm * $Id: linker.h,v 1.9 1998/10/16 03:55:01 peter 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 */ 47a2c99e3eSDoug Rabson 48a2c99e3eSDoug Rabson /* 49a2c99e3eSDoug Rabson * expanded out linker_sym_t 50a2c99e3eSDoug Rabson */ 51a2c99e3eSDoug Rabson typedef struct linker_symval { 52a2c99e3eSDoug Rabson const char* name; 53a2c99e3eSDoug Rabson caddr_t value; 54a2c99e3eSDoug Rabson size_t size; 55a2c99e3eSDoug Rabson } linker_symval_t; 56a2c99e3eSDoug Rabson 57cea6c86cSDoug Rabson struct linker_file_ops { 58cea6c86cSDoug Rabson /* 59cea6c86cSDoug Rabson * Lookup a symbol in the file's symbol table. If the symbol is 60cea6c86cSDoug Rabson * not found then return ENOENT, otherwise zero. If the symbol 61cea6c86cSDoug Rabson * found is a common symbol, return with *address set to zero and 62cea6c86cSDoug Rabson * *size set to the size of the common space required. Otherwise 63cea6c86cSDoug Rabson * set *address the value of the symbol. 64cea6c86cSDoug Rabson */ 65cea6c86cSDoug Rabson int (*lookup_symbol)(linker_file_t, const char* name, 66a2c99e3eSDoug Rabson linker_sym_t* sym); 67a2c99e3eSDoug Rabson 6881450045SPeter Wemm int (*symbol_values)(linker_file_t, linker_sym_t, 69a2c99e3eSDoug Rabson linker_symval_t*); 70a2c99e3eSDoug Rabson 71a2c99e3eSDoug Rabson int (*search_symbol)(linker_file_t, caddr_t value, 72a2c99e3eSDoug Rabson linker_sym_t* sym, long* diffp); 73cea6c86cSDoug Rabson 74cea6c86cSDoug Rabson /* 75cea6c86cSDoug Rabson * Unload a file, releasing dependancies and freeing storage. 76cea6c86cSDoug Rabson */ 77cea6c86cSDoug Rabson void (*unload)(linker_file_t); 78cea6c86cSDoug Rabson }; 79cea6c86cSDoug Rabson 80cea6c86cSDoug Rabson struct common_symbol { 81cea6c86cSDoug Rabson STAILQ_ENTRY(common_symbol) link; 82cea6c86cSDoug Rabson char* name; 83cea6c86cSDoug Rabson caddr_t address; 84cea6c86cSDoug Rabson }; 85cea6c86cSDoug Rabson 86cea6c86cSDoug Rabson struct linker_file { 87cea6c86cSDoug Rabson int refs; /* reference count */ 8881450045SPeter Wemm int userrefs; /* kldload(2) count */ 89cea6c86cSDoug Rabson TAILQ_ENTRY(linker_file) link; /* list of all loaded files */ 90cea6c86cSDoug Rabson char* filename; /* file which was loaded */ 91cea6c86cSDoug Rabson int id; /* unique id */ 92cea6c86cSDoug Rabson caddr_t address; /* load address */ 93cea6c86cSDoug Rabson size_t size; /* size of file */ 94cea6c86cSDoug Rabson int ndeps; /* number of dependancies */ 95cea6c86cSDoug Rabson linker_file_t* deps; /* list of dependancies */ 96cea6c86cSDoug Rabson STAILQ_HEAD(, common_symbol) common; /* list of common symbols */ 97cea6c86cSDoug Rabson TAILQ_HEAD(, module) modules; /* modules in this file */ 98cea6c86cSDoug Rabson void* priv; /* implementation data */ 99cea6c86cSDoug Rabson 100cea6c86cSDoug Rabson struct linker_file_ops* ops; 101cea6c86cSDoug Rabson }; 102cea6c86cSDoug Rabson 103cea6c86cSDoug Rabson /* 104cea6c86cSDoug Rabson * Object implementing a class of file (a.out, elf, etc.) 105cea6c86cSDoug Rabson */ 106cea6c86cSDoug Rabson typedef struct linker_class *linker_class_t; 107cea6c86cSDoug Rabson typedef TAILQ_HEAD(, linker_class) linker_class_list_t; 108cea6c86cSDoug Rabson 109cea6c86cSDoug Rabson struct linker_class_ops { 110cea6c86cSDoug Rabson /* 111cea6c86cSDoug Rabson * Load a file, returning the new linker_file_t in *result. If 112cea6c86cSDoug Rabson * the class does not recognise the file type, zero should be 113cea6c86cSDoug Rabson * returned, without modifying *result. If the file is 114cea6c86cSDoug Rabson * recognised, the file should be loaded, *result set to the new 115cea6c86cSDoug Rabson * file and zero returned. If some other error is detected an 116cea6c86cSDoug Rabson * appropriate errno should be returned. 117cea6c86cSDoug Rabson */ 118cea6c86cSDoug Rabson int (*load_file)(const char* filename, linker_file_t* result); 119cea6c86cSDoug Rabson }; 120cea6c86cSDoug Rabson 121cea6c86cSDoug Rabson struct linker_class { 122cea6c86cSDoug Rabson TAILQ_ENTRY(linker_class) link; /* list of all file classes */ 123cea6c86cSDoug Rabson const char* desc; /* description (e.g. "a.out") */ 124cea6c86cSDoug Rabson void* priv; /* implementation data */ 125cea6c86cSDoug Rabson 126cea6c86cSDoug Rabson struct linker_class_ops *ops; 127cea6c86cSDoug Rabson }; 128cea6c86cSDoug Rabson 129cea6c86cSDoug Rabson /* 130cea6c86cSDoug Rabson * The file which is currently loading. Used to register modules with 131cea6c86cSDoug Rabson * the files which contain them. 132cea6c86cSDoug Rabson */ 133d73424aaSBruce Evans extern linker_file_t linker_current_file; 134cea6c86cSDoug Rabson 135cea6c86cSDoug Rabson /* 13684e40f56SPeter Wemm * The "file" for the kernel. 13784e40f56SPeter Wemm */ 13884e40f56SPeter Wemm extern linker_file_t linker_kernel_file; 13984e40f56SPeter Wemm 14084e40f56SPeter Wemm /* 141cea6c86cSDoug Rabson * Add a new file class to the linker. 142cea6c86cSDoug Rabson */ 143cea6c86cSDoug Rabson int linker_add_class(const char* desc, void* priv, 144cea6c86cSDoug Rabson struct linker_class_ops* ops); 145cea6c86cSDoug Rabson 146cea6c86cSDoug Rabson /* 147cea6c86cSDoug Rabson * Load a file, trying each file class until one succeeds. 148cea6c86cSDoug Rabson */ 149cea6c86cSDoug Rabson int linker_load_file(const char* filename, linker_file_t* result); 150cea6c86cSDoug Rabson 151cea6c86cSDoug Rabson /* 152cea6c86cSDoug Rabson * Find a currently loaded file given its filename. 153cea6c86cSDoug Rabson */ 154cea6c86cSDoug Rabson linker_file_t linker_find_file_by_name(const char* filename); 155cea6c86cSDoug Rabson 156cea6c86cSDoug Rabson /* 157cea6c86cSDoug Rabson * Find a currently loaded file given its file id. 158cea6c86cSDoug Rabson */ 159cea6c86cSDoug Rabson linker_file_t linker_find_file_by_id(int fileid); 160cea6c86cSDoug Rabson 161cea6c86cSDoug Rabson /* 162cea6c86cSDoug Rabson * Called from a class handler when a file is laoded. 163cea6c86cSDoug Rabson */ 164cea6c86cSDoug Rabson linker_file_t linker_make_file(const char* filename, void* priv, 165cea6c86cSDoug Rabson struct linker_file_ops* ops); 166cea6c86cSDoug Rabson 167cea6c86cSDoug Rabson /* 168cea6c86cSDoug Rabson * Unload a file, freeing up memory. 169cea6c86cSDoug Rabson */ 170cea6c86cSDoug Rabson int linker_file_unload(linker_file_t file); 171cea6c86cSDoug Rabson 172cea6c86cSDoug Rabson /* 173cea6c86cSDoug Rabson * Add a dependancy to a file. 174cea6c86cSDoug Rabson */ 175cea6c86cSDoug Rabson int linker_file_add_dependancy(linker_file_t file, linker_file_t dep); 176cea6c86cSDoug Rabson 177cea6c86cSDoug Rabson /* 178cea6c86cSDoug Rabson * Lookup a symbol in a file. If deps is TRUE, look in dependancies 179cea6c86cSDoug Rabson * if not found in file. 180cea6c86cSDoug Rabson */ 181cea6c86cSDoug Rabson caddr_t linker_file_lookup_symbol(linker_file_t file, const char* name, 182cea6c86cSDoug Rabson int deps); 183cea6c86cSDoug Rabson 1847ec76718SMike Smith /* 18581450045SPeter Wemm * Search the linker path for the module. Return the full pathname in 18681450045SPeter Wemm * a malloc'ed buffer. 18781450045SPeter Wemm */ 18881450045SPeter Wemm char *linker_search_path(const char *filename); 18981450045SPeter Wemm 19081450045SPeter Wemm /* 19181450045SPeter Wemm * DDB Helpers, tuned specifically for ddb/db_kld.c 19281450045SPeter Wemm */ 19381450045SPeter Wemm int linker_ddb_lookup(char *symstr, linker_sym_t *sym); 19481450045SPeter Wemm int linker_ddb_search_symbol(caddr_t value, linker_sym_t *sym, long *diffp); 19581450045SPeter Wemm int linker_ddb_symbol_values(linker_sym_t sym, linker_symval_t *symval); 19681450045SPeter Wemm 19781450045SPeter Wemm 19881450045SPeter Wemm #endif /* KERNEL */ 19981450045SPeter Wemm 20081450045SPeter Wemm /* 2017ec76718SMike Smith * Module information subtypes 2027ec76718SMike Smith */ 20381450045SPeter Wemm #define MODINFO_END 0x0000 /* End of list */ 20481450045SPeter Wemm #define MODINFO_NAME 0x0001 /* Name of module (string) */ 20581450045SPeter Wemm #define MODINFO_TYPE 0x0002 /* Type of module (string) */ 20681450045SPeter Wemm #define MODINFO_ADDR 0x0003 /* Loaded address */ 20781450045SPeter Wemm #define MODINFO_SIZE 0x0004 /* Size of module */ 20881450045SPeter Wemm #define MODINFO_EMPTY 0x0005 /* Has been deleted */ 20981450045SPeter Wemm #define MODINFO_METADATA 0x8000 /* Module-specfic */ 2107ec76718SMike Smith 2117ec76718SMike Smith #define MODINFOMD_AOUTEXEC 0x0001 /* a.out exec header */ 2127ec76718SMike Smith #define MODINFOMD_ELFHDR 0x0002 /* ELF header */ 21381450045SPeter Wemm #define MODINFOMD_SSYM 0x0003 /* start of symbols */ 21481450045SPeter Wemm #define MODINFOMD_ESYM 0x0004 /* end of symbols */ 21581450045SPeter Wemm #define MODINFOMD_DYNAMIC 0x0005 /* _DYNAMIC pointer */ 2167ec76718SMike Smith #define MODINFOMD_NOCOPY 0x8000 /* don't copy this metadata to the kernel */ 2177ec76718SMike Smith 21881450045SPeter Wemm #define MODINFOMD_DEPLIST (0x4001 | MODINFOMD_NOCOPY) /* depends on */ 21981450045SPeter Wemm 22081450045SPeter Wemm #ifdef KERNEL 2217ec76718SMike Smith 2221d13be33SMike Smith /* 2231d13be33SMike Smith * Module lookup 2241d13be33SMike Smith */ 22581450045SPeter Wemm extern caddr_t preload_metadata; 22681450045SPeter Wemm extern caddr_t preload_search_by_name(const char *name); 22781450045SPeter Wemm extern caddr_t preload_search_by_type(const char *type); 22881450045SPeter Wemm extern caddr_t preload_search_next_name(caddr_t base); 22981450045SPeter Wemm extern caddr_t preload_search_info(caddr_t mod, int inf); 23081450045SPeter Wemm extern void preload_delete_name(const char *name); 23181450045SPeter Wemm extern void preload_bootstrap_relocate(vm_offset_t offset); 2321d13be33SMike Smith 233cea6c86cSDoug Rabson #ifdef KLD_DEBUG 234cea6c86cSDoug Rabson 235cea6c86cSDoug Rabson extern int kld_debug; 236cea6c86cSDoug Rabson #define KLD_DEBUG_FILE 1 /* file load/unload */ 237cea6c86cSDoug Rabson #define KLD_DEBUG_SYM 2 /* symbol lookup */ 238cea6c86cSDoug Rabson 239cea6c86cSDoug Rabson #define KLD_DPF(cat, args) \ 240cea6c86cSDoug Rabson do { \ 24181450045SPeter Wemm if (kld_debug & KLD_DEBUG_##cat) printf args; \ 242cea6c86cSDoug Rabson } while (0) 243cea6c86cSDoug Rabson 244cea6c86cSDoug Rabson #else 245cea6c86cSDoug Rabson 246cea6c86cSDoug Rabson #define KLD_DPF(cat, args) 247cea6c86cSDoug Rabson 248cea6c86cSDoug Rabson #endif 249cea6c86cSDoug Rabson 25081450045SPeter Wemm /* Support functions */ 251aa855a59SPeter Wemm int elf_reloc(linker_file_t lf, const void *rel, int type, const char *sym); 252aa855a59SPeter Wemm /* values for type */ 253aa855a59SPeter Wemm #define ELF_RELOC_REL 1 254aa855a59SPeter Wemm #define ELF_RELOC_RELA 2 25581450045SPeter Wemm 256cea6c86cSDoug Rabson #endif /* KERNEL */ 257cea6c86cSDoug Rabson 258cea6c86cSDoug Rabson struct kld_file_stat { 259cea6c86cSDoug Rabson int version; /* set to sizeof(linker_file_stat) */ 260cea6c86cSDoug Rabson char name[MAXPATHLEN]; 261cea6c86cSDoug Rabson int refs; 262cea6c86cSDoug Rabson int id; 263cea6c86cSDoug Rabson caddr_t address; /* load address */ 264cea6c86cSDoug Rabson size_t size; /* size in bytes */ 265cea6c86cSDoug Rabson }; 266cea6c86cSDoug Rabson 267cea6c86cSDoug Rabson #ifndef KERNEL 268cea6c86cSDoug Rabson 269cea6c86cSDoug Rabson #include <sys/cdefs.h> 270cea6c86cSDoug Rabson 271cea6c86cSDoug Rabson __BEGIN_DECLS 272cea6c86cSDoug Rabson int kldload(const char* file); 273cea6c86cSDoug Rabson int kldunload(int fileid); 274cea6c86cSDoug Rabson int kldfind(const char* file); 275cea6c86cSDoug Rabson int kldnext(int fileid); 276cea6c86cSDoug Rabson int kldstat(int fileid, struct kld_file_stat* stat); 277cea6c86cSDoug Rabson int kldfirstmod(int fileid); 278cea6c86cSDoug Rabson __END_DECLS 279cea6c86cSDoug Rabson 280cea6c86cSDoug Rabson #endif 281cea6c86cSDoug Rabson 282452ed6dcSBruce Evans #endif /* !_SYS_LINKER_H_ */ 283