Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
35266 views
1
//===- ELFObjcopy.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 "llvm/ObjCopy/ELF/ELFObjcopy.h"
10
#include "ELFObject.h"
11
#include "llvm/ADT/BitmaskEnum.h"
12
#include "llvm/ADT/DenseSet.h"
13
#include "llvm/ADT/STLExtras.h"
14
#include "llvm/ADT/SmallVector.h"
15
#include "llvm/ADT/StringRef.h"
16
#include "llvm/ADT/Twine.h"
17
#include "llvm/BinaryFormat/ELF.h"
18
#include "llvm/MC/MCTargetOptions.h"
19
#include "llvm/ObjCopy/CommonConfig.h"
20
#include "llvm/ObjCopy/ELF/ELFConfig.h"
21
#include "llvm/Object/Binary.h"
22
#include "llvm/Object/ELFObjectFile.h"
23
#include "llvm/Object/ELFTypes.h"
24
#include "llvm/Object/Error.h"
25
#include "llvm/Option/Option.h"
26
#include "llvm/Support/Casting.h"
27
#include "llvm/Support/Compression.h"
28
#include "llvm/Support/Errc.h"
29
#include "llvm/Support/Error.h"
30
#include "llvm/Support/ErrorHandling.h"
31
#include "llvm/Support/ErrorOr.h"
32
#include "llvm/Support/FileSystem.h"
33
#include "llvm/Support/Memory.h"
34
#include "llvm/Support/Path.h"
35
#include "llvm/Support/raw_ostream.h"
36
#include <algorithm>
37
#include <cassert>
38
#include <cstdlib>
39
#include <functional>
40
#include <iterator>
41
#include <memory>
42
#include <string>
43
#include <system_error>
44
#include <utility>
45
46
using namespace llvm;
47
using namespace llvm::ELF;
48
using namespace llvm::objcopy;
49
using namespace llvm::objcopy::elf;
50
using namespace llvm::object;
51
52
using SectionPred = std::function<bool(const SectionBase &Sec)>;
53
54
static bool isDebugSection(const SectionBase &Sec) {
55
return StringRef(Sec.Name).starts_with(".debug") || Sec.Name == ".gdb_index";
56
}
57
58
static bool isDWOSection(const SectionBase &Sec) {
59
return StringRef(Sec.Name).ends_with(".dwo");
60
}
61
62
static bool onlyKeepDWOPred(const Object &Obj, const SectionBase &Sec) {
63
// We can't remove the section header string table.
64
if (&Sec == Obj.SectionNames)
65
return false;
66
// Short of keeping the string table we want to keep everything that is a DWO
67
// section and remove everything else.
68
return !isDWOSection(Sec);
69
}
70
71
static Expected<uint64_t> getNewShfFlags(SectionFlag AllFlags,
72
uint16_t EMachine) {
73
uint64_t NewFlags = 0;
74
if (AllFlags & SectionFlag::SecAlloc)
75
NewFlags |= ELF::SHF_ALLOC;
76
if (!(AllFlags & SectionFlag::SecReadonly))
77
NewFlags |= ELF::SHF_WRITE;
78
if (AllFlags & SectionFlag::SecCode)
79
NewFlags |= ELF::SHF_EXECINSTR;
80
if (AllFlags & SectionFlag::SecMerge)
81
NewFlags |= ELF::SHF_MERGE;
82
if (AllFlags & SectionFlag::SecStrings)
83
NewFlags |= ELF::SHF_STRINGS;
84
if (AllFlags & SectionFlag::SecExclude)
85
NewFlags |= ELF::SHF_EXCLUDE;
86
if (AllFlags & SectionFlag::SecLarge) {
87
if (EMachine != EM_X86_64)
88
return createStringError(errc::invalid_argument,
89
"section flag SHF_X86_64_LARGE can only be used "
90
"with x86_64 architecture");
91
NewFlags |= ELF::SHF_X86_64_LARGE;
92
}
93
return NewFlags;
94
}
95
96
static uint64_t getSectionFlagsPreserveMask(uint64_t OldFlags,
97
uint64_t NewFlags,
98
uint16_t EMachine) {
99
// Preserve some flags which should not be dropped when setting flags.
100
// Also, preserve anything OS/processor dependant.
101
const uint64_t PreserveMask =
102
(ELF::SHF_COMPRESSED | ELF::SHF_GROUP | ELF::SHF_LINK_ORDER |
103
ELF::SHF_MASKOS | ELF::SHF_MASKPROC | ELF::SHF_TLS |
104
ELF::SHF_INFO_LINK) &
105
~ELF::SHF_EXCLUDE &
106
~(EMachine == EM_X86_64 ? (uint64_t)ELF::SHF_X86_64_LARGE : 0UL);
107
return (OldFlags & PreserveMask) | (NewFlags & ~PreserveMask);
108
}
109
110
static void setSectionType(SectionBase &Sec, uint64_t Type) {
111
// If Sec's type is changed from SHT_NOBITS due to --set-section-flags,
112
// Offset may not be aligned. Align it to max(Align, 1).
113
if (Sec.Type == ELF::SHT_NOBITS && Type != ELF::SHT_NOBITS)
114
Sec.Offset = alignTo(Sec.Offset, std::max(Sec.Align, uint64_t(1)));
115
Sec.Type = Type;
116
}
117
118
static Error setSectionFlagsAndType(SectionBase &Sec, SectionFlag Flags,
119
uint16_t EMachine) {
120
Expected<uint64_t> NewFlags = getNewShfFlags(Flags, EMachine);
121
if (!NewFlags)
122
return NewFlags.takeError();
123
Sec.Flags = getSectionFlagsPreserveMask(Sec.Flags, *NewFlags, EMachine);
124
125
// In GNU objcopy, certain flags promote SHT_NOBITS to SHT_PROGBITS. This rule
126
// may promote more non-ALLOC sections than GNU objcopy, but it is fine as
127
// non-ALLOC SHT_NOBITS sections do not make much sense.
128
if (Sec.Type == SHT_NOBITS &&
129
(!(Sec.Flags & ELF::SHF_ALLOC) ||
130
Flags & (SectionFlag::SecContents | SectionFlag::SecLoad)))
131
setSectionType(Sec, ELF::SHT_PROGBITS);
132
133
return Error::success();
134
}
135
136
static ElfType getOutputElfType(const Binary &Bin) {
137
// Infer output ELF type from the input ELF object
138
if (isa<ELFObjectFile<ELF32LE>>(Bin))
139
return ELFT_ELF32LE;
140
if (isa<ELFObjectFile<ELF64LE>>(Bin))
141
return ELFT_ELF64LE;
142
if (isa<ELFObjectFile<ELF32BE>>(Bin))
143
return ELFT_ELF32BE;
144
if (isa<ELFObjectFile<ELF64BE>>(Bin))
145
return ELFT_ELF64BE;
146
llvm_unreachable("Invalid ELFType");
147
}
148
149
static ElfType getOutputElfType(const MachineInfo &MI) {
150
// Infer output ELF type from the binary arch specified
151
if (MI.Is64Bit)
152
return MI.IsLittleEndian ? ELFT_ELF64LE : ELFT_ELF64BE;
153
else
154
return MI.IsLittleEndian ? ELFT_ELF32LE : ELFT_ELF32BE;
155
}
156
157
static std::unique_ptr<Writer> createELFWriter(const CommonConfig &Config,
158
Object &Obj, raw_ostream &Out,
159
ElfType OutputElfType) {
160
// Depending on the initial ELFT and OutputFormat we need a different Writer.
161
switch (OutputElfType) {
162
case ELFT_ELF32LE:
163
return std::make_unique<ELFWriter<ELF32LE>>(Obj, Out, !Config.StripSections,
164
Config.OnlyKeepDebug);
165
case ELFT_ELF64LE:
166
return std::make_unique<ELFWriter<ELF64LE>>(Obj, Out, !Config.StripSections,
167
Config.OnlyKeepDebug);
168
case ELFT_ELF32BE:
169
return std::make_unique<ELFWriter<ELF32BE>>(Obj, Out, !Config.StripSections,
170
Config.OnlyKeepDebug);
171
case ELFT_ELF64BE:
172
return std::make_unique<ELFWriter<ELF64BE>>(Obj, Out, !Config.StripSections,
173
Config.OnlyKeepDebug);
174
}
175
llvm_unreachable("Invalid output format");
176
}
177
178
static std::unique_ptr<Writer> createWriter(const CommonConfig &Config,
179
Object &Obj, raw_ostream &Out,
180
ElfType OutputElfType) {
181
switch (Config.OutputFormat) {
182
case FileFormat::Binary:
183
return std::make_unique<BinaryWriter>(Obj, Out, Config);
184
case FileFormat::IHex:
185
return std::make_unique<IHexWriter>(Obj, Out, Config.OutputFilename);
186
case FileFormat::SREC:
187
return std::make_unique<SRECWriter>(Obj, Out, Config.OutputFilename);
188
default:
189
return createELFWriter(Config, Obj, Out, OutputElfType);
190
}
191
}
192
193
static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
194
Object &Obj) {
195
for (auto &Sec : Obj.sections()) {
196
if (Sec.Name == SecName) {
197
if (Sec.Type == SHT_NOBITS)
198
return createStringError(object_error::parse_failed,
199
"cannot dump section '%s': it has no contents",
200
SecName.str().c_str());
201
Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
202
FileOutputBuffer::create(Filename, Sec.OriginalData.size());
203
if (!BufferOrErr)
204
return BufferOrErr.takeError();
205
std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);
206
std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(),
207
Buf->getBufferStart());
208
if (Error E = Buf->commit())
209
return E;
210
return Error::success();
211
}
212
}
213
return createStringError(object_error::parse_failed, "section '%s' not found",
214
SecName.str().c_str());
215
}
216
217
Error Object::compressOrDecompressSections(const CommonConfig &Config) {
218
// Build a list of sections we are going to replace.
219
// We can't call `addSection` while iterating over sections,
220
// because it would mutate the sections array.
221
SmallVector<std::pair<SectionBase *, std::function<SectionBase *()>>, 0>
222
ToReplace;
223
for (SectionBase &Sec : sections()) {
224
std::optional<DebugCompressionType> CType;
225
for (auto &[Matcher, T] : Config.compressSections)
226
if (Matcher.matches(Sec.Name))
227
CType = T;
228
// Handle --compress-debug-sections and --decompress-debug-sections, which
229
// apply to non-ALLOC debug sections.
230
if (!(Sec.Flags & SHF_ALLOC) && StringRef(Sec.Name).starts_with(".debug")) {
231
if (Config.CompressionType != DebugCompressionType::None)
232
CType = Config.CompressionType;
233
else if (Config.DecompressDebugSections)
234
CType = DebugCompressionType::None;
235
}
236
if (!CType)
237
continue;
238
239
if (Sec.ParentSegment)
240
return createStringError(
241
errc::invalid_argument,
242
"section '" + Sec.Name +
243
"' within a segment cannot be (de)compressed");
244
245
if (auto *CS = dyn_cast<CompressedSection>(&Sec)) {
246
if (*CType == DebugCompressionType::None)
247
ToReplace.emplace_back(
248
&Sec, [=] { return &addSection<DecompressedSection>(*CS); });
249
} else if (*CType != DebugCompressionType::None) {
250
ToReplace.emplace_back(&Sec, [=, S = &Sec] {
251
return &addSection<CompressedSection>(
252
CompressedSection(*S, *CType, Is64Bits));
253
});
254
}
255
}
256
257
DenseMap<SectionBase *, SectionBase *> FromTo;
258
for (auto [S, Func] : ToReplace)
259
FromTo[S] = Func();
260
return replaceSections(FromTo);
261
}
262
263
static bool isAArch64MappingSymbol(const Symbol &Sym) {
264
if (Sym.Binding != STB_LOCAL || Sym.Type != STT_NOTYPE ||
265
Sym.getShndx() == SHN_UNDEF)
266
return false;
267
StringRef Name = Sym.Name;
268
if (!Name.consume_front("$x") && !Name.consume_front("$d"))
269
return false;
270
return Name.empty() || Name.starts_with(".");
271
}
272
273
static bool isArmMappingSymbol(const Symbol &Sym) {
274
if (Sym.Binding != STB_LOCAL || Sym.Type != STT_NOTYPE ||
275
Sym.getShndx() == SHN_UNDEF)
276
return false;
277
StringRef Name = Sym.Name;
278
if (!Name.consume_front("$a") && !Name.consume_front("$d") &&
279
!Name.consume_front("$t"))
280
return false;
281
return Name.empty() || Name.starts_with(".");
282
}
283
284
// Check if the symbol should be preserved because it is required by ABI.
285
static bool isRequiredByABISymbol(const Object &Obj, const Symbol &Sym) {
286
switch (Obj.Machine) {
287
case EM_AARCH64:
288
// Mapping symbols should be preserved for a relocatable object file.
289
return Obj.isRelocatable() && isAArch64MappingSymbol(Sym);
290
case EM_ARM:
291
// Mapping symbols should be preserved for a relocatable object file.
292
return Obj.isRelocatable() && isArmMappingSymbol(Sym);
293
default:
294
return false;
295
}
296
}
297
298
static bool isUnneededSymbol(const Symbol &Sym) {
299
return !Sym.Referenced &&
300
(Sym.Binding == STB_LOCAL || Sym.getShndx() == SHN_UNDEF) &&
301
Sym.Type != STT_SECTION;
302
}
303
304
static Error updateAndRemoveSymbols(const CommonConfig &Config,
305
const ELFConfig &ELFConfig, Object &Obj) {
306
// TODO: update or remove symbols only if there is an option that affects
307
// them.
308
if (!Obj.SymbolTable)
309
return Error::success();
310
311
Obj.SymbolTable->updateSymbols([&](Symbol &Sym) {
312
if (Config.SymbolsToSkip.matches(Sym.Name))
313
return;
314
315
// Common and undefined symbols don't make sense as local symbols, and can
316
// even cause crashes if we localize those, so skip them.
317
if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF &&
318
((ELFConfig.LocalizeHidden &&
319
(Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) ||
320
Config.SymbolsToLocalize.matches(Sym.Name)))
321
Sym.Binding = STB_LOCAL;
322
323
for (auto &[Matcher, Visibility] : ELFConfig.SymbolsToSetVisibility)
324
if (Matcher.matches(Sym.Name))
325
Sym.Visibility = Visibility;
326
327
// Note: these two globalize flags have very similar names but different
328
// meanings:
329
//
330
// --globalize-symbol: promote a symbol to global
331
// --keep-global-symbol: all symbols except for these should be made local
332
//
333
// If --globalize-symbol is specified for a given symbol, it will be
334
// global in the output file even if it is not included via
335
// --keep-global-symbol. Because of that, make sure to check
336
// --globalize-symbol second.
337
if (!Config.SymbolsToKeepGlobal.empty() &&
338
!Config.SymbolsToKeepGlobal.matches(Sym.Name) &&
339
Sym.getShndx() != SHN_UNDEF)
340
Sym.Binding = STB_LOCAL;
341
342
if (Config.SymbolsToGlobalize.matches(Sym.Name) &&
343
Sym.getShndx() != SHN_UNDEF)
344
Sym.Binding = STB_GLOBAL;
345
346
// SymbolsToWeaken applies to both STB_GLOBAL and STB_GNU_UNIQUE.
347
if (Config.SymbolsToWeaken.matches(Sym.Name) && Sym.Binding != STB_LOCAL)
348
Sym.Binding = STB_WEAK;
349
350
if (Config.Weaken && Sym.Binding != STB_LOCAL &&
351
Sym.getShndx() != SHN_UNDEF)
352
Sym.Binding = STB_WEAK;
353
354
const auto I = Config.SymbolsToRename.find(Sym.Name);
355
if (I != Config.SymbolsToRename.end())
356
Sym.Name = std::string(I->getValue());
357
358
if (!Config.SymbolsPrefixRemove.empty() && Sym.Type != STT_SECTION)
359
if (Sym.Name.compare(0, Config.SymbolsPrefixRemove.size(),
360
Config.SymbolsPrefixRemove) == 0)
361
Sym.Name = Sym.Name.substr(Config.SymbolsPrefixRemove.size());
362
363
if (!Config.SymbolsPrefix.empty() && Sym.Type != STT_SECTION)
364
Sym.Name = (Config.SymbolsPrefix + Sym.Name).str();
365
});
366
367
// The purpose of this loop is to mark symbols referenced by sections
368
// (like GroupSection or RelocationSection). This way, we know which
369
// symbols are still 'needed' and which are not.
370
if (Config.StripUnneeded || !Config.UnneededSymbolsToRemove.empty() ||
371
!Config.OnlySection.empty() || Config.DiscardMode != DiscardType::None) {
372
for (SectionBase &Sec : Obj.sections())
373
Sec.markSymbols();
374
}
375
376
auto RemoveSymbolsPred = [&](const Symbol &Sym) {
377
if (Config.SymbolsToKeep.matches(Sym.Name) ||
378
(ELFConfig.KeepFileSymbols && Sym.Type == STT_FILE))
379
return false;
380
381
if (Config.SymbolsToRemove.matches(Sym.Name))
382
return true;
383
384
if (Config.StripAll || Config.StripAllGNU)
385
return true;
386
387
if (isRequiredByABISymbol(Obj, Sym))
388
return false;
389
390
if (Config.StripDebug && Sym.Type == STT_FILE)
391
return true;
392
393
if ((Config.StripUnneeded ||
394
Config.UnneededSymbolsToRemove.matches(Sym.Name)) &&
395
(!Obj.isRelocatable() || isUnneededSymbol(Sym)))
396
return true;
397
398
if (!Sym.Referenced) {
399
if ((Config.DiscardMode == DiscardType::All ||
400
(Config.DiscardMode == DiscardType::Locals &&
401
StringRef(Sym.Name).starts_with(".L"))) &&
402
Sym.Binding == STB_LOCAL && Sym.getShndx() != SHN_UNDEF &&
403
Sym.Type != STT_FILE && Sym.Type != STT_SECTION)
404
return true;
405
// We want to remove undefined symbols if all references have been
406
// stripped.
407
if (!Config.OnlySection.empty() && Sym.getShndx() == SHN_UNDEF)
408
return true;
409
}
410
411
return false;
412
};
413
414
return Obj.removeSymbols(RemoveSymbolsPred);
415
}
416
417
static Error replaceAndRemoveSections(const CommonConfig &Config,
418
const ELFConfig &ELFConfig, Object &Obj) {
419
SectionPred RemovePred = [](const SectionBase &) { return false; };
420
421
// Removes:
422
if (!Config.ToRemove.empty()) {
423
RemovePred = [&Config](const SectionBase &Sec) {
424
return Config.ToRemove.matches(Sec.Name);
425
};
426
}
427
428
if (Config.StripDWO)
429
RemovePred = [RemovePred](const SectionBase &Sec) {
430
return isDWOSection(Sec) || RemovePred(Sec);
431
};
432
433
if (Config.ExtractDWO)
434
RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
435
return onlyKeepDWOPred(Obj, Sec) || RemovePred(Sec);
436
};
437
438
if (Config.StripAllGNU)
439
RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
440
if (RemovePred(Sec))
441
return true;
442
if ((Sec.Flags & SHF_ALLOC) != 0)
443
return false;
444
if (&Sec == Obj.SectionNames)
445
return false;
446
switch (Sec.Type) {
447
case SHT_SYMTAB:
448
case SHT_REL:
449
case SHT_RELA:
450
case SHT_STRTAB:
451
return true;
452
}
453
return isDebugSection(Sec);
454
};
455
456
if (Config.StripSections) {
457
RemovePred = [RemovePred](const SectionBase &Sec) {
458
return RemovePred(Sec) || Sec.ParentSegment == nullptr;
459
};
460
}
461
462
if (Config.StripDebug || Config.StripUnneeded) {
463
RemovePred = [RemovePred](const SectionBase &Sec) {
464
return RemovePred(Sec) || isDebugSection(Sec);
465
};
466
}
467
468
if (Config.StripNonAlloc)
469
RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
470
if (RemovePred(Sec))
471
return true;
472
if (&Sec == Obj.SectionNames)
473
return false;
474
return (Sec.Flags & SHF_ALLOC) == 0 && Sec.ParentSegment == nullptr;
475
};
476
477
if (Config.StripAll)
478
RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
479
if (RemovePred(Sec))
480
return true;
481
if (&Sec == Obj.SectionNames)
482
return false;
483
if (StringRef(Sec.Name).starts_with(".gnu.warning"))
484
return false;
485
if (StringRef(Sec.Name).starts_with(".gnu_debuglink"))
486
return false;
487
// We keep the .ARM.attribute section to maintain compatibility
488
// with Debian derived distributions. This is a bug in their
489
// patchset as documented here:
490
// https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=943798
491
if (Sec.Type == SHT_ARM_ATTRIBUTES)
492
return false;
493
if (Sec.ParentSegment != nullptr)
494
return false;
495
return (Sec.Flags & SHF_ALLOC) == 0;
496
};
497
498
if (Config.ExtractPartition || Config.ExtractMainPartition) {
499
RemovePred = [RemovePred](const SectionBase &Sec) {
500
if (RemovePred(Sec))
501
return true;
502
if (Sec.Type == SHT_LLVM_PART_EHDR || Sec.Type == SHT_LLVM_PART_PHDR)
503
return true;
504
return (Sec.Flags & SHF_ALLOC) != 0 && !Sec.ParentSegment;
505
};
506
}
507
508
// Explicit copies:
509
if (!Config.OnlySection.empty()) {
510
RemovePred = [&Config, RemovePred, &Obj](const SectionBase &Sec) {
511
// Explicitly keep these sections regardless of previous removes.
512
if (Config.OnlySection.matches(Sec.Name))
513
return false;
514
515
// Allow all implicit removes.
516
if (RemovePred(Sec))
517
return true;
518
519
// Keep special sections.
520
if (Obj.SectionNames == &Sec)
521
return false;
522
if (Obj.SymbolTable == &Sec ||
523
(Obj.SymbolTable && Obj.SymbolTable->getStrTab() == &Sec))
524
return false;
525
526
// Remove everything else.
527
return true;
528
};
529
}
530
531
if (!Config.KeepSection.empty()) {
532
RemovePred = [&Config, RemovePred](const SectionBase &Sec) {
533
// Explicitly keep these sections regardless of previous removes.
534
if (Config.KeepSection.matches(Sec.Name))
535
return false;
536
// Otherwise defer to RemovePred.
537
return RemovePred(Sec);
538
};
539
}
540
541
// This has to be the last predicate assignment.
542
// If the option --keep-symbol has been specified
543
// and at least one of those symbols is present
544
// (equivalently, the updated symbol table is not empty)
545
// the symbol table and the string table should not be removed.
546
if ((!Config.SymbolsToKeep.empty() || ELFConfig.KeepFileSymbols) &&
547
Obj.SymbolTable && !Obj.SymbolTable->empty()) {
548
RemovePred = [&Obj, RemovePred](const SectionBase &Sec) {
549
if (&Sec == Obj.SymbolTable || &Sec == Obj.SymbolTable->getStrTab())
550
return false;
551
return RemovePred(Sec);
552
};
553
}
554
555
if (Error E = Obj.removeSections(ELFConfig.AllowBrokenLinks, RemovePred))
556
return E;
557
558
if (Error E = Obj.compressOrDecompressSections(Config))
559
return E;
560
561
return Error::success();
562
}
563
564
// Add symbol to the Object symbol table with the specified properties.
565
static void addSymbol(Object &Obj, const NewSymbolInfo &SymInfo,
566
uint8_t DefaultVisibility) {
567
SectionBase *Sec = Obj.findSection(SymInfo.SectionName);
568
uint64_t Value = Sec ? Sec->Addr + SymInfo.Value : SymInfo.Value;
569
570
uint8_t Bind = ELF::STB_GLOBAL;
571
uint8_t Type = ELF::STT_NOTYPE;
572
uint8_t Visibility = DefaultVisibility;
573
574
for (SymbolFlag FlagValue : SymInfo.Flags)
575
switch (FlagValue) {
576
case SymbolFlag::Global:
577
Bind = ELF::STB_GLOBAL;
578
break;
579
case SymbolFlag::Local:
580
Bind = ELF::STB_LOCAL;
581
break;
582
case SymbolFlag::Weak:
583
Bind = ELF::STB_WEAK;
584
break;
585
case SymbolFlag::Default:
586
Visibility = ELF::STV_DEFAULT;
587
break;
588
case SymbolFlag::Hidden:
589
Visibility = ELF::STV_HIDDEN;
590
break;
591
case SymbolFlag::Protected:
592
Visibility = ELF::STV_PROTECTED;
593
break;
594
case SymbolFlag::File:
595
Type = ELF::STT_FILE;
596
break;
597
case SymbolFlag::Section:
598
Type = ELF::STT_SECTION;
599
break;
600
case SymbolFlag::Object:
601
Type = ELF::STT_OBJECT;
602
break;
603
case SymbolFlag::Function:
604
Type = ELF::STT_FUNC;
605
break;
606
case SymbolFlag::IndirectFunction:
607
Type = ELF::STT_GNU_IFUNC;
608
break;
609
default: /* Other flag values are ignored for ELF. */
610
break;
611
};
612
613
Obj.SymbolTable->addSymbol(
614
SymInfo.SymbolName, Bind, Type, Sec, Value, Visibility,
615
Sec ? (uint16_t)SYMBOL_SIMPLE_INDEX : (uint16_t)SHN_ABS, 0);
616
}
617
618
static Error
619
handleUserSection(const NewSectionInfo &NewSection,
620
function_ref<Error(StringRef, ArrayRef<uint8_t>)> F) {
621
ArrayRef<uint8_t> Data(reinterpret_cast<const uint8_t *>(
622
NewSection.SectionData->getBufferStart()),
623
NewSection.SectionData->getBufferSize());
624
return F(NewSection.SectionName, Data);
625
}
626
627
static Error verifyNoteSection(StringRef Name, endianness Endianness,
628
ArrayRef<uint8_t> Data) {
629
// An ELF note has the following structure:
630
// Name Size: 4 bytes (integer)
631
// Desc Size: 4 bytes (integer)
632
// Type : 4 bytes
633
// Name : variable size, padded to a 4 byte boundary
634
// Desc : variable size, padded to a 4 byte boundary
635
636
if (Data.empty())
637
return Error::success();
638
639
if (Data.size() < 12) {
640
std::string msg;
641
raw_string_ostream(msg)
642
<< Name << " data must be either empty or at least 12 bytes long";
643
return createStringError(errc::invalid_argument, msg);
644
}
645
if (Data.size() % 4 != 0) {
646
std::string msg;
647
raw_string_ostream(msg)
648
<< Name << " data size must be a multiple of 4 bytes";
649
return createStringError(errc::invalid_argument, msg);
650
}
651
ArrayRef<uint8_t> NameSize = Data.slice(0, 4);
652
ArrayRef<uint8_t> DescSize = Data.slice(4, 4);
653
654
uint32_t NameSizeValue = support::endian::read32(NameSize.data(), Endianness);
655
uint32_t DescSizeValue = support::endian::read32(DescSize.data(), Endianness);
656
657
uint64_t ExpectedDataSize =
658
/*NameSize=*/4 + /*DescSize=*/4 + /*Type=*/4 +
659
/*Name=*/alignTo(NameSizeValue, 4) +
660
/*Desc=*/alignTo(DescSizeValue, 4);
661
uint64_t ActualDataSize = Data.size();
662
if (ActualDataSize != ExpectedDataSize) {
663
std::string msg;
664
raw_string_ostream(msg)
665
<< Name
666
<< " data size is incompatible with the content of "
667
"the name and description size fields:"
668
<< " expecting " << ExpectedDataSize << ", found " << ActualDataSize;
669
return createStringError(errc::invalid_argument, msg);
670
}
671
672
return Error::success();
673
}
674
675
// This function handles the high level operations of GNU objcopy including
676
// handling command line options. It's important to outline certain properties
677
// we expect to hold of the command line operations. Any operation that "keeps"
678
// should keep regardless of a remove. Additionally any removal should respect
679
// any previous removals. Lastly whether or not something is removed shouldn't
680
// depend a) on the order the options occur in or b) on some opaque priority
681
// system. The only priority is that keeps/copies overrule removes.
682
static Error handleArgs(const CommonConfig &Config, const ELFConfig &ELFConfig,
683
ElfType OutputElfType, Object &Obj) {
684
if (Config.OutputArch) {
685
Obj.Machine = Config.OutputArch->EMachine;
686
Obj.OSABI = Config.OutputArch->OSABI;
687
}
688
689
if (!Config.SplitDWO.empty() && Config.ExtractDWO) {
690
return Obj.removeSections(
691
ELFConfig.AllowBrokenLinks,
692
[&Obj](const SectionBase &Sec) { return onlyKeepDWOPred(Obj, Sec); });
693
}
694
695
// Dump sections before add/remove for compatibility with GNU objcopy.
696
for (StringRef Flag : Config.DumpSection) {
697
StringRef SectionName;
698
StringRef FileName;
699
std::tie(SectionName, FileName) = Flag.split('=');
700
if (Error E = dumpSectionToFile(SectionName, FileName, Obj))
701
return E;
702
}
703
704
// It is important to remove the sections first. For example, we want to
705
// remove the relocation sections before removing the symbols. That allows
706
// us to avoid reporting the inappropriate errors about removing symbols
707
// named in relocations.
708
if (Error E = replaceAndRemoveSections(Config, ELFConfig, Obj))
709
return E;
710
711
if (Error E = updateAndRemoveSymbols(Config, ELFConfig, Obj))
712
return E;
713
714
if (!Config.SetSectionAlignment.empty()) {
715
for (SectionBase &Sec : Obj.sections()) {
716
auto I = Config.SetSectionAlignment.find(Sec.Name);
717
if (I != Config.SetSectionAlignment.end())
718
Sec.Align = I->second;
719
}
720
}
721
722
if (Config.ChangeSectionLMAValAll != 0) {
723
for (Segment &Seg : Obj.segments()) {
724
if (Seg.FileSize > 0) {
725
if (Config.ChangeSectionLMAValAll > 0 &&
726
Seg.PAddr > std::numeric_limits<uint64_t>::max() -
727
Config.ChangeSectionLMAValAll) {
728
return createStringError(
729
errc::invalid_argument,
730
"address 0x" + Twine::utohexstr(Seg.PAddr) +
731
" cannot be increased by 0x" +
732
Twine::utohexstr(Config.ChangeSectionLMAValAll) +
733
". The result would overflow");
734
} else if (Config.ChangeSectionLMAValAll < 0 &&
735
Seg.PAddr < std::numeric_limits<uint64_t>::min() -
736
Config.ChangeSectionLMAValAll) {
737
return createStringError(
738
errc::invalid_argument,
739
"address 0x" + Twine::utohexstr(Seg.PAddr) +
740
" cannot be decreased by 0x" +
741
Twine::utohexstr(std::abs(Config.ChangeSectionLMAValAll)) +
742
". The result would underflow");
743
}
744
Seg.PAddr += Config.ChangeSectionLMAValAll;
745
}
746
}
747
}
748
749
if (Config.OnlyKeepDebug)
750
for (auto &Sec : Obj.sections())
751
if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE)
752
Sec.Type = SHT_NOBITS;
753
754
endianness E = OutputElfType == ELFT_ELF32LE || OutputElfType == ELFT_ELF64LE
755
? endianness::little
756
: endianness::big;
757
758
for (const NewSectionInfo &AddedSection : Config.AddSection) {
759
auto AddSection = [&](StringRef Name, ArrayRef<uint8_t> Data) -> Error {
760
OwnedDataSection &NewSection =
761
Obj.addSection<OwnedDataSection>(Name, Data);
762
if (Name.starts_with(".note") && Name != ".note.GNU-stack") {
763
NewSection.Type = SHT_NOTE;
764
if (ELFConfig.VerifyNoteSections)
765
return verifyNoteSection(Name, E, Data);
766
}
767
return Error::success();
768
};
769
if (Error E = handleUserSection(AddedSection, AddSection))
770
return E;
771
}
772
773
for (const NewSectionInfo &NewSection : Config.UpdateSection) {
774
auto UpdateSection = [&](StringRef Name, ArrayRef<uint8_t> Data) {
775
return Obj.updateSection(Name, Data);
776
};
777
if (Error E = handleUserSection(NewSection, UpdateSection))
778
return E;
779
}
780
781
if (!Config.AddGnuDebugLink.empty())
782
Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink,
783
Config.GnuDebugLinkCRC32);
784
785
// If the symbol table was previously removed, we need to create a new one
786
// before adding new symbols.
787
if (!Obj.SymbolTable && !Config.SymbolsToAdd.empty())
788
if (Error E = Obj.addNewSymbolTable())
789
return E;
790
791
for (const NewSymbolInfo &SI : Config.SymbolsToAdd)
792
addSymbol(Obj, SI, ELFConfig.NewSymbolVisibility);
793
794
// --set-section-{flags,type} work with sections added by --add-section.
795
if (!Config.SetSectionFlags.empty() || !Config.SetSectionType.empty()) {
796
for (auto &Sec : Obj.sections()) {
797
const auto Iter = Config.SetSectionFlags.find(Sec.Name);
798
if (Iter != Config.SetSectionFlags.end()) {
799
const SectionFlagsUpdate &SFU = Iter->second;
800
if (Error E = setSectionFlagsAndType(Sec, SFU.NewFlags, Obj.Machine))
801
return E;
802
}
803
auto It2 = Config.SetSectionType.find(Sec.Name);
804
if (It2 != Config.SetSectionType.end())
805
setSectionType(Sec, It2->second);
806
}
807
}
808
809
if (!Config.SectionsToRename.empty()) {
810
std::vector<RelocationSectionBase *> RelocSections;
811
DenseSet<SectionBase *> RenamedSections;
812
for (SectionBase &Sec : Obj.sections()) {
813
auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec);
814
const auto Iter = Config.SectionsToRename.find(Sec.Name);
815
if (Iter != Config.SectionsToRename.end()) {
816
const SectionRename &SR = Iter->second;
817
Sec.Name = std::string(SR.NewName);
818
if (SR.NewFlags) {
819
if (Error E = setSectionFlagsAndType(Sec, *SR.NewFlags, Obj.Machine))
820
return E;
821
}
822
RenamedSections.insert(&Sec);
823
} else if (RelocSec && !(Sec.Flags & SHF_ALLOC))
824
// Postpone processing relocation sections which are not specified in
825
// their explicit '--rename-section' commands until after their target
826
// sections are renamed.
827
// Dynamic relocation sections (i.e. ones with SHF_ALLOC) should be
828
// renamed only explicitly. Otherwise, renaming, for example, '.got.plt'
829
// would affect '.rela.plt', which is not desirable.
830
RelocSections.push_back(RelocSec);
831
}
832
833
// Rename relocation sections according to their target sections.
834
for (RelocationSectionBase *RelocSec : RelocSections) {
835
auto Iter = RenamedSections.find(RelocSec->getSection());
836
if (Iter != RenamedSections.end())
837
RelocSec->Name = (RelocSec->getNamePrefix() + (*Iter)->Name).str();
838
}
839
}
840
841
// Add a prefix to allocated sections and their relocation sections. This
842
// should be done after renaming the section by Config.SectionToRename to
843
// imitate the GNU objcopy behavior.
844
if (!Config.AllocSectionsPrefix.empty()) {
845
DenseSet<SectionBase *> PrefixedSections;
846
for (SectionBase &Sec : Obj.sections()) {
847
if (Sec.Flags & SHF_ALLOC) {
848
Sec.Name = (Config.AllocSectionsPrefix + Sec.Name).str();
849
PrefixedSections.insert(&Sec);
850
} else if (auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec)) {
851
// Rename relocation sections associated to the allocated sections.
852
// For example, if we rename .text to .prefix.text, we also rename
853
// .rel.text to .rel.prefix.text.
854
//
855
// Dynamic relocation sections (SHT_REL[A] with SHF_ALLOC) are handled
856
// above, e.g., .rela.plt is renamed to .prefix.rela.plt, not
857
// .rela.prefix.plt since GNU objcopy does so.
858
const SectionBase *TargetSec = RelocSec->getSection();
859
if (TargetSec && (TargetSec->Flags & SHF_ALLOC)) {
860
// If the relocation section comes *after* the target section, we
861
// don't add Config.AllocSectionsPrefix because we've already added
862
// the prefix to TargetSec->Name. Otherwise, if the relocation
863
// section comes *before* the target section, we add the prefix.
864
if (PrefixedSections.count(TargetSec))
865
Sec.Name = (RelocSec->getNamePrefix() + TargetSec->Name).str();
866
else
867
Sec.Name = (RelocSec->getNamePrefix() + Config.AllocSectionsPrefix +
868
TargetSec->Name)
869
.str();
870
}
871
}
872
}
873
}
874
875
if (ELFConfig.EntryExpr)
876
Obj.Entry = ELFConfig.EntryExpr(Obj.Entry);
877
return Error::success();
878
}
879
880
static Error writeOutput(const CommonConfig &Config, Object &Obj,
881
raw_ostream &Out, ElfType OutputElfType) {
882
std::unique_ptr<Writer> Writer =
883
createWriter(Config, Obj, Out, OutputElfType);
884
if (Error E = Writer->finalize())
885
return E;
886
return Writer->write();
887
}
888
889
Error objcopy::elf::executeObjcopyOnIHex(const CommonConfig &Config,
890
const ELFConfig &ELFConfig,
891
MemoryBuffer &In, raw_ostream &Out) {
892
IHexReader Reader(&In);
893
Expected<std::unique_ptr<Object>> Obj = Reader.create(true);
894
if (!Obj)
895
return Obj.takeError();
896
897
const ElfType OutputElfType =
898
getOutputElfType(Config.OutputArch.value_or(MachineInfo()));
899
if (Error E = handleArgs(Config, ELFConfig, OutputElfType, **Obj))
900
return E;
901
return writeOutput(Config, **Obj, Out, OutputElfType);
902
}
903
904
Error objcopy::elf::executeObjcopyOnRawBinary(const CommonConfig &Config,
905
const ELFConfig &ELFConfig,
906
MemoryBuffer &In,
907
raw_ostream &Out) {
908
BinaryReader Reader(&In, ELFConfig.NewSymbolVisibility);
909
Expected<std::unique_ptr<Object>> Obj = Reader.create(true);
910
if (!Obj)
911
return Obj.takeError();
912
913
// Prefer OutputArch (-O<format>) if set, otherwise fallback to BinaryArch
914
// (-B<arch>).
915
const ElfType OutputElfType =
916
getOutputElfType(Config.OutputArch.value_or(MachineInfo()));
917
if (Error E = handleArgs(Config, ELFConfig, OutputElfType, **Obj))
918
return E;
919
return writeOutput(Config, **Obj, Out, OutputElfType);
920
}
921
922
Error objcopy::elf::executeObjcopyOnBinary(const CommonConfig &Config,
923
const ELFConfig &ELFConfig,
924
object::ELFObjectFileBase &In,
925
raw_ostream &Out) {
926
ELFReader Reader(&In, Config.ExtractPartition);
927
Expected<std::unique_ptr<Object>> Obj =
928
Reader.create(!Config.SymbolsToAdd.empty());
929
if (!Obj)
930
return Obj.takeError();
931
// Prefer OutputArch (-O<format>) if set, otherwise infer it from the input.
932
const ElfType OutputElfType = Config.OutputArch
933
? getOutputElfType(*Config.OutputArch)
934
: getOutputElfType(In);
935
936
if (Error E = handleArgs(Config, ELFConfig, OutputElfType, **Obj))
937
return createFileError(Config.InputFilename, std::move(E));
938
939
if (Error E = writeOutput(Config, **Obj, Out, OutputElfType))
940
return createFileError(Config.InputFilename, std::move(E));
941
942
return Error::success();
943
}
944
945