1*1424dfb3Schristos // arm-reloc-property.cc -- ARM relocation property.
2*1424dfb3Schristos
3*1424dfb3Schristos // Copyright (C) 2010-2020 Free Software Foundation, Inc.
4*1424dfb3Schristos // Written by Doug Kwan <dougkwan@google.com>.
5*1424dfb3Schristos
6*1424dfb3Schristos // This file is part of gold.
7*1424dfb3Schristos
8*1424dfb3Schristos // This program is free software; you can redistribute it and/or modify
9*1424dfb3Schristos // it under the terms of the GNU General Public License as published by
10*1424dfb3Schristos // the Free Software Foundation; either version 3 of the License, or
11*1424dfb3Schristos // (at your option) any later version.
12*1424dfb3Schristos
13*1424dfb3Schristos // This program is distributed in the hope that it will be useful,
14*1424dfb3Schristos // but WITHOUT ANY WARRANTY; without even the implied warranty of
15*1424dfb3Schristos // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16*1424dfb3Schristos // GNU General Public License for more details.
17*1424dfb3Schristos
18*1424dfb3Schristos // You should have received a copy of the GNU General Public License
19*1424dfb3Schristos // along with this program; if not, write to the Free Software
20*1424dfb3Schristos // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21*1424dfb3Schristos // MA 02110-1301, USA.
22*1424dfb3Schristos
23*1424dfb3Schristos #include "gold.h"
24*1424dfb3Schristos
25*1424dfb3Schristos #include <cstdio>
26*1424dfb3Schristos #include <cstring>
27*1424dfb3Schristos #include <stack>
28*1424dfb3Schristos #include <string>
29*1424dfb3Schristos #include <vector>
30*1424dfb3Schristos
31*1424dfb3Schristos #include "elfcpp.h"
32*1424dfb3Schristos #include "arm.h"
33*1424dfb3Schristos #include "arm-reloc-property.h"
34*1424dfb3Schristos
35*1424dfb3Schristos namespace gold
36*1424dfb3Schristos {
37*1424dfb3Schristos
38*1424dfb3Schristos // Arm_reloc_property::Tree_node methods.
39*1424dfb3Schristos
40*1424dfb3Schristos // Parse an S-expression S and build a tree and return the root node.
41*1424dfb3Schristos // Caller is responsible for releasing tree after use.
42*1424dfb3Schristos
43*1424dfb3Schristos Arm_reloc_property::Tree_node*
make_tree(const std::string & s)44*1424dfb3Schristos Arm_reloc_property::Tree_node::make_tree(const std::string& s)
45*1424dfb3Schristos {
46*1424dfb3Schristos std::stack<size_t> size_stack;
47*1424dfb3Schristos Tree_node_vector node_stack;
48*1424dfb3Schristos
49*1424dfb3Schristos // strtok needs a non-const string pointer.
50*1424dfb3Schristos char* buffer = new char[s.size() + 1];
51*1424dfb3Schristos memcpy(buffer, s.data(), s.size());
52*1424dfb3Schristos buffer[s.size()] = '\0';
53*1424dfb3Schristos char* token = strtok(buffer, " ");
54*1424dfb3Schristos
55*1424dfb3Schristos while (token != NULL)
56*1424dfb3Schristos {
57*1424dfb3Schristos if (strcmp(token, "(") == 0)
58*1424dfb3Schristos // Remember the node stack position for start of a new internal node.
59*1424dfb3Schristos size_stack.push(node_stack.size());
60*1424dfb3Schristos else if (strcmp(token, ")") == 0)
61*1424dfb3Schristos {
62*1424dfb3Schristos // Pop all tree nodes after the previous '(' and use them as
63*1424dfb3Schristos // children to build a new internal node. Push internal node back.
64*1424dfb3Schristos size_t current_size = node_stack.size();
65*1424dfb3Schristos size_t prev_size = size_stack.top();
66*1424dfb3Schristos size_stack.pop();
67*1424dfb3Schristos Tree_node* node =
68*1424dfb3Schristos new Tree_node(node_stack.begin() + prev_size,
69*1424dfb3Schristos node_stack.begin() + current_size);
70*1424dfb3Schristos node_stack.resize(prev_size);
71*1424dfb3Schristos node_stack.push_back(node);
72*1424dfb3Schristos }
73*1424dfb3Schristos else
74*1424dfb3Schristos // Just push a leaf node to node_stack.
75*1424dfb3Schristos node_stack.push_back(new Tree_node(token));
76*1424dfb3Schristos
77*1424dfb3Schristos token = strtok(NULL, " ");
78*1424dfb3Schristos }
79*1424dfb3Schristos
80*1424dfb3Schristos delete[] buffer;
81*1424dfb3Schristos
82*1424dfb3Schristos // At this point, size_stack should be empty and node_stack should only
83*1424dfb3Schristos // contain the root node.
84*1424dfb3Schristos gold_assert(size_stack.empty() && node_stack.size() == 1);
85*1424dfb3Schristos return node_stack[0];
86*1424dfb3Schristos }
87*1424dfb3Schristos
88*1424dfb3Schristos // Arm_reloc_property methods.
89*1424dfb3Schristos
90*1424dfb3Schristos // Constructor.
91*1424dfb3Schristos
Arm_reloc_property(unsigned int code,const char * name,Reloc_type rtype,bool is_deprecated,Reloc_class rclass,const std::string & operation,bool is_implemented,int group_index,bool checks_overflow)92*1424dfb3Schristos Arm_reloc_property::Arm_reloc_property(
93*1424dfb3Schristos unsigned int code,
94*1424dfb3Schristos const char* name,
95*1424dfb3Schristos Reloc_type rtype,
96*1424dfb3Schristos bool is_deprecated,
97*1424dfb3Schristos Reloc_class rclass,
98*1424dfb3Schristos const std::string& operation,
99*1424dfb3Schristos bool is_implemented,
100*1424dfb3Schristos int group_index,
101*1424dfb3Schristos bool checks_overflow)
102*1424dfb3Schristos : code_(code), name_(name), reloc_type_(rtype), reloc_class_(rclass),
103*1424dfb3Schristos group_index_(group_index), size_(0), align_(1),
104*1424dfb3Schristos relative_address_base_(RAB_NONE), is_deprecated_(is_deprecated),
105*1424dfb3Schristos is_implemented_(is_implemented), checks_overflow_(checks_overflow),
106*1424dfb3Schristos uses_got_entry_(false), uses_got_origin_(false), uses_plt_entry_(false),
107*1424dfb3Schristos uses_thumb_bit_(false), uses_symbol_base_(false), uses_addend_(false),
108*1424dfb3Schristos uses_symbol_(false)
109*1424dfb3Schristos {
110*1424dfb3Schristos // Set size and alignment of static and dynamic relocations.
111*1424dfb3Schristos if (rtype == RT_STATIC)
112*1424dfb3Schristos {
113*1424dfb3Schristos switch (rclass)
114*1424dfb3Schristos {
115*1424dfb3Schristos case RC_DATA:
116*1424dfb3Schristos // Except for R_ARM_ABS16 and R_ARM_ABS8, all static data relocations
117*1424dfb3Schristos // have size 4. All static data relocations have alignment of 1.
118*1424dfb3Schristos if (code == elfcpp::R_ARM_ABS8)
119*1424dfb3Schristos this->size_ = 1;
120*1424dfb3Schristos else if (code == elfcpp::R_ARM_ABS16)
121*1424dfb3Schristos this->size_ = 2;
122*1424dfb3Schristos else
123*1424dfb3Schristos this->size_ = 4;
124*1424dfb3Schristos this->align_ = 1;
125*1424dfb3Schristos break;
126*1424dfb3Schristos case RC_MISC:
127*1424dfb3Schristos // R_ARM_V4BX should be treated as an ARM relocation. For all
128*1424dfb3Schristos // others, just use defaults.
129*1424dfb3Schristos if (code != elfcpp::R_ARM_V4BX)
130*1424dfb3Schristos break;
131*1424dfb3Schristos // Fall through.
132*1424dfb3Schristos case RC_ARM:
133*1424dfb3Schristos this->size_ = 4;
134*1424dfb3Schristos this->align_ = 4;
135*1424dfb3Schristos break;
136*1424dfb3Schristos case RC_THM16:
137*1424dfb3Schristos this->size_ = 2;
138*1424dfb3Schristos this->align_ = 2;
139*1424dfb3Schristos break;
140*1424dfb3Schristos case RC_THM32:
141*1424dfb3Schristos this->size_ = 4;
142*1424dfb3Schristos this->align_ = 2;
143*1424dfb3Schristos break;
144*1424dfb3Schristos default:
145*1424dfb3Schristos gold_unreachable();
146*1424dfb3Schristos }
147*1424dfb3Schristos }
148*1424dfb3Schristos else if (rtype == RT_DYNAMIC)
149*1424dfb3Schristos {
150*1424dfb3Schristos // With the exception of R_ARM_COPY, all dynamic relocations requires
151*1424dfb3Schristos // that the place being relocated is a word-aligned 32-bit object.
152*1424dfb3Schristos if (code != elfcpp::R_ARM_COPY)
153*1424dfb3Schristos {
154*1424dfb3Schristos this->size_ = 4;
155*1424dfb3Schristos this->align_ = 4;
156*1424dfb3Schristos }
157*1424dfb3Schristos }
158*1424dfb3Schristos
159*1424dfb3Schristos // If no relocation operation is specified, we are done.
160*1424dfb3Schristos if (operation == "NONE")
161*1424dfb3Schristos return;
162*1424dfb3Schristos
163*1424dfb3Schristos // Extract information from relocation operation.
164*1424dfb3Schristos Tree_node* root_node = Tree_node::make_tree(operation);
165*1424dfb3Schristos Tree_node* node = root_node;
166*1424dfb3Schristos
167*1424dfb3Schristos // Check for an expression of the form XXX - YYY.
168*1424dfb3Schristos if (!node->is_leaf()
169*1424dfb3Schristos && node->child(0)->is_leaf()
170*1424dfb3Schristos && node->child(0)->name() == "-")
171*1424dfb3Schristos {
172*1424dfb3Schristos struct RAB_table_entry
173*1424dfb3Schristos {
174*1424dfb3Schristos Relative_address_base rab;
175*1424dfb3Schristos const char* name;
176*1424dfb3Schristos };
177*1424dfb3Schristos
178*1424dfb3Schristos static const RAB_table_entry rab_table[] =
179*1424dfb3Schristos {
180*1424dfb3Schristos { RAB_B_S, "( B S )" },
181*1424dfb3Schristos { RAB_DELTA_B_S, "( DELTA_B ( S ) )" },
182*1424dfb3Schristos { RAB_GOT_ORG, "GOT_ORG" },
183*1424dfb3Schristos { RAB_P, "P" },
184*1424dfb3Schristos { RAB_Pa, "Pa" },
185*1424dfb3Schristos { RAB_TLS, "TLS" },
186*1424dfb3Schristos { RAB_tp, "tp" }
187*1424dfb3Schristos };
188*1424dfb3Schristos
189*1424dfb3Schristos static size_t rab_table_size = sizeof(rab_table) / sizeof(rab_table[0]);
190*1424dfb3Schristos const std::string rhs(node->child(2)->s_expression());
191*1424dfb3Schristos for (size_t i = 0; i < rab_table_size; ++i)
192*1424dfb3Schristos if (rhs == rab_table[i].name)
193*1424dfb3Schristos {
194*1424dfb3Schristos this->relative_address_base_ = rab_table[i].rab;
195*1424dfb3Schristos break;
196*1424dfb3Schristos }
197*1424dfb3Schristos
198*1424dfb3Schristos gold_assert(this->relative_address_base_ != RAB_NONE);
199*1424dfb3Schristos if (this->relative_address_base_ == RAB_B_S)
200*1424dfb3Schristos this->uses_symbol_base_ = true;
201*1424dfb3Schristos node = node->child(1);
202*1424dfb3Schristos }
203*1424dfb3Schristos
204*1424dfb3Schristos // Check for an expression of the form XXX | T.
205*1424dfb3Schristos if (!node->is_leaf()
206*1424dfb3Schristos && node->child(0)->is_leaf()
207*1424dfb3Schristos && node->child(0)->name() == "|")
208*1424dfb3Schristos {
209*1424dfb3Schristos gold_assert(node->number_of_children() == 3
210*1424dfb3Schristos && node->child(2)->is_leaf()
211*1424dfb3Schristos && node->child(2)->name() == "T");
212*1424dfb3Schristos this->uses_thumb_bit_ = true;
213*1424dfb3Schristos node = node->child(1);
214*1424dfb3Schristos }
215*1424dfb3Schristos
216*1424dfb3Schristos // Check for an expression of the form XXX + A.
217*1424dfb3Schristos if (!node->is_leaf()
218*1424dfb3Schristos && node->child(0)->is_leaf()
219*1424dfb3Schristos && node->child(0)->name() == "+")
220*1424dfb3Schristos {
221*1424dfb3Schristos gold_assert(node->number_of_children() == 3
222*1424dfb3Schristos && node->child(2)->is_leaf()
223*1424dfb3Schristos && node->child(2)->name() == "A");
224*1424dfb3Schristos this->uses_addend_ = true;
225*1424dfb3Schristos node = node->child(1);
226*1424dfb3Schristos }
227*1424dfb3Schristos
228*1424dfb3Schristos // Check for an expression of the form XXX(S).
229*1424dfb3Schristos if (!node->is_leaf() && node->child(0)->is_leaf())
230*1424dfb3Schristos {
231*1424dfb3Schristos gold_assert(node->number_of_children() == 2
232*1424dfb3Schristos && node->child(1)->is_leaf()
233*1424dfb3Schristos && node->child(1)->name() == "S");
234*1424dfb3Schristos const std::string func(node->child(0)->name());
235*1424dfb3Schristos if (func == "B")
236*1424dfb3Schristos this->uses_symbol_base_ = true;
237*1424dfb3Schristos else if (func == "GOT")
238*1424dfb3Schristos this->uses_got_entry_ = true;
239*1424dfb3Schristos else if (func == "PLT")
240*1424dfb3Schristos this->uses_plt_entry_ = true;
241*1424dfb3Schristos else if (func == "Module" || func == "DELTA_B")
242*1424dfb3Schristos // These are used in dynamic relocations.
243*1424dfb3Schristos ;
244*1424dfb3Schristos else
245*1424dfb3Schristos gold_unreachable();
246*1424dfb3Schristos node = node->child(1);
247*1424dfb3Schristos }
248*1424dfb3Schristos
249*1424dfb3Schristos gold_assert(node->is_leaf() && node->name() == "S");
250*1424dfb3Schristos this->uses_symbol_ = true;
251*1424dfb3Schristos
252*1424dfb3Schristos delete root_node;
253*1424dfb3Schristos }
254*1424dfb3Schristos
255*1424dfb3Schristos // Arm_reloc_property_table methods.
256*1424dfb3Schristos
257*1424dfb3Schristos // Constructor. This processing informations in arm-reloc.def to
258*1424dfb3Schristos // initialize the table.
259*1424dfb3Schristos
Arm_reloc_property_table()260*1424dfb3Schristos Arm_reloc_property_table::Arm_reloc_property_table()
261*1424dfb3Schristos {
262*1424dfb3Schristos // These appear in arm-reloc.def. Do not rename them.
263*1424dfb3Schristos Parse_expression A("A"), GOT_ORG("GOT_ORG"), NONE("NONE"), P("P"),
264*1424dfb3Schristos Pa("Pa"), S("S"), T("T"), TLS("TLS"), tp("tp");
265*1424dfb3Schristos const bool Y(true), N(false);
266*1424dfb3Schristos
267*1424dfb3Schristos for (unsigned int i = 0; i < Property_table_size; ++i)
268*1424dfb3Schristos this->table_[i] = NULL;
269*1424dfb3Schristos
270*1424dfb3Schristos #undef RD
271*1424dfb3Schristos #define RD(name, type, deprecated, class, operation, is_implemented, \
272*1424dfb3Schristos group_index, checks_oveflow) \
273*1424dfb3Schristos do \
274*1424dfb3Schristos { \
275*1424dfb3Schristos unsigned int code = elfcpp::R_ARM_##name; \
276*1424dfb3Schristos gold_assert(code < Property_table_size); \
277*1424dfb3Schristos this->table_[code] = \
278*1424dfb3Schristos new Arm_reloc_property(elfcpp::R_ARM_##name, "R_ARM_" #name, \
279*1424dfb3Schristos Arm_reloc_property::RT_##type, deprecated, \
280*1424dfb3Schristos Arm_reloc_property::RC_##class, \
281*1424dfb3Schristos (operation).s_expression(), is_implemented, \
282*1424dfb3Schristos group_index, checks_oveflow); \
283*1424dfb3Schristos } \
284*1424dfb3Schristos while(0);
285*1424dfb3Schristos
286*1424dfb3Schristos #include "arm-reloc.def"
287*1424dfb3Schristos #undef RD
288*1424dfb3Schristos }
289*1424dfb3Schristos
290*1424dfb3Schristos // Return a string describing a relocation code that fails to get a
291*1424dfb3Schristos // relocation property in get_implemented_static_reloc_property().
292*1424dfb3Schristos
293*1424dfb3Schristos std::string
reloc_name_in_error_message(unsigned int code)294*1424dfb3Schristos Arm_reloc_property_table::reloc_name_in_error_message(unsigned int code)
295*1424dfb3Schristos {
296*1424dfb3Schristos gold_assert(code < Property_table_size);
297*1424dfb3Schristos
298*1424dfb3Schristos const Arm_reloc_property* arp = this->table_[code];
299*1424dfb3Schristos
300*1424dfb3Schristos if (arp == NULL)
301*1424dfb3Schristos {
302*1424dfb3Schristos char buffer[100];
303*1424dfb3Schristos sprintf(buffer, _("invalid reloc %u"), code);
304*1424dfb3Schristos return std::string(buffer);
305*1424dfb3Schristos }
306*1424dfb3Schristos
307*1424dfb3Schristos // gold only implements static relocation codes.
308*1424dfb3Schristos Arm_reloc_property::Reloc_type reloc_type = arp->reloc_type();
309*1424dfb3Schristos gold_assert(reloc_type == Arm_reloc_property::RT_STATIC
310*1424dfb3Schristos || !arp->is_implemented());
311*1424dfb3Schristos
312*1424dfb3Schristos const char* prefix = NULL;
313*1424dfb3Schristos switch (reloc_type)
314*1424dfb3Schristos {
315*1424dfb3Schristos case Arm_reloc_property::RT_STATIC:
316*1424dfb3Schristos prefix = arp->is_implemented() ? _("reloc ") : _("unimplemented reloc ");
317*1424dfb3Schristos break;
318*1424dfb3Schristos case Arm_reloc_property::RT_DYNAMIC:
319*1424dfb3Schristos prefix = _("dynamic reloc ");
320*1424dfb3Schristos break;
321*1424dfb3Schristos case Arm_reloc_property::RT_PRIVATE:
322*1424dfb3Schristos prefix = _("private reloc ");
323*1424dfb3Schristos break;
324*1424dfb3Schristos case Arm_reloc_property::RT_OBSOLETE:
325*1424dfb3Schristos prefix = _("obsolete reloc ");
326*1424dfb3Schristos break;
327*1424dfb3Schristos default:
328*1424dfb3Schristos gold_unreachable();
329*1424dfb3Schristos }
330*1424dfb3Schristos return std::string(prefix) + arp->name();
331*1424dfb3Schristos }
332*1424dfb3Schristos
333*1424dfb3Schristos } // End namespace gold.
334