2 * Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3 * All rights reserved. Distributed under the terms of the MIT License.
6 * Copyright 2002, Travis Geiselbrecht. All rights reserved.
7 * Distributed under the terms of the NewOS License.
11 #include <boot/arch.h>
14 #include <KernelExport.h>
24 boot_arch_elf_relocate_rel(struct preloaded_elf32_image
*image
, Elf32_Rel
*rel
,
28 arch_elf_relocate_rel(struct elf_image_info
*image
,
29 struct elf_image_info
*resolve_image
, Elf32_Rel
*rel
, int rel_len
)
32 // there are no rel entries in PPC elf
38 write_word32(addr_t P
, Elf32_Word value
)
40 *(Elf32_Word
*)P
= value
;
45 write_word30(addr_t P
, Elf32_Word value
)
48 *(Elf32_Word
*)P
= (*(Elf32_Word
*)P
& 0x3) | (value
<< 2);
53 write_low24_check(addr_t P
, Elf32_Word value
)
56 if ((value
& 0x3f000000) && (~value
& 0x3f800000))
58 *(Elf32_Word
*)P
= (*(Elf32_Word
*)P
& 0xfc000003)
59 | ((value
& 0x00ffffff) << 2);
65 write_low14_check(addr_t P
, Elf32_Word value
)
68 if ((value
& 0x3fffc000) && (~value
& 0x3fffe000))
70 *(Elf32_Word
*)P
= (*(Elf32_Word
*)P
& 0xffff0003)
71 | ((value
& 0x00003fff) << 2);
77 write_half16(addr_t P
, Elf32_Word value
)
80 *(Elf32_Half
*)P
= (Elf32_Half
)value
;
85 write_half16_check(addr_t P
, Elf32_Word value
)
88 if ((value
& 0xffff0000) && (~value
& 0xffff8000))
90 *(Elf32_Half
*)P
= (Elf32_Half
)value
;
95 static inline Elf32_Word
98 return (value
& 0xffff);
102 static inline Elf32_Word
105 return ((value
>> 16) & 0xffff);
109 static inline Elf32_Word
112 return (((value
>> 16) + (value
& 0x8000 ? 1 : 0)) & 0xffff);
118 boot_arch_elf_relocate_rela(struct preloaded_elf32_image
*image
,
119 Elf32_Rela
*rel
, int rel_len
)
122 arch_elf_relocate_rela(struct elf_image_info
*image
,
123 struct elf_image_info
*resolve_image
, Elf32_Rela
*rel
, int rel_len
)
129 addr_t S
= 0; // symbol address
130 addr_t R
= 0; // section relative symbol address
132 addr_t G
= 0; // GOT address
133 addr_t L
= 0; // PLT address
135 #define P ((addr_t)(image->text_region.delta + rel[i].r_offset))
136 #define A ((addr_t)rel[i].r_addend)
137 #define B (image->text_region.delta)
139 // TODO: Get the GOT address!
140 #define REQUIRE_GOT \
142 dprintf("arch_elf_relocate_rela(): Failed to get GOT address!\n"); \
146 // TODO: Get the PLT address!
147 #define REQUIRE_PLT \
149 dprintf("arch_elf_relocate_rela(): Failed to get PLT address!\n"); \
153 for (i
= 0; i
* (int)sizeof(Elf32_Rela
) < rel_len
; i
++) {
155 dprintf("looking at rel type %d, offset 0x%lx, sym 0x%lx, addend 0x%lx\n",
156 ELF32_R_TYPE(rel
[i
].r_info
), rel
[i
].r_offset
, ELF32_R_SYM(rel
[i
].r_info
), rel
[i
].r_addend
);
158 switch (ELF32_R_TYPE(rel
[i
].r_info
)) {
160 case R_PPC_SECTOFF_LO
:
161 case R_PPC_SECTOFF_HI
:
162 case R_PPC_SECTOFF_HA
:
163 dprintf("arch_elf_relocate_rela(): Getting section relative "
164 "symbol addresses not yet supported!\n");
170 case R_PPC_ADDR16_LO
:
171 case R_PPC_ADDR16_HI
:
172 case R_PPC_ADDR16_HA
:
174 case R_PPC_ADDR14_BRTAKEN
:
175 case R_PPC_ADDR14_BRNTAKEN
:
178 case R_PPC_REL14_BRTAKEN
:
179 case R_PPC_REL14_BRNTAKEN
:
187 sym
= SYMBOL(image
, ELF32_R_SYM(rel
[i
].r_info
));
190 vlErr
= boot_elf_resolve_symbol(image
, sym
, &S
);
192 vlErr
= elf_resolve_symbol(image
, sym
, resolve_image
, &S
);
195 dprintf("%s(): Failed to relocate "
196 "entry index %d, rel type %d, offset 0x%lx, sym 0x%lx, "
197 "addend 0x%lx\n", __FUNCTION__
, i
, ELF32_R_TYPE(rel
[i
].r_info
),
198 rel
[i
].r_offset
, ELF32_R_SYM(rel
[i
].r_info
),
205 switch (ELF32_R_TYPE(rel
[i
].r_info
)) {
211 dprintf("arch_elf_relocate_rela(): R_PPC_COPY not yet "
218 write_word32(P
, S
+ A
);
222 if (write_low24_check(P
, (S
+ A
) >> 2))
224 dprintf("R_PPC_ADDR24 overflow\n");
229 if (write_half16_check(P
, S
+ A
))
231 dprintf("R_PPC_ADDR16 overflow\n");
234 case R_PPC_ADDR16_LO
:
235 write_half16(P
, lo(S
+ A
));
238 case R_PPC_ADDR16_HI
:
239 write_half16(P
, hi(S
+ A
));
242 case R_PPC_ADDR16_HA
:
243 write_half16(P
, ha(S
+ A
));
247 case R_PPC_ADDR14_BRTAKEN
:
248 case R_PPC_ADDR14_BRNTAKEN
:
249 if (write_low14_check(P
, (S
+ A
) >> 2))
251 dprintf("R_PPC_ADDR14 overflow\n");
255 if (write_low24_check(P
, (S
+ A
- P
) >> 2))
257 dprintf("R_PPC_REL24 overflow: 0x%lx\n", (S
+ A
- P
) >> 2);
261 case R_PPC_REL14_BRTAKEN
:
262 case R_PPC_REL14_BRNTAKEN
:
263 if (write_low14_check(P
, (S
+ A
- P
) >> 2))
265 dprintf("R_PPC_REL14 overflow\n");
270 if (write_half16_check(P
, G
+ A
))
272 dprintf("R_PPC_GOT16 overflow\n");
277 write_half16(P
, lo(G
+ A
));
282 write_half16(P
, hi(G
+ A
));
287 write_half16(P
, ha(G
+ A
));
292 // If the relative offset is small enough, we fabricate a
293 // relative branch instruction ("b <addr>").
294 addr_t jumpOffset
= S
- P
;
295 if ((jumpOffset
& 0xfc000000) != 0
296 && (~jumpOffset
& 0xfe000000) != 0) {
299 // See System V PPC ABI supplement, p. 5-6!
300 dprintf("arch_elf_relocate_rela(): R_PPC_JMP_SLOT: "
301 "Offsets > 24 bit currently not supported!\n");
302 dprintf("jumpOffset: %p\n", (void*)jumpOffset
);
306 // 0:5 opcode (= 18), 6:29 address, 30 AA, 31 LK
307 // "b" instruction: opcode = 18, AA = 0, LK = 0
308 // address: 24 high-order bits of 26 bit offset
309 *(uint32
*)P
= 0x48000000 | ((jumpOffset
) & 0x03fffffc);
315 write_word32(P
, B
+ A
);
318 case R_PPC_LOCAL24PC
:
321 // if (write_low24_check(P, ?)
323 // return B_BAD_DATA;
324 dprintf("arch_elf_relocate_rela(): R_PPC_LOCAL24PC not yet "
329 write_word32(P
, S
+ A
- P
);
334 if (write_low24_check(P
, (L
+ A
- P
) >> 2))
336 dprintf("R_PPC_PLTREL24 overflow\n");
341 write_word32(P
, L
+ A
);
346 write_word32(P
, L
+ A
- P
);
351 write_half16(P
, lo(L
+ A
));
356 write_half16(P
, hi(L
+ A
));
360 write_half16(P
, ha(L
+ A
));
365 // if (write_half16_check(P, S + A - _SDA_BASE_))
367 // return B_BAD_DATA;
368 dprintf("arch_elf_relocate_rela(): R_PPC_SDAREL16 not yet "
373 if (write_half16_check(P
, R
+ A
))
375 dprintf("R_PPC_SECTOFF overflow\n");
378 case R_PPC_SECTOFF_LO
:
379 write_half16(P
, lo(R
+ A
));
382 case R_PPC_SECTOFF_HI
:
383 write_half16(P
, hi(R
+ A
));
386 case R_PPC_SECTOFF_HA
:
387 write_half16(P
, ha(R
+ A
));
391 write_word30(P
, (S
+ A
- P
) >> 2);
395 dprintf("arch_elf_relocate_rela: unhandled relocation type %d\n", ELF32_R_TYPE(rel
[i
].r_info
));