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(args&: 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(Val: UniqueId); |
34 | } |
35 | |
36 | Error Object::removeSymbols( |
37 | function_ref<Expected<bool>(const Symbol &)> ToRemove) { |
38 | Error Errs = Error::success(); |
39 | llvm::erase_if(C&: Symbols, P: [ToRemove, &Errs](const Symbol &Sym) { |
40 | Expected<bool> ShouldRemove = ToRemove(Sym); |
41 | if (!ShouldRemove) { |
42 | Errs = joinErrors(E1: std::move(Errs), E2: 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(Val: R.Target); |
58 | if (It == SymbolMap.end()) |
59 | return createStringError(EC: object_error::invalid_symbol_index, |
60 | Fmt: "relocation target %zu not found" , Vals: 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(args&: 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(Val: 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(V: Sec.UniqueId); |
92 | }; |
93 | do { |
94 | DenseSet<ssize_t> RemovedSections; |
95 | llvm::erase_if(C&: Sections, P: [ToRemove, &RemovedSections](const Section &Sec) { |
96 | bool Remove = ToRemove(Sec); |
97 | if (Remove) |
98 | RemovedSections.insert(V: Sec.UniqueId); |
99 | return Remove; |
100 | }); |
101 | // Remove all symbols referring to the removed sections. |
102 | AssociatedSections.clear(); |
103 | llvm::erase_if( |
104 | C&: Symbols, P: [&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(V: Sym.AssociativeComdatTargetSectionId)) |
110 | AssociatedSections.insert(V: Sym.TargetSectionId); |
111 | return RemovedSections.contains(V: 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 | |