• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- GarbageCollection.cpp ----------------------------------------------===//
2 //
3 //                     The MCLinker Project
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include "mcld/LD/GarbageCollection.h"
10 
11 #include "mcld/Fragment/Fragment.h"
12 #include "mcld/Fragment/Relocation.h"
13 #include "mcld/LD/LDContext.h"
14 #include "mcld/LD/LDFileFormat.h"
15 #include "mcld/LD/LDSection.h"
16 #include "mcld/LD/LDSymbol.h"
17 #include "mcld/LD/SectionData.h"
18 #include "mcld/LD/RelocData.h"
19 #include "mcld/LinkerConfig.h"
20 #include "mcld/LinkerScript.h"
21 #include "mcld/Module.h"
22 #include "mcld/Support/MsgHandling.h"
23 #include "mcld/Target/TargetLDBackend.h"
24 
25 #include <llvm/Support/Casting.h>
26 
27 #include <queue>
28 #if !defined(MCLD_ON_WIN32)
29 #include <fnmatch.h>
30 #define fnmatch0(pattern, string) (fnmatch(pattern, string, 0) == 0)
31 #else
32 #include <windows.h>
33 #include <shlwapi.h>
34 #define fnmatch0(pattern, string) (PathMatchSpec(string, pattern) == true)
35 #endif
36 
37 namespace mcld {
38 
39 //===----------------------------------------------------------------------===//
40 // Non-member functions
41 //===----------------------------------------------------------------------===//
42 // FIXME: these rules should be added into SectionMap, while currently adding to
43 // SectionMap will cause the output order change in .text section and leads to
44 // the .ARM.exidx order incorrect. We should sort the .ARM.exidx.
45 static const char* pattern_to_keep[] = {".text*personality*",
46                                         ".data*personality*",
47                                         ".gnu.linkonce.d*personality*",
48                                         ".sdata*personality*"};
49 
50 /// shouldKeep - check the section name for the keep sections
shouldKeep(const std::string & pName)51 static bool shouldKeep(const std::string& pName) {
52   static const unsigned int pattern_size =
53       sizeof(pattern_to_keep) / sizeof(pattern_to_keep[0]);
54   for (unsigned int i = 0; i < pattern_size; ++i) {
55     if (fnmatch0(pattern_to_keep[i], pName.c_str()))
56       return true;
57   }
58   return false;
59 }
60 
61 /// shouldProcessGC - check if the section kind is handled in GC
mayProcessGC(const LDSection & pSection)62 static bool mayProcessGC(const LDSection& pSection) {
63   if (pSection.kind() == LDFileFormat::TEXT ||
64       pSection.kind() == LDFileFormat::DATA ||
65       pSection.kind() == LDFileFormat::BSS ||
66       pSection.kind() == LDFileFormat::GCCExceptTable)
67     return true;
68   return false;
69 }
70 
71 //===----------------------------------------------------------------------===//
72 // GarbageCollection::SectionReachedListMap
73 //===----------------------------------------------------------------------===//
addReference(const LDSection & pFrom,const LDSection & pTo)74 void GarbageCollection::SectionReachedListMap::addReference(
75     const LDSection& pFrom,
76     const LDSection& pTo) {
77   m_ReachedSections[&pFrom].insert(&pTo);
78 }
79 
80 GarbageCollection::SectionListTy&
getReachedList(const LDSection & pSection)81 GarbageCollection::SectionReachedListMap::getReachedList(
82     const LDSection& pSection) {
83   return m_ReachedSections[&pSection];
84 }
85 
86 GarbageCollection::SectionListTy*
findReachedList(const LDSection & pSection)87 GarbageCollection::SectionReachedListMap::findReachedList(
88     const LDSection& pSection) {
89   ReachedSectionsTy::iterator it = m_ReachedSections.find(&pSection);
90   if (it == m_ReachedSections.end())
91     return NULL;
92   return &it->second;
93 }
94 
95 //===----------------------------------------------------------------------===//
96 // GarbageCollection
97 //===----------------------------------------------------------------------===//
GarbageCollection(const LinkerConfig & pConfig,const TargetLDBackend & pBackend,Module & pModule)98 GarbageCollection::GarbageCollection(const LinkerConfig& pConfig,
99                                      const TargetLDBackend& pBackend,
100                                      Module& pModule)
101     : m_Config(pConfig), m_Backend(pBackend), m_Module(pModule) {
102 }
103 
~GarbageCollection()104 GarbageCollection::~GarbageCollection() {
105 }
106 
run()107 bool GarbageCollection::run() {
108   // 1. traverse all the relocations to set up the reached sections of each
109   // section
110   setUpReachedSections();
111   m_Backend.setUpReachedSectionsForGC(m_Module, m_SectionReachedListMap);
112 
113   // 2. get all sections defined the entry point
114   SectionVecTy entry;
115   getEntrySections(entry);
116 
117   // 3. find all the referenced sections those can be reached by entry
118   findReferencedSections(entry);
119 
120   // 4. stripSections - set the unreached sections to Ignore
121   stripSections();
122   return true;
123 }
124 
setUpReachedSections()125 void GarbageCollection::setUpReachedSections() {
126   // traverse all the input relocations to setup the reached sections
127   Module::obj_iterator input, inEnd = m_Module.obj_end();
128   for (input = m_Module.obj_begin(); input != inEnd; ++input) {
129     LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
130     for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
131       // bypass the discarded relocation section
132       // 1. its section kind is changed to Ignore. (The target section is a
133       // discarded group section.)
134       // 2. it has no reloc data. (All symbols in the input relocs are in the
135       // discarded group sections)
136       LDSection* reloc_sect = *rs;
137       LDSection* apply_sect = reloc_sect->getLink();
138       if ((LDFileFormat::Ignore == reloc_sect->kind()) ||
139           (!reloc_sect->hasRelocData()))
140         continue;
141 
142       // bypass the apply target sections which are not handled by gc
143       if (!mayProcessGC(*apply_sect))
144         continue;
145 
146       bool add_first = false;
147       SectionListTy* reached_sects = NULL;
148       RelocData::iterator reloc_it, rEnd = reloc_sect->getRelocData()->end();
149       for (reloc_it = reloc_sect->getRelocData()->begin(); reloc_it != rEnd;
150            ++reloc_it) {
151         Relocation* reloc = llvm::cast<Relocation>(reloc_it);
152         ResolveInfo* sym = reloc->symInfo();
153         // only the target symbols defined in the input fragments can make the
154         // reference
155         if (sym == NULL)
156           continue;
157         if (!sym->isDefine() || !sym->outSymbol()->hasFragRef())
158           continue;
159 
160         // only the target symbols defined in the concerned sections can make
161         // the reference
162         const LDSection* target_sect =
163             &sym->outSymbol()->fragRef()->frag()->getParent()->getSection();
164         if (!mayProcessGC(*target_sect))
165           continue;
166 
167         // setup the reached list, if we first add the element to reached list
168         // of this section, create an entry in ReachedSections map
169         if (!add_first) {
170           reached_sects = &m_SectionReachedListMap.getReachedList(*apply_sect);
171           add_first = true;
172         }
173         reached_sects->insert(target_sect);
174       }
175       reached_sects = NULL;
176       add_first = false;
177     }
178   }
179 }
180 
getEntrySections(SectionVecTy & pEntry)181 void GarbageCollection::getEntrySections(SectionVecTy& pEntry) {
182   // all the KEEP sections defined in ldscript are entries, traverse all the
183   // input sections and check the SectionMap to find the KEEP sections
184   Module::obj_iterator obj, objEnd = m_Module.obj_end();
185   SectionMap& sect_map = m_Module.getScript().sectionMap();
186   for (obj = m_Module.obj_begin(); obj != objEnd; ++obj) {
187     const std::string input_name = (*obj)->name();
188     LDContext::sect_iterator sect, sectEnd = (*obj)->context()->sectEnd();
189     for (sect = (*obj)->context()->sectBegin(); sect != sectEnd; ++sect) {
190       LDSection* section = *sect;
191       if (!mayProcessGC(*section))
192         continue;
193 
194       SectionMap::Input* sm_input =
195           sect_map.find(input_name, section->name()).second;
196       if (((sm_input != NULL) && (InputSectDesc::Keep == sm_input->policy())) ||
197           shouldKeep(section->name()))
198         pEntry.push_back(section);
199     }
200   }
201 
202   // when building shared object or the --export-dynamic has been given, the
203   // global define symbols are entries
204   if (LinkerConfig::DynObj == m_Config.codeGenType() ||
205       m_Config.options().exportDynamic()) {
206     NamePool::syminfo_iterator info_it,
207         info_end = m_Module.getNamePool().syminfo_end();
208     for (info_it = m_Module.getNamePool().syminfo_begin(); info_it != info_end;
209          ++info_it) {
210       ResolveInfo* info = info_it.getEntry();
211       if (!info->isDefine() || info->isLocal() ||
212           info->shouldForceLocal(m_Config))
213         continue;
214       LDSymbol* sym = info->outSymbol();
215       if (sym == NULL || !sym->hasFragRef())
216         continue;
217 
218       // only the target symbols defined in the concerned sections can be
219       // entries
220       const LDSection* sect =
221           &sym->fragRef()->frag()->getParent()->getSection();
222       if (!mayProcessGC(*sect))
223         continue;
224       pEntry.push_back(sect);
225     }
226   }
227 
228   // when building executable or PIE
229   if (LinkerConfig::Exec == m_Config.codeGenType() ||
230       m_Config.options().isPIE()) {
231     // 1. the entry symbol is the entry
232     LDSymbol* entry_sym =
233         m_Module.getNamePool().findSymbol(m_Backend.getEntry(m_Module));
234     assert(entry_sym != NULL);
235     pEntry.push_back(&entry_sym->fragRef()->frag()->getParent()->getSection());
236 
237     // 2. the symbols have been seen in dynamic objects are entries. If
238     // --export-dynamic is set, then these sections already been added. No need
239     // to add them again
240     if (!m_Config.options().exportDynamic()) {
241       NamePool::syminfo_iterator info_it,
242           info_end = m_Module.getNamePool().syminfo_end();
243       for (info_it = m_Module.getNamePool().syminfo_begin();
244            info_it != info_end; ++info_it) {
245         ResolveInfo* info = info_it.getEntry();
246         if (!info->isDefine() || info->isLocal())
247           continue;
248 
249         if (!info->isInDyn())
250           continue;
251 
252         LDSymbol* sym = info->outSymbol();
253         if (sym == NULL || !sym->hasFragRef())
254           continue;
255 
256         // only the target symbols defined in the concerned sections can be
257         // entries
258         const LDSection* sect =
259             &sym->fragRef()->frag()->getParent()->getSection();
260         if (!mayProcessGC(*sect))
261           continue;
262 
263         pEntry.push_back(sect);
264       }
265     }
266   }
267 
268   // symbols set by -u should not be garbage collected. Set them entries.
269   GeneralOptions::const_undef_sym_iterator usym;
270   GeneralOptions::const_undef_sym_iterator usymEnd =
271       m_Config.options().undef_sym_end();
272   for (usym = m_Config.options().undef_sym_begin(); usym != usymEnd; ++usym) {
273     LDSymbol* sym = m_Module.getNamePool().findSymbol(*usym);
274     assert(sym);
275     ResolveInfo* info = sym->resolveInfo();
276     assert(info);
277     if (!info->isDefine() || !sym->hasFragRef())
278       continue;
279     // only the symbols defined in the concerned sections can be entries
280     const LDSection* sect = &sym->fragRef()->frag()->getParent()->getSection();
281     if (!mayProcessGC(*sect))
282       continue;
283     pEntry.push_back(sect);
284   }
285 }
286 
findReferencedSections(SectionVecTy & pEntry)287 void GarbageCollection::findReferencedSections(SectionVecTy& pEntry) {
288   // list of sections waiting to be processed
289   typedef std::queue<const LDSection*> WorkListTy;
290   WorkListTy work_list;
291   // start from each entry, resolve the transitive closure
292   SectionVecTy::iterator entry_it, entry_end = pEntry.end();
293   for (entry_it = pEntry.begin(); entry_it != entry_end; ++entry_it) {
294     // add entry point to work list
295     work_list.push(*entry_it);
296 
297     // add section from the work_list to the referencedSections until every
298     // reached sections are added
299     while (!work_list.empty()) {
300       const LDSection* sect = work_list.front();
301       work_list.pop();
302       // add section to the ReferencedSections, if the section has been put into
303       // referencedSections, skip this section
304       if (!m_ReferencedSections.insert(sect).second)
305         continue;
306 
307       // get the section reached list, if the section do not has one, which
308       // means no referenced between it and other sections, then skip it
309       SectionListTy* reach_list =
310           m_SectionReachedListMap.findReachedList(*sect);
311       if (reach_list == NULL)
312         continue;
313 
314       // put the reached sections to work list, skip the one already be in
315       // referencedSections
316       SectionListTy::iterator it, end = reach_list->end();
317       for (it = reach_list->begin(); it != end; ++it) {
318         if (m_ReferencedSections.find(*it) == m_ReferencedSections.end())
319           work_list.push(*it);
320       }
321     }
322   }
323 }
324 
stripSections()325 void GarbageCollection::stripSections() {
326   // Traverse all the input Regular and BSS sections, if a section is not found
327   // in the ReferencedSections, then it should be garbage collected
328   Module::obj_iterator obj, objEnd = m_Module.obj_end();
329   for (obj = m_Module.obj_begin(); obj != objEnd; ++obj) {
330     LDContext::sect_iterator sect, sectEnd = (*obj)->context()->sectEnd();
331     for (sect = (*obj)->context()->sectBegin(); sect != sectEnd; ++sect) {
332       LDSection* section = *sect;
333       if (!mayProcessGC(*section))
334         continue;
335 
336       if (m_ReferencedSections.find(section) == m_ReferencedSections.end()) {
337         section->setKind(LDFileFormat::Ignore);
338         debug(diag::debug_print_gc_sections) << section->name()
339                                              << (*obj)->name();
340       }
341     }
342   }
343 
344   // Traverse all the relocation sections, if its target section is set to
345   // Ignore, then set the relocation section to Ignore as well
346   Module::obj_iterator input, inEnd = m_Module.obj_end();
347   for (input = m_Module.obj_begin(); input != inEnd; ++input) {
348     LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd();
349     for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) {
350       LDSection* reloc_sect = *rs;
351       if (LDFileFormat::Ignore == reloc_sect->getLink()->kind())
352         reloc_sect->setKind(LDFileFormat::Ignore);
353     }
354   }
355 }
356 
357 }  // namespace mcld
358