Merge branch 'vendor/GREP'
[dragonfly.git] / contrib / binutils-2.25 / gold / aarch64-reloc-property.cc
1 // aarch64-reloc-property.cc -- AArch64 relocation properties   -*- C++ -*-
2
3 // Copyright (C) 2014 Free Software Foundation, Inc.
4 // Written by Han Shen <shenhan@google.com> and Jing Yu <jingyu@google.com>.
5
6 // This file is part of gold.
7
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 3 of the License, or
11 // (at your option) any later version.
12
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 // MA 02110-1301, USA.
22
23 #include "gold.h"
24
25 #include "aarch64-reloc-property.h"
26 #include "aarch64.h"
27
28 #include "symtab.h"
29
30 #include<stdio.h>
31
32 namespace gold
33 {
34
35 template<int L, int U>
36 bool
37 rvalue_checkup(int64_t x)
38 {
39   // We save the extra_alignment_requirement bits on [31:16] of U.
40   // "extra_alignment_requirement" could be 0, 1, 3, 7 and 15.
41   unsigned short extra_alignment_requirement = (U & 0xFFFF0000) >> 16;
42   // [15:0] of U indicates the upper bound check.
43   int64_t u = U & 0x0000FFFF;
44   if (u == 0)
45     {
46       // No requirement to check overflow.
47       gold_assert(L == 0);
48       return (x & extra_alignment_requirement) == 0;
49     }
50
51   // Check both overflow and alignment if needed.
52   int64_t low_bound = -(L == 0 ? 0 : ((int64_t)1 << L));
53   int64_t up_bound = ((int64_t)1 << u);
54   return ((low_bound <= x && x < up_bound)
55           && ((x & extra_alignment_requirement) == 0));
56 }
57
58 template<>
59 bool
60 rvalue_checkup<0, 0>(int64_t) { return true; }
61
62 template<int L, int U>
63 uint64_t
64 rvalue_bit_select(uint64_t x)
65 {
66   if (U == 63) return x >> L;
67   return (x & (((uint64_t)1 << (U+1)) - 1)) >> L;
68 }
69
70 template<>
71 uint64_t
72 rvalue_bit_select<0, 0>(uint64_t x) { return x; }
73
74 AArch64_reloc_property::AArch64_reloc_property(
75     unsigned int code,
76     const char* name,
77     Reloc_type rtype,
78     Reloc_class rclass,
79     bool is_implemented,
80     int group_index,
81     int reference_flags,
82     Reloc_inst reloc_inst,
83     rvalue_checkup_func_p rvalue_checkup_func,
84     rvalue_bit_select_func rvalue_bit_select)
85   : code_(code), name_(name), reloc_type_(rtype), reloc_class_(rclass),
86     group_index_(group_index),
87     is_implemented_(is_implemented),
88     reference_flags_(reference_flags),
89     reloc_inst_(reloc_inst),
90     rvalue_checkup_func_(rvalue_checkup_func),
91     rvalue_bit_select_func_(rvalue_bit_select)
92 {}
93
94 AArch64_reloc_property_table::AArch64_reloc_property_table()
95 {
96   const bool Y(true), N(false);
97   for (unsigned int i = 0; i < Property_table_size; ++i)
98     table_[i] = NULL;
99
100 #define RL_CHECK_ALIGN2   (1  << 16)
101 #define RL_CHECK_ALIGN4   (3  << 16)
102 #define RL_CHECK_ALIGN8   (7  << 16)
103 #define RL_CHECK_ALIGN16  (15 << 16)
104
105 #undef ARD
106 #define ARD(rname, type, class, is_implemented, group_index, LB, UB, BSL, BSH, RFLAGS, inst) \
107     do \
108       { \
109         int tidx = code_to_array_index(elfcpp::R_AARCH64_##rname); \
110         AArch64_reloc_property * p = new AArch64_reloc_property( \
111           elfcpp::R_AARCH64_##rname, "R_AARCH64_" #rname, \
112           AArch64_reloc_property::RT_##type, \
113           AArch64_reloc_property::RC_##class, \
114           is_implemented, \
115           group_index, \
116           (RFLAGS), \
117           AArch64_reloc_property::INST_##inst,  \
118           rvalue_checkup<LB,UB>,    \
119           rvalue_bit_select<BSL,BSH>);          \
120         table_[tidx] = p; \
121       } \
122     while (0);
123 #include"aarch64-reloc.def"
124 #undef ARD
125 }
126
127 // Return a string describing a relocation code that fails to get a
128 // relocation property in get_implemented_static_reloc_property().
129
130 std::string
131 AArch64_reloc_property_table::reloc_name_in_error_message(unsigned int code)
132 {
133   int tidx = code_to_array_index(code);
134   const AArch64_reloc_property* arp = this->table_[tidx];
135
136   if (arp == NULL)
137     {
138       char buffer[100];
139       sprintf(buffer, _("invalid reloc %u"), code);
140       return std::string(buffer);
141     }
142
143   // gold only implements static relocation codes.
144   AArch64_reloc_property::Reloc_type reloc_type = arp->reloc_type();
145   gold_assert(reloc_type == AArch64_reloc_property::RT_STATIC
146               || !arp->is_implemented());
147
148   const char* prefix = NULL;
149   switch (reloc_type)
150     {
151     case AArch64_reloc_property::RT_STATIC:
152       prefix = arp->is_implemented() ? _("reloc ") : _("unimplemented reloc ");
153       break;
154     case AArch64_reloc_property::RT_DYNAMIC:
155       prefix = _("dynamic reloc ");
156       break;
157     default:
158       gold_unreachable();
159     }
160   return std::string(prefix) + arp->name();
161 }
162
163 }