2 * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
4 * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in this tarball.
10 * Define this if the system uses RELOCA.
12 #define ELF_USES_RELOCA
15 * Dynamic Linking ABI for ARCompact ISA
18 * --------------------------------
19 * | ld r11, [pcl, off-to-GOT[1] | 0 (20 bytes)
21 * plt0 | ld r10, [pcl, off-to-GOT[2] | 8
24 * --------------------------------
25 * | Base address of GOT | 20
26 * --------------------------------
27 * | ld r12, [pcl, off-to-GOT[3] | 24 (12 bytes each)
30 * | mov_s r12, pcl | 34
31 * --------------------------------
36 * --------------------------------
42 * | [1] | Module info - setup by ldso
44 * | [2] | resolver entry point
47 * | ... | Runtime address for function symbols
51 * | ... | Runtime address for data symbols
57 * Initialization sequence for a GOT.
58 * Caller elf_resolve() seeds @GOT_BASE from DT_PLTGOT - which essentially is
59 * pointer to first PLT entry. The actual GOT base is 5th word in PLT
62 #define INIT_GOT(GOT_BASE,MODULE) \
64 unsigned long *__plt_base = (unsigned long *)GOT_BASE; \
65 GOT_BASE = (unsigned long *)(__plt_base[5] + \
66 (unsigned long)MODULE->loadaddr); \
67 GOT_BASE[1] = (unsigned long) MODULE; \
68 GOT_BASE[2] = (unsigned long) _dl_linux_resolve; \
71 /* Here we define the magic numbers that this dynamic loader should accept */
72 #define MAGIC1 EM_ARCOMPACT
75 /* Used for error messages */
76 #define ELF_TARGET "ARC"
79 extern unsigned long _dl_linux_resolver(struct elf_resolve * tpnt,
82 extern unsigned __udivmodsi4(unsigned, unsigned) attribute_hidden;
84 #define do_rem(result, n, base) ((result) = \
86 __builtin_constant_p (base) ? (n) % (unsigned) (base) : \
88 register unsigned r1 __asm__ ("r1") = (base); \
90 __asm__("bl.d @__udivmodsi4` mov r0,%1" \
93 : "r0", "r2", "r3", "r4", "lp_count", "blink", "cc"); \
99 /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry, so
100 PLT entries should not be allowed to define the value.
101 ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
102 of the main executable's symbols, as for a COPY reloc. */
103 #define elf_machine_type_class(type) \
104 ((((type) == R_ARC_JMP_SLOT) * ELF_RTYPE_CLASS_PLT) \
105 | (((type) == R_ARC_COPY) * ELF_RTYPE_CLASS_COPY))
108 * Get the runtime address of GOT[0]
110 static __always_inline Elf32_Addr elf_machine_dynamic(void)
114 __asm__("ld %0,[pcl,_DYNAMIC@gotpc]\n\t" : "=r" (dyn));
118 * Another way would have been to simply return GP, which due to some
119 * PIC reference would be automatically setup by gcc in caller
120 * register Elf32_Addr *got __asm__ ("gp"); return *got;
124 /* Return the run-time load address of the shared object. */
125 static __always_inline Elf32_Addr elf_machine_load_address(void)
127 /* To find the loadaddr we subtract the runtime addr of a non-local symbol
128 * say _DYNAMIC from it's build-time addr.
129 * N.B., gotpc loads get optimized by the linker if it finds the symbol
130 * is resolved locally.
131 * A more robust - and efficient - solution would be to use a symbol
132 * set by the linker. To make it actually save space, we'd have to
133 * suppress the unwanted text relocation in the linked dso, though.
134 * (I.e. in ldso.so.*, though it's just another dso as far as bfd/ld
137 Elf32_Addr addr, tmp;
139 "ld %1, [pcl, _DYNAMIC@gotpc] ;build addr of _DYNAMIC" "\n"
140 "add %0, pcl, _DYNAMIC@pcl ;runtime addr of _DYNAMIC" "\n"
141 "sub %0, %0, %1 ;delta" "\n"
142 : "=&r" (addr), "=r"(tmp)
147 static __always_inline void
148 elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
149 Elf32_Word relative_count)
151 Elf32_Rel * rpnt = (void *) rel_addr;
154 Elf32_Addr *const reloc_addr = (void *) (load_off + (++rpnt)->r_offset);
155 *reloc_addr += load_off;
156 } while (--relative_count);