1ed0d50c3Schristos // aarch64.cc -- aarch64 target support for gold.
2ed0d50c3Schristos 
3*b88e3e88Schristos // Copyright (C) 2014-2020 Free Software Foundation, Inc.
4ed0d50c3Schristos // Written by Jing Yu <jingyu@google.com> and Han Shen <shenhan@google.com>.
5ed0d50c3Schristos 
6ed0d50c3Schristos // This file is part of gold.
7ed0d50c3Schristos 
8ed0d50c3Schristos // This program is free software; you can redistribute it and/or modify
9ed0d50c3Schristos // it under the terms of the GNU General Public License as published by
10ed0d50c3Schristos // the Free Software Foundation; either version 3 of the License, or
11ed0d50c3Schristos // (at your option) any later version.
12ed0d50c3Schristos 
13ed0d50c3Schristos // This program is distributed in the hope that it will be useful,
14ed0d50c3Schristos // but WITHOUT ANY WARRANTY; without even the implied warranty of
15ed0d50c3Schristos // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16ed0d50c3Schristos // GNU General Public License for more details.
17ed0d50c3Schristos 
18ed0d50c3Schristos // You should have received a copy of the GNU General Public License
19ed0d50c3Schristos // along with this program; if not, write to the Free Software
20ed0d50c3Schristos // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21ed0d50c3Schristos // MA 02110-1301, USA.
22ed0d50c3Schristos 
23ed0d50c3Schristos #include "gold.h"
24ed0d50c3Schristos 
25ed0d50c3Schristos #include <cstring>
26ed0d50c3Schristos #include <map>
27ed0d50c3Schristos #include <set>
28ed0d50c3Schristos 
29ed0d50c3Schristos #include "elfcpp.h"
30ed0d50c3Schristos #include "dwarf.h"
31ed0d50c3Schristos #include "parameters.h"
32ed0d50c3Schristos #include "reloc.h"
33ed0d50c3Schristos #include "aarch64.h"
34ed0d50c3Schristos #include "object.h"
35ed0d50c3Schristos #include "symtab.h"
36ed0d50c3Schristos #include "layout.h"
37ed0d50c3Schristos #include "output.h"
38ed0d50c3Schristos #include "copy-relocs.h"
39ed0d50c3Schristos #include "target.h"
40ed0d50c3Schristos #include "target-reloc.h"
41ed0d50c3Schristos #include "target-select.h"
42ed0d50c3Schristos #include "tls.h"
43ed0d50c3Schristos #include "freebsd.h"
44ed0d50c3Schristos #include "nacl.h"
45ed0d50c3Schristos #include "gc.h"
46ed0d50c3Schristos #include "icf.h"
47ed0d50c3Schristos #include "aarch64-reloc-property.h"
48ed0d50c3Schristos 
49ed0d50c3Schristos // The first three .got.plt entries are reserved.
50ed0d50c3Schristos const int32_t AARCH64_GOTPLT_RESERVE_COUNT = 3;
51ed0d50c3Schristos 
52ed0d50c3Schristos 
53ed0d50c3Schristos namespace
54ed0d50c3Schristos {
55ed0d50c3Schristos 
56ed0d50c3Schristos using namespace gold;
57ed0d50c3Schristos 
58ed0d50c3Schristos template<int size, bool big_endian>
59ed0d50c3Schristos class Output_data_plt_aarch64;
60ed0d50c3Schristos 
61ed0d50c3Schristos template<int size, bool big_endian>
62ed0d50c3Schristos class Output_data_plt_aarch64_standard;
63ed0d50c3Schristos 
64ed0d50c3Schristos template<int size, bool big_endian>
65ed0d50c3Schristos class Target_aarch64;
66ed0d50c3Schristos 
67ed0d50c3Schristos template<int size, bool big_endian>
68ed0d50c3Schristos class AArch64_relocate_functions;
69ed0d50c3Schristos 
70ed0d50c3Schristos // Utility class dealing with insns. This is ported from macros in
71ed0d50c3Schristos // bfd/elfnn-aarch64.cc, but wrapped inside a class as static members. This
72ed0d50c3Schristos // class is used in erratum sequence scanning.
73ed0d50c3Schristos 
74ed0d50c3Schristos template<bool big_endian>
75ed0d50c3Schristos class AArch64_insn_utilities
76ed0d50c3Schristos {
77ed0d50c3Schristos public:
78ed0d50c3Schristos   typedef typename elfcpp::Swap<32, big_endian>::Valtype Insntype;
79ed0d50c3Schristos 
80ed0d50c3Schristos   static const int BYTES_PER_INSN;
81ed0d50c3Schristos 
82ed0d50c3Schristos   // Zero register encoding - 31.
83ed0d50c3Schristos   static const unsigned int AARCH64_ZR;
84ed0d50c3Schristos 
85ed0d50c3Schristos   static unsigned int
aarch64_bit(Insntype insn,int pos)86ed0d50c3Schristos   aarch64_bit(Insntype insn, int pos)
87ed0d50c3Schristos   { return ((1 << pos)  & insn) >> pos; }
88ed0d50c3Schristos 
89ed0d50c3Schristos   static unsigned int
aarch64_bits(Insntype insn,int pos,int l)90ed0d50c3Schristos   aarch64_bits(Insntype insn, int pos, int l)
91ed0d50c3Schristos   { return (insn >> pos) & ((1 << l) - 1); }
92ed0d50c3Schristos 
93ed0d50c3Schristos   // Get the encoding field "op31" of 3-source data processing insns. "op31" is
94ed0d50c3Schristos   // the name defined in armv8 insn manual C3.5.9.
95ed0d50c3Schristos   static unsigned int
aarch64_op31(Insntype insn)96ed0d50c3Schristos   aarch64_op31(Insntype insn)
97ed0d50c3Schristos   { return aarch64_bits(insn, 21, 3); }
98ed0d50c3Schristos 
99ed0d50c3Schristos   // Get the encoding field "ra" of 3-source data processing insns. "ra" is the
100ed0d50c3Schristos   // third source register. See armv8 insn manual C3.5.9.
101ed0d50c3Schristos   static unsigned int
aarch64_ra(Insntype insn)102ed0d50c3Schristos   aarch64_ra(Insntype insn)
103ed0d50c3Schristos   { return aarch64_bits(insn, 10, 5); }
104ed0d50c3Schristos 
105ed0d50c3Schristos   static bool
is_adr(const Insntype insn)106ed0d50c3Schristos   is_adr(const Insntype insn)
107ed0d50c3Schristos   { return (insn & 0x9F000000) == 0x10000000; }
108ed0d50c3Schristos 
109ed0d50c3Schristos   static bool
is_adrp(const Insntype insn)110ed0d50c3Schristos   is_adrp(const Insntype insn)
111ed0d50c3Schristos   { return (insn & 0x9F000000) == 0x90000000; }
112ed0d50c3Schristos 
11306324dcfSchristos   static bool
is_mrs_tpidr_el0(const Insntype insn)11406324dcfSchristos   is_mrs_tpidr_el0(const Insntype insn)
11506324dcfSchristos   { return (insn & 0xFFFFFFE0) == 0xd53bd040; }
11606324dcfSchristos 
117ed0d50c3Schristos   static unsigned int
aarch64_rm(const Insntype insn)118ed0d50c3Schristos   aarch64_rm(const Insntype insn)
119ed0d50c3Schristos   { return aarch64_bits(insn, 16, 5); }
120ed0d50c3Schristos 
121ed0d50c3Schristos   static unsigned int
aarch64_rn(const Insntype insn)122ed0d50c3Schristos   aarch64_rn(const Insntype insn)
123ed0d50c3Schristos   { return aarch64_bits(insn, 5, 5); }
124ed0d50c3Schristos 
125ed0d50c3Schristos   static unsigned int
aarch64_rd(const Insntype insn)126ed0d50c3Schristos   aarch64_rd(const Insntype insn)
127ed0d50c3Schristos   { return aarch64_bits(insn, 0, 5); }
128ed0d50c3Schristos 
129ed0d50c3Schristos   static unsigned int
aarch64_rt(const Insntype insn)130ed0d50c3Schristos   aarch64_rt(const Insntype insn)
131ed0d50c3Schristos   { return aarch64_bits(insn, 0, 5); }
132ed0d50c3Schristos 
133ed0d50c3Schristos   static unsigned int
aarch64_rt2(const Insntype insn)134ed0d50c3Schristos   aarch64_rt2(const Insntype insn)
135ed0d50c3Schristos   { return aarch64_bits(insn, 10, 5); }
136ed0d50c3Schristos 
137ed0d50c3Schristos   // Encode imm21 into adr. Signed imm21 is in the range of [-1M, 1M).
138ed0d50c3Schristos   static Insntype
aarch64_adr_encode_imm(Insntype adr,int imm21)139ed0d50c3Schristos   aarch64_adr_encode_imm(Insntype adr, int imm21)
140ed0d50c3Schristos   {
141ed0d50c3Schristos     gold_assert(is_adr(adr));
142ed0d50c3Schristos     gold_assert(-(1 << 20) <= imm21 && imm21 < (1 << 20));
143ed0d50c3Schristos     const int mask19 = (1 << 19) - 1;
144ed0d50c3Schristos     const int mask2 = 3;
145ed0d50c3Schristos     adr &= ~((mask19 << 5) | (mask2 << 29));
146ed0d50c3Schristos     adr |= ((imm21 & mask2) << 29) | (((imm21 >> 2) & mask19) << 5);
147ed0d50c3Schristos     return adr;
148ed0d50c3Schristos   }
149ed0d50c3Schristos 
150ed0d50c3Schristos   // Retrieve encoded adrp 33-bit signed imm value. This value is obtained by
151ed0d50c3Schristos   // 21-bit signed imm encoded in the insn multiplied by 4k (page size) and
152ed0d50c3Schristos   // 64-bit sign-extended, resulting in [-4G, 4G) with 12-lsb being 0.
153ed0d50c3Schristos   static int64_t
aarch64_adrp_decode_imm(const Insntype adrp)154ed0d50c3Schristos   aarch64_adrp_decode_imm(const Insntype adrp)
155ed0d50c3Schristos   {
156ed0d50c3Schristos     const int mask19 = (1 << 19) - 1;
157ed0d50c3Schristos     const int mask2 = 3;
158ed0d50c3Schristos     gold_assert(is_adrp(adrp));
159ed0d50c3Schristos     // 21-bit imm encoded in adrp.
160ed0d50c3Schristos     uint64_t imm = ((adrp >> 29) & mask2) | (((adrp >> 5) & mask19) << 2);
161ed0d50c3Schristos     // Retrieve msb of 21-bit-signed imm for sign extension.
162ed0d50c3Schristos     uint64_t msbt = (imm >> 20) & 1;
16306324dcfSchristos     // Real value is imm multiplied by 4k. Value now has 33-bit information.
164ed0d50c3Schristos     int64_t value = imm << 12;
165ed0d50c3Schristos     // Sign extend to 64-bit by repeating msbt 31 (64-33) times and merge it
166ed0d50c3Schristos     // with value.
167ed0d50c3Schristos     return ((((uint64_t)(1) << 32) - msbt) << 33) | value;
168ed0d50c3Schristos   }
169ed0d50c3Schristos 
170ed0d50c3Schristos   static bool
aarch64_b(const Insntype insn)171ed0d50c3Schristos   aarch64_b(const Insntype insn)
172ed0d50c3Schristos   { return (insn & 0xFC000000) == 0x14000000; }
173ed0d50c3Schristos 
174ed0d50c3Schristos   static bool
aarch64_bl(const Insntype insn)175ed0d50c3Schristos   aarch64_bl(const Insntype insn)
176ed0d50c3Schristos   { return (insn & 0xFC000000) == 0x94000000; }
177ed0d50c3Schristos 
178ed0d50c3Schristos   static bool
aarch64_blr(const Insntype insn)179ed0d50c3Schristos   aarch64_blr(const Insntype insn)
180ed0d50c3Schristos   { return (insn & 0xFFFFFC1F) == 0xD63F0000; }
181ed0d50c3Schristos 
182ed0d50c3Schristos   static bool
aarch64_br(const Insntype insn)183ed0d50c3Schristos   aarch64_br(const Insntype insn)
184ed0d50c3Schristos   { return (insn & 0xFFFFFC1F) == 0xD61F0000; }
185ed0d50c3Schristos 
186ed0d50c3Schristos   // All ld/st ops.  See C4-182 of the ARM ARM.  The encoding space for
187ed0d50c3Schristos   // LD_PCREL, LDST_RO, LDST_UI and LDST_UIMM cover prefetch ops.
188ed0d50c3Schristos   static bool
aarch64_ld(Insntype insn)189ed0d50c3Schristos   aarch64_ld(Insntype insn) { return aarch64_bit(insn, 22) == 1; }
190ed0d50c3Schristos 
191ed0d50c3Schristos   static bool
aarch64_ldst(Insntype insn)192ed0d50c3Schristos   aarch64_ldst(Insntype insn)
193ed0d50c3Schristos   { return (insn & 0x0a000000) == 0x08000000; }
194ed0d50c3Schristos 
195ed0d50c3Schristos   static bool
aarch64_ldst_ex(Insntype insn)196ed0d50c3Schristos   aarch64_ldst_ex(Insntype insn)
197ed0d50c3Schristos   { return (insn & 0x3f000000) == 0x08000000; }
198ed0d50c3Schristos 
199ed0d50c3Schristos   static bool
aarch64_ldst_pcrel(Insntype insn)200ed0d50c3Schristos   aarch64_ldst_pcrel(Insntype insn)
201ed0d50c3Schristos   { return (insn & 0x3b000000) == 0x18000000; }
202ed0d50c3Schristos 
203ed0d50c3Schristos   static bool
aarch64_ldst_nap(Insntype insn)204ed0d50c3Schristos   aarch64_ldst_nap(Insntype insn)
205ed0d50c3Schristos   { return (insn & 0x3b800000) == 0x28000000; }
206ed0d50c3Schristos 
207ed0d50c3Schristos   static bool
aarch64_ldstp_pi(Insntype insn)208ed0d50c3Schristos   aarch64_ldstp_pi(Insntype insn)
209ed0d50c3Schristos   { return (insn & 0x3b800000) == 0x28800000; }
210ed0d50c3Schristos 
211ed0d50c3Schristos   static bool
aarch64_ldstp_o(Insntype insn)212ed0d50c3Schristos   aarch64_ldstp_o(Insntype insn)
213ed0d50c3Schristos   { return (insn & 0x3b800000) == 0x29000000; }
214ed0d50c3Schristos 
215ed0d50c3Schristos   static bool
aarch64_ldstp_pre(Insntype insn)216ed0d50c3Schristos   aarch64_ldstp_pre(Insntype insn)
217ed0d50c3Schristos   { return (insn & 0x3b800000) == 0x29800000; }
218ed0d50c3Schristos 
219ed0d50c3Schristos   static bool
aarch64_ldst_ui(Insntype insn)220ed0d50c3Schristos   aarch64_ldst_ui(Insntype insn)
221ed0d50c3Schristos   { return (insn & 0x3b200c00) == 0x38000000; }
222ed0d50c3Schristos 
223ed0d50c3Schristos   static bool
aarch64_ldst_piimm(Insntype insn)224ed0d50c3Schristos   aarch64_ldst_piimm(Insntype insn)
225ed0d50c3Schristos   { return (insn & 0x3b200c00) == 0x38000400; }
226ed0d50c3Schristos 
227ed0d50c3Schristos   static bool
aarch64_ldst_u(Insntype insn)228ed0d50c3Schristos   aarch64_ldst_u(Insntype insn)
229ed0d50c3Schristos   { return (insn & 0x3b200c00) == 0x38000800; }
230ed0d50c3Schristos 
231ed0d50c3Schristos   static bool
aarch64_ldst_preimm(Insntype insn)232ed0d50c3Schristos   aarch64_ldst_preimm(Insntype insn)
233ed0d50c3Schristos   { return (insn & 0x3b200c00) == 0x38000c00; }
234ed0d50c3Schristos 
235ed0d50c3Schristos   static bool
aarch64_ldst_ro(Insntype insn)236ed0d50c3Schristos   aarch64_ldst_ro(Insntype insn)
237ed0d50c3Schristos   { return (insn & 0x3b200c00) == 0x38200800; }
238ed0d50c3Schristos 
239ed0d50c3Schristos   static bool
aarch64_ldst_uimm(Insntype insn)240ed0d50c3Schristos   aarch64_ldst_uimm(Insntype insn)
241ed0d50c3Schristos   { return (insn & 0x3b000000) == 0x39000000; }
242ed0d50c3Schristos 
243ed0d50c3Schristos   static bool
aarch64_ldst_simd_m(Insntype insn)244ed0d50c3Schristos   aarch64_ldst_simd_m(Insntype insn)
245ed0d50c3Schristos   { return (insn & 0xbfbf0000) == 0x0c000000; }
246ed0d50c3Schristos 
247ed0d50c3Schristos   static bool
aarch64_ldst_simd_m_pi(Insntype insn)248ed0d50c3Schristos   aarch64_ldst_simd_m_pi(Insntype insn)
249ed0d50c3Schristos   { return (insn & 0xbfa00000) == 0x0c800000; }
250ed0d50c3Schristos 
251ed0d50c3Schristos   static bool
aarch64_ldst_simd_s(Insntype insn)252ed0d50c3Schristos   aarch64_ldst_simd_s(Insntype insn)
253ed0d50c3Schristos   { return (insn & 0xbf9f0000) == 0x0d000000; }
254ed0d50c3Schristos 
255ed0d50c3Schristos   static bool
aarch64_ldst_simd_s_pi(Insntype insn)256ed0d50c3Schristos   aarch64_ldst_simd_s_pi(Insntype insn)
257ed0d50c3Schristos   { return (insn & 0xbf800000) == 0x0d800000; }
258ed0d50c3Schristos 
259ed0d50c3Schristos   // Classify an INSN if it is indeed a load/store. Return true if INSN is a
260ed0d50c3Schristos   // LD/ST instruction otherwise return false. For scalar LD/ST instructions
261ed0d50c3Schristos   // PAIR is FALSE, RT is returned and RT2 is set equal to RT. For LD/ST pair
262ed0d50c3Schristos   // instructions PAIR is TRUE, RT and RT2 are returned.
263ed0d50c3Schristos   static bool
aarch64_mem_op_p(Insntype insn,unsigned int * rt,unsigned int * rt2,bool * pair,bool * load)264ed0d50c3Schristos   aarch64_mem_op_p(Insntype insn, unsigned int *rt, unsigned int *rt2,
265ed0d50c3Schristos 		   bool *pair, bool *load)
266ed0d50c3Schristos   {
267ed0d50c3Schristos     uint32_t opcode;
268ed0d50c3Schristos     unsigned int r;
269ed0d50c3Schristos     uint32_t opc = 0;
270ed0d50c3Schristos     uint32_t v = 0;
271ed0d50c3Schristos     uint32_t opc_v = 0;
272ed0d50c3Schristos 
27306324dcfSchristos     /* Bail out quickly if INSN doesn't fall into the load-store
274ed0d50c3Schristos        encoding space.  */
275ed0d50c3Schristos     if (!aarch64_ldst (insn))
276ed0d50c3Schristos       return false;
277ed0d50c3Schristos 
278ed0d50c3Schristos     *pair = false;
279ed0d50c3Schristos     *load = false;
280ed0d50c3Schristos     if (aarch64_ldst_ex (insn))
281ed0d50c3Schristos       {
282ed0d50c3Schristos 	*rt = aarch64_rt (insn);
283ed0d50c3Schristos 	*rt2 = *rt;
284ed0d50c3Schristos 	if (aarch64_bit (insn, 21) == 1)
285ed0d50c3Schristos 	  {
286ed0d50c3Schristos 	    *pair = true;
287ed0d50c3Schristos 	    *rt2 = aarch64_rt2 (insn);
288ed0d50c3Schristos 	  }
289ed0d50c3Schristos 	*load = aarch64_ld (insn);
290ed0d50c3Schristos 	return true;
291ed0d50c3Schristos       }
292ed0d50c3Schristos     else if (aarch64_ldst_nap (insn)
293ed0d50c3Schristos 	     || aarch64_ldstp_pi (insn)
294ed0d50c3Schristos 	     || aarch64_ldstp_o (insn)
295ed0d50c3Schristos 	     || aarch64_ldstp_pre (insn))
296ed0d50c3Schristos       {
297ed0d50c3Schristos 	*pair = true;
298ed0d50c3Schristos 	*rt = aarch64_rt (insn);
299ed0d50c3Schristos 	*rt2 = aarch64_rt2 (insn);
300ed0d50c3Schristos 	*load = aarch64_ld (insn);
301ed0d50c3Schristos 	return true;
302ed0d50c3Schristos       }
303ed0d50c3Schristos     else if (aarch64_ldst_pcrel (insn)
304ed0d50c3Schristos 	     || aarch64_ldst_ui (insn)
305ed0d50c3Schristos 	     || aarch64_ldst_piimm (insn)
306ed0d50c3Schristos 	     || aarch64_ldst_u (insn)
307ed0d50c3Schristos 	     || aarch64_ldst_preimm (insn)
308ed0d50c3Schristos 	     || aarch64_ldst_ro (insn)
309ed0d50c3Schristos 	     || aarch64_ldst_uimm (insn))
310ed0d50c3Schristos       {
311ed0d50c3Schristos 	*rt = aarch64_rt (insn);
312ed0d50c3Schristos 	*rt2 = *rt;
313ed0d50c3Schristos 	if (aarch64_ldst_pcrel (insn))
314ed0d50c3Schristos 	  *load = true;
315ed0d50c3Schristos 	opc = aarch64_bits (insn, 22, 2);
316ed0d50c3Schristos 	v = aarch64_bit (insn, 26);
317ed0d50c3Schristos 	opc_v = opc | (v << 2);
318ed0d50c3Schristos 	*load =  (opc_v == 1 || opc_v == 2 || opc_v == 3
319ed0d50c3Schristos 		  || opc_v == 5 || opc_v == 7);
320ed0d50c3Schristos 	return true;
321ed0d50c3Schristos       }
322ed0d50c3Schristos     else if (aarch64_ldst_simd_m (insn)
323ed0d50c3Schristos 	     || aarch64_ldst_simd_m_pi (insn))
324ed0d50c3Schristos       {
325ed0d50c3Schristos 	*rt = aarch64_rt (insn);
326ed0d50c3Schristos 	*load = aarch64_bit (insn, 22);
327ed0d50c3Schristos 	opcode = (insn >> 12) & 0xf;
328ed0d50c3Schristos 	switch (opcode)
329ed0d50c3Schristos 	  {
330ed0d50c3Schristos 	  case 0:
331ed0d50c3Schristos 	  case 2:
332ed0d50c3Schristos 	    *rt2 = *rt + 3;
333ed0d50c3Schristos 	    break;
334ed0d50c3Schristos 
335ed0d50c3Schristos 	  case 4:
336ed0d50c3Schristos 	  case 6:
337ed0d50c3Schristos 	    *rt2 = *rt + 2;
338ed0d50c3Schristos 	    break;
339ed0d50c3Schristos 
340ed0d50c3Schristos 	  case 7:
341ed0d50c3Schristos 	    *rt2 = *rt;
342ed0d50c3Schristos 	    break;
343ed0d50c3Schristos 
344ed0d50c3Schristos 	  case 8:
345ed0d50c3Schristos 	  case 10:
346ed0d50c3Schristos 	    *rt2 = *rt + 1;
347ed0d50c3Schristos 	    break;
348ed0d50c3Schristos 
349ed0d50c3Schristos 	  default:
350ed0d50c3Schristos 	    return false;
351ed0d50c3Schristos 	  }
352ed0d50c3Schristos 	return true;
353ed0d50c3Schristos       }
354ed0d50c3Schristos     else if (aarch64_ldst_simd_s (insn)
355ed0d50c3Schristos 	     || aarch64_ldst_simd_s_pi (insn))
356ed0d50c3Schristos       {
357ed0d50c3Schristos 	*rt = aarch64_rt (insn);
358ed0d50c3Schristos 	r = (insn >> 21) & 1;
359ed0d50c3Schristos 	*load = aarch64_bit (insn, 22);
360ed0d50c3Schristos 	opcode = (insn >> 13) & 0x7;
361ed0d50c3Schristos 	switch (opcode)
362ed0d50c3Schristos 	  {
363ed0d50c3Schristos 	  case 0:
364ed0d50c3Schristos 	  case 2:
365ed0d50c3Schristos 	  case 4:
366ed0d50c3Schristos 	    *rt2 = *rt + r;
367ed0d50c3Schristos 	    break;
368ed0d50c3Schristos 
369ed0d50c3Schristos 	  case 1:
370ed0d50c3Schristos 	  case 3:
371ed0d50c3Schristos 	  case 5:
372ed0d50c3Schristos 	    *rt2 = *rt + (r == 0 ? 2 : 3);
373ed0d50c3Schristos 	    break;
374ed0d50c3Schristos 
375ed0d50c3Schristos 	  case 6:
376ed0d50c3Schristos 	    *rt2 = *rt + r;
377ed0d50c3Schristos 	    break;
378ed0d50c3Schristos 
379ed0d50c3Schristos 	  case 7:
380ed0d50c3Schristos 	    *rt2 = *rt + (r == 0 ? 2 : 3);
381ed0d50c3Schristos 	    break;
382ed0d50c3Schristos 
383ed0d50c3Schristos 	  default:
384ed0d50c3Schristos 	    return false;
385ed0d50c3Schristos 	  }
386ed0d50c3Schristos 	return true;
387ed0d50c3Schristos       }
388ed0d50c3Schristos     return false;
389ed0d50c3Schristos   }  // End of "aarch64_mem_op_p".
390ed0d50c3Schristos 
391ed0d50c3Schristos   // Return true if INSN is mac insn.
392ed0d50c3Schristos   static bool
aarch64_mac(Insntype insn)393ed0d50c3Schristos   aarch64_mac(Insntype insn)
394ed0d50c3Schristos   { return (insn & 0xff000000) == 0x9b000000; }
395ed0d50c3Schristos 
396ed0d50c3Schristos   // Return true if INSN is multiply-accumulate.
397ed0d50c3Schristos   // (This is similar to implementaton in elfnn-aarch64.c.)
398ed0d50c3Schristos   static bool
aarch64_mlxl(Insntype insn)399ed0d50c3Schristos   aarch64_mlxl(Insntype insn)
400ed0d50c3Schristos   {
401ed0d50c3Schristos     uint32_t op31 = aarch64_op31(insn);
402ed0d50c3Schristos     if (aarch64_mac(insn)
403ed0d50c3Schristos 	&& (op31 == 0 || op31 == 1 || op31 == 5)
404ed0d50c3Schristos 	/* Exclude MUL instructions which are encoded as a multiple-accumulate
405ed0d50c3Schristos 	   with RA = XZR.  */
406ed0d50c3Schristos 	&& aarch64_ra(insn) != AARCH64_ZR)
407ed0d50c3Schristos       {
408ed0d50c3Schristos 	return true;
409ed0d50c3Schristos       }
410ed0d50c3Schristos     return false;
411ed0d50c3Schristos   }
412ed0d50c3Schristos };  // End of "AArch64_insn_utilities".
413ed0d50c3Schristos 
414ed0d50c3Schristos 
415ed0d50c3Schristos // Insn length in byte.
416ed0d50c3Schristos 
417ed0d50c3Schristos template<bool big_endian>
418ed0d50c3Schristos const int AArch64_insn_utilities<big_endian>::BYTES_PER_INSN = 4;
419ed0d50c3Schristos 
420ed0d50c3Schristos 
421ed0d50c3Schristos // Zero register encoding - 31.
422ed0d50c3Schristos 
423ed0d50c3Schristos template<bool big_endian>
424ed0d50c3Schristos const unsigned int AArch64_insn_utilities<big_endian>::AARCH64_ZR = 0x1f;
425ed0d50c3Schristos 
426ed0d50c3Schristos 
427ed0d50c3Schristos // Output_data_got_aarch64 class.
428ed0d50c3Schristos 
429ed0d50c3Schristos template<int size, bool big_endian>
430ed0d50c3Schristos class Output_data_got_aarch64 : public Output_data_got<size, big_endian>
431ed0d50c3Schristos {
432ed0d50c3Schristos  public:
433ed0d50c3Schristos   typedef typename elfcpp::Elf_types<size>::Elf_Addr Valtype;
Output_data_got_aarch64(Symbol_table * symtab,Layout * layout)434ed0d50c3Schristos   Output_data_got_aarch64(Symbol_table* symtab, Layout* layout)
435ed0d50c3Schristos     : Output_data_got<size, big_endian>(),
436ed0d50c3Schristos       symbol_table_(symtab), layout_(layout)
437ed0d50c3Schristos   { }
438ed0d50c3Schristos 
439ed0d50c3Schristos   // Add a static entry for the GOT entry at OFFSET.  GSYM is a global
440ed0d50c3Schristos   // symbol and R_TYPE is the code of a dynamic relocation that needs to be
441ed0d50c3Schristos   // applied in a static link.
442ed0d50c3Schristos   void
add_static_reloc(unsigned int got_offset,unsigned int r_type,Symbol * gsym)443ed0d50c3Schristos   add_static_reloc(unsigned int got_offset, unsigned int r_type, Symbol* gsym)
444ed0d50c3Schristos   { this->static_relocs_.push_back(Static_reloc(got_offset, r_type, gsym)); }
445ed0d50c3Schristos 
446ed0d50c3Schristos 
447ed0d50c3Schristos   // Add a static reloc for the GOT entry at OFFSET.  RELOBJ is an object
448ed0d50c3Schristos   // defining a local symbol with INDEX.  R_TYPE is the code of a dynamic
449ed0d50c3Schristos   // relocation that needs to be applied in a static link.
450ed0d50c3Schristos   void
add_static_reloc(unsigned int got_offset,unsigned int r_type,Sized_relobj_file<size,big_endian> * relobj,unsigned int index)451ed0d50c3Schristos   add_static_reloc(unsigned int got_offset, unsigned int r_type,
452ed0d50c3Schristos 		   Sized_relobj_file<size, big_endian>* relobj,
453ed0d50c3Schristos 		   unsigned int index)
454ed0d50c3Schristos   {
455ed0d50c3Schristos     this->static_relocs_.push_back(Static_reloc(got_offset, r_type, relobj,
456ed0d50c3Schristos 						index));
457ed0d50c3Schristos   }
458ed0d50c3Schristos 
459ed0d50c3Schristos 
460ed0d50c3Schristos  protected:
461ed0d50c3Schristos   // Write out the GOT table.
462ed0d50c3Schristos   void
do_write(Output_file * of)463ed0d50c3Schristos   do_write(Output_file* of) {
464ed0d50c3Schristos     // The first entry in the GOT is the address of the .dynamic section.
465ed0d50c3Schristos     gold_assert(this->data_size() >= size / 8);
466ed0d50c3Schristos     Output_section* dynamic = this->layout_->dynamic_section();
467ed0d50c3Schristos     Valtype dynamic_addr = dynamic == NULL ? 0 : dynamic->address();
468ed0d50c3Schristos     this->replace_constant(0, dynamic_addr);
469ed0d50c3Schristos     Output_data_got<size, big_endian>::do_write(of);
470ed0d50c3Schristos 
471ed0d50c3Schristos     // Handling static relocs
472ed0d50c3Schristos     if (this->static_relocs_.empty())
473ed0d50c3Schristos       return;
474ed0d50c3Schristos 
475ed0d50c3Schristos     typedef typename elfcpp::Elf_types<size>::Elf_Addr AArch64_address;
476ed0d50c3Schristos 
477ed0d50c3Schristos     gold_assert(parameters->doing_static_link());
478ed0d50c3Schristos     const off_t offset = this->offset();
479ed0d50c3Schristos     const section_size_type oview_size =
480ed0d50c3Schristos       convert_to_section_size_type(this->data_size());
481ed0d50c3Schristos     unsigned char* const oview = of->get_output_view(offset, oview_size);
482ed0d50c3Schristos 
483ed0d50c3Schristos     Output_segment* tls_segment = this->layout_->tls_segment();
484ed0d50c3Schristos     gold_assert(tls_segment != NULL);
485ed0d50c3Schristos 
486ed0d50c3Schristos     AArch64_address aligned_tcb_address =
487ed0d50c3Schristos       align_address(Target_aarch64<size, big_endian>::TCB_SIZE,
488ed0d50c3Schristos 		    tls_segment->maximum_alignment());
489ed0d50c3Schristos 
490ed0d50c3Schristos     for (size_t i = 0; i < this->static_relocs_.size(); ++i)
491ed0d50c3Schristos       {
492ed0d50c3Schristos 	Static_reloc& reloc(this->static_relocs_[i]);
493ed0d50c3Schristos 	AArch64_address value;
494ed0d50c3Schristos 
495ed0d50c3Schristos 	if (!reloc.symbol_is_global())
496ed0d50c3Schristos 	  {
497ed0d50c3Schristos 	    Sized_relobj_file<size, big_endian>* object = reloc.relobj();
498ed0d50c3Schristos 	    const Symbol_value<size>* psymval =
499ed0d50c3Schristos 	      reloc.relobj()->local_symbol(reloc.index());
500ed0d50c3Schristos 
501ed0d50c3Schristos 	    // We are doing static linking.  Issue an error and skip this
502ed0d50c3Schristos 	    // relocation if the symbol is undefined or in a discarded_section.
503ed0d50c3Schristos 	    bool is_ordinary;
504ed0d50c3Schristos 	    unsigned int shndx = psymval->input_shndx(&is_ordinary);
505ed0d50c3Schristos 	    if ((shndx == elfcpp::SHN_UNDEF)
506ed0d50c3Schristos 		|| (is_ordinary
507ed0d50c3Schristos 		    && shndx != elfcpp::SHN_UNDEF
508ed0d50c3Schristos 		    && !object->is_section_included(shndx)
509ed0d50c3Schristos 		    && !this->symbol_table_->is_section_folded(object, shndx)))
510ed0d50c3Schristos 	      {
511ed0d50c3Schristos 		gold_error(_("undefined or discarded local symbol %u from "
512ed0d50c3Schristos 			     " object %s in GOT"),
513ed0d50c3Schristos 			   reloc.index(), reloc.relobj()->name().c_str());
514ed0d50c3Schristos 		continue;
515ed0d50c3Schristos 	      }
516ed0d50c3Schristos 	    value = psymval->value(object, 0);
517ed0d50c3Schristos 	  }
518ed0d50c3Schristos 	else
519ed0d50c3Schristos 	  {
520ed0d50c3Schristos 	    const Symbol* gsym = reloc.symbol();
521ed0d50c3Schristos 	    gold_assert(gsym != NULL);
522ed0d50c3Schristos 	    if (gsym->is_forwarder())
523ed0d50c3Schristos 	      gsym = this->symbol_table_->resolve_forwards(gsym);
524ed0d50c3Schristos 
525ed0d50c3Schristos 	    // We are doing static linking.  Issue an error and skip this
526ed0d50c3Schristos 	    // relocation if the symbol is undefined or in a discarded_section
527ed0d50c3Schristos 	    // unless it is a weakly_undefined symbol.
528ed0d50c3Schristos 	    if ((gsym->is_defined_in_discarded_section()
529ed0d50c3Schristos 		 || gsym->is_undefined())
530ed0d50c3Schristos 		&& !gsym->is_weak_undefined())
531ed0d50c3Schristos 	      {
532ed0d50c3Schristos 		gold_error(_("undefined or discarded symbol %s in GOT"),
533ed0d50c3Schristos 			   gsym->name());
534ed0d50c3Schristos 		continue;
535ed0d50c3Schristos 	      }
536ed0d50c3Schristos 
537ed0d50c3Schristos 	    if (!gsym->is_weak_undefined())
538ed0d50c3Schristos 	      {
539ed0d50c3Schristos 		const Sized_symbol<size>* sym =
540ed0d50c3Schristos 		  static_cast<const Sized_symbol<size>*>(gsym);
541ed0d50c3Schristos 		value = sym->value();
542ed0d50c3Schristos 	      }
543ed0d50c3Schristos 	    else
544ed0d50c3Schristos 	      value = 0;
545ed0d50c3Schristos 	  }
546ed0d50c3Schristos 
547ed0d50c3Schristos 	unsigned got_offset = reloc.got_offset();
548ed0d50c3Schristos 	gold_assert(got_offset < oview_size);
549ed0d50c3Schristos 
550ed0d50c3Schristos 	typedef typename elfcpp::Swap<size, big_endian>::Valtype Valtype;
551ed0d50c3Schristos 	Valtype* wv = reinterpret_cast<Valtype*>(oview + got_offset);
552ed0d50c3Schristos 	Valtype x;
553ed0d50c3Schristos 	switch (reloc.r_type())
554ed0d50c3Schristos 	  {
555ed0d50c3Schristos 	  case elfcpp::R_AARCH64_TLS_DTPREL64:
556ed0d50c3Schristos 	    x = value;
557ed0d50c3Schristos 	    break;
558ed0d50c3Schristos 	  case elfcpp::R_AARCH64_TLS_TPREL64:
559ed0d50c3Schristos 	    x = value + aligned_tcb_address;
560ed0d50c3Schristos 	    break;
561ed0d50c3Schristos 	  default:
562ed0d50c3Schristos 	    gold_unreachable();
563ed0d50c3Schristos 	  }
564ed0d50c3Schristos 	elfcpp::Swap<size, big_endian>::writeval(wv, x);
565ed0d50c3Schristos       }
566ed0d50c3Schristos 
567ed0d50c3Schristos     of->write_output_view(offset, oview_size, oview);
568ed0d50c3Schristos   }
569ed0d50c3Schristos 
570ed0d50c3Schristos  private:
571ed0d50c3Schristos   // Symbol table of the output object.
572ed0d50c3Schristos   Symbol_table* symbol_table_;
573ed0d50c3Schristos   // A pointer to the Layout class, so that we can find the .dynamic
574ed0d50c3Schristos   // section when we write out the GOT section.
575ed0d50c3Schristos   Layout* layout_;
576ed0d50c3Schristos 
577ed0d50c3Schristos   // This class represent dynamic relocations that need to be applied by
578ed0d50c3Schristos   // gold because we are using TLS relocations in a static link.
579ed0d50c3Schristos   class Static_reloc
580ed0d50c3Schristos   {
581ed0d50c3Schristos    public:
Static_reloc(unsigned int got_offset,unsigned int r_type,Symbol * gsym)582ed0d50c3Schristos     Static_reloc(unsigned int got_offset, unsigned int r_type, Symbol* gsym)
583ed0d50c3Schristos       : got_offset_(got_offset), r_type_(r_type), symbol_is_global_(true)
584ed0d50c3Schristos     { this->u_.global.symbol = gsym; }
585ed0d50c3Schristos 
Static_reloc(unsigned int got_offset,unsigned int r_type,Sized_relobj_file<size,big_endian> * relobj,unsigned int index)586ed0d50c3Schristos     Static_reloc(unsigned int got_offset, unsigned int r_type,
587ed0d50c3Schristos 	  Sized_relobj_file<size, big_endian>* relobj, unsigned int index)
588ed0d50c3Schristos       : got_offset_(got_offset), r_type_(r_type), symbol_is_global_(false)
589ed0d50c3Schristos     {
590ed0d50c3Schristos       this->u_.local.relobj = relobj;
591ed0d50c3Schristos       this->u_.local.index = index;
592ed0d50c3Schristos     }
593ed0d50c3Schristos 
594ed0d50c3Schristos     // Return the GOT offset.
595ed0d50c3Schristos     unsigned int
got_offset() const596ed0d50c3Schristos     got_offset() const
597ed0d50c3Schristos     { return this->got_offset_; }
598ed0d50c3Schristos 
599ed0d50c3Schristos     // Relocation type.
600ed0d50c3Schristos     unsigned int
r_type() const601ed0d50c3Schristos     r_type() const
602ed0d50c3Schristos     { return this->r_type_; }
603ed0d50c3Schristos 
604ed0d50c3Schristos     // Whether the symbol is global or not.
605ed0d50c3Schristos     bool
symbol_is_global() const606ed0d50c3Schristos     symbol_is_global() const
607ed0d50c3Schristos     { return this->symbol_is_global_; }
608ed0d50c3Schristos 
609ed0d50c3Schristos     // For a relocation against a global symbol, the global symbol.
610ed0d50c3Schristos     Symbol*
symbol() const611ed0d50c3Schristos     symbol() const
612ed0d50c3Schristos     {
613ed0d50c3Schristos       gold_assert(this->symbol_is_global_);
614ed0d50c3Schristos       return this->u_.global.symbol;
615ed0d50c3Schristos     }
616ed0d50c3Schristos 
617ed0d50c3Schristos     // For a relocation against a local symbol, the defining object.
618ed0d50c3Schristos     Sized_relobj_file<size, big_endian>*
relobj() const619ed0d50c3Schristos     relobj() const
620ed0d50c3Schristos     {
621ed0d50c3Schristos       gold_assert(!this->symbol_is_global_);
622ed0d50c3Schristos       return this->u_.local.relobj;
623ed0d50c3Schristos     }
624ed0d50c3Schristos 
625ed0d50c3Schristos     // For a relocation against a local symbol, the local symbol index.
626ed0d50c3Schristos     unsigned int
index() const627ed0d50c3Schristos     index() const
628ed0d50c3Schristos     {
629ed0d50c3Schristos       gold_assert(!this->symbol_is_global_);
630ed0d50c3Schristos       return this->u_.local.index;
631ed0d50c3Schristos     }
632ed0d50c3Schristos 
633ed0d50c3Schristos    private:
634ed0d50c3Schristos     // GOT offset of the entry to which this relocation is applied.
635ed0d50c3Schristos     unsigned int got_offset_;
636ed0d50c3Schristos     // Type of relocation.
637ed0d50c3Schristos     unsigned int r_type_;
638ed0d50c3Schristos     // Whether this relocation is against a global symbol.
639ed0d50c3Schristos     bool symbol_is_global_;
640ed0d50c3Schristos     // A global or local symbol.
641ed0d50c3Schristos     union
642ed0d50c3Schristos     {
643ed0d50c3Schristos       struct
644ed0d50c3Schristos       {
645ed0d50c3Schristos 	// For a global symbol, the symbol itself.
646ed0d50c3Schristos 	Symbol* symbol;
647ed0d50c3Schristos       } global;
648ed0d50c3Schristos       struct
649ed0d50c3Schristos       {
650ed0d50c3Schristos 	// For a local symbol, the object defining the symbol.
651ed0d50c3Schristos 	Sized_relobj_file<size, big_endian>* relobj;
652ed0d50c3Schristos 	// For a local symbol, the symbol index.
653ed0d50c3Schristos 	unsigned int index;
654ed0d50c3Schristos       } local;
655ed0d50c3Schristos     } u_;
656ed0d50c3Schristos   };  // End of inner class Static_reloc
657ed0d50c3Schristos 
658ed0d50c3Schristos   std::vector<Static_reloc> static_relocs_;
659ed0d50c3Schristos };  // End of Output_data_got_aarch64
660ed0d50c3Schristos 
661ed0d50c3Schristos 
662ed0d50c3Schristos template<int size, bool big_endian>
663ed0d50c3Schristos class AArch64_input_section;
664ed0d50c3Schristos 
665ed0d50c3Schristos 
666ed0d50c3Schristos template<int size, bool big_endian>
667ed0d50c3Schristos class AArch64_output_section;
668ed0d50c3Schristos 
669ed0d50c3Schristos 
670ed0d50c3Schristos template<int size, bool big_endian>
671ed0d50c3Schristos class AArch64_relobj;
672ed0d50c3Schristos 
673ed0d50c3Schristos 
674ed0d50c3Schristos // Stub type enum constants.
675ed0d50c3Schristos 
676ed0d50c3Schristos enum
677ed0d50c3Schristos {
678ed0d50c3Schristos   ST_NONE = 0,
679ed0d50c3Schristos 
680ed0d50c3Schristos   // Using adrp/add pair, 4 insns (including alignment) without mem access,
681ed0d50c3Schristos   // the fastest stub. This has a limited jump distance, which is tested by
682ed0d50c3Schristos   // aarch64_valid_for_adrp_p.
683ed0d50c3Schristos   ST_ADRP_BRANCH = 1,
684ed0d50c3Schristos 
685ed0d50c3Schristos   // Using ldr-absolute-address/br-register, 4 insns with 1 mem access,
686ed0d50c3Schristos   // unlimited in jump distance.
687ed0d50c3Schristos   ST_LONG_BRANCH_ABS = 2,
688ed0d50c3Schristos 
689ed0d50c3Schristos   // Using ldr/calculate-pcrel/jump, 8 insns (including alignment) with 1
690ed0d50c3Schristos   // mem access, slowest one. Only used in position independent executables.
691ed0d50c3Schristos   ST_LONG_BRANCH_PCREL = 3,
692ed0d50c3Schristos 
693ed0d50c3Schristos   // Stub for erratum 843419 handling.
694ed0d50c3Schristos   ST_E_843419 = 4,
695ed0d50c3Schristos 
696ed0d50c3Schristos   // Stub for erratum 835769 handling.
697ed0d50c3Schristos   ST_E_835769 = 5,
698ed0d50c3Schristos 
699ed0d50c3Schristos   // Number of total stub types.
700ed0d50c3Schristos   ST_NUMBER = 6
701ed0d50c3Schristos };
702ed0d50c3Schristos 
703ed0d50c3Schristos 
704ed0d50c3Schristos // Struct that wraps insns for a particular stub. All stub templates are
705ed0d50c3Schristos // created/initialized as constants by Stub_template_repertoire.
706ed0d50c3Schristos 
707ed0d50c3Schristos template<bool big_endian>
708ed0d50c3Schristos struct Stub_template
709ed0d50c3Schristos {
710ed0d50c3Schristos   const typename AArch64_insn_utilities<big_endian>::Insntype* insns;
711ed0d50c3Schristos   const int insn_num;
712ed0d50c3Schristos };
713ed0d50c3Schristos 
714ed0d50c3Schristos 
715ed0d50c3Schristos // Simple singleton class that creates/initializes/stores all types of stub
716ed0d50c3Schristos // templates.
717ed0d50c3Schristos 
718ed0d50c3Schristos template<bool big_endian>
719ed0d50c3Schristos class Stub_template_repertoire
720ed0d50c3Schristos {
721ed0d50c3Schristos public:
722ed0d50c3Schristos   typedef typename AArch64_insn_utilities<big_endian>::Insntype Insntype;
723ed0d50c3Schristos 
724ed0d50c3Schristos   // Single static method to get stub template for a given stub type.
725ed0d50c3Schristos   static const Stub_template<big_endian>*
get_stub_template(int type)726ed0d50c3Schristos   get_stub_template(int type)
727ed0d50c3Schristos   {
728ed0d50c3Schristos     static Stub_template_repertoire<big_endian> singleton;
729ed0d50c3Schristos     return singleton.stub_templates_[type];
730ed0d50c3Schristos   }
731ed0d50c3Schristos 
732ed0d50c3Schristos private:
733ed0d50c3Schristos   // Constructor - creates/initializes all stub templates.
734ed0d50c3Schristos   Stub_template_repertoire();
~Stub_template_repertoire()735ed0d50c3Schristos   ~Stub_template_repertoire()
736ed0d50c3Schristos   { }
737ed0d50c3Schristos 
738ed0d50c3Schristos   // Disallowing copy ctor and copy assignment operator.
739ed0d50c3Schristos   Stub_template_repertoire(Stub_template_repertoire&);
740ed0d50c3Schristos   Stub_template_repertoire& operator=(Stub_template_repertoire&);
741ed0d50c3Schristos 
742ed0d50c3Schristos   // Data that stores all insn templates.
743ed0d50c3Schristos   const Stub_template<big_endian>* stub_templates_[ST_NUMBER];
744ed0d50c3Schristos };  // End of "class Stub_template_repertoire".
745ed0d50c3Schristos 
746ed0d50c3Schristos 
747ed0d50c3Schristos // Constructor - creates/initilizes all stub templates.
748ed0d50c3Schristos 
749ed0d50c3Schristos template<bool big_endian>
Stub_template_repertoire()750ed0d50c3Schristos Stub_template_repertoire<big_endian>::Stub_template_repertoire()
751ed0d50c3Schristos {
752ed0d50c3Schristos   // Insn array definitions.
753ed0d50c3Schristos   const static Insntype ST_NONE_INSNS[] = {};
754ed0d50c3Schristos 
755ed0d50c3Schristos   const static Insntype ST_ADRP_BRANCH_INSNS[] =
756ed0d50c3Schristos     {
757ed0d50c3Schristos       0x90000010,	/*	adrp	ip0, X		   */
758ed0d50c3Schristos 			/*	  ADR_PREL_PG_HI21(X)	   */
759ed0d50c3Schristos       0x91000210,	/*	add	ip0, ip0, :lo12:X  */
760ed0d50c3Schristos 			/*	  ADD_ABS_LO12_NC(X)	   */
761ed0d50c3Schristos       0xd61f0200,	/*	br	ip0		   */
762ed0d50c3Schristos       0x00000000,	/*	alignment padding	   */
763ed0d50c3Schristos     };
764ed0d50c3Schristos 
765ed0d50c3Schristos   const static Insntype ST_LONG_BRANCH_ABS_INSNS[] =
766ed0d50c3Schristos     {
767ed0d50c3Schristos       0x58000050,	/*	ldr   ip0, 0x8		   */
768ed0d50c3Schristos       0xd61f0200,	/*	br    ip0		   */
769ed0d50c3Schristos       0x00000000,	/*	address field		   */
770ed0d50c3Schristos       0x00000000,	/*	address fields		   */
771ed0d50c3Schristos     };
772ed0d50c3Schristos 
773ed0d50c3Schristos   const static Insntype ST_LONG_BRANCH_PCREL_INSNS[] =
774ed0d50c3Schristos     {
775ed0d50c3Schristos       0x58000090,	/*	ldr   ip0, 0x10            */
776ed0d50c3Schristos       0x10000011,	/*	adr   ip1, #0		   */
777ed0d50c3Schristos       0x8b110210,	/*	add   ip0, ip0, ip1	   */
778ed0d50c3Schristos       0xd61f0200,	/*	br    ip0		   */
779ed0d50c3Schristos       0x00000000,	/*	address field		   */
780ed0d50c3Schristos       0x00000000,	/*	address field		   */
781ed0d50c3Schristos       0x00000000,	/*	alignment padding	   */
782ed0d50c3Schristos       0x00000000,	/*	alignment padding	   */
783ed0d50c3Schristos     };
784ed0d50c3Schristos 
785ed0d50c3Schristos   const static Insntype ST_E_843419_INSNS[] =
786ed0d50c3Schristos     {
787ed0d50c3Schristos       0x00000000,    /* Placeholder for erratum insn. */
788ed0d50c3Schristos       0x14000000,    /* b <label> */
789ed0d50c3Schristos     };
790ed0d50c3Schristos 
79106324dcfSchristos   // ST_E_835769 has the same stub template as ST_E_843419
79206324dcfSchristos   // but we reproduce the array here so that the sizeof
79306324dcfSchristos   // expressions in install_insn_template will work.
79406324dcfSchristos   const static Insntype ST_E_835769_INSNS[] =
79506324dcfSchristos     {
79606324dcfSchristos       0x00000000,    /* Placeholder for erratum insn. */
79706324dcfSchristos       0x14000000,    /* b <label> */
79806324dcfSchristos     };
799ed0d50c3Schristos 
800ed0d50c3Schristos #define install_insn_template(T) \
801ed0d50c3Schristos   const static Stub_template<big_endian> template_##T = {  \
802ed0d50c3Schristos     T##_INSNS, sizeof(T##_INSNS) / sizeof(T##_INSNS[0]) }; \
803ed0d50c3Schristos   this->stub_templates_[T] = &template_##T
804ed0d50c3Schristos 
805ed0d50c3Schristos   install_insn_template(ST_NONE);
806ed0d50c3Schristos   install_insn_template(ST_ADRP_BRANCH);
807ed0d50c3Schristos   install_insn_template(ST_LONG_BRANCH_ABS);
808ed0d50c3Schristos   install_insn_template(ST_LONG_BRANCH_PCREL);
809ed0d50c3Schristos   install_insn_template(ST_E_843419);
810ed0d50c3Schristos   install_insn_template(ST_E_835769);
811ed0d50c3Schristos 
812ed0d50c3Schristos #undef install_insn_template
813ed0d50c3Schristos }
814ed0d50c3Schristos 
815ed0d50c3Schristos 
816ed0d50c3Schristos // Base class for stubs.
817ed0d50c3Schristos 
818ed0d50c3Schristos template<int size, bool big_endian>
819ed0d50c3Schristos class Stub_base
820ed0d50c3Schristos {
821ed0d50c3Schristos public:
822ed0d50c3Schristos   typedef typename elfcpp::Elf_types<size>::Elf_Addr AArch64_address;
823ed0d50c3Schristos   typedef typename AArch64_insn_utilities<big_endian>::Insntype Insntype;
824ed0d50c3Schristos 
825ed0d50c3Schristos   static const AArch64_address invalid_address =
826ed0d50c3Schristos     static_cast<AArch64_address>(-1);
827ed0d50c3Schristos 
828ed0d50c3Schristos   static const section_offset_type invalid_offset =
829ed0d50c3Schristos     static_cast<section_offset_type>(-1);
830ed0d50c3Schristos 
Stub_base(int type)831ed0d50c3Schristos   Stub_base(int type)
832ed0d50c3Schristos     : destination_address_(invalid_address),
833ed0d50c3Schristos       offset_(invalid_offset),
834ed0d50c3Schristos       type_(type)
835ed0d50c3Schristos   {}
836ed0d50c3Schristos 
~Stub_base()837ed0d50c3Schristos   ~Stub_base()
838ed0d50c3Schristos   {}
839ed0d50c3Schristos 
840ed0d50c3Schristos   // Get stub type.
841ed0d50c3Schristos   int
type() const842ed0d50c3Schristos   type() const
843ed0d50c3Schristos   { return this->type_; }
844ed0d50c3Schristos 
845ed0d50c3Schristos   // Get stub template that provides stub insn information.
846ed0d50c3Schristos   const Stub_template<big_endian>*
stub_template() const847ed0d50c3Schristos   stub_template() const
848ed0d50c3Schristos   {
849ed0d50c3Schristos     return Stub_template_repertoire<big_endian>::
850ed0d50c3Schristos       get_stub_template(this->type());
851ed0d50c3Schristos   }
852ed0d50c3Schristos 
853ed0d50c3Schristos   // Get destination address.
854ed0d50c3Schristos   AArch64_address
destination_address() const855ed0d50c3Schristos   destination_address() const
856ed0d50c3Schristos   {
857ed0d50c3Schristos     gold_assert(this->destination_address_ != this->invalid_address);
858ed0d50c3Schristos     return this->destination_address_;
859ed0d50c3Schristos   }
860ed0d50c3Schristos 
861ed0d50c3Schristos   // Set destination address.
862ed0d50c3Schristos   void
set_destination_address(AArch64_address address)863ed0d50c3Schristos   set_destination_address(AArch64_address address)
864ed0d50c3Schristos   {
865ed0d50c3Schristos     gold_assert(address != this->invalid_address);
866ed0d50c3Schristos     this->destination_address_ = address;
867ed0d50c3Schristos   }
868ed0d50c3Schristos 
869ed0d50c3Schristos   // Reset the destination address.
870ed0d50c3Schristos   void
reset_destination_address()871ed0d50c3Schristos   reset_destination_address()
872ed0d50c3Schristos   { this->destination_address_ = this->invalid_address; }
873ed0d50c3Schristos 
874ed0d50c3Schristos   // Get offset of code stub. For Reloc_stub, it is the offset from the
875ed0d50c3Schristos   // beginning of its containing stub table; for Erratum_stub, it is the offset
876ed0d50c3Schristos   // from the end of reloc_stubs.
877ed0d50c3Schristos   section_offset_type
offset() const878ed0d50c3Schristos   offset() const
879ed0d50c3Schristos   {
880ed0d50c3Schristos     gold_assert(this->offset_ != this->invalid_offset);
881ed0d50c3Schristos     return this->offset_;
882ed0d50c3Schristos   }
883ed0d50c3Schristos 
884ed0d50c3Schristos   // Set stub offset.
885ed0d50c3Schristos   void
set_offset(section_offset_type offset)886ed0d50c3Schristos   set_offset(section_offset_type offset)
887ed0d50c3Schristos   { this->offset_ = offset; }
888ed0d50c3Schristos 
889ed0d50c3Schristos   // Return the stub insn.
890ed0d50c3Schristos   const Insntype*
insns() const891ed0d50c3Schristos   insns() const
892ed0d50c3Schristos   { return this->stub_template()->insns; }
893ed0d50c3Schristos 
894ed0d50c3Schristos   // Return num of stub insns.
895ed0d50c3Schristos   unsigned int
insn_num() const896ed0d50c3Schristos   insn_num() const
897ed0d50c3Schristos   { return this->stub_template()->insn_num; }
898ed0d50c3Schristos 
899ed0d50c3Schristos   // Get size of the stub.
900ed0d50c3Schristos   int
stub_size() const901ed0d50c3Schristos   stub_size() const
902ed0d50c3Schristos   {
903ed0d50c3Schristos     return this->insn_num() *
904ed0d50c3Schristos       AArch64_insn_utilities<big_endian>::BYTES_PER_INSN;
905ed0d50c3Schristos   }
906ed0d50c3Schristos 
907ed0d50c3Schristos   // Write stub to output file.
908ed0d50c3Schristos   void
write(unsigned char * view,section_size_type view_size)909ed0d50c3Schristos   write(unsigned char* view, section_size_type view_size)
910ed0d50c3Schristos   { this->do_write(view, view_size); }
911ed0d50c3Schristos 
912ed0d50c3Schristos protected:
913ed0d50c3Schristos   // Abstract method to be implemented by sub-classes.
914ed0d50c3Schristos   virtual void
915ed0d50c3Schristos   do_write(unsigned char*, section_size_type) = 0;
916ed0d50c3Schristos 
917ed0d50c3Schristos private:
918ed0d50c3Schristos   // The last insn of a stub is a jump to destination insn. This field records
919ed0d50c3Schristos   // the destination address.
920ed0d50c3Schristos   AArch64_address destination_address_;
921ed0d50c3Schristos   // The stub offset. Note this has difference interpretations between an
922ed0d50c3Schristos   // Reloc_stub and an Erratum_stub. For Reloc_stub this is the offset from the
923ed0d50c3Schristos   // beginning of the containing stub_table, whereas for Erratum_stub, this is
924ed0d50c3Schristos   // the offset from the end of reloc_stubs.
925ed0d50c3Schristos   section_offset_type offset_;
926ed0d50c3Schristos   // Stub type.
927ed0d50c3Schristos   const int type_;
928ed0d50c3Schristos };  // End of "Stub_base".
929ed0d50c3Schristos 
930ed0d50c3Schristos 
931ed0d50c3Schristos // Erratum stub class. An erratum stub differs from a reloc stub in that for
932ed0d50c3Schristos // each erratum occurrence, we generate an erratum stub. We never share erratum
93306324dcfSchristos // stubs, whereas for reloc stubs, different branch insns share a single reloc
934ed0d50c3Schristos // stub as long as the branch targets are the same. (More to the point, reloc
935ed0d50c3Schristos // stubs can be shared because they're used to reach a specific target, whereas
936ed0d50c3Schristos // erratum stubs branch back to the original control flow.)
937ed0d50c3Schristos 
938ed0d50c3Schristos template<int size, bool big_endian>
939ed0d50c3Schristos class Erratum_stub : public Stub_base<size, big_endian>
940ed0d50c3Schristos {
941ed0d50c3Schristos public:
942ed0d50c3Schristos   typedef AArch64_relobj<size, big_endian> The_aarch64_relobj;
943ed0d50c3Schristos   typedef typename elfcpp::Elf_types<size>::Elf_Addr AArch64_address;
944ed0d50c3Schristos   typedef AArch64_insn_utilities<big_endian> Insn_utilities;
945ed0d50c3Schristos   typedef typename AArch64_insn_utilities<big_endian>::Insntype Insntype;
946ed0d50c3Schristos 
947ed0d50c3Schristos   static const int STUB_ADDR_ALIGN;
948ed0d50c3Schristos 
949ed0d50c3Schristos   static const Insntype invalid_insn = static_cast<Insntype>(-1);
950ed0d50c3Schristos 
Erratum_stub(The_aarch64_relobj * relobj,int type,unsigned shndx,unsigned int sh_offset)951ed0d50c3Schristos   Erratum_stub(The_aarch64_relobj* relobj, int type,
952ed0d50c3Schristos 	       unsigned shndx, unsigned int sh_offset)
953ed0d50c3Schristos     : Stub_base<size, big_endian>(type), relobj_(relobj),
954ed0d50c3Schristos       shndx_(shndx), sh_offset_(sh_offset),
955ed0d50c3Schristos       erratum_insn_(invalid_insn),
956ed0d50c3Schristos       erratum_address_(this->invalid_address)
957ed0d50c3Schristos   {}
958ed0d50c3Schristos 
~Erratum_stub()959ed0d50c3Schristos   ~Erratum_stub() {}
960ed0d50c3Schristos 
961ed0d50c3Schristos   // Return the object that contains the erratum.
962ed0d50c3Schristos   The_aarch64_relobj*
relobj()963ed0d50c3Schristos   relobj()
964ed0d50c3Schristos   { return this->relobj_; }
965ed0d50c3Schristos 
966ed0d50c3Schristos   // Get section index of the erratum.
967ed0d50c3Schristos   unsigned int
shndx() const968ed0d50c3Schristos   shndx() const
969ed0d50c3Schristos   { return this->shndx_; }
970ed0d50c3Schristos 
971ed0d50c3Schristos   // Get section offset of the erratum.
972ed0d50c3Schristos   unsigned int
sh_offset() const973ed0d50c3Schristos   sh_offset() const
974ed0d50c3Schristos   { return this->sh_offset_; }
975ed0d50c3Schristos 
976ed0d50c3Schristos   // Get the erratum insn. This is the insn located at erratum_insn_address.
977ed0d50c3Schristos   Insntype
erratum_insn() const978ed0d50c3Schristos   erratum_insn() const
979ed0d50c3Schristos   {
980ed0d50c3Schristos     gold_assert(this->erratum_insn_ != this->invalid_insn);
981ed0d50c3Schristos     return this->erratum_insn_;
982ed0d50c3Schristos   }
983ed0d50c3Schristos 
984ed0d50c3Schristos   // Set the insn that the erratum happens to.
985ed0d50c3Schristos   void
set_erratum_insn(Insntype insn)986ed0d50c3Schristos   set_erratum_insn(Insntype insn)
987ed0d50c3Schristos   { this->erratum_insn_ = insn; }
988ed0d50c3Schristos 
989ed0d50c3Schristos   // For 843419, the erratum insn is ld/st xt, [xn, #uimm], which may be a
990ed0d50c3Schristos   // relocation spot, in this case, the erratum_insn_ recorded at scanning phase
991ed0d50c3Schristos   // is no longer the one we want to write out to the stub, update erratum_insn_
992ed0d50c3Schristos   // with relocated version. Also note that in this case xn must not be "PC", so
993ed0d50c3Schristos   // it is safe to move the erratum insn from the origin place to the stub. For
994ed0d50c3Schristos   // 835769, the erratum insn is multiply-accumulate insn, which could not be a
995ed0d50c3Schristos   // relocation spot (assertion added though).
996ed0d50c3Schristos   void
update_erratum_insn(Insntype insn)997ed0d50c3Schristos   update_erratum_insn(Insntype insn)
998ed0d50c3Schristos   {
999ed0d50c3Schristos     gold_assert(this->erratum_insn_ != this->invalid_insn);
1000ed0d50c3Schristos     switch (this->type())
1001ed0d50c3Schristos       {
1002ed0d50c3Schristos       case ST_E_843419:
1003ed0d50c3Schristos 	gold_assert(Insn_utilities::aarch64_ldst_uimm(insn));
1004ed0d50c3Schristos 	gold_assert(Insn_utilities::aarch64_ldst_uimm(this->erratum_insn()));
1005ed0d50c3Schristos 	gold_assert(Insn_utilities::aarch64_rd(insn) ==
1006ed0d50c3Schristos 		    Insn_utilities::aarch64_rd(this->erratum_insn()));
1007ed0d50c3Schristos 	gold_assert(Insn_utilities::aarch64_rn(insn) ==
1008ed0d50c3Schristos 		    Insn_utilities::aarch64_rn(this->erratum_insn()));
1009ed0d50c3Schristos 	// Update plain ld/st insn with relocated insn.
1010ed0d50c3Schristos 	this->erratum_insn_ = insn;
1011ed0d50c3Schristos 	break;
1012ed0d50c3Schristos       case ST_E_835769:
1013ed0d50c3Schristos 	gold_assert(insn == this->erratum_insn());
1014ed0d50c3Schristos 	break;
1015ed0d50c3Schristos       default:
1016ed0d50c3Schristos 	gold_unreachable();
1017ed0d50c3Schristos       }
1018ed0d50c3Schristos   }
1019ed0d50c3Schristos 
1020ed0d50c3Schristos 
1021ed0d50c3Schristos   // Return the address where an erratum must be done.
1022ed0d50c3Schristos   AArch64_address
erratum_address() const1023ed0d50c3Schristos   erratum_address() const
1024ed0d50c3Schristos   {
1025ed0d50c3Schristos     gold_assert(this->erratum_address_ != this->invalid_address);
1026ed0d50c3Schristos     return this->erratum_address_;
1027ed0d50c3Schristos   }
1028ed0d50c3Schristos 
1029ed0d50c3Schristos   // Set the address where an erratum must be done.
1030ed0d50c3Schristos   void
set_erratum_address(AArch64_address addr)1031ed0d50c3Schristos   set_erratum_address(AArch64_address addr)
1032ed0d50c3Schristos   { this->erratum_address_ = addr; }
1033ed0d50c3Schristos 
103406324dcfSchristos   // Later relaxation passes of may alter the recorded erratum and destination
103506324dcfSchristos   // address. Given an up to date output section address of shidx_ in
103606324dcfSchristos   // relobj_ we can derive the erratum_address and destination address.
103706324dcfSchristos   void
update_erratum_address(AArch64_address output_section_addr)103806324dcfSchristos   update_erratum_address(AArch64_address output_section_addr)
103906324dcfSchristos   {
104006324dcfSchristos     const int BPI = AArch64_insn_utilities<big_endian>::BYTES_PER_INSN;
104106324dcfSchristos     AArch64_address updated_addr = output_section_addr + this->sh_offset_;
104206324dcfSchristos     this->set_erratum_address(updated_addr);
104306324dcfSchristos     this->set_destination_address(updated_addr + BPI);
104406324dcfSchristos   }
104506324dcfSchristos 
1046ed0d50c3Schristos   // Comparator used to group Erratum_stubs in a set by (obj, shndx,
104706324dcfSchristos   // sh_offset). We do not include 'type' in the calculation, because there is
1048ed0d50c3Schristos   // at most one stub type at (obj, shndx, sh_offset).
1049ed0d50c3Schristos   bool
operator <(const Erratum_stub<size,big_endian> & k) const1050ed0d50c3Schristos   operator<(const Erratum_stub<size, big_endian>& k) const
1051ed0d50c3Schristos   {
1052ed0d50c3Schristos     if (this == &k)
1053ed0d50c3Schristos       return false;
1054ed0d50c3Schristos     // We group stubs by relobj.
1055ed0d50c3Schristos     if (this->relobj_ != k.relobj_)
1056ed0d50c3Schristos       return this->relobj_ < k.relobj_;
1057ed0d50c3Schristos     // Then by section index.
1058ed0d50c3Schristos     if (this->shndx_ != k.shndx_)
1059ed0d50c3Schristos       return this->shndx_ < k.shndx_;
1060ed0d50c3Schristos     // Lastly by section offset.
1061ed0d50c3Schristos     return this->sh_offset_ < k.sh_offset_;
1062ed0d50c3Schristos   }
1063ed0d50c3Schristos 
106406324dcfSchristos   void
invalidate_erratum_stub()106506324dcfSchristos   invalidate_erratum_stub()
106606324dcfSchristos   {
106706324dcfSchristos      gold_assert(this->erratum_insn_ != invalid_insn);
106806324dcfSchristos      this->erratum_insn_ = invalid_insn;
106906324dcfSchristos   }
107006324dcfSchristos 
107106324dcfSchristos   bool
is_invalidated_erratum_stub()107206324dcfSchristos   is_invalidated_erratum_stub()
107306324dcfSchristos   { return this->erratum_insn_ == invalid_insn; }
107406324dcfSchristos 
1075ed0d50c3Schristos protected:
1076ed0d50c3Schristos   virtual void
1077ed0d50c3Schristos   do_write(unsigned char*, section_size_type);
1078ed0d50c3Schristos 
1079ed0d50c3Schristos private:
1080ed0d50c3Schristos   // The object that needs to be fixed.
1081ed0d50c3Schristos   The_aarch64_relobj* relobj_;
1082ed0d50c3Schristos   // The shndx in the object that needs to be fixed.
1083ed0d50c3Schristos   const unsigned int shndx_;
1084ed0d50c3Schristos   // The section offset in the obejct that needs to be fixed.
1085ed0d50c3Schristos   const unsigned int sh_offset_;
1086ed0d50c3Schristos   // The insn to be fixed.
1087ed0d50c3Schristos   Insntype erratum_insn_;
1088ed0d50c3Schristos   // The address of the above insn.
1089ed0d50c3Schristos   AArch64_address erratum_address_;
1090ed0d50c3Schristos };  // End of "Erratum_stub".
1091ed0d50c3Schristos 
1092ed0d50c3Schristos 
1093ed0d50c3Schristos // Erratum sub class to wrap additional info needed by 843419.  In fixing this
1094ed0d50c3Schristos // erratum, we may choose to replace 'adrp' with 'adr', in this case, we need
1095ed0d50c3Schristos // adrp's code position (two or three insns before erratum insn itself).
1096ed0d50c3Schristos 
1097ed0d50c3Schristos template<int size, bool big_endian>
1098ed0d50c3Schristos class E843419_stub : public Erratum_stub<size, big_endian>
1099ed0d50c3Schristos {
1100ed0d50c3Schristos public:
1101ed0d50c3Schristos   typedef typename AArch64_insn_utilities<big_endian>::Insntype Insntype;
1102ed0d50c3Schristos 
E843419_stub(AArch64_relobj<size,big_endian> * relobj,unsigned int shndx,unsigned int sh_offset,unsigned int adrp_sh_offset)1103ed0d50c3Schristos   E843419_stub(AArch64_relobj<size, big_endian>* relobj,
1104ed0d50c3Schristos 		      unsigned int shndx, unsigned int sh_offset,
1105ed0d50c3Schristos 		      unsigned int adrp_sh_offset)
1106ed0d50c3Schristos     : Erratum_stub<size, big_endian>(relobj, ST_E_843419, shndx, sh_offset),
1107ed0d50c3Schristos       adrp_sh_offset_(adrp_sh_offset)
1108ed0d50c3Schristos   {}
1109ed0d50c3Schristos 
1110ed0d50c3Schristos   unsigned int
adrp_sh_offset() const1111ed0d50c3Schristos   adrp_sh_offset() const
1112ed0d50c3Schristos   { return this->adrp_sh_offset_; }
1113ed0d50c3Schristos 
1114ed0d50c3Schristos private:
1115ed0d50c3Schristos   // Section offset of "adrp". (We do not need a "adrp_shndx_" field, because we
111606324dcfSchristos   // can obtain it from its parent.)
1117ed0d50c3Schristos   const unsigned int adrp_sh_offset_;
1118ed0d50c3Schristos };
1119ed0d50c3Schristos 
1120ed0d50c3Schristos 
1121ed0d50c3Schristos template<int size, bool big_endian>
1122ed0d50c3Schristos const int Erratum_stub<size, big_endian>::STUB_ADDR_ALIGN = 4;
1123ed0d50c3Schristos 
1124ed0d50c3Schristos // Comparator used in set definition.
1125ed0d50c3Schristos template<int size, bool big_endian>
1126ed0d50c3Schristos struct Erratum_stub_less
1127ed0d50c3Schristos {
1128ed0d50c3Schristos   bool
operator ()__anond8ca3b600111::Erratum_stub_less1129ed0d50c3Schristos   operator()(const Erratum_stub<size, big_endian>* s1,
1130ed0d50c3Schristos 	     const Erratum_stub<size, big_endian>* s2) const
1131ed0d50c3Schristos   { return *s1 < *s2; }
1132ed0d50c3Schristos };
1133ed0d50c3Schristos 
1134ed0d50c3Schristos // Erratum_stub implementation for writing stub to output file.
1135ed0d50c3Schristos 
1136ed0d50c3Schristos template<int size, bool big_endian>
1137ed0d50c3Schristos void
do_write(unsigned char * view,section_size_type)1138ed0d50c3Schristos Erratum_stub<size, big_endian>::do_write(unsigned char* view, section_size_type)
1139ed0d50c3Schristos {
1140ed0d50c3Schristos   typedef typename elfcpp::Swap<32, big_endian>::Valtype Insntype;
1141ed0d50c3Schristos   const Insntype* insns = this->insns();
1142ed0d50c3Schristos   uint32_t num_insns = this->insn_num();
1143ed0d50c3Schristos   Insntype* ip = reinterpret_cast<Insntype*>(view);
1144ed0d50c3Schristos   // For current implemented erratum 843419 and 835769, the first insn in the
1145ed0d50c3Schristos   // stub is always a copy of the problematic insn (in 843419, the mem access
1146ed0d50c3Schristos   // insn, in 835769, the mac insn), followed by a jump-back.
1147ed0d50c3Schristos   elfcpp::Swap<32, big_endian>::writeval(ip, this->erratum_insn());
1148ed0d50c3Schristos   for (uint32_t i = 1; i < num_insns; ++i)
1149ed0d50c3Schristos     elfcpp::Swap<32, big_endian>::writeval(ip + i, insns[i]);
1150ed0d50c3Schristos }
1151ed0d50c3Schristos 
1152ed0d50c3Schristos 
1153ed0d50c3Schristos // Reloc stub class.
1154ed0d50c3Schristos 
1155ed0d50c3Schristos template<int size, bool big_endian>
1156ed0d50c3Schristos class Reloc_stub : public Stub_base<size, big_endian>
1157ed0d50c3Schristos {
1158ed0d50c3Schristos  public:
1159ed0d50c3Schristos   typedef Reloc_stub<size, big_endian> This;
1160ed0d50c3Schristos   typedef typename elfcpp::Elf_types<size>::Elf_Addr AArch64_address;
1161ed0d50c3Schristos 
1162ed0d50c3Schristos   // Branch range. This is used to calculate the section group size, as well as
1163ed0d50c3Schristos   // determine whether a stub is needed.
1164ed0d50c3Schristos   static const int MAX_BRANCH_OFFSET = ((1 << 25) - 1) << 2;
1165ed0d50c3Schristos   static const int MIN_BRANCH_OFFSET = -((1 << 25) << 2);
1166ed0d50c3Schristos 
1167ed0d50c3Schristos   // Constant used to determine if an offset fits in the adrp instruction
1168ed0d50c3Schristos   // encoding.
1169ed0d50c3Schristos   static const int MAX_ADRP_IMM = (1 << 20) - 1;
1170ed0d50c3Schristos   static const int MIN_ADRP_IMM = -(1 << 20);
1171ed0d50c3Schristos 
1172ed0d50c3Schristos   static const int BYTES_PER_INSN = 4;
1173ed0d50c3Schristos   static const int STUB_ADDR_ALIGN;
1174ed0d50c3Schristos 
1175ed0d50c3Schristos   // Determine whether the offset fits in the jump/branch instruction.
1176ed0d50c3Schristos   static bool
aarch64_valid_branch_offset_p(int64_t offset)1177ed0d50c3Schristos   aarch64_valid_branch_offset_p(int64_t offset)
1178ed0d50c3Schristos   { return offset >= MIN_BRANCH_OFFSET && offset <= MAX_BRANCH_OFFSET; }
1179ed0d50c3Schristos 
1180ed0d50c3Schristos   // Determine whether the offset fits in the adrp immediate field.
1181ed0d50c3Schristos   static bool
aarch64_valid_for_adrp_p(AArch64_address location,AArch64_address dest)1182ed0d50c3Schristos   aarch64_valid_for_adrp_p(AArch64_address location, AArch64_address dest)
1183ed0d50c3Schristos   {
1184ed0d50c3Schristos     typedef AArch64_relocate_functions<size, big_endian> Reloc;
1185ed0d50c3Schristos     int64_t adrp_imm = (Reloc::Page(dest) - Reloc::Page(location)) >> 12;
1186ed0d50c3Schristos     return adrp_imm >= MIN_ADRP_IMM && adrp_imm <= MAX_ADRP_IMM;
1187ed0d50c3Schristos   }
1188ed0d50c3Schristos 
1189ed0d50c3Schristos   // Determine the stub type for a certain relocation or ST_NONE, if no stub is
1190ed0d50c3Schristos   // needed.
1191ed0d50c3Schristos   static int
1192ed0d50c3Schristos   stub_type_for_reloc(unsigned int r_type, AArch64_address address,
1193ed0d50c3Schristos 		      AArch64_address target);
1194ed0d50c3Schristos 
Reloc_stub(int type)1195ed0d50c3Schristos   Reloc_stub(int type)
1196ed0d50c3Schristos     : Stub_base<size, big_endian>(type)
1197ed0d50c3Schristos   { }
1198ed0d50c3Schristos 
~Reloc_stub()1199ed0d50c3Schristos   ~Reloc_stub()
1200ed0d50c3Schristos   { }
1201ed0d50c3Schristos 
1202ed0d50c3Schristos   // The key class used to index the stub instance in the stub table's stub map.
1203ed0d50c3Schristos   class Key
1204ed0d50c3Schristos   {
1205ed0d50c3Schristos    public:
Key(int type,const Symbol * symbol,const Relobj * relobj,unsigned int r_sym,int32_t addend)1206ed0d50c3Schristos     Key(int type, const Symbol* symbol, const Relobj* relobj,
1207ed0d50c3Schristos 	unsigned int r_sym, int32_t addend)
1208ed0d50c3Schristos       : type_(type), addend_(addend)
1209ed0d50c3Schristos     {
1210ed0d50c3Schristos       if (symbol != NULL)
1211ed0d50c3Schristos 	{
1212ed0d50c3Schristos 	  this->r_sym_ = Reloc_stub::invalid_index;
1213ed0d50c3Schristos 	  this->u_.symbol = symbol;
1214ed0d50c3Schristos 	}
1215ed0d50c3Schristos       else
1216ed0d50c3Schristos 	{
1217ed0d50c3Schristos 	  gold_assert(relobj != NULL && r_sym != invalid_index);
1218ed0d50c3Schristos 	  this->r_sym_ = r_sym;
1219ed0d50c3Schristos 	  this->u_.relobj = relobj;
1220ed0d50c3Schristos 	}
1221ed0d50c3Schristos     }
1222ed0d50c3Schristos 
~Key()1223ed0d50c3Schristos     ~Key()
1224ed0d50c3Schristos     { }
1225ed0d50c3Schristos 
1226ed0d50c3Schristos     // Return stub type.
1227ed0d50c3Schristos     int
type() const1228ed0d50c3Schristos     type() const
1229ed0d50c3Schristos     { return this->type_; }
1230ed0d50c3Schristos 
1231ed0d50c3Schristos     // Return the local symbol index or invalid_index.
1232ed0d50c3Schristos     unsigned int
r_sym() const1233ed0d50c3Schristos     r_sym() const
1234ed0d50c3Schristos     { return this->r_sym_; }
1235ed0d50c3Schristos 
1236ed0d50c3Schristos     // Return the symbol if there is one.
1237ed0d50c3Schristos     const Symbol*
symbol() const1238ed0d50c3Schristos     symbol() const
1239ed0d50c3Schristos     { return this->r_sym_ == invalid_index ? this->u_.symbol : NULL; }
1240ed0d50c3Schristos 
1241ed0d50c3Schristos     // Return the relobj if there is one.
1242ed0d50c3Schristos     const Relobj*
relobj() const1243ed0d50c3Schristos     relobj() const
1244ed0d50c3Schristos     { return this->r_sym_ != invalid_index ? this->u_.relobj : NULL; }
1245ed0d50c3Schristos 
1246ed0d50c3Schristos     // Whether this equals to another key k.
1247ed0d50c3Schristos     bool
eq(const Key & k) const1248ed0d50c3Schristos     eq(const Key& k) const
1249ed0d50c3Schristos     {
1250ed0d50c3Schristos       return ((this->type_ == k.type_)
1251ed0d50c3Schristos 	      && (this->r_sym_ == k.r_sym_)
1252ed0d50c3Schristos 	      && ((this->r_sym_ != Reloc_stub::invalid_index)
1253ed0d50c3Schristos 		  ? (this->u_.relobj == k.u_.relobj)
1254ed0d50c3Schristos 		  : (this->u_.symbol == k.u_.symbol))
1255ed0d50c3Schristos 	      && (this->addend_ == k.addend_));
1256ed0d50c3Schristos     }
1257ed0d50c3Schristos 
1258ed0d50c3Schristos     // Return a hash value.
1259ed0d50c3Schristos     size_t
hash_value() const1260ed0d50c3Schristos     hash_value() const
1261ed0d50c3Schristos     {
1262ed0d50c3Schristos       size_t name_hash_value = gold::string_hash<char>(
1263ed0d50c3Schristos 	  (this->r_sym_ != Reloc_stub::invalid_index)
1264ed0d50c3Schristos 	  ? this->u_.relobj->name().c_str()
1265ed0d50c3Schristos 	  : this->u_.symbol->name());
1266ed0d50c3Schristos       // We only have 4 stub types.
1267ed0d50c3Schristos       size_t stub_type_hash_value = 0x03 & this->type_;
1268ed0d50c3Schristos       return (name_hash_value
1269ed0d50c3Schristos 	      ^ stub_type_hash_value
1270ed0d50c3Schristos 	      ^ ((this->r_sym_ & 0x3fff) << 2)
1271ed0d50c3Schristos 	      ^ ((this->addend_ & 0xffff) << 16));
1272ed0d50c3Schristos     }
1273ed0d50c3Schristos 
1274ed0d50c3Schristos     // Functors for STL associative containers.
1275ed0d50c3Schristos     struct hash
1276ed0d50c3Schristos     {
1277ed0d50c3Schristos       size_t
operator ()__anond8ca3b600111::Reloc_stub::Key::hash1278ed0d50c3Schristos       operator()(const Key& k) const
1279ed0d50c3Schristos       { return k.hash_value(); }
1280ed0d50c3Schristos     };
1281ed0d50c3Schristos 
1282ed0d50c3Schristos     struct equal_to
1283ed0d50c3Schristos     {
1284ed0d50c3Schristos       bool
operator ()__anond8ca3b600111::Reloc_stub::Key::equal_to1285ed0d50c3Schristos       operator()(const Key& k1, const Key& k2) const
1286ed0d50c3Schristos       { return k1.eq(k2); }
1287ed0d50c3Schristos     };
1288ed0d50c3Schristos 
1289ed0d50c3Schristos    private:
1290ed0d50c3Schristos     // Stub type.
1291ed0d50c3Schristos     const int type_;
1292ed0d50c3Schristos     // If this is a local symbol, this is the index in the defining object.
1293ed0d50c3Schristos     // Otherwise, it is invalid_index for a global symbol.
1294ed0d50c3Schristos     unsigned int r_sym_;
1295ed0d50c3Schristos     // If r_sym_ is an invalid index, this points to a global symbol.
1296ed0d50c3Schristos     // Otherwise, it points to a relobj.  We used the unsized and target
1297ed0d50c3Schristos     // independent Symbol and Relobj classes instead of Sized_symbol<32> and
1298ed0d50c3Schristos     // Arm_relobj, in order to avoid making the stub class a template
1299ed0d50c3Schristos     // as most of the stub machinery is endianness-neutral.  However, it
1300ed0d50c3Schristos     // may require a bit of casting done by users of this class.
1301ed0d50c3Schristos     union
1302ed0d50c3Schristos     {
1303ed0d50c3Schristos       const Symbol* symbol;
1304ed0d50c3Schristos       const Relobj* relobj;
1305ed0d50c3Schristos     } u_;
1306ed0d50c3Schristos     // Addend associated with a reloc.
1307ed0d50c3Schristos     int32_t addend_;
1308ed0d50c3Schristos   };  // End of inner class Reloc_stub::Key
1309ed0d50c3Schristos 
1310ed0d50c3Schristos  protected:
1311ed0d50c3Schristos   // This may be overridden in the child class.
1312ed0d50c3Schristos   virtual void
1313ed0d50c3Schristos   do_write(unsigned char*, section_size_type);
1314ed0d50c3Schristos 
1315ed0d50c3Schristos  private:
1316ed0d50c3Schristos   static const unsigned int invalid_index = static_cast<unsigned int>(-1);
1317ed0d50c3Schristos };  // End of Reloc_stub
1318ed0d50c3Schristos 
1319ed0d50c3Schristos template<int size, bool big_endian>
1320ed0d50c3Schristos const int Reloc_stub<size, big_endian>::STUB_ADDR_ALIGN = 4;
1321ed0d50c3Schristos 
1322ed0d50c3Schristos // Write data to output file.
1323ed0d50c3Schristos 
1324ed0d50c3Schristos template<int size, bool big_endian>
1325ed0d50c3Schristos void
1326ed0d50c3Schristos Reloc_stub<size, big_endian>::
do_write(unsigned char * view,section_size_type)1327ed0d50c3Schristos do_write(unsigned char* view, section_size_type)
1328ed0d50c3Schristos {
1329ed0d50c3Schristos   typedef typename elfcpp::Swap<32, big_endian>::Valtype Insntype;
1330ed0d50c3Schristos   const uint32_t* insns = this->insns();
1331ed0d50c3Schristos   uint32_t num_insns = this->insn_num();
1332ed0d50c3Schristos   Insntype* ip = reinterpret_cast<Insntype*>(view);
1333ed0d50c3Schristos   for (uint32_t i = 0; i < num_insns; ++i)
1334ed0d50c3Schristos     elfcpp::Swap<32, big_endian>::writeval(ip + i, insns[i]);
1335ed0d50c3Schristos }
1336ed0d50c3Schristos 
1337ed0d50c3Schristos 
1338ed0d50c3Schristos // Determine the stub type for a certain relocation or ST_NONE, if no stub is
1339ed0d50c3Schristos // needed.
1340ed0d50c3Schristos 
1341ed0d50c3Schristos template<int size, bool big_endian>
1342ed0d50c3Schristos inline int
stub_type_for_reloc(unsigned int r_type,AArch64_address location,AArch64_address dest)1343ed0d50c3Schristos Reloc_stub<size, big_endian>::stub_type_for_reloc(
1344ed0d50c3Schristos     unsigned int r_type, AArch64_address location, AArch64_address dest)
1345ed0d50c3Schristos {
1346ed0d50c3Schristos   int64_t branch_offset = 0;
1347ed0d50c3Schristos   switch(r_type)
1348ed0d50c3Schristos     {
1349ed0d50c3Schristos     case elfcpp::R_AARCH64_CALL26:
1350ed0d50c3Schristos     case elfcpp::R_AARCH64_JUMP26:
1351ed0d50c3Schristos       branch_offset = dest - location;
1352ed0d50c3Schristos       break;
1353ed0d50c3Schristos     default:
1354ed0d50c3Schristos       gold_unreachable();
1355ed0d50c3Schristos     }
1356ed0d50c3Schristos 
1357ed0d50c3Schristos   if (aarch64_valid_branch_offset_p(branch_offset))
1358ed0d50c3Schristos     return ST_NONE;
1359ed0d50c3Schristos 
1360ed0d50c3Schristos   if (aarch64_valid_for_adrp_p(location, dest))
1361ed0d50c3Schristos     return ST_ADRP_BRANCH;
1362ed0d50c3Schristos 
1363ed0d50c3Schristos   // Always use PC-relative addressing in case of -shared or -pie.
1364ed0d50c3Schristos   if (parameters->options().output_is_position_independent())
1365ed0d50c3Schristos     return ST_LONG_BRANCH_PCREL;
1366ed0d50c3Schristos 
1367ed0d50c3Schristos   // This saves 2 insns per stub, compared to ST_LONG_BRANCH_PCREL.
1368ed0d50c3Schristos   // But is only applicable to non-shared or non-pie.
1369ed0d50c3Schristos   return ST_LONG_BRANCH_ABS;
1370ed0d50c3Schristos }
1371ed0d50c3Schristos 
137206324dcfSchristos // A class to hold stubs for the ARM target. This contains 2 different types of
137306324dcfSchristos // stubs - reloc stubs and erratum stubs.
1374ed0d50c3Schristos 
1375ed0d50c3Schristos template<int size, bool big_endian>
1376ed0d50c3Schristos class Stub_table : public Output_data
1377ed0d50c3Schristos {
1378ed0d50c3Schristos  public:
1379ed0d50c3Schristos   typedef Target_aarch64<size, big_endian> The_target_aarch64;
1380ed0d50c3Schristos   typedef typename elfcpp::Elf_types<size>::Elf_Addr AArch64_address;
1381ed0d50c3Schristos   typedef AArch64_relobj<size, big_endian> The_aarch64_relobj;
1382ed0d50c3Schristos   typedef AArch64_input_section<size, big_endian> The_aarch64_input_section;
1383ed0d50c3Schristos   typedef Reloc_stub<size, big_endian> The_reloc_stub;
1384ed0d50c3Schristos   typedef typename The_reloc_stub::Key The_reloc_stub_key;
1385ed0d50c3Schristos   typedef Erratum_stub<size, big_endian> The_erratum_stub;
1386ed0d50c3Schristos   typedef Erratum_stub_less<size, big_endian> The_erratum_stub_less;
1387ed0d50c3Schristos   typedef typename The_reloc_stub_key::hash The_reloc_stub_key_hash;
1388ed0d50c3Schristos   typedef typename The_reloc_stub_key::equal_to The_reloc_stub_key_equal_to;
1389ed0d50c3Schristos   typedef Stub_table<size, big_endian> The_stub_table;
1390ed0d50c3Schristos   typedef Unordered_map<The_reloc_stub_key, The_reloc_stub*,
1391ed0d50c3Schristos 			The_reloc_stub_key_hash, The_reloc_stub_key_equal_to>
1392ed0d50c3Schristos 			Reloc_stub_map;
1393ed0d50c3Schristos   typedef typename Reloc_stub_map::const_iterator Reloc_stub_map_const_iter;
1394ed0d50c3Schristos   typedef Relocate_info<size, big_endian> The_relocate_info;
1395ed0d50c3Schristos 
1396ed0d50c3Schristos   typedef std::set<The_erratum_stub*, The_erratum_stub_less> Erratum_stub_set;
1397ed0d50c3Schristos   typedef typename Erratum_stub_set::iterator Erratum_stub_set_iter;
1398ed0d50c3Schristos 
Stub_table(The_aarch64_input_section * owner)1399ed0d50c3Schristos   Stub_table(The_aarch64_input_section* owner)
1400ed0d50c3Schristos     : Output_data(), owner_(owner), reloc_stubs_size_(0),
1401ed0d50c3Schristos       erratum_stubs_size_(0), prev_data_size_(0)
1402ed0d50c3Schristos   { }
1403ed0d50c3Schristos 
~Stub_table()1404ed0d50c3Schristos   ~Stub_table()
1405ed0d50c3Schristos   { }
1406ed0d50c3Schristos 
1407ed0d50c3Schristos   The_aarch64_input_section*
owner() const1408ed0d50c3Schristos   owner() const
1409ed0d50c3Schristos   { return owner_; }
1410ed0d50c3Schristos 
1411ed0d50c3Schristos   // Whether this stub table is empty.
1412ed0d50c3Schristos   bool
empty() const1413ed0d50c3Schristos   empty() const
1414ed0d50c3Schristos   { return reloc_stubs_.empty() && erratum_stubs_.empty(); }
1415ed0d50c3Schristos 
1416ed0d50c3Schristos   // Return the current data size.
1417ed0d50c3Schristos   off_t
current_data_size() const1418ed0d50c3Schristos   current_data_size() const
1419ed0d50c3Schristos   { return this->current_data_size_for_child(); }
1420ed0d50c3Schristos 
1421ed0d50c3Schristos   // Add a STUB using KEY.  The caller is responsible for avoiding addition
1422ed0d50c3Schristos   // if a STUB with the same key has already been added.
1423ed0d50c3Schristos   void
1424ed0d50c3Schristos   add_reloc_stub(The_reloc_stub* stub, const The_reloc_stub_key& key);
1425ed0d50c3Schristos 
1426ed0d50c3Schristos   // Add an erratum stub into the erratum stub set. The set is ordered by
1427ed0d50c3Schristos   // (relobj, shndx, sh_offset).
1428ed0d50c3Schristos   void
1429ed0d50c3Schristos   add_erratum_stub(The_erratum_stub* stub);
1430ed0d50c3Schristos 
1431ed0d50c3Schristos   // Find if such erratum exists for any given (obj, shndx, sh_offset).
1432ed0d50c3Schristos   The_erratum_stub*
1433ed0d50c3Schristos   find_erratum_stub(The_aarch64_relobj* a64relobj,
1434ed0d50c3Schristos 		    unsigned int shndx, unsigned int sh_offset);
1435ed0d50c3Schristos 
1436ed0d50c3Schristos   // Find all the erratums for a given input section. The return value is a pair
1437ed0d50c3Schristos   // of iterators [begin, end).
1438ed0d50c3Schristos   std::pair<Erratum_stub_set_iter, Erratum_stub_set_iter>
1439ed0d50c3Schristos   find_erratum_stubs_for_input_section(The_aarch64_relobj* a64relobj,
1440ed0d50c3Schristos 				       unsigned int shndx);
1441ed0d50c3Schristos 
1442ed0d50c3Schristos   // Compute the erratum stub address.
1443ed0d50c3Schristos   AArch64_address
erratum_stub_address(The_erratum_stub * stub) const1444ed0d50c3Schristos   erratum_stub_address(The_erratum_stub* stub) const
1445ed0d50c3Schristos   {
1446ed0d50c3Schristos     AArch64_address r = align_address(this->address() + this->reloc_stubs_size_,
1447ed0d50c3Schristos 				      The_erratum_stub::STUB_ADDR_ALIGN);
1448ed0d50c3Schristos     r += stub->offset();
1449ed0d50c3Schristos     return r;
1450ed0d50c3Schristos   }
1451ed0d50c3Schristos 
1452ed0d50c3Schristos   // Finalize stubs. No-op here, just for completeness.
1453ed0d50c3Schristos   void
finalize_stubs()1454ed0d50c3Schristos   finalize_stubs()
1455ed0d50c3Schristos   { }
1456ed0d50c3Schristos 
1457ed0d50c3Schristos   // Look up a relocation stub using KEY. Return NULL if there is none.
1458ed0d50c3Schristos   The_reloc_stub*
find_reloc_stub(The_reloc_stub_key & key)1459ed0d50c3Schristos   find_reloc_stub(The_reloc_stub_key& key)
1460ed0d50c3Schristos   {
1461ed0d50c3Schristos     Reloc_stub_map_const_iter p = this->reloc_stubs_.find(key);
1462ed0d50c3Schristos     return (p != this->reloc_stubs_.end()) ? p->second : NULL;
1463ed0d50c3Schristos   }
1464ed0d50c3Schristos 
146506324dcfSchristos   // Relocate reloc stubs in this stub table. This does not relocate erratum stubs.
1466ed0d50c3Schristos   void
146706324dcfSchristos   relocate_reloc_stubs(const The_relocate_info*,
1468ed0d50c3Schristos                        The_target_aarch64*,
1469ed0d50c3Schristos                        Output_section*,
1470ed0d50c3Schristos                        unsigned char*,
1471ed0d50c3Schristos                        AArch64_address,
1472ed0d50c3Schristos                        section_size_type);
1473ed0d50c3Schristos 
147406324dcfSchristos   // Relocate an erratum stub.
147506324dcfSchristos   void
147606324dcfSchristos   relocate_erratum_stub(The_erratum_stub*, unsigned char*);
147706324dcfSchristos 
1478ed0d50c3Schristos   // Update data size at the end of a relaxation pass.  Return true if data size
1479ed0d50c3Schristos   // is different from that of the previous relaxation pass.
1480ed0d50c3Schristos   bool
update_data_size_changed_p()1481ed0d50c3Schristos   update_data_size_changed_p()
1482ed0d50c3Schristos   {
1483ed0d50c3Schristos     // No addralign changed here.
1484ed0d50c3Schristos     off_t s = align_address(this->reloc_stubs_size_,
1485ed0d50c3Schristos 			    The_erratum_stub::STUB_ADDR_ALIGN)
1486ed0d50c3Schristos 	      + this->erratum_stubs_size_;
1487ed0d50c3Schristos     bool changed = (s != this->prev_data_size_);
1488ed0d50c3Schristos     this->prev_data_size_ = s;
1489ed0d50c3Schristos     return changed;
1490ed0d50c3Schristos   }
1491ed0d50c3Schristos 
1492ed0d50c3Schristos  protected:
1493ed0d50c3Schristos   // Write out section contents.
1494ed0d50c3Schristos   void
1495ed0d50c3Schristos   do_write(Output_file*);
1496ed0d50c3Schristos 
1497ed0d50c3Schristos   // Return the required alignment.
1498ed0d50c3Schristos   uint64_t
do_addralign() const1499ed0d50c3Schristos   do_addralign() const
1500ed0d50c3Schristos   {
1501ed0d50c3Schristos     return std::max(The_reloc_stub::STUB_ADDR_ALIGN,
1502ed0d50c3Schristos 		    The_erratum_stub::STUB_ADDR_ALIGN);
1503ed0d50c3Schristos   }
1504ed0d50c3Schristos 
1505ed0d50c3Schristos   // Reset address and file offset.
1506ed0d50c3Schristos   void
do_reset_address_and_file_offset()1507ed0d50c3Schristos   do_reset_address_and_file_offset()
1508ed0d50c3Schristos   { this->set_current_data_size_for_child(this->prev_data_size_); }
1509ed0d50c3Schristos 
1510ed0d50c3Schristos   // Set final data size.
1511ed0d50c3Schristos   void
set_final_data_size()1512ed0d50c3Schristos   set_final_data_size()
1513ed0d50c3Schristos   { this->set_data_size(this->current_data_size()); }
1514ed0d50c3Schristos 
1515ed0d50c3Schristos  private:
151606324dcfSchristos   // Relocate one reloc stub.
1517ed0d50c3Schristos   void
151806324dcfSchristos   relocate_reloc_stub(The_reloc_stub*,
1519ed0d50c3Schristos                       const The_relocate_info*,
1520ed0d50c3Schristos                       The_target_aarch64*,
1521ed0d50c3Schristos                       Output_section*,
1522ed0d50c3Schristos                       unsigned char*,
1523ed0d50c3Schristos                       AArch64_address,
1524ed0d50c3Schristos                       section_size_type);
1525ed0d50c3Schristos 
1526ed0d50c3Schristos  private:
1527ed0d50c3Schristos   // Owner of this stub table.
1528ed0d50c3Schristos   The_aarch64_input_section* owner_;
1529ed0d50c3Schristos   // The relocation stubs.
1530ed0d50c3Schristos   Reloc_stub_map reloc_stubs_;
1531ed0d50c3Schristos   // The erratum stubs.
1532ed0d50c3Schristos   Erratum_stub_set erratum_stubs_;
1533ed0d50c3Schristos   // Size of reloc stubs.
1534ed0d50c3Schristos   off_t reloc_stubs_size_;
1535ed0d50c3Schristos   // Size of erratum stubs.
1536ed0d50c3Schristos   off_t erratum_stubs_size_;
1537ed0d50c3Schristos   // data size of this in the previous pass.
1538ed0d50c3Schristos   off_t prev_data_size_;
1539ed0d50c3Schristos };  // End of Stub_table
1540ed0d50c3Schristos 
1541ed0d50c3Schristos 
1542ed0d50c3Schristos // Add an erratum stub into the erratum stub set. The set is ordered by
1543ed0d50c3Schristos // (relobj, shndx, sh_offset).
1544ed0d50c3Schristos 
1545ed0d50c3Schristos template<int size, bool big_endian>
1546ed0d50c3Schristos void
add_erratum_stub(The_erratum_stub * stub)1547ed0d50c3Schristos Stub_table<size, big_endian>::add_erratum_stub(The_erratum_stub* stub)
1548ed0d50c3Schristos {
1549ed0d50c3Schristos   std::pair<Erratum_stub_set_iter, bool> ret =
1550ed0d50c3Schristos     this->erratum_stubs_.insert(stub);
1551ed0d50c3Schristos   gold_assert(ret.second);
1552ed0d50c3Schristos   this->erratum_stubs_size_ = align_address(
1553ed0d50c3Schristos 	this->erratum_stubs_size_, The_erratum_stub::STUB_ADDR_ALIGN);
1554ed0d50c3Schristos   stub->set_offset(this->erratum_stubs_size_);
1555ed0d50c3Schristos   this->erratum_stubs_size_ += stub->stub_size();
1556ed0d50c3Schristos }
1557ed0d50c3Schristos 
1558ed0d50c3Schristos 
1559ed0d50c3Schristos // Find if such erratum exists for given (obj, shndx, sh_offset).
1560ed0d50c3Schristos 
1561ed0d50c3Schristos template<int size, bool big_endian>
1562ed0d50c3Schristos Erratum_stub<size, big_endian>*
find_erratum_stub(The_aarch64_relobj * a64relobj,unsigned int shndx,unsigned int sh_offset)1563ed0d50c3Schristos Stub_table<size, big_endian>::find_erratum_stub(
1564ed0d50c3Schristos     The_aarch64_relobj* a64relobj, unsigned int shndx, unsigned int sh_offset)
1565ed0d50c3Schristos {
1566ed0d50c3Schristos   // A dummy object used as key to search in the set.
1567ed0d50c3Schristos   The_erratum_stub key(a64relobj, ST_NONE,
1568ed0d50c3Schristos 			 shndx, sh_offset);
1569ed0d50c3Schristos   Erratum_stub_set_iter i = this->erratum_stubs_.find(&key);
1570ed0d50c3Schristos   if (i != this->erratum_stubs_.end())
1571ed0d50c3Schristos     {
1572ed0d50c3Schristos 	The_erratum_stub* stub(*i);
1573ed0d50c3Schristos 	gold_assert(stub->erratum_insn() != 0);
1574ed0d50c3Schristos 	return stub;
1575ed0d50c3Schristos     }
1576ed0d50c3Schristos   return NULL;
1577ed0d50c3Schristos }
1578ed0d50c3Schristos 
1579ed0d50c3Schristos 
1580ed0d50c3Schristos // Find all the errata for a given input section. The return value is a pair of
1581ed0d50c3Schristos // iterators [begin, end).
1582ed0d50c3Schristos 
1583ed0d50c3Schristos template<int size, bool big_endian>
1584ed0d50c3Schristos std::pair<typename Stub_table<size, big_endian>::Erratum_stub_set_iter,
1585ed0d50c3Schristos 	  typename Stub_table<size, big_endian>::Erratum_stub_set_iter>
find_erratum_stubs_for_input_section(The_aarch64_relobj * a64relobj,unsigned int shndx)1586ed0d50c3Schristos Stub_table<size, big_endian>::find_erratum_stubs_for_input_section(
1587ed0d50c3Schristos     The_aarch64_relobj* a64relobj, unsigned int shndx)
1588ed0d50c3Schristos {
1589ed0d50c3Schristos   typedef std::pair<Erratum_stub_set_iter, Erratum_stub_set_iter> Result_pair;
1590ed0d50c3Schristos   Erratum_stub_set_iter start, end;
1591ed0d50c3Schristos   The_erratum_stub low_key(a64relobj, ST_NONE, shndx, 0);
1592ed0d50c3Schristos   start = this->erratum_stubs_.lower_bound(&low_key);
1593ed0d50c3Schristos   if (start == this->erratum_stubs_.end())
1594ed0d50c3Schristos     return Result_pair(this->erratum_stubs_.end(),
1595ed0d50c3Schristos 		       this->erratum_stubs_.end());
1596ed0d50c3Schristos   end = start;
1597ed0d50c3Schristos   while (end != this->erratum_stubs_.end() &&
1598ed0d50c3Schristos 	 (*end)->relobj() == a64relobj && (*end)->shndx() == shndx)
1599ed0d50c3Schristos     ++end;
1600ed0d50c3Schristos   return Result_pair(start, end);
1601ed0d50c3Schristos }
1602ed0d50c3Schristos 
1603ed0d50c3Schristos 
1604ed0d50c3Schristos // Add a STUB using KEY.  The caller is responsible for avoiding addition
1605ed0d50c3Schristos // if a STUB with the same key has already been added.
1606ed0d50c3Schristos 
1607ed0d50c3Schristos template<int size, bool big_endian>
1608ed0d50c3Schristos void
add_reloc_stub(The_reloc_stub * stub,const The_reloc_stub_key & key)1609ed0d50c3Schristos Stub_table<size, big_endian>::add_reloc_stub(
1610ed0d50c3Schristos     The_reloc_stub* stub, const The_reloc_stub_key& key)
1611ed0d50c3Schristos {
1612ed0d50c3Schristos   gold_assert(stub->type() == key.type());
1613ed0d50c3Schristos   this->reloc_stubs_[key] = stub;
1614ed0d50c3Schristos 
1615ed0d50c3Schristos   // Assign stub offset early.  We can do this because we never remove
1616ed0d50c3Schristos   // reloc stubs and they are in the beginning of the stub table.
1617ed0d50c3Schristos   this->reloc_stubs_size_ = align_address(this->reloc_stubs_size_,
1618ed0d50c3Schristos 					  The_reloc_stub::STUB_ADDR_ALIGN);
1619ed0d50c3Schristos   stub->set_offset(this->reloc_stubs_size_);
1620ed0d50c3Schristos   this->reloc_stubs_size_ += stub->stub_size();
1621ed0d50c3Schristos }
1622ed0d50c3Schristos 
1623ed0d50c3Schristos 
162406324dcfSchristos // Relocate an erratum stub.
1625ed0d50c3Schristos 
1626ed0d50c3Schristos template<int size, bool big_endian>
1627ed0d50c3Schristos void
1628ed0d50c3Schristos Stub_table<size, big_endian>::
relocate_erratum_stub(The_erratum_stub * estub,unsigned char * view)162906324dcfSchristos relocate_erratum_stub(The_erratum_stub* estub,
163006324dcfSchristos                       unsigned char* view)
163106324dcfSchristos {
163206324dcfSchristos   // Just for convenience.
163306324dcfSchristos   const int BPI = AArch64_insn_utilities<big_endian>::BYTES_PER_INSN;
163406324dcfSchristos 
163506324dcfSchristos   gold_assert(!estub->is_invalidated_erratum_stub());
163606324dcfSchristos   AArch64_address stub_address = this->erratum_stub_address(estub);
163706324dcfSchristos   // The address of "b" in the stub that is to be "relocated".
163806324dcfSchristos   AArch64_address stub_b_insn_address;
163906324dcfSchristos   // Branch offset that is to be filled in "b" insn.
164006324dcfSchristos   int b_offset = 0;
164106324dcfSchristos   switch (estub->type())
164206324dcfSchristos     {
164306324dcfSchristos     case ST_E_843419:
164406324dcfSchristos     case ST_E_835769:
164506324dcfSchristos       // The 1st insn of the erratum could be a relocation spot,
164606324dcfSchristos       // in this case we need to fix it with
164706324dcfSchristos       // "(*i)->erratum_insn()".
164806324dcfSchristos       elfcpp::Swap<32, big_endian>::writeval(
164906324dcfSchristos           view + (stub_address - this->address()),
165006324dcfSchristos           estub->erratum_insn());
165106324dcfSchristos       // For the erratum, the 2nd insn is a b-insn to be patched
165206324dcfSchristos       // (relocated).
165306324dcfSchristos       stub_b_insn_address = stub_address + 1 * BPI;
165406324dcfSchristos       b_offset = estub->destination_address() - stub_b_insn_address;
165506324dcfSchristos       AArch64_relocate_functions<size, big_endian>::construct_b(
165606324dcfSchristos           view + (stub_b_insn_address - this->address()),
165706324dcfSchristos           ((unsigned int)(b_offset)) & 0xfffffff);
165806324dcfSchristos       break;
165906324dcfSchristos     default:
166006324dcfSchristos       gold_unreachable();
166106324dcfSchristos       break;
166206324dcfSchristos     }
166306324dcfSchristos   estub->invalidate_erratum_stub();
166406324dcfSchristos }
166506324dcfSchristos 
166606324dcfSchristos 
166706324dcfSchristos // Relocate only reloc stubs in this stub table. This does not relocate erratum
166806324dcfSchristos // stubs.
166906324dcfSchristos 
167006324dcfSchristos template<int size, bool big_endian>
167106324dcfSchristos void
167206324dcfSchristos Stub_table<size, big_endian>::
relocate_reloc_stubs(const The_relocate_info * relinfo,The_target_aarch64 * target_aarch64,Output_section * output_section,unsigned char * view,AArch64_address address,section_size_type view_size)167306324dcfSchristos relocate_reloc_stubs(const The_relocate_info* relinfo,
1674ed0d50c3Schristos                      The_target_aarch64* target_aarch64,
1675ed0d50c3Schristos                      Output_section* output_section,
1676ed0d50c3Schristos                      unsigned char* view,
1677ed0d50c3Schristos                      AArch64_address address,
1678ed0d50c3Schristos                      section_size_type view_size)
1679ed0d50c3Schristos {
1680ed0d50c3Schristos   // "view_size" is the total size of the stub_table.
1681ed0d50c3Schristos   gold_assert(address == this->address() &&
1682ed0d50c3Schristos 	      view_size == static_cast<section_size_type>(this->data_size()));
1683ed0d50c3Schristos   for(Reloc_stub_map_const_iter p = this->reloc_stubs_.begin();
1684ed0d50c3Schristos       p != this->reloc_stubs_.end(); ++p)
168506324dcfSchristos     relocate_reloc_stub(p->second, relinfo, target_aarch64, output_section,
1686ed0d50c3Schristos                         view, address, view_size);
1687ed0d50c3Schristos }
1688ed0d50c3Schristos 
1689ed0d50c3Schristos 
169006324dcfSchristos // Relocate one reloc stub. This is a helper for
169106324dcfSchristos // Stub_table::relocate_reloc_stubs().
1692ed0d50c3Schristos 
1693ed0d50c3Schristos template<int size, bool big_endian>
1694ed0d50c3Schristos void
1695ed0d50c3Schristos Stub_table<size, big_endian>::
relocate_reloc_stub(The_reloc_stub * stub,const The_relocate_info * relinfo,The_target_aarch64 * target_aarch64,Output_section * output_section,unsigned char * view,AArch64_address address,section_size_type view_size)169606324dcfSchristos relocate_reloc_stub(The_reloc_stub* stub,
1697ed0d50c3Schristos                     const The_relocate_info* relinfo,
1698ed0d50c3Schristos                     The_target_aarch64* target_aarch64,
1699ed0d50c3Schristos                     Output_section* output_section,
1700ed0d50c3Schristos                     unsigned char* view,
1701ed0d50c3Schristos                     AArch64_address address,
1702ed0d50c3Schristos                     section_size_type view_size)
1703ed0d50c3Schristos {
1704ed0d50c3Schristos   // "offset" is the offset from the beginning of the stub_table.
1705ed0d50c3Schristos   section_size_type offset = stub->offset();
1706ed0d50c3Schristos   section_size_type stub_size = stub->stub_size();
1707ed0d50c3Schristos   // "view_size" is the total size of the stub_table.
1708ed0d50c3Schristos   gold_assert(offset + stub_size <= view_size);
1709ed0d50c3Schristos 
171006324dcfSchristos   target_aarch64->relocate_reloc_stub(stub, relinfo, output_section,
1711ed0d50c3Schristos                                       view + offset, address + offset, view_size);
1712ed0d50c3Schristos }
1713ed0d50c3Schristos 
1714ed0d50c3Schristos 
1715ed0d50c3Schristos // Write out the stubs to file.
1716ed0d50c3Schristos 
1717ed0d50c3Schristos template<int size, bool big_endian>
1718ed0d50c3Schristos void
do_write(Output_file * of)1719ed0d50c3Schristos Stub_table<size, big_endian>::do_write(Output_file* of)
1720ed0d50c3Schristos {
1721ed0d50c3Schristos   off_t offset = this->offset();
1722ed0d50c3Schristos   const section_size_type oview_size =
1723ed0d50c3Schristos     convert_to_section_size_type(this->data_size());
1724ed0d50c3Schristos   unsigned char* const oview = of->get_output_view(offset, oview_size);
1725ed0d50c3Schristos 
1726ed0d50c3Schristos   // Write relocation stubs.
1727ed0d50c3Schristos   for (typename Reloc_stub_map::const_iterator p = this->reloc_stubs_.begin();
1728ed0d50c3Schristos       p != this->reloc_stubs_.end(); ++p)
1729ed0d50c3Schristos     {
1730ed0d50c3Schristos       The_reloc_stub* stub = p->second;
1731ed0d50c3Schristos       AArch64_address address = this->address() + stub->offset();
1732ed0d50c3Schristos       gold_assert(address ==
1733ed0d50c3Schristos 		  align_address(address, The_reloc_stub::STUB_ADDR_ALIGN));
1734ed0d50c3Schristos       stub->write(oview + stub->offset(), stub->stub_size());
1735ed0d50c3Schristos     }
1736ed0d50c3Schristos 
1737ed0d50c3Schristos   // Write erratum stubs.
1738ed0d50c3Schristos   unsigned int erratum_stub_start_offset =
1739ed0d50c3Schristos     align_address(this->reloc_stubs_size_, The_erratum_stub::STUB_ADDR_ALIGN);
1740ed0d50c3Schristos   for (typename Erratum_stub_set::iterator p = this->erratum_stubs_.begin();
1741ed0d50c3Schristos        p != this->erratum_stubs_.end(); ++p)
1742ed0d50c3Schristos     {
1743ed0d50c3Schristos       The_erratum_stub* stub(*p);
1744ed0d50c3Schristos       stub->write(oview + erratum_stub_start_offset + stub->offset(),
1745ed0d50c3Schristos 		  stub->stub_size());
1746ed0d50c3Schristos     }
1747ed0d50c3Schristos 
1748ed0d50c3Schristos   of->write_output_view(this->offset(), oview_size, oview);
1749ed0d50c3Schristos }
1750ed0d50c3Schristos 
1751ed0d50c3Schristos 
1752ed0d50c3Schristos // AArch64_relobj class.
1753ed0d50c3Schristos 
1754ed0d50c3Schristos template<int size, bool big_endian>
1755ed0d50c3Schristos class AArch64_relobj : public Sized_relobj_file<size, big_endian>
1756ed0d50c3Schristos {
1757ed0d50c3Schristos  public:
1758ed0d50c3Schristos   typedef AArch64_relobj<size, big_endian> This;
1759ed0d50c3Schristos   typedef Target_aarch64<size, big_endian> The_target_aarch64;
1760ed0d50c3Schristos   typedef AArch64_input_section<size, big_endian> The_aarch64_input_section;
1761ed0d50c3Schristos   typedef typename elfcpp::Elf_types<size>::Elf_Addr AArch64_address;
1762ed0d50c3Schristos   typedef Stub_table<size, big_endian> The_stub_table;
1763ed0d50c3Schristos   typedef Erratum_stub<size, big_endian> The_erratum_stub;
1764ed0d50c3Schristos   typedef typename The_stub_table::Erratum_stub_set_iter Erratum_stub_set_iter;
1765ed0d50c3Schristos   typedef std::vector<The_stub_table*> Stub_table_list;
1766ed0d50c3Schristos   static const AArch64_address invalid_address =
1767ed0d50c3Schristos       static_cast<AArch64_address>(-1);
1768ed0d50c3Schristos 
AArch64_relobj(const std::string & name,Input_file * input_file,off_t offset,const typename elfcpp::Ehdr<size,big_endian> & ehdr)1769ed0d50c3Schristos   AArch64_relobj(const std::string& name, Input_file* input_file, off_t offset,
1770ed0d50c3Schristos 		 const typename elfcpp::Ehdr<size, big_endian>& ehdr)
1771ed0d50c3Schristos     : Sized_relobj_file<size, big_endian>(name, input_file, offset, ehdr),
1772ed0d50c3Schristos       stub_tables_()
1773ed0d50c3Schristos   { }
1774ed0d50c3Schristos 
~AArch64_relobj()1775ed0d50c3Schristos   ~AArch64_relobj()
1776ed0d50c3Schristos   { }
1777ed0d50c3Schristos 
1778ed0d50c3Schristos   // Return the stub table of the SHNDX-th section if there is one.
1779ed0d50c3Schristos   The_stub_table*
stub_table(unsigned int shndx) const1780ed0d50c3Schristos   stub_table(unsigned int shndx) const
1781ed0d50c3Schristos   {
1782ed0d50c3Schristos     gold_assert(shndx < this->stub_tables_.size());
1783ed0d50c3Schristos     return this->stub_tables_[shndx];
1784ed0d50c3Schristos   }
1785ed0d50c3Schristos 
1786ed0d50c3Schristos   // Set STUB_TABLE to be the stub_table of the SHNDX-th section.
1787ed0d50c3Schristos   void
set_stub_table(unsigned int shndx,The_stub_table * stub_table)1788ed0d50c3Schristos   set_stub_table(unsigned int shndx, The_stub_table* stub_table)
1789ed0d50c3Schristos   {
1790ed0d50c3Schristos     gold_assert(shndx < this->stub_tables_.size());
1791ed0d50c3Schristos     this->stub_tables_[shndx] = stub_table;
1792ed0d50c3Schristos   }
1793ed0d50c3Schristos 
1794ed0d50c3Schristos   // Entrance to errata scanning.
1795ed0d50c3Schristos   void
1796ed0d50c3Schristos   scan_errata(unsigned int shndx,
1797ed0d50c3Schristos 	      const elfcpp::Shdr<size, big_endian>&,
1798ed0d50c3Schristos 	      Output_section*, const Symbol_table*,
1799ed0d50c3Schristos 	      The_target_aarch64*);
1800ed0d50c3Schristos 
1801ed0d50c3Schristos   // Scan all relocation sections for stub generation.
1802ed0d50c3Schristos   void
1803ed0d50c3Schristos   scan_sections_for_stubs(The_target_aarch64*, const Symbol_table*,
1804ed0d50c3Schristos 			  const Layout*);
1805ed0d50c3Schristos 
1806ed0d50c3Schristos   // Whether a section is a scannable text section.
1807ed0d50c3Schristos   bool
1808ed0d50c3Schristos   text_section_is_scannable(const elfcpp::Shdr<size, big_endian>&, unsigned int,
1809ed0d50c3Schristos 			    const Output_section*, const Symbol_table*);
1810ed0d50c3Schristos 
1811ed0d50c3Schristos   // Convert regular input section with index SHNDX to a relaxed section.
1812ed0d50c3Schristos   void
convert_input_section_to_relaxed_section(unsigned shndx)181306324dcfSchristos   convert_input_section_to_relaxed_section(unsigned shndx)
1814ed0d50c3Schristos   {
1815ed0d50c3Schristos     // The stubs have relocations and we need to process them after writing
1816ed0d50c3Schristos     // out the stubs.  So relocation now must follow section write.
181706324dcfSchristos     this->set_section_offset(shndx, -1ULL);
1818ed0d50c3Schristos     this->set_relocs_must_follow_section_writes();
1819ed0d50c3Schristos   }
1820ed0d50c3Schristos 
1821ed0d50c3Schristos   // Structure for mapping symbol position.
1822ed0d50c3Schristos   struct Mapping_symbol_position
1823ed0d50c3Schristos   {
Mapping_symbol_position__anond8ca3b600111::AArch64_relobj::Mapping_symbol_position1824ed0d50c3Schristos     Mapping_symbol_position(unsigned int shndx, AArch64_address offset):
1825ed0d50c3Schristos       shndx_(shndx), offset_(offset)
1826ed0d50c3Schristos     {}
1827ed0d50c3Schristos 
1828ed0d50c3Schristos     // "<" comparator used in ordered_map container.
1829ed0d50c3Schristos     bool
operator <__anond8ca3b600111::AArch64_relobj::Mapping_symbol_position1830ed0d50c3Schristos     operator<(const Mapping_symbol_position& p) const
1831ed0d50c3Schristos     {
1832ed0d50c3Schristos       return (this->shndx_ < p.shndx_
1833ed0d50c3Schristos 	      || (this->shndx_ == p.shndx_ && this->offset_ < p.offset_));
1834ed0d50c3Schristos     }
1835ed0d50c3Schristos 
1836ed0d50c3Schristos     // Section index.
1837ed0d50c3Schristos     unsigned int shndx_;
1838ed0d50c3Schristos 
1839ed0d50c3Schristos     // Section offset.
1840ed0d50c3Schristos     AArch64_address offset_;
1841ed0d50c3Schristos   };
1842ed0d50c3Schristos 
1843ed0d50c3Schristos   typedef std::map<Mapping_symbol_position, char> Mapping_symbol_info;
1844ed0d50c3Schristos 
1845ed0d50c3Schristos  protected:
1846ed0d50c3Schristos   // Post constructor setup.
1847ed0d50c3Schristos   void
do_setup()1848ed0d50c3Schristos   do_setup()
1849ed0d50c3Schristos   {
1850ed0d50c3Schristos     // Call parent's setup method.
1851ed0d50c3Schristos     Sized_relobj_file<size, big_endian>::do_setup();
1852ed0d50c3Schristos 
1853ed0d50c3Schristos     // Initialize look-up tables.
1854ed0d50c3Schristos     this->stub_tables_.resize(this->shnum());
1855ed0d50c3Schristos   }
1856ed0d50c3Schristos 
1857ed0d50c3Schristos   virtual void
1858ed0d50c3Schristos   do_relocate_sections(
1859ed0d50c3Schristos       const Symbol_table* symtab, const Layout* layout,
1860ed0d50c3Schristos       const unsigned char* pshdrs, Output_file* of,
1861ed0d50c3Schristos       typename Sized_relobj_file<size, big_endian>::Views* pviews);
1862ed0d50c3Schristos 
1863ed0d50c3Schristos   // Count local symbols and (optionally) record mapping info.
1864ed0d50c3Schristos   virtual void
1865ed0d50c3Schristos   do_count_local_symbols(Stringpool_template<char>*,
1866ed0d50c3Schristos 			 Stringpool_template<char>*);
1867ed0d50c3Schristos 
1868ed0d50c3Schristos  private:
186906324dcfSchristos   // Fix all errata in the object, and for each erratum, relocate corresponding
187006324dcfSchristos   // erratum stub.
1871ed0d50c3Schristos   void
187206324dcfSchristos   fix_errata_and_relocate_erratum_stubs(
187306324dcfSchristos       typename Sized_relobj_file<size, big_endian>::Views* pviews);
1874ed0d50c3Schristos 
1875ed0d50c3Schristos   // Try to fix erratum 843419 in an optimized way. Return true if patch is
1876ed0d50c3Schristos   // applied.
1877ed0d50c3Schristos   bool
1878ed0d50c3Schristos   try_fix_erratum_843419_optimized(
187906324dcfSchristos       The_erratum_stub*, AArch64_address,
1880ed0d50c3Schristos       typename Sized_relobj_file<size, big_endian>::View_size&);
1881ed0d50c3Schristos 
1882ed0d50c3Schristos   // Whether a section needs to be scanned for relocation stubs.
1883ed0d50c3Schristos   bool
1884ed0d50c3Schristos   section_needs_reloc_stub_scanning(const elfcpp::Shdr<size, big_endian>&,
1885ed0d50c3Schristos 				    const Relobj::Output_sections&,
1886ed0d50c3Schristos 				    const Symbol_table*, const unsigned char*);
1887ed0d50c3Schristos 
1888ed0d50c3Schristos   // List of stub tables.
1889ed0d50c3Schristos   Stub_table_list stub_tables_;
1890ed0d50c3Schristos 
1891ed0d50c3Schristos   // Mapping symbol information sorted by (section index, section_offset).
1892ed0d50c3Schristos   Mapping_symbol_info mapping_symbol_info_;
1893ed0d50c3Schristos };  // End of AArch64_relobj
1894ed0d50c3Schristos 
1895ed0d50c3Schristos 
1896ed0d50c3Schristos // Override to record mapping symbol information.
1897ed0d50c3Schristos template<int size, bool big_endian>
1898ed0d50c3Schristos void
do_count_local_symbols(Stringpool_template<char> * pool,Stringpool_template<char> * dynpool)1899ed0d50c3Schristos AArch64_relobj<size, big_endian>::do_count_local_symbols(
1900ed0d50c3Schristos     Stringpool_template<char>* pool, Stringpool_template<char>* dynpool)
1901ed0d50c3Schristos {
1902ed0d50c3Schristos   Sized_relobj_file<size, big_endian>::do_count_local_symbols(pool, dynpool);
1903ed0d50c3Schristos 
1904ed0d50c3Schristos   // Only erratum-fixing work needs mapping symbols, so skip this time consuming
1905ed0d50c3Schristos   // processing if not fixing erratum.
1906ed0d50c3Schristos   if (!parameters->options().fix_cortex_a53_843419()
1907ed0d50c3Schristos       && !parameters->options().fix_cortex_a53_835769())
1908ed0d50c3Schristos     return;
1909ed0d50c3Schristos 
1910ed0d50c3Schristos   const unsigned int loccount = this->local_symbol_count();
1911ed0d50c3Schristos   if (loccount == 0)
1912ed0d50c3Schristos     return;
1913ed0d50c3Schristos 
1914ed0d50c3Schristos   // Read the symbol table section header.
1915ed0d50c3Schristos   const unsigned int symtab_shndx = this->symtab_shndx();
1916ed0d50c3Schristos   elfcpp::Shdr<size, big_endian>
1917ed0d50c3Schristos       symtabshdr(this, this->elf_file()->section_header(symtab_shndx));
1918ed0d50c3Schristos   gold_assert(symtabshdr.get_sh_type() == elfcpp::SHT_SYMTAB);
1919ed0d50c3Schristos 
1920ed0d50c3Schristos   // Read the local symbols.
1921ed0d50c3Schristos   const int sym_size =elfcpp::Elf_sizes<size>::sym_size;
1922ed0d50c3Schristos   gold_assert(loccount == symtabshdr.get_sh_info());
1923ed0d50c3Schristos   off_t locsize = loccount * sym_size;
1924ed0d50c3Schristos   const unsigned char* psyms = this->get_view(symtabshdr.get_sh_offset(),
1925ed0d50c3Schristos 					      locsize, true, true);
1926ed0d50c3Schristos 
1927ed0d50c3Schristos   // For mapping symbol processing, we need to read the symbol names.
1928ed0d50c3Schristos   unsigned int strtab_shndx = this->adjust_shndx(symtabshdr.get_sh_link());
1929ed0d50c3Schristos   if (strtab_shndx >= this->shnum())
1930ed0d50c3Schristos     {
1931ed0d50c3Schristos       this->error(_("invalid symbol table name index: %u"), strtab_shndx);
1932ed0d50c3Schristos       return;
1933ed0d50c3Schristos     }
1934ed0d50c3Schristos 
1935ed0d50c3Schristos   elfcpp::Shdr<size, big_endian>
1936ed0d50c3Schristos     strtabshdr(this, this->elf_file()->section_header(strtab_shndx));
1937ed0d50c3Schristos   if (strtabshdr.get_sh_type() != elfcpp::SHT_STRTAB)
1938ed0d50c3Schristos     {
1939ed0d50c3Schristos       this->error(_("symbol table name section has wrong type: %u"),
1940ed0d50c3Schristos 		  static_cast<unsigned int>(strtabshdr.get_sh_type()));
1941ed0d50c3Schristos       return;
1942ed0d50c3Schristos     }
1943ed0d50c3Schristos 
1944ed0d50c3Schristos   const char* pnames =
1945ed0d50c3Schristos     reinterpret_cast<const char*>(this->get_view(strtabshdr.get_sh_offset(),
1946ed0d50c3Schristos 						 strtabshdr.get_sh_size(),
1947ed0d50c3Schristos 						 false, false));
1948ed0d50c3Schristos 
1949ed0d50c3Schristos   // Skip the first dummy symbol.
1950ed0d50c3Schristos   psyms += sym_size;
1951ed0d50c3Schristos   typename Sized_relobj_file<size, big_endian>::Local_values*
1952ed0d50c3Schristos     plocal_values = this->local_values();
1953ed0d50c3Schristos   for (unsigned int i = 1; i < loccount; ++i, psyms += sym_size)
1954ed0d50c3Schristos     {
1955ed0d50c3Schristos       elfcpp::Sym<size, big_endian> sym(psyms);
1956ed0d50c3Schristos       Symbol_value<size>& lv((*plocal_values)[i]);
1957ed0d50c3Schristos       AArch64_address input_value = lv.input_value();
1958ed0d50c3Schristos 
1959ed0d50c3Schristos       // Check to see if this is a mapping symbol. AArch64 mapping symbols are
1960ed0d50c3Schristos       // defined in "ELF for the ARM 64-bit Architecture", Table 4-4, Mapping
1961ed0d50c3Schristos       // symbols.
1962ed0d50c3Schristos       // Mapping symbols could be one of the following 4 forms -
1963ed0d50c3Schristos       //   a) $x
1964ed0d50c3Schristos       //   b) $x.<any...>
1965ed0d50c3Schristos       //   c) $d
1966ed0d50c3Schristos       //   d) $d.<any...>
1967ed0d50c3Schristos       const char* sym_name = pnames + sym.get_st_name();
1968ed0d50c3Schristos       if (sym_name[0] == '$' && (sym_name[1] == 'x' || sym_name[1] == 'd')
1969ed0d50c3Schristos 	  && (sym_name[2] == '\0' || sym_name[2] == '.'))
1970ed0d50c3Schristos 	{
1971ed0d50c3Schristos 	  bool is_ordinary;
1972ed0d50c3Schristos 	  unsigned int input_shndx =
1973ed0d50c3Schristos 	    this->adjust_sym_shndx(i, sym.get_st_shndx(), &is_ordinary);
1974ed0d50c3Schristos 	  gold_assert(is_ordinary);
1975ed0d50c3Schristos 
1976ed0d50c3Schristos 	  Mapping_symbol_position msp(input_shndx, input_value);
1977ed0d50c3Schristos 	  // Insert mapping_symbol_info into map whose ordering is defined by
1978ed0d50c3Schristos 	  // (shndx, offset_within_section).
1979ed0d50c3Schristos 	  this->mapping_symbol_info_[msp] = sym_name[1];
1980ed0d50c3Schristos 	}
1981ed0d50c3Schristos    }
1982ed0d50c3Schristos }
1983ed0d50c3Schristos 
1984ed0d50c3Schristos 
198506324dcfSchristos // Fix all errata in the object and for each erratum, we relocate the
198606324dcfSchristos // corresponding erratum stub (by calling Stub_table::relocate_erratum_stub).
1987ed0d50c3Schristos 
1988ed0d50c3Schristos template<int size, bool big_endian>
1989ed0d50c3Schristos void
fix_errata_and_relocate_erratum_stubs(typename Sized_relobj_file<size,big_endian>::Views * pviews)199006324dcfSchristos AArch64_relobj<size, big_endian>::fix_errata_and_relocate_erratum_stubs(
1991ed0d50c3Schristos     typename Sized_relobj_file<size, big_endian>::Views* pviews)
1992ed0d50c3Schristos {
1993ed0d50c3Schristos   typedef typename elfcpp::Swap<32,big_endian>::Valtype Insntype;
1994ed0d50c3Schristos   unsigned int shnum = this->shnum();
199506324dcfSchristos   const Relobj::Output_sections& out_sections(this->output_sections());
1996ed0d50c3Schristos   for (unsigned int i = 1; i < shnum; ++i)
1997ed0d50c3Schristos     {
1998ed0d50c3Schristos       The_stub_table* stub_table = this->stub_table(i);
1999ed0d50c3Schristos       if (!stub_table)
2000ed0d50c3Schristos 	continue;
2001ed0d50c3Schristos       std::pair<Erratum_stub_set_iter, Erratum_stub_set_iter>
2002ed0d50c3Schristos 	ipair(stub_table->find_erratum_stubs_for_input_section(this, i));
2003ed0d50c3Schristos       Erratum_stub_set_iter p = ipair.first, end = ipair.second;
200406324dcfSchristos       typename Sized_relobj_file<size, big_endian>::View_size&
200506324dcfSchristos 	pview((*pviews)[i]);
200606324dcfSchristos       AArch64_address view_offset = 0;
200706324dcfSchristos       if (pview.is_input_output_view)
200806324dcfSchristos 	{
200906324dcfSchristos 	  // In this case, write_sections has not added the output offset to
201006324dcfSchristos 	  // the view's address, so we must do so. Currently this only happens
201106324dcfSchristos 	  // for a relaxed section.
201206324dcfSchristos 	  unsigned int index = this->adjust_shndx(i);
201306324dcfSchristos 	  const Output_relaxed_input_section* poris =
201406324dcfSchristos 	      out_sections[index]->find_relaxed_input_section(this, index);
201506324dcfSchristos 	  gold_assert(poris != NULL);
201606324dcfSchristos 	  view_offset = poris->address() - pview.address;
201706324dcfSchristos 	}
201806324dcfSchristos 
2019ed0d50c3Schristos       while (p != end)
2020ed0d50c3Schristos 	{
2021ed0d50c3Schristos 	  The_erratum_stub* stub = *p;
2022ed0d50c3Schristos 
2023ed0d50c3Schristos 	  // Double check data before fix.
202406324dcfSchristos 	  gold_assert(pview.address + view_offset + stub->sh_offset()
2025ed0d50c3Schristos 		      == stub->erratum_address());
2026ed0d50c3Schristos 
2027ed0d50c3Schristos 	  // Update previously recorded erratum insn with relocated
2028ed0d50c3Schristos 	  // version.
2029ed0d50c3Schristos 	  Insntype* ip =
203006324dcfSchristos 	    reinterpret_cast<Insntype*>(
203106324dcfSchristos 	      pview.view + view_offset + stub->sh_offset());
2032ed0d50c3Schristos 	  Insntype insn_to_fix = ip[0];
2033ed0d50c3Schristos 	  stub->update_erratum_insn(insn_to_fix);
2034ed0d50c3Schristos 
2035ed0d50c3Schristos 	  // First try to see if erratum is 843419 and if it can be fixed
2036ed0d50c3Schristos 	  // without using branch-to-stub.
203706324dcfSchristos 	  if (!try_fix_erratum_843419_optimized(stub, view_offset, pview))
2038ed0d50c3Schristos 	    {
2039ed0d50c3Schristos 	      // Replace the erratum insn with a branch-to-stub.
2040ed0d50c3Schristos 	      AArch64_address stub_address =
2041ed0d50c3Schristos 		stub_table->erratum_stub_address(stub);
2042ed0d50c3Schristos 	      unsigned int b_offset = stub_address - stub->erratum_address();
2043ed0d50c3Schristos 	      AArch64_relocate_functions<size, big_endian>::construct_b(
204406324dcfSchristos 		pview.view + view_offset + stub->sh_offset(),
204506324dcfSchristos 		b_offset & 0xfffffff);
2046ed0d50c3Schristos 	    }
204706324dcfSchristos 
204806324dcfSchristos           // Erratum fix is done (or skipped), continue to relocate erratum
204906324dcfSchristos           // stub. Note, when erratum fix is skipped (either because we
205006324dcfSchristos           // proactively change the code sequence or the code sequence is
205106324dcfSchristos           // changed by relaxation, etc), we can still safely relocate the
205206324dcfSchristos           // erratum stub, ignoring the fact the erratum could never be
205306324dcfSchristos           // executed.
205406324dcfSchristos           stub_table->relocate_erratum_stub(
205506324dcfSchristos 	    stub,
205606324dcfSchristos 	    pview.view + (stub_table->address() - pview.address));
205706324dcfSchristos 
205806324dcfSchristos           // Next erratum stub.
2059ed0d50c3Schristos 	  ++p;
2060ed0d50c3Schristos 	}
2061ed0d50c3Schristos     }
2062ed0d50c3Schristos }
2063ed0d50c3Schristos 
2064ed0d50c3Schristos 
2065ed0d50c3Schristos // This is an optimization for 843419. This erratum requires the sequence begin
2066ed0d50c3Schristos // with 'adrp', when final value calculated by adrp fits in adr, we can just
2067ed0d50c3Schristos // replace 'adrp' with 'adr', so we save 2 jumps per occurrence. (Note, however,
2068ed0d50c3Schristos // in this case, we do not delete the erratum stub (too late to do so), it is
2069ed0d50c3Schristos // merely generated without ever being called.)
2070ed0d50c3Schristos 
2071ed0d50c3Schristos template<int size, bool big_endian>
2072ed0d50c3Schristos bool
try_fix_erratum_843419_optimized(The_erratum_stub * stub,AArch64_address view_offset,typename Sized_relobj_file<size,big_endian>::View_size & pview)2073ed0d50c3Schristos AArch64_relobj<size, big_endian>::try_fix_erratum_843419_optimized(
207406324dcfSchristos     The_erratum_stub* stub, AArch64_address view_offset,
2075ed0d50c3Schristos     typename Sized_relobj_file<size, big_endian>::View_size& pview)
2076ed0d50c3Schristos {
2077ed0d50c3Schristos   if (stub->type() != ST_E_843419)
2078ed0d50c3Schristos     return false;
2079ed0d50c3Schristos 
2080ed0d50c3Schristos   typedef AArch64_insn_utilities<big_endian> Insn_utilities;
2081ed0d50c3Schristos   typedef typename elfcpp::Swap<32,big_endian>::Valtype Insntype;
2082ed0d50c3Schristos   E843419_stub<size, big_endian>* e843419_stub =
2083ed0d50c3Schristos     reinterpret_cast<E843419_stub<size, big_endian>*>(stub);
208406324dcfSchristos   AArch64_address pc =
208506324dcfSchristos     pview.address + view_offset + e843419_stub->adrp_sh_offset();
208606324dcfSchristos   unsigned int adrp_offset = e843419_stub->adrp_sh_offset ();
208706324dcfSchristos   Insntype* adrp_view =
208806324dcfSchristos     reinterpret_cast<Insntype*>(pview.view + view_offset + adrp_offset);
2089ed0d50c3Schristos   Insntype adrp_insn = adrp_view[0];
209006324dcfSchristos 
209106324dcfSchristos   // If the instruction at adrp_sh_offset is "mrs R, tpidr_el0", it may come
209206324dcfSchristos   // from IE -> LE relaxation etc.  This is a side-effect of TLS relaxation that
209306324dcfSchristos   // ADRP has been turned into MRS, there is no erratum risk anymore.
209406324dcfSchristos   // Therefore, we return true to avoid doing unnecessary branch-to-stub.
209506324dcfSchristos   if (Insn_utilities::is_mrs_tpidr_el0(adrp_insn))
209606324dcfSchristos     return true;
209706324dcfSchristos 
209806324dcfSchristos   // If the instruction at adrp_sh_offset is not ADRP and the instruction before
209906324dcfSchristos   // it is "mrs R, tpidr_el0", it may come from LD -> LE relaxation etc.
210006324dcfSchristos   // Like the above case, there is no erratum risk any more, we can safely
210106324dcfSchristos   // return true.
210206324dcfSchristos   if (!Insn_utilities::is_adrp(adrp_insn) && adrp_offset)
210306324dcfSchristos     {
210406324dcfSchristos       Insntype* prev_view =
210506324dcfSchristos 	reinterpret_cast<Insntype*>(
210606324dcfSchristos 	  pview.view + view_offset + adrp_offset - 4);
210706324dcfSchristos       Insntype prev_insn = prev_view[0];
210806324dcfSchristos 
210906324dcfSchristos       if (Insn_utilities::is_mrs_tpidr_el0(prev_insn))
211006324dcfSchristos 	return true;
211106324dcfSchristos     }
211206324dcfSchristos 
211306324dcfSchristos   /* If we reach here, the first instruction must be ADRP.  */
2114ed0d50c3Schristos   gold_assert(Insn_utilities::is_adrp(adrp_insn));
2115ed0d50c3Schristos   // Get adrp 33-bit signed imm value.
2116ed0d50c3Schristos   int64_t adrp_imm = Insn_utilities::
2117ed0d50c3Schristos     aarch64_adrp_decode_imm(adrp_insn);
2118ed0d50c3Schristos   // adrp - final value transferred to target register is calculated as:
2119ed0d50c3Schristos   //     PC[11:0] = Zeros(12)
2120ed0d50c3Schristos   //     adrp_dest_value = PC + adrp_imm;
2121ed0d50c3Schristos   int64_t adrp_dest_value = (pc & ~((1 << 12) - 1)) + adrp_imm;
2122ed0d50c3Schristos   // adr -final value transferred to target register is calucalted as:
2123ed0d50c3Schristos   //     PC + adr_imm
2124ed0d50c3Schristos   // So we have:
2125ed0d50c3Schristos   //     PC + adr_imm = adrp_dest_value
2126ed0d50c3Schristos   //   ==>
2127ed0d50c3Schristos   //     adr_imm = adrp_dest_value - PC
2128ed0d50c3Schristos   int64_t adr_imm = adrp_dest_value - pc;
2129ed0d50c3Schristos   // Check if imm fits in adr (21-bit signed).
2130ed0d50c3Schristos   if (-(1 << 20) <= adr_imm && adr_imm < (1 << 20))
2131ed0d50c3Schristos     {
2132ed0d50c3Schristos       // Convert 'adrp' into 'adr'.
2133ed0d50c3Schristos       Insntype adr_insn = adrp_insn & ((1u << 31) - 1);
2134ed0d50c3Schristos       adr_insn = Insn_utilities::
2135ed0d50c3Schristos 	aarch64_adr_encode_imm(adr_insn, adr_imm);
2136ed0d50c3Schristos       elfcpp::Swap<32, big_endian>::writeval(adrp_view, adr_insn);
2137ed0d50c3Schristos       return true;
2138ed0d50c3Schristos     }
2139ed0d50c3Schristos   return false;
2140ed0d50c3Schristos }
2141ed0d50c3Schristos 
2142ed0d50c3Schristos 
2143ed0d50c3Schristos // Relocate sections.
2144ed0d50c3Schristos 
2145ed0d50c3Schristos template<int size, bool big_endian>
2146ed0d50c3Schristos void
do_relocate_sections(const Symbol_table * symtab,const Layout * layout,const unsigned char * pshdrs,Output_file * of,typename Sized_relobj_file<size,big_endian>::Views * pviews)2147ed0d50c3Schristos AArch64_relobj<size, big_endian>::do_relocate_sections(
2148ed0d50c3Schristos     const Symbol_table* symtab, const Layout* layout,
2149ed0d50c3Schristos     const unsigned char* pshdrs, Output_file* of,
2150ed0d50c3Schristos     typename Sized_relobj_file<size, big_endian>::Views* pviews)
2151ed0d50c3Schristos {
215206324dcfSchristos   // Relocate the section data.
215306324dcfSchristos   this->relocate_section_range(symtab, layout, pshdrs, of, pviews,
215406324dcfSchristos 			       1, this->shnum() - 1);
2155ed0d50c3Schristos 
2156ed0d50c3Schristos   // We do not generate stubs if doing a relocatable link.
2157ed0d50c3Schristos   if (parameters->options().relocatable())
2158ed0d50c3Schristos     return;
2159ed0d50c3Schristos 
216006324dcfSchristos   // This part only relocates erratum stubs that belong to input sections of this
216106324dcfSchristos   // object file.
2162ed0d50c3Schristos   if (parameters->options().fix_cortex_a53_843419()
2163ed0d50c3Schristos       || parameters->options().fix_cortex_a53_835769())
216406324dcfSchristos     this->fix_errata_and_relocate_erratum_stubs(pviews);
2165ed0d50c3Schristos 
2166ed0d50c3Schristos   Relocate_info<size, big_endian> relinfo;
2167ed0d50c3Schristos   relinfo.symtab = symtab;
2168ed0d50c3Schristos   relinfo.layout = layout;
2169ed0d50c3Schristos   relinfo.object = this;
2170ed0d50c3Schristos 
217106324dcfSchristos   // This part relocates all reloc stubs that are contained in stub_tables of
217206324dcfSchristos   // this object file.
2173ed0d50c3Schristos   unsigned int shnum = this->shnum();
2174ed0d50c3Schristos   The_target_aarch64* target = The_target_aarch64::current_target();
2175ed0d50c3Schristos 
2176ed0d50c3Schristos   for (unsigned int i = 1; i < shnum; ++i)
2177ed0d50c3Schristos     {
2178ed0d50c3Schristos       The_aarch64_input_section* aarch64_input_section =
2179ed0d50c3Schristos 	  target->find_aarch64_input_section(this, i);
2180ed0d50c3Schristos       if (aarch64_input_section != NULL
2181ed0d50c3Schristos 	  && aarch64_input_section->is_stub_table_owner()
2182ed0d50c3Schristos 	  && !aarch64_input_section->stub_table()->empty())
2183ed0d50c3Schristos 	{
2184ed0d50c3Schristos 	  Output_section* os = this->output_section(i);
2185ed0d50c3Schristos 	  gold_assert(os != NULL);
2186ed0d50c3Schristos 
2187ed0d50c3Schristos 	  relinfo.reloc_shndx = elfcpp::SHN_UNDEF;
2188ed0d50c3Schristos 	  relinfo.reloc_shdr = NULL;
2189ed0d50c3Schristos 	  relinfo.data_shndx = i;
2190ed0d50c3Schristos 	  relinfo.data_shdr = pshdrs + i * elfcpp::Elf_sizes<size>::shdr_size;
2191ed0d50c3Schristos 
2192ed0d50c3Schristos 	  typename Sized_relobj_file<size, big_endian>::View_size&
2193ed0d50c3Schristos 	      view_struct = (*pviews)[i];
2194ed0d50c3Schristos 	  gold_assert(view_struct.view != NULL);
2195ed0d50c3Schristos 
2196ed0d50c3Schristos 	  The_stub_table* stub_table = aarch64_input_section->stub_table();
2197ed0d50c3Schristos 	  off_t offset = stub_table->address() - view_struct.address;
2198ed0d50c3Schristos 	  unsigned char* view = view_struct.view + offset;
2199ed0d50c3Schristos 	  AArch64_address address = stub_table->address();
2200ed0d50c3Schristos 	  section_size_type view_size = stub_table->data_size();
220106324dcfSchristos 	  stub_table->relocate_reloc_stubs(&relinfo, target, os, view, address,
2202ed0d50c3Schristos 					   view_size);
2203ed0d50c3Schristos 	}
2204ed0d50c3Schristos     }
2205ed0d50c3Schristos }
2206ed0d50c3Schristos 
2207ed0d50c3Schristos 
2208ed0d50c3Schristos // Determine if an input section is scannable for stub processing.  SHDR is
2209ed0d50c3Schristos // the header of the section and SHNDX is the section index.  OS is the output
2210ed0d50c3Schristos // section for the input section and SYMTAB is the global symbol table used to
2211ed0d50c3Schristos // look up ICF information.
2212ed0d50c3Schristos 
2213ed0d50c3Schristos template<int size, bool big_endian>
2214ed0d50c3Schristos bool
text_section_is_scannable(const elfcpp::Shdr<size,big_endian> & text_shdr,unsigned int text_shndx,const Output_section * os,const Symbol_table * symtab)2215ed0d50c3Schristos AArch64_relobj<size, big_endian>::text_section_is_scannable(
2216ed0d50c3Schristos     const elfcpp::Shdr<size, big_endian>& text_shdr,
2217ed0d50c3Schristos     unsigned int text_shndx,
2218ed0d50c3Schristos     const Output_section* os,
2219ed0d50c3Schristos     const Symbol_table* symtab)
2220ed0d50c3Schristos {
2221ed0d50c3Schristos   // Skip any empty sections, unallocated sections or sections whose
2222ed0d50c3Schristos   // type are not SHT_PROGBITS.
2223ed0d50c3Schristos   if (text_shdr.get_sh_size() == 0
2224ed0d50c3Schristos       || (text_shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0
2225ed0d50c3Schristos       || text_shdr.get_sh_type() != elfcpp::SHT_PROGBITS)
2226ed0d50c3Schristos     return false;
2227ed0d50c3Schristos 
2228ed0d50c3Schristos   // Skip any discarded or ICF'ed sections.
2229ed0d50c3Schristos   if (os == NULL || symtab->is_section_folded(this, text_shndx))
2230ed0d50c3Schristos     return false;
2231ed0d50c3Schristos 
2232ed0d50c3Schristos   // Skip exception frame.
2233ed0d50c3Schristos   if (strcmp(os->name(), ".eh_frame") == 0)
2234ed0d50c3Schristos     return false ;
2235ed0d50c3Schristos 
2236ed0d50c3Schristos   gold_assert(!this->is_output_section_offset_invalid(text_shndx) ||
2237ed0d50c3Schristos 	      os->find_relaxed_input_section(this, text_shndx) != NULL);
2238ed0d50c3Schristos 
2239ed0d50c3Schristos   return true;
2240ed0d50c3Schristos }
2241ed0d50c3Schristos 
2242ed0d50c3Schristos 
2243ed0d50c3Schristos // Determine if we want to scan the SHNDX-th section for relocation stubs.
2244ed0d50c3Schristos // This is a helper for AArch64_relobj::scan_sections_for_stubs().
2245ed0d50c3Schristos 
2246ed0d50c3Schristos template<int size, bool big_endian>
2247ed0d50c3Schristos bool
section_needs_reloc_stub_scanning(const elfcpp::Shdr<size,big_endian> & shdr,const Relobj::Output_sections & out_sections,const Symbol_table * symtab,const unsigned char * pshdrs)2248ed0d50c3Schristos AArch64_relobj<size, big_endian>::section_needs_reloc_stub_scanning(
2249ed0d50c3Schristos     const elfcpp::Shdr<size, big_endian>& shdr,
2250ed0d50c3Schristos     const Relobj::Output_sections& out_sections,
2251ed0d50c3Schristos     const Symbol_table* symtab,
2252ed0d50c3Schristos     const unsigned char* pshdrs)
2253ed0d50c3Schristos {
2254ed0d50c3Schristos   unsigned int sh_type = shdr.get_sh_type();
2255ed0d50c3Schristos   if (sh_type != elfcpp::SHT_RELA)
2256ed0d50c3Schristos     return false;
2257ed0d50c3Schristos 
2258ed0d50c3Schristos   // Ignore empty section.
2259ed0d50c3Schristos   off_t sh_size = shdr.get_sh_size();
2260ed0d50c3Schristos   if (sh_size == 0)
2261ed0d50c3Schristos     return false;
2262ed0d50c3Schristos 
2263ed0d50c3Schristos   // Ignore reloc section with unexpected symbol table.  The
2264ed0d50c3Schristos   // error will be reported in the final link.
2265ed0d50c3Schristos   if (this->adjust_shndx(shdr.get_sh_link()) != this->symtab_shndx())
2266ed0d50c3Schristos     return false;
2267ed0d50c3Schristos 
2268ed0d50c3Schristos   gold_assert(sh_type == elfcpp::SHT_RELA);
2269ed0d50c3Schristos   unsigned int reloc_size = elfcpp::Elf_sizes<size>::rela_size;
2270ed0d50c3Schristos 
2271ed0d50c3Schristos   // Ignore reloc section with unexpected entsize or uneven size.
2272ed0d50c3Schristos   // The error will be reported in the final link.
2273ed0d50c3Schristos   if (reloc_size != shdr.get_sh_entsize() || sh_size % reloc_size != 0)
2274ed0d50c3Schristos     return false;
2275ed0d50c3Schristos 
2276ed0d50c3Schristos   // Ignore reloc section with bad info.  This error will be
2277ed0d50c3Schristos   // reported in the final link.
2278ed0d50c3Schristos   unsigned int text_shndx = this->adjust_shndx(shdr.get_sh_info());
2279ed0d50c3Schristos   if (text_shndx >= this->shnum())
2280ed0d50c3Schristos     return false;
2281ed0d50c3Schristos 
2282ed0d50c3Schristos   const unsigned int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
2283ed0d50c3Schristos   const elfcpp::Shdr<size, big_endian> text_shdr(pshdrs +
2284ed0d50c3Schristos 						 text_shndx * shdr_size);
2285ed0d50c3Schristos   return this->text_section_is_scannable(text_shdr, text_shndx,
2286ed0d50c3Schristos 					 out_sections[text_shndx], symtab);
2287ed0d50c3Schristos }
2288ed0d50c3Schristos 
2289ed0d50c3Schristos 
2290ed0d50c3Schristos // Scan section SHNDX for erratum 843419 and 835769.
2291ed0d50c3Schristos 
2292ed0d50c3Schristos template<int size, bool big_endian>
2293ed0d50c3Schristos void
scan_errata(unsigned int shndx,const elfcpp::Shdr<size,big_endian> & shdr,Output_section * os,const Symbol_table * symtab,The_target_aarch64 * target)2294ed0d50c3Schristos AArch64_relobj<size, big_endian>::scan_errata(
2295ed0d50c3Schristos     unsigned int shndx, const elfcpp::Shdr<size, big_endian>& shdr,
2296ed0d50c3Schristos     Output_section* os, const Symbol_table* symtab,
2297ed0d50c3Schristos     The_target_aarch64* target)
2298ed0d50c3Schristos {
2299ed0d50c3Schristos   if (shdr.get_sh_size() == 0
2300ed0d50c3Schristos       || (shdr.get_sh_flags() &
2301ed0d50c3Schristos 	  (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR)) == 0
2302ed0d50c3Schristos       || shdr.get_sh_type() != elfcpp::SHT_PROGBITS)
2303ed0d50c3Schristos     return;
2304ed0d50c3Schristos 
2305ed0d50c3Schristos   if (!os || symtab->is_section_folded(this, shndx)) return;
2306ed0d50c3Schristos 
2307ed0d50c3Schristos   AArch64_address output_offset = this->get_output_section_offset(shndx);
2308ed0d50c3Schristos   AArch64_address output_address;
2309ed0d50c3Schristos   if (output_offset != invalid_address)
2310ed0d50c3Schristos     output_address = os->address() + output_offset;
2311ed0d50c3Schristos   else
2312ed0d50c3Schristos     {
2313ed0d50c3Schristos       const Output_relaxed_input_section* poris =
2314ed0d50c3Schristos 	os->find_relaxed_input_section(this, shndx);
2315ed0d50c3Schristos       if (!poris) return;
2316ed0d50c3Schristos       output_address = poris->address();
2317ed0d50c3Schristos     }
2318ed0d50c3Schristos 
231906324dcfSchristos   // Update the addresses in previously generated erratum stubs. Unlike when
232006324dcfSchristos   // we scan relocations for stubs, if section addresses have changed due to
232106324dcfSchristos   // other relaxations we are unlikely to scan the same erratum instances
232206324dcfSchristos   // again.
232306324dcfSchristos   The_stub_table* stub_table = this->stub_table(shndx);
232406324dcfSchristos   if (stub_table)
232506324dcfSchristos     {
232606324dcfSchristos       std::pair<Erratum_stub_set_iter, Erratum_stub_set_iter>
232706324dcfSchristos 	  ipair(stub_table->find_erratum_stubs_for_input_section(this, shndx));
232806324dcfSchristos       for (Erratum_stub_set_iter p = ipair.first;  p != ipair.second; ++p)
232906324dcfSchristos           (*p)->update_erratum_address(output_address);
233006324dcfSchristos     }
233106324dcfSchristos 
2332ed0d50c3Schristos   section_size_type input_view_size = 0;
2333ed0d50c3Schristos   const unsigned char* input_view =
2334ed0d50c3Schristos     this->section_contents(shndx, &input_view_size, false);
2335ed0d50c3Schristos 
2336ed0d50c3Schristos   Mapping_symbol_position section_start(shndx, 0);
2337ed0d50c3Schristos   // Find the first mapping symbol record within section shndx.
2338ed0d50c3Schristos   typename Mapping_symbol_info::const_iterator p =
2339ed0d50c3Schristos     this->mapping_symbol_info_.lower_bound(section_start);
2340ed0d50c3Schristos   while (p != this->mapping_symbol_info_.end() &&
2341ed0d50c3Schristos 	 p->first.shndx_ == shndx)
2342ed0d50c3Schristos     {
2343ed0d50c3Schristos       typename Mapping_symbol_info::const_iterator prev = p;
2344ed0d50c3Schristos       ++p;
2345ed0d50c3Schristos       if (prev->second == 'x')
2346ed0d50c3Schristos 	{
2347ed0d50c3Schristos 	  section_size_type span_start =
2348ed0d50c3Schristos 	    convert_to_section_size_type(prev->first.offset_);
2349ed0d50c3Schristos 	  section_size_type span_end;
2350ed0d50c3Schristos 	  if (p != this->mapping_symbol_info_.end()
2351ed0d50c3Schristos 	      && p->first.shndx_ == shndx)
2352ed0d50c3Schristos 	    span_end = convert_to_section_size_type(p->first.offset_);
2353ed0d50c3Schristos 	  else
2354ed0d50c3Schristos 	    span_end = convert_to_section_size_type(shdr.get_sh_size());
2355ed0d50c3Schristos 
2356ed0d50c3Schristos 	  // Here we do not share the scanning code of both errata. For 843419,
2357ed0d50c3Schristos 	  // only the last few insns of each page are examined, which is fast,
2358ed0d50c3Schristos 	  // whereas, for 835769, every insn pair needs to be checked.
2359ed0d50c3Schristos 
2360ed0d50c3Schristos 	  if (parameters->options().fix_cortex_a53_843419())
2361ed0d50c3Schristos 	    target->scan_erratum_843419_span(
2362ed0d50c3Schristos 	      this, shndx, span_start, span_end,
2363ed0d50c3Schristos 	      const_cast<unsigned char*>(input_view), output_address);
2364ed0d50c3Schristos 
2365ed0d50c3Schristos 	  if (parameters->options().fix_cortex_a53_835769())
2366ed0d50c3Schristos 	    target->scan_erratum_835769_span(
2367ed0d50c3Schristos 	      this, shndx, span_start, span_end,
2368ed0d50c3Schristos 	      const_cast<unsigned char*>(input_view), output_address);
2369ed0d50c3Schristos 	}
2370ed0d50c3Schristos     }
2371ed0d50c3Schristos }
2372ed0d50c3Schristos 
2373ed0d50c3Schristos 
2374ed0d50c3Schristos // Scan relocations for stub generation.
2375ed0d50c3Schristos 
2376ed0d50c3Schristos template<int size, bool big_endian>
2377ed0d50c3Schristos void
scan_sections_for_stubs(The_target_aarch64 * target,const Symbol_table * symtab,const Layout * layout)2378ed0d50c3Schristos AArch64_relobj<size, big_endian>::scan_sections_for_stubs(
2379ed0d50c3Schristos     The_target_aarch64* target,
2380ed0d50c3Schristos     const Symbol_table* symtab,
2381ed0d50c3Schristos     const Layout* layout)
2382ed0d50c3Schristos {
2383ed0d50c3Schristos   unsigned int shnum = this->shnum();
2384ed0d50c3Schristos   const unsigned int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
2385ed0d50c3Schristos 
2386ed0d50c3Schristos   // Read the section headers.
2387ed0d50c3Schristos   const unsigned char* pshdrs = this->get_view(this->elf_file()->shoff(),
2388ed0d50c3Schristos 					       shnum * shdr_size,
2389ed0d50c3Schristos 					       true, true);
2390ed0d50c3Schristos 
2391ed0d50c3Schristos   // To speed up processing, we set up hash tables for fast lookup of
2392ed0d50c3Schristos   // input offsets to output addresses.
2393ed0d50c3Schristos   this->initialize_input_to_output_maps();
2394ed0d50c3Schristos 
2395ed0d50c3Schristos   const Relobj::Output_sections& out_sections(this->output_sections());
2396ed0d50c3Schristos 
2397ed0d50c3Schristos   Relocate_info<size, big_endian> relinfo;
2398ed0d50c3Schristos   relinfo.symtab = symtab;
2399ed0d50c3Schristos   relinfo.layout = layout;
2400ed0d50c3Schristos   relinfo.object = this;
2401ed0d50c3Schristos 
2402ed0d50c3Schristos   // Do relocation stubs scanning.
2403ed0d50c3Schristos   const unsigned char* p = pshdrs + shdr_size;
2404ed0d50c3Schristos   for (unsigned int i = 1; i < shnum; ++i, p += shdr_size)
2405ed0d50c3Schristos     {
2406ed0d50c3Schristos       const elfcpp::Shdr<size, big_endian> shdr(p);
2407ed0d50c3Schristos       if (parameters->options().fix_cortex_a53_843419()
2408ed0d50c3Schristos 	  || parameters->options().fix_cortex_a53_835769())
2409ed0d50c3Schristos 	scan_errata(i, shdr, out_sections[i], symtab, target);
2410ed0d50c3Schristos       if (this->section_needs_reloc_stub_scanning(shdr, out_sections, symtab,
2411ed0d50c3Schristos 						  pshdrs))
2412ed0d50c3Schristos 	{
2413ed0d50c3Schristos 	  unsigned int index = this->adjust_shndx(shdr.get_sh_info());
2414ed0d50c3Schristos 	  AArch64_address output_offset =
2415ed0d50c3Schristos 	      this->get_output_section_offset(index);
2416ed0d50c3Schristos 	  AArch64_address output_address;
2417ed0d50c3Schristos 	  if (output_offset != invalid_address)
2418ed0d50c3Schristos 	    {
2419ed0d50c3Schristos 	      output_address = out_sections[index]->address() + output_offset;
2420ed0d50c3Schristos 	    }
2421ed0d50c3Schristos 	  else
2422ed0d50c3Schristos 	    {
2423ed0d50c3Schristos 	      // Currently this only happens for a relaxed section.
2424ed0d50c3Schristos 	      const Output_relaxed_input_section* poris =
2425ed0d50c3Schristos 		  out_sections[index]->find_relaxed_input_section(this, index);
2426ed0d50c3Schristos 	      gold_assert(poris != NULL);
2427ed0d50c3Schristos 	      output_address = poris->address();
2428ed0d50c3Schristos 	    }
2429ed0d50c3Schristos 
2430ed0d50c3Schristos 	  // Get the relocations.
2431ed0d50c3Schristos 	  const unsigned char* prelocs = this->get_view(shdr.get_sh_offset(),
2432ed0d50c3Schristos 							shdr.get_sh_size(),
2433ed0d50c3Schristos 							true, false);
2434ed0d50c3Schristos 
2435ed0d50c3Schristos 	  // Get the section contents.
2436ed0d50c3Schristos 	  section_size_type input_view_size = 0;
2437ed0d50c3Schristos 	  const unsigned char* input_view =
2438ed0d50c3Schristos 	      this->section_contents(index, &input_view_size, false);
2439ed0d50c3Schristos 
2440ed0d50c3Schristos 	  relinfo.reloc_shndx = i;
2441ed0d50c3Schristos 	  relinfo.data_shndx = index;
2442ed0d50c3Schristos 	  unsigned int sh_type = shdr.get_sh_type();
2443ed0d50c3Schristos 	  unsigned int reloc_size;
2444ed0d50c3Schristos 	  gold_assert (sh_type == elfcpp::SHT_RELA);
2445ed0d50c3Schristos 	  reloc_size = elfcpp::Elf_sizes<size>::rela_size;
2446ed0d50c3Schristos 
2447ed0d50c3Schristos 	  Output_section* os = out_sections[index];
2448ed0d50c3Schristos 	  target->scan_section_for_stubs(&relinfo, sh_type, prelocs,
2449ed0d50c3Schristos 					 shdr.get_sh_size() / reloc_size,
2450ed0d50c3Schristos 					 os,
2451ed0d50c3Schristos 					 output_offset == invalid_address,
2452ed0d50c3Schristos 					 input_view, output_address,
2453ed0d50c3Schristos 					 input_view_size);
2454ed0d50c3Schristos 	}
2455ed0d50c3Schristos     }
2456ed0d50c3Schristos }
2457ed0d50c3Schristos 
2458ed0d50c3Schristos 
2459ed0d50c3Schristos // A class to wrap an ordinary input section containing executable code.
2460ed0d50c3Schristos 
2461ed0d50c3Schristos template<int size, bool big_endian>
2462ed0d50c3Schristos class AArch64_input_section : public Output_relaxed_input_section
2463ed0d50c3Schristos {
2464ed0d50c3Schristos  public:
2465ed0d50c3Schristos   typedef Stub_table<size, big_endian> The_stub_table;
2466ed0d50c3Schristos 
AArch64_input_section(Relobj * relobj,unsigned int shndx)2467ed0d50c3Schristos   AArch64_input_section(Relobj* relobj, unsigned int shndx)
2468ed0d50c3Schristos     : Output_relaxed_input_section(relobj, shndx, 1),
2469ed0d50c3Schristos       stub_table_(NULL),
2470ed0d50c3Schristos       original_contents_(NULL), original_size_(0),
2471ed0d50c3Schristos       original_addralign_(1)
2472ed0d50c3Schristos   { }
2473ed0d50c3Schristos 
~AArch64_input_section()2474ed0d50c3Schristos   ~AArch64_input_section()
2475ed0d50c3Schristos   { delete[] this->original_contents_; }
2476ed0d50c3Schristos 
2477ed0d50c3Schristos   // Initialize.
2478ed0d50c3Schristos   void
2479ed0d50c3Schristos   init();
2480ed0d50c3Schristos 
2481ed0d50c3Schristos   // Set the stub_table.
2482ed0d50c3Schristos   void
set_stub_table(The_stub_table * st)2483ed0d50c3Schristos   set_stub_table(The_stub_table* st)
2484ed0d50c3Schristos   { this->stub_table_ = st; }
2485ed0d50c3Schristos 
2486ed0d50c3Schristos   // Whether this is a stub table owner.
2487ed0d50c3Schristos   bool
is_stub_table_owner() const2488ed0d50c3Schristos   is_stub_table_owner() const
2489ed0d50c3Schristos   { return this->stub_table_ != NULL && this->stub_table_->owner() == this; }
2490ed0d50c3Schristos 
2491ed0d50c3Schristos   // Return the original size of the section.
2492ed0d50c3Schristos   uint32_t
original_size() const2493ed0d50c3Schristos   original_size() const
2494ed0d50c3Schristos   { return this->original_size_; }
2495ed0d50c3Schristos 
2496ed0d50c3Schristos   // Return the stub table.
2497ed0d50c3Schristos   The_stub_table*
stub_table()2498ed0d50c3Schristos   stub_table()
2499ed0d50c3Schristos   { return stub_table_; }
2500ed0d50c3Schristos 
2501ed0d50c3Schristos  protected:
2502ed0d50c3Schristos   // Write out this input section.
2503ed0d50c3Schristos   void
2504ed0d50c3Schristos   do_write(Output_file*);
2505ed0d50c3Schristos 
2506ed0d50c3Schristos   // Return required alignment of this.
2507ed0d50c3Schristos   uint64_t
do_addralign() const2508ed0d50c3Schristos   do_addralign() const
2509ed0d50c3Schristos   {
2510ed0d50c3Schristos     if (this->is_stub_table_owner())
2511ed0d50c3Schristos       return std::max(this->stub_table_->addralign(),
2512ed0d50c3Schristos 		      static_cast<uint64_t>(this->original_addralign_));
2513ed0d50c3Schristos     else
2514ed0d50c3Schristos       return this->original_addralign_;
2515ed0d50c3Schristos   }
2516ed0d50c3Schristos 
2517ed0d50c3Schristos   // Finalize data size.
2518ed0d50c3Schristos   void
2519ed0d50c3Schristos   set_final_data_size();
2520ed0d50c3Schristos 
2521ed0d50c3Schristos   // Reset address and file offset.
2522ed0d50c3Schristos   void
2523ed0d50c3Schristos   do_reset_address_and_file_offset();
2524ed0d50c3Schristos 
2525ed0d50c3Schristos   // Output offset.
2526ed0d50c3Schristos   bool
do_output_offset(const Relobj * object,unsigned int shndx,section_offset_type offset,section_offset_type * poutput) const2527ed0d50c3Schristos   do_output_offset(const Relobj* object, unsigned int shndx,
2528ed0d50c3Schristos 		   section_offset_type offset,
2529ed0d50c3Schristos 		   section_offset_type* poutput) const
2530ed0d50c3Schristos   {
2531ed0d50c3Schristos     if ((object == this->relobj())
2532ed0d50c3Schristos 	&& (shndx == this->shndx())
2533ed0d50c3Schristos 	&& (offset >= 0)
2534ed0d50c3Schristos 	&& (offset <=
2535ed0d50c3Schristos 	    convert_types<section_offset_type, uint32_t>(this->original_size_)))
2536ed0d50c3Schristos       {
2537ed0d50c3Schristos 	*poutput = offset;
2538ed0d50c3Schristos 	return true;
2539ed0d50c3Schristos       }
2540ed0d50c3Schristos     else
2541ed0d50c3Schristos       return false;
2542ed0d50c3Schristos   }
2543ed0d50c3Schristos 
2544ed0d50c3Schristos  private:
2545ed0d50c3Schristos   // Copying is not allowed.
2546ed0d50c3Schristos   AArch64_input_section(const AArch64_input_section&);
2547ed0d50c3Schristos   AArch64_input_section& operator=(const AArch64_input_section&);
2548ed0d50c3Schristos 
2549ed0d50c3Schristos   // The relocation stubs.
2550ed0d50c3Schristos   The_stub_table* stub_table_;
2551ed0d50c3Schristos   // Original section contents.  We have to make a copy here since the file
2552ed0d50c3Schristos   // containing the original section may not be locked when we need to access
2553ed0d50c3Schristos   // the contents.
2554ed0d50c3Schristos   unsigned char* original_contents_;
2555ed0d50c3Schristos   // Section size of the original input section.
2556ed0d50c3Schristos   uint32_t original_size_;
2557ed0d50c3Schristos   // Address alignment of the original input section.
2558ed0d50c3Schristos   uint32_t original_addralign_;
2559ed0d50c3Schristos };  // End of AArch64_input_section
2560ed0d50c3Schristos 
2561ed0d50c3Schristos 
2562ed0d50c3Schristos // Finalize data size.
2563ed0d50c3Schristos 
2564ed0d50c3Schristos template<int size, bool big_endian>
2565ed0d50c3Schristos void
set_final_data_size()2566ed0d50c3Schristos AArch64_input_section<size, big_endian>::set_final_data_size()
2567ed0d50c3Schristos {
2568ed0d50c3Schristos   off_t off = convert_types<off_t, uint64_t>(this->original_size_);
2569ed0d50c3Schristos 
2570ed0d50c3Schristos   if (this->is_stub_table_owner())
2571ed0d50c3Schristos     {
2572ed0d50c3Schristos       this->stub_table_->finalize_data_size();
2573ed0d50c3Schristos       off = align_address(off, this->stub_table_->addralign());
2574ed0d50c3Schristos       off += this->stub_table_->data_size();
2575ed0d50c3Schristos     }
2576ed0d50c3Schristos   this->set_data_size(off);
2577ed0d50c3Schristos }
2578ed0d50c3Schristos 
2579ed0d50c3Schristos 
2580ed0d50c3Schristos // Reset address and file offset.
2581ed0d50c3Schristos 
2582ed0d50c3Schristos template<int size, bool big_endian>
2583ed0d50c3Schristos void
do_reset_address_and_file_offset()2584ed0d50c3Schristos AArch64_input_section<size, big_endian>::do_reset_address_and_file_offset()
2585ed0d50c3Schristos {
2586ed0d50c3Schristos   // Size of the original input section contents.
2587ed0d50c3Schristos   off_t off = convert_types<off_t, uint64_t>(this->original_size_);
2588ed0d50c3Schristos 
2589ed0d50c3Schristos   // If this is a stub table owner, account for the stub table size.
2590ed0d50c3Schristos   if (this->is_stub_table_owner())
2591ed0d50c3Schristos     {
2592ed0d50c3Schristos       The_stub_table* stub_table = this->stub_table_;
2593ed0d50c3Schristos 
2594ed0d50c3Schristos       // Reset the stub table's address and file offset.  The
2595ed0d50c3Schristos       // current data size for child will be updated after that.
2596ed0d50c3Schristos       stub_table_->reset_address_and_file_offset();
2597ed0d50c3Schristos       off = align_address(off, stub_table_->addralign());
2598ed0d50c3Schristos       off += stub_table->current_data_size();
2599ed0d50c3Schristos     }
2600ed0d50c3Schristos 
2601ed0d50c3Schristos   this->set_current_data_size(off);
2602ed0d50c3Schristos }
2603ed0d50c3Schristos 
2604ed0d50c3Schristos 
2605ed0d50c3Schristos // Initialize an Arm_input_section.
2606ed0d50c3Schristos 
2607ed0d50c3Schristos template<int size, bool big_endian>
2608ed0d50c3Schristos void
init()2609ed0d50c3Schristos AArch64_input_section<size, big_endian>::init()
2610ed0d50c3Schristos {
2611ed0d50c3Schristos   Relobj* relobj = this->relobj();
2612ed0d50c3Schristos   unsigned int shndx = this->shndx();
2613ed0d50c3Schristos 
2614ed0d50c3Schristos   // We have to cache original size, alignment and contents to avoid locking
2615ed0d50c3Schristos   // the original file.
2616ed0d50c3Schristos   this->original_addralign_ =
2617ed0d50c3Schristos       convert_types<uint32_t, uint64_t>(relobj->section_addralign(shndx));
2618ed0d50c3Schristos 
2619ed0d50c3Schristos   // This is not efficient but we expect only a small number of relaxed
2620ed0d50c3Schristos   // input sections for stubs.
2621ed0d50c3Schristos   section_size_type section_size;
2622ed0d50c3Schristos   const unsigned char* section_contents =
2623ed0d50c3Schristos       relobj->section_contents(shndx, &section_size, false);
2624ed0d50c3Schristos   this->original_size_ =
2625ed0d50c3Schristos       convert_types<uint32_t, uint64_t>(relobj->section_size(shndx));
2626ed0d50c3Schristos 
2627ed0d50c3Schristos   gold_assert(this->original_contents_ == NULL);
2628ed0d50c3Schristos   this->original_contents_ = new unsigned char[section_size];
2629ed0d50c3Schristos   memcpy(this->original_contents_, section_contents, section_size);
2630ed0d50c3Schristos 
2631ed0d50c3Schristos   // We want to make this look like the original input section after
2632ed0d50c3Schristos   // output sections are finalized.
2633ed0d50c3Schristos   Output_section* os = relobj->output_section(shndx);
2634ed0d50c3Schristos   off_t offset = relobj->output_section_offset(shndx);
2635ed0d50c3Schristos   gold_assert(os != NULL && !relobj->is_output_section_offset_invalid(shndx));
2636ed0d50c3Schristos   this->set_address(os->address() + offset);
2637ed0d50c3Schristos   this->set_file_offset(os->offset() + offset);
2638ed0d50c3Schristos   this->set_current_data_size(this->original_size_);
2639ed0d50c3Schristos   this->finalize_data_size();
2640ed0d50c3Schristos }
2641ed0d50c3Schristos 
2642ed0d50c3Schristos 
2643ed0d50c3Schristos // Write data to output file.
2644ed0d50c3Schristos 
2645ed0d50c3Schristos template<int size, bool big_endian>
2646ed0d50c3Schristos void
do_write(Output_file * of)2647ed0d50c3Schristos AArch64_input_section<size, big_endian>::do_write(Output_file* of)
2648ed0d50c3Schristos {
2649ed0d50c3Schristos   // We have to write out the original section content.
2650ed0d50c3Schristos   gold_assert(this->original_contents_ != NULL);
2651ed0d50c3Schristos   of->write(this->offset(), this->original_contents_,
2652ed0d50c3Schristos 	    this->original_size_);
2653ed0d50c3Schristos 
2654ed0d50c3Schristos   // If this owns a stub table and it is not empty, write it.
2655ed0d50c3Schristos   if (this->is_stub_table_owner() && !this->stub_table_->empty())
2656ed0d50c3Schristos     this->stub_table_->write(of);
2657ed0d50c3Schristos }
2658ed0d50c3Schristos 
2659ed0d50c3Schristos 
2660ed0d50c3Schristos // Arm output section class.  This is defined mainly to add a number of stub
2661ed0d50c3Schristos // generation methods.
2662ed0d50c3Schristos 
2663ed0d50c3Schristos template<int size, bool big_endian>
2664ed0d50c3Schristos class AArch64_output_section : public Output_section
2665ed0d50c3Schristos {
2666ed0d50c3Schristos  public:
2667ed0d50c3Schristos   typedef Target_aarch64<size, big_endian> The_target_aarch64;
2668ed0d50c3Schristos   typedef AArch64_relobj<size, big_endian> The_aarch64_relobj;
2669ed0d50c3Schristos   typedef Stub_table<size, big_endian> The_stub_table;
2670ed0d50c3Schristos   typedef AArch64_input_section<size, big_endian> The_aarch64_input_section;
2671ed0d50c3Schristos 
2672ed0d50c3Schristos  public:
AArch64_output_section(const char * name,elfcpp::Elf_Word type,elfcpp::Elf_Xword flags)2673ed0d50c3Schristos   AArch64_output_section(const char* name, elfcpp::Elf_Word type,
2674ed0d50c3Schristos 			 elfcpp::Elf_Xword flags)
2675ed0d50c3Schristos     : Output_section(name, type, flags)
2676ed0d50c3Schristos   { }
2677ed0d50c3Schristos 
~AArch64_output_section()2678ed0d50c3Schristos   ~AArch64_output_section() {}
2679ed0d50c3Schristos 
2680ed0d50c3Schristos   // Group input sections for stub generation.
2681ed0d50c3Schristos   void
2682ed0d50c3Schristos   group_sections(section_size_type, bool, Target_aarch64<size, big_endian>*,
2683ed0d50c3Schristos 		 const Task*);
2684ed0d50c3Schristos 
2685ed0d50c3Schristos  private:
2686ed0d50c3Schristos   typedef Output_section::Input_section Input_section;
2687ed0d50c3Schristos   typedef Output_section::Input_section_list Input_section_list;
2688ed0d50c3Schristos 
2689ed0d50c3Schristos   // Create a stub group.
2690ed0d50c3Schristos   void
2691ed0d50c3Schristos   create_stub_group(Input_section_list::const_iterator,
2692ed0d50c3Schristos 		    Input_section_list::const_iterator,
2693ed0d50c3Schristos 		    Input_section_list::const_iterator,
2694ed0d50c3Schristos 		    The_target_aarch64*,
2695ed0d50c3Schristos 		    std::vector<Output_relaxed_input_section*>&,
2696ed0d50c3Schristos 		    const Task*);
2697ed0d50c3Schristos };  // End of AArch64_output_section
2698ed0d50c3Schristos 
2699ed0d50c3Schristos 
2700ed0d50c3Schristos // Create a stub group for input sections from FIRST to LAST. OWNER points to
2701ed0d50c3Schristos // the input section that will be the owner of the stub table.
2702ed0d50c3Schristos 
2703ed0d50c3Schristos template<int size, bool big_endian> void
create_stub_group(Input_section_list::const_iterator first,Input_section_list::const_iterator last,Input_section_list::const_iterator owner,The_target_aarch64 * target,std::vector<Output_relaxed_input_section * > & new_relaxed_sections,const Task * task)2704ed0d50c3Schristos AArch64_output_section<size, big_endian>::create_stub_group(
2705ed0d50c3Schristos     Input_section_list::const_iterator first,
2706ed0d50c3Schristos     Input_section_list::const_iterator last,
2707ed0d50c3Schristos     Input_section_list::const_iterator owner,
2708ed0d50c3Schristos     The_target_aarch64* target,
2709ed0d50c3Schristos     std::vector<Output_relaxed_input_section*>& new_relaxed_sections,
2710ed0d50c3Schristos     const Task* task)
2711ed0d50c3Schristos {
2712ed0d50c3Schristos   // Currently we convert ordinary input sections into relaxed sections only
2713ed0d50c3Schristos   // at this point.
2714ed0d50c3Schristos   The_aarch64_input_section* input_section;
2715ed0d50c3Schristos   if (owner->is_relaxed_input_section())
2716ed0d50c3Schristos     gold_unreachable();
2717ed0d50c3Schristos   else
2718ed0d50c3Schristos     {
2719ed0d50c3Schristos       gold_assert(owner->is_input_section());
2720ed0d50c3Schristos       // Create a new relaxed input section.  We need to lock the original
2721ed0d50c3Schristos       // file.
2722ed0d50c3Schristos       Task_lock_obj<Object> tl(task, owner->relobj());
2723ed0d50c3Schristos       input_section =
2724ed0d50c3Schristos 	  target->new_aarch64_input_section(owner->relobj(), owner->shndx());
2725ed0d50c3Schristos       new_relaxed_sections.push_back(input_section);
2726ed0d50c3Schristos     }
2727ed0d50c3Schristos 
2728ed0d50c3Schristos   // Create a stub table.
2729ed0d50c3Schristos   The_stub_table* stub_table =
2730ed0d50c3Schristos       target->new_stub_table(input_section);
2731ed0d50c3Schristos 
2732ed0d50c3Schristos   input_section->set_stub_table(stub_table);
2733ed0d50c3Schristos 
2734ed0d50c3Schristos   Input_section_list::const_iterator p = first;
2735ed0d50c3Schristos   // Look for input sections or relaxed input sections in [first ... last].
2736ed0d50c3Schristos   do
2737ed0d50c3Schristos     {
2738ed0d50c3Schristos       if (p->is_input_section() || p->is_relaxed_input_section())
2739ed0d50c3Schristos 	{
2740ed0d50c3Schristos 	  // The stub table information for input sections live
2741ed0d50c3Schristos 	  // in their objects.
2742ed0d50c3Schristos 	  The_aarch64_relobj* aarch64_relobj =
2743ed0d50c3Schristos 	      static_cast<The_aarch64_relobj*>(p->relobj());
2744ed0d50c3Schristos 	  aarch64_relobj->set_stub_table(p->shndx(), stub_table);
2745ed0d50c3Schristos 	}
2746ed0d50c3Schristos     }
2747ed0d50c3Schristos   while (p++ != last);
2748ed0d50c3Schristos }
2749ed0d50c3Schristos 
2750ed0d50c3Schristos 
2751ed0d50c3Schristos // Group input sections for stub generation. GROUP_SIZE is roughly the limit of
2752ed0d50c3Schristos // stub groups. We grow a stub group by adding input section until the size is
2753ed0d50c3Schristos // just below GROUP_SIZE. The last input section will be converted into a stub
2754ed0d50c3Schristos // table owner. If STUB_ALWAYS_AFTER_BRANCH is false, we also add input sectiond
2755ed0d50c3Schristos // after the stub table, effectively doubling the group size.
2756ed0d50c3Schristos //
2757ed0d50c3Schristos // This is similar to the group_sections() function in elf32-arm.c but is
2758ed0d50c3Schristos // implemented differently.
2759ed0d50c3Schristos 
2760ed0d50c3Schristos template<int size, bool big_endian>
group_sections(section_size_type group_size,bool stubs_always_after_branch,Target_aarch64<size,big_endian> * target,const Task * task)2761ed0d50c3Schristos void AArch64_output_section<size, big_endian>::group_sections(
2762ed0d50c3Schristos     section_size_type group_size,
2763ed0d50c3Schristos     bool stubs_always_after_branch,
2764ed0d50c3Schristos     Target_aarch64<size, big_endian>* target,
2765ed0d50c3Schristos     const Task* task)
2766ed0d50c3Schristos {
2767ed0d50c3Schristos   typedef enum
2768ed0d50c3Schristos   {
2769ed0d50c3Schristos     NO_GROUP,
2770ed0d50c3Schristos     FINDING_STUB_SECTION,
2771ed0d50c3Schristos     HAS_STUB_SECTION
2772ed0d50c3Schristos   } State;
2773ed0d50c3Schristos 
2774ed0d50c3Schristos   std::vector<Output_relaxed_input_section*> new_relaxed_sections;
2775ed0d50c3Schristos 
2776ed0d50c3Schristos   State state = NO_GROUP;
2777ed0d50c3Schristos   section_size_type off = 0;
2778ed0d50c3Schristos   section_size_type group_begin_offset = 0;
2779ed0d50c3Schristos   section_size_type group_end_offset = 0;
2780ed0d50c3Schristos   section_size_type stub_table_end_offset = 0;
2781ed0d50c3Schristos   Input_section_list::const_iterator group_begin =
2782ed0d50c3Schristos       this->input_sections().end();
2783ed0d50c3Schristos   Input_section_list::const_iterator stub_table =
2784ed0d50c3Schristos       this->input_sections().end();
2785ed0d50c3Schristos   Input_section_list::const_iterator group_end = this->input_sections().end();
2786ed0d50c3Schristos   for (Input_section_list::const_iterator p = this->input_sections().begin();
2787ed0d50c3Schristos        p != this->input_sections().end();
2788ed0d50c3Schristos        ++p)
2789ed0d50c3Schristos     {
2790ed0d50c3Schristos       section_size_type section_begin_offset =
2791ed0d50c3Schristos 	align_address(off, p->addralign());
2792ed0d50c3Schristos       section_size_type section_end_offset =
2793ed0d50c3Schristos 	section_begin_offset + p->data_size();
2794ed0d50c3Schristos 
2795ed0d50c3Schristos       // Check to see if we should group the previously seen sections.
2796ed0d50c3Schristos       switch (state)
2797ed0d50c3Schristos 	{
2798ed0d50c3Schristos 	case NO_GROUP:
2799ed0d50c3Schristos 	  break;
2800ed0d50c3Schristos 
2801ed0d50c3Schristos 	case FINDING_STUB_SECTION:
2802ed0d50c3Schristos 	  // Adding this section makes the group larger than GROUP_SIZE.
2803ed0d50c3Schristos 	  if (section_end_offset - group_begin_offset >= group_size)
2804ed0d50c3Schristos 	    {
2805ed0d50c3Schristos 	      if (stubs_always_after_branch)
2806ed0d50c3Schristos 		{
2807ed0d50c3Schristos 		  gold_assert(group_end != this->input_sections().end());
2808ed0d50c3Schristos 		  this->create_stub_group(group_begin, group_end, group_end,
2809ed0d50c3Schristos 					  target, new_relaxed_sections,
2810ed0d50c3Schristos 					  task);
2811ed0d50c3Schristos 		  state = NO_GROUP;
2812ed0d50c3Schristos 		}
2813ed0d50c3Schristos 	      else
2814ed0d50c3Schristos 		{
2815ed0d50c3Schristos 		  // Input sections up to stub_group_size bytes after the stub
2816ed0d50c3Schristos 		  // table can be handled by it too.
2817ed0d50c3Schristos 		  state = HAS_STUB_SECTION;
2818ed0d50c3Schristos 		  stub_table = group_end;
2819ed0d50c3Schristos 		  stub_table_end_offset = group_end_offset;
2820ed0d50c3Schristos 		}
2821ed0d50c3Schristos 	    }
2822ed0d50c3Schristos 	    break;
2823ed0d50c3Schristos 
2824ed0d50c3Schristos 	case HAS_STUB_SECTION:
2825ed0d50c3Schristos 	  // Adding this section makes the post stub-section group larger
2826ed0d50c3Schristos 	  // than GROUP_SIZE.
2827ed0d50c3Schristos 	  gold_unreachable();
2828ed0d50c3Schristos 	  // NOT SUPPORTED YET. For completeness only.
2829ed0d50c3Schristos 	  if (section_end_offset - stub_table_end_offset >= group_size)
2830ed0d50c3Schristos 	   {
2831ed0d50c3Schristos 	     gold_assert(group_end != this->input_sections().end());
2832ed0d50c3Schristos 	     this->create_stub_group(group_begin, group_end, stub_table,
2833ed0d50c3Schristos 				     target, new_relaxed_sections, task);
2834ed0d50c3Schristos 	     state = NO_GROUP;
2835ed0d50c3Schristos 	   }
2836ed0d50c3Schristos 	   break;
2837ed0d50c3Schristos 
2838ed0d50c3Schristos 	  default:
2839ed0d50c3Schristos 	    gold_unreachable();
2840ed0d50c3Schristos 	}
2841ed0d50c3Schristos 
2842ed0d50c3Schristos       // If we see an input section and currently there is no group, start
2843ed0d50c3Schristos       // a new one.  Skip any empty sections.  We look at the data size
2844ed0d50c3Schristos       // instead of calling p->relobj()->section_size() to avoid locking.
2845ed0d50c3Schristos       if ((p->is_input_section() || p->is_relaxed_input_section())
2846ed0d50c3Schristos 	  && (p->data_size() != 0))
2847ed0d50c3Schristos 	{
2848ed0d50c3Schristos 	  if (state == NO_GROUP)
2849ed0d50c3Schristos 	    {
2850ed0d50c3Schristos 	      state = FINDING_STUB_SECTION;
2851ed0d50c3Schristos 	      group_begin = p;
2852ed0d50c3Schristos 	      group_begin_offset = section_begin_offset;
2853ed0d50c3Schristos 	    }
2854ed0d50c3Schristos 
2855ed0d50c3Schristos 	  // Keep track of the last input section seen.
2856ed0d50c3Schristos 	  group_end = p;
2857ed0d50c3Schristos 	  group_end_offset = section_end_offset;
2858ed0d50c3Schristos 	}
2859ed0d50c3Schristos 
2860ed0d50c3Schristos       off = section_end_offset;
2861ed0d50c3Schristos     }
2862ed0d50c3Schristos 
2863ed0d50c3Schristos   // Create a stub group for any ungrouped sections.
2864ed0d50c3Schristos   if (state == FINDING_STUB_SECTION || state == HAS_STUB_SECTION)
2865ed0d50c3Schristos     {
2866ed0d50c3Schristos       gold_assert(group_end != this->input_sections().end());
2867ed0d50c3Schristos       this->create_stub_group(group_begin, group_end,
2868ed0d50c3Schristos 			      (state == FINDING_STUB_SECTION
2869ed0d50c3Schristos 			       ? group_end
2870ed0d50c3Schristos 			       : stub_table),
2871ed0d50c3Schristos 			      target, new_relaxed_sections, task);
2872ed0d50c3Schristos     }
2873ed0d50c3Schristos 
2874ed0d50c3Schristos   if (!new_relaxed_sections.empty())
2875ed0d50c3Schristos     this->convert_input_sections_to_relaxed_sections(new_relaxed_sections);
2876ed0d50c3Schristos 
2877ed0d50c3Schristos   // Update the section offsets
2878ed0d50c3Schristos   for (size_t i = 0; i < new_relaxed_sections.size(); ++i)
2879ed0d50c3Schristos     {
2880ed0d50c3Schristos       The_aarch64_relobj* relobj = static_cast<The_aarch64_relobj*>(
2881ed0d50c3Schristos 	  new_relaxed_sections[i]->relobj());
2882ed0d50c3Schristos       unsigned int shndx = new_relaxed_sections[i]->shndx();
2883ed0d50c3Schristos       // Tell AArch64_relobj that this input section is converted.
2884ed0d50c3Schristos       relobj->convert_input_section_to_relaxed_section(shndx);
2885ed0d50c3Schristos     }
2886ed0d50c3Schristos }  // End of AArch64_output_section::group_sections
2887ed0d50c3Schristos 
2888ed0d50c3Schristos 
2889ed0d50c3Schristos AArch64_reloc_property_table* aarch64_reloc_property_table = NULL;
2890ed0d50c3Schristos 
2891ed0d50c3Schristos 
2892ed0d50c3Schristos // The aarch64 target class.
2893ed0d50c3Schristos // See the ABI at
2894ed0d50c3Schristos // http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf
2895ed0d50c3Schristos template<int size, bool big_endian>
2896ed0d50c3Schristos class Target_aarch64 : public Sized_target<size, big_endian>
2897ed0d50c3Schristos {
2898ed0d50c3Schristos  public:
2899ed0d50c3Schristos   typedef Target_aarch64<size, big_endian> This;
2900ed0d50c3Schristos   typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>
2901ed0d50c3Schristos       Reloc_section;
2902ed0d50c3Schristos   typedef Relocate_info<size, big_endian> The_relocate_info;
2903ed0d50c3Schristos   typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
2904ed0d50c3Schristos   typedef AArch64_relobj<size, big_endian> The_aarch64_relobj;
2905ed0d50c3Schristos   typedef Reloc_stub<size, big_endian> The_reloc_stub;
2906ed0d50c3Schristos   typedef Erratum_stub<size, big_endian> The_erratum_stub;
2907ed0d50c3Schristos   typedef typename Reloc_stub<size, big_endian>::Key The_reloc_stub_key;
2908ed0d50c3Schristos   typedef Stub_table<size, big_endian> The_stub_table;
2909ed0d50c3Schristos   typedef std::vector<The_stub_table*> Stub_table_list;
2910ed0d50c3Schristos   typedef typename Stub_table_list::iterator Stub_table_iterator;
2911ed0d50c3Schristos   typedef AArch64_input_section<size, big_endian> The_aarch64_input_section;
2912ed0d50c3Schristos   typedef AArch64_output_section<size, big_endian> The_aarch64_output_section;
2913ed0d50c3Schristos   typedef Unordered_map<Section_id,
2914ed0d50c3Schristos 			AArch64_input_section<size, big_endian>*,
2915ed0d50c3Schristos 			Section_id_hash> AArch64_input_section_map;
2916ed0d50c3Schristos   typedef AArch64_insn_utilities<big_endian> Insn_utilities;
2917ed0d50c3Schristos   const static int TCB_SIZE = size / 8 * 2;
2918ed0d50c3Schristos 
Target_aarch64(const Target::Target_info * info=& aarch64_info)2919ed0d50c3Schristos   Target_aarch64(const Target::Target_info* info = &aarch64_info)
2920ed0d50c3Schristos     : Sized_target<size, big_endian>(info),
2921ed0d50c3Schristos       got_(NULL), plt_(NULL), got_plt_(NULL), got_irelative_(NULL),
2922ed0d50c3Schristos       got_tlsdesc_(NULL), global_offset_table_(NULL), rela_dyn_(NULL),
2923ed0d50c3Schristos       rela_irelative_(NULL), copy_relocs_(elfcpp::R_AARCH64_COPY),
2924ed0d50c3Schristos       got_mod_index_offset_(-1U),
2925ed0d50c3Schristos       tlsdesc_reloc_info_(), tls_base_symbol_defined_(false),
2926ed0d50c3Schristos       stub_tables_(), stub_group_size_(0), aarch64_input_section_map_()
2927ed0d50c3Schristos   { }
2928ed0d50c3Schristos 
2929ed0d50c3Schristos   // Scan the relocations to determine unreferenced sections for
2930ed0d50c3Schristos   // garbage collection.
2931ed0d50c3Schristos   void
2932ed0d50c3Schristos   gc_process_relocs(Symbol_table* symtab,
2933ed0d50c3Schristos 		    Layout* layout,
2934ed0d50c3Schristos 		    Sized_relobj_file<size, big_endian>* object,
2935ed0d50c3Schristos 		    unsigned int data_shndx,
2936ed0d50c3Schristos 		    unsigned int sh_type,
2937ed0d50c3Schristos 		    const unsigned char* prelocs,
2938ed0d50c3Schristos 		    size_t reloc_count,
2939ed0d50c3Schristos 		    Output_section* output_section,
2940ed0d50c3Schristos 		    bool needs_special_offset_handling,
2941ed0d50c3Schristos 		    size_t local_symbol_count,
2942ed0d50c3Schristos 		    const unsigned char* plocal_symbols);
2943ed0d50c3Schristos 
2944ed0d50c3Schristos   // Scan the relocations to look for symbol adjustments.
2945ed0d50c3Schristos   void
2946ed0d50c3Schristos   scan_relocs(Symbol_table* symtab,
2947ed0d50c3Schristos 	      Layout* layout,
2948ed0d50c3Schristos 	      Sized_relobj_file<size, big_endian>* object,
2949ed0d50c3Schristos 	      unsigned int data_shndx,
2950ed0d50c3Schristos 	      unsigned int sh_type,
2951ed0d50c3Schristos 	      const unsigned char* prelocs,
2952ed0d50c3Schristos 	      size_t reloc_count,
2953ed0d50c3Schristos 	      Output_section* output_section,
2954ed0d50c3Schristos 	      bool needs_special_offset_handling,
2955ed0d50c3Schristos 	      size_t local_symbol_count,
2956ed0d50c3Schristos 	      const unsigned char* plocal_symbols);
2957ed0d50c3Schristos 
2958ed0d50c3Schristos   // Finalize the sections.
2959ed0d50c3Schristos   void
2960ed0d50c3Schristos   do_finalize_sections(Layout*, const Input_objects*, Symbol_table*);
2961ed0d50c3Schristos 
2962ed0d50c3Schristos   // Return the value to use for a dynamic which requires special
2963ed0d50c3Schristos   // treatment.
2964ed0d50c3Schristos   uint64_t
2965ed0d50c3Schristos   do_dynsym_value(const Symbol*) const;
2966ed0d50c3Schristos 
2967ed0d50c3Schristos   // Relocate a section.
2968ed0d50c3Schristos   void
2969ed0d50c3Schristos   relocate_section(const Relocate_info<size, big_endian>*,
2970ed0d50c3Schristos 		   unsigned int sh_type,
2971ed0d50c3Schristos 		   const unsigned char* prelocs,
2972ed0d50c3Schristos 		   size_t reloc_count,
2973ed0d50c3Schristos 		   Output_section* output_section,
2974ed0d50c3Schristos 		   bool needs_special_offset_handling,
2975ed0d50c3Schristos 		   unsigned char* view,
2976ed0d50c3Schristos 		   typename elfcpp::Elf_types<size>::Elf_Addr view_address,
2977ed0d50c3Schristos 		   section_size_type view_size,
2978ed0d50c3Schristos 		   const Reloc_symbol_changes*);
2979ed0d50c3Schristos 
2980ed0d50c3Schristos   // Scan the relocs during a relocatable link.
2981ed0d50c3Schristos   void
2982ed0d50c3Schristos   scan_relocatable_relocs(Symbol_table* symtab,
2983ed0d50c3Schristos 			  Layout* layout,
2984ed0d50c3Schristos 			  Sized_relobj_file<size, big_endian>* object,
2985ed0d50c3Schristos 			  unsigned int data_shndx,
2986ed0d50c3Schristos 			  unsigned int sh_type,
2987ed0d50c3Schristos 			  const unsigned char* prelocs,
2988ed0d50c3Schristos 			  size_t reloc_count,
2989ed0d50c3Schristos 			  Output_section* output_section,
2990ed0d50c3Schristos 			  bool needs_special_offset_handling,
2991ed0d50c3Schristos 			  size_t local_symbol_count,
2992ed0d50c3Schristos 			  const unsigned char* plocal_symbols,
2993ed0d50c3Schristos 			  Relocatable_relocs*);
2994ed0d50c3Schristos 
2995ed0d50c3Schristos   // Scan the relocs for --emit-relocs.
2996ed0d50c3Schristos   void
2997ed0d50c3Schristos   emit_relocs_scan(Symbol_table* symtab,
2998ed0d50c3Schristos 		   Layout* layout,
2999ed0d50c3Schristos 		   Sized_relobj_file<size, big_endian>* object,
3000ed0d50c3Schristos 		   unsigned int data_shndx,
3001ed0d50c3Schristos 		   unsigned int sh_type,
3002ed0d50c3Schristos 		   const unsigned char* prelocs,
3003ed0d50c3Schristos 		   size_t reloc_count,
3004ed0d50c3Schristos 		   Output_section* output_section,
3005ed0d50c3Schristos 		   bool needs_special_offset_handling,
3006ed0d50c3Schristos 		   size_t local_symbol_count,
3007ed0d50c3Schristos 		   const unsigned char* plocal_syms,
3008ed0d50c3Schristos 		   Relocatable_relocs* rr);
3009ed0d50c3Schristos 
3010ed0d50c3Schristos   // Relocate a section during a relocatable link.
3011ed0d50c3Schristos   void
3012ed0d50c3Schristos   relocate_relocs(
3013ed0d50c3Schristos       const Relocate_info<size, big_endian>*,
3014ed0d50c3Schristos       unsigned int sh_type,
3015ed0d50c3Schristos       const unsigned char* prelocs,
3016ed0d50c3Schristos       size_t reloc_count,
3017ed0d50c3Schristos       Output_section* output_section,
3018ed0d50c3Schristos       typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,
3019ed0d50c3Schristos       unsigned char* view,
3020ed0d50c3Schristos       typename elfcpp::Elf_types<size>::Elf_Addr view_address,
3021ed0d50c3Schristos       section_size_type view_size,
3022ed0d50c3Schristos       unsigned char* reloc_view,
3023ed0d50c3Schristos       section_size_type reloc_view_size);
3024ed0d50c3Schristos 
3025ed0d50c3Schristos   // Return the symbol index to use for a target specific relocation.
3026ed0d50c3Schristos   // The only target specific relocation is R_AARCH64_TLSDESC for a
3027ed0d50c3Schristos   // local symbol, which is an absolute reloc.
3028ed0d50c3Schristos   unsigned int
do_reloc_symbol_index(void *,unsigned int r_type) const3029ed0d50c3Schristos   do_reloc_symbol_index(void*, unsigned int r_type) const
3030ed0d50c3Schristos   {
3031ed0d50c3Schristos     gold_assert(r_type == elfcpp::R_AARCH64_TLSDESC);
3032ed0d50c3Schristos     return 0;
3033ed0d50c3Schristos   }
3034ed0d50c3Schristos 
3035ed0d50c3Schristos   // Return the addend to use for a target specific relocation.
3036ed0d50c3Schristos   uint64_t
3037ed0d50c3Schristos   do_reloc_addend(void* arg, unsigned int r_type, uint64_t addend) const;
3038ed0d50c3Schristos 
3039ed0d50c3Schristos   // Return the PLT section.
3040ed0d50c3Schristos   uint64_t
do_plt_address_for_global(const Symbol * gsym) const3041ed0d50c3Schristos   do_plt_address_for_global(const Symbol* gsym) const
3042ed0d50c3Schristos   { return this->plt_section()->address_for_global(gsym); }
3043ed0d50c3Schristos 
3044ed0d50c3Schristos   uint64_t
do_plt_address_for_local(const Relobj * relobj,unsigned int symndx) const3045ed0d50c3Schristos   do_plt_address_for_local(const Relobj* relobj, unsigned int symndx) const
3046ed0d50c3Schristos   { return this->plt_section()->address_for_local(relobj, symndx); }
3047ed0d50c3Schristos 
3048ed0d50c3Schristos   // This function should be defined in targets that can use relocation
3049ed0d50c3Schristos   // types to determine (implemented in local_reloc_may_be_function_pointer
3050ed0d50c3Schristos   // and global_reloc_may_be_function_pointer)
3051ed0d50c3Schristos   // if a function's pointer is taken.  ICF uses this in safe mode to only
3052ed0d50c3Schristos   // fold those functions whose pointer is defintely not taken.
3053ed0d50c3Schristos   bool
do_can_check_for_function_pointers() const3054ed0d50c3Schristos   do_can_check_for_function_pointers() const
3055ed0d50c3Schristos   { return true; }
3056ed0d50c3Schristos 
3057ed0d50c3Schristos   // Return the number of entries in the PLT.
3058ed0d50c3Schristos   unsigned int
3059ed0d50c3Schristos   plt_entry_count() const;
3060ed0d50c3Schristos 
3061ed0d50c3Schristos   //Return the offset of the first non-reserved PLT entry.
3062ed0d50c3Schristos   unsigned int
3063ed0d50c3Schristos   first_plt_entry_offset() const;
3064ed0d50c3Schristos 
3065ed0d50c3Schristos   // Return the size of each PLT entry.
3066ed0d50c3Schristos   unsigned int
3067ed0d50c3Schristos   plt_entry_size() const;
3068ed0d50c3Schristos 
3069ed0d50c3Schristos   // Create a stub table.
3070ed0d50c3Schristos   The_stub_table*
3071ed0d50c3Schristos   new_stub_table(The_aarch64_input_section*);
3072ed0d50c3Schristos 
3073ed0d50c3Schristos   // Create an aarch64 input section.
3074ed0d50c3Schristos   The_aarch64_input_section*
3075ed0d50c3Schristos   new_aarch64_input_section(Relobj*, unsigned int);
3076ed0d50c3Schristos 
3077ed0d50c3Schristos   // Find an aarch64 input section instance for a given OBJ and SHNDX.
3078ed0d50c3Schristos   The_aarch64_input_section*
3079ed0d50c3Schristos   find_aarch64_input_section(Relobj*, unsigned int) const;
3080ed0d50c3Schristos 
3081ed0d50c3Schristos   // Return the thread control block size.
3082ed0d50c3Schristos   unsigned int
tcb_size() const3083ed0d50c3Schristos   tcb_size() const { return This::TCB_SIZE; }
3084ed0d50c3Schristos 
3085ed0d50c3Schristos   // Scan a section for stub generation.
3086ed0d50c3Schristos   void
3087ed0d50c3Schristos   scan_section_for_stubs(const Relocate_info<size, big_endian>*, unsigned int,
3088ed0d50c3Schristos 			 const unsigned char*, size_t, Output_section*,
3089ed0d50c3Schristos 			 bool, const unsigned char*,
3090ed0d50c3Schristos 			 Address,
3091ed0d50c3Schristos 			 section_size_type);
3092ed0d50c3Schristos 
3093ed0d50c3Schristos   // Scan a relocation section for stub.
3094ed0d50c3Schristos   template<int sh_type>
3095ed0d50c3Schristos   void
3096ed0d50c3Schristos   scan_reloc_section_for_stubs(
3097ed0d50c3Schristos       const The_relocate_info* relinfo,
3098ed0d50c3Schristos       const unsigned char* prelocs,
3099ed0d50c3Schristos       size_t reloc_count,
3100ed0d50c3Schristos       Output_section* output_section,
3101ed0d50c3Schristos       bool needs_special_offset_handling,
3102ed0d50c3Schristos       const unsigned char* view,
3103ed0d50c3Schristos       Address view_address,
3104ed0d50c3Schristos       section_size_type);
3105ed0d50c3Schristos 
310606324dcfSchristos   // Relocate a single reloc stub.
3107ed0d50c3Schristos   void
310806324dcfSchristos   relocate_reloc_stub(The_reloc_stub*, const Relocate_info<size, big_endian>*,
3109ed0d50c3Schristos                       Output_section*, unsigned char*, Address,
3110ed0d50c3Schristos                       section_size_type);
3111ed0d50c3Schristos 
3112ed0d50c3Schristos   // Get the default AArch64 target.
3113ed0d50c3Schristos   static This*
current_target()3114ed0d50c3Schristos   current_target()
3115ed0d50c3Schristos   {
3116ed0d50c3Schristos     gold_assert(parameters->target().machine_code() == elfcpp::EM_AARCH64
3117ed0d50c3Schristos 		&& parameters->target().get_size() == size
3118ed0d50c3Schristos 		&& parameters->target().is_big_endian() == big_endian);
3119ed0d50c3Schristos     return static_cast<This*>(parameters->sized_target<size, big_endian>());
3120ed0d50c3Schristos   }
3121ed0d50c3Schristos 
3122ed0d50c3Schristos 
3123ed0d50c3Schristos   // Scan erratum 843419 for a part of a section.
3124ed0d50c3Schristos   void
3125ed0d50c3Schristos   scan_erratum_843419_span(
3126ed0d50c3Schristos     AArch64_relobj<size, big_endian>*,
3127ed0d50c3Schristos     unsigned int,
3128ed0d50c3Schristos     const section_size_type,
3129ed0d50c3Schristos     const section_size_type,
3130ed0d50c3Schristos     unsigned char*,
3131ed0d50c3Schristos     Address);
3132ed0d50c3Schristos 
3133ed0d50c3Schristos   // Scan erratum 835769 for a part of a section.
3134ed0d50c3Schristos   void
3135ed0d50c3Schristos   scan_erratum_835769_span(
3136ed0d50c3Schristos     AArch64_relobj<size, big_endian>*,
3137ed0d50c3Schristos     unsigned int,
3138ed0d50c3Schristos     const section_size_type,
3139ed0d50c3Schristos     const section_size_type,
3140ed0d50c3Schristos     unsigned char*,
3141ed0d50c3Schristos     Address);
3142ed0d50c3Schristos 
3143ed0d50c3Schristos  protected:
3144ed0d50c3Schristos   void
do_select_as_default_target()3145ed0d50c3Schristos   do_select_as_default_target()
3146ed0d50c3Schristos   {
3147ed0d50c3Schristos     gold_assert(aarch64_reloc_property_table == NULL);
3148ed0d50c3Schristos     aarch64_reloc_property_table = new AArch64_reloc_property_table();
3149ed0d50c3Schristos   }
3150ed0d50c3Schristos 
3151ed0d50c3Schristos   // Add a new reloc argument, returning the index in the vector.
3152ed0d50c3Schristos   size_t
add_tlsdesc_info(Sized_relobj_file<size,big_endian> * object,unsigned int r_sym)3153ed0d50c3Schristos   add_tlsdesc_info(Sized_relobj_file<size, big_endian>* object,
3154ed0d50c3Schristos 		   unsigned int r_sym)
3155ed0d50c3Schristos   {
3156ed0d50c3Schristos     this->tlsdesc_reloc_info_.push_back(Tlsdesc_info(object, r_sym));
3157ed0d50c3Schristos     return this->tlsdesc_reloc_info_.size() - 1;
3158ed0d50c3Schristos   }
3159ed0d50c3Schristos 
3160ed0d50c3Schristos   virtual Output_data_plt_aarch64<size, big_endian>*
do_make_data_plt(Layout * layout,Output_data_got_aarch64<size,big_endian> * got,Output_data_space * got_plt,Output_data_space * got_irelative)3161ed0d50c3Schristos   do_make_data_plt(Layout* layout,
3162ed0d50c3Schristos 		   Output_data_got_aarch64<size, big_endian>* got,
3163ed0d50c3Schristos 		   Output_data_space* got_plt,
3164ed0d50c3Schristos 		   Output_data_space* got_irelative)
3165ed0d50c3Schristos   {
3166ed0d50c3Schristos     return new Output_data_plt_aarch64_standard<size, big_endian>(
3167ed0d50c3Schristos       layout, got, got_plt, got_irelative);
3168ed0d50c3Schristos   }
3169ed0d50c3Schristos 
3170ed0d50c3Schristos 
3171ed0d50c3Schristos   // do_make_elf_object to override the same function in the base class.
3172ed0d50c3Schristos   Object*
3173ed0d50c3Schristos   do_make_elf_object(const std::string&, Input_file*, off_t,
3174ed0d50c3Schristos 		     const elfcpp::Ehdr<size, big_endian>&);
3175ed0d50c3Schristos 
3176ed0d50c3Schristos   Output_data_plt_aarch64<size, big_endian>*
make_data_plt(Layout * layout,Output_data_got_aarch64<size,big_endian> * got,Output_data_space * got_plt,Output_data_space * got_irelative)3177ed0d50c3Schristos   make_data_plt(Layout* layout,
3178ed0d50c3Schristos 		Output_data_got_aarch64<size, big_endian>* got,
3179ed0d50c3Schristos 		Output_data_space* got_plt,
3180ed0d50c3Schristos 		Output_data_space* got_irelative)
3181ed0d50c3Schristos   {
3182ed0d50c3Schristos     return this->do_make_data_plt(layout, got, got_plt, got_irelative);
3183ed0d50c3Schristos   }
3184ed0d50c3Schristos 
3185ed0d50c3Schristos   // We only need to generate stubs, and hence perform relaxation if we are
3186ed0d50c3Schristos   // not doing relocatable linking.
3187ed0d50c3Schristos   virtual bool
do_may_relax() const3188ed0d50c3Schristos   do_may_relax() const
3189ed0d50c3Schristos   { return !parameters->options().relocatable(); }
3190ed0d50c3Schristos 
3191ed0d50c3Schristos   // Relaxation hook.  This is where we do stub generation.
3192ed0d50c3Schristos   virtual bool
3193ed0d50c3Schristos   do_relax(int, const Input_objects*, Symbol_table*, Layout*, const Task*);
3194ed0d50c3Schristos 
3195ed0d50c3Schristos   void
3196ed0d50c3Schristos   group_sections(Layout* layout,
3197ed0d50c3Schristos 		 section_size_type group_size,
3198ed0d50c3Schristos 		 bool stubs_always_after_branch,
3199ed0d50c3Schristos 		 const Task* task);
3200ed0d50c3Schristos 
3201ed0d50c3Schristos   void
3202ed0d50c3Schristos   scan_reloc_for_stub(const The_relocate_info*, unsigned int,
3203ed0d50c3Schristos 		      const Sized_symbol<size>*, unsigned int,
3204ed0d50c3Schristos 		      const Symbol_value<size>*,
3205ed0d50c3Schristos 		      typename elfcpp::Elf_types<size>::Elf_Swxword,
3206ed0d50c3Schristos 		      Address Elf_Addr);
3207ed0d50c3Schristos 
3208ed0d50c3Schristos   // Make an output section.
3209ed0d50c3Schristos   Output_section*
do_make_output_section(const char * name,elfcpp::Elf_Word type,elfcpp::Elf_Xword flags)3210ed0d50c3Schristos   do_make_output_section(const char* name, elfcpp::Elf_Word type,
3211ed0d50c3Schristos 			 elfcpp::Elf_Xword flags)
3212ed0d50c3Schristos   { return new The_aarch64_output_section(name, type, flags); }
3213ed0d50c3Schristos 
3214ed0d50c3Schristos  private:
3215ed0d50c3Schristos   // The class which scans relocations.
3216ed0d50c3Schristos   class Scan
3217ed0d50c3Schristos   {
3218ed0d50c3Schristos   public:
Scan()3219ed0d50c3Schristos     Scan()
3220ed0d50c3Schristos       : issued_non_pic_error_(false)
3221ed0d50c3Schristos     { }
3222ed0d50c3Schristos 
3223ed0d50c3Schristos     inline void
3224ed0d50c3Schristos     local(Symbol_table* symtab, Layout* layout, Target_aarch64* target,
3225ed0d50c3Schristos 	  Sized_relobj_file<size, big_endian>* object,
3226ed0d50c3Schristos 	  unsigned int data_shndx,
3227ed0d50c3Schristos 	  Output_section* output_section,
3228ed0d50c3Schristos 	  const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
3229ed0d50c3Schristos 	  const elfcpp::Sym<size, big_endian>& lsym,
3230ed0d50c3Schristos 	  bool is_discarded);
3231ed0d50c3Schristos 
3232ed0d50c3Schristos     inline void
3233ed0d50c3Schristos     global(Symbol_table* symtab, Layout* layout, Target_aarch64* target,
3234ed0d50c3Schristos 	   Sized_relobj_file<size, big_endian>* object,
3235ed0d50c3Schristos 	   unsigned int data_shndx,
3236ed0d50c3Schristos 	   Output_section* output_section,
3237ed0d50c3Schristos 	   const elfcpp::Rela<size, big_endian>& reloc, unsigned int r_type,
3238ed0d50c3Schristos 	   Symbol* gsym);
3239ed0d50c3Schristos 
3240ed0d50c3Schristos     inline bool
3241ed0d50c3Schristos     local_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
3242ed0d50c3Schristos 					Target_aarch64<size, big_endian>* ,
3243ed0d50c3Schristos 					Sized_relobj_file<size, big_endian>* ,
3244ed0d50c3Schristos 					unsigned int ,
3245ed0d50c3Schristos 					Output_section* ,
3246ed0d50c3Schristos 					const elfcpp::Rela<size, big_endian>& ,
3247ed0d50c3Schristos 					unsigned int r_type,
3248ed0d50c3Schristos 					const elfcpp::Sym<size, big_endian>&);
3249ed0d50c3Schristos 
3250ed0d50c3Schristos     inline bool
3251ed0d50c3Schristos     global_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
3252ed0d50c3Schristos 					 Target_aarch64<size, big_endian>* ,
3253ed0d50c3Schristos 					 Sized_relobj_file<size, big_endian>* ,
3254ed0d50c3Schristos 					 unsigned int ,
3255ed0d50c3Schristos 					 Output_section* ,
3256ed0d50c3Schristos 					 const elfcpp::Rela<size, big_endian>& ,
3257ed0d50c3Schristos 					 unsigned int r_type,
3258ed0d50c3Schristos 					 Symbol* gsym);
3259ed0d50c3Schristos 
3260ed0d50c3Schristos   private:
3261ed0d50c3Schristos     static void
3262ed0d50c3Schristos     unsupported_reloc_local(Sized_relobj_file<size, big_endian>*,
3263ed0d50c3Schristos 			    unsigned int r_type);
3264ed0d50c3Schristos 
3265ed0d50c3Schristos     static void
3266ed0d50c3Schristos     unsupported_reloc_global(Sized_relobj_file<size, big_endian>*,
3267ed0d50c3Schristos 			     unsigned int r_type, Symbol*);
3268ed0d50c3Schristos 
3269ed0d50c3Schristos     inline bool
3270ed0d50c3Schristos     possible_function_pointer_reloc(unsigned int r_type);
3271ed0d50c3Schristos 
3272ed0d50c3Schristos     void
3273ed0d50c3Schristos     check_non_pic(Relobj*, unsigned int r_type);
3274ed0d50c3Schristos 
3275ed0d50c3Schristos     bool
3276ed0d50c3Schristos     reloc_needs_plt_for_ifunc(Sized_relobj_file<size, big_endian>*,
3277ed0d50c3Schristos 			      unsigned int r_type);
3278ed0d50c3Schristos 
3279ed0d50c3Schristos     // Whether we have issued an error about a non-PIC compilation.
3280ed0d50c3Schristos     bool issued_non_pic_error_;
3281ed0d50c3Schristos   };
3282ed0d50c3Schristos 
3283ed0d50c3Schristos   // The class which implements relocation.
3284ed0d50c3Schristos   class Relocate
3285ed0d50c3Schristos   {
3286ed0d50c3Schristos    public:
Relocate()3287ed0d50c3Schristos     Relocate()
3288ed0d50c3Schristos       : skip_call_tls_get_addr_(false)
3289ed0d50c3Schristos     { }
3290ed0d50c3Schristos 
~Relocate()3291ed0d50c3Schristos     ~Relocate()
3292ed0d50c3Schristos     { }
3293ed0d50c3Schristos 
3294ed0d50c3Schristos     // Do a relocation.  Return false if the caller should not issue
3295ed0d50c3Schristos     // any warnings about this relocation.
3296ed0d50c3Schristos     inline bool
3297ed0d50c3Schristos     relocate(const Relocate_info<size, big_endian>*, unsigned int,
3298ed0d50c3Schristos 	     Target_aarch64*, Output_section*, size_t, const unsigned char*,
3299ed0d50c3Schristos 	     const Sized_symbol<size>*, const Symbol_value<size>*,
3300ed0d50c3Schristos 	     unsigned char*, typename elfcpp::Elf_types<size>::Elf_Addr,
3301ed0d50c3Schristos 	     section_size_type);
3302ed0d50c3Schristos 
3303ed0d50c3Schristos   private:
3304ed0d50c3Schristos     inline typename AArch64_relocate_functions<size, big_endian>::Status
3305ed0d50c3Schristos     relocate_tls(const Relocate_info<size, big_endian>*,
3306ed0d50c3Schristos 		 Target_aarch64<size, big_endian>*,
3307ed0d50c3Schristos 		 size_t,
3308ed0d50c3Schristos 		 const elfcpp::Rela<size, big_endian>&,
3309ed0d50c3Schristos 		 unsigned int r_type, const Sized_symbol<size>*,
3310ed0d50c3Schristos 		 const Symbol_value<size>*,
3311ed0d50c3Schristos 		 unsigned char*,
3312ed0d50c3Schristos 		 typename elfcpp::Elf_types<size>::Elf_Addr);
3313ed0d50c3Schristos 
3314ed0d50c3Schristos     inline typename AArch64_relocate_functions<size, big_endian>::Status
3315ed0d50c3Schristos     tls_gd_to_le(
3316ed0d50c3Schristos 		 const Relocate_info<size, big_endian>*,
3317ed0d50c3Schristos 		 Target_aarch64<size, big_endian>*,
3318ed0d50c3Schristos 		 const elfcpp::Rela<size, big_endian>&,
3319ed0d50c3Schristos 		 unsigned int,
3320ed0d50c3Schristos 		 unsigned char*,
3321ed0d50c3Schristos 		 const Symbol_value<size>*);
3322ed0d50c3Schristos 
3323ed0d50c3Schristos     inline typename AArch64_relocate_functions<size, big_endian>::Status
3324ed0d50c3Schristos     tls_ld_to_le(
3325ed0d50c3Schristos 		 const Relocate_info<size, big_endian>*,
3326ed0d50c3Schristos 		 Target_aarch64<size, big_endian>*,
3327ed0d50c3Schristos 		 const elfcpp::Rela<size, big_endian>&,
3328ed0d50c3Schristos 		 unsigned int,
3329ed0d50c3Schristos 		 unsigned char*,
3330ed0d50c3Schristos 		 const Symbol_value<size>*);
3331ed0d50c3Schristos 
3332ed0d50c3Schristos     inline typename AArch64_relocate_functions<size, big_endian>::Status
3333ed0d50c3Schristos     tls_ie_to_le(
3334ed0d50c3Schristos 		 const Relocate_info<size, big_endian>*,
3335ed0d50c3Schristos 		 Target_aarch64<size, big_endian>*,
3336ed0d50c3Schristos 		 const elfcpp::Rela<size, big_endian>&,
3337ed0d50c3Schristos 		 unsigned int,
3338ed0d50c3Schristos 		 unsigned char*,
3339ed0d50c3Schristos 		 const Symbol_value<size>*);
3340ed0d50c3Schristos 
3341ed0d50c3Schristos     inline typename AArch64_relocate_functions<size, big_endian>::Status
3342ed0d50c3Schristos     tls_desc_gd_to_le(
3343ed0d50c3Schristos 		 const Relocate_info<size, big_endian>*,
3344ed0d50c3Schristos 		 Target_aarch64<size, big_endian>*,
3345ed0d50c3Schristos 		 const elfcpp::Rela<size, big_endian>&,
3346ed0d50c3Schristos 		 unsigned int,
3347ed0d50c3Schristos 		 unsigned char*,
3348ed0d50c3Schristos 		 const Symbol_value<size>*);
3349ed0d50c3Schristos 
3350ed0d50c3Schristos     inline typename AArch64_relocate_functions<size, big_endian>::Status
3351ed0d50c3Schristos     tls_desc_gd_to_ie(
3352ed0d50c3Schristos 		 const Relocate_info<size, big_endian>*,
3353ed0d50c3Schristos 		 Target_aarch64<size, big_endian>*,
3354ed0d50c3Schristos 		 const elfcpp::Rela<size, big_endian>&,
3355ed0d50c3Schristos 		 unsigned int,
3356ed0d50c3Schristos 		 unsigned char*,
3357ed0d50c3Schristos 		 const Symbol_value<size>*,
3358ed0d50c3Schristos 		 typename elfcpp::Elf_types<size>::Elf_Addr,
3359ed0d50c3Schristos 		 typename elfcpp::Elf_types<size>::Elf_Addr);
3360ed0d50c3Schristos 
3361ed0d50c3Schristos     bool skip_call_tls_get_addr_;
3362ed0d50c3Schristos 
3363ed0d50c3Schristos   };  // End of class Relocate
3364ed0d50c3Schristos 
3365ed0d50c3Schristos   // Adjust TLS relocation type based on the options and whether this
3366ed0d50c3Schristos   // is a local symbol.
3367ed0d50c3Schristos   static tls::Tls_optimization
3368ed0d50c3Schristos   optimize_tls_reloc(bool is_final, int r_type);
3369ed0d50c3Schristos 
3370ed0d50c3Schristos   // Get the GOT section, creating it if necessary.
3371ed0d50c3Schristos   Output_data_got_aarch64<size, big_endian>*
3372ed0d50c3Schristos   got_section(Symbol_table*, Layout*);
3373ed0d50c3Schristos 
3374ed0d50c3Schristos   // Get the GOT PLT section.
3375ed0d50c3Schristos   Output_data_space*
got_plt_section() const3376ed0d50c3Schristos   got_plt_section() const
3377ed0d50c3Schristos   {
3378ed0d50c3Schristos     gold_assert(this->got_plt_ != NULL);
3379ed0d50c3Schristos     return this->got_plt_;
3380ed0d50c3Schristos   }
3381ed0d50c3Schristos 
3382ed0d50c3Schristos   // Get the GOT section for TLSDESC entries.
3383ed0d50c3Schristos   Output_data_got<size, big_endian>*
got_tlsdesc_section() const3384ed0d50c3Schristos   got_tlsdesc_section() const
3385ed0d50c3Schristos   {
3386ed0d50c3Schristos     gold_assert(this->got_tlsdesc_ != NULL);
3387ed0d50c3Schristos     return this->got_tlsdesc_;
3388ed0d50c3Schristos   }
3389ed0d50c3Schristos 
3390ed0d50c3Schristos   // Create the PLT section.
3391ed0d50c3Schristos   void
3392ed0d50c3Schristos   make_plt_section(Symbol_table* symtab, Layout* layout);
3393ed0d50c3Schristos 
3394ed0d50c3Schristos   // Create a PLT entry for a global symbol.
3395ed0d50c3Schristos   void
3396ed0d50c3Schristos   make_plt_entry(Symbol_table*, Layout*, Symbol*);
3397ed0d50c3Schristos 
3398ed0d50c3Schristos   // Create a PLT entry for a local STT_GNU_IFUNC symbol.
3399ed0d50c3Schristos   void
3400ed0d50c3Schristos   make_local_ifunc_plt_entry(Symbol_table*, Layout*,
3401ed0d50c3Schristos 			     Sized_relobj_file<size, big_endian>* relobj,
3402ed0d50c3Schristos 			     unsigned int local_sym_index);
3403ed0d50c3Schristos 
3404ed0d50c3Schristos   // Define the _TLS_MODULE_BASE_ symbol in the TLS segment.
3405ed0d50c3Schristos   void
3406ed0d50c3Schristos   define_tls_base_symbol(Symbol_table*, Layout*);
3407ed0d50c3Schristos 
3408ed0d50c3Schristos   // Create the reserved PLT and GOT entries for the TLS descriptor resolver.
3409ed0d50c3Schristos   void
3410ed0d50c3Schristos   reserve_tlsdesc_entries(Symbol_table* symtab, Layout* layout);
3411ed0d50c3Schristos 
3412ed0d50c3Schristos   // Create a GOT entry for the TLS module index.
3413ed0d50c3Schristos   unsigned int
3414ed0d50c3Schristos   got_mod_index_entry(Symbol_table* symtab, Layout* layout,
3415ed0d50c3Schristos 		      Sized_relobj_file<size, big_endian>* object);
3416ed0d50c3Schristos 
3417ed0d50c3Schristos   // Get the PLT section.
3418ed0d50c3Schristos   Output_data_plt_aarch64<size, big_endian>*
plt_section() const3419ed0d50c3Schristos   plt_section() const
3420ed0d50c3Schristos   {
3421ed0d50c3Schristos     gold_assert(this->plt_ != NULL);
3422ed0d50c3Schristos     return this->plt_;
3423ed0d50c3Schristos   }
3424ed0d50c3Schristos 
3425ed0d50c3Schristos   // Helper method to create erratum stubs for ST_E_843419 and ST_E_835769. For
3426ed0d50c3Schristos   // ST_E_843419, we need an additional field for adrp offset.
3427ed0d50c3Schristos   void create_erratum_stub(
3428ed0d50c3Schristos     AArch64_relobj<size, big_endian>* relobj,
3429ed0d50c3Schristos     unsigned int shndx,
3430ed0d50c3Schristos     section_size_type erratum_insn_offset,
3431ed0d50c3Schristos     Address erratum_address,
3432ed0d50c3Schristos     typename Insn_utilities::Insntype erratum_insn,
3433ed0d50c3Schristos     int erratum_type,
3434ed0d50c3Schristos     unsigned int e843419_adrp_offset=0);
3435ed0d50c3Schristos 
3436ed0d50c3Schristos   // Return whether this is a 3-insn erratum sequence.
3437ed0d50c3Schristos   bool is_erratum_843419_sequence(
3438ed0d50c3Schristos       typename elfcpp::Swap<32,big_endian>::Valtype insn1,
3439ed0d50c3Schristos       typename elfcpp::Swap<32,big_endian>::Valtype insn2,
3440ed0d50c3Schristos       typename elfcpp::Swap<32,big_endian>::Valtype insn3);
3441ed0d50c3Schristos 
3442ed0d50c3Schristos   // Return whether this is a 835769 sequence.
3443ed0d50c3Schristos   // (Similarly implemented as in elfnn-aarch64.c.)
3444ed0d50c3Schristos   bool is_erratum_835769_sequence(
3445ed0d50c3Schristos       typename elfcpp::Swap<32,big_endian>::Valtype,
3446ed0d50c3Schristos       typename elfcpp::Swap<32,big_endian>::Valtype);
3447ed0d50c3Schristos 
3448ed0d50c3Schristos   // Get the dynamic reloc section, creating it if necessary.
3449ed0d50c3Schristos   Reloc_section*
3450ed0d50c3Schristos   rela_dyn_section(Layout*);
3451ed0d50c3Schristos 
3452ed0d50c3Schristos   // Get the section to use for TLSDESC relocations.
3453ed0d50c3Schristos   Reloc_section*
3454ed0d50c3Schristos   rela_tlsdesc_section(Layout*) const;
3455ed0d50c3Schristos 
3456ed0d50c3Schristos   // Get the section to use for IRELATIVE relocations.
3457ed0d50c3Schristos   Reloc_section*
3458ed0d50c3Schristos   rela_irelative_section(Layout*);
3459ed0d50c3Schristos 
3460ed0d50c3Schristos   // Add a potential copy relocation.
3461ed0d50c3Schristos   void
copy_reloc(Symbol_table * symtab,Layout * layout,Sized_relobj_file<size,big_endian> * object,unsigned int shndx,Output_section * output_section,Symbol * sym,const elfcpp::Rela<size,big_endian> & reloc)3462ed0d50c3Schristos   copy_reloc(Symbol_table* symtab, Layout* layout,
3463ed0d50c3Schristos 	     Sized_relobj_file<size, big_endian>* object,
3464ed0d50c3Schristos 	     unsigned int shndx, Output_section* output_section,
3465ed0d50c3Schristos 	     Symbol* sym, const elfcpp::Rela<size, big_endian>& reloc)
3466ed0d50c3Schristos   {
3467ed0d50c3Schristos     unsigned int r_type = elfcpp::elf_r_type<size>(reloc.get_r_info());
3468ed0d50c3Schristos     this->copy_relocs_.copy_reloc(symtab, layout,
3469ed0d50c3Schristos 				  symtab->get_sized_symbol<size>(sym),
3470ed0d50c3Schristos 				  object, shndx, output_section,
3471ed0d50c3Schristos 				  r_type, reloc.get_r_offset(),
3472ed0d50c3Schristos 				  reloc.get_r_addend(),
3473ed0d50c3Schristos 				  this->rela_dyn_section(layout));
3474ed0d50c3Schristos   }
3475ed0d50c3Schristos 
3476ed0d50c3Schristos   // Information about this specific target which we pass to the
3477ed0d50c3Schristos   // general Target structure.
3478ed0d50c3Schristos   static const Target::Target_info aarch64_info;
3479ed0d50c3Schristos 
3480ed0d50c3Schristos   // The types of GOT entries needed for this platform.
3481ed0d50c3Schristos   // These values are exposed to the ABI in an incremental link.
3482ed0d50c3Schristos   // Do not renumber existing values without changing the version
3483ed0d50c3Schristos   // number of the .gnu_incremental_inputs section.
3484ed0d50c3Schristos   enum Got_type
3485ed0d50c3Schristos   {
3486ed0d50c3Schristos     GOT_TYPE_STANDARD = 0,      // GOT entry for a regular symbol
3487ed0d50c3Schristos     GOT_TYPE_TLS_OFFSET = 1,    // GOT entry for TLS offset
3488ed0d50c3Schristos     GOT_TYPE_TLS_PAIR = 2,      // GOT entry for TLS module/offset pair
3489ed0d50c3Schristos     GOT_TYPE_TLS_DESC = 3       // GOT entry for TLS_DESC pair
3490ed0d50c3Schristos   };
3491ed0d50c3Schristos 
3492ed0d50c3Schristos   // This type is used as the argument to the target specific
3493ed0d50c3Schristos   // relocation routines.  The only target specific reloc is
3494ed0d50c3Schristos   // R_AARCh64_TLSDESC against a local symbol.
3495ed0d50c3Schristos   struct Tlsdesc_info
3496ed0d50c3Schristos   {
Tlsdesc_info__anond8ca3b600111::Target_aarch64::Tlsdesc_info3497ed0d50c3Schristos     Tlsdesc_info(Sized_relobj_file<size, big_endian>* a_object,
3498ed0d50c3Schristos 		 unsigned int a_r_sym)
3499ed0d50c3Schristos       : object(a_object), r_sym(a_r_sym)
3500ed0d50c3Schristos     { }
3501ed0d50c3Schristos 
3502ed0d50c3Schristos     // The object in which the local symbol is defined.
3503ed0d50c3Schristos     Sized_relobj_file<size, big_endian>* object;
3504ed0d50c3Schristos     // The local symbol index in the object.
3505ed0d50c3Schristos     unsigned int r_sym;
3506ed0d50c3Schristos   };
3507ed0d50c3Schristos 
3508ed0d50c3Schristos   // The GOT section.
3509ed0d50c3Schristos   Output_data_got_aarch64<size, big_endian>* got_;
3510ed0d50c3Schristos   // The PLT section.
3511ed0d50c3Schristos   Output_data_plt_aarch64<size, big_endian>* plt_;
3512ed0d50c3Schristos   // The GOT PLT section.
3513ed0d50c3Schristos   Output_data_space* got_plt_;
3514ed0d50c3Schristos   // The GOT section for IRELATIVE relocations.
3515ed0d50c3Schristos   Output_data_space* got_irelative_;
3516ed0d50c3Schristos   // The GOT section for TLSDESC relocations.
3517ed0d50c3Schristos   Output_data_got<size, big_endian>* got_tlsdesc_;
3518ed0d50c3Schristos   // The _GLOBAL_OFFSET_TABLE_ symbol.
3519ed0d50c3Schristos   Symbol* global_offset_table_;
3520ed0d50c3Schristos   // The dynamic reloc section.
3521ed0d50c3Schristos   Reloc_section* rela_dyn_;
3522ed0d50c3Schristos   // The section to use for IRELATIVE relocs.
3523ed0d50c3Schristos   Reloc_section* rela_irelative_;
3524ed0d50c3Schristos   // Relocs saved to avoid a COPY reloc.
3525ed0d50c3Schristos   Copy_relocs<elfcpp::SHT_RELA, size, big_endian> copy_relocs_;
3526ed0d50c3Schristos   // Offset of the GOT entry for the TLS module index.
3527ed0d50c3Schristos   unsigned int got_mod_index_offset_;
3528ed0d50c3Schristos   // We handle R_AARCH64_TLSDESC against a local symbol as a target
3529ed0d50c3Schristos   // specific relocation. Here we store the object and local symbol
3530ed0d50c3Schristos   // index for the relocation.
3531ed0d50c3Schristos   std::vector<Tlsdesc_info> tlsdesc_reloc_info_;
3532ed0d50c3Schristos   // True if the _TLS_MODULE_BASE_ symbol has been defined.
3533ed0d50c3Schristos   bool tls_base_symbol_defined_;
3534ed0d50c3Schristos   // List of stub_tables
3535ed0d50c3Schristos   Stub_table_list stub_tables_;
3536ed0d50c3Schristos   // Actual stub group size
3537ed0d50c3Schristos   section_size_type stub_group_size_;
3538ed0d50c3Schristos   AArch64_input_section_map aarch64_input_section_map_;
3539ed0d50c3Schristos };  // End of Target_aarch64
3540ed0d50c3Schristos 
3541ed0d50c3Schristos 
3542ed0d50c3Schristos template<>
3543ed0d50c3Schristos const Target::Target_info Target_aarch64<64, false>::aarch64_info =
3544ed0d50c3Schristos {
3545ed0d50c3Schristos   64,			// size
3546ed0d50c3Schristos   false,		// is_big_endian
3547ed0d50c3Schristos   elfcpp::EM_AARCH64,	// machine_code
3548ed0d50c3Schristos   false,		// has_make_symbol
3549ed0d50c3Schristos   false,		// has_resolve
3550ed0d50c3Schristos   false,		// has_code_fill
355106324dcfSchristos   false,		// is_default_stack_executable
3552ed0d50c3Schristos   true,			// can_icf_inline_merge_sections
3553ed0d50c3Schristos   '\0',			// wrap_char
3554ed0d50c3Schristos   "/lib/ld.so.1",	// program interpreter
3555ed0d50c3Schristos   0x400000,		// default_text_segment_address
3556ed0d50c3Schristos   0x10000,		// abi_pagesize (overridable by -z max-page-size)
3557ed0d50c3Schristos   0x1000,		// common_pagesize (overridable by -z common-page-size)
3558ed0d50c3Schristos   false,                // isolate_execinstr
3559ed0d50c3Schristos   0,                    // rosegment_gap
3560ed0d50c3Schristos   elfcpp::SHN_UNDEF,	// small_common_shndx
3561ed0d50c3Schristos   elfcpp::SHN_UNDEF,	// large_common_shndx
3562ed0d50c3Schristos   0,			// small_common_section_flags
3563ed0d50c3Schristos   0,			// large_common_section_flags
3564ed0d50c3Schristos   NULL,			// attributes_section
3565ed0d50c3Schristos   NULL,			// attributes_vendor
3566ed0d50c3Schristos   "_start",		// entry_symbol_name
3567ed0d50c3Schristos   32,			// hash_entry_size
356806324dcfSchristos   elfcpp::SHT_PROGBITS,	// unwind_section_type
3569ed0d50c3Schristos };
3570ed0d50c3Schristos 
3571ed0d50c3Schristos template<>
3572ed0d50c3Schristos const Target::Target_info Target_aarch64<32, false>::aarch64_info =
3573ed0d50c3Schristos {
3574ed0d50c3Schristos   32,			// size
3575ed0d50c3Schristos   false,		// is_big_endian
3576ed0d50c3Schristos   elfcpp::EM_AARCH64,	// machine_code
3577ed0d50c3Schristos   false,		// has_make_symbol
3578ed0d50c3Schristos   false,		// has_resolve
3579ed0d50c3Schristos   false,		// has_code_fill
358006324dcfSchristos   false,		// is_default_stack_executable
3581ed0d50c3Schristos   false,		// can_icf_inline_merge_sections
3582ed0d50c3Schristos   '\0',			// wrap_char
3583ed0d50c3Schristos   "/lib/ld.so.1",	// program interpreter
3584ed0d50c3Schristos   0x400000,		// default_text_segment_address
3585ed0d50c3Schristos   0x10000,		// abi_pagesize (overridable by -z max-page-size)
3586ed0d50c3Schristos   0x1000,		// common_pagesize (overridable by -z common-page-size)
3587ed0d50c3Schristos   false,                // isolate_execinstr
3588ed0d50c3Schristos   0,                    // rosegment_gap
3589ed0d50c3Schristos   elfcpp::SHN_UNDEF,	// small_common_shndx
3590ed0d50c3Schristos   elfcpp::SHN_UNDEF,	// large_common_shndx
3591ed0d50c3Schristos   0,			// small_common_section_flags
3592ed0d50c3Schristos   0,			// large_common_section_flags
3593ed0d50c3Schristos   NULL,			// attributes_section
3594ed0d50c3Schristos   NULL,			// attributes_vendor
3595ed0d50c3Schristos   "_start",		// entry_symbol_name
3596ed0d50c3Schristos   32,			// hash_entry_size
359706324dcfSchristos   elfcpp::SHT_PROGBITS,	// unwind_section_type
3598ed0d50c3Schristos };
3599ed0d50c3Schristos 
3600ed0d50c3Schristos template<>
3601ed0d50c3Schristos const Target::Target_info Target_aarch64<64, true>::aarch64_info =
3602ed0d50c3Schristos {
3603ed0d50c3Schristos   64,			// size
3604ed0d50c3Schristos   true,			// is_big_endian
3605ed0d50c3Schristos   elfcpp::EM_AARCH64,	// machine_code
3606ed0d50c3Schristos   false,		// has_make_symbol
3607ed0d50c3Schristos   false,		// has_resolve
3608ed0d50c3Schristos   false,		// has_code_fill
360906324dcfSchristos   false,		// is_default_stack_executable
3610ed0d50c3Schristos   true,			// can_icf_inline_merge_sections
3611ed0d50c3Schristos   '\0',			// wrap_char
3612ed0d50c3Schristos   "/lib/ld.so.1",	// program interpreter
3613ed0d50c3Schristos   0x400000,		// default_text_segment_address
3614ed0d50c3Schristos   0x10000,		// abi_pagesize (overridable by -z max-page-size)
3615ed0d50c3Schristos   0x1000,		// common_pagesize (overridable by -z common-page-size)
3616ed0d50c3Schristos   false,                // isolate_execinstr
3617ed0d50c3Schristos   0,                    // rosegment_gap
3618ed0d50c3Schristos   elfcpp::SHN_UNDEF,	// small_common_shndx
3619ed0d50c3Schristos   elfcpp::SHN_UNDEF,	// large_common_shndx
3620ed0d50c3Schristos   0,			// small_common_section_flags
3621ed0d50c3Schristos   0,			// large_common_section_flags
3622ed0d50c3Schristos   NULL,			// attributes_section
3623ed0d50c3Schristos   NULL,			// attributes_vendor
3624ed0d50c3Schristos   "_start",		// entry_symbol_name
3625ed0d50c3Schristos   32,			// hash_entry_size
362606324dcfSchristos   elfcpp::SHT_PROGBITS,	// unwind_section_type
3627ed0d50c3Schristos };
3628ed0d50c3Schristos 
3629ed0d50c3Schristos template<>
3630ed0d50c3Schristos const Target::Target_info Target_aarch64<32, true>::aarch64_info =
3631ed0d50c3Schristos {
3632ed0d50c3Schristos   32,			// size
3633ed0d50c3Schristos   true,			// is_big_endian
3634ed0d50c3Schristos   elfcpp::EM_AARCH64,	// machine_code
3635ed0d50c3Schristos   false,		// has_make_symbol
3636ed0d50c3Schristos   false,		// has_resolve
3637ed0d50c3Schristos   false,		// has_code_fill
363806324dcfSchristos   false,		// is_default_stack_executable
3639ed0d50c3Schristos   false,		// can_icf_inline_merge_sections
3640ed0d50c3Schristos   '\0',			// wrap_char
3641ed0d50c3Schristos   "/lib/ld.so.1",	// program interpreter
3642ed0d50c3Schristos   0x400000,		// default_text_segment_address
3643ed0d50c3Schristos   0x10000,		// abi_pagesize (overridable by -z max-page-size)
3644ed0d50c3Schristos   0x1000,		// common_pagesize (overridable by -z common-page-size)
3645ed0d50c3Schristos   false,                // isolate_execinstr
3646ed0d50c3Schristos   0,                    // rosegment_gap
3647ed0d50c3Schristos   elfcpp::SHN_UNDEF,	// small_common_shndx
3648ed0d50c3Schristos   elfcpp::SHN_UNDEF,	// large_common_shndx
3649ed0d50c3Schristos   0,			// small_common_section_flags
3650ed0d50c3Schristos   0,			// large_common_section_flags
3651ed0d50c3Schristos   NULL,			// attributes_section
3652ed0d50c3Schristos   NULL,			// attributes_vendor
3653ed0d50c3Schristos   "_start",		// entry_symbol_name
3654ed0d50c3Schristos   32,			// hash_entry_size
365506324dcfSchristos   elfcpp::SHT_PROGBITS,	// unwind_section_type
3656ed0d50c3Schristos };
3657ed0d50c3Schristos 
3658ed0d50c3Schristos // Get the GOT section, creating it if necessary.
3659ed0d50c3Schristos 
3660ed0d50c3Schristos template<int size, bool big_endian>
3661ed0d50c3Schristos Output_data_got_aarch64<size, big_endian>*
got_section(Symbol_table * symtab,Layout * layout)3662ed0d50c3Schristos Target_aarch64<size, big_endian>::got_section(Symbol_table* symtab,
3663ed0d50c3Schristos 					      Layout* layout)
3664ed0d50c3Schristos {
3665ed0d50c3Schristos   if (this->got_ == NULL)
3666ed0d50c3Schristos     {
3667ed0d50c3Schristos       gold_assert(symtab != NULL && layout != NULL);
3668ed0d50c3Schristos 
3669ed0d50c3Schristos       // When using -z now, we can treat .got.plt as a relro section.
3670ed0d50c3Schristos       // Without -z now, it is modified after program startup by lazy
3671ed0d50c3Schristos       // PLT relocations.
3672ed0d50c3Schristos       bool is_got_plt_relro = parameters->options().now();
3673ed0d50c3Schristos       Output_section_order got_order = (is_got_plt_relro
3674ed0d50c3Schristos 					? ORDER_RELRO
3675ed0d50c3Schristos 					: ORDER_RELRO_LAST);
3676ed0d50c3Schristos       Output_section_order got_plt_order = (is_got_plt_relro
3677ed0d50c3Schristos 					    ? ORDER_RELRO
3678ed0d50c3Schristos 					    : ORDER_NON_RELRO_FIRST);
3679ed0d50c3Schristos 
3680ed0d50c3Schristos       // Layout of .got and .got.plt sections.
3681ed0d50c3Schristos       // .got[0] &_DYNAMIC                          <-_GLOBAL_OFFSET_TABLE_
3682ed0d50c3Schristos       // ...
3683ed0d50c3Schristos       // .gotplt[0] reserved for ld.so (&linkmap)   <--DT_PLTGOT
3684ed0d50c3Schristos       // .gotplt[1] reserved for ld.so (resolver)
3685ed0d50c3Schristos       // .gotplt[2] reserved
3686ed0d50c3Schristos 
3687ed0d50c3Schristos       // Generate .got section.
3688ed0d50c3Schristos       this->got_ = new Output_data_got_aarch64<size, big_endian>(symtab,
3689ed0d50c3Schristos 								 layout);
3690ed0d50c3Schristos       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
3691ed0d50c3Schristos 				      (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE),
3692ed0d50c3Schristos 				      this->got_, got_order, true);
3693ed0d50c3Schristos       // The first word of GOT is reserved for the address of .dynamic.
3694ed0d50c3Schristos       // We put 0 here now. The value will be replaced later in
3695ed0d50c3Schristos       // Output_data_got_aarch64::do_write.
3696ed0d50c3Schristos       this->got_->add_constant(0);
3697ed0d50c3Schristos 
3698ed0d50c3Schristos       // Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT.
3699ed0d50c3Schristos       // _GLOBAL_OFFSET_TABLE_ value points to the start of the .got section,
3700ed0d50c3Schristos       // even if there is a .got.plt section.
3701ed0d50c3Schristos       this->global_offset_table_ =
3702ed0d50c3Schristos 	symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL,
3703ed0d50c3Schristos 				      Symbol_table::PREDEFINED,
3704ed0d50c3Schristos 				      this->got_,
3705ed0d50c3Schristos 				      0, 0, elfcpp::STT_OBJECT,
3706ed0d50c3Schristos 				      elfcpp::STB_LOCAL,
3707ed0d50c3Schristos 				      elfcpp::STV_HIDDEN, 0,
3708ed0d50c3Schristos 				      false, false);
3709ed0d50c3Schristos 
3710ed0d50c3Schristos       // Generate .got.plt section.
3711ed0d50c3Schristos       this->got_plt_ = new Output_data_space(size / 8, "** GOT PLT");
3712ed0d50c3Schristos       layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
3713ed0d50c3Schristos 				      (elfcpp::SHF_ALLOC
3714ed0d50c3Schristos 				       | elfcpp::SHF_WRITE),
3715ed0d50c3Schristos 				      this->got_plt_, got_plt_order,
3716ed0d50c3Schristos 				      is_got_plt_relro);
3717ed0d50c3Schristos 
3718ed0d50c3Schristos       // The first three entries are reserved.
3719ed0d50c3Schristos       this->got_plt_->set_current_data_size(
3720ed0d50c3Schristos 	AARCH64_GOTPLT_RESERVE_COUNT * (size / 8));
3721ed0d50c3Schristos 
3722ed0d50c3Schristos       // If there are any IRELATIVE relocations, they get GOT entries
3723ed0d50c3Schristos       // in .got.plt after the jump slot entries.
3724ed0d50c3Schristos       this->got_irelative_ = new Output_data_space(size / 8,
3725ed0d50c3Schristos 						   "** GOT IRELATIVE PLT");
3726ed0d50c3Schristos       layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
3727ed0d50c3Schristos 				      (elfcpp::SHF_ALLOC
3728ed0d50c3Schristos 				       | elfcpp::SHF_WRITE),
3729ed0d50c3Schristos 				      this->got_irelative_,
3730ed0d50c3Schristos 				      got_plt_order,
3731ed0d50c3Schristos 				      is_got_plt_relro);
3732ed0d50c3Schristos 
3733ed0d50c3Schristos       // If there are any TLSDESC relocations, they get GOT entries in
3734ed0d50c3Schristos       // .got.plt after the jump slot and IRELATIVE entries.
3735ed0d50c3Schristos       this->got_tlsdesc_ = new Output_data_got<size, big_endian>();
3736ed0d50c3Schristos       layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
3737ed0d50c3Schristos 				      (elfcpp::SHF_ALLOC
3738ed0d50c3Schristos 				       | elfcpp::SHF_WRITE),
3739ed0d50c3Schristos 				      this->got_tlsdesc_,
3740ed0d50c3Schristos 				      got_plt_order,
3741ed0d50c3Schristos 				      is_got_plt_relro);
3742ed0d50c3Schristos 
3743ed0d50c3Schristos       if (!is_got_plt_relro)
3744ed0d50c3Schristos 	{
3745ed0d50c3Schristos 	  // Those bytes can go into the relro segment.
3746ed0d50c3Schristos 	  layout->increase_relro(
3747ed0d50c3Schristos 	    AARCH64_GOTPLT_RESERVE_COUNT * (size / 8));
3748ed0d50c3Schristos 	}
3749ed0d50c3Schristos 
3750ed0d50c3Schristos     }
3751ed0d50c3Schristos   return this->got_;
3752ed0d50c3Schristos }
3753ed0d50c3Schristos 
3754ed0d50c3Schristos // Get the dynamic reloc section, creating it if necessary.
3755ed0d50c3Schristos 
3756ed0d50c3Schristos template<int size, bool big_endian>
3757ed0d50c3Schristos typename Target_aarch64<size, big_endian>::Reloc_section*
rela_dyn_section(Layout * layout)3758ed0d50c3Schristos Target_aarch64<size, big_endian>::rela_dyn_section(Layout* layout)
3759ed0d50c3Schristos {
3760ed0d50c3Schristos   if (this->rela_dyn_ == NULL)
3761ed0d50c3Schristos     {
3762ed0d50c3Schristos       gold_assert(layout != NULL);
3763ed0d50c3Schristos       this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
3764ed0d50c3Schristos       layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
3765ed0d50c3Schristos 				      elfcpp::SHF_ALLOC, this->rela_dyn_,
3766ed0d50c3Schristos 				      ORDER_DYNAMIC_RELOCS, false);
3767ed0d50c3Schristos     }
3768ed0d50c3Schristos   return this->rela_dyn_;
3769ed0d50c3Schristos }
3770ed0d50c3Schristos 
3771ed0d50c3Schristos // Get the section to use for IRELATIVE relocs, creating it if
3772ed0d50c3Schristos // necessary.  These go in .rela.dyn, but only after all other dynamic
3773ed0d50c3Schristos // relocations.  They need to follow the other dynamic relocations so
3774ed0d50c3Schristos // that they can refer to global variables initialized by those
3775ed0d50c3Schristos // relocs.
3776ed0d50c3Schristos 
3777ed0d50c3Schristos template<int size, bool big_endian>
3778ed0d50c3Schristos typename Target_aarch64<size, big_endian>::Reloc_section*
rela_irelative_section(Layout * layout)3779ed0d50c3Schristos Target_aarch64<size, big_endian>::rela_irelative_section(Layout* layout)
3780ed0d50c3Schristos {
3781ed0d50c3Schristos   if (this->rela_irelative_ == NULL)
3782ed0d50c3Schristos     {
3783ed0d50c3Schristos       // Make sure we have already created the dynamic reloc section.
3784ed0d50c3Schristos       this->rela_dyn_section(layout);
3785ed0d50c3Schristos       this->rela_irelative_ = new Reloc_section(false);
3786ed0d50c3Schristos       layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
3787ed0d50c3Schristos 				      elfcpp::SHF_ALLOC, this->rela_irelative_,
3788ed0d50c3Schristos 				      ORDER_DYNAMIC_RELOCS, false);
3789ed0d50c3Schristos       gold_assert(this->rela_dyn_->output_section()
3790ed0d50c3Schristos 		  == this->rela_irelative_->output_section());
3791ed0d50c3Schristos     }
3792ed0d50c3Schristos   return this->rela_irelative_;
3793ed0d50c3Schristos }
3794ed0d50c3Schristos 
3795ed0d50c3Schristos 
3796ed0d50c3Schristos // do_make_elf_object to override the same function in the base class.  We need
3797ed0d50c3Schristos // to use a target-specific sub-class of Sized_relobj_file<size, big_endian> to
3798ed0d50c3Schristos // store backend specific information. Hence we need to have our own ELF object
3799ed0d50c3Schristos // creation.
3800ed0d50c3Schristos 
3801ed0d50c3Schristos template<int size, bool big_endian>
3802ed0d50c3Schristos Object*
do_make_elf_object(const std::string & name,Input_file * input_file,off_t offset,const elfcpp::Ehdr<size,big_endian> & ehdr)3803ed0d50c3Schristos Target_aarch64<size, big_endian>::do_make_elf_object(
3804ed0d50c3Schristos     const std::string& name,
3805ed0d50c3Schristos     Input_file* input_file,
3806ed0d50c3Schristos     off_t offset, const elfcpp::Ehdr<size, big_endian>& ehdr)
3807ed0d50c3Schristos {
3808ed0d50c3Schristos   int et = ehdr.get_e_type();
3809ed0d50c3Schristos   // ET_EXEC files are valid input for --just-symbols/-R,
3810ed0d50c3Schristos   // and we treat them as relocatable objects.
3811ed0d50c3Schristos   if (et == elfcpp::ET_EXEC && input_file->just_symbols())
3812ed0d50c3Schristos     return Sized_target<size, big_endian>::do_make_elf_object(
3813ed0d50c3Schristos 	name, input_file, offset, ehdr);
3814ed0d50c3Schristos   else if (et == elfcpp::ET_REL)
3815ed0d50c3Schristos     {
3816ed0d50c3Schristos       AArch64_relobj<size, big_endian>* obj =
3817ed0d50c3Schristos 	new AArch64_relobj<size, big_endian>(name, input_file, offset, ehdr);
3818ed0d50c3Schristos       obj->setup();
3819ed0d50c3Schristos       return obj;
3820ed0d50c3Schristos     }
3821ed0d50c3Schristos   else if (et == elfcpp::ET_DYN)
3822ed0d50c3Schristos     {
3823ed0d50c3Schristos       // Keep base implementation.
3824ed0d50c3Schristos       Sized_dynobj<size, big_endian>* obj =
3825ed0d50c3Schristos 	  new Sized_dynobj<size, big_endian>(name, input_file, offset, ehdr);
3826ed0d50c3Schristos       obj->setup();
3827ed0d50c3Schristos       return obj;
3828ed0d50c3Schristos     }
3829ed0d50c3Schristos   else
3830ed0d50c3Schristos     {
3831ed0d50c3Schristos       gold_error(_("%s: unsupported ELF file type %d"),
3832ed0d50c3Schristos 		 name.c_str(), et);
3833ed0d50c3Schristos       return NULL;
3834ed0d50c3Schristos     }
3835ed0d50c3Schristos }
3836ed0d50c3Schristos 
3837ed0d50c3Schristos 
3838ed0d50c3Schristos // Scan a relocation for stub generation.
3839ed0d50c3Schristos 
3840ed0d50c3Schristos template<int size, bool big_endian>
3841ed0d50c3Schristos void
scan_reloc_for_stub(const Relocate_info<size,big_endian> * relinfo,unsigned int r_type,const Sized_symbol<size> * gsym,unsigned int r_sym,const Symbol_value<size> * psymval,typename elfcpp::Elf_types<size>::Elf_Swxword addend,Address address)3842ed0d50c3Schristos Target_aarch64<size, big_endian>::scan_reloc_for_stub(
3843ed0d50c3Schristos     const Relocate_info<size, big_endian>* relinfo,
3844ed0d50c3Schristos     unsigned int r_type,
3845ed0d50c3Schristos     const Sized_symbol<size>* gsym,
3846ed0d50c3Schristos     unsigned int r_sym,
3847ed0d50c3Schristos     const Symbol_value<size>* psymval,
3848ed0d50c3Schristos     typename elfcpp::Elf_types<size>::Elf_Swxword addend,
3849ed0d50c3Schristos     Address address)
3850ed0d50c3Schristos {
3851ed0d50c3Schristos   const AArch64_relobj<size, big_endian>* aarch64_relobj =
3852ed0d50c3Schristos       static_cast<AArch64_relobj<size, big_endian>*>(relinfo->object);
3853ed0d50c3Schristos 
3854ed0d50c3Schristos   Symbol_value<size> symval;
3855ed0d50c3Schristos   if (gsym != NULL)
3856ed0d50c3Schristos     {
3857ed0d50c3Schristos       const AArch64_reloc_property* arp = aarch64_reloc_property_table->
3858ed0d50c3Schristos 	get_reloc_property(r_type);
3859ed0d50c3Schristos       if (gsym->use_plt_offset(arp->reference_flags()))
3860ed0d50c3Schristos 	{
3861ed0d50c3Schristos 	  // This uses a PLT, change the symbol value.
386206324dcfSchristos 	  symval.set_output_value(this->plt_address_for_global(gsym));
3863ed0d50c3Schristos 	  psymval = &symval;
3864ed0d50c3Schristos 	}
3865ed0d50c3Schristos       else if (gsym->is_undefined())
386606324dcfSchristos 	{
386706324dcfSchristos           // There is no need to generate a stub symbol if the original symbol
386806324dcfSchristos           // is undefined.
386906324dcfSchristos           gold_debug(DEBUG_TARGET,
387006324dcfSchristos                      "stub: not creating a stub for undefined symbol %s in file %s",
387106324dcfSchristos                      gsym->name(), aarch64_relobj->name().c_str());
3872ed0d50c3Schristos           return;
3873ed0d50c3Schristos 	}
387406324dcfSchristos     }
3875ed0d50c3Schristos 
3876ed0d50c3Schristos   // Get the symbol value.
3877ed0d50c3Schristos   typename Symbol_value<size>::Value value = psymval->value(aarch64_relobj, 0);
3878ed0d50c3Schristos 
3879ed0d50c3Schristos   // Owing to pipelining, the PC relative branches below actually skip
3880ed0d50c3Schristos   // two instructions when the branch offset is 0.
3881ed0d50c3Schristos   Address destination = static_cast<Address>(-1);
3882ed0d50c3Schristos   switch (r_type)
3883ed0d50c3Schristos     {
3884ed0d50c3Schristos     case elfcpp::R_AARCH64_CALL26:
3885ed0d50c3Schristos     case elfcpp::R_AARCH64_JUMP26:
3886ed0d50c3Schristos       destination = value + addend;
3887ed0d50c3Schristos       break;
3888ed0d50c3Schristos     default:
3889ed0d50c3Schristos       gold_unreachable();
3890ed0d50c3Schristos     }
3891ed0d50c3Schristos 
3892ed0d50c3Schristos   int stub_type = The_reloc_stub::
3893ed0d50c3Schristos       stub_type_for_reloc(r_type, address, destination);
3894ed0d50c3Schristos   if (stub_type == ST_NONE)
3895ed0d50c3Schristos     return;
3896ed0d50c3Schristos 
3897ed0d50c3Schristos   The_stub_table* stub_table = aarch64_relobj->stub_table(relinfo->data_shndx);
3898ed0d50c3Schristos   gold_assert(stub_table != NULL);
3899ed0d50c3Schristos 
3900ed0d50c3Schristos   The_reloc_stub_key key(stub_type, gsym, aarch64_relobj, r_sym, addend);
3901ed0d50c3Schristos   The_reloc_stub* stub = stub_table->find_reloc_stub(key);
3902ed0d50c3Schristos   if (stub == NULL)
3903ed0d50c3Schristos     {
3904ed0d50c3Schristos       stub = new The_reloc_stub(stub_type);
3905ed0d50c3Schristos       stub_table->add_reloc_stub(stub, key);
3906ed0d50c3Schristos     }
3907ed0d50c3Schristos   stub->set_destination_address(destination);
3908ed0d50c3Schristos }  // End of Target_aarch64::scan_reloc_for_stub
3909ed0d50c3Schristos 
3910ed0d50c3Schristos 
3911ed0d50c3Schristos // This function scans a relocation section for stub generation.
3912ed0d50c3Schristos // The template parameter Relocate must be a class type which provides
3913ed0d50c3Schristos // a single function, relocate(), which implements the machine
3914ed0d50c3Schristos // specific part of a relocation.
3915ed0d50c3Schristos 
3916ed0d50c3Schristos // BIG_ENDIAN is the endianness of the data.  SH_TYPE is the section type:
3917ed0d50c3Schristos // SHT_REL or SHT_RELA.
3918ed0d50c3Schristos 
3919ed0d50c3Schristos // PRELOCS points to the relocation data.  RELOC_COUNT is the number
3920ed0d50c3Schristos // of relocs.  OUTPUT_SECTION is the output section.
3921ed0d50c3Schristos // NEEDS_SPECIAL_OFFSET_HANDLING is true if input offsets need to be
3922ed0d50c3Schristos // mapped to output offsets.
3923ed0d50c3Schristos 
3924ed0d50c3Schristos // VIEW is the section data, VIEW_ADDRESS is its memory address, and
3925ed0d50c3Schristos // VIEW_SIZE is the size.  These refer to the input section, unless
3926ed0d50c3Schristos // NEEDS_SPECIAL_OFFSET_HANDLING is true, in which case they refer to
3927ed0d50c3Schristos // the output section.
3928ed0d50c3Schristos 
3929ed0d50c3Schristos template<int size, bool big_endian>
3930ed0d50c3Schristos template<int sh_type>
3931ed0d50c3Schristos void inline
scan_reloc_section_for_stubs(const Relocate_info<size,big_endian> * relinfo,const unsigned char * prelocs,size_t reloc_count,Output_section *,bool,const unsigned char *,Address view_address,section_size_type)3932ed0d50c3Schristos Target_aarch64<size, big_endian>::scan_reloc_section_for_stubs(
3933ed0d50c3Schristos     const Relocate_info<size, big_endian>* relinfo,
3934ed0d50c3Schristos     const unsigned char* prelocs,
3935ed0d50c3Schristos     size_t reloc_count,
3936ed0d50c3Schristos     Output_section* /*output_section*/,
3937ed0d50c3Schristos     bool /*needs_special_offset_handling*/,
3938ed0d50c3Schristos     const unsigned char* /*view*/,
3939ed0d50c3Schristos     Address view_address,
3940ed0d50c3Schristos     section_size_type)
3941ed0d50c3Schristos {
3942ed0d50c3Schristos   typedef typename Reloc_types<sh_type,size,big_endian>::Reloc Reltype;
3943ed0d50c3Schristos 
3944ed0d50c3Schristos   const int reloc_size =
3945ed0d50c3Schristos       Reloc_types<sh_type,size,big_endian>::reloc_size;
3946ed0d50c3Schristos   AArch64_relobj<size, big_endian>* object =
3947ed0d50c3Schristos       static_cast<AArch64_relobj<size, big_endian>*>(relinfo->object);
3948ed0d50c3Schristos   unsigned int local_count = object->local_symbol_count();
3949ed0d50c3Schristos 
3950ed0d50c3Schristos   gold::Default_comdat_behavior default_comdat_behavior;
3951ed0d50c3Schristos   Comdat_behavior comdat_behavior = CB_UNDETERMINED;
3952ed0d50c3Schristos 
3953ed0d50c3Schristos   for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
3954ed0d50c3Schristos     {
3955ed0d50c3Schristos       Reltype reloc(prelocs);
3956ed0d50c3Schristos       typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
3957ed0d50c3Schristos       unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
3958ed0d50c3Schristos       unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
3959ed0d50c3Schristos       if (r_type != elfcpp::R_AARCH64_CALL26
3960ed0d50c3Schristos 	  && r_type != elfcpp::R_AARCH64_JUMP26)
3961ed0d50c3Schristos 	continue;
3962ed0d50c3Schristos 
3963ed0d50c3Schristos       section_offset_type offset =
3964ed0d50c3Schristos 	  convert_to_section_size_type(reloc.get_r_offset());
3965ed0d50c3Schristos 
3966ed0d50c3Schristos       // Get the addend.
3967ed0d50c3Schristos       typename elfcpp::Elf_types<size>::Elf_Swxword addend =
3968ed0d50c3Schristos 	  reloc.get_r_addend();
3969ed0d50c3Schristos 
3970ed0d50c3Schristos       const Sized_symbol<size>* sym;
3971ed0d50c3Schristos       Symbol_value<size> symval;
3972ed0d50c3Schristos       const Symbol_value<size> *psymval;
3973ed0d50c3Schristos       bool is_defined_in_discarded_section;
3974ed0d50c3Schristos       unsigned int shndx;
397506324dcfSchristos       const Symbol* gsym = NULL;
3976ed0d50c3Schristos       if (r_sym < local_count)
3977ed0d50c3Schristos 	{
3978ed0d50c3Schristos 	  sym = NULL;
3979ed0d50c3Schristos 	  psymval = object->local_symbol(r_sym);
3980ed0d50c3Schristos 
3981ed0d50c3Schristos 	  // If the local symbol belongs to a section we are discarding,
3982ed0d50c3Schristos 	  // and that section is a debug section, try to find the
3983ed0d50c3Schristos 	  // corresponding kept section and map this symbol to its
3984ed0d50c3Schristos 	  // counterpart in the kept section.  The symbol must not
3985ed0d50c3Schristos 	  // correspond to a section we are folding.
3986ed0d50c3Schristos 	  bool is_ordinary;
3987ed0d50c3Schristos 	  shndx = psymval->input_shndx(&is_ordinary);
3988ed0d50c3Schristos 	  is_defined_in_discarded_section =
3989ed0d50c3Schristos 	    (is_ordinary
3990ed0d50c3Schristos 	     && shndx != elfcpp::SHN_UNDEF
3991ed0d50c3Schristos 	     && !object->is_section_included(shndx)
3992ed0d50c3Schristos 	     && !relinfo->symtab->is_section_folded(object, shndx));
3993ed0d50c3Schristos 
3994ed0d50c3Schristos 	  // We need to compute the would-be final value of this local
3995ed0d50c3Schristos 	  // symbol.
3996ed0d50c3Schristos 	  if (!is_defined_in_discarded_section)
3997ed0d50c3Schristos 	    {
3998ed0d50c3Schristos 	      typedef Sized_relobj_file<size, big_endian> ObjType;
399906324dcfSchristos 	      if (psymval->is_section_symbol())
400006324dcfSchristos 		symval.set_is_section_symbol();
4001ed0d50c3Schristos 	      typename ObjType::Compute_final_local_value_status status =
4002ed0d50c3Schristos 		object->compute_final_local_value(r_sym, psymval, &symval,
4003ed0d50c3Schristos 						  relinfo->symtab);
4004ed0d50c3Schristos 	      if (status == ObjType::CFLV_OK)
4005ed0d50c3Schristos 		{
4006ed0d50c3Schristos 		  // Currently we cannot handle a branch to a target in
4007ed0d50c3Schristos 		  // a merged section.  If this is the case, issue an error
4008ed0d50c3Schristos 		  // and also free the merge symbol value.
4009ed0d50c3Schristos 		  if (!symval.has_output_value())
4010ed0d50c3Schristos 		    {
4011ed0d50c3Schristos 		      const std::string& section_name =
4012ed0d50c3Schristos 			object->section_name(shndx);
4013ed0d50c3Schristos 		      object->error(_("cannot handle branch to local %u "
4014ed0d50c3Schristos 					  "in a merged section %s"),
4015ed0d50c3Schristos 					r_sym, section_name.c_str());
4016ed0d50c3Schristos 		    }
4017ed0d50c3Schristos 		  psymval = &symval;
4018ed0d50c3Schristos 		}
4019ed0d50c3Schristos 	      else
4020ed0d50c3Schristos 		{
4021ed0d50c3Schristos 		  // We cannot determine the final value.
4022ed0d50c3Schristos 		  continue;
4023ed0d50c3Schristos 		}
4024ed0d50c3Schristos 	    }
4025ed0d50c3Schristos 	}
4026ed0d50c3Schristos       else
4027ed0d50c3Schristos 	{
4028ed0d50c3Schristos 	  gsym = object->global_symbol(r_sym);
4029ed0d50c3Schristos 	  gold_assert(gsym != NULL);
4030ed0d50c3Schristos 	  if (gsym->is_forwarder())
4031ed0d50c3Schristos 	    gsym = relinfo->symtab->resolve_forwards(gsym);
4032ed0d50c3Schristos 
4033ed0d50c3Schristos 	  sym = static_cast<const Sized_symbol<size>*>(gsym);
4034ed0d50c3Schristos 	  if (sym->has_symtab_index() && sym->symtab_index() != -1U)
4035ed0d50c3Schristos 	    symval.set_output_symtab_index(sym->symtab_index());
4036ed0d50c3Schristos 	  else
4037ed0d50c3Schristos 	    symval.set_no_output_symtab_entry();
4038ed0d50c3Schristos 
4039ed0d50c3Schristos 	  // We need to compute the would-be final value of this global
4040ed0d50c3Schristos 	  // symbol.
4041ed0d50c3Schristos 	  const Symbol_table* symtab = relinfo->symtab;
4042ed0d50c3Schristos 	  const Sized_symbol<size>* sized_symbol =
4043ed0d50c3Schristos 	      symtab->get_sized_symbol<size>(gsym);
4044ed0d50c3Schristos 	  Symbol_table::Compute_final_value_status status;
4045ed0d50c3Schristos 	  typename elfcpp::Elf_types<size>::Elf_Addr value =
4046ed0d50c3Schristos 	      symtab->compute_final_value<size>(sized_symbol, &status);
4047ed0d50c3Schristos 
4048ed0d50c3Schristos 	  // Skip this if the symbol has not output section.
4049ed0d50c3Schristos 	  if (status == Symbol_table::CFVS_NO_OUTPUT_SECTION)
4050ed0d50c3Schristos 	    continue;
4051ed0d50c3Schristos 	  symval.set_output_value(value);
4052ed0d50c3Schristos 
4053ed0d50c3Schristos 	  if (gsym->type() == elfcpp::STT_TLS)
4054ed0d50c3Schristos 	    symval.set_is_tls_symbol();
4055ed0d50c3Schristos 	  else if (gsym->type() == elfcpp::STT_GNU_IFUNC)
4056ed0d50c3Schristos 	    symval.set_is_ifunc_symbol();
4057ed0d50c3Schristos 	  psymval = &symval;
4058ed0d50c3Schristos 
4059ed0d50c3Schristos 	  is_defined_in_discarded_section =
4060ed0d50c3Schristos 	      (gsym->is_defined_in_discarded_section()
4061ed0d50c3Schristos 	       && gsym->is_undefined());
4062ed0d50c3Schristos 	  shndx = 0;
4063ed0d50c3Schristos 	}
4064ed0d50c3Schristos 
4065ed0d50c3Schristos       Symbol_value<size> symval2;
4066ed0d50c3Schristos       if (is_defined_in_discarded_section)
4067ed0d50c3Schristos 	{
4068ed0d50c3Schristos 	  std::string name = object->section_name(relinfo->data_shndx);
406906324dcfSchristos 
407006324dcfSchristos 	  if (comdat_behavior == CB_UNDETERMINED)
4071ed0d50c3Schristos 	      comdat_behavior = default_comdat_behavior.get(name.c_str());
407206324dcfSchristos 
4073ed0d50c3Schristos 	  if (comdat_behavior == CB_PRETEND)
4074ed0d50c3Schristos 	    {
4075ed0d50c3Schristos 	      bool found;
4076ed0d50c3Schristos 	      typename elfcpp::Elf_types<size>::Elf_Addr value =
407706324dcfSchristos 		object->map_to_kept_section(shndx, name, &found);
4078ed0d50c3Schristos 	      if (found)
4079ed0d50c3Schristos 		symval2.set_output_value(value + psymval->input_value());
4080ed0d50c3Schristos 	      else
4081ed0d50c3Schristos 		symval2.set_output_value(0);
4082ed0d50c3Schristos 	    }
4083ed0d50c3Schristos 	  else
4084ed0d50c3Schristos 	    {
408506324dcfSchristos 	      if (comdat_behavior == CB_ERROR)
408606324dcfSchristos 	        issue_discarded_error(relinfo, i, offset, r_sym, gsym);
4087ed0d50c3Schristos 	      symval2.set_output_value(0);
4088ed0d50c3Schristos 	    }
4089ed0d50c3Schristos 	  symval2.set_no_output_symtab_entry();
4090ed0d50c3Schristos 	  psymval = &symval2;
4091ed0d50c3Schristos 	}
4092ed0d50c3Schristos 
4093ed0d50c3Schristos       this->scan_reloc_for_stub(relinfo, r_type, sym, r_sym, psymval,
4094ed0d50c3Schristos 				addend, view_address + offset);
4095ed0d50c3Schristos     }  // End of iterating relocs in a section
4096ed0d50c3Schristos }  // End of Target_aarch64::scan_reloc_section_for_stubs
4097ed0d50c3Schristos 
4098ed0d50c3Schristos 
4099ed0d50c3Schristos // Scan an input section for stub generation.
4100ed0d50c3Schristos 
4101ed0d50c3Schristos template<int size, bool big_endian>
4102ed0d50c3Schristos void
scan_section_for_stubs(const Relocate_info<size,big_endian> * relinfo,unsigned int sh_type,const unsigned char * prelocs,size_t reloc_count,Output_section * output_section,bool needs_special_offset_handling,const unsigned char * view,Address view_address,section_size_type view_size)4103ed0d50c3Schristos Target_aarch64<size, big_endian>::scan_section_for_stubs(
4104ed0d50c3Schristos     const Relocate_info<size, big_endian>* relinfo,
4105ed0d50c3Schristos     unsigned int sh_type,
4106ed0d50c3Schristos     const unsigned char* prelocs,
4107ed0d50c3Schristos     size_t reloc_count,
4108ed0d50c3Schristos     Output_section* output_section,
4109ed0d50c3Schristos     bool needs_special_offset_handling,
4110ed0d50c3Schristos     const unsigned char* view,
4111ed0d50c3Schristos     Address view_address,
4112ed0d50c3Schristos     section_size_type view_size)
4113ed0d50c3Schristos {
4114ed0d50c3Schristos   gold_assert(sh_type == elfcpp::SHT_RELA);
4115ed0d50c3Schristos   this->scan_reloc_section_for_stubs<elfcpp::SHT_RELA>(
4116ed0d50c3Schristos       relinfo,
4117ed0d50c3Schristos       prelocs,
4118ed0d50c3Schristos       reloc_count,
4119ed0d50c3Schristos       output_section,
4120ed0d50c3Schristos       needs_special_offset_handling,
4121ed0d50c3Schristos       view,
4122ed0d50c3Schristos       view_address,
4123ed0d50c3Schristos       view_size);
4124ed0d50c3Schristos }
4125ed0d50c3Schristos 
4126ed0d50c3Schristos 
412706324dcfSchristos // Relocate a single reloc stub.
4128ed0d50c3Schristos 
4129ed0d50c3Schristos template<int size, bool big_endian>
4130ed0d50c3Schristos void Target_aarch64<size, big_endian>::
relocate_reloc_stub(The_reloc_stub * stub,const The_relocate_info *,Output_section *,unsigned char * view,Address address,section_size_type)413106324dcfSchristos relocate_reloc_stub(The_reloc_stub* stub,
4132ed0d50c3Schristos                     const The_relocate_info*,
4133ed0d50c3Schristos                     Output_section*,
4134ed0d50c3Schristos                     unsigned char* view,
4135ed0d50c3Schristos                     Address address,
4136ed0d50c3Schristos                     section_size_type)
4137ed0d50c3Schristos {
4138ed0d50c3Schristos   typedef AArch64_relocate_functions<size, big_endian> The_reloc_functions;
4139ed0d50c3Schristos   typedef typename The_reloc_functions::Status The_reloc_functions_status;
4140ed0d50c3Schristos   typedef typename elfcpp::Swap<32,big_endian>::Valtype Insntype;
4141ed0d50c3Schristos 
4142ed0d50c3Schristos   Insntype* ip = reinterpret_cast<Insntype*>(view);
4143ed0d50c3Schristos   int insn_number = stub->insn_num();
4144ed0d50c3Schristos   const uint32_t* insns = stub->insns();
4145ed0d50c3Schristos   // Check the insns are really those stub insns.
4146ed0d50c3Schristos   for (int i = 0; i < insn_number; ++i)
4147ed0d50c3Schristos     {
4148ed0d50c3Schristos       Insntype insn = elfcpp::Swap<32,big_endian>::readval(ip + i);
4149ed0d50c3Schristos       gold_assert(((uint32_t)insn == insns[i]));
4150ed0d50c3Schristos     }
4151ed0d50c3Schristos 
4152ed0d50c3Schristos   Address dest = stub->destination_address();
4153ed0d50c3Schristos 
4154ed0d50c3Schristos   switch(stub->type())
4155ed0d50c3Schristos     {
4156ed0d50c3Schristos     case ST_ADRP_BRANCH:
4157ed0d50c3Schristos       {
4158ed0d50c3Schristos 	// 1st reloc is ADR_PREL_PG_HI21
4159ed0d50c3Schristos 	The_reloc_functions_status status =
4160ed0d50c3Schristos 	    The_reloc_functions::adrp(view, dest, address);
4161ed0d50c3Schristos 	// An error should never arise in the above step. If so, please
4162ed0d50c3Schristos 	// check 'aarch64_valid_for_adrp_p'.
4163ed0d50c3Schristos 	gold_assert(status == The_reloc_functions::STATUS_OKAY);
4164ed0d50c3Schristos 
4165ed0d50c3Schristos 	// 2nd reloc is ADD_ABS_LO12_NC
4166ed0d50c3Schristos 	const AArch64_reloc_property* arp =
4167ed0d50c3Schristos 	    aarch64_reloc_property_table->get_reloc_property(
4168ed0d50c3Schristos 		elfcpp::R_AARCH64_ADD_ABS_LO12_NC);
4169ed0d50c3Schristos 	gold_assert(arp != NULL);
4170ed0d50c3Schristos 	status = The_reloc_functions::template
4171ed0d50c3Schristos 	    rela_general<32>(view + 4, dest, 0, arp);
4172ed0d50c3Schristos 	// An error should never arise, it is an "_NC" relocation.
4173ed0d50c3Schristos 	gold_assert(status == The_reloc_functions::STATUS_OKAY);
4174ed0d50c3Schristos       }
4175ed0d50c3Schristos       break;
4176ed0d50c3Schristos 
4177ed0d50c3Schristos     case ST_LONG_BRANCH_ABS:
4178ed0d50c3Schristos       // 1st reloc is R_AARCH64_PREL64, at offset 8
4179ed0d50c3Schristos       elfcpp::Swap<64,big_endian>::writeval(view + 8, dest);
4180ed0d50c3Schristos       break;
4181ed0d50c3Schristos 
4182ed0d50c3Schristos     case ST_LONG_BRANCH_PCREL:
4183ed0d50c3Schristos       {
4184ed0d50c3Schristos 	// "PC" calculation is the 2nd insn in the stub.
4185ed0d50c3Schristos 	uint64_t offset = dest - (address + 4);
4186ed0d50c3Schristos 	// Offset is placed at offset 4 and 5.
4187ed0d50c3Schristos 	elfcpp::Swap<64,big_endian>::writeval(view + 16, offset);
4188ed0d50c3Schristos       }
4189ed0d50c3Schristos       break;
4190ed0d50c3Schristos 
4191ed0d50c3Schristos     default:
4192ed0d50c3Schristos       gold_unreachable();
4193ed0d50c3Schristos     }
4194ed0d50c3Schristos }
4195ed0d50c3Schristos 
4196ed0d50c3Schristos 
4197ed0d50c3Schristos // A class to handle the PLT data.
4198ed0d50c3Schristos // This is an abstract base class that handles most of the linker details
4199ed0d50c3Schristos // but does not know the actual contents of PLT entries.  The derived
4200ed0d50c3Schristos // classes below fill in those details.
4201ed0d50c3Schristos 
4202ed0d50c3Schristos template<int size, bool big_endian>
4203ed0d50c3Schristos class Output_data_plt_aarch64 : public Output_section_data
4204ed0d50c3Schristos {
4205ed0d50c3Schristos  public:
4206ed0d50c3Schristos   typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>
4207ed0d50c3Schristos       Reloc_section;
4208ed0d50c3Schristos   typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
4209ed0d50c3Schristos 
Output_data_plt_aarch64(Layout * layout,uint64_t addralign,Output_data_got_aarch64<size,big_endian> * got,Output_data_space * got_plt,Output_data_space * got_irelative)4210ed0d50c3Schristos   Output_data_plt_aarch64(Layout* layout,
4211ed0d50c3Schristos 			  uint64_t addralign,
4212ed0d50c3Schristos 			  Output_data_got_aarch64<size, big_endian>* got,
4213ed0d50c3Schristos 			  Output_data_space* got_plt,
4214ed0d50c3Schristos 			  Output_data_space* got_irelative)
4215ed0d50c3Schristos     : Output_section_data(addralign), tlsdesc_rel_(NULL), irelative_rel_(NULL),
4216ed0d50c3Schristos       got_(got), got_plt_(got_plt), got_irelative_(got_irelative),
4217ed0d50c3Schristos       count_(0), irelative_count_(0), tlsdesc_got_offset_(-1U)
4218ed0d50c3Schristos   { this->init(layout); }
4219ed0d50c3Schristos 
4220ed0d50c3Schristos   // Initialize the PLT section.
4221ed0d50c3Schristos   void
4222ed0d50c3Schristos   init(Layout* layout);
4223ed0d50c3Schristos 
4224ed0d50c3Schristos   // Add an entry to the PLT.
4225ed0d50c3Schristos   void
4226ed0d50c3Schristos   add_entry(Symbol_table*, Layout*, Symbol* gsym);
4227ed0d50c3Schristos 
4228ed0d50c3Schristos   // Add an entry to the PLT for a local STT_GNU_IFUNC symbol.
4229ed0d50c3Schristos   unsigned int
4230ed0d50c3Schristos   add_local_ifunc_entry(Symbol_table* symtab, Layout*,
4231ed0d50c3Schristos 			Sized_relobj_file<size, big_endian>* relobj,
4232ed0d50c3Schristos 			unsigned int local_sym_index);
4233ed0d50c3Schristos 
4234ed0d50c3Schristos   // Add the relocation for a PLT entry.
4235ed0d50c3Schristos   void
4236ed0d50c3Schristos   add_relocation(Symbol_table*, Layout*, Symbol* gsym,
4237ed0d50c3Schristos 		 unsigned int got_offset);
4238ed0d50c3Schristos 
4239ed0d50c3Schristos   // Add the reserved TLSDESC_PLT entry to the PLT.
4240ed0d50c3Schristos   void
reserve_tlsdesc_entry(unsigned int got_offset)4241ed0d50c3Schristos   reserve_tlsdesc_entry(unsigned int got_offset)
4242ed0d50c3Schristos   { this->tlsdesc_got_offset_ = got_offset; }
4243ed0d50c3Schristos 
4244ed0d50c3Schristos   // Return true if a TLSDESC_PLT entry has been reserved.
4245ed0d50c3Schristos   bool
has_tlsdesc_entry() const4246ed0d50c3Schristos   has_tlsdesc_entry() const
4247ed0d50c3Schristos   { return this->tlsdesc_got_offset_ != -1U; }
4248ed0d50c3Schristos 
4249ed0d50c3Schristos   // Return the GOT offset for the reserved TLSDESC_PLT entry.
4250ed0d50c3Schristos   unsigned int
get_tlsdesc_got_offset() const4251ed0d50c3Schristos   get_tlsdesc_got_offset() const
4252ed0d50c3Schristos   { return this->tlsdesc_got_offset_; }
4253ed0d50c3Schristos 
4254ed0d50c3Schristos   // Return the PLT offset of the reserved TLSDESC_PLT entry.
4255ed0d50c3Schristos   unsigned int
get_tlsdesc_plt_offset() const4256ed0d50c3Schristos   get_tlsdesc_plt_offset() const
4257ed0d50c3Schristos   {
4258ed0d50c3Schristos     return (this->first_plt_entry_offset() +
4259ed0d50c3Schristos 	    (this->count_ + this->irelative_count_)
4260ed0d50c3Schristos 	    * this->get_plt_entry_size());
4261ed0d50c3Schristos   }
4262ed0d50c3Schristos 
4263ed0d50c3Schristos   // Return the .rela.plt section data.
4264ed0d50c3Schristos   Reloc_section*
rela_plt()4265ed0d50c3Schristos   rela_plt()
4266ed0d50c3Schristos   { return this->rel_; }
4267ed0d50c3Schristos 
4268ed0d50c3Schristos   // Return where the TLSDESC relocations should go.
4269ed0d50c3Schristos   Reloc_section*
4270ed0d50c3Schristos   rela_tlsdesc(Layout*);
4271ed0d50c3Schristos 
4272ed0d50c3Schristos   // Return where the IRELATIVE relocations should go in the PLT
4273ed0d50c3Schristos   // relocations.
4274ed0d50c3Schristos   Reloc_section*
4275ed0d50c3Schristos   rela_irelative(Symbol_table*, Layout*);
4276ed0d50c3Schristos 
4277ed0d50c3Schristos   // Return whether we created a section for IRELATIVE relocations.
4278ed0d50c3Schristos   bool
has_irelative_section() const4279ed0d50c3Schristos   has_irelative_section() const
4280ed0d50c3Schristos   { return this->irelative_rel_ != NULL; }
4281ed0d50c3Schristos 
4282ed0d50c3Schristos   // Return the number of PLT entries.
4283ed0d50c3Schristos   unsigned int
entry_count() const4284ed0d50c3Schristos   entry_count() const
4285ed0d50c3Schristos   { return this->count_ + this->irelative_count_; }
4286ed0d50c3Schristos 
4287ed0d50c3Schristos   // Return the offset of the first non-reserved PLT entry.
4288ed0d50c3Schristos   unsigned int
first_plt_entry_offset() const4289ed0d50c3Schristos   first_plt_entry_offset() const
4290ed0d50c3Schristos   { return this->do_first_plt_entry_offset(); }
4291ed0d50c3Schristos 
4292ed0d50c3Schristos   // Return the size of a PLT entry.
4293ed0d50c3Schristos   unsigned int
get_plt_entry_size() const4294ed0d50c3Schristos   get_plt_entry_size() const
4295ed0d50c3Schristos   { return this->do_get_plt_entry_size(); }
4296ed0d50c3Schristos 
4297ed0d50c3Schristos   // Return the reserved tlsdesc entry size.
4298ed0d50c3Schristos   unsigned int
get_plt_tlsdesc_entry_size() const4299ed0d50c3Schristos   get_plt_tlsdesc_entry_size() const
4300ed0d50c3Schristos   { return this->do_get_plt_tlsdesc_entry_size(); }
4301ed0d50c3Schristos 
4302ed0d50c3Schristos   // Return the PLT address to use for a global symbol.
4303ed0d50c3Schristos   uint64_t
4304ed0d50c3Schristos   address_for_global(const Symbol*);
4305ed0d50c3Schristos 
4306ed0d50c3Schristos   // Return the PLT address to use for a local symbol.
4307ed0d50c3Schristos   uint64_t
4308ed0d50c3Schristos   address_for_local(const Relobj*, unsigned int symndx);
4309ed0d50c3Schristos 
4310ed0d50c3Schristos  protected:
4311ed0d50c3Schristos   // Fill in the first PLT entry.
4312ed0d50c3Schristos   void
fill_first_plt_entry(unsigned char * pov,Address got_address,Address plt_address)4313ed0d50c3Schristos   fill_first_plt_entry(unsigned char* pov,
4314ed0d50c3Schristos 		       Address got_address,
4315ed0d50c3Schristos 		       Address plt_address)
4316ed0d50c3Schristos   { this->do_fill_first_plt_entry(pov, got_address, plt_address); }
4317ed0d50c3Schristos 
4318ed0d50c3Schristos   // Fill in a normal PLT entry.
4319ed0d50c3Schristos   void
fill_plt_entry(unsigned char * pov,Address got_address,Address plt_address,unsigned int got_offset,unsigned int plt_offset)4320ed0d50c3Schristos   fill_plt_entry(unsigned char* pov,
4321ed0d50c3Schristos 		 Address got_address,
4322ed0d50c3Schristos 		 Address plt_address,
4323ed0d50c3Schristos 		 unsigned int got_offset,
4324ed0d50c3Schristos 		 unsigned int plt_offset)
4325ed0d50c3Schristos   {
4326ed0d50c3Schristos     this->do_fill_plt_entry(pov, got_address, plt_address,
4327ed0d50c3Schristos 			    got_offset, plt_offset);
4328ed0d50c3Schristos   }
4329ed0d50c3Schristos 
4330ed0d50c3Schristos   // Fill in the reserved TLSDESC PLT entry.
4331ed0d50c3Schristos   void
fill_tlsdesc_entry(unsigned char * pov,Address gotplt_address,Address plt_address,Address got_base,unsigned int tlsdesc_got_offset,unsigned int plt_offset)4332ed0d50c3Schristos   fill_tlsdesc_entry(unsigned char* pov,
4333ed0d50c3Schristos 		     Address gotplt_address,
4334ed0d50c3Schristos 		     Address plt_address,
4335ed0d50c3Schristos 		     Address got_base,
4336ed0d50c3Schristos 		     unsigned int tlsdesc_got_offset,
4337ed0d50c3Schristos 		     unsigned int plt_offset)
4338ed0d50c3Schristos   {
4339ed0d50c3Schristos     this->do_fill_tlsdesc_entry(pov, gotplt_address, plt_address, got_base,
4340ed0d50c3Schristos 				tlsdesc_got_offset, plt_offset);
4341ed0d50c3Schristos   }
4342ed0d50c3Schristos 
4343ed0d50c3Schristos   virtual unsigned int
4344ed0d50c3Schristos   do_first_plt_entry_offset() const = 0;
4345ed0d50c3Schristos 
4346ed0d50c3Schristos   virtual unsigned int
4347ed0d50c3Schristos   do_get_plt_entry_size() const = 0;
4348ed0d50c3Schristos 
4349ed0d50c3Schristos   virtual unsigned int
4350ed0d50c3Schristos   do_get_plt_tlsdesc_entry_size() const = 0;
4351ed0d50c3Schristos 
4352ed0d50c3Schristos   virtual void
4353ed0d50c3Schristos   do_fill_first_plt_entry(unsigned char* pov,
4354ed0d50c3Schristos 			  Address got_addr,
4355ed0d50c3Schristos 			  Address plt_addr) = 0;
4356ed0d50c3Schristos 
4357ed0d50c3Schristos   virtual void
4358ed0d50c3Schristos   do_fill_plt_entry(unsigned char* pov,
4359ed0d50c3Schristos 		    Address got_address,
4360ed0d50c3Schristos 		    Address plt_address,
4361ed0d50c3Schristos 		    unsigned int got_offset,
4362ed0d50c3Schristos 		    unsigned int plt_offset) = 0;
4363ed0d50c3Schristos 
4364ed0d50c3Schristos   virtual void
4365ed0d50c3Schristos   do_fill_tlsdesc_entry(unsigned char* pov,
4366ed0d50c3Schristos 			Address gotplt_address,
4367ed0d50c3Schristos 			Address plt_address,
4368ed0d50c3Schristos 			Address got_base,
4369ed0d50c3Schristos 			unsigned int tlsdesc_got_offset,
4370ed0d50c3Schristos 			unsigned int plt_offset) = 0;
4371ed0d50c3Schristos 
4372ed0d50c3Schristos   void
4373ed0d50c3Schristos   do_adjust_output_section(Output_section* os);
4374ed0d50c3Schristos 
4375ed0d50c3Schristos   // Write to a map file.
4376ed0d50c3Schristos   void
do_print_to_mapfile(Mapfile * mapfile) const4377ed0d50c3Schristos   do_print_to_mapfile(Mapfile* mapfile) const
4378ed0d50c3Schristos   { mapfile->print_output_data(this, _("** PLT")); }
4379ed0d50c3Schristos 
4380ed0d50c3Schristos  private:
4381ed0d50c3Schristos   // Set the final size.
4382ed0d50c3Schristos   void
4383ed0d50c3Schristos   set_final_data_size();
4384ed0d50c3Schristos 
4385ed0d50c3Schristos   // Write out the PLT data.
4386ed0d50c3Schristos   void
4387ed0d50c3Schristos   do_write(Output_file*);
4388ed0d50c3Schristos 
4389ed0d50c3Schristos   // The reloc section.
4390ed0d50c3Schristos   Reloc_section* rel_;
4391ed0d50c3Schristos 
4392ed0d50c3Schristos   // The TLSDESC relocs, if necessary.  These must follow the regular
4393ed0d50c3Schristos   // PLT relocs.
4394ed0d50c3Schristos   Reloc_section* tlsdesc_rel_;
4395ed0d50c3Schristos 
4396ed0d50c3Schristos   // The IRELATIVE relocs, if necessary.  These must follow the
4397ed0d50c3Schristos   // regular PLT relocations.
4398ed0d50c3Schristos   Reloc_section* irelative_rel_;
4399ed0d50c3Schristos 
4400ed0d50c3Schristos   // The .got section.
4401ed0d50c3Schristos   Output_data_got_aarch64<size, big_endian>* got_;
4402ed0d50c3Schristos 
4403ed0d50c3Schristos   // The .got.plt section.
4404ed0d50c3Schristos   Output_data_space* got_plt_;
4405ed0d50c3Schristos 
4406ed0d50c3Schristos   // The part of the .got.plt section used for IRELATIVE relocs.
4407ed0d50c3Schristos   Output_data_space* got_irelative_;
4408ed0d50c3Schristos 
4409ed0d50c3Schristos   // The number of PLT entries.
4410ed0d50c3Schristos   unsigned int count_;
4411ed0d50c3Schristos 
4412ed0d50c3Schristos   // Number of PLT entries with R_AARCH64_IRELATIVE relocs.  These
4413ed0d50c3Schristos   // follow the regular PLT entries.
4414ed0d50c3Schristos   unsigned int irelative_count_;
4415ed0d50c3Schristos 
4416ed0d50c3Schristos   // GOT offset of the reserved TLSDESC_GOT entry for the lazy trampoline.
4417ed0d50c3Schristos   // Communicated to the loader via DT_TLSDESC_GOT. The magic value -1
4418ed0d50c3Schristos   // indicates an offset is not allocated.
4419ed0d50c3Schristos   unsigned int tlsdesc_got_offset_;
4420ed0d50c3Schristos };
4421ed0d50c3Schristos 
4422ed0d50c3Schristos // Initialize the PLT section.
4423ed0d50c3Schristos 
4424ed0d50c3Schristos template<int size, bool big_endian>
4425ed0d50c3Schristos void
init(Layout * layout)4426ed0d50c3Schristos Output_data_plt_aarch64<size, big_endian>::init(Layout* layout)
4427ed0d50c3Schristos {
4428ed0d50c3Schristos   this->rel_ = new Reloc_section(false);
4429ed0d50c3Schristos   layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
4430ed0d50c3Schristos 				  elfcpp::SHF_ALLOC, this->rel_,
4431ed0d50c3Schristos 				  ORDER_DYNAMIC_PLT_RELOCS, false);
4432ed0d50c3Schristos }
4433ed0d50c3Schristos 
4434ed0d50c3Schristos template<int size, bool big_endian>
4435ed0d50c3Schristos void
do_adjust_output_section(Output_section * os)4436ed0d50c3Schristos Output_data_plt_aarch64<size, big_endian>::do_adjust_output_section(
4437ed0d50c3Schristos     Output_section* os)
4438ed0d50c3Schristos {
4439ed0d50c3Schristos   os->set_entsize(this->get_plt_entry_size());
4440ed0d50c3Schristos }
4441ed0d50c3Schristos 
4442ed0d50c3Schristos // Add an entry to the PLT.
4443ed0d50c3Schristos 
4444ed0d50c3Schristos template<int size, bool big_endian>
4445ed0d50c3Schristos void
add_entry(Symbol_table * symtab,Layout * layout,Symbol * gsym)4446ed0d50c3Schristos Output_data_plt_aarch64<size, big_endian>::add_entry(Symbol_table* symtab,
4447ed0d50c3Schristos     Layout* layout, Symbol* gsym)
4448ed0d50c3Schristos {
4449ed0d50c3Schristos   gold_assert(!gsym->has_plt_offset());
4450ed0d50c3Schristos 
4451ed0d50c3Schristos   unsigned int* pcount;
4452ed0d50c3Schristos   unsigned int plt_reserved;
4453ed0d50c3Schristos   Output_section_data_build* got;
4454ed0d50c3Schristos 
4455ed0d50c3Schristos   if (gsym->type() == elfcpp::STT_GNU_IFUNC
4456ed0d50c3Schristos       && gsym->can_use_relative_reloc(false))
4457ed0d50c3Schristos     {
4458ed0d50c3Schristos       pcount = &this->irelative_count_;
4459ed0d50c3Schristos       plt_reserved = 0;
4460ed0d50c3Schristos       got = this->got_irelative_;
4461ed0d50c3Schristos     }
4462ed0d50c3Schristos   else
4463ed0d50c3Schristos     {
4464ed0d50c3Schristos       pcount = &this->count_;
4465ed0d50c3Schristos       plt_reserved = this->first_plt_entry_offset();
4466ed0d50c3Schristos       got = this->got_plt_;
4467ed0d50c3Schristos     }
4468ed0d50c3Schristos 
4469ed0d50c3Schristos   gsym->set_plt_offset((*pcount) * this->get_plt_entry_size()
4470ed0d50c3Schristos 		       + plt_reserved);
4471ed0d50c3Schristos 
4472ed0d50c3Schristos   ++*pcount;
4473ed0d50c3Schristos 
4474ed0d50c3Schristos   section_offset_type got_offset = got->current_data_size();
4475ed0d50c3Schristos 
4476ed0d50c3Schristos   // Every PLT entry needs a GOT entry which points back to the PLT
4477ed0d50c3Schristos   // entry (this will be changed by the dynamic linker, normally
4478ed0d50c3Schristos   // lazily when the function is called).
4479ed0d50c3Schristos   got->set_current_data_size(got_offset + size / 8);
4480ed0d50c3Schristos 
4481ed0d50c3Schristos   // Every PLT entry needs a reloc.
4482ed0d50c3Schristos   this->add_relocation(symtab, layout, gsym, got_offset);
4483ed0d50c3Schristos 
4484ed0d50c3Schristos   // Note that we don't need to save the symbol. The contents of the
4485ed0d50c3Schristos   // PLT are independent of which symbols are used. The symbols only
4486ed0d50c3Schristos   // appear in the relocations.
4487ed0d50c3Schristos }
4488ed0d50c3Schristos 
4489ed0d50c3Schristos // Add an entry to the PLT for a local STT_GNU_IFUNC symbol.  Return
4490ed0d50c3Schristos // the PLT offset.
4491ed0d50c3Schristos 
4492ed0d50c3Schristos template<int size, bool big_endian>
4493ed0d50c3Schristos unsigned int
add_local_ifunc_entry(Symbol_table * symtab,Layout * layout,Sized_relobj_file<size,big_endian> * relobj,unsigned int local_sym_index)4494ed0d50c3Schristos Output_data_plt_aarch64<size, big_endian>::add_local_ifunc_entry(
4495ed0d50c3Schristos     Symbol_table* symtab,
4496ed0d50c3Schristos     Layout* layout,
4497ed0d50c3Schristos     Sized_relobj_file<size, big_endian>* relobj,
4498ed0d50c3Schristos     unsigned int local_sym_index)
4499ed0d50c3Schristos {
4500ed0d50c3Schristos   unsigned int plt_offset = this->irelative_count_ * this->get_plt_entry_size();
4501ed0d50c3Schristos   ++this->irelative_count_;
4502ed0d50c3Schristos 
4503ed0d50c3Schristos   section_offset_type got_offset = this->got_irelative_->current_data_size();
4504ed0d50c3Schristos 
4505ed0d50c3Schristos   // Every PLT entry needs a GOT entry which points back to the PLT
4506ed0d50c3Schristos   // entry.
4507ed0d50c3Schristos   this->got_irelative_->set_current_data_size(got_offset + size / 8);
4508ed0d50c3Schristos 
4509ed0d50c3Schristos   // Every PLT entry needs a reloc.
4510ed0d50c3Schristos   Reloc_section* rela = this->rela_irelative(symtab, layout);
4511ed0d50c3Schristos   rela->add_symbolless_local_addend(relobj, local_sym_index,
4512ed0d50c3Schristos 				    elfcpp::R_AARCH64_IRELATIVE,
4513ed0d50c3Schristos 				    this->got_irelative_, got_offset, 0);
4514ed0d50c3Schristos 
4515ed0d50c3Schristos   return plt_offset;
4516ed0d50c3Schristos }
4517ed0d50c3Schristos 
4518ed0d50c3Schristos // Add the relocation for a PLT entry.
4519ed0d50c3Schristos 
4520ed0d50c3Schristos template<int size, bool big_endian>
4521ed0d50c3Schristos void
add_relocation(Symbol_table * symtab,Layout * layout,Symbol * gsym,unsigned int got_offset)4522ed0d50c3Schristos Output_data_plt_aarch64<size, big_endian>::add_relocation(
4523ed0d50c3Schristos     Symbol_table* symtab, Layout* layout, Symbol* gsym, unsigned int got_offset)
4524ed0d50c3Schristos {
4525ed0d50c3Schristos   if (gsym->type() == elfcpp::STT_GNU_IFUNC
4526ed0d50c3Schristos       && gsym->can_use_relative_reloc(false))
4527ed0d50c3Schristos     {
4528ed0d50c3Schristos       Reloc_section* rela = this->rela_irelative(symtab, layout);
4529ed0d50c3Schristos       rela->add_symbolless_global_addend(gsym, elfcpp::R_AARCH64_IRELATIVE,
4530ed0d50c3Schristos 					 this->got_irelative_, got_offset, 0);
4531ed0d50c3Schristos     }
4532ed0d50c3Schristos   else
4533ed0d50c3Schristos     {
4534ed0d50c3Schristos       gsym->set_needs_dynsym_entry();
4535ed0d50c3Schristos       this->rel_->add_global(gsym, elfcpp::R_AARCH64_JUMP_SLOT, this->got_plt_,
4536ed0d50c3Schristos 			     got_offset, 0);
4537ed0d50c3Schristos     }
4538ed0d50c3Schristos }
4539ed0d50c3Schristos 
4540ed0d50c3Schristos // Return where the TLSDESC relocations should go, creating it if
4541ed0d50c3Schristos // necessary.  These follow the JUMP_SLOT relocations.
4542ed0d50c3Schristos 
4543ed0d50c3Schristos template<int size, bool big_endian>
4544ed0d50c3Schristos typename Output_data_plt_aarch64<size, big_endian>::Reloc_section*
rela_tlsdesc(Layout * layout)4545ed0d50c3Schristos Output_data_plt_aarch64<size, big_endian>::rela_tlsdesc(Layout* layout)
4546ed0d50c3Schristos {
4547ed0d50c3Schristos   if (this->tlsdesc_rel_ == NULL)
4548ed0d50c3Schristos     {
4549ed0d50c3Schristos       this->tlsdesc_rel_ = new Reloc_section(false);
4550ed0d50c3Schristos       layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
4551ed0d50c3Schristos 				      elfcpp::SHF_ALLOC, this->tlsdesc_rel_,
4552ed0d50c3Schristos 				      ORDER_DYNAMIC_PLT_RELOCS, false);
4553ed0d50c3Schristos       gold_assert(this->tlsdesc_rel_->output_section()
4554ed0d50c3Schristos 		  == this->rel_->output_section());
4555ed0d50c3Schristos     }
4556ed0d50c3Schristos   return this->tlsdesc_rel_;
4557ed0d50c3Schristos }
4558ed0d50c3Schristos 
4559ed0d50c3Schristos // Return where the IRELATIVE relocations should go in the PLT.  These
4560ed0d50c3Schristos // follow the JUMP_SLOT and the TLSDESC relocations.
4561ed0d50c3Schristos 
4562ed0d50c3Schristos template<int size, bool big_endian>
4563ed0d50c3Schristos typename Output_data_plt_aarch64<size, big_endian>::Reloc_section*
rela_irelative(Symbol_table * symtab,Layout * layout)4564ed0d50c3Schristos Output_data_plt_aarch64<size, big_endian>::rela_irelative(Symbol_table* symtab,
4565ed0d50c3Schristos 							  Layout* layout)
4566ed0d50c3Schristos {
4567ed0d50c3Schristos   if (this->irelative_rel_ == NULL)
4568ed0d50c3Schristos     {
4569ed0d50c3Schristos       // Make sure we have a place for the TLSDESC relocations, in
4570ed0d50c3Schristos       // case we see any later on.
4571ed0d50c3Schristos       this->rela_tlsdesc(layout);
4572ed0d50c3Schristos       this->irelative_rel_ = new Reloc_section(false);
4573ed0d50c3Schristos       layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
4574ed0d50c3Schristos 				      elfcpp::SHF_ALLOC, this->irelative_rel_,
4575ed0d50c3Schristos 				      ORDER_DYNAMIC_PLT_RELOCS, false);
4576ed0d50c3Schristos       gold_assert(this->irelative_rel_->output_section()
4577ed0d50c3Schristos 		  == this->rel_->output_section());
4578ed0d50c3Schristos 
4579ed0d50c3Schristos       if (parameters->doing_static_link())
4580ed0d50c3Schristos 	{
4581ed0d50c3Schristos 	  // A statically linked executable will only have a .rela.plt
4582ed0d50c3Schristos 	  // section to hold R_AARCH64_IRELATIVE relocs for
4583ed0d50c3Schristos 	  // STT_GNU_IFUNC symbols.  The library will use these
4584ed0d50c3Schristos 	  // symbols to locate the IRELATIVE relocs at program startup
4585ed0d50c3Schristos 	  // time.
4586ed0d50c3Schristos 	  symtab->define_in_output_data("__rela_iplt_start", NULL,
4587ed0d50c3Schristos 					Symbol_table::PREDEFINED,
4588ed0d50c3Schristos 					this->irelative_rel_, 0, 0,
4589ed0d50c3Schristos 					elfcpp::STT_NOTYPE, elfcpp::STB_GLOBAL,
4590ed0d50c3Schristos 					elfcpp::STV_HIDDEN, 0, false, true);
4591ed0d50c3Schristos 	  symtab->define_in_output_data("__rela_iplt_end", NULL,
4592ed0d50c3Schristos 					Symbol_table::PREDEFINED,
4593ed0d50c3Schristos 					this->irelative_rel_, 0, 0,
4594ed0d50c3Schristos 					elfcpp::STT_NOTYPE, elfcpp::STB_GLOBAL,
4595ed0d50c3Schristos 					elfcpp::STV_HIDDEN, 0, true, true);
4596ed0d50c3Schristos 	}
4597ed0d50c3Schristos     }
4598ed0d50c3Schristos   return this->irelative_rel_;
4599ed0d50c3Schristos }
4600ed0d50c3Schristos 
4601ed0d50c3Schristos // Return the PLT address to use for a global symbol.
4602ed0d50c3Schristos 
4603ed0d50c3Schristos template<int size, bool big_endian>
4604ed0d50c3Schristos uint64_t
address_for_global(const Symbol * gsym)4605ed0d50c3Schristos Output_data_plt_aarch64<size, big_endian>::address_for_global(
4606ed0d50c3Schristos   const Symbol* gsym)
4607ed0d50c3Schristos {
4608ed0d50c3Schristos   uint64_t offset = 0;
4609ed0d50c3Schristos   if (gsym->type() == elfcpp::STT_GNU_IFUNC
4610ed0d50c3Schristos       && gsym->can_use_relative_reloc(false))
4611ed0d50c3Schristos     offset = (this->first_plt_entry_offset() +
4612ed0d50c3Schristos 	      this->count_ * this->get_plt_entry_size());
4613ed0d50c3Schristos   return this->address() + offset + gsym->plt_offset();
4614ed0d50c3Schristos }
4615ed0d50c3Schristos 
4616ed0d50c3Schristos // Return the PLT address to use for a local symbol.  These are always
4617ed0d50c3Schristos // IRELATIVE relocs.
4618ed0d50c3Schristos 
4619ed0d50c3Schristos template<int size, bool big_endian>
4620ed0d50c3Schristos uint64_t
address_for_local(const Relobj * object,unsigned int r_sym)4621ed0d50c3Schristos Output_data_plt_aarch64<size, big_endian>::address_for_local(
4622ed0d50c3Schristos     const Relobj* object,
4623ed0d50c3Schristos     unsigned int r_sym)
4624ed0d50c3Schristos {
4625ed0d50c3Schristos   return (this->address()
4626ed0d50c3Schristos 	  + this->first_plt_entry_offset()
4627ed0d50c3Schristos 	  + this->count_ * this->get_plt_entry_size()
4628ed0d50c3Schristos 	  + object->local_plt_offset(r_sym));
4629ed0d50c3Schristos }
4630ed0d50c3Schristos 
4631ed0d50c3Schristos // Set the final size.
4632ed0d50c3Schristos 
4633ed0d50c3Schristos template<int size, bool big_endian>
4634ed0d50c3Schristos void
set_final_data_size()4635ed0d50c3Schristos Output_data_plt_aarch64<size, big_endian>::set_final_data_size()
4636ed0d50c3Schristos {
4637ed0d50c3Schristos   unsigned int count = this->count_ + this->irelative_count_;
4638ed0d50c3Schristos   unsigned int extra_size = 0;
4639ed0d50c3Schristos   if (this->has_tlsdesc_entry())
4640ed0d50c3Schristos     extra_size += this->get_plt_tlsdesc_entry_size();
4641ed0d50c3Schristos   this->set_data_size(this->first_plt_entry_offset()
4642ed0d50c3Schristos 		      + count * this->get_plt_entry_size()
4643ed0d50c3Schristos 		      + extra_size);
4644ed0d50c3Schristos }
4645ed0d50c3Schristos 
4646ed0d50c3Schristos template<int size, bool big_endian>
4647ed0d50c3Schristos class Output_data_plt_aarch64_standard :
4648ed0d50c3Schristos   public Output_data_plt_aarch64<size, big_endian>
4649ed0d50c3Schristos {
4650ed0d50c3Schristos  public:
4651ed0d50c3Schristos   typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
Output_data_plt_aarch64_standard(Layout * layout,Output_data_got_aarch64<size,big_endian> * got,Output_data_space * got_plt,Output_data_space * got_irelative)4652ed0d50c3Schristos   Output_data_plt_aarch64_standard(
4653ed0d50c3Schristos       Layout* layout,
4654ed0d50c3Schristos       Output_data_got_aarch64<size, big_endian>* got,
4655ed0d50c3Schristos       Output_data_space* got_plt,
4656ed0d50c3Schristos       Output_data_space* got_irelative)
4657ed0d50c3Schristos     : Output_data_plt_aarch64<size, big_endian>(layout,
4658ed0d50c3Schristos 						size == 32 ? 4 : 8,
4659ed0d50c3Schristos 						got, got_plt,
4660ed0d50c3Schristos 						got_irelative)
4661ed0d50c3Schristos   { }
4662ed0d50c3Schristos 
4663ed0d50c3Schristos  protected:
4664ed0d50c3Schristos   // Return the offset of the first non-reserved PLT entry.
4665ed0d50c3Schristos   virtual unsigned int
do_first_plt_entry_offset() const4666ed0d50c3Schristos   do_first_plt_entry_offset() const
4667ed0d50c3Schristos   { return this->first_plt_entry_size; }
4668ed0d50c3Schristos 
4669ed0d50c3Schristos   // Return the size of a PLT entry
4670ed0d50c3Schristos   virtual unsigned int
do_get_plt_entry_size() const4671ed0d50c3Schristos   do_get_plt_entry_size() const
4672ed0d50c3Schristos   { return this->plt_entry_size; }
4673ed0d50c3Schristos 
4674ed0d50c3Schristos   // Return the size of a tlsdesc entry
4675ed0d50c3Schristos   virtual unsigned int
do_get_plt_tlsdesc_entry_size() const4676ed0d50c3Schristos   do_get_plt_tlsdesc_entry_size() const
4677ed0d50c3Schristos   { return this->plt_tlsdesc_entry_size; }
4678ed0d50c3Schristos 
4679ed0d50c3Schristos   virtual void
4680ed0d50c3Schristos   do_fill_first_plt_entry(unsigned char* pov,
4681ed0d50c3Schristos 			  Address got_address,
4682ed0d50c3Schristos 			  Address plt_address);
4683ed0d50c3Schristos 
4684ed0d50c3Schristos   virtual void
4685ed0d50c3Schristos   do_fill_plt_entry(unsigned char* pov,
4686ed0d50c3Schristos 		    Address got_address,
4687ed0d50c3Schristos 		    Address plt_address,
4688ed0d50c3Schristos 		    unsigned int got_offset,
4689ed0d50c3Schristos 		    unsigned int plt_offset);
4690ed0d50c3Schristos 
4691ed0d50c3Schristos   virtual void
4692ed0d50c3Schristos   do_fill_tlsdesc_entry(unsigned char* pov,
4693ed0d50c3Schristos 			Address gotplt_address,
4694ed0d50c3Schristos 			Address plt_address,
4695ed0d50c3Schristos 			Address got_base,
4696ed0d50c3Schristos 			unsigned int tlsdesc_got_offset,
4697ed0d50c3Schristos 			unsigned int plt_offset);
4698ed0d50c3Schristos 
4699ed0d50c3Schristos  private:
4700ed0d50c3Schristos   // The size of the first plt entry size.
4701ed0d50c3Schristos   static const int first_plt_entry_size = 32;
4702ed0d50c3Schristos   // The size of the plt entry size.
4703ed0d50c3Schristos   static const int plt_entry_size = 16;
4704ed0d50c3Schristos   // The size of the plt tlsdesc entry size.
4705ed0d50c3Schristos   static const int plt_tlsdesc_entry_size = 32;
4706ed0d50c3Schristos   // Template for the first PLT entry.
4707ed0d50c3Schristos   static const uint32_t first_plt_entry[first_plt_entry_size / 4];
4708ed0d50c3Schristos   // Template for subsequent PLT entries.
4709ed0d50c3Schristos   static const uint32_t plt_entry[plt_entry_size / 4];
4710ed0d50c3Schristos   // The reserved TLSDESC entry in the PLT for an executable.
4711ed0d50c3Schristos   static const uint32_t tlsdesc_plt_entry[plt_tlsdesc_entry_size / 4];
4712ed0d50c3Schristos };
4713ed0d50c3Schristos 
4714ed0d50c3Schristos // The first entry in the PLT for an executable.
4715ed0d50c3Schristos 
4716ed0d50c3Schristos template<>
4717ed0d50c3Schristos const uint32_t
4718ed0d50c3Schristos Output_data_plt_aarch64_standard<32, false>::
4719ed0d50c3Schristos     first_plt_entry[first_plt_entry_size / 4] =
4720ed0d50c3Schristos {
4721ed0d50c3Schristos   0xa9bf7bf0,	/* stp x16, x30, [sp, #-16]!  */
4722ed0d50c3Schristos   0x90000010,	/* adrp x16, PLT_GOT+0x8  */
4723ed0d50c3Schristos   0xb9400A11,	/* ldr w17, [x16, #PLT_GOT+0x8]  */
4724ed0d50c3Schristos   0x11002210,	/* add w16, w16,#PLT_GOT+0x8   */
4725ed0d50c3Schristos   0xd61f0220,	/* br x17  */
4726ed0d50c3Schristos   0xd503201f,	/* nop */
4727ed0d50c3Schristos   0xd503201f,	/* nop */
4728ed0d50c3Schristos   0xd503201f,	/* nop */
4729ed0d50c3Schristos };
4730ed0d50c3Schristos 
4731ed0d50c3Schristos 
4732ed0d50c3Schristos template<>
4733ed0d50c3Schristos const uint32_t
4734ed0d50c3Schristos Output_data_plt_aarch64_standard<32, true>::
4735ed0d50c3Schristos     first_plt_entry[first_plt_entry_size / 4] =
4736ed0d50c3Schristos {
4737ed0d50c3Schristos   0xa9bf7bf0,	/* stp x16, x30, [sp, #-16]!  */
4738ed0d50c3Schristos   0x90000010,	/* adrp x16, PLT_GOT+0x8  */
4739ed0d50c3Schristos   0xb9400A11,	/* ldr w17, [x16, #PLT_GOT+0x8]  */
4740ed0d50c3Schristos   0x11002210,	/* add w16, w16,#PLT_GOT+0x8   */
4741ed0d50c3Schristos   0xd61f0220,	/* br x17  */
4742ed0d50c3Schristos   0xd503201f,	/* nop */
4743ed0d50c3Schristos   0xd503201f,	/* nop */
4744ed0d50c3Schristos   0xd503201f,	/* nop */
4745ed0d50c3Schristos };
4746ed0d50c3Schristos 
4747ed0d50c3Schristos 
4748ed0d50c3Schristos template<>
4749ed0d50c3Schristos const uint32_t
4750ed0d50c3Schristos Output_data_plt_aarch64_standard<64, false>::
4751ed0d50c3Schristos     first_plt_entry[first_plt_entry_size / 4] =
4752ed0d50c3Schristos {
4753ed0d50c3Schristos   0xa9bf7bf0,	/* stp x16, x30, [sp, #-16]!  */
4754ed0d50c3Schristos   0x90000010,	/* adrp x16, PLT_GOT+16  */
4755ed0d50c3Schristos   0xf9400A11,	/* ldr x17, [x16, #PLT_GOT+0x10]  */
4756ed0d50c3Schristos   0x91004210,	/* add x16, x16,#PLT_GOT+0x10   */
4757ed0d50c3Schristos   0xd61f0220,	/* br x17  */
4758ed0d50c3Schristos   0xd503201f,	/* nop */
4759ed0d50c3Schristos   0xd503201f,	/* nop */
4760ed0d50c3Schristos   0xd503201f,	/* nop */
4761ed0d50c3Schristos };
4762ed0d50c3Schristos 
4763ed0d50c3Schristos 
4764ed0d50c3Schristos template<>
4765ed0d50c3Schristos const uint32_t
4766ed0d50c3Schristos Output_data_plt_aarch64_standard<64, true>::
4767ed0d50c3Schristos     first_plt_entry[first_plt_entry_size / 4] =
4768ed0d50c3Schristos {
4769ed0d50c3Schristos   0xa9bf7bf0,	/* stp x16, x30, [sp, #-16]!  */
4770ed0d50c3Schristos   0x90000010,	/* adrp x16, PLT_GOT+16  */
4771ed0d50c3Schristos   0xf9400A11,	/* ldr x17, [x16, #PLT_GOT+0x10]  */
4772ed0d50c3Schristos   0x91004210,	/* add x16, x16,#PLT_GOT+0x10   */
4773ed0d50c3Schristos   0xd61f0220,	/* br x17  */
4774ed0d50c3Schristos   0xd503201f,	/* nop */
4775ed0d50c3Schristos   0xd503201f,	/* nop */
4776ed0d50c3Schristos   0xd503201f,	/* nop */
4777ed0d50c3Schristos };
4778ed0d50c3Schristos 
4779ed0d50c3Schristos 
4780ed0d50c3Schristos template<>
4781ed0d50c3Schristos const uint32_t
4782ed0d50c3Schristos Output_data_plt_aarch64_standard<32, false>::
4783ed0d50c3Schristos     plt_entry[plt_entry_size / 4] =
4784ed0d50c3Schristos {
4785ed0d50c3Schristos   0x90000010,	/* adrp x16, PLTGOT + n * 4  */
4786ed0d50c3Schristos   0xb9400211,	/* ldr w17, [w16, PLTGOT + n * 4] */
4787ed0d50c3Schristos   0x11000210,	/* add w16, w16, :lo12:PLTGOT + n * 4  */
4788ed0d50c3Schristos   0xd61f0220,	/* br x17.  */
4789ed0d50c3Schristos };
4790ed0d50c3Schristos 
4791ed0d50c3Schristos 
4792ed0d50c3Schristos template<>
4793ed0d50c3Schristos const uint32_t
4794ed0d50c3Schristos Output_data_plt_aarch64_standard<32, true>::
4795ed0d50c3Schristos     plt_entry[plt_entry_size / 4] =
4796ed0d50c3Schristos {
4797ed0d50c3Schristos   0x90000010,	/* adrp x16, PLTGOT + n * 4  */
4798ed0d50c3Schristos   0xb9400211,	/* ldr w17, [w16, PLTGOT + n * 4] */
4799ed0d50c3Schristos   0x11000210,	/* add w16, w16, :lo12:PLTGOT + n * 4  */
4800ed0d50c3Schristos   0xd61f0220,	/* br x17.  */
4801ed0d50c3Schristos };
4802ed0d50c3Schristos 
4803ed0d50c3Schristos 
4804ed0d50c3Schristos template<>
4805ed0d50c3Schristos const uint32_t
4806ed0d50c3Schristos Output_data_plt_aarch64_standard<64, false>::
4807ed0d50c3Schristos     plt_entry[plt_entry_size / 4] =
4808ed0d50c3Schristos {
4809ed0d50c3Schristos   0x90000010,	/* adrp x16, PLTGOT + n * 8  */
4810ed0d50c3Schristos   0xf9400211,	/* ldr x17, [x16, PLTGOT + n * 8] */
4811ed0d50c3Schristos   0x91000210,	/* add x16, x16, :lo12:PLTGOT + n * 8  */
4812ed0d50c3Schristos   0xd61f0220,	/* br x17.  */
4813ed0d50c3Schristos };
4814ed0d50c3Schristos 
4815ed0d50c3Schristos 
4816ed0d50c3Schristos template<>
4817ed0d50c3Schristos const uint32_t
4818ed0d50c3Schristos Output_data_plt_aarch64_standard<64, true>::
4819ed0d50c3Schristos     plt_entry[plt_entry_size / 4] =
4820ed0d50c3Schristos {
4821ed0d50c3Schristos   0x90000010,	/* adrp x16, PLTGOT + n * 8  */
4822ed0d50c3Schristos   0xf9400211,	/* ldr x17, [x16, PLTGOT + n * 8] */
4823ed0d50c3Schristos   0x91000210,	/* add x16, x16, :lo12:PLTGOT + n * 8  */
4824ed0d50c3Schristos   0xd61f0220,	/* br x17.  */
4825ed0d50c3Schristos };
4826ed0d50c3Schristos 
4827ed0d50c3Schristos 
4828ed0d50c3Schristos template<int size, bool big_endian>
4829ed0d50c3Schristos void
do_fill_first_plt_entry(unsigned char * pov,Address got_address,Address plt_address)4830ed0d50c3Schristos Output_data_plt_aarch64_standard<size, big_endian>::do_fill_first_plt_entry(
4831ed0d50c3Schristos     unsigned char* pov,
4832ed0d50c3Schristos     Address got_address,
4833ed0d50c3Schristos     Address plt_address)
4834ed0d50c3Schristos {
4835ed0d50c3Schristos   // PLT0 of the small PLT looks like this in ELF64 -
4836ed0d50c3Schristos   // stp x16, x30, [sp, #-16]!	 	Save the reloc and lr on stack.
4837ed0d50c3Schristos   // adrp x16, PLT_GOT + 16		Get the page base of the GOTPLT
4838ed0d50c3Schristos   // ldr  x17, [x16, #:lo12:PLT_GOT+16]	Load the address of the
4839ed0d50c3Schristos   // 					symbol resolver
4840ed0d50c3Schristos   // add  x16, x16, #:lo12:PLT_GOT+16	Load the lo12 bits of the
4841ed0d50c3Schristos   // 					GOTPLT entry for this.
4842ed0d50c3Schristos   // br   x17
4843ed0d50c3Schristos   // PLT0 will be slightly different in ELF32 due to different got entry
4844ed0d50c3Schristos   // size.
4845ed0d50c3Schristos   memcpy(pov, this->first_plt_entry, this->first_plt_entry_size);
4846ed0d50c3Schristos   Address gotplt_2nd_ent = got_address + (size / 8) * 2;
4847ed0d50c3Schristos 
4848ed0d50c3Schristos   // Fill in the top 21 bits for this: ADRP x16, PLT_GOT + 8 * 2.
4849ed0d50c3Schristos   // ADRP:  (PG(S+A)-PG(P)) >> 12) & 0x1fffff.
4850ed0d50c3Schristos   // FIXME: This only works for 64bit
4851ed0d50c3Schristos   AArch64_relocate_functions<size, big_endian>::adrp(pov + 4,
4852ed0d50c3Schristos       gotplt_2nd_ent, plt_address + 4);
4853ed0d50c3Schristos 
4854ed0d50c3Schristos   // Fill in R_AARCH64_LDST8_LO12
4855ed0d50c3Schristos   elfcpp::Swap<32, big_endian>::writeval(
4856ed0d50c3Schristos       pov + 8,
4857ed0d50c3Schristos       ((this->first_plt_entry[2] & 0xffc003ff)
4858ed0d50c3Schristos        | ((gotplt_2nd_ent & 0xff8) << 7)));
4859ed0d50c3Schristos 
4860ed0d50c3Schristos   // Fill in R_AARCH64_ADD_ABS_LO12
4861ed0d50c3Schristos   elfcpp::Swap<32, big_endian>::writeval(
4862ed0d50c3Schristos       pov + 12,
4863ed0d50c3Schristos       ((this->first_plt_entry[3] & 0xffc003ff)
4864ed0d50c3Schristos        | ((gotplt_2nd_ent & 0xfff) << 10)));
4865ed0d50c3Schristos }
4866ed0d50c3Schristos 
4867ed0d50c3Schristos 
4868ed0d50c3Schristos // Subsequent entries in the PLT for an executable.
4869ed0d50c3Schristos // FIXME: This only works for 64bit
4870ed0d50c3Schristos 
4871ed0d50c3Schristos template<int size, bool big_endian>
4872ed0d50c3Schristos void
do_fill_plt_entry(unsigned char * pov,Address got_address,Address plt_address,unsigned int got_offset,unsigned int plt_offset)4873ed0d50c3Schristos Output_data_plt_aarch64_standard<size, big_endian>::do_fill_plt_entry(
4874ed0d50c3Schristos     unsigned char* pov,
4875ed0d50c3Schristos     Address got_address,
4876ed0d50c3Schristos     Address plt_address,
4877ed0d50c3Schristos     unsigned int got_offset,
4878ed0d50c3Schristos     unsigned int plt_offset)
4879ed0d50c3Schristos {
4880ed0d50c3Schristos   memcpy(pov, this->plt_entry, this->plt_entry_size);
4881ed0d50c3Schristos 
4882ed0d50c3Schristos   Address gotplt_entry_address = got_address + got_offset;
4883ed0d50c3Schristos   Address plt_entry_address = plt_address + plt_offset;
4884ed0d50c3Schristos 
4885ed0d50c3Schristos   // Fill in R_AARCH64_PCREL_ADR_HI21
4886ed0d50c3Schristos   AArch64_relocate_functions<size, big_endian>::adrp(
4887ed0d50c3Schristos       pov,
4888ed0d50c3Schristos       gotplt_entry_address,
4889ed0d50c3Schristos       plt_entry_address);
4890ed0d50c3Schristos 
4891ed0d50c3Schristos   // Fill in R_AARCH64_LDST64_ABS_LO12
4892ed0d50c3Schristos   elfcpp::Swap<32, big_endian>::writeval(
4893ed0d50c3Schristos       pov + 4,
4894ed0d50c3Schristos       ((this->plt_entry[1] & 0xffc003ff)
4895ed0d50c3Schristos        | ((gotplt_entry_address & 0xff8) << 7)));
4896ed0d50c3Schristos 
4897ed0d50c3Schristos   // Fill in R_AARCH64_ADD_ABS_LO12
4898ed0d50c3Schristos   elfcpp::Swap<32, big_endian>::writeval(
4899ed0d50c3Schristos       pov + 8,
4900ed0d50c3Schristos       ((this->plt_entry[2] & 0xffc003ff)
4901ed0d50c3Schristos        | ((gotplt_entry_address & 0xfff) <<10)));
4902ed0d50c3Schristos 
4903ed0d50c3Schristos }
4904ed0d50c3Schristos 
4905ed0d50c3Schristos 
4906ed0d50c3Schristos template<>
4907ed0d50c3Schristos const uint32_t
4908ed0d50c3Schristos Output_data_plt_aarch64_standard<32, false>::
4909ed0d50c3Schristos     tlsdesc_plt_entry[plt_tlsdesc_entry_size / 4] =
4910ed0d50c3Schristos {
4911ed0d50c3Schristos   0xa9bf0fe2,	/* stp x2, x3, [sp, #-16]!  */
4912ed0d50c3Schristos   0x90000002,	/* adrp x2, 0 */
4913ed0d50c3Schristos   0x90000003,	/* adrp x3, 0 */
4914ed0d50c3Schristos   0xb9400042,	/* ldr w2, [w2, #0] */
4915ed0d50c3Schristos   0x11000063,	/* add w3, w3, 0 */
4916ed0d50c3Schristos   0xd61f0040,	/* br x2 */
4917ed0d50c3Schristos   0xd503201f,	/* nop */
4918ed0d50c3Schristos   0xd503201f,	/* nop */
4919ed0d50c3Schristos };
4920ed0d50c3Schristos 
4921ed0d50c3Schristos template<>
4922ed0d50c3Schristos const uint32_t
4923ed0d50c3Schristos Output_data_plt_aarch64_standard<32, true>::
4924ed0d50c3Schristos     tlsdesc_plt_entry[plt_tlsdesc_entry_size / 4] =
4925ed0d50c3Schristos {
4926ed0d50c3Schristos   0xa9bf0fe2,	/* stp x2, x3, [sp, #-16]!  */
4927ed0d50c3Schristos   0x90000002,	/* adrp x2, 0 */
4928ed0d50c3Schristos   0x90000003,	/* adrp x3, 0 */
4929ed0d50c3Schristos   0xb9400042,	/* ldr w2, [w2, #0] */
4930ed0d50c3Schristos   0x11000063,	/* add w3, w3, 0 */
4931ed0d50c3Schristos   0xd61f0040,	/* br x2 */
4932ed0d50c3Schristos   0xd503201f,	/* nop */
4933ed0d50c3Schristos   0xd503201f,	/* nop */
4934ed0d50c3Schristos };
4935ed0d50c3Schristos 
4936ed0d50c3Schristos template<>
4937ed0d50c3Schristos const uint32_t
4938ed0d50c3Schristos Output_data_plt_aarch64_standard<64, false>::
4939ed0d50c3Schristos     tlsdesc_plt_entry[plt_tlsdesc_entry_size / 4] =
4940ed0d50c3Schristos {
4941ed0d50c3Schristos   0xa9bf0fe2,	/* stp x2, x3, [sp, #-16]!  */
4942ed0d50c3Schristos   0x90000002,	/* adrp x2, 0 */
4943ed0d50c3Schristos   0x90000003,	/* adrp x3, 0 */
4944ed0d50c3Schristos   0xf9400042,	/* ldr x2, [x2, #0] */
4945ed0d50c3Schristos   0x91000063,	/* add x3, x3, 0 */
4946ed0d50c3Schristos   0xd61f0040,	/* br x2 */
4947ed0d50c3Schristos   0xd503201f,	/* nop */
4948ed0d50c3Schristos   0xd503201f,	/* nop */
4949ed0d50c3Schristos };
4950ed0d50c3Schristos 
4951ed0d50c3Schristos template<>
4952ed0d50c3Schristos const uint32_t
4953ed0d50c3Schristos Output_data_plt_aarch64_standard<64, true>::
4954ed0d50c3Schristos     tlsdesc_plt_entry[plt_tlsdesc_entry_size / 4] =
4955ed0d50c3Schristos {
4956ed0d50c3Schristos   0xa9bf0fe2,	/* stp x2, x3, [sp, #-16]!  */
4957ed0d50c3Schristos   0x90000002,	/* adrp x2, 0 */
4958ed0d50c3Schristos   0x90000003,	/* adrp x3, 0 */
4959ed0d50c3Schristos   0xf9400042,	/* ldr x2, [x2, #0] */
4960ed0d50c3Schristos   0x91000063,	/* add x3, x3, 0 */
4961ed0d50c3Schristos   0xd61f0040,	/* br x2 */
4962ed0d50c3Schristos   0xd503201f,	/* nop */
4963ed0d50c3Schristos   0xd503201f,	/* nop */
4964ed0d50c3Schristos };
4965ed0d50c3Schristos 
4966ed0d50c3Schristos template<int size, bool big_endian>
4967ed0d50c3Schristos void
do_fill_tlsdesc_entry(unsigned char * pov,Address gotplt_address,Address plt_address,Address got_base,unsigned int tlsdesc_got_offset,unsigned int plt_offset)4968ed0d50c3Schristos Output_data_plt_aarch64_standard<size, big_endian>::do_fill_tlsdesc_entry(
4969ed0d50c3Schristos     unsigned char* pov,
4970ed0d50c3Schristos     Address gotplt_address,
4971ed0d50c3Schristos     Address plt_address,
4972ed0d50c3Schristos     Address got_base,
4973ed0d50c3Schristos     unsigned int tlsdesc_got_offset,
4974ed0d50c3Schristos     unsigned int plt_offset)
4975ed0d50c3Schristos {
4976ed0d50c3Schristos   memcpy(pov, tlsdesc_plt_entry, plt_tlsdesc_entry_size);
4977ed0d50c3Schristos 
4978ed0d50c3Schristos   // move DT_TLSDESC_GOT address into x2
4979ed0d50c3Schristos   // move .got.plt address into x3
4980ed0d50c3Schristos   Address tlsdesc_got_entry = got_base + tlsdesc_got_offset;
4981ed0d50c3Schristos   Address plt_entry_address = plt_address + plt_offset;
4982ed0d50c3Schristos 
4983ed0d50c3Schristos   // R_AARCH64_ADR_PREL_PG_HI21
4984ed0d50c3Schristos   AArch64_relocate_functions<size, big_endian>::adrp(
4985ed0d50c3Schristos       pov + 4,
4986ed0d50c3Schristos       tlsdesc_got_entry,
4987ed0d50c3Schristos       plt_entry_address + 4);
4988ed0d50c3Schristos 
4989ed0d50c3Schristos   // R_AARCH64_ADR_PREL_PG_HI21
4990ed0d50c3Schristos   AArch64_relocate_functions<size, big_endian>::adrp(
4991ed0d50c3Schristos       pov + 8,
4992ed0d50c3Schristos       gotplt_address,
4993ed0d50c3Schristos       plt_entry_address + 8);
4994ed0d50c3Schristos 
4995ed0d50c3Schristos   // R_AARCH64_LDST64_ABS_LO12
4996ed0d50c3Schristos   elfcpp::Swap<32, big_endian>::writeval(
4997ed0d50c3Schristos       pov + 12,
4998ed0d50c3Schristos       ((this->tlsdesc_plt_entry[3] & 0xffc003ff)
4999ed0d50c3Schristos        | ((tlsdesc_got_entry & 0xff8) << 7)));
5000ed0d50c3Schristos 
5001ed0d50c3Schristos   // R_AARCH64_ADD_ABS_LO12
5002ed0d50c3Schristos   elfcpp::Swap<32, big_endian>::writeval(
5003ed0d50c3Schristos       pov + 16,
5004ed0d50c3Schristos       ((this->tlsdesc_plt_entry[4] & 0xffc003ff)
5005ed0d50c3Schristos        | ((gotplt_address & 0xfff) << 10)));
5006ed0d50c3Schristos }
5007ed0d50c3Schristos 
5008ed0d50c3Schristos // Write out the PLT.  This uses the hand-coded instructions above,
5009ed0d50c3Schristos // and adjusts them as needed.  This is specified by the AMD64 ABI.
5010ed0d50c3Schristos 
5011ed0d50c3Schristos template<int size, bool big_endian>
5012ed0d50c3Schristos void
do_write(Output_file * of)5013ed0d50c3Schristos Output_data_plt_aarch64<size, big_endian>::do_write(Output_file* of)
5014ed0d50c3Schristos {
5015ed0d50c3Schristos   const off_t offset = this->offset();
5016ed0d50c3Schristos   const section_size_type oview_size =
5017ed0d50c3Schristos     convert_to_section_size_type(this->data_size());
5018ed0d50c3Schristos   unsigned char* const oview = of->get_output_view(offset, oview_size);
5019ed0d50c3Schristos 
5020ed0d50c3Schristos   const off_t got_file_offset = this->got_plt_->offset();
5021ed0d50c3Schristos   gold_assert(got_file_offset + this->got_plt_->data_size()
5022ed0d50c3Schristos 	      == this->got_irelative_->offset());
5023ed0d50c3Schristos 
5024ed0d50c3Schristos   const section_size_type got_size =
5025ed0d50c3Schristos       convert_to_section_size_type(this->got_plt_->data_size()
5026ed0d50c3Schristos 				   + this->got_irelative_->data_size());
5027ed0d50c3Schristos   unsigned char* const got_view = of->get_output_view(got_file_offset,
5028ed0d50c3Schristos 						      got_size);
5029ed0d50c3Schristos 
5030ed0d50c3Schristos   unsigned char* pov = oview;
5031ed0d50c3Schristos 
5032ed0d50c3Schristos   // The base address of the .plt section.
5033ed0d50c3Schristos   typename elfcpp::Elf_types<size>::Elf_Addr plt_address = this->address();
5034ed0d50c3Schristos   // The base address of the PLT portion of the .got section.
5035ed0d50c3Schristos   typename elfcpp::Elf_types<size>::Elf_Addr gotplt_address
5036ed0d50c3Schristos       = this->got_plt_->address();
5037ed0d50c3Schristos 
5038ed0d50c3Schristos   this->fill_first_plt_entry(pov, gotplt_address, plt_address);
5039ed0d50c3Schristos   pov += this->first_plt_entry_offset();
5040ed0d50c3Schristos 
5041ed0d50c3Schristos   // The first three entries in .got.plt are reserved.
5042ed0d50c3Schristos   unsigned char* got_pov = got_view;
5043ed0d50c3Schristos   memset(got_pov, 0, size / 8 * AARCH64_GOTPLT_RESERVE_COUNT);
5044ed0d50c3Schristos   got_pov += (size / 8) * AARCH64_GOTPLT_RESERVE_COUNT;
5045ed0d50c3Schristos 
5046ed0d50c3Schristos   unsigned int plt_offset = this->first_plt_entry_offset();
5047ed0d50c3Schristos   unsigned int got_offset = (size / 8) * AARCH64_GOTPLT_RESERVE_COUNT;
5048ed0d50c3Schristos   const unsigned int count = this->count_ + this->irelative_count_;
5049ed0d50c3Schristos   for (unsigned int plt_index = 0;
5050ed0d50c3Schristos        plt_index < count;
5051ed0d50c3Schristos        ++plt_index,
5052ed0d50c3Schristos 	 pov += this->get_plt_entry_size(),
5053ed0d50c3Schristos 	 got_pov += size / 8,
5054ed0d50c3Schristos 	 plt_offset += this->get_plt_entry_size(),
5055ed0d50c3Schristos 	 got_offset += size / 8)
5056ed0d50c3Schristos     {
5057ed0d50c3Schristos       // Set and adjust the PLT entry itself.
5058ed0d50c3Schristos       this->fill_plt_entry(pov, gotplt_address, plt_address,
5059ed0d50c3Schristos 			   got_offset, plt_offset);
5060ed0d50c3Schristos 
5061ed0d50c3Schristos       // Set the entry in the GOT, which points to plt0.
5062ed0d50c3Schristos       elfcpp::Swap<size, big_endian>::writeval(got_pov, plt_address);
5063ed0d50c3Schristos     }
5064ed0d50c3Schristos 
5065ed0d50c3Schristos   if (this->has_tlsdesc_entry())
5066ed0d50c3Schristos     {
5067ed0d50c3Schristos       // Set and adjust the reserved TLSDESC PLT entry.
5068ed0d50c3Schristos       unsigned int tlsdesc_got_offset = this->get_tlsdesc_got_offset();
5069ed0d50c3Schristos       // The base address of the .base section.
5070ed0d50c3Schristos       typename elfcpp::Elf_types<size>::Elf_Addr got_base =
5071ed0d50c3Schristos 	  this->got_->address();
5072ed0d50c3Schristos       this->fill_tlsdesc_entry(pov, gotplt_address, plt_address, got_base,
5073ed0d50c3Schristos 			       tlsdesc_got_offset, plt_offset);
5074ed0d50c3Schristos       pov += this->get_plt_tlsdesc_entry_size();
5075ed0d50c3Schristos     }
5076ed0d50c3Schristos 
5077ed0d50c3Schristos   gold_assert(static_cast<section_size_type>(pov - oview) == oview_size);
5078ed0d50c3Schristos   gold_assert(static_cast<section_size_type>(got_pov - got_view) == got_size);
5079ed0d50c3Schristos 
5080ed0d50c3Schristos   of->write_output_view(offset, oview_size, oview);
5081ed0d50c3Schristos   of->write_output_view(got_file_offset, got_size, got_view);
5082ed0d50c3Schristos }
5083ed0d50c3Schristos 
5084ed0d50c3Schristos // Telling how to update the immediate field of an instruction.
5085ed0d50c3Schristos struct AArch64_howto
5086ed0d50c3Schristos {
5087ed0d50c3Schristos   // The immediate field mask.
5088ed0d50c3Schristos   elfcpp::Elf_Xword dst_mask;
5089ed0d50c3Schristos 
5090ed0d50c3Schristos   // The offset to apply relocation immediate
5091ed0d50c3Schristos   int doffset;
5092ed0d50c3Schristos 
5093ed0d50c3Schristos   // The second part offset, if the immediate field has two parts.
5094ed0d50c3Schristos   // -1 if the immediate field has only one part.
5095ed0d50c3Schristos   int doffset2;
5096ed0d50c3Schristos };
5097ed0d50c3Schristos 
5098ed0d50c3Schristos static const AArch64_howto aarch64_howto[AArch64_reloc_property::INST_NUM] =
5099ed0d50c3Schristos {
5100ed0d50c3Schristos   {0, -1, -1},		// DATA
5101ed0d50c3Schristos   {0x1fffe0, 5, -1},	// MOVW  [20:5]-imm16
5102ed0d50c3Schristos   {0xffffe0, 5, -1},	// LD    [23:5]-imm19
5103ed0d50c3Schristos   {0x60ffffe0, 29, 5},	// ADR   [30:29]-immlo  [23:5]-immhi
5104ed0d50c3Schristos   {0x60ffffe0, 29, 5},	// ADRP  [30:29]-immlo  [23:5]-immhi
5105ed0d50c3Schristos   {0x3ffc00, 10, -1},	// ADD   [21:10]-imm12
5106ed0d50c3Schristos   {0x3ffc00, 10, -1},	// LDST  [21:10]-imm12
5107ed0d50c3Schristos   {0x7ffe0, 5, -1},	// TBZNZ [18:5]-imm14
5108ed0d50c3Schristos   {0xffffe0, 5, -1},	// CONDB [23:5]-imm19
5109ed0d50c3Schristos   {0x3ffffff, 0, -1},	// B     [25:0]-imm26
5110ed0d50c3Schristos   {0x3ffffff, 0, -1},	// CALL  [25:0]-imm26
5111ed0d50c3Schristos };
5112ed0d50c3Schristos 
5113ed0d50c3Schristos // AArch64 relocate function class
5114ed0d50c3Schristos 
5115ed0d50c3Schristos template<int size, bool big_endian>
5116ed0d50c3Schristos class AArch64_relocate_functions
5117ed0d50c3Schristos {
5118ed0d50c3Schristos  public:
5119ed0d50c3Schristos   typedef enum
5120ed0d50c3Schristos   {
5121ed0d50c3Schristos     STATUS_OKAY,	// No error during relocation.
5122ed0d50c3Schristos     STATUS_OVERFLOW,	// Relocation overflow.
5123ed0d50c3Schristos     STATUS_BAD_RELOC,	// Relocation cannot be applied.
5124ed0d50c3Schristos   } Status;
5125ed0d50c3Schristos 
5126ed0d50c3Schristos   typedef AArch64_relocate_functions<size, big_endian> This;
5127ed0d50c3Schristos   typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
5128ed0d50c3Schristos   typedef Relocate_info<size, big_endian> The_relocate_info;
5129ed0d50c3Schristos   typedef AArch64_relobj<size, big_endian> The_aarch64_relobj;
5130ed0d50c3Schristos   typedef Reloc_stub<size, big_endian> The_reloc_stub;
5131ed0d50c3Schristos   typedef Stub_table<size, big_endian> The_stub_table;
5132ed0d50c3Schristos   typedef elfcpp::Rela<size, big_endian> The_rela;
5133ed0d50c3Schristos   typedef typename elfcpp::Swap<size, big_endian>::Valtype AArch64_valtype;
5134ed0d50c3Schristos 
5135ed0d50c3Schristos   // Return the page address of the address.
5136ed0d50c3Schristos   // Page(address) = address & ~0xFFF
5137ed0d50c3Schristos 
5138ed0d50c3Schristos   static inline AArch64_valtype
Page(Address address)5139ed0d50c3Schristos   Page(Address address)
5140ed0d50c3Schristos   {
5141ed0d50c3Schristos     return (address & (~static_cast<Address>(0xFFF)));
5142ed0d50c3Schristos   }
5143ed0d50c3Schristos 
5144ed0d50c3Schristos  private:
5145ed0d50c3Schristos   // Update instruction (pointed by view) with selected bits (immed).
5146ed0d50c3Schristos   // val = (val & ~dst_mask) | (immed << doffset)
5147ed0d50c3Schristos 
5148ed0d50c3Schristos   template<int valsize>
5149ed0d50c3Schristos   static inline void
update_view(unsigned char * view,AArch64_valtype immed,elfcpp::Elf_Xword doffset,elfcpp::Elf_Xword dst_mask)5150ed0d50c3Schristos   update_view(unsigned char* view,
5151ed0d50c3Schristos 	      AArch64_valtype immed,
5152ed0d50c3Schristos 	      elfcpp::Elf_Xword doffset,
5153ed0d50c3Schristos 	      elfcpp::Elf_Xword dst_mask)
5154ed0d50c3Schristos   {
5155ed0d50c3Schristos     typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype;
5156ed0d50c3Schristos     Valtype* wv = reinterpret_cast<Valtype*>(view);
5157ed0d50c3Schristos     Valtype val = elfcpp::Swap<valsize, big_endian>::readval(wv);
5158ed0d50c3Schristos 
5159ed0d50c3Schristos     // Clear immediate fields.
5160ed0d50c3Schristos     val &= ~dst_mask;
5161ed0d50c3Schristos     elfcpp::Swap<valsize, big_endian>::writeval(wv,
5162ed0d50c3Schristos       static_cast<Valtype>(val | (immed << doffset)));
5163ed0d50c3Schristos   }
5164ed0d50c3Schristos 
5165ed0d50c3Schristos   // Update two parts of an instruction (pointed by view) with selected
5166ed0d50c3Schristos   // bits (immed1 and immed2).
5167ed0d50c3Schristos   // val = (val & ~dst_mask) | (immed1 << doffset1) | (immed2 << doffset2)
5168ed0d50c3Schristos 
5169ed0d50c3Schristos   template<int valsize>
5170ed0d50c3Schristos   static inline void
update_view_two_parts(unsigned char * view,AArch64_valtype immed1,AArch64_valtype immed2,elfcpp::Elf_Xword doffset1,elfcpp::Elf_Xword doffset2,elfcpp::Elf_Xword dst_mask)5171ed0d50c3Schristos   update_view_two_parts(
5172ed0d50c3Schristos     unsigned char* view,
5173ed0d50c3Schristos     AArch64_valtype immed1,
5174ed0d50c3Schristos     AArch64_valtype immed2,
5175ed0d50c3Schristos     elfcpp::Elf_Xword doffset1,
5176ed0d50c3Schristos     elfcpp::Elf_Xword doffset2,
5177ed0d50c3Schristos     elfcpp::Elf_Xword dst_mask)
5178ed0d50c3Schristos   {
5179ed0d50c3Schristos     typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype;
5180ed0d50c3Schristos     Valtype* wv = reinterpret_cast<Valtype*>(view);
5181ed0d50c3Schristos     Valtype val = elfcpp::Swap<valsize, big_endian>::readval(wv);
5182ed0d50c3Schristos     val &= ~dst_mask;
5183ed0d50c3Schristos     elfcpp::Swap<valsize, big_endian>::writeval(wv,
5184ed0d50c3Schristos       static_cast<Valtype>(val | (immed1 << doffset1) |
5185ed0d50c3Schristos 			   (immed2 << doffset2)));
5186ed0d50c3Schristos   }
5187ed0d50c3Schristos 
5188ed0d50c3Schristos   // Update adr or adrp instruction with immed.
5189ed0d50c3Schristos   // In adr and adrp: [30:29] immlo   [23:5] immhi
5190ed0d50c3Schristos 
5191ed0d50c3Schristos   static inline void
update_adr(unsigned char * view,AArch64_valtype immed)5192ed0d50c3Schristos   update_adr(unsigned char* view, AArch64_valtype immed)
5193ed0d50c3Schristos   {
5194ed0d50c3Schristos     elfcpp::Elf_Xword dst_mask = (0x3 << 29) | (0x7ffff << 5);
5195ed0d50c3Schristos     This::template update_view_two_parts<32>(
5196ed0d50c3Schristos       view,
5197ed0d50c3Schristos       immed & 0x3,
5198ed0d50c3Schristos       (immed & 0x1ffffc) >> 2,
5199ed0d50c3Schristos       29,
5200ed0d50c3Schristos       5,
5201ed0d50c3Schristos       dst_mask);
5202ed0d50c3Schristos   }
5203ed0d50c3Schristos 
5204ed0d50c3Schristos   // Update movz/movn instruction with bits immed.
5205ed0d50c3Schristos   // Set instruction to movz if is_movz is true, otherwise set instruction
5206ed0d50c3Schristos   // to movn.
5207ed0d50c3Schristos 
5208ed0d50c3Schristos   static inline void
update_movnz(unsigned char * view,AArch64_valtype immed,bool is_movz)5209ed0d50c3Schristos   update_movnz(unsigned char* view,
5210ed0d50c3Schristos 	       AArch64_valtype immed,
5211ed0d50c3Schristos 	       bool is_movz)
5212ed0d50c3Schristos   {
5213ed0d50c3Schristos     typedef typename elfcpp::Swap<32, big_endian>::Valtype Valtype;
5214ed0d50c3Schristos     Valtype* wv = reinterpret_cast<Valtype*>(view);
5215ed0d50c3Schristos     Valtype val = elfcpp::Swap<32, big_endian>::readval(wv);
5216ed0d50c3Schristos 
5217ed0d50c3Schristos     const elfcpp::Elf_Xword doffset =
5218ed0d50c3Schristos 	aarch64_howto[AArch64_reloc_property::INST_MOVW].doffset;
5219ed0d50c3Schristos     const elfcpp::Elf_Xword dst_mask =
5220ed0d50c3Schristos 	aarch64_howto[AArch64_reloc_property::INST_MOVW].dst_mask;
5221ed0d50c3Schristos 
5222ed0d50c3Schristos     // Clear immediate fields and opc code.
5223ed0d50c3Schristos     val &= ~(dst_mask | (0x3 << 29));
5224ed0d50c3Schristos 
5225ed0d50c3Schristos     // Set instruction to movz or movn.
5226ed0d50c3Schristos     // movz: [30:29] is 10   movn: [30:29] is 00
5227ed0d50c3Schristos     if (is_movz)
5228ed0d50c3Schristos       val |= (0x2 << 29);
5229ed0d50c3Schristos 
5230ed0d50c3Schristos     elfcpp::Swap<32, big_endian>::writeval(wv,
5231ed0d50c3Schristos       static_cast<Valtype>(val | (immed << doffset)));
5232ed0d50c3Schristos   }
5233ed0d50c3Schristos 
5234ed0d50c3Schristos  public:
5235ed0d50c3Schristos 
5236ed0d50c3Schristos   // Update selected bits in text.
5237ed0d50c3Schristos 
5238ed0d50c3Schristos   template<int valsize>
5239ed0d50c3Schristos   static inline typename This::Status
reloc_common(unsigned char * view,Address x,const AArch64_reloc_property * reloc_property)5240ed0d50c3Schristos   reloc_common(unsigned char* view, Address x,
5241ed0d50c3Schristos 		const AArch64_reloc_property* reloc_property)
5242ed0d50c3Schristos   {
5243ed0d50c3Schristos     // Select bits from X.
5244ed0d50c3Schristos     Address immed = reloc_property->select_x_value(x);
5245ed0d50c3Schristos 
5246ed0d50c3Schristos     // Update view.
5247ed0d50c3Schristos     const AArch64_reloc_property::Reloc_inst inst =
5248ed0d50c3Schristos       reloc_property->reloc_inst();
5249ed0d50c3Schristos     // If it is a data relocation or instruction has 2 parts of immediate
5250ed0d50c3Schristos     // fields, you should not call pcrela_general.
5251ed0d50c3Schristos     gold_assert(aarch64_howto[inst].doffset2 == -1 &&
5252ed0d50c3Schristos 		aarch64_howto[inst].doffset != -1);
5253ed0d50c3Schristos     This::template update_view<valsize>(view, immed,
5254ed0d50c3Schristos 					aarch64_howto[inst].doffset,
5255ed0d50c3Schristos 					aarch64_howto[inst].dst_mask);
5256ed0d50c3Schristos 
5257ed0d50c3Schristos     // Do check overflow or alignment if needed.
5258ed0d50c3Schristos     return (reloc_property->checkup_x_value(x)
5259ed0d50c3Schristos 	    ? This::STATUS_OKAY
5260ed0d50c3Schristos 	    : This::STATUS_OVERFLOW);
5261ed0d50c3Schristos   }
5262ed0d50c3Schristos 
5263ed0d50c3Schristos   // Construct a B insn. Note, although we group it here with other relocation
5264ed0d50c3Schristos   // operation, there is actually no 'relocation' involved here.
5265ed0d50c3Schristos   static inline void
construct_b(unsigned char * view,unsigned int branch_offset)5266ed0d50c3Schristos   construct_b(unsigned char* view, unsigned int branch_offset)
5267ed0d50c3Schristos   {
5268ed0d50c3Schristos     update_view_two_parts<32>(view, 0x05, (branch_offset >> 2),
5269ed0d50c3Schristos 			      26, 0, 0xffffffff);
5270ed0d50c3Schristos   }
5271ed0d50c3Schristos 
5272ed0d50c3Schristos   // Do a simple rela relocation at unaligned addresses.
5273ed0d50c3Schristos 
5274ed0d50c3Schristos   template<int valsize>
5275ed0d50c3Schristos   static inline typename This::Status
rela_ua(unsigned char * view,const Sized_relobj_file<size,big_endian> * object,const Symbol_value<size> * psymval,AArch64_valtype addend,const AArch64_reloc_property * reloc_property)5276ed0d50c3Schristos   rela_ua(unsigned char* view,
5277ed0d50c3Schristos 	  const Sized_relobj_file<size, big_endian>* object,
5278ed0d50c3Schristos 	  const Symbol_value<size>* psymval,
5279ed0d50c3Schristos 	  AArch64_valtype addend,
5280ed0d50c3Schristos 	  const AArch64_reloc_property* reloc_property)
5281ed0d50c3Schristos   {
5282ed0d50c3Schristos     typedef typename elfcpp::Swap_unaligned<valsize, big_endian>::Valtype
5283ed0d50c3Schristos       Valtype;
5284ed0d50c3Schristos     typename elfcpp::Elf_types<size>::Elf_Addr x =
5285ed0d50c3Schristos 	psymval->value(object, addend);
5286ed0d50c3Schristos     elfcpp::Swap_unaligned<valsize, big_endian>::writeval(view,
5287ed0d50c3Schristos       static_cast<Valtype>(x));
5288ed0d50c3Schristos     return (reloc_property->checkup_x_value(x)
5289ed0d50c3Schristos 	    ? This::STATUS_OKAY
5290ed0d50c3Schristos 	    : This::STATUS_OVERFLOW);
5291ed0d50c3Schristos   }
5292ed0d50c3Schristos 
5293ed0d50c3Schristos   // Do a simple pc-relative relocation at unaligned addresses.
5294ed0d50c3Schristos 
5295ed0d50c3Schristos   template<int valsize>
5296ed0d50c3Schristos   static inline typename This::Status
pcrela_ua(unsigned char * view,const Sized_relobj_file<size,big_endian> * object,const Symbol_value<size> * psymval,AArch64_valtype addend,Address address,const AArch64_reloc_property * reloc_property)5297ed0d50c3Schristos   pcrela_ua(unsigned char* view,
5298ed0d50c3Schristos 	    const Sized_relobj_file<size, big_endian>* object,
5299ed0d50c3Schristos 	    const Symbol_value<size>* psymval,
5300ed0d50c3Schristos 	    AArch64_valtype addend,
5301ed0d50c3Schristos 	    Address address,
5302ed0d50c3Schristos 	    const AArch64_reloc_property* reloc_property)
5303ed0d50c3Schristos   {
5304ed0d50c3Schristos     typedef typename elfcpp::Swap_unaligned<valsize, big_endian>::Valtype
5305ed0d50c3Schristos       Valtype;
5306ed0d50c3Schristos     Address x = psymval->value(object, addend) - address;
5307ed0d50c3Schristos     elfcpp::Swap_unaligned<valsize, big_endian>::writeval(view,
5308ed0d50c3Schristos       static_cast<Valtype>(x));
5309ed0d50c3Schristos     return (reloc_property->checkup_x_value(x)
5310ed0d50c3Schristos 	    ? This::STATUS_OKAY
5311ed0d50c3Schristos 	    : This::STATUS_OVERFLOW);
5312ed0d50c3Schristos   }
5313ed0d50c3Schristos 
5314ed0d50c3Schristos   // Do a simple rela relocation at aligned addresses.
5315ed0d50c3Schristos 
5316ed0d50c3Schristos   template<int valsize>
5317ed0d50c3Schristos   static inline typename This::Status
rela(unsigned char * view,const Sized_relobj_file<size,big_endian> * object,const Symbol_value<size> * psymval,AArch64_valtype addend,const AArch64_reloc_property * reloc_property)5318ed0d50c3Schristos   rela(
5319ed0d50c3Schristos     unsigned char* view,
5320ed0d50c3Schristos     const Sized_relobj_file<size, big_endian>* object,
5321ed0d50c3Schristos     const Symbol_value<size>* psymval,
5322ed0d50c3Schristos     AArch64_valtype addend,
5323ed0d50c3Schristos     const AArch64_reloc_property* reloc_property)
5324ed0d50c3Schristos   {
5325ed0d50c3Schristos     typedef typename elfcpp::Swap<valsize, big_endian>::Valtype Valtype;
5326ed0d50c3Schristos     Valtype* wv = reinterpret_cast<Valtype*>(view);
5327ed0d50c3Schristos     Address x = psymval->value(object, addend);
5328ed0d50c3Schristos     elfcpp::Swap<valsize, big_endian>::writeval(wv,static_cast<Valtype>(x));
5329ed0d50c3Schristos     return (reloc_property->checkup_x_value(x)
5330ed0d50c3Schristos 	    ? This::STATUS_OKAY
5331ed0d50c3Schristos 	    : This::STATUS_OVERFLOW);
5332ed0d50c3Schristos   }
5333ed0d50c3Schristos 
5334ed0d50c3Schristos   // Do relocate. Update selected bits in text.
5335ed0d50c3Schristos   // new_val = (val & ~dst_mask) | (immed << doffset)
5336ed0d50c3Schristos 
5337ed0d50c3Schristos   template<int valsize>
5338ed0d50c3Schristos   static inline typename This::Status
rela_general(unsigned char * view,const Sized_relobj_file<size,big_endian> * object,const Symbol_value<size> * psymval,AArch64_valtype addend,const AArch64_reloc_property * reloc_property)5339ed0d50c3Schristos   rela_general(unsigned char* view,
5340ed0d50c3Schristos 	       const Sized_relobj_file<size, big_endian>* object,
5341ed0d50c3Schristos 	       const Symbol_value<size>* psymval,
5342ed0d50c3Schristos 	       AArch64_valtype addend,
5343ed0d50c3Schristos 	       const AArch64_reloc_property* reloc_property)
5344ed0d50c3Schristos   {
5345ed0d50c3Schristos     // Calculate relocation.
5346ed0d50c3Schristos     Address x = psymval->value(object, addend);
5347ed0d50c3Schristos     return This::template reloc_common<valsize>(view, x, reloc_property);
5348ed0d50c3Schristos   }
5349ed0d50c3Schristos 
5350ed0d50c3Schristos   // Do relocate. Update selected bits in text.
5351ed0d50c3Schristos   // new val = (val & ~dst_mask) | (immed << doffset)
5352ed0d50c3Schristos 
5353ed0d50c3Schristos   template<int valsize>
5354ed0d50c3Schristos   static inline typename This::Status
rela_general(unsigned char * view,AArch64_valtype s,AArch64_valtype addend,const AArch64_reloc_property * reloc_property)5355ed0d50c3Schristos   rela_general(
5356ed0d50c3Schristos     unsigned char* view,
5357ed0d50c3Schristos     AArch64_valtype s,
5358ed0d50c3Schristos     AArch64_valtype addend,
5359ed0d50c3Schristos     const AArch64_reloc_property* reloc_property)
5360ed0d50c3Schristos   {
5361ed0d50c3Schristos     // Calculate relocation.
5362ed0d50c3Schristos     Address x = s + addend;
5363ed0d50c3Schristos     return This::template reloc_common<valsize>(view, x, reloc_property);
5364ed0d50c3Schristos   }
5365ed0d50c3Schristos 
5366ed0d50c3Schristos   // Do address relative relocate. Update selected bits in text.
5367ed0d50c3Schristos   // new val = (val & ~dst_mask) | (immed << doffset)
5368ed0d50c3Schristos 
5369ed0d50c3Schristos   template<int valsize>
5370ed0d50c3Schristos   static inline typename This::Status
pcrela_general(unsigned char * view,const Sized_relobj_file<size,big_endian> * object,const Symbol_value<size> * psymval,AArch64_valtype addend,Address address,const AArch64_reloc_property * reloc_property)5371ed0d50c3Schristos   pcrela_general(
5372ed0d50c3Schristos     unsigned char* view,
5373ed0d50c3Schristos     const Sized_relobj_file<size, big_endian>* object,
5374ed0d50c3Schristos     const Symbol_value<size>* psymval,
5375ed0d50c3Schristos     AArch64_valtype addend,
5376ed0d50c3Schristos     Address address,
5377ed0d50c3Schristos     const AArch64_reloc_property* reloc_property)
5378ed0d50c3Schristos   {
5379ed0d50c3Schristos     // Calculate relocation.
5380ed0d50c3Schristos     Address x = psymval->value(object, addend) - address;
5381ed0d50c3Schristos     return This::template reloc_common<valsize>(view, x, reloc_property);
5382ed0d50c3Schristos   }
5383ed0d50c3Schristos 
5384ed0d50c3Schristos 
5385ed0d50c3Schristos   // Calculate (S + A) - address, update adr instruction.
5386ed0d50c3Schristos 
5387ed0d50c3Schristos   static inline typename This::Status
adr(unsigned char * view,const Sized_relobj_file<size,big_endian> * object,const Symbol_value<size> * psymval,Address addend,Address address,const AArch64_reloc_property *)5388ed0d50c3Schristos   adr(unsigned char* view,
5389ed0d50c3Schristos       const Sized_relobj_file<size, big_endian>* object,
5390ed0d50c3Schristos       const Symbol_value<size>* psymval,
5391ed0d50c3Schristos       Address addend,
5392ed0d50c3Schristos       Address address,
5393ed0d50c3Schristos       const AArch64_reloc_property* /* reloc_property */)
5394ed0d50c3Schristos   {
5395ed0d50c3Schristos     AArch64_valtype x = psymval->value(object, addend) - address;
5396ed0d50c3Schristos     // Pick bits [20:0] of X.
5397ed0d50c3Schristos     AArch64_valtype immed = x & 0x1fffff;
5398ed0d50c3Schristos     update_adr(view, immed);
5399ed0d50c3Schristos     // Check -2^20 <= X < 2^20
5400ed0d50c3Schristos     return (size == 64 && Bits<21>::has_overflow((x))
5401ed0d50c3Schristos 	    ? This::STATUS_OVERFLOW
5402ed0d50c3Schristos 	    : This::STATUS_OKAY);
5403ed0d50c3Schristos   }
5404ed0d50c3Schristos 
5405ed0d50c3Schristos   // Calculate PG(S+A) - PG(address), update adrp instruction.
5406ed0d50c3Schristos   // R_AARCH64_ADR_PREL_PG_HI21
5407ed0d50c3Schristos 
5408ed0d50c3Schristos   static inline typename This::Status
adrp(unsigned char * view,Address sa,Address address)5409ed0d50c3Schristos   adrp(
5410ed0d50c3Schristos     unsigned char* view,
5411ed0d50c3Schristos     Address sa,
5412ed0d50c3Schristos     Address address)
5413ed0d50c3Schristos   {
5414ed0d50c3Schristos     AArch64_valtype x = This::Page(sa) - This::Page(address);
5415ed0d50c3Schristos     // Pick [32:12] of X.
5416ed0d50c3Schristos     AArch64_valtype immed = (x >> 12) & 0x1fffff;
5417ed0d50c3Schristos     update_adr(view, immed);
5418ed0d50c3Schristos     // Check -2^32 <= X < 2^32
5419ed0d50c3Schristos     return (size == 64 && Bits<33>::has_overflow((x))
5420ed0d50c3Schristos 	    ? This::STATUS_OVERFLOW
5421ed0d50c3Schristos 	    : This::STATUS_OKAY);
5422ed0d50c3Schristos   }
5423ed0d50c3Schristos 
5424ed0d50c3Schristos   // Calculate PG(S+A) - PG(address), update adrp instruction.
5425ed0d50c3Schristos   // R_AARCH64_ADR_PREL_PG_HI21
5426ed0d50c3Schristos 
5427ed0d50c3Schristos   static inline typename This::Status
adrp(unsigned char * view,const Sized_relobj_file<size,big_endian> * object,const Symbol_value<size> * psymval,Address addend,Address address,const AArch64_reloc_property * reloc_property)5428ed0d50c3Schristos   adrp(unsigned char* view,
5429ed0d50c3Schristos        const Sized_relobj_file<size, big_endian>* object,
5430ed0d50c3Schristos        const Symbol_value<size>* psymval,
5431ed0d50c3Schristos        Address addend,
5432ed0d50c3Schristos        Address address,
5433ed0d50c3Schristos        const AArch64_reloc_property* reloc_property)
5434ed0d50c3Schristos   {
5435ed0d50c3Schristos     Address sa = psymval->value(object, addend);
5436ed0d50c3Schristos     AArch64_valtype x = This::Page(sa) - This::Page(address);
5437ed0d50c3Schristos     // Pick [32:12] of X.
5438ed0d50c3Schristos     AArch64_valtype immed = (x >> 12) & 0x1fffff;
5439ed0d50c3Schristos     update_adr(view, immed);
5440ed0d50c3Schristos     return (reloc_property->checkup_x_value(x)
5441ed0d50c3Schristos 	    ? This::STATUS_OKAY
5442ed0d50c3Schristos 	    : This::STATUS_OVERFLOW);
5443ed0d50c3Schristos   }
5444ed0d50c3Schristos 
5445ed0d50c3Schristos   // Update mov[n/z] instruction. Check overflow if needed.
5446ed0d50c3Schristos   // If X >=0, set the instruction to movz and its immediate value to the
5447ed0d50c3Schristos   // selected bits S.
5448ed0d50c3Schristos   // If X < 0, set the instruction to movn and its immediate value to
5449ed0d50c3Schristos   // NOT (selected bits of).
5450ed0d50c3Schristos 
5451ed0d50c3Schristos   static inline typename This::Status
movnz(unsigned char * view,AArch64_valtype x,const AArch64_reloc_property * reloc_property)5452ed0d50c3Schristos   movnz(unsigned char* view,
5453ed0d50c3Schristos 	AArch64_valtype x,
5454ed0d50c3Schristos 	const AArch64_reloc_property* reloc_property)
5455ed0d50c3Schristos   {
5456ed0d50c3Schristos     // Select bits from X.
5457ed0d50c3Schristos     Address immed;
5458ed0d50c3Schristos     bool is_movz;
5459ed0d50c3Schristos     typedef typename elfcpp::Elf_types<size>::Elf_Swxword SignedW;
5460ed0d50c3Schristos     if (static_cast<SignedW>(x) >= 0)
5461ed0d50c3Schristos       {
5462ed0d50c3Schristos 	immed = reloc_property->select_x_value(x);
5463ed0d50c3Schristos         is_movz = true;
5464ed0d50c3Schristos       }
5465ed0d50c3Schristos     else
5466ed0d50c3Schristos       {
5467ed0d50c3Schristos 	immed = reloc_property->select_x_value(~x);;
5468ed0d50c3Schristos 	is_movz = false;
5469ed0d50c3Schristos       }
5470ed0d50c3Schristos 
5471ed0d50c3Schristos     // Update movnz instruction.
5472ed0d50c3Schristos     update_movnz(view, immed, is_movz);
5473ed0d50c3Schristos 
5474ed0d50c3Schristos     // Do check overflow or alignment if needed.
5475ed0d50c3Schristos     return (reloc_property->checkup_x_value(x)
5476ed0d50c3Schristos 	    ? This::STATUS_OKAY
5477ed0d50c3Schristos 	    : This::STATUS_OVERFLOW);
5478ed0d50c3Schristos   }
5479ed0d50c3Schristos 
5480ed0d50c3Schristos   static inline bool
5481ed0d50c3Schristos   maybe_apply_stub(unsigned int,
5482ed0d50c3Schristos 		   const The_relocate_info*,
5483ed0d50c3Schristos 		   const The_rela&,
5484ed0d50c3Schristos 		   unsigned char*,
5485ed0d50c3Schristos 		   Address,
5486ed0d50c3Schristos 		   const Sized_symbol<size>*,
5487ed0d50c3Schristos 		   const Symbol_value<size>*,
5488ed0d50c3Schristos 		   const Sized_relobj_file<size, big_endian>*,
5489ed0d50c3Schristos 		   section_size_type);
5490ed0d50c3Schristos 
5491ed0d50c3Schristos };  // End of AArch64_relocate_functions
5492ed0d50c3Schristos 
5493ed0d50c3Schristos 
5494ed0d50c3Schristos // For a certain relocation type (usually jump/branch), test to see if the
5495ed0d50c3Schristos // destination needs a stub to fulfil. If so, re-route the destination of the
5496ed0d50c3Schristos // original instruction to the stub, note, at this time, the stub has already
5497ed0d50c3Schristos // been generated.
5498ed0d50c3Schristos 
5499ed0d50c3Schristos template<int size, bool big_endian>
5500ed0d50c3Schristos bool
5501ed0d50c3Schristos AArch64_relocate_functions<size, big_endian>::
maybe_apply_stub(unsigned int r_type,const The_relocate_info * relinfo,const The_rela & rela,unsigned char * view,Address address,const Sized_symbol<size> * gsym,const Symbol_value<size> * psymval,const Sized_relobj_file<size,big_endian> * object,section_size_type current_group_size)5502ed0d50c3Schristos maybe_apply_stub(unsigned int r_type,
5503ed0d50c3Schristos 		 const The_relocate_info* relinfo,
5504ed0d50c3Schristos 		 const The_rela& rela,
5505ed0d50c3Schristos 		 unsigned char* view,
5506ed0d50c3Schristos 		 Address address,
5507ed0d50c3Schristos 		 const Sized_symbol<size>* gsym,
5508ed0d50c3Schristos 		 const Symbol_value<size>* psymval,
5509ed0d50c3Schristos 		 const Sized_relobj_file<size, big_endian>* object,
5510ed0d50c3Schristos 		 section_size_type current_group_size)
5511ed0d50c3Schristos {
5512ed0d50c3Schristos   if (parameters->options().relocatable())
5513ed0d50c3Schristos     return false;
5514ed0d50c3Schristos 
5515ed0d50c3Schristos   typename elfcpp::Elf_types<size>::Elf_Swxword addend = rela.get_r_addend();
5516ed0d50c3Schristos   Address branch_target = psymval->value(object, 0) + addend;
5517ed0d50c3Schristos   int stub_type =
5518ed0d50c3Schristos     The_reloc_stub::stub_type_for_reloc(r_type, address, branch_target);
5519ed0d50c3Schristos   if (stub_type == ST_NONE)
5520ed0d50c3Schristos     return false;
5521ed0d50c3Schristos 
5522ed0d50c3Schristos   const The_aarch64_relobj* aarch64_relobj =
5523ed0d50c3Schristos       static_cast<const The_aarch64_relobj*>(object);
552406324dcfSchristos   const AArch64_reloc_property* arp =
552506324dcfSchristos     aarch64_reloc_property_table->get_reloc_property(r_type);
552606324dcfSchristos   gold_assert(arp != NULL);
552706324dcfSchristos 
552806324dcfSchristos   // We don't create stubs for undefined symbols, but do for weak.
552906324dcfSchristos   if (gsym
553006324dcfSchristos       && !gsym->use_plt_offset(arp->reference_flags())
553106324dcfSchristos       && gsym->is_undefined())
553206324dcfSchristos     {
553306324dcfSchristos       gold_debug(DEBUG_TARGET,
553406324dcfSchristos 		 "stub: looking for a stub for undefined symbol %s in file %s",
553506324dcfSchristos 		 gsym->name(), aarch64_relobj->name().c_str());
553606324dcfSchristos       return false;
553706324dcfSchristos     }
553806324dcfSchristos 
5539ed0d50c3Schristos   The_stub_table* stub_table = aarch64_relobj->stub_table(relinfo->data_shndx);
5540ed0d50c3Schristos   gold_assert(stub_table != NULL);
5541ed0d50c3Schristos 
5542ed0d50c3Schristos   unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
5543ed0d50c3Schristos   typename The_reloc_stub::Key stub_key(stub_type, gsym, object, r_sym, addend);
5544ed0d50c3Schristos   The_reloc_stub* stub = stub_table->find_reloc_stub(stub_key);
5545ed0d50c3Schristos   gold_assert(stub != NULL);
5546ed0d50c3Schristos 
5547ed0d50c3Schristos   Address new_branch_target = stub_table->address() + stub->offset();
5548ed0d50c3Schristos   typename elfcpp::Swap<size, big_endian>::Valtype branch_offset =
5549ed0d50c3Schristos       new_branch_target - address;
5550ed0d50c3Schristos   typename This::Status status = This::template
5551ed0d50c3Schristos       rela_general<32>(view, branch_offset, 0, arp);
5552ed0d50c3Schristos   if (status != This::STATUS_OKAY)
5553ed0d50c3Schristos     gold_error(_("Stub is too far away, try a smaller value "
5554ed0d50c3Schristos 		 "for '--stub-group-size'. The current value is 0x%lx."),
5555ed0d50c3Schristos 	       static_cast<unsigned long>(current_group_size));
5556ed0d50c3Schristos   return true;
5557ed0d50c3Schristos }
5558ed0d50c3Schristos 
5559ed0d50c3Schristos 
5560ed0d50c3Schristos // Group input sections for stub generation.
5561ed0d50c3Schristos //
5562ed0d50c3Schristos // We group input sections in an output section so that the total size,
5563ed0d50c3Schristos // including any padding space due to alignment is smaller than GROUP_SIZE
5564ed0d50c3Schristos // unless the only input section in group is bigger than GROUP_SIZE already.
5565ed0d50c3Schristos // Then an ARM stub table is created to follow the last input section
5566ed0d50c3Schristos // in group.  For each group an ARM stub table is created an is placed
5567ed0d50c3Schristos // after the last group.  If STUB_ALWAYS_AFTER_BRANCH is false, we further
5568ed0d50c3Schristos // extend the group after the stub table.
5569ed0d50c3Schristos 
5570ed0d50c3Schristos template<int size, bool big_endian>
5571ed0d50c3Schristos void
group_sections(Layout * layout,section_size_type group_size,bool stubs_always_after_branch,const Task * task)5572ed0d50c3Schristos Target_aarch64<size, big_endian>::group_sections(
5573ed0d50c3Schristos     Layout* layout,
5574ed0d50c3Schristos     section_size_type group_size,
5575ed0d50c3Schristos     bool stubs_always_after_branch,
5576ed0d50c3Schristos     const Task* task)
5577ed0d50c3Schristos {
5578ed0d50c3Schristos   // Group input sections and insert stub table
5579ed0d50c3Schristos   Layout::Section_list section_list;
5580ed0d50c3Schristos   layout->get_executable_sections(&section_list);
5581ed0d50c3Schristos   for (Layout::Section_list::const_iterator p = section_list.begin();
5582ed0d50c3Schristos        p != section_list.end();
5583ed0d50c3Schristos        ++p)
5584ed0d50c3Schristos     {
5585ed0d50c3Schristos       AArch64_output_section<size, big_endian>* output_section =
5586ed0d50c3Schristos 	  static_cast<AArch64_output_section<size, big_endian>*>(*p);
5587ed0d50c3Schristos       output_section->group_sections(group_size, stubs_always_after_branch,
5588ed0d50c3Schristos 				     this, task);
5589ed0d50c3Schristos     }
5590ed0d50c3Schristos }
5591ed0d50c3Schristos 
5592ed0d50c3Schristos 
5593ed0d50c3Schristos // Find the AArch64_input_section object corresponding to the SHNDX-th input
5594ed0d50c3Schristos // section of RELOBJ.
5595ed0d50c3Schristos 
5596ed0d50c3Schristos template<int size, bool big_endian>
5597ed0d50c3Schristos AArch64_input_section<size, big_endian>*
find_aarch64_input_section(Relobj * relobj,unsigned int shndx) const5598ed0d50c3Schristos Target_aarch64<size, big_endian>::find_aarch64_input_section(
5599ed0d50c3Schristos     Relobj* relobj, unsigned int shndx) const
5600ed0d50c3Schristos {
5601ed0d50c3Schristos   Section_id sid(relobj, shndx);
5602ed0d50c3Schristos   typename AArch64_input_section_map::const_iterator p =
5603ed0d50c3Schristos     this->aarch64_input_section_map_.find(sid);
5604ed0d50c3Schristos   return (p != this->aarch64_input_section_map_.end()) ? p->second : NULL;
5605ed0d50c3Schristos }
5606ed0d50c3Schristos 
5607ed0d50c3Schristos 
5608ed0d50c3Schristos // Make a new AArch64_input_section object.
5609ed0d50c3Schristos 
5610ed0d50c3Schristos template<int size, bool big_endian>
5611ed0d50c3Schristos AArch64_input_section<size, big_endian>*
new_aarch64_input_section(Relobj * relobj,unsigned int shndx)5612ed0d50c3Schristos Target_aarch64<size, big_endian>::new_aarch64_input_section(
5613ed0d50c3Schristos     Relobj* relobj, unsigned int shndx)
5614ed0d50c3Schristos {
5615ed0d50c3Schristos   Section_id sid(relobj, shndx);
5616ed0d50c3Schristos 
5617ed0d50c3Schristos   AArch64_input_section<size, big_endian>* input_section =
5618ed0d50c3Schristos       new AArch64_input_section<size, big_endian>(relobj, shndx);
5619ed0d50c3Schristos   input_section->init();
5620ed0d50c3Schristos 
5621ed0d50c3Schristos   // Register new AArch64_input_section in map for look-up.
5622ed0d50c3Schristos   std::pair<typename AArch64_input_section_map::iterator,bool> ins =
5623ed0d50c3Schristos       this->aarch64_input_section_map_.insert(
5624ed0d50c3Schristos 	  std::make_pair(sid, input_section));
5625ed0d50c3Schristos 
5626ed0d50c3Schristos   // Make sure that it we have not created another AArch64_input_section
5627ed0d50c3Schristos   // for this input section already.
5628ed0d50c3Schristos   gold_assert(ins.second);
5629ed0d50c3Schristos 
5630ed0d50c3Schristos   return input_section;
5631ed0d50c3Schristos }
5632ed0d50c3Schristos 
5633ed0d50c3Schristos 
5634ed0d50c3Schristos // Relaxation hook.  This is where we do stub generation.
5635ed0d50c3Schristos 
5636ed0d50c3Schristos template<int size, bool big_endian>
5637ed0d50c3Schristos bool
do_relax(int pass,const Input_objects * input_objects,Symbol_table * symtab,Layout * layout,const Task * task)5638ed0d50c3Schristos Target_aarch64<size, big_endian>::do_relax(
5639ed0d50c3Schristos     int pass,
5640ed0d50c3Schristos     const Input_objects* input_objects,
5641ed0d50c3Schristos     Symbol_table* symtab,
5642ed0d50c3Schristos     Layout* layout ,
5643ed0d50c3Schristos     const Task* task)
5644ed0d50c3Schristos {
5645ed0d50c3Schristos   gold_assert(!parameters->options().relocatable());
5646ed0d50c3Schristos   if (pass == 1)
5647ed0d50c3Schristos     {
5648ed0d50c3Schristos       // We don't handle negative stub_group_size right now.
5649ed0d50c3Schristos       this->stub_group_size_ = abs(parameters->options().stub_group_size());
5650ed0d50c3Schristos       if (this->stub_group_size_ == 1)
5651ed0d50c3Schristos 	{
5652ed0d50c3Schristos 	  // Leave room for 4096 4-byte stub entries. If we exceed that, then we
5653ed0d50c3Schristos 	  // will fail to link.  The user will have to relink with an explicit
5654ed0d50c3Schristos 	  // group size option.
5655ed0d50c3Schristos 	  this->stub_group_size_ = The_reloc_stub::MAX_BRANCH_OFFSET -
5656ed0d50c3Schristos 				   4096 * 4;
5657ed0d50c3Schristos 	}
5658ed0d50c3Schristos       group_sections(layout, this->stub_group_size_, true, task);
5659ed0d50c3Schristos     }
5660ed0d50c3Schristos   else
5661ed0d50c3Schristos     {
5662ed0d50c3Schristos       // If this is not the first pass, addresses and file offsets have
5663ed0d50c3Schristos       // been reset at this point, set them here.
5664ed0d50c3Schristos       for (Stub_table_iterator sp = this->stub_tables_.begin();
5665ed0d50c3Schristos 	   sp != this->stub_tables_.end(); ++sp)
5666ed0d50c3Schristos 	{
5667ed0d50c3Schristos 	  The_stub_table* stt = *sp;
5668ed0d50c3Schristos 	  The_aarch64_input_section* owner = stt->owner();
5669ed0d50c3Schristos 	  off_t off = align_address(owner->original_size(),
5670ed0d50c3Schristos 				    stt->addralign());
5671ed0d50c3Schristos 	  stt->set_address_and_file_offset(owner->address() + off,
5672ed0d50c3Schristos 					   owner->offset() + off);
5673ed0d50c3Schristos 	}
5674ed0d50c3Schristos     }
5675ed0d50c3Schristos 
5676ed0d50c3Schristos   // Scan relocs for relocation stubs
5677ed0d50c3Schristos   for (Input_objects::Relobj_iterator op = input_objects->relobj_begin();
5678ed0d50c3Schristos        op != input_objects->relobj_end();
5679ed0d50c3Schristos        ++op)
5680ed0d50c3Schristos     {
5681ed0d50c3Schristos       The_aarch64_relobj* aarch64_relobj =
5682ed0d50c3Schristos 	  static_cast<The_aarch64_relobj*>(*op);
5683ed0d50c3Schristos       // Lock the object so we can read from it.  This is only called
5684ed0d50c3Schristos       // single-threaded from Layout::finalize, so it is OK to lock.
5685ed0d50c3Schristos       Task_lock_obj<Object> tl(task, aarch64_relobj);
5686ed0d50c3Schristos       aarch64_relobj->scan_sections_for_stubs(this, symtab, layout);
5687ed0d50c3Schristos     }
5688ed0d50c3Schristos 
5689ed0d50c3Schristos   bool any_stub_table_changed = false;
5690ed0d50c3Schristos   for (Stub_table_iterator siter = this->stub_tables_.begin();
5691ed0d50c3Schristos        siter != this->stub_tables_.end() && !any_stub_table_changed; ++siter)
5692ed0d50c3Schristos     {
5693ed0d50c3Schristos       The_stub_table* stub_table = *siter;
5694ed0d50c3Schristos       if (stub_table->update_data_size_changed_p())
5695ed0d50c3Schristos 	{
5696ed0d50c3Schristos 	  The_aarch64_input_section* owner = stub_table->owner();
5697ed0d50c3Schristos 	  uint64_t address = owner->address();
5698ed0d50c3Schristos 	  off_t offset = owner->offset();
5699ed0d50c3Schristos 	  owner->reset_address_and_file_offset();
5700ed0d50c3Schristos 	  owner->set_address_and_file_offset(address, offset);
5701ed0d50c3Schristos 
5702ed0d50c3Schristos 	  any_stub_table_changed = true;
5703ed0d50c3Schristos 	}
5704ed0d50c3Schristos     }
5705ed0d50c3Schristos 
5706ed0d50c3Schristos   // Do not continue relaxation.
5707ed0d50c3Schristos   bool continue_relaxation = any_stub_table_changed;
5708ed0d50c3Schristos   if (!continue_relaxation)
5709ed0d50c3Schristos     for (Stub_table_iterator sp = this->stub_tables_.begin();
5710ed0d50c3Schristos 	 (sp != this->stub_tables_.end());
5711ed0d50c3Schristos 	 ++sp)
5712ed0d50c3Schristos       (*sp)->finalize_stubs();
5713ed0d50c3Schristos 
5714ed0d50c3Schristos   return continue_relaxation;
5715ed0d50c3Schristos }
5716ed0d50c3Schristos 
5717ed0d50c3Schristos 
5718ed0d50c3Schristos // Make a new Stub_table.
5719ed0d50c3Schristos 
5720ed0d50c3Schristos template<int size, bool big_endian>
5721ed0d50c3Schristos Stub_table<size, big_endian>*
new_stub_table(AArch64_input_section<size,big_endian> * owner)5722ed0d50c3Schristos Target_aarch64<size, big_endian>::new_stub_table(
5723ed0d50c3Schristos     AArch64_input_section<size, big_endian>* owner)
5724ed0d50c3Schristos {
5725ed0d50c3Schristos   Stub_table<size, big_endian>* stub_table =
5726ed0d50c3Schristos       new Stub_table<size, big_endian>(owner);
5727ed0d50c3Schristos   stub_table->set_address(align_address(
5728ed0d50c3Schristos       owner->address() + owner->data_size(), 8));
5729ed0d50c3Schristos   stub_table->set_file_offset(owner->offset() + owner->data_size());
5730ed0d50c3Schristos   stub_table->finalize_data_size();
5731ed0d50c3Schristos 
5732ed0d50c3Schristos   this->stub_tables_.push_back(stub_table);
5733ed0d50c3Schristos 
5734ed0d50c3Schristos   return stub_table;
5735ed0d50c3Schristos }
5736ed0d50c3Schristos 
5737ed0d50c3Schristos 
5738ed0d50c3Schristos template<int size, bool big_endian>
5739ed0d50c3Schristos uint64_t
do_reloc_addend(void * arg,unsigned int r_type,uint64_t) const5740ed0d50c3Schristos Target_aarch64<size, big_endian>::do_reloc_addend(
5741ed0d50c3Schristos     void* arg, unsigned int r_type, uint64_t) const
5742ed0d50c3Schristos {
5743ed0d50c3Schristos   gold_assert(r_type == elfcpp::R_AARCH64_TLSDESC);
5744ed0d50c3Schristos   uintptr_t intarg = reinterpret_cast<uintptr_t>(arg);
5745ed0d50c3Schristos   gold_assert(intarg < this->tlsdesc_reloc_info_.size());
5746ed0d50c3Schristos   const Tlsdesc_info& ti(this->tlsdesc_reloc_info_[intarg]);
5747ed0d50c3Schristos   const Symbol_value<size>* psymval = ti.object->local_symbol(ti.r_sym);
5748ed0d50c3Schristos   gold_assert(psymval->is_tls_symbol());
5749ed0d50c3Schristos   // The value of a TLS symbol is the offset in the TLS segment.
5750ed0d50c3Schristos   return psymval->value(ti.object, 0);
5751ed0d50c3Schristos }
5752ed0d50c3Schristos 
5753ed0d50c3Schristos // Return the number of entries in the PLT.
5754ed0d50c3Schristos 
5755ed0d50c3Schristos template<int size, bool big_endian>
5756ed0d50c3Schristos unsigned int
plt_entry_count() const5757ed0d50c3Schristos Target_aarch64<size, big_endian>::plt_entry_count() const
5758ed0d50c3Schristos {
5759ed0d50c3Schristos   if (this->plt_ == NULL)
5760ed0d50c3Schristos     return 0;
5761ed0d50c3Schristos   return this->plt_->entry_count();
5762ed0d50c3Schristos }
5763ed0d50c3Schristos 
5764ed0d50c3Schristos // Return the offset of the first non-reserved PLT entry.
5765ed0d50c3Schristos 
5766ed0d50c3Schristos template<int size, bool big_endian>
5767ed0d50c3Schristos unsigned int
first_plt_entry_offset() const5768ed0d50c3Schristos Target_aarch64<size, big_endian>::first_plt_entry_offset() const
5769ed0d50c3Schristos {
5770ed0d50c3Schristos   return this->plt_->first_plt_entry_offset();
5771ed0d50c3Schristos }
5772ed0d50c3Schristos 
5773ed0d50c3Schristos // Return the size of each PLT entry.
5774ed0d50c3Schristos 
5775ed0d50c3Schristos template<int size, bool big_endian>
5776ed0d50c3Schristos unsigned int
plt_entry_size() const5777ed0d50c3Schristos Target_aarch64<size, big_endian>::plt_entry_size() const
5778ed0d50c3Schristos {
5779ed0d50c3Schristos   return this->plt_->get_plt_entry_size();
5780ed0d50c3Schristos }
5781ed0d50c3Schristos 
5782ed0d50c3Schristos // Define the _TLS_MODULE_BASE_ symbol in the TLS segment.
5783ed0d50c3Schristos 
5784ed0d50c3Schristos template<int size, bool big_endian>
5785ed0d50c3Schristos void
define_tls_base_symbol(Symbol_table * symtab,Layout * layout)5786ed0d50c3Schristos Target_aarch64<size, big_endian>::define_tls_base_symbol(
5787ed0d50c3Schristos     Symbol_table* symtab, Layout* layout)
5788ed0d50c3Schristos {
5789ed0d50c3Schristos   if (this->tls_base_symbol_defined_)
5790ed0d50c3Schristos     return;
5791ed0d50c3Schristos 
5792ed0d50c3Schristos   Output_segment* tls_segment = layout->tls_segment();
5793ed0d50c3Schristos   if (tls_segment != NULL)
5794ed0d50c3Schristos     {
5795ed0d50c3Schristos       // _TLS_MODULE_BASE_ always points to the beginning of tls segment.
5796ed0d50c3Schristos       symtab->define_in_output_segment("_TLS_MODULE_BASE_", NULL,
5797ed0d50c3Schristos 				       Symbol_table::PREDEFINED,
5798ed0d50c3Schristos 				       tls_segment, 0, 0,
5799ed0d50c3Schristos 				       elfcpp::STT_TLS,
5800ed0d50c3Schristos 				       elfcpp::STB_LOCAL,
5801ed0d50c3Schristos 				       elfcpp::STV_HIDDEN, 0,
5802ed0d50c3Schristos 				       Symbol::SEGMENT_START,
5803ed0d50c3Schristos 				       true);
5804ed0d50c3Schristos     }
5805ed0d50c3Schristos   this->tls_base_symbol_defined_ = true;
5806ed0d50c3Schristos }
5807ed0d50c3Schristos 
5808ed0d50c3Schristos // Create the reserved PLT and GOT entries for the TLS descriptor resolver.
5809ed0d50c3Schristos 
5810ed0d50c3Schristos template<int size, bool big_endian>
5811ed0d50c3Schristos void
reserve_tlsdesc_entries(Symbol_table * symtab,Layout * layout)5812ed0d50c3Schristos Target_aarch64<size, big_endian>::reserve_tlsdesc_entries(
5813ed0d50c3Schristos     Symbol_table* symtab, Layout* layout)
5814ed0d50c3Schristos {
5815ed0d50c3Schristos   if (this->plt_ == NULL)
5816ed0d50c3Schristos     this->make_plt_section(symtab, layout);
5817ed0d50c3Schristos 
5818ed0d50c3Schristos   if (!this->plt_->has_tlsdesc_entry())
5819ed0d50c3Schristos     {
5820ed0d50c3Schristos       // Allocate the TLSDESC_GOT entry.
5821ed0d50c3Schristos       Output_data_got_aarch64<size, big_endian>* got =
5822ed0d50c3Schristos 	  this->got_section(symtab, layout);
5823ed0d50c3Schristos       unsigned int got_offset = got->add_constant(0);
5824ed0d50c3Schristos 
5825ed0d50c3Schristos       // Allocate the TLSDESC_PLT entry.
5826ed0d50c3Schristos       this->plt_->reserve_tlsdesc_entry(got_offset);
5827ed0d50c3Schristos     }
5828ed0d50c3Schristos }
5829ed0d50c3Schristos 
5830ed0d50c3Schristos // Create a GOT entry for the TLS module index.
5831ed0d50c3Schristos 
5832ed0d50c3Schristos template<int size, bool big_endian>
5833ed0d50c3Schristos unsigned int
got_mod_index_entry(Symbol_table * symtab,Layout * layout,Sized_relobj_file<size,big_endian> * object)5834ed0d50c3Schristos Target_aarch64<size, big_endian>::got_mod_index_entry(
5835ed0d50c3Schristos     Symbol_table* symtab, Layout* layout,
5836ed0d50c3Schristos     Sized_relobj_file<size, big_endian>* object)
5837ed0d50c3Schristos {
5838ed0d50c3Schristos   if (this->got_mod_index_offset_ == -1U)
5839ed0d50c3Schristos     {
5840ed0d50c3Schristos       gold_assert(symtab != NULL && layout != NULL && object != NULL);
5841ed0d50c3Schristos       Reloc_section* rela_dyn = this->rela_dyn_section(layout);
5842ed0d50c3Schristos       Output_data_got_aarch64<size, big_endian>* got =
5843ed0d50c3Schristos 	  this->got_section(symtab, layout);
5844ed0d50c3Schristos       unsigned int got_offset = got->add_constant(0);
5845ed0d50c3Schristos       rela_dyn->add_local(object, 0, elfcpp::R_AARCH64_TLS_DTPMOD64, got,
5846ed0d50c3Schristos 			  got_offset, 0);
5847ed0d50c3Schristos       got->add_constant(0);
5848ed0d50c3Schristos       this->got_mod_index_offset_ = got_offset;
5849ed0d50c3Schristos     }
5850ed0d50c3Schristos   return this->got_mod_index_offset_;
5851ed0d50c3Schristos }
5852ed0d50c3Schristos 
5853ed0d50c3Schristos // Optimize the TLS relocation type based on what we know about the
5854ed0d50c3Schristos // symbol.  IS_FINAL is true if the final address of this symbol is
5855ed0d50c3Schristos // known at link time.
5856ed0d50c3Schristos 
5857ed0d50c3Schristos template<int size, bool big_endian>
5858ed0d50c3Schristos tls::Tls_optimization
optimize_tls_reloc(bool is_final,int r_type)5859ed0d50c3Schristos Target_aarch64<size, big_endian>::optimize_tls_reloc(bool is_final,
5860ed0d50c3Schristos 						     int r_type)
5861ed0d50c3Schristos {
5862ed0d50c3Schristos   // If we are generating a shared library, then we can't do anything
5863ed0d50c3Schristos   // in the linker
5864ed0d50c3Schristos   if (parameters->options().shared())
5865ed0d50c3Schristos     return tls::TLSOPT_NONE;
5866ed0d50c3Schristos 
5867ed0d50c3Schristos   switch (r_type)
5868ed0d50c3Schristos     {
5869ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSGD_ADR_PAGE21:
5870ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSGD_ADD_LO12_NC:
5871ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_LD_PREL19:
5872ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_ADR_PREL21:
5873ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_ADR_PAGE21:
5874ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_LD64_LO12:
5875ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_ADD_LO12:
5876ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_OFF_G1:
5877ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_OFF_G0_NC:
5878ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_LDR:
5879ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_ADD:
5880ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_CALL:
5881ed0d50c3Schristos       // These are General-Dynamic which permits fully general TLS
5882ed0d50c3Schristos       // access.  Since we know that we are generating an executable,
5883ed0d50c3Schristos       // we can convert this to Initial-Exec.  If we also know that
5884ed0d50c3Schristos       // this is a local symbol, we can further switch to Local-Exec.
5885ed0d50c3Schristos       if (is_final)
5886ed0d50c3Schristos 	return tls::TLSOPT_TO_LE;
5887ed0d50c3Schristos       return tls::TLSOPT_TO_IE;
5888ed0d50c3Schristos 
5889ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADR_PAGE21:
5890ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADD_LO12_NC:
5891ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G1:
5892ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
5893ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_HI12:
5894ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:
5895ed0d50c3Schristos       // These are Local-Dynamic, which refer to local symbols in the
5896ed0d50c3Schristos       // dynamic TLS block. Since we know that we generating an
5897ed0d50c3Schristos       // executable, we can switch to Local-Exec.
5898ed0d50c3Schristos       return tls::TLSOPT_TO_LE;
5899ed0d50c3Schristos 
5900ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSIE_MOVW_GOTTPREL_G1:
5901ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC:
5902ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
5903ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
5904ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSIE_LD_GOTTPREL_PREL19:
5905ed0d50c3Schristos       // These are Initial-Exec relocs which get the thread offset
5906ed0d50c3Schristos       // from the GOT. If we know that we are linking against the
5907ed0d50c3Schristos       // local symbol, we can switch to Local-Exec, which links the
5908ed0d50c3Schristos       // thread offset into the instruction.
5909ed0d50c3Schristos       if (is_final)
5910ed0d50c3Schristos 	return tls::TLSOPT_TO_LE;
5911ed0d50c3Schristos       return tls::TLSOPT_NONE;
5912ed0d50c3Schristos 
5913ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G2:
5914ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G1:
5915ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
5916ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G0:
5917ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
5918ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_HI12:
5919ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12:
5920ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
592106324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12:
592206324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
592306324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12:
592406324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
592506324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12:
592606324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
592706324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12:
592806324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
5929ed0d50c3Schristos       // When we already have Local-Exec, there is nothing further we
5930ed0d50c3Schristos       // can do.
5931ed0d50c3Schristos       return tls::TLSOPT_NONE;
5932ed0d50c3Schristos 
5933ed0d50c3Schristos     default:
5934ed0d50c3Schristos       gold_unreachable();
5935ed0d50c3Schristos     }
5936ed0d50c3Schristos }
5937ed0d50c3Schristos 
5938ed0d50c3Schristos // Returns true if this relocation type could be that of a function pointer.
5939ed0d50c3Schristos 
5940ed0d50c3Schristos template<int size, bool big_endian>
5941ed0d50c3Schristos inline bool
possible_function_pointer_reloc(unsigned int r_type)5942ed0d50c3Schristos Target_aarch64<size, big_endian>::Scan::possible_function_pointer_reloc(
5943ed0d50c3Schristos   unsigned int r_type)
5944ed0d50c3Schristos {
5945ed0d50c3Schristos   switch (r_type)
5946ed0d50c3Schristos     {
5947ed0d50c3Schristos     case elfcpp::R_AARCH64_ADR_PREL_PG_HI21:
5948ed0d50c3Schristos     case elfcpp::R_AARCH64_ADR_PREL_PG_HI21_NC:
5949ed0d50c3Schristos     case elfcpp::R_AARCH64_ADD_ABS_LO12_NC:
5950ed0d50c3Schristos     case elfcpp::R_AARCH64_ADR_GOT_PAGE:
5951ed0d50c3Schristos     case elfcpp::R_AARCH64_LD64_GOT_LO12_NC:
5952ed0d50c3Schristos       {
5953ed0d50c3Schristos 	return true;
5954ed0d50c3Schristos       }
5955ed0d50c3Schristos     }
5956ed0d50c3Schristos   return false;
5957ed0d50c3Schristos }
5958ed0d50c3Schristos 
5959ed0d50c3Schristos // For safe ICF, scan a relocation for a local symbol to check if it
5960ed0d50c3Schristos // corresponds to a function pointer being taken.  In that case mark
5961ed0d50c3Schristos // the function whose pointer was taken as not foldable.
5962ed0d50c3Schristos 
5963ed0d50c3Schristos template<int size, bool big_endian>
5964ed0d50c3Schristos inline bool
local_reloc_may_be_function_pointer(Symbol_table *,Layout *,Target_aarch64<size,big_endian> *,Sized_relobj_file<size,big_endian> *,unsigned int,Output_section *,const elfcpp::Rela<size,big_endian> &,unsigned int r_type,const elfcpp::Sym<size,big_endian> &)5965ed0d50c3Schristos Target_aarch64<size, big_endian>::Scan::local_reloc_may_be_function_pointer(
5966ed0d50c3Schristos   Symbol_table* ,
5967ed0d50c3Schristos   Layout* ,
5968ed0d50c3Schristos   Target_aarch64<size, big_endian>* ,
5969ed0d50c3Schristos   Sized_relobj_file<size, big_endian>* ,
5970ed0d50c3Schristos   unsigned int ,
5971ed0d50c3Schristos   Output_section* ,
5972ed0d50c3Schristos   const elfcpp::Rela<size, big_endian>& ,
5973ed0d50c3Schristos   unsigned int r_type,
5974ed0d50c3Schristos   const elfcpp::Sym<size, big_endian>&)
5975ed0d50c3Schristos {
5976ed0d50c3Schristos   // When building a shared library, do not fold any local symbols.
5977ed0d50c3Schristos   return (parameters->options().shared()
5978ed0d50c3Schristos 	  || possible_function_pointer_reloc(r_type));
5979ed0d50c3Schristos }
5980ed0d50c3Schristos 
5981ed0d50c3Schristos // For safe ICF, scan a relocation for a global symbol to check if it
5982ed0d50c3Schristos // corresponds to a function pointer being taken.  In that case mark
5983ed0d50c3Schristos // the function whose pointer was taken as not foldable.
5984ed0d50c3Schristos 
5985ed0d50c3Schristos template<int size, bool big_endian>
5986ed0d50c3Schristos inline bool
global_reloc_may_be_function_pointer(Symbol_table *,Layout *,Target_aarch64<size,big_endian> *,Sized_relobj_file<size,big_endian> *,unsigned int,Output_section *,const elfcpp::Rela<size,big_endian> &,unsigned int r_type,Symbol * gsym)5987ed0d50c3Schristos Target_aarch64<size, big_endian>::Scan::global_reloc_may_be_function_pointer(
5988ed0d50c3Schristos   Symbol_table* ,
5989ed0d50c3Schristos   Layout* ,
5990ed0d50c3Schristos   Target_aarch64<size, big_endian>* ,
5991ed0d50c3Schristos   Sized_relobj_file<size, big_endian>* ,
5992ed0d50c3Schristos   unsigned int ,
5993ed0d50c3Schristos   Output_section* ,
5994ed0d50c3Schristos   const elfcpp::Rela<size, big_endian>& ,
5995ed0d50c3Schristos   unsigned int r_type,
5996ed0d50c3Schristos   Symbol* gsym)
5997ed0d50c3Schristos {
5998ed0d50c3Schristos   // When building a shared library, do not fold symbols whose visibility
5999ed0d50c3Schristos   // is hidden, internal or protected.
6000ed0d50c3Schristos   return ((parameters->options().shared()
6001ed0d50c3Schristos 	   && (gsym->visibility() == elfcpp::STV_INTERNAL
6002ed0d50c3Schristos 	       || gsym->visibility() == elfcpp::STV_PROTECTED
6003ed0d50c3Schristos 	       || gsym->visibility() == elfcpp::STV_HIDDEN))
6004ed0d50c3Schristos 	  || possible_function_pointer_reloc(r_type));
6005ed0d50c3Schristos }
6006ed0d50c3Schristos 
6007ed0d50c3Schristos // Report an unsupported relocation against a local symbol.
6008ed0d50c3Schristos 
6009ed0d50c3Schristos template<int size, bool big_endian>
6010ed0d50c3Schristos void
unsupported_reloc_local(Sized_relobj_file<size,big_endian> * object,unsigned int r_type)6011ed0d50c3Schristos Target_aarch64<size, big_endian>::Scan::unsupported_reloc_local(
6012ed0d50c3Schristos      Sized_relobj_file<size, big_endian>* object,
6013ed0d50c3Schristos      unsigned int r_type)
6014ed0d50c3Schristos {
6015ed0d50c3Schristos   gold_error(_("%s: unsupported reloc %u against local symbol"),
6016ed0d50c3Schristos 	     object->name().c_str(), r_type);
6017ed0d50c3Schristos }
6018ed0d50c3Schristos 
6019ed0d50c3Schristos // We are about to emit a dynamic relocation of type R_TYPE.  If the
6020ed0d50c3Schristos // dynamic linker does not support it, issue an error.
6021ed0d50c3Schristos 
6022ed0d50c3Schristos template<int size, bool big_endian>
6023ed0d50c3Schristos void
check_non_pic(Relobj * object,unsigned int r_type)6024ed0d50c3Schristos Target_aarch64<size, big_endian>::Scan::check_non_pic(Relobj* object,
6025ed0d50c3Schristos 						      unsigned int r_type)
6026ed0d50c3Schristos {
6027ed0d50c3Schristos   gold_assert(r_type != elfcpp::R_AARCH64_NONE);
6028ed0d50c3Schristos 
6029ed0d50c3Schristos   switch (r_type)
6030ed0d50c3Schristos     {
6031ed0d50c3Schristos     // These are the relocation types supported by glibc for AARCH64.
6032ed0d50c3Schristos     case elfcpp::R_AARCH64_NONE:
6033ed0d50c3Schristos     case elfcpp::R_AARCH64_COPY:
6034ed0d50c3Schristos     case elfcpp::R_AARCH64_GLOB_DAT:
6035ed0d50c3Schristos     case elfcpp::R_AARCH64_JUMP_SLOT:
6036ed0d50c3Schristos     case elfcpp::R_AARCH64_RELATIVE:
6037ed0d50c3Schristos     case elfcpp::R_AARCH64_TLS_DTPREL64:
6038ed0d50c3Schristos     case elfcpp::R_AARCH64_TLS_DTPMOD64:
6039ed0d50c3Schristos     case elfcpp::R_AARCH64_TLS_TPREL64:
6040ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC:
6041ed0d50c3Schristos     case elfcpp::R_AARCH64_IRELATIVE:
6042ed0d50c3Schristos     case elfcpp::R_AARCH64_ABS32:
6043ed0d50c3Schristos     case elfcpp::R_AARCH64_ABS64:
6044ed0d50c3Schristos       return;
6045ed0d50c3Schristos 
6046ed0d50c3Schristos     default:
6047ed0d50c3Schristos       break;
6048ed0d50c3Schristos     }
6049ed0d50c3Schristos 
6050ed0d50c3Schristos   // This prevents us from issuing more than one error per reloc
6051ed0d50c3Schristos   // section. But we can still wind up issuing more than one
6052ed0d50c3Schristos   // error per object file.
6053ed0d50c3Schristos   if (this->issued_non_pic_error_)
6054ed0d50c3Schristos     return;
6055ed0d50c3Schristos   gold_assert(parameters->options().output_is_position_independent());
6056ed0d50c3Schristos   object->error(_("requires unsupported dynamic reloc; "
6057ed0d50c3Schristos 		  "recompile with -fPIC"));
6058ed0d50c3Schristos   this->issued_non_pic_error_ = true;
6059ed0d50c3Schristos   return;
6060ed0d50c3Schristos }
6061ed0d50c3Schristos 
6062ed0d50c3Schristos // Return whether we need to make a PLT entry for a relocation of the
6063ed0d50c3Schristos // given type against a STT_GNU_IFUNC symbol.
6064ed0d50c3Schristos 
6065ed0d50c3Schristos template<int size, bool big_endian>
6066ed0d50c3Schristos bool
reloc_needs_plt_for_ifunc(Sized_relobj_file<size,big_endian> * object,unsigned int r_type)6067ed0d50c3Schristos Target_aarch64<size, big_endian>::Scan::reloc_needs_plt_for_ifunc(
6068ed0d50c3Schristos     Sized_relobj_file<size, big_endian>* object,
6069ed0d50c3Schristos     unsigned int r_type)
6070ed0d50c3Schristos {
6071ed0d50c3Schristos   const AArch64_reloc_property* arp =
6072ed0d50c3Schristos       aarch64_reloc_property_table->get_reloc_property(r_type);
6073ed0d50c3Schristos   gold_assert(arp != NULL);
6074ed0d50c3Schristos 
6075ed0d50c3Schristos   int flags = arp->reference_flags();
6076ed0d50c3Schristos   if (flags & Symbol::TLS_REF)
6077ed0d50c3Schristos     {
6078ed0d50c3Schristos       gold_error(_("%s: unsupported TLS reloc %s for IFUNC symbol"),
6079ed0d50c3Schristos 		 object->name().c_str(), arp->name().c_str());
6080ed0d50c3Schristos       return false;
6081ed0d50c3Schristos     }
6082ed0d50c3Schristos   return flags != 0;
6083ed0d50c3Schristos }
6084ed0d50c3Schristos 
6085ed0d50c3Schristos // Scan a relocation for a local symbol.
6086ed0d50c3Schristos 
6087ed0d50c3Schristos template<int size, bool big_endian>
6088ed0d50c3Schristos inline void
local(Symbol_table * symtab,Layout * layout,Target_aarch64<size,big_endian> * target,Sized_relobj_file<size,big_endian> * object,unsigned int data_shndx,Output_section * output_section,const elfcpp::Rela<size,big_endian> & rela,unsigned int r_type,const elfcpp::Sym<size,big_endian> & lsym,bool is_discarded)6089ed0d50c3Schristos Target_aarch64<size, big_endian>::Scan::local(
6090ed0d50c3Schristos     Symbol_table* symtab,
6091ed0d50c3Schristos     Layout* layout,
6092ed0d50c3Schristos     Target_aarch64<size, big_endian>* target,
6093ed0d50c3Schristos     Sized_relobj_file<size, big_endian>* object,
6094ed0d50c3Schristos     unsigned int data_shndx,
6095ed0d50c3Schristos     Output_section* output_section,
6096ed0d50c3Schristos     const elfcpp::Rela<size, big_endian>& rela,
6097ed0d50c3Schristos     unsigned int r_type,
6098ed0d50c3Schristos     const elfcpp::Sym<size, big_endian>& lsym,
6099ed0d50c3Schristos     bool is_discarded)
6100ed0d50c3Schristos {
6101ed0d50c3Schristos   if (is_discarded)
6102ed0d50c3Schristos     return;
6103ed0d50c3Schristos 
6104ed0d50c3Schristos   typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>
6105ed0d50c3Schristos       Reloc_section;
6106ed0d50c3Schristos   unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
6107ed0d50c3Schristos 
6108ed0d50c3Schristos   // A local STT_GNU_IFUNC symbol may require a PLT entry.
6109ed0d50c3Schristos   bool is_ifunc = lsym.get_st_type() == elfcpp::STT_GNU_IFUNC;
6110ed0d50c3Schristos   if (is_ifunc && this->reloc_needs_plt_for_ifunc(object, r_type))
6111ed0d50c3Schristos     target->make_local_ifunc_plt_entry(symtab, layout, object, r_sym);
6112ed0d50c3Schristos 
6113ed0d50c3Schristos   switch (r_type)
6114ed0d50c3Schristos     {
6115ed0d50c3Schristos     case elfcpp::R_AARCH64_NONE:
6116ed0d50c3Schristos       break;
6117ed0d50c3Schristos 
6118ed0d50c3Schristos     case elfcpp::R_AARCH64_ABS32:
6119ed0d50c3Schristos     case elfcpp::R_AARCH64_ABS16:
6120ed0d50c3Schristos       if (parameters->options().output_is_position_independent())
6121ed0d50c3Schristos 	{
6122ed0d50c3Schristos 	  gold_error(_("%s: unsupported reloc %u in pos independent link."),
6123ed0d50c3Schristos 		     object->name().c_str(), r_type);
6124ed0d50c3Schristos 	}
6125ed0d50c3Schristos       break;
6126ed0d50c3Schristos 
6127ed0d50c3Schristos     case elfcpp::R_AARCH64_ABS64:
6128ed0d50c3Schristos       // If building a shared library or pie, we need to mark this as a dynmic
6129ed0d50c3Schristos       // reloction, so that the dynamic loader can relocate it.
6130ed0d50c3Schristos       if (parameters->options().output_is_position_independent())
6131ed0d50c3Schristos 	{
6132ed0d50c3Schristos 	  Reloc_section* rela_dyn = target->rela_dyn_section(layout);
6133ed0d50c3Schristos 	  rela_dyn->add_local_relative(object, r_sym,
6134ed0d50c3Schristos 				       elfcpp::R_AARCH64_RELATIVE,
6135ed0d50c3Schristos 				       output_section,
6136ed0d50c3Schristos 				       data_shndx,
6137ed0d50c3Schristos 				       rela.get_r_offset(),
6138ed0d50c3Schristos 				       rela.get_r_addend(),
6139ed0d50c3Schristos 				       is_ifunc);
6140ed0d50c3Schristos 	}
6141ed0d50c3Schristos       break;
6142ed0d50c3Schristos 
6143ed0d50c3Schristos     case elfcpp::R_AARCH64_PREL64:
6144ed0d50c3Schristos     case elfcpp::R_AARCH64_PREL32:
6145ed0d50c3Schristos     case elfcpp::R_AARCH64_PREL16:
6146ed0d50c3Schristos       break;
6147ed0d50c3Schristos 
6148ed0d50c3Schristos     case elfcpp::R_AARCH64_ADR_GOT_PAGE:
6149ed0d50c3Schristos     case elfcpp::R_AARCH64_LD64_GOT_LO12_NC:
6150ed0d50c3Schristos     case elfcpp::R_AARCH64_LD64_GOTPAGE_LO15:
6151ed0d50c3Schristos       // The above relocations are used to access GOT entries.
6152ed0d50c3Schristos       {
6153ed0d50c3Schristos 	Output_data_got_aarch64<size, big_endian>* got =
6154ed0d50c3Schristos 	    target->got_section(symtab, layout);
6155ed0d50c3Schristos 	bool is_new = false;
6156ed0d50c3Schristos 	// This symbol requires a GOT entry.
6157ed0d50c3Schristos 	if (is_ifunc)
6158ed0d50c3Schristos 	  is_new = got->add_local_plt(object, r_sym, GOT_TYPE_STANDARD);
6159ed0d50c3Schristos 	else
6160ed0d50c3Schristos 	  is_new = got->add_local(object, r_sym, GOT_TYPE_STANDARD);
6161ed0d50c3Schristos 	if (is_new && parameters->options().output_is_position_independent())
6162ed0d50c3Schristos 	  target->rela_dyn_section(layout)->
6163ed0d50c3Schristos 	    add_local_relative(object,
6164ed0d50c3Schristos 			       r_sym,
6165ed0d50c3Schristos 			       elfcpp::R_AARCH64_RELATIVE,
6166ed0d50c3Schristos 			       got,
6167ed0d50c3Schristos 			       object->local_got_offset(r_sym,
6168ed0d50c3Schristos 							GOT_TYPE_STANDARD),
6169ed0d50c3Schristos 			       0,
6170ed0d50c3Schristos 			       false);
6171ed0d50c3Schristos       }
6172ed0d50c3Schristos       break;
6173ed0d50c3Schristos 
617406324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G0:        // 263
617506324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G0_NC:     // 264
617606324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G1:        // 265
617706324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G1_NC:     // 266
617806324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G2:        // 267
617906324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G2_NC:     // 268
618006324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G3:        // 269
618106324dcfSchristos     case elfcpp::R_AARCH64_MOVW_SABS_G0:        // 270
618206324dcfSchristos     case elfcpp::R_AARCH64_MOVW_SABS_G1:        // 271
618306324dcfSchristos     case elfcpp::R_AARCH64_MOVW_SABS_G2:        // 272
618406324dcfSchristos       if (parameters->options().output_is_position_independent())
618506324dcfSchristos 	{
618606324dcfSchristos 	  gold_error(_("%s: unsupported reloc %u in pos independent link."),
618706324dcfSchristos 		     object->name().c_str(), r_type);
618806324dcfSchristos 	}
618906324dcfSchristos       break;
619006324dcfSchristos 
6191ed0d50c3Schristos     case elfcpp::R_AARCH64_LD_PREL_LO19:        // 273
6192ed0d50c3Schristos     case elfcpp::R_AARCH64_ADR_PREL_LO21:       // 274
6193ed0d50c3Schristos     case elfcpp::R_AARCH64_ADR_PREL_PG_HI21:    // 275
6194ed0d50c3Schristos     case elfcpp::R_AARCH64_ADR_PREL_PG_HI21_NC: // 276
6195ed0d50c3Schristos     case elfcpp::R_AARCH64_ADD_ABS_LO12_NC:     // 277
6196ed0d50c3Schristos     case elfcpp::R_AARCH64_LDST8_ABS_LO12_NC:   // 278
6197ed0d50c3Schristos     case elfcpp::R_AARCH64_LDST16_ABS_LO12_NC:  // 284
6198ed0d50c3Schristos     case elfcpp::R_AARCH64_LDST32_ABS_LO12_NC:  // 285
6199ed0d50c3Schristos     case elfcpp::R_AARCH64_LDST64_ABS_LO12_NC:  // 286
6200ed0d50c3Schristos     case elfcpp::R_AARCH64_LDST128_ABS_LO12_NC: // 299
6201ed0d50c3Schristos        break;
6202ed0d50c3Schristos 
6203ed0d50c3Schristos     // Control flow, pc-relative. We don't need to do anything for a relative
6204ed0d50c3Schristos     // addressing relocation against a local symbol if it does not reference
6205ed0d50c3Schristos     // the GOT.
6206ed0d50c3Schristos     case elfcpp::R_AARCH64_TSTBR14:
6207ed0d50c3Schristos     case elfcpp::R_AARCH64_CONDBR19:
6208ed0d50c3Schristos     case elfcpp::R_AARCH64_JUMP26:
6209ed0d50c3Schristos     case elfcpp::R_AARCH64_CALL26:
6210ed0d50c3Schristos       break;
6211ed0d50c3Schristos 
6212ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
6213ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
6214ed0d50c3Schristos       {
6215ed0d50c3Schristos 	tls::Tls_optimization tlsopt = Target_aarch64<size, big_endian>::
6216ed0d50c3Schristos 	  optimize_tls_reloc(!parameters->options().shared(), r_type);
6217ed0d50c3Schristos 	if (tlsopt == tls::TLSOPT_TO_LE)
6218ed0d50c3Schristos 	  break;
6219ed0d50c3Schristos 
6220ed0d50c3Schristos 	layout->set_has_static_tls();
6221ed0d50c3Schristos 	// Create a GOT entry for the tp-relative offset.
6222ed0d50c3Schristos 	if (!parameters->doing_static_link())
6223ed0d50c3Schristos 	  {
6224ed0d50c3Schristos 	    Output_data_got_aarch64<size, big_endian>* got =
6225ed0d50c3Schristos 		target->got_section(symtab, layout);
6226ed0d50c3Schristos 	    got->add_local_with_rel(object, r_sym, GOT_TYPE_TLS_OFFSET,
6227ed0d50c3Schristos 				    target->rela_dyn_section(layout),
6228ed0d50c3Schristos 				    elfcpp::R_AARCH64_TLS_TPREL64);
6229ed0d50c3Schristos 	  }
6230ed0d50c3Schristos 	else if (!object->local_has_got_offset(r_sym,
6231ed0d50c3Schristos 					       GOT_TYPE_TLS_OFFSET))
6232ed0d50c3Schristos 	  {
6233ed0d50c3Schristos 	    Output_data_got_aarch64<size, big_endian>* got =
6234ed0d50c3Schristos 		target->got_section(symtab, layout);
6235ed0d50c3Schristos 	    got->add_local(object, r_sym, GOT_TYPE_TLS_OFFSET);
6236ed0d50c3Schristos 	    unsigned int got_offset =
6237ed0d50c3Schristos 		object->local_got_offset(r_sym, GOT_TYPE_TLS_OFFSET);
6238ed0d50c3Schristos 	    const elfcpp::Elf_Xword addend = rela.get_r_addend();
6239ed0d50c3Schristos 	    gold_assert(addend == 0);
6240ed0d50c3Schristos 	    got->add_static_reloc(got_offset, elfcpp::R_AARCH64_TLS_TPREL64,
6241ed0d50c3Schristos 				  object, r_sym);
6242ed0d50c3Schristos 	  }
6243ed0d50c3Schristos       }
6244ed0d50c3Schristos       break;
6245ed0d50c3Schristos 
6246ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSGD_ADR_PAGE21:
6247ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSGD_ADD_LO12_NC:
6248ed0d50c3Schristos       {
6249ed0d50c3Schristos 	tls::Tls_optimization tlsopt = Target_aarch64<size, big_endian>::
6250ed0d50c3Schristos 	    optimize_tls_reloc(!parameters->options().shared(), r_type);
6251ed0d50c3Schristos 	if (tlsopt == tls::TLSOPT_TO_LE)
6252ed0d50c3Schristos 	  {
6253ed0d50c3Schristos 	    layout->set_has_static_tls();
6254ed0d50c3Schristos 	    break;
6255ed0d50c3Schristos 	  }
6256ed0d50c3Schristos 	gold_assert(tlsopt == tls::TLSOPT_NONE);
6257ed0d50c3Schristos 
6258ed0d50c3Schristos 	Output_data_got_aarch64<size, big_endian>* got =
6259ed0d50c3Schristos 	    target->got_section(symtab, layout);
6260ed0d50c3Schristos 	got->add_local_pair_with_rel(object,r_sym, data_shndx,
6261ed0d50c3Schristos 				     GOT_TYPE_TLS_PAIR,
6262ed0d50c3Schristos 				     target->rela_dyn_section(layout),
6263ed0d50c3Schristos 				     elfcpp::R_AARCH64_TLS_DTPMOD64);
6264ed0d50c3Schristos       }
6265ed0d50c3Schristos       break;
6266ed0d50c3Schristos 
6267ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G2:
6268ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G1:
6269ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
6270ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G0:
6271ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
6272ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_HI12:
6273ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12:
6274ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
627506324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12:
627606324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
627706324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12:
627806324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
627906324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12:
628006324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
628106324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12:
628206324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
6283ed0d50c3Schristos       {
6284ed0d50c3Schristos 	layout->set_has_static_tls();
6285ed0d50c3Schristos 	bool output_is_shared = parameters->options().shared();
6286ed0d50c3Schristos 	if (output_is_shared)
6287ed0d50c3Schristos 	  gold_error(_("%s: unsupported TLSLE reloc %u in shared code."),
6288ed0d50c3Schristos 		     object->name().c_str(), r_type);
6289ed0d50c3Schristos       }
6290ed0d50c3Schristos       break;
6291ed0d50c3Schristos 
6292ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADR_PAGE21:
6293ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADD_LO12_NC:
6294ed0d50c3Schristos       {
6295ed0d50c3Schristos 	tls::Tls_optimization tlsopt = Target_aarch64<size, big_endian>::
6296ed0d50c3Schristos 	    optimize_tls_reloc(!parameters->options().shared(), r_type);
6297ed0d50c3Schristos 	if (tlsopt == tls::TLSOPT_NONE)
6298ed0d50c3Schristos 	  {
6299ed0d50c3Schristos 	    // Create a GOT entry for the module index.
6300ed0d50c3Schristos 	    target->got_mod_index_entry(symtab, layout, object);
6301ed0d50c3Schristos 	  }
6302ed0d50c3Schristos 	else if (tlsopt != tls::TLSOPT_TO_LE)
6303ed0d50c3Schristos 	  unsupported_reloc_local(object, r_type);
6304ed0d50c3Schristos       }
6305ed0d50c3Schristos       break;
6306ed0d50c3Schristos 
6307ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G1:
6308ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
6309ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_HI12:
6310ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:
6311ed0d50c3Schristos       break;
6312ed0d50c3Schristos 
6313ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_ADR_PAGE21:
6314ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_LD64_LO12:
6315ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_ADD_LO12:
6316ed0d50c3Schristos       {
6317ed0d50c3Schristos 	tls::Tls_optimization tlsopt = Target_aarch64<size, big_endian>::
6318ed0d50c3Schristos 	    optimize_tls_reloc(!parameters->options().shared(), r_type);
6319ed0d50c3Schristos 	target->define_tls_base_symbol(symtab, layout);
6320ed0d50c3Schristos 	if (tlsopt == tls::TLSOPT_NONE)
6321ed0d50c3Schristos 	  {
6322ed0d50c3Schristos 	    // Create reserved PLT and GOT entries for the resolver.
6323ed0d50c3Schristos 	    target->reserve_tlsdesc_entries(symtab, layout);
6324ed0d50c3Schristos 
6325ed0d50c3Schristos 	    // Generate a double GOT entry with an R_AARCH64_TLSDESC reloc.
6326ed0d50c3Schristos 	    // The R_AARCH64_TLSDESC reloc is resolved lazily, so the GOT
6327ed0d50c3Schristos 	    // entry needs to be in an area in .got.plt, not .got. Call
6328ed0d50c3Schristos 	    // got_section to make sure the section has been created.
6329ed0d50c3Schristos 	    target->got_section(symtab, layout);
6330ed0d50c3Schristos 	    Output_data_got<size, big_endian>* got =
6331ed0d50c3Schristos 		target->got_tlsdesc_section();
6332ed0d50c3Schristos 	    unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
6333ed0d50c3Schristos 	    if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC))
6334ed0d50c3Schristos 	      {
6335ed0d50c3Schristos 		unsigned int got_offset = got->add_constant(0);
6336ed0d50c3Schristos 		got->add_constant(0);
6337ed0d50c3Schristos 		object->set_local_got_offset(r_sym, GOT_TYPE_TLS_DESC,
6338ed0d50c3Schristos 					     got_offset);
6339ed0d50c3Schristos 		Reloc_section* rt = target->rela_tlsdesc_section(layout);
6340ed0d50c3Schristos 		// We store the arguments we need in a vector, and use
6341ed0d50c3Schristos 		// the index into the vector as the parameter to pass
6342ed0d50c3Schristos 		// to the target specific routines.
6343ed0d50c3Schristos 		uintptr_t intarg = target->add_tlsdesc_info(object, r_sym);
6344ed0d50c3Schristos 		void* arg = reinterpret_cast<void*>(intarg);
6345ed0d50c3Schristos 		rt->add_target_specific(elfcpp::R_AARCH64_TLSDESC, arg,
6346ed0d50c3Schristos 					got, got_offset, 0);
6347ed0d50c3Schristos 	      }
6348ed0d50c3Schristos 	  }
6349ed0d50c3Schristos 	else if (tlsopt != tls::TLSOPT_TO_LE)
6350ed0d50c3Schristos 	  unsupported_reloc_local(object, r_type);
6351ed0d50c3Schristos       }
6352ed0d50c3Schristos       break;
6353ed0d50c3Schristos 
6354ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_CALL:
6355ed0d50c3Schristos       break;
6356ed0d50c3Schristos 
6357ed0d50c3Schristos     default:
6358ed0d50c3Schristos       unsupported_reloc_local(object, r_type);
6359ed0d50c3Schristos     }
6360ed0d50c3Schristos }
6361ed0d50c3Schristos 
6362ed0d50c3Schristos 
6363ed0d50c3Schristos // Report an unsupported relocation against a global symbol.
6364ed0d50c3Schristos 
6365ed0d50c3Schristos template<int size, bool big_endian>
6366ed0d50c3Schristos void
unsupported_reloc_global(Sized_relobj_file<size,big_endian> * object,unsigned int r_type,Symbol * gsym)6367ed0d50c3Schristos Target_aarch64<size, big_endian>::Scan::unsupported_reloc_global(
6368ed0d50c3Schristos     Sized_relobj_file<size, big_endian>* object,
6369ed0d50c3Schristos     unsigned int r_type,
6370ed0d50c3Schristos     Symbol* gsym)
6371ed0d50c3Schristos {
6372ed0d50c3Schristos   gold_error(_("%s: unsupported reloc %u against global symbol %s"),
6373ed0d50c3Schristos 	     object->name().c_str(), r_type, gsym->demangled_name().c_str());
6374ed0d50c3Schristos }
6375ed0d50c3Schristos 
6376ed0d50c3Schristos template<int size, bool big_endian>
6377ed0d50c3Schristos inline void
global(Symbol_table * symtab,Layout * layout,Target_aarch64<size,big_endian> * target,Sized_relobj_file<size,big_endian> * object,unsigned int data_shndx,Output_section * output_section,const elfcpp::Rela<size,big_endian> & rela,unsigned int r_type,Symbol * gsym)6378ed0d50c3Schristos Target_aarch64<size, big_endian>::Scan::global(
6379ed0d50c3Schristos     Symbol_table* symtab,
6380ed0d50c3Schristos     Layout* layout,
6381ed0d50c3Schristos     Target_aarch64<size, big_endian>* target,
6382ed0d50c3Schristos     Sized_relobj_file<size, big_endian> * object,
6383ed0d50c3Schristos     unsigned int data_shndx,
6384ed0d50c3Schristos     Output_section* output_section,
6385ed0d50c3Schristos     const elfcpp::Rela<size, big_endian>& rela,
6386ed0d50c3Schristos     unsigned int r_type,
6387ed0d50c3Schristos     Symbol* gsym)
6388ed0d50c3Schristos {
6389ed0d50c3Schristos   // A STT_GNU_IFUNC symbol may require a PLT entry.
6390ed0d50c3Schristos   if (gsym->type() == elfcpp::STT_GNU_IFUNC
6391ed0d50c3Schristos       && this->reloc_needs_plt_for_ifunc(object, r_type))
6392ed0d50c3Schristos     target->make_plt_entry(symtab, layout, gsym);
6393ed0d50c3Schristos 
6394ed0d50c3Schristos   typedef Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>
6395ed0d50c3Schristos     Reloc_section;
6396ed0d50c3Schristos   const AArch64_reloc_property* arp =
6397ed0d50c3Schristos       aarch64_reloc_property_table->get_reloc_property(r_type);
6398ed0d50c3Schristos   gold_assert(arp != NULL);
6399ed0d50c3Schristos 
6400ed0d50c3Schristos   switch (r_type)
6401ed0d50c3Schristos     {
6402ed0d50c3Schristos     case elfcpp::R_AARCH64_NONE:
6403ed0d50c3Schristos       break;
6404ed0d50c3Schristos 
6405ed0d50c3Schristos     case elfcpp::R_AARCH64_ABS16:
6406ed0d50c3Schristos     case elfcpp::R_AARCH64_ABS32:
6407ed0d50c3Schristos     case elfcpp::R_AARCH64_ABS64:
6408ed0d50c3Schristos       {
6409ed0d50c3Schristos 	// Make a PLT entry if necessary.
6410ed0d50c3Schristos 	if (gsym->needs_plt_entry())
6411ed0d50c3Schristos 	  {
6412ed0d50c3Schristos 	    target->make_plt_entry(symtab, layout, gsym);
6413ed0d50c3Schristos 	    // Since this is not a PC-relative relocation, we may be
6414ed0d50c3Schristos 	    // taking the address of a function. In that case we need to
6415ed0d50c3Schristos 	    // set the entry in the dynamic symbol table to the address of
6416ed0d50c3Schristos 	    // the PLT entry.
6417ed0d50c3Schristos 	    if (gsym->is_from_dynobj() && !parameters->options().shared())
6418ed0d50c3Schristos 	      gsym->set_needs_dynsym_value();
6419ed0d50c3Schristos 	  }
6420ed0d50c3Schristos 	// Make a dynamic relocation if necessary.
6421ed0d50c3Schristos 	if (gsym->needs_dynamic_reloc(arp->reference_flags()))
6422ed0d50c3Schristos 	  {
6423ed0d50c3Schristos 	    if (!parameters->options().output_is_position_independent()
6424ed0d50c3Schristos 		&& gsym->may_need_copy_reloc())
6425ed0d50c3Schristos 	      {
6426ed0d50c3Schristos 		target->copy_reloc(symtab, layout, object,
6427ed0d50c3Schristos 				   data_shndx, output_section, gsym, rela);
6428ed0d50c3Schristos 	      }
6429ed0d50c3Schristos 	    else if (r_type == elfcpp::R_AARCH64_ABS64
6430ed0d50c3Schristos 		     && gsym->type() == elfcpp::STT_GNU_IFUNC
6431ed0d50c3Schristos 		     && gsym->can_use_relative_reloc(false)
6432ed0d50c3Schristos 		     && !gsym->is_from_dynobj()
6433ed0d50c3Schristos 		     && !gsym->is_undefined()
6434ed0d50c3Schristos 		     && !gsym->is_preemptible())
6435ed0d50c3Schristos 	      {
6436ed0d50c3Schristos 		// Use an IRELATIVE reloc for a locally defined STT_GNU_IFUNC
6437ed0d50c3Schristos 		// symbol. This makes a function address in a PIE executable
6438ed0d50c3Schristos 		// match the address in a shared library that it links against.
6439ed0d50c3Schristos 		Reloc_section* rela_dyn =
6440ed0d50c3Schristos 		    target->rela_irelative_section(layout);
6441ed0d50c3Schristos 		unsigned int r_type = elfcpp::R_AARCH64_IRELATIVE;
6442ed0d50c3Schristos 		rela_dyn->add_symbolless_global_addend(gsym, r_type,
6443ed0d50c3Schristos 						       output_section, object,
6444ed0d50c3Schristos 						       data_shndx,
6445ed0d50c3Schristos 						       rela.get_r_offset(),
6446ed0d50c3Schristos 						       rela.get_r_addend());
6447ed0d50c3Schristos 	      }
6448ed0d50c3Schristos 	    else if (r_type == elfcpp::R_AARCH64_ABS64
6449ed0d50c3Schristos 		     && gsym->can_use_relative_reloc(false))
6450ed0d50c3Schristos 	      {
6451ed0d50c3Schristos 		Reloc_section* rela_dyn = target->rela_dyn_section(layout);
6452ed0d50c3Schristos 		rela_dyn->add_global_relative(gsym,
6453ed0d50c3Schristos 					      elfcpp::R_AARCH64_RELATIVE,
6454ed0d50c3Schristos 					      output_section,
6455ed0d50c3Schristos 					      object,
6456ed0d50c3Schristos 					      data_shndx,
6457ed0d50c3Schristos 					      rela.get_r_offset(),
6458ed0d50c3Schristos 					      rela.get_r_addend(),
6459ed0d50c3Schristos 					      false);
6460ed0d50c3Schristos 	      }
6461ed0d50c3Schristos 	    else
6462ed0d50c3Schristos 	      {
6463ed0d50c3Schristos 		check_non_pic(object, r_type);
6464ed0d50c3Schristos 		Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>*
6465ed0d50c3Schristos 		    rela_dyn = target->rela_dyn_section(layout);
6466ed0d50c3Schristos 		rela_dyn->add_global(
6467ed0d50c3Schristos 		  gsym, r_type, output_section, object,
6468ed0d50c3Schristos 		  data_shndx, rela.get_r_offset(),rela.get_r_addend());
6469ed0d50c3Schristos 	      }
6470ed0d50c3Schristos 	  }
6471ed0d50c3Schristos       }
6472ed0d50c3Schristos       break;
6473ed0d50c3Schristos 
6474ed0d50c3Schristos     case elfcpp::R_AARCH64_PREL16:
6475ed0d50c3Schristos     case elfcpp::R_AARCH64_PREL32:
6476ed0d50c3Schristos     case elfcpp::R_AARCH64_PREL64:
6477ed0d50c3Schristos       // This is used to fill the GOT absolute address.
6478ed0d50c3Schristos       if (gsym->needs_plt_entry())
6479ed0d50c3Schristos 	{
6480ed0d50c3Schristos 	  target->make_plt_entry(symtab, layout, gsym);
6481ed0d50c3Schristos 	}
6482ed0d50c3Schristos       break;
6483ed0d50c3Schristos 
648406324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G0:        // 263
648506324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G0_NC:     // 264
648606324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G1:        // 265
648706324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G1_NC:     // 266
648806324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G2:        // 267
648906324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G2_NC:     // 268
649006324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G3:        // 269
649106324dcfSchristos     case elfcpp::R_AARCH64_MOVW_SABS_G0:        // 270
649206324dcfSchristos     case elfcpp::R_AARCH64_MOVW_SABS_G1:        // 271
649306324dcfSchristos     case elfcpp::R_AARCH64_MOVW_SABS_G2:        // 272
649406324dcfSchristos       if (parameters->options().output_is_position_independent())
649506324dcfSchristos 	{
649606324dcfSchristos 	  gold_error(_("%s: unsupported reloc %u in pos independent link."),
649706324dcfSchristos 		     object->name().c_str(), r_type);
649806324dcfSchristos 	}
6499*b88e3e88Schristos       // Make a PLT entry if necessary.
6500*b88e3e88Schristos       if (gsym->needs_plt_entry())
6501*b88e3e88Schristos 	{
6502*b88e3e88Schristos 	  target->make_plt_entry(symtab, layout, gsym);
6503*b88e3e88Schristos 	  // Since this is not a PC-relative relocation, we may be
6504*b88e3e88Schristos 	  // taking the address of a function. In that case we need to
6505*b88e3e88Schristos 	  // set the entry in the dynamic symbol table to the address of
6506*b88e3e88Schristos 	  // the PLT entry.
6507*b88e3e88Schristos 	  if (gsym->is_from_dynobj() && !parameters->options().shared())
6508*b88e3e88Schristos 	    gsym->set_needs_dynsym_value();
6509*b88e3e88Schristos 	}
651006324dcfSchristos       break;
651106324dcfSchristos 
6512ed0d50c3Schristos     case elfcpp::R_AARCH64_LD_PREL_LO19:        // 273
6513ed0d50c3Schristos     case elfcpp::R_AARCH64_ADR_PREL_LO21:       // 274
6514ed0d50c3Schristos     case elfcpp::R_AARCH64_ADR_PREL_PG_HI21:    // 275
6515ed0d50c3Schristos     case elfcpp::R_AARCH64_ADR_PREL_PG_HI21_NC: // 276
6516ed0d50c3Schristos     case elfcpp::R_AARCH64_ADD_ABS_LO12_NC:     // 277
6517ed0d50c3Schristos     case elfcpp::R_AARCH64_LDST8_ABS_LO12_NC:   // 278
6518ed0d50c3Schristos     case elfcpp::R_AARCH64_LDST16_ABS_LO12_NC:  // 284
6519ed0d50c3Schristos     case elfcpp::R_AARCH64_LDST32_ABS_LO12_NC:  // 285
6520ed0d50c3Schristos     case elfcpp::R_AARCH64_LDST64_ABS_LO12_NC:  // 286
6521ed0d50c3Schristos     case elfcpp::R_AARCH64_LDST128_ABS_LO12_NC: // 299
6522ed0d50c3Schristos       {
6523ed0d50c3Schristos 	if (gsym->needs_plt_entry())
6524ed0d50c3Schristos 	  target->make_plt_entry(symtab, layout, gsym);
6525ed0d50c3Schristos 	// Make a dynamic relocation if necessary.
6526ed0d50c3Schristos 	if (gsym->needs_dynamic_reloc(arp->reference_flags()))
6527ed0d50c3Schristos 	  {
6528ed0d50c3Schristos 	    if (parameters->options().output_is_executable()
6529ed0d50c3Schristos 		&& gsym->may_need_copy_reloc())
6530ed0d50c3Schristos 	      {
6531ed0d50c3Schristos 		target->copy_reloc(symtab, layout, object,
6532ed0d50c3Schristos 				   data_shndx, output_section, gsym, rela);
6533ed0d50c3Schristos 	      }
6534ed0d50c3Schristos 	  }
6535ed0d50c3Schristos 	break;
6536ed0d50c3Schristos       }
6537ed0d50c3Schristos 
6538ed0d50c3Schristos     case elfcpp::R_AARCH64_ADR_GOT_PAGE:
6539ed0d50c3Schristos     case elfcpp::R_AARCH64_LD64_GOT_LO12_NC:
6540ed0d50c3Schristos     case elfcpp::R_AARCH64_LD64_GOTPAGE_LO15:
6541ed0d50c3Schristos       {
6542ed0d50c3Schristos 	// The above relocations are used to access GOT entries.
6543ed0d50c3Schristos 	// Note a GOT entry is an *address* to a symbol.
6544ed0d50c3Schristos 	// The symbol requires a GOT entry
6545ed0d50c3Schristos 	Output_data_got_aarch64<size, big_endian>* got =
6546ed0d50c3Schristos 	  target->got_section(symtab, layout);
6547ed0d50c3Schristos 	if (gsym->final_value_is_known())
6548ed0d50c3Schristos 	  {
6549ed0d50c3Schristos 	    // For a STT_GNU_IFUNC symbol we want the PLT address.
6550ed0d50c3Schristos 	    if (gsym->type() == elfcpp::STT_GNU_IFUNC)
6551ed0d50c3Schristos 	      got->add_global_plt(gsym, GOT_TYPE_STANDARD);
6552ed0d50c3Schristos 	    else
6553ed0d50c3Schristos 	      got->add_global(gsym, GOT_TYPE_STANDARD);
6554ed0d50c3Schristos 	  }
6555ed0d50c3Schristos 	else
6556ed0d50c3Schristos 	  {
6557ed0d50c3Schristos 	    // If this symbol is not fully resolved, we need to add a dynamic
6558ed0d50c3Schristos 	    // relocation for it.
6559ed0d50c3Schristos 	    Reloc_section* rela_dyn = target->rela_dyn_section(layout);
6560ed0d50c3Schristos 
6561ed0d50c3Schristos 	    // Use a GLOB_DAT rather than a RELATIVE reloc if:
6562ed0d50c3Schristos 	    //
6563ed0d50c3Schristos 	    // 1) The symbol may be defined in some other module.
6564ed0d50c3Schristos 	    // 2) We are building a shared library and this is a protected
6565ed0d50c3Schristos 	    // symbol; using GLOB_DAT means that the dynamic linker can use
6566ed0d50c3Schristos 	    // the address of the PLT in the main executable when appropriate
6567ed0d50c3Schristos 	    // so that function address comparisons work.
6568ed0d50c3Schristos 	    // 3) This is a STT_GNU_IFUNC symbol in position dependent code,
6569ed0d50c3Schristos 	    // again so that function address comparisons work.
6570ed0d50c3Schristos 	    if (gsym->is_from_dynobj()
6571ed0d50c3Schristos 		|| gsym->is_undefined()
6572ed0d50c3Schristos 		|| gsym->is_preemptible()
6573ed0d50c3Schristos 		|| (gsym->visibility() == elfcpp::STV_PROTECTED
6574ed0d50c3Schristos 		    && parameters->options().shared())
6575ed0d50c3Schristos 		|| (gsym->type() == elfcpp::STT_GNU_IFUNC
6576ed0d50c3Schristos 		    && parameters->options().output_is_position_independent()))
6577ed0d50c3Schristos 	      got->add_global_with_rel(gsym, GOT_TYPE_STANDARD,
6578ed0d50c3Schristos 				       rela_dyn, elfcpp::R_AARCH64_GLOB_DAT);
6579ed0d50c3Schristos 	    else
6580ed0d50c3Schristos 	      {
6581ed0d50c3Schristos 		// For a STT_GNU_IFUNC symbol we want to write the PLT
6582ed0d50c3Schristos 		// offset into the GOT, so that function pointer
6583ed0d50c3Schristos 		// comparisons work correctly.
6584ed0d50c3Schristos 		bool is_new;
6585ed0d50c3Schristos 		if (gsym->type() != elfcpp::STT_GNU_IFUNC)
6586ed0d50c3Schristos 		  is_new = got->add_global(gsym, GOT_TYPE_STANDARD);
6587ed0d50c3Schristos 		else
6588ed0d50c3Schristos 		  {
6589ed0d50c3Schristos 		    is_new = got->add_global_plt(gsym, GOT_TYPE_STANDARD);
6590ed0d50c3Schristos 		    // Tell the dynamic linker to use the PLT address
6591ed0d50c3Schristos 		    // when resolving relocations.
6592ed0d50c3Schristos 		    if (gsym->is_from_dynobj()
6593ed0d50c3Schristos 			&& !parameters->options().shared())
6594ed0d50c3Schristos 		      gsym->set_needs_dynsym_value();
6595ed0d50c3Schristos 		  }
6596ed0d50c3Schristos 		if (is_new)
6597ed0d50c3Schristos 		  {
6598ed0d50c3Schristos 		    rela_dyn->add_global_relative(
6599ed0d50c3Schristos 			gsym, elfcpp::R_AARCH64_RELATIVE,
6600ed0d50c3Schristos 			got,
6601ed0d50c3Schristos 			gsym->got_offset(GOT_TYPE_STANDARD),
6602ed0d50c3Schristos 			0,
6603ed0d50c3Schristos 			false);
6604ed0d50c3Schristos 		  }
6605ed0d50c3Schristos 	      }
6606ed0d50c3Schristos 	  }
6607ed0d50c3Schristos 	break;
6608ed0d50c3Schristos       }
6609ed0d50c3Schristos 
6610ed0d50c3Schristos     case elfcpp::R_AARCH64_TSTBR14:
6611ed0d50c3Schristos     case elfcpp::R_AARCH64_CONDBR19:
6612ed0d50c3Schristos     case elfcpp::R_AARCH64_JUMP26:
6613ed0d50c3Schristos     case elfcpp::R_AARCH64_CALL26:
6614ed0d50c3Schristos       {
6615ed0d50c3Schristos 	if (gsym->final_value_is_known())
6616ed0d50c3Schristos 	  break;
6617ed0d50c3Schristos 
6618ed0d50c3Schristos 	if (gsym->is_defined() &&
6619ed0d50c3Schristos 	    !gsym->is_from_dynobj() &&
6620ed0d50c3Schristos 	    !gsym->is_preemptible())
6621ed0d50c3Schristos 	  break;
6622ed0d50c3Schristos 
6623ed0d50c3Schristos 	// Make plt entry for function call.
6624ed0d50c3Schristos 	target->make_plt_entry(symtab, layout, gsym);
6625ed0d50c3Schristos 	break;
6626ed0d50c3Schristos       }
6627ed0d50c3Schristos 
6628ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSGD_ADR_PAGE21:
6629ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSGD_ADD_LO12_NC:  // General dynamic
6630ed0d50c3Schristos       {
6631ed0d50c3Schristos 	tls::Tls_optimization tlsopt = Target_aarch64<size, big_endian>::
6632ed0d50c3Schristos 	    optimize_tls_reloc(gsym->final_value_is_known(), r_type);
6633ed0d50c3Schristos 	if (tlsopt == tls::TLSOPT_TO_LE)
6634ed0d50c3Schristos 	  {
6635ed0d50c3Schristos 	    layout->set_has_static_tls();
6636ed0d50c3Schristos 	    break;
6637ed0d50c3Schristos 	  }
6638ed0d50c3Schristos 	gold_assert(tlsopt == tls::TLSOPT_NONE);
6639ed0d50c3Schristos 
6640ed0d50c3Schristos 	// General dynamic.
6641ed0d50c3Schristos 	Output_data_got_aarch64<size, big_endian>* got =
6642ed0d50c3Schristos 	    target->got_section(symtab, layout);
6643ed0d50c3Schristos 	// Create 2 consecutive entries for module index and offset.
6644ed0d50c3Schristos 	got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_PAIR,
6645ed0d50c3Schristos 				      target->rela_dyn_section(layout),
6646ed0d50c3Schristos 				      elfcpp::R_AARCH64_TLS_DTPMOD64,
6647ed0d50c3Schristos 				      elfcpp::R_AARCH64_TLS_DTPREL64);
6648ed0d50c3Schristos       }
6649ed0d50c3Schristos       break;
6650ed0d50c3Schristos 
6651ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADR_PAGE21:
6652ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADD_LO12_NC:  // Local dynamic
6653ed0d50c3Schristos       {
6654ed0d50c3Schristos 	tls::Tls_optimization tlsopt = Target_aarch64<size, big_endian>::
6655ed0d50c3Schristos 	    optimize_tls_reloc(!parameters->options().shared(), r_type);
6656ed0d50c3Schristos 	if (tlsopt == tls::TLSOPT_NONE)
6657ed0d50c3Schristos 	  {
6658ed0d50c3Schristos 	    // Create a GOT entry for the module index.
6659ed0d50c3Schristos 	    target->got_mod_index_entry(symtab, layout, object);
6660ed0d50c3Schristos 	  }
6661ed0d50c3Schristos 	else if (tlsopt != tls::TLSOPT_TO_LE)
6662ed0d50c3Schristos 	  unsupported_reloc_local(object, r_type);
6663ed0d50c3Schristos       }
6664ed0d50c3Schristos       break;
6665ed0d50c3Schristos 
6666ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G1:
6667ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
6668ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_HI12:
6669ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:  // Other local dynamic
6670ed0d50c3Schristos       break;
6671ed0d50c3Schristos 
6672ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
6673ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:  // Initial executable
6674ed0d50c3Schristos       {
6675ed0d50c3Schristos 	tls::Tls_optimization tlsopt = Target_aarch64<size, big_endian>::
6676ed0d50c3Schristos 	  optimize_tls_reloc(gsym->final_value_is_known(), r_type);
6677ed0d50c3Schristos 	if (tlsopt == tls::TLSOPT_TO_LE)
6678ed0d50c3Schristos 	  break;
6679ed0d50c3Schristos 
6680ed0d50c3Schristos 	layout->set_has_static_tls();
6681ed0d50c3Schristos 	// Create a GOT entry for the tp-relative offset.
6682ed0d50c3Schristos 	Output_data_got_aarch64<size, big_endian>* got
6683ed0d50c3Schristos 	  = target->got_section(symtab, layout);
6684ed0d50c3Schristos 	if (!parameters->doing_static_link())
6685ed0d50c3Schristos 	  {
6686ed0d50c3Schristos 	    got->add_global_with_rel(
6687ed0d50c3Schristos 	      gsym, GOT_TYPE_TLS_OFFSET,
6688ed0d50c3Schristos 	      target->rela_dyn_section(layout),
6689ed0d50c3Schristos 	      elfcpp::R_AARCH64_TLS_TPREL64);
6690ed0d50c3Schristos 	  }
6691ed0d50c3Schristos 	if (!gsym->has_got_offset(GOT_TYPE_TLS_OFFSET))
6692ed0d50c3Schristos 	  {
6693ed0d50c3Schristos 	    got->add_global(gsym, GOT_TYPE_TLS_OFFSET);
6694ed0d50c3Schristos 	    unsigned int got_offset =
6695ed0d50c3Schristos 	      gsym->got_offset(GOT_TYPE_TLS_OFFSET);
6696ed0d50c3Schristos 	    const elfcpp::Elf_Xword addend = rela.get_r_addend();
6697ed0d50c3Schristos 	    gold_assert(addend == 0);
6698ed0d50c3Schristos 	    got->add_static_reloc(got_offset,
6699ed0d50c3Schristos 				  elfcpp::R_AARCH64_TLS_TPREL64, gsym);
6700ed0d50c3Schristos 	  }
6701ed0d50c3Schristos       }
6702ed0d50c3Schristos       break;
6703ed0d50c3Schristos 
6704ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G2:
6705ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G1:
6706ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
6707ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G0:
6708ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
6709ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_HI12:
6710ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12:
671106324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
671206324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12:
671306324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
671406324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12:
671506324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
671606324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12:
671706324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
671806324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12:
671906324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:  // Local executable
6720ed0d50c3Schristos       layout->set_has_static_tls();
6721ed0d50c3Schristos       if (parameters->options().shared())
6722ed0d50c3Schristos 	gold_error(_("%s: unsupported TLSLE reloc type %u in shared objects."),
6723ed0d50c3Schristos 		   object->name().c_str(), r_type);
6724ed0d50c3Schristos       break;
6725ed0d50c3Schristos 
6726ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_ADR_PAGE21:
6727ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_LD64_LO12:
6728ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_ADD_LO12:  // TLS descriptor
6729ed0d50c3Schristos       {
6730ed0d50c3Schristos 	target->define_tls_base_symbol(symtab, layout);
6731ed0d50c3Schristos 	tls::Tls_optimization tlsopt = Target_aarch64<size, big_endian>::
6732ed0d50c3Schristos 	    optimize_tls_reloc(gsym->final_value_is_known(), r_type);
6733ed0d50c3Schristos 	if (tlsopt == tls::TLSOPT_NONE)
6734ed0d50c3Schristos 	  {
6735ed0d50c3Schristos 	    // Create reserved PLT and GOT entries for the resolver.
6736ed0d50c3Schristos 	    target->reserve_tlsdesc_entries(symtab, layout);
6737ed0d50c3Schristos 
6738ed0d50c3Schristos 	    // Create a double GOT entry with an R_AARCH64_TLSDESC
6739ed0d50c3Schristos 	    // relocation. The R_AARCH64_TLSDESC is resolved lazily, so the GOT
6740ed0d50c3Schristos 	    // entry needs to be in an area in .got.plt, not .got. Call
6741ed0d50c3Schristos 	    // got_section to make sure the section has been created.
6742ed0d50c3Schristos 	    target->got_section(symtab, layout);
6743ed0d50c3Schristos 	    Output_data_got<size, big_endian>* got =
6744ed0d50c3Schristos 		target->got_tlsdesc_section();
6745ed0d50c3Schristos 	    Reloc_section* rt = target->rela_tlsdesc_section(layout);
6746ed0d50c3Schristos 	    got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, rt,
6747ed0d50c3Schristos 					  elfcpp::R_AARCH64_TLSDESC, 0);
6748ed0d50c3Schristos 	  }
6749ed0d50c3Schristos 	else if (tlsopt == tls::TLSOPT_TO_IE)
6750ed0d50c3Schristos 	  {
6751ed0d50c3Schristos 	    // Create a GOT entry for the tp-relative offset.
6752ed0d50c3Schristos 	    Output_data_got<size, big_endian>* got
6753ed0d50c3Schristos 		= target->got_section(symtab, layout);
6754ed0d50c3Schristos 	    got->add_global_with_rel(gsym, GOT_TYPE_TLS_OFFSET,
6755ed0d50c3Schristos 				     target->rela_dyn_section(layout),
6756ed0d50c3Schristos 				     elfcpp::R_AARCH64_TLS_TPREL64);
6757ed0d50c3Schristos 	  }
6758ed0d50c3Schristos 	else if (tlsopt != tls::TLSOPT_TO_LE)
6759ed0d50c3Schristos 	  unsupported_reloc_global(object, r_type, gsym);
6760ed0d50c3Schristos       }
6761ed0d50c3Schristos       break;
6762ed0d50c3Schristos 
6763ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_CALL:
6764ed0d50c3Schristos       break;
6765ed0d50c3Schristos 
6766ed0d50c3Schristos     default:
6767ed0d50c3Schristos       gold_error(_("%s: unsupported reloc type in global scan"),
6768ed0d50c3Schristos 		 aarch64_reloc_property_table->
6769ed0d50c3Schristos 		 reloc_name_in_error_message(r_type).c_str());
6770ed0d50c3Schristos     }
6771ed0d50c3Schristos   return;
6772ed0d50c3Schristos }  // End of Scan::global
6773ed0d50c3Schristos 
6774ed0d50c3Schristos 
6775ed0d50c3Schristos // Create the PLT section.
6776ed0d50c3Schristos template<int size, bool big_endian>
6777ed0d50c3Schristos void
make_plt_section(Symbol_table * symtab,Layout * layout)6778ed0d50c3Schristos Target_aarch64<size, big_endian>::make_plt_section(
6779ed0d50c3Schristos   Symbol_table* symtab, Layout* layout)
6780ed0d50c3Schristos {
6781ed0d50c3Schristos   if (this->plt_ == NULL)
6782ed0d50c3Schristos     {
6783ed0d50c3Schristos       // Create the GOT section first.
6784ed0d50c3Schristos       this->got_section(symtab, layout);
6785ed0d50c3Schristos 
6786ed0d50c3Schristos       this->plt_ = this->make_data_plt(layout, this->got_, this->got_plt_,
6787ed0d50c3Schristos 				       this->got_irelative_);
6788ed0d50c3Schristos 
6789ed0d50c3Schristos       layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
6790ed0d50c3Schristos 				      (elfcpp::SHF_ALLOC
6791ed0d50c3Schristos 				       | elfcpp::SHF_EXECINSTR),
6792ed0d50c3Schristos 				      this->plt_, ORDER_PLT, false);
6793ed0d50c3Schristos 
6794ed0d50c3Schristos       // Make the sh_info field of .rela.plt point to .plt.
6795ed0d50c3Schristos       Output_section* rela_plt_os = this->plt_->rela_plt()->output_section();
6796ed0d50c3Schristos       rela_plt_os->set_info_section(this->plt_->output_section());
6797ed0d50c3Schristos     }
6798ed0d50c3Schristos }
6799ed0d50c3Schristos 
6800ed0d50c3Schristos // Return the section for TLSDESC relocations.
6801ed0d50c3Schristos 
6802ed0d50c3Schristos template<int size, bool big_endian>
6803ed0d50c3Schristos typename Target_aarch64<size, big_endian>::Reloc_section*
rela_tlsdesc_section(Layout * layout) const6804ed0d50c3Schristos Target_aarch64<size, big_endian>::rela_tlsdesc_section(Layout* layout) const
6805ed0d50c3Schristos {
6806ed0d50c3Schristos   return this->plt_section()->rela_tlsdesc(layout);
6807ed0d50c3Schristos }
6808ed0d50c3Schristos 
6809ed0d50c3Schristos // Create a PLT entry for a global symbol.
6810ed0d50c3Schristos 
6811ed0d50c3Schristos template<int size, bool big_endian>
6812ed0d50c3Schristos void
make_plt_entry(Symbol_table * symtab,Layout * layout,Symbol * gsym)6813ed0d50c3Schristos Target_aarch64<size, big_endian>::make_plt_entry(
6814ed0d50c3Schristos     Symbol_table* symtab,
6815ed0d50c3Schristos     Layout* layout,
6816ed0d50c3Schristos     Symbol* gsym)
6817ed0d50c3Schristos {
6818ed0d50c3Schristos   if (gsym->has_plt_offset())
6819ed0d50c3Schristos     return;
6820ed0d50c3Schristos 
6821ed0d50c3Schristos   if (this->plt_ == NULL)
6822ed0d50c3Schristos     this->make_plt_section(symtab, layout);
6823ed0d50c3Schristos 
6824ed0d50c3Schristos   this->plt_->add_entry(symtab, layout, gsym);
6825ed0d50c3Schristos }
6826ed0d50c3Schristos 
6827ed0d50c3Schristos // Make a PLT entry for a local STT_GNU_IFUNC symbol.
6828ed0d50c3Schristos 
6829ed0d50c3Schristos template<int size, bool big_endian>
6830ed0d50c3Schristos void
make_local_ifunc_plt_entry(Symbol_table * symtab,Layout * layout,Sized_relobj_file<size,big_endian> * relobj,unsigned int local_sym_index)6831ed0d50c3Schristos Target_aarch64<size, big_endian>::make_local_ifunc_plt_entry(
6832ed0d50c3Schristos     Symbol_table* symtab, Layout* layout,
6833ed0d50c3Schristos     Sized_relobj_file<size, big_endian>* relobj,
6834ed0d50c3Schristos     unsigned int local_sym_index)
6835ed0d50c3Schristos {
6836ed0d50c3Schristos   if (relobj->local_has_plt_offset(local_sym_index))
6837ed0d50c3Schristos     return;
6838ed0d50c3Schristos   if (this->plt_ == NULL)
6839ed0d50c3Schristos     this->make_plt_section(symtab, layout);
6840ed0d50c3Schristos   unsigned int plt_offset = this->plt_->add_local_ifunc_entry(symtab, layout,
6841ed0d50c3Schristos 							      relobj,
6842ed0d50c3Schristos 							      local_sym_index);
6843ed0d50c3Schristos   relobj->set_local_plt_offset(local_sym_index, plt_offset);
6844ed0d50c3Schristos }
6845ed0d50c3Schristos 
6846ed0d50c3Schristos template<int size, bool big_endian>
6847ed0d50c3Schristos void
gc_process_relocs(Symbol_table * symtab,Layout * layout,Sized_relobj_file<size,big_endian> * object,unsigned int data_shndx,unsigned int sh_type,const unsigned char * prelocs,size_t reloc_count,Output_section * output_section,bool needs_special_offset_handling,size_t local_symbol_count,const unsigned char * plocal_symbols)6848ed0d50c3Schristos Target_aarch64<size, big_endian>::gc_process_relocs(
6849ed0d50c3Schristos     Symbol_table* symtab,
6850ed0d50c3Schristos     Layout* layout,
6851ed0d50c3Schristos     Sized_relobj_file<size, big_endian>* object,
6852ed0d50c3Schristos     unsigned int data_shndx,
6853ed0d50c3Schristos     unsigned int sh_type,
6854ed0d50c3Schristos     const unsigned char* prelocs,
6855ed0d50c3Schristos     size_t reloc_count,
6856ed0d50c3Schristos     Output_section* output_section,
6857ed0d50c3Schristos     bool needs_special_offset_handling,
6858ed0d50c3Schristos     size_t local_symbol_count,
6859ed0d50c3Schristos     const unsigned char* plocal_symbols)
6860ed0d50c3Schristos {
6861ed0d50c3Schristos   typedef Target_aarch64<size, big_endian> Aarch64;
6862ed0d50c3Schristos   typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
6863ed0d50c3Schristos       Classify_reloc;
6864ed0d50c3Schristos 
6865ed0d50c3Schristos   if (sh_type == elfcpp::SHT_REL)
6866ed0d50c3Schristos     {
6867ed0d50c3Schristos       return;
6868ed0d50c3Schristos     }
6869ed0d50c3Schristos 
6870ed0d50c3Schristos   gold::gc_process_relocs<size, big_endian, Aarch64, Scan, Classify_reloc>(
6871ed0d50c3Schristos     symtab,
6872ed0d50c3Schristos     layout,
6873ed0d50c3Schristos     this,
6874ed0d50c3Schristos     object,
6875ed0d50c3Schristos     data_shndx,
6876ed0d50c3Schristos     prelocs,
6877ed0d50c3Schristos     reloc_count,
6878ed0d50c3Schristos     output_section,
6879ed0d50c3Schristos     needs_special_offset_handling,
6880ed0d50c3Schristos     local_symbol_count,
6881ed0d50c3Schristos     plocal_symbols);
6882ed0d50c3Schristos }
6883ed0d50c3Schristos 
6884ed0d50c3Schristos // Scan relocations for a section.
6885ed0d50c3Schristos 
6886ed0d50c3Schristos template<int size, bool big_endian>
6887ed0d50c3Schristos void
scan_relocs(Symbol_table * symtab,Layout * layout,Sized_relobj_file<size,big_endian> * object,unsigned int data_shndx,unsigned int sh_type,const unsigned char * prelocs,size_t reloc_count,Output_section * output_section,bool needs_special_offset_handling,size_t local_symbol_count,const unsigned char * plocal_symbols)6888ed0d50c3Schristos Target_aarch64<size, big_endian>::scan_relocs(
6889ed0d50c3Schristos     Symbol_table* symtab,
6890ed0d50c3Schristos     Layout* layout,
6891ed0d50c3Schristos     Sized_relobj_file<size, big_endian>* object,
6892ed0d50c3Schristos     unsigned int data_shndx,
6893ed0d50c3Schristos     unsigned int sh_type,
6894ed0d50c3Schristos     const unsigned char* prelocs,
6895ed0d50c3Schristos     size_t reloc_count,
6896ed0d50c3Schristos     Output_section* output_section,
6897ed0d50c3Schristos     bool needs_special_offset_handling,
6898ed0d50c3Schristos     size_t local_symbol_count,
6899ed0d50c3Schristos     const unsigned char* plocal_symbols)
6900ed0d50c3Schristos {
6901ed0d50c3Schristos   typedef Target_aarch64<size, big_endian> Aarch64;
6902ed0d50c3Schristos   typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
6903ed0d50c3Schristos       Classify_reloc;
6904ed0d50c3Schristos 
6905ed0d50c3Schristos   if (sh_type == elfcpp::SHT_REL)
6906ed0d50c3Schristos     {
6907ed0d50c3Schristos       gold_error(_("%s: unsupported REL reloc section"),
6908ed0d50c3Schristos 		 object->name().c_str());
6909ed0d50c3Schristos       return;
6910ed0d50c3Schristos     }
6911ed0d50c3Schristos 
6912ed0d50c3Schristos   gold::scan_relocs<size, big_endian, Aarch64, Scan, Classify_reloc>(
6913ed0d50c3Schristos     symtab,
6914ed0d50c3Schristos     layout,
6915ed0d50c3Schristos     this,
6916ed0d50c3Schristos     object,
6917ed0d50c3Schristos     data_shndx,
6918ed0d50c3Schristos     prelocs,
6919ed0d50c3Schristos     reloc_count,
6920ed0d50c3Schristos     output_section,
6921ed0d50c3Schristos     needs_special_offset_handling,
6922ed0d50c3Schristos     local_symbol_count,
6923ed0d50c3Schristos     plocal_symbols);
6924ed0d50c3Schristos }
6925ed0d50c3Schristos 
6926ed0d50c3Schristos // Return the value to use for a dynamic which requires special
6927ed0d50c3Schristos // treatment.  This is how we support equality comparisons of function
6928ed0d50c3Schristos // pointers across shared library boundaries, as described in the
6929ed0d50c3Schristos // processor specific ABI supplement.
6930ed0d50c3Schristos 
6931ed0d50c3Schristos template<int size, bool big_endian>
6932ed0d50c3Schristos uint64_t
do_dynsym_value(const Symbol * gsym) const6933ed0d50c3Schristos Target_aarch64<size, big_endian>::do_dynsym_value(const Symbol* gsym) const
6934ed0d50c3Schristos {
6935ed0d50c3Schristos   gold_assert(gsym->is_from_dynobj() && gsym->has_plt_offset());
6936ed0d50c3Schristos   return this->plt_address_for_global(gsym);
6937ed0d50c3Schristos }
6938ed0d50c3Schristos 
6939ed0d50c3Schristos 
6940ed0d50c3Schristos // Finalize the sections.
6941ed0d50c3Schristos 
6942ed0d50c3Schristos template<int size, bool big_endian>
6943ed0d50c3Schristos void
do_finalize_sections(Layout * layout,const Input_objects *,Symbol_table * symtab)6944ed0d50c3Schristos Target_aarch64<size, big_endian>::do_finalize_sections(
6945ed0d50c3Schristos     Layout* layout,
6946ed0d50c3Schristos     const Input_objects*,
6947ed0d50c3Schristos     Symbol_table* symtab)
6948ed0d50c3Schristos {
6949ed0d50c3Schristos   const Reloc_section* rel_plt = (this->plt_ == NULL
6950ed0d50c3Schristos 				  ? NULL
6951ed0d50c3Schristos 				  : this->plt_->rela_plt());
6952ed0d50c3Schristos   layout->add_target_dynamic_tags(false, this->got_plt_, rel_plt,
6953ed0d50c3Schristos 				  this->rela_dyn_, true, false);
6954ed0d50c3Schristos 
6955ed0d50c3Schristos   // Emit any relocs we saved in an attempt to avoid generating COPY
6956ed0d50c3Schristos   // relocs.
6957ed0d50c3Schristos   if (this->copy_relocs_.any_saved_relocs())
6958ed0d50c3Schristos     this->copy_relocs_.emit(this->rela_dyn_section(layout));
6959ed0d50c3Schristos 
6960ed0d50c3Schristos   // Fill in some more dynamic tags.
6961ed0d50c3Schristos   Output_data_dynamic* const odyn = layout->dynamic_data();
6962ed0d50c3Schristos   if (odyn != NULL)
6963ed0d50c3Schristos     {
6964ed0d50c3Schristos       if (this->plt_ != NULL
6965ed0d50c3Schristos 	  && this->plt_->output_section() != NULL
6966ed0d50c3Schristos 	  && this->plt_ ->has_tlsdesc_entry())
6967ed0d50c3Schristos 	{
6968ed0d50c3Schristos 	  unsigned int plt_offset = this->plt_->get_tlsdesc_plt_offset();
6969ed0d50c3Schristos 	  unsigned int got_offset = this->plt_->get_tlsdesc_got_offset();
6970ed0d50c3Schristos 	  this->got_->finalize_data_size();
6971ed0d50c3Schristos 	  odyn->add_section_plus_offset(elfcpp::DT_TLSDESC_PLT,
6972ed0d50c3Schristos 					this->plt_, plt_offset);
6973ed0d50c3Schristos 	  odyn->add_section_plus_offset(elfcpp::DT_TLSDESC_GOT,
6974ed0d50c3Schristos 					this->got_, got_offset);
6975ed0d50c3Schristos 	}
6976ed0d50c3Schristos     }
6977ed0d50c3Schristos 
6978ed0d50c3Schristos   // Set the size of the _GLOBAL_OFFSET_TABLE_ symbol to the size of
697906324dcfSchristos   // the .got section.
6980ed0d50c3Schristos   Symbol* sym = this->global_offset_table_;
6981ed0d50c3Schristos   if (sym != NULL)
6982ed0d50c3Schristos     {
698306324dcfSchristos       uint64_t data_size = this->got_->current_data_size();
6984ed0d50c3Schristos       symtab->get_sized_symbol<size>(sym)->set_symsize(data_size);
6985ed0d50c3Schristos 
6986ed0d50c3Schristos       // If the .got section is more than 0x8000 bytes, we add
6987ed0d50c3Schristos       // 0x8000 to the value of _GLOBAL_OFFSET_TABLE_, so that 16
6988ed0d50c3Schristos       // bit relocations have a greater chance of working.
6989ed0d50c3Schristos       if (data_size >= 0x8000)
6990ed0d50c3Schristos 	symtab->get_sized_symbol<size>(sym)->set_value(
6991ed0d50c3Schristos 	  symtab->get_sized_symbol<size>(sym)->value() + 0x8000);
6992ed0d50c3Schristos     }
6993ed0d50c3Schristos 
6994ed0d50c3Schristos   if (parameters->doing_static_link()
6995ed0d50c3Schristos       && (this->plt_ == NULL || !this->plt_->has_irelative_section()))
6996ed0d50c3Schristos     {
6997ed0d50c3Schristos       // If linking statically, make sure that the __rela_iplt symbols
6998ed0d50c3Schristos       // were defined if necessary, even if we didn't create a PLT.
6999ed0d50c3Schristos       static const Define_symbol_in_segment syms[] =
7000ed0d50c3Schristos 	{
7001ed0d50c3Schristos 	  {
7002ed0d50c3Schristos 	    "__rela_iplt_start",	// name
7003ed0d50c3Schristos 	    elfcpp::PT_LOAD,		// segment_type
7004ed0d50c3Schristos 	    elfcpp::PF_W,		// segment_flags_set
7005ed0d50c3Schristos 	    elfcpp::PF(0),		// segment_flags_clear
7006ed0d50c3Schristos 	    0,				// value
7007ed0d50c3Schristos 	    0,				// size
7008ed0d50c3Schristos 	    elfcpp::STT_NOTYPE,		// type
7009ed0d50c3Schristos 	    elfcpp::STB_GLOBAL,		// binding
7010ed0d50c3Schristos 	    elfcpp::STV_HIDDEN,		// visibility
7011ed0d50c3Schristos 	    0,				// nonvis
7012ed0d50c3Schristos 	    Symbol::SEGMENT_START,	// offset_from_base
7013ed0d50c3Schristos 	    true			// only_if_ref
7014ed0d50c3Schristos 	  },
7015ed0d50c3Schristos 	  {
7016ed0d50c3Schristos 	    "__rela_iplt_end",		// name
7017ed0d50c3Schristos 	    elfcpp::PT_LOAD,		// segment_type
7018ed0d50c3Schristos 	    elfcpp::PF_W,		// segment_flags_set
7019ed0d50c3Schristos 	    elfcpp::PF(0),		// segment_flags_clear
7020ed0d50c3Schristos 	    0,				// value
7021ed0d50c3Schristos 	    0,				// size
7022ed0d50c3Schristos 	    elfcpp::STT_NOTYPE,		// type
7023ed0d50c3Schristos 	    elfcpp::STB_GLOBAL,		// binding
7024ed0d50c3Schristos 	    elfcpp::STV_HIDDEN,		// visibility
7025ed0d50c3Schristos 	    0,				// nonvis
7026ed0d50c3Schristos 	    Symbol::SEGMENT_START,	// offset_from_base
7027ed0d50c3Schristos 	    true			// only_if_ref
7028ed0d50c3Schristos 	  }
7029ed0d50c3Schristos 	};
7030ed0d50c3Schristos 
7031ed0d50c3Schristos       symtab->define_symbols(layout, 2, syms,
7032ed0d50c3Schristos 			     layout->script_options()->saw_sections_clause());
7033ed0d50c3Schristos     }
7034ed0d50c3Schristos 
7035ed0d50c3Schristos   return;
7036ed0d50c3Schristos }
7037ed0d50c3Schristos 
7038ed0d50c3Schristos // Perform a relocation.
7039ed0d50c3Schristos 
7040ed0d50c3Schristos template<int size, bool big_endian>
7041ed0d50c3Schristos inline bool
relocate(const Relocate_info<size,big_endian> * relinfo,unsigned int,Target_aarch64<size,big_endian> * target,Output_section *,size_t relnum,const unsigned char * preloc,const Sized_symbol<size> * gsym,const Symbol_value<size> * psymval,unsigned char * view,typename elfcpp::Elf_types<size>::Elf_Addr address,section_size_type)7042ed0d50c3Schristos Target_aarch64<size, big_endian>::Relocate::relocate(
7043ed0d50c3Schristos     const Relocate_info<size, big_endian>* relinfo,
7044ed0d50c3Schristos     unsigned int,
7045ed0d50c3Schristos     Target_aarch64<size, big_endian>* target,
7046ed0d50c3Schristos     Output_section* ,
7047ed0d50c3Schristos     size_t relnum,
7048ed0d50c3Schristos     const unsigned char* preloc,
7049ed0d50c3Schristos     const Sized_symbol<size>* gsym,
7050ed0d50c3Schristos     const Symbol_value<size>* psymval,
7051ed0d50c3Schristos     unsigned char* view,
7052ed0d50c3Schristos     typename elfcpp::Elf_types<size>::Elf_Addr address,
7053ed0d50c3Schristos     section_size_type /* view_size */)
7054ed0d50c3Schristos {
7055ed0d50c3Schristos   if (view == NULL)
7056ed0d50c3Schristos     return true;
7057ed0d50c3Schristos 
7058ed0d50c3Schristos   typedef AArch64_relocate_functions<size, big_endian> Reloc;
7059ed0d50c3Schristos 
7060ed0d50c3Schristos   const elfcpp::Rela<size, big_endian> rela(preloc);
7061ed0d50c3Schristos   unsigned int r_type = elfcpp::elf_r_type<size>(rela.get_r_info());
7062ed0d50c3Schristos   const AArch64_reloc_property* reloc_property =
7063ed0d50c3Schristos       aarch64_reloc_property_table->get_reloc_property(r_type);
7064ed0d50c3Schristos 
7065ed0d50c3Schristos   if (reloc_property == NULL)
7066ed0d50c3Schristos     {
7067ed0d50c3Schristos       std::string reloc_name =
7068ed0d50c3Schristos 	  aarch64_reloc_property_table->reloc_name_in_error_message(r_type);
7069ed0d50c3Schristos       gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
7070ed0d50c3Schristos 			     _("cannot relocate %s in object file"),
7071ed0d50c3Schristos 			     reloc_name.c_str());
7072ed0d50c3Schristos       return true;
7073ed0d50c3Schristos     }
7074ed0d50c3Schristos 
7075ed0d50c3Schristos   const Sized_relobj_file<size, big_endian>* object = relinfo->object;
7076ed0d50c3Schristos 
7077ed0d50c3Schristos   // Pick the value to use for symbols defined in the PLT.
7078ed0d50c3Schristos   Symbol_value<size> symval;
7079ed0d50c3Schristos   if (gsym != NULL
7080ed0d50c3Schristos       && gsym->use_plt_offset(reloc_property->reference_flags()))
7081ed0d50c3Schristos     {
7082ed0d50c3Schristos       symval.set_output_value(target->plt_address_for_global(gsym));
7083ed0d50c3Schristos       psymval = &symval;
7084ed0d50c3Schristos     }
7085ed0d50c3Schristos   else if (gsym == NULL && psymval->is_ifunc_symbol())
7086ed0d50c3Schristos     {
7087ed0d50c3Schristos       unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
7088ed0d50c3Schristos       if (object->local_has_plt_offset(r_sym))
7089ed0d50c3Schristos 	{
7090ed0d50c3Schristos 	  symval.set_output_value(target->plt_address_for_local(object, r_sym));
7091ed0d50c3Schristos 	  psymval = &symval;
7092ed0d50c3Schristos 	}
7093ed0d50c3Schristos     }
7094ed0d50c3Schristos 
7095ed0d50c3Schristos   const elfcpp::Elf_Xword addend = rela.get_r_addend();
7096ed0d50c3Schristos 
7097ed0d50c3Schristos   // Get the GOT offset if needed.
7098ed0d50c3Schristos   // For aarch64, the GOT pointer points to the start of the GOT section.
7099ed0d50c3Schristos   bool have_got_offset = false;
7100ed0d50c3Schristos   int got_offset = 0;
7101ed0d50c3Schristos   int got_base = (target->got_ != NULL
7102ed0d50c3Schristos 		  ? (target->got_->current_data_size() >= 0x8000
7103ed0d50c3Schristos 		     ? 0x8000 : 0)
7104ed0d50c3Schristos 		  : 0);
7105ed0d50c3Schristos   switch (r_type)
7106ed0d50c3Schristos     {
7107ed0d50c3Schristos     case elfcpp::R_AARCH64_MOVW_GOTOFF_G0:
7108ed0d50c3Schristos     case elfcpp::R_AARCH64_MOVW_GOTOFF_G0_NC:
7109ed0d50c3Schristos     case elfcpp::R_AARCH64_MOVW_GOTOFF_G1:
7110ed0d50c3Schristos     case elfcpp::R_AARCH64_MOVW_GOTOFF_G1_NC:
7111ed0d50c3Schristos     case elfcpp::R_AARCH64_MOVW_GOTOFF_G2:
7112ed0d50c3Schristos     case elfcpp::R_AARCH64_MOVW_GOTOFF_G2_NC:
7113ed0d50c3Schristos     case elfcpp::R_AARCH64_MOVW_GOTOFF_G3:
7114ed0d50c3Schristos     case elfcpp::R_AARCH64_GOTREL64:
7115ed0d50c3Schristos     case elfcpp::R_AARCH64_GOTREL32:
7116ed0d50c3Schristos     case elfcpp::R_AARCH64_GOT_LD_PREL19:
7117ed0d50c3Schristos     case elfcpp::R_AARCH64_LD64_GOTOFF_LO15:
7118ed0d50c3Schristos     case elfcpp::R_AARCH64_ADR_GOT_PAGE:
7119ed0d50c3Schristos     case elfcpp::R_AARCH64_LD64_GOT_LO12_NC:
7120ed0d50c3Schristos     case elfcpp::R_AARCH64_LD64_GOTPAGE_LO15:
7121ed0d50c3Schristos       if (gsym != NULL)
7122ed0d50c3Schristos 	{
7123ed0d50c3Schristos 	  gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD));
7124ed0d50c3Schristos 	  got_offset = gsym->got_offset(GOT_TYPE_STANDARD) - got_base;
7125ed0d50c3Schristos 	}
7126ed0d50c3Schristos       else
7127ed0d50c3Schristos 	{
7128ed0d50c3Schristos 	  unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
7129ed0d50c3Schristos 	  gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
7130ed0d50c3Schristos 	  got_offset = (object->local_got_offset(r_sym, GOT_TYPE_STANDARD)
7131ed0d50c3Schristos 			- got_base);
7132ed0d50c3Schristos 	}
7133ed0d50c3Schristos       have_got_offset = true;
7134ed0d50c3Schristos       break;
7135ed0d50c3Schristos 
7136ed0d50c3Schristos     default:
7137ed0d50c3Schristos       break;
7138ed0d50c3Schristos     }
7139ed0d50c3Schristos 
7140ed0d50c3Schristos   typename Reloc::Status reloc_status = Reloc::STATUS_OKAY;
7141ed0d50c3Schristos   typename elfcpp::Elf_types<size>::Elf_Addr value;
7142ed0d50c3Schristos   switch (r_type)
7143ed0d50c3Schristos     {
7144ed0d50c3Schristos     case elfcpp::R_AARCH64_NONE:
7145ed0d50c3Schristos       break;
7146ed0d50c3Schristos 
7147ed0d50c3Schristos     case elfcpp::R_AARCH64_ABS64:
7148ed0d50c3Schristos       if (!parameters->options().apply_dynamic_relocs()
7149ed0d50c3Schristos           && parameters->options().output_is_position_independent()
7150ed0d50c3Schristos           && gsym != NULL
7151ed0d50c3Schristos           && gsym->needs_dynamic_reloc(reloc_property->reference_flags())
7152ed0d50c3Schristos           && !gsym->can_use_relative_reloc(false))
7153ed0d50c3Schristos         // We have generated an absolute dynamic relocation, so do not
7154ed0d50c3Schristos         // apply the relocation statically. (Works around bugs in older
7155ed0d50c3Schristos         // Android dynamic linkers.)
7156ed0d50c3Schristos         break;
7157ed0d50c3Schristos       reloc_status = Reloc::template rela_ua<64>(
7158ed0d50c3Schristos 	view, object, psymval, addend, reloc_property);
7159ed0d50c3Schristos       break;
7160ed0d50c3Schristos 
7161ed0d50c3Schristos     case elfcpp::R_AARCH64_ABS32:
7162ed0d50c3Schristos       if (!parameters->options().apply_dynamic_relocs()
7163ed0d50c3Schristos           && parameters->options().output_is_position_independent()
7164ed0d50c3Schristos           && gsym != NULL
7165ed0d50c3Schristos           && gsym->needs_dynamic_reloc(reloc_property->reference_flags()))
7166ed0d50c3Schristos         // We have generated an absolute dynamic relocation, so do not
7167ed0d50c3Schristos         // apply the relocation statically. (Works around bugs in older
7168ed0d50c3Schristos         // Android dynamic linkers.)
7169ed0d50c3Schristos         break;
7170ed0d50c3Schristos       reloc_status = Reloc::template rela_ua<32>(
7171ed0d50c3Schristos 	view, object, psymval, addend, reloc_property);
7172ed0d50c3Schristos       break;
7173ed0d50c3Schristos 
7174ed0d50c3Schristos     case elfcpp::R_AARCH64_ABS16:
7175ed0d50c3Schristos       if (!parameters->options().apply_dynamic_relocs()
7176ed0d50c3Schristos           && parameters->options().output_is_position_independent()
7177ed0d50c3Schristos           && gsym != NULL
7178ed0d50c3Schristos           && gsym->needs_dynamic_reloc(reloc_property->reference_flags()))
7179ed0d50c3Schristos         // We have generated an absolute dynamic relocation, so do not
7180ed0d50c3Schristos         // apply the relocation statically. (Works around bugs in older
7181ed0d50c3Schristos         // Android dynamic linkers.)
7182ed0d50c3Schristos         break;
7183ed0d50c3Schristos       reloc_status = Reloc::template rela_ua<16>(
7184ed0d50c3Schristos 	view, object, psymval, addend, reloc_property);
7185ed0d50c3Schristos       break;
7186ed0d50c3Schristos 
7187ed0d50c3Schristos     case elfcpp::R_AARCH64_PREL64:
7188ed0d50c3Schristos       reloc_status = Reloc::template pcrela_ua<64>(
7189ed0d50c3Schristos 	view, object, psymval, addend, address, reloc_property);
7190ed0d50c3Schristos       break;
7191ed0d50c3Schristos 
7192ed0d50c3Schristos     case elfcpp::R_AARCH64_PREL32:
7193ed0d50c3Schristos       reloc_status = Reloc::template pcrela_ua<32>(
7194ed0d50c3Schristos 	view, object, psymval, addend, address, reloc_property);
7195ed0d50c3Schristos       break;
7196ed0d50c3Schristos 
7197ed0d50c3Schristos     case elfcpp::R_AARCH64_PREL16:
7198ed0d50c3Schristos       reloc_status = Reloc::template pcrela_ua<16>(
7199ed0d50c3Schristos 	view, object, psymval, addend, address, reloc_property);
7200ed0d50c3Schristos       break;
7201ed0d50c3Schristos 
720206324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G0:
720306324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G0_NC:
720406324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G1:
720506324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G1_NC:
720606324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G2:
720706324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G2_NC:
720806324dcfSchristos     case elfcpp::R_AARCH64_MOVW_UABS_G3:
720906324dcfSchristos       reloc_status = Reloc::template rela_general<32>(
721006324dcfSchristos 	view, object, psymval, addend, reloc_property);
721106324dcfSchristos       break;
721206324dcfSchristos     case elfcpp::R_AARCH64_MOVW_SABS_G0:
721306324dcfSchristos     case elfcpp::R_AARCH64_MOVW_SABS_G1:
721406324dcfSchristos     case elfcpp::R_AARCH64_MOVW_SABS_G2:
721506324dcfSchristos       reloc_status = Reloc::movnz(view, psymval->value(object, addend),
721606324dcfSchristos 				  reloc_property);
721706324dcfSchristos       break;
721806324dcfSchristos 
7219ed0d50c3Schristos     case elfcpp::R_AARCH64_LD_PREL_LO19:
7220ed0d50c3Schristos       reloc_status = Reloc::template pcrela_general<32>(
7221ed0d50c3Schristos 	  view, object, psymval, addend, address, reloc_property);
7222ed0d50c3Schristos       break;
7223ed0d50c3Schristos 
7224ed0d50c3Schristos     case elfcpp::R_AARCH64_ADR_PREL_LO21:
7225ed0d50c3Schristos       reloc_status = Reloc::adr(view, object, psymval, addend,
7226ed0d50c3Schristos 				address, reloc_property);
7227ed0d50c3Schristos       break;
7228ed0d50c3Schristos 
7229ed0d50c3Schristos     case elfcpp::R_AARCH64_ADR_PREL_PG_HI21_NC:
7230ed0d50c3Schristos     case elfcpp::R_AARCH64_ADR_PREL_PG_HI21:
7231ed0d50c3Schristos       reloc_status = Reloc::adrp(view, object, psymval, addend, address,
7232ed0d50c3Schristos 				 reloc_property);
7233ed0d50c3Schristos       break;
7234ed0d50c3Schristos 
7235ed0d50c3Schristos     case elfcpp::R_AARCH64_LDST8_ABS_LO12_NC:
7236ed0d50c3Schristos     case elfcpp::R_AARCH64_LDST16_ABS_LO12_NC:
7237ed0d50c3Schristos     case elfcpp::R_AARCH64_LDST32_ABS_LO12_NC:
7238ed0d50c3Schristos     case elfcpp::R_AARCH64_LDST64_ABS_LO12_NC:
7239ed0d50c3Schristos     case elfcpp::R_AARCH64_LDST128_ABS_LO12_NC:
7240ed0d50c3Schristos     case elfcpp::R_AARCH64_ADD_ABS_LO12_NC:
7241ed0d50c3Schristos       reloc_status = Reloc::template rela_general<32>(
7242ed0d50c3Schristos 	view, object, psymval, addend, reloc_property);
7243ed0d50c3Schristos       break;
7244ed0d50c3Schristos 
7245ed0d50c3Schristos     case elfcpp::R_AARCH64_CALL26:
7246ed0d50c3Schristos       if (this->skip_call_tls_get_addr_)
7247ed0d50c3Schristos 	{
7248ed0d50c3Schristos 	  // Double check that the TLSGD insn has been optimized away.
7249ed0d50c3Schristos 	  typedef typename elfcpp::Swap<32, big_endian>::Valtype Insntype;
7250ed0d50c3Schristos 	  Insntype insn = elfcpp::Swap<32, big_endian>::readval(
7251ed0d50c3Schristos 	      reinterpret_cast<Insntype*>(view));
7252ed0d50c3Schristos 	  gold_assert((insn & 0xff000000) == 0x91000000);
7253ed0d50c3Schristos 
7254ed0d50c3Schristos 	  reloc_status = Reloc::STATUS_OKAY;
7255ed0d50c3Schristos 	  this->skip_call_tls_get_addr_ = false;
7256ed0d50c3Schristos 	  // Return false to stop further processing this reloc.
7257ed0d50c3Schristos 	  return false;
7258ed0d50c3Schristos 	}
725906324dcfSchristos       // Fall through.
7260ed0d50c3Schristos     case elfcpp::R_AARCH64_JUMP26:
7261ed0d50c3Schristos       if (Reloc::maybe_apply_stub(r_type, relinfo, rela, view, address,
7262ed0d50c3Schristos 				  gsym, psymval, object,
7263ed0d50c3Schristos 				  target->stub_group_size_))
7264ed0d50c3Schristos 	break;
726506324dcfSchristos       // Fall through.
7266ed0d50c3Schristos     case elfcpp::R_AARCH64_TSTBR14:
7267ed0d50c3Schristos     case elfcpp::R_AARCH64_CONDBR19:
7268ed0d50c3Schristos       reloc_status = Reloc::template pcrela_general<32>(
7269ed0d50c3Schristos 	view, object, psymval, addend, address, reloc_property);
7270ed0d50c3Schristos       break;
7271ed0d50c3Schristos 
7272ed0d50c3Schristos     case elfcpp::R_AARCH64_ADR_GOT_PAGE:
7273ed0d50c3Schristos       gold_assert(have_got_offset);
7274ed0d50c3Schristos       value = target->got_->address() + got_base + got_offset;
7275ed0d50c3Schristos       reloc_status = Reloc::adrp(view, value + addend, address);
7276ed0d50c3Schristos       break;
7277ed0d50c3Schristos 
7278ed0d50c3Schristos     case elfcpp::R_AARCH64_LD64_GOT_LO12_NC:
7279ed0d50c3Schristos       gold_assert(have_got_offset);
7280ed0d50c3Schristos       value = target->got_->address() + got_base + got_offset;
7281ed0d50c3Schristos       reloc_status = Reloc::template rela_general<32>(
7282ed0d50c3Schristos 	view, value, addend, reloc_property);
7283ed0d50c3Schristos       break;
7284ed0d50c3Schristos 
7285ed0d50c3Schristos     case elfcpp::R_AARCH64_LD64_GOTPAGE_LO15:
7286ed0d50c3Schristos       {
7287ed0d50c3Schristos 	gold_assert(have_got_offset);
7288ed0d50c3Schristos 	value = target->got_->address() + got_base + got_offset + addend -
7289ed0d50c3Schristos 	  Reloc::Page(target->got_->address() + got_base);
7290ed0d50c3Schristos 	if ((value & 7) != 0)
7291ed0d50c3Schristos 	  reloc_status = Reloc::STATUS_OVERFLOW;
7292ed0d50c3Schristos 	else
7293ed0d50c3Schristos 	  reloc_status = Reloc::template reloc_common<32>(
7294ed0d50c3Schristos 	    view, value, reloc_property);
7295ed0d50c3Schristos 	break;
7296ed0d50c3Schristos       }
7297ed0d50c3Schristos 
7298ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSGD_ADR_PAGE21:
7299ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSGD_ADD_LO12_NC:
7300ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADR_PAGE21:
7301ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADD_LO12_NC:
7302ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G1:
7303ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
7304ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_HI12:
7305ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:
7306ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
7307ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
7308ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G2:
7309ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G1:
7310ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
7311ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G0:
7312ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
7313ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_HI12:
7314ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12:
7315ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
731606324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12:
731706324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
731806324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12:
731906324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
732006324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12:
732106324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
732206324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12:
732306324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
7324ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_ADR_PAGE21:
7325ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_LD64_LO12:
7326ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_ADD_LO12:
7327ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_CALL:
7328ed0d50c3Schristos       reloc_status = relocate_tls(relinfo, target, relnum, rela, r_type,
7329ed0d50c3Schristos 				  gsym, psymval, view, address);
7330ed0d50c3Schristos       break;
7331ed0d50c3Schristos 
7332ed0d50c3Schristos     // These are dynamic relocations, which are unexpected when linking.
7333ed0d50c3Schristos     case elfcpp::R_AARCH64_COPY:
7334ed0d50c3Schristos     case elfcpp::R_AARCH64_GLOB_DAT:
7335ed0d50c3Schristos     case elfcpp::R_AARCH64_JUMP_SLOT:
7336ed0d50c3Schristos     case elfcpp::R_AARCH64_RELATIVE:
7337ed0d50c3Schristos     case elfcpp::R_AARCH64_IRELATIVE:
7338ed0d50c3Schristos     case elfcpp::R_AARCH64_TLS_DTPREL64:
7339ed0d50c3Schristos     case elfcpp::R_AARCH64_TLS_DTPMOD64:
7340ed0d50c3Schristos     case elfcpp::R_AARCH64_TLS_TPREL64:
7341ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC:
7342ed0d50c3Schristos       gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
7343ed0d50c3Schristos 			     _("unexpected reloc %u in object file"),
7344ed0d50c3Schristos 			     r_type);
7345ed0d50c3Schristos       break;
7346ed0d50c3Schristos 
7347ed0d50c3Schristos     default:
7348ed0d50c3Schristos       gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
7349ed0d50c3Schristos 			     _("unsupported reloc %s"),
7350ed0d50c3Schristos 			     reloc_property->name().c_str());
7351ed0d50c3Schristos       break;
7352ed0d50c3Schristos     }
7353ed0d50c3Schristos 
7354ed0d50c3Schristos   // Report any errors.
7355ed0d50c3Schristos   switch (reloc_status)
7356ed0d50c3Schristos     {
7357ed0d50c3Schristos     case Reloc::STATUS_OKAY:
7358ed0d50c3Schristos       break;
7359ed0d50c3Schristos     case Reloc::STATUS_OVERFLOW:
7360ed0d50c3Schristos       gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
7361ed0d50c3Schristos 			     _("relocation overflow in %s"),
7362ed0d50c3Schristos 			     reloc_property->name().c_str());
7363ed0d50c3Schristos       break;
7364ed0d50c3Schristos     case Reloc::STATUS_BAD_RELOC:
7365ed0d50c3Schristos       gold_error_at_location(
7366ed0d50c3Schristos 	  relinfo,
7367ed0d50c3Schristos 	  relnum,
7368ed0d50c3Schristos 	  rela.get_r_offset(),
7369ed0d50c3Schristos 	  _("unexpected opcode while processing relocation %s"),
7370ed0d50c3Schristos 	  reloc_property->name().c_str());
7371ed0d50c3Schristos       break;
7372ed0d50c3Schristos     default:
7373ed0d50c3Schristos       gold_unreachable();
7374ed0d50c3Schristos     }
7375ed0d50c3Schristos 
7376ed0d50c3Schristos   return true;
7377ed0d50c3Schristos }
7378ed0d50c3Schristos 
7379ed0d50c3Schristos 
7380ed0d50c3Schristos template<int size, bool big_endian>
7381ed0d50c3Schristos inline
7382ed0d50c3Schristos typename AArch64_relocate_functions<size, big_endian>::Status
relocate_tls(const Relocate_info<size,big_endian> * relinfo,Target_aarch64<size,big_endian> * target,size_t relnum,const elfcpp::Rela<size,big_endian> & rela,unsigned int r_type,const Sized_symbol<size> * gsym,const Symbol_value<size> * psymval,unsigned char * view,typename elfcpp::Elf_types<size>::Elf_Addr address)7383ed0d50c3Schristos Target_aarch64<size, big_endian>::Relocate::relocate_tls(
7384ed0d50c3Schristos     const Relocate_info<size, big_endian>* relinfo,
7385ed0d50c3Schristos     Target_aarch64<size, big_endian>* target,
7386ed0d50c3Schristos     size_t relnum,
7387ed0d50c3Schristos     const elfcpp::Rela<size, big_endian>& rela,
7388ed0d50c3Schristos     unsigned int r_type, const Sized_symbol<size>* gsym,
7389ed0d50c3Schristos     const Symbol_value<size>* psymval,
7390ed0d50c3Schristos     unsigned char* view,
7391ed0d50c3Schristos     typename elfcpp::Elf_types<size>::Elf_Addr address)
7392ed0d50c3Schristos {
7393ed0d50c3Schristos   typedef AArch64_relocate_functions<size, big_endian> aarch64_reloc_funcs;
7394ed0d50c3Schristos   typedef typename elfcpp::Elf_types<size>::Elf_Addr AArch64_address;
7395ed0d50c3Schristos 
7396ed0d50c3Schristos   Output_segment* tls_segment = relinfo->layout->tls_segment();
7397ed0d50c3Schristos   const elfcpp::Elf_Xword addend = rela.get_r_addend();
7398ed0d50c3Schristos   const AArch64_reloc_property* reloc_property =
7399ed0d50c3Schristos       aarch64_reloc_property_table->get_reloc_property(r_type);
7400ed0d50c3Schristos   gold_assert(reloc_property != NULL);
7401ed0d50c3Schristos 
7402ed0d50c3Schristos   const bool is_final = (gsym == NULL
7403ed0d50c3Schristos 			 ? !parameters->options().shared()
7404ed0d50c3Schristos 			 : gsym->final_value_is_known());
7405ed0d50c3Schristos   tls::Tls_optimization tlsopt = Target_aarch64<size, big_endian>::
7406ed0d50c3Schristos       optimize_tls_reloc(is_final, r_type);
7407ed0d50c3Schristos 
7408ed0d50c3Schristos   Sized_relobj_file<size, big_endian>* object = relinfo->object;
7409ed0d50c3Schristos   int tls_got_offset_type;
7410ed0d50c3Schristos   switch (r_type)
7411ed0d50c3Schristos     {
7412ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSGD_ADR_PAGE21:
7413ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSGD_ADD_LO12_NC:  // Global-dynamic
7414ed0d50c3Schristos       {
7415ed0d50c3Schristos 	if (tlsopt == tls::TLSOPT_TO_LE)
7416ed0d50c3Schristos 	  {
7417ed0d50c3Schristos 	    if (tls_segment == NULL)
7418ed0d50c3Schristos 	      {
7419ed0d50c3Schristos 		gold_assert(parameters->errors()->error_count() > 0
7420ed0d50c3Schristos 			    || issue_undefined_symbol_error(gsym));
7421ed0d50c3Schristos 		return aarch64_reloc_funcs::STATUS_BAD_RELOC;
7422ed0d50c3Schristos 	      }
7423ed0d50c3Schristos 	    return tls_gd_to_le(relinfo, target, rela, r_type, view,
7424ed0d50c3Schristos 				psymval);
7425ed0d50c3Schristos 	  }
7426ed0d50c3Schristos 	else if (tlsopt == tls::TLSOPT_NONE)
7427ed0d50c3Schristos 	  {
7428ed0d50c3Schristos 	    tls_got_offset_type = GOT_TYPE_TLS_PAIR;
7429ed0d50c3Schristos 	    // Firstly get the address for the got entry.
7430ed0d50c3Schristos 	    typename elfcpp::Elf_types<size>::Elf_Addr got_entry_address;
7431ed0d50c3Schristos 	    if (gsym != NULL)
7432ed0d50c3Schristos 	      {
7433ed0d50c3Schristos 		gold_assert(gsym->has_got_offset(tls_got_offset_type));
7434ed0d50c3Schristos 		got_entry_address = target->got_->address() +
7435ed0d50c3Schristos 				    gsym->got_offset(tls_got_offset_type);
7436ed0d50c3Schristos 	      }
7437ed0d50c3Schristos 	    else
7438ed0d50c3Schristos 	      {
7439ed0d50c3Schristos 		unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
7440ed0d50c3Schristos 		gold_assert(
7441ed0d50c3Schristos 		  object->local_has_got_offset(r_sym, tls_got_offset_type));
7442ed0d50c3Schristos 		got_entry_address = target->got_->address() +
7443ed0d50c3Schristos 		  object->local_got_offset(r_sym, tls_got_offset_type);
7444ed0d50c3Schristos 	      }
7445ed0d50c3Schristos 
7446ed0d50c3Schristos 	    // Relocate the address into adrp/ld, adrp/add pair.
7447ed0d50c3Schristos 	    switch (r_type)
7448ed0d50c3Schristos 	      {
7449ed0d50c3Schristos 	      case elfcpp::R_AARCH64_TLSGD_ADR_PAGE21:
7450ed0d50c3Schristos 		return aarch64_reloc_funcs::adrp(
7451ed0d50c3Schristos 		  view, got_entry_address + addend, address);
7452ed0d50c3Schristos 
7453ed0d50c3Schristos 		break;
7454ed0d50c3Schristos 
7455ed0d50c3Schristos 	      case elfcpp::R_AARCH64_TLSGD_ADD_LO12_NC:
7456ed0d50c3Schristos 		return aarch64_reloc_funcs::template rela_general<32>(
7457ed0d50c3Schristos 		  view, got_entry_address, addend, reloc_property);
7458ed0d50c3Schristos 		break;
7459ed0d50c3Schristos 
7460ed0d50c3Schristos 	      default:
7461ed0d50c3Schristos 		gold_unreachable();
7462ed0d50c3Schristos 	      }
7463ed0d50c3Schristos 	  }
7464ed0d50c3Schristos 	gold_error_at_location(relinfo, relnum, rela.get_r_offset(),
7465ed0d50c3Schristos 			       _("unsupported gd_to_ie relaxation on %u"),
7466ed0d50c3Schristos 			       r_type);
7467ed0d50c3Schristos       }
7468ed0d50c3Schristos       break;
7469ed0d50c3Schristos 
7470ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADR_PAGE21:
7471ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADD_LO12_NC:  // Local-dynamic
7472ed0d50c3Schristos       {
7473ed0d50c3Schristos 	if (tlsopt == tls::TLSOPT_TO_LE)
7474ed0d50c3Schristos 	  {
7475ed0d50c3Schristos 	    if (tls_segment == NULL)
7476ed0d50c3Schristos 	      {
7477ed0d50c3Schristos 		gold_assert(parameters->errors()->error_count() > 0
7478ed0d50c3Schristos 			    || issue_undefined_symbol_error(gsym));
7479ed0d50c3Schristos 		return aarch64_reloc_funcs::STATUS_BAD_RELOC;
7480ed0d50c3Schristos 	      }
7481ed0d50c3Schristos 	    return this->tls_ld_to_le(relinfo, target, rela, r_type, view,
7482ed0d50c3Schristos 				      psymval);
7483ed0d50c3Schristos 	  }
7484ed0d50c3Schristos 
7485ed0d50c3Schristos 	gold_assert(tlsopt == tls::TLSOPT_NONE);
7486ed0d50c3Schristos 	// Relocate the field with the offset of the GOT entry for
7487ed0d50c3Schristos 	// the module index.
7488ed0d50c3Schristos 	typename elfcpp::Elf_types<size>::Elf_Addr got_entry_address;
7489ed0d50c3Schristos 	got_entry_address = (target->got_mod_index_entry(NULL, NULL, NULL) +
7490ed0d50c3Schristos 			     target->got_->address());
7491ed0d50c3Schristos 
7492ed0d50c3Schristos 	switch (r_type)
7493ed0d50c3Schristos 	  {
7494ed0d50c3Schristos 	  case elfcpp::R_AARCH64_TLSLD_ADR_PAGE21:
7495ed0d50c3Schristos 	    return aarch64_reloc_funcs::adrp(
7496ed0d50c3Schristos 	      view, got_entry_address + addend, address);
7497ed0d50c3Schristos 	    break;
7498ed0d50c3Schristos 
7499ed0d50c3Schristos 	  case elfcpp::R_AARCH64_TLSLD_ADD_LO12_NC:
7500ed0d50c3Schristos 	    return aarch64_reloc_funcs::template rela_general<32>(
7501ed0d50c3Schristos 	      view, got_entry_address, addend, reloc_property);
7502ed0d50c3Schristos 	    break;
7503ed0d50c3Schristos 
7504ed0d50c3Schristos 	  default:
7505ed0d50c3Schristos 	    gold_unreachable();
7506ed0d50c3Schristos 	  }
7507ed0d50c3Schristos       }
7508ed0d50c3Schristos       break;
7509ed0d50c3Schristos 
7510ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G1:
7511ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
7512ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_HI12:
7513ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:  // Other local-dynamic
7514ed0d50c3Schristos       {
7515ed0d50c3Schristos 	AArch64_address value = psymval->value(object, 0);
7516ed0d50c3Schristos 	if (tlsopt == tls::TLSOPT_TO_LE)
7517ed0d50c3Schristos 	  {
7518ed0d50c3Schristos 	    if (tls_segment == NULL)
7519ed0d50c3Schristos 	      {
7520ed0d50c3Schristos 		gold_assert(parameters->errors()->error_count() > 0
7521ed0d50c3Schristos 			    || issue_undefined_symbol_error(gsym));
7522ed0d50c3Schristos 		return aarch64_reloc_funcs::STATUS_BAD_RELOC;
7523ed0d50c3Schristos 	      }
7524ed0d50c3Schristos 	  }
7525ed0d50c3Schristos 	switch (r_type)
7526ed0d50c3Schristos 	  {
7527ed0d50c3Schristos 	  case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G1:
7528ed0d50c3Schristos 	    return aarch64_reloc_funcs::movnz(view, value + addend,
7529ed0d50c3Schristos 					      reloc_property);
7530ed0d50c3Schristos 	    break;
7531ed0d50c3Schristos 
7532ed0d50c3Schristos 	  case elfcpp::R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC:
7533ed0d50c3Schristos 	  case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_HI12:
7534ed0d50c3Schristos 	  case elfcpp::R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC:
7535ed0d50c3Schristos 	    return aarch64_reloc_funcs::template rela_general<32>(
7536ed0d50c3Schristos 		view, value, addend, reloc_property);
7537ed0d50c3Schristos 	    break;
7538ed0d50c3Schristos 
7539ed0d50c3Schristos 	  default:
7540ed0d50c3Schristos 	    gold_unreachable();
7541ed0d50c3Schristos 	  }
7542ed0d50c3Schristos 	// We should never reach here.
7543ed0d50c3Schristos       }
7544ed0d50c3Schristos       break;
7545ed0d50c3Schristos 
7546ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
7547ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:  // Initial-exec
7548ed0d50c3Schristos       {
7549ed0d50c3Schristos 	if (tlsopt == tls::TLSOPT_TO_LE)
7550ed0d50c3Schristos 	  {
7551ed0d50c3Schristos 	    if (tls_segment == NULL)
7552ed0d50c3Schristos 	      {
7553ed0d50c3Schristos 		gold_assert(parameters->errors()->error_count() > 0
7554ed0d50c3Schristos 			    || issue_undefined_symbol_error(gsym));
7555ed0d50c3Schristos 		return aarch64_reloc_funcs::STATUS_BAD_RELOC;
7556ed0d50c3Schristos 	      }
7557ed0d50c3Schristos 	    return tls_ie_to_le(relinfo, target, rela, r_type, view,
7558ed0d50c3Schristos 				psymval);
7559ed0d50c3Schristos 	  }
7560ed0d50c3Schristos 	tls_got_offset_type = GOT_TYPE_TLS_OFFSET;
7561ed0d50c3Schristos 
7562ed0d50c3Schristos 	// Firstly get the address for the got entry.
7563ed0d50c3Schristos 	typename elfcpp::Elf_types<size>::Elf_Addr got_entry_address;
7564ed0d50c3Schristos 	if (gsym != NULL)
7565ed0d50c3Schristos 	  {
7566ed0d50c3Schristos 	    gold_assert(gsym->has_got_offset(tls_got_offset_type));
7567ed0d50c3Schristos 	    got_entry_address = target->got_->address() +
7568ed0d50c3Schristos 				gsym->got_offset(tls_got_offset_type);
7569ed0d50c3Schristos 	  }
7570ed0d50c3Schristos 	else
7571ed0d50c3Schristos 	  {
7572ed0d50c3Schristos 	    unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
7573ed0d50c3Schristos 	    gold_assert(
7574ed0d50c3Schristos 		object->local_has_got_offset(r_sym, tls_got_offset_type));
7575ed0d50c3Schristos 	    got_entry_address = target->got_->address() +
7576ed0d50c3Schristos 		object->local_got_offset(r_sym, tls_got_offset_type);
7577ed0d50c3Schristos 	  }
7578ed0d50c3Schristos 	// Relocate the address into adrp/ld, adrp/add pair.
7579ed0d50c3Schristos 	switch (r_type)
7580ed0d50c3Schristos 	  {
7581ed0d50c3Schristos 	  case elfcpp::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
7582ed0d50c3Schristos 	    return aarch64_reloc_funcs::adrp(view, got_entry_address + addend,
7583ed0d50c3Schristos 					     address);
7584ed0d50c3Schristos 	    break;
7585ed0d50c3Schristos 	  case elfcpp::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
7586ed0d50c3Schristos 	    return aarch64_reloc_funcs::template rela_general<32>(
7587ed0d50c3Schristos 	      view, got_entry_address, addend, reloc_property);
7588ed0d50c3Schristos 	  default:
7589ed0d50c3Schristos 	    gold_unreachable();
7590ed0d50c3Schristos 	  }
7591ed0d50c3Schristos       }
7592ed0d50c3Schristos       // We shall never reach here.
7593ed0d50c3Schristos       break;
7594ed0d50c3Schristos 
7595ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G2:
7596ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G1:
7597ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
7598ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G0:
7599ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
7600ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_HI12:
7601ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12:
7602ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
760306324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12:
760406324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
760506324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12:
760606324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
760706324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12:
760806324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
760906324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12:
761006324dcfSchristos     case elfcpp::R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
7611ed0d50c3Schristos       {
7612ed0d50c3Schristos 	gold_assert(tls_segment != NULL);
7613ed0d50c3Schristos 	AArch64_address value = psymval->value(object, 0);
7614ed0d50c3Schristos 
7615ed0d50c3Schristos 	if (!parameters->options().shared())
7616ed0d50c3Schristos 	  {
7617ed0d50c3Schristos 	    AArch64_address aligned_tcb_size =
7618ed0d50c3Schristos 		align_address(target->tcb_size(),
7619ed0d50c3Schristos 			      tls_segment->maximum_alignment());
7620ed0d50c3Schristos 	    value += aligned_tcb_size;
7621ed0d50c3Schristos 	    switch (r_type)
7622ed0d50c3Schristos 	      {
7623ed0d50c3Schristos 	      case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G2:
7624ed0d50c3Schristos 	      case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G1:
7625ed0d50c3Schristos 	      case elfcpp::R_AARCH64_TLSLE_MOVW_TPREL_G0:
7626ed0d50c3Schristos 		return aarch64_reloc_funcs::movnz(view, value + addend,
7627ed0d50c3Schristos 						  reloc_property);
7628ed0d50c3Schristos 	      default:
7629ed0d50c3Schristos 		return aarch64_reloc_funcs::template
7630ed0d50c3Schristos 		  rela_general<32>(view,
7631ed0d50c3Schristos 				   value,
7632ed0d50c3Schristos 				   addend,
7633ed0d50c3Schristos 				   reloc_property);
7634ed0d50c3Schristos 	      }
7635ed0d50c3Schristos 	  }
7636ed0d50c3Schristos 	else
7637ed0d50c3Schristos 	  gold_error(_("%s: unsupported reloc %u "
7638ed0d50c3Schristos 		       "in non-static TLSLE mode."),
7639ed0d50c3Schristos 		     object->name().c_str(), r_type);
7640ed0d50c3Schristos       }
7641ed0d50c3Schristos       break;
7642ed0d50c3Schristos 
7643ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_ADR_PAGE21:
7644ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_LD64_LO12:
7645ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_ADD_LO12:
7646ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_CALL:
7647ed0d50c3Schristos       {
7648ed0d50c3Schristos 	if (tlsopt == tls::TLSOPT_TO_LE)
7649ed0d50c3Schristos 	  {
7650ed0d50c3Schristos 	    if (tls_segment == NULL)
7651ed0d50c3Schristos 	      {
7652ed0d50c3Schristos 		gold_assert(parameters->errors()->error_count() > 0
7653ed0d50c3Schristos 			    || issue_undefined_symbol_error(gsym));
7654ed0d50c3Schristos 		return aarch64_reloc_funcs::STATUS_BAD_RELOC;
7655ed0d50c3Schristos 	      }
7656ed0d50c3Schristos 	    return tls_desc_gd_to_le(relinfo, target, rela, r_type,
7657ed0d50c3Schristos 				     view, psymval);
7658ed0d50c3Schristos 	  }
7659ed0d50c3Schristos 	else
7660ed0d50c3Schristos 	  {
7661ed0d50c3Schristos 	    tls_got_offset_type = (tlsopt == tls::TLSOPT_TO_IE
7662ed0d50c3Schristos 				   ? GOT_TYPE_TLS_OFFSET
7663ed0d50c3Schristos 				   : GOT_TYPE_TLS_DESC);
766406324dcfSchristos 	    int got_tlsdesc_offset = 0;
7665ed0d50c3Schristos 	    if (r_type != elfcpp::R_AARCH64_TLSDESC_CALL
7666ed0d50c3Schristos 		&& tlsopt == tls::TLSOPT_NONE)
7667ed0d50c3Schristos 	      {
7668ed0d50c3Schristos 		// We created GOT entries in the .got.tlsdesc portion of the
7669ed0d50c3Schristos 		// .got.plt section, but the offset stored in the symbol is the
7670ed0d50c3Schristos 		// offset within .got.tlsdesc.
767106324dcfSchristos 		got_tlsdesc_offset = (target->got_tlsdesc_->address()
767206324dcfSchristos 				      - target->got_->address());
7673ed0d50c3Schristos 	      }
7674ed0d50c3Schristos 	    typename elfcpp::Elf_types<size>::Elf_Addr got_entry_address;
7675ed0d50c3Schristos 	    if (gsym != NULL)
7676ed0d50c3Schristos 	      {
7677ed0d50c3Schristos 		gold_assert(gsym->has_got_offset(tls_got_offset_type));
7678ed0d50c3Schristos 		got_entry_address = target->got_->address()
7679ed0d50c3Schristos 				    + got_tlsdesc_offset
7680ed0d50c3Schristos 				    + gsym->got_offset(tls_got_offset_type);
7681ed0d50c3Schristos 	      }
7682ed0d50c3Schristos 	    else
7683ed0d50c3Schristos 	      {
7684ed0d50c3Schristos 		unsigned int r_sym = elfcpp::elf_r_sym<size>(rela.get_r_info());
7685ed0d50c3Schristos 		gold_assert(
7686ed0d50c3Schristos 		    object->local_has_got_offset(r_sym, tls_got_offset_type));
7687ed0d50c3Schristos 		got_entry_address = target->got_->address() +
7688ed0d50c3Schristos 		  got_tlsdesc_offset +
7689ed0d50c3Schristos 		  object->local_got_offset(r_sym, tls_got_offset_type);
7690ed0d50c3Schristos 	      }
7691ed0d50c3Schristos 	    if (tlsopt == tls::TLSOPT_TO_IE)
7692ed0d50c3Schristos 	      {
7693ed0d50c3Schristos 		return tls_desc_gd_to_ie(relinfo, target, rela, r_type,
7694ed0d50c3Schristos 					 view, psymval, got_entry_address,
7695ed0d50c3Schristos 					 address);
7696ed0d50c3Schristos 	      }
7697ed0d50c3Schristos 
7698ed0d50c3Schristos 	    // Now do tlsdesc relocation.
7699ed0d50c3Schristos 	    switch (r_type)
7700ed0d50c3Schristos 	      {
7701ed0d50c3Schristos 	      case elfcpp::R_AARCH64_TLSDESC_ADR_PAGE21:
7702ed0d50c3Schristos 		return aarch64_reloc_funcs::adrp(view,
7703ed0d50c3Schristos 						 got_entry_address + addend,
7704ed0d50c3Schristos 						 address);
7705ed0d50c3Schristos 		break;
7706ed0d50c3Schristos 	      case elfcpp::R_AARCH64_TLSDESC_LD64_LO12:
7707ed0d50c3Schristos 	      case elfcpp::R_AARCH64_TLSDESC_ADD_LO12:
7708ed0d50c3Schristos 		return aarch64_reloc_funcs::template rela_general<32>(
7709ed0d50c3Schristos 		  view, got_entry_address, addend, reloc_property);
7710ed0d50c3Schristos 		break;
7711ed0d50c3Schristos 	      case elfcpp::R_AARCH64_TLSDESC_CALL:
7712ed0d50c3Schristos 		return aarch64_reloc_funcs::STATUS_OKAY;
7713ed0d50c3Schristos 		break;
7714ed0d50c3Schristos 	      default:
7715ed0d50c3Schristos 		gold_unreachable();
7716ed0d50c3Schristos 	      }
7717ed0d50c3Schristos 	  }
7718ed0d50c3Schristos 	}
7719ed0d50c3Schristos       break;
7720ed0d50c3Schristos 
7721ed0d50c3Schristos     default:
7722ed0d50c3Schristos       gold_error(_("%s: unsupported TLS reloc %u."),
7723ed0d50c3Schristos 		 object->name().c_str(), r_type);
7724ed0d50c3Schristos     }
7725ed0d50c3Schristos   return aarch64_reloc_funcs::STATUS_BAD_RELOC;
7726ed0d50c3Schristos }  // End of relocate_tls.
7727ed0d50c3Schristos 
7728ed0d50c3Schristos 
7729ed0d50c3Schristos template<int size, bool big_endian>
7730ed0d50c3Schristos inline
7731ed0d50c3Schristos typename AArch64_relocate_functions<size, big_endian>::Status
tls_gd_to_le(const Relocate_info<size,big_endian> * relinfo,Target_aarch64<size,big_endian> * target,const elfcpp::Rela<size,big_endian> & rela,unsigned int r_type,unsigned char * view,const Symbol_value<size> * psymval)7732ed0d50c3Schristos Target_aarch64<size, big_endian>::Relocate::tls_gd_to_le(
7733ed0d50c3Schristos 	     const Relocate_info<size, big_endian>* relinfo,
7734ed0d50c3Schristos 	     Target_aarch64<size, big_endian>* target,
7735ed0d50c3Schristos 	     const elfcpp::Rela<size, big_endian>& rela,
7736ed0d50c3Schristos 	     unsigned int r_type,
7737ed0d50c3Schristos 	     unsigned char* view,
7738ed0d50c3Schristos 	     const Symbol_value<size>* psymval)
7739ed0d50c3Schristos {
7740ed0d50c3Schristos   typedef AArch64_relocate_functions<size, big_endian> aarch64_reloc_funcs;
7741ed0d50c3Schristos   typedef typename elfcpp::Swap<32, big_endian>::Valtype Insntype;
7742ed0d50c3Schristos   typedef typename elfcpp::Elf_types<size>::Elf_Addr AArch64_address;
7743ed0d50c3Schristos 
7744ed0d50c3Schristos   Insntype* ip = reinterpret_cast<Insntype*>(view);
7745ed0d50c3Schristos   Insntype insn1 = elfcpp::Swap<32, big_endian>::readval(ip);
7746ed0d50c3Schristos   Insntype insn2 = elfcpp::Swap<32, big_endian>::readval(ip + 1);
7747ed0d50c3Schristos   Insntype insn3 = elfcpp::Swap<32, big_endian>::readval(ip + 2);
7748ed0d50c3Schristos 
7749ed0d50c3Schristos   if (r_type == elfcpp::R_AARCH64_TLSGD_ADD_LO12_NC)
7750ed0d50c3Schristos     {
7751ed0d50c3Schristos       // This is the 2nd relocs, optimization should already have been
7752ed0d50c3Schristos       // done.
7753ed0d50c3Schristos       gold_assert((insn1 & 0xfff00000) == 0x91400000);
7754ed0d50c3Schristos       return aarch64_reloc_funcs::STATUS_OKAY;
7755ed0d50c3Schristos     }
7756ed0d50c3Schristos 
7757ed0d50c3Schristos   // The original sequence is -
7758ed0d50c3Schristos   //   90000000        adrp    x0, 0 <main>
7759ed0d50c3Schristos   //   91000000        add     x0, x0, #0x0
7760ed0d50c3Schristos   //   94000000        bl      0 <__tls_get_addr>
7761ed0d50c3Schristos   // optimized to sequence -
7762ed0d50c3Schristos   //   d53bd040        mrs     x0, tpidr_el0
7763ed0d50c3Schristos   //   91400000        add     x0, x0, #0x0, lsl #12
7764ed0d50c3Schristos   //   91000000        add     x0, x0, #0x0
7765ed0d50c3Schristos 
7766ed0d50c3Schristos   // Unlike tls_ie_to_le, we change the 3 insns in one function call when we
7767ed0d50c3Schristos   // encounter the first relocation "R_AARCH64_TLSGD_ADR_PAGE21". Because we
7768ed0d50c3Schristos   // have to change "bl tls_get_addr", which does not have a corresponding tls
7769ed0d50c3Schristos   // relocation type. So before proceeding, we need to make sure compiler
7770ed0d50c3Schristos   // does not change the sequence.
7771ed0d50c3Schristos   if(!(insn1 == 0x90000000      // adrp x0,0
7772ed0d50c3Schristos        && insn2 == 0x91000000   // add x0, x0, #0x0
7773ed0d50c3Schristos        && insn3 == 0x94000000)) // bl 0
7774ed0d50c3Schristos     {
7775ed0d50c3Schristos       // Ideally we should give up gd_to_le relaxation and do gd access.
7776ed0d50c3Schristos       // However the gd_to_le relaxation decision has been made early
7777ed0d50c3Schristos       // in the scan stage, where we did not allocate any GOT entry for
7778ed0d50c3Schristos       // this symbol. Therefore we have to exit and report error now.
7779ed0d50c3Schristos       gold_error(_("unexpected reloc insn sequence while relaxing "
7780ed0d50c3Schristos 		   "tls gd to le for reloc %u."), r_type);
7781ed0d50c3Schristos       return aarch64_reloc_funcs::STATUS_BAD_RELOC;
7782ed0d50c3Schristos     }
7783ed0d50c3Schristos 
7784ed0d50c3Schristos   // Write new insns.
7785ed0d50c3Schristos   insn1 = 0xd53bd040;  // mrs x0, tpidr_el0
7786ed0d50c3Schristos   insn2 = 0x91400000;  // add x0, x0, #0x0, lsl #12
7787ed0d50c3Schristos   insn3 = 0x91000000;  // add x0, x0, #0x0
7788ed0d50c3Schristos   elfcpp::Swap<32, big_endian>::writeval(ip, insn1);
7789ed0d50c3Schristos   elfcpp::Swap<32, big_endian>::writeval(ip + 1, insn2);
7790ed0d50c3Schristos   elfcpp::Swap<32, big_endian>::writeval(ip + 2, insn3);
7791ed0d50c3Schristos 
7792ed0d50c3Schristos   // Calculate tprel value.
7793ed0d50c3Schristos   Output_segment* tls_segment = relinfo->layout->tls_segment();
7794ed0d50c3Schristos   gold_assert(tls_segment != NULL);
7795ed0d50c3Schristos   AArch64_address value = psymval->value(relinfo->object, 0);
7796ed0d50c3Schristos   const elfcpp::Elf_Xword addend = rela.get_r_addend();
7797ed0d50c3Schristos   AArch64_address aligned_tcb_size =
7798ed0d50c3Schristos       align_address(target->tcb_size(), tls_segment->maximum_alignment());
7799ed0d50c3Schristos   AArch64_address x = value + aligned_tcb_size;
7800ed0d50c3Schristos 
7801ed0d50c3Schristos   // After new insns are written, apply TLSLE relocs.
7802ed0d50c3Schristos   const AArch64_reloc_property* rp1 =
7803ed0d50c3Schristos       aarch64_reloc_property_table->get_reloc_property(
7804ed0d50c3Schristos 	  elfcpp::R_AARCH64_TLSLE_ADD_TPREL_HI12);
7805ed0d50c3Schristos   const AArch64_reloc_property* rp2 =
7806ed0d50c3Schristos       aarch64_reloc_property_table->get_reloc_property(
7807ed0d50c3Schristos 	  elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12);
7808ed0d50c3Schristos   gold_assert(rp1 != NULL && rp2 != NULL);
7809ed0d50c3Schristos 
7810ed0d50c3Schristos   typename aarch64_reloc_funcs::Status s1 =
7811ed0d50c3Schristos       aarch64_reloc_funcs::template rela_general<32>(view + 4,
7812ed0d50c3Schristos 						     x,
7813ed0d50c3Schristos 						     addend,
7814ed0d50c3Schristos 						     rp1);
7815ed0d50c3Schristos   if (s1 != aarch64_reloc_funcs::STATUS_OKAY)
7816ed0d50c3Schristos     return s1;
7817ed0d50c3Schristos 
7818ed0d50c3Schristos   typename aarch64_reloc_funcs::Status s2 =
7819ed0d50c3Schristos       aarch64_reloc_funcs::template rela_general<32>(view + 8,
7820ed0d50c3Schristos 						     x,
7821ed0d50c3Schristos 						     addend,
7822ed0d50c3Schristos 						     rp2);
7823ed0d50c3Schristos 
7824ed0d50c3Schristos   this->skip_call_tls_get_addr_ = true;
7825ed0d50c3Schristos   return s2;
7826ed0d50c3Schristos }  // End of tls_gd_to_le
7827ed0d50c3Schristos 
7828ed0d50c3Schristos 
7829ed0d50c3Schristos template<int size, bool big_endian>
7830ed0d50c3Schristos inline
7831ed0d50c3Schristos typename AArch64_relocate_functions<size, big_endian>::Status
tls_ld_to_le(const Relocate_info<size,big_endian> * relinfo,Target_aarch64<size,big_endian> * target,const elfcpp::Rela<size,big_endian> & rela,unsigned int r_type,unsigned char * view,const Symbol_value<size> * psymval)7832ed0d50c3Schristos Target_aarch64<size, big_endian>::Relocate::tls_ld_to_le(
7833ed0d50c3Schristos 	     const Relocate_info<size, big_endian>* relinfo,
7834ed0d50c3Schristos 	     Target_aarch64<size, big_endian>* target,
7835ed0d50c3Schristos 	     const elfcpp::Rela<size, big_endian>& rela,
7836ed0d50c3Schristos 	     unsigned int r_type,
7837ed0d50c3Schristos 	     unsigned char* view,
7838ed0d50c3Schristos 	     const Symbol_value<size>* psymval)
7839ed0d50c3Schristos {
7840ed0d50c3Schristos   typedef AArch64_relocate_functions<size, big_endian> aarch64_reloc_funcs;
7841ed0d50c3Schristos   typedef typename elfcpp::Swap<32, big_endian>::Valtype Insntype;
7842ed0d50c3Schristos   typedef typename elfcpp::Elf_types<size>::Elf_Addr AArch64_address;
7843ed0d50c3Schristos 
7844ed0d50c3Schristos   Insntype* ip = reinterpret_cast<Insntype*>(view);
7845ed0d50c3Schristos   Insntype insn1 = elfcpp::Swap<32, big_endian>::readval(ip);
7846ed0d50c3Schristos   Insntype insn2 = elfcpp::Swap<32, big_endian>::readval(ip + 1);
7847ed0d50c3Schristos   Insntype insn3 = elfcpp::Swap<32, big_endian>::readval(ip + 2);
7848ed0d50c3Schristos 
7849ed0d50c3Schristos   if (r_type == elfcpp::R_AARCH64_TLSLD_ADD_LO12_NC)
7850ed0d50c3Schristos     {
7851ed0d50c3Schristos       // This is the 2nd relocs, optimization should already have been
7852ed0d50c3Schristos       // done.
7853ed0d50c3Schristos       gold_assert((insn1 & 0xfff00000) == 0x91400000);
7854ed0d50c3Schristos       return aarch64_reloc_funcs::STATUS_OKAY;
7855ed0d50c3Schristos     }
7856ed0d50c3Schristos 
7857ed0d50c3Schristos   // The original sequence is -
7858ed0d50c3Schristos   //   90000000        adrp    x0, 0 <main>
7859ed0d50c3Schristos   //   91000000        add     x0, x0, #0x0
7860ed0d50c3Schristos   //   94000000        bl      0 <__tls_get_addr>
7861ed0d50c3Schristos   // optimized to sequence -
7862ed0d50c3Schristos   //   d53bd040        mrs     x0, tpidr_el0
7863ed0d50c3Schristos   //   91400000        add     x0, x0, #0x0, lsl #12
7864ed0d50c3Schristos   //   91000000        add     x0, x0, #0x0
7865ed0d50c3Schristos 
7866ed0d50c3Schristos   // Unlike tls_ie_to_le, we change the 3 insns in one function call when we
7867ed0d50c3Schristos   // encounter the first relocation "R_AARCH64_TLSLD_ADR_PAGE21". Because we
7868ed0d50c3Schristos   // have to change "bl tls_get_addr", which does not have a corresponding tls
7869ed0d50c3Schristos   // relocation type. So before proceeding, we need to make sure compiler
7870ed0d50c3Schristos   // does not change the sequence.
7871ed0d50c3Schristos   if(!(insn1 == 0x90000000      // adrp x0,0
7872ed0d50c3Schristos        && insn2 == 0x91000000   // add x0, x0, #0x0
7873ed0d50c3Schristos        && insn3 == 0x94000000)) // bl 0
7874ed0d50c3Schristos     {
7875ed0d50c3Schristos       // Ideally we should give up gd_to_le relaxation and do gd access.
7876ed0d50c3Schristos       // However the gd_to_le relaxation decision has been made early
787706324dcfSchristos       // in the scan stage, where we did not allocate a GOT entry for
787806324dcfSchristos       // this symbol. Therefore we have to exit and report an error now.
7879ed0d50c3Schristos       gold_error(_("unexpected reloc insn sequence while relaxing "
7880ed0d50c3Schristos 		   "tls gd to le for reloc %u."), r_type);
7881ed0d50c3Schristos       return aarch64_reloc_funcs::STATUS_BAD_RELOC;
7882ed0d50c3Schristos     }
7883ed0d50c3Schristos 
7884ed0d50c3Schristos   // Write new insns.
7885ed0d50c3Schristos   insn1 = 0xd53bd040;  // mrs x0, tpidr_el0
7886ed0d50c3Schristos   insn2 = 0x91400000;  // add x0, x0, #0x0, lsl #12
7887ed0d50c3Schristos   insn3 = 0x91000000;  // add x0, x0, #0x0
7888ed0d50c3Schristos   elfcpp::Swap<32, big_endian>::writeval(ip, insn1);
7889ed0d50c3Schristos   elfcpp::Swap<32, big_endian>::writeval(ip + 1, insn2);
7890ed0d50c3Schristos   elfcpp::Swap<32, big_endian>::writeval(ip + 2, insn3);
7891ed0d50c3Schristos 
7892ed0d50c3Schristos   // Calculate tprel value.
7893ed0d50c3Schristos   Output_segment* tls_segment = relinfo->layout->tls_segment();
7894ed0d50c3Schristos   gold_assert(tls_segment != NULL);
7895ed0d50c3Schristos   AArch64_address value = psymval->value(relinfo->object, 0);
7896ed0d50c3Schristos   const elfcpp::Elf_Xword addend = rela.get_r_addend();
7897ed0d50c3Schristos   AArch64_address aligned_tcb_size =
7898ed0d50c3Schristos       align_address(target->tcb_size(), tls_segment->maximum_alignment());
7899ed0d50c3Schristos   AArch64_address x = value + aligned_tcb_size;
7900ed0d50c3Schristos 
7901ed0d50c3Schristos   // After new insns are written, apply TLSLE relocs.
7902ed0d50c3Schristos   const AArch64_reloc_property* rp1 =
7903ed0d50c3Schristos       aarch64_reloc_property_table->get_reloc_property(
7904ed0d50c3Schristos 	  elfcpp::R_AARCH64_TLSLE_ADD_TPREL_HI12);
7905ed0d50c3Schristos   const AArch64_reloc_property* rp2 =
7906ed0d50c3Schristos       aarch64_reloc_property_table->get_reloc_property(
7907ed0d50c3Schristos 	  elfcpp::R_AARCH64_TLSLE_ADD_TPREL_LO12);
7908ed0d50c3Schristos   gold_assert(rp1 != NULL && rp2 != NULL);
7909ed0d50c3Schristos 
7910ed0d50c3Schristos   typename aarch64_reloc_funcs::Status s1 =
7911ed0d50c3Schristos       aarch64_reloc_funcs::template rela_general<32>(view + 4,
7912ed0d50c3Schristos 						     x,
7913ed0d50c3Schristos 						     addend,
7914ed0d50c3Schristos 						     rp1);
7915ed0d50c3Schristos   if (s1 != aarch64_reloc_funcs::STATUS_OKAY)
7916ed0d50c3Schristos     return s1;
7917ed0d50c3Schristos 
7918ed0d50c3Schristos   typename aarch64_reloc_funcs::Status s2 =
7919ed0d50c3Schristos       aarch64_reloc_funcs::template rela_general<32>(view + 8,
7920ed0d50c3Schristos 						     x,
7921ed0d50c3Schristos 						     addend,
7922ed0d50c3Schristos 						     rp2);
7923ed0d50c3Schristos 
7924ed0d50c3Schristos   this->skip_call_tls_get_addr_ = true;
7925ed0d50c3Schristos   return s2;
7926ed0d50c3Schristos 
7927ed0d50c3Schristos }  // End of tls_ld_to_le
7928ed0d50c3Schristos 
7929ed0d50c3Schristos template<int size, bool big_endian>
7930ed0d50c3Schristos inline
7931ed0d50c3Schristos typename AArch64_relocate_functions<size, big_endian>::Status
tls_ie_to_le(const Relocate_info<size,big_endian> * relinfo,Target_aarch64<size,big_endian> * target,const elfcpp::Rela<size,big_endian> & rela,unsigned int r_type,unsigned char * view,const Symbol_value<size> * psymval)7932ed0d50c3Schristos Target_aarch64<size, big_endian>::Relocate::tls_ie_to_le(
7933ed0d50c3Schristos 	     const Relocate_info<size, big_endian>* relinfo,
7934ed0d50c3Schristos 	     Target_aarch64<size, big_endian>* target,
7935ed0d50c3Schristos 	     const elfcpp::Rela<size, big_endian>& rela,
7936ed0d50c3Schristos 	     unsigned int r_type,
7937ed0d50c3Schristos 	     unsigned char* view,
7938ed0d50c3Schristos 	     const Symbol_value<size>* psymval)
7939ed0d50c3Schristos {
7940ed0d50c3Schristos   typedef typename elfcpp::Elf_types<size>::Elf_Addr AArch64_address;
7941ed0d50c3Schristos   typedef typename elfcpp::Swap<32, big_endian>::Valtype Insntype;
7942ed0d50c3Schristos   typedef AArch64_relocate_functions<size, big_endian> aarch64_reloc_funcs;
7943ed0d50c3Schristos 
7944ed0d50c3Schristos   AArch64_address value = psymval->value(relinfo->object, 0);
7945ed0d50c3Schristos   Output_segment* tls_segment = relinfo->layout->tls_segment();
7946ed0d50c3Schristos   AArch64_address aligned_tcb_address =
7947ed0d50c3Schristos       align_address(target->tcb_size(), tls_segment->maximum_alignment());
7948ed0d50c3Schristos   const elfcpp::Elf_Xword addend = rela.get_r_addend();
7949ed0d50c3Schristos   AArch64_address x = value + addend + aligned_tcb_address;
7950ed0d50c3Schristos   // "x" is the offset to tp, we can only do this if x is within
7951ed0d50c3Schristos   // range [0, 2^32-1]
7952ed0d50c3Schristos   if (!(size == 32 || (size == 64 && (static_cast<uint64_t>(x) >> 32) == 0)))
7953ed0d50c3Schristos     {
7954ed0d50c3Schristos       gold_error(_("TLS variable referred by reloc %u is too far from TP."),
7955ed0d50c3Schristos 		 r_type);
7956ed0d50c3Schristos       return aarch64_reloc_funcs::STATUS_BAD_RELOC;
7957ed0d50c3Schristos     }
7958ed0d50c3Schristos 
7959ed0d50c3Schristos   Insntype* ip = reinterpret_cast<Insntype*>(view);
7960ed0d50c3Schristos   Insntype insn = elfcpp::Swap<32, big_endian>::readval(ip);
7961ed0d50c3Schristos   unsigned int regno;
7962ed0d50c3Schristos   Insntype newinsn;
7963ed0d50c3Schristos   if (r_type == elfcpp::R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21)
7964ed0d50c3Schristos     {
7965ed0d50c3Schristos       // Generate movz.
7966ed0d50c3Schristos       regno = (insn & 0x1f);
7967ed0d50c3Schristos       newinsn = (0xd2a00000 | regno) | (((x >> 16) & 0xffff) << 5);
7968ed0d50c3Schristos     }
7969ed0d50c3Schristos   else if (r_type == elfcpp::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC)
7970ed0d50c3Schristos     {
7971ed0d50c3Schristos       // Generate movk.
7972ed0d50c3Schristos       regno = (insn & 0x1f);
7973ed0d50c3Schristos       gold_assert(regno == ((insn >> 5) & 0x1f));
7974ed0d50c3Schristos       newinsn = (0xf2800000 | regno) | ((x & 0xffff) << 5);
7975ed0d50c3Schristos     }
7976ed0d50c3Schristos   else
7977ed0d50c3Schristos     gold_unreachable();
7978ed0d50c3Schristos 
7979ed0d50c3Schristos   elfcpp::Swap<32, big_endian>::writeval(ip, newinsn);
7980ed0d50c3Schristos   return aarch64_reloc_funcs::STATUS_OKAY;
7981ed0d50c3Schristos }  // End of tls_ie_to_le
7982ed0d50c3Schristos 
7983ed0d50c3Schristos 
7984ed0d50c3Schristos template<int size, bool big_endian>
7985ed0d50c3Schristos inline
7986ed0d50c3Schristos typename AArch64_relocate_functions<size, big_endian>::Status
tls_desc_gd_to_le(const Relocate_info<size,big_endian> * relinfo,Target_aarch64<size,big_endian> * target,const elfcpp::Rela<size,big_endian> & rela,unsigned int r_type,unsigned char * view,const Symbol_value<size> * psymval)7987ed0d50c3Schristos Target_aarch64<size, big_endian>::Relocate::tls_desc_gd_to_le(
7988ed0d50c3Schristos 	     const Relocate_info<size, big_endian>* relinfo,
7989ed0d50c3Schristos 	     Target_aarch64<size, big_endian>* target,
7990ed0d50c3Schristos 	     const elfcpp::Rela<size, big_endian>& rela,
7991ed0d50c3Schristos 	     unsigned int r_type,
7992ed0d50c3Schristos 	     unsigned char* view,
7993ed0d50c3Schristos 	     const Symbol_value<size>* psymval)
7994ed0d50c3Schristos {
7995ed0d50c3Schristos   typedef typename elfcpp::Elf_types<size>::Elf_Addr AArch64_address;
7996ed0d50c3Schristos   typedef typename elfcpp::Swap<32, big_endian>::Valtype Insntype;
7997ed0d50c3Schristos   typedef AArch64_relocate_functions<size, big_endian> aarch64_reloc_funcs;
7998ed0d50c3Schristos 
7999ed0d50c3Schristos   // TLSDESC-GD sequence is like:
8000ed0d50c3Schristos   //   adrp  x0, :tlsdesc:v1
8001ed0d50c3Schristos   //   ldr   x1, [x0, #:tlsdesc_lo12:v1]
8002ed0d50c3Schristos   //   add   x0, x0, :tlsdesc_lo12:v1
8003ed0d50c3Schristos   //   .tlsdesccall    v1
8004ed0d50c3Schristos   //   blr   x1
8005ed0d50c3Schristos   // After desc_gd_to_le optimization, the sequence will be like:
8006ed0d50c3Schristos   //   movz  x0, #0x0, lsl #16
8007ed0d50c3Schristos   //   movk  x0, #0x10
8008ed0d50c3Schristos   //   nop
8009ed0d50c3Schristos   //   nop
8010ed0d50c3Schristos 
8011ed0d50c3Schristos   // Calculate tprel value.
8012ed0d50c3Schristos   Output_segment* tls_segment = relinfo->layout->tls_segment();
8013ed0d50c3Schristos   gold_assert(tls_segment != NULL);
8014ed0d50c3Schristos   Insntype* ip = reinterpret_cast<Insntype*>(view);
8015ed0d50c3Schristos   const elfcpp::Elf_Xword addend = rela.get_r_addend();
8016ed0d50c3Schristos   AArch64_address value = psymval->value(relinfo->object, addend);
8017ed0d50c3Schristos   AArch64_address aligned_tcb_size =
8018ed0d50c3Schristos       align_address(target->tcb_size(), tls_segment->maximum_alignment());
8019ed0d50c3Schristos   AArch64_address x = value + aligned_tcb_size;
8020ed0d50c3Schristos   // x is the offset to tp, we can only do this if x is within range
8021ed0d50c3Schristos   // [0, 2^32-1]. If x is out of range, fail and exit.
8022ed0d50c3Schristos   if (size == 64 && (static_cast<uint64_t>(x) >> 32) != 0)
8023ed0d50c3Schristos     {
8024ed0d50c3Schristos       gold_error(_("TLS variable referred by reloc %u is too far from TP. "
8025ed0d50c3Schristos 		   "We Can't do gd_to_le relaxation.\n"), r_type);
8026ed0d50c3Schristos       return aarch64_reloc_funcs::STATUS_BAD_RELOC;
8027ed0d50c3Schristos     }
8028ed0d50c3Schristos   Insntype newinsn;
8029ed0d50c3Schristos   switch (r_type)
8030ed0d50c3Schristos     {
8031ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_ADD_LO12:
8032ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_CALL:
8033ed0d50c3Schristos       // Change to nop
8034ed0d50c3Schristos       newinsn = 0xd503201f;
8035ed0d50c3Schristos       break;
8036ed0d50c3Schristos 
8037ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_ADR_PAGE21:
8038ed0d50c3Schristos       // Change to movz.
8039ed0d50c3Schristos       newinsn = 0xd2a00000 | (((x >> 16) & 0xffff) << 5);
8040ed0d50c3Schristos       break;
8041ed0d50c3Schristos 
8042ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_LD64_LO12:
8043ed0d50c3Schristos       // Change to movk.
8044ed0d50c3Schristos       newinsn = 0xf2800000 | ((x & 0xffff) << 5);
8045ed0d50c3Schristos       break;
8046ed0d50c3Schristos 
8047ed0d50c3Schristos     default:
8048ed0d50c3Schristos       gold_error(_("unsupported tlsdesc gd_to_le optimization on reloc %u"),
8049ed0d50c3Schristos 		 r_type);
8050ed0d50c3Schristos       gold_unreachable();
8051ed0d50c3Schristos     }
8052ed0d50c3Schristos   elfcpp::Swap<32, big_endian>::writeval(ip, newinsn);
8053ed0d50c3Schristos   return aarch64_reloc_funcs::STATUS_OKAY;
8054ed0d50c3Schristos }  // End of tls_desc_gd_to_le
8055ed0d50c3Schristos 
8056ed0d50c3Schristos 
8057ed0d50c3Schristos template<int size, bool big_endian>
8058ed0d50c3Schristos inline
8059ed0d50c3Schristos typename AArch64_relocate_functions<size, big_endian>::Status
tls_desc_gd_to_ie(const Relocate_info<size,big_endian> *,Target_aarch64<size,big_endian> *,const elfcpp::Rela<size,big_endian> & rela,unsigned int r_type,unsigned char * view,const Symbol_value<size> *,typename elfcpp::Elf_types<size>::Elf_Addr got_entry_address,typename elfcpp::Elf_types<size>::Elf_Addr address)8060ed0d50c3Schristos Target_aarch64<size, big_endian>::Relocate::tls_desc_gd_to_ie(
8061ed0d50c3Schristos 	     const Relocate_info<size, big_endian>* /* relinfo */,
8062ed0d50c3Schristos 	     Target_aarch64<size, big_endian>* /* target */,
8063ed0d50c3Schristos 	     const elfcpp::Rela<size, big_endian>& rela,
8064ed0d50c3Schristos 	     unsigned int r_type,
8065ed0d50c3Schristos 	     unsigned char* view,
8066ed0d50c3Schristos 	     const Symbol_value<size>* /* psymval */,
8067ed0d50c3Schristos 	     typename elfcpp::Elf_types<size>::Elf_Addr got_entry_address,
8068ed0d50c3Schristos 	     typename elfcpp::Elf_types<size>::Elf_Addr address)
8069ed0d50c3Schristos {
8070ed0d50c3Schristos   typedef typename elfcpp::Swap<32, big_endian>::Valtype Insntype;
8071ed0d50c3Schristos   typedef AArch64_relocate_functions<size, big_endian> aarch64_reloc_funcs;
8072ed0d50c3Schristos 
8073ed0d50c3Schristos   // TLSDESC-GD sequence is like:
8074ed0d50c3Schristos   //   adrp  x0, :tlsdesc:v1
8075ed0d50c3Schristos   //   ldr   x1, [x0, #:tlsdesc_lo12:v1]
8076ed0d50c3Schristos   //   add   x0, x0, :tlsdesc_lo12:v1
8077ed0d50c3Schristos   //   .tlsdesccall    v1
8078ed0d50c3Schristos   //   blr   x1
8079ed0d50c3Schristos   // After desc_gd_to_ie optimization, the sequence will be like:
8080ed0d50c3Schristos   //   adrp  x0, :tlsie:v1
8081ed0d50c3Schristos   //   ldr   x0, [x0, :tlsie_lo12:v1]
8082ed0d50c3Schristos   //   nop
8083ed0d50c3Schristos   //   nop
8084ed0d50c3Schristos 
8085ed0d50c3Schristos   Insntype* ip = reinterpret_cast<Insntype*>(view);
8086ed0d50c3Schristos   const elfcpp::Elf_Xword addend = rela.get_r_addend();
8087ed0d50c3Schristos   Insntype newinsn;
8088ed0d50c3Schristos   switch (r_type)
8089ed0d50c3Schristos     {
8090ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_ADD_LO12:
8091ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_CALL:
8092ed0d50c3Schristos       // Change to nop
8093ed0d50c3Schristos       newinsn = 0xd503201f;
8094ed0d50c3Schristos       elfcpp::Swap<32, big_endian>::writeval(ip, newinsn);
8095ed0d50c3Schristos       break;
8096ed0d50c3Schristos 
8097ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_ADR_PAGE21:
8098ed0d50c3Schristos       {
8099ed0d50c3Schristos 	return aarch64_reloc_funcs::adrp(view, got_entry_address + addend,
8100ed0d50c3Schristos 					 address);
8101ed0d50c3Schristos       }
8102ed0d50c3Schristos       break;
8103ed0d50c3Schristos 
8104ed0d50c3Schristos     case elfcpp::R_AARCH64_TLSDESC_LD64_LO12:
8105ed0d50c3Schristos       {
8106ed0d50c3Schristos        // Set ldr target register to be x0.
8107ed0d50c3Schristos        Insntype insn = elfcpp::Swap<32, big_endian>::readval(ip);
8108ed0d50c3Schristos        insn &= 0xffffffe0;
8109ed0d50c3Schristos        elfcpp::Swap<32, big_endian>::writeval(ip, insn);
8110ed0d50c3Schristos        // Do relocation.
8111ed0d50c3Schristos 	const AArch64_reloc_property* reloc_property =
8112ed0d50c3Schristos 	    aarch64_reloc_property_table->get_reloc_property(
8113ed0d50c3Schristos 	      elfcpp::R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC);
8114ed0d50c3Schristos 	return aarch64_reloc_funcs::template rela_general<32>(
8115ed0d50c3Schristos 		 view, got_entry_address, addend, reloc_property);
8116ed0d50c3Schristos       }
8117ed0d50c3Schristos       break;
8118ed0d50c3Schristos 
8119ed0d50c3Schristos     default:
8120ed0d50c3Schristos       gold_error(_("Don't support tlsdesc gd_to_ie optimization on reloc %u"),
8121ed0d50c3Schristos 		 r_type);
8122ed0d50c3Schristos       gold_unreachable();
8123ed0d50c3Schristos     }
8124ed0d50c3Schristos   return aarch64_reloc_funcs::STATUS_OKAY;
8125ed0d50c3Schristos }  // End of tls_desc_gd_to_ie
8126ed0d50c3Schristos 
8127ed0d50c3Schristos // Relocate section data.
8128ed0d50c3Schristos 
8129ed0d50c3Schristos template<int size, bool big_endian>
8130ed0d50c3Schristos void
relocate_section(const Relocate_info<size,big_endian> * relinfo,unsigned int sh_type,const unsigned char * prelocs,size_t reloc_count,Output_section * output_section,bool needs_special_offset_handling,unsigned char * view,typename elfcpp::Elf_types<size>::Elf_Addr address,section_size_type view_size,const Reloc_symbol_changes * reloc_symbol_changes)8131ed0d50c3Schristos Target_aarch64<size, big_endian>::relocate_section(
8132ed0d50c3Schristos     const Relocate_info<size, big_endian>* relinfo,
8133ed0d50c3Schristos     unsigned int sh_type,
8134ed0d50c3Schristos     const unsigned char* prelocs,
8135ed0d50c3Schristos     size_t reloc_count,
8136ed0d50c3Schristos     Output_section* output_section,
8137ed0d50c3Schristos     bool needs_special_offset_handling,
8138ed0d50c3Schristos     unsigned char* view,
8139ed0d50c3Schristos     typename elfcpp::Elf_types<size>::Elf_Addr address,
8140ed0d50c3Schristos     section_size_type view_size,
8141ed0d50c3Schristos     const Reloc_symbol_changes* reloc_symbol_changes)
8142ed0d50c3Schristos {
814306324dcfSchristos   typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
8144ed0d50c3Schristos   typedef Target_aarch64<size, big_endian> Aarch64;
8145ed0d50c3Schristos   typedef typename Target_aarch64<size, big_endian>::Relocate AArch64_relocate;
8146ed0d50c3Schristos   typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
8147ed0d50c3Schristos       Classify_reloc;
8148ed0d50c3Schristos 
8149ed0d50c3Schristos   gold_assert(sh_type == elfcpp::SHT_RELA);
8150ed0d50c3Schristos 
815106324dcfSchristos   // See if we are relocating a relaxed input section.  If so, the view
815206324dcfSchristos   // covers the whole output section and we need to adjust accordingly.
815306324dcfSchristos   if (needs_special_offset_handling)
815406324dcfSchristos     {
815506324dcfSchristos       const Output_relaxed_input_section* poris =
815606324dcfSchristos 	output_section->find_relaxed_input_section(relinfo->object,
815706324dcfSchristos 						   relinfo->data_shndx);
815806324dcfSchristos       if (poris != NULL)
815906324dcfSchristos 	{
816006324dcfSchristos 	  Address section_address = poris->address();
816106324dcfSchristos 	  section_size_type section_size = poris->data_size();
816206324dcfSchristos 
816306324dcfSchristos 	  gold_assert((section_address >= address)
816406324dcfSchristos 		      && ((section_address + section_size)
816506324dcfSchristos 			  <= (address + view_size)));
816606324dcfSchristos 
816706324dcfSchristos 	  off_t offset = section_address - address;
816806324dcfSchristos 	  view += offset;
816906324dcfSchristos 	  address += offset;
817006324dcfSchristos 	  view_size = section_size;
817106324dcfSchristos 	}
817206324dcfSchristos     }
817306324dcfSchristos 
8174ed0d50c3Schristos   gold::relocate_section<size, big_endian, Aarch64, AArch64_relocate,
8175ed0d50c3Schristos 			 gold::Default_comdat_behavior, Classify_reloc>(
8176ed0d50c3Schristos     relinfo,
8177ed0d50c3Schristos     this,
8178ed0d50c3Schristos     prelocs,
8179ed0d50c3Schristos     reloc_count,
8180ed0d50c3Schristos     output_section,
8181ed0d50c3Schristos     needs_special_offset_handling,
8182ed0d50c3Schristos     view,
8183ed0d50c3Schristos     address,
8184ed0d50c3Schristos     view_size,
8185ed0d50c3Schristos     reloc_symbol_changes);
8186ed0d50c3Schristos }
8187ed0d50c3Schristos 
8188ed0d50c3Schristos // Scan the relocs during a relocatable link.
8189ed0d50c3Schristos 
8190ed0d50c3Schristos template<int size, bool big_endian>
8191ed0d50c3Schristos void
scan_relocatable_relocs(Symbol_table * symtab,Layout * layout,Sized_relobj_file<size,big_endian> * object,unsigned int data_shndx,unsigned int sh_type,const unsigned char * prelocs,size_t reloc_count,Output_section * output_section,bool needs_special_offset_handling,size_t local_symbol_count,const unsigned char * plocal_symbols,Relocatable_relocs * rr)8192ed0d50c3Schristos Target_aarch64<size, big_endian>::scan_relocatable_relocs(
8193ed0d50c3Schristos     Symbol_table* symtab,
8194ed0d50c3Schristos     Layout* layout,
8195ed0d50c3Schristos     Sized_relobj_file<size, big_endian>* object,
8196ed0d50c3Schristos     unsigned int data_shndx,
8197ed0d50c3Schristos     unsigned int sh_type,
8198ed0d50c3Schristos     const unsigned char* prelocs,
8199ed0d50c3Schristos     size_t reloc_count,
8200ed0d50c3Schristos     Output_section* output_section,
8201ed0d50c3Schristos     bool needs_special_offset_handling,
8202ed0d50c3Schristos     size_t local_symbol_count,
8203ed0d50c3Schristos     const unsigned char* plocal_symbols,
8204ed0d50c3Schristos     Relocatable_relocs* rr)
8205ed0d50c3Schristos {
8206ed0d50c3Schristos   typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
8207ed0d50c3Schristos       Classify_reloc;
8208ed0d50c3Schristos   typedef gold::Default_scan_relocatable_relocs<Classify_reloc>
8209ed0d50c3Schristos       Scan_relocatable_relocs;
8210ed0d50c3Schristos 
8211ed0d50c3Schristos   gold_assert(sh_type == elfcpp::SHT_RELA);
8212ed0d50c3Schristos 
8213ed0d50c3Schristos   gold::scan_relocatable_relocs<size, big_endian, Scan_relocatable_relocs>(
8214ed0d50c3Schristos     symtab,
8215ed0d50c3Schristos     layout,
8216ed0d50c3Schristos     object,
8217ed0d50c3Schristos     data_shndx,
8218ed0d50c3Schristos     prelocs,
8219ed0d50c3Schristos     reloc_count,
8220ed0d50c3Schristos     output_section,
8221ed0d50c3Schristos     needs_special_offset_handling,
8222ed0d50c3Schristos     local_symbol_count,
8223ed0d50c3Schristos     plocal_symbols,
8224ed0d50c3Schristos     rr);
8225ed0d50c3Schristos }
8226ed0d50c3Schristos 
8227ed0d50c3Schristos // Scan the relocs for --emit-relocs.
8228ed0d50c3Schristos 
8229ed0d50c3Schristos template<int size, bool big_endian>
8230ed0d50c3Schristos void
emit_relocs_scan(Symbol_table * symtab,Layout * layout,Sized_relobj_file<size,big_endian> * object,unsigned int data_shndx,unsigned int sh_type,const unsigned char * prelocs,size_t reloc_count,Output_section * output_section,bool needs_special_offset_handling,size_t local_symbol_count,const unsigned char * plocal_syms,Relocatable_relocs * rr)8231ed0d50c3Schristos Target_aarch64<size, big_endian>::emit_relocs_scan(
8232ed0d50c3Schristos     Symbol_table* symtab,
8233ed0d50c3Schristos     Layout* layout,
8234ed0d50c3Schristos     Sized_relobj_file<size, big_endian>* object,
8235ed0d50c3Schristos     unsigned int data_shndx,
8236ed0d50c3Schristos     unsigned int sh_type,
8237ed0d50c3Schristos     const unsigned char* prelocs,
8238ed0d50c3Schristos     size_t reloc_count,
8239ed0d50c3Schristos     Output_section* output_section,
8240ed0d50c3Schristos     bool needs_special_offset_handling,
8241ed0d50c3Schristos     size_t local_symbol_count,
8242ed0d50c3Schristos     const unsigned char* plocal_syms,
8243ed0d50c3Schristos     Relocatable_relocs* rr)
8244ed0d50c3Schristos {
8245ed0d50c3Schristos   typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
8246ed0d50c3Schristos       Classify_reloc;
8247ed0d50c3Schristos   typedef gold::Default_emit_relocs_strategy<Classify_reloc>
8248ed0d50c3Schristos       Emit_relocs_strategy;
8249ed0d50c3Schristos 
8250ed0d50c3Schristos   gold_assert(sh_type == elfcpp::SHT_RELA);
8251ed0d50c3Schristos 
8252ed0d50c3Schristos   gold::scan_relocatable_relocs<size, big_endian, Emit_relocs_strategy>(
8253ed0d50c3Schristos     symtab,
8254ed0d50c3Schristos     layout,
8255ed0d50c3Schristos     object,
8256ed0d50c3Schristos     data_shndx,
8257ed0d50c3Schristos     prelocs,
8258ed0d50c3Schristos     reloc_count,
8259ed0d50c3Schristos     output_section,
8260ed0d50c3Schristos     needs_special_offset_handling,
8261ed0d50c3Schristos     local_symbol_count,
8262ed0d50c3Schristos     plocal_syms,
8263ed0d50c3Schristos     rr);
8264ed0d50c3Schristos }
8265ed0d50c3Schristos 
8266ed0d50c3Schristos // Relocate a section during a relocatable link.
8267ed0d50c3Schristos 
8268ed0d50c3Schristos template<int size, bool big_endian>
8269ed0d50c3Schristos void
relocate_relocs(const Relocate_info<size,big_endian> * relinfo,unsigned int sh_type,const unsigned char * prelocs,size_t reloc_count,Output_section * output_section,typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,unsigned char * view,typename elfcpp::Elf_types<size>::Elf_Addr view_address,section_size_type view_size,unsigned char * reloc_view,section_size_type reloc_view_size)8270ed0d50c3Schristos Target_aarch64<size, big_endian>::relocate_relocs(
8271ed0d50c3Schristos     const Relocate_info<size, big_endian>* relinfo,
8272ed0d50c3Schristos     unsigned int sh_type,
8273ed0d50c3Schristos     const unsigned char* prelocs,
8274ed0d50c3Schristos     size_t reloc_count,
8275ed0d50c3Schristos     Output_section* output_section,
8276ed0d50c3Schristos     typename elfcpp::Elf_types<size>::Elf_Off offset_in_output_section,
8277ed0d50c3Schristos     unsigned char* view,
8278ed0d50c3Schristos     typename elfcpp::Elf_types<size>::Elf_Addr view_address,
8279ed0d50c3Schristos     section_size_type view_size,
8280ed0d50c3Schristos     unsigned char* reloc_view,
8281ed0d50c3Schristos     section_size_type reloc_view_size)
8282ed0d50c3Schristos {
8283ed0d50c3Schristos   typedef gold::Default_classify_reloc<elfcpp::SHT_RELA, size, big_endian>
8284ed0d50c3Schristos       Classify_reloc;
8285ed0d50c3Schristos 
8286ed0d50c3Schristos   gold_assert(sh_type == elfcpp::SHT_RELA);
8287ed0d50c3Schristos 
8288ed0d50c3Schristos   gold::relocate_relocs<size, big_endian, Classify_reloc>(
8289ed0d50c3Schristos     relinfo,
8290ed0d50c3Schristos     prelocs,
8291ed0d50c3Schristos     reloc_count,
8292ed0d50c3Schristos     output_section,
8293ed0d50c3Schristos     offset_in_output_section,
8294ed0d50c3Schristos     view,
8295ed0d50c3Schristos     view_address,
8296ed0d50c3Schristos     view_size,
8297ed0d50c3Schristos     reloc_view,
8298ed0d50c3Schristos     reloc_view_size);
8299ed0d50c3Schristos }
8300ed0d50c3Schristos 
8301ed0d50c3Schristos 
8302ed0d50c3Schristos // Return whether this is a 3-insn erratum sequence.
8303ed0d50c3Schristos 
8304ed0d50c3Schristos template<int size, bool big_endian>
8305ed0d50c3Schristos bool
is_erratum_843419_sequence(typename elfcpp::Swap<32,big_endian>::Valtype insn1,typename elfcpp::Swap<32,big_endian>::Valtype insn2,typename elfcpp::Swap<32,big_endian>::Valtype insn3)8306ed0d50c3Schristos Target_aarch64<size, big_endian>::is_erratum_843419_sequence(
8307ed0d50c3Schristos     typename elfcpp::Swap<32,big_endian>::Valtype insn1,
8308ed0d50c3Schristos     typename elfcpp::Swap<32,big_endian>::Valtype insn2,
8309ed0d50c3Schristos     typename elfcpp::Swap<32,big_endian>::Valtype insn3)
8310ed0d50c3Schristos {
8311ed0d50c3Schristos   unsigned rt1, rt2;
8312ed0d50c3Schristos   bool load, pair;
8313ed0d50c3Schristos 
8314ed0d50c3Schristos   // The 2nd insn is a single register load or store; or register pair
8315ed0d50c3Schristos   // store.
8316ed0d50c3Schristos   if (Insn_utilities::aarch64_mem_op_p(insn2, &rt1, &rt2, &pair, &load)
8317ed0d50c3Schristos       && (!pair || (pair && !load)))
8318ed0d50c3Schristos     {
8319ed0d50c3Schristos       // The 3rd insn is a load or store instruction from the "Load/store
8320ed0d50c3Schristos       // register (unsigned immediate)" encoding class, using Rn as the
8321ed0d50c3Schristos       // base address register.
8322ed0d50c3Schristos       if (Insn_utilities::aarch64_ldst_uimm(insn3)
8323ed0d50c3Schristos 	  && (Insn_utilities::aarch64_rn(insn3)
8324ed0d50c3Schristos 	      == Insn_utilities::aarch64_rd(insn1)))
8325ed0d50c3Schristos 	return true;
8326ed0d50c3Schristos     }
8327ed0d50c3Schristos   return false;
8328ed0d50c3Schristos }
8329ed0d50c3Schristos 
8330ed0d50c3Schristos 
8331ed0d50c3Schristos // Return whether this is a 835769 sequence.
8332ed0d50c3Schristos // (Similarly implemented as in elfnn-aarch64.c.)
8333ed0d50c3Schristos 
8334ed0d50c3Schristos template<int size, bool big_endian>
8335ed0d50c3Schristos bool
is_erratum_835769_sequence(typename elfcpp::Swap<32,big_endian>::Valtype insn1,typename elfcpp::Swap<32,big_endian>::Valtype insn2)8336ed0d50c3Schristos Target_aarch64<size, big_endian>::is_erratum_835769_sequence(
8337ed0d50c3Schristos     typename elfcpp::Swap<32,big_endian>::Valtype insn1,
8338ed0d50c3Schristos     typename elfcpp::Swap<32,big_endian>::Valtype insn2)
8339ed0d50c3Schristos {
8340ed0d50c3Schristos   uint32_t rt;
834106324dcfSchristos   uint32_t rt2 = 0;
8342ed0d50c3Schristos   uint32_t rn;
8343ed0d50c3Schristos   uint32_t rm;
8344ed0d50c3Schristos   uint32_t ra;
8345ed0d50c3Schristos   bool pair;
8346ed0d50c3Schristos   bool load;
8347ed0d50c3Schristos 
8348ed0d50c3Schristos   if (Insn_utilities::aarch64_mlxl(insn2)
8349ed0d50c3Schristos       && Insn_utilities::aarch64_mem_op_p (insn1, &rt, &rt2, &pair, &load))
8350ed0d50c3Schristos     {
8351ed0d50c3Schristos       /* Any SIMD memory op is independent of the subsequent MLA
8352ed0d50c3Schristos 	 by definition of the erratum.  */
8353ed0d50c3Schristos       if (Insn_utilities::aarch64_bit(insn1, 26))
8354ed0d50c3Schristos 	return true;
8355ed0d50c3Schristos 
8356ed0d50c3Schristos       /* If not SIMD, check for integer memory ops and MLA relationship.  */
8357ed0d50c3Schristos       rn = Insn_utilities::aarch64_rn(insn2);
8358ed0d50c3Schristos       ra = Insn_utilities::aarch64_ra(insn2);
8359ed0d50c3Schristos       rm = Insn_utilities::aarch64_rm(insn2);
8360ed0d50c3Schristos 
8361ed0d50c3Schristos       /* If this is a load and there's a true(RAW) dependency, we are safe
8362ed0d50c3Schristos 	 and this is not an erratum sequence.  */
8363ed0d50c3Schristos       if (load &&
8364ed0d50c3Schristos 	  (rt == rn || rt == rm || rt == ra
8365ed0d50c3Schristos 	   || (pair && (rt2 == rn || rt2 == rm || rt2 == ra))))
8366ed0d50c3Schristos 	return false;
8367ed0d50c3Schristos 
8368ed0d50c3Schristos       /* We conservatively put out stubs for all other cases (including
8369ed0d50c3Schristos 	 writebacks).  */
8370ed0d50c3Schristos       return true;
8371ed0d50c3Schristos     }
8372ed0d50c3Schristos 
8373ed0d50c3Schristos   return false;
8374ed0d50c3Schristos }
8375ed0d50c3Schristos 
8376ed0d50c3Schristos 
8377ed0d50c3Schristos // Helper method to create erratum stub for ST_E_843419 and ST_E_835769.
8378ed0d50c3Schristos 
8379ed0d50c3Schristos template<int size, bool big_endian>
8380ed0d50c3Schristos void
create_erratum_stub(AArch64_relobj<size,big_endian> * relobj,unsigned int shndx,section_size_type erratum_insn_offset,Address erratum_address,typename Insn_utilities::Insntype erratum_insn,int erratum_type,unsigned int e843419_adrp_offset)8381ed0d50c3Schristos Target_aarch64<size, big_endian>::create_erratum_stub(
8382ed0d50c3Schristos     AArch64_relobj<size, big_endian>* relobj,
8383ed0d50c3Schristos     unsigned int shndx,
8384ed0d50c3Schristos     section_size_type erratum_insn_offset,
8385ed0d50c3Schristos     Address erratum_address,
8386ed0d50c3Schristos     typename Insn_utilities::Insntype erratum_insn,
8387ed0d50c3Schristos     int erratum_type,
8388ed0d50c3Schristos     unsigned int e843419_adrp_offset)
8389ed0d50c3Schristos {
8390ed0d50c3Schristos   gold_assert(erratum_type == ST_E_843419 || erratum_type == ST_E_835769);
8391ed0d50c3Schristos   The_stub_table* stub_table = relobj->stub_table(shndx);
8392ed0d50c3Schristos   gold_assert(stub_table != NULL);
8393ed0d50c3Schristos   if (stub_table->find_erratum_stub(relobj,
8394ed0d50c3Schristos 				    shndx,
8395ed0d50c3Schristos 				    erratum_insn_offset) == NULL)
8396ed0d50c3Schristos     {
8397ed0d50c3Schristos       const int BPI = AArch64_insn_utilities<big_endian>::BYTES_PER_INSN;
8398ed0d50c3Schristos       The_erratum_stub* stub;
8399ed0d50c3Schristos       if (erratum_type == ST_E_835769)
8400ed0d50c3Schristos 	stub = new The_erratum_stub(relobj, erratum_type, shndx,
8401ed0d50c3Schristos 				    erratum_insn_offset);
8402ed0d50c3Schristos       else if (erratum_type == ST_E_843419)
8403ed0d50c3Schristos 	stub = new E843419_stub<size, big_endian>(
8404ed0d50c3Schristos 	    relobj, shndx, erratum_insn_offset, e843419_adrp_offset);
8405ed0d50c3Schristos       else
8406ed0d50c3Schristos 	gold_unreachable();
8407ed0d50c3Schristos       stub->set_erratum_insn(erratum_insn);
8408ed0d50c3Schristos       stub->set_erratum_address(erratum_address);
8409ed0d50c3Schristos       // For erratum ST_E_843419 and ST_E_835769, the destination address is
8410ed0d50c3Schristos       // always the next insn after erratum insn.
8411ed0d50c3Schristos       stub->set_destination_address(erratum_address + BPI);
8412ed0d50c3Schristos       stub_table->add_erratum_stub(stub);
8413ed0d50c3Schristos     }
8414ed0d50c3Schristos }
8415ed0d50c3Schristos 
8416ed0d50c3Schristos 
8417ed0d50c3Schristos // Scan erratum for section SHNDX range [output_address + span_start,
8418ed0d50c3Schristos // output_address + span_end). Note here we do not share the code with
8419ed0d50c3Schristos // scan_erratum_843419_span function, because for 843419 we optimize by only
8420ed0d50c3Schristos // scanning the last few insns of a page, whereas for 835769, we need to scan
8421ed0d50c3Schristos // every insn.
8422ed0d50c3Schristos 
8423ed0d50c3Schristos template<int size, bool big_endian>
8424ed0d50c3Schristos void
scan_erratum_835769_span(AArch64_relobj<size,big_endian> * relobj,unsigned int shndx,const section_size_type span_start,const section_size_type span_end,unsigned char * input_view,Address output_address)8425ed0d50c3Schristos Target_aarch64<size, big_endian>::scan_erratum_835769_span(
8426ed0d50c3Schristos     AArch64_relobj<size, big_endian>*  relobj,
8427ed0d50c3Schristos     unsigned int shndx,
8428ed0d50c3Schristos     const section_size_type span_start,
8429ed0d50c3Schristos     const section_size_type span_end,
8430ed0d50c3Schristos     unsigned char* input_view,
8431ed0d50c3Schristos     Address output_address)
8432ed0d50c3Schristos {
8433ed0d50c3Schristos   typedef typename Insn_utilities::Insntype Insntype;
8434ed0d50c3Schristos 
8435ed0d50c3Schristos   const int BPI = AArch64_insn_utilities<big_endian>::BYTES_PER_INSN;
8436ed0d50c3Schristos 
8437ed0d50c3Schristos   // Adjust output_address and view to the start of span.
8438ed0d50c3Schristos   output_address += span_start;
8439ed0d50c3Schristos   input_view += span_start;
8440ed0d50c3Schristos 
8441ed0d50c3Schristos   section_size_type span_length = span_end - span_start;
8442ed0d50c3Schristos   section_size_type offset = 0;
8443ed0d50c3Schristos   for (offset = 0; offset + BPI < span_length; offset += BPI)
8444ed0d50c3Schristos     {
8445ed0d50c3Schristos       Insntype* ip = reinterpret_cast<Insntype*>(input_view + offset);
8446ed0d50c3Schristos       Insntype insn1 = ip[0];
8447ed0d50c3Schristos       Insntype insn2 = ip[1];
8448ed0d50c3Schristos       if (is_erratum_835769_sequence(insn1, insn2))
8449ed0d50c3Schristos 	{
8450ed0d50c3Schristos 	  Insntype erratum_insn = insn2;
8451ed0d50c3Schristos 	  // "span_start + offset" is the offset for insn1. So for insn2, it is
8452ed0d50c3Schristos 	  // "span_start + offset + BPI".
8453ed0d50c3Schristos 	  section_size_type erratum_insn_offset = span_start + offset + BPI;
8454ed0d50c3Schristos 	  Address erratum_address = output_address + offset + BPI;
8455ed0d50c3Schristos 	  gold_info(_("Erratum 835769 found and fixed at \"%s\", "
8456ed0d50c3Schristos 			 "section %d, offset 0x%08x."),
8457ed0d50c3Schristos 		       relobj->name().c_str(), shndx,
8458ed0d50c3Schristos 		       (unsigned int)(span_start + offset));
8459ed0d50c3Schristos 
8460ed0d50c3Schristos 	  this->create_erratum_stub(relobj, shndx,
8461ed0d50c3Schristos 				    erratum_insn_offset, erratum_address,
8462ed0d50c3Schristos 				    erratum_insn, ST_E_835769);
8463ed0d50c3Schristos 	  offset += BPI;  // Skip mac insn.
8464ed0d50c3Schristos 	}
8465ed0d50c3Schristos     }
8466ed0d50c3Schristos }  // End of "Target_aarch64::scan_erratum_835769_span".
8467ed0d50c3Schristos 
8468ed0d50c3Schristos 
8469ed0d50c3Schristos // Scan erratum for section SHNDX range
8470ed0d50c3Schristos // [output_address + span_start, output_address + span_end).
8471ed0d50c3Schristos 
8472ed0d50c3Schristos template<int size, bool big_endian>
8473ed0d50c3Schristos void
scan_erratum_843419_span(AArch64_relobj<size,big_endian> * relobj,unsigned int shndx,const section_size_type span_start,const section_size_type span_end,unsigned char * input_view,Address output_address)8474ed0d50c3Schristos Target_aarch64<size, big_endian>::scan_erratum_843419_span(
8475ed0d50c3Schristos     AArch64_relobj<size, big_endian>*  relobj,
8476ed0d50c3Schristos     unsigned int shndx,
8477ed0d50c3Schristos     const section_size_type span_start,
8478ed0d50c3Schristos     const section_size_type span_end,
8479ed0d50c3Schristos     unsigned char* input_view,
8480ed0d50c3Schristos     Address output_address)
8481ed0d50c3Schristos {
8482ed0d50c3Schristos   typedef typename Insn_utilities::Insntype Insntype;
8483ed0d50c3Schristos 
8484ed0d50c3Schristos   // Adjust output_address and view to the start of span.
8485ed0d50c3Schristos   output_address += span_start;
8486ed0d50c3Schristos   input_view += span_start;
8487ed0d50c3Schristos 
8488ed0d50c3Schristos   if ((output_address & 0x03) != 0)
8489ed0d50c3Schristos     return;
8490ed0d50c3Schristos 
8491ed0d50c3Schristos   section_size_type offset = 0;
8492ed0d50c3Schristos   section_size_type span_length = span_end - span_start;
8493ed0d50c3Schristos   // The first instruction must be ending at 0xFF8 or 0xFFC.
8494ed0d50c3Schristos   unsigned int page_offset = output_address & 0xFFF;
8495ed0d50c3Schristos   // Make sure starting position, that is "output_address+offset",
8496ed0d50c3Schristos   // starts at page position 0xff8 or 0xffc.
8497ed0d50c3Schristos   if (page_offset < 0xff8)
8498ed0d50c3Schristos     offset = 0xff8 - page_offset;
8499ed0d50c3Schristos   while (offset + 3 * Insn_utilities::BYTES_PER_INSN <= span_length)
8500ed0d50c3Schristos     {
8501ed0d50c3Schristos       Insntype* ip = reinterpret_cast<Insntype*>(input_view + offset);
8502ed0d50c3Schristos       Insntype insn1 = ip[0];
8503ed0d50c3Schristos       if (Insn_utilities::is_adrp(insn1))
8504ed0d50c3Schristos 	{
8505ed0d50c3Schristos 	  Insntype insn2 = ip[1];
8506ed0d50c3Schristos 	  Insntype insn3 = ip[2];
8507ed0d50c3Schristos 	  Insntype erratum_insn;
8508ed0d50c3Schristos 	  unsigned insn_offset;
8509ed0d50c3Schristos 	  bool do_report = false;
8510ed0d50c3Schristos 	  if (is_erratum_843419_sequence(insn1, insn2, insn3))
8511ed0d50c3Schristos 	    {
8512ed0d50c3Schristos 	      do_report = true;
8513ed0d50c3Schristos 	      erratum_insn = insn3;
8514ed0d50c3Schristos 	      insn_offset = 2 * Insn_utilities::BYTES_PER_INSN;
8515ed0d50c3Schristos 	    }
8516ed0d50c3Schristos 	  else if (offset + 4 * Insn_utilities::BYTES_PER_INSN <= span_length)
8517ed0d50c3Schristos 	    {
8518ed0d50c3Schristos 	      // Optionally we can have an insn between ins2 and ins3
8519ed0d50c3Schristos 	      Insntype insn_opt = ip[2];
8520ed0d50c3Schristos 	      // And insn_opt must not be a branch.
8521ed0d50c3Schristos 	      if (!Insn_utilities::aarch64_b(insn_opt)
8522ed0d50c3Schristos 		  && !Insn_utilities::aarch64_bl(insn_opt)
8523ed0d50c3Schristos 		  && !Insn_utilities::aarch64_blr(insn_opt)
8524ed0d50c3Schristos 		  && !Insn_utilities::aarch64_br(insn_opt))
8525ed0d50c3Schristos 		{
8526ed0d50c3Schristos 		  // And insn_opt must not write to dest reg in insn1. However
8527ed0d50c3Schristos 		  // we do a conservative scan, which means we may fix/report
8528ed0d50c3Schristos 		  // more than necessary, but it doesn't hurt.
8529ed0d50c3Schristos 
8530ed0d50c3Schristos 		  Insntype insn4 = ip[3];
8531ed0d50c3Schristos 		  if (is_erratum_843419_sequence(insn1, insn2, insn4))
8532ed0d50c3Schristos 		    {
8533ed0d50c3Schristos 		      do_report = true;
8534ed0d50c3Schristos 		      erratum_insn = insn4;
8535ed0d50c3Schristos 		      insn_offset = 3 * Insn_utilities::BYTES_PER_INSN;
8536ed0d50c3Schristos 		    }
8537ed0d50c3Schristos 		}
8538ed0d50c3Schristos 	    }
8539ed0d50c3Schristos 	  if (do_report)
8540ed0d50c3Schristos 	    {
8541ed0d50c3Schristos 	      unsigned int erratum_insn_offset =
8542ed0d50c3Schristos 		span_start + offset + insn_offset;
8543ed0d50c3Schristos 	      Address erratum_address =
8544ed0d50c3Schristos 		output_address + offset + insn_offset;
8545ed0d50c3Schristos 	      create_erratum_stub(relobj, shndx,
8546ed0d50c3Schristos 				  erratum_insn_offset, erratum_address,
8547ed0d50c3Schristos 				  erratum_insn, ST_E_843419,
8548ed0d50c3Schristos 				  span_start + offset);
8549ed0d50c3Schristos 	    }
8550ed0d50c3Schristos 	}
8551ed0d50c3Schristos 
8552ed0d50c3Schristos       // Advance to next candidate instruction. We only consider instruction
8553ed0d50c3Schristos       // sequences starting at a page offset of 0xff8 or 0xffc.
8554ed0d50c3Schristos       page_offset = (output_address + offset) & 0xfff;
8555ed0d50c3Schristos       if (page_offset == 0xff8)
8556ed0d50c3Schristos 	offset += 4;
8557ed0d50c3Schristos       else  // (page_offset == 0xffc), we move to next page's 0xff8.
8558ed0d50c3Schristos 	offset += 0xffc;
8559ed0d50c3Schristos     }
8560ed0d50c3Schristos }  // End of "Target_aarch64::scan_erratum_843419_span".
8561ed0d50c3Schristos 
8562ed0d50c3Schristos 
8563ed0d50c3Schristos // The selector for aarch64 object files.
8564ed0d50c3Schristos 
8565ed0d50c3Schristos template<int size, bool big_endian>
8566ed0d50c3Schristos class Target_selector_aarch64 : public Target_selector
8567ed0d50c3Schristos {
8568ed0d50c3Schristos  public:
8569ed0d50c3Schristos   Target_selector_aarch64();
8570ed0d50c3Schristos 
8571ed0d50c3Schristos   virtual Target*
do_instantiate_target()8572ed0d50c3Schristos   do_instantiate_target()
8573ed0d50c3Schristos   { return new Target_aarch64<size, big_endian>(); }
8574ed0d50c3Schristos };
8575ed0d50c3Schristos 
8576ed0d50c3Schristos template<>
Target_selector_aarch64()8577ed0d50c3Schristos Target_selector_aarch64<32, true>::Target_selector_aarch64()
8578ed0d50c3Schristos   : Target_selector(elfcpp::EM_AARCH64, 32, true,
8579ed0d50c3Schristos 		    "elf32-bigaarch64", "aarch64_elf32_be_vec")
8580ed0d50c3Schristos { }
8581ed0d50c3Schristos 
8582ed0d50c3Schristos template<>
Target_selector_aarch64()8583ed0d50c3Schristos Target_selector_aarch64<32, false>::Target_selector_aarch64()
8584ed0d50c3Schristos   : Target_selector(elfcpp::EM_AARCH64, 32, false,
8585ed0d50c3Schristos 		    "elf32-littleaarch64", "aarch64_elf32_le_vec")
8586ed0d50c3Schristos { }
8587ed0d50c3Schristos 
8588ed0d50c3Schristos template<>
Target_selector_aarch64()8589ed0d50c3Schristos Target_selector_aarch64<64, true>::Target_selector_aarch64()
8590ed0d50c3Schristos   : Target_selector(elfcpp::EM_AARCH64, 64, true,
8591ed0d50c3Schristos 		    "elf64-bigaarch64", "aarch64_elf64_be_vec")
8592ed0d50c3Schristos { }
8593ed0d50c3Schristos 
8594ed0d50c3Schristos template<>
Target_selector_aarch64()8595ed0d50c3Schristos Target_selector_aarch64<64, false>::Target_selector_aarch64()
8596ed0d50c3Schristos   : Target_selector(elfcpp::EM_AARCH64, 64, false,
8597ed0d50c3Schristos 		    "elf64-littleaarch64", "aarch64_elf64_le_vec")
8598ed0d50c3Schristos { }
8599ed0d50c3Schristos 
8600ed0d50c3Schristos Target_selector_aarch64<32, true> target_selector_aarch64elf32b;
8601ed0d50c3Schristos Target_selector_aarch64<32, false> target_selector_aarch64elf32;
8602ed0d50c3Schristos Target_selector_aarch64<64, true> target_selector_aarch64elfb;
8603ed0d50c3Schristos Target_selector_aarch64<64, false> target_selector_aarch64elf;
8604ed0d50c3Schristos 
8605ed0d50c3Schristos } // End anonymous namespace.
8606