summaryrefslogtreecommitdiffstats
path: root/arch/sandbox/lib
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2007-07-12 12:12:34 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2007-07-12 12:12:34 +0200
commitd757720766629dcd94af70ea65ccd8ba5eb47e4b (patch)
tree1263204fa6e46fc3555f232b81e6c9ce2bd13df2 /arch/sandbox/lib
parent2557787389f8ec40381d1201a15badd25d4aab10 (diff)
downloadbarebox-d757720766629dcd94af70ea65ccd8ba5eb47e4b.tar.gz
barebox-d757720766629dcd94af70ea65ccd8ba5eb47e4b.tar.xz
arch/linux -> arch/sandbox
Diffstat (limited to 'arch/sandbox/lib')
-rw-r--r--arch/sandbox/lib/Makefile12
-rw-r--r--arch/sandbox/lib/common.c339
-rw-r--r--arch/sandbox/lib/tap.c63
-rw-r--r--arch/sandbox/lib/u-boot.lds.S229
4 files changed, 643 insertions, 0 deletions
diff --git a/arch/sandbox/lib/Makefile b/arch/sandbox/lib/Makefile
new file mode 100644
index 0000000000..418f4d3427
--- /dev/null
+++ b/arch/sandbox/lib/Makefile
@@ -0,0 +1,12 @@
+CPPFLAGS_u-boot.lds = -U$(SUBARCH) -DELF_ARCH=$(ELF_ARCH) \
+ -DELF_FORMAT="$(ELF_FORMAT)"
+
+extra-y += u-boot.lds
+
+CPPFLAGS := -I/usr/include -Iinclude -P
+CFLAGS := -Wall
+#NOSTDINC_FLAGS :=
+
+obj-y = common.o tap.o
+
+USER_OBJS := common.o
diff --git a/arch/sandbox/lib/common.c b/arch/sandbox/lib/common.c
new file mode 100644
index 0000000000..6416a54381
--- /dev/null
+++ b/arch/sandbox/lib/common.c
@@ -0,0 +1,339 @@
+/*
+ * common.c - common wrapper functions between U-Boot and the host
+ *
+ * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * These are host includes. Never include any U-Boot header
+ * files here...
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <termios.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <libgen.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/select.h>
+/*
+ * ...except the ones needed to connect with U-Boot
+ */
+#include <asm/arch/linux.h>
+#include <asm/arch/hostfile.h>
+
+static struct termios term_orig, term_vi;
+static char erase_char; /* the users erase character */
+
+static void rawmode(void)
+{
+ tcgetattr(0, &term_orig);
+ term_vi = term_orig;
+ term_vi.c_lflag &= (~ICANON & ~ECHO & ~ISIG);
+ term_vi.c_iflag &= (~IXON & ~ICRNL);
+ term_vi.c_oflag |= (ONLCR);
+ term_vi.c_cc[VMIN] = 1;
+ term_vi.c_cc[VTIME] = 0;
+ erase_char = term_vi.c_cc[VERASE];
+ tcsetattr(0, TCSANOW, &term_vi);
+}
+
+static void cookmode(void)
+{
+ fflush(stdout);
+ tcsetattr(0, TCSANOW, &term_orig);
+}
+
+void linux_putc(const char c)
+{
+ fputc(c, stdout);
+
+ /* If \n, also do \r */
+ if (c == '\n')
+ linux_putc ('\r');
+
+ fflush(stdout);
+}
+
+int linux_tstc(int fd)
+{
+ fd_set rfds;
+ struct timeval tv;
+ int ret;
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+
+ /*
+ * We set the timeout here to 100us, because otherwise
+ * U-Boot would eat all cpu resources while waiting
+ * for input. On the other hand this makes some
+ * things like networking slow, because U-Boot will
+ * poll this function very often.
+ */
+ tv.tv_sec = 0;
+ tv.tv_usec = 100;
+
+ ret = select(fd + 1, &rfds, NULL, NULL, &tv);
+
+ if (ret)
+ return 1;
+
+ return 0;
+}
+
+int linux_getc(void)
+{
+ char ret;
+
+ read(0, &ret, 1);
+
+ return ret;
+}
+
+uint64_t linux_get_time(void)
+{
+ struct timespec ts;
+ uint64_t now;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ now = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
+
+ return now;
+}
+
+int reset_cpu(int unused)
+{
+ cookmode();
+ exit(0);
+}
+
+void enable_interrupts(void)
+{
+}
+
+void disable_interrupt(void)
+{
+}
+
+int linux_read(int fd, void *buf, size_t count)
+{
+ return read(fd, buf, count);
+}
+
+int linux_read_nonblock(int fd, void *buf, size_t count)
+{
+ int oldflags, ret;
+
+ oldflags = fcntl(fd, F_GETFL);
+ if (oldflags == -1)
+ goto err_out;
+
+ if (fcntl(fd, F_SETFL, oldflags | O_NONBLOCK) == -1)
+ goto err_out;
+
+ ret = read(fd, buf, count);
+
+ if (fcntl(fd, F_SETFL, oldflags) == -1)
+ goto err_out;
+
+ if (ret == -1)
+ usleep(100);
+
+ return ret;
+
+err_out:
+ perror("fcntl");
+ return -1;
+}
+
+ssize_t linux_write(int fd, const void *buf, size_t count)
+{
+ return write(fd, buf, count);
+}
+
+off_t linux_lseek(int fd, off_t offset)
+{
+ return lseek(fd, offset, SEEK_SET);
+}
+
+void flush_cache(unsigned long dummy1, unsigned long dummy2)
+{
+ /* why should we? */
+}
+
+extern void start_uboot(void);
+extern void mem_malloc_init(void *start, void *end);
+
+int add_image(char *str, char *name_template)
+{
+ char *file;
+ int readonly = 0, map = 1;
+ struct stat s;
+ char *opt;
+ int fd, ret;
+ struct hf_platform_data *hf = malloc(sizeof(struct hf_platform_data));
+
+ if (!hf)
+ return -1;
+
+ file = strtok(str, ",");
+ while ((opt = strtok(NULL, ","))) {
+ if (!strcmp(opt, "ro"))
+ readonly = 1;
+ if (!strcmp(opt, "map"))
+ map = 1;
+ }
+
+ printf("add file %s(%s)\n", file, readonly ? "ro" : "");
+
+ fd = open(file, readonly ? O_RDONLY : O_RDWR);
+ hf->fd = fd;
+ hf->filename = file;
+
+ if (fd < 0) {
+ perror("open");
+ goto err_out;
+ }
+
+ if (fstat(fd, &s)) {
+ perror("fstat");
+ goto err_out;
+ }
+
+ hf->size = s.st_size;
+
+ if (map) {
+ hf->map_base = (unsigned long)mmap(0, hf->size,
+ PROT_READ | (readonly ? 0 : PROT_WRITE),
+ MAP_SHARED, fd, 0);
+ if ((void *)hf->map_base == MAP_FAILED)
+ printf("warning: mmapping %s failed\n", file);
+ }
+
+
+ ret = u_boot_register_filedev(hf, name_template);
+ if (ret)
+ goto err_out;
+ return 0;
+
+err_out:
+ if (fd > 0)
+ close(fd);
+ free(hf);
+ return -1;
+}
+
+static void print_usage(const char *prgname)
+{
+ printf(
+"Usage: %s [OPTIONS]\n"
+"Start U-Boot.\n"
+"Options:\n"
+" -i <file> Map a file to U-Boot. This option can be given multiple\n"
+" times. The files will show up as /dev/fd0 ... /dev/fdx\n"
+" under U-Boot.\n"
+" -e <file> Map a file to U-Boot. With this option files are mapped as\n"
+" /dev/env0 ... /dev/envx and thus are used as default\n"
+" environment. An empty file generated with dd will do to get\n"
+" started wth an empty environment\n"
+" -O <file> Register file as a console capable of doing stdout. File can\n"
+" be a regular file or a fifo.\n"
+" -I <file> Register file as a console capable of doing stdin. File can\n"
+" be a regular file or a fifo.\n",
+ prgname
+ );
+}
+
+int main(int argc, char *argv[])
+{
+ void *ram;
+ int opt, ret, fd;
+ int malloc_size = 8 * 1024 * 1024;
+
+ ram = malloc(malloc_size);
+ if (!ram) {
+ printf("unable to get malloc space\n");
+ exit(1);
+ }
+ mem_malloc_init(ram, ram + malloc_size);
+
+ while ((opt = getopt(argc, argv, "hi:e:I:O:")) != -1) {
+ switch (opt) {
+ case 'h':
+ print_usage(basename(argv[0]));
+ exit(0);
+ case 'i':
+ ret = add_image(optarg, "fd");
+ if (ret)
+ exit(1);
+ break;
+ case 'm':
+ /* This option is broken. add_image needs malloc, so
+ * mem_alloc_init() has to be called before option
+ * parsing
+ */
+ malloc_size = strtoul(optarg, NULL, 0);
+ break;
+ case 'e':
+ ret = add_image(optarg, "env");
+ if (ret)
+ exit(1);
+ break;
+ case 'O':
+ fd = open(optarg, O_WRONLY);
+ if (fd < 0) {
+ perror("open");
+ exit(1);
+ }
+
+ u_boot_register_console("cout", -1, fd);
+ break;
+ case 'I':
+ fd = open(optarg, O_RDWR);
+ if (fd < 0) {
+ perror("open");
+ exit(1);
+ }
+
+ u_boot_register_console("cin", fd, -1);
+ break;
+ default:
+ exit(1);
+ }
+ }
+
+ u_boot_register_console("console", 1, 0);
+
+ rawmode();
+ start_uboot();
+
+ /* never reached */
+ return 0;
+}
+
diff --git a/arch/sandbox/lib/tap.c b/arch/sandbox/lib/tap.c
new file mode 100644
index 0000000000..b620612626
--- /dev/null
+++ b/arch/sandbox/lib/tap.c
@@ -0,0 +1,63 @@
+/*
+ * tap.c - host side functions for tap driver
+ *
+ * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <string.h>
+
+int tap_alloc(char *dev)
+{
+ struct ifreq ifr;
+ int fd, err;
+
+ if ((fd = open("/dev/net/tun", O_RDWR)) < 0) {
+ perror("could not open /dev/net/tun");
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+
+ /* Flags: IFF_TUN - TUN device (no Ethernet headers)
+ * IFF_TAP - TAP device
+ *
+ * IFF_NO_PI - Do not provide packet information
+ */
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+ if (*dev)
+ strncpy(ifr.ifr_name, dev, IFNAMSIZ);
+
+ if ((err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0) {
+ perror("could not get tap device");
+ close(fd);
+ return err;
+ }
+
+ strcpy(dev, ifr.ifr_name);
+ return fd;
+}
diff --git a/arch/sandbox/lib/u-boot.lds.S b/arch/sandbox/lib/u-boot.lds.S
new file mode 100644
index 0000000000..25d42b1e5e
--- /dev/null
+++ b/arch/sandbox/lib/u-boot.lds.S
@@ -0,0 +1,229 @@
+#include <asm-generic/u-boot.lds.h>
+
+OUTPUT_FORMAT(ELF_FORMAT)
+OUTPUT_ARCH(ELF_ARCH)
+ENTRY(_start)
+
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ PROVIDE (__executable_start = 0x400000); . = 0x400000 + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .gnu.hash : { *(.gnu.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.dyn :
+ {
+ *(.rel.init)
+ *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*)
+ *(.rel.fini)
+ *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
+ *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*)
+ *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
+ *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*)
+ *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*)
+ *(.rel.ctors)
+ *(.rel.dtors)
+ *(.rel.got)
+ *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*)
+ *(.rel.ldata .rel.ldata.* .rel.gnu.linkonce.l.*)
+ *(.rel.lbss .rel.lbss.* .rel.gnu.linkonce.lb.*)
+ *(.rel.lrodata .rel.lrodata.* .rel.gnu.linkonce.lr.*)
+ }
+ .rela.dyn :
+ {
+ *(.rela.init)
+ *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
+ *(.rela.fini)
+ *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
+ *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
+ *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
+ *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
+ *(.rela.ctors)
+ *(.rela.dtors)
+ *(.rela.got)
+ *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
+ *(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
+ *(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
+ *(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
+ }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init :
+ {
+ KEEP (*(.init))
+ } =0x90909090
+ .plt : { *(.plt) }
+ .text :
+ {
+ *(.text .stub .text.* .gnu.linkonce.t.*)
+ KEEP (*(.text.*personality*))
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ } =0x90909090
+ .fini :
+ {
+ KEEP (*(.fini))
+ } =0x90909090
+
+ . = ALIGN(64);
+ __u_boot_initcalls_start = .;
+ __u_boot_initcalls : { INITCALLS }
+ __u_boot_initcalls_end = .;
+ . = ALIGN(64);
+ __u_boot_cmd_start = .;
+ __u_boot_cmd : { U_BOOT_CMDS }
+ __u_boot_cmd_end = .;
+
+ PROVIDE (__etext = .);
+ PROVIDE (_etext = .);
+ PROVIDE (etext = .);
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
+ .rodata1 : { *(.rodata1) }
+ .eh_frame_hdr : { *(.eh_frame_hdr) }
+ .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
+ /* Exception handling */
+ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) }
+ .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
+ /* Thread Local Storage sections */
+ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
+ .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
+ .preinit_array :
+ {
+ PROVIDE_HIDDEN (__preinit_array_start = .);
+ KEEP (*(.preinit_array))
+ PROVIDE_HIDDEN (__preinit_array_end = .);
+ }
+ .init_array :
+ {
+ PROVIDE_HIDDEN (__init_array_start = .);
+ KEEP (*(SORT(.init_array.*)))
+ KEEP (*(.init_array))
+ PROVIDE_HIDDEN (__init_array_end = .);
+ }
+ .fini_array :
+ {
+ PROVIDE_HIDDEN (__fini_array_start = .);
+ KEEP (*(.fini_array))
+ KEEP (*(SORT(.fini_array.*)))
+ PROVIDE_HIDDEN (__fini_array_end = .);
+ }
+ .ctors :
+ {
+ /* gcc uses crtbegin.o to find the start of
+ the constructors, so we make sure it is
+ first. Because this is a wildcard, it
+ doesn't matter if the user does not
+ actually link against crtbegin.o; the
+ linker won't look for a file to match a
+ wildcard. The wildcard also means that it
+ doesn't matter which directory crtbegin.o
+ is in. */
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*crtbegin?.o(.ctors))
+ /* We don't want to include the .ctor section from
+ the crtend.o file until after the sorted ctors.
+ The .ctor section from the crtend file contains the
+ end of ctors marker and it must be last */
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ }
+ .dtors :
+ {
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*crtbegin?.o(.dtors))
+ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ }
+ .jcr : { KEEP (*(.jcr)) }
+ .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) }
+ .dynamic : { *(.dynamic) }
+ .got : { *(.got) }
+ . = DATA_SEGMENT_RELRO_END (24, .);
+ .got.plt : { *(.got.plt) }
+ .data :
+ {
+ *(.data .data.* .gnu.linkonce.d.*)
+ KEEP (*(.gnu.linkonce.d.*personality*))
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ _edata = .; PROVIDE (edata = .);
+ __bss_start = .;
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss .bss.* .gnu.linkonce.b.*)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections.
+ FIXME: Why do we need it? When there is no .bss section, we don't
+ pad the .data section. */
+ . = ALIGN(. != 0 ? 64 / 8 : 1);
+ }
+ .lbss :
+ {
+ *(.dynlbss)
+ *(.lbss .lbss.* .gnu.linkonce.lb.*)
+ *(LARGE_COMMON)
+ }
+ . = ALIGN(64 / 8);
+ .lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+ {
+ *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
+ }
+ .ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
+ {
+ *(.ldata .ldata.* .gnu.linkonce.l.*)
+ . = ALIGN(. != 0 ? 64 / 8 : 1);
+ }
+ . = ALIGN(64 / 8);
+ _end = .; PROVIDE (end = .);
+ . = DATA_SEGMENT_END (.);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /DISCARD/ : { *(.note.GNU-stack) }
+}
+