1 //===- ELFObjcopy.cpp -----------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
43 #include <system_error>
47 using namespace llvm::ELF
;
48 using namespace llvm::objcopy
;
49 using namespace llvm::objcopy::elf
;
50 using namespace llvm::object
;
52 using SectionPred
= std::function
<bool(const SectionBase
&Sec
)>;
54 static bool isDebugSection(const SectionBase
&Sec
) {
55 return StringRef(Sec
.Name
).starts_with(".debug") || Sec
.Name
== ".gdb_index";
58 static bool isDWOSection(const SectionBase
&Sec
) {
59 return StringRef(Sec
.Name
).ends_with(".dwo");
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
)
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
);
71 static Expected
<uint64_t> getNewShfFlags(SectionFlag AllFlags
,
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
;
96 static uint64_t getSectionFlagsPreserveMask(uint64_t OldFlags
,
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
) &
106 ~(EMachine
== EM_X86_64
? (uint64_t)ELF::SHF_X86_64_LARGE
: 0UL);
107 return (OldFlags
& PreserveMask
) | (NewFlags
& ~PreserveMask
);
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)));
118 static Error
setSectionFlagsAndType(SectionBase
&Sec
, SectionFlag Flags
,
120 Expected
<uint64_t> NewFlags
= getNewShfFlags(Flags
, EMachine
);
122 return NewFlags
.takeError();
123 Sec
.Flags
= getSectionFlagsPreserveMask(Sec
.Flags
, *NewFlags
, EMachine
);
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
);
133 return Error::success();
136 static ElfType
getOutputElfType(const Binary
&Bin
) {
137 // Infer output ELF type from the input ELF object
138 if (isa
<ELFObjectFile
<ELF32LE
>>(Bin
))
140 if (isa
<ELFObjectFile
<ELF64LE
>>(Bin
))
142 if (isa
<ELFObjectFile
<ELF32BE
>>(Bin
))
144 if (isa
<ELFObjectFile
<ELF64BE
>>(Bin
))
146 llvm_unreachable("Invalid ELFType");
149 static ElfType
getOutputElfType(const MachineInfo
&MI
) {
150 // Infer output ELF type from the binary arch specified
152 return MI
.IsLittleEndian
? ELFT_ELF64LE
: ELFT_ELF64BE
;
154 return MI
.IsLittleEndian
? ELFT_ELF32LE
: ELFT_ELF32BE
;
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
) {
163 return std::make_unique
<ELFWriter
<ELF32LE
>>(Obj
, Out
, !Config
.StripSections
,
164 Config
.OnlyKeepDebug
);
166 return std::make_unique
<ELFWriter
<ELF64LE
>>(Obj
, Out
, !Config
.StripSections
,
167 Config
.OnlyKeepDebug
);
169 return std::make_unique
<ELFWriter
<ELF32BE
>>(Obj
, Out
, !Config
.StripSections
,
170 Config
.OnlyKeepDebug
);
172 return std::make_unique
<ELFWriter
<ELF64BE
>>(Obj
, Out
, !Config
.StripSections
,
173 Config
.OnlyKeepDebug
);
175 llvm_unreachable("Invalid output format");
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
);
187 return createELFWriter(Config
, Obj
, Out
, OutputElfType
);
191 static Error
dumpSectionToFile(StringRef SecName
, StringRef Filename
,
193 for (auto &Sec
: Obj
.sections()) {
194 if (Sec
.Name
== SecName
) {
195 if (Sec
.Type
== SHT_NOBITS
)
196 return createStringError(object_error::parse_failed
,
197 "cannot dump section '%s': it has no contents",
198 SecName
.str().c_str());
199 Expected
<std::unique_ptr
<FileOutputBuffer
>> BufferOrErr
=
200 FileOutputBuffer::create(Filename
, Sec
.OriginalData
.size());
202 return BufferOrErr
.takeError();
203 std::unique_ptr
<FileOutputBuffer
> Buf
= std::move(*BufferOrErr
);
204 std::copy(Sec
.OriginalData
.begin(), Sec
.OriginalData
.end(),
205 Buf
->getBufferStart());
206 if (Error E
= Buf
->commit())
208 return Error::success();
211 return createStringError(object_error::parse_failed
, "section '%s' not found",
212 SecName
.str().c_str());
215 static bool isCompressable(const SectionBase
&Sec
) {
216 return !(Sec
.Flags
& ELF::SHF_COMPRESSED
) &&
217 StringRef(Sec
.Name
).starts_with(".debug");
220 static Error
replaceDebugSections(
221 Object
&Obj
, function_ref
<bool(const SectionBase
&)> ShouldReplace
,
222 function_ref
<Expected
<SectionBase
*>(const SectionBase
*)> AddSection
) {
223 // Build a list of the debug sections we are going to replace.
224 // We can't call `AddSection` while iterating over sections,
225 // because it would mutate the sections array.
226 SmallVector
<SectionBase
*, 13> ToReplace
;
227 for (auto &Sec
: Obj
.sections())
228 if (ShouldReplace(Sec
))
229 ToReplace
.push_back(&Sec
);
231 // Build a mapping from original section to a new one.
232 DenseMap
<SectionBase
*, SectionBase
*> FromTo
;
233 for (SectionBase
*S
: ToReplace
) {
234 Expected
<SectionBase
*> NewSection
= AddSection(S
);
236 return NewSection
.takeError();
238 FromTo
[S
] = *NewSection
;
241 return Obj
.replaceSections(FromTo
);
244 static bool isAArch64MappingSymbol(const Symbol
&Sym
) {
245 if (Sym
.Binding
!= STB_LOCAL
|| Sym
.Type
!= STT_NOTYPE
||
246 Sym
.getShndx() == SHN_UNDEF
)
248 StringRef Name
= Sym
.Name
;
249 if (!Name
.consume_front("$x") && !Name
.consume_front("$d"))
251 return Name
.empty() || Name
.starts_with(".");
254 static bool isArmMappingSymbol(const Symbol
&Sym
) {
255 if (Sym
.Binding
!= STB_LOCAL
|| Sym
.Type
!= STT_NOTYPE
||
256 Sym
.getShndx() == SHN_UNDEF
)
258 StringRef Name
= Sym
.Name
;
259 if (!Name
.consume_front("$a") && !Name
.consume_front("$d") &&
260 !Name
.consume_front("$t"))
262 return Name
.empty() || Name
.starts_with(".");
265 // Check if the symbol should be preserved because it is required by ABI.
266 static bool isRequiredByABISymbol(const Object
&Obj
, const Symbol
&Sym
) {
267 switch (Obj
.Machine
) {
269 // Mapping symbols should be preserved for a relocatable object file.
270 return Obj
.isRelocatable() && isAArch64MappingSymbol(Sym
);
272 // Mapping symbols should be preserved for a relocatable object file.
273 return Obj
.isRelocatable() && isArmMappingSymbol(Sym
);
279 static bool isUnneededSymbol(const Symbol
&Sym
) {
280 return !Sym
.Referenced
&&
281 (Sym
.Binding
== STB_LOCAL
|| Sym
.getShndx() == SHN_UNDEF
) &&
282 Sym
.Type
!= STT_SECTION
;
285 static Error
updateAndRemoveSymbols(const CommonConfig
&Config
,
286 const ELFConfig
&ELFConfig
, Object
&Obj
) {
287 // TODO: update or remove symbols only if there is an option that affects
289 if (!Obj
.SymbolTable
)
290 return Error::success();
292 Obj
.SymbolTable
->updateSymbols([&](Symbol
&Sym
) {
293 // Common and undefined symbols don't make sense as local symbols, and can
294 // even cause crashes if we localize those, so skip them.
295 if (!Sym
.isCommon() && Sym
.getShndx() != SHN_UNDEF
&&
296 ((ELFConfig
.LocalizeHidden
&&
297 (Sym
.Visibility
== STV_HIDDEN
|| Sym
.Visibility
== STV_INTERNAL
)) ||
298 Config
.SymbolsToLocalize
.matches(Sym
.Name
)))
299 Sym
.Binding
= STB_LOCAL
;
301 // Note: these two globalize flags have very similar names but different
304 // --globalize-symbol: promote a symbol to global
305 // --keep-global-symbol: all symbols except for these should be made local
307 // If --globalize-symbol is specified for a given symbol, it will be
308 // global in the output file even if it is not included via
309 // --keep-global-symbol. Because of that, make sure to check
310 // --globalize-symbol second.
311 if (!Config
.SymbolsToKeepGlobal
.empty() &&
312 !Config
.SymbolsToKeepGlobal
.matches(Sym
.Name
) &&
313 Sym
.getShndx() != SHN_UNDEF
)
314 Sym
.Binding
= STB_LOCAL
;
316 if (Config
.SymbolsToGlobalize
.matches(Sym
.Name
) &&
317 Sym
.getShndx() != SHN_UNDEF
)
318 Sym
.Binding
= STB_GLOBAL
;
320 // SymbolsToWeaken applies to both STB_GLOBAL and STB_GNU_UNIQUE.
321 if (Config
.SymbolsToWeaken
.matches(Sym
.Name
) && Sym
.Binding
!= STB_LOCAL
)
322 Sym
.Binding
= STB_WEAK
;
324 if (Config
.Weaken
&& Sym
.Binding
!= STB_LOCAL
&&
325 Sym
.getShndx() != SHN_UNDEF
)
326 Sym
.Binding
= STB_WEAK
;
328 const auto I
= Config
.SymbolsToRename
.find(Sym
.Name
);
329 if (I
!= Config
.SymbolsToRename
.end())
330 Sym
.Name
= std::string(I
->getValue());
332 if (!Config
.SymbolsPrefix
.empty() && Sym
.Type
!= STT_SECTION
)
333 Sym
.Name
= (Config
.SymbolsPrefix
+ Sym
.Name
).str();
336 // The purpose of this loop is to mark symbols referenced by sections
337 // (like GroupSection or RelocationSection). This way, we know which
338 // symbols are still 'needed' and which are not.
339 if (Config
.StripUnneeded
|| !Config
.UnneededSymbolsToRemove
.empty() ||
340 !Config
.OnlySection
.empty()) {
341 for (SectionBase
&Sec
: Obj
.sections())
345 auto RemoveSymbolsPred
= [&](const Symbol
&Sym
) {
346 if (Config
.SymbolsToKeep
.matches(Sym
.Name
) ||
347 (ELFConfig
.KeepFileSymbols
&& Sym
.Type
== STT_FILE
))
350 if (Config
.SymbolsToRemove
.matches(Sym
.Name
))
353 if (Config
.StripAll
|| Config
.StripAllGNU
)
356 if (isRequiredByABISymbol(Obj
, Sym
))
359 if (Config
.StripDebug
&& Sym
.Type
== STT_FILE
)
362 if ((Config
.DiscardMode
== DiscardType::All
||
363 (Config
.DiscardMode
== DiscardType::Locals
&&
364 StringRef(Sym
.Name
).starts_with(".L"))) &&
365 Sym
.Binding
== STB_LOCAL
&& Sym
.getShndx() != SHN_UNDEF
&&
366 Sym
.Type
!= STT_FILE
&& Sym
.Type
!= STT_SECTION
)
369 if ((Config
.StripUnneeded
||
370 Config
.UnneededSymbolsToRemove
.matches(Sym
.Name
)) &&
371 (!Obj
.isRelocatable() || isUnneededSymbol(Sym
)))
374 // We want to remove undefined symbols if all references have been stripped.
375 if (!Config
.OnlySection
.empty() && !Sym
.Referenced
&&
376 Sym
.getShndx() == SHN_UNDEF
)
382 return Obj
.removeSymbols(RemoveSymbolsPred
);
385 static Error
replaceAndRemoveSections(const CommonConfig
&Config
,
386 const ELFConfig
&ELFConfig
, Object
&Obj
) {
387 SectionPred RemovePred
= [](const SectionBase
&) { return false; };
390 if (!Config
.ToRemove
.empty()) {
391 RemovePred
= [&Config
](const SectionBase
&Sec
) {
392 return Config
.ToRemove
.matches(Sec
.Name
);
397 RemovePred
= [RemovePred
](const SectionBase
&Sec
) {
398 return isDWOSection(Sec
) || RemovePred(Sec
);
401 if (Config
.ExtractDWO
)
402 RemovePred
= [RemovePred
, &Obj
](const SectionBase
&Sec
) {
403 return onlyKeepDWOPred(Obj
, Sec
) || RemovePred(Sec
);
406 if (Config
.StripAllGNU
)
407 RemovePred
= [RemovePred
, &Obj
](const SectionBase
&Sec
) {
410 if ((Sec
.Flags
& SHF_ALLOC
) != 0)
412 if (&Sec
== Obj
.SectionNames
)
421 return isDebugSection(Sec
);
424 if (Config
.StripSections
) {
425 RemovePred
= [RemovePred
](const SectionBase
&Sec
) {
426 return RemovePred(Sec
) || Sec
.ParentSegment
== nullptr;
430 if (Config
.StripDebug
|| Config
.StripUnneeded
) {
431 RemovePred
= [RemovePred
](const SectionBase
&Sec
) {
432 return RemovePred(Sec
) || isDebugSection(Sec
);
436 if (Config
.StripNonAlloc
)
437 RemovePred
= [RemovePred
, &Obj
](const SectionBase
&Sec
) {
440 if (&Sec
== Obj
.SectionNames
)
442 return (Sec
.Flags
& SHF_ALLOC
) == 0 && Sec
.ParentSegment
== nullptr;
446 RemovePred
= [RemovePred
, &Obj
](const SectionBase
&Sec
) {
449 if (&Sec
== Obj
.SectionNames
)
451 if (StringRef(Sec
.Name
).starts_with(".gnu.warning"))
453 // We keep the .ARM.attribute section to maintain compatibility
454 // with Debian derived distributions. This is a bug in their
455 // patchset as documented here:
456 // https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=943798
457 if (Sec
.Type
== SHT_ARM_ATTRIBUTES
)
459 if (Sec
.ParentSegment
!= nullptr)
461 return (Sec
.Flags
& SHF_ALLOC
) == 0;
464 if (Config
.ExtractPartition
|| Config
.ExtractMainPartition
) {
465 RemovePred
= [RemovePred
](const SectionBase
&Sec
) {
468 if (Sec
.Type
== SHT_LLVM_PART_EHDR
|| Sec
.Type
== SHT_LLVM_PART_PHDR
)
470 return (Sec
.Flags
& SHF_ALLOC
) != 0 && !Sec
.ParentSegment
;
475 if (!Config
.OnlySection
.empty()) {
476 RemovePred
= [&Config
, RemovePred
, &Obj
](const SectionBase
&Sec
) {
477 // Explicitly keep these sections regardless of previous removes.
478 if (Config
.OnlySection
.matches(Sec
.Name
))
481 // Allow all implicit removes.
485 // Keep special sections.
486 if (Obj
.SectionNames
== &Sec
)
488 if (Obj
.SymbolTable
== &Sec
||
489 (Obj
.SymbolTable
&& Obj
.SymbolTable
->getStrTab() == &Sec
))
492 // Remove everything else.
497 if (!Config
.KeepSection
.empty()) {
498 RemovePred
= [&Config
, RemovePred
](const SectionBase
&Sec
) {
499 // Explicitly keep these sections regardless of previous removes.
500 if (Config
.KeepSection
.matches(Sec
.Name
))
502 // Otherwise defer to RemovePred.
503 return RemovePred(Sec
);
507 // This has to be the last predicate assignment.
508 // If the option --keep-symbol has been specified
509 // and at least one of those symbols is present
510 // (equivalently, the updated symbol table is not empty)
511 // the symbol table and the string table should not be removed.
512 if ((!Config
.SymbolsToKeep
.empty() || ELFConfig
.KeepFileSymbols
) &&
513 Obj
.SymbolTable
&& !Obj
.SymbolTable
->empty()) {
514 RemovePred
= [&Obj
, RemovePred
](const SectionBase
&Sec
) {
515 if (&Sec
== Obj
.SymbolTable
|| &Sec
== Obj
.SymbolTable
->getStrTab())
517 return RemovePred(Sec
);
521 if (Error E
= Obj
.removeSections(ELFConfig
.AllowBrokenLinks
, RemovePred
))
524 if (Config
.CompressionType
!= DebugCompressionType::None
) {
525 if (Error Err
= replaceDebugSections(
527 [&Config
, &Obj
](const SectionBase
*S
) -> Expected
<SectionBase
*> {
528 return &Obj
.addSection
<CompressedSection
>(
529 CompressedSection(*S
, Config
.CompressionType
, Obj
.Is64Bits
));
532 } else if (Config
.DecompressDebugSections
) {
533 if (Error Err
= replaceDebugSections(
535 [](const SectionBase
&S
) { return isa
<CompressedSection
>(&S
); },
536 [&Obj
](const SectionBase
*S
) {
537 const CompressedSection
*CS
= cast
<CompressedSection
>(S
);
538 return &Obj
.addSection
<DecompressedSection
>(*CS
);
543 return Error::success();
546 // Add symbol to the Object symbol table with the specified properties.
547 static void addSymbol(Object
&Obj
, const NewSymbolInfo
&SymInfo
,
548 uint8_t DefaultVisibility
) {
549 SectionBase
*Sec
= Obj
.findSection(SymInfo
.SectionName
);
550 uint64_t Value
= Sec
? Sec
->Addr
+ SymInfo
.Value
: SymInfo
.Value
;
552 uint8_t Bind
= ELF::STB_GLOBAL
;
553 uint8_t Type
= ELF::STT_NOTYPE
;
554 uint8_t Visibility
= DefaultVisibility
;
556 for (SymbolFlag FlagValue
: SymInfo
.Flags
)
558 case SymbolFlag::Global
:
559 Bind
= ELF::STB_GLOBAL
;
561 case SymbolFlag::Local
:
562 Bind
= ELF::STB_LOCAL
;
564 case SymbolFlag::Weak
:
565 Bind
= ELF::STB_WEAK
;
567 case SymbolFlag::Default
:
568 Visibility
= ELF::STV_DEFAULT
;
570 case SymbolFlag::Hidden
:
571 Visibility
= ELF::STV_HIDDEN
;
573 case SymbolFlag::Protected
:
574 Visibility
= ELF::STV_PROTECTED
;
576 case SymbolFlag::File
:
577 Type
= ELF::STT_FILE
;
579 case SymbolFlag::Section
:
580 Type
= ELF::STT_SECTION
;
582 case SymbolFlag::Object
:
583 Type
= ELF::STT_OBJECT
;
585 case SymbolFlag::Function
:
586 Type
= ELF::STT_FUNC
;
588 case SymbolFlag::IndirectFunction
:
589 Type
= ELF::STT_GNU_IFUNC
;
591 default: /* Other flag values are ignored for ELF. */
595 Obj
.SymbolTable
->addSymbol(
596 SymInfo
.SymbolName
, Bind
, Type
, Sec
, Value
, Visibility
,
597 Sec
? (uint16_t)SYMBOL_SIMPLE_INDEX
: (uint16_t)SHN_ABS
, 0);
601 handleUserSection(const NewSectionInfo
&NewSection
,
602 function_ref
<Error(StringRef
, ArrayRef
<uint8_t>)> F
) {
603 ArrayRef
<uint8_t> Data(reinterpret_cast<const uint8_t *>(
604 NewSection
.SectionData
->getBufferStart()),
605 NewSection
.SectionData
->getBufferSize());
606 return F(NewSection
.SectionName
, Data
);
609 // This function handles the high level operations of GNU objcopy including
610 // handling command line options. It's important to outline certain properties
611 // we expect to hold of the command line operations. Any operation that "keeps"
612 // should keep regardless of a remove. Additionally any removal should respect
613 // any previous removals. Lastly whether or not something is removed shouldn't
614 // depend a) on the order the options occur in or b) on some opaque priority
615 // system. The only priority is that keeps/copies overrule removes.
616 static Error
handleArgs(const CommonConfig
&Config
, const ELFConfig
&ELFConfig
,
618 if (Config
.OutputArch
) {
619 Obj
.Machine
= Config
.OutputArch
->EMachine
;
620 Obj
.OSABI
= Config
.OutputArch
->OSABI
;
623 if (!Config
.SplitDWO
.empty() && Config
.ExtractDWO
) {
624 return Obj
.removeSections(
625 ELFConfig
.AllowBrokenLinks
,
626 [&Obj
](const SectionBase
&Sec
) { return onlyKeepDWOPred(Obj
, Sec
); });
629 // Dump sections before add/remove for compatibility with GNU objcopy.
630 for (StringRef Flag
: Config
.DumpSection
) {
631 StringRef SectionName
;
633 std::tie(SectionName
, FileName
) = Flag
.split('=');
634 if (Error E
= dumpSectionToFile(SectionName
, FileName
, Obj
))
638 // It is important to remove the sections first. For example, we want to
639 // remove the relocation sections before removing the symbols. That allows
640 // us to avoid reporting the inappropriate errors about removing symbols
641 // named in relocations.
642 if (Error E
= replaceAndRemoveSections(Config
, ELFConfig
, Obj
))
645 if (Error E
= updateAndRemoveSymbols(Config
, ELFConfig
, Obj
))
648 if (!Config
.SetSectionAlignment
.empty()) {
649 for (SectionBase
&Sec
: Obj
.sections()) {
650 auto I
= Config
.SetSectionAlignment
.find(Sec
.Name
);
651 if (I
!= Config
.SetSectionAlignment
.end())
652 Sec
.Align
= I
->second
;
656 if (Config
.OnlyKeepDebug
)
657 for (auto &Sec
: Obj
.sections())
658 if (Sec
.Flags
& SHF_ALLOC
&& Sec
.Type
!= SHT_NOTE
)
659 Sec
.Type
= SHT_NOBITS
;
661 for (const NewSectionInfo
&AddedSection
: Config
.AddSection
) {
662 auto AddSection
= [&](StringRef Name
, ArrayRef
<uint8_t> Data
) {
663 OwnedDataSection
&NewSection
=
664 Obj
.addSection
<OwnedDataSection
>(Name
, Data
);
665 if (Name
.starts_with(".note") && Name
!= ".note.GNU-stack")
666 NewSection
.Type
= SHT_NOTE
;
667 return Error::success();
669 if (Error E
= handleUserSection(AddedSection
, AddSection
))
673 for (const NewSectionInfo
&NewSection
: Config
.UpdateSection
) {
674 auto UpdateSection
= [&](StringRef Name
, ArrayRef
<uint8_t> Data
) {
675 return Obj
.updateSection(Name
, Data
);
677 if (Error E
= handleUserSection(NewSection
, UpdateSection
))
681 if (!Config
.AddGnuDebugLink
.empty())
682 Obj
.addSection
<GnuDebugLinkSection
>(Config
.AddGnuDebugLink
,
683 Config
.GnuDebugLinkCRC32
);
685 // If the symbol table was previously removed, we need to create a new one
686 // before adding new symbols.
687 if (!Obj
.SymbolTable
&& !Config
.SymbolsToAdd
.empty())
688 if (Error E
= Obj
.addNewSymbolTable())
691 for (const NewSymbolInfo
&SI
: Config
.SymbolsToAdd
)
692 addSymbol(Obj
, SI
, ELFConfig
.NewSymbolVisibility
);
694 // --set-section-{flags,type} work with sections added by --add-section.
695 if (!Config
.SetSectionFlags
.empty() || !Config
.SetSectionType
.empty()) {
696 for (auto &Sec
: Obj
.sections()) {
697 const auto Iter
= Config
.SetSectionFlags
.find(Sec
.Name
);
698 if (Iter
!= Config
.SetSectionFlags
.end()) {
699 const SectionFlagsUpdate
&SFU
= Iter
->second
;
700 if (Error E
= setSectionFlagsAndType(Sec
, SFU
.NewFlags
, Obj
.Machine
))
703 auto It2
= Config
.SetSectionType
.find(Sec
.Name
);
704 if (It2
!= Config
.SetSectionType
.end())
705 setSectionType(Sec
, It2
->second
);
709 if (!Config
.SectionsToRename
.empty()) {
710 std::vector
<RelocationSectionBase
*> RelocSections
;
711 DenseSet
<SectionBase
*> RenamedSections
;
712 for (SectionBase
&Sec
: Obj
.sections()) {
713 auto *RelocSec
= dyn_cast
<RelocationSectionBase
>(&Sec
);
714 const auto Iter
= Config
.SectionsToRename
.find(Sec
.Name
);
715 if (Iter
!= Config
.SectionsToRename
.end()) {
716 const SectionRename
&SR
= Iter
->second
;
717 Sec
.Name
= std::string(SR
.NewName
);
719 if (Error E
= setSectionFlagsAndType(Sec
, *SR
.NewFlags
, Obj
.Machine
))
722 RenamedSections
.insert(&Sec
);
723 } else if (RelocSec
&& !(Sec
.Flags
& SHF_ALLOC
))
724 // Postpone processing relocation sections which are not specified in
725 // their explicit '--rename-section' commands until after their target
726 // sections are renamed.
727 // Dynamic relocation sections (i.e. ones with SHF_ALLOC) should be
728 // renamed only explicitly. Otherwise, renaming, for example, '.got.plt'
729 // would affect '.rela.plt', which is not desirable.
730 RelocSections
.push_back(RelocSec
);
733 // Rename relocation sections according to their target sections.
734 for (RelocationSectionBase
*RelocSec
: RelocSections
) {
735 auto Iter
= RenamedSections
.find(RelocSec
->getSection());
736 if (Iter
!= RenamedSections
.end())
737 RelocSec
->Name
= (RelocSec
->getNamePrefix() + (*Iter
)->Name
).str();
741 // Add a prefix to allocated sections and their relocation sections. This
742 // should be done after renaming the section by Config.SectionToRename to
743 // imitate the GNU objcopy behavior.
744 if (!Config
.AllocSectionsPrefix
.empty()) {
745 DenseSet
<SectionBase
*> PrefixedSections
;
746 for (SectionBase
&Sec
: Obj
.sections()) {
747 if (Sec
.Flags
& SHF_ALLOC
) {
748 Sec
.Name
= (Config
.AllocSectionsPrefix
+ Sec
.Name
).str();
749 PrefixedSections
.insert(&Sec
);
750 } else if (auto *RelocSec
= dyn_cast
<RelocationSectionBase
>(&Sec
)) {
751 // Rename relocation sections associated to the allocated sections.
752 // For example, if we rename .text to .prefix.text, we also rename
753 // .rel.text to .rel.prefix.text.
755 // Dynamic relocation sections (SHT_REL[A] with SHF_ALLOC) are handled
756 // above, e.g., .rela.plt is renamed to .prefix.rela.plt, not
757 // .rela.prefix.plt since GNU objcopy does so.
758 const SectionBase
*TargetSec
= RelocSec
->getSection();
759 if (TargetSec
&& (TargetSec
->Flags
& SHF_ALLOC
)) {
760 // If the relocation section comes *after* the target section, we
761 // don't add Config.AllocSectionsPrefix because we've already added
762 // the prefix to TargetSec->Name. Otherwise, if the relocation
763 // section comes *before* the target section, we add the prefix.
764 if (PrefixedSections
.count(TargetSec
))
765 Sec
.Name
= (RelocSec
->getNamePrefix() + TargetSec
->Name
).str();
767 Sec
.Name
= (RelocSec
->getNamePrefix() + Config
.AllocSectionsPrefix
+
775 if (ELFConfig
.EntryExpr
)
776 Obj
.Entry
= ELFConfig
.EntryExpr(Obj
.Entry
);
777 return Error::success();
780 static Error
writeOutput(const CommonConfig
&Config
, Object
&Obj
,
781 raw_ostream
&Out
, ElfType OutputElfType
) {
782 std::unique_ptr
<Writer
> Writer
=
783 createWriter(Config
, Obj
, Out
, OutputElfType
);
784 if (Error E
= Writer
->finalize())
786 return Writer
->write();
789 Error
objcopy::elf::executeObjcopyOnIHex(const CommonConfig
&Config
,
790 const ELFConfig
&ELFConfig
,
791 MemoryBuffer
&In
, raw_ostream
&Out
) {
792 IHexReader
Reader(&In
);
793 Expected
<std::unique_ptr
<Object
>> Obj
= Reader
.create(true);
795 return Obj
.takeError();
797 const ElfType OutputElfType
=
798 getOutputElfType(Config
.OutputArch
.value_or(MachineInfo()));
799 if (Error E
= handleArgs(Config
, ELFConfig
, **Obj
))
801 return writeOutput(Config
, **Obj
, Out
, OutputElfType
);
804 Error
objcopy::elf::executeObjcopyOnRawBinary(const CommonConfig
&Config
,
805 const ELFConfig
&ELFConfig
,
808 BinaryReader
Reader(&In
, ELFConfig
.NewSymbolVisibility
);
809 Expected
<std::unique_ptr
<Object
>> Obj
= Reader
.create(true);
811 return Obj
.takeError();
813 // Prefer OutputArch (-O<format>) if set, otherwise fallback to BinaryArch
815 const ElfType OutputElfType
=
816 getOutputElfType(Config
.OutputArch
.value_or(MachineInfo()));
817 if (Error E
= handleArgs(Config
, ELFConfig
, **Obj
))
819 return writeOutput(Config
, **Obj
, Out
, OutputElfType
);
822 Error
objcopy::elf::executeObjcopyOnBinary(const CommonConfig
&Config
,
823 const ELFConfig
&ELFConfig
,
824 object::ELFObjectFileBase
&In
,
826 ELFReader
Reader(&In
, Config
.ExtractPartition
);
827 Expected
<std::unique_ptr
<Object
>> Obj
=
828 Reader
.create(!Config
.SymbolsToAdd
.empty());
830 return Obj
.takeError();
831 // Prefer OutputArch (-O<format>) if set, otherwise infer it from the input.
832 const ElfType OutputElfType
= Config
.OutputArch
833 ? getOutputElfType(*Config
.OutputArch
)
834 : getOutputElfType(In
);
836 if (Error E
= handleArgs(Config
, ELFConfig
, **Obj
))
837 return createFileError(Config
.InputFilename
, std::move(E
));
839 if (Error E
= writeOutput(Config
, **Obj
, Out
, OutputElfType
))
840 return createFileError(Config
.InputFilename
, std::move(E
));
842 return Error::success();