2 * Copyright 2013 Texas Instruments, Inc.
3 * Russ Dill <russ.dill@ti.com>
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
10 #include <linux/kernel.h>
11 #include <linux/pie.h>
12 #include <linux/elf.h>
17 extern char __pie_rel_dyn_start[];
18 extern char __pie_rel_dyn_end[];
19 extern char __pie_tail_offset[];
20 extern char __pie_reloc_offset[];
27 int pie_arch_fill_tail(void *tail, void *common_start, void *common_end,
28 void *overlay_start, void *code_start, void *code_end)
33 struct arm_pie_tail *pie_tail = tail;
36 rel = (Elf32_Rel *) __pie_rel_dyn_start;
37 records = (__pie_rel_dyn_end - __pie_rel_dyn_start) /
41 for (i = 0; i < records; i++, rel++) {
43 if (ELF32_R_TYPE(rel->r_info) != R_ARM_RELATIVE)
46 /* Adjust offset to match area in kernel */
47 kern_off = common_start + rel->r_offset;
49 if (kern_off >= common_start && kern_off < code_end) {
51 pie_tail->offset[count] = rel->r_offset;
53 } else if (kern_off >= code_start && kern_off < code_end) {
55 pie_tail->offset[count] = rel->r_offset -
56 (code_start - overlay_start);
62 pie_tail->count = count;
64 return count * sizeof(uintptr_t) + sizeof(*pie_tail);
66 EXPORT_SYMBOL_GPL(pie_arch_fill_tail);
69 * R_ARM_RELATIVE: B(S) + A
70 * B(S) - Addressing origin of the output segment defining the symbol S.
71 * A - Addend for the relocation.
73 int pie_arch_fixup(struct pie_chunk *chunk, void *base, void *tail,
76 struct arm_pie_tail *pie_tail = tail;
80 /* Perform relocation fixups for given offset */
81 for (i = 0; i < pie_tail->count; i++)
82 *((uintptr_t *) (pie_tail->offset[i] + base)) += offset;
84 /* Store the PIE offset to tail and recol func */
85 *kern_to_pie(chunk, (uintptr_t *) __pie_tail_offset) = tail - base;
86 reloc = kern_to_pie(chunk,
87 (void *) fnptr_to_addr(&__pie___pie_relocate));
88 *kern_to_pie(chunk, (uintptr_t *) __pie_reloc_offset) = reloc - base;
92 EXPORT_SYMBOL_GPL(pie_arch_fixup);