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