diff options
author | Chris Johns <chrisj@rtems.org> | 2012-04-25 10:12:19 +1000 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2012-04-25 10:12:19 +1000 |
commit | 673b40c95705127635af12bda15694fd6ab5a96b (patch) | |
tree | 5c243823cf495ba3702773f94b275a442ac218de |
Import the current project to git.
110 files changed, 12817 insertions, 0 deletions
diff --git a/WAF-README b/WAF-README new file mode 100644 index 0000000..9bbb79f --- /dev/null +++ b/WAF-README @@ -0,0 +1,42 @@ +RTEMS Waf Build Module. + + Chris Johns <chrisj@rtems.org> + +Background + +Waf is a build tool that manages all aspects of building software. You can find +waf here: + + http://waf.googlecode.com/ + +I suggest you read the Waf Book to find about waf and what it does. It is fast, +easy to program and additive. It uses Python as the scripting language so the +build scripts require a Python syntax. It also allows you to use the power of +Python and its full programming language to implement a build system with the +same approach you design the software you embed on RTEMS. Just because it is a +build system does not mean you are limited to using design techniques, tools +and scripting formats from 30 years ago. + +RTEMS Module + +The rtems.py and pkgconfig.py provide the support you need. Place these files +in the top of your source tree where you will add your wscript file. You need +to add a wscript. This example is for a simple hello world program (source not +provided): + + import rtems + + def init(ctx): + rtems.init(ctx) + + def options(opt): + rtems.options(opt) + + def configure(conf): + rtems.configure(conf) + + def build(bld): + rtems.build(bld) + bld.program(target = 'hello-world', + features = 'cprogram', + source = 'main.c') diff --git a/dlfcn-shell.c b/dlfcn-shell.c new file mode 100644 index 0000000..88b9dcd --- /dev/null +++ b/dlfcn-shell.c @@ -0,0 +1,118 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtld + * + * @brief RTEMS Run-Time Link Editor Dynamic Loading API Shell Support. + * + * Shell command wrappers for the Dynamic Loading API. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <dlfcn.h> + +static void* +convert_ascii_to_voidp (const char* arg) +{ + if (strcmp (arg, "base") == 0) + return RTLD_DEFAULT; + return (void*) strtoul (arg, NULL, 16); +} + +int +shell_dlopen (int argc, char* argv[]) +{ + int arg; + for (arg = 1; arg < argc; arg++) + { + void* handle = dlopen (argv[arg], RTLD_NOW | RTLD_GLOBAL); + if (handle) + { + int unresolved; + char* message = "loaded"; + if (dlinfo (handle, RTLD_DI_UNRESOLVED, &unresolved) < 0) + message = "dlinfo error checking unresolved status"; + else if (unresolved) + message = "has unresolved externals"; + printf ("handle: %p %s\n", handle, message); + } + else + printf ("error: %s\n", dlerror ()); + } + return 0; +} + +int +shell_dlclose (int argc, char* argv[]) +{ + return 0; +} + +static bool +lookup_dlsym (void** value, int argc, char* argv[]) +{ + if (argc >= 3) + { + void* handle = convert_ascii_to_voidp (argv[1]); + if (handle) + { + *value = dlsym (handle, argv[2]); + if (*value) + return true; + else + printf ("error: invalid handle or symbol\n"); + } + else + printf ("error: invalid handle"); + } + else + printf ("error: requires handle and symbol name\n"); + return false; +} + +int +shell_dlsym (int argc, char* argv[]) +{ + void* value; + if (lookup_dlsym (&value, argc, argv)) + { + printf ("%s = %p\n", argv[2], value); + return 0; + } + return -1; +} + +typedef int (*call_t)(int argc, char* argv[]); + +int +shell_dlcall (int argc, char* argv[]) +{ + void* value; + if (lookup_dlsym (&value, argc, argv)) + { + call_t call = value; + int r; + printf ("(*%p)(%d, ....)\n", value, argc - 3); + r = call (argc - 3, argv + 3); + printf ("return %d\n", r); + return 0; + } + return -1; +} @@ -0,0 +1,155 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtl + * + * @brief RTEMS POSIX Dynamic Module Loading Interface. + * + * This is the POSIX interface to run-time loading of code into RTEMS. + */ + +#include <stdint.h> +#include <dlfcn.h> +#include <rtl.h> + +static rtems_rtl_obj_t* +dl_get_obj_from_handle (void* handle) +{ + rtems_rtl_obj_t* obj; + + /* + * Handle the special cases provided in NetBSD and Sun documentation. + * http://download.oracle.com/docs/cd/E19253-01/816-5168/dlsym-3c/index.html + * We currently do not manage the loading dependences in the module mappings + * so we cannot handle the searching based on loading order where overriding + * can occur. + */ + + if ((handle == RTLD_DEFAULT) || (handle == RTLD_SELF)) + obj = rtems_rtl_baseimage (); + else + obj = rtems_rtl_check_handle (handle); + + return obj; +} + +void* +dlopen (const char* name, int mode) +{ + rtems_rtl_obj_t* obj = NULL; + + if (!rtems_rtl_lock ()) + return NULL; + + _rtld_debug.r_state = RT_ADD; + _rtld_debug_state (); + + if (name) + obj = rtems_rtl_load_object (name, mode); + else + obj = rtems_rtl_baseimage (); + + _rtld_debug.r_state = RT_CONSISTENT; + _rtld_debug_state(); + + rtems_rtl_unlock (); + + return obj; +} + +int +dlclose (void* handle) +{ + rtems_rtl_obj_t* obj; + int r; + + if (!rtems_rtl_lock ()) + return -1; + + obj = rtems_rtl_check_handle (handle); + if (!obj) + { + rtems_rtl_unlock (); + return -1; + } + + _rtld_debug.r_state = RT_DELETE; + _rtld_debug_state (); + + r = rtems_rtl_unload_object (obj) ? 0 : -1; + + _rtld_debug.r_state = RT_CONSISTENT; + _rtld_debug_state (); + + rtems_rtl_unlock (); + + return r; +} + +void* +dlsym (void* handle, const char *symbol) +{ + rtems_rtl_obj_t* obj; + rtems_rtl_obj_sym_t* sym; + void* symval = NULL; + + if (!rtems_rtl_lock ()) + return NULL; + + obj = dl_get_obj_from_handle (handle); + if (obj) + { + sym = rtems_rtl_symbol_obj_find (obj, symbol); + if (sym) + symval = sym->value; + } + + rtems_rtl_unlock (); + + return symval; +} + +char* +dlerror (void) +{ + static char msg[64]; + rtems_rtl_get_error (msg, sizeof (msg)); + return msg; +} + +int +dlinfo (void* handle, int request, void* p) +{ + rtems_rtl_obj_t* obj; + int rc = -1; + + if (!rtems_rtl_lock () || !p) + return -1; + + obj = dl_get_obj_from_handle (handle); + if (obj) + { + switch (request) + { + case RTLD_DI_UNRESOLVED: + *((int*) p) = rtems_rtl_obj_unresolved (obj) ? 1 : 0; + rc = 0; + break; + default: + break; + } + } + + rtems_rtl_unlock (); + + return rc; +} diff --git a/images/icons/README b/images/icons/README new file mode 100644 index 0000000..f12b2a7 --- /dev/null +++ b/images/icons/README @@ -0,0 +1,5 @@ +Replaced the plain DocBook XSL admonition icons with Jimmac's DocBook +icons (http://jimmac.musichall.cz/ikony.php3). I dropped transparency +from the Jimmac icons to get round MS IE and FOP PNG incompatibilies. + +Stuart Rackham diff --git a/images/icons/callouts/1.png b/images/icons/callouts/1.png Binary files differnew file mode 100644 index 0000000..7d47343 --- /dev/null +++ b/images/icons/callouts/1.png diff --git a/images/icons/callouts/10.png b/images/icons/callouts/10.png Binary files differnew file mode 100644 index 0000000..997bbc8 --- /dev/null +++ b/images/icons/callouts/10.png diff --git a/images/icons/callouts/11.png b/images/icons/callouts/11.png Binary files differnew file mode 100644 index 0000000..ce47dac --- /dev/null +++ b/images/icons/callouts/11.png diff --git a/images/icons/callouts/12.png b/images/icons/callouts/12.png Binary files differnew file mode 100644 index 0000000..31daf4e --- /dev/null +++ b/images/icons/callouts/12.png diff --git a/images/icons/callouts/13.png b/images/icons/callouts/13.png Binary files differnew file mode 100644 index 0000000..14021a8 --- /dev/null +++ b/images/icons/callouts/13.png diff --git a/images/icons/callouts/14.png b/images/icons/callouts/14.png Binary files differnew file mode 100644 index 0000000..64014b7 --- /dev/null +++ b/images/icons/callouts/14.png diff --git a/images/icons/callouts/15.png b/images/icons/callouts/15.png Binary files differnew file mode 100644 index 0000000..0d65765 --- /dev/null +++ b/images/icons/callouts/15.png diff --git a/images/icons/callouts/2.png b/images/icons/callouts/2.png Binary files differnew file mode 100644 index 0000000..5d09341 --- /dev/null +++ b/images/icons/callouts/2.png diff --git a/images/icons/callouts/3.png b/images/icons/callouts/3.png Binary files differnew file mode 100644 index 0000000..ef7b700 --- /dev/null +++ b/images/icons/callouts/3.png diff --git a/images/icons/callouts/4.png b/images/icons/callouts/4.png Binary files differnew file mode 100644 index 0000000..adb8364 --- /dev/null +++ b/images/icons/callouts/4.png diff --git a/images/icons/callouts/5.png b/images/icons/callouts/5.png Binary files differnew file mode 100644 index 0000000..4d7eb46 --- /dev/null +++ b/images/icons/callouts/5.png diff --git a/images/icons/callouts/6.png b/images/icons/callouts/6.png Binary files differnew file mode 100644 index 0000000..0ba694a --- /dev/null +++ b/images/icons/callouts/6.png diff --git a/images/icons/callouts/7.png b/images/icons/callouts/7.png Binary files differnew file mode 100644 index 0000000..472e96f --- /dev/null +++ b/images/icons/callouts/7.png diff --git a/images/icons/callouts/8.png b/images/icons/callouts/8.png Binary files differnew file mode 100644 index 0000000..5e60973 --- /dev/null +++ b/images/icons/callouts/8.png diff --git a/images/icons/callouts/9.png b/images/icons/callouts/9.png Binary files differnew file mode 100644 index 0000000..a0676d2 --- /dev/null +++ b/images/icons/callouts/9.png diff --git a/images/icons/caution.png b/images/icons/caution.png Binary files differnew file mode 100644 index 0000000..9a8c515 --- /dev/null +++ b/images/icons/caution.png diff --git a/images/icons/example.png b/images/icons/example.png Binary files differnew file mode 100644 index 0000000..1199e86 --- /dev/null +++ b/images/icons/example.png diff --git a/images/icons/home.png b/images/icons/home.png Binary files differnew file mode 100644 index 0000000..37a5231 --- /dev/null +++ b/images/icons/home.png diff --git a/images/icons/important.png b/images/icons/important.png Binary files differnew file mode 100644 index 0000000..be685cc --- /dev/null +++ b/images/icons/important.png diff --git a/images/icons/next.png b/images/icons/next.png Binary files differnew file mode 100644 index 0000000..64e126b --- /dev/null +++ b/images/icons/next.png diff --git a/images/icons/note.png b/images/icons/note.png Binary files differnew file mode 100644 index 0000000..7c1f3e2 --- /dev/null +++ b/images/icons/note.png diff --git a/images/icons/prev.png b/images/icons/prev.png Binary files differnew file mode 100644 index 0000000..3e8f12f --- /dev/null +++ b/images/icons/prev.png diff --git a/images/icons/tip.png b/images/icons/tip.png Binary files differnew file mode 100644 index 0000000..f087c73 --- /dev/null +++ b/images/icons/tip.png diff --git a/images/icons/up.png b/images/icons/up.png Binary files differnew file mode 100644 index 0000000..2db1ce6 --- /dev/null +++ b/images/icons/up.png diff --git a/images/icons/warning.png b/images/icons/warning.png Binary files differnew file mode 100644 index 0000000..d41edb9 --- /dev/null +++ b/images/icons/warning.png diff --git a/images/rtemswhitebg.jpg b/images/rtemswhitebg.jpg Binary files differnew file mode 100644 index 0000000..f883f2c --- /dev/null +++ b/images/rtemswhitebg.jpg @@ -0,0 +1,222 @@ +/* + * $Id$ + */ + +/** + * Configure the RTEMS initialisation. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> + +#include <rtems.h> + +#if !RTEMS_APP_NETWORKING +#undef RTEMS_NETWORKING +#endif + +#ifdef RTEMS_NETWORKING +#include <rtems/rtems_bsdnet.h> +#include <rtems/dhcp.h> +#endif + +/** + * Configure base RTEMS resources. + */ +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE +#define CONFIGURE_MEMORY_OVERHEAD 512 +#define CONFIGURE_MAXIMUM_TASKS rtems_resource_unlimited (10) +#define CONFIGURE_MAXIMUM_SEMAPHORES rtems_resource_unlimited (10) +#define CONFIGURE_MAXIMUM_MESSAGE_QUEUES rtems_resource_unlimited (5) +#define CONFIGURE_MAXIMUM_PARTITIONS rtems_resource_unlimited (2) +#define CONFIGURE_MAXIMUM_TIMERS 10 + +/** + * Configure drivers. + */ +#define CONFIGURE_MAXIMUM_DRIVERS 10 +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER + +/** + * Configure file system and libblock. + */ +#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM +#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 20 +#define CONFIGURE_APPLICATION_NEEDS_LIBBLOCK +#define CONFIGURE_SWAPOUT_TASK_PRIORITY 15 + +#if RTEMS_APP_IDEDISK +#define CONFIGURE_BDBUF_CACHE_MEMORY_SIZE (16 * 1024 * 1024) +#define CONFIGURE_BDBUF_MAX_READ_AHEAD_BLOCKS 2 +#define CONFIGURE_BDBUF_MAX_WRITE_BLOCKS 32 +#define CONFIGURE_APPLICATION_NEEDS_IDE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_ATA_DRIVER +#define CONFIGURE_ATA_DRIVER_TASK_PRIORITY 14 +#endif + +#define CONFIGURE_FILESYSTEM_ALL + +/** + * Tell confdefs.h to provide the configuration. + */ +#define CONFIGURE_INIT + +#include <rtems/confdefs.h> + +#ifdef RTEMS_NETWORKING + +#define CONFIGURE_NETWORK_PRIORITY 10 + +#if pc586 +#define LIBBSDPORT 1 +#define MULTI_NETDRIVER 0 +#define NEK 0 + +#include <rtems/pci.h> + +#if LIBBSDPORT + +#include <bsp/libbsdport_api.h> + +driver_t* libbsdport_netdriver_table[] = +{ + &libbsdport_rl_driver, + &libbsdport_re_driver, + &libbsdport_fxp_driver, + NULL +}; + +static int libbsdport_net_attach (struct rtems_bsdnet_ifconfig* ocfg, int attaching); + +static struct rtems_bsdnet_ifconfig libbsdport_config[] = +{ + { "", libbsdport_net_attach, NULL } +}; + +static int libbsdport_net_attach (struct rtems_bsdnet_ifconfig* ocfg, int attaching) +{ + int result; + result = pci_initialize (); + if (result) + { + printk ("PCI initialise failed\n"); + return result; + } + printk ("Initialising libbsdport...\n"); + result = libbsdport_netdriver_attach (&libbsdport_config[0], attaching); + if (result) + printk ("libbsdport failed: %d: %s\n", result, strerror (result)); + return result; +} + +#define CONFIGURE_NETWORK_DRIVER_NAME "" +#define CONFIGURE_NETWORK_DRIVER_ATTACH libbsdport_net_attach + +#elif MULTI_NETDRIVER + +int rtems_fxp_attach(struct rtems_bsdnet_ifconfig *config, int attaching); +int rtems_3c509_driver_attach (struct rtems_bsdnet_ifconfig *, int); +int rtems_fxp_attach (struct rtems_bsdnet_ifconfig *, int); +int rtems_elnk_driver_attach (struct rtems_bsdnet_ifconfig *, int); +int rtems_dec21140_driver_attach (struct rtems_bsdnet_ifconfig *, int); +/* these don't probe and will be used even if there's no device :-( */ +int rtems_ne_driver_attach (struct rtems_bsdnet_ifconfig *, int); +int rtems_wd_driver_attach (struct rtems_bsdnet_ifconfig *, int); + +static struct rtems_bsdnet_ifconfig isa_netdriver_config[] = +{ + { "ep0", rtems_3c509_driver_attach, isa_netdriver_config + 1 }, + /* qemu cannot configure irq-no :-(; has it hardwired to 9 */ + { "ne1", rtems_ne_driver_attach, 0, irno: 9 }, +}; + +static struct rtems_bsdnet_ifconfig pci_netdriver_config[]= +{ + { "dc1", rtems_dec21140_driver_attach, pci_netdriver_config + 1 }, + { "fxp1", rtems_fxp_attach, pci_netdriver_config + 2 }, + { "elnk1", rtems_elnk_driver_attach, isa_netdriver_config }, +}; + +extern int if_index; + +static int net_prober (struct rtems_bsdnet_ifconfig* ocfg, int attaching) +{ + struct rtems_bsdnet_ifconfig* cfg = NULL; + int if_index_pre; + if (attaching) + cfg = pci_initialize () ? isa_netdriver_config : pci_netdriver_config; + + while ( cfg ) + { + printk ("Probing %s : ", cfg->name); + /* + * Unfortunately, the return value is unreliable - some drivers report + * success even if they fail. Check if they chained an interface (ifnet) + * structure instead + */ + if_index_pre = if_index; + cfg->attach (cfg, attaching); + if (if_index > if_index_pre) + { + /* + * Assume success. + */ + printk("attached\n"); + ocfg->name = cfg->name; + ocfg->attach = cfg->attach; + return 0; + } + printk ("Probing %s : failed\n", cfg->name); + cfg = cfg->next; + } + return -1; +} + +#define CONFIGURE_NETWORK_DRIVER_NAME "probing" +#define CONFIGURE_NETWORK_DRIVER_ATTACH net_prober +#define CONFIGURE_ETHERNET_ADDRESS 0x00, 0x08, 0xc7, 0x21, 0x01, 0xf9 +#elif NEK +int rtems_ne_driver_attach (struct rtems_bsdnet_ifconfig *, int); +#define CONFIGURE_NETWORK_DRIVER_NAME "ne1" +#define CONFIGURE_NETWORK_DRIVER_ATTACH rtems_ne_driver_attach +#define CONFIGURE_ETHERNET_ADDRESS 0x00, 0x08, 0xc7, 0x21, 0x01, 0xf9 +#else +int rtems_fxp_attach(struct rtems_bsdnet_ifconfig *config, int attaching); +#define CONFIGURE_NETWORK_DRIVER_NAME "fxp1" +#define CONFIGURE_NETWORK_DRIVER_ATTACH rtems_fxp_attach +#define CONFIGURE_ETHERNET_ADDRESS 0x00, 0x08, 0xc7, 0x21, 0x01, 0xf9 +#endif +#else +#define CONFIGURE_NETWORK_DRIVER_NAME "fec0" +#define CONFIGURE_NETWORK_DRIVER_ATTACH rtems_fec_driver_attach +#define CONFIGURE_ETHERNET_ADDRESS 0x00, 0x20, 0xDD, 0xFF, 0x00, 0x01 +#endif + +#if RTEMS_APP_NETWORKING_DHCP +#define CONFIGURE_NETWORK_DHCP +#endif + +#if RTEMS_APP_NETWORKING_STATIC +#define CONFIGURE_NETWORK_IPADDR "172.16.100.50" +#define CONFIGURE_NETWORK_NETMASK "255.255.255.0" +#define CONFIGURE_NETWORK_GATEWAY "172.16.100.1" +#endif + +#define CONFIGURE_NETWORK_MBUFS (180*1024) +#define CONFIGURE_NETWORK_MCLUSTERS (350*1024) + +#include "networkconfig.h" +#endif + +#define CONFIGURE_SHELL_COMMANDS_INIT +#define CONFIGURE_SHELL_COMMANDS_ALL +#define CONFIGURE_SHELL_DEBUGRFS +#ifdef RTEMS_NETWORKING +#define CONFIGURE_SHELL_COMMANDS_ALL_NETWORKING +#endif + +#include <rtems/shellconfig.h> diff --git a/libbsd/include/arch/i386/machine/ansi.h b/libbsd/include/arch/i386/machine/ansi.h new file mode 100644 index 0000000..f27e9ea --- /dev/null +++ b/libbsd/include/arch/i386/machine/ansi.h @@ -0,0 +1,77 @@ +/* $NetBSD: ansi.h,v 1.23 2009/01/11 02:45:45 christos Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _I386_ANSI_H_ +#define _I386_ANSI_H_ + +#include <sys/cdefs.h> + +#include <machine/int_types.h> + +/* + * Types which are fundamental to the implementation and may appear in + * more than one standard header are defined here. Standard headers + * then use: + * #ifdef _BSD_SIZE_T_ + * typedef _BSD_SIZE_T_ size_t; + * #undef _BSD_SIZE_T_ + * #endif + */ +#define _BSD_CLOCK_T_ unsigned long /* clock() */ +#define _BSD_SSIZE_T_ int /* byte count or error */ +#define _BSD_TIME_T_ __int64_t /* time() */ +#if __GNUC_PREREQ__(2, 96) +#define _BSD_VA_LIST_ __builtin_va_list /* GCC built-in type */ +#else +#define _BSD_VA_LIST_ char * /* va_list */ +#endif +#define _BSD_CLOCKID_T_ int /* clockid_t */ +#define _BSD_TIMER_T_ int /* timer_t */ +#define _BSD_SUSECONDS_T_ int /* suseconds_t */ +#define _BSD_USECONDS_T_ unsigned int /* useconds_t */ +#define _BSD_WCHAR_T_ int /* wchar_t */ +#define _BSD_WINT_T_ int /* wint_t */ +#define _BSD_WCTRANS_T_ void * /* wctrans_t */ +#define _BSD_WCTYPE_T_ void * /* wctype_t */ + +/* + * mbstate_t is an opaque object to keep conversion state, during multibyte + * stream conversions. The content must not be referenced by user programs. + */ +typedef union { + __int64_t __mbstateL; /* for alignment */ + char __mbstate8[128]; +} __mbstate_t; +#define _BSD_MBSTATE_T_ __mbstate_t /* mbstate_t */ + +#endif /* _I386_ANSI_H_ */ diff --git a/libbsd/include/arch/i386/machine/asm.h b/libbsd/include/arch/i386/machine/asm.h new file mode 100644 index 0000000..faefb38 --- /dev/null +++ b/libbsd/include/arch/i386/machine/asm.h @@ -0,0 +1,220 @@ +/* $NetBSD: asm.h,v 1.38 2008/05/03 05:54:52 yamt Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)asm.h 5.5 (Berkeley) 5/7/91 + */ + +#ifndef _I386_ASM_H_ +#define _I386_ASM_H_ + +#ifdef _KERNEL_OPT +#include "opt_multiprocessor.h" +#endif + +#ifdef PIC +#define PIC_PROLOGUE \ + pushl %ebx; \ + call 1f; \ +1: \ + popl %ebx; \ + addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx +#define PIC_EPILOGUE \ + popl %ebx +#define PIC_PLT(x) x@PLT +#define PIC_GOT(x) x@GOT(%ebx) +#define PIC_GOTOFF(x) x@GOTOFF(%ebx) +#else +#define PIC_PROLOGUE +#define PIC_EPILOGUE +#define PIC_PLT(x) x +#define PIC_GOT(x) x +#define PIC_GOTOFF(x) x +#endif + +#ifdef __ELF__ +# define _C_LABEL(x) x +#else +# ifdef __STDC__ +# define _C_LABEL(x) _ ## x +# else +# define _C_LABEL(x) _/**/x +# endif +#endif +#define _ASM_LABEL(x) x + +#define CVAROFF(x, y) _C_LABEL(x) + y + +#ifdef __STDC__ +# define __CONCAT(x,y) x ## y +# define __STRING(x) #x +#else +# define __CONCAT(x,y) x/**/y +# define __STRING(x) "x" +#endif + +/* let kernels and others override entrypoint alignment */ +#if !defined(_ALIGN_TEXT) && !defined(_KERNEL) +# ifdef _STANDALONE +# define _ALIGN_TEXT .align 4 +# elif defined __ELF__ +# define _ALIGN_TEXT .align 16 +# else +# define _ALIGN_TEXT .align 4 +# endif +#endif + +#define _ENTRY(x) \ + .text; _ALIGN_TEXT; .globl x; .type x,@function; x: +#define _LABEL(x) \ + .globl x; x: + +#ifdef _KERNEL + +#define CPUVAR(off) %fs:__CONCAT(CPU_INFO_,off) + +/* XXX Can't use __CONCAT() here, as it would be evaluated incorrectly. */ +#ifdef __ELF__ +#ifdef __STDC__ +#define IDTVEC(name) \ + ALIGN_TEXT; .globl X ## name; .type X ## name,@function; X ## name: +#define IDTVEC_END(name) \ + .size X ## name, . - X ## name +#else +#define IDTVEC(name) \ + ALIGN_TEXT; .globl X/**/name; .type X/**/name,@function; X/**/name: +#define IDTVEC_END(name) \ + .size X/**/name, . - X/**/name +#endif /* __STDC__ */ +#else +#ifdef __STDC__ +#define IDTVEC(name) \ + ALIGN_TEXT; .globl _X ## name; .type _X ## name,@function; _X ## name: +#define IDTVEC_END(name) \ + .size _X ## name, . - _X ## name +#else +#define IDTVEC(name) \ + ALIGN_TEXT; .globl _X/**/name; .type _X/**/name,@function; _X/**/name: +#define IDTVEC_END(name) \ + .size _X/**/name, . - _X/**/name +#endif /* __STDC__ */ +#endif /* __ELF__ */ + +#ifdef _STANDALONE +#define ALIGN_DATA .align 4 +#define ALIGN_TEXT .align 4 /* 4-byte boundaries */ +#define SUPERALIGN_TEXT .align 16 /* 15-byte boundaries */ +#elif defined __ELF__ +#define ALIGN_DATA .align 4 +#define ALIGN_TEXT .align 16 /* 16-byte boundaries */ +#define SUPERALIGN_TEXT .align 16 /* 16-byte boundaries */ +#else +#define ALIGN_DATA .align 2 +#define ALIGN_TEXT .align 4 /* 16-byte boundaries */ +#define SUPERALIGN_TEXT .align 4 /* 16-byte boundaries */ +#endif /* __ELF__ */ + +#define _ALIGN_TEXT ALIGN_TEXT + +#ifdef GPROF +#ifdef __ELF__ +#define MCOUNT_ASM call _C_LABEL(__mcount) +#else /* __ELF__ */ +#define MCOUNT_ASM call _C_LABEL(mcount) +#endif /* __ELF__ */ +#else /* GPROF */ +#define MCOUNT_ASM /* nothing */ +#endif /* GPROF */ + +#endif /* _KERNEL */ + + + +#ifdef GPROF +# ifdef __ELF__ +# define _PROF_PROLOGUE \ + pushl %ebp; movl %esp,%ebp; call PIC_PLT(__mcount); popl %ebp +# else +# define _PROF_PROLOGUE \ + pushl %ebp; movl %esp,%ebp; call PIC_PLT(mcount); popl %ebp +# endif +#else +# define _PROF_PROLOGUE +#endif + +#define ENTRY(y) _ENTRY(_C_LABEL(y)); _PROF_PROLOGUE +#define NENTRY(y) _ENTRY(_C_LABEL(y)) +#define ASENTRY(y) _ENTRY(_ASM_LABEL(y)); _PROF_PROLOGUE +#define LABEL(y) _LABEL(_C_LABEL(y)) +#define END(y) .size y, . - y + +#define ASMSTR .asciz + +#ifdef __ELF__ +#define RCSID(x) .pushsection ".ident"; .asciz x; .popsection +#else +#define RCSID(x) .text; .asciz x +#endif + +#ifdef NO_KERNEL_RCSIDS +#define __KERNEL_RCSID(_n, _s) /* nothing */ +#else +#define __KERNEL_RCSID(_n, _s) RCSID(_s) +#endif + +#ifdef __ELF__ +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym +#endif +/* + * STRONG_ALIAS: create a strong alias. + */ +#define STRONG_ALIAS(alias,sym) \ + .globl alias; \ + alias = sym + +#ifdef __STDC__ +#define WARN_REFERENCES(sym,msg) \ + .stabs msg ## ,30,0,0,0 ; \ + .stabs __STRING(_C_LABEL(sym)) ## ,1,0,0,0 +#elif defined(__ELF__) +#define WARN_REFERENCES(sym,msg) \ + .stabs msg,30,0,0,0 ; \ + .stabs __STRING(sym),1,0,0,0 +#else +#define WARN_REFERENCES(sym,msg) \ + .stabs msg,30,0,0,0 ; \ + .stabs __STRING(_/**/sym),1,0,0,0 +#endif /* __STDC__ */ + +#endif /* !_I386_ASM_H_ */ diff --git a/libbsd/include/arch/i386/machine/cdefs.h b/libbsd/include/arch/i386/machine/cdefs.h new file mode 100644 index 0000000..0541bd7 --- /dev/null +++ b/libbsd/include/arch/i386/machine/cdefs.h @@ -0,0 +1,8 @@ +/* $NetBSD: cdefs.h,v 1.7 2008/10/26 06:57:30 mrg Exp $ */ + +#ifndef _I386_CDEFS_H_ +#define _I386_CDEFS_H_ + +/* No arch-specific cdefs. */ + +#endif /* !_I386_CDEFS_H_ */ diff --git a/libbsd/include/arch/i386/machine/elf_machdep.h b/libbsd/include/arch/i386/machine/elf_machdep.h new file mode 100644 index 0000000..442c561 --- /dev/null +++ b/libbsd/include/arch/i386/machine/elf_machdep.h @@ -0,0 +1,63 @@ +/* $NetBSD: elf_machdep.h,v 1.10 2009/05/30 05:56:52 skrll Exp $ */ + +#define ELF32_MACHDEP_ENDIANNESS ELFDATA2LSB +#define ELF32_MACHDEP_ID_CASES \ + case EM_386: \ + case EM_486: \ + break; + +#define ELF64_MACHDEP_ENDIANNESS XXX /* break compilation */ +#define ELF64_MACHDEP_ID_CASES \ + /* no 64-bit ELF machine types supported */ + +#define ELF32_MACHDEP_ID EM_386 + +#define ARCH_ELFSIZE 32 /* MD native binary size */ + +/* i386 relocations */ +#define R_386_NONE 0 +#define R_386_32 1 +#define R_386_PC32 2 +#define R_386_GOT32 3 +#define R_386_PLT32 4 +#define R_386_COPY 5 +#define R_386_GLOB_DAT 6 +#define R_386_JMP_SLOT 7 +#define R_386_RELATIVE 8 +#define R_386_GOTOFF 9 +#define R_386_GOTPC 10 + +/* TLS relocations */ +#define R_386_TLS_TPOFF 14 +#define R_386_TLS_IE 15 +#define R_386_TLS_GOTIE 16 +#define R_386_TLS_LE 17 +#define R_386_TLS_GD 18 +#define R_386_TLS_LDM 19 + +/* The following relocations are GNU extensions. */ +#define R_386_16 20 +#define R_386_PC16 21 +#define R_386_8 22 +#define R_386_PC8 23 + +/* More TLS relocations */ +#define R_386_TLS_GD_32 24 +#define R_386_TLS_GD_PUSH 25 +#define R_386_TLS_GD_CALL 26 +#define R_386_TLS_GD_POP 27 +#define R_386_TLS_LDM_32 28 +#define R_386_TLS_LDM_PUSH 29 +#define R_386_TLS_LDM_CALL 30 +#define R_386_TLS_LDM_POP 31 +#define R_386_TLS_LDO_32 32 +#define R_386_TLS_IE_32 33 +#define R_386_TLS_LE_32 34 +#define R_386_TLS_DTPMOD32 35 +#define R_386_TLS_DTPOFF32 36 +#define R_386_TLS_TPOFF32 37 +#define R_386_TLS_GOTDESC 39 +#define R_386_TLS_DESC_CALL 40 +#define R_386_TLS_DESC 41 + +#define R_TYPE(name) __CONCAT(R_386_,name) diff --git a/libbsd/include/arch/i386/machine/int_types.h b/libbsd/include/arch/i386/machine/int_types.h new file mode 100644 index 0000000..69c661c --- /dev/null +++ b/libbsd/include/arch/i386/machine/int_types.h @@ -0,0 +1,66 @@ +/* $NetBSD: int_types.h,v 1.10 2005/12/24 20:07:10 perry Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)types.h 7.5 (Berkeley) 3/9/91 + */ + +#ifndef _I386_INT_TYPES_H_ +#define _I386_INT_TYPES_H_ + +#include <sys/cdefs.h> + +/* + * 7.18.1 Integer types + */ + +/* 7.18.1.1 Exact-width integer types */ + +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short int __int16_t; +typedef unsigned short int __uint16_t; +#ifdef __COMPILER_INT64__ +typedef __COMPILER_INT64__ __int64_t; +typedef __COMPILER_UINT64__ __uint64_t; +#else +/* LONGLONG */ +typedef long long int __int64_t; +/* LONGLONG */ +typedef unsigned long long int __uint64_t; +#endif + +#define __BIT_TYPES_DEFINED__ + +/* 7.18.1.4 Integer types capable of holding object pointers */ + +typedef int __intptr_t; +typedef unsigned int __uintptr_t; + +#endif /* !_I386_INT_TYPES_H_ */ diff --git a/libbsd/include/arch/m68k/machine/ansi.h b/libbsd/include/arch/m68k/machine/ansi.h new file mode 100644 index 0000000..a6e1f6c --- /dev/null +++ b/libbsd/include/arch/m68k/machine/ansi.h @@ -0,0 +1,104 @@ +/* $NetBSD: ansi.h,v 1.16 2005/04/14 20:06:15 matt Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _ANSI_H_ +#define _ANSI_H_ + +#include <sys/cdefs.h> +#include <machine/int_types.h> + +/* + * Types which are fundamental to the implementation and may appear in + * more than one standard header are defined here. Standard headers + * then use: + * #ifdef _BSD_SIZE_T_ + * typedef _BSD_SIZE_T_ size_t; + * #undef _BSD_SIZE_T_ + * #endif + */ +#define _BSD_CLOCK_T_ unsigned long /* clock() */ +#ifndef _BSD_PTRDIFF_T_ +#define _BSD_PTRDIFF_T_ int /* ptr1 - ptr2 */ +#endif +#ifdef _BSD_SIZE_T_ +#undef _BSD_SIZE_T_ +#define _BSD_SIZE_T_ size_t +#else +#define _BSD_SIZE_T_ unsigned int /* sizeof() */ +#endif +#define _BSD_SSIZE_T_ int /* byte count or error */ +#define _BSD_TIME_T_ long /* time() */ +#if __GNUC_PREREQ__(3,0) +#define _BSD_VA_LIST_ __builtin_va_list /* va_list */ +#else +#define _BSD_VA_LIST_ char * /* va_list */ +#endif +#define _BSD_CLOCKID_T_ int /* clockid_t */ +#define _BSD_TIMER_T_ int /* timer_t */ +#define _BSD_SUSECONDS_T_ int /* suseconds_t */ +#define _BSD_USECONDS_T_ unsigned int /* useconds_t */ + +/* + * NOTE: rune_t is not covered by ANSI nor other standards, and should not + * be instantiated outside of lib/libc/locale. use wchar_t. + * + * Runes (wchar_t) is declared to be an ``int'' instead of the more natural + * ``unsigned long'' or ``long''. Two things are happening here. It is not + * unsigned so that EOF (-1) can be naturally assigned to it and used. Also, + * it looks like 10646 will be a 31 bit standard. This means that if your + * ints cannot hold 32 bits, you will be in trouble. The reason an int was + * chosen over a long is that the is*() and to*() routines take ints (says + * ANSI C), but they use _RUNE_T_ instead of int. By changing it here, you + * lose a bit of ANSI conformance, but your programs will still work. + * + * Note that _WCHAR_T_ and _RUNE_T_ must be of the same type. When wchar_t + * and rune_t are typedef'd, _WCHAR_T_ will be undef'd, but _RUNE_T remains + * defined for ctype.h. + */ +#define _BSD_WCHAR_T_ int /* wchar_t */ +#define _BSD_WINT_T_ int /* wint_t */ +#define _BSD_RUNE_T_ int /* rune_t */ +#define _BSD_WCTRANS_T_ void * /* wctrans_t */ +#define _BSD_WCTYPE_T_ void * /* wctype_t */ + +/* + * mbstate_t is an opaque object to keep conversion state, during multibyte + * stream conversions. The content must not be referenced by user programs. + */ +typedef union { + char __mbstate8[128]; + __int64_t __mbstateL; /* for alignment */ +} __mbstate_t; +#define _BSD_MBSTATE_T_ __mbstate_t /* mbstate_t */ + +#endif /* _ANSI_H_ */ diff --git a/libbsd/include/arch/m68k/machine/asm.h b/libbsd/include/arch/m68k/machine/asm.h new file mode 100644 index 0000000..ec932b9 --- /dev/null +++ b/libbsd/include/arch/m68k/machine/asm.h @@ -0,0 +1,232 @@ +/* $NetBSD: asm.h,v 1.25 2008/04/28 20:23:26 martin Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1994 Allen Briggs + * All rights reserved. + * + * Gleaned from locore.s and sun3 asm.h which had the following copyrights: + * locore.s: + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1990 The Regents of the University of California. + * sun3/include/asm.h: + * Copyright (c) 1993 Adam Glass + * Copyright (c) 1990 The Regents of the University of California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _M68K_ASM_H_ +#define _M68K_ASM_H_ + +#if defined(__ELF__) && defined(PIC) +#define PIC_PLT(name) name@PLTPC +#else +#define PIC_PLT(name) name +#endif + +#ifdef __ELF__ +# if __STDC__ +# define _C_LABEL(name) name +# else +# define _C_LABEL(name) name +#endif /* __STDC__ */ +#else /* __ELF__ */ +# if __STDC__ +# define _C_LABEL(name) _ ## name +# else +# define _C_LABEL(name) _/**/name +# endif /* __STDC__ */ +#endif /* __ELF__ */ + +#define _ASM_LABEL(name) name + +#define _ENTRY(name) \ + .text; .even; .globl name; .type name,@function; name: + +#ifdef __ELF__ +#define MCOUNT_ENTRY __mcount +#else +#define MCOUNT_ENTRY mcount +#endif + +#ifdef GPROF +#define _PROF_PROLOG link %a6,#0; jbsr MCOUNT_ENTRY; unlk %a6 +#else +#define _PROF_PROLOG +#endif + +#define ENTRY(name) _ENTRY(_C_LABEL(name)) _PROF_PROLOG +#define ASENTRY(name) _ENTRY(_ASM_LABEL(name)) _PROF_PROLOG + +#define ENTRY_NOPROFILE(name) _ENTRY(_C_LABEL(name)) +#define ASENTRY_NOPROFILE(name) _ENTRY(_ASM_LABEL(name)) + +/* + * The m68k ALTENTRY macro is very different than the traditional + * implementation used by other NetBSD ports. Usually ALTENTRY + * simply provides an alternate function entry point. The m68k + * definition takes a second argument and jumps inside the second + * function when profiling is enabled. + * + * The m68k behavior is similar to the ENTRY2 macro found in + * solaris' asm_linkage.h. + * + * Providing ENTRY2 and changing all the code that uses ALTENTRY + * to use it would be a desirable change. + */ +#ifdef PROF +#define ALTENTRY(name, rname) ENTRY(name); jra rname+12 +#else +#define ALTENTRY(name, rname) _ENTRY(_C_LABEL(name)) +#endif + +#define RCSID(x) .text ; \ + .asciz x ; \ + .even + +/* + * Global variables of whatever sort. + */ +#define GLOBAL(x) \ + .globl _C_LABEL(x) ; \ + _C_LABEL(x): + +#define ASGLOBAL(x) \ + .globl _ASM_LABEL(x) ; \ + _ASM_LABEL(x): + +/* + * ...and local variables. + */ +#define LOCAL(x) \ + _C_LABEL(x): + +#define ASLOCAL(x) \ + _ASM_LABEL(x): + +/* + * Items in the BSS segment. + */ +#define BSS(name, size) \ + .comm _C_LABEL(name),size + +#define ASBSS(name, size) \ + .comm _ASM_LABEL(name),size + +#ifdef _KERNEL +/* + * Shorthand for calling panic(). + * Note the side-effect: it uses up the 9: label, so be careful! + */ +#define PANIC(x) \ + pea 9f ; \ + jbsr _C_LABEL(panic) ; \ + 9: .asciz x ; \ + .even + +#endif /* _KERNEL */ + +/* + * Shorthand for defining vectors for the vector table. + */ +#define VECTOR(x) \ + .long _C_LABEL(x) + +#define ASVECTOR(x) \ + .long _ASM_LABEL(x) + +#define VECTOR_UNUSED \ + .long 0 + +#ifdef __ELF__ +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym +#endif +/* + * STRONG_ALIAS: create a strong alias. + */ +#define STRONG_ALIAS(alias,sym) \ + .globl alias; \ + alias = sym + +#ifdef __STDC__ +#define __STRING(x) #x +#define WARN_REFERENCES(sym,msg) \ + .stabs msg ## ,30,0,0,0 ; \ + .stabs __STRING(_ ## sym) ## ,1,0,0,0 +#else +#define __STRING(x) "x" +#define WARN_REFERENCES(sym,msg) \ + .stabs msg,30,0,0,0 ; \ + .stabs __STRING(_/**/sym),1,0,0,0 +#endif /* __STDC__ */ + +/* + * Macros to hide shortcomings in the 68010. + */ +#ifndef __mc68010__ +#define EXTBL(reg) \ + extbl reg +#else /* __mc68010__ */ +#define EXTBL(reg) \ + extw reg ; \ + extl reg +#endif /* __mc68010__ */ + +#endif /* _M68K_ASM_H_ */ diff --git a/libbsd/include/arch/m68k/machine/cdefs.h b/libbsd/include/arch/m68k/machine/cdefs.h new file mode 100644 index 0000000..00b74e9 --- /dev/null +++ b/libbsd/include/arch/m68k/machine/cdefs.h @@ -0,0 +1,8 @@ +/* $NetBSD: cdefs.h,v 1.6 1999/03/20 01:40:26 thorpej Exp $ */ + +#ifndef _M68K_CDEFS_H_ +#define _M68K_CDEFS_H_ + +/* No arch-specific cdefs. */ + +#endif /* !_M68K_CDEFS_H_ */ diff --git a/libbsd/include/arch/m68k/machine/elf_machdep.h b/libbsd/include/arch/m68k/machine/elf_machdep.h new file mode 100644 index 0000000..9a987c6 --- /dev/null +++ b/libbsd/include/arch/m68k/machine/elf_machdep.h @@ -0,0 +1,47 @@ +/* $NetBSD: elf_machdep.h,v 1.7 2002/01/28 21:34:48 thorpej Exp $ */ + +#define ELF32_MACHDEP_ENDIANNESS ELFDATA2MSB +#define ELF32_MACHDEP_ID_CASES \ + case EM_68K: \ + break; + +#define ELF64_MACHDEP_ENDIANNESS XXX /* break compilation */ +#define ELF64_MACHDEP_ID_CASES \ + /* no 64-bit ELF machine types supported */ + +#define ELF32_MACHDEP_ID EM_68K + +/* + * Machine-dependent ELF flags. These are defined by the GNU tools. + */ +#define EF_CPU32 0x00810000 +#define EF_M68000 0x01000000 + +#define ARCH_ELFSIZE 32 /* MD native binary size */ + +/* m68k relocation types */ +#define R_68K_NONE 0 +#define R_68K_32 1 +#define R_68K_16 2 +#define R_68K_8 3 +#define R_68K_PC32 4 +#define R_68K_PC16 5 +#define R_68K_PC8 6 +#define R_68K_GOT32 7 +#define R_68K_GOT16 8 +#define R_68K_GOT8 9 +#define R_68K_GOT32O 10 +#define R_68K_GOT16O 11 +#define R_68K_GOT8O 12 +#define R_68K_PLT32 13 +#define R_68K_PLT16 14 +#define R_68K_PLT8 15 +#define R_68K_PLT32O 16 +#define R_68K_PLT16O 17 +#define R_68K_PLT8O 18 +#define R_68K_COPY 19 +#define R_68K_GLOB_DAT 20 +#define R_68K_JMP_SLOT 21 +#define R_68K_RELATIVE 22 + +#define R_TYPE(name) __CONCAT(R_68K_,name) diff --git a/libbsd/include/arch/m68k/machine/int_types.h b/libbsd/include/arch/m68k/machine/int_types.h new file mode 100644 index 0000000..5940785 --- /dev/null +++ b/libbsd/include/arch/m68k/machine/int_types.h @@ -0,0 +1,70 @@ +/* $NetBSD: int_types.h,v 1.7 2005/09/06 19:18:23 kleink Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)types.h 7.9 (Berkeley) 3/9/91 + */ + +#ifndef _M68K_INT_TYPES_H_ +#define _M68K_INT_TYPES_H_ + +#include <sys/cdefs.h> + +#ifndef __rtems__ +/* + * 7.18.1 Integer types + */ + +/* 7.18.1.1 Exact-width integer types */ + +typedef __signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short int __int16_t; +typedef unsigned short int __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +#endif +#ifdef __COMPILER_INT64__ +typedef __COMPILER_INT64__ __int64_t; +typedef __COMPILER_UINT64__ __uint64_t; +#else +/* LONGLONG */ +typedef long long int __int64_t; +/* LONGLONG */ +typedef unsigned long long int __uint64_t; +#endif + +#define __BIT_TYPES_DEFINED__ + +/* 7.18.1.4 Integer types capable of holding object pointers */ + +typedef int __intptr_t; +typedef unsigned int __uintptr_t; + +#endif /* !_M68K_INT_TYPES_H_ */ diff --git a/libbsd/include/arch/nios2/machine/ansi.h b/libbsd/include/arch/nios2/machine/ansi.h new file mode 100644 index 0000000..a6e1f6c --- /dev/null +++ b/libbsd/include/arch/nios2/machine/ansi.h @@ -0,0 +1,104 @@ +/* $NetBSD: ansi.h,v 1.16 2005/04/14 20:06:15 matt Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _ANSI_H_ +#define _ANSI_H_ + +#include <sys/cdefs.h> +#include <machine/int_types.h> + +/* + * Types which are fundamental to the implementation and may appear in + * more than one standard header are defined here. Standard headers + * then use: + * #ifdef _BSD_SIZE_T_ + * typedef _BSD_SIZE_T_ size_t; + * #undef _BSD_SIZE_T_ + * #endif + */ +#define _BSD_CLOCK_T_ unsigned long /* clock() */ +#ifndef _BSD_PTRDIFF_T_ +#define _BSD_PTRDIFF_T_ int /* ptr1 - ptr2 */ +#endif +#ifdef _BSD_SIZE_T_ +#undef _BSD_SIZE_T_ +#define _BSD_SIZE_T_ size_t +#else +#define _BSD_SIZE_T_ unsigned int /* sizeof() */ +#endif +#define _BSD_SSIZE_T_ int /* byte count or error */ +#define _BSD_TIME_T_ long /* time() */ +#if __GNUC_PREREQ__(3,0) +#define _BSD_VA_LIST_ __builtin_va_list /* va_list */ +#else +#define _BSD_VA_LIST_ char * /* va_list */ +#endif +#define _BSD_CLOCKID_T_ int /* clockid_t */ +#define _BSD_TIMER_T_ int /* timer_t */ +#define _BSD_SUSECONDS_T_ int /* suseconds_t */ +#define _BSD_USECONDS_T_ unsigned int /* useconds_t */ + +/* + * NOTE: rune_t is not covered by ANSI nor other standards, and should not + * be instantiated outside of lib/libc/locale. use wchar_t. + * + * Runes (wchar_t) is declared to be an ``int'' instead of the more natural + * ``unsigned long'' or ``long''. Two things are happening here. It is not + * unsigned so that EOF (-1) can be naturally assigned to it and used. Also, + * it looks like 10646 will be a 31 bit standard. This means that if your + * ints cannot hold 32 bits, you will be in trouble. The reason an int was + * chosen over a long is that the is*() and to*() routines take ints (says + * ANSI C), but they use _RUNE_T_ instead of int. By changing it here, you + * lose a bit of ANSI conformance, but your programs will still work. + * + * Note that _WCHAR_T_ and _RUNE_T_ must be of the same type. When wchar_t + * and rune_t are typedef'd, _WCHAR_T_ will be undef'd, but _RUNE_T remains + * defined for ctype.h. + */ +#define _BSD_WCHAR_T_ int /* wchar_t */ +#define _BSD_WINT_T_ int /* wint_t */ +#define _BSD_RUNE_T_ int /* rune_t */ +#define _BSD_WCTRANS_T_ void * /* wctrans_t */ +#define _BSD_WCTYPE_T_ void * /* wctype_t */ + +/* + * mbstate_t is an opaque object to keep conversion state, during multibyte + * stream conversions. The content must not be referenced by user programs. + */ +typedef union { + char __mbstate8[128]; + __int64_t __mbstateL; /* for alignment */ +} __mbstate_t; +#define _BSD_MBSTATE_T_ __mbstate_t /* mbstate_t */ + +#endif /* _ANSI_H_ */ diff --git a/libbsd/include/arch/nios2/machine/asm.h b/libbsd/include/arch/nios2/machine/asm.h new file mode 100644 index 0000000..04a1973 --- /dev/null +++ b/libbsd/include/arch/nios2/machine/asm.h @@ -0,0 +1,219 @@ +/* $NetBSD: asm.h,v 1.25 2008/04/28 20:23:26 martin Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1994 Allen Briggs + * All rights reserved. + * + * Gleaned from locore.s and sun3 asm.h which had the following copyrights: + * locore.s: + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1990 The Regents of the University of California. + * sun3/include/asm.h: + * Copyright (c) 1993 Adam Glass + * Copyright (c) 1990 The Regents of the University of California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _NIOS2_ASM_H_ +#define _NIOS2_ASM_H_ + +#if defined(__ELF__) && defined(PIC) +#define PIC_PLT(name) name@PLTPC +#else +#define PIC_PLT(name) name +#endif + +#ifdef __ELF__ +# if __STDC__ +# define _C_LABEL(name) name +# else +# define _C_LABEL(name) name +#endif /* __STDC__ */ +#else /* __ELF__ */ +# if __STDC__ +# define _C_LABEL(name) _ ## name +# else +# define _C_LABEL(name) _/**/name +# endif /* __STDC__ */ +#endif /* __ELF__ */ + +#define _ASM_LABEL(name) name + +#define _ENTRY(name) \ + .text; .even; .globl name; .type name,@function; name: + +#ifdef __ELF__ +#define MCOUNT_ENTRY __mcount +#else +#define MCOUNT_ENTRY mcount +#endif + +#ifdef GPROF +#define _PROF_PROLOG xx +#else +#define _PROF_PROLOG +#endif + +#define ENTRY(name) _ENTRY(_C_LABEL(name)) _PROF_PROLOG +#define ASENTRY(name) _ENTRY(_ASM_LABEL(name)) _PROF_PROLOG + +#define ENTRY_NOPROFILE(name) _ENTRY(_C_LABEL(name)) +#define ASENTRY_NOPROFILE(name) _ENTRY(_ASM_LABEL(name)) + +/* + * The m68k ALTENTRY macro is very different than the traditional + * implementation used by other NetBSD ports. Usually ALTENTRY + * simply provides an alternate function entry point. The m68k + * definition takes a second argument and jumps inside the second + * function when profiling is enabled. + * + * The m68k behavior is similar to the ENTRY2 macro found in + * solaris' asm_linkage.h. + * + * Providing ENTRY2 and changing all the code that uses ALTENTRY + * to use it would be a desirable change. + */ +#ifdef PROF +#define ALTENTRY(name, rname) ENTRY(name); jmp rname+12 +#else +#define ALTENTRY(name, rname) _ENTRY(_C_LABEL(name)) +#endif + +#define RCSID(x) .text ; \ + .asciz x ; \ + .even + +/* + * Global variables of whatever sort. + */ +#define GLOBAL(x) \ + .globl _C_LABEL(x) ; \ + _C_LABEL(x): + +#define ASGLOBAL(x) \ + .globl _ASM_LABEL(x) ; \ + _ASM_LABEL(x): + +/* + * ...and local variables. + */ +#define LOCAL(x) \ + _C_LABEL(x): + +#define ASLOCAL(x) \ + _ASM_LABEL(x): + +/* + * Items in the BSS segment. + */ +#define BSS(name, size) \ + .comm _C_LABEL(name),size + +#define ASBSS(name, size) \ + .comm _ASM_LABEL(name),size + +#ifdef _KERNEL +/* + * Shorthand for calling panic(). + * Note the side-effect: it uses up the 9: label, so be careful! + */ +#define PANIC(x) \ + jmp _C_LABEL(panic) ; \ + 9: .asciz x ; \ + .even + +#endif /* _KERNEL */ + +/* + * Shorthand for defining vectors for the vector table. + */ +#define VECTOR(x) \ + .long _C_LABEL(x) + +#define ASVECTOR(x) \ + .long _ASM_LABEL(x) + +#define VECTOR_UNUSED \ + .long 0 + +#ifdef __ELF__ +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym +#endif +/* + * STRONG_ALIAS: create a strong alias. + */ +#define STRONG_ALIAS(alias,sym) \ + .globl alias; \ + alias = sym + +#ifdef __STDC__ +#define __STRING(x) #x +#define WARN_REFERENCES(sym,msg) \ + .stabs msg ## ,30,0,0,0 ; \ + .stabs __STRING(_ ## sym) ## ,1,0,0,0 +#else +#define __STRING(x) "x" +#define WARN_REFERENCES(sym,msg) \ + .stabs msg,30,0,0,0 ; \ + .stabs __STRING(_/**/sym),1,0,0,0 +#endif /* __STDC__ */ + +#endif /* _NIOS2_ASM_H_ */ diff --git a/libbsd/include/arch/nios2/machine/cdefs.h b/libbsd/include/arch/nios2/machine/cdefs.h new file mode 100644 index 0000000..f407a80 --- /dev/null +++ b/libbsd/include/arch/nios2/machine/cdefs.h @@ -0,0 +1,8 @@ +/* $NetBSD: cdefs.h,v 1.6 1999/03/20 01:40:26 thorpej Exp $ */ + +#ifndef _NIOS2_CDEFS_H_ +#define _NIOS2_CDEFS_H_ + +/* No arch-specific cdefs. */ + +#endif /* !_NIOS2_CDEFS_H_ */ diff --git a/libbsd/include/arch/nios2/machine/elf_machdep.h b/libbsd/include/arch/nios2/machine/elf_machdep.h new file mode 100644 index 0000000..3f3c108 --- /dev/null +++ b/libbsd/include/arch/nios2/machine/elf_machdep.h @@ -0,0 +1,46 @@ +/* $NetBSD: elf_machdep.h,v 1.7 2002/01/28 21:34:48 thorpej Exp $ */ + +#define ELF32_MACHDEP_ENDIANNESS ELFDATA2MSB +#define ELF32_MACHDEP_ID_CASES \ + case EM_ALTERA_NIOS2: \ + break; + +#define ELF64_MACHDEP_ENDIANNESS XXX /* break compilation */ +#define ELF64_MACHDEP_ID_CASES \ + /* no 64-bit ELF machine types supported */ + +#define ELF32_MACHDEP_ID EM_ALTERA_NIOS2 + +/* + * Machine-dependent ELF flags. These are defined by the GNU tools. + */ +#define EF_NIOS2 0x00810000 + +#define ARCH_ELFSIZE 32 /* MD native binary size */ + +/* NIOS2 relocation types */ +#define R_NIOS2_NONE 0 +#define R_NIOS2_32 1 +#define R_NIOS2_16 2 +#define R_NIOS2_8 3 +#define R_NIOS2_PC32 4 +#define R_NIOS2_PC16 5 +#define R_NIOS2_PC8 6 +#define R_NIOS2_GOT32 7 +#define R_NIOS2_GOT16 8 +#define R_NIOS2_GOT8 9 +#define R_NIOS2_GOT32O 10 +#define R_NIOS2_GOT16O 11 +#define R_NIOS2_GOT8O 12 +#define R_NIOS2_PLT32 13 +#define R_NIOS2_PLT16 14 +#define R_NIOS2_PLT8 15 +#define R_NIOS2_PLT32O 16 +#define R_NIOS2_PLT16O 17 +#define R_NIOS2_PLT8O 18 +#define R_NIOS2_COPY 19 +#define R_NIOS2_GLOB_DAT 20 +#define R_NIOS2_JMP_SLOT 21 +#define R_NIOS2_RELATIVE 22 + +#define R_TYPE(name) __CONCAT(R_NIOS2_,name) diff --git a/libbsd/include/arch/nios2/machine/int_types.h b/libbsd/include/arch/nios2/machine/int_types.h new file mode 100644 index 0000000..2a869d1 --- /dev/null +++ b/libbsd/include/arch/nios2/machine/int_types.h @@ -0,0 +1,70 @@ +/* $NetBSD: int_types.h,v 1.7 2005/09/06 19:18:23 kleink Exp $ */ + +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)types.h 7.9 (Berkeley) 3/9/91 + */ + +#ifndef _NIOS2_INT_TYPES_H_ +#define _NIOS2_INT_TYPES_H_ + +#include <sys/cdefs.h> + +#ifndef __rtems__ +/* + * 7.18.1 Integer types + */ + +/* 7.18.1.1 Exact-width integer types */ + +typedef __signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short int __int16_t; +typedef unsigned short int __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; +#endif +#ifdef __COMPILER_INT64__ +typedef __COMPILER_INT64__ __int64_t; +typedef __COMPILER_UINT64__ __uint64_t; +#else +/* LONGLONG */ +typedef long long int __int64_t; +/* LONGLONG */ +typedef unsigned long long int __uint64_t; +#endif + +#define __BIT_TYPES_DEFINED__ + +/* 7.18.1.4 Integer types capable of holding object pointers */ + +typedef int __intptr_t; +typedef unsigned int __uintptr_t; + +#endif /* !_NIOS2_INT_TYPES_H_ */ diff --git a/libbsd/include/arch/sparc/machine/ansi.h b/libbsd/include/arch/sparc/machine/ansi.h new file mode 100644 index 0000000..07a3ca5 --- /dev/null +++ b/libbsd/include/arch/sparc/machine/ansi.h @@ -0,0 +1,78 @@ +/* $NetBSD: ansi.h,v 1.21 2009/01/11 02:45:46 christos Exp $ */ + +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ansi.h 8.2 (Berkeley) 1/4/94 + */ + +#ifndef _ANSI_H_ +#define _ANSI_H_ + +#include <sys/cdefs.h> +#include <machine/int_types.h> + +/* + * Types which are fundamental to the implementation and may appear in + * more than one standard header are defined here. Standard headers + * then use: + * #ifdef _BSD_SIZE_T_ + * typedef _BSD_SIZE_T_ size_t; + * #undef _BSD_SIZE_T_ + * #endif + */ +#define _BSD_CLOCK_T_ unsigned long /* clock() */ +#define _BSD_PTRDIFF_T_ long /* ptr1 - ptr2 */ +#define _BSD_SIZE_T_ unsigned long /* sizeof() */ +#define _BSD_SSIZE_T_ long /* byte count or error */ +#define _BSD_TIME_T_ __int64_t /* time() */ +#if __GNUC_PREREQ__(3, 0) +#define _BSD_VA_LIST_ __builtin_va_list /* va_list */ +#else +#define _BSD_VA_LIST_ char * /* va_list */ +#endif +#define _BSD_CLOCKID_T_ int /* clockid_t */ +#define _BSD_TIMER_T_ int /* timer_t */ +#define _BSD_SUSECONDS_T_ int /* suseconds_t */ +#define _BSD_USECONDS_T_ unsigned int /* useconds_t */ +#define _BSD_WCHAR_T_ int /* wchar_t */ +#define _BSD_WINT_T_ int /* wint_t */ +#define _BSD_WCTRANS_T_ void * /* wctrans_t */ +#define _BSD_WCTYPE_T_ void * /* wctype_t */ + +/* + * mbstate_t is an opaque object to keep conversion state, during multibyte + * stream conversions. The content must not be referenced by user programs. + */ +typedef union { + __int64_t __mbstateL; /* for alignment */ + char __mbstate8[128]; +} __mbstate_t; +#define _BSD_MBSTATE_T_ __mbstate_t /* mbstate_t */ + +#endif /* _ANSI_H_ */ diff --git a/libbsd/include/arch/sparc/machine/asm.h b/libbsd/include/arch/sparc/machine/asm.h new file mode 100644 index 0000000..3cacfbb --- /dev/null +++ b/libbsd/include/arch/sparc/machine/asm.h @@ -0,0 +1,208 @@ +/* $NetBSD: asm.h,v 1.16 2006/01/20 22:02:40 christos Exp $ */ + +/* + * Copyright (c) 1994 Allen Briggs + * All rights reserved. + * + * Gleaned from locore.s and sun3 asm.h which had the following copyrights: + * locore.s: + * Copyright (c) 1988 University of Utah. + * Copyright (c) 1982, 1990 The Regents of the University of California. + * sun3/include/asm.h: + * Copyright (c) 1993 Adam Glass + * Copyright (c) 1990 The Regents of the University of California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _ASM_H_ +#define _ASM_H_ + +/* Pull in CCFSZ, CC64FSZ, and BIAS from frame.h */ +#ifndef _LOCORE +#define _LOCORE +#endif +#include <machine/frame.h> + +#ifdef __ELF__ +#define _C_LABEL(name) name +#else +#ifdef __STDC__ +#define _C_LABEL(name) _ ## name +#else +#define _C_LABEL(name) _/**/name +#endif +#endif +#define _ASM_LABEL(name) name + +#ifdef PIC +/* + * PIC_PROLOGUE() is akin to the compiler generated function prologue for + * PIC code. It leaves the address of the Global Offset Table in DEST, + * clobbering register TMP in the process. + * + * We can use two code sequences. We can read the %pc or use the call + * instruction that saves the pc in %o7. Call requires the branch unit and + * IEU1, and clobbers %o7 which needs to be restored. This instruction + * sequence takes about 4 cycles due to instruction interdependence. Reading + * the pc takes 4 cycles to dispatch and is always dispatched alone. That + * sequence takes 7 cycles. + */ +#ifdef __arch64__ +#define PIC_PROLOGUE(dest,tmp) \ + mov %o7, tmp; \ + sethi %hi(_GLOBAL_OFFSET_TABLE_-4),dest; \ + call 0f; \ + or dest,%lo(_GLOBAL_OFFSET_TABLE_+4),dest; \ +0: \ + add dest,%o7,dest; \ + mov tmp, %o7 +#else +#define PIC_PROLOGUE(dest,tmp) \ + mov %o7,tmp; 3: call 4f; nop; 4: \ + sethi %hi(_C_LABEL(_GLOBAL_OFFSET_TABLE_)-(3b-.)),dest; \ + or dest,%lo(_C_LABEL(_GLOBAL_OFFSET_TABLE_)-(3b-.)),dest; \ + add dest,%o7,dest; mov tmp,%o7 +#endif + +/* + * PICCY_SET() does the equivalent of a `set var, %dest' instruction in + * a PIC-like way, but without involving the Global Offset Table. This + * only works for VARs defined in the same file *and* in the text segment. + */ +#ifdef __arch64__ +#define PICCY_SET(var,dest,tmp) \ + 3: rd %pc, tmp; add tmp,(var-3b),dest +#else +#define PICCY_SET(var,dest,tmp) \ + mov %o7,tmp; 3: call 4f; nop; 4: \ + add %o7,(var-3b),dest; mov tmp,%o7 +#endif +#else +#define PIC_PROLOGUE(dest,tmp) +#define PICCY_OFFSET(var,dest,tmp) +#endif + +#define FTYPE(x) .type x,@function +#define OTYPE(x) .type x,@object + +#define _ENTRY(name) \ + .align 4; .globl name; .proc 1; FTYPE(name); name: + +#ifdef GPROF +/* see _MCOUNT_ENTRY in profile.h */ +#ifdef __ELF__ +#ifdef __arch64__ +#define _PROF_PROLOGUE \ + .data; .align 8; 1: .uaword 0; .uaword 0; \ + .text; save %sp,-CC64FSZ,%sp; sethi %hi(1b),%o0; call _mcount; \ + or %o0,%lo(1b),%o0; restore +#else +#define _PROF_PROLOGUE \ + .data; .align 4; 1: .long 0; \ + .text; save %sp,-96,%sp; sethi %hi(1b),%o0; call _mcount; \ + or %o0,%lo(1b),%o0; restore +#endif +#else +#ifdef __arch64__ +#define _PROF_PROLOGUE \ + .data; .align 8; 1: .uaword 0; .uaword 0; \ + .text; save %sp,-CC64FSZ,%sp; sethi %hi(1b),%o0; call mcount; \ + or %o0,%lo(1b),%o0; restore +#else +#define _PROF_PROLOGUE \ + .data; .align 4; 1: .long 0; \ + .text; save %sp,-96,%sp; sethi %hi(1b),%o0; call mcount; \ + or %o0,%lo(1b),%o0; restore +#endif +#endif +#else +#define _PROF_PROLOGUE +#endif + +#define ENTRY(name) _ENTRY(_C_LABEL(name)); _PROF_PROLOGUE +#define ENTRY_NOPROFILE(name) _ENTRY(_C_LABEL(name)) +#define ASENTRY(name) _ENTRY(_ASM_LABEL(name)); _PROF_PROLOGUE +#define FUNC(name) ASENTRY(name) +#define RODATA(name) .align 4; .text; .globl _C_LABEL(name); \ + OTYPE(_C_LABEL(name)); _C_LABEL(name): + + +#define ASMSTR .asciz + +#ifdef __ELF__ +#define RCSID(name) .pushsection ".ident"; .asciz name; .popsection +#else +#define RCSID(name) .asciz name +#endif + +#ifdef NO_KERNEL_RCSIDS +#define __KERNEL_RCSID(_n, _s) /* nothing */ +#else +#define __KERNEL_RCSID(_n, _s) RCSID(_s) +#endif + +#ifdef __ELF__ +#define WEAK_ALIAS(alias,sym) \ + .weak alias; \ + alias = sym +#endif +/* + * STRONG_ALIAS: create a strong alias. + */ +#define STRONG_ALIAS(alias,sym) \ + .globl alias; \ + alias = sym + +/* + * WARN_REFERENCES: create a warning if the specified symbol is referenced. + */ +#ifdef __ELF__ +#ifdef __STDC__ +#define WARN_REFERENCES(_sym,_msg) \ + .section .gnu.warning. ## _sym ; .ascii _msg ; .text +#else +#define WARN_REFERENCES(_sym,_msg) \ + .section .gnu.warning./**/_sym ; .ascii _msg ; .text +#endif /* __STDC__ */ +#else +#ifdef __STDC__ +#define __STRING(x) #x +#define WARN_REFERENCES(sym,msg) \ + .stabs msg ## ,30,0,0,0 ; \ + .stabs __STRING(_ ## sym) ## ,1,0,0,0 +#else +#define __STRING(x) "x" +#define WARN_REFERENCES(sym,msg) \ + .stabs msg,30,0,0,0 ; \ + .stabs __STRING(_/**/sym),1,0,0,0 +#endif /* __STDC__ */ +#endif /* __ELF__ */ + +#endif /* _ASM_H_ */ diff --git a/libbsd/include/arch/sparc/machine/cdefs.h b/libbsd/include/arch/sparc/machine/cdefs.h new file mode 100644 index 0000000..93b436f --- /dev/null +++ b/libbsd/include/arch/sparc/machine/cdefs.h @@ -0,0 +1,8 @@ +/* $NetBSD: cdefs.h,v 1.11 2005/12/11 12:19:05 christos Exp $ */ + +#ifndef _MACHINE_CDEFS_H_ +#define _MACHINE_CDEFS_H_ + +/* No arch-specific cdefs. */ + +#endif /* !_MACHINE_CDEFS_H_ */ diff --git a/libbsd/include/arch/sparc/machine/elf_machdep.h b/libbsd/include/arch/sparc/machine/elf_machdep.h new file mode 100644 index 0000000..e8f2b63 --- /dev/null +++ b/libbsd/include/arch/sparc/machine/elf_machdep.h @@ -0,0 +1,92 @@ +/* $NetBSD: elf_machdep.h,v 1.7 2009/05/30 05:56:53 skrll Exp $ */ + +#define ELF32_MACHDEP_ENDIANNESS ELFDATA2MSB +#define ELF32_MACHDEP_ID_CASES \ + case EM_SPARC: \ + case EM_SPARC32PLUS: \ + break; + +#define ELF64_MACHDEP_ENDIANNESS ELFDATA2MSB +#define ELF64_MACHDEP_ID_CASES \ + case EM_SPARC32PLUS: \ + case EM_SPARCV9: \ + /* no 64-bit ELF machine types supported */ + +#define ELF32_MACHDEP_ID EM_SPARC /* XXX right? */ + +#define ARCH_ELFSIZE 32 /* MD native binary size */ + +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 + +/* TLS relocations */ +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 + +#define R_TYPE(name) __CONCAT(R_SPARC_,name) diff --git a/libbsd/include/arch/sparc/machine/int_types.h b/libbsd/include/arch/sparc/machine/int_types.h new file mode 100644 index 0000000..c875844 --- /dev/null +++ b/libbsd/include/arch/sparc/machine/int_types.h @@ -0,0 +1,85 @@ +/* $NetBSD: int_types.h,v 1.10 2005/12/24 20:07:32 perry Exp $ */ + +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This software was developed by the Computer Systems Engineering group + * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and + * contributed to Berkeley. + * + * All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Lawrence Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)types.h 8.1 (Berkeley) 6/11/93 + */ + +#ifndef _SPARC_INT_TYPES_H_ +#define _SPARC_INT_TYPES_H_ + +#include <sys/cdefs.h> + +/* + * 7.18.1 Integer types + */ + +/* 7.18.1.1 Exact-width integer types */ + +typedef signed char __int8_t; +typedef unsigned char __uint8_t; +typedef short int __int16_t; +typedef unsigned short int __uint16_t; +typedef int __int32_t; +typedef unsigned int __uint32_t; + +#ifdef __COMPILER_INT64__ +typedef __COMPILER_INT64__ __int64_t; +typedef __COMPILER_UINT64__ __uint64_t; +#else +#ifdef __arch64__ +/* 64-bit compiler */ +typedef long int __int64_t; +typedef unsigned long int __uint64_t; +#else +/* 32-bit compiler */ +/* LONGLONG */ +typedef long long int __int64_t; +/* LONGLONG */ +typedef unsigned long long int __uint64_t; +#endif +#endif /* !__COMPILER_INT64__ */ + +#define __BIT_TYPES_DEFINED__ + +/* 7.18.1.4 Integer types capable of holding object pointers */ + +typedef long int __intptr_t; +typedef unsigned long int __uintptr_t; + +#endif /* !_SPARC_INT_TYPES_H_ */ diff --git a/libbsd/include/dlfcn.h b/libbsd/include/dlfcn.h new file mode 100644 index 0000000..f1faf45 --- /dev/null +++ b/libbsd/include/dlfcn.h @@ -0,0 +1,112 @@ +/* $NetBSD: dlfcn.h,v 1.21 2010/01/07 07:35:35 skrll Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _DLFCN_H_ +#define _DLFCN_H_ + +#include <sys/featuretest.h> +#include <sys/cdefs.h> + +#if defined(_NETBSD_SOURCE) +typedef struct _dl_info { + const char *dli_fname; /* File defining the symbol */ + void *dli_fbase; /* Base address */ + const char *dli_sname; /* Symbol name */ + const void *dli_saddr; /* Symbol address */ +} Dl_info; +#endif /* defined(_NETBSD_SOURCE) */ + +/* + * User interface to the run-time linker. + */ +__BEGIN_DECLS +void *dlopen(const char *, int); +int dlclose(void *); +void *dlsym(void * __restrict, const char * __restrict); +#if defined(_NETBSD_SOURCE) +int dladdr(void * __restrict, Dl_info * __restrict); +int dlctl(void *, int, void *); +#endif +int dlinfo(void *, int, void *); +__aconst char *dlerror(void); +__END_DECLS + +/* Values for dlopen `mode'. */ +#define RTLD_LAZY 1 +#define RTLD_NOW 2 +#define RTLD_GLOBAL 0x100 /* Allow global searches in object */ +#define RTLD_LOCAL 0x200 +#if defined(_NETBSD_SOURCE) +#define DL_LAZY RTLD_LAZY /* Compat */ +#endif + +/* + * Special handle arguments for dlsym(). + */ +#define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */ +#define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */ +#define RTLD_SELF ((void *) -3) /* Search the caller itself. */ + +/* + * dlctl() commands + */ +#if defined(_NETBSD_SOURCE) +#define DL_GETERRNO 1 +#define DL_GETSYMBOL 2 +#if 0 +#define DL_SETSRCHPATH x +#define DL_GETLIST x +#define DL_GETREFCNT x +#define DL_GETLOADADDR x +#endif /* 0 */ +#endif /* defined(_NETBSD_SOURCE) */ + +/* + * dlinfo() commands + * + * From Solaris: http://docs.sun.com/app/docs/doc/816-5168/dlinfo-3c?a=view + */ +#define RTLD_DI_UNRESOLVED 10 +#if defined(_NETBSD_SOURCE) +#define RTLD_DI_LINKMAP 3 +#if 0 +#define RTLD_DI_ARGSINFO 1 +#define RTLD_DI_CONFIGADDR 2 +#define RTLD_DI_LMID 4 +#define RTLD_DI_SERINFO 5 +#define RTLD_DI_SERINFOSIZE 6 +#define RTLD_DI_ORIGIN 7 +#define RTLD_DI_GETSIGNAL 8 +#define RTLD_DI_SETSIGNAL 9 +#endif +#endif /* _NETBSD_SOURCE */ + +#endif /* !defined(_DLFCN_H_) */ diff --git a/libbsd/include/err.h b/libbsd/include/err.h new file mode 100644 index 0000000..0eba5af --- /dev/null +++ b/libbsd/include/err.h @@ -0,0 +1,83 @@ +/* $NetBSD: err.h,v 1.14 2005/02/03 04:39:32 perry Exp $ */ + +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)err.h 8.1 (Berkeley) 6/2/93 + */ + +#ifndef _ERR_H_ +#define _ERR_H_ + +/* + * Don't use va_list in the err/warn prototypes. Va_list is typedef'd in two + * places (<machine/varargs.h> and <machine/stdarg.h>), so if we include one + * of them here we may collide with the utility's includes. It's unreasonable + * for utilities to have to include one of them to include err.h, so we get + * _BSD_VA_LIST_ from <machine/ansi.h> and use it. + */ +#include <machine/ansi.h> +#include <sys/cdefs.h> + +#include <stdarg.h> + +#define __dead + +#define err rtems_rtld_err +#define verr rtems_rtld_verr +#define errx rtems_rtld_errx +#define verrx rtems_rtld_verrx +#define warn rtems_rtld_warn +#define vwarn rtems_rtld_vwarn +#define warnx rtems_rtld_warnx +#define vwarnx rtems_rtld_vwarnx + +#include <setjmp.h> + +extern jmp_buf rtems_shell_bsd_exit_recover; + +__BEGIN_DECLS +__dead void err(jmp_buf*, int, const char *, ...) + __attribute__((__noreturn__, __format__(__printf__, 3, 4))); +__dead void verr(jmp_buf*, int, const char *, _BSD_VA_LIST_) + __attribute__((__noreturn__, __format__(__printf__, 3, 0))); +__dead void errx(jmp_buf*, int, const char *, ...) + __attribute__((__noreturn__, __format__(__printf__, 3, 4))); +__dead void verrx(jmp_buf*, int, const char *, _BSD_VA_LIST_) + __attribute__((__noreturn__, __format__(__printf__, 3, 0))); +void warn(const char *, ...) + __attribute__((__format__(__printf__, 1, 2))); +void vwarn(const char *, _BSD_VA_LIST_) + __attribute__((__format__(__printf__, 1, 0))); +void warnx(const char *, ...) + __attribute__((__format__(__printf__, 1, 2))); +void vwarnx(const char *, _BSD_VA_LIST_) + __attribute__((__format__(__printf__, 1, 0))); +__END_DECLS + +#endif /* !_ERR_H_ */ diff --git a/libbsd/include/link.h b/libbsd/include/link.h new file mode 100644 index 0000000..c93efd9 --- /dev/null +++ b/libbsd/include/link.h @@ -0,0 +1,45 @@ +/* $NetBSD: link.h,v 1.13 2008/04/28 20:22:54 martin Exp $ */ + +/*- + * Copyright (c) 1999 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, + * NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _LINK_H_ +#define _LINK_H_ + +/* + * Pull in the correct definitions for our toolchain target. + */ +#ifdef __ELF__ +#include <link_elf.h> +#else +#include <link_aout.h> +#endif + +#endif /* _LINK_H_ */ diff --git a/libbsd/include/link_elf.h b/libbsd/include/link_elf.h new file mode 100644 index 0000000..7236b5d --- /dev/null +++ b/libbsd/include/link_elf.h @@ -0,0 +1,36 @@ +/* $NetBSD: link_elf.h,v 1.8 2009/11/04 19:28:03 pooka Exp $ */ + +/* + * This only exists for GDB. + */ + +#ifndef _LINK_ELF_H_ +#define _LINK_ELF_H_ + +#include <sys/types.h> + +#include <machine/elf_machdep.h> + +typedef struct link_map { + caddr_t l_addr; /* Base Address of library */ +#ifdef __mips__ + caddr_t l_offs; /* Load Offset of library */ +#endif + const char *l_name; /* Absolute Path to Library */ + void *l_ld; /* Pointer to .dynamic in memory */ + struct link_map *l_next; /* linked list of of mapped libs */ + struct link_map *l_prev; +} Link_map; + +struct r_debug { + int r_version; /* not used */ + struct link_map *r_map; /* list of loaded images */ + void (*r_brk)(void); /* pointer to break point */ + enum { + RT_CONSISTENT, /* things are stable */ + RT_ADD, /* adding a shared library */ + RT_DELETE /* removing a shared library */ + } r_state; +}; + +#endif /* _LINK_ELF_H_ */ diff --git a/libbsd/include/sys/ansi.h b/libbsd/include/sys/ansi.h new file mode 100644 index 0000000..9dfe42d --- /dev/null +++ b/libbsd/include/sys/ansi.h @@ -0,0 +1,63 @@ +/* $NetBSD: ansi.h,v 1.10 2004/04/21 01:05:43 christos Exp $ */ + +/*- + * Copyright (c) 2000, 2001, 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jun-ichiro itojun Hagino and by Klaus Klein. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_ANSI_H_ +#define _SYS_ANSI_H_ + +#include <machine/int_types.h> + +typedef char * __caddr_t; /* core address */ +#ifndef __rtems__ +typedef __uint32_t __gid_t; /* group id */ +typedef __uint32_t __in_addr_t; /* IP(v4) address */ +typedef __uint32_t __mode_t; /* file permissions */ +#endif +typedef __uint16_t __in_port_t; /* "Internet" port number */ +#ifndef __rtems__ +typedef __int64_t __off_t; /* file offset */ +typedef __int32_t __pid_t; /* process id */ +#endif +typedef __uint8_t __sa_family_t; /* socket address family */ +typedef unsigned int __socklen_t; /* socket-related datum length */ +#ifndef __rtems__ +typedef __uint32_t __uid_t; /* user id */ +#endif +typedef __uint64_t __fsblkcnt_t; /* fs block count (statvfs) */ +typedef __uint64_t __fsfilcnt_t; /* fs file count */ + +#endif /* !_SYS_ANSI_H_ */ diff --git a/libbsd/include/sys/cdefs.h b/libbsd/include/sys/cdefs.h new file mode 100644 index 0000000..a257ae4 --- /dev/null +++ b/libbsd/include/sys/cdefs.h @@ -0,0 +1,363 @@ +/* $NetBSD: cdefs.h,v 1.59 2005/06/02 14:31:38 he Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Berkeley Software Design, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cdefs.h 8.8 (Berkeley) 1/9/95 + */ + +#ifndef _SYS_CDEFS_H_ +#define _SYS_CDEFS_H_ + +/* + * Macro to test if we're using a GNU C compiler of a specific vintage + * or later, for e.g. features that appeared in a particular version + * of GNU C. Usage: + * + * #if __GNUC_PREREQ__(major, minor) + * ...cool feature... + * #else + * ...delete feature... + * #endif + */ +#ifdef __GNUC__ +#define __GNUC_PREREQ__(x, y) \ + ((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \ + (__GNUC__ > (x))) +#else +#define __GNUC_PREREQ__(x, y) 0 +#endif + +#include <machine/cdefs.h> +#ifdef __ELF__ +#include <sys/cdefs_elf.h> +#else +#include <sys/cdefs_aout.h> +#endif + +#if defined(__cplusplus) +#define __BEGIN_DECLS extern "C" { +#define __END_DECLS } +#define __static_cast(x,y) static_cast<x>(y) +#else +#define __BEGIN_DECLS +#define __END_DECLS +#define __static_cast(x,y) (x)y +#endif + +/* + * The __CONCAT macro is used to concatenate parts of symbol names, e.g. + * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo. + * The __CONCAT macro is a bit tricky -- make sure you don't put spaces + * in between its arguments. __CONCAT can also concatenate double-quoted + * strings produced by the __STRING macro, but this only works with ANSI C. + */ + +#define ___STRING(x) __STRING(x) +#define ___CONCAT(x,y) __CONCAT(x,y) +#define __XSTRING(x) __STRING(x) /* expand x, then stringify */ + +#ifdef __GNUC__ +# define __ASMNAME(cname) __XSTRING (__USER_LABEL_PREFIX__) cname +#endif + + +#if __STDC__ || defined(__cplusplus) +#define __P(protos) protos /* full-blown ANSI C */ +#define __CONCAT(x,y) x ## y +#define __STRING(x) #x + +#define __const const /* define reserved names to standard */ +#define __signed signed +#define __volatile volatile +#if defined(__cplusplus) +#define __inline inline /* convert to C++ keyword */ +#else +#if !defined(__GNUC__) && !defined(__lint__) +#define __inline /* delete GCC keyword */ +#endif /* !__GNUC__ && !__lint__ */ +#endif /* !__cplusplus */ + +#else /* !(__STDC__ || __cplusplus) */ +#define __P(protos) () /* traditional C preprocessor */ +#define __CONCAT(x,y) x/**/y +#define __STRING(x) "x" + +#ifndef __GNUC__ +#define __const /* delete pseudo-ANSI C keywords */ +#define __inline +#define __signed +#define __volatile +#endif /* !__GNUC__ */ + +/* + * In non-ANSI C environments, new programs will want ANSI-only C keywords + * deleted from the program and old programs will want them left alone. + * Programs using the ANSI C keywords const, inline etc. as normal + * identifiers should define -DNO_ANSI_KEYWORDS. + */ +#ifndef NO_ANSI_KEYWORDS +#define const __const /* convert ANSI C keywords */ +#define inline __inline +#define signed __signed +#define volatile __volatile +#endif /* !NO_ANSI_KEYWORDS */ +#endif /* !(__STDC__ || __cplusplus) */ + +/* + * Used for internal auditing of the NetBSD source tree. + */ +#ifdef __AUDIT__ +#define __aconst __const +#else +#define __aconst +#endif + +/* + * The following macro is used to remove const cast-away warnings + * from gcc -Wcast-qual; it should be used with caution because it + * can hide valid errors; in particular most valid uses are in + * situations where the API requires it, not to cast away string + * constants. We don't use *intptr_t on purpose here and we are + * explicit about unsigned long so that we don't have additional + * dependencies. + */ +#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) + +/* + * The following macro is used to remove the volatile cast-away warnings + * from gcc -Wcast-qual; as above it should be used with caution + * because it can hide valid errors or warnings. Valid uses include + * making it possible to pass a volatile pointer to memset(). + * For the same reasons as above, we use unsigned long and not intptr_t. + */ +#define __UNVOLATILE(a) ((void *)(unsigned long)(volatile void *)(a)) + +/* + * GCC2 provides __extension__ to suppress warnings for various GNU C + * language extensions under "-ansi -pedantic". + */ +#if !__GNUC_PREREQ__(2, 0) +#define __extension__ /* delete __extension__ if non-gcc or gcc1 */ +#endif + +/* + * GCC1 and some versions of GCC2 declare dead (non-returning) and + * pure (no side effects) functions using "volatile" and "const"; + * unfortunately, these then cause warnings under "-ansi -pedantic". + * GCC2 uses a new, peculiar __attribute__((attrs)) style. All of + * these work for GNU C++ (modulo a slight glitch in the C++ grammar + * in the distribution version of 2.5.5). + */ +#if !__GNUC_PREREQ__(2, 5) +#define __attribute__(x) /* delete __attribute__ if non-gcc or gcc1 */ +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +#define __dead __volatile +#define __pure __const +#endif +#endif + +/* Delete pseudo-keywords wherever they are not available or needed. */ +#ifndef __dead +#define __dead +#define __pure +#endif + +#if __GNUC_PREREQ__(2, 7) +#define __unused __attribute__((__unused__)) +#else +#define __unused /* delete */ +#endif + +#if __GNUC_PREREQ__(3, 1) +#define __used __attribute__((__used__)) +#else +#define __used /* delete */ +#endif + +#if __GNUC_PREREQ__(2, 7) +#define __packed __attribute__((__packed__)) +#define __aligned(x) __attribute__((__aligned__(x))) +#define __section(x) __attribute__((__section__(x))) +#elif defined(__lint__) +#define __packed /* delete */ +#define __aligned(x) /* delete */ +#define __section(x) /* delete */ +#else +#define __packed error: no __packed for this compiler +#define __aligned(x) error: no __aligned for this compiler +#define __section(x) error: no __section for this compiler +#endif + +/* + * C99 defines the restrict type qualifier keyword, which was made available + * in GCC 2.92. + */ +#if __STDC_VERSION__ >= 199901L +#define __restrict restrict +#else +#if !__GNUC_PREREQ__(2, 92) +#define __restrict /* delete __restrict when not supported */ +#endif +#endif + +/* + * C99 defines __func__ predefined identifier, which was made available + * in GCC 2.95. + */ +#if !(__STDC_VERSION__ >= 199901L) +#if __GNUC_PREREQ__(2, 6) +#define __func__ __PRETTY_FUNCTION__ +#elif __GNUC_PREREQ__(2, 4) +#define __func__ __FUNCTION__ +#else +#define __func__ "" +#endif +#endif /* !(__STDC_VERSION__ >= 199901L) */ + +#if defined(_KERNEL) +#if defined(NO_KERNEL_RCSIDS) +#undef __KERNEL_RCSID +#define __KERNEL_RCSID(_n, _s) /* nothing */ +#endif /* NO_KERNEL_RCSIDS */ +#endif /* _KERNEL */ + +#if !defined(_STANDALONE) && !defined(_KERNEL) +#ifdef __GNUC__ +#define __RENAME(x) ___RENAME(x) +#else +#ifdef __lint__ +#define __RENAME(x) __symbolrename(x) +#else +#error "No function renaming possible" +#endif /* __lint__ */ +#endif /* __GNUC__ */ +#else /* _STANDALONE || _KERNEL */ +#define __RENAME(x) no renaming in kernel or standalone environment +#endif + +/* + * A barrier to stop the optimizer from moving code or assume live + * register values. This is gcc specific, the version is more or less + * arbitrary, might work with older compilers. + */ +#if __GNUC_PREREQ__(2, 95) +#define __insn_barrier() __asm __volatile("":::"memory") +#else +#define __insn_barrier() /* */ +#endif + +/* + * GNU C version 2.96 adds explicit branch prediction so that + * the CPU back-end can hint the processor and also so that + * code blocks can be reordered such that the predicted path + * sees a more linear flow, thus improving cache behavior, etc. + * + * The following two macros provide us with a way to use this + * compiler feature. Use __predict_true() if you expect the expression + * to evaluate to true, and __predict_false() if you expect the + * expression to evaluate to false. + * + * A few notes about usage: + * + * * Generally, __predict_false() error condition checks (unless + * you have some _strong_ reason to do otherwise, in which case + * document it), and/or __predict_true() `no-error' condition + * checks, assuming you want to optimize for the no-error case. + * + * * Other than that, if you don't know the likelihood of a test + * succeeding from empirical or other `hard' evidence, don't + * make predictions. + * + * * These are meant to be used in places that are run `a lot'. + * It is wasteful to make predictions in code that is run + * seldomly (e.g. at subsystem initialization time) as the + * basic block reordering that this affects can often generate + * larger code. + */ +#if __GNUC_PREREQ__(2, 96) +#define __predict_true(exp) __builtin_expect((exp) != 0, 1) +#define __predict_false(exp) __builtin_expect((exp) != 0, 0) +#else +#define __predict_true(exp) (exp) +#define __predict_false(exp) (exp) +#endif + +/* + * Macros for manipulating "link sets". Link sets are arrays of pointers + * to objects, which are gathered up by the linker. + * + * Object format-specific code has provided us with the following macros: + * + * __link_set_add_text(set, sym) + * Add a reference to the .text symbol `sym' to `set'. + * + * __link_set_add_rodata(set, sym) + * Add a reference to the .rodata symbol `sym' to `set'. + * + * __link_set_add_data(set, sym) + * Add a reference to the .data symbol `sym' to `set'. + * + * __link_set_add_bss(set, sym) + * Add a reference to the .bss symbol `sym' to `set'. + * + * __link_set_decl(set, ptype) + * Provide an extern declaration of the set `set', which + * contains an array of the pointer type `ptype'. This + * macro must be used by any code which wishes to reference + * the elements of a link set. + * + * __link_set_start(set) + * This points to the first slot in the link set. + * + * __link_set_end(set) + * This points to the (non-existent) slot after the last + * entry in the link set. + * + * __link_set_count(set) + * Count the number of entries in link set `set'. + * + * In addition, we provide the following macros for accessing link sets: + * + * __link_set_foreach(pvar, set) + * Iterate over the link set `set'. Because a link set is + * an array of pointers, pvar must be declared as "type **pvar", + * and the actual entry accessed as "*pvar". + * + * __link_set_entry(set, idx) + * Access the link set entry at index `idx' from set `set'. + */ +#define __link_set_foreach(pvar, set) \ + for (pvar = __link_set_start(set); pvar < __link_set_end(set); pvar++) + +#define __link_set_entry(set, idx) (__link_set_begin(set)[idx]) + +#endif /* !_SYS_CDEFS_H_ */ diff --git a/libbsd/include/sys/cdefs_elf.h b/libbsd/include/sys/cdefs_elf.h new file mode 100644 index 0000000..91903d6 --- /dev/null +++ b/libbsd/include/sys/cdefs_elf.h @@ -0,0 +1,152 @@ +/* $NetBSD: cdefs_elf.h,v 1.24 2005/07/16 17:53:36 christos Exp $ */ + +/* + * Copyright (c) 1995, 1996 Carnegie-Mellon University. + * All rights reserved. + * + * Author: Chris G. Demetriou + * + * Permission to use, copy, modify and distribute this software and + * its documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND + * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ + +#ifndef _SYS_CDEFS_ELF_H_ +#define _SYS_CDEFS_ELF_H_ + +#ifdef __LEADING_UNDERSCORE +#define _C_LABEL(x) __CONCAT(_,x) +#define _C_LABEL_STRING(x) "_"x +#else +#define _C_LABEL(x) x +#define _C_LABEL_STRING(x) x +#endif + +#if __STDC__ +#define ___RENAME(x) __asm__(___STRING(_C_LABEL(x))) +#else +#ifdef __LEADING_UNDERSCORE +#define ___RENAME(x) ____RENAME(_/**/x) +#define ____RENAME(x) __asm__(___STRING(x)) +#else +#define ___RENAME(x) __asm__(___STRING(x)) +#endif +#endif + +#define __indr_reference(sym,alias) /* nada, since we do weak refs */ + +#if __STDC__ +#define __strong_alias(alias,sym) \ + __asm__(".global " _C_LABEL_STRING(#alias) "\n" \ + _C_LABEL_STRING(#alias) " = " _C_LABEL_STRING(#sym)); + +#define __weak_alias(alias,sym) \ + __asm__(".weak " _C_LABEL_STRING(#alias) "\n" \ + _C_LABEL_STRING(#alias) " = " _C_LABEL_STRING(#sym)); +#define __weak_extern(sym) \ + __asm__(".weak " _C_LABEL_STRING(#sym)); +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning." #sym "\n\t.ascii \"" msg "\"\n\t.text"); + +#else /* !__STDC__ */ + +#ifdef __LEADING_UNDERSCORE +#define __weak_alias(alias,sym) ___weak_alias(_/**/alias,_/**/sym) +#define ___weak_alias(alias,sym) \ + __asm__(".weak alias\nalias = sym"); +#else +#define __weak_alias(alias,sym) \ + __asm__(".weak alias\nalias = sym"); +#endif +#ifdef __LEADING_UNDERSCORE +#define __weak_extern(sym) ___weak_extern(_/**/sym) +#define ___weak_extern(sym) \ + __asm__(".weak sym"); +#else +#define __weak_extern(sym) \ + __asm__(".weak sym"); +#endif +#define __warn_references(sym,msg) \ + __asm__(".section .gnu.warning.sym\n\t.ascii msg ; .text"); + +#endif /* !__STDC__ */ + +#if __STDC__ +#define __SECTIONSTRING(_sec, _str) \ + __asm__(".section " #_sec "\n\t.asciz \"" _str "\"\n\t.previous") +#else +#define __SECTIONSTRING(_sec, _str) \ + __asm__(".section _sec\n\t.asciz _str\n\t.previous") +#endif + +#define __IDSTRING(_n,_s) __SECTIONSTRING(.ident,_s) + +#define __RCSID(_s) __IDSTRING(rcsid,_s) +#define __SCCSID(_s) +#define __SCCSID2(_s) +#if 0 /* XXX userland __COPYRIGHTs have \ns in them */ +#define __COPYRIGHT(_s) __SECTIONSTRING(.copyright,_s) +#else +#define __COPYRIGHT(_s) \ + static const char copyright[] \ + __attribute__((__unused__,__section__(".copyright"))) = _s +#endif + +#define __KERNEL_RCSID(_n, _s) __RCSID(_s) +#define __KERNEL_SCCSID(_n, _s) +#if 0 /* XXX see above */ +#define __KERNEL_COPYRIGHT(_n, _s) __COPYRIGHT(_s) +#else +#define __KERNEL_COPYRIGHT(_n, _s) __SECTIONSTRING(.copyright, _s) +#endif + +#ifndef __lint__ +#define __link_set_make_entry(set, sym) \ + static void const * const __link_set_##set##_sym_##sym \ + __section("link_set_" #set) __used = &sym +#define __link_set_make_entry2(set, sym, n) \ + static void const * const __link_set_##set##_sym_##sym##_##n \ + __section("link_set_" #set) __used = &sym[n] +#else +#define __link_set_make_entry(set, sym) \ + extern void const * const __link_set_##set##_sym_##sym +#define __link_set_make_entry2(set, sym, n) \ + extern void const * const __link_set_##set##_sym_##sym##_##n +#endif /* __lint__ */ + +#define __link_set_add_text(set, sym) __link_set_make_entry(set, sym) +#define __link_set_add_rodata(set, sym) __link_set_make_entry(set, sym) +#define __link_set_add_data(set, sym) __link_set_make_entry(set, sym) +#define __link_set_add_bss(set, sym) __link_set_make_entry(set, sym) +#define __link_set_add_text2(set, sym, n) __link_set_make_entry2(set, sym, n) +#define __link_set_add_rodata2(set, sym, n) __link_set_make_entry2(set, sym, n) +#define __link_set_add_data2(set, sym, n) __link_set_make_entry2(set, sym, n) +#define __link_set_add_bss2(set, sym, n) __link_set_make_entry2(set, sym, n) + +#define __link_set_decl(set, ptype) \ + extern ptype * const __start_link_set_##set[]; \ + extern ptype * const __stop_link_set_##set[] \ + +#define __link_set_start(set) (__start_link_set_##set) +#define __link_set_end(set) (__stop_link_set_##set) + +#define __link_set_count(set) \ + (__link_set_end(set) - __link_set_start(set)) + +#endif /* !_SYS_CDEFS_ELF_H_ */ diff --git a/libbsd/include/sys/exec_elf.h b/libbsd/include/sys/exec_elf.h new file mode 100644 index 0000000..392cd33 --- /dev/null +++ b/libbsd/include/sys/exec_elf.h @@ -0,0 +1,1093 @@ +/* $NetBSD: exec_elf.h,v 1.102 2010/03/01 11:27:29 skrll Exp $ */ + +/*- + * Copyright (c) 1994 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Christos Zoulas. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_EXEC_ELF_H_ +#define _SYS_EXEC_ELF_H_ + +/* + * The current ELF ABI specification is available at: + * http://www.sco.com/developers/gabi/ + * + * Current header definitions are in: + * http://www.sco.com/developers/gabi/latest/ch4.eheader.html + */ + +#if defined(_KERNEL) || defined(_STANDALONE) +#include <sys/types.h> +#else +#include <inttypes.h> +#endif /* _KERNEL || _STANDALONE */ + +#if defined(ELFSIZE) +#define CONCAT(x,y) __CONCAT(x,y) +#define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x))) +#define ELFNAME2(x,y) CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y)))) +#define ELFNAMEEND(x) CONCAT(x,CONCAT(_elf,ELFSIZE)) +#define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x))) +#endif + +#if HAVE_NBTOOL_CONFIG_H +#include <nbinclude/machine/elf_machdep.h> +#else +#include <machine/elf_machdep.h> +#endif + +typedef uint8_t Elf_Byte; + +typedef uint32_t Elf32_Addr; +#define ELF32_FSZ_ADDR 4 +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_SOff; +#define ELF32_FSZ_OFF 4 +typedef int32_t Elf32_Sword; +#define ELF32_FSZ_SWORD 4 +typedef uint32_t Elf32_Word; +#define ELF32_FSZ_WORD 4 +typedef uint16_t Elf32_Half; +#define ELF32_FSZ_HALF 2 +typedef uint64_t Elf32_Lword; +#define ELF32_FSZ_LWORD 8 + +typedef uint64_t Elf64_Addr; +#define ELF64_FSZ_ADDR 8 +typedef uint64_t Elf64_Off; +typedef int64_t Elf64_SOff; +#define ELF64_FSZ_OFF 8 +typedef int32_t Elf64_Shalf; +#define ELF64_FSZ_SHALF 4 + +#ifndef ELF64_FSZ_SWORD +typedef int32_t Elf64_Sword; +#define ELF64_FSZ_SWORD 4 +#endif /* ELF64_FSZ_SWORD */ +#ifndef ELF64_FSZ_WORD +typedef uint32_t Elf64_Word; +#define ELF64_FSZ_WORD 4 +#endif /* ELF64_FSZ_WORD */ + +typedef int64_t Elf64_Sxword; +#define ELF64_FSZ_SXWORD 8 +typedef uint64_t Elf64_Xword; +#define ELF64_FSZ_XWORD 8 +typedef uint64_t Elf64_Lword; +#define ELF64_FSZ_LWORD 8 +typedef uint32_t Elf64_Half; +#define ELF64_FSZ_HALF 4 +typedef uint16_t Elf64_Quarter; +#define ELF64_FSZ_QUARTER 2 + +/* + * ELF Header + */ +#define ELF_NIDENT 16 + +typedef struct { + unsigned char e_ident[ELF_NIDENT]; /* Id bytes */ + Elf32_Half e_type; /* file type */ + Elf32_Half e_machine; /* machine type */ + Elf32_Word e_version; /* version number */ + Elf32_Addr e_entry; /* entry point */ + Elf32_Off e_phoff; /* Program hdr offset */ + Elf32_Off e_shoff; /* Section hdr offset */ + Elf32_Word e_flags; /* Processor flags */ + Elf32_Half e_ehsize; /* sizeof ehdr */ + Elf32_Half e_phentsize; /* Program header entry size */ + Elf32_Half e_phnum; /* Number of program headers */ + Elf32_Half e_shentsize; /* Section header entry size */ + Elf32_Half e_shnum; /* Number of section headers */ + Elf32_Half e_shstrndx; /* String table index */ +} Elf32_Ehdr; + +typedef struct { + unsigned char e_ident[ELF_NIDENT]; /* Id bytes */ + Elf64_Quarter e_type; /* file type */ + Elf64_Quarter e_machine; /* machine type */ + Elf64_Half e_version; /* version number */ + Elf64_Addr e_entry; /* entry point */ + Elf64_Off e_phoff; /* Program hdr offset */ + Elf64_Off e_shoff; /* Section hdr offset */ + Elf64_Half e_flags; /* Processor flags */ + Elf64_Quarter e_ehsize; /* sizeof ehdr */ + Elf64_Quarter e_phentsize; /* Program header entry size */ + Elf64_Quarter e_phnum; /* Number of program headers */ + Elf64_Quarter e_shentsize; /* Section header entry size */ + Elf64_Quarter e_shnum; /* Number of section headers */ + Elf64_Quarter e_shstrndx; /* String table index */ +} Elf64_Ehdr; + +/* e_ident offsets */ +#define EI_MAG0 0 /* '\177' */ +#define EI_MAG1 1 /* 'E' */ +#define EI_MAG2 2 /* 'L' */ +#define EI_MAG3 3 /* 'F' */ +#define EI_CLASS 4 /* File class */ +#define EI_DATA 5 /* Data encoding */ +#define EI_VERSION 6 /* File version */ +#define EI_OSABI 7 /* Operating system/ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define EI_PAD 9 /* Start of padding bytes up to EI_NIDENT*/ +#define EI_NIDENT 16 /* First non-ident header byte */ + +/* e_ident[EI_MAG0,EI_MAG3] */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +/* e_ident[EI_CLASS] */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ +#define ELFCLASSNUM 3 + +/* e_ident[EI_DATA] */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* 2's complement values, LSB first */ +#define ELFDATA2MSB 2 /* 2's complement values, MSB first */ + +/* e_ident[EI_VERSION] */ +#define EV_NONE 0 /* Invalid version */ +#define EV_CURRENT 1 /* Current version */ +#define EV_NUM 2 + +/* e_ident[EI_OSABI] */ +#define ELFOSABI_SYSV 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_MONTEREY 7 /* Monterey */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_OPENVMS 13 /* OpenVMS */ +#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ +#define ELFOSABI_AROS 15 /* Amiga Research OS */ +/* Unofficial OSABIs follow */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define ELFOSABI_NONE ELFOSABI_SYSV +#define ELFOSABI_AIX ELFOSABI_MONTEREY + +/* e_type */ +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_NUM 5 + +#define ET_LOOS 0xfe00 /* Operating system specific range */ +#define ET_HIOS 0xfeff +#define ET_LOPROC 0xff00 /* Processor-specific range */ +#define ET_HIPROC 0xffff + +/* e_machine */ +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola 68000 */ +#define EM_88K 5 /* Motorola 88000 */ +#define EM_486 6 /* Intel 80486 */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS I Architecture */ +#define EM_S370 9 /* Amdahl UTS on System/370 */ +#define EM_MIPS_RS3_LE 10 /* MIPS RS3000 Little-endian */ + /* 11-14 - Reserved */ +#define EM_RS6000 11 /* IBM RS/6000 XXX reserved */ +#define EM_PARISC 15 /* Hewlett-Packard PA-RISC */ +#define EM_NCUBE 16 /* NCube XXX reserved */ +#define EM_VPP500 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Enhanced instruction set SPARC */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* 64-bit PowerPC */ + /* 22-35 - Reserved */ +#define EM_S390 22 /* System/390 XXX reserved */ +#define EM_V800 36 /* NEC V800 */ +#define EM_FR20 37 /* Fujitsu FR20 */ +#define EM_RH32 38 /* TRW RH-32 */ +#define EM_RCE 39 /* Motorola RCE */ +#define EM_ARM 40 /* Advanced RISC Machines ARM */ +#define EM_ALPHA 41 /* DIGITAL Alpha */ +#define EM_SH 42 /* Hitachi Super-H */ +#define EM_SPARCV9 43 /* SPARC Version 9 */ +#define EM_TRICORE 44 /* Siemens Tricore */ +#define EM_ARC 45 /* Argonaut RISC Core */ +#define EM_H8_300 46 /* Hitachi H8/300 */ +#define EM_H8_300H 47 /* Hitachi H8/300H */ +#define EM_H8S 48 /* Hitachi H8S */ +#define EM_H8_500 49 /* Hitachi H8/500 */ +#define EM_IA_64 50 /* Intel Merced Processor */ +#define EM_MIPS_X 51 /* Stanford MIPS-X */ +#define EM_COLDFIRE 52 /* Motorola Coldfire */ +#define EM_68HC12 53 /* Motorola MC68HC12 */ +#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator */ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embedded RISC processor */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +#define EM_STARCORE 58 /* Motorola Star*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ embedded family processor */ +#define EM_X86_64 62 /* AMD x86-64 architecture */ +#define EM_PDSP 63 /* Sony DSP Processor */ +#define EM_PDP10 64 /* Digital Equipment Corp. PDP-10 */ +#define EM_PDP11 65 /* Digital Equipment Corp. PDP-11 */ +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 bit microcontroller */ +#define EM_ST7 68 /* STMicroelectronics ST7 8-bit microcontroller */ +#define EM_68HC16 69 /* Motorola MC68HC16 Microcontroller */ +#define EM_68HC11 70 /* Motorola MC68HC11 Microcontroller */ +#define EM_68HC08 71 /* Motorola MC68HC08 Microcontroller */ +#define EM_68HC05 72 /* Motorola MC68HC05 Microcontroller */ +#define EM_SVX 73 /* Silicon Graphics SVx */ +#define EM_ST19 74 /* STMicroelectronics ST19 8-bit CPU */ +#define EM_VAX 75 /* Digital VAX */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded CPU */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP processor */ +#define EM_ZSP 79 /* LSI Logic's 16-bit DSP processor */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ +#define EM_HUANY 81 /* Harvard's machine-independent format */ +#define EM_PRISM 82 /* SiTera Prism */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +#define EM_FR30 84 /* Fujitsu FR30 */ +#define EM_D10V 85 /* Mitsubishi D10V */ +#define EM_D30V 86 /* Mitsubishi D30V */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Mitsubishi M32R */ +#define EM_MN10300 89 /* Matsushita MN10300 */ +#define EM_MN10200 90 /* Matsushita MN10200 */ +#define EM_PJ 91 /* picoJava */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor */ +#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose Processor */ +#define EM_NS32K 97 /* National Semiconductor 32000 series */ +#define EM_TPC 98 /* Tenor Network TPC processor */ +#define EM_SNP1K 99 /* Trebia SNP 1000 processor */ +#define EM_ST200 100 /* STMicroelectronics ST200 microcontroller */ +#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family */ +#define EM_MAX 102 /* MAX processor */ +#define EM_CR 103 /* National Semiconductor CompactRISC micorprocessor */ +#define EM_F2MC16 104 /* Fujitsu F2MC16 */ +#define EM_MSP430 105 /* Texas Instruments MSP430 */ +#define EM_BLACKFIN 106 /* Analog Devices Blackfin DSP */ +#define EM_SE_C33 107 /* Seiko Epson S1C33 family */ +#define EM_SEP 108 /* Sharp embedded microprocessor */ +#define EM_ARCA 109 /* Arca RISC microprocessor */ +#define EM_UNICORE 110 /* UNICORE from PKU-Unity Ltd. and MPRC Peking University */ +#define EM_EXCESS 111 /* eXcess: 16/32/64-bit configurable embedded CPU */ +#define EM_DXP 112 /* Icera Semiconductor Inc. Deep Execution Processor */ +#define EM_ALTERA_NIOS2 113 /* Altera Nios II soft-core processor */ +#define EM_CRX 114 /* National Semiconductor CRX */ +#define EM_XGATE 115 /* Motorola XGATE embedded processor */ +#define EM_C166 116 /* Infineon C16x/XC16x processor */ +#define EM_M16C 117 /* Renesas M16C series microprocessors */ +#define EM_DSPIC30F 118 /* Microchip Technology dsPIC30F Digital Signal Controller */ +#define EM_CE 119 /* Freescale Communication Engine RISC core */ +#define EM_M32C 120 /* Renesas M32C series microprocessors */ + +#define EM_MICROBLAZE 189 /* Xilinx MicroBlaze 32-bit RISC soft processor core */ + +/* Unofficial machine types follow */ +#define EM_AVR32 6317 /* used by NetBSD/avr32 */ +#define EM_ALPHA_EXP 36902 /* used by NetBSD/alpha; obsolete */ +#define EM_NUM 36903 + +/* + * Program Header + */ +typedef struct { + Elf32_Word p_type; /* entry type */ + Elf32_Off p_offset; /* offset */ + Elf32_Addr p_vaddr; /* virtual address */ + Elf32_Addr p_paddr; /* physical address */ + Elf32_Word p_filesz; /* file size */ + Elf32_Word p_memsz; /* memory size */ + Elf32_Word p_flags; /* flags */ + Elf32_Word p_align; /* memory & file alignment */ +} Elf32_Phdr; + +typedef struct { + Elf64_Half p_type; /* entry type */ + Elf64_Half p_flags; /* flags */ + Elf64_Off p_offset; /* offset */ + Elf64_Addr p_vaddr; /* virtual address */ + Elf64_Addr p_paddr; /* physical address */ + Elf64_Xword p_filesz; /* file size */ + Elf64_Xword p_memsz; /* memory size */ + Elf64_Xword p_align; /* memory & file alignment */ +} Elf64_Phdr; + +/* p_type */ +#define PT_NULL 0 /* Program header table entry unused */ +#define PT_LOAD 1 /* Loadable program segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ +#define PT_INTERP 3 /* Program interpreter */ +#define PT_NOTE 4 /* Auxiliary information */ +#define PT_SHLIB 5 /* Reserved, unspecified semantics */ +#define PT_PHDR 6 /* Entry for header table itself */ +#define PT_NUM 7 + +#define PT_LOOS 0x60000000 /* OS-specific range */ +#define PT_HIOS 0x6fffffff +#define PT_LOPROC 0x70000000 /* Processor-specific range */ +#define PT_HIPROC 0x7fffffff + +#define PT_MIPS_REGINFO 0x70000000 + +/* p_flags */ +#define PF_R 0x4 /* Segment is readable */ +#define PF_W 0x2 /* Segment is writable */ +#define PF_X 0x1 /* Segment is executable */ + +#define PF_MASKOS 0x0ff00000 /* Operating system specific values */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific values */ + +/* Extended program header index. */ +#define PN_XNUM 0xffff + +/* + * Section Headers + */ +typedef struct { + Elf32_Word sh_name; /* section name (.shstrtab index) */ + Elf32_Word sh_type; /* section type */ + Elf32_Word sh_flags; /* section flags */ + Elf32_Addr sh_addr; /* virtual address */ + Elf32_Off sh_offset; /* file offset */ + Elf32_Word sh_size; /* section size */ + Elf32_Word sh_link; /* link to another */ + Elf32_Word sh_info; /* misc info */ + Elf32_Word sh_addralign; /* memory alignment */ + Elf32_Word sh_entsize; /* table entry size */ +} Elf32_Shdr; + +typedef struct { + Elf64_Half sh_name; /* section name (.shstrtab index) */ + Elf64_Half sh_type; /* section type */ + Elf64_Xword sh_flags; /* section flags */ + Elf64_Addr sh_addr; /* virtual address */ + Elf64_Off sh_offset; /* file offset */ + Elf64_Xword sh_size; /* section size */ + Elf64_Half sh_link; /* link to another */ + Elf64_Half sh_info; /* misc info */ + Elf64_Xword sh_addralign; /* memory alignment */ + Elf64_Xword sh_entsize; /* table entry size */ +} Elf64_Shdr; + +/* sh_type */ +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program information */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation information w/ addend */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Auxiliary information */ +#define SHT_NOBITS 8 /* No space allocated in file image */ +#define SHT_REL 9 /* Relocation information w/o addend */ +#define SHT_SHLIB 10 /* Reserved, unspecified semantics */ +#define SHT_DYNSYM 11 /* Symbol table for dynamic linker */ +#define SHT_INIT_ARRAY 14 /* Initialization function pointers */ +#define SHT_FINI_ARRAY 15 /* Termination function pointers */ +#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX) */ +#define SHT_NUM 19 + +#define SHT_LOOS 0x60000000 /* Operating system specific range */ +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_SUNW_verdef 0x6ffffffd /* Versions defined by file */ +#define SHT_GNU_verdef SHT_SUNW_verdef +#define SHT_SUNW_verneed 0x6ffffffe /* Versions needed by file */ +#define SHT_GNU_verneed SHT_SUNW_verneed +#define SHT_SUNW_versym 0x6fffffff /* Symbol versions */ +#define SHT_GNU_versym SHT_SUNW_versym +#define SHT_HIOS 0x6fffffff +#define SHT_LOPROC 0x70000000 /* Processor-specific range */ +#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 /* Application-specific range */ +#define SHT_HIUSER 0xffffffff + +/* sh_flags */ +#define SHF_WRITE 0x1 /* Section contains writable data */ +#define SHF_ALLOC 0x2 /* Section occupies memory */ +#define SHF_EXECINSTR 0x4 /* Section contains executable insns */ + +#define SHF_MASKOS 0x0f000000 /* Operating system specific values */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific values */ + +/* + * Symbol Table + */ +typedef struct { + Elf32_Word st_name; /* Symbol name (.strtab index) */ + Elf32_Word st_value; /* value of symbol */ + Elf32_Word st_size; /* size of symbol */ + Elf_Byte st_info; /* type / binding attrs */ + Elf_Byte st_other; /* unused */ + Elf32_Half st_shndx; /* section index of symbol */ +} Elf32_Sym; + +typedef struct { + Elf64_Half st_name; /* Symbol name (.strtab index) */ + Elf_Byte st_info; /* type / binding attrs */ + Elf_Byte st_other; /* unused */ + Elf64_Quarter st_shndx; /* section index of symbol */ + Elf64_Addr st_value; /* value of symbol */ + Elf64_Xword st_size; /* size of symbol */ +} Elf64_Sym; + +/* Symbol Table index of the undefined symbol */ +#define ELF_SYM_UNDEFINED 0 + +#define STN_UNDEF 0 /* undefined index */ + +/* st_info: Symbol Bindings */ +#define STB_LOCAL 0 /* local symbol */ +#define STB_GLOBAL 1 /* global symbol */ +#define STB_WEAK 2 /* weakly defined global symbol */ +#define STB_NUM 3 + +#define STB_LOOS 10 /* Operating system specific range */ +#define STB_HIOS 12 +#define STB_LOPROC 13 /* Processor-specific range */ +#define STB_HIPROC 15 + +/* st_info: Symbol Types */ +#define STT_NOTYPE 0 /* Type not specified */ +#define STT_OBJECT 1 /* Associated with a data object */ +#define STT_FUNC 2 /* Associated with a function */ +#define STT_SECTION 3 /* Associated with a section */ +#define STT_FILE 4 /* Associated with a file name */ +#define STT_COMMON 5 /* Uninitialised common block */ +#define STT_TLS 6 /* Thread local data object */ +#define STT_NUM 7 + +#define STT_LOOS 10 /* Operating system specific range */ +#define STT_HIOS 12 +#define STT_LOPROC 13 /* Processor-specific range */ +#define STT_HIPROC 15 + +/* st_other: Visibility Types */ +#define STV_DEFAULT 0 /* use binding type */ +#define STV_INTERNAL 1 /* not referenced from outside */ +#define STV_HIDDEN 2 /* not visible, may be used via ptr */ +#define STV_PROTECTED 3 /* visible, not preemptible */ +#define STV_EXPORTED 4 +#define STV_SINGLETON 5 +#define STV_ELIMINATE 6 + +/* st_info/st_other utility macros */ +#define ELF_ST_BIND(info) ((uint32_t)(info) >> 4) +#define ELF_ST_TYPE(info) ((uint32_t)(info) & 0xf) +#define ELF_ST_INFO(bind,type) ((Elf_Byte)(((bind) << 4) | \ + ((type) & 0xf))) +#define ELF_ST_VISIBILITY(other) ((uint32_t)(other) & 3) + +/* + * Special section indexes + */ +#define SHN_UNDEF 0 /* Undefined section */ + +#define SHN_LORESERVE 0xff00 /* Reserved range */ +#define SHN_ABS 0xfff1 /* Absolute symbols */ +#define SHN_COMMON 0xfff2 /* Common symbols */ +#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere */ +#define SHN_HIRESERVE 0xffff + +#define SHN_LOPROC 0xff00 /* Processor-specific range */ +#define SHN_HIPROC 0xff1f +#define SHN_LOOS 0xff20 /* Operating system specific range */ +#define SHN_HIOS 0xff3f + +#define SHN_MIPS_ACOMMON 0xff00 +#define SHN_MIPS_TEXT 0xff01 +#define SHN_MIPS_DATA 0xff02 +#define SHN_MIPS_SCOMMON 0xff03 + +/* + * Relocation Entries + */ +typedef struct { + Elf32_Word r_offset; /* where to do it */ + Elf32_Word r_info; /* index & type of relocation */ +} Elf32_Rel; + +typedef struct { + Elf32_Word r_offset; /* where to do it */ + Elf32_Word r_info; /* index & type of relocation */ + Elf32_Sword r_addend; /* adjustment value */ +} Elf32_Rela; + +/* r_info utility macros */ +#define ELF32_R_SYM(info) ((info) >> 8) +#define ELF32_R_TYPE(info) ((info) & 0xff) +#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) + +typedef struct { + Elf64_Addr r_offset; /* where to do it */ + Elf64_Xword r_info; /* index & type of relocation */ +} Elf64_Rel; + +typedef struct { + Elf64_Addr r_offset; /* where to do it */ + Elf64_Xword r_info; /* index & type of relocation */ + Elf64_Sxword r_addend; /* adjustment value */ +} Elf64_Rela; + +/* r_info utility macros */ +#define ELF64_R_SYM(info) ((info) >> 32) +#define ELF64_R_TYPE(info) ((info) & 0xffffffff) +#define ELF64_R_INFO(sym,type) (((sym) << 32) + (type)) + +/* + * Move entries + */ +typedef struct { + Elf32_Lword m_value; /* symbol value */ + Elf32_Word m_info; /* size + index */ + Elf32_Word m_poffset; /* symbol offset */ + Elf32_Half m_repeat; /* repeat count */ + Elf32_Half m_stride; /* stride info */ +} Elf32_Move; + +#define ELF32_M_SYM(info) ((info) >> 8) +#define ELF32_M_SIZE(info) (info) & 0xff) +#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char)(size)) + +typedef struct { + Elf64_Lword m_value; /* symbol value */ + Elf64_Xword m_info; /* size + index */ + Elf64_Xword m_poffset; /* symbol offset */ + Elf64_Half m_repeat; /* repeat count */ + Elf64_Half m_stride; /* stride info */ +} Elf64_Move; + +#define ELF64_M_SYM(info) ((info) >> 8) +#define ELF64_M_SIZE(info) (info) & 0xff) +#define ELF64_M_INFO(sym, size) (((sym) << 8) + (unsigned char)(size)) + +/* + * Hardware/software capabilities entry + */ +typedef struct { + Elf32_Word c_tag; /* entry tag value */ + union { + Elf32_Addr c_ptr; + Elf32_Word c_val; + } c_un; +} Elf32_Cap; + +typedef struct { + Elf64_Xword c_tag; /* entry tag value */ + union { + Elf64_Addr c_ptr; + Elf64_Xword c_val; + } c_un; +} Elf64_Cap; + +/* + * Dynamic Section structure array + */ +typedef struct { + Elf32_Word d_tag; /* entry tag value */ + union { + Elf32_Addr d_ptr; + Elf32_Word d_val; + } d_un; +} Elf32_Dyn; + +typedef struct { + Elf64_Xword d_tag; /* entry tag value */ + union { + Elf64_Addr d_ptr; + Elf64_Xword d_val; + } d_un; +} Elf64_Dyn; + +/* d_tag */ +#define DT_NULL 0 /* Marks end of dynamic array */ +#define DT_NEEDED 1 /* Name of needed library (DT_STRTAB offset) */ +#define DT_PLTRELSZ 2 /* Size, in bytes, of relocations in PLT */ +#define DT_PLTGOT 3 /* Address of PLT and/or GOT */ +#define DT_HASH 4 /* Address of symbol hash table */ +#define DT_STRTAB 5 /* Address of string table */ +#define DT_SYMTAB 6 /* Address of symbol table */ +#define DT_RELA 7 /* Address of Rela relocation table */ +#define DT_RELASZ 8 /* Size, in bytes, of DT_RELA table */ +#define DT_RELAENT 9 /* Size, in bytes, of one DT_RELA entry */ +#define DT_STRSZ 10 /* Size, in bytes, of DT_STRTAB table */ +#define DT_SYMENT 11 /* Size, in bytes, of one DT_SYMTAB entry */ +#define DT_INIT 12 /* Address of initialization function */ +#define DT_FINI 13 /* Address of termination function */ +#define DT_SONAME 14 /* Shared object name (DT_STRTAB offset) */ +#define DT_RPATH 15 /* Library search path (DT_STRTAB offset) */ +#define DT_SYMBOLIC 16 /* Start symbol search within local object */ +#define DT_REL 17 /* Address of Rel relocation table */ +#define DT_RELSZ 18 /* Size, in bytes, of DT_REL table */ +#define DT_RELENT 19 /* Size, in bytes, of one DT_REL entry */ +#define DT_PLTREL 20 /* Type of PLT relocation entries */ +#define DT_DEBUG 21 /* Used for debugging; unspecified */ +#define DT_TEXTREL 22 /* Relocations might modify non-writable seg */ +#define DT_JMPREL 23 /* Address of relocations associated with PLT */ +#define DT_BIND_NOW 24 /* Process all relocations at load-time */ +#define DT_INIT_ARRAY 25 /* Address of initialization function array */ +#define DT_FINI_ARRAY 26 /* Size, in bytes, of DT_INIT_ARRAY array */ +#define DT_INIT_ARRAYSZ 27 /* Address of termination function array */ +#define DT_FINI_ARRAYSZ 28 /* Size, in bytes, of DT_FINI_ARRAY array*/ +#define DT_NUM 29 + +#define DT_LOOS 0x60000000 /* Operating system specific range */ +#define DT_VERSYM 0x6ffffff0 /* Symbol versions */ +#define DT_FLAGS_1 0x6ffffffb /* ELF dynamic flags */ +#define DT_VERDEF 0x6ffffffc /* Versions defined by file */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of versions defined by file */ +#define DT_VERNEED 0x6ffffffe /* Versions needed by file */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of versions needed by file */ +#define DT_HIOS 0x6fffffff +#define DT_LOPROC 0x70000000 /* Processor-specific range */ +#define DT_HIPROC 0x7fffffff + +/* Flag values for DT_FLAGS_1 (incomplete) */ +#define DF_1_INITFIRST 0x00000020 /* Object's init/fini take priority */ + +/* + * Auxiliary Vectors + */ +typedef struct { + Elf32_Word a_type; /* 32-bit id */ + Elf32_Word a_v; /* 32-bit id */ +} Aux32Info; + +typedef struct { + Elf64_Half a_type; /* 32-bit id */ + Elf64_Xword a_v; /* 64-bit id */ +} Aux64Info; + +/* a_type */ +#define AT_NULL 0 /* Marks end of array */ +#define AT_IGNORE 1 /* No meaning, a_un is undefined */ +#define AT_EXECFD 2 /* Open file descriptor of object file */ +#define AT_PHDR 3 /* &phdr[0] */ +#define AT_PHENT 4 /* sizeof(phdr[0]) */ +#define AT_PHNUM 5 /* # phdr entries */ +#define AT_PAGESZ 6 /* PAGESIZE */ +#define AT_BASE 7 /* Interpreter base addr */ +#define AT_FLAGS 8 /* Processor flags */ +#define AT_ENTRY 9 /* Entry address of executable */ +#define AT_DCACHEBSIZE 10 /* Data cache block size */ +#define AT_ICACHEBSIZE 11 /* Instruction cache block size */ +#define AT_UCACHEBSIZE 12 /* Unified cache block size */ + + /* Vendor specific */ +#define AT_MIPS_NOTELF 10 /* XXX a_val != 0 -> MIPS XCOFF executable */ + +#define AT_EUID 2000 /* euid (solaris compatible numbers) */ +#define AT_RUID 2001 /* ruid (solaris compatible numbers) */ +#define AT_EGID 2002 /* egid (solaris compatible numbers) */ +#define AT_RGID 2003 /* rgid (solaris compatible numbers) */ + + /* Solaris kernel specific */ +#define AT_SUN_LDELF 2004 /* dynamic linker's ELF header */ +#define AT_SUN_LDSHDR 2005 /* dynamic linker's section header */ +#define AT_SUN_LDNAME 2006 /* dynamic linker's name */ +#define AT_SUN_LPGSIZE 2007 /* large pagesize */ + + /* Other information */ +#define AT_SUN_PLATFORM 2008 /* sysinfo(SI_PLATFORM) */ +#define AT_SUN_HWCAP 2009 /* process hardware capabilities */ +#define AT_SUN_IFLUSH 2010 /* do we need to flush the instruction cache? */ +#define AT_SUN_CPU 2011 /* CPU name */ + /* ibcs2 emulation band aid */ +#define AT_SUN_EMUL_ENTRY 2012 /* coff entry point */ +#define AT_SUN_EMUL_EXECFD 2013 /* coff file descriptor */ + /* Executable's fully resolved name */ +#define AT_SUN_EXECNAME 2014 + +/* + * Note Headers + */ +typedef struct { + Elf32_Word n_namesz; + Elf32_Word n_descsz; + Elf32_Word n_type; +} Elf32_Nhdr; + +typedef struct { + Elf64_Half n_namesz; + Elf64_Half n_descsz; + Elf64_Half n_type; +} Elf64_Nhdr; + +#define ELF_NOTE_TYPE_ABI_TAG 1 + +/* GNU-specific note name and description sizes */ +#define ELF_NOTE_ABI_NAMESZ 4 +#define ELF_NOTE_ABI_DESCSZ 16 +/* GNU-specific note name */ +#define ELF_NOTE_ABI_NAME "GNU\0" + +/* GNU-specific OS/version value stuff */ +#define ELF_NOTE_ABI_OS_LINUX 0 +#define ELF_NOTE_ABI_OS_HURD 1 +#define ELF_NOTE_ABI_OS_SOLARIS 2 + +/* NetBSD-specific note type: Emulation name. desc is emul name string. */ +#define ELF_NOTE_TYPE_NETBSD_TAG 1 +/* NetBSD-specific note name and description sizes */ +#define ELF_NOTE_NETBSD_NAMESZ 7 +#define ELF_NOTE_NETBSD_DESCSZ 4 +/* NetBSD-specific note name */ +#define ELF_NOTE_NETBSD_NAME "NetBSD\0\0" + +/* NetBSD-specific note type: Checksum. There should be 1 NOTE per PT_LOAD + section. desc is a tuple of <phnum>(16),<chk-type>(16),<chk-value>. */ +#define ELF_NOTE_TYPE_CHECKSUM_TAG 2 +#define ELF_NOTE_CHECKSUM_CRC32 1 +#define ELF_NOTE_CHECKSUM_MD5 2 +#define ELF_NOTE_CHECKSUM_SHA1 3 +#define ELF_NOTE_CHECKSUM_SHA256 4 + +/* NetBSD-specific note type: PaX. There should be 1 NOTE per executable. + section. desc is a 32 bit bitmask */ +#define ELF_NOTE_TYPE_PAX_TAG 3 +#define ELF_NOTE_PAX_MPROTECT 0x01 /* Force enable Mprotect */ +#define ELF_NOTE_PAX_NOMPROTECT 0x02 /* Force disable Mprotect */ +#define ELF_NOTE_PAX_GUARD 0x04 /* Force enable Segvguard */ +#define ELF_NOTE_PAX_NOGUARD 0x08 /* Force disable Servguard */ +#define ELF_NOTE_PAX_ASLR 0x10 /* Force enable ASLR */ +#define ELF_NOTE_PAX_NOASLR 0x20 /* Force disable ASLR */ +#define ELF_NOTE_PAX_NAMESZ 4 +#define ELF_NOTE_PAX_NAME "PaX\0" +#define ELF_NOTE_PAX_DESCSZ 4 + +/* + * NetBSD-specific core file information. + * + * NetBSD ELF core files use notes to provide information about + * the process's state. The note name is "NetBSD-CORE" for + * information that is global to the process, and "NetBSD-CORE@nn", + * where "nn" is the lwpid of the LWP that the information belongs + * to (such as register state). + * + * We use the following note identifiers: + * + * ELF_NOTE_NETBSD_CORE_PROCINFO + * Note is a "netbsd_elfcore_procinfo" structure. + * + * We also use ptrace(2) request numbers (the ones that exist in + * machine-dependent space) to identify register info notes. The + * info in such notes is in the same format that ptrace(2) would + * export that information. + * + * Please try to keep the members of this structure nicely aligned, + * and if you add elements, add them to the end and bump the version. + */ + +#define ELF_NOTE_NETBSD_CORE_NAME "NetBSD-CORE" + +#define ELF_NOTE_NETBSD_CORE_PROCINFO 1 + +#define NETBSD_ELFCORE_PROCINFO_VERSION 1 + +struct netbsd_elfcore_procinfo { + /* Version 1 fields start here. */ + uint32_t cpi_version; /* netbsd_elfcore_procinfo version */ + uint32_t cpi_cpisize; /* sizeof(netbsd_elfcore_procinfo) */ + uint32_t cpi_signo; /* killing signal */ + uint32_t cpi_sigcode; /* signal code */ + uint32_t cpi_sigpend[4]; /* pending signals */ + uint32_t cpi_sigmask[4]; /* blocked signals */ + uint32_t cpi_sigignore[4];/* blocked signals */ + uint32_t cpi_sigcatch[4];/* blocked signals */ + int32_t cpi_pid; /* process ID */ + int32_t cpi_ppid; /* parent process ID */ + int32_t cpi_pgrp; /* process group ID */ + int32_t cpi_sid; /* session ID */ + uint32_t cpi_ruid; /* real user ID */ + uint32_t cpi_euid; /* effective user ID */ + uint32_t cpi_svuid; /* saved user ID */ + uint32_t cpi_rgid; /* real group ID */ + uint32_t cpi_egid; /* effective group ID */ + uint32_t cpi_svgid; /* saved group ID */ + uint32_t cpi_nlwps; /* number of LWPs */ + int8_t cpi_name[32]; /* copy of p->p_comm */ + /* Add version 2 fields below here. */ + int32_t cpi_siglwp; /* LWP target of killing signal */ +}; + +#if defined(ELFSIZE) && (ELFSIZE == 32) +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Phdr Elf32_Phdr +#define Elf_Shdr Elf32_Shdr +#define Elf_Sym Elf32_Sym +#define Elf_Rel Elf32_Rel +#define Elf_Rela Elf32_Rela +#define Elf_Dyn Elf32_Dyn +#define Elf_Word Elf32_Word +#define Elf_Sword Elf32_Sword +#define Elf_Addr Elf32_Addr +#define Elf_Off Elf32_Off +#define Elf_SOff Elf32_SOff +#define Elf_Nhdr Elf32_Nhdr + +#define ELF_R_SYM ELF32_R_SYM +#define ELF_R_TYPE ELF32_R_TYPE +#define ELFCLASS ELFCLASS32 + +#define AuxInfo Aux32Info +#elif defined(ELFSIZE) && (ELFSIZE == 64) +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Phdr Elf64_Phdr +#define Elf_Shdr Elf64_Shdr +#define Elf_Sym Elf64_Sym +#define Elf_Rel Elf64_Rel +#define Elf_Rela Elf64_Rela +#define Elf_Dyn Elf64_Dyn +#define Elf_Word Elf64_Word +#define Elf_Sword Elf64_Sword +#define Elf_Addr Elf64_Addr +#define Elf_Off Elf64_Off +#define Elf_SOff Elf64_SOff +#define Elf_Nhdr Elf64_Nhdr + +#define ELF_R_SYM ELF64_R_SYM +#define ELF_R_TYPE ELF64_R_TYPE +#define ELFCLASS ELFCLASS64 + +#define AuxInfo Aux64Info +#endif + +#define ELF32_ST_BIND(info) ELF_ST_BIND(info) +#define ELF32_ST_TYPE(info) ELF_ST_TYPE(info) +#define ELF32_ST_INFO(bind,type) ELF_ST_INFO(bind,type) +#define ELF32_ST_VISIBILITY(other) ELF_ST_VISIBILITY(other) + +#define ELF64_ST_BIND(info) ELF_ST_BIND(info) +#define ELF64_ST_TYPE(info) ELF_ST_TYPE(info) +#define ELF64_ST_INFO(bind,type) ELF_ST_INFO(bind,type) +#define ELF64_ST_VISIBILITY(other) ELF_ST_VISIBILITY(other) + +typedef struct { + Elf32_Half si_boundto; /* direct bindings - symbol bound to */ + Elf32_Half si_flags; /* per symbol flags */ +} Elf32_Syminfo; + +typedef struct { + Elf64_Half si_boundto; /* direct bindings - symbol bound to */ + Elf64_Half si_flags; /* per symbol flags */ +} Elf64_Syminfo; + +#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association + to object containing definition */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */ +#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be + lazily-loaded */ +#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to + object containing definition */ +#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference + directly bind to this symbol */ +#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */ +#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */ + +#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */ +#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */ +#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */ + +#define SYMINFO_NONE 0 /* Syminfo version */ +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +/* + * These constants are used for Elf32_Verdef struct's version number. + */ +#define VER_DEF_NONE 0 +#define VER_DEF_CURRENT 1 + +/* + * These constants are used for Elf32_Verdef struct's vd_flags. + */ +#define VER_FLG_BASE 0x1 +#define VER_FLG_WEAK 0x2 + +/* + * These are used in an Elf32_Versym field. + */ +#define VER_NDX_LOCAL 0 +#define VER_NDX_GLOBAL 1 + +/* + * These constants are used for Elf32_Verneed struct's version number. + */ +#define VER_NEED_NONE 0 +#define VER_NEED_CURRENT 1 + +/* + * GNU Extension hidding symb + */ +#define VERSYM_HIDDEN 0x8000 +#define VERSYM_VERSION 0x7fff + +#define ELF_VER_CHR '@' + +/* + * These are current size independent. + */ + +typedef struct { + Elf32_Half vd_version; /* version number of structure */ + Elf32_Half vd_flags; /* flags (VER_FLG_*) */ + Elf32_Half vd_ndx; /* version index */ + Elf32_Half vd_cnt; /* number of verdaux entries */ + Elf32_Word vd_hash; /* hash of name */ + Elf32_Word vd_aux; /* offset to verdaux entries */ + Elf32_Word vd_next; /* offset to next verdef */ +} Elf32_Verdef; +typedef Elf32_Verdef Elf64_Verdef; + +typedef struct { + Elf32_Word vda_name; /* string table offset of name */ + Elf32_Word vda_next; /* offset to verdaux */ +} Elf32_Verdaux; +typedef Elf32_Verdaux Elf64_Verdaux; + +typedef struct { + Elf32_Half vn_version; /* version number of structure */ + Elf32_Half vn_cnt; /* number of vernaux entries */ + Elf32_Word vn_file; /* string table offset of library name*/ + Elf32_Word vn_aux; /* offset to vernaux entries */ + Elf32_Word vn_next; /* offset to next verneed */ +} Elf32_Verneed; +typedef Elf32_Verneed Elf64_Verneed; + +typedef struct { + Elf32_Word vna_hash; /* Hash of dependency name */ + Elf32_Half vna_flags; /* flags (VER_FLG_*) */ + Elf32_Half vna_other; /* unused */ + Elf32_Word vna_name; /* string table offset to version name*/ + Elf32_Word vna_next; /* offset to next vernaux */ +} Elf32_Vernaux; +typedef Elf32_Vernaux Elf64_Vernaux; + +typedef struct { + Elf32_Half vs_vers; +} Elf32_Versym; +typedef Elf32_Versym Elf64_Versym; + +#ifdef _KERNEL + +#define ELF_AUX_ENTRIES 14 /* Max size of aux array passed to loader */ +#define ELF32_NO_ADDR (~(Elf32_Addr)0) /* Indicates addr. not yet filled in */ +#define ELF32_LINK_ADDR ((Elf32_Addr)-2) /* advises to use link address */ +#define ELF64_NO_ADDR (~(Elf64_Addr)0) /* Indicates addr. not yet filled in */ +#define ELF64_LINK_ADDR ((Elf64_Addr)-2) /* advises to use link address */ + +#if defined(ELFSIZE) && (ELFSIZE == 64) +#define ELF_NO_ADDR ELF64_NO_ADDR +#define ELF_LINK_ADDR ELF64_LINK_ADDR +#elif defined(ELFSIZE) && (ELFSIZE == 32) +#define ELF_NO_ADDR ELF32_NO_ADDR +#define ELF_LINK_ADDR ELF32_LINK_ADDR +#endif + +#ifndef ELF32_EHDR_FLAGS_OK +#define ELF32_EHDR_FLAGS_OK(eh) 1 +#endif + +#ifndef ELF64_EHDR_FLAGS_OK +#define ELF64_EHDR_FLAGS_OK(eh) 1 +#endif + +#if defined(ELFSIZE) && (ELFSIZE == 64) +#define ELF_EHDR_FLAGS_OK(eh) ELF64_EHDR_FLAGS_OK(eh) +#else +#define ELF_EHDR_FLAGS_OK(eh) ELF32_EHDR_FLAGS_OK(eh) +#endif + +#if defined(ELFSIZE) +struct elf_args { + Elf_Addr arg_entry; /* program entry point */ + Elf_Addr arg_interp; /* Interpreter load address */ + Elf_Addr arg_phaddr; /* program header address */ + Elf_Addr arg_phentsize; /* Size of program header */ + Elf_Addr arg_phnum; /* Number of program headers */ +}; +#endif + +#ifdef _KERNEL_OPT +#include "opt_execfmt.h" +#endif + +#ifdef EXEC_ELF32 +int exec_elf32_makecmds(struct lwp *, struct exec_package *); +int elf32_copyargs(struct lwp *, struct exec_package *, + struct ps_strings *, char **, void *); + +int coredump_elf32(struct lwp *, void *); +int coredump_writenote_elf32(struct proc *, void *, Elf32_Nhdr *, + const char *, void *); + +int elf32_check_header(Elf32_Ehdr *, int); +#endif + +#ifdef EXEC_ELF64 +int exec_elf64_makecmds(struct lwp *, struct exec_package *); +int elf64_copyargs(struct lwp *, struct exec_package *, + struct ps_strings *, char **, void *); + +int coredump_elf64(struct lwp *, void *); +int coredump_writenote_elf64(struct proc *, void *, Elf64_Nhdr *, + const char *, void *); + +int elf64_check_header(Elf64_Ehdr *, int); +#endif + +#endif /* _KERNEL */ + +#endif /* !_SYS_EXEC_ELF_H_ */ diff --git a/libbsd/include/sys/featuretest.h b/libbsd/include/sys/featuretest.h new file mode 100644 index 0000000..d9085a8 --- /dev/null +++ b/libbsd/include/sys/featuretest.h @@ -0,0 +1,73 @@ +/* $NetBSD: featuretest.h,v 1.7 2003/12/04 12:42:54 keihan Exp $ */ + +/* + * Written by Klaus Klein <kleink@NetBSD.org>, February 2, 1998. + * Public domain. + * + * NOTE: Do not protect this header against multiple inclusion. Doing + * so can have subtle side-effects due to header file inclusion order + * and testing of e.g. _POSIX_SOURCE vs. _POSIX_C_SOURCE. Instead, + * protect each CPP macro that we want to supply. + */ + +/* + * Feature-test macros are defined by several standards, and allow an + * application to specify what symbols they want the system headers to + * expose, and hence what standard they want them to conform to. + * There are two classes of feature-test macros. The first class + * specify complete standards, and if one of these is defined, header + * files will try to conform to the relevant standard. They are: + * + * ANSI macros: + * _ANSI_SOURCE ANSI C89 + * + * POSIX macros: + * _POSIX_SOURCE == 1 IEEE Std 1003.1 (version?) + * _POSIX_C_SOURCE == 1 IEEE Std 1003.1-1990 + * _POSIX_C_SOURCE == 2 IEEE Std 1003.2-1992 + * _POSIX_C_SOURCE == 199309L IEEE Std 1003.1b-1993 + * _POSIX_C_SOURCE == 199506L ISO/IEC 9945-1:1996 + * _POSIX_C_SOURCE == 200112L IEEE Std 1003.1-2001 + * + * X/Open macros: + * _XOPEN_SOURCE System Interfaces and Headers, Issue 4, Ver 2 + * _XOPEN_SOURCE_EXTENDED == 1 XSH4.2 UNIX extensions + * _XOPEN_SOURCE == 500 System Interfaces and Headers, Issue 5 + * _XOPEN_SOURCE == 520 Networking Services (XNS), Issue 5.2 + * _XOPEN_SOURCE == 600 IEEE Std 1003.1-2001, XSI option + * + * NetBSD macros: + * _NETBSD_SOURCE == 1 Make all NetBSD features available. + * + * If more than one of these "major" feature-test macros is defined, + * then the set of facilities provided (and namespace used) is the + * union of that specified by the relevant standards, and in case of + * conflict, the earlier standard in the above list has precedence (so + * if both _POSIX_C_SOURCE and _NETBSD_SOURCE are defined, the version + * of rename() that's used is the POSIX one). If none of the "major" + * feature-test macros is defined, _NETBSD_SOURCE is assumed. + * + * There are also "minor" feature-test macros, which enable extra + * functionality in addition to some base standard. They should be + * defined along with one of the "major" macros. The "minor" macros + * are: + * + * _REENTRANT + * _ISOC99_SOURCE + * _LARGEFILE_SOURCE Large File Support + * <http://ftp.sas.com/standards/large.file/x_open.20Mar96.html> + */ + +#if defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 1L +#endif + +#if !defined(_ANSI_SOURCE) && !defined(_POSIX_C_SOURCE) && \ + !defined(_XOPEN_SOURCE) && !defined(_NETBSD_SOURCE) +#define _NETBSD_SOURCE 1 +#endif + +#if ((_POSIX_C_SOURCE - 0) >= 199506L || (_XOPEN_SOURCE - 0) >= 500) && \ + !defined(_REENTRANT) +#define _REENTRANT +#endif diff --git a/libbsd/include/sys/nb-queue.h b/libbsd/include/sys/nb-queue.h new file mode 100644 index 0000000..a4aef7b --- /dev/null +++ b/libbsd/include/sys/nb-queue.h @@ -0,0 +1,665 @@ +/* $NetBSD: queue.h,v 1.43 2005/10/02 15:34:42 chs Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef _SYS_QUEUE_H_ +#define _SYS_QUEUE_H_ + +/* + * This file defines five types of data structures: singly-linked lists, + * lists, simple queues, tail queues, and circular queues. + * + * A singly-linked list is headed by a single forward pointer. The + * elements are singly linked for minimum space and pointer manipulation + * overhead at the expense of O(n) removal for arbitrary elements. New + * elements can be added to the list after an existing element or at the + * head of the list. Elements being removed from the head of the list + * should use the explicit macro for this purpose for optimum + * efficiency. A singly-linked list may only be traversed in the forward + * direction. Singly-linked lists are ideal for applications with large + * datasets and few or no removals or for implementing a LIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A simple queue is headed by a pair of pointers, one the head of the + * list and the other to the tail of the list. The elements are singly + * linked to save space, so elements can only be removed from the + * head of the list. New elements can be added to the list after + * an existing element, at the head of the list, or at the end of the + * list. A simple queue may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * A circle queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or after + * an existing element, at the head of the list, or at the end of the list. + * A circle queue may be traversed in either direction, but has a more + * complex end of list detection. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +/* + * List definitions. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ +#if defined(_KERNEL) && defined(QUEUEDEBUG) +#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) \ + if ((head)->lh_first && \ + (head)->lh_first->field.le_prev != &(head)->lh_first) \ + panic("LIST_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__); +#define QUEUEDEBUG_LIST_OP(elm, field) \ + if ((elm)->field.le_next && \ + (elm)->field.le_next->field.le_prev != \ + &(elm)->field.le_next) \ + panic("LIST_* forw %p %s:%d", (elm), __FILE__, __LINE__);\ + if (*(elm)->field.le_prev != (elm)) \ + panic("LIST_* back %p %s:%d", (elm), __FILE__, __LINE__); +#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) \ + (elm)->field.le_next = (void *)1L; \ + (elm)->field.le_prev = (void *)1L; +#else +#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) +#define QUEUEDEBUG_LIST_OP(elm, field) +#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) +#endif + +#ifndef __rtems__ +#define LIST_INIT(head) do { \ + (head)->lh_first = NULL; \ +} while (/*CONSTCOND*/0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + QUEUEDEBUG_LIST_OP((listelm), field) \ + if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ + (listelm)->field.le_next->field.le_prev = \ + &(elm)->field.le_next; \ + (listelm)->field.le_next = (elm); \ + (elm)->field.le_prev = &(listelm)->field.le_next; \ +} while (/*CONSTCOND*/0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + QUEUEDEBUG_LIST_OP((listelm), field) \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + (elm)->field.le_next = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &(elm)->field.le_next; \ +} while (/*CONSTCOND*/0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field) \ + if (((elm)->field.le_next = (head)->lh_first) != NULL) \ + (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ + (head)->lh_first = (elm); \ + (elm)->field.le_prev = &(head)->lh_first; \ +} while (/*CONSTCOND*/0) + +#define LIST_REMOVE(elm, field) do { \ + QUEUEDEBUG_LIST_OP((elm), field) \ + if ((elm)->field.le_next != NULL) \ + (elm)->field.le_next->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = (elm)->field.le_next; \ + QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \ +} while (/*CONSTCOND*/0) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = ((head)->lh_first); \ + (var); \ + (var) = ((var)->field.le_next)) + +/* + * List access methods. + */ +#define LIST_EMPTY(head) ((head)->lh_first == NULL) +#define LIST_FIRST(head) ((head)->lh_first) +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + + +/* + * Singly-linked List definitions. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#define SLIST_INIT(head) do { \ + (head)->slh_first = NULL; \ +} while (/*CONSTCOND*/0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (/*CONSTCOND*/0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (/*CONSTCOND*/0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (/*CONSTCOND*/0) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = (head)->slh_first; \ + while(curelm->field.sle_next != (elm)) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = \ + curelm->field.sle_next->field.sle_next; \ + } \ +} while (/*CONSTCOND*/0) + +#define SLIST_FOREACH(var, head, field) \ + for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next) + +/* + * Singly-linked List access methods. + */ +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) +#define SLIST_FIRST(head) ((head)->slh_first) +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first; /* first element */ \ + struct type **stqh_last; /* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_INIT(head) do { \ + (head)->stqh_first = NULL; \ + (head)->stqh_last = &(head)->stqh_first; \ +} while (/*CONSTCOND*/0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \ + (head)->stqh_last = &(elm)->field.stqe_next; \ + (head)->stqh_first = (elm); \ +} while (/*CONSTCOND*/0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.stqe_next = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &(elm)->field.stqe_next; \ +} while (/*CONSTCOND*/0) + +#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\ + (head)->stqh_last = &(elm)->field.stqe_next; \ + (listelm)->field.stqe_next = (elm); \ +} while (/*CONSTCOND*/0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \ + (head)->stqh_last = &(head)->stqh_first; \ +} while (/*CONSTCOND*/0) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + if ((head)->stqh_first == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->stqh_first; \ + while (curelm->field.stqe_next != (elm)) \ + curelm = curelm->field.stqe_next; \ + if ((curelm->field.stqe_next = \ + curelm->field.stqe_next->field.stqe_next) == NULL) \ + (head)->stqh_last = &(curelm)->field.stqe_next; \ + } \ +} while (/*CONSTCOND*/0) + +#define STAILQ_FOREACH(var, head, field) \ + for ((var) = ((head)->stqh_first); \ + (var); \ + (var) = ((var)->field.stqe_next)) + +/* + * Singly-linked Tail queue access methods. + */ +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) +#define STAILQ_FIRST(head) ((head)->stqh_first) +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#endif + +/* + * Simple queue definitions. + */ +#define SIMPLEQ_HEAD(name, type) \ +struct name { \ + struct type *sqh_first; /* first element */ \ + struct type **sqh_last; /* addr of last next element */ \ +} + +#define SIMPLEQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).sqh_first } + +#define SIMPLEQ_ENTRY(type) \ +struct { \ + struct type *sqe_next; /* next element */ \ +} + +/* + * Simple queue functions. + */ +#define SIMPLEQ_INIT(head) do { \ + (head)->sqh_first = NULL; \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (/*CONSTCOND*/0) + +#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ + if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (head)->sqh_first = (elm); \ +} while (/*CONSTCOND*/0) + +#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.sqe_next = NULL; \ + *(head)->sqh_last = (elm); \ + (head)->sqh_last = &(elm)->field.sqe_next; \ +} while (/*CONSTCOND*/0) + +#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ + (head)->sqh_last = &(elm)->field.sqe_next; \ + (listelm)->field.sqe_next = (elm); \ +} while (/*CONSTCOND*/0) + +#define SIMPLEQ_REMOVE_HEAD(head, field) do { \ + if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ + (head)->sqh_last = &(head)->sqh_first; \ +} while (/*CONSTCOND*/0) + +#define SIMPLEQ_REMOVE(head, elm, type, field) do { \ + if ((head)->sqh_first == (elm)) { \ + SIMPLEQ_REMOVE_HEAD((head), field); \ + } else { \ + struct type *curelm = (head)->sqh_first; \ + while (curelm->field.sqe_next != (elm)) \ + curelm = curelm->field.sqe_next; \ + if ((curelm->field.sqe_next = \ + curelm->field.sqe_next->field.sqe_next) == NULL) \ + (head)->sqh_last = &(curelm)->field.sqe_next; \ + } \ +} while (/*CONSTCOND*/0) + +#define SIMPLEQ_FOREACH(var, head, field) \ + for ((var) = ((head)->sqh_first); \ + (var); \ + (var) = ((var)->field.sqe_next)) + +/* + * Simple queue access methods. + */ +#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL) +#define SIMPLEQ_FIRST(head) ((head)->sqh_first) +#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) + +#ifndef __rtems__ + +/* + * Tail queue definitions. + */ +#define _TAILQ_HEAD(name, type, qual) \ +struct name { \ + qual type *tqh_first; /* first element */ \ + qual type *qual *tqh_last; /* addr of last next element */ \ +} +#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,) + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define _TAILQ_ENTRY(type, qual) \ +struct { \ + qual type *tqe_next; /* next element */ \ + qual type *qual *tqe_prev; /* address of previous next element */\ +} +#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,) + +/* + * Tail queue functions. + */ +#if defined(_KERNEL) && defined(QUEUEDEBUG) +#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) \ + if ((head)->tqh_first && \ + (head)->tqh_first->field.tqe_prev != &(head)->tqh_first) \ + panic("TAILQ_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__); +#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) \ + if (*(head)->tqh_last != NULL) \ + panic("TAILQ_INSERT_TAIL %p %s:%d", (head), __FILE__, __LINE__); +#define QUEUEDEBUG_TAILQ_OP(elm, field) \ + if ((elm)->field.tqe_next && \ + (elm)->field.tqe_next->field.tqe_prev != \ + &(elm)->field.tqe_next) \ + panic("TAILQ_* forw %p %s:%d", (elm), __FILE__, __LINE__);\ + if (*(elm)->field.tqe_prev != (elm)) \ + panic("TAILQ_* back %p %s:%d", (elm), __FILE__, __LINE__); +#define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) \ + if ((elm)->field.tqe_next == NULL && \ + (head)->tqh_last != &(elm)->field.tqe_next) \ + panic("TAILQ_PREREMOVE head %p elm %p %s:%d", \ + (head), (elm), __FILE__, __LINE__); +#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) \ + (elm)->field.tqe_next = (void *)1L; \ + (elm)->field.tqe_prev = (void *)1L; +#else +#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) +#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) +#define QUEUEDEBUG_TAILQ_OP(elm, field) +#define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) +#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) +#endif + +#define TAILQ_INIT(head) do { \ + (head)->tqh_first = NULL; \ + (head)->tqh_last = &(head)->tqh_first; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field) \ + if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ + (head)->tqh_first->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (head)->tqh_first = (elm); \ + (elm)->field.tqe_prev = &(head)->tqh_first; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field) \ + (elm)->field.tqe_next = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &(elm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QUEUEDEBUG_TAILQ_OP((listelm), field) \ + if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ + (elm)->field.tqe_next->field.tqe_prev = \ + &(elm)->field.tqe_next; \ + else \ + (head)->tqh_last = &(elm)->field.tqe_next; \ + (listelm)->field.tqe_next = (elm); \ + (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + QUEUEDEBUG_TAILQ_OP((listelm), field) \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + (elm)->field.tqe_next = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ +} while (/*CONSTCOND*/0) + +#define TAILQ_REMOVE(head, elm, field) do { \ + QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field) \ + QUEUEDEBUG_TAILQ_OP((elm), field) \ + if (((elm)->field.tqe_next) != NULL) \ + (elm)->field.tqe_next->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ + QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \ +} while (/*CONSTCOND*/0) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = ((head)->tqh_first); \ + (var); \ + (var) = ((var)->field.tqe_next)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \ + (var); \ + (var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) + +/* + * Tail queue access methods. + */ +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) +#define TAILQ_FIRST(head) ((head)->tqh_first) +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + + +/* + * Circular queue definitions. + */ +#if defined(_KERNEL) && defined(QUEUEDEBUG) +#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field) \ + if ((head)->cqh_first != (void *)(head) && \ + (head)->cqh_first->field.cqe_prev != (void *)(head)) \ + panic("CIRCLEQ head forw %p %s:%d", (head), \ + __FILE__, __LINE__); \ + if ((head)->cqh_last != (void *)(head) && \ + (head)->cqh_last->field.cqe_next != (void *)(head)) \ + panic("CIRCLEQ head back %p %s:%d", (head), \ + __FILE__, __LINE__); +#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field) \ + if ((elm)->field.cqe_next == (void *)(head)) { \ + if ((head)->cqh_last != (elm)) \ + panic("CIRCLEQ elm last %p %s:%d", (elm), \ + __FILE__, __LINE__); \ + } else { \ + if ((elm)->field.cqe_next->field.cqe_prev != (elm)) \ + panic("CIRCLEQ elm forw %p %s:%d", (elm), \ + __FILE__, __LINE__); \ + } \ + if ((elm)->field.cqe_prev == (void *)(head)) { \ + if ((head)->cqh_first != (elm)) \ + panic("CIRCLEQ elm first %p %s:%d", (elm), \ + __FILE__, __LINE__); \ + } else { \ + if ((elm)->field.cqe_prev->field.cqe_next != (elm)) \ + panic("CIRCLEQ elm prev %p %s:%d", (elm), \ + __FILE__, __LINE__); \ + } +#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field) \ + (elm)->field.cqe_next = (void *)1L; \ + (elm)->field.cqe_prev = (void *)1L; +#else +#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field) +#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field) +#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field) +#endif + +#define CIRCLEQ_HEAD(name, type) \ +struct name { \ + struct type *cqh_first; /* first element */ \ + struct type *cqh_last; /* last element */ \ +} + +#define CIRCLEQ_HEAD_INITIALIZER(head) \ + { (void *)&head, (void *)&head } + +#define CIRCLEQ_ENTRY(type) \ +struct { \ + struct type *cqe_next; /* next element */ \ + struct type *cqe_prev; /* previous element */ \ +} + +/* + * Circular queue functions. + */ +#define CIRCLEQ_INIT(head) do { \ + (head)->cqh_first = (void *)(head); \ + (head)->cqh_last = (void *)(head); \ +} while (/*CONSTCOND*/0) + +#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ + QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \ + (elm)->field.cqe_next = (listelm)->field.cqe_next; \ + (elm)->field.cqe_prev = (listelm); \ + if ((listelm)->field.cqe_next == (void *)(head)) \ + (head)->cqh_last = (elm); \ + else \ + (listelm)->field.cqe_next->field.cqe_prev = (elm); \ + (listelm)->field.cqe_next = (elm); \ +} while (/*CONSTCOND*/0) + +#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ + QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ + QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \ + (elm)->field.cqe_next = (listelm); \ + (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ + if ((listelm)->field.cqe_prev == (void *)(head)) \ + (head)->cqh_first = (elm); \ + else \ + (listelm)->field.cqe_prev->field.cqe_next = (elm); \ + (listelm)->field.cqe_prev = (elm); \ +} while (/*CONSTCOND*/0) + +#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ + QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ + (elm)->field.cqe_next = (head)->cqh_first; \ + (elm)->field.cqe_prev = (void *)(head); \ + if ((head)->cqh_last == (void *)(head)) \ + (head)->cqh_last = (elm); \ + else \ + (head)->cqh_first->field.cqe_prev = (elm); \ + (head)->cqh_first = (elm); \ +} while (/*CONSTCOND*/0) + +#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ + QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ + (elm)->field.cqe_next = (void *)(head); \ + (elm)->field.cqe_prev = (head)->cqh_last; \ + if ((head)->cqh_first == (void *)(head)) \ + (head)->cqh_first = (elm); \ + else \ + (head)->cqh_last->field.cqe_next = (elm); \ + (head)->cqh_last = (elm); \ +} while (/*CONSTCOND*/0) + +#define CIRCLEQ_REMOVE(head, elm, field) do { \ + QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \ + QUEUEDEBUG_CIRCLEQ_ELM((head), (elm), field) \ + if ((elm)->field.cqe_next == (void *)(head)) \ + (head)->cqh_last = (elm)->field.cqe_prev; \ + else \ + (elm)->field.cqe_next->field.cqe_prev = \ + (elm)->field.cqe_prev; \ + if ((elm)->field.cqe_prev == (void *)(head)) \ + (head)->cqh_first = (elm)->field.cqe_next; \ + else \ + (elm)->field.cqe_prev->field.cqe_next = \ + (elm)->field.cqe_next; \ + QUEUEDEBUG_CIRCLEQ_POSTREMOVE((elm), field) \ +} while (/*CONSTCOND*/0) + +#define CIRCLEQ_FOREACH(var, head, field) \ + for ((var) = ((head)->cqh_first); \ + (var) != (void *)(head); \ + (var) = ((var)->field.cqe_next)) + +#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ + for ((var) = ((head)->cqh_last); \ + (var) != (void *)(head); \ + (var) = ((var)->field.cqe_prev)) + +/* + * Circular queue access methods. + */ +#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) +#define CIRCLEQ_FIRST(head) ((head)->cqh_first) +#define CIRCLEQ_LAST(head) ((head)->cqh_last) +#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) +#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) + +#endif +#endif /* !_SYS_QUEUE_H_ */ @@ -0,0 +1,463 @@ +/* + * $Id$ + * + * RTEMS Project (http://www.rtems.org/) + * + * Copyright 2010 Chris Johns (chrisj@rtems.org) + */ + +/** + * Run Time Linker test program. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <setjmp.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <termios.h> + +#include <dlfcn.h> + +#include <rtems.h> +#include <rtems/bdbuf.h> +#include <rtems/blkdev.h> +#include <rtems/diskdevs.h> +#include <rtems/error.h> +#include <rtems/fsmount.h> +#include <rtems/ramdisk.h> +#include <rtems/shell.h> +#include <rtems/untar.h> + +#if RTEMS_APP_FLASHDISK +#include <rtems/flashdisk.h> +#include <libchip/am29lv160.h> +#endif + +#if RTEMS_APP_IDEDISK +#include <libchip/ide_ctrl.h> +#include <libchip/ata.h> +#endif + +#if pc586 +#include "pc386-gdb.h" +int remote_debug; +#endif + +#include <rtl-shell.h> +#include <rtl-trace.h> + +/* + * The tarfile is built automatically externally so we need to account + * for the leading symbol on the names. + */ +#if defined(__sh__) + #define SYM(_x) _x +#else + #define SYM(_x) _ ## _x +#endif + +/** + * The shell-init tarfile parameters. + */ +extern int SYM(binary_fs_root_tar_start); +extern int SYM(binary_fs_root_tar_size); + +#define TARFILE_START SYM(binary_fs_root_tar_start) +#define TARFILE_SIZE SYM(binary_fs_root_tar_size) + +/** + * The RAM Disk configuration. + */ +rtems_ramdisk_config rtems_ramdisk_configuration[] = +{ + { + block_size: 512, + block_num: 3 * 1024 * 2, + location: NULL + } +}; + +/** + * The number of RAM Disk configurations. + */ +size_t rtems_ramdisk_configuration_size = 1; + +/** + * Create the RAM Disk Driver entry. + */ +rtems_driver_address_table rtems_ramdisk_io_ops = { + initialization_entry: ramdisk_initialize, + open_entry: rtems_blkdev_generic_open, + close_entry: rtems_blkdev_generic_close, + read_entry: rtems_blkdev_generic_read, + write_entry: rtems_blkdev_generic_write, + control_entry: rtems_blkdev_generic_ioctl +}; + +#if RTEMS_APP_FLASHDISK +/** + * The Flash Device Driver configuration. + */ +const rtems_am29lv160_config rtems_am29lv160_configuration[] = +{ + { + bus_8bit: 0, + base: (void*) 0xFFE00000 + } +}; + +/** + * The number of AM29LV160 configurations. + */ +uint32_t rtems_am29lv160_configuration_size = 1; + +/** + * The Flash Segment descriptor. The mcf5235 board uses the + * bottom part of the flash for the dBug monitor. + */ +const rtems_fdisk_segment_desc rtems_mcf5235_segment_descriptor[] = +{ + { + count: 26, + segment: 0, + offset: 0x00050000, + size: RTEMS_FDISK_KBYTES (64) + } +}; + +/** + * The Flash Device descriptor. + */ +const rtems_fdisk_device_desc rtems_mcf5235_device_descriptor[] = +{ + { + segment_count: 1, + segments: &rtems_mcf5235_segment_descriptor[0], + flash_ops: &rtems_am29lv160_handlers + } +}; + +/** + * The Flash Disk configuration. + */ +const rtems_flashdisk_config rtems_flashdisk_configuration[] = +{ + { + block_size: 512, + device_count: 1, + devices: &rtems_mcf5235_device_descriptor[0], + flags: RTEMS_FDISK_BLANK_CHECK_BEFORE_WRITE, + unavail_blocks: 256, + compact_segs: 100, + avail_compact_segs: 100, + info_level: 0 + } +}; + +/** + * The number of Flash Disk configurations. + */ +size_t rtems_flashdisk_configuration_size = 1; + +/** + * Create the Flash Disk Driver entry. + */ +rtems_driver_address_table rtems_flashdisk_io_ops = { + initialization_entry: rtems_fdisk_initialize, + open_entry: rtems_blkdev_generic_open, + close_entry: rtems_blkdev_generic_close, + read_entry: rtems_blkdev_generic_read, + write_entry: rtems_blkdev_generic_write, + control_entry: rtems_blkdev_generic_ioctl +}; +#endif + +#if RTEMS_APP_IDEDISK +/** + * Create the IDE Disk Driver entry. + */ +rtems_driver_address_table rtems_idedisk_io_ops = { + initialization_entry: rtems_ata_initialize, + open_entry: rtems_blkdev_generic_open, + close_entry: rtems_blkdev_generic_close, + read_entry: rtems_blkdev_generic_read, + write_entry: rtems_blkdev_generic_write, + control_entry: rtems_blkdev_generic_ioctl +}; +#endif + +/** + * Let the IO system allocation the next available major number. + */ +#define RTEMS_DRIVER_AUTO_MAJOR (0) + +/** + * Start the RTEMS Shell. + */ +void +shell_start (void) +{ + rtems_status_code sc; + printf ("Starting shell....\n\n"); + sc = rtems_shell_init ("fstst", 60 * 1024, 150, "/dev/console", 0, 1, NULL); + if (sc != RTEMS_SUCCESSFUL) + printf ("error: starting shell: %s (%d)\n", rtems_status_text (sc), sc); +} + +/** + * Run the /shell-init script. + */ +void +shell_init_script (void) +{ + rtems_status_code sc; + printf ("Running /shell-init....\n\n"); + sc = rtems_shell_script ("fstst", 60 * 1024, 160, "/shell-init", "stdout", + 0, 1, 1); + if (sc != RTEMS_SUCCESSFUL) + printf ("error: running shell script: %s (%d)\n", rtems_status_text (sc), sc); +} + +int +setup_ramdisk (void) +{ + rtems_device_major_number major; + rtems_status_code sc; + + /* + * Register the RAM Disk driver. + */ + printf ("Register RAM Disk Driver: "); + sc = rtems_io_register_driver (RTEMS_DRIVER_AUTO_MAJOR, + &rtems_ramdisk_io_ops, + &major); + if (sc != RTEMS_SUCCESSFUL) + { + printf ("error: ramdisk driver not initialised: %s\n", + rtems_status_text (sc)); + return 1; + } + + printf ("successful\n"); + + return 0; +} + +int +setup_flashdisk (void) +{ +#if RTEMS_APP_FLASHDISK + rtems_device_major_number major; + rtems_status_code sc; + + /* + * Register the Flash Disk driver. + */ + printf ("Register Flash Disk Driver: "); + sc = rtems_io_register_driver (RTEMS_DRIVER_AUTO_MAJOR, + &rtems_flashdisk_io_ops, + &major); + if (sc != RTEMS_SUCCESSFUL) + { + printf ("error: flashdisk driver not initialised: %s\n", + rtems_status_text (sc)); + return 1; + } + + printf ("successful\n"); +#endif + return 0; +} + +#if RTEMS_APP_IDEDISK +extern rtems_status_code rtems_ide_part_table_initialize (const char* ); +#endif + +int +setup_idedisk (const char* path) +{ +#if RTEMS_APP_IDEDISK + rtems_status_code sc; + + /* + * Register the IDE Disk driver. + */ + printf ("Read IDE Disk Partition Table: "); + sc = rtems_ide_part_table_initialize (path); + if (sc != RTEMS_SUCCESSFUL) + printf ("error: ide partition table not found: %s\n", + rtems_status_text (sc)); + else + printf ("successful\n"); + +#endif + return 0; +} + +int +setup_rootfs (void) +{ + rtems_status_code sc; + + printf("Loading filesystem: "); + + sc = Untar_FromMemory((void *)(&TARFILE_START), (size_t)&TARFILE_SIZE); + + if (sc != RTEMS_SUCCESSFUL) + { + printf ("error: untar failed: %s\n", rtems_status_text (sc)); + return 1; + } + + printf ("successful\n"); + + return 0; +} + +int +shell_flash_erase (int argc, char* argv[]) +{ +#if RTEMS_APP_FLASHDISK + const char* driver = NULL; + int arg; + int fd; + + for (arg = 1; arg < argc; arg++) + { + if (argv[arg][0] == '-') + { + printf ("error: invalid option: %s\n", argv[arg]); + return 1; + } + else + { + if (!driver) + driver = argv[arg]; + else + { + printf ("error: only one driver name allowed: %s\n", argv[arg]); + return 1; + } + } + } + + printf ("erase flash disk: %s\n", driver); + + fd = open (driver, O_WRONLY, 0); + if (fd < 0) + { + printf ("error: flash driver open failed: %s\n", strerror (errno)); + return 1; + } + + if (ioctl (fd, RTEMS_FDISK_IOCTL_ERASE_DISK) < 0) + { + printf ("error: flash driver erase failed: %s\n", strerror (errno)); + return 1; + } + + close (fd); + + printf ("flash disk erased successful\n"); +#endif + return 0; +} + +int shell_dlopen (int argc, char* argv[]); +int shell_dlclose (int argc, char* argv[]); +int shell_dlsym (int argc, char* argv[]); +int shell_dlcall (int argc, char* argv[]); + +int +main (int argc, char* argv[]) +{ + struct termios term; + int ret; + +#if pc586 + int arg; + for (arg = 1; arg < argc; arg++) + if (strcmp (argv[arg], "--gdb") == 0) + pc386_gdb_init (); +#endif + + if (tcgetattr(fileno(stdout), &term) < 0) + printf ("error: cannot get terminal attributes: %s\n", strerror (errno)); + cfsetispeed (&term, B115200); + cfsetospeed (&term, B115200); + if (tcsetattr (fileno(stdout), TCSADRAIN, &term) < 0) + printf ("error: cannot set terminal attributes: %s\n", strerror (errno)); + + if (tcgetattr(fileno(stdin), &term) < 0) + printf ("error: cannot get terminal attributes: %s\n", strerror (errno)); + cfsetispeed (&term, B115200); + cfsetospeed (&term, B115200); + if (tcsetattr (fileno(stdin), TCSADRAIN, &term) < 0) + printf ("error: cannot set terminal attributes: %s\n", strerror (errno)); + + printf ("\nRTEMS Run Time Link Editor Test, Version " \ + PACKAGE_VERSION "\n\n"); + + ret = setup_ramdisk (); + if (ret) + exit (ret); + + ret = setup_flashdisk (); + if (ret) + exit (ret); + + ret = setup_idedisk ("/dev/hda"); + if (ret) + exit (ret); + + ret = setup_idedisk ("/dev/hdb"); + if (ret) + exit (ret); + + ret = setup_rootfs (); + if (ret) + exit (ret); + +#if RTEMS_RTL_TRACE + rtems_shell_add_cmd ("rtl-trace", "misc", + "RLT trace", + rtems_rtl_trace_shell_command); +#endif + + rtems_shell_add_cmd ("fderase", "misc", + "fderase driver", shell_flash_erase); + rtems_shell_add_cmd ("rtl", "misc", + "Runtime Linker", rtems_rtl_shell_command); + rtems_shell_add_cmd ("dlo", "misc", + "load object file", shell_dlopen); + rtems_shell_add_cmd ("dlc", "misc", + "unload object file", shell_dlclose); + rtems_shell_add_cmd ("dls", "misc", + "symbol search file", shell_dlsym); + rtems_shell_add_cmd ("dlx", "misc", + "execute a call to the symbol", shell_dlcall); + + shell_init_script (); + + while (true) + shell_start (); + + rtems_task_delete (RTEMS_SELF); + + return 0; +} + +#if pc586 +void +rtems_fatal_error_occurred (uint32_t code) +{ + printf ("fatal error: %08lx\n", code); + for (;;); +} +#endif diff --git a/mcf5235-gdbinit-script b/mcf5235-gdbinit-script new file mode 100644 index 0000000..f7eca8c --- /dev/null +++ b/mcf5235-gdbinit-script @@ -0,0 +1,58 @@ +# +# Connect to the target. +# +target remote | m68k-bdm-gdbserver pipe 253-005 +#target remote | m68k-bdm-gdbserver pipe /dev/tblcf1 +#target remote :7777 +#target remote me:7777 +#target remote lapdog:7777 + +# +# The console loop in the Axman dbug monitor. Found by trial and error +# with the debugger. +# +thb *0xffe254c0 + +# +# Show the exception stack frame. +# +define show-exception-sframe + set $frsr = *(unsigned short *)((unsigned long)$sp + 2) + set $frpc = *(unsigned long *)((unsigned long)$sp + 4) + set $frfvo = *(unsigned short *)((unsigned long)$sp + 0) + set $frcode = $frfvo >> 12 + set $frvect = ($frfvo & 0xFFF) >> 2 + set $frstatus = ((($frfvo >> 10) & 3) << 2) | ($frfvo & 3) + printf "EXCEPTION -- SR:0x%X PC:0x%X FRAME:0x%x VECTOR:%d STATUS:%d\n", $frsr, $frpc, $frcode, $frvect, $frstatus + if $frstatus == 4 + printf " Fault Type: Error on instruction fetch" + end + if $frstatus == 8 + printf " Fault Type: Error on operand write" + end + if $frstatus == 12 + printf " Fault Type: Error on operand read" + end + if $frstatus == 9 + printf " Fault Type: Attempted write to write-protected space" + end +end + +# +# Run to initialise the RAM. The target will stop when the +# breakpoint is hit. Load the program. +# +c +load + +# +# Break on an exception. +# +b _uhoh +b rtems_fatal_error_occurred + +# +# Travel to main then stop. +# +tb main +c diff --git a/mksyms.awk b/mksyms.awk new file mode 100644 index 0000000..ce41567 --- /dev/null +++ b/mksyms.awk @@ -0,0 +1,115 @@ +# +# COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> +# +# The license and distribution terms for this file may be +# found in the file LICENSE in this distribution or at +# http://www.rtems.com/license/LICENSE. +# +# $Id$ +# +# Covert the list of symbols into a C structure. +# +# + +function c_header() +{ + print ("/*"); + print (" * RTEMS Global Symbol Table"); + print (" * Automatically generated. Do not edit, just regenerate."); + print (" */"); + print (""); + print ("extern unsigned char __rtems_rtl_base_globals[];"); + print ("extern unsigned int __rtems_rtl_base_globals_size;"); + print (""); + print ("asm(\" .align 4\");"); + print ("asm(\"__rtems_rtl_base_globals:\");"); +} + +function c_trailer() +{ + print ("asm(\" .byte 0\");"); + print ("asm(\" .align 0\");"); + print ("asm(\" .ascii \\\"\\xde\\xad\\xbe\\xef\\\"\");"); + print ("asm(\" .align 4\");"); + print ("asm(\"__rtems_rtl_base_globals_size:\");"); + print ("asm(\" .long __rtems_rtl_base_globals_size - __rtems_rtl_base_globals\");"); + print (""); + print ("void rtems_rtl_base_sym_global_add (const unsigned char* , unsigned int );"); +} + +function c_rtl_call_body() +{ + print ("{"); + print (" rtems_rtl_base_sym_global_add (__rtems_rtl_base_globals,"); + print (" __rtems_rtl_base_globals_size);"); + print ("}"); +} + +function c_constructor_trailer() +{ + c_trailer(); + print ("static void init(void) __attribute__ ((constructor));"); + print ("static void init(void)"); + c_rtl_call_body(); +} + +function c_embedded_trailer() +{ + c_trailer(); + print ("void rtems_rtl_base_global_syms_init(void)"); + c_rtl_call_body(); +} + +BEGIN { + FS = "[ \t\n]"; + OFS = " "; + embed = 0 + for (a = 0; a < ARGC; ++a) + { + if (ARGV[a] == "--embed") + { + embed = 1 + delete ARGV[a]; + } + } + c_header(); + syms = 0 +} +END { + for (s = 0; s < syms; ++s) + { + printf ("asm(\" .asciz \\\"%s\\\"\");\n", symbols[s]); + if (embed) + { + printf ("asm(\" .align 0\");\n"); + printf ("asm(\" .long %s\");\n", symbols[s]); + } + else + printf ("asm(\" .long 0x%s\");\n", addresses[s]); + } + if (embed) + c_embedded_trailer(); + else + c_constructor_trailer(); +} + +# +# Parse the output of 'nm' +# + +{ + # + # We need 3 fields + # + if (NF == 3) + { + if (($3 != "__DTOR_END__") || + ($3 != "__CTOR_END__") || + ($3 != "__DYNAMIC")) + { + symbols[syms] = $3; + addresses[syms] = $1; + ++syms; + } + } +} diff --git a/mmap-internal.h b/mmap-internal.h new file mode 100644 index 0000000..ec36e3a --- /dev/null +++ b/mmap-internal.h @@ -0,0 +1,37 @@ +/* + * mmap() - POSIX 1003.1b 6.3.1 - map pages of memory + * + * COPYRIGHT (c) 2010. + * Chris Johns (chrisj@rtems.org) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#ifndef MMAP_INTERNAL_H + +#include <stdint.h> + +#include <rtems.h> +#include <rtems/chain.h> + +/** + * Every mmap'ed region has a mapping. + */ +typedef struct mmap_mappings_s { + rtems_chain_node node; /**< The mapping chain's node */ + void* addr; /**< The address of the mapped memory */ + size_t len; /**< The length of memory mapped */ + int flags; /**< The mapping flags */ +} mmap_mapping; + +extern rtems_chain_control mmap_mappings; + +bool mmap_mappings_lock_obtain( void ); +bool mmap_mappings_lock_release( void ); + + +#endif @@ -0,0 +1,235 @@ +/* + * mmap() - POSIX 1003.1b 6.3.1 - map pages of memory + * + * COPYRIGHT (c) 2010. + * Chris Johns (chrisj@rtems.org) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems.h> +#include <errno.h> +#include <stdlib.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "rtems/libio_.h" + +#include "mmap-internal.h" + +#define RTEMS_MUTEX_ATTRIBS \ + (RTEMS_PRIORITY | RTEMS_SIMPLE_BINARY_SEMAPHORE | \ + RTEMS_NO_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL) + +/** + * Mmap chain of mappings. + */ +rtems_chain_control mmap_mappings; + +/** + * The id of the MMAP lock. + */ +static rtems_id mmap_mappings_lock; + +/** + * Create the lock. + */ +static +bool mmap_mappings_lock_create( + void +) +{ + /* + * Lock the mapping table. We only create a lock if a call is made. First we + * test if a mapping lock is present. If one is present we lock it. If not + * the libio lock is locked and we then test the mapping lock again. If not + * present we create the mapping lock then release libio lock. + */ + if ( mmap_mappings_lock == 0 ) { + rtems_status_code sc = RTEMS_SUCCESSFUL; + rtems_chain_initialize_empty( &mmap_mappings ); + rtems_semaphore_obtain( rtems_libio_semaphore, + RTEMS_WAIT, RTEMS_NO_TIMEOUT ); + if ( mmap_mappings_lock == 0 ) + sc = rtems_semaphore_create( rtems_build_name( 'M', 'M', 'A', 'P' ), + 1, + RTEMS_MUTEX_ATTRIBS, + RTEMS_NO_PRIORITY, + &mmap_mappings_lock ); + rtems_semaphore_release( rtems_libio_semaphore ); + if ( sc != RTEMS_SUCCESSFUL ) { + errno = EINVAL; + return false; + } + } + return true; +} + +bool mmap_mappings_lock_obtain( + void +) +{ + if ( mmap_mappings_lock_create( ) ) { + rtems_status_code sc; + sc = rtems_semaphore_obtain( mmap_mappings_lock, + RTEMS_WAIT, RTEMS_NO_TIMEOUT ); + if ( sc != RTEMS_SUCCESSFUL ) { + errno = EINVAL; + return false; + } + } + return true; +} + +bool mmap_mappings_lock_release( + void +) +{ + rtems_status_code sc; + sc = rtems_semaphore_release( mmap_mappings_lock ); + if (( sc != RTEMS_SUCCESSFUL ) && ( errno == 0 )) { + errno = EINVAL; + return false; + } + return true; +} + +void *mmap( + void *addr, size_t len, int prot, int flags, int fildes, off_t off +) +{ + struct stat sb; + mmap_mapping* mapping; + ssize_t r; + + /* + * Clear errno. + */ + errno = 0; + + /* + * Get a stat of the file to get the dev + inode number and to make sure the + * fd is ok. The normal libio calls cannot be used because we need to return + * MAP_FAILED on error and they return -1 directly without coming back to + * here. + */ + if ( fstat( fildes, &sb ) < 0 ) { + errno = EBADF; + return MAP_FAILED; + } + + if ( len == 0 ) { + errno = EINVAL; + return MAP_FAILED; + } + + /* + * Check the type of file we have and make sure it is supported. + */ + if ( S_ISDIR( sb.st_mode ) || S_ISLNK( sb.st_mode )) { + errno = ENODEV; + return MAP_FAILED; + } + + /* + * We can provide read, write and execute because the memory in RTEMS does + * not normally have protections but we cannot hide access to memory. + */ + if ( prot == PROT_NONE ) { + errno = EINVAL; + return MAP_FAILED; + } + + /* + * Check to see if the mapping is valid for the file. + */ + if ( S_ISREG( sb.st_mode ) + && (( off >= sb.st_size ) || (( off + len ) >= sb.st_size ))) { + errno = EOVERFLOW; + return MAP_FAILED; + } + + /* + * Obtain the mmap lock. Sets errno on failure. + */ + if ( !mmap_mappings_lock_obtain( ) ) + return MAP_FAILED; + + if (( flags & MAP_FIXED ) == MAP_FIXED ) { + rtems_chain_node* node = rtems_chain_first (&mmap_mappings); + while ( !rtems_chain_is_tail( &mmap_mappings, node )) { + /* + * If the map is fixed see if this address is already mapped. At this + * point in time if there is an overlap in the mappings we return an + * error. + */ + mapping = (mmap_mapping*) node; + if ( ( addr >= mapping->addr ) && + ( addr < ( mapping->addr + mapping->len )) ) { + mmap_mappings_lock_release( ); + errno = ENXIO; + return MAP_FAILED; + } + node = rtems_chain_next( node ); + } + } + + mapping = malloc( sizeof( mmap_mapping )); + if ( !mapping ) { + mmap_mappings_lock_release( ); + errno = ENOMEM; + return NULL; + } + + memset( mapping, 0, sizeof( mmap_mapping )); + + mapping->len = len; + mapping->flags = flags; + + if (( flags & MAP_FIXED ) != MAP_FIXED ) { + mapping->addr = malloc( len ); + if ( !mapping->addr ) { + mmap_mappings_lock_release( ); + free( mapping ); + errno = ENOMEM; + return MAP_FAILED; + } + + /* + * Do not seek on character devices, pipes or sockets. + */ + if ( S_ISREG( sb.st_mode ) || S_ISBLK( sb.st_mode ) ) { + if ( lseek( fildes, off, SEEK_SET ) < 0 ) { + mmap_mappings_lock_release( ); + free( mapping->addr ); + free( mapping ); + return MAP_FAILED; + } + } + } + + r = read( fildes, mapping->addr, len ); + + if ( r != len ) { + mmap_mappings_lock_release( ); + free( mapping->addr ); + free( mapping ); + errno = ENXIO; + return MAP_FAILED; + } + + rtems_chain_append( &mmap_mappings, &mapping->node ); + + mmap_mappings_lock_release( ); + + return mapping->addr; +} diff --git a/munmap.c b/munmap.c new file mode 100644 index 0000000..0dfe6a9 --- /dev/null +++ b/munmap.c @@ -0,0 +1,73 @@ +/* + * mmap() - POSIX 1003.1b 6.3.1 - map pages of memory + * + * COPYRIGHT (c) 2010. + * Chris Johns (chrisj@rtems.org) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtems.h> +#include <errno.h> +#include <stdlib.h> +#include <sys/mman.h> + +#include "mmap-internal.h" + +int munmap( + void *addr, size_t len +) +{ + mmap_mapping* mapping; + rtems_chain_node* node; + + /* + * Clear errno. + */ + errno = 0; + + /* + * Length cannot be 0. + */ + if ( len == 0 ) { + errno = EINVAL; + return -1; + } + + /* + * Obtain the mmap lock. Sets errno on failure. + */ + if ( !mmap_mappings_lock_obtain( )) + return -1; + + node = rtems_chain_first (&mmap_mappings); + while ( !rtems_chain_is_tail( &mmap_mappings, node )) { + /* + * If the map is fixed see if this address is already mapped. At this + * point in time if there is an overlap in the mappings we return an + * error. + */ + mapping = (mmap_mapping*) node; + if ( ( addr >= mapping->addr ) && + ( addr < ( mapping->addr + mapping->len )) ) { + rtems_chain_extract( node ); + if (( mapping->flags & MAP_FIXED ) != MAP_FIXED ) { + free( mapping->addr ); + free( mapping ); + } + break; + } + node = rtems_chain_next( node ); + } + + mmap_mappings_lock_release( ); + return 0; +} diff --git a/networkconfig.h b/networkconfig.h new file mode 100644 index 0000000..20368b4 --- /dev/null +++ b/networkconfig.h @@ -0,0 +1,162 @@ +/* + * Network configuration EXAMPLE!!! + * + ************************************************************ + * EDIT THIS FILE TO REFLECT YOUR NETWORK CONFIGURATION * + * BEFORE RUNNING ANY RTEMS PROGRAMS WHICH USE THE NETWORK! * + ************************************************************ + * + * $Id: networkconfig.h,v 1.9 2007/07/18 19:35:18 joel Exp $ + */ + +#ifndef _CONFIGURE_NETWORKCONFIG_H_ +#define _CONFIGURE_NETWORKCONFIG_H_ + +/* + * The following will normally be set by the BSP if it supports + * a single network device driver. In the event, it supports + * multiple network device drivers, then the user's default + * network device driver will have to be selected by a BSP + * specific mechanism. + */ + +#if !defined(CONFIGURE_NETWORK_DRIVER_NAME) +#warning "CONFIGURE_NETWORK_DRIVER_NAME is not defined" +#define CONFIGURE_NETWORK_DRIVER_NAME "no_network1" +#endif + +#if !defined(CONFIGURE_NETWORK_DRIVER_ATTACH) +#warning "CONFIGURE_NETWORK_DRIVER_ATTACH is not defined" +#define CONFIGURE_NETWORK_DRIVER_ATTACH 0 +#endif + +#if !defined(CONFIGURE_NETWORK_HOSTNAME) +#define CONFIGURE_NETWORK_HOSTNAME "rtemstst" +#endif + +#if !defined(CONFIGURE_NETWORK_DOMAINNAME) +#define CONFIGURE_NETWORK_DOMAINNAME "nodomain.com" +#endif + +#if !defined(CONFIGURE_NETWORK_IPADDR) +#define CONFIGURE_NETWORK_IPADDR "10.10.10.10" +#endif + +#if !defined(CONFIGURE_NETWORK_NETMASK) +#define CONFIGURE_NETWORK_NETMASK "255.255.255.0" +#endif + +#if !defined(CONFIGURE_NETWORK_GATEWAY) +#define CONFIGURE_NETWORK_GATEWAY "10.10.10.1" +#endif + +#if !defined(CONFIGURE_NETWORK_LOGHOST) +#define CONFIGURE_NETWORK_LOGHOST CONFIGURE_NETWORK_GATEWAY +#endif + +#if !defined(CONFIGURE_NETWORK_DNS) +#define CONFIGURE_NETWORK_DNS CONFIGURE_NETWORK_GATEWAY +#endif + +#if !defined(CONFIGURE_NETWORK_NTP) +#define CONFIGURE_NETWORK_NTP CONFIGURE_NETWORK_GATEWAY +#endif + +#include <bsp.h> + +/* + * Define RTEMS_SET_ETHERNET_ADDRESS if you want to specify the + * Ethernet address here. If RTEMS_SET_ETHERNET_ADDRESS is not + * defined the driver will choose an address. + */ +#if defined(CONFIGURE_ETHERNET_ADDRESS) +static char ethernet_address[6] = { CONFIGURE_ETHERNET_ADDRESS }; +#endif + +#ifdef CONFIGURE_NETWORK_LOOPBACK +/* + * Loopback interface + */ +extern void rtems_bsdnet_loopattach(); +static struct rtems_bsdnet_ifconfig loopback_config = { + "lo0", /* name */ + rtems_bsdnet_loopattach, /* attach function */ + NULL, /* link to next interface */ + "127.0.0.1", /* IP address */ + "255.0.0.0", /* IP net mask */ +}; +#endif + +/* + * Default network interface + */ +static struct rtems_bsdnet_ifconfig netdriver_config = { + CONFIGURE_NETWORK_DRIVER_NAME, /* name */ + CONFIGURE_NETWORK_DRIVER_ATTACH, /* attach function */ +#ifdef CONFIGURE_NETWORK_LOOPBACK + &loopback_config, /* link to next interface */ +#else + NULL, /* No more interfaces */ +#endif + +#if defined (CONFIGURE_NETWORK_BOOTP) || defined (CONFIGURE_NETWORK_DHCP) + NULL, /* BOOTP/DHCP supplies IP address */ + NULL, /* BOOTP/DHCP supplies IP net mask */ +#else + CONFIGURE_NETWORK_IPADDR, /* IP address */ + CONFIGURE_NETWORK_NETMASK, /* IP net mask */ +#endif /* !CONFIGURE_NETWORK_BOOTP */ + +#if (defined (CONFIGURE_ETHERNET_ADDRESS)) + ethernet_address, /* Ethernet hardware address */ +#else + NULL, /* Driver supplies hardware address */ +#endif + 0 /* Use default driver parameters */ +}; + +/* + * Network configuration + */ +struct rtems_bsdnet_config rtems_bsdnet_config = { + &netdriver_config, + +#if (defined (CONFIGURE_NETWORK_BOOTP)) + rtems_bsdnet_do_bootp, +#elif (defined (CONFIGURE_NETWORK_DHCP)) + rtems_bsdnet_do_dhcp, +#else + NULL, +#endif + +#if (defined (CONFIGURE_NETWORK_PRIORITY)) + CONFIGURE_NETWORK_PRIORITY, /* Default network task priority */ +#else + 0, /* Default network task priority */ +#endif + +#if (defined (CONFIGURE_NETWORK_MBUFS)) + CONFIGURE_NETWORK_MBUFS, /* Default mbuf capacity */ +#else + 0, /* Default mbuf capacity */ +#endif + +#if (defined (CONFIGURE_NETWORK_MCLUSTERS)) + CONFIGURE_NETWORK_MCLUSTERS, /* Default mbuf cluster capacity */ +#else + 0, /* Default mbuf cluster capacity */ +#endif + +#if !defined (CONFIGURE_NETWORK_BOOTP) + CONFIGURE_NETWORK_HOSTNAME, /* Host name */ +#endif +#if !defined (CONFIGURE_NETWORK_BOOTP) && !defined(CONFIGURE_NETWORK_DHCP) + CONFIGURE_NETWORK_DOMAINNAME, /* Domain name */ + CONFIGURE_NETWORK_GATEWAY, /* Gateway */ + CONFIGURE_NETWORK_LOGHOST, /* Log host */ + { CONFIGURE_NETWORK_DNS }, /* Name server(s) */ + { CONFIGURE_NETWORK_NTP }, /* NTP server(s) */ +#endif /* !CONFIGURE_NETWORK_BOOTP */ +}; + +#endif /* _CONFIGURE_NETWORKCONFIG_H_ */ diff --git a/pc386-gdb.c b/pc386-gdb.c new file mode 100644 index 0000000..08d5fe5 --- /dev/null +++ b/pc386-gdb.c @@ -0,0 +1,39 @@ +/* + * $Id$ + * + * RTEMS Project (http://www.rtems.org/) + * + * Copyright 2007 Chris Johns (chrisj@rtems.org) + */ + +/** + * PC386 GDB support. + */ + +#include <stdio.h> + +#include <bsp.h> +#include <uart.h> + +void +pc386_gdb_init (void) +{ + printf ("GDB Initialisation\n"); + + i386_stub_glue_init (BSP_UART_COM2); + + /* + * Init GDB stub itself + */ + set_debug_traps(); + + /* + * Init GDB break in capability, has to be called after set_debug_traps + */ + i386_stub_glue_init_breakin(); + + /* + * Put breakpoint in and stop and wait for GDB. + */ + breakpoint(); +} diff --git a/pc386-gdb.h b/pc386-gdb.h new file mode 100644 index 0000000..4b93591 --- /dev/null +++ b/pc386-gdb.h @@ -0,0 +1,18 @@ +/* + * $Id$ + * + * RTEMS Project (http://www.rtems.org/) + * + * Copyright 2007 Chris Johns (chrisj@rtems.org) + */ + +/** + * PC386 GDB support. + */ + +#if !defined (_PC386_GDB_H_) +#define _PC386_GDB_H_ + +void pc386_gdb_init (void); + +#endif diff --git a/pc586-gdbinit-script b/pc586-gdbinit-script new file mode 100644 index 0000000..6baf230 --- /dev/null +++ b/pc586-gdbinit-script @@ -0,0 +1,12 @@ +define rrb + set $pc=bsp_reset + c +end +#set remotebaud 115200 +#target remote /dev/ttyUSB0 +target remote :1234 +b rtems_fatal_error_occurred +#source /opt/work/sw/rtems/src/rtems-gdb-macros +#finish +#finish +#next diff --git a/pkgconfig.py b/pkgconfig.py new file mode 100644 index 0000000..3e14574 --- /dev/null +++ b/pkgconfig.py @@ -0,0 +1,79 @@ +# +# Pkg-config in python. Pkg-config as a tool is a good idea how-ever the +# implementation is really Linux (or Unix) based and requires a couple of +# packages that it should not. If it was implemented with all parts included it +# would be portable and I suspect useful to others on platforms other than +# Linux or Unix equivs that contain the required packages. +# +import re + +class error(Exception): + def __init__(self, msg): + self.msg = msg + + def __str__(self): + return self.msg + +class package: + def __init__(self, file = None): + self.defines = {} + self.fields = {} + if file: + self.load(file) + + def load(self, file): + f = open(file) + tm = False + for l in f.readlines(): + l = l[:-1] + hash = l.find('#') + if hash >= 0: + l = l[:hash] + if len(l): + d = 0 + define = False + eq = l.find('=') + dd = l.find(':') + if eq > 0 and dd > 0: + if eq < dd: + define = True + d = eq + else: + define = False + d = dd + elif eq >= 0: + define = True + d = eq + elif dd >= 0: + define = False + d = dd + if d > 0: + lhs = l[:d].lower() + rhs = l[d + 1:] + + if tm: + print('define: ' + str(define) + ', lhs: ' + lhs + ', ' + rhs) + + if define: + self.defines[lhs] = rhs + else: + self.fields[lhs] = rhs + + def get(self, label): + if label.lower() not in self.fields: + raise error('Label not found: ' + label) + mre = re.compile('\$\{[^\}]+\}') + s = self.fields[label.lower()] + expanded = True + tm = False + while expanded: + expanded = False + if tm: + print 'pc:get: "' + s + '"' + ms = mre.findall(s) + for m in ms: + mn = m[2:-1] + if mn.lower() in self.defines: + s = s.replace(m, self.defines[mn.lower()]) + expanded = True + return s diff --git a/pkgconfig.pyc b/pkgconfig.pyc Binary files differnew file mode 100644 index 0000000..1883af6 --- /dev/null +++ b/pkgconfig.pyc diff --git a/rtems-grub-h0-1.cfg b/rtems-grub-h0-1.cfg new file mode 100755 index 0000000..3438d63 --- /dev/null +++ b/rtems-grub-h0-1.cfg @@ -0,0 +1,9 @@ +# RTEMS Grub configuration for RTEMS Testing
+set default=0
+timeout=0
+
+menuentry "RTEMS RTL Tester" {
+ set root=(hd0,1)
+ multiboot (hd0,1)/rtld --console=com1 --ide=0
+}
+
diff --git a/rtems-rtl.txt b/rtems-rtl.txt new file mode 100644 index 0000000..80645cd --- /dev/null +++ b/rtems-rtl.txt @@ -0,0 +1,310 @@ +RTEMS Runtime Link Editor (RTL) +=============================== +Chris Johns <chrisj@rtems.org> +1.0, Decemeber 2011 +:doctype: book +:toc: +:icons: +:numbered: + +image:images/rtemswhitebg.jpg["RTEMS",width="40%"] + +Background +---------- + +This project adds support for the 'dlopen', 'dlclose' and 'dlsym' calls as +defined in the POSIX and related standards to the RTEMS operating system. + +This test harness contains a new runtime linker as well as the Android and +NetBSD RTLD code. This support will go away so check earlier snapshots to find +that support. Neither the Android or NetBSD code is being directly used in this +project and only serves as a reference. + +The project built and tested the NetBSD code to look into using dynamic ELF +object files as a means of runtime loading code into RTEMS. Dynamic object +files are used by ELF based operating systems to share libraries and support +this function well. This model of dynamic loading does not map to RTEMS with +the same benefits. Simply put, RTEMS is not a multi-process environment nor +does it use memory protection or partitioned memory systems to create a virtual +process environment and this is where the benefits of using dynamic object +file's appear. Shared libraries allow code to be shared amongst a number of +processes operating in different virtual address spaces and while these +processes may share code they are kept separate for security reasons. Dynamic +ELF files provide the following characteristics to support sharing: + +. Procedure Lookup Tables (PLT) +. Global Offset Tables (GOT) +. Position Independent Code (PIC) +. Whole file memory footprint + +The PLT and GOT tables along with PIC code provide a small contained way to +locate a dynamic object file without the dynamic object file requiring +relocation fixups all through itself. This is important on shared library +system as it avoids the need for each process having a private copy of the +shared library code which defeats the purpose of sharing increasing the memory +usage across the system. On a shared library system the whole object file is +mapped into the process's address space and demand loading manages the physical +memory used by the process. If a process modifies a part of the shared library +the 'copy on write' or COW features of the operating system takes a copy of +that page of memory and makes it private to that process. With a shared library +made up of dynamic object files This happens when the process writes to a data +variable that is part of the shared library or the code is modified. To +minimise possible changes execution within the shared library is realtive using +position independent code (PIC) and calls externally are made using the PLT +tables which are altered to match the shared code's address mapping. The PTL +tables are small relative to the size of a shared library. + +The downside of this design is the performance overhead the indirect procedure +and data references incur plus the need to load the whole object file image +into memory. On a multi-process system with virtual memory demand paging these +negatives are minor compared to the positives, how-ever on RTEMS, a single +process system without virtual memory there are no positives only negatives. + +The NetBSD code was used to attempt to get relocatable code into a dynamic ELF +file. The tools for RTEMS would not do this. Relocatable code can be found in +relocatable type ELF file. The NetBSD loader checks for any ELF file that is +not dynamic returning an error. This means this code base could not be used +without major changes. The NetBSD code does support a large number of +architectures and has relocation support. + +The Android code also only supports dynamic modules and its code base only +supports a few targets and this support is not as cleanly implemented as +NetBSD. + +<<<< +RTEMS Runtime Link Editor +------------------------- + +The RTL code contained in this project is new code developed for RTEMS using +the features of RTEMS to give a small tight implementation. It supports the +loading of relocatable object files, invoking of contructor and destructor +functions, global symbol relocation and loading directly from archive format +files. The header files provide documentation about the functions provided and +the main.c file shows the command added to support development. + +The target code is supported by a host RTEMS specific linker called +'rtems-ld'. The RTEMS linker is contained in a separate package. + +Build System +~~~~~~~~~~~~ + +The package uses the waf build system. You can find waf here: + + http://waf.googlecode.com/ + +Waf is a fast full featured build environment that removes the need for make, +make files or any other traditional build system infrastructure. For details +please refer to the WAF-README file. It can be used to build any RTEMS project. + +Follow the download instructions for waf and install into your path. If you are +on Windows you will need to download a recent 2.7 or later version of Python +and add to the global path. + +Testing +------- + +The development is using the HEAD branch of RTEMS and the BSP is the Sparc +Instruction Simulator. Other architectures are support and if you have tools +and BSPs installed. The build scripts will attempt to detect them and build for +them. If there is no support for a specific architecture just copy the empty +NIOS2 file to the missing architecture. + +To build: + +. Get the latest tools. +. Check out RTEMS from CVS and run a bootstrap. +. Build using: ++ +------------------------------------------------------------- +$RTEMS_SRC/configure --target=sparc-rtems4.11 \ <1> + --prefix=$RTEMS_TEST_PREFIX/build/4.11 \ <2> + --enable-rtemsbsp=sis \ + --enable-tests=samples \ + --enable-cxx \ + --enable-maintainer-mode \ + --enable-rtems-debug +------------------------------------------------------------- + +<1> $RTEMS_SRC is the path to the RTEMS source code. +<2> $RTEMS_TEST_PREFIX is the path you install your test RTEMS builds. + +. Configure this package change directory to the source code and then: ++ +------------------------------------------------------------- +waf configure --rtems=/opt/work/rtems/build/4.11 \ + --rtems-tools=/opt/work/rtems/4.11,/opt/work/rtems/nios/nios2-rtems-11.0 +------------------------------------------------------------- ++ +You can also use: ++ +------------------------------------------------------------- +waf --help +------------------------------------------------------------- ++ +to get a list of options. The RTEMS specific ones are: ++ +--rtems=RTEMS_PATH:: Path to an installed RTEMS BSPs. ++ +--rtems-tools=RTEMS_TOOLS:: Path to RTEMS tools. This options avoids the need +to have the tools in your shell path. ++ +--rtems-version=RTEMS_VERSION:: RTEMS version (default 4.11). This is only +needed if you are not using the default. ++ +--rtems-archs=RTEMS_ARCHS:: List of RTEMS architectures to build. By default +all architectures detected when configuring are built. ++ +--rtems-bsps=RTEMS_BSPS:: List of BSPs to build. This lets you specify a +specific set of BSPs to build for. By default all BSPs are built. ++ +--show-commands:: Print the commands as strings. This will display the full +command used. This can help when debugging tool related issues. + +. Build the RTL test application do: ++ +------------------------------------------------------------- +waf +------------------------------------------------------------- + +. Run in the GDB SIS simulator: ++ +------------------------------------------------------------- +sparc-rtems4.11-run build/sparc-rtems4.11-sis/rtld +------------------------------------------------------------- + +RTEMS Linker +------------ + +The loading of relocatable object files allows the memory map to be determined +at run time giving us the maximum flexibility because the user does not need to +manage the memory. This approach how-ever requires loading be managed at the +object file level and this means there will be unresolved symbols and these +symbols can be from any library referenced by the project. + +The target link editor can resolve these symbols as it loads object files if +given a list of object files. A linker typically generates this list by loading +the symbol tables of the referenced librarys and then selecting the object +files referenced. The target does not have access to the librarys nor does it +typically have the memory and performance needed to manage large symbol tables. + +To resolve this an RTEMS linker has been developed. This is a C++ host only +program that can read and access the ELF files, load the symbols tables and +resolve the external symbols. It has a typical linker command line and outputs +a list of dependent object files or an archive file containting all referenced +object files. You can provide the linker with the base image and only the +object files not present are included. The base image is the static RTEMS image +you boot on your target hardware. + +This approach over comes the "library dependence" problem present in embedded +systems that use cross-compilation and standards linkers. If you have a +statically linked base image containing code from a library and you wish to +create a run time loadable image, either statically or incrementally linked +using code from the same library you do not know if code from the library is +present or not. If you feed the linker the base image's symbols and library the +linker will generate errors for duplicant symbols in the base image from the +same library. If you do not provide the library the linker will generate +unresolved symbol errors. We need a special linker that can handle this and +understand the role of the base image and the libraries present. + +Run Loadable Models +~~~~~~~~~~~~~~~~~~~ + +There are a number of possible application models users may wish to use. A +project may decide to vary the model used depending on the phase the project is +in. + +Script:: + +Load the application from the object files in the application and the +libraries. The target needs to have access to all libraries and this typically +means networked file system (NFS) access to the development host containing the +libraries being used. With a suitable initialisation mounting the network disk +and libraries paths being set an application can be loaded using a script of +files. The approach gives the developer flexiblity to update and play with +various parts of the code as they go. + +Single Image:: + +The RTEMS linker creates a single image of the application by pulling in the +object files from the libraries used by the application. The linker can be +given the base image and will link against the symbols it contains. This means +the base image and an application can use the same library and the application +will only contain the code from the library it needs. If at the point of +loading the object file has been loaded from another application the one +included in this application will not be loaded. + +For those users who need a determinisitic layout the loader should load the +same object files in the same place each time. This is deterministic. + +Status +------ + +The current status is loading is: + +. Loading of an object file as a file or within a archive works on the Sparc, +i386 and m68k architectures. Other architectures are present how-ever testing +may be limited. The NIOS file is an empty template to allow the package to +build. + +. Shell commands +dlopen+ ('dlo'), +dlclose+ ('dlc'), +dlsearch+ ('dls'), and +execute (+dlx+) provide a way to test the loader. + +. Shell access to the loader is provided via the 'rtl' command. The command +provdes: ++ +. status:: The status of the loader. ++ +. list:: List of loaded object modules. ++ +. sym:: Symbol table access. ++ +. obj:: Object file details. + +. The RTEMS linker and loader need a simple way to have a single application +archive loaded and run. This could be a script in a special section of the +archive, an elf file or something else. + +Development Tasks +~~~~~~~~~~~~~~~~~ + +. Add the ability to hold unresolved externals an object module may have once +loaded. We need the ability to load object modules with unresolved externals +because object modules may depend on eac other. + +This is complex issue due to the memory management issues it creates. Holding +the unresolved externals and then releasing them later will fragment the +heap. The proper solution is to add a memory manager and allocator to the +loader. This would be used for all symbol allocations. + +The other solution is to not allow loading of object modules with unresolved +symbols and to force application that have them to incrementally link. The +issue is here is 3rd party libraries and that makes this solution less than +ideal. + +. Add an application loader. An application needs to be formally +defined. Currently the RTEMS linker creates a standard library archive. A +application format needs some extra information. This could be as simple as +something that indicates this is an RTEMS application, through to the entry +point and a load order for the object modules in the archive to avoid +unresolved externals. + +. Place the code into the RTEMS source tree. + +Development Cut-n-Pastes for Chris +---------------------------------- + +Note: the '--' is required to abort getopt processing in sis-gdb + +------------------------------------------------------------- +waf configure --rtems=/Users/chris/Development/rtems/build/4.11 \ +--rtems-tools=/Users/chris/Development/rtems/4.11,/Users/chris/Development/rtems/nios/gnu/nios2-rtems-11.0 +~/Development/rtems/build/testing/sim-scripts/sis-gdb -- \ +--annotate=3 /Users/chris/Development/rtems/build/rtl/sparc/rtld +------------------------------------------------------------- + +------------------------------------------------------------- +sparc-rtems4.11-readelf -all x-long-name-to-create-gnu-extension-in-archive.o | less +~/Development/rtems/build/testing/sim-scripts/sis -l 10 \ +$(find sparc-rtems4.11/c/sis/testsuites/psxtests -name \*.exe) > results-no-oe-align +/Users/chris/Development/rtems/build/newlib/newlib-1.18.0/newlib/libc +------------------------------------------------------------- diff --git a/rtems.py b/rtems.py new file mode 100644 index 0000000..a98e433 --- /dev/null +++ b/rtems.py @@ -0,0 +1,392 @@ +# +# RTEMS support for applications. +# +# Copyright Chris Johns (chrisj@rtems.org) +# +import os +import os.path +import pkgconfig +import subprocess + +default_version = '4.11' +default_label = 'rtems-' + default_version +default_path = '/opt/' + default_label + +def options(opt): + opt.add_option('--rtems', + default = default_path, + dest = 'rtems_path', + help = 'Path to an installed RTEMS.') + opt.add_option('--rtems-tools', + default = None, + dest = 'rtems_tools', + help = 'Path to RTEMS tools.') + opt.add_option('--rtems-version', + default = default_version, + dest = 'rtems_version', + help = 'RTEMS version (default ' + default_version + ').') + opt.add_option('--rtems-archs', + default = 'all', + dest = 'rtems_archs', + help = 'List of RTEMS architectures to build.') + opt.add_option('--rtems-bsps', + default = 'all', + dest = 'rtems_bsps', + help = 'List of BSPs to build.') + opt.add_option('--show-commands', + action = 'store_true', + default = False, + dest = 'show_commands', + help = 'Print the commands as strings.') + +def init(ctx): + try: + import waflib.Options + import waflib.ConfigSet + + # + # Load the configuation set from the lock file. + # + env = waflib.ConfigSet.ConfigSet() + env.load(waflib.Options.lockfile) + + # + # Check the tools, architectures and bsps. + # + rtems_tools, archs, arch_bsps = check_options(ctx, + env.options['rtems_tools'], + env.options['rtems_path'], + env.options['rtems_version'], + env.options['rtems_archs'], + env.options['rtems_bsps']) + + # + # Update the contextes for all the bsps. + # + from waflib.Build import BuildContext, CleanContext, \ + InstallContext, UninstallContext + for x in arch_bsps: + for y in (BuildContext, CleanContext, InstallContext, UninstallContext): + name = y.__name__.replace('Context','').lower() + class context(y): + cmd = name + '-' + x + variant = x + + # + # Add the various commands. + # + for cmd in ['build', 'clean']: + if cmd in waflib.Options.commands: + waflib.Options.commands.remove(cmd) + for x in arch_bsps: + waflib.Options.commands.insert(0, cmd + '-' + x) + except: + pass + +def configure(conf): + # + # Handle the show commands option. + # + if conf.options.show_commands: + show_commands = 'yes' + else: + show_commands = 'no' + + rtems_tools, archs, arch_bsps = check_options(conf, + conf.options.rtems_tools, + conf.options.rtems_path, + conf.options.rtems_version, + conf.options.rtems_archs, + conf.options.rtems_bsps) + + _log_header(conf) + conf.to_log('Architectures: ' + ','.join(archs)) + + tools = _find_tools(conf, archs, rtems_tools) + + for ab in arch_bsps: + env = conf.env.copy() + env.set_variant(ab) + conf.set_env_name(ab, env) + conf.setenv(ab) + + arch = _arch_from_arch_bsp(ab) + + conf.env.RTEMS_PATH = conf.options.rtems_path + conf.env.RTEMS_VERSION = conf.options.rtems_version + conf.env.RTEMS_ARCH_BSP = ab + conf.env.RTEMS_ARCH = arch.split('-')[0] + conf.env.RTEMS_ARCH_RTEMS = arch + conf.env.RTEMS_BSP = _bsp_from_arch_bsp(ab) + + for t in tools[arch]: + conf.env[t] = tools[arch][t] + + conf.load('gcc') + conf.load('g++') + conf.load('gas') + + flags = _load_flags(conf, ab, conf.options.rtems_path) + + conf.env.CFLAGS = flags['CFLAGS'] + conf.env.LINKFLAGS = flags['CFLAGS'] + flags['LDFLAGS'] + conf.env.LIB = flags['LIB'] + + # + # Hack to work around NIOS2 naming. + # + if conf.env.RTEMS_ARCH in ['nios2']: + objcopy_format = 'elf32-little' + conf.env.RTEMS_ARCH + else: + objcopy_format = 'elf32-' + conf.env.RTEMS_ARCH + + conf.env.OBJCOPY_FLAGS = ['-O ', objcopy_format] + + conf.env.SHOW_COMMANDS = show_commands + + conf.setenv('') + + conf.env.RTEMS_TOOLS = rtems_tools + conf.env.ARCHS = archs + conf.env.ARCH_BSPS = arch_bsps + + conf.env.SHOW_COMMANDS = show_commands + +def build(bld): + if bld.env.SHOW_COMMANDS == 'yes': + output_command_line() + +def check_options(ctx, rtems_tools, rtems_path, rtems_version, rtems_archs, rtems_bsps): + # + # Check the paths are valid. + # + if not os.path.exists(rtems_path): + ctx.fatal('RTEMS path not found.') + if os.path.exists(os.path.join(rtems_path, 'lib', 'pkgconfig')): + rtems_config = None + elif os.path.exists(os.path.join(rtems_path, 'rtems-config')): + rtems_config = os.path.join(rtems_path, 'rtems-config') + else: + ctx.fatal('RTEMS path is not valid. No lib/pkgconfig or rtems-config found.') + + # + # We can more than one path to tools. This happens when testing different + # versions. + # + if rtems_tools is not None: + rt = rtems_tools.split(',') + tools = [] + for path in rt: + if not os.path.exists(path): + ctx.fatal('RTEMS tools path not found: ' + path) + if not os.path.exists(os.path.join(path, 'bin')): + ctx.fatal('RTEMS tools path does not contain a \'bin\' directory: ' + path) + tools += [os.path.join(path, 'bin')] + else: + tools = None + + # + # Match the archs requested against the ones found. If the user + # wants all (default) set all used. + # + if rtems_archs == 'all': + archs = _find_installed_archs(rtems_config, rtems_path, rtems_version) + else: + archs = _check_archs(rtems_config, rtems_archs, rtems_path, rtems_version) + + if len(archs) == 0: + ctx.fatal('Could not find any architectures') + + # + # Get the list of valid BSPs. This process filters the architectures + # to those referenced by the BSPs. + # + if rtems_bsps == 'all': + arch_bsps = _find_installed_arch_bsps(rtems_config, rtems_path, archs) + else: + arch_bsps = _check_arch_bsps(rtems_config, rtems_bsps, rtems_path, archs) + + return tools, archs, arch_bsps + +def arch(arch_bsp): + return _arch_from_arch_bsp(arch_bsp).split('-')[0] + +def bsp(arch_bsp): + return _bsp_from_arch_bsp(arch_bsp) + +def arch_bsps(ctx): + return ctx.env.ARCH_BSPS + +def arch_bsp_env(ctx, arch_bsp): + return ctx.env_of_name(arch_bsp).derive() + +def clone_tasks(bld): + if bld.cmd == 'build': + for obj in bld.all_task_gen[:]: + for x in arch_bsp: + cloned_obj = obj.clone(x) + kind = Options.options.build_kind + if kind.find(x) < 0: + cloned_obj.posted = True + obj.posted = True + +# +# From the demos. Use this to get the command to cut+paste to play. +# +def output_command_line(): + # first, display strings, people like them + from waflib import Utils, Logs + from waflib.Context import Context + def exec_command(self, cmd, **kw): + subprocess = Utils.subprocess + kw['shell'] = isinstance(cmd, str) + if isinstance(cmd, str): + Logs.info('%s' % cmd) + else: + Logs.info('%s' % ' '.join(cmd)) # here is the change + Logs.debug('runner_env: kw=%s' % kw) + try: + if self.logger: + self.logger.info(cmd) + kw['stdout'] = kw['stderr'] = subprocess.PIPE + p = subprocess.Popen(cmd, **kw) + (out, err) = p.communicate() + if out: + self.logger.debug('out: %s' % out.decode(sys.stdout.encoding or 'iso8859-1')) + if err: + self.logger.error('err: %s' % err.decode(sys.stdout.encoding or 'iso8859-1')) + return p.returncode + else: + p = subprocess.Popen(cmd, **kw) + return p.wait() + except OSError: + return -1 + Context.exec_command = exec_command + + # Change the outputs for tasks too + from waflib.Task import Task + def display(self): + return '' # no output on empty strings + + Task.__str__ = display + +def _find_tools(conf, archs, paths): + tools = {} + for arch in archs: + arch_tools = {} + arch_tools['CC'] = conf.find_program([arch + '-gcc'], path_list = paths) + arch_tools['CXX'] = conf.find_program([arch + '-g++'], path_list = paths) + arch_tools['AS'] = conf.find_program([arch + '-gcc'], path_list = paths) + arch_tools['LD'] = conf.find_program([arch + '-ld'], path_list = paths) + arch_tools['AR'] = conf.find_program([arch + '-ar'], path_list = paths) + arch_tools['LINK_CC'] = arch_tools['CC'] + arch_tools['LINK_CXX'] = arch_tools['CXX'] + arch_tools['AR'] = conf.find_program([arch + '-ar'], path_list = paths) + arch_tools['LD'] = conf.find_program([arch + '-ld'], path_list = paths) + arch_tools['NM'] = conf.find_program([arch + '-nm'], path_list = paths) + arch_tools['OBJDUMP'] = conf.find_program([arch + '-objdump'], path_list = paths) + arch_tools['OBJCOPY'] = conf.find_program([arch + '-objcopy'], path_list = paths) + arch_tools['READELF'] = conf.find_program([arch + '-readelf'], path_list = paths) + tools[arch] = arch_tools + return tools + +def _find_installed_archs(config, path, version): + archs = [] + if config is None: + for d in os.listdir(path): + if d.endswith('-rtems' + version): + archs += [d] + else: + a = subprocess.check_output([config, '--list-format', '"%(arch)s"']) + a = a[:-1].replace('"', '') + archs = a.split() + archs = ['%s-rtems4.11' %(x) for x in archs] + archs.sort() + return archs + +def _check_archs(config, req, path, version): + installed = _find_all_archs(config, path, version) + archs = [] + for a in req.split(','): + arch = a + '-rtems' + version + if arch in installed: + archs += [arch] + archs.sort() + return archs + +def _find_installed_arch_bsps(config, path, archs): + arch_bsps = [] + if config is None: + for f in os.listdir(_pkgconfig_path(path)): + if f.endswith('.pc'): + if _arch_from_arch_bsp(f[:-3]) in archs: + arch_bsps += [f[:-3]] + else: + ab = subprocess.check_output([config, '--list-format']) + ab = ab[:-1].replace('"', '') + ab = ab.replace('/', '-rtems4.11-') + arch_bsps = ab.split() + arch_bsps.sort() + return arch_bsps + +def _check_arch_bsps(req, path, archs): + installed = _find_installed_bsps(path, archs) + bsps = [] + for b in req.split(','): + if b in installed: + bsps += [b] + bsps.sort() + return bsps + +def _arch_from_arch_bsp(arch_bsp): + return '-'.join(arch_bsp.split('-')[:2]) + +def _bsp_from_arch_bsp(arch_bsp): + return '-'.join(arch_bsp.split('-')[2:]) + +def _pkgconfig_path(path): + return os.path.join(path, 'lib', 'pkgconfig') + +def _load_flags(conf, arch_bsp, path): + if not os.path.exists(path): + ctx.fatal('RTEMS path not found.') + if os.path.exists(_pkgconfig_path(path)): + pc = os.path.join(_pkgconfig_path(path), arch_bsp + '.pc') + conf.to_log('Opening and load pkgconfig: ' + pc) + pkg = pkgconfig.package(pc) + config = None + elif os.path.exists(os.path.join(path, 'rtems-config')): + config = os.path.join(path, 'rtems-config') + pkg = None + flags = {} + _log_header(conf) + flags['CFLAGS'] = _load_flags_set('CFLAGS', arch_bsp, conf, config, pkg) + flags['LDFLAGS'] = _load_flags_set('LDFLAGS', arch_bsp, conf, config, pkg) + flags['LIB'] = _load_flags_set('LIB', arch_bsp, conf, config, pkg) + return flags + +def _load_flags_set(flags, arch_bsp, conf, config, pkg): + conf.to_log('%s ->' % flags) + if pkg is not None: + try: + flagstr = pkg.get(flags) + except pkgconfig.error as e: + conf.to_log('pkconfig warning: ' + e.msg) + conf.to_log(' ' + flagstr) + else: + flags_map = { 'CFLAGS': '--cflags', + 'LDFLAGS': '--ldflags', + 'LIB': '--libs' } + ab = arch_bsp.split('-') + #conf.check_cfg(path = config, + # package = '', + # uselib_store = 'rtems', + # args = '--bsp %s/%s %s' % (ab[0], ab[2], flags_map[flags])) + #print conf.env + #print '%r' % conf + #flagstr = '-l -c' + flagstr = subprocess.check_output([config, '--bsp', '%s/%s' % (ab[0], ab[2]), flags_map[flags]]) + return flagstr.split() + +def _log_header(conf): + conf.to_log('-----------------------------------------') diff --git a/rtl-chain-iterator.c b/rtl-chain-iterator.c new file mode 100644 index 0000000..414b4ba --- /dev/null +++ b/rtl-chain-iterator.c @@ -0,0 +1,59 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtld + * + * @brief RTEMS Run-Time Link Editor Chain Iterator + * + * A means of executing an iterator on a chain. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <rtl-chain-iterator.h> + +bool +rtems_rtl_chain_iterate (rtems_chain_control* chain, + rtems_chain_iterator iterator, + void* data) +{ + rtems_chain_node* node = rtems_chain_first (chain); + while (!rtems_chain_is_tail (chain, node)) + { + rtems_chain_node* next_node = rtems_chain_next (node); + if (!iterator (node, data)) + return false; + node = next_node; + } + return true; +} + +/** + * Count iterator. + */ +static bool +rtems_rtl_count_iterator (rtems_chain_node* node, void* data) +{ + int* count = data; + ++(*count); + return true; +} + +int +rtems_rtl_chain_count (rtems_chain_control* chain) +{ + int count = 0; + rtems_rtl_chain_iterate (chain, rtems_rtl_count_iterator, &count); + return count; +} diff --git a/rtl-chain-iterator.h b/rtl-chain-iterator.h new file mode 100644 index 0000000..bdaa90e --- /dev/null +++ b/rtl-chain-iterator.h @@ -0,0 +1,61 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtl + * + * @brief RTEMS Run-Time Linker Chain Iterator. + */ + +#if !defined (_RTEMS_RTL_CHAIN_ITERATOR_H_) +#define _RTEMS_RTL_CHAIN_ITERATOR_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include <rtems/chain.h> + +/** + * Chain iterator handler. + */ +typedef bool (*rtems_chain_iterator) (rtems_chain_node* node, void* data); + +/** + * Iterate a chain of nodes invoking the iterator handler. Supply a data + * pointer the iterator moves data between the invoker and the iterator. + * + * The iterator allows removal of the node from the chain. + * + * @param chain The chain of nodes to iterator over. + * @param iterator The iterator handler called once for each node. + * @param data Pointer to the data used by the iterator. + * @retval true The whole chain was iterated over. + * @retval false The iterator returned false. + */ +bool +rtems_rtl_chain_iterate (rtems_chain_control* chain, + rtems_chain_iterator iterator, + void* data); + +/** + * Count the number of nodes on the chain. + * + * @param chain The chain to count the nodes of. + * @return int The number of nodes. + */ +int rtems_rtl_chain_count (rtems_chain_control* chain); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/rtl-debugger.c b/rtl-debugger.c new file mode 100644 index 0000000..d6360ef --- /dev/null +++ b/rtl-debugger.c @@ -0,0 +1,41 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtl + * + * @brief RTEMS Module Loading Debugger Interface. + * + * Inspection of run-time linkers in NetBSD and Android show a common type of + * structure that is used to interface to GDB. The NetBSD definition of this + * interface is being used and is defined in <link.h>. It defines a protocol + * that is used by GDB to inspect the state of dynamic libraries. I have not + * checked GDB code at when writing this comment but I suspect GDB sets a break + * point on the r_brk field of _rtld_debug and it has code that detects this + * break point being hit. When this happens it reads the state and performs the + * operation based on the r_state field. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <link.h> + +struct r_debug _rtld_debug; + +void +_rtld_debug_state (void) +{ + /* + * Empty. GDB only needs to hit this location. + */ +} diff --git a/rtl-elf.c b/rtl-elf.c new file mode 100644 index 0000000..7ef8104 --- /dev/null +++ b/rtl-elf.c @@ -0,0 +1,605 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtld + * + * @brief RTEMS Run-Time Link Editor + * + * This is the RTL implementation. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> + +#include <rtl.h> +#include "rtl-elf.h" +#include "rtl-error.h" +#include "rtl-trace.h" + +static bool +rtems_rtl_elf_machine_check (Elf_Ehdr* ehdr) +{ + /* + * This code is determined by the NetBSD machine headers. + */ + switch (ehdr->e_machine) + { + ELFDEFNNAME (MACHDEP_ID_CASES) + default: + return false; + } + return true; +} + +bool +rtems_rtl_elf_find_symbol (rtems_rtl_obj_t* obj, + const Elf_Sym* sym, + const char* symname, + Elf_Word* value) +{ + rtems_rtl_obj_sect_t* sect; + + if (ELF_ST_TYPE(sym->st_info) == STT_NOTYPE) + { + rtems_rtl_obj_sym_t* symbol = rtems_rtl_symbol_global_find (symname); + if (!symbol) + { + rtems_rtl_set_error (EINVAL, "global symbol not found: %s", symname); + return false; + } + + *value = (Elf_Word) symbol->value; + return true; + } + + sect = rtems_rtl_obj_find_section_by_index (obj, sym->st_shndx); + if (!sect) + { + rtems_rtl_set_error (EINVAL, "reloc symbol's section not found"); + return false; + } + + *value = sym->st_value + (Elf_Word) sect->base; + return true; +} + +static bool +rtems_rtl_elf_relocator (rtems_rtl_obj_t* obj, + int fd, + rtems_rtl_obj_sect_t* sect, + void* data) +{ + rtems_rtl_obj_cache_t* symbols; + rtems_rtl_obj_cache_t* strings; + rtems_rtl_obj_cache_t* relocs; + rtems_rtl_obj_sect_t* targetsect; + rtems_rtl_obj_sect_t* symsect; + rtems_rtl_obj_sect_t* strtab; + bool is_rela; + size_t reloc_size; + int reloc; + int unresolved; + + /* + * First check if the section the relocations are for exists. If it does not + * exist ignore these relocations. They are most probably debug sections. + */ + targetsect = rtems_rtl_obj_find_section_by_index (obj, sect->info); + if (!targetsect) + return true; + + rtems_rtl_obj_caches (&symbols, &strings, &relocs); + + if (!symbols || !strings || !relocs) + return false; + + symsect = rtems_rtl_obj_find_section (obj, ".symtab"); + if (!symsect) + { + rtems_rtl_set_error (EINVAL, "no .symtab section"); + return false; + } + + strtab = rtems_rtl_obj_find_section (obj, ".strtab"); + if (!strtab) + { + rtems_rtl_set_error (EINVAL, "no .strtab section"); + return false; + } + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("relocation: %s, syms:%s\n", sect->name, symsect->name); + + /* + * Handle the different relocation record types. + */ + is_rela = ((sect->flags & RTEMS_RTL_OBJ_SECT_RELA) == + RTEMS_RTL_OBJ_SECT_RELA) ? true : false; + reloc_size = is_rela ? sizeof (Elf_Rela) : sizeof (Elf_Rel); + + unresolved = 0; + + for (reloc = 0; reloc < (sect->size / reloc_size); ++reloc) + { + uint8_t relbuf[reloc_size]; + const Elf_Rela* rela = (const Elf_Rela*) relbuf; + const Elf_Rel* rel = (const Elf_Rel*) relbuf; + Elf_Sym sym; + const char* symname = NULL; + off_t off; + Elf_Word type; + Elf_Word symvalue; + bool relocate; + + off = obj->ooffset + sect->offset + (reloc * reloc_size); + + if (!rtems_rtl_obj_cache_read_byval (relocs, fd, off, + &relbuf[0], reloc_size)) + return false; + + if (is_rela) + off = (obj->ooffset + symsect->offset + + (ELF_R_SYM (rela->r_info) * sizeof (sym))); + else + off = (obj->ooffset + symsect->offset + + (ELF_R_SYM (rel->r_info) * sizeof (sym))); + + if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off, + &sym, sizeof (sym))) + return false; + + /* + * Only need the name of the symbol if global. + */ + if (ELF_ST_TYPE (sym.st_info) == STT_NOTYPE) + { + size_t len; + off = obj->ooffset + strtab->offset + sym.st_name; + len = RTEMS_RTL_ELF_STRING_MAX; + + if (!rtems_rtl_obj_cache_read (strings, fd, off, + (void**) &symname, &len)) + return false; + } + + /* + * See if the record references an external symbol. If it does find the + * symbol value. If the symbol cannot be found flag the object file as + * having unresolved externals. + */ + if (is_rela) + type = ELF_R_TYPE(rela->r_info); + else + type = ELF_R_TYPE(rel->r_info); + + relocate = true; + + if (rtems_rtl_elf_rel_resolve_sym (type)) + { + if (!rtems_rtl_elf_find_symbol (obj, &sym, symname, &symvalue)) + { + ++unresolved; + relocate = false; + } + } + + if (relocate) + { + if (is_rela) + { + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rela: sym:%-2d type:%-2d off:%08lx addend:%d\n", + (int) ELF_R_SYM (rela->r_info), (int) ELF_R_TYPE (rela->r_info), + rela->r_offset, (int) rela->r_addend); + if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect, symvalue)) + return false; + } + else + { + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rel: sym:%-2d type:%-2d off:%08lx\n", + (int) ELF_R_SYM (rel->r_info), (int) ELF_R_TYPE (rel->r_info), + rel->r_offset); + if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect, symvalue)) + return false; + } + } + } + + /* + * Set the unresolved externals status if there are unresolved externals. + */ + if (unresolved) + obj->flags |= RTEMS_RTL_OBJ_UNRESOLVED; + + return true; +} + +static bool +rtems_rtl_elf_symbols (rtems_rtl_obj_t* obj, + int fd, + rtems_rtl_obj_sect_t* sect, + void* data) +{ + rtems_rtl_obj_cache_t* symbols; + rtems_rtl_obj_cache_t* strings; + rtems_rtl_obj_sect_t* strtab; + int globals; + int string_space; + char* string; + int sym; + + strtab = rtems_rtl_obj_find_section (obj, ".strtab"); + if (!strtab) + { + rtems_rtl_set_error (EINVAL, "no .strtab section"); + return false; + } + + rtems_rtl_obj_caches (&symbols, &strings, NULL); + + if (!symbols || !strings) + return false; + + /* + * Find the number of globals and the amount of string space + * needed. Also check for duplicate symbols. + */ + + globals = 0; + string_space = 0; + + for (sym = 0; sym < (sect->size / sizeof (Elf_Sym)); ++sym) + { + Elf_Sym symbol; + off_t off; + const char* name; + size_t len; + + off = obj->ooffset + sect->offset + (sym * sizeof (symbol)); + + if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off, + &symbol, sizeof (symbol))) + return false; + + off = obj->ooffset + strtab->offset + symbol.st_name; + len = RTEMS_RTL_ELF_STRING_MAX; + + if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len)) + return false; + + /* + * Only keep the functions and global or weak symbols. + */ + if ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) || + (ELF_ST_TYPE (symbol.st_info) == STT_FUNC)) + { + if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) || + (ELF_ST_BIND (symbol.st_info) == STB_WEAK)) + { + /* + * If there is a globally exported symbol already present and this + * symbol is not weak raise an error. If the symbol is weak and present + * globally ignore this symbol and use the global one and if it is not + * present take this symbol global or weak. We accept the first weak + * symbol we find and make it globally exported. + */ + if (rtems_rtl_symbol_global_find (name) && + (ELF_ST_BIND (symbol.st_info) != STB_WEAK)) + { + rtems_rtl_set_error (ENOMEM, "duplicate global symbol: %s", name); + return false; + } + else + { + ++globals; + string_space += strlen (name) + 1; + } + } + } + } + + if (globals) + { + rtems_rtl_obj_sym_t* gsym; + + obj->global_size = globals * sizeof (rtems_rtl_obj_sym_t) + string_space; + obj->global_table = calloc (1, obj->global_size); + if (!obj->global_table) + { + obj->global_size = 0; + rtems_rtl_set_error (ENOMEM, "no memory for obj global syms"); + return false; + } + + obj->global_syms = globals; + + for (sym = 0, + gsym = obj->global_table, + string = (((char*) obj->global_table) + + (globals * sizeof (rtems_rtl_obj_sym_t))); + sym < (sect->size / sizeof (Elf_Sym)); + ++sym) + { + Elf_Sym symbol; + off_t off; + const char* name; + size_t len; + + off = obj->ooffset + sect->offset + (sym * sizeof (symbol)); + + if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off, + &symbol, sizeof (symbol))) + { + free (obj->global_table); + obj->global_table = NULL; + obj->global_syms = 0; + obj->global_size = 0; + return false; + } + + off = obj->ooffset + strtab->offset + symbol.st_name; + len = RTEMS_RTL_ELF_STRING_MAX; + + if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len)) + return false; + + if (((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) || + (ELF_ST_TYPE (symbol.st_info) == STT_FUNC)) && + ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) || + (ELF_ST_BIND (symbol.st_info) == STB_WEAK))) + { + rtems_rtl_obj_sect_t* symsect; + symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx); + if (!symsect) + { + free (obj->global_table); + obj->global_table = NULL; + obj->global_syms = 0; + obj->global_size = 0; + rtems_rtl_set_error (EINVAL, "sym section not found"); + return false; + } + memcpy (string, name, strlen (name) + 1); + gsym->name = string; + string += strlen (name) + 1; + gsym->value = symbol.st_value + (uint8_t*) symsect->base; + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL)) + printf ("sym:%-2d name:%-2d:%-20s bind:%-2d type:%-2d val:%8p sect:%d size:%d\n", + sym, (int) symbol.st_name, gsym->name, + (int) ELF_ST_BIND (symbol.st_info), + (int) ELF_ST_TYPE (symbol.st_info), + gsym->value, symbol.st_shndx, + (int) symbol.st_size); + + ++gsym; + } + } + } + + return true; +} + +static bool +rtems_rtl_elf_parse_sections (rtems_rtl_obj_t* obj, int fd, Elf_Ehdr* ehdr) +{ + rtems_rtl_obj_cache_t* sects; + rtems_rtl_obj_cache_t* strings; + int section; + off_t sectstroff; + off_t off; + Elf_Shdr shdr; + + rtems_rtl_obj_caches (§s, &strings, NULL); + + if (!sects || !strings) + return false; + + /* + * Get the offset to the section string table. + */ + off = obj->ooffset + ehdr->e_shoff + (ehdr->e_shstrndx * ehdr->e_shentsize); + + if (!rtems_rtl_obj_cache_read_byval (sects, fd, off, &shdr, sizeof (shdr))) + return false; + + if (shdr.sh_type != SHT_STRTAB) + { + rtems_rtl_set_error (EINVAL, "bad .sectstr section type"); + return false; + } + + sectstroff = obj->ooffset + shdr.sh_offset; + + for (section = 0; section < ehdr->e_shnum; ++section) + { + uint32_t flags; + + off = obj->ooffset + ehdr->e_shoff + (section * ehdr->e_shentsize); + + if (!rtems_rtl_obj_cache_read_byval (sects, fd, off, &shdr, sizeof (shdr))) + return false; + + flags = 0; + + switch (shdr.sh_type) + { + case SHT_NULL: + /* + * Ignore. + */ + break; + + case SHT_PROGBITS: + /* + * There are 2 program bits sections. One is the program text and the + * other is the program data. The program text is flagged + * alloc/executable and the program data is flagged alloc/writable. + */ + if ((shdr.sh_flags & SHF_ALLOC) == SHF_ALLOC) + { + if ((shdr.sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR) + flags = RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_LOAD; + else if ((shdr.sh_flags & SHF_WRITE) == SHF_WRITE) + flags = RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_LOAD; + else + flags = RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD; + } + break; + + case SHT_NOBITS: + /* + * There is 1 NOBIT section which is the .bss section. There is nothing + * but a definition as the .bss is just a clear region of memory. + */ + if ((shdr.sh_flags & (SHF_ALLOC | SHF_WRITE)) == (SHF_ALLOC | SHF_WRITE)) + flags = RTEMS_RTL_OBJ_SECT_BSS | RTEMS_RTL_OBJ_SECT_ZERO; + break; + + case SHT_RELA: + flags = RTEMS_RTL_OBJ_SECT_RELA; + break; + + case SHT_REL: + /* + * The sh_link holds the section index for the symbol table. The sh_info + * holds the section index the relocations apply to. + */ + flags = RTEMS_RTL_OBJ_SECT_REL; + break; + + case SHT_SYMTAB: + flags = RTEMS_RTL_OBJ_SECT_SYM; + break; + + case SHT_STRTAB: + flags = RTEMS_RTL_OBJ_SECT_STR; + break; + + default: + printf ("unsupported section: %2d: type=%02d flags=%02x\n", + section, (int) shdr.sh_type, (int) shdr.sh_flags); + break; + } + + if (flags != 0) + { + char* name; + size_t len; + + len = RTEMS_RTL_ELF_STRING_MAX; + if (!rtems_rtl_obj_cache_read (strings, fd, + sectstroff + shdr.sh_name, + (void**) &name, &len)) + return false; + + if (strcmp (".ctors", name) == 0) + flags |= RTEMS_RTL_OBJ_SECT_CTOR; + if (strcmp (".dtors", name) == 0) + flags |= RTEMS_RTL_OBJ_SECT_DTOR; + + if (!rtems_rtl_obj_add_section (obj, section, name, + shdr.sh_size, shdr.sh_offset, + shdr.sh_addralign, shdr.sh_link, + shdr.sh_info, flags)) + return false; + } + } + + return true; +} + +bool +rtems_rtl_obj_file_load (rtems_rtl_obj_t* obj, int fd) +{ + rtems_rtl_obj_cache_t* header; + Elf_Ehdr ehdr; + + rtems_rtl_obj_caches (&header, NULL, NULL); + + if (!rtems_rtl_obj_cache_read_byval (header, fd, obj->ooffset, + &ehdr, sizeof (ehdr))) + return false; + + /* + * Check we have a valid ELF file. + */ + if ((memcmp (ELFMAG, ehdr.e_ident, SELFMAG) != 0) + || ehdr.e_ident[EI_CLASS] != ELFCLASS) + { + rtems_rtl_set_error (EINVAL, "invalid ELF file format"); + return false; + } + + if ((ehdr.e_ident[EI_VERSION] != EV_CURRENT) + || (ehdr.e_version != EV_CURRENT) + || (ehdr.e_ident[EI_DATA] != ELFDEFNNAME (MACHDEP_ENDIANNESS))) + { + rtems_rtl_set_error (EINVAL, "unsupported ELF file version"); + return false; + } + + if (!rtems_rtl_elf_machine_check (&ehdr)) + { + rtems_rtl_set_error (EINVAL, "unsupported machine type"); + return false; + } + + if (ehdr.e_type == ET_DYN) + { + rtems_rtl_set_error (EINVAL, "unsupported ELF file type"); + return false; + } + + if (ehdr.e_phentsize != 0) + { + rtems_rtl_set_error (EINVAL, "ELF file contains program headers"); + return false; + } + + if (ehdr.e_shentsize != sizeof (Elf_Shdr)) + { + rtems_rtl_set_error (EINVAL, "invalid ELF section header size"); + return false; + } + + /* + * Parse the section information first so we have the memory map of the object + * file and the memory allocated. Any further allocations we make to complete + * the load will not fragment the memory. + */ + if (!rtems_rtl_elf_parse_sections (obj, fd, &ehdr)) + return false; + + obj->entry = (void*)(uintptr_t) ehdr.e_entry; + + if (!rtems_rtl_obj_load_sections (obj, fd)) + return false; + + if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols, &ehdr)) + return false; + + if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocator, &ehdr)) + return false; + + return true; +} + diff --git a/rtl-elf.h b/rtl-elf.h new file mode 100644 index 0000000..b6dc4a8 --- /dev/null +++ b/rtl-elf.h @@ -0,0 +1,129 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtl + * + * @brief RTEMS Run-Time Linker ELF Headers + */ + +#if !defined (_RTEMS_RTL_ELF_H_) +#define _RTEMS_RTL_ELF_H_ + +#include <rtl-fwd.h> +#include <rtl-obj-fwd.h> +#include <rtl-sym.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + ** Imported NetBSD ELF Specifics Start. + **/ + +/* + * Always 32bit for RTEMS at the moment. Do not add '()'. Leave plain. + */ +#define ELFSIZE 32 + +/* + * Define _STANDALONE then remove after. + */ +#define _STANDALONE 1 + +#include <sys/cdefs.h> +#include <sys/exec_elf.h> + +#undef _STANDALONE + +/** + ** Imported NetBSD ELF Specifics End. + **/ + +/** + * Maximum string length. This a read buffering limit rather than a + * specific ELF length. I hope this is ok as I am concerned about + * some C++ symbol lengths. + */ +#define RTEMS_RTL_ELF_STRING_MAX (256) + +/** + * Architecture specific handler to check is a relocation record's type is + * required to resolve a symbol. + * + * @param type The type field in the relocation record. + * @retval true The relocation record require symbol resolution. + * @retval false The relocation record does not require symbol resolution. + */ +bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type); + +/** + * Architecture specific relocation handler compiled in for a specific + * architecture by the build system. The handler applies the relocation + * to the target. + * + * @param obj The object file being relocated. + * @param rel The ELF relocation record. + * @param sect The section of the object file the relocation is for. + * @param symvalue If a symbol is referenced, this is the symbols value. + * @retval bool The relocation has been applied. + * @retval bool The relocation could not be applied. + */ +bool rtems_rtl_elf_relocate_rel (rtems_rtl_obj_t* obj, + const Elf_Rel* rel, + rtems_rtl_obj_sect_t* sect, + Elf_Word symvalue); + +/** + * Architecture specific relocation handler compiled in for a specific + * architecture by the build system. The handler applies the relocation + * to the target. + * + * @param obj The object file being relocated. + * @param rela The ELF addend relocation record. + * @param sect The section of the object file the relocation is for. + * @param symvalue If a symbol is referenced, this is the symbols value. + * @retval bool The relocation has been applied. + * @retval bool The relocation could not be applied. + */ +bool rtems_rtl_elf_relocate_rela (rtems_rtl_obj_t* obj, + const Elf_Rela* rela, + rtems_rtl_obj_sect_t* sect, + Elf_Word symvalue); + +/** + * Find the symbol. The symbol is passed as an ELF type symbol with the name + * and the value returned is the absolute address of the symbol. + * + * If the symbol type is STT_NOTYPE the symbol references a global symbol. The + * gobal symbol table is searched to find it and that value returned. If the + * symbol is local to the object module the section for the symbol is located + * and it's base added to the symbol's value giving an absolute location. + * + * @param obj The object the symbol is being resolved for. + * @param sym The ELF type symbol. + * @param symname The sym's name read from the symbol string table. + * @param value Return the value of the symbol. Only valid if the return value + * is true. + * @retval true The symbol resolved. + * @retval false The symbol could not be result. The RTL error is set. + */ +bool rtems_rtl_elf_find_symbol (rtems_rtl_obj_t* obj, + const Elf_Sym* sym, + const char* symname, + Elf_Word* value); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/rtl-error.c b/rtl-error.c new file mode 100644 index 0000000..cef6452 --- /dev/null +++ b/rtl-error.c @@ -0,0 +1,49 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtl + * + * @brief RTEMS Run-Time Linker Error + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdarg.h> + +#include <rtl.h> +#include "rtl-error.h" + +void +rtems_rtl_set_error (int error, const char* format, ...) +{ + rtems_rtl_data_t* rtl = rtems_rtl_lock (); + va_list ap; + va_start (ap, format); + rtl->last_errno = error; + vsnprintf (rtl->last_error, sizeof (rtl->last_error), format, ap); + rtems_rtl_unlock (); + va_end (ap); +} + +int +rtems_rtl_get_error (char* message, size_t max_message) +{ + rtems_rtl_data_t* rtl = rtems_rtl_lock (); + int last_errno = rtl->last_errno; + strncpy (message, rtl->last_error, sizeof (rtl->last_error)); + rtems_rtl_unlock (); + return last_errno; +} + diff --git a/rtl-error.h b/rtl-error.h new file mode 100644 index 0000000..0aaf24d --- /dev/null +++ b/rtl-error.h @@ -0,0 +1,46 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtl + * + * @brief RTEMS Run-Time Linker Error + */ + +#if !defined (_RTEMS_RTL_ERROR_H_) +#define _RTEMS_RTL_ERROR_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if __GNUC__ +#define RTEMS_RTL_PRINTF_ATTR __attribute__((__format__(__printf__,2,3))) +#else +#define RTEMS_RTL_PRINTF_ATTR +#endif + +/** + * Sets the error. + * + * Assumes the RTL has been locked. + * + * @param error The errno error number. + * @param format The error format string. + * @param ... The variable arguments that depend on the format string. + */ +void rtems_rtl_set_error (int error, const char* format, ...) RTEMS_RTL_PRINTF_ATTR; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/rtl-fwd.h b/rtl-fwd.h new file mode 100644 index 0000000..3527fca --- /dev/null +++ b/rtl-fwd.h @@ -0,0 +1,35 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtl + * + * @brief RTEMS Run-Time Linker ELF Headers + */ + +#if !defined (_RTEMS_RTL_FWD_H_) +#define _RTEMS_RTL_FWD_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * The forward declaration of the obj structure. + */ +struct rtems_rtl_data_s; +typedef struct rtems_rtl_data_s rtems_rtl_data_t; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/rtl-mdreloc-arm.c b/rtl-mdreloc-arm.c new file mode 100644 index 0000000..8b210a2 --- /dev/null +++ b/rtl-mdreloc-arm.c @@ -0,0 +1,153 @@ +/* + * Taken from NetBSD and stripped of the relocations not needed on RTEMS. + * + * $Id$ + */ + +/* $NetBSD: mdreloc.c,v 1.33 2010/01/14 12:12:07 skrll Exp $ */ + +#include <sys/cdefs.h> + +#include <errno.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <rtl.h> +#include "rtl-elf.h" +#include "rtl-error.h" +#include <rtl-trace.h> + +/* + * It is possible for the compiler to emit relocations for unaligned data. + * We handle this situation with these inlines. + */ +#define RELOC_ALIGNED_P(x) \ + (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0) + +static inline Elf_Addr +load_ptr (void *where) +{ + Elf_Addr res; + memcpy (&res, where, sizeof(res)); + return (res); +} + +static inline void +store_ptr (void *where, Elf_Addr val) +{ + memcpy(where, &val, sizeof(val)); +} + +bool +rtems_rtl_elf_relocate_rela (rtems_rtl_obj_t* obj, + const Elf_Rela* rela, + rtems_rtl_obj_sect_t* sect, + const Elf_Sym* sym, + const char* symname) +{ + printf ("rtl: rela record not supported; please report\n"); + return false; +} + +bool +rtems_rtl_elf_relocate_rel (rtems_rtl_obj_t* obj, + const Elf_Rel* rel, + rtems_rtl_obj_sect_t* sect, + const Elf_Sym* sym, + const char* symname) +{ + Elf_Addr target = 0; + Elf_Addr* where; + Elf_Addr tmp; + Elf_Word symvalue; + + where = (Elf_Addr *)(sect->base + rel->r_offset); + + switch (ELF_R_TYPE(rel->r_info)) { + case R_TYPE(NONE): + break; + + case R_TYPE(PC24): { /* word32 S - P + A */ + Elf32_Sword addend; + + /* + * Extract addend and sign-extend if needed. + */ + addend = *where; + if (addend & 0x00800000) + addend |= 0xff000000; + + if (!rtems_rtl_elf_find_symbol (obj, sym, symname, &symvalue)) + return false; + + tmp = (Elf_Addr) symvalue - (Elf_Addr) where + (addend << 2); + if ((tmp & 0xfe000000) != 0xfe000000 && + (tmp & 0xfe000000) != 0) { + rtems_rtl_set_error ("%s: R_ARM_PC24 relocation @ %p to %s failed " + "(displacement %ld (%#lx) out of range)", + obj->oname, where, symname, + (long) tmp, (long) tmp); + return false; + } + tmp >>= 2; + *where = (*where & 0xff000000) | (tmp & 0x00ffffff); + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: reloc PC24 %s in %s --> %p @ %p\n", + symname, obj->oname, (void *)*where, where); + break; + } + + case R_TYPE(ABS32): /* word32 B + S + A */ + case R_TYPE(GLOB_DAT): /* word32 B + S */ + if (!rtems_rtl_elf_find_symbol (obj, sym, symname, &symvalue)) + return false; + + if (__predict_true (RELOC_ALIGNED_P (where))) { + tmp = *where + symvalue; + /* Set the Thumb bit, if needed. */ + if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC) + tmp |= 1; + *where = tmp; + } else { + tmp = load_ptr (where) + symvalue; + /* Set the Thumb bit, if needed. */ + if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC) + tmp |= 1; + store_ptr (where, tmp); + } + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: reloc ABS32/GLOB_DAT %s in %s --> %p @ %p\n", + symname, obj->oname, (void *)tmp, where); + break; + + case R_TYPE(RELATIVE): /* word32 B + A */ + if (__predict_true (RELOC_ALIGNED_P (where))) { + tmp = *where + (Elf_Addr) sect->base; + *where = tmp; + } else { + tmp = load_ptr (where) + (Elf_Addr) sect->base; + store_ptr (where, tmp); + } + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: reloc RELATIVE in %s --> %p", obj->oname, (void *)tmp)); + break; + + case R_TYPE(COPY): + printf ("rtl: reloc COPY (please report)\n"); + break; + + default: + printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, " + "contents = %p, symbol = %s\n", + ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info), + (void *)rel->r_offset, (void *)*where, symname); + rtems_rtl_set_error (EINVAL, + "%s: Unsupported relocation type %ld " + "in non-PLT relocations", + sect->name, (uint32_t) ELF_R_TYPE(rel->r_info)); + return false; + } + + return true; +} diff --git a/rtl-mdreloc-i386.c b/rtl-mdreloc-i386.c new file mode 100644 index 0000000..472a246 --- /dev/null +++ b/rtl-mdreloc-i386.c @@ -0,0 +1,99 @@ +/* + * Taken from NetBSD and stripped of the relocations not needed on RTEMS. + * + * $Id$ + */ + +/* $NetBSD: mdreloc.c,v 1.31 2010/01/14 11:58:32 skrll Exp $ */ + +#include <sys/cdefs.h> + +#include <errno.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <rtl.h> +#include "rtl-elf.h" +#include "rtl-error.h" +#include <rtl-trace.h> + +bool +rtems_rtl_elf_rel_resolve_sym (Elf_Word type) +{ + return true; +} + +bool +rtems_rtl_elf_relocate_rela (rtems_rtl_obj_t* obj, + const Elf_Rela* rela, + rtems_rtl_obj_sect_t* sect, + Elf_Word symvalue) +{ + printf ("rtl: rela record not supported; please report\n"); + return false; +} + +bool +rtems_rtl_elf_relocate_rel (rtems_rtl_obj_t* obj, + const Elf_Rel* rel, + rtems_rtl_obj_sect_t* sect, + Elf_Word symvalue) +{ + Elf_Addr target = 0; + Elf_Addr* where; + Elf_Addr tmp; + + where = (Elf_Addr *)(sect->base + rel->r_offset); + + switch (ELF_R_TYPE(rel->r_info)) { + case R_TYPE(NONE): + break; + + case R_TYPE(PC32): + target = (Elf_Addr) symvalue; + *where += target - (Elf_Addr)where; + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: reloc PC32 in %s --> %p (%p) in %s\n", + sect->name, (void*) symvalue, + (void *)*where, obj->oname); + break; + + case R_TYPE(GOT32): + case R_TYPE(32): + case R_TYPE(GLOB_DAT): + target = (Elf_Addr) symvalue; + + tmp = target + *where; + if (*where != tmp) + *where = tmp; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: reloc 32/GLOB_DAT in %s --> %p in %s\n", + sect->name, (void *)*where, obj->oname); + break; + + case R_TYPE(RELATIVE): + *where += (Elf_Addr)sect->base; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: reloc RELATIVE in %s --> %p\n", obj->oname, (void *)*where); + break; + + case R_TYPE(COPY): + printf ("rtl: reloc COPY (please report)\n"); + break; + + default: + printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, " + "contents = %p\n", + ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info), + (void *)rel->r_offset, (void *)*where); + rtems_rtl_set_error (EINVAL, + "%s: Unsupported relocation type %ld " + "in non-PLT relocations", + sect->name, (uint32_t) ELF_R_TYPE(rel->r_info)); + return false; + } + + return true; +} diff --git a/rtl-mdreloc-m68k.c b/rtl-mdreloc-m68k.c new file mode 100644 index 0000000..fef380c --- /dev/null +++ b/rtl-mdreloc-m68k.c @@ -0,0 +1,104 @@ +/* + * Taken from NetBSD and stripped of the relocations not needed on RTEMS. + * + * $Id$ + */ + +/* $NetBSD: mdreloc.c,v 1.26 2010/01/14 11:58:32 skrll Exp $ */ + +#include <sys/cdefs.h> + +#include <errno.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <rtl.h> +#include "rtl-elf.h" +#include "rtl-error.h" +#include <rtl-trace.h> + +bool +rtems_rtl_elf_rel_resolve_sym (Elf_Word type) +{ + return true; +} + +bool +rtems_rtl_elf_relocate_rela (rtems_rtl_obj_t* obj, + const Elf_Rela* rela, + rtems_rtl_obj_sect_t* sect, + Elf_Word symvalue) +{ + Elf_Addr target = 0; + Elf_Addr* where; + + where = (Elf_Addr *)(sect->base + rela->r_offset); + + switch (ELF_R_TYPE(rela->r_info)) { + case R_TYPE(NONE): + break; + + case R_TYPE(PC32): + target = (Elf_Addr) symvalue + rela->r_addend; + *where += target - (Elf_Addr)where; + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: reloc PC32 in %s --> %p (%p) in %s\n", + sect->name, (void*) (symvalue + rela->r_addend), + (void *)*where, obj->oname); + break; + + case R_TYPE(GOT32): + case R_TYPE(32): + case R_TYPE(GLOB_DAT): + target = (Elf_Addr) symvalue + rela->r_addend; + + if (*where != target) + *where = target; + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: reloc 32/GLOB_DAT in %s --> %p in %s\n", + sect->name, (void *)*where, obj->oname); + break; + + case R_TYPE(RELATIVE): + *where += (Elf_Addr) sect->base + rela->r_addend; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: reloc RELATIVE in %s --> %p\n", obj->oname, (void *)*where); + break; + + case R_TYPE(COPY): + /* + * These are deferred until all other relocations have + * been done. All we do here is make sure that the + * COPY relocation is not in a shared library. They + * are allowed only in executable files. + */ + printf ("rtl: reloc COPY (please report)\n"); + break; + + default: + printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, " + "contents = %p\n", + ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info), + (void *)rela->r_offset, (void *)*where); + rtems_rtl_set_error (EINVAL, + "%s: Unsupported relocation type %ld " + "in non-PLT relocations", + sect->name, (uint32_t) ELF_R_TYPE(rela->r_info)); + return false; + } + + return false; +} + +bool +rtems_rtl_elf_relocate_rel (rtems_rtl_obj_t* obj, + const Elf_Rel* rel, + rtems_rtl_obj_sect_t* sect, + Elf_Word symvalue) +{ + printf ("rtl: rel type record not supported; please report\n"); + return false; +} diff --git a/rtl-mdreloc-nios2.c b/rtl-mdreloc-nios2.c new file mode 100644 index 0000000..e96b3f6 --- /dev/null +++ b/rtl-mdreloc-nios2.c @@ -0,0 +1,46 @@ +/* + * Taken from NetBSD and stripped of the relocations not needed on RTEMS. + * + * $Id$ + */ + +/* $NetBSD: mdreloc.c,v 1.26 2010/01/14 11:58:32 skrll Exp $ */ + +#include <sys/cdefs.h> + +#include <errno.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <rtl.h> +#include "rtl-elf.h" +#include "rtl-error.h" +#include <rtl-trace.h> + +bool +rtems_rtl_elf_rel_resolve_sym (Elf_Word type) +{ + return true; +} + + +bool +rtems_rtl_elf_relocate_rela (rtems_rtl_obj_t* obj, + const Elf_Rela* rela, + rtems_rtl_obj_sect_t* sect, + Elf_Word symvalue) +{ + + return true; +} + +bool +rtems_rtl_elf_relocate_rel (rtems_rtl_obj_t* obj, + const Elf_Rel* rel, + rtems_rtl_obj_sect_t* sect, + Elf_Word symvalue) +{ + printf ("rtl: rel type record not supported; please report\n"); + return false; +} diff --git a/rtl-mdreloc-powerpc.c b/rtl-mdreloc-powerpc.c new file mode 100644 index 0000000..eb6c9b9 --- /dev/null +++ b/rtl-mdreloc-powerpc.c @@ -0,0 +1,155 @@ +/* + * Taken from NetBSD and stripped of the relocations not needed on RTEMS. + * + * $Id$ + */ + +/* $NetBSD: ppc_reloc.c,v 1.44 2010/01/13 20:17:22 christos Exp $ */ + +/*- + * Copyright (C) 1998 Tsubai Masanari + * Portions copyright 2002 Charles M. Hannum <root@ihack.net> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> + +#include <errno.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <rtl.h> +#include "rtl-elf.h" +#include "rtl-error.h" +#include <rtl-trace.h> + +#define ha(x) ((((u_int32_t)(x) & 0x8000) ? \ + ((u_int32_t)(x) + 0x10000) : (u_int32_t)(x)) >> 16) +#define l(x) ((u_int32_t)(x) & 0xffff) + +/* + * The PPC PLT format consists of three sections: + * (1) The "pltcall" and "pltresolve" glue code. This is always 18 words. + * (2) The code part of the PLT entries. There are 2 words per entry for + * up to 8192 entries, then 4 words per entry for any additional entries. + * (3) The data part of the PLT entries, comprising a jump table. + * This section is half the size of the second section (ie. 1 or 2 words + * per entry). + */ + +/* + * Setup the plt glue routines. + */ +#define PLTCALL_SIZE 20 +#define PLTRESOLVE_SIZE 24 + +bool +rtems_rtl_elf_relocate_rela (rtems_rtl_obj_t* obj, + const Elf_Rela* rela, + rtems_rtl_obj_sect_t* sect, + const Elf_Sym* sym, + const char* symname) +{ + Elf_Addr target = 0; + Elf_Addr* where; + Elf_Word symvalue; + + where = (Elf_Addr *)(sect->base + rela->r_offset); + + switch (ELF_R_TYPE(rela->r_info)) { + case R_TYPE(JMP_SLOT): + case R_TYPE(NONE): + break; + + case R_TYPE(PC32): + if (!rtems_rtl_elf_find_symbol (obj, sym, symname, &symvalue)) + return false; + + target = (Elf_Addr) symvalue + rela->r_addend; + *where += target - (Elf_Addr)where; + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: reloc PC32 %s in %s --> %p (%p) in %s\n", + symname, sect->name, (void*) (symvalue + rela->r_addend), + (void *)*where, obj->oname); + break; + + case R_TYPE(32): /* word32 S + A */ + case R_TYPE(GLOB_DAT): /* word32 S + A */ + if (!rtems_rtl_elf_find_symbol (obj, sym, symname, &symvalue)) + return false; + + target = (Elf_Addr) symvalue + rela->r_addend; + + if (*where != target) + *where = target; + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: reloc 32/GLOB_DAT %s in %s --> %p in %s\n", + symname, sect->name, (void *)*where, obj->oname); + break; + + case R_TYPE(RELATIVE): /* word32 B + A */ + *where += (Elf_Addr) sect->base + rela->r_addend; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: reloc RELATIVE in %s --> %p\n", obj->oname, (void *)*where); + break; + + case R_TYPE(COPY): + /* + * These are deferred until all other relocations have + * been done. All we do here is make sure that the + * COPY relocation is not in a shared library. They + * are allowed only in executable files. + */ + printf ("rtl: reloc COPY (please report)\n"); + break; + + default: + printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, " + "contents = %p, symbol = %s\n", + ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info), + (void *)rela->r_offset, (void *)*where, symname); + rtems_rtl_set_error (EINVAL, + "%s: Unsupported relocation type %ld " + "in non-PLT relocations", + sect->name, (uint32_t) ELF_R_TYPE(rela->r_info)); + return false; + } + + return false; +} + +bool +rtems_rtl_elf_relocate_rel (rtems_rtl_obj_t* obj, + const Elf_Rel* rel, + rtems_rtl_obj_sect_t* sect, + const Elf_Sym* sym, + const char* symname) +{ + printf ("rtl: rel type record not supported; please report\n"); + return false; +} diff --git a/rtl-mdreloc-sparc.c b/rtl-mdreloc-sparc.c new file mode 100644 index 0000000..4c2b861 --- /dev/null +++ b/rtl-mdreloc-sparc.c @@ -0,0 +1,256 @@ +/* + * Taken from NetBSD and stripped of the relocations not needed on RTEMS. + * + * $Id$ + */ + +/* $NetBSD: mdreloc.c,v 1.43 2010/01/13 20:17:22 christos Exp $ */ + +/*- + * Copyright (c) 1999, 2002 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Paul Kranenburg and by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> + +#include <rtl.h> +#include "rtl-elf.h" +#include "rtl-error.h" +#include <rtl-trace.h> + +/* + * The following table holds for each relocation type: + * - the width in bits of the memory location the relocation + * applies to (not currently used) + * - the number of bits the relocation value must be shifted to the + * right (i.e. discard least significant bits) to fit into + * the appropriate field in the instruction word. + * - flags indicating whether + * * the relocation involves a symbol + * * the relocation is relative to the current position + * * the relocation is for a GOT entry + * * the relocation is relative to the load address + * + */ +#define _RF_S 0x80000000 /* Resolve symbol */ +#define _RF_A 0x40000000 /* Use addend */ +#define _RF_P 0x20000000 /* Location relative */ +#define _RF_G 0x10000000 /* GOT offset */ +#define _RF_B 0x08000000 /* Load address relative */ +#define _RF_U 0x04000000 /* Unaligned */ +#define _RF_SZ(s) (((s) & 0xff) << 8) /* memory target size */ +#define _RF_RS(s) ( (s) & 0xff) /* right shift */ + +static const int reloc_target_flags[] = { + 0, /* NONE */ + _RF_S|_RF_A| _RF_SZ(8) | _RF_RS(0), /* RELOC_8 */ + _RF_S|_RF_A| _RF_SZ(16) | _RF_RS(0), /* RELOC_16 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* RELOC_32 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(8) | _RF_RS(0), /* DISP_8 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(16) | _RF_RS(0), /* DISP_16 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* DISP_32 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_30 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_22 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* HI22 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 22 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 13 */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* LO10 */ + _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT10 */ + _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT13 */ + _RF_G| _RF_SZ(32) | _RF_RS(10), /* GOT22 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PC10 */ + _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC22 */ + _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WPLT30 */ + _RF_SZ(32) | _RF_RS(0), /* COPY */ + _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* GLOB_DAT */ + _RF_SZ(32) | _RF_RS(0), /* JMP_SLOT */ + _RF_A| _RF_B|_RF_SZ(32) | _RF_RS(0), /* RELATIVE */ + _RF_S|_RF_A| _RF_U|_RF_SZ(32) | _RF_RS(0), /* UA_32 */ +}; + +#ifdef NOT_CURRENTLY_USED_BUT_MAYBE_USEFUL +static const char *reloc_names[] = { + "NONE", "RELOC_8", "RELOC_16", "RELOC_32", "DISP_8", + "DISP_16", "DISP_32", "WDISP_30", "WDISP_22", "HI22", + "22", "13", "LO10", "GOT10", "GOT13", + "GOT22", "PC10", "PC22", "WPLT30", "COPY", + "GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32" +}; +#endif + +#define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0) +#define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0) +#define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0) +#define RELOC_UNALIGNED(t) ((reloc_target_flags[t] & _RF_U) != 0) +#define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0) +#define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff) +#define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff) + +static const int reloc_target_bitmask[] = { +#define _BM(x) (~(-(1ULL << (x)))) + 0, /* NONE */ + _BM(8), _BM(16), _BM(32), /* RELOC_8, _16, _32 */ + _BM(8), _BM(16), _BM(32), /* DISP8, DISP16, DISP32 */ + _BM(30), _BM(22), /* WDISP30, WDISP22 */ + _BM(22), _BM(22), /* HI22, _22 */ + _BM(13), _BM(10), /* RELOC_13, _LO10 */ + _BM(10), _BM(13), _BM(22), /* GOT10, GOT13, GOT22 */ + _BM(10), _BM(22), /* _PC10, _PC22 */ + _BM(30), 0, /* _WPLT30, _COPY */ + -1, -1, -1, /* _GLOB_DAT, JMP_SLOT, _RELATIVE */ + _BM(32) /* _UA32 */ +#undef _BM +}; +#define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) + +bool +rtems_rtl_elf_rel_resolve_sym (Elf_Word type) +{ + return RELOC_RESOLVE_SYMBOL (type) ? true : false; +} + +bool +rtems_rtl_elf_relocate_rela (rtems_rtl_obj_t* obj, + const Elf_Rela* rela, + rtems_rtl_obj_sect_t* sect, + Elf_Word symvalue) +{ + Elf_Addr *where; + Elf_Word type, value, mask; + + where = (Elf_Addr *) (sect->base + rela->r_offset); + + type = ELF_R_TYPE(rela->r_info); + if (type == R_TYPE(NONE)) + return true; + + /* We do JMP_SLOTs in _rtld_bind() below */ + if (type == R_TYPE(JMP_SLOT)) + return true; + + /* COPY relocs are also handled elsewhere */ + if (type == R_TYPE(COPY)) + return true; + + /* + * We use the fact that relocation types are an `enum' + * Note: R_SPARC_6 is currently numerically largest. + */ + if (type > R_TYPE(6)) + return false; + + value = rela->r_addend; + + /* + * Handle relative relocs here, as an optimization. + */ + if (type == R_TYPE (RELATIVE)) { + *where += (Elf_Addr)(sect->base + value); + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: reloc relative in %s --> %p", obj->oname, (void *)*where); + return true; + } + + if (RELOC_RESOLVE_SYMBOL (type)) { + /* Add in the symbol's absolute address */ + value += symvalue; + } + + if (RELOC_PC_RELATIVE (type)) { + value -= (Elf_Word)where; + } + + if (RELOC_BASE_RELATIVE (type)) { + /* + * Note that even though sparcs use `Elf_rela' + * exclusively we still need the implicit memory addend + * in relocations referring to GOT entries. + * Undoubtedly, someone f*cked this up in the distant + * past, and now we're stuck with it in the name of + * compatibility for all eternity.. + * + * In any case, the implicit and explicit should be + * mutually exclusive. We provide a check for that + * here. + */ +#define DIAGNOSTIC +#ifdef DIAGNOSTIC + if (value != 0 && *where != 0) { + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf("rtl: reloc base_rel(%s): where=%p, *where 0x%lx, " + "addend=0x%lx, base %p\n", + obj->oname, where, *where, rela->r_addend, sect->base); + } +#endif + value += (Elf_Word)(sect->base + *where); + } + + mask = RELOC_VALUE_BITMASK (type); + value >>= RELOC_VALUE_RIGHTSHIFT (type); + value &= mask; + + if (RELOC_UNALIGNED(type)) { + /* Handle unaligned relocations. */ + Elf_Addr tmp = 0; + char *ptr = (char *)where; + int i, size = RELOC_TARGET_SIZE (type) / 8; + + /* Read it in one byte at a time. */ + for (i=0; i<size; i++) + tmp = (tmp << 8) | ptr[i]; + + tmp &= ~mask; + tmp |= value; + + /* Write it back out. */ + for (i=0; i<size; i++) + ptr[i] = ((tmp >> (8*i)) & 0xff); + + } else { + *where &= ~mask; + *where |= value; + } + + return true; +} + +bool +rtems_rtl_elf_relocate_rel (rtems_rtl_obj_t* obj, + const Elf_Rel* rel, + rtems_rtl_obj_sect_t* sect, + Elf_Word symvalue) +{ + printf ("rtl: rel type record not supported; please report\n"); + return false; +} diff --git a/rtl-obj-cache.c b/rtl-obj-cache.c new file mode 100644 index 0000000..fbe550b --- /dev/null +++ b/rtl-obj-cache.c @@ -0,0 +1,178 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtl + * + * @brief RTEMS Run-Time Linker Object File cache buffers a section of the + * object file in a buffer to localise read performance. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <string.h> +#include <unistd.h> + +#include <rtl-obj-cache.h> +#include <rtl-error.h> + +bool +rtems_rtl_obj_cache_open (rtems_rtl_obj_cache_t* cache, size_t size) +{ + cache->fd = -1; + cache->offset = 0; + cache->size = size; + cache->level = 0; + cache->buffer = malloc (size); + if (!cache->buffer) + { + rtems_rtl_set_error (ENOMEM, "no memory for cache buffer"); + return false; + } + return true; +} + +void +rtems_rtl_obj_cache_close (rtems_rtl_obj_cache_t* cache) +{ + free (cache->buffer); + cache->fd = -1; + cache->level = 0; +} + +void +rtems_rtl_obj_cache_flush (rtems_rtl_obj_cache_t* cache) +{ + cache->fd = -1; + cache->level = 0; +} + +bool +rtems_rtl_obj_cache_read (rtems_rtl_obj_cache_t* cache, + int fd, + off_t offset, + void** buffer, + size_t* length) +{ + if (*length > cache->size) + { + rtems_rtl_set_error (EINVAL, "read size larger than cache size"); + return false; + } + + while (true) + { + size_t buffer_offset = 0; + size_t buffer_read = cache->size; + + /* + * Is the data in the cache for this file ? + */ + if (fd == cache->fd) + { + /* + * Is any part of the data in the cache ? + */ + if ((offset >= cache->offset) && + (offset < (cache->offset + cache->level))) + { + buffer_offset = offset - cache->offset; + + /* + * Return the location of the data in the cache. + */ + *buffer = cache->buffer + buffer_offset; + + /* + * Is all the data in the cache or just a part ? + */ + if (*length < (cache->level - buffer_offset)) + return true; + else if (cache->level < cache->size) + { + /* + * This is the remaining data in the file. + */ + *length = cache->level - buffer_offset; + return true; + } + + /* + * Copy down the data in the buffer and then fill the remaining + * space with as much data we are able to read. + */ + memmove (cache->buffer, + cache->buffer + buffer_offset, + cache->size - buffer_offset); + + buffer_read = buffer_offset; + buffer_offset = cache->size - buffer_offset; + } + } + + if (lseek (fd, offset + buffer_offset, SEEK_SET) < 0) + { + rtems_rtl_set_error (errno, "file seek failed"); + return false; + } + + /* + * Loop reading the data from the file until either an error or 0 is + * returned and if data has been read check if the amount is what we + * want. If not it is an error. A POSIX read can read data in fragments. + */ + cache->level = buffer_read; + while (buffer_read) + { + int r = read (fd, cache->buffer + buffer_offset, buffer_read); + if (r < 0) + { + rtems_rtl_set_error (errno, "file read failed"); + return false; + } + if ((r == 0) && buffer_read) + { + cache->level = cache->level - buffer_read; + buffer_read = 0; + } + else + { + buffer_read -= r; + buffer_offset += r; + } + } + + cache->fd = fd; + cache->offset = offset; + } + + return false; +} + +bool +rtems_rtl_obj_cache_read_byval (rtems_rtl_obj_cache_t* cache, + int fd, + off_t offset, + void* buffer, + size_t length) +{ + void* cbuffer = 0; + size_t len = length; + bool ok = rtems_rtl_obj_cache_read (cache, fd, offset, &cbuffer, &len); + if (ok && (len != length)) + ok = false; + if (ok) + memcpy (buffer, cbuffer, length); + return ok; +} diff --git a/rtl-obj-cache.h b/rtl-obj-cache.h new file mode 100644 index 0000000..014cfd7 --- /dev/null +++ b/rtl-obj-cache.h @@ -0,0 +1,131 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtl + * + * @brief RTEMS Run-Time Linker Object File cache buffers a section of the + * object file in a buffer to localise read performance. + * + * This is a simple object file cache that holds a buffer of data from the + * offset in the file the read is requested from. Writes are not supported. + * + * The cache holds the file descriptor, the offset into the file and the amount + * of valid data in the cache. If the file is ever modified the user of the + * cache to responsible for flushing the cache. For example the cache should be + * flused if the file is closed. + * + * The cache can return by reference or by value. By reference allow access to + * the cache buffer. Do not modify the cache's data. By value will copy the + * requested data into the user supplied buffer. + * + * The read by reference call allows you to probe the file's data. For example + * a string in an object file can be an unknown length. You can request a read + * up to the cache's size by reference. The code will attempt to have this data + * in the buffer. If there is not enough data in the file the length will be + * modifed to reflect this. + * + * You can have more than one cache for a single file all looking at different + * parts of the file. + */ + +#if !defined (_RTEMS_RTL_OBJ_CACHE_H_) +#define _RTEMS_RTL_OBJ_CACHE_H_ + +#include <fcntl.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * The buffer cache. + */ +typedef struct rtems_rtl_obj_cache_s +{ + int fd; /**< The file descriptor of the data in the cache. */ + off_t offset; /**< The base offset of the buffer. */ + size_t size; /**< The size of the cache. */ + size_t level; /**< The amount of data in the cache. A file can be + * smaller than the cache file. */ + uint8_t* buffer; /**< The buffer */ +} rtems_rtl_obj_cache_t; + +/** + * Open a cache allocating a single buffer of the size passed. The default + * state of the cache is flushed. No already open checks are made. + * + * @param cache The cache to initialise. + * @param size The size of the cache. + * @retval true The cache is open. + * @retval false The cache is not open. The RTL error is set. + */ +bool rtems_rtl_obj_cache_open (rtems_rtl_obj_cache_t* cache, size_t size); + +/** + * Close a cache. + * + * @param cache The cache to close. + */ +void rtems_rtl_obj_cache_close (rtems_rtl_obj_cache_t* cache); + +/** + * Flush the cache. Any further read will read the data from the file. + * + * @param cache The cache to flush. + */ +void rtems_rtl_obj_cache_flush (rtems_rtl_obj_cache_t* cache); + +/** + * Read data by reference. The length contains the amount of data that should + * be available in the cache and referenced by the buffer handle. It must be + * less than or equal to the size of the cache. This call will return the + * amount of data that is available. It can be less than you ask if the offset + * and size is past the end of the file. + * + * @param cache The cache to reference data from. + * @param fs The file descriptor. Must be an open file. + * @param offset The offset in the file to reference the data to. + * @param length The length of data to reference. Can be modified to a + * lesser value and true is still returned so check it. + * @retval true The data referenced is in the cache. + * @retval false The read failed and the RTL error has been set. + */ +bool rtems_rtl_obj_cache_read (rtems_rtl_obj_cache_t* cache, + int fd, + off_t offset, + void** buffer, + size_t* length); + +/** + * Read data by value. The data is copied to the user supplied buffer. + * + * @param cache The cache to read the data from. + * @param fs The file descriptor. Must be an open file. + * @param offset The offset in the file to read the data from. + * @param length The length of data to read. + * @retval true The data has been read from the cache. + * @retval false The read failed and the RTL error has been set. + */ +bool rtems_rtl_obj_cache_read_byval (rtems_rtl_obj_cache_t* cache, + int fd, + off_t offset, + void* buffer, + size_t length); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/rtl-obj-fwd.h b/rtl-obj-fwd.h new file mode 100644 index 0000000..9f1e757 --- /dev/null +++ b/rtl-obj-fwd.h @@ -0,0 +1,41 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtl + * + * @brief RTEMS Run-Time Linker ELF Headers + */ + +#if !defined (_RTEMS_RTL_OBJ_FWD_H_) +#define _RTEMS_RTL_OBJ_FWD_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * The forward declaration of the obj section structure. + */ +struct rtems_rtl_obj_sect_s; +typedef struct rtems_rtl_obj_sect_s rtems_rtl_obj_sect_t; + +/** + * The forward declaration of the obj structure. + */ +struct rtems_rtl_obj_s; +typedef struct rtems_rtl_obj_s rtems_rtl_obj_t; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/rtl-obj.c b/rtl-obj.c new file mode 100644 index 0000000..ef2a894 --- /dev/null +++ b/rtl-obj.c @@ -0,0 +1,1040 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtl + * + * @brief RTEMS Run-Time Linker Error + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <fcntl.h> +#include <inttypes.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> + +#include <rtems/libio_.h> + +#include <rtl.h> +#include <rtl-chain-iterator.h> +#include <rtl-obj.h> +#include "rtl-error.h" +#include "rtl-trace.h" + +rtems_rtl_obj_t* +rtems_rtl_obj_alloc (void) +{ + rtems_rtl_obj_t* obj = malloc (sizeof (rtems_rtl_obj_t)); + if (obj) + { + /* + * Initalise to 0. + */ + *obj = (rtems_rtl_obj_t) { { 0 } }; + + /* + * Initialise the chains. + */ + rtems_chain_initialize_empty (&obj->sections); + } + return obj; +} + +static void +rtems_rtl_obj_free_names (rtems_rtl_obj_t* obj) +{ + free ((void*) obj->oname); + free ((void*) obj->aname); + if ((obj->fname != obj->aname) && (obj->fname != obj->oname)) + free ((void*) obj->fname); +} + +bool +rtems_rtl_obj_free (rtems_rtl_obj_t* obj) +{ + if (obj->users || ((obj->flags & RTEMS_RTL_OBJ_LOCKED) != 0)) + { + rtems_rtl_set_error (EINVAL, "cannot free obj still in use"); + return false; + } + if (!rtems_chain_is_node_off_chain (&obj->link)) + rtems_chain_extract (&obj->link); + rtems_rtl_obj_symbol_erase (obj); + if (obj->text_base) + free (obj->text_base); + rtems_rtl_obj_free_names (obj); + free (obj); + return true; +} + +bool +rtems_rtl_obj_unresolved (rtems_rtl_obj_t* obj) +{ + return (obj->flags & RTEMS_RTL_OBJ_UNRESOLVED) != 0 ? true : false; +} + +static bool +rtems_rtl_obj_parse_name (rtems_rtl_obj_t* obj, const char* name) +{ + const char* p; + const char* e; + char* aname; + char* oname; + + /* + * Parse the name to determine if the object file is part of an archive or it + * is an object file. + */ + e = name + strlen (name); + + p = strchr (name, ':'); + + if (p == NULL) + p = e; + + aname = NULL; + + oname = malloc (p - name + 1); + if (oname == NULL) + { + rtems_rtl_set_error (ENOMEM, "no memory for object file name"); + return false; + } + + memcpy (oname, name, p - name); + oname[p - name] = '\0'; + + if (p != e) + { + const char* o; + + /* + * The file name is an archive and the object file name is next after the + * delimiter. + */ + aname = oname; + ++p; + + /* + * See if there is a '@' to delimit an archive offset for the object in the + * archive. + */ + o = strchr (p, '@'); + + if (o == NULL) + o = e; + + oname = malloc (o - p + 1); + if (oname == NULL) + { + free (aname); + rtems_rtl_set_error (ENOMEM, "no memory for object file name"); + return false; + } + + memcpy (oname, p, o - p); + oname[o - p] = '\0'; + + if (o != e) + { + /* + * The object name has an archive offset. If the number + * does not parse 0 will be returned and the archive will be + * searched. + */ + obj->ooffset = strtoul (o + 1, 0, 0); + } + } + + obj->oname = oname; + obj->aname = aname; + + return true; +} + +static bool +rtems_rtl_seek_read (int fd, off_t off, size_t len, uint8_t* buffer) +{ + if (lseek (fd, off, SEEK_SET) < 0) + return false; + if (read (fd, buffer, len) != len) + return false; + return true; +} + +/** + * Scan the decimal number returning the value found. + */ +static uint64_t +rtems_rtl_scan_decimal (const uint8_t* string, size_t len) +{ + uint64_t value = 0; + + while (len && (*string != ' ')) + { + value *= 10; + value += *string - '0'; + ++string; + --len; + } + + return value; +} + +/** + * Align the size to the next alignment point. Assume the alignment is a + * positive integral power of 2 if not 0 or 1. If 0 or 1 then there is no + * alignment. + */ +static size_t +rtems_rtl_sect_align (size_t offset, uint32_t alignment) +{ + if ((alignment > 1) && ((offset & ~alignment) != 0)) + offset = (offset + alignment) & ~(alignment - 1); + return offset; +} + +/** + * Section size summer iterator data. + */ +typedef struct +{ + uint32_t mask; /**< The selection mask to sum. */ + size_t size; /**< The size of all section fragments. */ +} rtems_rtl_obj_sect_summer_t; + +static bool +rtems_rtl_obj_sect_summer (rtems_chain_node* node, void* data) +{ + rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node; + rtems_rtl_obj_sect_summer_t* summer = data; + if ((sect->flags & summer->mask) == summer->mask) + summer->size = + rtems_rtl_sect_align (summer->size, sect->alignment) + sect->size; + return true; +} + +static size_t +rtems_rtl_obj_section_size (rtems_rtl_obj_t* obj, uint32_t mask) +{ + rtems_rtl_obj_sect_summer_t summer; + summer.mask = mask; + summer.size = 0; + rtems_rtl_chain_iterate (&obj->sections, + rtems_rtl_obj_sect_summer, + &summer); + return summer.size; +} + +/** + * Section alignment iterator data. The first section's alignment sets the + * alignment for that type of section. + */ +typedef struct +{ + uint32_t mask; /**< The selection mask to look for alignment. */ + uint32_t alignment; /**< The alignment of the section type. */ +} rtems_rtl_obj_sect_aligner_t; + +/** + * The section aligner iterator. + */ +static bool +rtems_rtl_obj_sect_aligner (rtems_chain_node* node, void* data) +{ + rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node; + rtems_rtl_obj_sect_aligner_t* aligner = data; + if ((sect->flags & aligner->mask) == aligner->mask) + { + aligner->alignment = sect->alignment; + return false; + } + return true; +} + +static size_t +rtems_rtl_obj_section_alignment (rtems_rtl_obj_t* obj, uint32_t mask) +{ + rtems_rtl_obj_sect_aligner_t aligner; + aligner.mask = mask; + aligner.alignment = 0; + rtems_rtl_chain_iterate (&obj->sections, + rtems_rtl_obj_sect_aligner, + &aligner); + return aligner.alignment; +} + +static bool +rtems_rtl_obj_section_handler (uint32_t mask, + rtems_rtl_obj_t* obj, + int fd, + rtems_rtl_obj_sect_handler_t handler, + void* data) +{ + rtems_chain_node* node = rtems_chain_first (&obj->sections); + while (!rtems_chain_is_tail (&obj->sections, node)) + { + rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node; + if ((sect->flags & mask) != 0) + { + if (!handler (obj, fd, sect, data)) + return false; + } + node = rtems_chain_next (node); + } + return true; +} + +bool +rtems_rtl_match_name (rtems_rtl_obj_t* obj, const char* name) +{ + const char* n1 = obj->oname; + while ((*n1 != '\0') && (*n1 != '\n') && (*n1 != '/') && + (*name != '\0') && (*name != '/') && (*n1 == *name)) + { + ++n1; + ++name; + } + if (((*n1 == '\0') || (*n1 == '\n') || (*n1 == '/')) && + ((*name == '\0') || (*name == '/'))) + return true; + return false; +} + +bool +rtems_rtl_obj_find_file (rtems_rtl_obj_t* obj, const char* name) +{ + struct stat sb; + const char* n; + + /* + * Parse the name. The object descriptor will have the archive name and/or + * object name fields filled in. A find of the file will result in the file + * name (fname) field pointing to the actual file if present on the file + * system. + */ + if (!rtems_rtl_obj_parse_name (obj, name)) + return false; + + /* + * If the archive field (aname) is set we use that name else we use the + * object field (oname). If selected name is absolute we just point the aname + * field to the fname field to that name. If the field is relative we search + * the paths set in the RTL for the file. + */ + if (obj->aname != NULL) + n = obj->aname; + else + n = obj->oname; + + if (rtems_filesystem_is_separator (n[0])) + { + if (stat (n, &sb) == 0) + obj->fname = n; + } + else + { + rtems_rtl_data_t* rtl; + const char* s; + const char* e; + int l; + + rtl = rtems_rtl_lock (); + + s = rtl->paths; + e = s + strlen (rtl->paths); + l = strlen (n); + + while ((obj->fname == NULL) && (s != e)) + { + const char* d; + char* p; + + d = strchr (s, ':'); + if (d == NULL) + d = e; + + /* + * Allocate the path fragment, separator, name, terminating nul. + */ + p = malloc ((d - s) + 1 + l + 1); + if (p == NULL) + { + rtems_rtl_set_error (ENOMEM, "no memory searching for object file"); + rtems_rtl_unlock (); + return false; + } + + memcpy (p, s, d - s); + p[d - s] = '/'; + memcpy (p + (d - s) + 1, n, l); + p[(d - s) + 1 + l] = '\0'; + + if (stat (p, &sb) < 0) + free (p); + else + { + /* + * We have found the file. Do not release the path memory. + */ + obj->fname = p; + } + + s = d; + } + + rtems_rtl_unlock (); + } + + if (obj->fname) + obj->fsize = sb.st_size; + else + rtems_rtl_set_error (ENOMEM, "object file not found"); + + return obj->fname ? true : false; +} + +bool +rtems_rtl_obj_add_section (rtems_rtl_obj_t* obj, + int section, + const char* name, + size_t size, + off_t offset, + uint32_t alignment, + int link, + int info, + uint32_t flags) +{ + rtems_rtl_obj_sect_t* sect = malloc (sizeof (rtems_rtl_obj_sect_t)); + if (!sect) + { + rtems_rtl_set_error (ENOMEM, "adding allocated section"); + return false; + } + sect->section = section; + sect->name = strdup (name); + sect->size = size; + sect->offset = offset; + sect->alignment = alignment; + sect->link = link; + sect->info = info; + sect->flags = flags; + sect->base = NULL; + rtems_chain_append (&obj->sections, §->node); + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_SECTION)) + printf ("sect: %-2d: %s\n", section, name); + + return true; +} + +void +rtems_rtl_obj_erase_sections (rtems_rtl_obj_t* obj) +{ + rtems_chain_node* node = rtems_chain_first (&obj->sections); + while (!rtems_chain_is_tail (&obj->sections, node)) + { + rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node; + rtems_chain_node* next_node = rtems_chain_next (node); + rtems_chain_extract (node); + free ((void*) sect->name); + free (node); + node = next_node; + } +} + +/** + * Section finder iterator data. + */ +typedef struct +{ + rtems_rtl_obj_sect_t* sect; /**< The matching section. */ + const char* name; /**< The name to match. */ + int index; /**< The index to match. */ +} rtems_rtl_obj_sect_finder_t; + +static bool +rtems_rtl_obj_sect_match_name (rtems_chain_node* node, void* data) +{ + rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node; + rtems_rtl_obj_sect_finder_t* match = data; + if (strcmp (sect->name, match->name) == 0) + { + match->sect = sect; + return false; + } + return true; +} + +rtems_rtl_obj_sect_t* +rtems_rtl_obj_find_section (rtems_rtl_obj_t* obj, const char* name) +{ + rtems_rtl_obj_sect_finder_t match; + match.sect = NULL; + match.name = name; + rtems_rtl_chain_iterate (&obj->sections, + rtems_rtl_obj_sect_match_name, + &match); + return match.sect; +} + +static bool +rtems_rtl_obj_sect_match_index (rtems_chain_node* node, void* data) +{ + rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node; + rtems_rtl_obj_sect_finder_t* match = data; + if (sect->section == match->index) + { + match->sect = sect; + return false; + } + return true; +} + +rtems_rtl_obj_sect_t* +rtems_rtl_obj_find_section_by_index (rtems_rtl_obj_t* obj, int index) +{ + rtems_rtl_obj_sect_finder_t match; + match.sect = NULL; + match.index = index; + rtems_rtl_chain_iterate (&obj->sections, + rtems_rtl_obj_sect_match_index, + &match); + return match.sect; +} + +size_t +rtems_rtl_obj_text_size (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_TEXT); +} + +uint32_t +rtems_rtl_obj_text_alignment (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_TEXT); +} + +size_t +rtems_rtl_obj_const_size (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_CONST); +} + +uint32_t +rtems_rtl_obj_const_alignment (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_CONST); +} + +size_t +rtems_rtl_obj_data_size (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_DATA); +} + +uint32_t +rtems_rtl_obj_data_alignment (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_DATA); +} + +size_t +rtems_rtl_obj_bss_size (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_BSS); +} + +uint32_t +rtems_rtl_obj_bss_alignment (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_BSS); +} + +bool +rtems_rtl_obj_relocate (rtems_rtl_obj_t* obj, + int fd, + rtems_rtl_obj_sect_handler_t handler, + void* data) +{ + uint32_t mask = RTEMS_RTL_OBJ_SECT_REL | RTEMS_RTL_OBJ_SECT_RELA; + return rtems_rtl_obj_section_handler (mask, obj, fd, handler, data); +} + +bool +rtems_rtl_obj_load_symbols (rtems_rtl_obj_t* obj, + int fd, + rtems_rtl_obj_sect_handler_t handler, + void* data) +{ + uint32_t mask = RTEMS_RTL_OBJ_SECT_SYM; + return rtems_rtl_obj_section_handler (mask, obj, fd, handler, data); +} + +static size_t +rtems_rtl_obj_sections_loader (rtems_chain_control* sections, + uint32_t mask, + int fd, + off_t offset, + uint8_t* base) +{ + rtems_chain_node* node = rtems_chain_first (sections); + size_t base_offset = 0; + bool first = true; + while (!rtems_chain_is_tail (sections, node)) + { + rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node; + + if ((sect->size != 0) && ((sect->flags & mask) != 0)) + { + uint8_t* sect_base = base + base_offset; + + if (!first) + base_offset = rtems_rtl_sect_align (base_offset, sect->alignment); + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT)) + printf ("rtl: loading: %s -> %8p (%zi)\n", + sect->name, base + base_offset, sect->size); + + if ((sect->flags & RTEMS_RTL_OBJ_SECT_LOAD) == RTEMS_RTL_OBJ_SECT_LOAD) + { + size_t len; + + if (lseek (fd, offset + sect->offset, SEEK_SET) < 0) + { + rtems_rtl_set_error (errno, "section load seek failed"); + return false; + } + + len = sect->size; + while (len) + { + ssize_t r = read (fd, base + base_offset, len); + if (r <= 0) + { + rtems_rtl_set_error (errno, "section load read failed"); + return false; + } + base_offset += r; + len -= r; + } + } + else if ((sect->flags & RTEMS_RTL_OBJ_SECT_ZERO) == RTEMS_RTL_OBJ_SECT_ZERO) + { + memset (base + base_offset, 0, sect->size); + base_offset += sect->size; + } + else + { + rtems_rtl_set_error (errno, "section has no load op"); + return false; + } + + sect->base = sect_base; + first = false; + } + + node = rtems_chain_next (node); + } + + return true; +} + +bool +rtems_rtl_obj_load_sections (rtems_rtl_obj_t* obj, int fd) +{ + size_t text_size; + size_t const_size; + size_t data_size; + size_t bss_size; + + text_size = rtems_rtl_obj_text_size (obj) + rtems_rtl_obj_const_alignment (obj); + const_size = rtems_rtl_obj_const_size (obj) + rtems_rtl_obj_data_alignment (obj); + data_size = rtems_rtl_obj_data_size (obj) + rtems_rtl_obj_bss_alignment (obj); + bss_size = rtems_rtl_obj_bss_size (obj); + + /* + * The object file's memory allocated on the heap. This should be the + * first allocation and any temporary allocations come after this + * so the heap does not become fragmented. + */ + obj->exec_size = text_size + const_size + data_size + bss_size; + obj->text_base = malloc (obj->exec_size); + if (!obj->text_base) + { + obj->exec_size = 0; + rtems_rtl_set_error (ENOMEM, "no memory to load obj"); + return false; + } + + obj->const_base = obj->text_base + text_size; + obj->data_base = obj->const_base + const_size; + obj->bss_base = obj->data_base + data_size; + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT)) + { + printf ("rtl: load sect: text - b:%p s:%zi a:%" PRIu32 "\n", + obj->text_base, text_size, rtems_rtl_obj_text_alignment (obj)); + printf ("rtl: load sect: const - b:%p s:%zi a:%" PRIu32 "\n", + obj->const_base, const_size, rtems_rtl_obj_const_alignment (obj)); + printf ("rtl: load sect: data - b:%p s:%zi a:%" PRIu32 "\n", + obj->data_base, data_size, rtems_rtl_obj_data_alignment (obj)); + printf ("rtl: load sect: bss - b:%p s:%zi a:%" PRIu32 "\n", + obj->bss_base, bss_size, rtems_rtl_obj_bss_alignment (obj)); + } + + /* + * Load all text then data then bss sections in seperate operations so each + * type of section is grouped together. + */ + if (!rtems_rtl_obj_sections_loader (&obj->sections, RTEMS_RTL_OBJ_SECT_TEXT, + fd, obj->ooffset, obj->text_base) || + !rtems_rtl_obj_sections_loader (&obj->sections, RTEMS_RTL_OBJ_SECT_CONST, + fd, obj->ooffset, obj->const_base) || + !rtems_rtl_obj_sections_loader (&obj->sections, RTEMS_RTL_OBJ_SECT_DATA, + fd, obj->ooffset, obj->data_base) || + !rtems_rtl_obj_sections_loader (&obj->sections, RTEMS_RTL_OBJ_SECT_BSS, + fd, obj->ooffset, obj->bss_base)) + { + free (obj->text_base); + obj->exec_size = 0; + obj->text_base = 0; + obj->data_base = 0; + obj->bss_base = 0; + return false; + } + + return true; +} + +static void +rtems_rtl_obj_run_cdtors (rtems_rtl_obj_t* obj, uint32_t mask) +{ + rtems_chain_node* node = rtems_chain_first (&obj->sections); + while (!rtems_chain_is_tail (&obj->sections, node)) + { + rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node; + if ((sect->flags & mask) == mask) + { + rtems_rtl_cdtor_t* handler; + size_t handlers = sect->size / sizeof (rtems_rtl_cdtor_t); + int c; + for (c = 0, handler = sect->base; c < handlers; ++c) + if (*handler) + (*handler) (); + } + node = rtems_chain_next (node); + } +} + +void +rtems_rtl_obj_run_ctors (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_obj_run_cdtors (obj, RTEMS_RTL_OBJ_SECT_CTOR); +} + +void +rtems_rtl_obj_run_dtors (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_obj_run_cdtors (obj, RTEMS_RTL_OBJ_SECT_DTOR); +} + +/** + * Find a module in an archive returning the offset in the archive in the + * object descriptor. + */ +static bool +rtems_rtl_obj_archive_find (rtems_rtl_obj_t* obj, int fd) +{ +#define RTEMS_RTL_AR_IDENT "!<arch>\n" +#define RTEMS_RTL_AR_IDENT_SIZE (sizeof (RTEMS_RTL_AR_IDENT) - 1) +#define RTEMS_RTL_AR_FHDR_BASE RTEMS_RTL_AR_IDENT_SIZE +#define RTEMS_RTL_AR_FNAME (0) +#define RTEMS_RTL_AR_FNAME_SIZE (16) +#define RTEMS_RTL_AR_SIZE (48) +#define RTEMS_RTL_AR_SIZE_SIZE (10) +#define RTEMS_RTL_AR_MAGIC (58) +#define RTEMS_RTL_AR_MAGIC_SIZE (2) +#define RTEMS_RTL_AR_FHDR_SIZE (60) + + size_t fsize = obj->fsize; + off_t extended_file_names; + uint8_t header[RTEMS_RTL_AR_FHDR_SIZE]; + bool scanning; + + if (read (fd, &header[0], RTEMS_RTL_AR_IDENT_SIZE) != RTEMS_RTL_AR_IDENT_SIZE) + { + rtems_rtl_set_error (errno, "reading archive identifer"); + return false; + } + + if (memcmp (header, RTEMS_RTL_AR_IDENT, RTEMS_RTL_AR_IDENT_SIZE) != 0) + { + rtems_rtl_set_error (EINVAL, "invalid archive identifer"); + return false; + } + + /* + * Seek to the current offset in the archive and if we have a valid archive + * file header present check the file name for a match with the oname field + * of the object descriptor. If the archive header is not valid and it is the + * first pass reset the offset and start the search again in case the offset + * provided is not valid any more. + * + * The archive can have a symbol table at the start. Ignore it. A symbol + * table has the file name '/'. + * + * The archive can also have the GNU extended file name table. This + * complicates the processing. If the object's file name starts with '/' the + * remainder of the file name is an offset into the extended file name + * table. To find the extended file name table we need to scan from start of + * the archive for a file name of '//'. Once found we remeber the table's + * start and can direct seek to file name location. In other words the scan + * only happens once. + * + * If the name had the offset encoded we go straight to that location. + */ + + if (obj->ooffset != 0) + scanning = false; + else + { + scanning = true; + obj->ooffset = RTEMS_RTL_AR_FHDR_BASE; + } + + extended_file_names = 0; + + while (obj->ooffset < fsize) + { + /* + * Clean up any existing data so + */ + memset (header, 0, sizeof (header)); + + if (!rtems_rtl_seek_read (fd, obj->ooffset, RTEMS_RTL_AR_FHDR_SIZE, &header[0])) + { + rtems_rtl_set_error (errno, "seek/read archive file header"); + obj->ooffset = 0; + obj->fsize = 0; + return false; + } + + if ((header[RTEMS_RTL_AR_MAGIC] != 0x60) || + (header[RTEMS_RTL_AR_MAGIC + 1] != 0x0a)) + { + if (scanning) + { + rtems_rtl_set_error (EINVAL, "invalid archive file header"); + obj->ooffset = 0; + obj->fsize = 0; + return false; + } + + scanning = true; + obj->ooffset = RTEMS_RTL_AR_FHDR_BASE; + continue; + } + + /* + * The archive header is always aligned to an even address. + */ + obj->fsize = (rtems_rtl_scan_decimal (&header[RTEMS_RTL_AR_SIZE], + RTEMS_RTL_AR_SIZE_SIZE) + 1) & ~1; + + /* + * Check for the GNU extensions. + */ + if (header[0] == '/') + { + off_t extended_off; + + switch (header[1]) + { + case ' ': + /* + * Symbols table. Ignore the table. + */ + break; + case '/': + /* + * Extended file names table. Remember. + */ + extended_file_names = obj->ooffset + RTEMS_RTL_AR_FHDR_SIZE; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + /* + * Offset into the extended file name table. If we do not have the + * offset to the extended file name table find it. + */ + extended_off = + rtems_rtl_scan_decimal (&header[1], RTEMS_RTL_AR_FNAME_SIZE); + + if (extended_file_names == 0) + { + off_t off = obj->ooffset; + while (extended_file_names == 0) + { + off_t esize = + (rtems_rtl_scan_decimal (&header[RTEMS_RTL_AR_SIZE], + RTEMS_RTL_AR_SIZE_SIZE) + 1) & ~1; + off += esize + RTEMS_RTL_AR_FHDR_SIZE; + + if (!rtems_rtl_seek_read (fd, off, + RTEMS_RTL_AR_FHDR_SIZE, &header[0])) + { + rtems_rtl_set_error (errno, + "seeking/reading archive ext file name header"); + obj->ooffset = 0; + obj->fsize = 0; + return false; + } + + if ((header[RTEMS_RTL_AR_MAGIC] != 0x60) || + (header[RTEMS_RTL_AR_MAGIC + 1] != 0x0a)) + { + rtems_rtl_set_error (errno, "invalid archive file header"); + obj->ooffset = 0; + obj->fsize = 0; + return false; + } + + if ((header[0] == '/') && (header[1] == '/')) + { + extended_file_names = off + RTEMS_RTL_AR_FHDR_SIZE; + break; + } + } + } + + if (extended_file_names) + { + /* + * We know the offset in the archive to the extended file. Read the + * name from the table and compare with the name we are after. + */ +#define RTEMS_RTL_MAX_FILE_SIZE (256) + char name[RTEMS_RTL_MAX_FILE_SIZE]; + + if (!rtems_rtl_seek_read (fd, extended_file_names + extended_off, + RTEMS_RTL_MAX_FILE_SIZE, (uint8_t*) &name[0])) + { + rtems_rtl_set_error (errno, + "invalid archive ext file seek/read"); + obj->ooffset = 0; + obj->fsize = 0; + return false; + } + + if (rtems_rtl_match_name (obj, name)) + { + obj->ooffset += RTEMS_RTL_AR_FHDR_SIZE; + return true; + } + } + break; + default: + /* + * Ignore the file because we do not know what it it. + */ + break; + } + } + else + { + if (rtems_rtl_match_name (obj, (const char*) &header[RTEMS_RTL_AR_FNAME])) + { + obj->ooffset += RTEMS_RTL_AR_FHDR_SIZE; + return true; + } + } + + obj->ooffset += obj->fsize + RTEMS_RTL_AR_FHDR_SIZE; + + } + + rtems_rtl_set_error (ENOENT, "object file not found"); + obj->ooffset = 0; + obj->fsize = 0; + return false; +} + +bool +rtems_rtl_obj_load (rtems_rtl_obj_t* obj) +{ + int fd; + + if (!obj->fname) + { + rtems_rtl_set_error (ENOMEM, "invalid object file name path"); + return false; + } + + fd = open (obj->fname, O_RDONLY); + if (fd < 0) + { + rtems_rtl_set_error (ENOMEM, "opening for object file"); + return false; + } + + /* + * Find the object file in the archive if it is an archive that + * has been opened. + */ + if (obj->aname != NULL) + { + if (!rtems_rtl_obj_archive_find (obj, fd)) + { + rtems_rtl_obj_caches_flush (); + close (fd); + return false; + } + } + + /* + * Call the format specific loader. Currently this is a call to the ELF + * loader. This call could be changed to allow probes then calls if more than + * one format is supported. + */ + if (!rtems_rtl_obj_file_load (obj, fd)) + { + rtems_rtl_obj_caches_flush (); + close (fd); + return false; + } + + rtems_rtl_obj_caches_flush (); + + close (fd); + + return true; +} + +bool +rtems_rtl_obj_unload (rtems_rtl_obj_t* obj) +{ + rtems_rtl_obj_symbol_erase (obj); + return rtems_rtl_obj_free (obj); +} diff --git a/rtl-obj.h b/rtl-obj.h new file mode 100644 index 0000000..5074056 --- /dev/null +++ b/rtl-obj.h @@ -0,0 +1,423 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtl + * + * @brief RTEMS Run-Time Linker Object Support. + */ + +#if !defined (_RTEMS_RTL_MAP_H_) +#define _RTEMS_RTL_MAP_H_ + +#include <rtems.h> +#include <rtems/chain.h> +#include <rtl-sym.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * Flags for the various section types. + */ +#define RTEMS_RTL_OBJ_SECT_TEXT (1 << 0) /**< Section holds program text. */ +#define RTEMS_RTL_OBJ_SECT_CONST (1 << 1) /**< Section holds program text. */ +#define RTEMS_RTL_OBJ_SECT_DATA (1 << 2) /**< Section holds program data. */ +#define RTEMS_RTL_OBJ_SECT_BSS (1 << 3) /**< Section holds program bss. */ +#define RTEMS_RTL_OBJ_SECT_REL (1 << 4) /**< Section holds relocation records. */ +#define RTEMS_RTL_OBJ_SECT_RELA (1 << 5) /**< Section holds relocation addend + * records. */ +#define RTEMS_RTL_OBJ_SECT_SYM (1 << 6) /**< Section holds symbols. */ +#define RTEMS_RTL_OBJ_SECT_STR (1 << 7) /**< Section holds strings. */ +#define RTEMS_RTL_OBJ_SECT_ALLOC (1 << 8) /**< Section allocates runtime memory. */ +#define RTEMS_RTL_OBJ_SECT_LOAD (1 << 9) /**< Section is loaded from object file. */ +#define RTEMS_RTL_OBJ_SECT_WRITE (1 << 10) /**< Section is writable, ie data. */ +#define RTEMS_RTL_OBJ_SECT_EXEC (1 << 11) /**< Section is executable. */ +#define RTEMS_RTL_OBJ_SECT_ZERO (1 << 12) /**< Section is preset to zero. */ +#define RTEMS_RTL_OBJ_SECT_CTOR (1 << 13) /**< Section contains constructors. */ +#define RTEMS_RTL_OBJ_SECT_DTOR (1 << 14) /**< Section contains destructors. */ + +/** + * An object file is made up of sections and the can be more than + * one of a specific type of sections. All sections and grouped + * together in memory. + */ +struct rtems_rtl_obj_sect_s +{ + rtems_chain_node node; /**< The node's link in the chain. */ + int section; /**< The section number. */ + const char* name; /**< The section's name. */ + size_t size; /**< The size of the section in memory. */ + off_t offset; /**< Offset into the object file. Relative to + * the start of the object file. */ + uint32_t alignment; /**< Alignment of this section. */ + int link; /**< Section link field. */ + int info; /**< Secfion info field. */ + uint32_t flags; /**< The section's flags. */ + void* base; /**< The base address of the section in + * memory. */ +}; + +/** + * Object file descriptor flags. + */ +#define RTEMS_RTL_OBJ_LOCKED (1 << 0) /**< Lock the object file so it cannot + * be unloaded. */ +#define RTEMS_RTL_OBJ_UNRESOLVED (1 << 1) /**< The object file has unresolved + * external symbols. */ + +/** + * RTL Object. There is one for each object module loaded plus one for the base + * kernel image. + */ +struct rtems_rtl_obj_s +{ + rtems_chain_node link; /**< The node's link in the chain. */ + uint32_t flags; /**< The status of the object file. */ + uint32_t users; /**< References to the object file. */ + const char* fname; /**< The file name for the object. */ + const char* oname; /**< The object file name. Can be + * relative. */ + const char* aname; /**< The archive name containing the + * object. NULL means the object is not + * in a lib */ + off_t ooffset; /**< The object offset in the archive. */ + size_t fsize; /**< Size of the object file. */ + rtems_chain_control sections; /**< The sections of interest in the + * object file. */ + rtems_rtl_obj_sym_t* global_table; /**< Global symbol table. */ + size_t global_syms; /**< Global symbol count. */ + size_t global_size; /**< Global symbol memory usage. */ + void* text_base; /**< The base address of the text section + * in memory. */ + void* const_base; /**< The base address of the const section + * in memory. */ + void* data_base; /**< The base address of the data section + * in memory. */ + void* bss_base; /**< The base address of the bss section + * in memory. */ + size_t bss_size; /**< The size of the bss section. */ + size_t exec_size; /**< The amount of executable memory + * allocated */ + void* entry; /**< The entry point of the module. */ + uint32_t checksum; /**< The checksum of the text sections. A + * zero means do not checksum. */ +}; + +/** + * A section handler is called once for each section that needs to be + * processed by this handler. + * + * @param obj The object file's descriptor the section belongs too. + * @param fd The file descriptor of the object file beling loaded. + * @param sect The section the handler is being invoked to handle. + * @param data A user supplied data variable. + * @retval true The operation was successful. + * @retval false The operation failed and the RTL has been set. + */ +typedef bool (*rtems_rtl_obj_sect_handler_t)(rtems_rtl_obj_t* obj, + int fd, + rtems_rtl_obj_sect_t* sect, + void* data); + +/** + * Allocate an object structure on the heap. + * + * @retval NULL No memory for the object. + */ +rtems_rtl_obj_t* rtems_rtl_obj_alloc (void); + +/** + * Free the object structure and related resources. + * + * @param obj The object file's descriptor to free. + * @retval false The object has dependences. + * @retval true The object has been freed. + */ +bool rtems_rtl_obj_free (rtems_rtl_obj_t* obj); + +/** + * Does the object file have unresolved external references ? If it does the + * results of executing code is unpredictable. + * + * @param obj The object file's descriptor. + * @retval true The object file has unresolved externals. + * @retval false The object file has all external references resolved. + */ +bool rtems_rtl_obj_unresolved (rtems_rtl_obj_t* obj); + +/** + * Load the object file. + * + * @param obj The object file's descriptor. + * @param fd The file descriptor. + * @param load_syms Load symbols. + * @param load_dep Load dependent object files. + * @retval true The load was successful. + * @retval false The load failed. The RTL error has been set. + */ +bool rtems_rtl_obj_file_load (rtems_rtl_obj_t* obj, int fd); + +/** + * Check of the name matches the object file's object name. + * + * @param obj The object file's descriptor. + * @param name The name to match. + */ +bool rtems_rtl_match_name (rtems_rtl_obj_t* obj, const char* name); + +/** + * Find an object file on disk that matches the name. The object descriptor is + * fill in with the various parts of a name. A name can have archive, object + * file and offset components. The search path in the RTL is searched. + * + * @param obj The object file's descriptor. + * @param name The name to locate on disk. + * @retval true The file has been found. + * @retval false The file could not be located. The RTL error has been set. + */ +bool rtems_rtl_obj_find_file (rtems_rtl_obj_t* obj, const char* name); + +/** + * Add a section to the object descriptor. + * + * @param obj The object file's descriptor. + * @param section The section's index number. + * @param name The name of the section. + * @param size The size of the section in memory. + * @param offset The offset of the section in the object file. + * @param alignment The alignment of the section in memory. + * @param link The section's link field (from the ELF format). + * @param info The section's info field (from the ELF format). + * @param flags The section's flags. + * @retval true The section has been added. + * @retval false The section has not been added. See the RTL error. + */ +bool rtems_rtl_obj_add_section (rtems_rtl_obj_t* obj, + int section, + const char* name, + size_t size, + off_t offset, + uint32_t alignment, + int link, + int info, + uint32_t flags); + +/** + * Erase the object file descriptor's sections. + * + * @param obj The object file's descriptor. + */ +void rtems_rtl_obj_erase_sections (rtems_rtl_obj_t* obj); + +/** + * Find the section given a name. + * + * @param obj The object file's descriptor. + * @param name The name of the section to find. + * @retval NULL The section was not found. + * @return rtems_rtl_obj_sect_t* The named section. + */ +rtems_rtl_obj_sect_t* rtems_rtl_obj_find_section (rtems_rtl_obj_t* obj, + const char* name); + +/** + * Find a section given a section's index number. + * + * @param obj The object file's descriptor. + * @param index The section's index to find. + * @retval NULL The section was not found. + * @return rtems_rtl_obj_sect_t* The found section. + */ +rtems_rtl_obj_sect_t* rtems_rtl_obj_find_section_by_index (rtems_rtl_obj_t* obj, + int index); + +/** + * The text size of the object file. Only use once all the sections has been + * added. It includes alignments between sections that are part of the object's + * text area. The consts sections are included in this section. + * + * @param obj The object file's descriptor. + * @return size_t The size of the text area of the object file. + */ +size_t rtems_rtl_obj_text_size (rtems_rtl_obj_t* obj); + +/** + * The text section alignment of the object file. Only use once all the + * sections has been added. The section alignment is the alignment of the first + * text type section loaded the text section. + * + * You can assume the alignment is a positive integral power of 2 if not 0 or + * 1. If 0 or 1 then there is no alignment. + * + * @param obj The object file's descriptor. + * @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment. + */ +uint32_t rtems_rtl_obj_text_alignment (rtems_rtl_obj_t* obj); + +/** + * The const size of the object file. Only use once all the sections has been + * added. It includes alignments between sections that are part of the object's + * const area. The consts sections are included in this section. + * + * @param obj The object file's descriptor. + * @return size_t The size of the const area of the object file. + */ +size_t rtems_rtl_obj_const_size (rtems_rtl_obj_t* obj); + +/** + * The const section alignment of the object file. Only use once all the + * sections has been added. The section alignment is the alignment of the first + * const type section loaded the const section. + * + * You can assume the alignment is a positive integral power of 2 if not 0 or + * 1. If 0 or 1 then there is no alignment. + * + * @param obj The object file's descriptor. + * @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment. + */ +uint32_t rtems_rtl_obj_const_alignment (rtems_rtl_obj_t* obj); + +/** + * The data size of the object file. Only use once all the sections has been + * added. It includes alignments between sections that are part of the object's + * data area. + * + * @param obj The object file's descriptor. + * @return size_t The size of the data area of the object file. + */ +size_t rtems_rtl_obj_data_size (rtems_rtl_obj_t* obj); + +/** + * The data section alignment of the object file. Only use once all the + * sections has been added. The section alignment is the alignment of the first + * data type section loaded the data section. + * + * You can assume the alignment is a positive integral power of 2 if not 0 or + * 1. If 0 or 1 then there is no alignment. + * + * @param obj The object file's descriptor. + * @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment. + */ +uint32_t rtems_rtl_obj_data_alignment (rtems_rtl_obj_t* obj); + +/** + * The bss size of the object file. Only use once all the sections has been + * added. It includes alignments between sections that are part of the object's + * bss area. + * + * @param obj The object file's descriptor. + * @return size_t The size of the bss area of the object file. + */ +size_t rtems_rtl_obj_bss_size (rtems_rtl_obj_t* obj); + +/** + * The bss section alignment of the object file. Only use once all the + * sections has been added. The section alignment is the alignment of the first + * bss type section loaded the bss section. + * + * You can assume the alignment is a positive integral power of 2 if not 0 or + * 1. If 0 or 1 then there is no alignment. + * + * @param obj The object file's descriptor. + * @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment. + */ +uint32_t rtems_rtl_obj_bss_alignment (rtems_rtl_obj_t* obj); + +/** + * Relocate the object file. The object file's section are parsed for any + * relocation type sections. + * + * @param obj The object file's descriptor. + * @param fd The object file's file descriptor. + * @param handler The object file's format specific relocation handler. + * @param data User specific data handle. + * @retval true The object file was relocated. + * @retval false The relocation failed. The RTL error is set. + */ +bool rtems_rtl_obj_relocate (rtems_rtl_obj_t* obj, + int fd, + rtems_rtl_obj_sect_handler_t handler, + void* data); + +/** + * Load the symbols from the object file. Only the exported or public symbols + * are read into memory and held in the global symbol table. + * + * @param obj The object file's descriptor. + * @param fd The object file's file descriptor. + * @param handler The object file's format specific symbol handler. + * @param data User specific data handle. + * @retval true The object file's symbol where loaded. + * @retval false The symbol loading failed. The RTL error is set. + */ +bool rtems_rtl_obj_load_symbols (rtems_rtl_obj_t* obj, + int fd, + rtems_rtl_obj_sect_handler_t handler, + void* data); + +/** + * Load the sections that have been allocated memory in the target. The bss + * type section does not load any data, it is set to 0. The text and data + * sections read the detault data from the object file into the target memory. + * + * @param obj The object file's descriptor. + * @param fd The object file's file descriptor. + * @retval true The object has been sucessfully loaded. + * @retval false The load failed. The RTL error has been set. + */ +bool rtems_rtl_obj_load_sections (rtems_rtl_obj_t* obj, int fd); + +/** + * Invoke the constructors the object has. Constructors are a table of pointers + * to "void (*)(void);" where NULL pointers are skipped. The table's size is + * taken from the section's size. The objet ELF specific code is responisble + * for flagging which sections contain constructors. + * + * @param obj The object file's descriptor. + */ +void rtems_rtl_obj_run_ctors (rtems_rtl_obj_t* obj); + +/** + * Invoke the destructors the object has. Destructors are a table of pointers + * to "void (*)(void);" where NULL pointers are skipped. The table's size is + * taken from the section's size. The objet ELF specific code is responisble + * for flagging which sections contain destructors. + * + * @param obj The object file's descriptor. + */ +void rtems_rtl_obj_run_dtors (rtems_rtl_obj_t* obj); + +/** + * Load the object file, reading all sections into memory, symbols and + * performing any relocation fixups. + * + * @param obj The object file's descriptor. + * @retval true The object file has been loaded. + * @retval false The load failed. The RTL error has been set. + */ +bool rtems_rtl_obj_load (rtems_rtl_obj_t* obj); + +/** + * Unload the object file, erasing all symbols and releasing all memory. + * + * @param obj The object file's descriptor. + * @retval true The object file has been unloaded. + * @retval false The unload failed. The RTL error has been set. + */ +bool rtems_rtl_obj_unload (rtems_rtl_obj_t* obj); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/rtl-shell.c b/rtl-shell.c new file mode 100644 index 0000000..fac9509 --- /dev/null +++ b/rtl-shell.c @@ -0,0 +1,314 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtld + * + * @brief RTEMS Run-Time Link Editor Shell Commands + * + * A simple RTL command to aid using the RTL. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <inttypes.h> + +//#if SIZEOF_OFF_T == 8 +#define PRIdoff_t PRIo64 +//#elif SIZEOF_OFF_T == 4 +//#define PRIdoff_t PRIo32 +//#else +//#error "unsupported size of off_t" +//#endif + +#include <stdio.h> +#include <string.h> + +#include <rtl.h> +#include <rtl-chain-iterator.h> +#include <rtl-trace.h> + +/** + * The type of the shell handlers we have. + */ +typedef int (*rtems_rtl_shell_handler_t) (rtems_rtl_data_t* rtl, int argc, char *argv[]); + +/** + * Table of handlers we parse to invoke the command. + */ +typedef struct +{ + const char* name; /**< The sub-command's name. */ + rtems_rtl_shell_handler_t handler; /**< The sub-command's handler. */ + const char* help; /**< The sub-command's help. */ +} rtems_rtl_shell_cmd_t; + +/** + * Object summary data. + */ +typedef struct +{ + int count; /**< The number of object files. */ + size_t exec; /**< The amount of executable memory allocated. */ + size_t symbols; /**< The amount of symbol memory allocated. */ +} rtems_rtl_obj_summary_t; + +/** + * Object summary iterator. + */ +static bool +rtems_rtl_obj_summary_iterator (rtems_chain_node* node, void* data) +{ + rtems_rtl_obj_summary_t* summary = data; + rtems_rtl_obj_t* obj = (rtems_rtl_obj_t*) node; + ++summary->count; + summary->exec += obj->exec_size; + summary->symbols += obj->global_size; + return true; +} + +/** + * Count the number of symbols. + */ +static int +rtems_rtl_count_symbols (rtems_rtl_data_t* rtl) +{ + int count; + int bucket; + for (count = 0, bucket = 0; bucket < rtl->globals.nbuckets; ++bucket) + count += rtems_rtl_chain_count (&rtl->globals.buckets[bucket]); + return count; +} + +static int +rtems_rtl_shell_status (rtems_rtl_data_t* rtl, int argc, char *argv[]) +{ + rtems_rtl_obj_summary_t summary; + size_t total_memory; + + summary.count = 0; + summary.exec = 0; + summary.symbols = 0; + rtems_rtl_chain_iterate (&rtl->objects, + rtems_rtl_obj_summary_iterator, + &summary); + /* + * Currently does not include the name strings in the obj struct. + */ + total_memory = + sizeof (*rtl) + (summary.count * sizeof (rtems_rtl_obj_t)) + + summary.exec + summary.symbols; + + printf ("Runtime Linker Status:\n"); + printf (" paths: %s\n", rtl->paths); + printf (" objects: %d\n", summary.count); + printf (" total memory: %zi\n", total_memory); + printf (" exec memory: %zi\n", summary.exec); + printf (" sym memory: %zi\n", summary.symbols); + printf (" symbols: %d\n", rtems_rtl_count_symbols (rtl)); + + return 0; +} + +/** + * Object print data. + */ +typedef struct +{ + rtems_rtl_data_t* rtl; /**< The RTL data. */ + int indent; /**< Spaces to indent. */ + bool names; /**< Print details of all names. */ + bool memory_map; /**< Print the memory map. */ + bool symbols; /**< Print the global symbols. */ + bool base; /**< Include the base object file. */ +} rtems_rtl_obj_print_t; + +/** + * Return the different between 2 void*. + */ +static size_t +rtems_rtl_delta_voids (void* higher, void* lower) +{ + char* ch = higher; + char* cl = lower; + return ch - cl; +} + +/** + * Object print iterator. + */ +static bool +rtems_rtl_obj_print_iterator (rtems_chain_node* node, void* data) +{ + rtems_rtl_obj_print_t* print = data; + rtems_rtl_obj_t* obj = (rtems_rtl_obj_t*) node; + char flags_str[33]; + + /* + * Skip the base module unless asked to show it. + */ + if (!print->base && (obj == print->rtl->base)) + return true; + + printf ("%-*cobject name : %s\n", print->indent, ' ', obj->oname); + if (print->names) + { + printf ("%-*cfile name : %s\n", print->indent, ' ', obj->fname); + printf ("%-*carchive name : %s\n", print->indent, ' ', obj->aname); + strcpy (flags_str, "--"); + if (obj->flags & RTEMS_RTL_OBJ_LOCKED) + flags_str[0] = 'L'; + if (obj->flags & RTEMS_RTL_OBJ_UNRESOLVED) + flags_str[1] = 'U'; + printf ("%-*cflags : %s\n", print->indent, ' ', flags_str); + printf ("%-*cfile offset : %" PRIdoff_t "\n", print->indent, ' ', obj->ooffset); + printf ("%-*cfile size : %zi\n", print->indent, ' ', obj->fsize); + } + printf ("%-*cexec size : %zi\n", print->indent, ' ', obj->exec_size); + if (print->memory_map) + { + printf ("%-*ctext base : %p (%zi)\n", print->indent, ' ', + obj->text_base, rtems_rtl_delta_voids (obj->const_base, obj->text_base)); + printf ("%-*cconst base : %p (%zi)\n", print->indent, ' ', + obj->const_base, rtems_rtl_delta_voids (obj->data_base, obj->const_base)); + printf ("%-*cdata base : %p (%zi)\n", print->indent, ' ', + obj->data_base, rtems_rtl_delta_voids (obj->bss_base, obj->data_base)); + printf ("%-*cbss base : %p (%zi)\n", print->indent, ' ', + obj->bss_base, obj->bss_size); + } + printf ("%-*csymbols : %zi\n", print->indent, ' ', obj->global_syms); + printf ("%-*csymbol memory : %zi\n", print->indent, ' ', obj->global_size); + if (print->symbols) + { + int max_len = 0; + int s; + for (s = 0; s < obj->global_syms; ++s) + { + int len = strlen (obj->global_table[s].name); + if (len > max_len) + max_len = len; + } + for (s = 0; s < obj->global_syms; ++s) + printf ("%-*c%-*s = %p\n", print->indent + 2, ' ', + max_len, obj->global_table[s].name, obj->global_table[s].value); + } + return true; +} + +static int +rtems_rtl_shell_list (rtems_rtl_data_t* rtl, int argc, char *argv[]) +{ + rtems_rtl_obj_print_t print; + print.rtl = rtl; + print.indent = 1; + print.names = true; + print.memory_map = true; + print.symbols = true; + print.base = false; + rtems_rtl_chain_iterate (&rtl->objects, + rtems_rtl_obj_print_iterator, + &print); + return 0; +} + +static int +rtems_rtl_shell_sym (rtems_rtl_data_t* rtl, int argc, char *argv[]) +{ + return 0; +} + +static int +rtems_rtl_shell_object (rtems_rtl_data_t* rtl, int argc, char *argv[]) +{ + return 0; +} + +void +rtems_rtl_shell_usage (const char* arg) +{ + printf ("%s: Runtime Linker\n", arg); + printf (" %s [-hl] <command>\n", arg); + printf (" where:\n"); + printf (" command: A n RTL command. See -l for a list plus help.\n"); + printf (" -h: This help\n"); + printf (" -l: The command list.\n"); +} + +int +rtems_rtl_shell_command (int argc, char* argv[]) +{ + const rtems_rtl_shell_cmd_t table[] = + { + { "status", rtems_rtl_shell_status, + "Display the status of the RTL" }, + { "list", rtems_rtl_shell_list, + "\tList the object files currently loaded" }, + { "sym", rtems_rtl_shell_sym, + "\tDisplay the symbols, sym [<name>], sym -o <obj> [<name>]" }, + { "obj", rtems_rtl_shell_object, + "\tDisplay the object details, obj <name>" } + }; + + int arg; + int t; + + for (arg = 1; arg < argc; arg++) + { + if (argv[arg][0] != '-') + break; + + switch (argv[arg][1]) + { + case 'h': + rtems_rtl_shell_usage (argv[0]); + return 0; + case 'l': + printf ("%s: commands are:\n", argv[0]); + for (t = 0; + t < (sizeof (table) / sizeof (const rtems_rtl_shell_cmd_t)); + ++t) + printf (" %s\t%s\n", table[t].name, table[t].help); + return 0; + default: + printf ("error: unknown option: %s\n", argv[arg]); + return 1; + } + } + + if ((argc - arg) < 1) + printf ("error: you need to provide a command, try %s -h\n", argv[0]); + else + { + for (t = 0; + t < (sizeof (table) / sizeof (const rtems_rtl_shell_cmd_t)); + ++t) + { + if (strncmp (argv[arg], table[t].name, strlen (argv[arg])) == 0) + { + rtems_rtl_data_t* rtl = rtems_rtl_data (); + int r; + if (!rtl) + { + printf ("error: cannot lock the linker\n"); + return 1; + } + r = table[t].handler (rtl, argc - 1, argv + 1); + rtems_rtl_unlock (); + return r; + } + } + printf ("error: command not found: %s (try -h)\n", argv[arg]); + } + + return 1; +} diff --git a/rtl-shell.h b/rtl-shell.h new file mode 100644 index 0000000..93b5640 --- /dev/null +++ b/rtl-shell.h @@ -0,0 +1,41 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtl + * + * @brief RTEMS Run-Time Linker ELF Shell Support. + */ + +#if !defined (_RTEMS_RTL_SHELL_H_) +#define _RTEMS_RTL_SHELL_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include <stdint.h> + +/** + * The RTL single shell command contains sub-commands. + * + * @param argc The argument count. + * @param argv Array of argument strings. + * @retval 0 No error. + * @return int The exit code. + */ +int rtems_rtl_shell_command (int argc, char* argv[]); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/rtl-sym.c b/rtl-sym.c new file mode 100644 index 0000000..dc94e24 --- /dev/null +++ b/rtl-sym.c @@ -0,0 +1,231 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtl + * + * @brief RTEMS Run-Time Linker Object File Symbol Table. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include <inttypes.h> +#include <stdlib.h> +#include <stdio.h> + +#include <rtl.h> +#include <rtl-error.h> +#include <rtl-sym.h> +#include <rtl-trace.h> + +/** + * The single symbol forced into the global symbol table that is used to load a + * symbol table from an object file. + */ +static rtems_rtl_obj_sym_t global_sym_add = +{ + .name = "rtems_rtl_base_sym_global_add", + .value = (void*) rtems_rtl_base_sym_global_add +}; + +static uint_fast32_t +rtems_rtl_symbol_hash (const char *s) +{ + uint_fast32_t h = 5381; + unsigned char c; + for (c = *s; c != '\0'; c = *++s) + h = h * 33 + c; + return h & 0xffffffff; +} + +static void +rtems_rtl_symbol_global_insert (rtems_rtl_symbols_t* symbols, + rtems_rtl_obj_sym_t* symbol) +{ + uint_fast32_t hash = rtems_rtl_symbol_hash (symbol->name); + rtems_chain_append (&symbols->buckets[hash % symbols->nbuckets], + &symbol->node); +} + +bool +rtems_rtl_symbol_table_open (rtems_rtl_symbols_t* symbols, + size_t buckets) +{ + symbols->buckets = calloc (buckets, sizeof (rtems_chain_control)); + if (!symbols->buckets) + { + rtems_rtl_set_error (ENOMEM, "no memory for global symbol table"); + return false; + } + symbols->nbuckets = buckets; + for (buckets = 0; buckets < symbols->nbuckets; ++buckets) + rtems_chain_initialize_empty (&symbols->buckets[buckets]); + rtems_rtl_symbol_global_insert (symbols, &global_sym_add); + return true; +} + +void +rtems_rtl_symbol_table_close (rtems_rtl_symbols_t* symbols) +{ + free (symbols->buckets); +} + +bool +rtems_rtl_symbol_global_add (rtems_rtl_obj_t* obj, + const unsigned char* esyms, + unsigned int size) +{ + rtems_rtl_symbols_t* symbols; + rtems_rtl_obj_sym_t* sym; + size_t count; + size_t s; + uint32_t marker; + + count = 0; + s = 0; + while ((s < size) && (esyms[s] != 0)) + { + int l = strlen ((char*) &esyms[s]); + if ((esyms[s + l] != '\0') || ((s + l) > size)) + { + rtems_rtl_set_error (EINVAL, "invalid exported symbol table"); + return false; + } + ++count; + s += l + sizeof (unsigned long) + 1; + } + + /* + * Check this is the correct end of the table. + */ + marker = esyms[s + 1]; + marker <<= 8; + marker |= esyms[s + 2]; + marker <<= 8; + marker |= esyms[s + 3]; + marker <<= 8; + marker |= esyms[s + 4]; + + if (marker != 0xdeadbeefUL) + { + rtems_rtl_set_error (ENOMEM, "invalid export symbol table"); + return false; + } + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM)) + printf ("rtl: global symbol add: %zi\n", count); + + obj->global_size = count * sizeof (rtems_rtl_obj_sym_t); + obj->global_table = malloc (obj->global_size); + if (!obj->global_table) + { + obj->global_size = 0; + rtems_rtl_set_error (ENOMEM, "no memory for global symbols"); + return false; + } + + symbols = rtems_rtl_global_symbols (); + + s = 0; + sym = obj->global_table; + + while ((s < size) && (esyms[s] != 0)) + { + /* + * Copy the void* using a union and memcpy to avoid any strict aliasing or + * alignment issues. The variable length of the label and the packed nature + * of the table means casting is not suitable. + */ + union { + uint8_t data[sizeof (void*)]; + void* value; + } copy_voidp; + int b; + + sym->name = (const char*) &esyms[s]; + s += strlen (sym->name) + 1; + for (b = 0; b < sizeof (void*); ++b, ++s) + copy_voidp.data[b] = esyms[s]; + sym->value = copy_voidp.value; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM)) + printf ("rtl: esyms: %s -> %8p\n", sym->name, sym->value); + if (rtems_rtl_symbol_global_find (sym->name) == NULL) + rtems_rtl_symbol_global_insert (symbols, sym); + ++sym; + } + + obj->global_syms = count; + + return true; +} + +rtems_rtl_obj_sym_t* +rtems_rtl_symbol_global_find (const char* name) +{ + rtems_rtl_symbols_t* symbols; + uint_fast32_t hash; + rtems_chain_control* bucket; + rtems_chain_node* node; + + symbols = rtems_rtl_global_symbols (); + + hash = rtems_rtl_symbol_hash (name); + bucket = &symbols->buckets[hash % symbols->nbuckets]; + node = rtems_chain_first (bucket); + + while (!rtems_chain_is_tail (bucket, node)) + { + rtems_rtl_obj_sym_t* sym = (rtems_rtl_obj_sym_t*) node; + /* + * Use the hash. I could add this to the symbol but it uses more memory.. + */ + if (strcmp (name, sym->name) == 0) + return sym; + node = rtems_chain_next (node); + } + + return NULL; +} + +rtems_rtl_obj_sym_t* +rtems_rtl_symbol_obj_find (rtems_rtl_obj_t* obj, const char* name) +{ + rtems_rtl_obj_sym_t* sym; + size_t s; + /* + * Check the object file's symbols first. If not found search the + * global symbol table. + */ + for (s = 0, sym = obj->global_table; s < obj->global_syms; ++s, ++sym) + if (strcmp (name, sym->name) == 0) + return sym; + return rtems_rtl_symbol_global_find (name); +} + +void +rtems_rtl_obj_symbol_erase (rtems_rtl_obj_t* obj) +{ + if (obj->global_table) + { + rtems_rtl_obj_sym_t* sym; + size_t s; + for (s = 0, sym = obj->global_table; s < obj->global_syms; ++s, ++sym) + if (!rtems_chain_is_node_off_chain (&sym->node)) + rtems_chain_extract (&sym->node); + free (obj->global_table); + obj->global_table = NULL; + obj->global_size = 0; + obj->global_syms = 0; + } +} diff --git a/rtl-sym.h b/rtl-sym.h new file mode 100644 index 0000000..aa7946e --- /dev/null +++ b/rtl-sym.h @@ -0,0 +1,122 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtl + * + * @brief RTEMS Run-Time Linker Object File Symbol Table. + */ + +#if !defined (_RTEMS_RTL_SYM_H_) +#define _RTEMS_RTL_SYM_H_ + +#include <rtems.h> +#include <rtl-obj-fwd.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * An object file symbol. + */ +typedef struct rtems_rtl_obj_sym_s +{ + rtems_chain_node node; /**< The node's link in the chain. */ + const char* name; /**< The symbol's name. */ + void* value; /**< The value of the symbol. */ +} rtems_rtl_obj_sym_t; + +/** + * Table of symbols stored in a hash table. + */ +typedef struct rtems_rtl_symbols_s +{ + rtems_chain_control* buckets; + size_t nbuckets; +} rtems_rtl_symbols_t; + +/** + * Open a symbol table with the specified number of buckets. + * + * @param symbols The symbol table to open. + * @param buckets The number of buckets in the hash table. + * @retval true The symbol is open. + * @retval false The symbol table could not created. The RTL + * error has the error. + */ +bool rtems_rtl_symbol_table_open (rtems_rtl_symbols_t* symbols, + size_t buckets); + +/** + * Close the table and erase the hash table. + * + * @param symbols Close the symbol table. + */ +void rtems_rtl_symbol_table_close (rtems_rtl_symbols_t* symbols); + +/** + * Add a table of exported symbols to the symbol table. + * + * The export table is a series of symbol records and each record has two + * fields: + * + * 1. label + * 2. address + * + * The 'label' is an ASCIIZ string of variable length. The address is of size + * of an unsigned long for the target running the link editor. The byte order + * is defined by the machine type because the table should be built by the + * target compiler. + * + * The table is terminated with a nul string followed by the bytes 0xDE, 0xAD, + * 0xBE, and 0xEF. This avoids alignments issues. + * + * @param obj The object table the symbols are for. + * @param esyms The exported symbol table. + * @param size The size of the table in bytes. + */ +bool rtems_rtl_symbol_global_add (rtems_rtl_obj_t* obj, + const unsigned char* esyms, + unsigned int size); + +/** + * Find a symbol given the symbol label in the global symbol table. + * + * @param name The name as an ASCIIZ string. + * @retval NULL No symbol found. + * @return rtems_rtl_obj_sym_t* Reference to the symbol. + */ +rtems_rtl_obj_sym_t* rtems_rtl_symbol_global_find (const char* name); + +/** + * Find a symbol given the symbol label in the local object file. + * + * @param obj The object file to search. + * @param name The name as an ASCIIZ string. + * @retval NULL No symbol found. + * @return rtems_rtl_obj_sym_t* Reference to the symbol. + */ +rtems_rtl_obj_sym_t* rtems_rtl_symbol_obj_find (rtems_rtl_obj_t* obj, + const char* name); + +/** + * Erase the object file's symbols. + * + * @param obj The object file the symbols are to be erased from. + */ +void rtems_rtl_obj_symbol_erase (rtems_rtl_obj_t* obj); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/rtl-trace.c b/rtl-trace.c new file mode 100644 index 0000000..bce9c56 --- /dev/null +++ b/rtl-trace.c @@ -0,0 +1,133 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtld + * + * @brief RTEMS Run-Time Link Editor Trace + * + * A configurable tracer for the RTL. See the header file for the enable and + * disable. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <string.h> + +#include <rtl-trace.h> + +#if RTEMS_RTL_TRACE +static rtems_rtl_trace_mask rtems_rtl_trace_flags; + +bool +rtems_rtl_trace (rtems_rtl_trace_mask mask) +{ + bool result = false; + if (mask & rtems_rtl_trace_flags) + result = true; + return result; +} + +rtems_rtl_trace_mask +rtems_rtl_trace_set_mask (rtems_rtl_trace_mask mask) +{ + rtems_rtl_trace_mask state = rtems_rtl_trace_flags; + rtems_rtl_trace_flags |= mask; + return state; +} + +rtems_rtl_trace_mask +rtems_rtl_trace_clear_mask (rtems_rtl_trace_mask mask) +{ + rtems_rtl_trace_mask state = rtems_rtl_trace_flags; + rtems_rtl_trace_flags &= ~mask; + return state; +} + +int +rtems_rtl_trace_shell_command (int argc, char *argv[]) +{ + const char* table[] = + { + "load", + "unload", + "section", + "symbol", + "reloc", + "global-sym", + "load-sect" + }; + + rtems_rtl_trace_mask set_value = 0; + rtems_rtl_trace_mask clear_value = 0; + bool set = true; + int arg; + int t; + + for (arg = 1; arg < argc; arg++) + { + if (argv[arg][0] == '-') + { + switch (argv[arg][1]) + { + case 'h': + printf ("usage: %s [-hl] [set/clear] [flags]\n", argv[0]); + return 0; + case 'l': + printf ("%s: valid flags to set or clear are:\n", argv[0]); + for (t = 0; t < (sizeof (table) / sizeof (const char*)); t++) + printf (" %s\n", table[t]); + return 0; + default: + printf ("error: unknown option\n"); + return 1; + } + } + else + { + if (strcmp (argv[arg], "set") == 0) + set = true; + if (strcmp (argv[arg], "clear") == 0) + set = false; + else if (strcmp (argv[arg], "all") == 0) + { + if (set) + set_value = RTEMS_RTL_TRACE_ALL; + else + clear_value = RTEMS_RTL_TRACE_ALL; + } + else + { + for (t = 0; t < (sizeof (table) / sizeof (const char*)); t++) + { + if (strcmp (argv[arg], table[t]) == 0) + { + if (set) + set_value = 1 << t; + else + clear_value = 1 << t; + break; + } + } + } + + rtems_rtl_trace_flags |= set_value; + rtems_rtl_trace_flags &= ~clear_value; + } + } + + return 0; +} + +#endif diff --git a/rtl-trace.h b/rtl-trace.h new file mode 100644 index 0000000..1767761 --- /dev/null +++ b/rtl-trace.h @@ -0,0 +1,99 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtl + * + * @brief RTEMS Run-Time Linker ELF Trace Support. + */ + +#if !defined (_RTEMS_RTL_TRACE_H_) +#define _RTEMS_RTL_TRACE_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include <stdbool.h> +#include <stdint.h> + +/** + * Set to 1 to build trace support in to the RTL code. + */ +#define RTEMS_RTL_TRACE 1 + +/** + * The type of the mask. + */ +typedef uint32_t rtems_rtl_trace_mask; + +/** + * List of tracing bits for the various parts of the link editor. + */ +#define RTEMS_RTL_TRACE_ALL (0xffffffffUL) +#define RTEMS_RTL_TRACE_LOAD (1UL << 0) +#define RTEMS_RTL_TRACE_UNLOAD (1UL << 1) +#define RTEMS_RTL_TRACE_SECTION (1UL << 2) +#define RTEMS_RTL_TRACE_SYMBOL (1UL << 3) +#define RTEMS_RTL_TRACE_RELOC (1UL << 4) +#define RTEMS_RTL_TRACE_GLOBAL_SYM (1UL << 5) +#define RTEMS_RTL_TRACE_LOAD_SECT (1UL << 6) + +/** + * Call to check if this part is bring traced. If RTEMS_RTL_TRACE is defined to + * 0 the code is dead code elminiated when built with -Os, -O2, or higher. + * + * @param mask The part of the API to trace. + * @retval true Tracing is active for the mask. + * @retval false Do not trace. + */ +#if RTEMS_RTL_TRACE +bool rtems_rtl_trace (rtems_rtl_trace_mask mask); +#else +#define rtems_rtl_trace(_m) (0) +#endif + +/** + * Set the mask. + * + * @param mask The mask bits to set. + * @return The previous mask. + */ +#if RTEMS_RTL_TRACE +rtems_rtl_trace_mask rtems_rtl_trace_set_mask (rtems_rtl_trace_mask mask); +#else +#define rtems_rtl_trace_set_mask(_m) +#endif + +/** + * Clear the mask. + * + * @param mask The mask bits to clear. + * @return The previous mask. + */ +#if RTEMS_RTL_TRACE +rtems_rtl_trace_mask rtems_rtl_trace_clear_mask (rtems_rtl_trace_mask mask); +#else +#define rtems_rtl_trace_clear_mask(_m) +#endif + +/** + * Add shell trace shell command. + */ +#if RTEMS_RTL_TRACE +int rtems_rtl_trace_shell_command (int argc, char *argv[]); +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif @@ -0,0 +1,520 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtld + * + * @brief RTEMS Run-Time Link Editor + * + * This is the RTL implementation. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <rtems/libio_.h> + +#include <rtl.h> +#include "rtl-error.h" +#include "rtl-trace.h" + +/** + * Semaphore configuration to create a mutex. + */ +#define RTEMS_MUTEX_ATTRIBS \ + (RTEMS_PRIORITY | RTEMS_BINARY_SEMAPHORE | \ + RTEMS_NO_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL) + +/** + * Symbol table cache size. They can be big so the cache needs space to work. + */ +#define RTEMS_RTL_ELF_SYMBOL_CACHE (2048) + +/** + * String table cache size. + */ +#define RTEMS_RTL_ELF_STRING_CACHE (2048) + +/** + * Relocations table cache size. + */ +#define RTEMS_RTL_ELF_RELOC_CACHE (2048) + +/** + * Static RTL data is returned to the user when the linker is locked. + */ +static rtems_rtl_data_t* rtl; + +/** + * Define a default base global symbol loader function that is weak + * so a real table can be linked in when the user wants one. + */ +void rtems_rtl_base_global_syms_init (void) __attribute__ ((weak)); +void +rtems_rtl_base_global_syms_init (void) +{ + /* + * Do nothing. + */ +} + +static bool +rtems_rtl_data_init (void) +{ + /* + * Lock the RTL. We only create a lock if a call is made. First we test if a + * lock is present. If one is present we lock it. If not the libio lock is + * locked and we then test the lock again. If not present we create the lock + * then release libio lock. + */ + if (!rtl) + { + rtems_libio_lock (); + + if (!rtl) + { + rtems_status_code sc; + + rtl = malloc (sizeof (rtems_rtl_data_t)); + if (!rtl) + { + errno = ENOMEM; + return false; + } + + *rtl = (rtems_rtl_data_t) { 0 }; + + rtems_chain_initialize_empty (&rtl->objects); + + rtl->base = rtems_rtl_obj_alloc (); + if (!rtl->base) + { + free (rtl); + return false; + } + + /* + * Need to malloc the memory so the free does not complain. + */ + rtl->base->oname = strdup ("rtems-kernel"); + + rtems_chain_append (&rtl->objects, &rtl->base->link); + + if (!rtems_rtl_symbol_table_open (&rtl->globals, + RTEMS_RTL_SYMS_GLOBAL_BUCKETS)) + { + rtems_rtl_obj_free (rtl->base); + free (rtl); + return false; + } + + if (!rtems_rtl_obj_cache_open (&rtl->symbols, + RTEMS_RTL_ELF_SYMBOL_CACHE)) + { + rtems_rtl_symbol_table_close (&rtl->globals); + rtems_rtl_obj_free (rtl->base); + free (rtl); + return false; + } + + if (!rtems_rtl_obj_cache_open (&rtl->strings, + RTEMS_RTL_ELF_STRING_CACHE)) + { + rtems_rtl_obj_cache_close (&rtl->symbols); + rtems_rtl_symbol_table_close (&rtl->globals); + rtems_rtl_obj_free (rtl->base); + free (rtl); + return false; + } + + if (!rtems_rtl_obj_cache_open (&rtl->relocs, + RTEMS_RTL_ELF_RELOC_CACHE)) + { + rtems_rtl_obj_cache_close (&rtl->strings); + rtems_rtl_obj_cache_close (&rtl->symbols); + rtems_rtl_symbol_table_close (&rtl->globals); + rtems_rtl_obj_free (rtl->base); + free (rtl); + return false; + } + + sc = rtems_semaphore_create(rtems_build_name ('R', 'T', 'L', 'D'), + 1, RTEMS_MUTEX_ATTRIBS, + RTEMS_NO_PRIORITY, &rtl->lock); + if (sc != RTEMS_SUCCESSFUL) + { + rtems_rtl_obj_cache_close (&rtl->relocs); + rtems_rtl_obj_cache_close (&rtl->strings); + rtems_rtl_obj_cache_close (&rtl->symbols); + rtems_rtl_symbol_table_close (&rtl->globals); + rtems_rtl_obj_free (rtl->base); + free (rtl); + return false; + } + } + + rtems_libio_unlock (); + + rtems_rtl_path_append ("."); + + rtems_rtl_base_global_syms_init (); + } + return true; +} + +rtems_rtl_data_t* +rtems_rtl_data (void) +{ + return rtl; +} + +rtems_rtl_symbols_t* +rtems_rtl_global_symbols (void) +{ + if (!rtl) + return NULL; + return &rtl->globals; +} + +void +rtems_rtl_obj_caches (rtems_rtl_obj_cache_t** symbols, + rtems_rtl_obj_cache_t** strings, + rtems_rtl_obj_cache_t** relocs) +{ + if (!rtl) + { + if (symbols) + *symbols = NULL; + if (strings) + *strings = NULL; + if (relocs) + *relocs = NULL; + } + else + { + if (symbols) + *symbols = &rtl->symbols; + if (strings) + *strings = &rtl->strings; + if (relocs) + *relocs = &rtl->relocs; + } +} + +void +rtems_rtl_obj_caches_flush () +{ + if (rtl) + { + rtems_rtl_obj_cache_flush (&rtl->symbols); + rtems_rtl_obj_cache_flush (&rtl->strings); + rtems_rtl_obj_cache_flush (&rtl->relocs); + } +} + +rtems_rtl_data_t* +rtems_rtl_lock (void) +{ + rtems_status_code sc; + + if (!rtems_rtl_data_init ()) + return NULL; + + sc = rtems_semaphore_obtain (rtl->lock, + RTEMS_WAIT, RTEMS_NO_TIMEOUT); + if (sc != RTEMS_SUCCESSFUL) + { + errno = EINVAL; + return NULL; + } + + return rtl; +} + +bool +rtems_rtl_unlock (void) +{ + /* + * Not sure any error should be returned or an assert. + */ + rtems_status_code sc; + sc = rtems_semaphore_release (rtl->lock); + if ((sc != RTEMS_SUCCESSFUL) && (errno == 0)) + { + errno = EINVAL; + return false; + } + return true; +} + +rtems_rtl_obj_t* +rtems_rtl_check_handle (void* handle) +{ + rtems_rtl_obj_t* obj; + rtems_chain_node* node; + + obj = handle; + node = rtems_chain_first (&rtl->objects); + + while (!rtems_chain_is_tail (&rtl->objects, node)) + { + rtems_rtl_obj_t* check = (rtems_rtl_obj_t*) node; + if (check == obj) + return obj; + node = rtems_chain_next (node); + } + + return NULL; +} + +rtems_rtl_obj_t* +rtems_rtl_find_obj (const char* name) +{ + rtems_chain_node* node; + + node = rtems_chain_first (&rtl->objects); + + while (!rtems_chain_is_tail (&rtl->objects, node)) + { + rtems_rtl_obj_t* obj = (rtems_rtl_obj_t*) node; + if (rtems_rtl_match_name (obj, name)) + return obj; + node = rtems_chain_next (node); + } + + return NULL; +} + +rtems_rtl_obj_t* +rtems_rtl_load_object (const char* name, int mode) +{ + rtems_rtl_obj_t* obj; + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD)) + printf ("rtl: loading '%s'\n", name); + + /* + * See if the object module has already been loaded. + */ + obj = rtems_rtl_find_obj (name); + if (!obj) + { + /* + * Allocate a new object file descriptor and attempt to load it. + */ + obj = rtems_rtl_obj_alloc (); + if (obj == NULL) + { + rtems_rtl_set_error (ENOMEM, "no memory for object descriptor"); + return NULL; + } + + /* + * Find the file in the file system using the search path. The fname field + * will point to a valid file name if found. + */ + if (!rtems_rtl_obj_find_file (obj, name)) + { + rtems_rtl_obj_free (obj); + return NULL; + } + + rtems_chain_append (&rtl->objects, &obj->link); + + if (!rtems_rtl_obj_load (obj)) + { + rtems_rtl_obj_free (obj); + return NULL; + } + } + + /* + * Increase the number of users. + */ + ++obj->users; + + /* + * Run any local constructors if this is the first user because the object + * file will have just been loaded. Unlock the linker to avoid any dead locks + * if the object file needs to load files or update the symbol table. We also + * do not want a constructor to unload this object file. + */ + if (obj->users == 1) + { + obj->flags |= RTEMS_RTL_OBJ_LOCKED; + rtems_rtl_unlock (); + rtems_rtl_obj_run_ctors (obj); + rtems_rtl_lock (); + obj->flags &= ~RTEMS_RTL_OBJ_LOCKED; + } + + return obj; +} + +bool +rtems_rtl_unload_object (rtems_rtl_obj_t* obj) +{ + bool ok = true; + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNLOAD)) + printf ("rtl: unloading '%s'\n", obj->fname); + + /* + * If the object is locked it cannot be unloaded and the unload fails. + */ + if ((obj->flags & RTEMS_RTL_OBJ_LOCKED) == RTEMS_RTL_OBJ_LOCKED) + { + rtems_rtl_set_error (EINVAL, "cannot unload when locked"); + return false; + } + + /* + * Check the number of users in a safe manner. If this is the last user unload the + * object file from memory. + */ + if (obj->users > 0) + --obj->users; + + if (obj->users == 0) + { + obj->flags |= RTEMS_RTL_OBJ_LOCKED; + rtems_rtl_unlock (); + rtems_rtl_obj_run_dtors (obj); + rtems_rtl_lock (); + obj->flags &= ~RTEMS_RTL_OBJ_LOCKED; + + ok = rtems_rtl_obj_unload (obj); + } + + return ok; +} + +void +rtems_rtl_run_ctors (rtems_rtl_obj_t* obj) +{ + rtems_rtl_obj_run_ctors (obj); +} + +static bool +rtems_rtl_path_update (bool prepend, const char* path) +{ + char* paths; + const char* src = NULL; + char* dst; + int len; + + if (!rtems_rtl_lock ()) + return false; + + len = strlen (path); + + if (rtl->paths) + len += strlen (rtl->paths) + 1; + else + prepend = true; + + paths = malloc (len + 1); + + if (!paths) + { + rtems_rtl_unlock (); + return false; + } + + dst = paths; + + if (prepend) + { + len = strlen (path); + src = path; + } + else if (rtl->paths) + { + len = strlen (rtl->paths); + src = rtl->paths; + } + + memcpy (dst, src, len); + + dst += len; + + if (rtl->paths) + { + *dst = ':'; + ++dst; + } + + if (prepend) + { + src = rtl->paths; + if (src) + len = strlen (src); + } + else + { + len = strlen (path); + src = path; + } + + if (src) + { + memcpy (dst, src, len); + dst += len; + } + + *dst = '\0'; + + rtl->paths = paths; + + rtems_rtl_unlock (); + return false; +} + +bool +rtems_rtl_path_append (const char* path) +{ + return rtems_rtl_path_update (false, path); +} + +bool +rtems_rtl_path_prepend (const char* path) +{ + return rtems_rtl_path_update (true, path); +} + +void +rtems_rtl_base_sym_global_add (const unsigned char* esyms, + unsigned int size) +{ + if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM)) + printf ("rtl: adding global symbols, table size %u\n", size); + + if (!rtems_rtl_lock ()) + { + rtems_rtl_set_error (EINVAL, "global add cannot lock rtl"); + return; + } + + rtems_rtl_symbol_global_add (rtl->base, esyms, size); + + rtems_rtl_unlock (); +} + +rtems_rtl_obj_t* +rtems_rtl_baseimage (void) +{ + return NULL; +} @@ -0,0 +1,273 @@ +/* + * COPYRIGHT (c) 2010 Chris Johns <chrisj@rtems.org> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ +/** + * @file + * + * @ingroup rtems_rtl + * + * @brief RTEMS Run-Time Linker + * + * This is the POSIX interface to run-time loading of code into RTEMS. + */ + +#if !defined (_RTEMS_RTL_H_) +#define _RTEMS_RTL_H_ + +#include <link.h> +#include <rtems.h> +#include <rtems/chain.h> + +// #include <rtems/rtl/rtl-elf.h> +#include <rtl-fwd.h> +#include <rtl-elf.h> +#include <rtl-obj.h> +#include <rtl-obj-cache.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup rtems_rtl RTEMS Runtime Link Editor + * + * The module implements a runtime link editor with the standard dlopen, and + * dlclose family of functions. + * + * The runtime link editor is different to that found on Unix type systems. The + * object modules are compiled for PIC or position indepentent code and + * therefore require relocating when loaded. + * + * The object file format is currently ELF and object files can be separate + * files or in an archive. Object files in an archive are referenced by + * specifing 'archive:object' format. For example 'libfoo.a:bar.o'. + */ + +/** + * The number of buckets in the global symbol table. + */ +#define RTEMS_RTL_SYMS_GLOBAL_BUCKETS (32) + +/** + * The global debugger interface variable. + */ +extern struct r_debug _rtld_debug; + +/** + * Debugger break function. Call when debugging to have it read the _rtld_debug + * variable. + */ +extern void _rtld_debug_state (void); + +/** + * The type of constructor/destructor function. + */ +typedef void (*rtems_rtl_cdtor_t)(void); + +/** + * The global RTL data. This structure is allocated on the heap when the first + * call to the RTL is made and never released. + * + * The global symbol table is a hash table held in this structure and the + * actual symbols are part of the object's structure. If this is a problem we + * could look at a hash table per object file. + */ +struct rtems_rtl_data_s +{ + rtems_id lock; /**< The RTL lock id */ + rtems_chain_control objects; /**< List if loaded object files. */ + const char* paths; /**< Search paths for archives. */ + rtems_rtl_symbols_t globals; /**< Global symbol table. */ + rtems_rtl_obj_t* base; /**< Base object file. */ + rtems_rtl_obj_cache_t symbols; /**< Symbols object file cache. */ + rtems_rtl_obj_cache_t strings; /**< Strings object file cache. */ + rtems_rtl_obj_cache_t relocs; /**< Relocations object file cache. */ + int last_errno; /**< Last error number. */ + char last_error[64]; /**< Last error string. */ +}; + +/** + * Get the RTL data with out locking. This call assmes the RTL is locked. + * + * @return rtems_rtl_data_t* The RTL data after being locked. + * @retval NULL The RTL data is not initialised. + */ +rtems_rtl_data_t* rtems_rtl_data (void); + +/** + * Get the RTL global symbol table with out locking. This call assmes the RTL + * is locked. + * + * @return rtems_rtl_symbols_t* The RTL global symbols after being locked. + * @retval NULL The RTL data is not initialised. + */ +rtems_rtl_symbols_t* rtems_rtl_global_symbols (void); + +/** + * Get the RTL symbols, strings, or relocations object file caches. This call + * assmes the RTL is locked. + * + * @param symbols Pointer to the location to set the cache into. Returns NULL + * is rtl is not initialised. If NULL is passed in no value set. + * @param strings Pointer to the location to set the cache into. Returns NULL + * is rtl is not initialised. If NULL is passed in no value set. + * @param relocs Pointer to the location to set the cache into. Returns NULL + * is rtl is not initialised. If NULL is passed in no value set. + */ +void rtems_rtl_obj_caches (rtems_rtl_obj_cache_t** symbols, + rtems_rtl_obj_cache_t** strings, + rtems_rtl_obj_cache_t** relocs); + +/** + * Flush all the object file caches. + */ +void rtems_rtl_obj_caches_flush (void); + +/** + * Lock the Run-time Linker. + * + * @return rtems_rtl_data_t* The RTL data after being locked. + * @retval NULL The RTL data could not be initialised or locked. Typically this + * means the lock could not be created. + */ +rtems_rtl_data_t* rtems_rtl_lock (void); + +/** + * Unlock the Run-time Linker. + * + * @return True The RTL is unlocked. + * @return False The RTL could not be unlocked. Not much you can do. + */ +bool rtems_rtl_unlock (void); + +/** + * Check a pointer is a valid object file descriptor returning the pointer as + * that type. + * + * Assumes the RTL has been locked. + * + * @param handle Pointer to the object file to be validated. + * @return rtl_obj* The object file descriptor. NULL is returned if invalid. + */ +rtems_rtl_obj_t* rtems_rtl_check_handle (void* handle); + +/** + * Find the object given a file name. + * + * @param name The name of the object file. + * @retval NULL No object file with that name found. + * @return rtems_rtl_obj_t* The object file descriptor. + */ +rtems_rtl_obj_t* rtems_rtl_find_obj (const char* name); + +/** + * Load an object file into memory relocating it. It will not be resolved + * against other symbols in other object files or the base image. + * + * The name can be a file name for an ELF object file or it can be encoded to + * reference an archive of object modules (static library). This encoding is + * specific to RTEMS and allows dependences to specify an archive without the + * searching overhead normally incurred by linkers locating object files in an + * archive. The file name format rules are: + * + * 1. Absolute file references a specific ELF format file in that specific + * location on the file system. + * 2. Relative file references an ELF format file in the search path. + * 3. Absolute archive and file reference to a specific location in the file + * system. The archive and file are encoded as 'archive:file [@offset]' + * where 'archive' is a valid file at the absolute path in the file system, + * and 'file' is a contained in the archive, and optionally an offset to + * the 'file' in the 'archive'. If no offset is provided the archive is + * searched. + * 4. Relative archive and file in the search path. The encoding is the same + * as described in item 3 of this list. + * + * Assumes the RTL has been locked. + * + * @param name The name of the object file. + * @param mode The mode of the load as defined by the dlopen call. + * @return rtl_obj* The object file descriptor. NULL is returned if the load fails. + */ +rtems_rtl_obj_t* rtems_rtl_load_object (const char* name, int mode); + +/** + * Unload an object file. This only happens when the user count is 0. + * + * Assumes the RTL has been locked. + * + * @param obj The object file descriptor. + * @retval true The object file has been unloaded. + * @retval false The object file could not be unloaded. + */ +bool rtems_rtl_unload_object (rtems_rtl_obj_t* obj); + +/** + * Run any constructor functions the object file may contain. This call + * assumes the linker is unlocked. + * + * @param obj The object file. + */ +void rtems_rtl_run_ctors (rtems_rtl_obj_t* obj); + +/** + * Get the last error message clearing it. This operation locks the run time + * linker and therefore keeps the RTL thread safe. + * + * @param message Pointer to a buffer to copy the message into. + * @param max_message The maximum message that can be copied. + * @return int The last error number. + */ +int rtems_rtl_get_error (char* message, size_t max_message); + +/** + * Append the path to the search path. + * + * @path The path to append. + * @retval false The path could not be appended. + * @retval true The path was appended. + */ +bool rtems_rtl_path_append (const char* path); + +/** + * Prepend the path to the search path. + * + * @path The path to prepend. + * @retval false The path could not be prepended. + * @retval true The path was prepended. + */ + +bool rtems_rtl_path_prepend (const char* path); + +/** + * Add an exported symbol table to the global symbol table. This call is + * normally used by an object file when loaded that contains a global symbol + * table. + * + * @param esyms The exported symbol table. + * @param count The size of the exported symbol table. + */ +void rtems_rtl_base_sym_global_add (const unsigned char* esyms, + unsigned int count); + + /** + * Return the object file descriptor for the base image. The object file + * descriptor returned is created when the run time linker is initialised. + * + * Assumes the RTL has been locked. + * + * @return rtl_obj* The object file descriptor for the base image. NULL is + * returned if the load fails. + */ +rtems_rtl_obj_t* rtems_rtl_baseimage (void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/rtld-gsyms.c b/rtld-gsyms.c new file mode 100644 index 0000000..171818a --- /dev/null +++ b/rtld-gsyms.c @@ -0,0 +1 @@ +#include "gsyms.c" diff --git a/shell-init b/shell-init new file mode 100644 index 0000000..06a6cb7 --- /dev/null +++ b/shell-init @@ -0,0 +1,3 @@ +#rtl-trace set all +#rtl-trace set load load-sect reloc +#dlo libx.a:x-long-name-to-create-gnu-extension-in-archive.o diff --git a/sys/mman.h b/sys/mman.h new file mode 100644 index 0000000..8c816a6 --- /dev/null +++ b/sys/mman.h @@ -0,0 +1,185 @@ +/* $NetBSD: mman.h,v 1.36 2005/09/13 01:42:51 christos Exp $ */ + +/*- + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mman.h 8.2 (Berkeley) 1/9/95 + */ + +#ifndef _SYS_MMAN_H_ +#define _SYS_MMAN_H_ + +#ifdef __rtems__ + +#include <inttypes.h> +#include <stddef.h> +#include <sys/types.h> + +#else /* __rtems__ */ +#include <sys/featuretest.h> + +#include <machine/ansi.h> + +#ifdef _BSD_SIZE_T_ +typedef _BSD_SIZE_T_ size_t; +#undef _BSD_SIZE_T_ +#endif + +#include <sys/ansi.h> + +#ifndef mode_t +typedef __mode_t mode_t; +#define mode_t __mode_t +#endif + +#ifndef off_t +typedef __off_t off_t; /* file offset */ +#define off_t __off_t +#endif +#endif /* __rtems__ */ + + +/* + * Protections are chosen from these bits, or-ed together + */ +#define PROT_NONE 0x00 /* no permissions */ +#define PROT_READ 0x01 /* pages can be read */ +#define PROT_WRITE 0x02 /* pages can be written */ +#define PROT_EXEC 0x04 /* pages can be executed */ + +/* + * Flags contain sharing type and options. + * Sharing types; choose one. + */ +#define MAP_SHARED 0x0001 /* share changes */ +#define MAP_PRIVATE 0x0002 /* changes are private */ + +#ifdef _KERNEL +/* + * Deprecated flag; these are treated as MAP_PRIVATE internally by + * the kernel. + */ +#define MAP_COPY 0x0004 /* "copy" region at mmap time */ +#endif + +/* + * Other flags + */ +#define MAP_FIXED 0x0010 /* map addr must be exactly as requested */ +#define MAP_RENAME 0x0020 /* Sun: rename private pages to file */ +#define MAP_NORESERVE 0x0040 /* Sun: don't reserve needed swap area */ +#define MAP_INHERIT 0x0080 /* region is retained after exec */ +#define MAP_HASSEMAPHORE 0x0200 /* region may contain semaphores */ +#define MAP_TRYFIXED 0x0400 /* attempt hint address, even within break */ +#define MAP_WIRED 0x0800 /* mlock() mapping when it is established */ + +/* + * Mapping type + */ +#define MAP_FILE 0x0000 /* map from file (default) */ +#define MAP_ANON 0x1000 /* allocated from memory, swap space */ + +/* + * Alignment (expressed in log2). Must be >= log2(PAGE_SIZE) and + * < # bits in a pointer (26 (acorn26), 32 or 64). + */ +#define MAP_ALIGNED(n) ((n) << MAP_ALIGNMENT_SHIFT) +#define MAP_ALIGNMENT_SHIFT 24 +#define MAP_ALIGNMENT_MASK MAP_ALIGNED(0xff) +#define MAP_ALIGNMENT_64KB MAP_ALIGNED(16) /* 2^16 */ +#define MAP_ALIGNMENT_16MB MAP_ALIGNED(24) /* 2^24 */ +#define MAP_ALIGNMENT_4GB MAP_ALIGNED(32) /* 2^32 */ +#define MAP_ALIGNMENT_1TB MAP_ALIGNED(40) /* 2^40 */ +#define MAP_ALIGNMENT_256TB MAP_ALIGNED(48) /* 2^48 */ +#define MAP_ALIGNMENT_64PB MAP_ALIGNED(56) /* 2^56 */ + +/* + * Error indicator returned by mmap(2) + */ +#define MAP_FAILED ((void *) -1) /* mmap() failed */ + +/* + * Flags to msync + */ +#define MS_ASYNC 0x01 /* perform asynchronous writes */ +#define MS_INVALIDATE 0x02 /* invalidate cached data */ +#define MS_SYNC 0x04 /* perform synchronous writes */ + +/* + * Flags to mlockall + */ +#define MCL_CURRENT 0x01 /* lock all pages currently mapped */ +#define MCL_FUTURE 0x02 /* lock all pages mapped in the future */ + +#if defined(_NETBSD_SOURCE) +/* + * Advice to madvise + */ +#define MADV_NORMAL 0 /* no further special treatment */ +#define MADV_RANDOM 1 /* expect random page references */ +#define MADV_SEQUENTIAL 2 /* expect sequential page references */ +#define MADV_WILLNEED 3 /* will need these pages */ +#define MADV_DONTNEED 4 /* dont need these pages */ +#define MADV_SPACEAVAIL 5 /* insure that resources are reserved */ +#define MADV_FREE 6 /* pages are empty, free them */ +/* + * Flags to minherit + */ +#define MAP_INHERIT_SHARE 0 /* share with child */ +#define MAP_INHERIT_COPY 1 /* copy into child */ +#define MAP_INHERIT_NONE 2 /* absent from child */ +#define MAP_INHERIT_DONATE_COPY 3 /* copy and delete -- not + implemented in UVM */ +#define MAP_INHERIT_DEFAULT MAP_INHERIT_COPY +#endif + +#ifndef _KERNEL + +#include <sys/cdefs.h> + +__BEGIN_DECLS +void *mmap(void *, size_t, int, int, int, off_t); +int munmap(void *, size_t); +int mprotect(void *, size_t, int); +#ifndef __LIBC12_SOURCE__ +int msync(void *, size_t, int) __RENAME(__msync13); +#endif +int mlock(const void *, size_t); +int munlock(const void *, size_t); +int mlockall(int); +int munlockall(void); +#if defined(_NETBSD_SOURCE) +int madvise(void *, size_t, int); +int mincore(void *, size_t, char *); +int minherit(void *, size_t, int); +#endif +__END_DECLS + +#endif /* !_KERNEL */ + +#endif /* !_SYS_MMAN_H_ */ @@ -0,0 +1,142 @@ +# +# Waf build script for the Run Time Link editor development project. +# +import rtems + +version = "1.0.0" + +def init(ctx): + rtems.init(ctx) + +def options(opt): + rtems.options(opt) + +def configure(conf): + rtems.configure(conf) + + conf.env.ASCIIDOC = conf.find_program(['asciidoc.py'], mandatory = False) + conf.env.ASCIIDOC_FLAGS = ['-b', 'html5', '-a', 'data-uri', '-a', 'icons', '-a', 'max-width=55em-a'] + +def build(bld): + bld.add_post_fun(rtl_post_build) + + rtems.build(bld) + + arch = bld.get_env()['RTEMS_ARCH'] + + bld.includes = ['.', + 'libbsd/include', + 'libbsd/include/arch/' + arch] + + rtl_source(bld, arch) + rtl_liba(bld, arch) + rtl_root_fs(bld) + rtl_gsyms(bld) + + bld(target = 'rtld', + features = 'c cprogram', + source = ['init.c', + 'main.c', + 'fs-root-tarfile.o'], + includes = bld.includes, + defines = ['PACKAGE_VERSION="' + version + '"'], + use = ['rtl', 'rootfs', 'rtld-gsyms'], + depends_on = 'gsyms') + + if bld.env.ASCIIDOC: + bld(target = 'rtems-rtl.html', source = 'rtems-rtl.txt') + +def rtl_source(bld, arch): + bld(target = 'rtl', + features = 'c', + includes = bld.includes, + source = ['dlfcn.c', + 'dlfcn-shell.c', + 'rtl.c', + 'rtl-chain-iterator.c', + 'rtl-debugger.c', + 'rtl-elf.c', + 'rtl-error.c', + 'rtl-obj.c', + 'rtl-obj-cache.c', + 'rtl-shell.c', + 'rtl-sym.c', + 'rtl-trace.c', + 'rtl-mdreloc-' + arch + '.c']) + +def rtl_liba(bld, arch): + bld(target = 'x', + features = 'c cstlib', + includes = bld.includes, + source = ['xa.c', + 'x-long-name-to-create-gnu-extension-in-archive.c']) + +def mmap_source(bld, includes): + bld(target = 'mmap', + features = 'c', + includes = includes, + source = ['mmap.c', + 'munmap.c']) + +def rtl_root_fs(bld): + bld(target = 'fs-root.tar', + source = ['shell-init', 'libx.a', 'a.out'], + rule = 'tar cf - ${SRC} > ${TGT}') + bld.objects(name = 'rootfs', + target = 'fs-root-tarfile.o', + source = 'fs-root.tar', + rule = '${OBJCOPY} -I binary -B ${RTEMS_ARCH} ${OBJCOPY_FLAGS} ${SRC} ${TGT}') + +def rtl_pre_build(bld): + pass + +def rtl_post_build(bld): + rtl_gsyms(bld) + +def rtl_gsyms(bld): + import os.path + src = os.path.join(bld.get_variant_dir(), 'gsyms.c') + if os.path.exists(src): + if os.path.exists(os.path.join(bld.get_variant_dir(), 'rtld')): + import os + sb = os.stat(src) + if sb.st_size == 0: + bld(name = 'gsyms', + target = 'gsyms.c', + always = True, + rule = '${NM} -g rtld | awk -f ../../mksyms.awk - > ${TGT}') + else: + open(src, 'a').close() + bld(target = 'rtld-gsyms', + features = 'c', + includes = bld.includes, + source = ['rtld-gsyms.c'], + depends_on = 'gsyms') + +def x_rtl_gsyms(bld): + import os.path + src = os.path.join(bld.get_variant_dir(), 'gsyms.c') + if os.path.exists(src): + if os.path.exists(os.path.join(bld.get_variant_dir(), 'rtld')): + import os + sb = os.stat(src) + if sb.st_size == 0: + bld(name = 'gsyms', + target = 'gsyms.c', + always = True, + rule = '${NM} -g rtld | awk -f ../../mksyms.awk - > ${TGT}') + else: + open(src, 'a').close() + bld(target = 'rtld-gsyms', + features = 'c', + includes = bld.includes, + source = ['rtld-gsyms.c'], + depends_on = 'gsyms') + +import TaskGen +TaskGen.declare_chain(name = 'html', + rule = '${ASCIIDOC} ${ASCIIDOC_FLAGS} -o ${TGT} ${SRC}', + shell = False, + ext_in = '.txt', + ext_out = '.html', + reentrant = False) diff --git a/x-long-name-to-create-gnu-extension-in-archive.c b/x-long-name-to-create-gnu-extension-in-archive.c new file mode 100644 index 0000000..55d614a --- /dev/null +++ b/x-long-name-to-create-gnu-extension-in-archive.c @@ -0,0 +1,44 @@ + + +#include <stdlib.h> +#include <stdio.h> +#include <math.h> +#include "x.h" + +static int zero; +unsigned int public = 0x12345678; + +void x_writeln(const char* s); +void y_writeln(const char* s) __attribute__ ((section (".bar"))); + +void +w_writeln(double d) +{ + printf ("sin(%f) = %f\n", d, sin(d)); +} + +void +x_writeln(const char* s) +{ + printf ("%s\n", s); +} + +void y_writeln(const char* s) +{ + x_writeln (s); +} + +int z_writeln(int argc, const char* argv[]) +{ + int arg; + printf ("public = 0x%08x, zero = %d\n", public, ++zero); + for (arg = 0; arg < argc; ++arg) + y_writeln (argv[arg]); + return 123; +} + +int +my_main (int argc, char* argv[]) +{ + exit (0); +} @@ -0,0 +1,7 @@ + +#ifndef _X_H_ +#define _X_H_ + +void x_writeln (const char* s); + +#endif @@ -0,0 +1,9 @@ + + +#include "x.h" + +void +hello (void) +{ + x_writeln ("hello world"); +} |