1 /* Copyright (c) 2015 Google Inc
2 * Davide Libenzi <dlibenzi@google.com>
3 * See LICENSE for details.
5 * Part of this code coming from a Linux kernel file:
7 * linux/arch/x86/mm/extable.c
9 * Which, even though missing specific copyright, it is supposed to be
10 * ruled by the overall Linux copyright.
13 #include <arch/uaccess.h>
18 extern struct extable_ip_fixup __attribute__((weak)) __start___ex_table[];
19 extern struct extable_ip_fixup __attribute__((weak)) __stop___ex_table[];
21 static int fixup_cmp(const void *f1, const void *f2)
23 return ((const struct extable_ip_fixup *) f1)->insn <
24 ((const struct extable_ip_fixup *) f2)->insn ? -1 : 1;
27 void exception_table_init(void)
29 if (__start___ex_table) {
30 struct extable_ip_fixup *first = __start___ex_table;
31 struct extable_ip_fixup *last = __stop___ex_table;
34 for (struct extable_ip_fixup *fx = first; fx < last; fx++) {
36 offset += sizeof(fx->insn);
38 offset += sizeof(fx->fixup);
41 sort(first, last - first, sizeof(*first), fixup_cmp);
44 for (struct extable_ip_fixup *fx = first; fx < last; fx++) {
46 offset += sizeof(fx->insn);
48 offset += sizeof(fx->fixup);
53 uintptr_t get_fixup_ip(uintptr_t xip)
55 const struct extable_ip_fixup *first = __start___ex_table;
58 const struct extable_ip_fixup *last = __stop___ex_table;
60 while (first <= last) {
61 const struct extable_ip_fixup *x =
62 first + ((last - first) >> 1);
63 uintptr_t insn = ex_insn_addr(x);
70 return (uintptr_t) ex_fixup_addr(x);