1 //===- COFFObject.cpp -----------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "COFFObject.h" 10 #include "llvm/ADT/DenseSet.h" 11 12 namespace llvm { 13 namespace objcopy { 14 namespace coff { 15 16 using namespace object; 17 18 void Object::addSymbols(ArrayRef<Symbol> NewSymbols) { 19 for (Symbol S : NewSymbols) { 20 S.UniqueId = NextSymbolUniqueId++; 21 Symbols.emplace_back(S); 22 } 23 updateSymbols(); 24 } 25 26 void Object::updateSymbols() { 27 SymbolMap = DenseMap<size_t, Symbol *>(Symbols.size()); 28 for (Symbol &Sym : Symbols) 29 SymbolMap[Sym.UniqueId] = &Sym; 30 } 31 32 const Symbol *Object::findSymbol(size_t UniqueId) const { 33 return SymbolMap.lookup(UniqueId); 34 } 35 36 Error Object::removeSymbols( 37 function_ref<Expected<bool>(const Symbol &)> ToRemove) { 38 Error Errs = Error::success(); 39 llvm::erase_if(Symbols, [ToRemove, &Errs](const Symbol &Sym) { 40 Expected<bool> ShouldRemove = ToRemove(Sym); 41 if (!ShouldRemove) { 42 Errs = joinErrors(std::move(Errs), ShouldRemove.takeError()); 43 return false; 44 } 45 return *ShouldRemove; 46 }); 47 48 updateSymbols(); 49 return Errs; 50 } 51 52 Error Object::markSymbols() { 53 for (Symbol &Sym : Symbols) 54 Sym.Referenced = false; 55 for (const Section &Sec : Sections) { 56 for (const Relocation &R : Sec.Relocs) { 57 auto It = SymbolMap.find(R.Target); 58 if (It == SymbolMap.end()) 59 return createStringError(object_error::invalid_symbol_index, 60 "relocation target %zu not found", R.Target); 61 It->second->Referenced = true; 62 } 63 } 64 return Error::success(); 65 } 66 67 void Object::addSections(ArrayRef<Section> NewSections) { 68 for (Section S : NewSections) { 69 S.UniqueId = NextSectionUniqueId++; 70 Sections.emplace_back(S); 71 } 72 updateSections(); 73 } 74 75 void Object::updateSections() { 76 SectionMap = DenseMap<ssize_t, Section *>(Sections.size()); 77 size_t Index = 1; 78 for (Section &S : Sections) { 79 SectionMap[S.UniqueId] = &S; 80 S.Index = Index++; 81 } 82 } 83 84 const Section *Object::findSection(ssize_t UniqueId) const { 85 return SectionMap.lookup(UniqueId); 86 } 87 88 void Object::removeSections(function_ref<bool(const Section &)> ToRemove) { 89 DenseSet<ssize_t> AssociatedSections; 90 auto RemoveAssociated = [&AssociatedSections](const Section &Sec) { 91 return AssociatedSections.contains(Sec.UniqueId); 92 }; 93 do { 94 DenseSet<ssize_t> RemovedSections; 95 llvm::erase_if(Sections, [ToRemove, &RemovedSections](const Section &Sec) { 96 bool Remove = ToRemove(Sec); 97 if (Remove) 98 RemovedSections.insert(Sec.UniqueId); 99 return Remove; 100 }); 101 // Remove all symbols referring to the removed sections. 102 AssociatedSections.clear(); 103 llvm::erase_if( 104 Symbols, [&RemovedSections, &AssociatedSections](const Symbol &Sym) { 105 // If there are sections that are associative to a removed 106 // section, 107 // remove those as well as nothing will include them (and we can't 108 // leave them dangling). 109 if (RemovedSections.contains(Sym.AssociativeComdatTargetSectionId)) 110 AssociatedSections.insert(Sym.TargetSectionId); 111 return RemovedSections.contains(Sym.TargetSectionId); 112 }); 113 ToRemove = RemoveAssociated; 114 } while (!AssociatedSections.empty()); 115 updateSections(); 116 updateSymbols(); 117 } 118 119 void Object::truncateSections(function_ref<bool(const Section &)> ToTruncate) { 120 for (Section &Sec : Sections) { 121 if (ToTruncate(Sec)) { 122 Sec.clearContents(); 123 Sec.Relocs.clear(); 124 Sec.Header.SizeOfRawData = 0; 125 } 126 } 127 } 128 129 } // end namespace coff 130 } // end namespace objcopy 131 } // end namespace llvm 132