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 * 26aa855a59SPeter Wemm * $Id: linker.h,v 1.8 1998/10/09 23:07:27 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 /* 136cea6c86cSDoug Rabson * Add a new file class to the linker. 137cea6c86cSDoug Rabson */ 138cea6c86cSDoug Rabson int linker_add_class(const char* desc, void* priv, 139cea6c86cSDoug Rabson struct linker_class_ops* ops); 140cea6c86cSDoug Rabson 141cea6c86cSDoug Rabson /* 142cea6c86cSDoug Rabson * Load a file, trying each file class until one succeeds. 143cea6c86cSDoug Rabson */ 144cea6c86cSDoug Rabson int linker_load_file(const char* filename, linker_file_t* result); 145cea6c86cSDoug Rabson 146cea6c86cSDoug Rabson /* 147cea6c86cSDoug Rabson * Find a currently loaded file given its filename. 148cea6c86cSDoug Rabson */ 149cea6c86cSDoug Rabson linker_file_t linker_find_file_by_name(const char* filename); 150cea6c86cSDoug Rabson 151cea6c86cSDoug Rabson /* 152cea6c86cSDoug Rabson * Find a currently loaded file given its file id. 153cea6c86cSDoug Rabson */ 154cea6c86cSDoug Rabson linker_file_t linker_find_file_by_id(int fileid); 155cea6c86cSDoug Rabson 156cea6c86cSDoug Rabson /* 157cea6c86cSDoug Rabson * Called from a class handler when a file is laoded. 158cea6c86cSDoug Rabson */ 159cea6c86cSDoug Rabson linker_file_t linker_make_file(const char* filename, void* priv, 160cea6c86cSDoug Rabson struct linker_file_ops* ops); 161cea6c86cSDoug Rabson 162cea6c86cSDoug Rabson /* 163cea6c86cSDoug Rabson * Unload a file, freeing up memory. 164cea6c86cSDoug Rabson */ 165cea6c86cSDoug Rabson int linker_file_unload(linker_file_t file); 166cea6c86cSDoug Rabson 167cea6c86cSDoug Rabson /* 168cea6c86cSDoug Rabson * Add a dependancy to a file. 169cea6c86cSDoug Rabson */ 170cea6c86cSDoug Rabson int linker_file_add_dependancy(linker_file_t file, linker_file_t dep); 171cea6c86cSDoug Rabson 172cea6c86cSDoug Rabson /* 173cea6c86cSDoug Rabson * Lookup a symbol in a file. If deps is TRUE, look in dependancies 174cea6c86cSDoug Rabson * if not found in file. 175cea6c86cSDoug Rabson */ 176cea6c86cSDoug Rabson caddr_t linker_file_lookup_symbol(linker_file_t file, const char* name, 177cea6c86cSDoug Rabson int deps); 178cea6c86cSDoug Rabson 1797ec76718SMike Smith /* 18081450045SPeter Wemm * Search the linker path for the module. Return the full pathname in 18181450045SPeter Wemm * a malloc'ed buffer. 18281450045SPeter Wemm */ 18381450045SPeter Wemm char *linker_search_path(const char *filename); 18481450045SPeter Wemm 18581450045SPeter Wemm /* 18681450045SPeter Wemm * DDB Helpers, tuned specifically for ddb/db_kld.c 18781450045SPeter Wemm */ 18881450045SPeter Wemm int linker_ddb_lookup(char *symstr, linker_sym_t *sym); 18981450045SPeter Wemm int linker_ddb_search_symbol(caddr_t value, linker_sym_t *sym, long *diffp); 19081450045SPeter Wemm int linker_ddb_symbol_values(linker_sym_t sym, linker_symval_t *symval); 19181450045SPeter Wemm 19281450045SPeter Wemm 19381450045SPeter Wemm #endif /* KERNEL */ 19481450045SPeter Wemm 19581450045SPeter Wemm /* 1967ec76718SMike Smith * Module information subtypes 1977ec76718SMike Smith */ 19881450045SPeter Wemm #define MODINFO_END 0x0000 /* End of list */ 19981450045SPeter Wemm #define MODINFO_NAME 0x0001 /* Name of module (string) */ 20081450045SPeter Wemm #define MODINFO_TYPE 0x0002 /* Type of module (string) */ 20181450045SPeter Wemm #define MODINFO_ADDR 0x0003 /* Loaded address */ 20281450045SPeter Wemm #define MODINFO_SIZE 0x0004 /* Size of module */ 20381450045SPeter Wemm #define MODINFO_EMPTY 0x0005 /* Has been deleted */ 20481450045SPeter Wemm #define MODINFO_METADATA 0x8000 /* Module-specfic */ 2057ec76718SMike Smith 2067ec76718SMike Smith #define MODINFOMD_AOUTEXEC 0x0001 /* a.out exec header */ 2077ec76718SMike Smith #define MODINFOMD_ELFHDR 0x0002 /* ELF header */ 20881450045SPeter Wemm #define MODINFOMD_SSYM 0x0003 /* start of symbols */ 20981450045SPeter Wemm #define MODINFOMD_ESYM 0x0004 /* end of symbols */ 21081450045SPeter Wemm #define MODINFOMD_DYNAMIC 0x0005 /* _DYNAMIC pointer */ 2117ec76718SMike Smith #define MODINFOMD_NOCOPY 0x8000 /* don't copy this metadata to the kernel */ 2127ec76718SMike Smith 21381450045SPeter Wemm #define MODINFOMD_DEPLIST (0x4001 | MODINFOMD_NOCOPY) /* depends on */ 21481450045SPeter Wemm 21581450045SPeter Wemm #ifdef KERNEL 2167ec76718SMike Smith 2171d13be33SMike Smith /* 2181d13be33SMike Smith * Module lookup 2191d13be33SMike Smith */ 22081450045SPeter Wemm extern caddr_t preload_metadata; 22181450045SPeter Wemm extern caddr_t preload_search_by_name(const char *name); 22281450045SPeter Wemm extern caddr_t preload_search_by_type(const char *type); 22381450045SPeter Wemm extern caddr_t preload_search_next_name(caddr_t base); 22481450045SPeter Wemm extern caddr_t preload_search_info(caddr_t mod, int inf); 22581450045SPeter Wemm extern void preload_delete_name(const char *name); 22681450045SPeter Wemm extern void preload_bootstrap_relocate(vm_offset_t offset); 2271d13be33SMike Smith 228cea6c86cSDoug Rabson #ifdef KLD_DEBUG 229cea6c86cSDoug Rabson 230cea6c86cSDoug Rabson extern int kld_debug; 231cea6c86cSDoug Rabson #define KLD_DEBUG_FILE 1 /* file load/unload */ 232cea6c86cSDoug Rabson #define KLD_DEBUG_SYM 2 /* symbol lookup */ 233cea6c86cSDoug Rabson 234cea6c86cSDoug Rabson #define KLD_DPF(cat, args) \ 235cea6c86cSDoug Rabson do { \ 23681450045SPeter Wemm if (kld_debug & KLD_DEBUG_##cat) printf args; \ 237cea6c86cSDoug Rabson } while (0) 238cea6c86cSDoug Rabson 239cea6c86cSDoug Rabson #else 240cea6c86cSDoug Rabson 241cea6c86cSDoug Rabson #define KLD_DPF(cat, args) 242cea6c86cSDoug Rabson 243cea6c86cSDoug Rabson #endif 244cea6c86cSDoug Rabson 24581450045SPeter Wemm /* Support functions */ 246aa855a59SPeter Wemm int elf_reloc(linker_file_t lf, const void *rel, int type, const char *sym); 247aa855a59SPeter Wemm /* values for type */ 248aa855a59SPeter Wemm #define ELF_RELOC_REL 1 249aa855a59SPeter Wemm #define ELF_RELOC_RELA 2 25081450045SPeter Wemm 251cea6c86cSDoug Rabson #endif /* KERNEL */ 252cea6c86cSDoug Rabson 253cea6c86cSDoug Rabson struct kld_file_stat { 254cea6c86cSDoug Rabson int version; /* set to sizeof(linker_file_stat) */ 255cea6c86cSDoug Rabson char name[MAXPATHLEN]; 256cea6c86cSDoug Rabson int refs; 257cea6c86cSDoug Rabson int id; 258cea6c86cSDoug Rabson caddr_t address; /* load address */ 259cea6c86cSDoug Rabson size_t size; /* size in bytes */ 260cea6c86cSDoug Rabson }; 261cea6c86cSDoug Rabson 262cea6c86cSDoug Rabson #ifndef KERNEL 263cea6c86cSDoug Rabson 264cea6c86cSDoug Rabson #include <sys/cdefs.h> 265cea6c86cSDoug Rabson 266cea6c86cSDoug Rabson __BEGIN_DECLS 267cea6c86cSDoug Rabson int kldload(const char* file); 268cea6c86cSDoug Rabson int kldunload(int fileid); 269cea6c86cSDoug Rabson int kldfind(const char* file); 270cea6c86cSDoug Rabson int kldnext(int fileid); 271cea6c86cSDoug Rabson int kldstat(int fileid, struct kld_file_stat* stat); 272cea6c86cSDoug Rabson int kldfirstmod(int fileid); 273cea6c86cSDoug Rabson __END_DECLS 274cea6c86cSDoug Rabson 275cea6c86cSDoug Rabson #endif 276cea6c86cSDoug Rabson 277452ed6dcSBruce Evans #endif /* !_SYS_LINKER_H_ */ 278