2 * Copyright 2004-2008, Haiku Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT license.
5 * Copyright 2002, Travis Geiselbrecht. All rights reserved.
6 * Distributed under the terms of the NewOS License.
11 # include <boot/arch.h>
14 #include <KernelExport.h>
20 //#define TRACE_ARCH_ELF
22 # define TRACE(x) dprintf x
30 is_in_image(struct elf_image_info
*image
, addr_t address
)
32 return (address
>= image
->text_region
.start
33 && address
< image
->text_region
.start
+ image
->text_region
.size
)
34 || (address
>= image
->data_region
.start
35 && address
< image
->data_region
.start
+ image
->data_region
.size
);
40 #if !defined(__x86_64__) || (defined(_BOOT_MODE) && _BOOT_PLATFORM != efi)
44 static const char *kRelocations
[] = {
46 "R_386_32", /* add symbol value */
47 "R_386_PC32", /* add PC relative symbol value */
48 "R_386_GOT32", /* add PC relative GOT offset */
49 "R_386_PLT32", /* add PC relative PLT offset */
50 "R_386_COPY", /* copy data from shared object */
51 "R_386_GLOB_DAT", /* set GOT entry to data address */
52 "R_386_JMP_SLOT", /* set GOT entry to code address */
53 "R_386_RELATIVE", /* add load address of shared object */
54 "R_386_GOTOFF", /* add GOT relative symbol address */
55 "R_386_GOTPC", /* add PC relative GOT table address */
62 boot_arch_elf_relocate_rel(struct preloaded_elf32_image
*image
, Elf32_Rel
*rel
,
66 arch_elf_relocate_rel(struct elf_image_info
*image
,
67 struct elf_image_info
*resolveImage
, Elf32_Rel
*rel
, int relLength
)
74 addr_t
*resolveAddress
;
79 for (i
= 0; i
* (int)sizeof(Elf32_Rel
) < relLength
; i
++) {
80 TRACE(("looking at rel type %s, offset 0x%lx\n",
81 kRelocations
[ELF32_R_TYPE(rel
[i
].r_info
)], rel
[i
].r_offset
));
84 switch (ELF32_R_TYPE(rel
[i
].r_info
)) {
94 symbol
= SYMBOL(image
, ELF32_R_SYM(rel
[i
].r_info
));
97 status
= boot_elf_resolve_symbol(image
, symbol
, &S
);
99 status
= elf_resolve_symbol(image
, symbol
, resolveImage
, &S
);
103 TRACE(("S %p (%s)\n", (void *)S
, SYMNAME(image
, symbol
)));
107 switch (ELF32_R_TYPE(rel
[i
].r_info
)) {
115 A
= *(addr_t
*)(image
->text_region
.delta
+ rel
[i
].r_offset
);
116 TRACE(("A %p\n", (void *)A
));
120 switch (ELF32_R_TYPE(rel
[i
].r_info
)) {
125 P
= image
->text_region
.delta
+ rel
[i
].r_offset
;
126 TRACE(("P %p\n", (void *)P
));
130 switch (ELF32_R_TYPE(rel
[i
].r_info
)) {
134 finalAddress
= S
+ A
;
137 finalAddress
= S
+ A
- P
;
141 finalAddress
= image
->text_region
.delta
+ A
;
149 dprintf("arch_elf_relocate_rel: unhandled relocation type %d\n",
150 ELF32_R_TYPE(rel
[i
].r_info
));
154 resolveAddress
= (addr_t
*)(image
->text_region
.delta
+ rel
[i
].r_offset
);
156 if (!is_in_image(image
, (addr_t
)resolveAddress
)) {
157 dprintf("arch_elf_relocate_rel: invalid offset %#lx\n",
159 return B_BAD_ADDRESS
;
162 *resolveAddress
= finalAddress
;
163 TRACE(("-> offset %#lx = %#lx\n",
164 (image
->text_region
.delta
+ rel
[i
].r_offset
), finalAddress
));
173 boot_arch_elf_relocate_rela(struct preloaded_elf32_image
*image
,
174 Elf32_Rela
*rel
, int relLength
)
177 arch_elf_relocate_rela(struct elf_image_info
*image
,
178 struct elf_image_info
*resolveImage
, Elf32_Rela
*rel
, int relLength
)
181 dprintf("arch_elf_relocate_rela: not supported on x86\n");
186 #endif // !__x86_64__ || (_BOOT_MODE && _BOOT_PLATFORM != efi)
189 #if defined(__x86_64__) || defined(_BOOT_MODE)
194 boot_arch_elf_relocate_rel(preloaded_elf64_image
* image
, Elf64_Rel
* rel
,
198 arch_elf_relocate_rel(struct elf_image_info
*image
,
199 struct elf_image_info
*resolveImage
, Elf64_Rel
*rel
, int relLength
)
202 dprintf("arch_elf_relocate_rel: not supported on x86_64\n");
209 boot_arch_elf_relocate_rela(preloaded_elf64_image
* image
, Elf64_Rela
* rel
,
213 arch_elf_relocate_rela(struct elf_image_info
*image
,
214 struct elf_image_info
*resolveImage
, Elf64_Rela
*rel
, int relLength
)
217 for (int i
= 0; i
< relLength
/ (int)sizeof(Elf64_Rela
); i
++) {
218 int type
= ELF64_R_TYPE(rel
[i
].r_info
);
219 int symIndex
= ELF64_R_SYM(rel
[i
].r_info
);
220 Elf64_Addr symAddr
= 0;
222 // Resolve the symbol, if any.
224 Elf64_Sym
* symbol
= SYMBOL(image
, symIndex
);
228 status
= boot_elf_resolve_symbol(image
, symbol
, &symAddr
);
230 status
= elf_resolve_symbol(image
, symbol
, resolveImage
, &symAddr
);
236 // Address of the relocation.
237 Elf64_Addr relocAddr
= image
->text_region
.delta
+ rel
[i
].r_offset
;
239 // Calculate the relocation value.
240 Elf64_Addr relocValue
;
245 relocValue
= symAddr
+ rel
[i
].r_addend
;
248 relocValue
= symAddr
+ rel
[i
].r_addend
- rel
[i
].r_offset
;
250 case R_X86_64_GLOB_DAT
:
251 case R_X86_64_JUMP_SLOT
:
252 relocValue
= symAddr
+ rel
[i
].r_addend
;
254 case R_X86_64_RELATIVE
:
255 relocValue
= image
->text_region
.delta
+ rel
[i
].r_addend
;
258 dprintf("arch_elf_relocate_rela: unhandled relocation type %d\n",
263 boot_elf64_set_relocation(relocAddr
, relocValue
);
265 if (!is_in_image(image
, relocAddr
)) {
266 dprintf("arch_elf_relocate_rela: invalid offset %#lx\n",
268 return B_BAD_ADDRESS
;
271 *(Elf64_Addr
*)relocAddr
= relocValue
;
279 #endif // __x86_64__ || _BOOT_MODE