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