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/SmallVector.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/ADT/Twine.h"
16 #include "llvm/BinaryFormat/ELF.h"
17 #include "llvm/MC/MCTargetOptions.h"
18 #include "llvm/ObjCopy/CommonConfig.h"
19 #include "llvm/ObjCopy/ELF/ELFConfig.h"
20 #include "llvm/Object/Binary.h"
21 #include "llvm/Object/ELFObjectFile.h"
22 #include "llvm/Object/ELFTypes.h"
23 #include "llvm/Object/Error.h"
24 #include "llvm/Option/Option.h"
25 #include "llvm/Support/Casting.h"
26 #include "llvm/Support/Compression.h"
27 #include "llvm/Support/Errc.h"
28 #include "llvm/Support/Error.h"
29 #include "llvm/Support/ErrorHandling.h"
30 #include "llvm/Support/Memory.h"
31 #include "llvm/Support/raw_ostream.h"
38 #include <system_error>
42 using namespace llvm::ELF
;
43 using namespace llvm::objcopy
;
44 using namespace llvm::objcopy::elf
;
45 using namespace llvm::object
;
47 using SectionPred
= std::function
<bool(const SectionBase
&Sec
)>;
49 static bool isDebugSection(const SectionBase
&Sec
) {
50 return StringRef(Sec
.Name
).starts_with(".debug") || Sec
.Name
== ".gdb_index";
53 static bool isDWOSection(const SectionBase
&Sec
) {
54 return StringRef(Sec
.Name
).ends_with(".dwo");
57 static bool onlyKeepDWOPred(const Object
&Obj
, const SectionBase
&Sec
) {
58 // We can't remove the section header string table.
59 if (&Sec
== Obj
.SectionNames
)
61 // Short of keeping the string table we want to keep everything that is a DWO
62 // section and remove everything else.
63 return !isDWOSection(Sec
);
66 static Expected
<uint64_t> getNewShfFlags(SectionFlag AllFlags
,
68 uint64_t NewFlags
= 0;
69 if (AllFlags
& SectionFlag::SecAlloc
)
70 NewFlags
|= ELF::SHF_ALLOC
;
71 if (!(AllFlags
& SectionFlag::SecReadonly
))
72 NewFlags
|= ELF::SHF_WRITE
;
73 if (AllFlags
& SectionFlag::SecCode
)
74 NewFlags
|= ELF::SHF_EXECINSTR
;
75 if (AllFlags
& SectionFlag::SecMerge
)
76 NewFlags
|= ELF::SHF_MERGE
;
77 if (AllFlags
& SectionFlag::SecStrings
)
78 NewFlags
|= ELF::SHF_STRINGS
;
79 if (AllFlags
& SectionFlag::SecExclude
)
80 NewFlags
|= ELF::SHF_EXCLUDE
;
81 if (AllFlags
& SectionFlag::SecLarge
) {
82 if (EMachine
!= EM_X86_64
)
83 return createStringError(errc::invalid_argument
,
84 "section flag SHF_X86_64_LARGE can only be used "
85 "with x86_64 architecture");
86 NewFlags
|= ELF::SHF_X86_64_LARGE
;
91 static uint64_t getSectionFlagsPreserveMask(uint64_t OldFlags
,
94 // Preserve some flags which should not be dropped when setting flags.
95 // Also, preserve anything OS/processor dependant.
96 const uint64_t PreserveMask
=
97 (ELF::SHF_COMPRESSED
| ELF::SHF_GROUP
| ELF::SHF_LINK_ORDER
|
98 ELF::SHF_MASKOS
| ELF::SHF_MASKPROC
| ELF::SHF_TLS
|
101 ~(EMachine
== EM_X86_64
? (uint64_t)ELF::SHF_X86_64_LARGE
: 0UL);
102 return (OldFlags
& PreserveMask
) | (NewFlags
& ~PreserveMask
);
105 static void setSectionType(SectionBase
&Sec
, uint64_t Type
) {
106 // If Sec's type is changed from SHT_NOBITS due to --set-section-flags,
107 // Offset may not be aligned. Align it to max(Align, 1).
108 if (Sec
.Type
== ELF::SHT_NOBITS
&& Type
!= ELF::SHT_NOBITS
)
109 Sec
.Offset
= alignTo(Sec
.Offset
, std::max(Sec
.Align
, uint64_t(1)));
113 static Error
setSectionFlagsAndType(SectionBase
&Sec
, SectionFlag Flags
,
115 Expected
<uint64_t> NewFlags
= getNewShfFlags(Flags
, EMachine
);
117 return NewFlags
.takeError();
118 Sec
.Flags
= getSectionFlagsPreserveMask(Sec
.Flags
, *NewFlags
, EMachine
);
120 // In GNU objcopy, certain flags promote SHT_NOBITS to SHT_PROGBITS. This rule
121 // may promote more non-ALLOC sections than GNU objcopy, but it is fine as
122 // non-ALLOC SHT_NOBITS sections do not make much sense.
123 if (Sec
.Type
== SHT_NOBITS
&&
124 (!(Sec
.Flags
& ELF::SHF_ALLOC
) ||
125 Flags
& (SectionFlag::SecContents
| SectionFlag::SecLoad
)))
126 setSectionType(Sec
, ELF::SHT_PROGBITS
);
128 return Error::success();
131 static ElfType
getOutputElfType(const Binary
&Bin
) {
132 // Infer output ELF type from the input ELF object
133 if (isa
<ELFObjectFile
<ELF32LE
>>(Bin
))
135 if (isa
<ELFObjectFile
<ELF64LE
>>(Bin
))
137 if (isa
<ELFObjectFile
<ELF32BE
>>(Bin
))
139 if (isa
<ELFObjectFile
<ELF64BE
>>(Bin
))
141 llvm_unreachable("Invalid ELFType");
144 static ElfType
getOutputElfType(const MachineInfo
&MI
) {
145 // Infer output ELF type from the binary arch specified
147 return MI
.IsLittleEndian
? ELFT_ELF64LE
: ELFT_ELF64BE
;
149 return MI
.IsLittleEndian
? ELFT_ELF32LE
: ELFT_ELF32BE
;
152 static std::unique_ptr
<Writer
> createELFWriter(const CommonConfig
&Config
,
153 Object
&Obj
, raw_ostream
&Out
,
154 ElfType OutputElfType
) {
155 // Depending on the initial ELFT and OutputFormat we need a different Writer.
156 switch (OutputElfType
) {
158 return std::make_unique
<ELFWriter
<ELF32LE
>>(Obj
, Out
, !Config
.StripSections
,
159 Config
.OnlyKeepDebug
);
161 return std::make_unique
<ELFWriter
<ELF64LE
>>(Obj
, Out
, !Config
.StripSections
,
162 Config
.OnlyKeepDebug
);
164 return std::make_unique
<ELFWriter
<ELF32BE
>>(Obj
, Out
, !Config
.StripSections
,
165 Config
.OnlyKeepDebug
);
167 return std::make_unique
<ELFWriter
<ELF64BE
>>(Obj
, Out
, !Config
.StripSections
,
168 Config
.OnlyKeepDebug
);
170 llvm_unreachable("Invalid output format");
173 static std::unique_ptr
<Writer
> createWriter(const CommonConfig
&Config
,
174 Object
&Obj
, raw_ostream
&Out
,
175 ElfType OutputElfType
) {
176 switch (Config
.OutputFormat
) {
177 case FileFormat::Binary
:
178 return std::make_unique
<BinaryWriter
>(Obj
, Out
, Config
);
179 case FileFormat::IHex
:
180 return std::make_unique
<IHexWriter
>(Obj
, Out
, Config
.OutputFilename
);
181 case FileFormat::SREC
:
182 return std::make_unique
<SRECWriter
>(Obj
, Out
, Config
.OutputFilename
);
184 return createELFWriter(Config
, Obj
, Out
, OutputElfType
);
188 static Error
dumpSectionToFile(StringRef SecName
, StringRef Filename
,
190 for (auto &Sec
: Obj
.sections()) {
191 if (Sec
.Name
== SecName
) {
192 if (Sec
.Type
== SHT_NOBITS
)
193 return createStringError(object_error::parse_failed
,
194 "cannot dump section '%s': it has no contents",
195 SecName
.str().c_str());
196 Expected
<std::unique_ptr
<FileOutputBuffer
>> BufferOrErr
=
197 FileOutputBuffer::create(Filename
, Sec
.OriginalData
.size());
199 return BufferOrErr
.takeError();
200 std::unique_ptr
<FileOutputBuffer
> Buf
= std::move(*BufferOrErr
);
201 std::copy(Sec
.OriginalData
.begin(), Sec
.OriginalData
.end(),
202 Buf
->getBufferStart());
203 if (Error E
= Buf
->commit())
205 return Error::success();
208 return createStringError(object_error::parse_failed
, "section '%s' not found",
209 SecName
.str().c_str());
212 Error
Object::compressOrDecompressSections(const CommonConfig
&Config
) {
213 // Build a list of sections we are going to replace.
214 // We can't call `addSection` while iterating over sections,
215 // because it would mutate the sections array.
216 SmallVector
<std::pair
<SectionBase
*, std::function
<SectionBase
*()>>, 0>
218 for (SectionBase
&Sec
: sections()) {
219 std::optional
<DebugCompressionType
> CType
;
220 for (auto &[Matcher
, T
] : Config
.compressSections
)
221 if (Matcher
.matches(Sec
.Name
))
223 // Handle --compress-debug-sections and --decompress-debug-sections, which
224 // apply to non-ALLOC debug sections.
225 if (!(Sec
.Flags
& SHF_ALLOC
) && StringRef(Sec
.Name
).starts_with(".debug")) {
226 if (Config
.CompressionType
!= DebugCompressionType::None
)
227 CType
= Config
.CompressionType
;
228 else if (Config
.DecompressDebugSections
)
229 CType
= DebugCompressionType::None
;
234 if (Sec
.ParentSegment
)
235 return createStringError(
236 errc::invalid_argument
,
237 "section '" + Sec
.Name
+
238 "' within a segment cannot be (de)compressed");
240 if (auto *CS
= dyn_cast
<CompressedSection
>(&Sec
)) {
241 if (*CType
== DebugCompressionType::None
)
242 ToReplace
.emplace_back(
243 &Sec
, [=] { return &addSection
<DecompressedSection
>(*CS
); });
244 } else if (*CType
!= DebugCompressionType::None
) {
245 ToReplace
.emplace_back(&Sec
, [=, S
= &Sec
] {
246 return &addSection
<CompressedSection
>(
247 CompressedSection(*S
, *CType
, Is64Bits
));
252 DenseMap
<SectionBase
*, SectionBase
*> FromTo
;
253 for (auto [S
, Func
] : ToReplace
)
255 return replaceSections(FromTo
);
258 static bool isAArch64MappingSymbol(const Symbol
&Sym
) {
259 if (Sym
.Binding
!= STB_LOCAL
|| Sym
.Type
!= STT_NOTYPE
||
260 Sym
.getShndx() == SHN_UNDEF
)
262 StringRef Name
= Sym
.Name
;
263 if (!Name
.consume_front("$x") && !Name
.consume_front("$d"))
265 return Name
.empty() || Name
.starts_with(".");
268 static bool isArmMappingSymbol(const Symbol
&Sym
) {
269 if (Sym
.Binding
!= STB_LOCAL
|| Sym
.Type
!= STT_NOTYPE
||
270 Sym
.getShndx() == SHN_UNDEF
)
272 StringRef Name
= Sym
.Name
;
273 if (!Name
.consume_front("$a") && !Name
.consume_front("$d") &&
274 !Name
.consume_front("$t"))
276 return Name
.empty() || Name
.starts_with(".");
279 // Check if the symbol should be preserved because it is required by ABI.
280 static bool isRequiredByABISymbol(const Object
&Obj
, const Symbol
&Sym
) {
281 switch (Obj
.Machine
) {
283 // Mapping symbols should be preserved for a relocatable object file.
284 return Obj
.isRelocatable() && isAArch64MappingSymbol(Sym
);
286 // Mapping symbols should be preserved for a relocatable object file.
287 return Obj
.isRelocatable() && isArmMappingSymbol(Sym
);
293 static bool isUnneededSymbol(const Symbol
&Sym
) {
294 return !Sym
.Referenced
&&
295 (Sym
.Binding
== STB_LOCAL
|| Sym
.getShndx() == SHN_UNDEF
) &&
296 Sym
.Type
!= STT_SECTION
;
299 static Error
updateAndRemoveSymbols(const CommonConfig
&Config
,
300 const ELFConfig
&ELFConfig
, Object
&Obj
) {
301 // TODO: update or remove symbols only if there is an option that affects
303 if (!Obj
.SymbolTable
)
304 return Error::success();
306 Obj
.SymbolTable
->updateSymbols([&](Symbol
&Sym
) {
307 if (Config
.SymbolsToSkip
.matches(Sym
.Name
))
310 // Common and undefined symbols don't make sense as local symbols, and can
311 // even cause crashes if we localize those, so skip them.
312 if (!Sym
.isCommon() && Sym
.getShndx() != SHN_UNDEF
&&
313 ((ELFConfig
.LocalizeHidden
&&
314 (Sym
.Visibility
== STV_HIDDEN
|| Sym
.Visibility
== STV_INTERNAL
)) ||
315 Config
.SymbolsToLocalize
.matches(Sym
.Name
)))
316 Sym
.Binding
= STB_LOCAL
;
318 for (auto &[Matcher
, Visibility
] : ELFConfig
.SymbolsToSetVisibility
)
319 if (Matcher
.matches(Sym
.Name
))
320 Sym
.Visibility
= Visibility
;
322 // Note: these two globalize flags have very similar names but different
325 // --globalize-symbol: promote a symbol to global
326 // --keep-global-symbol: all symbols except for these should be made local
328 // If --globalize-symbol is specified for a given symbol, it will be
329 // global in the output file even if it is not included via
330 // --keep-global-symbol. Because of that, make sure to check
331 // --globalize-symbol second.
332 if (!Config
.SymbolsToKeepGlobal
.empty() &&
333 !Config
.SymbolsToKeepGlobal
.matches(Sym
.Name
) &&
334 Sym
.getShndx() != SHN_UNDEF
)
335 Sym
.Binding
= STB_LOCAL
;
337 if (Config
.SymbolsToGlobalize
.matches(Sym
.Name
) &&
338 Sym
.getShndx() != SHN_UNDEF
)
339 Sym
.Binding
= STB_GLOBAL
;
341 // SymbolsToWeaken applies to both STB_GLOBAL and STB_GNU_UNIQUE.
342 if (Config
.SymbolsToWeaken
.matches(Sym
.Name
) && Sym
.Binding
!= STB_LOCAL
)
343 Sym
.Binding
= STB_WEAK
;
345 if (Config
.Weaken
&& Sym
.Binding
!= STB_LOCAL
&&
346 Sym
.getShndx() != SHN_UNDEF
)
347 Sym
.Binding
= STB_WEAK
;
349 const auto I
= Config
.SymbolsToRename
.find(Sym
.Name
);
350 if (I
!= Config
.SymbolsToRename
.end())
351 Sym
.Name
= std::string(I
->getValue());
353 if (!Config
.SymbolsPrefixRemove
.empty() && Sym
.Type
!= STT_SECTION
)
354 if (Sym
.Name
.compare(0, Config
.SymbolsPrefixRemove
.size(),
355 Config
.SymbolsPrefixRemove
) == 0)
356 Sym
.Name
= Sym
.Name
.substr(Config
.SymbolsPrefixRemove
.size());
358 if (!Config
.SymbolsPrefix
.empty() && Sym
.Type
!= STT_SECTION
)
359 Sym
.Name
= (Config
.SymbolsPrefix
+ Sym
.Name
).str();
362 // The purpose of this loop is to mark symbols referenced by sections
363 // (like GroupSection or RelocationSection). This way, we know which
364 // symbols are still 'needed' and which are not.
365 if (Config
.StripUnneeded
|| !Config
.UnneededSymbolsToRemove
.empty() ||
366 !Config
.OnlySection
.empty()) {
367 for (SectionBase
&Sec
: Obj
.sections())
371 auto RemoveSymbolsPred
= [&](const Symbol
&Sym
) {
372 if (Config
.SymbolsToKeep
.matches(Sym
.Name
) ||
373 (ELFConfig
.KeepFileSymbols
&& Sym
.Type
== STT_FILE
))
376 if (Config
.SymbolsToRemove
.matches(Sym
.Name
))
379 if (Config
.StripAll
|| Config
.StripAllGNU
)
382 if (isRequiredByABISymbol(Obj
, Sym
))
385 if (Config
.StripDebug
&& Sym
.Type
== STT_FILE
)
388 if ((Config
.DiscardMode
== DiscardType::All
||
389 (Config
.DiscardMode
== DiscardType::Locals
&&
390 StringRef(Sym
.Name
).starts_with(".L"))) &&
391 Sym
.Binding
== STB_LOCAL
&& Sym
.getShndx() != SHN_UNDEF
&&
392 Sym
.Type
!= STT_FILE
&& Sym
.Type
!= STT_SECTION
)
395 if ((Config
.StripUnneeded
||
396 Config
.UnneededSymbolsToRemove
.matches(Sym
.Name
)) &&
397 (!Obj
.isRelocatable() || isUnneededSymbol(Sym
)))
400 // We want to remove undefined symbols if all references have been stripped.
401 if (!Config
.OnlySection
.empty() && !Sym
.Referenced
&&
402 Sym
.getShndx() == SHN_UNDEF
)
408 return Obj
.removeSymbols(RemoveSymbolsPred
);
411 static Error
replaceAndRemoveSections(const CommonConfig
&Config
,
412 const ELFConfig
&ELFConfig
, Object
&Obj
) {
413 SectionPred RemovePred
= [](const SectionBase
&) { return false; };
416 if (!Config
.ToRemove
.empty()) {
417 RemovePred
= [&Config
](const SectionBase
&Sec
) {
418 return Config
.ToRemove
.matches(Sec
.Name
);
423 RemovePred
= [RemovePred
](const SectionBase
&Sec
) {
424 return isDWOSection(Sec
) || RemovePred(Sec
);
427 if (Config
.ExtractDWO
)
428 RemovePred
= [RemovePred
, &Obj
](const SectionBase
&Sec
) {
429 return onlyKeepDWOPred(Obj
, Sec
) || RemovePred(Sec
);
432 if (Config
.StripAllGNU
)
433 RemovePred
= [RemovePred
, &Obj
](const SectionBase
&Sec
) {
436 if ((Sec
.Flags
& SHF_ALLOC
) != 0)
438 if (&Sec
== Obj
.SectionNames
)
447 return isDebugSection(Sec
);
450 if (Config
.StripSections
) {
451 RemovePred
= [RemovePred
](const SectionBase
&Sec
) {
452 return RemovePred(Sec
) || Sec
.ParentSegment
== nullptr;
456 if (Config
.StripDebug
|| Config
.StripUnneeded
) {
457 RemovePred
= [RemovePred
](const SectionBase
&Sec
) {
458 return RemovePred(Sec
) || isDebugSection(Sec
);
462 if (Config
.StripNonAlloc
)
463 RemovePred
= [RemovePred
, &Obj
](const SectionBase
&Sec
) {
466 if (&Sec
== Obj
.SectionNames
)
468 return (Sec
.Flags
& SHF_ALLOC
) == 0 && Sec
.ParentSegment
== nullptr;
472 RemovePred
= [RemovePred
, &Obj
](const SectionBase
&Sec
) {
475 if (&Sec
== Obj
.SectionNames
)
477 if (StringRef(Sec
.Name
).starts_with(".gnu.warning"))
479 if (StringRef(Sec
.Name
).starts_with(".gnu_debuglink"))
481 // We keep the .ARM.attribute section to maintain compatibility
482 // with Debian derived distributions. This is a bug in their
483 // patchset as documented here:
484 // https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=943798
485 if (Sec
.Type
== SHT_ARM_ATTRIBUTES
)
487 if (Sec
.ParentSegment
!= nullptr)
489 return (Sec
.Flags
& SHF_ALLOC
) == 0;
492 if (Config
.ExtractPartition
|| Config
.ExtractMainPartition
) {
493 RemovePred
= [RemovePred
](const SectionBase
&Sec
) {
496 if (Sec
.Type
== SHT_LLVM_PART_EHDR
|| Sec
.Type
== SHT_LLVM_PART_PHDR
)
498 return (Sec
.Flags
& SHF_ALLOC
) != 0 && !Sec
.ParentSegment
;
503 if (!Config
.OnlySection
.empty()) {
504 RemovePred
= [&Config
, RemovePred
, &Obj
](const SectionBase
&Sec
) {
505 // Explicitly keep these sections regardless of previous removes.
506 if (Config
.OnlySection
.matches(Sec
.Name
))
509 // Allow all implicit removes.
513 // Keep special sections.
514 if (Obj
.SectionNames
== &Sec
)
516 if (Obj
.SymbolTable
== &Sec
||
517 (Obj
.SymbolTable
&& Obj
.SymbolTable
->getStrTab() == &Sec
))
520 // Remove everything else.
525 if (!Config
.KeepSection
.empty()) {
526 RemovePred
= [&Config
, RemovePred
](const SectionBase
&Sec
) {
527 // Explicitly keep these sections regardless of previous removes.
528 if (Config
.KeepSection
.matches(Sec
.Name
))
530 // Otherwise defer to RemovePred.
531 return RemovePred(Sec
);
535 // This has to be the last predicate assignment.
536 // If the option --keep-symbol has been specified
537 // and at least one of those symbols is present
538 // (equivalently, the updated symbol table is not empty)
539 // the symbol table and the string table should not be removed.
540 if ((!Config
.SymbolsToKeep
.empty() || ELFConfig
.KeepFileSymbols
) &&
541 Obj
.SymbolTable
&& !Obj
.SymbolTable
->empty()) {
542 RemovePred
= [&Obj
, RemovePred
](const SectionBase
&Sec
) {
543 if (&Sec
== Obj
.SymbolTable
|| &Sec
== Obj
.SymbolTable
->getStrTab())
545 return RemovePred(Sec
);
549 if (Error E
= Obj
.removeSections(ELFConfig
.AllowBrokenLinks
, RemovePred
))
552 if (Error E
= Obj
.compressOrDecompressSections(Config
))
555 return Error::success();
558 // Add symbol to the Object symbol table with the specified properties.
559 static void addSymbol(Object
&Obj
, const NewSymbolInfo
&SymInfo
,
560 uint8_t DefaultVisibility
) {
561 SectionBase
*Sec
= Obj
.findSection(SymInfo
.SectionName
);
562 uint64_t Value
= Sec
? Sec
->Addr
+ SymInfo
.Value
: SymInfo
.Value
;
564 uint8_t Bind
= ELF::STB_GLOBAL
;
565 uint8_t Type
= ELF::STT_NOTYPE
;
566 uint8_t Visibility
= DefaultVisibility
;
568 for (SymbolFlag FlagValue
: SymInfo
.Flags
)
570 case SymbolFlag::Global
:
571 Bind
= ELF::STB_GLOBAL
;
573 case SymbolFlag::Local
:
574 Bind
= ELF::STB_LOCAL
;
576 case SymbolFlag::Weak
:
577 Bind
= ELF::STB_WEAK
;
579 case SymbolFlag::Default
:
580 Visibility
= ELF::STV_DEFAULT
;
582 case SymbolFlag::Hidden
:
583 Visibility
= ELF::STV_HIDDEN
;
585 case SymbolFlag::Protected
:
586 Visibility
= ELF::STV_PROTECTED
;
588 case SymbolFlag::File
:
589 Type
= ELF::STT_FILE
;
591 case SymbolFlag::Section
:
592 Type
= ELF::STT_SECTION
;
594 case SymbolFlag::Object
:
595 Type
= ELF::STT_OBJECT
;
597 case SymbolFlag::Function
:
598 Type
= ELF::STT_FUNC
;
600 case SymbolFlag::IndirectFunction
:
601 Type
= ELF::STT_GNU_IFUNC
;
603 default: /* Other flag values are ignored for ELF. */
607 Obj
.SymbolTable
->addSymbol(
608 SymInfo
.SymbolName
, Bind
, Type
, Sec
, Value
, Visibility
,
609 Sec
? (uint16_t)SYMBOL_SIMPLE_INDEX
: (uint16_t)SHN_ABS
, 0);
613 handleUserSection(const NewSectionInfo
&NewSection
,
614 function_ref
<Error(StringRef
, ArrayRef
<uint8_t>)> F
) {
615 ArrayRef
<uint8_t> Data(reinterpret_cast<const uint8_t *>(
616 NewSection
.SectionData
->getBufferStart()),
617 NewSection
.SectionData
->getBufferSize());
618 return F(NewSection
.SectionName
, Data
);
621 static Error
verifyNoteSection(StringRef Name
, endianness Endianness
,
622 ArrayRef
<uint8_t> Data
) {
623 // An ELF note has the following structure:
624 // Name Size: 4 bytes (integer)
625 // Desc Size: 4 bytes (integer)
627 // Name : variable size, padded to a 4 byte boundary
628 // Desc : variable size, padded to a 4 byte boundary
631 return Error::success();
633 if (Data
.size() < 12) {
635 raw_string_ostream(msg
)
636 << Name
<< " data must be either empty or at least 12 bytes long";
637 return createStringError(errc::invalid_argument
, msg
);
639 if (Data
.size() % 4 != 0) {
641 raw_string_ostream(msg
)
642 << Name
<< " data size must be a multiple of 4 bytes";
643 return createStringError(errc::invalid_argument
, msg
);
645 ArrayRef
<uint8_t> NameSize
= Data
.slice(0, 4);
646 ArrayRef
<uint8_t> DescSize
= Data
.slice(4, 4);
648 uint32_t NameSizeValue
= support::endian::read32(NameSize
.data(), Endianness
);
649 uint32_t DescSizeValue
= support::endian::read32(DescSize
.data(), Endianness
);
651 uint64_t ExpectedDataSize
=
652 /*NameSize=*/4 + /*DescSize=*/4 + /*Type=*/4 +
653 /*Name=*/alignTo(NameSizeValue
, 4) +
654 /*Desc=*/alignTo(DescSizeValue
, 4);
655 uint64_t ActualDataSize
= Data
.size();
656 if (ActualDataSize
!= ExpectedDataSize
) {
658 raw_string_ostream(msg
)
660 << " data size is incompatible with the content of "
661 "the name and description size fields:"
662 << " expecting " << ExpectedDataSize
<< ", found " << ActualDataSize
;
663 return createStringError(errc::invalid_argument
, msg
);
666 return Error::success();
669 // This function handles the high level operations of GNU objcopy including
670 // handling command line options. It's important to outline certain properties
671 // we expect to hold of the command line operations. Any operation that "keeps"
672 // should keep regardless of a remove. Additionally any removal should respect
673 // any previous removals. Lastly whether or not something is removed shouldn't
674 // depend a) on the order the options occur in or b) on some opaque priority
675 // system. The only priority is that keeps/copies overrule removes.
676 static Error
handleArgs(const CommonConfig
&Config
, const ELFConfig
&ELFConfig
,
677 ElfType OutputElfType
, Object
&Obj
) {
678 if (Config
.OutputArch
) {
679 Obj
.Machine
= Config
.OutputArch
->EMachine
;
680 Obj
.OSABI
= Config
.OutputArch
->OSABI
;
683 if (!Config
.SplitDWO
.empty() && Config
.ExtractDWO
) {
684 return Obj
.removeSections(
685 ELFConfig
.AllowBrokenLinks
,
686 [&Obj
](const SectionBase
&Sec
) { return onlyKeepDWOPred(Obj
, Sec
); });
689 // Dump sections before add/remove for compatibility with GNU objcopy.
690 for (StringRef Flag
: Config
.DumpSection
) {
691 StringRef SectionName
;
693 std::tie(SectionName
, FileName
) = Flag
.split('=');
694 if (Error E
= dumpSectionToFile(SectionName
, FileName
, Obj
))
698 // It is important to remove the sections first. For example, we want to
699 // remove the relocation sections before removing the symbols. That allows
700 // us to avoid reporting the inappropriate errors about removing symbols
701 // named in relocations.
702 if (Error E
= replaceAndRemoveSections(Config
, ELFConfig
, Obj
))
705 if (Error E
= updateAndRemoveSymbols(Config
, ELFConfig
, Obj
))
708 if (!Config
.SetSectionAlignment
.empty()) {
709 for (SectionBase
&Sec
: Obj
.sections()) {
710 auto I
= Config
.SetSectionAlignment
.find(Sec
.Name
);
711 if (I
!= Config
.SetSectionAlignment
.end())
712 Sec
.Align
= I
->second
;
716 if (Config
.ChangeSectionLMAValAll
!= 0) {
717 for (Segment
&Seg
: Obj
.segments()) {
718 if (Seg
.FileSize
> 0) {
719 if (Config
.ChangeSectionLMAValAll
> 0 &&
720 Seg
.PAddr
> std::numeric_limits
<uint64_t>::max() -
721 Config
.ChangeSectionLMAValAll
) {
722 return createStringError(
723 errc::invalid_argument
,
724 "address 0x" + Twine::utohexstr(Seg
.PAddr
) +
725 " cannot be increased by 0x" +
726 Twine::utohexstr(Config
.ChangeSectionLMAValAll
) +
727 ". The result would overflow");
728 } else if (Config
.ChangeSectionLMAValAll
< 0 &&
729 Seg
.PAddr
< std::numeric_limits
<uint64_t>::min() -
730 Config
.ChangeSectionLMAValAll
) {
731 return createStringError(
732 errc::invalid_argument
,
733 "address 0x" + Twine::utohexstr(Seg
.PAddr
) +
734 " cannot be decreased by 0x" +
735 Twine::utohexstr(std::abs(Config
.ChangeSectionLMAValAll
)) +
736 ". The result would underflow");
738 Seg
.PAddr
+= Config
.ChangeSectionLMAValAll
;
743 if (!Config
.ChangeSectionAddress
.empty()) {
744 if (Obj
.Type
!= ELF::ET_REL
)
745 return createStringError(
746 object_error::invalid_file_type
,
747 "cannot change section address in a non-relocatable file");
749 StringMap
<AddressUpdate
> SectionsToUpdateAddress
;
750 for (const SectionPatternAddressUpdate
&PatternUpdate
:
751 make_range(Config
.ChangeSectionAddress
.rbegin(),
752 Config
.ChangeSectionAddress
.rend())) {
753 for (SectionBase
&Sec
: Obj
.sections()) {
754 if (PatternUpdate
.SectionPattern
.matches(Sec
.Name
) &&
755 SectionsToUpdateAddress
.try_emplace(Sec
.Name
, PatternUpdate
.Update
)
757 if (PatternUpdate
.Update
.Kind
== AdjustKind::Subtract
&&
758 Sec
.Addr
< PatternUpdate
.Update
.Value
) {
759 return createStringError(
760 errc::invalid_argument
,
761 "address 0x" + Twine::utohexstr(Sec
.Addr
) +
762 " cannot be decreased by 0x" +
763 Twine::utohexstr(PatternUpdate
.Update
.Value
) +
764 ". The result would underflow");
766 if (PatternUpdate
.Update
.Kind
== AdjustKind::Add
&&
767 Sec
.Addr
> std::numeric_limits
<uint64_t>::max() -
768 PatternUpdate
.Update
.Value
) {
769 return createStringError(
770 errc::invalid_argument
,
771 "address 0x" + Twine::utohexstr(Sec
.Addr
) +
772 " cannot be increased by 0x" +
773 Twine::utohexstr(PatternUpdate
.Update
.Value
) +
774 ". The result would overflow");
777 switch (PatternUpdate
.Update
.Kind
) {
778 case (AdjustKind::Set
):
779 Sec
.Addr
= PatternUpdate
.Update
.Value
;
781 case (AdjustKind::Subtract
):
782 Sec
.Addr
-= PatternUpdate
.Update
.Value
;
784 case (AdjustKind::Add
):
785 Sec
.Addr
+= PatternUpdate
.Update
.Value
;
793 if (Config
.OnlyKeepDebug
)
794 for (auto &Sec
: Obj
.sections())
795 if (Sec
.Flags
& SHF_ALLOC
&& Sec
.Type
!= SHT_NOTE
)
796 Sec
.Type
= SHT_NOBITS
;
798 endianness E
= OutputElfType
== ELFT_ELF32LE
|| OutputElfType
== ELFT_ELF64LE
802 for (const NewSectionInfo
&AddedSection
: Config
.AddSection
) {
803 auto AddSection
= [&](StringRef Name
, ArrayRef
<uint8_t> Data
) -> Error
{
804 OwnedDataSection
&NewSection
=
805 Obj
.addSection
<OwnedDataSection
>(Name
, Data
);
806 if (Name
.starts_with(".note") && Name
!= ".note.GNU-stack") {
807 NewSection
.Type
= SHT_NOTE
;
808 if (ELFConfig
.VerifyNoteSections
)
809 return verifyNoteSection(Name
, E
, Data
);
811 return Error::success();
813 if (Error E
= handleUserSection(AddedSection
, AddSection
))
817 for (const NewSectionInfo
&NewSection
: Config
.UpdateSection
) {
818 auto UpdateSection
= [&](StringRef Name
, ArrayRef
<uint8_t> Data
) {
819 return Obj
.updateSection(Name
, Data
);
821 if (Error E
= handleUserSection(NewSection
, UpdateSection
))
825 if (!Config
.AddGnuDebugLink
.empty())
826 Obj
.addSection
<GnuDebugLinkSection
>(Config
.AddGnuDebugLink
,
827 Config
.GnuDebugLinkCRC32
);
829 // If the symbol table was previously removed, we need to create a new one
830 // before adding new symbols.
831 if (!Obj
.SymbolTable
&& !Config
.SymbolsToAdd
.empty())
832 if (Error E
= Obj
.addNewSymbolTable())
835 for (const NewSymbolInfo
&SI
: Config
.SymbolsToAdd
)
836 addSymbol(Obj
, SI
, ELFConfig
.NewSymbolVisibility
);
838 // --set-section-{flags,type} work with sections added by --add-section.
839 if (!Config
.SetSectionFlags
.empty() || !Config
.SetSectionType
.empty()) {
840 for (auto &Sec
: Obj
.sections()) {
841 const auto Iter
= Config
.SetSectionFlags
.find(Sec
.Name
);
842 if (Iter
!= Config
.SetSectionFlags
.end()) {
843 const SectionFlagsUpdate
&SFU
= Iter
->second
;
844 if (Error E
= setSectionFlagsAndType(Sec
, SFU
.NewFlags
, Obj
.Machine
))
847 auto It2
= Config
.SetSectionType
.find(Sec
.Name
);
848 if (It2
!= Config
.SetSectionType
.end())
849 setSectionType(Sec
, It2
->second
);
853 if (!Config
.SectionsToRename
.empty()) {
854 std::vector
<RelocationSectionBase
*> RelocSections
;
855 DenseSet
<SectionBase
*> RenamedSections
;
856 for (SectionBase
&Sec
: Obj
.sections()) {
857 auto *RelocSec
= dyn_cast
<RelocationSectionBase
>(&Sec
);
858 const auto Iter
= Config
.SectionsToRename
.find(Sec
.Name
);
859 if (Iter
!= Config
.SectionsToRename
.end()) {
860 const SectionRename
&SR
= Iter
->second
;
861 Sec
.Name
= std::string(SR
.NewName
);
863 if (Error E
= setSectionFlagsAndType(Sec
, *SR
.NewFlags
, Obj
.Machine
))
866 RenamedSections
.insert(&Sec
);
867 } else if (RelocSec
&& !(Sec
.Flags
& SHF_ALLOC
))
868 // Postpone processing relocation sections which are not specified in
869 // their explicit '--rename-section' commands until after their target
870 // sections are renamed.
871 // Dynamic relocation sections (i.e. ones with SHF_ALLOC) should be
872 // renamed only explicitly. Otherwise, renaming, for example, '.got.plt'
873 // would affect '.rela.plt', which is not desirable.
874 RelocSections
.push_back(RelocSec
);
877 // Rename relocation sections according to their target sections.
878 for (RelocationSectionBase
*RelocSec
: RelocSections
) {
879 auto Iter
= RenamedSections
.find(RelocSec
->getSection());
880 if (Iter
!= RenamedSections
.end())
881 RelocSec
->Name
= (RelocSec
->getNamePrefix() + (*Iter
)->Name
).str();
885 // Add a prefix to allocated sections and their relocation sections. This
886 // should be done after renaming the section by Config.SectionToRename to
887 // imitate the GNU objcopy behavior.
888 if (!Config
.AllocSectionsPrefix
.empty()) {
889 DenseSet
<SectionBase
*> PrefixedSections
;
890 for (SectionBase
&Sec
: Obj
.sections()) {
891 if (Sec
.Flags
& SHF_ALLOC
) {
892 Sec
.Name
= (Config
.AllocSectionsPrefix
+ Sec
.Name
).str();
893 PrefixedSections
.insert(&Sec
);
894 } else if (auto *RelocSec
= dyn_cast
<RelocationSectionBase
>(&Sec
)) {
895 // Rename relocation sections associated to the allocated sections.
896 // For example, if we rename .text to .prefix.text, we also rename
897 // .rel.text to .rel.prefix.text.
899 // Dynamic relocation sections (SHT_REL[A] with SHF_ALLOC) are handled
900 // above, e.g., .rela.plt is renamed to .prefix.rela.plt, not
901 // .rela.prefix.plt since GNU objcopy does so.
902 const SectionBase
*TargetSec
= RelocSec
->getSection();
903 if (TargetSec
&& (TargetSec
->Flags
& SHF_ALLOC
)) {
904 // If the relocation section comes *after* the target section, we
905 // don't add Config.AllocSectionsPrefix because we've already added
906 // the prefix to TargetSec->Name. Otherwise, if the relocation
907 // section comes *before* the target section, we add the prefix.
908 if (PrefixedSections
.count(TargetSec
))
909 Sec
.Name
= (RelocSec
->getNamePrefix() + TargetSec
->Name
).str();
911 Sec
.Name
= (RelocSec
->getNamePrefix() + Config
.AllocSectionsPrefix
+
919 if (ELFConfig
.EntryExpr
)
920 Obj
.Entry
= ELFConfig
.EntryExpr(Obj
.Entry
);
921 return Error::success();
924 static Error
writeOutput(const CommonConfig
&Config
, Object
&Obj
,
925 raw_ostream
&Out
, ElfType OutputElfType
) {
926 std::unique_ptr
<Writer
> Writer
=
927 createWriter(Config
, Obj
, Out
, OutputElfType
);
928 if (Error E
= Writer
->finalize())
930 return Writer
->write();
933 Error
objcopy::elf::executeObjcopyOnIHex(const CommonConfig
&Config
,
934 const ELFConfig
&ELFConfig
,
935 MemoryBuffer
&In
, raw_ostream
&Out
) {
936 IHexReader
Reader(&In
);
937 Expected
<std::unique_ptr
<Object
>> Obj
= Reader
.create(true);
939 return Obj
.takeError();
941 const ElfType OutputElfType
=
942 getOutputElfType(Config
.OutputArch
.value_or(MachineInfo()));
943 if (Error E
= handleArgs(Config
, ELFConfig
, OutputElfType
, **Obj
))
945 return writeOutput(Config
, **Obj
, Out
, OutputElfType
);
948 Error
objcopy::elf::executeObjcopyOnRawBinary(const CommonConfig
&Config
,
949 const ELFConfig
&ELFConfig
,
952 BinaryReader
Reader(&In
, ELFConfig
.NewSymbolVisibility
);
953 Expected
<std::unique_ptr
<Object
>> Obj
= Reader
.create(true);
955 return Obj
.takeError();
957 // Prefer OutputArch (-O<format>) if set, otherwise fallback to BinaryArch
959 const ElfType OutputElfType
=
960 getOutputElfType(Config
.OutputArch
.value_or(MachineInfo()));
961 if (Error E
= handleArgs(Config
, ELFConfig
, OutputElfType
, **Obj
))
963 return writeOutput(Config
, **Obj
, Out
, OutputElfType
);
966 Error
objcopy::elf::executeObjcopyOnBinary(const CommonConfig
&Config
,
967 const ELFConfig
&ELFConfig
,
968 object::ELFObjectFileBase
&In
,
970 ELFReader
Reader(&In
, Config
.ExtractPartition
);
971 Expected
<std::unique_ptr
<Object
>> Obj
=
972 Reader
.create(!Config
.SymbolsToAdd
.empty());
974 return Obj
.takeError();
975 // Prefer OutputArch (-O<format>) if set, otherwise infer it from the input.
976 const ElfType OutputElfType
= Config
.OutputArch
977 ? getOutputElfType(*Config
.OutputArch
)
978 : getOutputElfType(In
);
980 if (Error E
= handleArgs(Config
, ELFConfig
, OutputElfType
, **Obj
))
981 return createFileError(Config
.InputFilename
, std::move(E
));
983 if (Error E
= writeOutput(Config
, **Obj
, Out
, OutputElfType
))
984 return createFileError(Config
.InputFilename
, std::move(E
));
986 return Error::success();