1 //===- FragmentGraph.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/FragmentGraph.h> 10 #include <mcld/Fragment/Fragment.h> 11 #include <mcld/Fragment/Relocation.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/Module.h> 20 #include <mcld/Support/MsgHandling.h> 21 22 #include <llvm/Support/Casting.h> 23 #include <llvm/Support/ELF.h> 24 25 #include <iostream> 26 27 using namespace mcld; 28 29 //===----------------------------------------------------------------------===// 30 // non-member functions 31 //===----------------------------------------------------------------------===// 32 static int get_state(Fragment::Type pKind) 33 { 34 switch(pKind) { 35 case Fragment::Alignment: 36 return 0; 37 case Fragment::Fillment: 38 case Fragment::Region: 39 return 1; 40 case Fragment::Null: 41 return 2; 42 default: 43 unreachable(diag::unexpected_frag_type) << pKind; 44 } 45 return 0; 46 } 47 48 //===----------------------------------------------------------------------===// 49 // ReachMatrix 50 //===----------------------------------------------------------------------===// 51 FragmentGraph::ReachMatrix::ReachMatrix(size_t pSize) 52 { 53 assert(pSize != 0); 54 m_Data.assign(pSize * pSize, 0x0); 55 m_N = pSize; 56 } 57 58 uint32_t& FragmentGraph::ReachMatrix::at(uint32_t pX, uint32_t pY) 59 { 60 return m_Data[pX * m_N + pY]; 61 } 62 63 uint32_t FragmentGraph::ReachMatrix::at(uint32_t pX, uint32_t pY) const 64 { 65 return m_Data[pX * m_N + pY]; 66 } 67 68 //===----------------------------------------------------------------------===// 69 // FragmentGraph 70 //===----------------------------------------------------------------------===// 71 FragmentGraph::FragmentGraph() 72 : m_pMatrix(NULL), m_NumOfPNodes(0x0), m_NumOfRNodes(0x0), m_NumOfEdges(0x0) 73 { 74 m_pPseudoNodeFactory = new NodeFactoryType(); 75 m_pRegularNodeFactory = new NodeFactoryType(); 76 m_pFragNodeMap = new FragHashTableType(256); 77 m_pSymNodeMap = new SymHashTableType(256); 78 } 79 80 FragmentGraph::~FragmentGraph() 81 { 82 delete m_pPseudoNodeFactory; 83 delete m_pRegularNodeFactory; 84 delete m_pFragNodeMap; 85 } 86 87 FGNode* FragmentGraph::getNode(const Fragment& pFrag) 88 { 89 FragHashTableType::iterator entry = m_pFragNodeMap->find(&pFrag); 90 if (entry == m_pFragNodeMap->end()) 91 return NULL; 92 return entry.getEntry()->value(); 93 } 94 95 const FGNode* FragmentGraph::getNode(const Fragment& pFrag) const 96 { 97 FragHashTableType::iterator entry = m_pFragNodeMap->find(&pFrag); 98 if (entry == m_pFragNodeMap->end()) 99 return NULL; 100 return entry.getEntry()->value(); 101 } 102 103 FGNode* FragmentGraph::getNode(const ResolveInfo& pSym) 104 { 105 SymHashTableType::iterator entry = m_pSymNodeMap->find(&pSym); 106 if (entry == m_pSymNodeMap->end()) 107 return NULL; 108 return entry.getEntry()->value(); 109 } 110 111 const FGNode* FragmentGraph::getNode(const ResolveInfo& pSym) const 112 { 113 SymHashTableType::iterator entry = m_pSymNodeMap->find(&pSym); 114 if (entry == m_pSymNodeMap->end()) 115 return NULL; 116 return entry.getEntry()->value(); 117 } 118 119 FGNode* FragmentGraph::producePseudoNode() 120 { 121 FGNode* result = m_pPseudoNodeFactory->allocate(); 122 new (result) FGNode(m_NumOfPNodes + m_NumOfRNodes); 123 ++m_NumOfPNodes; 124 return result; 125 } 126 127 FGNode* FragmentGraph::produceRegularNode() 128 { 129 FGNode* result = m_pRegularNodeFactory->allocate(); 130 new (result) FGNode(m_NumOfPNodes + m_NumOfRNodes); 131 ++m_NumOfRNodes; 132 return result; 133 } 134 135 bool FragmentGraph::setNodeSlots(Module& pModule) 136 { 137 // symbols are the slots of nodes, push the symbols into the corresponding 138 // nodes. 139 140 // Traverse all defined symbols, including global and local symbols, to add 141 // symbols into the corresponding nodes 142 Module::SymbolTable& sym_tab = pModule.getSymbolTable(); 143 SymbolCategory::iterator sym_it, sym_end = sym_tab.end(); 144 for (sym_it = sym_tab.begin(); sym_it != sym_end; ++sym_it) { 145 // only the defined symbols with FragmnentRef can form a slot. The defined 146 // symbol with no FragmentRef such as ABS symbol should be skipped 147 LDSymbol* sym = *sym_it; 148 if (!sym->resolveInfo()->isDefine() || 149 !sym->hasFragRef()) 150 continue; 151 152 // FIXME: judge by getNode() is NULL or not 153 LDFileFormat::Kind sect_kind = 154 sym->fragRef()->frag()->getParent()->getSection().kind(); 155 if (sect_kind != LDFileFormat::Regular && 156 sect_kind != LDFileFormat::BSS) 157 continue; 158 159 FGNode* node = getNode(*sym->fragRef()->frag()); 160 assert(NULL != node); 161 node->addSlot(sym->resolveInfo()); 162 } 163 164 return true; 165 } 166 167 bool FragmentGraph::createRegularEdges(Module& pModule) 168 { 169 // The reference between nodes are presented by the relocations. Set the 170 // reachability matrix to present the connection 171 172 // Traverse all input relocations to set connection 173 Module::obj_iterator input, inEnd = pModule.obj_end(); 174 for (input = pModule.obj_begin(); input != inEnd; ++input) { 175 LDContext::sect_iterator rs, rsEnd = (*input)->context()->relocSectEnd(); 176 for (rs = (*input)->context()->relocSectBegin(); rs != rsEnd; ++rs) { 177 // bypass the discarded relocations 178 // 1. its section kind is changed to Ignore. (The target section is a 179 // discarded group section.) 180 // 2. it has no reloc data. (All symbols in the input relocs are in the 181 // discarded group sections) 182 if (LDFileFormat::Ignore == (*rs)->kind() || !(*rs)->hasRelocData()) 183 continue; 184 RelocData::iterator reloc_it, rEnd = (*rs)->getRelocData()->end(); 185 for (reloc_it = (*rs)->getRelocData()->begin(); reloc_it != rEnd; 186 ++reloc_it) { 187 Relocation* reloc = llvm::cast<Relocation>(reloc_it); 188 ResolveInfo* sym = reloc->symInfo(); 189 // only the target symbols defined in the input fragments can make the 190 // connection 191 if (NULL == sym) 192 continue; 193 if (!sym->isDefine() || !sym->outSymbol()->hasFragRef()) 194 continue; 195 196 // only the relocation target places which defined in the concerned 197 // sections can make the connection 198 // FIXME: judge by getNode() is NULL or not 199 LDFileFormat::Kind sect_kind = 200 reloc->targetRef().frag()->getParent()->getSection().kind(); 201 if (sect_kind != LDFileFormat::Regular && 202 sect_kind != LDFileFormat::BSS) 203 continue; 204 205 // only the target symbols defined in the concerned sections can make 206 // the connection 207 // FIXME: judge by getNode() is NULL or not 208 sect_kind = 209 sym->outSymbol()->fragRef()->frag()->getParent()->getSection().kind(); 210 if (sect_kind != LDFileFormat::Regular && 211 sect_kind != LDFileFormat::BSS) 212 continue; 213 214 connect(reloc, sym); 215 } 216 } 217 } 218 return true; 219 } 220 221 bool FragmentGraph::createPseudoEdges(Module& pModule) 222 { 223 // the pseudo edges are the edges from pseudo nodes to regular nodes, which 224 // present the reference from out-side world when building shared library 225 226 // Traverse all pseudo relocations in the pseudo nodes to set the connection 227 node_iterator node_it, node_end = m_pPseudoNodeFactory->end(); 228 for (node_it = m_pPseudoNodeFactory->begin(); node_it != node_end; ++node_it) { 229 FGNode& node = *node_it; 230 FGNode::signal_iterator sig_it, sig_end = node.signal_end(); 231 for (sig_it = node.signal_begin(); sig_it != sig_end; ++sig_it) { 232 connect(node, (*sig_it)->symInfo()); 233 } 234 } 235 return true; 236 } 237 238 bool FragmentGraph::connect(Signal pSignal, Slot pSlot) 239 { 240 FGNode* from = getNode(*pSignal->targetRef().frag()); 241 assert(NULL != from); 242 243 FGNode* to = getNode(*pSlot->outSymbol()->fragRef()->frag()); 244 assert(NULL != to); 245 246 // maintain edge counter 247 if (0 == m_pMatrix->at(from->getIndex(), to->getIndex())) 248 ++m_NumOfEdges; 249 ++m_pMatrix->at(from->getIndex(), to->getIndex()); 250 return true; 251 } 252 253 bool FragmentGraph::connect(FGNode& pFrom, Slot pSlot) 254 { 255 FGNode* to = getNode(*pSlot->outSymbol()->fragRef()->frag()); 256 assert(NULL != to); 257 258 // maintain edge counter 259 if (0 == m_pMatrix->at(pFrom.getIndex(), to->getIndex())) 260 ++m_NumOfEdges; 261 ++m_pMatrix->at(pFrom.getIndex(), to->getIndex()); 262 return true; 263 } 264 265 bool FragmentGraph::createPseudoNodes(Module& pModule) 266 { 267 // when generating shared library, we need to create pseudo node for every 268 // global defined symbols to present the fan-in of a regular node. 269 270 // Traverse all global defined symbols to build the pseudo nodes. 271 Module::SymbolTable& sym_tab = pModule.getSymbolTable(); 272 SymbolCategory::iterator sym_it, sym_end = sym_tab.dynamicEnd(); 273 for (sym_it = sym_tab.dynamicBegin(); sym_it != sym_end; ++sym_it) { 274 ResolveInfo* sym = (*sym_it)->resolveInfo(); 275 if (!sym->isDefine() || !sym->outSymbol()->hasFragRef()) 276 continue; 277 FGNode* node = producePseudoNode(); 278 // create the pseudo relocation to present the fan-out of the pseudo node 279 Relocation* reloc = Relocation::Create(); 280 reloc->setSymInfo(sym); 281 282 // set the signal of the pseudo node 283 node->addSignal(reloc); 284 285 // maintain the map for symbol to pseudo node 286 SymHashTableType::entry_type* entry = 0; 287 bool exist = false; 288 entry = m_pSymNodeMap->insert(sym, exist); 289 entry->setValue(node); 290 291 } 292 return true; 293 } 294 295 bool FragmentGraph::createRegularNodes(Module& pModule) 296 { 297 // Traverse all sections to build the Nodes. We build nodes only for Regular, 298 // and BSS 299 Module::iterator sect_it, sect_end = pModule.end(); 300 for (sect_it = pModule.begin(); sect_it != sect_end; ++sect_it) { 301 LDSection* section = *sect_it; 302 SectionData* sect_data = NULL; 303 304 if (LDFileFormat::Regular != section->kind() && 305 LDFileFormat::BSS != section->kind()) 306 continue; 307 308 sect_data = section->getSectionData(); 309 if (NULL == sect_data) 310 continue; 311 312 // Traverse all fragments in the sections, create Nodes and push the 313 // fragments into Nodes. Each Region or Fillment fragment belongs to a 314 // unique Node. The corresponding Align fragments and Null fragments belong 315 // to the same Node as the Region or Fillment fragment. 316 SectionData::iterator frag_it = sect_data->begin(); 317 SectionData::iterator frag_end = sect_data->end(); 318 if (frag_it == frag_end) 319 continue; 320 321 int cur_stat = 0; 322 int last_stat = 0; 323 // FIXME: 324 // To prevent some cases that we add the redundant NULL or Align fragments 325 // and lead a Region/Fillment fragment has more than one NULL or Align 326 // fragment. We should put all of them into the same Node. 327 static int stat_matrix[3][3] = {{0, 1, 1}, 328 {0, 1, 1}, 329 {0, 0, 0}}; 330 331 FragHashTableType::entry_type* entry = 0; 332 bool exist = false; 333 334 FGNode* node = produceRegularNode(); 335 Fragment* frag = NULL; 336 337 frag = &(*frag_it); 338 cur_stat = get_state(frag->getKind()); 339 340 node->addFragment(frag); 341 // maintain the fragment to Node map 342 entry = m_pFragNodeMap->insert(frag, exist); 343 entry->setValue(node); 344 ++frag_it; 345 346 while (frag_it != frag_end) { 347 last_stat = cur_stat; 348 frag = &(*frag_it); 349 350 cur_stat = get_state(frag->getKind()); 351 352 if (stat_matrix[cur_stat][last_stat]) { 353 node = produceRegularNode(); 354 } 355 node->addFragment(frag); 356 // maintain the fragment to Node map 357 entry = m_pFragNodeMap->insert(frag, exist); 358 entry->setValue(node); 359 360 ++frag_it; 361 } 362 } 363 return true; 364 } 365 366 void FragmentGraph::initMatrix() 367 { 368 m_pMatrix = new ReachMatrix(m_NumOfPNodes + m_NumOfRNodes); 369 } 370 371 bool FragmentGraph::getEdges(FGNode& pNode, EdgeListType& pEdges) 372 { 373 // Traverse all regular nodes to find the connection to pNode 374 node_iterator it, itEnd = m_pRegularNodeFactory->end(); 375 for (it = m_pRegularNodeFactory->begin(); it != itEnd; ++it) { 376 FGNode& node_to = *it; 377 uint32_t weight = m_pMatrix->at(pNode.getIndex(), node_to.getIndex()); 378 if (weight > 0) { 379 // build an Edge 380 pEdges.push_back(FGEdge(pNode, node_to, weight)); 381 } 382 } 383 384 return true; 385 } 386 387 bool FragmentGraph::construct(const LinkerConfig& pConfig, Module& pModule) 388 { 389 // create nodes - traverse all fragments to create the regular nodes, and 390 // then traverse all global defined symbols to create pseudo nodes 391 if (!createRegularNodes(pModule)) 392 return false; 393 if (!createPseudoNodes(pModule)) 394 return false; 395 396 // after all nodes created, we know the number of the nodes and then can 397 // create the reachability matrix 398 initMatrix(); 399 400 // set slots - traverse all symbols to set the slots of regular nodes 401 if(!setNodeSlots(pModule)) 402 return false; 403 404 // connect edges - traverse all relocations to set the edges 405 if(!createRegularEdges(pModule)) 406 return false; 407 if(!createPseudoEdges(pModule)) 408 return false; 409 410 return true; 411 } 412 413