llvm.org GIT mirror llvm / 318c4f1
[llvm-objcopy] [COFF] Add support for removing symbols Differential Revision: https://reviews.llvm.org/D55881 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@350893 91177308-0d34-0410-b5e6-96231b3b80d8 Martin Storsjo 7 months ago
11 changed file(s) with 290 addition(s) and 14 deletion(s). Raw diff Collapse all Expand all
0 --- !COFF
1 header:
2 Machine: IMAGE_FILE_MACHINE_AMD64
3 Characteristics: [ ]
4 sections:
5 - Name: .text
6 Characteristics: [ ]
7 Alignment: 4
8 SectionData: 488B0500000000488B0500000000488B0500000000
9 Relocations:
10 - VirtualAddress: 3
11 SymbolTableIndex: 0
12 Type: IMAGE_REL_AMD64_REL32
13 - VirtualAddress: 10
14 SymbolTableIndex: 1
15 Type: IMAGE_REL_AMD64_REL32
16 - VirtualAddress: 17
17 SymbolName: foo
18 Type: IMAGE_REL_AMD64_REL32
19 - Name: .rdata
20 Characteristics: [ ]
21 Alignment: 1
22 SectionData: '00'
23 - Name: .rdata
24 Characteristics: [ ]
25 Alignment: 1
26 SectionData: '01'
27 symbols:
28 - Name: .rdata
29 Value: 0
30 SectionNumber: 2
31 SimpleType: IMAGE_SYM_TYPE_NULL
32 ComplexType: IMAGE_SYM_DTYPE_NULL
33 StorageClass: IMAGE_SYM_CLASS_STATIC
34 - Name: .rdata
35 Value: 0
36 SectionNumber: 3
37 SimpleType: IMAGE_SYM_TYPE_NULL
38 ComplexType: IMAGE_SYM_DTYPE_NULL
39 StorageClass: IMAGE_SYM_CLASS_STATIC
40 - Name: mainfunc
41 Value: 0
42 SectionNumber: 1
43 SimpleType: IMAGE_SYM_TYPE_NULL
44 ComplexType: IMAGE_SYM_DTYPE_NULL
45 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
46 - Name: foo
47 Value: 0
48 SectionNumber: 3
49 SimpleType: IMAGE_SYM_TYPE_NULL
50 ComplexType: IMAGE_SYM_DTYPE_NULL
51 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
52 ...
0 # RUN: yaml2obj %p/Inputs/strip-symbols.yaml > %t.o
1 # RUN: not llvm-objcopy -N foo %t.o 2>&1 | FileCheck %s --check-prefix=ERROR
2 # RUN: not llvm-objcopy --strip-symbol foo %t.o 2>&1 | FileCheck %s --check-prefix=ERROR
3
4 # ERROR: error: '{{.*}}/strip-reloc-symbol.test.tmp.o': not stripping symbol 'foo' because it is named in a relocation.
0 # RUN: yaml2obj %p/Inputs/strip-symbols.yaml > %t.in.o
1
2 # RUN: llvm-readobj -relocations %t.in.o | FileCheck %s --check-prefixes=RELOCS,RELOCS-PRE
3 # RUN: llvm-objdump -t %t.in.o | FileCheck %s --check-prefixes=SYMBOLS,SYMBOLS-PRE
4
5 # RUN: llvm-objcopy -N mainfunc %t.in.o %t.out.o
6 # RUN: llvm-readobj -relocations %t.out.o | FileCheck %s --check-prefixes=RELOCS,RELOCS-POST
7 # RUN: llvm-objdump -t %t.out.o | FileCheck %s --check-prefix=SYMBOLS
8
9 # RUN: llvm-objcopy --strip-symbol mainfunc %t.in.o %t.out.o
10 # RUN: llvm-readobj -relocations %t.out.o | FileCheck %s --check-prefixes=RELOCS,RELOCS-POST
11 # RUN: llvm-objdump -t %t.out.o | FileCheck %s --check-prefix=SYMBOLS
12
13 # Explicitly listing the relocations for the input as well, to show
14 # that the symbol index of the symbol foo is updated in the relocations,
15 # while keeping relocations to two distinct .rdata symbols separate.
16
17 # RELOCS: Relocations [
18 # RELOCS-NEXT: Section (1) .text {
19 # RELOCS-NEXT: 0x3 IMAGE_REL_AMD64_REL32 .rdata (0)
20 # RELOCS-NEXT: 0xA IMAGE_REL_AMD64_REL32 .rdata (1)
21 # RELOCS-PRE-NEXT: 0x11 IMAGE_REL_AMD64_REL32 foo (3)
22 # RELOCS-POST-NEXT: 0x11 IMAGE_REL_AMD64_REL32 foo (2)
23 # RELOCS-NEXT: }
24 # RELOCS-NEXT: ]
25
26 # SYMBOLS: SYMBOL TABLE:
27 # SYMBOLS-NEXT: .rdata
28 # SYMBOLS-NEXT: .rdata
29 # SYMBOLS-PRE-NEXT: mainfunc
30 # SYMBOLS-NEXT: foo
31 # SYMBOLS-EMPTY:
1717 CopyConfig.cpp
1818 llvm-objcopy.cpp
1919 COFF/COFFObjcopy.cpp
20 COFF/Object.cpp
2021 COFF/Reader.cpp
2122 COFF/Writer.cpp
2223 ELF/ELFObjcopy.cpp
1616
1717 #include "llvm/Object/Binary.h"
1818 #include "llvm/Object/COFF.h"
19 #include "llvm/Support/Errc.h"
1920 #include
2021
2122 namespace llvm {
2526 using namespace object;
2627 using namespace COFF;
2728
29 static Error handleArgs(const CopyConfig &Config, Object &Obj) {
30 // If we need to do per-symbol removals, initialize the Referenced field.
31 if (!Config.SymbolsToRemove.empty())
32 if (Error E = Obj.markSymbols())
33 return E;
34
35 // Actually do removals of symbols.
36 Obj.removeSymbols([&](const Symbol &Sym) {
37 if (is_contained(Config.SymbolsToRemove, Sym.Name)) {
38 // Explicitly removing a referenced symbol is an error.
39 if (Sym.Referenced)
40 reportError(Config.OutputFilename,
41 make_error(
42 "not stripping symbol '" + Sym.Name +
43 "' because it is named in a relocation.",
44 llvm::errc::invalid_argument));
45 return true;
46 }
47
48 return false;
49 });
50 return Error::success();
51 }
52
2853 void executeObjcopyOnBinary(const CopyConfig &Config,
2954 object::COFFObjectFile &In, Buffer &Out) {
3055 COFFReader Reader(In);
3358 reportError(Config.InputFilename, ObjOrErr.takeError());
3459 Object *Obj = ObjOrErr->get();
3560 assert(Obj && "Unable to deserialize COFF object");
61 if (Error E = handleArgs(Config, *Obj))
62 reportError(Config.InputFilename, std::move(E));
3663 COFFWriter Writer(*Obj, Out);
3764 if (Error E = Writer.write())
3865 reportError(Config.OutputFilename, std::move(E));
0 //===- Object.cpp ---------------------------------------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "Object.h"
10 #include
11
12 namespace llvm {
13 namespace objcopy {
14 namespace coff {
15
16 using namespace object;
17
18 void Object::addSymbols(ArrayRef 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(Symbols.size());
28 size_t RawSymIndex = 0;
29 for (Symbol &Sym : Symbols) {
30 SymbolMap[Sym.UniqueId] = &Sym;
31 Sym.RawIndex = RawSymIndex;
32 RawSymIndex += 1 + Sym.Sym.NumberOfAuxSymbols;
33 }
34 }
35
36 const Symbol *Object::findSymbol(size_t UniqueId) const {
37 auto It = SymbolMap.find(UniqueId);
38 if (It == SymbolMap.end())
39 return nullptr;
40 return It->second;
41 }
42
43 void Object::removeSymbols(function_ref ToRemove) {
44 Symbols.erase(
45 std::remove_if(std::begin(Symbols), std::end(Symbols),
46 [ToRemove](const Symbol &Sym) { return ToRemove(Sym); }),
47 std::end(Symbols));
48 updateSymbols();
49 }
50
51 Error Object::markSymbols() {
52 for (Symbol &Sym : Symbols)
53 Sym.Referenced = false;
54 for (const Section &Sec : Sections) {
55 for (const Relocation &R : Sec.Relocs) {
56 auto It = SymbolMap.find(R.Target);
57 if (It == SymbolMap.end())
58 return make_error("Relocation target " + Twine(R.Target) +
59 " not found",
60 object_error::invalid_symbol_index);
61 It->second->Referenced = true;
62 }
63 }
64 return Error::success();
65 }
66
67 } // end namespace coff
68 } // end namespace objcopy
69 } // end namespace llvm
1010 #define LLVM_TOOLS_OBJCOPY_COFF_OBJECT_H
1111
1212 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/DenseMap.h"
1314 #include "llvm/ADT/StringRef.h"
15 #include "llvm/ADT/iterator_range.h"
1416 #include "llvm/BinaryFormat/COFF.h"
1517 #include "llvm/Object/COFF.h"
1618 #include
2123 namespace objcopy {
2224 namespace coff {
2325
26 struct Relocation {
27 object::coff_relocation Reloc;
28 size_t Target;
29 StringRef TargetName; // Used for diagnostics only
30 };
31
2432 struct Section {
2533 object::coff_section Header;
2634 ArrayRef Contents;
27 std::vector<object::coff_relocation> Relocs;
35 std::vector<Relocation> Relocs;
2836 StringRef Name;
2937 };
3038
3240 object::coff_symbol32 Sym;
3341 StringRef Name;
3442 ArrayRef AuxData;
43 size_t UniqueId;
44 size_t RawIndex;
45 bool Referenced;
3546 };
3647
3748 struct Object {
4859
4960 std::vector DataDirectories;
5061 std::vector
Sections;
62
63 ArrayRef getSymbols() const { return Symbols; }
64 // This allows mutating individual Symbols, but not mutating the list
65 // of symbols itself.
66 iterator_range::iterator> getMutableSymbols() {
67 return make_range(Symbols.begin(), Symbols.end());
68 }
69
70 const Symbol *findSymbol(size_t UniqueId) const;
71
72 void addSymbols(ArrayRef NewSymbols);
73 void removeSymbols(function_ref ToRemove);
74
75 // Set the Referenced field on all Symbols, based on relocations in
76 // all sections.
77 Error markSymbols();
78
79 private:
5180 std::vector Symbols;
81 DenseMap SymbolMap;
82
83 size_t NextSymbolUniqueId = 0;
84
85 // Update SymbolMap and RawIndex in each Symbol.
86 void updateSymbols();
5287 };
5388
5489 // Copy between coff_symbol16 and coff_symbol32.
7272 return errorCodeToError(EC);
7373 ArrayRef Relocs = COFFObj.getRelocations(Sec);
7474 for (const coff_relocation &R : Relocs)
75 S.Relocs.push_back(R);
75 S.Relocs.push_back(Relocation{R});
7676 if (auto EC = COFFObj.getSectionName(Sec, S.Name))
7777 return errorCodeToError(EC);
7878 if (Sec->hasExtendedRelocations())
8383 }
8484
8585 Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
86 std::vector Symbols;
87 Symbols.reserve(COFFObj.getRawNumberOfSymbols());
8688 for (uint32_t I = 0, E = COFFObj.getRawNumberOfSymbols(); I < E;) {
8789 Expected SymOrErr = COFFObj.getSymbol(I);
8890 if (!SymOrErr)
8991 return SymOrErr.takeError();
9092 COFFSymbolRef SymRef = *SymOrErr;
9193
92 Obj.Symbols.push_back(Symbol());
93 Symbol &Sym = Obj.Symbols.back();
94 Symbols.push_back(Symbol());
95 Symbol &Sym = Symbols.back();
9496 // Copy symbols from the original form into an intermediate coff_symbol32.
9597 if (IsBigObj)
9698 copySymbol(Sym.Sym,
104106 assert((Sym.AuxData.size() %
105107 (IsBigObj ? sizeof(coff_symbol32) : sizeof(coff_symbol16))) == 0);
106108 I += 1 + SymRef.getNumberOfAuxSymbols();
109 }
110 Obj.addSymbols(Symbols);
111 return Error::success();
112 }
113
114 Error COFFReader::setRelocTargets(Object &Obj) const {
115 std::vector RawSymbolTable;
116 for (const Symbol &Sym : Obj.getSymbols()) {
117 RawSymbolTable.push_back(&Sym);
118 for (size_t I = 0; I < Sym.Sym.NumberOfAuxSymbols; I++)
119 RawSymbolTable.push_back(nullptr);
120 }
121 for (Section &Sec : Obj.Sections) {
122 for (Relocation &R : Sec.Relocs) {
123 if (R.Reloc.SymbolTableIndex >= RawSymbolTable.size())
124 return make_error("SymbolTableIndex out of range",
125 object_error::parse_failed);
126 const Symbol *Sym = RawSymbolTable[R.Reloc.SymbolTableIndex];
127 if (Sym == nullptr)
128 return make_error("Invalid SymbolTableIndex",
129 object_error::parse_failed);
130 R.Target = Sym->UniqueId;
131 R.TargetName = Sym->Name;
132 }
107133 }
108134 return Error::success();
109135 }
135161 return std::move(E);
136162 if (Error E = readSymbols(*Obj, IsBigObj))
137163 return std::move(E);
164 if (Error E = setRelocTargets(*Obj))
165 return std::move(E);
138166
139167 return std::move(Obj);
140168 }
3434 Error readExecutableHeaders(Object &Obj) const;
3535 Error readSections(Object &Obj) const;
3636 Error readSymbols(Object &Obj, bool IsBigObj) const;
37 Error setRelocTargets(Object &Obj) const;
3738
3839 public:
3940 explicit COFFReader(const COFFObjectFile &O) : COFFObj(O) {}
2626
2727 Writer::~Writer() {}
2828
29 Error COFFWriter::finalizeRelocTargets() {
30 for (Section &Sec : Obj.Sections) {
31 for (Relocation &R : Sec.Relocs) {
32 const Symbol *Sym = Obj.findSymbol(R.Target);
33 if (Sym == nullptr)
34 return make_error("Relocation target " + R.TargetName +
35 " (" + Twine(R.Target) +
36 ") not found",
37 object_error::invalid_symbol_index);
38 R.Reloc.SymbolTableIndex = Sym->RawIndex;
39 }
40 }
41 return Error::success();
42 }
43
2944 void COFFWriter::layoutSections() {
3045 for (auto &S : Obj.Sections) {
3146 if (S.Header.SizeOfRawData > 0)
4762 if (S.Name.size() > COFF::NameSize)
4863 StrTabBuilder.add(S.Name);
4964
50 for (const auto &S : Obj.Symbols)
65 for (const auto &S : Obj.getSymbols())
5166 if (S.Name.size() > COFF::NameSize)
5267 StrTabBuilder.add(S.Name);
5368
6176 strncpy(S.Header.Name, S.Name.data(), COFF::NameSize);
6277 }
6378 }
64 for (auto &S : Obj.Symbols) {
79 for (auto &S : Obj.getMutableSymbols()) {
6580 if (S.Name.size() > COFF::NameSize) {
6681 S.Sym.Name.Offset.Zeroes = 0;
6782 S.Sym.Name.Offset.Offset = StrTabBuilder.getOffset(S.Name);
7489
7590 template
7691 std::pair COFFWriter::finalizeSymbolTable() {
77 size_t SymTabSize = Obj.Symbols.size() * sizeof(SymbolTy);
78 for (const auto &S : Obj.Symbols)
92 size_t SymTabSize = Obj.getSymbols().size() * sizeof(SymbolTy);
93 for (const auto &S : Obj.getSymbols())
7994 SymTabSize += S.AuxData.size();
8095 return std::make_pair(SymTabSize, sizeof(SymbolTy));
8196 }
8297
83 void COFFWriter::finalize(bool IsBigObj) {
98 Error COFFWriter::finalize(bool IsBigObj) {
99 if (Error E = finalizeRelocTargets())
100 return E;
101
84102 size_t SizeOfHeaders = 0;
85103 FileAlignment = 1;
86104 size_t PeHeaderSize = 0;
148166 Obj.CoffFileHeader.NumberOfSymbols = NumRawSymbols;
149167 FileSize += SymTabSize + StrTabSize;
150168 FileSize = alignTo(FileSize, FileAlignment);
169
170 return Error::success();
151171 }
152172
153173 void COFFWriter::writeHeaders(bool IsBigObj) {
224244 S.Header.SizeOfRawData - S.Contents.size());
225245
226246 Ptr += S.Header.SizeOfRawData;
227 std::copy(S.Relocs.begin(), S.Relocs.end(),
228 reinterpret_cast(Ptr));
247 for (const auto &R : S.Relocs) {
248 memcpy(Ptr, &R.Reloc, sizeof(R.Reloc));
249 Ptr += sizeof(R.Reloc);
250 }
229251 }
230252 }
231253
232254 template void COFFWriter::writeSymbolStringTables() {
233255 uint8_t *Ptr = Buf.getBufferStart() + Obj.CoffFileHeader.PointerToSymbolTable;
234 for (const auto &S : Obj.Symbols) {
256 for (const auto &S : Obj.getSymbols()) {
235257 // Convert symbols back to the right size, from coff_symbol32.
236258 copySymbol(*reinterpret_cast(Ptr),
237259 S.Sym);
247269 }
248270
249271 Error COFFWriter::write(bool IsBigObj) {
250 finalize(IsBigObj);
272 if (Error E = finalize(IsBigObj))
273 return E;
251274
252275 Buf.allocate(FileSize);
253276
3939 size_t SizeOfInitializedData;
4040 StringTableBuilder StrTabBuilder;
4141
42 Error finalizeRelocTargets();
4243 void layoutSections();
4344 size_t finalizeStringTable();
4445 template std::pair finalizeSymbolTable();
4546
46 void finalize(bool IsBigObj);
47 Error finalize(bool IsBigObj);
4748
4849 void writeHeaders(bool IsBigObj);
4950 void writeSections();