]>
Commit | Line | Data |
---|---|---|
d5e4222a | 1 | /* Machine-dependent ELF dynamic relocation inline functions. Alpha version. |
9ba537d2 | 2 | Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. |
f1fc1823 UD |
3 | This file is part of the GNU C Library. |
4 | Contributed by Richard Henderson <rth@tamu.edu>. | |
d5e4222a | 5 | |
f1fc1823 UD |
6 | The GNU C Library is free software; you can redistribute it and/or |
7 | modify it under the terms of the GNU Library General Public License as | |
8 | published by the Free Software Foundation; either version 2 of the | |
9 | License, or (at your option) any later version. | |
d5e4222a | 10 | |
f1fc1823 UD |
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 | Library General Public License for more details. | |
d5e4222a | 15 | |
f1fc1823 | 16 | You should have received a copy of the GNU Library General Public |
a91492b8 UD |
17 | License along with the GNU C Library; see the file COPYING.LIB. If not, |
18 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
19 | Boston, MA 02111-1307, USA. */ | |
d5e4222a | 20 | |
de4931d1 | 21 | /* This was written in the absence of an ABI -- don't expect |
d5e4222a RM |
22 | it to remain unchanged. */ |
23 | ||
de4931d1 RM |
24 | #ifndef dl_machine_h |
25 | #define dl_machine_h 1 | |
26 | ||
d5e4222a RM |
27 | #define ELF_MACHINE_NAME "alpha" |
28 | ||
29 | #include <assert.h> | |
30 | #include <string.h> | |
d5e4222a RM |
31 | |
32 | ||
33 | /* Return nonzero iff E_MACHINE is compatible with the running host. */ | |
34 | static inline int | |
35 | elf_machine_matches_host (Elf64_Word e_machine) | |
36 | { | |
37 | return e_machine == EM_ALPHA; | |
38 | } | |
39 | ||
f1fc1823 UD |
40 | /* Return the link-time address of _DYNAMIC. The multiple-got-capable |
41 | linker no longer allocates the first .got entry for this. But not to | |
42 | worry, no special tricks are needed. */ | |
43 | static inline Elf64_Addr | |
44 | elf_machine_dynamic (void) | |
d5e4222a | 45 | { |
19e7f5a6 | 46 | #ifndef NO_AXP_MULTI_GOT_LD |
f1fc1823 | 47 | return (Elf64_Addr) &_DYNAMIC; |
a91492b8 UD |
48 | #else |
49 | register Elf64_Addr *gp __asm__ ("$29"); | |
50 | return gp[-4096]; | |
51 | #endif | |
d5e4222a RM |
52 | } |
53 | ||
d5e4222a RM |
54 | /* Return the run-time load address of the shared object. */ |
55 | static inline Elf64_Addr | |
56 | elf_machine_load_address (void) | |
57 | { | |
58 | /* NOTE: While it is generally unfriendly to put data in the text | |
59 | segment, it is only slightly less so when the "data" is an | |
60 | instruction. While we don't have to worry about GLD just yet, an | |
61 | optimizing linker might decide that our "data" is an unreachable | |
62 | instruction and throw it away -- with the right switches, DEC's | |
63 | linker will do this. What ought to happen is we should add | |
64 | something to GAS to allow us access to the new GPREL_HI32/LO32 | |
65 | relocation types stolen from OSF/1 3.0. */ | |
66 | /* This code relies on the fact that BRADDR relocations do not | |
67 | appear in dynamic relocation tables. Not that that would be very | |
68 | useful anyway -- br/bsr has a 4MB range and the shared libraries | |
69 | are usually many many terabytes away. */ | |
70 | ||
71 | Elf64_Addr dot; | |
72 | long zero_disp; | |
73 | ||
74 | asm("br %0, 1f\n\t" | |
75 | ".weak __load_address_undefined\n\t" | |
76 | "br $0, __load_address_undefined\n" | |
77 | "1:" | |
78 | : "=r"(dot)); | |
79 | ||
80 | zero_disp = *(int *)dot; | |
81 | zero_disp = (zero_disp << 43) >> 41; | |
82 | ||
83 | return dot + 4 + zero_disp; | |
84 | } | |
85 | ||
de4931d1 RM |
86 | /* Set up the loaded object described by L so its unrelocated PLT |
87 | entries will jump to the on-demand fixup code in dl-runtime.c. */ | |
88 | ||
76a2c2cb | 89 | static inline int |
2ed72066 | 90 | elf_machine_runtime_setup (struct link_map *l, int lazy, int profile) |
de4931d1 RM |
91 | { |
92 | Elf64_Addr plt; | |
93 | extern void _dl_runtime_resolve (void); | |
a8e5f5a4 | 94 | extern void _dl_runtime_profile (void); |
de4931d1 RM |
95 | |
96 | if (l->l_info[DT_JMPREL] && lazy) | |
97 | { | |
98 | /* The GOT entries for the functions in the PLT have not been | |
99 | filled in yet. Their initial contents are directed to the | |
100 | PLT which arranges for the dynamic linker to be called. */ | |
101 | plt = l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr; | |
102 | ||
103 | /* This function will be called to perform the relocation. */ | |
a8e5f5a4 UD |
104 | if (!profile) |
105 | *(Elf64_Addr *)(plt + 16) = (Elf64_Addr) &_dl_runtime_resolve; | |
106 | else | |
107 | { | |
108 | *(Elf64_Addr *)(plt + 16) = (Elf64_Addr) &_dl_runtime_profile; | |
ca246d7e UD |
109 | |
110 | if (_dl_name_match_p (_dl_profile, l)) | |
111 | { | |
112 | /* This is the object we are looking for. Say that we really | |
113 | want profiling and the timers are started. */ | |
114 | _dl_profile_map = l; | |
115 | } | |
a8e5f5a4 | 116 | } |
de4931d1 RM |
117 | |
118 | /* Identify this shared object */ | |
119 | *(Elf64_Addr *)(plt + 24) = (Elf64_Addr) l; | |
76a2c2cb UD |
120 | |
121 | /* If the first instruction of the plt entry is not | |
122 | "br $28, plt0", we cannot do lazy relocation. */ | |
123 | lazy = (*(unsigned *)(plt + 32) == 0xc39ffff7); | |
de4931d1 | 124 | } |
76a2c2cb UD |
125 | |
126 | return lazy; | |
de4931d1 RM |
127 | } |
128 | ||
129 | /* This code is used in dl-runtime.c to call the `fixup' function | |
130 | and then redirect to the address it returns. */ | |
18a702a8 RH |
131 | #define TRAMPOLINE_TEMPLATE(tramp_name, fixup_name, IMB) \ |
132 | extern void tramp_name (void); \ | |
133 | asm ( "\ | |
a8e5f5a4 UD |
134 | .globl " #tramp_name " |
135 | .ent " #tramp_name " | |
136 | " #tramp_name ": | |
de4931d1 RM |
137 | lda $sp, -168($sp) |
138 | .frame $sp, 168, $26 | |
ca246d7e | 139 | /* Preserve all integer registers that C normally doesn't. */ |
de4931d1 RM |
140 | stq $26, 0($sp) |
141 | stq $0, 8($sp) | |
142 | stq $1, 16($sp) | |
143 | stq $2, 24($sp) | |
144 | stq $3, 32($sp) | |
145 | stq $4, 40($sp) | |
146 | stq $5, 48($sp) | |
147 | stq $6, 56($sp) | |
148 | stq $7, 64($sp) | |
149 | stq $8, 72($sp) | |
150 | stq $16, 80($sp) | |
151 | stq $17, 88($sp) | |
152 | stq $18, 96($sp) | |
153 | stq $19, 104($sp) | |
154 | stq $20, 112($sp) | |
155 | stq $21, 120($sp) | |
156 | stq $22, 128($sp) | |
157 | stq $23, 136($sp) | |
158 | stq $24, 144($sp) | |
159 | stq $25, 152($sp) | |
160 | stq $29, 160($sp) | |
161 | .mask 0x27ff01ff, -168 | |
162 | /* Set up our $gp */ | |
a8e5f5a4 UD |
163 | br $gp, .+4 |
164 | ldgp $gp, 0($gp) | |
ca246d7e | 165 | .prologue 0 |
a8e5f5a4 | 166 | /* Set up the arguments for fixup: */ |
de4931d1 | 167 | /* $16 = link_map out of plt0 */ |
76a2c2cb | 168 | /* $17 = offset of reloc entry = ($28 - $27 - 20) /12 * 24 */ |
a8e5f5a4 | 169 | /* $18 = return address */ |
76a2c2cb | 170 | subq $28, $27, $17 |
de4931d1 | 171 | ldq $16, 8($27) |
76a2c2cb | 172 | subq $17, 20, $17 |
a8e5f5a4 | 173 | mov $26, $18 |
76a2c2cb | 174 | addq $17, $17, $17 |
de4931d1 | 175 | /* Do the fixup */ |
2e67c045 | 176 | bsr $26, " ASM_ALPHA_NG_SYMBOL_PREFIX #fixup_name "..ng |
f526ac60 | 177 | /* Move the destination address into position. */ |
de4931d1 RM |
178 | mov $0, $27 |
179 | /* Restore program registers. */ | |
180 | ldq $26, 0($sp) | |
181 | ldq $0, 8($sp) | |
182 | ldq $1, 16($sp) | |
183 | ldq $2, 24($sp) | |
184 | ldq $3, 32($sp) | |
185 | ldq $4, 40($sp) | |
186 | ldq $5, 48($sp) | |
187 | ldq $6, 56($sp) | |
188 | ldq $7, 64($sp) | |
189 | ldq $8, 72($sp) | |
190 | ldq $16, 80($sp) | |
191 | ldq $17, 88($sp) | |
192 | ldq $18, 96($sp) | |
193 | ldq $19, 104($sp) | |
194 | ldq $20, 112($sp) | |
195 | ldq $21, 120($sp) | |
196 | ldq $22, 128($sp) | |
197 | ldq $23, 136($sp) | |
198 | ldq $24, 144($sp) | |
199 | ldq $25, 152($sp) | |
200 | ldq $29, 160($sp) | |
f526ac60 | 201 | /* Flush the Icache after having modified the .plt code. */ |
a8e5f5a4 | 202 | " #IMB " |
de4931d1 RM |
203 | /* Clean up and turn control to the destination */ |
204 | lda $sp, 168($sp) | |
205 | jmp $31, ($27) | |
a8e5f5a4 | 206 | .end " #tramp_name) |
de4931d1 | 207 | |
a8e5f5a4 UD |
208 | #ifndef PROF |
209 | #define ELF_MACHINE_RUNTIME_TRAMPOLINE \ | |
210 | TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup, imb); \ | |
211 | TRAMPOLINE_TEMPLATE (_dl_runtime_profile, profile_fixup, #nop); | |
212 | #else | |
213 | #define ELF_MACHINE_RUNTIME_TRAMPOLINE \ | |
49f3765c | 214 | TRAMPOLINE_TEMPLATE (_dl_runtime_resolve, fixup, imb); \ |
9ba537d2 | 215 | strong_alias (_dl_runtime_resolve, _dl_runtime_profile); |
a8e5f5a4 | 216 | #endif |
de4931d1 | 217 | |
de4931d1 RM |
218 | /* Initial entry point code for the dynamic linker. |
219 | The C function `_dl_start' is the real entry point; | |
220 | its return value is the user program's entry point. */ | |
221 | ||
222 | #define RTLD_START asm ("\ | |
223 | .text | |
ca246d7e | 224 | .set at |
de4931d1 | 225 | .globl _start |
11309adf | 226 | .ent _start |
de4931d1 | 227 | _start: |
11309adf | 228 | br $gp, 0f |
f526ac60 | 229 | 0: ldgp $gp, 0($gp) |
ca246d7e | 230 | .prologue 0 |
de4931d1 RM |
231 | /* Pass pointer to argument block to _dl_start. */ |
232 | mov $sp, $16 | |
2e67c045 | 233 | bsr $26, "ASM_ALPHA_NG_SYMBOL_PREFIX"_dl_start..ng |
11309adf UD |
234 | .end _start |
235 | /* FALLTHRU */ | |
236 | .globl _dl_start_user | |
237 | .ent _dl_start_user | |
de4931d1 | 238 | _dl_start_user: |
ca246d7e UD |
239 | .frame $30,0,$31,0 |
240 | .prologue 0 | |
de4931d1 RM |
241 | /* Save the user entry point address in s0. */ |
242 | mov $0, $9 | |
ca246d7e UD |
243 | /* Store the highest stack address. */ |
244 | stq $30, __libc_stack_end | |
de4931d1 RM |
245 | /* See if we were run as a command with the executable file |
246 | name as an extra leading argument. If so, adjust the stack | |
247 | pointer to skip _dl_skip_args words. */ | |
248 | ldl $1, _dl_skip_args | |
249 | beq $1, 0f | |
250 | ldq $2, 0($sp) | |
251 | subq $2, $1, $2 | |
252 | s8addq $1, $sp, $sp | |
253 | stq $2, 0($sp) | |
831f9aed RH |
254 | /* Load _dl_main_searchlist into s1 to pass to _dl_init_next. */ |
255 | 0: ldq $10, _dl_main_searchlist | |
910e2e14 | 256 | /* Call _dl_init_next to return the address of an initializer |
de4931d1 RM |
257 | function to run. */ |
258 | 1: mov $10, $16 | |
259 | jsr $26, _dl_init_next | |
260 | ldgp $gp, 0($26) | |
261 | beq $0, 2f | |
262 | mov $0, $27 | |
263 | jsr $26, ($0) | |
264 | ldgp $gp, 0($26) | |
265 | br 1b | |
8a7ad100 | 266 | 2: /* Clear the startup flag. */ |
8a7ad100 | 267 | stl $31, _dl_starting_up |
8a7ad100 | 268 | /* Pass our finalizer function to the user in $0. */ |
de4931d1 RM |
269 | lda $0, _dl_fini |
270 | /* Jump to the user's entry point. */ | |
271 | mov $9, $27 | |
11309adf | 272 | jmp ($9) |
c0d5b73e | 273 | .end _dl_start_user |
ca246d7e | 274 | .set noat |
c0d5b73e | 275 | .previous"); |
de4931d1 | 276 | |
f526ac60 | 277 | /* Nonzero iff TYPE describes relocation of a PLT entry, so |
de4931d1 | 278 | PLT entries should not be allowed to define the value. */ |
f2d725f3 UD |
279 | #define elf_machine_lookup_noplt_p(type) ((type) == R_ALPHA_JMP_SLOT) |
280 | ||
281 | /* Nonzero iff TYPE should not be allowed to resolve to one of | |
282 | the main executable's symbols, as for a COPY reloc, which we don't use. */ | |
283 | #define elf_machine_lookup_noexec_p(type) (0) | |
284 | ||
285 | /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ | |
a8e5f5a4 | 286 | #define ELF_MACHINE_JMP_SLOT R_ALPHA_JMP_SLOT |
de4931d1 RM |
287 | |
288 | /* The alpha never uses Elf64_Rel relocations. */ | |
289 | #define ELF_MACHINE_NO_REL 1 | |
290 | ||
d5e4222a RM |
291 | /* Fix up the instructions of a PLT entry to invoke the function |
292 | rather than the dynamic linker. */ | |
293 | static inline void | |
a8e5f5a4 UD |
294 | elf_machine_fixup_plt(struct link_map *l, const Elf64_Rela *reloc, |
295 | Elf64_Addr *got_addr, Elf64_Addr value) | |
d5e4222a RM |
296 | { |
297 | const Elf64_Rela *rela_plt; | |
298 | Elf64_Word *plte; | |
91149d13 | 299 | long edisp; |
d5e4222a | 300 | |
a8e5f5a4 UD |
301 | /* Store the value we are going to load. */ |
302 | *got_addr = value; | |
303 | ||
d5e4222a RM |
304 | /* Recover the PLT entry address by calculating reloc's index into the |
305 | .rela.plt, and finding that entry in the .plt. */ | |
d5e4222a | 306 | rela_plt = (void *)(l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr); |
91149d13 RM |
307 | plte = (void *)(l->l_addr + l->l_info[DT_PLTGOT]->d_un.d_ptr + 32); |
308 | plte += 3 * (reloc - rela_plt); | |
d5e4222a RM |
309 | |
310 | /* Find the displacement from the plt entry to the function. */ | |
91149d13 | 311 | edisp = (long)(value - (Elf64_Addr)&plte[3]) / 4; |
d5e4222a | 312 | |
91149d13 | 313 | if (edisp >= -0x100000 && edisp < 0x100000) |
d5e4222a RM |
314 | { |
315 | /* If we are in range, use br to perfect branch prediction and | |
e23ecc5f | 316 | elide the dependency on the address load. This case happens, |
d5e4222a | 317 | e.g., when a shared library call is resolved to the same library. */ |
91149d13 RM |
318 | |
319 | int hi, lo; | |
320 | hi = value - (Elf64_Addr)&plte[0]; | |
321 | lo = (short)hi; | |
322 | hi = (hi - lo) >> 16; | |
323 | ||
a8e5f5a4 | 324 | /* Emit "lda $27,lo($27)" */ |
91149d13 RM |
325 | plte[1] = 0x237b0000 | (lo & 0xffff); |
326 | ||
327 | /* Emit "br $31,function" */ | |
328 | plte[2] = 0xc3e00000 | (edisp & 0x1fffff); | |
76a2c2cb UD |
329 | |
330 | /* Think about thread-safety -- the previous instructions must be | |
331 | committed to memory before the first is overwritten. */ | |
332 | __asm__ __volatile__("wmb" : : : "memory"); | |
333 | ||
a8e5f5a4 | 334 | /* Emit "ldah $27,hi($27)" */ |
76a2c2cb | 335 | plte[0] = 0x277b0000 | (hi & 0xffff); |
d5e4222a RM |
336 | } |
337 | else | |
338 | { | |
339 | /* Don't bother with the hint since we already know the hint is | |
340 | wrong. Eliding it prevents the wrong page from getting pulled | |
341 | into the cache. */ | |
91149d13 RM |
342 | |
343 | int hi, lo; | |
a8e5f5a4 | 344 | hi = (Elf64_Addr)got_addr - (Elf64_Addr)&plte[0]; |
91149d13 RM |
345 | lo = (short)hi; |
346 | hi = (hi - lo) >> 16; | |
347 | ||
a8e5f5a4 | 348 | /* Emit "ldq $27,lo($27)" */ |
91149d13 RM |
349 | plte[1] = 0xa77b0000 | (lo & 0xffff); |
350 | ||
351 | /* Emit "jmp $31,($27)" */ | |
352 | plte[2] = 0x6bfb0000; | |
76a2c2cb UD |
353 | |
354 | /* Think about thread-safety -- the previous instructions must be | |
355 | committed to memory before the first is overwritten. */ | |
356 | __asm__ __volatile__("wmb" : : : "memory"); | |
357 | ||
a8e5f5a4 | 358 | /* Emit "ldah $27,hi($27)" */ |
76a2c2cb | 359 | plte[0] = 0x277b0000 | (hi & 0xffff); |
d5e4222a RM |
360 | } |
361 | ||
f526ac60 UD |
362 | /* At this point, if we've been doing runtime resolution, Icache is dirty. |
363 | This will be taken care of in _dl_runtime_resolve. If instead we are | |
364 | doing this as part of non-lazy startup relocation, that bit of code | |
365 | hasn't made it into Icache yet, so there's nothing to clean up. */ | |
d5e4222a RM |
366 | } |
367 | ||
0fc15eae UD |
368 | /* Return the final value of a plt relocation. */ |
369 | static inline Elf64_Addr | |
370 | elf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc, | |
371 | Elf64_Addr value) | |
372 | { | |
373 | return value + reloc->r_addend; | |
374 | } | |
375 | ||
a8e5f5a4 UD |
376 | #endif /* !dl_machine_h */ |
377 | ||
378 | #ifdef RESOLVE | |
379 | ||
d5e4222a RM |
380 | /* Perform the relocation specified by RELOC and SYM (which is fully resolved). |
381 | MAP is the object containing the reloc. */ | |
382 | static inline void | |
383 | elf_machine_rela (struct link_map *map, | |
384 | const Elf64_Rela *reloc, | |
4ead5e71 | 385 | const Elf64_Sym *sym, |
2ed72066 UD |
386 | const struct r_found_version *version, |
387 | Elf64_Addr *const reloc_addr) | |
d5e4222a | 388 | { |
f2d725f3 | 389 | unsigned long const r_type = ELF64_R_TYPE (reloc->r_info); |
de4931d1 | 390 | |
2c73b45b RM |
391 | #ifndef RTLD_BOOTSTRAP |
392 | /* This is defined in rtld.c, but nowhere in the static libc.a; make the | |
393 | reference weak so static programs can still link. This declaration | |
394 | cannot be done when compiling rtld.c (i.e. #ifdef RTLD_BOOTSTRAP) | |
395 | because rtld.c contains the common defn for _dl_rtld_map, which is | |
396 | incompatible with a weak decl in the same file. */ | |
397 | weak_extern (_dl_rtld_map); | |
398 | #endif | |
d5e4222a RM |
399 | |
400 | /* We cannot use a switch here because we cannot locate the switch | |
401 | jump table until we've self-relocated. */ | |
402 | ||
f2d725f3 | 403 | if (r_type == R_ALPHA_RELATIVE) |
d5e4222a | 404 | { |
2c73b45b | 405 | #ifndef RTLD_BOOTSTRAP |
de4931d1 | 406 | /* Already done in dynamic linker. */ |
2c73b45b RM |
407 | if (map != &_dl_rtld_map) |
408 | #endif | |
d5e4222a RM |
409 | *reloc_addr += map->l_addr; |
410 | } | |
f2d725f3 | 411 | else if (r_type == R_ALPHA_NONE) |
2c73b45b | 412 | return; |
d5e4222a RM |
413 | else |
414 | { | |
415 | Elf64_Addr loadbase, sym_value; | |
416 | ||
f2d725f3 | 417 | loadbase = RESOLVE (&sym, version, r_type); |
d5e4222a | 418 | sym_value = sym ? loadbase + sym->st_value : 0; |
a8e5f5a4 | 419 | sym_value += reloc->r_addend; |
d5e4222a | 420 | |
f2d725f3 | 421 | if (r_type == R_ALPHA_GLOB_DAT) |
2c73b45b | 422 | *reloc_addr = sym_value; |
f2d725f3 | 423 | else if (r_type == R_ALPHA_JMP_SLOT) |
a8e5f5a4 | 424 | elf_machine_fixup_plt (map, reloc, reloc_addr, sym_value); |
f2d725f3 | 425 | else if (r_type == R_ALPHA_REFQUAD) |
d5e4222a RM |
426 | { |
427 | sym_value += *reloc_addr; | |
2c73b45b RM |
428 | #ifndef RTLD_BOOTSTRAP |
429 | if (map == &_dl_rtld_map) | |
d5e4222a RM |
430 | { |
431 | /* Undo the relocation done here during bootstrapping. | |
432 | Now we will relocate anew, possibly using a binding | |
433 | found in the user program or a loaded library rather | |
434 | than the dynamic linker's built-in definitions used | |
435 | while loading those libraries. */ | |
436 | const Elf64_Sym *const dlsymtab | |
437 | = (void *)(map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr); | |
438 | sym_value -= map->l_addr; | |
439 | sym_value -= dlsymtab[ELF64_R_SYM(reloc->r_info)].st_value; | |
a8e5f5a4 | 440 | sym_value -= reloc->r_addend; |
d5e4222a | 441 | } |
2c73b45b | 442 | #endif |
d5e4222a RM |
443 | *reloc_addr = sym_value; |
444 | } | |
d5e4222a RM |
445 | else |
446 | assert (! "unexpected dynamic reloc type"); | |
447 | } | |
448 | } | |
449 | ||
450 | static inline void | |
68d11b26 | 451 | elf_machine_lazy_rel (Elf64_Addr l_addr, const Elf64_Rela *reloc) |
d5e4222a | 452 | { |
68d11b26 | 453 | Elf64_Addr * const reloc_addr = (void *)(l_addr + reloc->r_offset); |
f2d725f3 | 454 | unsigned long const r_type = ELF64_R_TYPE (reloc->r_info); |
d5e4222a | 455 | |
f2d725f3 | 456 | if (r_type == R_ALPHA_JMP_SLOT) |
d5e4222a RM |
457 | { |
458 | /* Perform a RELATIVE reloc on the .got entry that transfers | |
459 | to the .plt. */ | |
68d11b26 | 460 | *reloc_addr += l_addr; |
d5e4222a | 461 | } |
f2d725f3 | 462 | else if (r_type == R_ALPHA_NONE) |
de4931d1 | 463 | return; |
d5e4222a RM |
464 | else |
465 | assert (! "unexpected PLT reloc type"); | |
466 | } | |
467 | ||
de4931d1 | 468 | #endif /* RESOLVE */ |