xref: /dragonfly/contrib/binutils-2.34/gold/gc.h (revision fae548d3)
1*fae548d3Szrj // gc.h -- garbage collection of unused sections
2*fae548d3Szrj 
3*fae548d3Szrj // Copyright (C) 2009-2020 Free Software Foundation, Inc.
4*fae548d3Szrj // Written by Sriraman Tallam <tmsriram@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 #ifndef GOLD_GC_H
24*fae548d3Szrj #define GOLD_GC_H
25*fae548d3Szrj 
26*fae548d3Szrj #include <vector>
27*fae548d3Szrj 
28*fae548d3Szrj #include "elfcpp.h"
29*fae548d3Szrj #include "symtab.h"
30*fae548d3Szrj #include "object.h"
31*fae548d3Szrj #include "icf.h"
32*fae548d3Szrj 
33*fae548d3Szrj namespace gold
34*fae548d3Szrj {
35*fae548d3Szrj 
36*fae548d3Szrj class Object;
37*fae548d3Szrj 
38*fae548d3Szrj template<int size, bool big_endian>
39*fae548d3Szrj class Sized_relobj_file;
40*fae548d3Szrj 
41*fae548d3Szrj class Output_section;
42*fae548d3Szrj class General_options;
43*fae548d3Szrj class Layout;
44*fae548d3Szrj 
45*fae548d3Szrj class Garbage_collection
46*fae548d3Szrj {
47*fae548d3Szrj  public:
48*fae548d3Szrj 
49*fae548d3Szrj   typedef Unordered_set<Section_id, Section_id_hash> Sections_reachable;
50*fae548d3Szrj   typedef std::map<Section_id, Sections_reachable> Section_ref;
51*fae548d3Szrj   typedef std::vector<Section_id> Worklist_type;
52*fae548d3Szrj   // This maps the name of the section which can be represented as a C
53*fae548d3Szrj   // identifier (cident) to the list of sections that have that name.
54*fae548d3Szrj   // Different object files can have cident sections with the same name.
55*fae548d3Szrj   typedef std::map<std::string, Sections_reachable> Cident_section_map;
56*fae548d3Szrj 
Garbage_collection()57*fae548d3Szrj   Garbage_collection()
58*fae548d3Szrj   : is_worklist_ready_(false)
59*fae548d3Szrj   { }
60*fae548d3Szrj 
61*fae548d3Szrj   // Accessor methods for the private members.
62*fae548d3Szrj 
63*fae548d3Szrj   Sections_reachable&
referenced_list()64*fae548d3Szrj   referenced_list()
65*fae548d3Szrj   { return referenced_list_; }
66*fae548d3Szrj 
67*fae548d3Szrj   Section_ref&
section_reloc_map()68*fae548d3Szrj   section_reloc_map()
69*fae548d3Szrj   { return this->section_reloc_map_; }
70*fae548d3Szrj 
71*fae548d3Szrj   Worklist_type&
worklist()72*fae548d3Szrj   worklist()
73*fae548d3Szrj   { return this->work_list_; }
74*fae548d3Szrj 
75*fae548d3Szrj   bool
is_worklist_ready()76*fae548d3Szrj   is_worklist_ready()
77*fae548d3Szrj   { return this->is_worklist_ready_; }
78*fae548d3Szrj 
79*fae548d3Szrj   void
worklist_ready()80*fae548d3Szrj   worklist_ready()
81*fae548d3Szrj   { this->is_worklist_ready_ = true; }
82*fae548d3Szrj 
83*fae548d3Szrj   void
84*fae548d3Szrj   do_transitive_closure();
85*fae548d3Szrj 
86*fae548d3Szrj   bool
is_section_garbage(Relobj * obj,unsigned int shndx)87*fae548d3Szrj   is_section_garbage(Relobj* obj, unsigned int shndx)
88*fae548d3Szrj   { return (this->referenced_list().find(Section_id(obj, shndx))
89*fae548d3Szrj             == this->referenced_list().end()); }
90*fae548d3Szrj 
91*fae548d3Szrj   Cident_section_map*
cident_sections()92*fae548d3Szrj   cident_sections()
93*fae548d3Szrj   { return &cident_sections_; }
94*fae548d3Szrj 
95*fae548d3Szrj   void
add_cident_section(std::string section_name,Section_id secn)96*fae548d3Szrj   add_cident_section(std::string section_name,
97*fae548d3Szrj 		     Section_id secn)
98*fae548d3Szrj   { this->cident_sections_[section_name].insert(secn); }
99*fae548d3Szrj 
100*fae548d3Szrj   // Add a reference from the SRC_SHNDX-th section of SRC_OBJECT to
101*fae548d3Szrj   // DST_SHNDX-th section of DST_OBJECT.
102*fae548d3Szrj   void
add_reference(Relobj * src_object,unsigned int src_shndx,Relobj * dst_object,unsigned int dst_shndx)103*fae548d3Szrj   add_reference(Relobj* src_object, unsigned int src_shndx,
104*fae548d3Szrj 		Relobj* dst_object, unsigned int dst_shndx)
105*fae548d3Szrj   {
106*fae548d3Szrj     Section_id src_id(src_object, src_shndx);
107*fae548d3Szrj     Section_id dst_id(dst_object, dst_shndx);
108*fae548d3Szrj     Sections_reachable& reachable = this->section_reloc_map_[src_id];
109*fae548d3Szrj     reachable.insert(dst_id);
110*fae548d3Szrj   }
111*fae548d3Szrj 
112*fae548d3Szrj  private:
113*fae548d3Szrj 
114*fae548d3Szrj   Worklist_type work_list_;
115*fae548d3Szrj   bool is_worklist_ready_;
116*fae548d3Szrj   Section_ref section_reloc_map_;
117*fae548d3Szrj   Sections_reachable referenced_list_;
118*fae548d3Szrj   Cident_section_map cident_sections_;
119*fae548d3Szrj };
120*fae548d3Szrj 
121*fae548d3Szrj // Data to pass between successive invocations of do_layout
122*fae548d3Szrj // in object.cc while garbage collecting.  This data structure
123*fae548d3Szrj // is filled by using the data from Read_symbols_data.
124*fae548d3Szrj 
125*fae548d3Szrj struct Symbols_data
126*fae548d3Szrj {
127*fae548d3Szrj   // Section headers.
128*fae548d3Szrj   unsigned char* section_headers_data;
129*fae548d3Szrj   // Section names.
130*fae548d3Szrj   unsigned char* section_names_data;
131*fae548d3Szrj   // Size of section name data in bytes.
132*fae548d3Szrj   section_size_type section_names_size;
133*fae548d3Szrj   // Symbol data.
134*fae548d3Szrj   unsigned char* symbols_data;
135*fae548d3Szrj   // Size of symbol data in bytes.
136*fae548d3Szrj   section_size_type symbols_size;
137*fae548d3Szrj   // Offset of external symbols within symbol data.  This structure
138*fae548d3Szrj   // sometimes contains only external symbols, in which case this will
139*fae548d3Szrj   // be zero.  Sometimes it contains all symbols.
140*fae548d3Szrj   section_offset_type external_symbols_offset;
141*fae548d3Szrj   // Symbol names.
142*fae548d3Szrj   unsigned char* symbol_names_data;
143*fae548d3Szrj   // Size of symbol name data in bytes.
144*fae548d3Szrj   section_size_type symbol_names_size;
145*fae548d3Szrj };
146*fae548d3Szrj 
147*fae548d3Szrj // Relocations of type SHT_REL store the addend value in their bytes.
148*fae548d3Szrj // This function returns the size of the embedded addend which is
149*fae548d3Szrj // nothing but the size of the relocation.
150*fae548d3Szrj 
151*fae548d3Szrj template<typename Classify_reloc>
152*fae548d3Szrj inline unsigned int
get_embedded_addend_size(int r_type,Relobj * obj)153*fae548d3Szrj get_embedded_addend_size(int r_type, Relobj* obj)
154*fae548d3Szrj {
155*fae548d3Szrj   if (Classify_reloc::sh_type == elfcpp::SHT_REL)
156*fae548d3Szrj     return Classify_reloc::get_size_for_reloc(r_type, obj);
157*fae548d3Szrj   return 0;
158*fae548d3Szrj }
159*fae548d3Szrj 
160*fae548d3Szrj // This function implements the generic part of reloc
161*fae548d3Szrj // processing to map a section to all the sections it
162*fae548d3Szrj // references through relocs.  It is called only during
163*fae548d3Szrj // garbage collection (--gc-sections) and identical code
164*fae548d3Szrj // folding (--icf).
165*fae548d3Szrj 
166*fae548d3Szrj template<int size, bool big_endian, typename Target_type,
167*fae548d3Szrj 	 typename Scan, typename Classify_reloc>
168*fae548d3Szrj inline void
gc_process_relocs(Symbol_table * symtab,Layout *,Target_type * target,Sized_relobj_file<size,big_endian> * src_obj,unsigned int src_indx,const unsigned char * prelocs,size_t reloc_count,Output_section *,bool,size_t local_count,const unsigned char * plocal_syms)169*fae548d3Szrj gc_process_relocs(
170*fae548d3Szrj     Symbol_table* symtab,
171*fae548d3Szrj     Layout*,
172*fae548d3Szrj     Target_type* target,
173*fae548d3Szrj     Sized_relobj_file<size, big_endian>* src_obj,
174*fae548d3Szrj     unsigned int src_indx,
175*fae548d3Szrj     const unsigned char* prelocs,
176*fae548d3Szrj     size_t reloc_count,
177*fae548d3Szrj     Output_section*,
178*fae548d3Szrj     bool,
179*fae548d3Szrj     size_t local_count,
180*fae548d3Szrj     const unsigned char* plocal_syms)
181*fae548d3Szrj {
182*fae548d3Szrj   Scan scan;
183*fae548d3Szrj 
184*fae548d3Szrj   typedef typename Classify_reloc::Reltype Reltype;
185*fae548d3Szrj   const int reloc_size = Classify_reloc::reloc_size;
186*fae548d3Szrj   const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
187*fae548d3Szrj 
188*fae548d3Szrj   Icf::Sections_reachable_info* secvec = NULL;
189*fae548d3Szrj   Icf::Symbol_info* symvec = NULL;
190*fae548d3Szrj   Icf::Addend_info* addendvec = NULL;
191*fae548d3Szrj   Icf::Offset_info* offsetvec = NULL;
192*fae548d3Szrj   Icf::Reloc_addend_size_info* reloc_addend_size_vec = NULL;
193*fae548d3Szrj   bool is_icf_tracked = false;
194*fae548d3Szrj   const char* cident_section_name = NULL;
195*fae548d3Szrj 
196*fae548d3Szrj   std::string src_section_name = (parameters->options().icf_enabled()
197*fae548d3Szrj                                   ? src_obj->section_name(src_indx)
198*fae548d3Szrj                                   : "");
199*fae548d3Szrj 
200*fae548d3Szrj   bool check_section_for_function_pointers = false;
201*fae548d3Szrj 
202*fae548d3Szrj   if (parameters->options().icf_enabled()
203*fae548d3Szrj       && (is_section_foldable_candidate(src_section_name)
204*fae548d3Szrj           || is_prefix_of(".eh_frame", src_section_name.c_str())))
205*fae548d3Szrj     {
206*fae548d3Szrj       is_icf_tracked = true;
207*fae548d3Szrj       Section_id src_id(src_obj, src_indx);
208*fae548d3Szrj       Icf::Reloc_info* reloc_info =
209*fae548d3Szrj         &symtab->icf()->reloc_info_list()[src_id];
210*fae548d3Szrj       secvec = &reloc_info->section_info;
211*fae548d3Szrj       symvec = &reloc_info->symbol_info;
212*fae548d3Szrj       addendvec = &reloc_info->addend_info;
213*fae548d3Szrj       offsetvec = &reloc_info->offset_info;
214*fae548d3Szrj       reloc_addend_size_vec = &reloc_info->reloc_addend_size_info;
215*fae548d3Szrj     }
216*fae548d3Szrj 
217*fae548d3Szrj   check_section_for_function_pointers =
218*fae548d3Szrj     symtab->icf()->check_section_for_function_pointers(src_section_name,
219*fae548d3Szrj                                                        target);
220*fae548d3Szrj 
221*fae548d3Szrj   for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
222*fae548d3Szrj     {
223*fae548d3Szrj       Reltype reloc(prelocs);
224*fae548d3Szrj       unsigned int r_sym = Classify_reloc::get_r_sym(&reloc);
225*fae548d3Szrj       unsigned int r_type = Classify_reloc::get_r_type(&reloc);
226*fae548d3Szrj       typename elfcpp::Elf_types<size>::Elf_Swxword addend =
227*fae548d3Szrj 	  Classify_reloc::get_r_addend(&reloc);
228*fae548d3Szrj       Relobj* dst_obj;
229*fae548d3Szrj       unsigned int dst_indx;
230*fae548d3Szrj       typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
231*fae548d3Szrj       Address dst_off;
232*fae548d3Szrj 
233*fae548d3Szrj       if (r_sym < local_count)
234*fae548d3Szrj         {
235*fae548d3Szrj           gold_assert(plocal_syms != NULL);
236*fae548d3Szrj           typename elfcpp::Sym<size, big_endian> lsym(plocal_syms
237*fae548d3Szrj                                                       + r_sym * sym_size);
238*fae548d3Szrj 	  dst_indx = lsym.get_st_shndx();
239*fae548d3Szrj           bool is_ordinary;
240*fae548d3Szrj 	  dst_indx = src_obj->adjust_sym_shndx(r_sym, dst_indx, &is_ordinary);
241*fae548d3Szrj           dst_obj = src_obj;
242*fae548d3Szrj 	  dst_off = lsym.get_st_value() + addend;
243*fae548d3Szrj 
244*fae548d3Szrj           if (is_icf_tracked)
245*fae548d3Szrj             {
246*fae548d3Szrj 	      Address symvalue = dst_off - addend;
247*fae548d3Szrj 	      if (is_ordinary)
248*fae548d3Szrj 		(*secvec).push_back(Section_id(src_obj, dst_indx));
249*fae548d3Szrj 	      else
250*fae548d3Szrj                 (*secvec).push_back(Section_id(NULL, 0));
251*fae548d3Szrj               // If the target of the relocation is an STT_SECTION symbol,
252*fae548d3Szrj               // make a note of that by storing -1 in the symbol vector.
253*fae548d3Szrj               if (lsym.get_st_type() == elfcpp::STT_SECTION)
254*fae548d3Szrj 		(*symvec).push_back(reinterpret_cast<Symbol*>(-1));
255*fae548d3Szrj 	      else
256*fae548d3Szrj 		(*symvec).push_back(NULL);
257*fae548d3Szrj 	      (*addendvec).push_back(std::make_pair(
258*fae548d3Szrj 					static_cast<long long>(symvalue),
259*fae548d3Szrj 					static_cast<long long>(addend)));
260*fae548d3Szrj               uint64_t reloc_offset =
261*fae548d3Szrj                 convert_to_section_size_type(reloc.get_r_offset());
262*fae548d3Szrj 	      (*offsetvec).push_back(reloc_offset);
263*fae548d3Szrj               (*reloc_addend_size_vec).push_back(
264*fae548d3Szrj                 get_embedded_addend_size<Classify_reloc>(r_type, src_obj));
265*fae548d3Szrj             }
266*fae548d3Szrj 
267*fae548d3Szrj 	  // When doing safe folding, check to see if this relocation is that
268*fae548d3Szrj 	  // of a function pointer being taken.
269*fae548d3Szrj 	  if (is_ordinary
270*fae548d3Szrj 	      && check_section_for_function_pointers
271*fae548d3Szrj               && lsym.get_st_type() != elfcpp::STT_OBJECT
272*fae548d3Szrj  	      && scan.local_reloc_may_be_function_pointer(symtab, NULL, target,
273*fae548d3Szrj 							  src_obj, src_indx,
274*fae548d3Szrj 			                       		  NULL, reloc, r_type,
275*fae548d3Szrj 							  lsym))
276*fae548d3Szrj             symtab->icf()->set_section_has_function_pointers(
277*fae548d3Szrj               src_obj, lsym.get_st_shndx());
278*fae548d3Szrj 
279*fae548d3Szrj           if (!is_ordinary || dst_indx == src_indx)
280*fae548d3Szrj             continue;
281*fae548d3Szrj         }
282*fae548d3Szrj       else
283*fae548d3Szrj         {
284*fae548d3Szrj           Symbol* gsym = src_obj->global_symbol(r_sym);
285*fae548d3Szrj           gold_assert(gsym != NULL);
286*fae548d3Szrj           if (gsym->is_forwarder())
287*fae548d3Szrj             gsym = symtab->resolve_forwards(gsym);
288*fae548d3Szrj 
289*fae548d3Szrj           dst_obj = NULL;
290*fae548d3Szrj           dst_indx = 0;
291*fae548d3Szrj           bool is_ordinary = false;
292*fae548d3Szrj           if (gsym->source() == Symbol::FROM_OBJECT
293*fae548d3Szrj 	      && !gsym->object()->is_dynamic())
294*fae548d3Szrj             {
295*fae548d3Szrj               dst_obj = static_cast<Relobj*>(gsym->object());
296*fae548d3Szrj               dst_indx = gsym->shndx(&is_ordinary);
297*fae548d3Szrj             }
298*fae548d3Szrj 	  dst_off = static_cast<const Sized_symbol<size>*>(gsym)->value();
299*fae548d3Szrj 	  dst_off += addend;
300*fae548d3Szrj 
301*fae548d3Szrj 	  // When doing safe folding, check to see if this relocation is that
302*fae548d3Szrj 	  // of a function pointer being taken.
303*fae548d3Szrj 	  if (gsym->source() == Symbol::FROM_OBJECT
304*fae548d3Szrj               && gsym->type() == elfcpp::STT_FUNC
305*fae548d3Szrj               && check_section_for_function_pointers
306*fae548d3Szrj               && dst_obj != NULL
307*fae548d3Szrj               && (!is_ordinary
308*fae548d3Szrj                   || scan.global_reloc_may_be_function_pointer(
309*fae548d3Szrj                        symtab, NULL, target, src_obj, src_indx, NULL, reloc,
310*fae548d3Szrj                        r_type, gsym)))
311*fae548d3Szrj             symtab->icf()->set_section_has_function_pointers(dst_obj, dst_indx);
312*fae548d3Szrj 
313*fae548d3Szrj           // If the symbol name matches '__start_XXX' then the section with
314*fae548d3Szrj           // the C identifier like name 'XXX' should not be garbage collected.
315*fae548d3Szrj           // A similar treatment to symbols with the name '__stop_XXX'.
316*fae548d3Szrj           if (is_prefix_of(cident_section_start_prefix, gsym->name()))
317*fae548d3Szrj             {
318*fae548d3Szrj               cident_section_name = (gsym->name()
319*fae548d3Szrj                                      + strlen(cident_section_start_prefix));
320*fae548d3Szrj             }
321*fae548d3Szrj           else if (is_prefix_of(cident_section_stop_prefix, gsym->name()))
322*fae548d3Szrj             {
323*fae548d3Szrj               cident_section_name = (gsym->name()
324*fae548d3Szrj                                      + strlen(cident_section_stop_prefix));
325*fae548d3Szrj             }
326*fae548d3Szrj           if (is_icf_tracked)
327*fae548d3Szrj             {
328*fae548d3Szrj 	      Address symvalue = dst_off - addend;
329*fae548d3Szrj               if (is_ordinary && dst_obj != NULL)
330*fae548d3Szrj 		(*secvec).push_back(Section_id(dst_obj, dst_indx));
331*fae548d3Szrj 	      else
332*fae548d3Szrj                 (*secvec).push_back(Section_id(NULL, 0));
333*fae548d3Szrj               (*symvec).push_back(gsym);
334*fae548d3Szrj 	      (*addendvec).push_back(std::make_pair(
335*fae548d3Szrj 					static_cast<long long>(symvalue),
336*fae548d3Szrj 					static_cast<long long>(addend)));
337*fae548d3Szrj               uint64_t reloc_offset =
338*fae548d3Szrj                 convert_to_section_size_type(reloc.get_r_offset());
339*fae548d3Szrj 	      (*offsetvec).push_back(reloc_offset);
340*fae548d3Szrj               (*reloc_addend_size_vec).push_back(
341*fae548d3Szrj                 get_embedded_addend_size<Classify_reloc>(r_type, src_obj));
342*fae548d3Szrj 	    }
343*fae548d3Szrj 
344*fae548d3Szrj           if (dst_obj == NULL)
345*fae548d3Szrj             continue;
346*fae548d3Szrj           if (!is_ordinary)
347*fae548d3Szrj             continue;
348*fae548d3Szrj         }
349*fae548d3Szrj       if (parameters->options().gc_sections())
350*fae548d3Szrj         {
351*fae548d3Szrj 	  symtab->gc()->add_reference(src_obj, src_indx, dst_obj, dst_indx);
352*fae548d3Szrj 	  parameters->sized_target<size, big_endian>()
353*fae548d3Szrj 	    ->gc_add_reference(symtab, src_obj, src_indx, dst_obj, dst_indx,
354*fae548d3Szrj 			       dst_off);
355*fae548d3Szrj           if (cident_section_name != NULL)
356*fae548d3Szrj             {
357*fae548d3Szrj               Garbage_collection::Cident_section_map::iterator ele =
358*fae548d3Szrj                 symtab->gc()->cident_sections()->find(std::string(cident_section_name));
359*fae548d3Szrj               if (ele == symtab->gc()->cident_sections()->end())
360*fae548d3Szrj                 continue;
361*fae548d3Szrj 	      Section_id src_id(src_obj, src_indx);
362*fae548d3Szrj               Garbage_collection::Sections_reachable&
363*fae548d3Szrj                 v(symtab->gc()->section_reloc_map()[src_id]);
364*fae548d3Szrj               Garbage_collection::Sections_reachable& cident_secn(ele->second);
365*fae548d3Szrj               for (Garbage_collection::Sections_reachable::iterator it_v
366*fae548d3Szrj                      = cident_secn.begin();
367*fae548d3Szrj                    it_v != cident_secn.end();
368*fae548d3Szrj                    ++it_v)
369*fae548d3Szrj                 {
370*fae548d3Szrj                   v.insert(*it_v);
371*fae548d3Szrj                 }
372*fae548d3Szrj             }
373*fae548d3Szrj         }
374*fae548d3Szrj     }
375*fae548d3Szrj   return;
376*fae548d3Szrj }
377*fae548d3Szrj 
378*fae548d3Szrj } // End of namespace gold.
379*fae548d3Szrj 
380*fae548d3Szrj #endif
381