diff options
Diffstat (limited to 'llvm/tools/llvm-objcopy/COFF/Object.cpp')
| -rw-r--r-- | llvm/tools/llvm-objcopy/COFF/Object.cpp | 137 | 
1 files changed, 137 insertions, 0 deletions
| diff --git a/llvm/tools/llvm-objcopy/COFF/Object.cpp b/llvm/tools/llvm-objcopy/COFF/Object.cpp new file mode 100644 index 000000000000..b07532c1dc39 --- /dev/null +++ b/llvm/tools/llvm-objcopy/COFF/Object.cpp @@ -0,0 +1,137 @@ +//===- Object.cpp ---------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Object.h" +#include "llvm/ADT/DenseSet.h" +#include <algorithm> + +namespace llvm { +namespace objcopy { +namespace coff { + +using namespace object; + +void Object::addSymbols(ArrayRef<Symbol> NewSymbols) { +  for (Symbol S : NewSymbols) { +    S.UniqueId = NextSymbolUniqueId++; +    Symbols.emplace_back(S); +  } +  updateSymbols(); +} + +void Object::updateSymbols() { +  SymbolMap = DenseMap<size_t, Symbol *>(Symbols.size()); +  for (Symbol &Sym : Symbols) +    SymbolMap[Sym.UniqueId] = &Sym; +} + +const Symbol *Object::findSymbol(size_t UniqueId) const { +  auto It = SymbolMap.find(UniqueId); +  if (It == SymbolMap.end()) +    return nullptr; +  return It->second; +} + +void Object::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) { +  Symbols.erase( +      std::remove_if(std::begin(Symbols), std::end(Symbols), +                     [ToRemove](const Symbol &Sym) { return ToRemove(Sym); }), +      std::end(Symbols)); +  updateSymbols(); +} + +Error Object::markSymbols() { +  for (Symbol &Sym : Symbols) +    Sym.Referenced = false; +  for (const Section &Sec : Sections) { +    for (const Relocation &R : Sec.Relocs) { +      auto It = SymbolMap.find(R.Target); +      if (It == SymbolMap.end()) +        return createStringError(object_error::invalid_symbol_index, +                                 "relocation target %zu not found", R.Target); +      It->second->Referenced = true; +    } +  } +  return Error::success(); +} + +void Object::addSections(ArrayRef<Section> NewSections) { +  for (Section S : NewSections) { +    S.UniqueId = NextSectionUniqueId++; +    Sections.emplace_back(S); +  } +  updateSections(); +} + +void Object::updateSections() { +  SectionMap = DenseMap<ssize_t, Section *>(Sections.size()); +  size_t Index = 1; +  for (Section &S : Sections) { +    SectionMap[S.UniqueId] = &S; +    S.Index = Index++; +  } +} + +const Section *Object::findSection(ssize_t UniqueId) const { +  auto It = SectionMap.find(UniqueId); +  if (It == SectionMap.end()) +    return nullptr; +  return It->second; +} + +void Object::removeSections(function_ref<bool(const Section &)> ToRemove) { +  DenseSet<ssize_t> AssociatedSections; +  auto RemoveAssociated = [&AssociatedSections](const Section &Sec) { +    return AssociatedSections.count(Sec.UniqueId) == 1; +  }; +  do { +    DenseSet<ssize_t> RemovedSections; +    Sections.erase( +        std::remove_if(std::begin(Sections), std::end(Sections), +                       [ToRemove, &RemovedSections](const Section &Sec) { +                         bool Remove = ToRemove(Sec); +                         if (Remove) +                           RemovedSections.insert(Sec.UniqueId); +                         return Remove; +                       }), +        std::end(Sections)); +    // Remove all symbols referring to the removed sections. +    AssociatedSections.clear(); +    Symbols.erase( +        std::remove_if( +            std::begin(Symbols), std::end(Symbols), +            [&RemovedSections, &AssociatedSections](const Symbol &Sym) { +              // If there are sections that are associative to a removed +              // section, +              // remove those as well as nothing will include them (and we can't +              // leave them dangling). +              if (RemovedSections.count(Sym.AssociativeComdatTargetSectionId) == +                  1) +                AssociatedSections.insert(Sym.TargetSectionId); +              return RemovedSections.count(Sym.TargetSectionId) == 1; +            }), +        std::end(Symbols)); +    ToRemove = RemoveAssociated; +  } while (!AssociatedSections.empty()); +  updateSections(); +  updateSymbols(); +} + +void Object::truncateSections(function_ref<bool(const Section &)> ToTruncate) { +  for (Section &Sec : Sections) { +    if (ToTruncate(Sec)) { +      Sec.clearContents(); +      Sec.Relocs.clear(); +      Sec.Header.SizeOfRawData = 0; +    } +  } +} + +} // end namespace coff +} // end namespace objcopy +} // end namespace llvm | 
