kobj.c revision 1ee144f52d4da36525fa33b932021e610ab2caf8
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * CDDL HEADER START
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * The contents of this file are subject to the terms of the
c498d9365aa68b789215f4f356a9935f70b0fb3bmb * Common Development and Distribution License (the "License").
c498d9365aa68b789215f4f356a9935f70b0fb3bmb * You may not use this file except in compliance with the License.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * See the License for the specific language governing permissions
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * and limitations under the License.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * When distributing Covered Code, include this CDDL HEADER in each
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * If applicable, add the following below this CDDL HEADER, with the
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * fields enclosed by brackets "[]" replaced with your own identifying
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * information: Portions Copyright [yyyy] [name of copyright owner]
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * CDDL HEADER END
c498d9365aa68b789215f4f356a9935f70b0fb3bmb * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * Use is subject to license terms.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga#pragma ident "%Z%%M% %I% %E% SMI"
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga#if !defined(_OBP)
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * do_symbols() error codes
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga#define DOSYM_UNSAFE -2 /* MT-unsafe driver symbol */
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga#if !defined(_OBP)
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic struct modctl *add_primary(const char *filename, int);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic int get_progbits(struct module *, struct _buf *);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic void get_signature(struct module *, struct _buf *);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic void add_dependent(struct module *, struct module *);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic int do_dependents(struct modctl *, char *, size_t);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic void module_assign(struct modctl *, struct module *);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic char *getmodpath(const char *);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic char *basename(char *);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic char *find_libmacro(char *);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic char *expand_libmacro(char *, char *, char *);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic int read_bootflags(void);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic int kobj_comp_setup(struct _buf *, struct compinfo *);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic int kobj_uncomp_blk(struct _buf *, caddr_t, uint_t);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic int kobj_read_blks(struct _buf *, caddr_t, uint_t, uint_t);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic int kobj_boot_open(char *, int);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic int kobj_boot_close(int);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic int kobj_boot_compinfo(int, struct compinfo *);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic Sym *lookup_one(struct module *, const char *);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic void sym_insert(struct module *, char *, symid_t);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic struct kobjopen_tctl *kobjopen_alloc(char *filename);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic void kobjopen_free(struct kobjopen_tctl *ltp);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic void kobjopen_thread(struct kobjopen_tctl *ltp);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagaextern int alloc_gottable(struct module *, caddr_t *, caddr_t *);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga#if !defined(_OBP)
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagaextern int kobj_boot_mountroot(void);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic void tnf_unsplice_probes(uint_t, struct modctl *);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagaextern char stubs_base[];
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagaextern char stubs_end[];
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * Values that can be or'd in to kobj_debug and their effects:
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * D_DEBUG - misc. debugging information.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * D_SYMBOLS - list symbols and their values as they are entered
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * into the hash table
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * D_RELOCATIONS - display relocation processing information
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * D_LOADING - display information about each module as it
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * is loaded.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga (_kobj_printf(ops, "%d", __LINE__), _kobj_printf(ops, ": %s\n", s))
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic char slash_moddir_suffix_slash[] = MODDIR_SUFFIX "/";
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga#define _modrootloaded get_weakish_int(&modrootloaded)
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga#define _ioquiesced get_weakish_int(&bop_io_quiesced)
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga#define mod(X) (struct module *)((X)->modl_modp->mod_mp)
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * kobjopen thread control structure
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * Structure for defining dynamically expandable library macros
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga char *lmi_list; /* ptr to list of possible choices */
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga ushort_t lmi_ba_index; /* index into bootaux vector */
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga#define NLIBMACROS sizeof (libmacros) / sizeof (struct lib_macro_info)
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagachar *boot_cpu_compatible_list; /* make $CPU available */
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic vmem_t *data_arena; /* module data & bss arena */
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic struct modctl *kobj_modules = NULL; /* modules loaded */
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic int kobj_last_module_id = 0; /* id assignment */
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic kmutex_t kobj_lock; /* protects mach memory list */
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * The following functions have been implemented by the kernel.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * However, many 3rd party drivers provide their own implementations
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * of these functions. When such drivers are loaded, messages
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * indicating that these symbols have been multiply defined will be
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * emitted to the console. To avoid alarming customers for no good
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * reason, we simply suppress such warnings for the following set of
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * functions.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic char *suppress_sym_list[] =
c498d9365aa68b789215f4f356a9935f70b0fb3bmb "memmove",
c498d9365aa68b789215f4f356a9935f70b0fb3bmb "__udivdi3",
c498d9365aa68b789215f4f356a9935f70b0fb3bmb "__divdi3",
c498d9365aa68b789215f4f356a9935f70b0fb3bmb "__umoddi3",
c498d9365aa68b789215f4f356a9935f70b0fb3bmb "__moddi3",
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga/* indexed by KOBJ_NOTIFY_* */
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic kobj_notify_list_t *kobj_notifiers[KOBJ_NOTIFY_MAX + 1];
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * TNF probe management globals
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * Prefix for statically defined tracing (SDT) DTrace probes.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * Beginning and end of the kernel's dynamic text/data segments.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * The sparc linker doesn't create a memory location
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * for a variable named _edata, so _edata can only be
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * referred to, not modified. krtld needs a static
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * variable to modify it - within krtld, of course -
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * outside of krtld, e_data is used in all kernels.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagaAddr dynseg = 0; /* load address of "dynamic" segment */
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * _kobj_printf()
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * Common printf function pointer. Can handle only one conversion
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * specification in the format string. Some of the functions invoked
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * through this function pointer cannot handle more that one conversion
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * specification in the format string.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagavoid (*_kobj_printf)(void *, const char *, ...); /* printf routine */
c498d9365aa68b789215f4f356a9935f70b0fb3bmb * Standalone function pointers for use within krtld.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * Many platforms implement optimized platmod versions of
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * utilities such as bcopy and any such are not yet available
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * until the kernel is more completely stitched together.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagasize_t (*kobj_strlcat)(char *, const char *, size_t);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga return (0);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznagastatic void *
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga return (0);
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * XXX fix dependencies on "kernel"; this should work
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * for other standalone binaries as well.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * XXX Fix hashing code to use one pointer to
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * hash entries.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * |----------|
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * | nbuckets |
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * |----------|
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * | nchains |
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * |----------|
33129b339db105602c2677f5a80b6189ec63d2e5ayznaga * | bucket[] |
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * |----------|
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * | chain[] |
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * |----------|
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * Load, bind and relocate all modules that
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * form the primary kernel. At this point, our
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * externals have not been relocated.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * Save these to pass on to
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * the booted standalone.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * We don't support standalone debuggers anymore. The use of kadb
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * will interfere with the later use of kmdb. Let the user mend
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * their ways now. Users will reach this message if they still
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * have the kadb binary on their system (perhaps they used an old
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * bfu, or maybe they intentionally copied it there) and have
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * specified its use in a way that eluded our checking in the boot
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga _kobj_printf(ops, "\nWARNING: Standalone debuggers such as "
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga "kadb are no longer supported\n\n");
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga#if defined(_OBP)
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * OBP allows us to read both the ramdisk and
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * the underlying root fs when root is a disk.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * This can lower incidences of unbootable systems
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * when the archive is out-of-date with the /etc
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * state files.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga /* on x86, we always boot with a ramdisk */
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * Now that the ramdisk is mounted, finish boot property
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * initialization.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * 'unix' is linked together with 'krtld' into one executable and
33129b339db105602c2677f5a80b6189ec63d2e5ayznaga * the early boot code does -not- hand us any of the dynamic metadata
33129b339db105602c2677f5a80b6189ec63d2e5ayznaga * about the executable. In particular, it does not read in, map or
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * otherwise look at the program headers. We fake all that up now.
d00f0155af9a9a671eb08a0dc30f5ea0a379c36cayznaga * We do this early as DTrace static probes and tnf probes both call
goto fail;
goto fail;
goto fail;
#ifdef KOBJ_DEBUG
standalone = 0;
#ifdef KOBJ_DEBUG
#if defined(_DBOOT)
fail:
#if !defined(_UNIX_KRTLD)
filename);
filename);
for (i = 0; i < phnum; i++) {
#if defined(_RELSEG)
for (i = 0; i < NLIBMACROS; i++) {
static struct module *
#ifdef KOBJ_DEBUG
case DT_SYMTAB:
case DT_HASH:
case DT_STRTAB:
case DT_STRSZ:
case DT_SYMENT:
char *_lib;
KM_WAIT);
nsize++;
if (nsize) {
#ifdef KOBJ_DEBUG
#if defined(__sparc)
return (mp);
int shsize;
#ifdef KOBJ_DEBUG
static kobj_notify_list_t **
sizeof (kobj_notify_list_t *));
static struct modctl *
return (cp);
case DT_RELASZ:
case DT_RELSZ:
case DT_RELAENT:
case DT_RELENT:
case DT_RELA:
case DT_REL:
if (relasz == 0 ||
#ifdef KOBJ_DEBUG
static struct modctl *
return (mctl);
return (NULL);
q = modname;
if (q == modname)
console_is_usb_serial(void)
char *console;
return (ret);
if (console_is_usb_serial()) {
#ifdef KOBJ_DEBUG
(const char **)kobj_kmdb_argv) < 0)
char *depstr, *q;
return (NULL);
return (NULL);
return (depstr);
char *name;
locals++;
nsyms++;
nsyms++;
case SHT_RELA:
case SHT_REL:
int lsize;
case DT_NEEDED:
char *_lib;
KM_WAIT);
nsize++;
case DT_FLAGS_1:
case SHT_DYNAMIC:
dshn);
return (rc);
if (!standalone) {
#ifdef MODDIR_SUFFIX
int no_suffixdir_drv = 0;
#ifdef MODDIR_SUFFIX
goto bad;
#ifdef MODDIR_SUFFIX
modname);
goto bad;
for (i = 0; i < SELFMAG; i++) {
modname);
goto bad;
modname);
#ifdef MODDIR_SUFFIX
goto bad;
goto bad;
goto bad;
goto bad;
modname);
goto bad;
modname);
goto bad;
#ifdef KOBJ_DEBUG
if (!standalone) {
char *dependent_modname;
switch (dcrval) {
case DOSYM_UNSAFE:
modname);
case DOSYM_UNDEF:
modname);
modname);
if (dcrval < 0)
goto bad;
modname);
goto bad;
bad:
#ifdef KOBJ_DEBUG
#ifdef KOBJ_DEBUG
if (standalone) {
int ksyms_exported = 0;
while (lp) {
case SHT_RELA:
case SHT_REL:
goto done;
if (standalone) {
goto done;
while (pages--) {
if (text == 0)
goto done;
err = 0;
done:
if (err != 0) {
return (err);
uint_t i;
char *symname;
int dosymtab = 0;
case SHT_SYMTAB:
dosymtab++;
case SHT_RELA:
case SHT_REL:
shn);
if (!dosymtab) {
if ((standalone ||
uint_t i;
#ifdef KOBJ_DEBUG
uint_t i;
ELF_SIGNATURE_SECTION) == 0) {
q = modname;
if (q == modname)
#ifndef KOBJ_DEBUG
modname);
#ifndef KOBJ_DEBUG
KM_WAIT);
int err;
return (err);
if (standalone)
MINALIGN, 0);
return (err);
int bss_align;
int err;
char *name;
int assign;
bss_align = 0;
err = 0;
#if defined(__sparc)
name);
name);
resolved = 0;
if (err == 0)
if (assign) {
if (err)
return (err);
} else if (resolved) {
kobj_hash_name(const char *p)
uint_t g;
hval = 0;
hval &= ~g;
return (hval);
if (kernelonly)
return (value);
return (name);
return (name);
char *strtabptr;
int symnum;
return (NULL);
Sym *
return (sp);
return (sp);
return (sp);
return (NULL);
Sym *
return (sp);
return (NULL);
static Sym *
char *name1;
return (sp);
return (NULL);
static Sym *
return (ksp);
return (NULL);
#ifdef KOBJ_DEBUG
struct modctl *
return (mctl);
return (NULL);
#ifdef MODDIR_SUFFIX
struct _buf *
char *pathp;
char *pathpsave;
char *fullname;
int maxpathlen;
#if !defined(MODDIR_SUFFIX)
if (!use_path)
p = fullname;
*p++ = *pathp++;
if (use_moddir_suffix) {
q = name;
q = name;
return (file);
if (*pathp == 0)
pathp++;
int fd;
if (_modrootloaded) {
int Errno;
if (Errno) {
filename);
if (fd < 0)
thread_exit();
static struct kobjopen_tctl *
return (ltp);
int stat;
if (_modrootloaded) {
&resid)) != 0) {
int count = 0;
return (count);
if (_modrootloaded) {
if (_modrootloaded) {
struct _buf *
if (_modrootloaded) {
return (file);
int count = 0;
int page_addr;
while (size) {
if (c_size <= 0)
if (buf) {
c_size);
if (c_size < 0) {
return (count);
int ret;
int nret;
ret = 0;
return (ret);
return (dlen);
return (kobj_getc(f));
if (standalone)
if (standalone) {
#if defined(_OBP)
kobj_sync(void)
if (lg_pagesize) {
#if defined(__sparc)
if (limit)
return ((caddr_t)0);
return (NULL);
if (hsize % f == 0)
return (hsize);
if (_modrootloaded) {
return (EIO);
#if defined(_OBP)
return (EIO);
char *buf;
int count;
if (count < 0) {
return (EIO);
basename(char *s)
q = NULL;
return (lg_pagesize);
uintptr_t i;
int lmi;
return (NULL);
if (p == NULL)
return (NULL);
valid_macro = 0;
if (!valid_macro) {
return (path);
return (NULL);
more_macro = 0;
if (diff > 0)
if (p2) {
return (path);
if (p2)
return (NULL);
return (NULL);
tnf_probe_control_t **p;
tnf_tag_data_t **q;
for (p = &__tnf_probe_list_head; *p; )
*p = (*p)->next;
p = &(*p)->next;
for (q = &__tnf_tag_list_head; *q; )
int result = 0;
if (plist) {
if (!boot_load)
if (!boot_load)
if (tlist) {
if (!boot_load)
if (!boot_load)
add_notify = 0;
return (result);
char *kobj_file_buf;
int kobj_file_bufsize;
static char *buf;
static int size = 0;
if (n > size)
n = size;
size -= n;
buf += n;
#if defined(_OBP)
#if defined(_OBP)
#if defined(_OBP)
#if defined(_OBP)
#if defined(_OBP)