Move tilegx, tilepro, and linux-generic from ports to libc.
[jlayton/glibc.git] / sysdeps / tile / dl-machine.h
1 /* Copyright (C) 2011-2014 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Chris Metcalf <cmetcalf@tilera.com>, 2011.
4    Based on work contributed by by Carl Pederson & Martin Schwidefsky.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library.  If not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #ifndef dl_machine_h
21 #define dl_machine_h
22
23 #ifdef __tilegx__
24 #define ELF_MACHINE_NAME "tilegx"
25 #else
26 #define ELF_MACHINE_NAME "tilepro"
27 #endif
28
29 #include <sys/param.h>
30 #include <string.h>
31 #include <link.h>
32 #include <bits/wordsize.h>
33 #include <arch/icache.h>
34 #include <arch/opcode.h>
35
36 /* Return nonzero iff ELF header is compatible with the running host.  */
37 static inline int
38 elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
39 {
40 #if defined __tilegx__
41   if (ehdr->e_machine != EM_TILEGX)
42     return 0;
43 # if __WORDSIZE == 32
44   return (ehdr->e_ident[EI_CLASS] == ELFCLASS32);
45 # else
46   return (ehdr->e_ident[EI_CLASS] == ELFCLASS64);
47 # endif
48 #elif defined __tilepro__
49   return ehdr->e_machine == EM_TILEPRO;
50 #else
51 # error "Unknown tile architecture."
52 #endif
53 }
54
55
56 /* Return the link-time address of _DYNAMIC.  Conveniently, this is the
57    first element of the GOT.  This must be inlined in a function which
58    uses global data.  */
59
60 static inline ElfW(Addr)
61 elf_machine_dynamic (void)
62 {
63   ElfW(Addr) *got;
64
65 #ifdef __tilegx__
66   ElfW(Addr) tmp;
67   asm( "        { lnk %0; moveli %1, hw2_last(_GLOBAL_OFFSET_TABLE_ - 1f) }\n"
68        "1:      shl16insli %1, %1, hw1(_GLOBAL_OFFSET_TABLE_ - 1b)\n"
69        "        shl16insli %1, %1, hw0(_GLOBAL_OFFSET_TABLE_ - 1b)\n"
70        "        add %0, %0, %1"
71        : "=r" (got), "=r" (tmp));
72 #else
73   asm( "        lnk %0\n"
74        "1:      addli %0, %0, lo16(_GLOBAL_OFFSET_TABLE_ - 1b)\n"
75        "        auli %0, %0, ha16(_GLOBAL_OFFSET_TABLE_ - 1b)"
76        : "=r" (got));
77 #endif
78
79   return *got;
80 }
81
82
83 /* Return the run-time load address of the shared object.  */
84 static inline ElfW(Addr)
85 elf_machine_load_address (void)
86 {
87   ElfW(Addr) *got;
88   ElfW(Addr) dynamic;
89
90 #ifdef __tilegx__
91   ElfW(Addr) tmp;
92   asm( "        lnk %2\n"
93        "1:      {\n"
94        "         moveli %0, hw2_last(_GLOBAL_OFFSET_TABLE_ - 1b)\n"
95        "         moveli %1, hw2_last(_DYNAMIC - 1b)\n"
96        "        }\n"
97        "        {\n"
98        "         shl16insli %0, %0, hw1(_GLOBAL_OFFSET_TABLE_ - 1b)\n"
99        "         shl16insli %1, %1, hw1(_DYNAMIC - 1b)\n"
100        "        }\n"
101        "        {\n"
102        "         shl16insli %0, %0, hw0(_GLOBAL_OFFSET_TABLE_ - 1b)\n"
103        "         shl16insli %1, %1, hw0(_DYNAMIC - 1b)\n"
104        "        }\n"
105        "        {\n"
106        "         add %0, %0, %2\n"
107        "         add %1, %1, %2\n"
108        "        }"
109        : "=r" (got), "=r" (dynamic), "=r" (tmp));
110 #else
111   asm( "        lnk %0\n"
112        "1:      {\n"
113        "         addli %0, %0, lo16(_GLOBAL_OFFSET_TABLE_ - 1b)\n"
114        "         addli %1, %0, lo16(_DYNAMIC - 1b)\n"
115        "        }\n"
116        "        {\n"
117        "         auli %0, %0, ha16(_GLOBAL_OFFSET_TABLE_ - 1b)\n"
118        "         auli %1, %1, ha16(_DYNAMIC - 1b)\n"
119        "        }\n"
120        : "=r" (got), "=r" (dynamic));
121 #endif
122
123   return dynamic - *got;
124 }
125
126 /* Flush some range of the instruction cache.  If invoked prior to
127    actually setting dl_pagesize, we conservatively use 4KB, which
128    is the smallest page size we could plausibly be running with.  */
129 static inline void
130 _dl_flush_icache (const void *addr, unsigned long size)
131 {
132   invalidate_icache (addr, size, GLRO(dl_pagesize) ? : 4096);
133 }
134
135 /* Set up the loaded object described by L so its unrelocated PLT
136    entries will jump to the on-demand fixup code in dl-runtime.c.  */
137
138 static inline int __attribute__ ((unused))
139 elf_machine_runtime_setup (struct link_map *l, int lazy, int profile)
140 {
141   ElfW(Addr) *gotplt;
142   extern void _dl_runtime_resolve (ElfW(Word));
143   extern void _dl_runtime_profile (ElfW(Word));
144
145   if (l->l_info[DT_JMPREL] && lazy)
146     {
147       gotplt = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]);
148
149       /* The GOT entries for functions in the PLT have not yet been filled
150          in.  Their initial contents will arrange when called to put in
151          registers an offset into the .rel.plt section, and gotplt[0], then
152          jump to gotplt[1].  */
153
154       /* Identify this shared object.  */
155       gotplt[0] = (ElfW(Addr)) l;
156
157       /* The gotplt[1] entry contains the address of a function which gets
158          called to get the address of a so far unresolved function and jump
159          to it.  The profiling extension of the dynamic linker allows to
160          intercept the calls to collect information.  In this case we don't
161          store the address in the GOTPLT so that all future calls also end
162          in this function.  */
163       if (__builtin_expect (profile, 0))
164         {
165           gotplt[1] = (ElfW(Addr)) &_dl_runtime_profile;
166
167           if (GLRO(dl_profile) != NULL
168               && _dl_name_match_p (GLRO(dl_profile), l))
169             /* This is the object we are looking for.  Say that we really
170                want profiling and the timers are started.  */
171             GL(dl_profile_map) = l;
172         }
173       else
174         /* This function will get called to fix up the GOTPLT entry
175            indicated by the offset on the stack, and then jump to the
176            resolved address.  */
177         gotplt[1] = (ElfW(Addr)) &_dl_runtime_resolve;
178     }
179
180   return lazy;
181 }
182
183 #if __WORDSIZE == 32
184 /* Mask identifying addresses reserved for the user program,
185    where the dynamic linker should not map anything.  */
186 #define ELF_MACHINE_USER_ADDRESS_MASK   0xf8000000UL
187 #endif
188
189 /* Initial entry point code for the dynamic linker.
190    The C function `_dl_start' is the real entry point;
191    its return value is the user program's entry point.  */
192
193 #define RTLD_START asm (".globl _dl_start");
194
195 #ifndef RTLD_START_SPECIAL_INIT
196 #define RTLD_START_SPECIAL_INIT /* nothing */
197 #endif
198
199 /* Wrap a generic Tilera relocation type. */
200 #ifdef __tilegx__
201 #define R_TILE(x) R_TILEGX_##x
202 #define __R_TILE_TLS(x,c) R_TILEGX_TLS_##x##c
203 #define _R_TILE_TLS(x,c) __R_TILE_TLS(x,c)
204 #define R_TILE_TLS(x) _R_TILE_TLS(x,__ELF_NATIVE_CLASS)
205 #else
206 #define R_TILE(x) R_TILEPRO_##x
207 #define R_TILE_TLS(x) R_TILEPRO_TLS_##x##32
208 #endif
209
210 /* ELF_RTYPE_CLASS_PLT iff TYPE describes relocation of a PLT entry or
211    TLS variable, so undefined references should not be allowed to
212    define the value.
213    ELF_RTYPE_CLASS_NOCOPY iff TYPE should not be allowed to resolve to one
214    of the main executable's symbols, as for a COPY reloc.  */
215 #define elf_machine_type_class(type) \
216   ((((type) == R_TILE(JMP_SLOT) || (type) == R_TILE_TLS(DTPMOD)               \
217      || (type) == R_TILE_TLS(DTPOFF) || (type) == R_TILE_TLS(TPOFF))          \
218     * ELF_RTYPE_CLASS_PLT)                                                    \
219    | (((type) == R_TILE(COPY)) * ELF_RTYPE_CLASS_COPY))
220
221 /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries.  */
222 #define ELF_MACHINE_JMP_SLOT R_TILE(JMP_SLOT)
223
224 /* TILE never uses Elf32_Rel relocations.  */
225 #define ELF_MACHINE_NO_REL 1
226
227 /* We define an initialization functions.  This is called very early in
228    _dl_sysdep_start.  */
229 #define DL_PLATFORM_INIT dl_platform_init ()
230
231 static inline void __attribute__ ((unused))
232 dl_platform_init (void)
233 {
234   if (GLRO(dl_platform) != NULL && *GLRO(dl_platform) == '\0')
235     /* Avoid an empty string which would disturb us.  */
236     GLRO(dl_platform) = NULL;
237 }
238
239 static inline ElfW(Addr)
240 elf_machine_fixup_plt (struct link_map *map, lookup_t t,
241                        const ElfW(Rela) *reloc,
242                        ElfW(Addr) *reloc_addr, ElfW(Addr) value)
243 {
244   return *reloc_addr = value;
245 }
246
247 /* Return the final value of a plt relocation.  */
248 static inline ElfW(Addr)
249 elf_machine_plt_value (struct link_map *map, const ElfW(Rela) *reloc,
250                        ElfW(Addr) value)
251 {
252   return value;
253 }
254
255 /* Support notifying the simulator about new objects. */
256 void internal_function _dl_after_load (struct link_map *l);
257 #define DL_AFTER_LOAD _dl_after_load
258
259 /* Names of the architecture-specific auditing callback functions.  */
260 #define ARCH_LA_PLTENTER tile_gnu_pltenter
261 #define ARCH_LA_PLTEXIT tile_gnu_pltexit
262
263 #endif /* !dl_machine_h */
264
265
266 #ifdef RESOLVE_MAP
267
268 struct reloc_howto
269 {
270   /* Right shift operand by this number of bits. */
271   unsigned char right_shift;
272
273 #ifdef __tilegx__
274   /* If nonzero, this is updating a code bundle. */
275   unsigned char is_bundle_update;
276 #else
277   /* If nonzero, add 0x8000 to the value. */
278   unsigned char add_0x8000;
279 #endif
280
281   /* If nonzero, subtract the containing address from the address. */
282   unsigned char is_pcrel;
283
284   /* Size in bytes, or 0 if this table entry should be ignored. */
285   unsigned char byte_size;
286 };
287
288 /* Relocation information. Cannot contain create_* function pointers
289    because then the table would not be position-independent. */
290 static const struct reloc_howto howto[] =
291 {
292 #ifdef __tilegx__
293
294 # if __WORDSIZE == 32
295   /* The GX -m32 loader only handles 32-bit types, so it will be confused
296      by shifts larger than that.  We convert them to just sign-extend;
297      they usually indicate a program bug or missed optimization, but we
298      have to handle them correctly anyway.  */
299 #  define S32 31
300 #  define S48 31
301 # else
302 #  define S32 32
303 #  define S48 48
304 # endif
305
306   /* R_TILEGX_NONE */                    {   0, 0, 0, 0 },
307   /* R_TILEGX_64 */                      {   0, 0, 0, 8 },
308   /* R_TILEGX_32 */                      {   0, 0, 0, 4 },
309   /* R_TILEGX_16 */                      {   0, 0, 0, 2 },
310   /* R_TILEGX_8 */                       {   0, 0, 0, 1 },
311   /* R_TILEGX_64_PCREL */                {   0, 0, 1, 8 },
312   /* R_TILEGX_32_PCREL */                {   0, 0, 1, 4 },
313   /* R_TILEGX_16_PCREL */                {   0, 0, 1, 2 },
314   /* R_TILEGX_8_PCREL */                 {   0, 0, 1, 1 },
315   /* R_TILEGX_HW0 */                     {   0, 0, 0, 0 },
316   /* R_TILEGX_HW1 */                     {  16, 0, 0, 0 },
317   /* R_TILEGX_HW2 */                     { S32, 0, 0, 0 },
318   /* R_TILEGX_HW3 */                     { S48, 0, 0, 0 },
319   /* R_TILEGX_HW0_LAST */                {   0, 0, 0, 0 },
320   /* R_TILEGX_HW1_LAST */                {  16, 0, 0, 0 },
321   /* R_TILEGX_HW2_LAST */                { S32, 0, 0, 0 },
322   /* R_TILEGX_COPY */                    {   0, 0, 0, 0 },
323   /* R_TILEGX_GLOB_DAT */                {   0, 0, 0, 8 },
324   /* R_TILEGX_JMP_SLOT */                {   0, 0, 0, 0 },
325   /* R_TILEGX_RELATIVE */                {   0, 0, 0, 0 },
326   /* R_TILEGX_BROFF_X1 */                {   3, 1, 1, 8 },
327   /* R_TILEGX_JUMPOFF_X1 */              {   3, 1, 1, 8 },
328   /* R_TILEGX_JUMPOFF_X1_PLT */          {   3, 1, 1, 8 },
329   /* R_TILEGX_IMM8_X0 */                 {   0, 1, 0, 8 },
330   /* R_TILEGX_IMM8_Y0 */                 {   0, 1, 0, 8 },
331   /* R_TILEGX_IMM8_X1 */                 {   0, 1, 0, 8 },
332   /* R_TILEGX_IMM8_Y1 */                 {   0, 1, 0, 8 },
333   /* R_TILEGX_DEST_IMM8_X1 */            {   0, 1, 0, 8 },
334   /* R_TILEGX_MT_IMM14_X1 */             {   0, 1, 0, 8 },
335   /* R_TILEGX_MF_IMM14_X1 */             {   0, 1, 0, 8 },
336   /* R_TILEGX_MMSTART_X0 */              {   0, 1, 0, 8 },
337   /* R_TILEGX_MMEND_X0 */                {   0, 1, 0, 8 },
338   /* R_TILEGX_SHAMT_X0 */                {   0, 1, 0, 8 },
339   /* R_TILEGX_SHAMT_X1 */                {   0, 1, 0, 8 },
340   /* R_TILEGX_SHAMT_Y0 */                {   0, 1, 0, 8 },
341   /* R_TILEGX_SHAMT_Y1 */                {   0, 1, 0, 8 },
342   /* R_TILEGX_IMM16_X0_HW0 */            {   0, 1, 0, 8 },
343   /* R_TILEGX_IMM16_X1_HW0 */            {   0, 1, 0, 8 },
344   /* R_TILEGX_IMM16_X0_HW1 */            {  16, 1, 0, 8 },
345   /* R_TILEGX_IMM16_X1_HW1 */            {  16, 1, 0, 8 },
346   /* R_TILEGX_IMM16_X0_HW2 */            { S32, 1, 0, 8 },
347   /* R_TILEGX_IMM16_X1_HW2 */            { S32, 1, 0, 8 },
348   /* R_TILEGX_IMM16_X0_HW3 */            { S48, 1, 0, 8 },
349   /* R_TILEGX_IMM16_X1_HW3 */            { S48, 1, 0, 8 },
350   /* R_TILEGX_IMM16_X0_HW0_LAST */       {   0, 1, 0, 8 },
351   /* R_TILEGX_IMM16_X1_HW0_LAST */       {   0, 1, 0, 8 },
352   /* R_TILEGX_IMM16_X0_HW1_LAST */       {  16, 1, 0, 8 },
353   /* R_TILEGX_IMM16_X1_HW1_LAST */       {  16, 1, 0, 8 },
354   /* R_TILEGX_IMM16_X0_HW2_LAST */       { S32, 1, 0, 8 },
355   /* R_TILEGX_IMM16_X1_HW2_LAST */       { S32, 1, 0, 8 },
356   /* R_TILEGX_IMM16_X0_HW0_PCREL */      {   0, 1, 1, 8 },
357   /* R_TILEGX_IMM16_X1_HW0_PCREL */      {   0, 1, 1, 8 },
358   /* R_TILEGX_IMM16_X0_HW1_PCREL */      {  16, 1, 1, 8 },
359   /* R_TILEGX_IMM16_X1_HW1_PCREL */      {  16, 1, 1, 8 },
360   /* R_TILEGX_IMM16_X0_HW2_PCREL */      { S32, 1, 1, 8 },
361   /* R_TILEGX_IMM16_X1_HW2_PCREL */      { S32, 1, 1, 8 },
362   /* R_TILEGX_IMM16_X0_HW3_PCREL */      { S48, 1, 1, 8 },
363   /* R_TILEGX_IMM16_X1_HW3_PCREL */      { S48, 1, 1, 8 },
364   /* R_TILEGX_IMM16_X0_HW0_LAST_PCREL */ {   0, 1, 1, 8 },
365   /* R_TILEGX_IMM16_X1_HW0_LAST_PCREL */ {   0, 1, 1, 8 },
366   /* R_TILEGX_IMM16_X0_HW1_LAST_PCREL */ {  16, 1, 1, 8 },
367   /* R_TILEGX_IMM16_X1_HW1_LAST_PCREL */ {  16, 1, 1, 8 },
368   /* R_TILEGX_IMM16_X0_HW2_LAST_PCREL */ { S32, 1, 1, 8 },
369   /* R_TILEGX_IMM16_X1_HW2_LAST_PCREL */ { S32, 1, 1, 8 },
370   /* R_TILEGX_IMM16_X0_HW0_GOT */        {   0, 1, 0, 0 },
371   /* R_TILEGX_IMM16_X1_HW0_GOT */        {   0, 1, 0, 0 },
372   /* R_TILEGX_IMM16_X0_HW1_GOT */        {  16, 1, 0, 0 },
373   /* R_TILEGX_IMM16_X1_HW1_GOT */        {  16, 1, 0, 0 },
374   /* R_TILEGX_IMM16_X0_HW2_GOT */        { S32, 1, 0, 0 },
375   /* R_TILEGX_IMM16_X1_HW2_GOT */        { S32, 1, 0, 0 },
376   /* R_TILEGX_IMM16_X0_HW3_GOT */        { S48, 1, 0, 0 },
377   /* R_TILEGX_IMM16_X1_HW3_GOT */        { S48, 1, 0, 0 },
378   /* R_TILEGX_IMM16_X0_HW0_LAST_GOT */   {   0, 1, 0, 0 },
379   /* R_TILEGX_IMM16_X1_HW0_LAST_GOT */   {   0, 1, 0, 0 },
380   /* R_TILEGX_IMM16_X0_HW1_LAST_GOT */   {  16, 1, 0, 0 },
381   /* R_TILEGX_IMM16_X1_HW1_LAST_GOT */   {  16, 1, 0, 0 },
382   /* R_TILEGX_IMM16_X0_HW2_LAST_GOT */   { S32, 1, 0, 0 },
383   /* R_TILEGX_IMM16_X1_HW2_LAST_GOT */   { S32, 1, 0, 0 },
384   /* R_TILEGX_IMM16_X0_HW0_TLS_GD */     {   0, 1, 0, 8 },
385   /* R_TILEGX_IMM16_X1_HW0_TLS_GD */     {   0, 1, 0, 8 },
386   /* R_TILEGX_IMM16_X0_HW1_TLS_GD */     {  16, 1, 0, 8 },
387   /* R_TILEGX_IMM16_X1_HW1_TLS_GD */     {  16, 1, 0, 8 },
388   /* R_TILEGX_IMM16_X0_HW2_TLS_GD */     { S32, 1, 0, 8 },
389   /* R_TILEGX_IMM16_X1_HW2_TLS_GD */     { S32, 1, 0, 8 },
390   /* R_TILEGX_IMM16_X0_HW3_TLS_GD */     { S48, 1, 0, 8 },
391   /* R_TILEGX_IMM16_X1_HW3_TLS_GD */     { S48, 1, 0, 8 },
392   /* R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD */{   0, 1, 0, 8 },
393   /* R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD */{   0, 1, 0, 8 },
394   /* R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD */{  16, 1, 0, 8 },
395   /* R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD */{  16, 1, 0, 8 },
396   /* R_TILEGX_IMM16_X0_HW2_LAST_TLS_GD */{ S32, 1, 0, 8 },
397   /* R_TILEGX_IMM16_X1_HW2_LAST_TLS_GD */{ S32, 1, 0, 8 },
398   /* R_TILEGX_IMM16_X0_HW0_TLS_IE */     {   0, 1, 0, 8 },
399   /* R_TILEGX_IMM16_X1_HW0_TLS_IE */     {   0, 1, 0, 8 },
400   /* R_TILEGX_IMM16_X0_HW1_TLS_IE */     {  16, 1, 0, 8 },
401   /* R_TILEGX_IMM16_X1_HW1_TLS_IE */     {  16, 1, 0, 8 },
402   /* R_TILEGX_IMM16_X0_HW2_TLS_IE */     { S32, 1, 0, 8 },
403   /* R_TILEGX_IMM16_X1_HW2_TLS_IE */     { S32, 1, 0, 8 },
404   /* R_TILEGX_IMM16_X0_HW3_TLS_IE */     { S48, 1, 0, 8 },
405   /* R_TILEGX_IMM16_X1_HW3_TLS_IE */     { S48, 1, 0, 8 },
406   /* R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE */{   0, 1, 0, 8 },
407   /* R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE */{   0, 1, 0, 8 },
408   /* R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE */{  16, 1, 0, 8 },
409   /* R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE */{  16, 1, 0, 8 },
410   /* R_TILEGX_IMM16_X0_HW2_LAST_TLS_IE */{ S32, 1, 0, 8 },
411   /* R_TILEGX_IMM16_X1_HW2_LAST_TLS_IE */{ S32, 1, 0, 8 },
412   /* R_TILEGX_TLS_DTPMOD64 */            {   0, 0, 0, 0 },
413   /* R_TILEGX_TLS_DTPOFF64 */            {   0, 0, 0, 0 },
414   /* R_TILEGX_TLS_TPOFF64 */             {   0, 0, 0, 0 },
415   /* R_TILEGX_TLS_DTPMOD32 */            {   0, 0, 0, 0 },
416   /* R_TILEGX_TLS_DTPOFF32 */            {   0, 0, 0, 0 },
417   /* R_TILEGX_TLS_TPOFF32 */             {   0, 0, 0, 0 }
418 #else
419   /* R_TILEPRO_NONE */                   { 0,  0, 0, 0 },
420   /* R_TILEPRO_32 */                     { 0,  0, 0, 4 },
421   /* R_TILEPRO_16 */                     { 0,  0, 0, 2 },
422   /* R_TILEPRO_8 */                      { 0,  0, 0, 1 },
423   /* R_TILEPRO_32_PCREL */               { 0,  0, 1, 4 },
424   /* R_TILEPRO_16_PCREL */               { 0,  0, 1, 2 },
425   /* R_TILEPRO_8_PCREL */                { 0,  0, 1, 1 },
426   /* R_TILEPRO_LO16 */                   { 0,  0, 0, 2 },
427   /* R_TILEPRO_HI16 */                   { 16, 0, 0, 2 },
428   /* R_TILEPRO_HA16 */                   { 16, 1, 0, 2 },
429   /* R_TILEPRO_COPY */                   { 0,  0, 0, 0 },
430   /* R_TILEPRO_GLOB_DAT */               { 0,  0, 0, 4 },
431   /* R_TILEPRO_JMP_SLOT */               { 0,  0, 0, 0 },
432   /* R_TILEPRO_RELATIVE */               { 0,  0, 0, 0 },
433   /* R_TILEPRO_BROFF_X1 */               { 3,  0, 1, 8 },
434   /* R_TILEPRO_JOFFLONG_X1 */            { 3,  0, 1, 8 },
435   /* R_TILEPRO_JOFFLONG_X1_PLT */        { 3,  0, 1, 8 },
436   /* R_TILEPRO_IMM8_X0 */                { 0,  0, 0, 8 },
437   /* R_TILEPRO_IMM8_Y0 */                { 0,  0, 0, 8 },
438   /* R_TILEPRO_IMM8_X1 */                { 0,  0, 0, 8 },
439   /* R_TILEPRO_IMM8_Y1 */                { 0,  0, 0, 8 },
440   /* R_TILEPRO_MT_IMM15_X1 */            { 0,  0, 0, 8 },
441   /* R_TILEPRO_MF_IMM15_X1 */            { 0,  0, 0, 8 },
442   /* R_TILEPRO_IMM16_X0 */               { 0,  0, 0, 8 },
443   /* R_TILEPRO_IMM16_X1 */               { 0,  0, 0, 8 },
444   /* R_TILEPRO_IMM16_X0_LO */            { 0,  0, 0, 8 },
445   /* R_TILEPRO_IMM16_X1_LO */            { 0,  0, 0, 8 },
446   /* R_TILEPRO_IMM16_X0_HI */            { 16, 0, 0, 8 },
447   /* R_TILEPRO_IMM16_X1_HI */            { 16, 0, 0, 8 },
448   /* R_TILEPRO_IMM16_X0_HA */            { 16, 1, 0, 8 },
449   /* R_TILEPRO_IMM16_X1_HA */            { 16, 1, 0, 8 },
450   /* R_TILEPRO_IMM16_X0_PCREL */         { 0,  0, 1, 8 },
451   /* R_TILEPRO_IMM16_X1_PCREL */         { 0,  0, 1, 8 },
452   /* R_TILEPRO_IMM16_X0_LO_PCREL */      { 0,  0, 1, 8 },
453   /* R_TILEPRO_IMM16_X1_LO_PCREL */      { 0,  0, 1, 8 },
454   /* R_TILEPRO_IMM16_X0_HI_PCREL */      { 16, 0, 1, 8 },
455   /* R_TILEPRO_IMM16_X1_HI_PCREL */      { 16, 0, 1, 8 },
456   /* R_TILEPRO_IMM16_X0_HA_PCREL */      { 16, 1, 1, 8 },
457   /* R_TILEPRO_IMM16_X1_HA_PCREL */      { 16, 1, 1, 8 },
458   /* R_TILEPRO_IMM16_X0_GOT */           { 0,  0, 0, 0 },
459   /* R_TILEPRO_IMM16_X1_GOT */           { 0,  0, 0, 0 },
460   /* R_TILEPRO_IMM16_X0_GOT_LO */        { 0,  0, 0, 0 },
461   /* R_TILEPRO_IMM16_X1_GOT_LO */        { 0,  0, 0, 0 },
462   /* R_TILEPRO_IMM16_X0_GOT_HI */        { 0,  0, 0, 0 },
463   /* R_TILEPRO_IMM16_X1_GOT_HI */        { 0,  0, 0, 0 },
464   /* R_TILEPRO_IMM16_X0_GOT_HA */        { 0,  0, 0, 0 },
465   /* R_TILEPRO_IMM16_X1_GOT_HA */        { 0,  0, 0, 0 },
466   /* R_TILEPRO_MMSTART_X0 */             { 0,  0, 0, 8 },
467   /* R_TILEPRO_MMEND_X0 */               { 0,  0, 0, 8 },
468   /* R_TILEPRO_MMSTART_X1 */             { 0,  0, 0, 8 },
469   /* R_TILEPRO_MMEND_X1 */               { 0,  0, 0, 8 },
470   /* R_TILEPRO_SHAMT_X0 */               { 0,  0, 0, 8 },
471   /* R_TILEPRO_SHAMT_X1 */               { 0,  0, 0, 8 },
472   /* R_TILEPRO_SHAMT_Y0 */               { 0,  0, 0, 8 },
473   /* R_TILEPRO_SHAMT_Y1 */               { 0,  0, 0, 8 },
474   /* R_TILEPRO_SN_BROFF */               { 0,  0, 0, 0 },
475   /* R_TILEPRO_SN_IMM8 */                { 0,  0, 0, 0 },
476   /* R_TILEPRO_SN_UIMM8 */               { 0,  0, 0, 0 },
477   /* R_TILEPRO_SN_BYTE0 */               { 0,  0, 0, 0 },
478   /* R_TILEPRO_SN_BYTE1 */               { 0,  0, 0, 0 },
479   /* R_TILEPRO_SN_BYTE2 */               { 0,  0, 0, 0 },
480   /* R_TILEPRO_SN_BYTE3 */               { 0,  0, 0, 0 },
481   /* R_TILEPRO_SN_SPCREL0 */             { 0,  0, 0, 0 },
482   /* R_TILEPRO_SN_SPCREL1 */             { 0,  0, 0, 0 },
483   /* R_TILEPRO_SN_SPCREL2 */             { 0,  0, 0, 0 },
484   /* R_TILEPRO_SN_SPCREL3 */             { 0,  0, 0, 0 },
485   /* R_TILEPRO_IMM16_X0_TLS_GD */        { 0,  0, 0, 8 },
486   /* R_TILEPRO_IMM16_X1_TLS_GD */        { 0,  0, 0, 8 },
487   /* R_TILEPRO_IMM16_X0_TLS_GD_LO */     { 0,  0, 0, 8 },
488   /* R_TILEPRO_IMM16_X1_TLS_GD_LO */     { 0,  0, 0, 8 },
489   /* R_TILEPRO_IMM16_X0_TLS_GD_HI */     { 16, 0, 0, 8 },
490   /* R_TILEPRO_IMM16_X1_TLS_GD_HI */     { 16, 0, 0, 8 },
491   /* R_TILEPRO_IMM16_X0_TLS_GD_HA */     { 16, 1, 0, 8 },
492   /* R_TILEPRO_IMM16_X1_TLS_GD_HA */     { 16, 1, 0, 8 },
493   /* R_TILEPRO_IMM16_X0_TLS_IE */        { 0,  0, 0, 8 },
494   /* R_TILEPRO_IMM16_X1_TLS_IE */        { 0,  0, 0, 8 },
495   /* R_TILEPRO_IMM16_X0_TLS_IE_LO */     { 0,  0, 0, 8 },
496   /* R_TILEPRO_IMM16_X1_TLS_IE_LO */     { 0,  0, 0, 8 },
497   /* R_TILEPRO_IMM16_X0_TLS_IE_HI */     { 16, 0, 0, 8 },
498   /* R_TILEPRO_IMM16_X1_TLS_IE_HI */     { 16, 0, 0, 8 },
499   /* R_TILEPRO_IMM16_X0_TLS_IE_HA */     { 16, 1, 0, 8 },
500   /* R_TILEPRO_IMM16_X1_TLS_IE_HA */     { 16, 1, 0, 8 },
501   /* R_TILEPRO_TLS_DTPMOD32 */           { 0,  0, 0, 0 },
502   /* R_TILEPRO_TLS_DTPOFF32 */           { 0,  0, 0, 0 },
503   /* R_TILEPRO_TLS_TPOFF32 */            { 0,  0, 0, 0 },
504 #endif
505 };
506
507 #if __ELF_NATIVE_CLASS == 32
508 #define ELFW_R_TYPE     ELF32_R_TYPE
509 #define ELFW_ST_TYPE    ELF32_ST_TYPE
510 #else
511 #define ELFW_R_TYPE     ELF64_R_TYPE
512 #define ELFW_ST_TYPE    ELF64_ST_TYPE
513 #endif
514
515 /* Perform the relocation specified by RELOC and SYM (which is fully resolved).
516    MAP is the object containing the reloc.  */
517
518 auto inline void __attribute__ ((always_inline))
519 elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc,
520                   const ElfW(Sym) *sym, const struct r_found_version *version,
521                   void *const reloc_addr_arg, int skip_ifunc)
522 {
523   ElfW(Addr) *const reloc_addr = reloc_addr_arg;
524   const unsigned int r_type = ELFW_R_TYPE (reloc->r_info);
525
526 #if !defined RTLD_BOOTSTRAP || !defined HAVE_Z_COMBRELOC
527   if (__builtin_expect (r_type == R_TILE(RELATIVE), 0))
528     {
529 # if !defined RTLD_BOOTSTRAP && !defined HAVE_Z_COMBRELOC
530       /* This is defined in rtld.c, but nowhere in the static libc.a;
531          make the reference weak so static programs can still link.
532          This declaration cannot be done when compiling rtld.c
533          (i.e. #ifdef RTLD_BOOTSTRAP) because rtld.c contains the
534          common defn for _dl_rtld_map, which is incompatible with a
535          weak decl in the same file.  */
536 #  ifndef SHARED
537       weak_extern (GL(dl_rtld_map));
538 #  endif
539       if (map != &GL(dl_rtld_map)) /* Already done in rtld itself.  */
540 # endif
541         *reloc_addr = map->l_addr + reloc->r_addend;
542       return;
543     }
544 #endif
545
546   if (__builtin_expect (r_type == R_TILE(NONE), 0))
547     return;
548
549 #if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
550   const ElfW(Sym) *const refsym = sym;
551 #endif
552   struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
553   ElfW(Addr) value;
554
555   if (sym == NULL)
556     value = 0;
557   else if (ELFW_ST_TYPE (sym->st_info) == STT_SECTION)
558     value = map->l_addr;  /* like a RELATIVE reloc */
559   else
560     value = sym_map->l_addr + sym->st_value;
561
562   if (sym != NULL
563       && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)
564       && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
565       && __builtin_expect (!skip_ifunc, 1))
566     value = ((Elf64_Addr (*) (void)) value) ();
567
568   switch (r_type)
569     {
570     case R_TILE(JMP_SLOT):
571       elf_machine_fixup_plt (map, 0, reloc, reloc_addr,
572                              value + reloc->r_addend);
573       return;
574
575 #ifndef RESOLVE_CONFLICT_FIND_MAP
576     case R_TILE_TLS(DTPMOD):
577 # ifdef RTLD_BOOTSTRAP
578       /* During startup the dynamic linker is always the module
579          with index 1.
580          XXX If this relocation is necessary move before RESOLVE
581          call.  */
582       *reloc_addr = 1;
583 # else
584       /* Get the information from the link map returned by the
585          resolv function.  */
586       if (sym_map != NULL)
587         *reloc_addr = sym_map->l_tls_modid;
588 # endif
589       return;
590     case R_TILE_TLS(DTPOFF):
591 # ifndef RTLD_BOOTSTRAP
592       /* During relocation all TLS symbols are defined and used.
593          Therefore the offset is already correct.  */
594       if (sym != NULL)
595         *reloc_addr = sym->st_value + reloc->r_addend;
596 # endif
597       return;
598     case R_TILE_TLS(TPOFF):
599 # ifdef RTLD_BOOTSTRAP
600       *reloc_addr = sym->st_value + reloc->r_addend + map->l_tls_offset;
601 # else
602       if (sym != NULL)
603         {
604           CHECK_STATIC_TLS (map, sym_map);
605           *reloc_addr = (sym->st_value + reloc->r_addend
606                          + sym_map->l_tls_offset);
607         }
608 #endif
609       return;
610 #endif /* use TLS */
611
612 #if !defined RTLD_BOOTSTRAP && !defined RESOLVE_CONFLICT_FIND_MAP
613       /* Not needed in dl-conflict.c.  */
614     case R_TILE(COPY):
615       if (sym == NULL)
616         /* This can happen in trace mode if an object could not be found.  */
617         return;
618       if (__builtin_expect (sym->st_size > refsym->st_size, 0)
619           || (__builtin_expect (sym->st_size < refsym->st_size, 0)
620               && __builtin_expect (GLRO(dl_verbose), 0)))
621         {
622           const char *strtab;
623
624           strtab = (const char *) D_PTR (map,l_info[DT_STRTAB]);
625           _dl_error_printf ("%s: Symbol `%s' has different size in shared"
626                             " object, consider re-linking\n",
627                             RTLD_PROGNAME, strtab + refsym->st_name);
628         }
629       memcpy (reloc_addr_arg, (void *) value,
630               MIN (sym->st_size, refsym->st_size));
631       return;
632 #endif
633     }
634
635   /* All remaining relocations must be in the lookup table. */
636   const struct reloc_howto *h = &howto[r_type];
637   if ((unsigned int) r_type >= sizeof howto / sizeof howto[0] ||
638       h->byte_size == 0)
639     {
640 #if !defined RTLD_BOOTSTRAP || defined _NDEBUG
641       /* We add these checks in the version to relocate ld.so only
642          if we are still debugging.  */
643       _dl_reloc_bad_type (map, r_type, 0);
644 #endif
645       return;
646     }
647
648   value += reloc->r_addend;
649
650   /* The lookup table entry knows how to perform this reloc. */
651   if (h->is_pcrel)
652     value -= (ElfW(Addr)) reloc_addr;
653
654 #ifndef __tilegx__
655   if (h->add_0x8000)
656     value += 0x8000;
657 #endif
658
659   value >>= h->right_shift;
660
661   switch (h->byte_size)
662     {
663     case 1:
664       *(char *) reloc_addr = value;
665       return;
666     case 2:
667       *(short *) reloc_addr = value;
668       return;
669     case 4:
670       *(int *) reloc_addr = value;
671       return;
672 #ifdef __tilegx__
673     case 8:
674       if (!h->is_bundle_update)
675         {
676           *(ElfW(Addr) *) reloc_addr = value;
677           return;
678         }
679 #endif
680     }
681
682   /* We are updating a bundle, so use the function pointer that
683      swizzles the operand bits into the right location. */
684
685   tile_bundle_bits *p = (tile_bundle_bits *) reloc_addr;
686   tile_bundle_bits bits = *p;
687
688 #define MUNGE(func) do {                                            \
689     bits = ((bits & ~create_##func (-1)) | create_##func (value));  \
690     if (get_##func (bits) != value)                                 \
691       _dl_signal_error (0, map->l_name, NULL,                       \
692                         "relocation value too large for " #func);   \
693   } while (0)
694
695 #define MUNGE_NOCHECK(func)                                     \
696   bits = ((bits & ~create_##func (-1)) | create_##func (value))
697
698   switch (r_type)
699     {
700 #ifdef __tilegx__
701     case R_TILEGX_BROFF_X1:
702       MUNGE (BrOff_X1);
703       break;
704     case R_TILEGX_JUMPOFF_X1:
705     case R_TILEGX_JUMPOFF_X1_PLT:
706       MUNGE (JumpOff_X1);
707       break;
708     case R_TILEGX_IMM8_X0:
709       MUNGE (Imm8_X0);
710       break;
711     case R_TILEGX_IMM8_Y0:
712       MUNGE (Imm8_Y0);
713       break;
714     case R_TILEGX_IMM8_X1:
715       MUNGE (Imm8_X1);
716       break;
717     case R_TILEGX_IMM8_Y1:
718       MUNGE (Imm8_Y1);
719       break;
720     case R_TILEGX_MT_IMM14_X1:
721       MUNGE (MT_Imm14_X1);
722       break;
723     case R_TILEGX_MF_IMM14_X1:
724       MUNGE (MF_Imm14_X1);
725       break;
726     case R_TILEGX_IMM16_X0_HW0:
727     case R_TILEGX_IMM16_X0_HW1:
728     case R_TILEGX_IMM16_X0_HW2:
729     case R_TILEGX_IMM16_X0_HW3:
730     case R_TILEGX_IMM16_X0_HW0_PCREL:
731     case R_TILEGX_IMM16_X0_HW1_PCREL:
732     case R_TILEGX_IMM16_X0_HW2_PCREL:
733     case R_TILEGX_IMM16_X0_HW3_PCREL:
734     case R_TILEGX_IMM16_X0_HW0_TLS_GD:
735     case R_TILEGX_IMM16_X0_HW0_TLS_IE:
736       MUNGE_NOCHECK (Imm16_X0);
737       break;
738     case R_TILEGX_IMM16_X0_HW0_LAST:
739     case R_TILEGX_IMM16_X0_HW1_LAST:
740     case R_TILEGX_IMM16_X0_HW2_LAST:
741     case R_TILEGX_IMM16_X0_HW0_LAST_PCREL:
742     case R_TILEGX_IMM16_X0_HW1_LAST_PCREL:
743     case R_TILEGX_IMM16_X0_HW2_LAST_PCREL:
744     case R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD:
745     case R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD:
746     case R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE:
747     case R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE:
748       MUNGE (Imm16_X0);
749       break;
750     case R_TILEGX_IMM16_X1_HW0:
751     case R_TILEGX_IMM16_X1_HW1:
752     case R_TILEGX_IMM16_X1_HW2:
753     case R_TILEGX_IMM16_X1_HW3:
754     case R_TILEGX_IMM16_X1_HW0_PCREL:
755     case R_TILEGX_IMM16_X1_HW1_PCREL:
756     case R_TILEGX_IMM16_X1_HW2_PCREL:
757     case R_TILEGX_IMM16_X1_HW3_PCREL:
758     case R_TILEGX_IMM16_X1_HW0_TLS_GD:
759     case R_TILEGX_IMM16_X1_HW0_TLS_IE:
760       MUNGE_NOCHECK (Imm16_X1);
761       break;
762     case R_TILEGX_IMM16_X1_HW0_LAST:
763     case R_TILEGX_IMM16_X1_HW1_LAST:
764     case R_TILEGX_IMM16_X1_HW2_LAST:
765     case R_TILEGX_IMM16_X1_HW0_LAST_PCREL:
766     case R_TILEGX_IMM16_X1_HW1_LAST_PCREL:
767     case R_TILEGX_IMM16_X1_HW2_LAST_PCREL:
768     case R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD:
769     case R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD:
770     case R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE:
771     case R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE:
772       MUNGE (Imm16_X1);
773       break;
774     case R_TILEGX_MMSTART_X0:
775       MUNGE (BFStart_X0);
776       break;
777     case R_TILEGX_MMEND_X0:
778       MUNGE (BFEnd_X0);
779       break;
780     case R_TILEGX_SHAMT_X0:
781       MUNGE (ShAmt_X0);
782       break;
783     case R_TILEGX_SHAMT_X1:
784       MUNGE (ShAmt_X1);
785       break;
786     case R_TILEGX_SHAMT_Y0:
787       MUNGE (ShAmt_Y0);
788       break;
789     case R_TILEGX_SHAMT_Y1:
790       MUNGE (ShAmt_Y1);
791       break;
792 #else
793     case R_TILEPRO_BROFF_X1:
794       MUNGE (BrOff_X1);
795       break;
796     case R_TILEPRO_JOFFLONG_X1:
797     case R_TILEPRO_JOFFLONG_X1_PLT:
798       MUNGE_NOCHECK (JOffLong_X1);   /* holds full 32-bit value */
799       break;
800     case R_TILEPRO_IMM8_X0:
801       MUNGE (Imm8_X0);
802       break;
803     case R_TILEPRO_IMM8_Y0:
804       MUNGE (Imm8_Y0);
805       break;
806     case R_TILEPRO_IMM8_X1:
807       MUNGE (Imm8_X1);
808       break;
809     case R_TILEPRO_IMM8_Y1:
810       MUNGE (Imm8_Y1);
811       break;
812     case R_TILEPRO_MT_IMM15_X1:
813       MUNGE (MT_Imm15_X1);
814       break;
815     case R_TILEPRO_MF_IMM15_X1:
816       MUNGE (MF_Imm15_X1);
817       break;
818     case R_TILEPRO_IMM16_X0_LO:
819     case R_TILEPRO_IMM16_X0_HI:
820     case R_TILEPRO_IMM16_X0_HA:
821     case R_TILEPRO_IMM16_X0_LO_PCREL:
822     case R_TILEPRO_IMM16_X0_HI_PCREL:
823     case R_TILEPRO_IMM16_X0_HA_PCREL:
824     case R_TILEPRO_IMM16_X0_TLS_GD_LO:
825     case R_TILEPRO_IMM16_X0_TLS_GD_HI:
826     case R_TILEPRO_IMM16_X0_TLS_GD_HA:
827     case R_TILEPRO_IMM16_X0_TLS_IE_LO:
828     case R_TILEPRO_IMM16_X0_TLS_IE_HI:
829     case R_TILEPRO_IMM16_X0_TLS_IE_HA:
830       MUNGE_NOCHECK (Imm16_X0);
831       break;
832     case R_TILEPRO_IMM16_X0:
833     case R_TILEPRO_IMM16_X0_PCREL:
834     case R_TILEPRO_IMM16_X0_TLS_GD:
835     case R_TILEPRO_IMM16_X0_TLS_IE:
836       MUNGE (Imm16_X0);
837       break;
838     case R_TILEPRO_IMM16_X1_LO:
839     case R_TILEPRO_IMM16_X1_HI:
840     case R_TILEPRO_IMM16_X1_HA:
841     case R_TILEPRO_IMM16_X1_LO_PCREL:
842     case R_TILEPRO_IMM16_X1_HI_PCREL:
843     case R_TILEPRO_IMM16_X1_HA_PCREL:
844     case R_TILEPRO_IMM16_X1_TLS_GD_LO:
845     case R_TILEPRO_IMM16_X1_TLS_GD_HI:
846     case R_TILEPRO_IMM16_X1_TLS_GD_HA:
847     case R_TILEPRO_IMM16_X1_TLS_IE_LO:
848     case R_TILEPRO_IMM16_X1_TLS_IE_HI:
849     case R_TILEPRO_IMM16_X1_TLS_IE_HA:
850       MUNGE_NOCHECK (Imm16_X1);
851       break;
852     case R_TILEPRO_IMM16_X1:
853     case R_TILEPRO_IMM16_X1_PCREL:
854     case R_TILEPRO_IMM16_X1_TLS_GD:
855     case R_TILEPRO_IMM16_X1_TLS_IE:
856       MUNGE (Imm16_X1);
857       break;
858     case R_TILEPRO_MMSTART_X0:
859       MUNGE (MMStart_X0);
860       break;
861     case R_TILEPRO_MMEND_X0:
862       MUNGE (MMEnd_X0);
863       break;
864     case R_TILEPRO_MMSTART_X1:
865       MUNGE (MMStart_X1);
866       break;
867     case R_TILEPRO_MMEND_X1:
868       MUNGE (MMEnd_X1);
869       break;
870     case R_TILEPRO_SHAMT_X0:
871       MUNGE (ShAmt_X0);
872       break;
873     case R_TILEPRO_SHAMT_X1:
874       MUNGE (ShAmt_X1);
875       break;
876     case R_TILEPRO_SHAMT_Y0:
877       MUNGE (ShAmt_Y0);
878       break;
879     case R_TILEPRO_SHAMT_Y1:
880       MUNGE (ShAmt_Y1);
881       break;
882 #endif
883     }
884 #undef MUNGE
885   *p = bits;
886   _dl_flush_icache (p, sizeof (*p));
887 }
888
889 auto inline void __attribute__ ((always_inline))
890 elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
891                            void *const reloc_addr_arg)
892 {
893   ElfW(Addr) *const reloc_addr = reloc_addr_arg;
894   *reloc_addr = l_addr + reloc->r_addend;
895 }
896
897 auto inline void __attribute__ ((always_inline))
898 elf_machine_lazy_rel (struct link_map *map,
899                       ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
900                       int skip_ifunc)
901 {
902   const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
903
904   /* Check for unexpected PLT reloc type.  */
905   if (__builtin_expect (r_type == R_TILE(JMP_SLOT), 1))
906     {
907       *(ElfW(Addr) *) (l_addr + reloc->r_offset) += l_addr;
908     }
909   else
910     _dl_reloc_bad_type (map, r_type, 1);
911 }
912
913 #endif /* RESOLVE_MAP */