1*fae548d3Szrj // copy-relocs.cc -- handle COPY relocations for gold.
2*fae548d3Szrj 
3*fae548d3Szrj // Copyright (C) 2006-2020 Free Software Foundation, Inc.
4*fae548d3Szrj // Written by Ian Lance Taylor <iant@google.com>.
5*fae548d3Szrj 
6*fae548d3Szrj // This file is part of gold.
7*fae548d3Szrj 
8*fae548d3Szrj // This program is free software; you can redistribute it and/or modify
9*fae548d3Szrj // it under the terms of the GNU General Public License as published by
10*fae548d3Szrj // the Free Software Foundation; either version 3 of the License, or
11*fae548d3Szrj // (at your option) any later version.
12*fae548d3Szrj 
13*fae548d3Szrj // This program is distributed in the hope that it will be useful,
14*fae548d3Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
15*fae548d3Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*fae548d3Szrj // GNU General Public License for more details.
17*fae548d3Szrj 
18*fae548d3Szrj // You should have received a copy of the GNU General Public License
19*fae548d3Szrj // along with this program; if not, write to the Free Software
20*fae548d3Szrj // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21*fae548d3Szrj // MA 02110-1301, USA.
22*fae548d3Szrj 
23*fae548d3Szrj #include "gold.h"
24*fae548d3Szrj 
25*fae548d3Szrj #include "symtab.h"
26*fae548d3Szrj #include "copy-relocs.h"
27*fae548d3Szrj 
28*fae548d3Szrj namespace gold
29*fae548d3Szrj {
30*fae548d3Szrj 
31*fae548d3Szrj // Copy_relocs methods.
32*fae548d3Szrj 
33*fae548d3Szrj // Handle a relocation against a symbol which may force us to generate
34*fae548d3Szrj // a COPY reloc.
35*fae548d3Szrj 
36*fae548d3Szrj template<int sh_type, int size, bool big_endian>
37*fae548d3Szrj void
copy_reloc(Symbol_table * symtab,Layout * layout,Sized_symbol<size> * sym,Sized_relobj_file<size,big_endian> * object,unsigned int shndx,Output_section * output_section,unsigned int r_type,typename elfcpp::Elf_types<size>::Elf_Addr r_offset,typename elfcpp::Elf_types<size>::Elf_Swxword r_addend,Output_data_reloc<sh_type,true,size,big_endian> * reloc_section)38*fae548d3Szrj Copy_relocs<sh_type, size, big_endian>::copy_reloc(
39*fae548d3Szrj     Symbol_table* symtab,
40*fae548d3Szrj     Layout* layout,
41*fae548d3Szrj     Sized_symbol<size>* sym,
42*fae548d3Szrj     Sized_relobj_file<size, big_endian>* object,
43*fae548d3Szrj     unsigned int shndx,
44*fae548d3Szrj     Output_section* output_section,
45*fae548d3Szrj     unsigned int r_type,
46*fae548d3Szrj     typename elfcpp::Elf_types<size>::Elf_Addr r_offset,
47*fae548d3Szrj     typename elfcpp::Elf_types<size>::Elf_Swxword r_addend,
48*fae548d3Szrj     Output_data_reloc<sh_type, true, size, big_endian>* reloc_section)
49*fae548d3Szrj {
50*fae548d3Szrj   if (this->need_copy_reloc(sym, object, shndx))
51*fae548d3Szrj     this->make_copy_reloc(symtab, layout, sym, object, reloc_section);
52*fae548d3Szrj   else
53*fae548d3Szrj     {
54*fae548d3Szrj       // We may not need a COPY relocation.  Save this relocation to
55*fae548d3Szrj       // possibly be emitted later.
56*fae548d3Szrj       this->save(sym, object, shndx, output_section,
57*fae548d3Szrj 		 r_type, r_offset, r_addend);
58*fae548d3Szrj     }
59*fae548d3Szrj }
60*fae548d3Szrj 
61*fae548d3Szrj // Return whether we need a COPY reloc for a relocation against SYM.
62*fae548d3Szrj // The relocation is begin applied to section SHNDX in OBJECT.
63*fae548d3Szrj 
64*fae548d3Szrj template<int sh_type, int size, bool big_endian>
65*fae548d3Szrj bool
need_copy_reloc(Sized_symbol<size> * sym,Sized_relobj_file<size,big_endian> * object,unsigned int shndx) const66*fae548d3Szrj Copy_relocs<sh_type, size, big_endian>::need_copy_reloc(
67*fae548d3Szrj     Sized_symbol<size>* sym,
68*fae548d3Szrj     Sized_relobj_file<size, big_endian>* object,
69*fae548d3Szrj     unsigned int shndx) const
70*fae548d3Szrj {
71*fae548d3Szrj   if (!parameters->options().copyreloc())
72*fae548d3Szrj     return false;
73*fae548d3Szrj 
74*fae548d3Szrj   if (sym->symsize() == 0)
75*fae548d3Szrj     return false;
76*fae548d3Szrj 
77*fae548d3Szrj   // If this is a readonly section, then we need a COPY reloc.
78*fae548d3Szrj   // Otherwise we can use a dynamic reloc.  Note that calling
79*fae548d3Szrj   // section_flags here can be slow, as the information is not cached;
80*fae548d3Szrj   // fortunately we shouldn't see too many potential COPY relocs.
81*fae548d3Szrj   if ((object->section_flags(shndx) & elfcpp::SHF_WRITE) == 0)
82*fae548d3Szrj     return true;
83*fae548d3Szrj 
84*fae548d3Szrj   return false;
85*fae548d3Szrj }
86*fae548d3Szrj 
87*fae548d3Szrj // Emit a COPY relocation for SYM.
88*fae548d3Szrj 
89*fae548d3Szrj template<int sh_type, int size, bool big_endian>
90*fae548d3Szrj void
emit_copy_reloc(Symbol_table * symtab,Sized_symbol<size> * sym,Output_data * posd,off_t offset,Output_data_reloc<sh_type,true,size,big_endian> * reloc_section)91*fae548d3Szrj Copy_relocs<sh_type, size, big_endian>::emit_copy_reloc(
92*fae548d3Szrj     Symbol_table* symtab,
93*fae548d3Szrj     Sized_symbol<size>* sym,
94*fae548d3Szrj     Output_data* posd,
95*fae548d3Szrj     off_t offset,
96*fae548d3Szrj     Output_data_reloc<sh_type, true, size, big_endian>* reloc_section)
97*fae548d3Szrj {
98*fae548d3Szrj   // Define the symbol as being copied.
99*fae548d3Szrj   symtab->define_with_copy_reloc(sym, posd, offset);
100*fae548d3Szrj 
101*fae548d3Szrj   // Add the COPY relocation to the dynamic reloc section.
102*fae548d3Szrj   reloc_section->add_global_generic(sym, this->copy_reloc_type_, posd,
103*fae548d3Szrj 				    offset, 0);
104*fae548d3Szrj }
105*fae548d3Szrj 
106*fae548d3Szrj // Make a COPY relocation for SYM and emit it.
107*fae548d3Szrj 
108*fae548d3Szrj template<int sh_type, int size, bool big_endian>
109*fae548d3Szrj void
make_copy_reloc(Symbol_table * symtab,Layout * layout,Sized_symbol<size> * sym,Sized_relobj_file<size,big_endian> * object,Output_data_reloc<sh_type,true,size,big_endian> * reloc_section)110*fae548d3Szrj Copy_relocs<sh_type, size, big_endian>::make_copy_reloc(
111*fae548d3Szrj     Symbol_table* symtab,
112*fae548d3Szrj     Layout* layout,
113*fae548d3Szrj     Sized_symbol<size>* sym,
114*fae548d3Szrj     Sized_relobj_file<size, big_endian>* object,
115*fae548d3Szrj     Output_data_reloc<sh_type, true, size, big_endian>* reloc_section)
116*fae548d3Szrj {
117*fae548d3Szrj   // We should not be here if -z nocopyreloc is given.
118*fae548d3Szrj   gold_assert(parameters->options().copyreloc());
119*fae548d3Szrj 
120*fae548d3Szrj   gold_assert(sym->is_from_dynobj());
121*fae548d3Szrj 
122*fae548d3Szrj   // The symbol must not have protected visibility.
123*fae548d3Szrj   if (sym->is_protected())
124*fae548d3Szrj     {
125*fae548d3Szrj       gold_error(_("%s: cannot make copy relocation for "
126*fae548d3Szrj 		   "protected symbol '%s', defined in %s"),
127*fae548d3Szrj 		 object->name().c_str(),
128*fae548d3Szrj 		 sym->name(),
129*fae548d3Szrj 		 sym->object()->name().c_str());
130*fae548d3Szrj     }
131*fae548d3Szrj 
132*fae548d3Szrj   typename elfcpp::Elf_types<size>::Elf_WXword symsize = sym->symsize();
133*fae548d3Szrj 
134*fae548d3Szrj   // There is no defined way to determine the required alignment of
135*fae548d3Szrj   // the symbol.  We know that the symbol is defined in a dynamic
136*fae548d3Szrj   // object.  We start with the alignment of the section in which it
137*fae548d3Szrj   // is defined; presumably we do not require an alignment larger than
138*fae548d3Szrj   // that.  Then we reduce that alignment if the symbol is not aligned
139*fae548d3Szrj   // within the section.
140*fae548d3Szrj   bool is_ordinary;
141*fae548d3Szrj   unsigned int shndx = sym->shndx(&is_ordinary);
142*fae548d3Szrj   gold_assert(is_ordinary);
143*fae548d3Szrj   typename elfcpp::Elf_types<size>::Elf_WXword addralign;
144*fae548d3Szrj   bool is_readonly = false;
145*fae548d3Szrj 
146*fae548d3Szrj   {
147*fae548d3Szrj     // Lock the object so we can read from it.  This is only called
148*fae548d3Szrj     // single-threaded from scan_relocs, so it is OK to lock.
149*fae548d3Szrj     // Unfortunately we have no way to pass in a Task token.
150*fae548d3Szrj     const Task* dummy_task = reinterpret_cast<const Task*>(-1);
151*fae548d3Szrj     Object* obj = sym->object();
152*fae548d3Szrj     Task_lock_obj<Object> tl(dummy_task, obj);
153*fae548d3Szrj     addralign = obj->section_addralign(shndx);
154*fae548d3Szrj     if (parameters->options().relro())
155*fae548d3Szrj       {
156*fae548d3Szrj 	if ((obj->section_flags(shndx) & elfcpp::SHF_WRITE) == 0)
157*fae548d3Szrj 	  is_readonly = true;
158*fae548d3Szrj 	else
159*fae548d3Szrj 	  {
160*fae548d3Szrj 	    // Symbols in .data.rel.ro should also be treated as read-only.
161*fae548d3Szrj 	    if (obj->section_name(shndx) == ".data.rel.ro")
162*fae548d3Szrj 	      is_readonly = true;
163*fae548d3Szrj 	  }
164*fae548d3Szrj       }
165*fae548d3Szrj   }
166*fae548d3Szrj 
167*fae548d3Szrj   typename Sized_symbol<size>::Value_type value = sym->value();
168*fae548d3Szrj   while ((value & (addralign - 1)) != 0)
169*fae548d3Szrj     addralign >>= 1;
170*fae548d3Szrj 
171*fae548d3Szrj   // Mark the dynamic object as needed for the --as-needed option.
172*fae548d3Szrj   sym->object()->set_is_needed();
173*fae548d3Szrj 
174*fae548d3Szrj   Output_data_space* dynbss;
175*fae548d3Szrj 
176*fae548d3Szrj   if (is_readonly)
177*fae548d3Szrj     {
178*fae548d3Szrj       if (this->dynrelro_ == NULL)
179*fae548d3Szrj 	{
180*fae548d3Szrj 	  this->dynrelro_ = new Output_data_space(addralign, "** dynrelro");
181*fae548d3Szrj 	  layout->add_output_section_data(".data.rel.ro",
182*fae548d3Szrj 					  elfcpp::SHT_PROGBITS,
183*fae548d3Szrj 					  elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
184*fae548d3Szrj 					  this->dynrelro_, ORDER_RELRO, false);
185*fae548d3Szrj 	}
186*fae548d3Szrj       dynbss = this->dynrelro_;
187*fae548d3Szrj     }
188*fae548d3Szrj   else
189*fae548d3Szrj     {
190*fae548d3Szrj       if (this->dynbss_ == NULL)
191*fae548d3Szrj 	{
192*fae548d3Szrj 	  this->dynbss_ = new Output_data_space(addralign, "** dynbss");
193*fae548d3Szrj 	  layout->add_output_section_data(".bss",
194*fae548d3Szrj 					  elfcpp::SHT_NOBITS,
195*fae548d3Szrj 					  elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
196*fae548d3Szrj 					  this->dynbss_, ORDER_BSS, false);
197*fae548d3Szrj 	}
198*fae548d3Szrj       dynbss = this->dynbss_;
199*fae548d3Szrj     }
200*fae548d3Szrj 
201*fae548d3Szrj   if (addralign > dynbss->addralign())
202*fae548d3Szrj     dynbss->set_space_alignment(addralign);
203*fae548d3Szrj 
204*fae548d3Szrj   section_size_type dynbss_size =
205*fae548d3Szrj     convert_to_section_size_type(dynbss->current_data_size());
206*fae548d3Szrj   dynbss_size = align_address(dynbss_size, addralign);
207*fae548d3Szrj   section_size_type offset = dynbss_size;
208*fae548d3Szrj   dynbss->set_current_data_size(dynbss_size + symsize);
209*fae548d3Szrj 
210*fae548d3Szrj   this->emit_copy_reloc(symtab, sym, dynbss, offset, reloc_section);
211*fae548d3Szrj }
212*fae548d3Szrj 
213*fae548d3Szrj // Save a relocation to possibly be emitted later.
214*fae548d3Szrj 
215*fae548d3Szrj template<int sh_type, int size, bool big_endian>
216*fae548d3Szrj void
save(Symbol * sym,Sized_relobj_file<size,big_endian> * object,unsigned int shndx,Output_section * output_section,unsigned int r_type,typename elfcpp::Elf_types<size>::Elf_Addr r_offset,typename elfcpp::Elf_types<size>::Elf_Swxword r_addend)217*fae548d3Szrj Copy_relocs<sh_type, size, big_endian>::save(
218*fae548d3Szrj     Symbol* sym,
219*fae548d3Szrj     Sized_relobj_file<size, big_endian>* object,
220*fae548d3Szrj     unsigned int shndx,
221*fae548d3Szrj     Output_section* output_section,
222*fae548d3Szrj     unsigned int r_type,
223*fae548d3Szrj     typename elfcpp::Elf_types<size>::Elf_Addr r_offset,
224*fae548d3Szrj     typename elfcpp::Elf_types<size>::Elf_Swxword r_addend)
225*fae548d3Szrj {
226*fae548d3Szrj   this->entries_.push_back(Copy_reloc_entry(sym, r_type, object, shndx,
227*fae548d3Szrj 					    output_section, r_offset,
228*fae548d3Szrj 					    r_addend));
229*fae548d3Szrj }
230*fae548d3Szrj 
231*fae548d3Szrj // Emit any saved relocs.
232*fae548d3Szrj 
233*fae548d3Szrj template<int sh_type, int size, bool big_endian>
234*fae548d3Szrj void
emit(Output_data_reloc<sh_type,true,size,big_endian> * reloc_section)235*fae548d3Szrj Copy_relocs<sh_type, size, big_endian>::emit(
236*fae548d3Szrj     Output_data_reloc<sh_type, true, size, big_endian>* reloc_section)
237*fae548d3Szrj {
238*fae548d3Szrj   for (typename Copy_reloc_entries::iterator p = this->entries_.begin();
239*fae548d3Szrj        p != this->entries_.end();
240*fae548d3Szrj        ++p)
241*fae548d3Szrj     {
242*fae548d3Szrj       Copy_reloc_entry& entry = *p;
243*fae548d3Szrj 
244*fae548d3Szrj       // If the symbol is no longer defined in a dynamic object, then we
245*fae548d3Szrj       // emitted a COPY relocation, and we do not want to emit this
246*fae548d3Szrj       // dynamic relocation.
247*fae548d3Szrj       if (entry.sym_->is_from_dynobj())
248*fae548d3Szrj         reloc_section->add_global_generic(entry.sym_, entry.reloc_type_,
249*fae548d3Szrj                                           entry.output_section_, entry.relobj_,
250*fae548d3Szrj                                           entry.shndx_, entry.address_,
251*fae548d3Szrj                                           entry.addend_);
252*fae548d3Szrj     }
253*fae548d3Szrj 
254*fae548d3Szrj   // We no longer need the saved information.
255*fae548d3Szrj   this->entries_.clear();
256*fae548d3Szrj }
257*fae548d3Szrj 
258*fae548d3Szrj // Instantiate the templates we need.
259*fae548d3Szrj 
260*fae548d3Szrj #ifdef HAVE_TARGET_32_LITTLE
261*fae548d3Szrj template
262*fae548d3Szrj class Copy_relocs<elfcpp::SHT_REL, 32, false>;
263*fae548d3Szrj 
264*fae548d3Szrj template
265*fae548d3Szrj class Copy_relocs<elfcpp::SHT_RELA, 32, false>;
266*fae548d3Szrj #endif
267*fae548d3Szrj 
268*fae548d3Szrj #ifdef HAVE_TARGET_32_BIG
269*fae548d3Szrj template
270*fae548d3Szrj class Copy_relocs<elfcpp::SHT_REL, 32, true>;
271*fae548d3Szrj 
272*fae548d3Szrj template
273*fae548d3Szrj class Copy_relocs<elfcpp::SHT_RELA, 32, true>;
274*fae548d3Szrj #endif
275*fae548d3Szrj 
276*fae548d3Szrj #ifdef HAVE_TARGET_64_LITTLE
277*fae548d3Szrj template
278*fae548d3Szrj class Copy_relocs<elfcpp::SHT_REL, 64, false>;
279*fae548d3Szrj 
280*fae548d3Szrj template
281*fae548d3Szrj class Copy_relocs<elfcpp::SHT_RELA, 64, false>;
282*fae548d3Szrj #endif
283*fae548d3Szrj 
284*fae548d3Szrj #ifdef HAVE_TARGET_64_BIG
285*fae548d3Szrj template
286*fae548d3Szrj class Copy_relocs<elfcpp::SHT_REL, 64, true>;
287*fae548d3Szrj 
288*fae548d3Szrj template
289*fae548d3Szrj class Copy_relocs<elfcpp::SHT_RELA, 64, true>;
290*fae548d3Szrj #endif
291*fae548d3Szrj 
292*fae548d3Szrj } // End namespace gold.
293