From 0809e5a5e1355d8b85b95f798b01708a69bb6353 Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Mon, 5 Nov 2018 14:53:35 -0800 Subject: [PATCH] [LibOS] Add support for vDSO This commit adds vDSO support: creates vDSO memory region which contains necessary symbols __vdso_{gettimeofday, clock_getime, time, getcpu} with wrappers to call function pointers with actual LibOS implementation. On startup, function pointers are setup to point to actual functions. With this commit, the Glibc modification to not use vDSO can be removed. --- LibOS/shim/include/shim_defs.h | 2 +- LibOS/shim/include/shim_vdso.h | 31 ++++++ LibOS/shim/src/Makefile | 20 +++- LibOS/shim/src/elf/shim_rtld.c | 165 ++++++++++++++++++++++++++++---- LibOS/shim/src/shim_init.c | 5 +- LibOS/shim/src/vdso/.gitignore | 2 + LibOS/shim/src/vdso/vdso-data.S | 19 ++++ LibOS/shim/src/vdso/vdso-note.S | 19 ++++ LibOS/shim/src/vdso/vdso.c | 63 ++++++++++++ LibOS/shim/src/vdso/vdso.lds | 82 ++++++++++++++++ Makefile.configs | 1 + Makefile.rules | 10 +- 12 files changed, 395 insertions(+), 24 deletions(-) create mode 100644 LibOS/shim/include/shim_vdso.h create mode 100644 LibOS/shim/src/vdso/.gitignore create mode 100644 LibOS/shim/src/vdso/vdso-data.S create mode 100644 LibOS/shim/src/vdso/vdso-note.S create mode 100644 LibOS/shim/src/vdso/vdso.c create mode 100644 LibOS/shim/src/vdso/vdso.lds diff --git a/LibOS/shim/include/shim_defs.h b/LibOS/shim/include/shim_defs.h index 8c4789f7..031397da 100644 --- a/LibOS/shim/include/shim_defs.h +++ b/LibOS/shim/include/shim_defs.h @@ -35,7 +35,7 @@ #define MIGRATE_SYSV_MSG 1 /* ELF aux vectors */ -#define REQUIRED_ELF_AUXV 7 /* number of LibOS-supported vectors */ +#define REQUIRED_ELF_AUXV 8 /* number of LibOS-supported vectors */ #define REQUIRED_ELF_AUXV_SPACE 16 /* extra memory space (in bytes) */ #endif /* _SHIM_DEFS_H_ */ diff --git a/LibOS/shim/include/shim_vdso.h b/LibOS/shim/include/shim_vdso.h new file mode 100644 index 00000000..b1a32a99 --- /dev/null +++ b/LibOS/shim/include/shim_vdso.h @@ -0,0 +1,31 @@ +/* + * Copyright 2018 Intel Corporation. + * Copyright 2018 Isaku Yamahata + * + * All Rights Reserved. + * + * This file is part of Graphene Library OS. + * + * Graphene Library OS is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Graphene Library OS 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +#ifndef _SHIM_VDSO_H_ +#define _SHIM_VDSO_H_ + +extern const uint8_t vdso_so[]; +extern const size_t vdso_so_size; + +int vdso_map_migrate(void); + +#endif /* _SHIM_VDSO_H_ */ diff --git a/LibOS/shim/src/Makefile b/LibOS/shim/src/Makefile index 6a0f08fa..952b8ab5 100644 --- a/LibOS/shim/src/Makefile +++ b/LibOS/shim/src/Makefile @@ -49,7 +49,9 @@ objs = $(addprefix bookkeep/shim_,handle vma thread signal) \ elf/shim_rtld \ $(addprefix shim_,init table syscalls checkpoint malloc \ async parser debug object) syscallas start \ - $(patsubst %.c,%,$(wildcard sys/*.c)) + $(patsubst %.c,%,$(wildcard sys/*.c)) \ + vdso/vdso-data + graphene_lib = .lib/graphene-lib.a pal_lib = $(RUNTIME_DIR)/libpal-$(PAL_HOST).so headers = ../include/*.h ../../../Pal/lib/*.h ../../../Pal/include/pal/*.h @@ -120,5 +122,21 @@ syscallas.S shim_checkpoint.c: asm-offsets.h include ../../../Makefile.rules +LDFLAGS-vdso/vdso.so.dbg = -nostdlib -shared \ + --hash-style=both --build-id -Bsymbolic \ + -m elf_x86_64 --no-undefined \ + -z max-page-size=4096 -z common-page-size=4096 \ + -T vdso/vdso.lds -soname linux-vdso.so.1 +vdso/vdso.so.dbg: LDFLAGS = +vdso/vdso.so.dbg: vdso/vdso.lds vdso/vdso.o vdso/vdso-note.o + $(call cmd,ld) + +OBJCOPYFLAGS-vdso/vdso.so = -S +vdso/vdso.so: vdso/vdso.so.dbg + $(call cmd,objcopy) + +vdso/vdso-data.o: vdso/vdso.so +CLEAN_FILES += vdso/vdso.so.dbg vdso/vdso.so + clean: rm -rf $(addsuffix .o,$(objs)) $(shim_target) $(files_to_build) .lib $(CLEAN_FILES) diff --git a/LibOS/shim/src/elf/shim_rtld.c b/LibOS/shim/src/elf/shim_rtld.c index 2724f972..2fd3af7f 100644 --- a/LibOS/shim/src/elf/shim_rtld.c +++ b/LibOS/shim/src/elf/shim_rtld.c @@ -32,6 +32,7 @@ #include #include #include +#include #include @@ -55,6 +56,7 @@ enum object_type { OBJECT_MAPPED = 2, OBJECT_REMAP = 3, OBJECT_USER = 4, + OBJECT_VDSO = 5, }; /* Structure describing a loaded shared object. The `l_next' and `l_prev' @@ -147,6 +149,7 @@ struct link_map * lookup_symbol (const char * undef_name, ElfW(Sym) ** ref); static struct link_map * loaded_libraries = NULL; static struct link_map * internal_map = NULL, * interp_map = NULL; +static struct link_map * vdso_map = NULL; /* This macro is used as a callback from the ELF_DYNAMIC_RELOCATE code. */ static ElfW(Addr) resolve_map (const char ** strtab, ElfW(Sym) ** ref) @@ -376,7 +379,7 @@ __map_elf_object (struct shim_handle * file, const char * errstring __attribute__((unused)) = NULL; int ret; - if (type != OBJECT_INTERNAL && !file) { + if (type != OBJECT_INTERNAL && type != OBJECT_VDSO && !file) { errstring = "shared object has to be backed by file"; goto call_lose; } @@ -589,9 +592,9 @@ do_remap: } #if BOOKKEEP_INTERNAL_OBJ == 0 - if (type != OBJECT_INTERNAL && type != OBJECT_USER) + if (type != OBJECT_INTERNAL && type != OBJECT_USER && type != OBJECT_VDSO) #else - if (type != OBJECT_USER) + if (type != OBJECT_USER && type != OBJECT_VDSO) #endif bkeep_mmap(mapaddr, c->mapend - c->mapstart, c->prot, c->flags|MAP_FIXED|MAP_PRIVATE| @@ -623,7 +626,9 @@ postmap: if (type != OBJECT_MAPPED && type != OBJECT_INTERNAL && - type != OBJECT_USER && zeropage > zero) { + type != OBJECT_USER && + type != OBJECT_VDSO && + zeropage > zero) { /* Zero the final part of the last page of the segment. */ if (__builtin_expect ((c->prot & PROT_WRITE) == 0, 0)) { /* Dag nab it. */ @@ -647,7 +652,8 @@ postmap: if (zeroend > zeropage) { if (type != OBJECT_MAPPED && type != OBJECT_INTERNAL && - type != OBJECT_USER) { + type != OBJECT_USER && + type != OBJECT_VDSO) { PAL_PTR mapat = DkVirtualMemoryAlloc((void *)zeropage, zeroend - zeropage, 0, c->prot); if (__builtin_expect (!mapat, 0)) { @@ -657,9 +663,9 @@ postmap: } #if BOOKKEEP_INTERNAL_OBJ == 0 - if (type != OBJECT_INTERNAL && type != OBJECT_USER) + if (type != OBJECT_INTERNAL && type != OBJECT_USER && type != OBJECT_VDSO) #else - if (type != OBJECT_USER) + if (type != OBJECT_USER && type != OBJECT_VDSO) #endif bkeep_mmap((void *) zeropage, zeroend - zeropage, c->prot, MAP_ANONYMOUS|MAP_PRIVATE|MAP_FIXED| @@ -1057,7 +1063,7 @@ static int __load_elf_object (struct shim_handle * file, void * addr, goto out; } - if (type != OBJECT_INTERNAL) + if (type != OBJECT_INTERNAL && type != OBJECT_VDSO) do_relocate_object(map); if (internal_map) { @@ -1067,6 +1073,8 @@ static int __load_elf_object (struct shim_handle * file, void * addr, if (type == OBJECT_INTERNAL) internal_map = map; + if (type == OBJECT_VDSO) + vdso_map = map; if (type != OBJECT_REMAP) { if (file) { @@ -1261,14 +1269,21 @@ do_lookup_map (ElfW(Sym) * ref, const char * undef_name, /* Inner part of the lookup functions. We return a value > 0 if we found the symbol, the value 0 if nothing is found and < 0 if something bad happened. */ -static int do_lookup (const char * undef_name, ElfW(Sym) * ref, - struct sym_val * result) +static ElfW(Sym) * +__do_lookup (const char * undef_name, ElfW(Sym) * ref, + struct link_map * map) { const uint_fast32_t fast_hash = elf_fast_hash(undef_name); const long int hash = elf_hash(undef_name); + return do_lookup_map(ref, undef_name, fast_hash, hash, map); +} + +static int do_lookup (const char * undef_name, ElfW(Sym) * ref, + struct sym_val * result) +{ ElfW(Sym) *sym = NULL; - sym = do_lookup_map(ref, undef_name, fast_hash, hash, internal_map); + sym = __do_lookup(undef_name, ref, internal_map); if (!sym) return 0; @@ -1463,7 +1478,7 @@ int remove_loaded_libraries (void) { struct link_map * map = loaded_libraries, * next_map = map->l_next; while (map) { - if (map->l_type != OBJECT_INTERNAL) + if (map->l_type != OBJECT_INTERNAL && map->l_type != OBJECT_VDSO) __remove_elf_object(map); map = next_map; @@ -1473,6 +1488,107 @@ int remove_loaded_libraries (void) return 0; } +/* + * libsysdb.so is loaded as shared library and load address for child may not match the one for + * parent. Just treat vdso page as user-program data and adjust function pointers for vdso + * functions after migration. + */ +static void * vdso_addr __attribute_migratable = NULL; +static ElfW(Addr) * __vdso_shim_clock_gettime __attribute_migratable = NULL; +static ElfW(Addr) * __vdso_shim_gettimeofday __attribute_migratable = NULL; +static ElfW(Addr) * __vdso_shim_time __attribute_migratable = NULL; +static ElfW(Addr) * __vdso_shim_getcpu __attribute_migratable = NULL; + +static const struct { + const char *name; + ElfW(Addr) value; + ElfW(Addr) ** func; +} vsyms[] = { + { + .name = "__vdso_shim_clock_gettime", + .value = (ElfW(Addr))&__shim_clock_gettime, + .func = &__vdso_shim_clock_gettime, + }, + { + .name = "__vdso_shim_gettimeofday", + .value = (ElfW(Addr))&__shim_gettimeofday, + .func = &__vdso_shim_gettimeofday, + }, + { + .name = "__vdso_shim_time", + .value = (ElfW(Addr))&__shim_time, + .func = &__vdso_shim_time, + }, + { + .name = "__vdso_shim_getcpu", + .value = (ElfW(Addr))&__shim_getcpu, + .func = &__vdso_shim_getcpu, + } +}; + +static int vdso_map_init(void) +{ + /* + * Allocate vdso page as user program allocated it. + * Using directly vdso code in LibOS causes trouble when emulating fork. + * In host child process, LibOS may or may not be loaded at the same address. + * When LibOS is loaded at different address, it may overlap with the old vDSO area. + */ + void *addr = bkeep_unmapped_heap( + ALIGN_UP(vdso_so_size), PROT_READ | PROT_EXEC, 0, NULL, 0, + "linux-vdso.so.1"); + if (addr == NULL) + return -ENOMEM; + assert(addr == ALIGN_UP(addr)); + + void *ret_addr = (void *)DkVirtualMemoryAlloc( + addr, ALIGN_UP(vdso_so_size), 0, PAL_PROT_READ | PAL_PROT_WRITE); + if (!ret_addr) + return -PAL_ERRNO; + assert(addr == ret_addr); + + memcpy(addr, &vdso_so, vdso_so_size); + memset(addr + vdso_so_size, 0, ALIGN_UP(vdso_so_size) - vdso_so_size); + __load_elf_object(NULL, addr, OBJECT_VDSO, NULL); + vdso_map->l_name = "vDSO"; + + for (size_t i = 0; i < sizeof(vsyms)/sizeof(vsyms[0]); i++) { + ElfW(Sym) *sym = __do_lookup(vsyms[i].name, NULL, vdso_map); + if (sym == NULL) { + debug("vDSO: symbol value for %s not found\n", vsyms[i].name); + continue; + } + *vsyms[i].func = (ElfW(Addr)*)(vdso_map->l_addr + sym->st_value); + **vsyms[i].func = vsyms[i].value; + } + + if (!DkVirtualMemoryProtect(addr, ALIGN_UP(vdso_so_size), + PAL_PROT_READ | PAL_PROT_EXEC)) + return -PAL_ERRNO; + + vdso_addr = addr; + return 0; +} + +int vdso_map_migrate(void) +{ + if (!vdso_addr) + return 0; + + if (!DkVirtualMemoryProtect(vdso_addr, ALIGN_UP(vdso_so_size), + PAL_PROT_READ | PAL_PROT_WRITE)) + return -PAL_ERRNO; + + /* adjust funcs to loaded address for newly loaded libsysdb */ + for (size_t i = 0; i < sizeof(vsyms)/sizeof(vsyms[0]); i++) + **vsyms[i].func = vsyms[i].value; + + if (!DkVirtualMemoryProtect(vdso_addr, ALIGN_UP(vdso_so_size), + PAL_PROT_READ | PAL_PROT_EXEC)) + return -PAL_ERRNO; + return 0; +} + int init_internal_map (void) { __load_elf_object(NULL, &__load_address, OBJECT_INTERNAL, NULL); @@ -1562,14 +1678,18 @@ noreturn void execute_elf_object (struct shim_handle * exec, int * argcp, const char ** argp, ElfW(auxv_t) * auxp) { + int ret = vdso_map_init(); + if (ret < 0) { + SYS_PRINTF("Could not initialize vDSO (error code = %d)", ret); + shim_clean(ret); + } + struct link_map * exec_map = __search_map_by_handle(exec); assert(exec_map); assert((uintptr_t)argcp % 16 == 0); /* stack must be 16B-aligned */ assert((void*)argcp + sizeof(long) == argp || argp == NULL); - /* populate ELF aux vectors */ - assert(REQUIRED_ELF_AUXV >= 7); /* stack allocated enough space */ - + assert(REQUIRED_ELF_AUXV >= 8); /* stack allocated enough space */ auxp[0].a_type = AT_PHDR; auxp[0].a_un.a_val = (__typeof(auxp[0].a_un.a_val)) exec_map->l_phdr; auxp[1].a_type = AT_PHNUM; @@ -1582,15 +1702,22 @@ noreturn void execute_elf_object (struct shim_handle * exec, auxp[4].a_un.a_val = interp_map ? interp_map->l_addr : 0; auxp[5].a_type = AT_RANDOM; auxp[5].a_un.a_val = 0; /* filled later */ - auxp[6].a_type = AT_NULL; - auxp[6].a_un.a_val = 0; + if (vdso_addr) { + auxp[6].a_type = AT_SYSINFO_EHDR; + auxp[6].a_un.a_val = (uint64_t)vdso_addr; + } else { + auxp[6].a_type = AT_NULL; + auxp[6].a_un.a_val = 0; + } + auxp[7].a_type = AT_NULL; + auxp[7].a_un.a_val = 0; /* populate extra memory space for aux vector data */ assert(REQUIRED_ELF_AUXV_SPACE >= 16); /* stack allocated enough space */ - ElfW(Addr) auxp_extra = (ElfW(Addr))&auxp[7]; + ElfW(Addr) auxp_extra = (ElfW(Addr))&auxp[8]; ElfW(Addr) random = auxp_extra; /* random 16B for AT_RANDOM */ - int ret = DkRandomBitsRead((PAL_PTR)random, 16); + ret = DkRandomBitsRead((PAL_PTR)random, 16); if (ret < 0) { debug("execute_elf_object: DkRandomBitsRead failed.\n"); DkThreadExit(); diff --git a/LibOS/shim/src/shim_init.c b/LibOS/shim/src/shim_init.c index bb07f083..4bb38d5d 100644 --- a/LibOS/shim/src/shim_init.c +++ b/LibOS/shim/src/shim_init.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -801,8 +802,10 @@ restore: shim_tcb_t * cur_tcb = shim_get_tls(); struct shim_thread * cur_thread = (struct shim_thread *) cur_tcb->tp; - if (cur_tcb->context.regs && cur_tcb->context.regs->rsp) + if (cur_tcb->context.regs && cur_tcb->context.regs->rsp) { + vdso_map_migrate(); restore_context(&cur_tcb->context); + } if (cur_thread->exec) execute_elf_object(cur_thread->exec, argcp, argp, auxp); diff --git a/LibOS/shim/src/vdso/.gitignore b/LibOS/shim/src/vdso/.gitignore new file mode 100644 index 00000000..dfaf50d0 --- /dev/null +++ b/LibOS/shim/src/vdso/.gitignore @@ -0,0 +1,2 @@ +/vdso-data.c +/vdso.so.dbg diff --git a/LibOS/shim/src/vdso/vdso-data.S b/LibOS/shim/src/vdso/vdso-data.S new file mode 100644 index 00000000..54c23730 --- /dev/null +++ b/LibOS/shim/src/vdso/vdso-data.S @@ -0,0 +1,19 @@ + .section .rodata + + .global vdso_so + .type vdso_so, @object + .align 4 +vdso_so: + .incbin "vdso/vdso.so" + + .global vdso_so_end + .type vdso_so_end, @object + .align 4 +vdso_so_end: + + .global vdso_so_size + .type vdso_so_size, @object + .size vdso_so_size, 8 + .align 8 +vdso_so_size: + .quad vdso_so_end - vdso_so diff --git a/LibOS/shim/src/vdso/vdso-note.S b/LibOS/shim/src/vdso/vdso-note.S new file mode 100644 index 00000000..545bc476 --- /dev/null +++ b/LibOS/shim/src/vdso/vdso-note.S @@ -0,0 +1,19 @@ + /* This .note section informs dynamic linker about vDSO */ + .section .note.Linux, "a", @note + + .balign 4 + .long 6 /* namesz */ + .long 4 /* descsz */ + .long 0 /* type */ + .string "Linux" /* name */ + .zero 2 /* padding for 4-byte alignment */ + .long 267008 /* LINUX_VERSION_CODE */ + + .balign 4 + .long 6 /* namesz */ + .long 4 /* descsz */ + .long 0x100 /* type */ + .string "Linux" /* name */ + .zero 2 /* padding for 4-byte alignment */ + .long 0 /* CONFIG_BUILD_SALT. 0 for now. + TODO: make it compile-time configurable */ diff --git a/LibOS/shim/src/vdso/vdso.c b/LibOS/shim/src/vdso/vdso.c new file mode 100644 index 00000000..a689ea52 --- /dev/null +++ b/LibOS/shim/src/vdso/vdso.c @@ -0,0 +1,63 @@ +/* Copyright (C) 2018 Intel Corporation + Isaku Yamahata + + All Rights Reserved. + + This file is part of Graphene Library OS. + + Graphene Library OS is free software: you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation, either version 3 of the + License, or (at your option) any later version. + + Graphene Library OS 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ + +#include + +int (*__vdso_shim_clock_gettime)(clockid_t clock, struct timespec *t) = NULL; +int (*__vdso_shim_gettimeofday)(struct timeval *tv, struct timezone *tz) = NULL; +time_t (*__vdso_shim_time)(time_t *t) = NULL; +long (*__vdso_shim_getcpu)(unsigned *cpu, struct getcpu_cache *unused) = NULL; + + +int __vdso_clock_gettime(clockid_t clock, struct timespec *t) +{ + if (__vdso_shim_clock_gettime) + return (*__vdso_shim_clock_gettime)(clock, t); + return -ENOSYS; +} +int clock_gettime(clockid_t clock, struct timespec *t) + __attribute__((weak, alias("__vdso_clock_gettime"))); + +int __vdso_gettimeofday(struct timeval *tv, struct timezone *tz) +{ + if (__vdso_shim_gettimeofday) + return (*__vdso_shim_gettimeofday)(tv, tz); + return -ENOSYS; +} +int gettimeofday(struct timeval *tv, struct timezone *tz) + __attribute__((weak, alias("__vdso_gettimeofday"))); + +time_t __vdso_time(time_t *t) +{ + if (__vdso_shim_time) + return (*__vdso_shim_time)(t); + return -ENOSYS; +} +time_t time(time_t *t) __attribute__((weak, alias("__vdso_time"))); + +long __vdso_getcpu(unsigned *cpu, struct getcpu_cache *unused) +{ + if (__vdso_shim_getcpu) + return (*__vdso_shim_getcpu)(cpu, unused); + return -ENOSYS; +} +long getcpu(unsigned *cpu, struct getcpu_cache *unused) + __attribute__((weak, alias("__vdso_getcpu"))); diff --git a/LibOS/shim/src/vdso/vdso.lds b/LibOS/shim/src/vdso/vdso.lds new file mode 100644 index 00000000..f278c015 --- /dev/null +++ b/LibOS/shim/src/vdso/vdso.lds @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2018 Intel Corporation + * Isaku Yamahata + * + * All Rights Reserved. + * This file is part of Graphene Library OS. + * + * Graphene Library OS is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * Graphene Library OS 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Linker script for Graphene vDSO emulation + */ + +PHDRS +{ + text PT_LOAD FLAGS(5) FILEHDR PHDRS; + dynamic PT_DYNAMIC FLAGS(4); + note PT_NOTE FLAGS(4); + eh_frame_header PT_GNU_EH_FRAME; +} + +SECTIONS +{ + . = SIZEOF_HEADERS; + .hash : { *(.hash) } :text + .gnu.hash : { *(.gnu.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .dynamic : { *(.dynamic) } :text :dynamic + .rodata : { + *(.rodata*) + *(.data*) + *(.sdata*) + *(.got.plt) *(.got) + *(.gnu.linkonce.d.*) + *(.bss*) + *(.dynbss*) + *(.gnu.linkonce.b.*) + } : text + .note : { *(.note.*) } :text :note + .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr + .eh_frame : { KEEP (*(.eh_frame)) } :text + .text : { *(.text*) } : text = 0x909090 + + /DISCARD/ : { + *(.discard) + *(.discard.*) + } +} + +VERSION { + LINUX_2.6 { + global: + clock_gettime; + __vdso_clock_gettime; + gettimeofday; + __vdso_gettimeofday; + getcpu; + __vdso_getcpu; + time; + __vdso_time; + + __vdso_shim_clock_gettime; + __vdso_shim_gettimeofday; + __vdso_shim_getcpu; + __vdso_shim_time; + local: *; + }; +} diff --git a/Makefile.configs b/Makefile.configs index 3da199bc..71c491a7 100644 --- a/Makefile.configs +++ b/Makefile.configs @@ -10,3 +10,4 @@ endif ifeq ($(origin LD),default) LD = ld endif +OBJCOPY ?= objcopy diff --git a/Makefile.rules b/Makefile.rules index 777f8108..b4a47aae 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -69,13 +69,11 @@ CLEAN_FILES += generated_offsets.py generated_offsets.pyc quiet_cmd_ln_sf = [ $@ ] cmd_ln_sf = ln -sf $(abspath $<) $@ - cc-option = $(shell set -e; \ if ($(CC) -Werror $(1) -c -x c /dev/null -o /dev/null) >/dev/null 2>&1; \ then echo "$(1)"; \ fi) - # .c quiet_cmd_cc_o_c = [ $@ ] cmd_cc_o_c = $(CC) $(CFLAGS) $(CFLAGS-$@) -c -o $@ $< @@ -103,3 +101,11 @@ quiet_cmd_ar_so_o = [ $@ ] quiet_cmd_ar_a_o = [ $@ ] cmd_ar_a_o = $(AR) $(ARFLAGS) $(ARFLAGS-$@) $@ $^ + +# LD only +quiet_cmd_ld = [ $@ ] + cmd_ld = $(LD) $(LDFLAGS) $(LDFLAGS-$@) -o $@ $(filter-out %.map %.lds,$^) + +# OBJCOPY +quiet_cmd_objcopy = [ $@ ] + cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS-$@) $< $@