Revision | 60eae0def70b8a2e768c6a5bec352da9d648b26c (tree) |
---|---|
Time | 2019-11-01 08:39:10 |
Author | Waldemar Brodkorb <wbx@open...> |
Commiter | Waldemar Brodkorb |
riscv64: add shared library support
@@ -480,7 +480,7 @@ config LDSO_LD_LIBRARY_PATH | ||
480 | 480 | |
481 | 481 | config UCLIBC_CTOR_DTOR |
482 | 482 | bool |
483 | - default y | |
483 | + default y if !TARGET_riscv64 | |
484 | 484 | help |
485 | 485 | If you wish to build uClibc with support for global constructor |
486 | 486 | (ctor) and global destructor (dtor) support, then answer Y here. |
@@ -12,4 +12,3 @@ config FORCE_OPTIONS_FOR_ARCH | ||
12 | 12 | default y |
13 | 13 | select ARCH_LITTLE_ENDIAN |
14 | 14 | select ARCH_HAS_MMU |
15 | - select ARCH_HAS_NO_LDSO |
@@ -271,6 +271,7 @@ typedef struct | ||
271 | 271 | #define EM_AARCH64 183 /* ARM AARCH64 */ |
272 | 272 | #define EM_MICROBLAZE 189 /* Xilinx Microblaze */ |
273 | 273 | #define EM_ARCV2 195 /* ARCv2 Cores */ |
274 | +#define EM_RISCV 243 /* RISC-V */ | |
274 | 275 | #define EM_CSKY 252 /* C-SKY Cores */ |
275 | 276 | |
276 | 277 | /* NEXT FREE NUMBER: Increment this after adding your official arch number */ |
@@ -3725,6 +3726,72 @@ typedef Elf32_Addr Elf32_Conflict; | ||
3725 | 3726 | #define R_ARC_TLS_LE_S9 0x4a |
3726 | 3727 | #define R_ARC_TLS_LE_32 0x4b |
3727 | 3728 | |
3729 | +/* RISC-V ELF Flags */ | |
3730 | +#define EF_RISCV_RVC 0x0001 | |
3731 | +#define EF_RISCV_FLOAT_ABI 0x0006 | |
3732 | +#define EF_RISCV_FLOAT_ABI_SOFT 0x0000 | |
3733 | +#define EF_RISCV_FLOAT_ABI_SINGLE 0x0002 | |
3734 | +#define EF_RISCV_FLOAT_ABI_DOUBLE 0x0004 | |
3735 | +#define EF_RISCV_FLOAT_ABI_QUAD 0x0006 | |
3736 | + | |
3737 | +/* RISC-V relocations. */ | |
3738 | +#define R_RISCV_NONE 0 | |
3739 | +#define R_RISCV_32 1 | |
3740 | +#define R_RISCV_64 2 | |
3741 | +#define R_RISCV_RELATIVE 3 | |
3742 | +#define R_RISCV_COPY 4 | |
3743 | +#define R_RISCV_JUMP_SLOT 5 | |
3744 | +#define R_RISCV_TLS_DTPMOD32 6 | |
3745 | +#define R_RISCV_TLS_DTPMOD64 7 | |
3746 | +#define R_RISCV_TLS_DTPREL32 8 | |
3747 | +#define R_RISCV_TLS_DTPREL64 9 | |
3748 | +#define R_RISCV_TLS_TPREL32 10 | |
3749 | +#define R_RISCV_TLS_TPREL64 11 | |
3750 | +#define R_RISCV_BRANCH 16 | |
3751 | +#define R_RISCV_JAL 17 | |
3752 | +#define R_RISCV_CALL 18 | |
3753 | +#define R_RISCV_CALL_PLT 19 | |
3754 | +#define R_RISCV_GOT_HI20 20 | |
3755 | +#define R_RISCV_TLS_GOT_HI20 21 | |
3756 | +#define R_RISCV_TLS_GD_HI20 22 | |
3757 | +#define R_RISCV_PCREL_HI20 23 | |
3758 | +#define R_RISCV_PCREL_LO12_I 24 | |
3759 | +#define R_RISCV_PCREL_LO12_S 25 | |
3760 | +#define R_RISCV_HI20 26 | |
3761 | +#define R_RISCV_LO12_I 27 | |
3762 | +#define R_RISCV_LO12_S 28 | |
3763 | +#define R_RISCV_TPREL_HI20 29 | |
3764 | +#define R_RISCV_TPREL_LO12_I 30 | |
3765 | +#define R_RISCV_TPREL_LO12_S 31 | |
3766 | +#define R_RISCV_TPREL_ADD 32 | |
3767 | +#define R_RISCV_ADD8 33 | |
3768 | +#define R_RISCV_ADD16 34 | |
3769 | +#define R_RISCV_ADD32 35 | |
3770 | +#define R_RISCV_ADD64 36 | |
3771 | +#define R_RISCV_SUB8 37 | |
3772 | +#define R_RISCV_SUB16 38 | |
3773 | +#define R_RISCV_SUB32 39 | |
3774 | +#define R_RISCV_SUB64 40 | |
3775 | +#define R_RISCV_GNU_VTINHERIT 41 | |
3776 | +#define R_RISCV_GNU_VTENTRY 42 | |
3777 | +#define R_RISCV_ALIGN 43 | |
3778 | +#define R_RISCV_RVC_BRANCH 44 | |
3779 | +#define R_RISCV_RVC_JUMP 45 | |
3780 | +#define R_RISCV_RVC_LUI 46 | |
3781 | +#define R_RISCV_GPREL_I 47 | |
3782 | +#define R_RISCV_GPREL_S 48 | |
3783 | +#define R_RISCV_TPREL_I 49 | |
3784 | +#define R_RISCV_TPREL_S 50 | |
3785 | +#define R_RISCV_RELAX 51 | |
3786 | +#define R_RISCV_SUB6 52 | |
3787 | +#define R_RISCV_SET6 53 | |
3788 | +#define R_RISCV_SET8 54 | |
3789 | +#define R_RISCV_SET16 55 | |
3790 | +#define R_RISCV_SET32 56 | |
3791 | +#define R_RISCV_32_PCREL 57 | |
3792 | + | |
3793 | +#define R_RISCV_NUM 58 | |
3794 | + | |
3728 | 3795 | #ifdef __cplusplus |
3729 | 3796 | } |
3730 | 3797 | #endif |
@@ -0,0 +1,90 @@ | ||
1 | +/* | |
2 | + * Architecture specific code used by dl-startup.c | |
3 | + * Copyright (C) 2019 Waldemar Brodkorb <wbx@uclibc-ng.org> | |
4 | + * Ported from GNU libc | |
5 | + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. | |
6 | + */ | |
7 | + | |
8 | +/* Copyright (C) 2011-2019 Free Software Foundation, Inc. | |
9 | + | |
10 | + The GNU C Library is free software; you can redistribute it and/or | |
11 | + modify it under the terms of the GNU Lesser General Public License as | |
12 | + published by the Free Software Foundation; either version 2.1 of the | |
13 | + License, or (at your option) any later version. | |
14 | + | |
15 | + The GNU C Library is distributed in the hope that it will be useful, | |
16 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
18 | + Lesser General Public License for more details. | |
19 | + | |
20 | + You should have received a copy of the GNU Lesser General Public | |
21 | + License along with the GNU C Library; if not, see | |
22 | + <https://www.gnu.org/licenses/>. */ | |
23 | + | |
24 | +#include <features.h> | |
25 | +#include <sys/asm.h> | |
26 | + | |
27 | +#ifndef _RTLD_PROLOGUE | |
28 | +# define _RTLD_PROLOGUE(entry) \ | |
29 | + ".globl\t" __STRING (entry) "\n\t" \ | |
30 | + ".type\t" __STRING (entry) ", @function\n" \ | |
31 | + __STRING (entry) ":\n\t" | |
32 | +#endif | |
33 | + | |
34 | +#ifndef _RTLD_EPILOGUE | |
35 | +# define _RTLD_EPILOGUE(entry) \ | |
36 | + ".size\t" __STRING (entry) ", . - " __STRING (entry) "\n\t" | |
37 | +#endif | |
38 | + | |
39 | +#define STRINGXP(X) __STRING (X) | |
40 | + | |
41 | +__asm__(\ | |
42 | + ".text\n\ | |
43 | + " _RTLD_PROLOGUE (_start) "\ | |
44 | + mv a0, sp\n\ | |
45 | + jal _dl_start\n\ | |
46 | + # Stash user entry point in s0.\n\ | |
47 | + mv s0, a0\n\ | |
48 | + # See if we were run as a command with the executable file\n\ | |
49 | + # name as an extra leading argument.\n\ | |
50 | + lw a0, _dl_skip_args\n\ | |
51 | + # Load the original argument count.\n\ | |
52 | + " STRINGXP (REG_L) " a1, 0(sp)\n\ | |
53 | + # Subtract _dl_skip_args from it.\n\ | |
54 | + sub a1, a1, a0\n\ | |
55 | + # Adjust the stack pointer to skip _dl_skip_args words.\n\ | |
56 | + sll a0, a0, " STRINGXP (PTRLOG) "\n\ | |
57 | + add sp, sp, a0\n\ | |
58 | + # Save back the modified argument count.\n\ | |
59 | + " STRINGXP (REG_S) " a1, 0(sp)\n\ | |
60 | + # Pass our finalizer function to _start.\n\ | |
61 | + lla a0, _dl_fini\n\ | |
62 | + # Jump to the user entry point.\n\ | |
63 | + jr s0\n\ | |
64 | + " _RTLD_EPILOGUE (_start) "\ | |
65 | + .previous" \ | |
66 | +); | |
67 | + | |
68 | +/* Get a pointer to the argv array. On many platforms this can be just | |
69 | + * the address of the first argument, on other platforms we need to | |
70 | + * do something a little more subtle here. */ | |
71 | +#define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*)ARGS)+1) | |
72 | + | |
73 | +/* Function calls are not safe until the GOT relocations have been done. */ | |
74 | +#define NO_FUNCS_BEFORE_BOOTSTRAP | |
75 | + | |
76 | +/* Handle relocation of the symbols in the dynamic loader. */ | |
77 | +static __always_inline | |
78 | +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, ElfW(Addr) *reloc_addr, | |
79 | + ElfW(Addr) symbol_addr, ElfW(Addr) load_addr, ElfW(Addr) *sym) | |
80 | +{ | |
81 | + switch (ELF_R_TYPE(rpnt->r_info)) { | |
82 | + case R_RISCV_NONE: | |
83 | + break; | |
84 | + case R_RISCV_JUMP_SLOT: | |
85 | + *reloc_addr = symbol_addr + rpnt->r_addend; | |
86 | + break; | |
87 | + default: | |
88 | + _dl_exit(1); | |
89 | + } | |
90 | +} |
@@ -0,0 +1 @@ | ||
1 | +/* stub for arch-specific syscall issues */ |
@@ -0,0 +1,91 @@ | ||
1 | +/* | |
2 | + * Various assembly language/system dependent hacks that are required | |
3 | + * so that we can minimize the amount of platform specific code. | |
4 | + * Copyright (C) 2000-2004 by Erik Andersen <andersen@codepoet.org> | |
5 | + * Copyright (C) 2019 by Waldemar Brodkorb <wbx@uclibc-ng.org> | |
6 | + * Ported from GNU C Library | |
7 | + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. | |
8 | + */ | |
9 | + | |
10 | +/* Copyright (C) 2011-2019 Free Software Foundation, Inc. | |
11 | + | |
12 | + The GNU C Library is free software; you can redistribute it and/or | |
13 | + modify it under the terms of the GNU Lesser General Public License as | |
14 | + published by the Free Software Foundation; either version 2.1 of the | |
15 | + License, or (at your option) any later version. | |
16 | + | |
17 | + The GNU C Library is distributed in the hope that it will be useful, | |
18 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
20 | + Lesser General Public License for more details. | |
21 | + | |
22 | + You should have received a copy of the GNU Lesser General Public | |
23 | + License along with the GNU C Library; if not, see | |
24 | + <https://www.gnu.org/licenses/>. */ | |
25 | + | |
26 | +/* Define this if the system uses RELOCA. */ | |
27 | +#define ELF_USES_RELOCA | |
28 | + | |
29 | +#include <elf.h> | |
30 | +#include <link.h> | |
31 | + | |
32 | +/* Initialization sequence for the GOT. */ | |
33 | +#define INIT_GOT(GOT_BASE,MODULE) \ | |
34 | +{ \ | |
35 | + GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \ | |
36 | + GOT_BASE[1] = (unsigned long) MODULE; \ | |
37 | +} | |
38 | + | |
39 | +/* Here we define the magic numbers that this dynamic loader should accept */ | |
40 | +#define MAGIC1 EM_RISCV | |
41 | +#undef MAGIC2 | |
42 | + | |
43 | +/* Used for error messages */ | |
44 | +#define ELF_TARGET "RISC-V" | |
45 | + | |
46 | +struct elf_resolve; | |
47 | +unsigned long _dl_linux_resolver(struct elf_resolve * tpnt, int reloc_entry); | |
48 | + | |
49 | +#define ELF_MACHINE_JMP_SLOT R_RISCV_JUMP_SLOT | |
50 | + | |
51 | +#define elf_machine_type_class(type) \ | |
52 | + ((ELF_RTYPE_CLASS_PLT * ((type) == ELF_MACHINE_JMP_SLOT \ | |
53 | + || (__WORDSIZE == 32 && (type) == R_RISCV_TLS_DTPREL32) \ | |
54 | + || (__WORDSIZE == 32 && (type) == R_RISCV_TLS_DTPMOD32) \ | |
55 | + || (__WORDSIZE == 32 && (type) == R_RISCV_TLS_TPREL32) \ | |
56 | + || (__WORDSIZE == 64 && (type) == R_RISCV_TLS_DTPREL64) \ | |
57 | + || (__WORDSIZE == 64 && (type) == R_RISCV_TLS_DTPMOD64) \ | |
58 | + || (__WORDSIZE == 64 && (type) == R_RISCV_TLS_TPREL64))) \ | |
59 | + | (ELF_RTYPE_CLASS_COPY * ((type) == R_RISCV_COPY))) | |
60 | + | |
61 | + | |
62 | +/* Return the link-time address of _DYNAMIC. */ | |
63 | +static inline ElfW(Addr) | |
64 | +elf_machine_dynamic (void) | |
65 | +{ | |
66 | + extern ElfW(Addr) _GLOBAL_OFFSET_TABLE_ __attribute__ ((visibility ("hidden"))); | |
67 | + return _GLOBAL_OFFSET_TABLE_; | |
68 | +} | |
69 | + | |
70 | + | |
71 | +/* Return the run-time load address of the shared object. */ | |
72 | +static __always_inline ElfW(Addr) __attribute__ ((unused)) | |
73 | +elf_machine_load_address (void) | |
74 | +{ | |
75 | + ElfW(Addr) load_addr; | |
76 | + __asm__ ("lla %0, _DYNAMIC" : "=r" (load_addr)); | |
77 | + return load_addr - elf_machine_dynamic (); | |
78 | +} | |
79 | + | |
80 | +static __always_inline void | |
81 | +elf_machine_relative(Elf64_Addr load_off, const Elf64_Addr rel_addr, | |
82 | + Elf64_Word relative_count) | |
83 | +{ | |
84 | + Elf64_Rela *rpnt = (Elf64_Rela*)rel_addr; | |
85 | + --rpnt; | |
86 | + do { | |
87 | + Elf64_Addr *const reloc_addr = (Elf64_Addr*)(load_off + (++rpnt)->r_offset); | |
88 | + | |
89 | + *reloc_addr = load_off + rpnt->r_addend; | |
90 | + } while (--relative_count); | |
91 | +} |
@@ -0,0 +1,279 @@ | ||
1 | +/* RISCV ELF shared library loader suppport | |
2 | + * | |
3 | + * Copyright (C) 2001-2004 Erik Andersen | |
4 | + * Copyright (C) 2019 Waldemar Brodkorb <wbx@uclibc-ng.org> | |
5 | + * | |
6 | + * All rights reserved. | |
7 | + * | |
8 | + * Redistribution and use in source and binary forms, with or without | |
9 | + * modification, are permitted provided that the following conditions | |
10 | + * are met: | |
11 | + * 1. Redistributions of source code must retain the above copyright | |
12 | + * notice, this list of conditions and the following disclaimer. | |
13 | + * 2. The name of the above contributors may not be | |
14 | + * used to endorse or promote products derived from this software | |
15 | + * without specific prior written permission. | |
16 | + * | |
17 | + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND | |
18 | + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
19 | + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
20 | + * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE | |
21 | + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
22 | + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
23 | + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
24 | + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
25 | + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
26 | + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
27 | + * SUCH DAMAGE. | |
28 | + */ | |
29 | + | |
30 | +/* Program to load an ELF binary on a linux system, and run it. | |
31 | + References to symbols in sharable libraries can be resolved by either | |
32 | + an ELF sharable library or a linux style of shared library. */ | |
33 | + | |
34 | +#include "ldso.h" | |
35 | + | |
36 | +#if defined(USE_TLS) && USE_TLS | |
37 | +#include "dl-tls.h" | |
38 | +#include "tlsdeschtab.h" | |
39 | +#endif | |
40 | + | |
41 | +extern int _dl_linux_resolve(void); | |
42 | + | |
43 | +unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry) | |
44 | +{ | |
45 | + ELF_RELOC *this_reloc; | |
46 | + char *strtab; | |
47 | + ElfW(Sym) *symtab; | |
48 | + int symtab_index; | |
49 | + char *rel_addr; | |
50 | + char *new_addr; | |
51 | + char **got_addr; | |
52 | + ElfW(Addr) instr_addr; | |
53 | + char *symname; | |
54 | + | |
55 | + rel_addr = (char *)tpnt->dynamic_info[DT_JMPREL]; | |
56 | + this_reloc = (ELF_RELOC *)(rel_addr + reloc_entry); | |
57 | + symtab_index = ELF_R_SYM(this_reloc->r_info); | |
58 | + | |
59 | + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; | |
60 | + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; | |
61 | + symname = strtab + symtab[symtab_index].st_name; | |
62 | + | |
63 | + /* Address of jump instruction to fix up */ | |
64 | + instr_addr = (this_reloc->r_offset + tpnt->loadaddr); | |
65 | + got_addr = (char **)instr_addr; | |
66 | + | |
67 | + /* Get the address of the GOT entry */ | |
68 | + new_addr = _dl_find_hash(symname, &_dl_loaded_modules->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL); | |
69 | + if (unlikely(!new_addr)) { | |
70 | + _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname); | |
71 | + _dl_exit(1); | |
72 | + } | |
73 | +#if defined (__SUPPORT_LD_DEBUG__) | |
74 | + if (_dl_debug_bindings) { | |
75 | + _dl_dprintf(_dl_debug_file, "\nresolve function: %s", symname); | |
76 | + if (_dl_debug_detail) _dl_dprintf(_dl_debug_file, | |
77 | + "\tpatched %x ==> %x @ %x", *got_addr, new_addr, got_addr); | |
78 | + } | |
79 | + if (!_dl_debug_nofixups) { | |
80 | + *got_addr = new_addr; | |
81 | + } | |
82 | +#else | |
83 | + *got_addr = new_addr; | |
84 | +#endif | |
85 | + return (unsigned long)new_addr; | |
86 | +} | |
87 | + | |
88 | +static int | |
89 | +_dl_parse(struct elf_resolve *tpnt, struct r_scope_elem *scope, | |
90 | + unsigned long rel_addr, unsigned long rel_size, | |
91 | + int (*reloc_fnc) (struct elf_resolve *tpnt, struct r_scope_elem *scope, | |
92 | + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab)) | |
93 | +{ | |
94 | + unsigned int i; | |
95 | + char *strtab; | |
96 | + ElfW(Sym) *symtab; | |
97 | + ELF_RELOC *rpnt; | |
98 | + int symtab_index; | |
99 | + | |
100 | + /* Parse the relocation information */ | |
101 | + rpnt = (ELF_RELOC *)rel_addr; | |
102 | + rel_size = rel_size / sizeof(ELF_RELOC); | |
103 | + | |
104 | + symtab = (ElfW(Sym) *)tpnt->dynamic_info[DT_SYMTAB]; | |
105 | + strtab = (char *)tpnt->dynamic_info[DT_STRTAB]; | |
106 | + | |
107 | + for (i = 0; i < rel_size; i++, rpnt++) { | |
108 | + int res; | |
109 | + | |
110 | + symtab_index = ELF_R_SYM(rpnt->r_info); | |
111 | + | |
112 | + debug_sym(symtab, strtab, symtab_index); | |
113 | + debug_reloc(symtab, strtab, rpnt); | |
114 | + | |
115 | + res = reloc_fnc(tpnt, scope, rpnt, symtab, strtab); | |
116 | + | |
117 | + if (res==0) | |
118 | + continue; | |
119 | + | |
120 | + _dl_dprintf(2, "\n%s: ", _dl_progname); | |
121 | + | |
122 | + if (symtab_index) | |
123 | + _dl_dprintf(2, "symbol '%s': ", | |
124 | + strtab + symtab[symtab_index].st_name); | |
125 | + | |
126 | + if (unlikely(res < 0)) { | |
127 | + int reloc_type = ELF_R_TYPE(rpnt->r_info); | |
128 | + _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type); | |
129 | + _dl_exit(-res); | |
130 | + } else if (unlikely(res > 0)) { | |
131 | + _dl_dprintf(2, "can't resolve symbol\n"); | |
132 | + return res; | |
133 | + } | |
134 | + } | |
135 | + | |
136 | + return 0; | |
137 | +} | |
138 | + | |
139 | +static int | |
140 | +_dl_do_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, | |
141 | + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) | |
142 | +{ | |
143 | + int reloc_type; | |
144 | + int symtab_index; | |
145 | + char *symname; | |
146 | +#if defined USE_TLS && USE_TLS | |
147 | + struct elf_resolve *tls_tpnt = NULL; | |
148 | +#endif | |
149 | + struct symbol_ref sym_ref; | |
150 | + ElfW(Addr) *reloc_addr; | |
151 | + ElfW(Addr) symbol_addr; | |
152 | +#if defined (__SUPPORT_LD_DEBUG__) | |
153 | + ElfW(Addr) old_val; | |
154 | +#endif | |
155 | + | |
156 | + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + (unsigned long)rpnt->r_offset); | |
157 | + reloc_type = ELF_R_TYPE(rpnt->r_info); | |
158 | + symtab_index = ELF_R_SYM(rpnt->r_info); | |
159 | + sym_ref.sym = &symtab[symtab_index]; | |
160 | + sym_ref.tpnt = NULL; | |
161 | + symbol_addr = 0; | |
162 | + symname = strtab + sym_ref.sym->st_name; | |
163 | + | |
164 | + if (symtab_index) { | |
165 | + symbol_addr = (ElfW(Addr))_dl_find_hash(symname, scope, tpnt, | |
166 | + elf_machine_type_class(reloc_type), &sym_ref); | |
167 | + | |
168 | + /* | |
169 | + * We want to allow undefined references to weak symbols - this might | |
170 | + * have been intentional. We should not be linking local symbols | |
171 | + * here, so all bases should be covered. | |
172 | + */ | |
173 | + if (unlikely (!symbol_addr && | |
174 | + (ELF_ST_TYPE(symtab[symtab_index].st_info) != STT_TLS) && | |
175 | + (ELF_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK))) { | |
176 | + return 1; | |
177 | + } | |
178 | + if (_dl_trace_prelink) { | |
179 | + _dl_debug_lookup (symname, tpnt, &symtab[symtab_index], | |
180 | + &sym_ref, elf_machine_type_class(reloc_type)); | |
181 | + } | |
182 | +#if defined USE_TLS && USE_TLS | |
183 | + tls_tpnt = sym_ref.tpnt; | |
184 | +#endif | |
185 | + } else { | |
186 | + /* | |
187 | + * Relocs against STN_UNDEF are usually treated as using a | |
188 | + * symbol value of zero, and using the module containing the | |
189 | + * reloc itself. | |
190 | + */ | |
191 | + symbol_addr = sym_ref.sym->st_value; | |
192 | +#if defined USE_TLS && USE_TLS | |
193 | + tls_tpnt = tpnt; | |
194 | +#endif | |
195 | + } | |
196 | + | |
197 | +#if defined (__SUPPORT_LD_DEBUG__) | |
198 | + old_val = *reloc_addr; | |
199 | +#endif | |
200 | + | |
201 | + switch (reloc_type) { | |
202 | + case R_RISCV_NONE: | |
203 | + break; | |
204 | + case R_RISCV_64: /* REL_SYMBOLIC */ | |
205 | + case R_RISCV_JUMP_SLOT: /* REL_PLT */ | |
206 | + *reloc_addr = symbol_addr + rpnt->r_addend; | |
207 | + break; | |
208 | + case R_RISCV_RELATIVE: | |
209 | + *reloc_addr += tpnt->loadaddr + rpnt->r_addend; | |
210 | + break; | |
211 | + case R_RISCV_COPY: | |
212 | + _dl_memcpy((void *) reloc_addr, | |
213 | + (void *) symbol_addr, sym_ref.sym->st_size); | |
214 | + break; | |
215 | + default: | |
216 | + return -1; /*call _dl_exit(1) */ | |
217 | + } | |
218 | + | |
219 | +#if defined (__SUPPORT_LD_DEBUG__) | |
220 | + if (_dl_debug_reloc && _dl_debug_detail) { | |
221 | + _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n", | |
222 | + old_val, *reloc_addr, reloc_addr); | |
223 | + } | |
224 | +#endif | |
225 | + | |
226 | + return 0; | |
227 | +} | |
228 | + | |
229 | +static int | |
230 | +_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct r_scope_elem *scope, | |
231 | + ELF_RELOC *rpnt, ElfW(Sym) *symtab, char *strtab) | |
232 | +{ | |
233 | + int reloc_type; | |
234 | + ElfW(Addr) *reloc_addr; | |
235 | +#if defined (__SUPPORT_LD_DEBUG__) | |
236 | + ElfW(Addr) old_val; | |
237 | +#endif | |
238 | + | |
239 | + (void)scope; | |
240 | + (void)strtab; | |
241 | + | |
242 | + reloc_addr = (ElfW(Addr)*)(tpnt->loadaddr + rpnt->r_offset); | |
243 | + reloc_type = ELF_R_TYPE(rpnt->r_info); | |
244 | + | |
245 | +#if defined (__SUPPORT_LD_DEBUG__) | |
246 | + old_val = *reloc_addr; | |
247 | +#endif | |
248 | + | |
249 | + switch (reloc_type) { | |
250 | + case R_RISCV_NONE: | |
251 | + break; | |
252 | + case R_RISCV_JUMP_SLOT: | |
253 | + *reloc_addr += tpnt->loadaddr; | |
254 | + break; | |
255 | + default: | |
256 | + return -1; /*call _dl_exit(1) */ | |
257 | + } | |
258 | + | |
259 | +#if defined (__SUPPORT_LD_DEBUG__) | |
260 | + if (_dl_debug_reloc && _dl_debug_detail) { | |
261 | + _dl_dprintf(_dl_debug_file, "\tpatched_lazy: %x ==> %x @ %x\n", | |
262 | + old_val, *reloc_addr, reloc_addr); | |
263 | + } | |
264 | +#endif | |
265 | + | |
266 | + return 0; | |
267 | +} | |
268 | + | |
269 | +void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt, | |
270 | + unsigned long rel_addr, unsigned long rel_size) | |
271 | +{ | |
272 | + (void)_dl_parse(rpnt->dyn, NULL, rel_addr, rel_size, _dl_do_lazy_reloc); | |
273 | +} | |
274 | + | |
275 | +int _dl_parse_relocation_information(struct dyn_elf *rpnt, | |
276 | + struct r_scope_elem *scope, unsigned long rel_addr, unsigned long rel_size) | |
277 | +{ | |
278 | + return _dl_parse(rpnt->dyn, scope, rel_addr, rel_size, _dl_do_reloc); | |
279 | +} |
@@ -0,0 +1,96 @@ | ||
1 | +/* | |
2 | + * Copyright (C) 2019 by Waldemar Brodkorb <wbx@uclibc-ng.org> | |
3 | + * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. | |
4 | + * ported from GNU libc | |
5 | + */ | |
6 | + | |
7 | +/* Copyright (C) 2017-2019 Free Software Foundation, Inc. | |
8 | + | |
9 | + The GNU C Library is free software; you can redistribute it and/or | |
10 | + modify it under the terms of the GNU Lesser General Public License as | |
11 | + published by the Free Software Foundation; either version 2.1 of the | |
12 | + License, or (at your option) any later version. | |
13 | + | |
14 | + The GNU C Library is distributed in the hope that it will be useful, | |
15 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | + Lesser General Public License for more details. | |
18 | + | |
19 | + You should have received a copy of the GNU Lesser General Public | |
20 | + License along with the GNU C Library. If not, see | |
21 | + <https://www.gnu.org/licenses/>. */ | |
22 | + | |
23 | +#include <features.h> | |
24 | + | |
25 | +#include <sysdep.h> | |
26 | +#include <sys/asm.h> | |
27 | + | |
28 | +/* Assembler veneer called from the PLT header code for lazy loading. | |
29 | + The PLT header passes its own args in t0-t2. */ | |
30 | + | |
31 | +#ifdef __riscv_float_abi_soft | |
32 | +# define FRAME_SIZE (-((-10 * SZREG) & ALMASK)) | |
33 | +#else | |
34 | +# define FRAME_SIZE (-((-10 * SZREG - 8 * SZFREG) & ALMASK)) | |
35 | +#endif | |
36 | + | |
37 | +ENTRY (_dl_linux_resolve) | |
38 | + # Save arguments to stack. | |
39 | + addi sp, sp, -FRAME_SIZE | |
40 | + REG_S ra, 9*SZREG(sp) | |
41 | + REG_S a0, 1*SZREG(sp) | |
42 | + REG_S a1, 2*SZREG(sp) | |
43 | + REG_S a2, 3*SZREG(sp) | |
44 | + REG_S a3, 4*SZREG(sp) | |
45 | + REG_S a4, 5*SZREG(sp) | |
46 | + REG_S a5, 6*SZREG(sp) | |
47 | + REG_S a6, 7*SZREG(sp) | |
48 | + REG_S a7, 8*SZREG(sp) | |
49 | + | |
50 | +#ifndef __riscv_float_abi_soft | |
51 | + FREG_S fa0, (10*SZREG + 0*SZFREG)(sp) | |
52 | + FREG_S fa1, (10*SZREG + 1*SZFREG)(sp) | |
53 | + FREG_S fa2, (10*SZREG + 2*SZFREG)(sp) | |
54 | + FREG_S fa3, (10*SZREG + 3*SZFREG)(sp) | |
55 | + FREG_S fa4, (10*SZREG + 4*SZFREG)(sp) | |
56 | + FREG_S fa5, (10*SZREG + 5*SZFREG)(sp) | |
57 | + FREG_S fa6, (10*SZREG + 6*SZFREG)(sp) | |
58 | + FREG_S fa7, (10*SZREG + 7*SZFREG)(sp) | |
59 | +#endif | |
60 | + | |
61 | + # Update .got.plt and obtain runtime address of callee. | |
62 | + slli a1, t1, 1 | |
63 | + mv a0, t0 # link map | |
64 | + add a1, a1, t1 # reloc offset (== thrice the .got.plt offset) | |
65 | + la a2, _dl_fixup | |
66 | + jalr a2 | |
67 | + mv t1, a0 | |
68 | + | |
69 | + # Restore arguments from stack. | |
70 | + REG_L ra, 9*SZREG(sp) | |
71 | + REG_L a0, 1*SZREG(sp) | |
72 | + REG_L a1, 2*SZREG(sp) | |
73 | + REG_L a2, 3*SZREG(sp) | |
74 | + REG_L a3, 4*SZREG(sp) | |
75 | + REG_L a4, 5*SZREG(sp) | |
76 | + REG_L a5, 6*SZREG(sp) | |
77 | + REG_L a6, 7*SZREG(sp) | |
78 | + REG_L a7, 8*SZREG(sp) | |
79 | + | |
80 | +#ifndef __riscv_float_abi_soft | |
81 | + FREG_L fa0, (10*SZREG + 0*SZFREG)(sp) | |
82 | + FREG_L fa1, (10*SZREG + 1*SZFREG)(sp) | |
83 | + FREG_L fa2, (10*SZREG + 2*SZFREG)(sp) | |
84 | + FREG_L fa3, (10*SZREG + 3*SZFREG)(sp) | |
85 | + FREG_L fa4, (10*SZREG + 4*SZFREG)(sp) | |
86 | + FREG_L fa5, (10*SZREG + 5*SZFREG)(sp) | |
87 | + FREG_L fa6, (10*SZREG + 6*SZFREG)(sp) | |
88 | + FREG_L fa7, (10*SZREG + 7*SZFREG)(sp) | |
89 | +#endif | |
90 | + | |
91 | + addi sp, sp, FRAME_SIZE | |
92 | + | |
93 | + # Invoke the callee. | |
94 | + jr t1 | |
95 | +END (_dl_linux_resolve) | |
96 | + |
@@ -500,7 +500,6 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc, | ||
500 | 500 | #endif |
501 | 501 | } |
502 | 502 | # endif |
503 | -#endif | |
504 | 503 | |
505 | 504 | /* Note: It is possible that any initialization done above could |
506 | 505 | * have resulted in errno being set nonzero, so set it to 0 before |
@@ -512,6 +511,7 @@ void __uClibc_main(int (*main)(int, char **, char **), int argc, | ||
512 | 511 | /* Set h_errno to 0 as well */ |
513 | 512 | if (likely(not_null_ptr(__h_errno_location))) |
514 | 513 | *(__h_errno_location()) = 0; |
514 | +#endif | |
515 | 515 | |
516 | 516 | #if defined HAVE_CLEANUP_JMP_BUF && defined __UCLIBC_HAS_THREADS_NATIVE__ |
517 | 517 | /* Memory for the cancellation buffer. */ |
@@ -8,7 +8,7 @@ | ||
8 | 8 | #undef __UCLIBC_ABORT_INSTRUCTION__ |
9 | 9 | |
10 | 10 | /* can your target use syscall6() for mmap ? */ |
11 | -#undef __UCLIBC_MMAP_HAS_6_ARGS__ | |
11 | +#define __UCLIBC_MMAP_HAS_6_ARGS__ | |
12 | 12 | |
13 | 13 | #define __UCLIBC_SYSCALL_ALIGN_64BIT__ |
14 | 14 |
@@ -0,0 +1,34 @@ | ||
1 | +/* Copyright (C) 2004 Erik Andersen | |
2 | + * | |
3 | + * This library is free software; you can redistribute it and/or | |
4 | + * modify it under the terms of the GNU Lesser General Public | |
5 | + * License as published by the Free Software Foundation; either | |
6 | + * version 2.1 of the License, or (at your option) any later version. | |
7 | + * | |
8 | + * The GNU C Library is distributed in the hope that it will be useful, | |
9 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
11 | + * Lesser General Public License for more details. | |
12 | + * | |
13 | + * You should have received a copy of the GNU Lesser General Public | |
14 | + * License along with the GNU C Library; see the file COPYING.LIB. If | |
15 | + * not, see <http://www.gnu.org/licenses/>. | |
16 | + */ | |
17 | + | |
18 | +/* Supply an architecture specific value for PAGE_SIZE and friends. */ | |
19 | + | |
20 | +#ifndef _UCLIBC_PAGE_H | |
21 | +#define _UCLIBC_PAGE_H | |
22 | + | |
23 | +/* PAGE_SHIFT determines the page size -- in this case 4096 */ | |
24 | +#define PAGE_SHIFT 13 | |
25 | +#define PAGE_SIZE (1UL << PAGE_SHIFT) | |
26 | +#define PAGE_MASK (~(PAGE_SIZE-1)) | |
27 | + | |
28 | +/* Some architectures always use 12 as page shift for mmap2() eventhough the | |
29 | + * real PAGE_SHIFT != 12. Other architectures use the same value as | |
30 | + * PAGE_SHIFT... | |
31 | + */ | |
32 | +#define MMAP2_PAGE_SHIFT PAGE_SHIFT | |
33 | + | |
34 | +#endif /* _UCLIBC_PAGE_H */ |
@@ -122,6 +122,11 @@ | ||
122 | 122 | #define ELFCLASSM ELFCLASS32 |
123 | 123 | #endif |
124 | 124 | |
125 | +#if defined(__riscv) | |
126 | +#define MATCH_MACHINE(x) (x == EM_RISCV) | |
127 | +#define ELFCLASSM ELFCLASS64 | |
128 | +#endif | |
129 | + | |
125 | 130 | #if defined(__sh__) |
126 | 131 | #define MATCH_MACHINE(x) (x == EM_SH) |
127 | 132 | #define ELFCLASSM ELFCLASS32 |