aboutsummaryrefslogtreecommitdiff
path: root/tools/llvm-objcopy/ELF
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-10-23 17:51:42 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-10-23 17:51:42 +0000
commit1d5ae1026e831016fc29fd927877c86af904481f (patch)
tree2cdfd12620fcfa5d9e4a0389f85368e8e36f63f9 /tools/llvm-objcopy/ELF
parente6d1592492a3a379186bfb02bd0f4eda0669c0d5 (diff)
Notes
Diffstat (limited to 'tools/llvm-objcopy/ELF')
-rw-r--r--tools/llvm-objcopy/ELF/ELFConfig.cpp133
-rw-r--r--tools/llvm-objcopy/ELF/ELFConfig.h44
-rw-r--r--tools/llvm-objcopy/ELF/ELFObjcopy.cpp169
-rw-r--r--tools/llvm-objcopy/ELF/Object.cpp252
-rw-r--r--tools/llvm-objcopy/ELF/Object.h56
5 files changed, 429 insertions, 225 deletions
diff --git a/tools/llvm-objcopy/ELF/ELFConfig.cpp b/tools/llvm-objcopy/ELF/ELFConfig.cpp
new file mode 100644
index 000000000000..40993760add7
--- /dev/null
+++ b/tools/llvm-objcopy/ELF/ELFConfig.cpp
@@ -0,0 +1,133 @@
+//===- ELFConfig.cpp ------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "CopyConfig.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace objcopy {
+namespace elf {
+
+static Expected<NewSymbolInfo> parseNewSymbolInfo(StringRef FlagValue,
+ uint8_t DefaultVisibility) {
+ // Parse value given with --add-symbol option and create the
+ // new symbol if possible. The value format for --add-symbol is:
+ //
+ // <name>=[<section>:]<value>[,<flags>]
+ //
+ // where:
+ // <name> - symbol name, can be empty string
+ // <section> - optional section name. If not given ABS symbol is created
+ // <value> - symbol value, can be decimal or hexadecimal number prefixed
+ // with 0x.
+ // <flags> - optional flags affecting symbol type, binding or visibility:
+ // The following are currently supported:
+ //
+ // global, local, weak, default, hidden, file, section, object,
+ // indirect-function.
+ //
+ // The following flags are ignored and provided for GNU
+ // compatibility only:
+ //
+ // warning, debug, constructor, indirect, synthetic,
+ // unique-object, before=<symbol>.
+ NewSymbolInfo SI;
+ StringRef Value;
+ std::tie(SI.SymbolName, Value) = FlagValue.split('=');
+ if (Value.empty())
+ return createStringError(
+ errc::invalid_argument,
+ "bad format for --add-symbol, missing '=' after '%s'",
+ SI.SymbolName.str().c_str());
+
+ if (Value.contains(':')) {
+ std::tie(SI.SectionName, Value) = Value.split(':');
+ if (SI.SectionName.empty() || Value.empty())
+ return createStringError(
+ errc::invalid_argument,
+ "bad format for --add-symbol, missing section name or symbol value");
+ }
+
+ SmallVector<StringRef, 6> Flags;
+ Value.split(Flags, ',');
+ if (Flags[0].getAsInteger(0, SI.Value))
+ return createStringError(errc::invalid_argument, "bad symbol value: '%s'",
+ Flags[0].str().c_str());
+
+ SI.Visibility = DefaultVisibility;
+
+ using Functor = std::function<void(void)>;
+ SmallVector<StringRef, 6> UnsupportedFlags;
+ for (size_t I = 1, NumFlags = Flags.size(); I < NumFlags; ++I)
+ static_cast<Functor>(
+ StringSwitch<Functor>(Flags[I])
+ .CaseLower("global", [&SI] { SI.Bind = ELF::STB_GLOBAL; })
+ .CaseLower("local", [&SI] { SI.Bind = ELF::STB_LOCAL; })
+ .CaseLower("weak", [&SI] { SI.Bind = ELF::STB_WEAK; })
+ .CaseLower("default", [&SI] { SI.Visibility = ELF::STV_DEFAULT; })
+ .CaseLower("hidden", [&SI] { SI.Visibility = ELF::STV_HIDDEN; })
+ .CaseLower("protected",
+ [&SI] { SI.Visibility = ELF::STV_PROTECTED; })
+ .CaseLower("file", [&SI] { SI.Type = ELF::STT_FILE; })
+ .CaseLower("section", [&SI] { SI.Type = ELF::STT_SECTION; })
+ .CaseLower("object", [&SI] { SI.Type = ELF::STT_OBJECT; })
+ .CaseLower("function", [&SI] { SI.Type = ELF::STT_FUNC; })
+ .CaseLower("indirect-function",
+ [&SI] { SI.Type = ELF::STT_GNU_IFUNC; })
+ .CaseLower("debug", [] {})
+ .CaseLower("constructor", [] {})
+ .CaseLower("warning", [] {})
+ .CaseLower("indirect", [] {})
+ .CaseLower("synthetic", [] {})
+ .CaseLower("unique-object", [] {})
+ .StartsWithLower("before", [] {})
+ .Default([&] { UnsupportedFlags.push_back(Flags[I]); }))();
+ if (!UnsupportedFlags.empty())
+ return createStringError(errc::invalid_argument,
+ "unsupported flag%s for --add-symbol: '%s'",
+ UnsupportedFlags.size() > 1 ? "s" : "",
+ join(UnsupportedFlags, "', '").c_str());
+ return SI;
+}
+
+Expected<ELFCopyConfig> parseConfig(const CopyConfig &Config) {
+ ELFCopyConfig ELFConfig;
+ if (Config.NewSymbolVisibility) {
+ const uint8_t Invalid = 0xff;
+ ELFConfig.NewSymbolVisibility =
+ StringSwitch<uint8_t>(*Config.NewSymbolVisibility)
+ .Case("default", ELF::STV_DEFAULT)
+ .Case("hidden", ELF::STV_HIDDEN)
+ .Case("internal", ELF::STV_INTERNAL)
+ .Case("protected", ELF::STV_PROTECTED)
+ .Default(Invalid);
+
+ if (ELFConfig.NewSymbolVisibility == Invalid)
+ return createStringError(errc::invalid_argument,
+ "'%s' is not a valid symbol visibility",
+ Config.NewSymbolVisibility->str().c_str());
+ }
+
+ for (StringRef Arg : Config.SymbolsToAdd) {
+ Expected<elf::NewSymbolInfo> NSI = parseNewSymbolInfo(
+ Arg,
+ ELFConfig.NewSymbolVisibility.getValueOr((uint8_t)ELF::STV_DEFAULT));
+ if (!NSI)
+ return NSI.takeError();
+ ELFConfig.SymbolsToAdd.push_back(*NSI);
+ }
+
+ return ELFConfig;
+}
+
+} // end namespace elf
+} // end namespace objcopy
+} // end namespace llvm
diff --git a/tools/llvm-objcopy/ELF/ELFConfig.h b/tools/llvm-objcopy/ELF/ELFConfig.h
new file mode 100644
index 000000000000..977efbc4166f
--- /dev/null
+++ b/tools/llvm-objcopy/ELF/ELFConfig.h
@@ -0,0 +1,44 @@
+//===- ELFConfig.h ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_OBJCOPY_ELFCONFIG_H
+#define LLVM_TOOLS_OBJCOPY_ELFCONFIG_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Object/ELFTypes.h"
+#include "llvm/Support/Error.h"
+#include <vector>
+
+namespace llvm {
+namespace objcopy {
+struct CopyConfig;
+
+namespace elf {
+
+struct NewSymbolInfo {
+ StringRef SymbolName;
+ StringRef SectionName;
+ uint64_t Value = 0;
+ uint8_t Type = ELF::STT_NOTYPE;
+ uint8_t Bind = ELF::STB_GLOBAL;
+ uint8_t Visibility = ELF::STV_DEFAULT;
+};
+
+struct ELFCopyConfig {
+ Optional<uint8_t> NewSymbolVisibility;
+ std::vector<NewSymbolInfo> SymbolsToAdd;
+};
+
+Expected<ELFCopyConfig> parseConfig(const CopyConfig &Config);
+
+} // namespace elf
+} // namespace objcopy
+} // namespace llvm
+
+#endif
diff --git a/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
index b366c6e55987..8bf7e0f88010 100644
--- a/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
+++ b/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
@@ -136,16 +136,16 @@ static std::unique_ptr<Writer> createELFWriter(const CopyConfig &Config,
// Depending on the initial ELFT and OutputFormat we need a different Writer.
switch (OutputElfType) {
case ELFT_ELF32LE:
- return llvm::make_unique<ELFWriter<ELF32LE>>(Obj, Buf,
+ return std::make_unique<ELFWriter<ELF32LE>>(Obj, Buf,
!Config.StripSections);
case ELFT_ELF64LE:
- return llvm::make_unique<ELFWriter<ELF64LE>>(Obj, Buf,
+ return std::make_unique<ELFWriter<ELF64LE>>(Obj, Buf,
!Config.StripSections);
case ELFT_ELF32BE:
- return llvm::make_unique<ELFWriter<ELF32BE>>(Obj, Buf,
+ return std::make_unique<ELFWriter<ELF32BE>>(Obj, Buf,
!Config.StripSections);
case ELFT_ELF64BE:
- return llvm::make_unique<ELFWriter<ELF64BE>>(Obj, Buf,
+ return std::make_unique<ELFWriter<ELF64BE>>(Obj, Buf,
!Config.StripSections);
}
llvm_unreachable("Invalid output format");
@@ -156,9 +156,9 @@ static std::unique_ptr<Writer> createWriter(const CopyConfig &Config,
ElfType OutputElfType) {
switch (Config.OutputFormat) {
case FileFormat::Binary:
- return llvm::make_unique<BinaryWriter>(Obj, Buf);
+ return std::make_unique<BinaryWriter>(Obj, Buf);
case FileFormat::IHex:
- return llvm::make_unique<IHexWriter>(Obj, Buf);
+ return std::make_unique<IHexWriter>(Obj, Buf);
default:
return createELFWriter(Config, Obj, Buf, OutputElfType);
}
@@ -263,7 +263,7 @@ static Error linkToBuildIdDir(const CopyConfig &Config, StringRef ToLink,
static Error splitDWOToFile(const CopyConfig &Config, const Reader &Reader,
StringRef File, ElfType OutputElfType) {
- auto DWOFile = Reader.create();
+ auto DWOFile = Reader.create(false);
auto OnlyKeepDWOPred = [&DWOFile](const SectionBase &Sec) {
return onlyKeepDWOPred(*DWOFile, Sec);
};
@@ -305,9 +305,9 @@ static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
SecName.str().c_str());
}
-static bool isCompressable(const SectionBase &Section) {
- return !(Section.Flags & ELF::SHF_COMPRESSED) &&
- StringRef(Section.Name).startswith(".debug");
+static bool isCompressable(const SectionBase &Sec) {
+ return !(Sec.Flags & ELF::SHF_COMPRESSED) &&
+ StringRef(Sec.Name).startswith(".debug");
}
static void replaceDebugSections(
@@ -356,7 +356,7 @@ static Error updateAndRemoveSymbols(const CopyConfig &Config, Object &Obj) {
if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF &&
((Config.LocalizeHidden &&
(Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) ||
- is_contained(Config.SymbolsToLocalize, Sym.Name)))
+ Config.SymbolsToLocalize.matches(Sym.Name)))
Sym.Binding = STB_LOCAL;
// Note: these two globalize flags have very similar names but different
@@ -370,16 +370,15 @@ static Error updateAndRemoveSymbols(const CopyConfig &Config, Object &Obj) {
// --keep-global-symbol. Because of that, make sure to check
// --globalize-symbol second.
if (!Config.SymbolsToKeepGlobal.empty() &&
- !is_contained(Config.SymbolsToKeepGlobal, Sym.Name) &&
+ !Config.SymbolsToKeepGlobal.matches(Sym.Name) &&
Sym.getShndx() != SHN_UNDEF)
Sym.Binding = STB_LOCAL;
- if (is_contained(Config.SymbolsToGlobalize, Sym.Name) &&
+ if (Config.SymbolsToGlobalize.matches(Sym.Name) &&
Sym.getShndx() != SHN_UNDEF)
Sym.Binding = STB_GLOBAL;
- if (is_contained(Config.SymbolsToWeaken, Sym.Name) &&
- Sym.Binding == STB_GLOBAL)
+ if (Config.SymbolsToWeaken.matches(Sym.Name) && Sym.Binding == STB_GLOBAL)
Sym.Binding = STB_WEAK;
if (Config.Weaken && Sym.Binding == STB_GLOBAL &&
@@ -399,12 +398,12 @@ static Error updateAndRemoveSymbols(const CopyConfig &Config, Object &Obj) {
// symbols are still 'needed' and which are not.
if (Config.StripUnneeded || !Config.UnneededSymbolsToRemove.empty() ||
!Config.OnlySection.empty()) {
- for (auto &Section : Obj.sections())
- Section.markSymbols();
+ for (SectionBase &Sec : Obj.sections())
+ Sec.markSymbols();
}
auto RemoveSymbolsPred = [&](const Symbol &Sym) {
- if (is_contained(Config.SymbolsToKeep, Sym.Name) ||
+ if (Config.SymbolsToKeep.matches(Sym.Name) ||
(Config.KeepFileSymbols && Sym.Type == STT_FILE))
return false;
@@ -418,12 +417,12 @@ static Error updateAndRemoveSymbols(const CopyConfig &Config, Object &Obj) {
if (Config.StripAll || Config.StripAllGNU)
return true;
- if (is_contained(Config.SymbolsToRemove, Sym.Name))
+ if (Config.SymbolsToRemove.matches(Sym.Name))
return true;
if ((Config.StripUnneeded ||
- is_contained(Config.UnneededSymbolsToRemove, Sym.Name)) &&
- isUnneededSymbol(Sym))
+ Config.UnneededSymbolsToRemove.matches(Sym.Name)) &&
+ (!Obj.isRelocatable() || isUnneededSymbol(Sym)))
return true;
// We want to remove undefined symbols if all references have been stripped.
@@ -443,7 +442,7 @@ static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) {
// Removes:
if (!Config.ToRemove.empty()) {
RemovePred = [&Config](const SectionBase &Sec) {
- return is_contained(Config.ToRemove, Sec.Name);
+ return Config.ToRemove.matches(Sec.Name);
};
}
@@ -481,7 +480,7 @@ static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) {
};
}
- if (Config.StripDebug) {
+ if (Config.StripDebug || Config.StripUnneeded) {
RemovePred = [RemovePred](const SectionBase &Sec) {
return RemovePred(Sec) || isDebugSection(Sec);
};
@@ -523,7 +522,7 @@ static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) {
if (!Config.OnlySection.empty()) {
RemovePred = [&Config, RemovePred, &Obj](const SectionBase &Sec) {
// Explicitly keep these sections regardless of previous removes.
- if (is_contained(Config.OnlySection, Sec.Name))
+ if (Config.OnlySection.matches(Sec.Name))
return false;
// Allow all implicit removes.
@@ -545,7 +544,7 @@ static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) {
if (!Config.KeepSection.empty()) {
RemovePred = [&Config, RemovePred](const SectionBase &Sec) {
// Explicitly keep these sections regardless of previous removes.
- if (is_contained(Config.KeepSection, Sec.Name))
+ if (Config.KeepSection.matches(Sec.Name))
return false;
// Otherwise defer to RemovePred.
return RemovePred(Sec);
@@ -614,9 +613,8 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj,
if (Error E = updateAndRemoveSymbols(Config, Obj))
return E;
- if (!Config.SectionsToRename.empty() || !Config.AllocSectionsPrefix.empty()) {
- DenseSet<SectionBase *> PrefixedSections;
- for (auto &Sec : Obj.sections()) {
+ if (!Config.SectionsToRename.empty()) {
+ for (SectionBase &Sec : Obj.sections()) {
const auto Iter = Config.SectionsToRename.find(Sec.Name);
if (Iter != Config.SectionsToRename.end()) {
const SectionRename &SR = Iter->second;
@@ -624,63 +622,62 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj,
if (SR.NewFlags.hasValue())
setSectionFlagsAndType(Sec, SR.NewFlags.getValue());
}
+ }
+ }
- // Add a prefix to allocated sections and their relocation sections. This
- // should be done after renaming the section by Config.SectionToRename to
- // imitate the GNU objcopy behavior.
- if (!Config.AllocSectionsPrefix.empty()) {
- if (Sec.Flags & SHF_ALLOC) {
- Sec.Name = (Config.AllocSectionsPrefix + Sec.Name).str();
- PrefixedSections.insert(&Sec);
-
- // Rename relocation sections associated to the allocated sections.
- // For example, if we rename .text to .prefix.text, we also rename
- // .rel.text to .rel.prefix.text.
- //
- // Dynamic relocation sections (SHT_REL[A] with SHF_ALLOC) are handled
- // above, e.g., .rela.plt is renamed to .prefix.rela.plt, not
- // .rela.prefix.plt since GNU objcopy does so.
- } else if (auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec)) {
- auto *TargetSec = RelocSec->getSection();
- if (TargetSec && (TargetSec->Flags & SHF_ALLOC)) {
- StringRef prefix;
- switch (Sec.Type) {
- case SHT_REL:
- prefix = ".rel";
- break;
- case SHT_RELA:
- prefix = ".rela";
- break;
- default:
- continue;
- }
-
- // If the relocation section comes *after* the target section, we
- // don't add Config.AllocSectionsPrefix because we've already added
- // the prefix to TargetSec->Name. Otherwise, if the relocation
- // section comes *before* the target section, we add the prefix.
- if (PrefixedSections.count(TargetSec)) {
- Sec.Name = (prefix + TargetSec->Name).str();
- } else {
- const auto Iter = Config.SectionsToRename.find(TargetSec->Name);
- if (Iter != Config.SectionsToRename.end()) {
- // Both `--rename-section` and `--prefix-alloc-sections` are
- // given but the target section is not yet renamed.
- Sec.Name =
- (prefix + Config.AllocSectionsPrefix + Iter->second.NewName)
- .str();
- } else {
- Sec.Name =
- (prefix + Config.AllocSectionsPrefix + TargetSec->Name)
- .str();
- }
- }
+ // Add a prefix to allocated sections and their relocation sections. This
+ // should be done after renaming the section by Config.SectionToRename to
+ // imitate the GNU objcopy behavior.
+ if (!Config.AllocSectionsPrefix.empty()) {
+ DenseSet<SectionBase *> PrefixedSections;
+ for (SectionBase &Sec : Obj.sections()) {
+ if (Sec.Flags & SHF_ALLOC) {
+ Sec.Name = (Config.AllocSectionsPrefix + Sec.Name).str();
+ PrefixedSections.insert(&Sec);
+ } else if (auto *RelocSec = dyn_cast<RelocationSectionBase>(&Sec)) {
+ // Rename relocation sections associated to the allocated sections.
+ // For example, if we rename .text to .prefix.text, we also rename
+ // .rel.text to .rel.prefix.text.
+ //
+ // Dynamic relocation sections (SHT_REL[A] with SHF_ALLOC) are handled
+ // above, e.g., .rela.plt is renamed to .prefix.rela.plt, not
+ // .rela.prefix.plt since GNU objcopy does so.
+ const SectionBase *TargetSec = RelocSec->getSection();
+ if (TargetSec && (TargetSec->Flags & SHF_ALLOC)) {
+ StringRef prefix;
+ switch (Sec.Type) {
+ case SHT_REL:
+ prefix = ".rel";
+ break;
+ case SHT_RELA:
+ prefix = ".rela";
+ break;
+ default:
+ llvm_unreachable("not a relocation section");
}
+
+ // If the relocation section comes *after* the target section, we
+ // don't add Config.AllocSectionsPrefix because we've already added
+ // the prefix to TargetSec->Name. Otherwise, if the relocation
+ // section comes *before* the target section, we add the prefix.
+ if (PrefixedSections.count(TargetSec))
+ Sec.Name = (prefix + TargetSec->Name).str();
+ else
+ Sec.Name =
+ (prefix + Config.AllocSectionsPrefix + TargetSec->Name).str();
}
}
}
}
+ if (!Config.SetSectionAlignment.empty()) {
+ for (SectionBase &Sec : Obj.sections()) {
+ auto I = Config.SetSectionAlignment.find(Sec.Name);
+ if (I != Config.SetSectionAlignment.end())
+ Sec.Align = I->second;
+ }
+ }
+
if (!Config.SetSectionFlags.empty()) {
for (auto &Sec : Obj.sections()) {
const auto Iter = Config.SetSectionFlags.find(Sec.Name);
@@ -721,7 +718,7 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj,
Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink,
Config.GnuDebugLinkCRC32);
- for (const NewSymbolInfo &SI : Config.SymbolsToAdd) {
+ for (const NewSymbolInfo &SI : Config.ELF->SymbolsToAdd) {
SectionBase *Sec = Obj.findSection(SI.SectionName);
uint64_t Value = Sec ? Sec->Addr + SI.Value : SI.Value;
Obj.SymbolTable->addSymbol(
@@ -746,9 +743,9 @@ static Error writeOutput(const CopyConfig &Config, Object &Obj, Buffer &Out,
Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In,
Buffer &Out) {
IHexReader Reader(&In);
- std::unique_ptr<Object> Obj = Reader.create();
+ std::unique_ptr<Object> Obj = Reader.create(true);
const ElfType OutputElfType =
- getOutputElfType(Config.OutputArch.getValueOr(Config.BinaryArch));
+ getOutputElfType(Config.OutputArch.getValueOr(MachineInfo()));
if (Error E = handleArgs(Config, *Obj, Reader, OutputElfType))
return E;
return writeOutput(Config, *Obj, Out, OutputElfType);
@@ -756,13 +753,15 @@ Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In,
Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
Buffer &Out) {
- BinaryReader Reader(Config.BinaryArch, &In);
- std::unique_ptr<Object> Obj = Reader.create();
+ uint8_t NewSymbolVisibility =
+ Config.ELF->NewSymbolVisibility.getValueOr((uint8_t)ELF::STV_DEFAULT);
+ BinaryReader Reader(&In, NewSymbolVisibility);
+ std::unique_ptr<Object> Obj = Reader.create(true);
// Prefer OutputArch (-O<format>) if set, otherwise fallback to BinaryArch
// (-B<arch>).
const ElfType OutputElfType =
- getOutputElfType(Config.OutputArch.getValueOr(Config.BinaryArch));
+ getOutputElfType(Config.OutputArch.getValueOr(MachineInfo()));
if (Error E = handleArgs(Config, *Obj, Reader, OutputElfType))
return E;
return writeOutput(Config, *Obj, Out, OutputElfType);
@@ -771,7 +770,7 @@ Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
Error executeObjcopyOnBinary(const CopyConfig &Config,
object::ELFObjectFileBase &In, Buffer &Out) {
ELFReader Reader(&In, Config.ExtractPartition);
- std::unique_ptr<Object> Obj = Reader.create();
+ std::unique_ptr<Object> Obj = Reader.create(!Config.SymbolsToAdd.empty());
// Prefer OutputArch (-O<format>) if set, otherwise infer it from the input.
const ElfType OutputElfType =
Config.OutputArch ? getOutputElfType(Config.OutputArch.getValue())
diff --git a/tools/llvm-objcopy/ELF/Object.cpp b/tools/llvm-objcopy/ELF/Object.cpp
index fa696380e17c..74145dad6e6b 100644
--- a/tools/llvm-objcopy/ELF/Object.cpp
+++ b/tools/llvm-objcopy/ELF/Object.cpp
@@ -397,7 +397,7 @@ void SectionWriter::visit(const OwnedDataSection &Sec) {
llvm::copy(Sec.Data, Out.getBufferStart() + Sec.Offset);
}
-static const std::vector<uint8_t> ZlibGnuMagic = {'Z', 'L', 'I', 'B'};
+static constexpr std::array<uint8_t, 4> ZlibGnuMagic = {{'Z', 'L', 'I', 'B'}};
static bool isDataGnuCompressed(ArrayRef<uint8_t> Data) {
return Data.size() > ZlibGnuMagic.size() &&
@@ -665,7 +665,7 @@ void SymbolTableSection::addSymbol(Twine Name, uint8_t Bind, uint8_t Type,
Sym.Visibility = Visibility;
Sym.Size = SymbolSize;
Sym.Index = Symbols.size();
- Symbols.emplace_back(llvm::make_unique<Symbol>(Sym));
+ Symbols.emplace_back(std::make_unique<Symbol>(Sym));
Size += this->EntrySize;
}
@@ -1055,29 +1055,28 @@ void GroupSection::accept(MutableSectionVisitor &Visitor) {
}
// Returns true IFF a section is wholly inside the range of a segment
-static bool sectionWithinSegment(const SectionBase &Section,
- const Segment &Segment) {
+static bool sectionWithinSegment(const SectionBase &Sec, const Segment &Seg) {
// If a section is empty it should be treated like it has a size of 1. This is
// to clarify the case when an empty section lies on a boundary between two
// segments and ensures that the section "belongs" to the second segment and
// not the first.
- uint64_t SecSize = Section.Size ? Section.Size : 1;
+ uint64_t SecSize = Sec.Size ? Sec.Size : 1;
- if (Section.Type == SHT_NOBITS) {
- if (!(Section.Flags & SHF_ALLOC))
+ if (Sec.Type == SHT_NOBITS) {
+ if (!(Sec.Flags & SHF_ALLOC))
return false;
- bool SectionIsTLS = Section.Flags & SHF_TLS;
- bool SegmentIsTLS = Segment.Type == PT_TLS;
+ bool SectionIsTLS = Sec.Flags & SHF_TLS;
+ bool SegmentIsTLS = Seg.Type == PT_TLS;
if (SectionIsTLS != SegmentIsTLS)
return false;
- return Segment.VAddr <= Section.Addr &&
- Segment.VAddr + Segment.MemSize >= Section.Addr + SecSize;
+ return Seg.VAddr <= Sec.Addr &&
+ Seg.VAddr + Seg.MemSize >= Sec.Addr + SecSize;
}
- return Segment.Offset <= Section.OriginalOffset &&
- Segment.Offset + Segment.FileSize >= Section.OriginalOffset + SecSize;
+ return Seg.Offset <= Sec.OriginalOffset &&
+ Seg.Offset + Seg.FileSize >= Sec.OriginalOffset + SecSize;
}
// Returns true IFF a segment's original offset is inside of another segment's
@@ -1113,7 +1112,7 @@ void BasicELFBuilder::initFileHeader() {
Obj->OSABI = ELFOSABI_NONE;
Obj->ABIVersion = 0;
Obj->Entry = 0x0;
- Obj->Machine = EMachine;
+ Obj->Machine = EM_NONE;
Obj->Version = 1;
}
@@ -1141,8 +1140,8 @@ SymbolTableSection *BasicELFBuilder::addSymTab(StringTableSection *StrTab) {
}
void BasicELFBuilder::initSections() {
- for (auto &Section : Obj->sections())
- Section.initialize(Obj->sections());
+ for (SectionBase &Sec : Obj->sections())
+ Sec.initialize(Obj->sections());
}
void BinaryELFBuilder::addData(SymbolTableSection *SymTab) {
@@ -1161,11 +1160,12 @@ void BinaryELFBuilder::addData(SymbolTableSection *SymTab) {
Twine Prefix = Twine("_binary_") + SanitizedFilename;
SymTab->addSymbol(Prefix + "_start", STB_GLOBAL, STT_NOTYPE, &DataSection,
- /*Value=*/0, STV_DEFAULT, 0, 0);
+ /*Value=*/0, NewSymbolVisibility, 0, 0);
SymTab->addSymbol(Prefix + "_end", STB_GLOBAL, STT_NOTYPE, &DataSection,
- /*Value=*/DataSection.Size, STV_DEFAULT, 0, 0);
+ /*Value=*/DataSection.Size, NewSymbolVisibility, 0, 0);
SymTab->addSymbol(Prefix + "_size", STB_GLOBAL, STT_NOTYPE, nullptr,
- /*Value=*/DataSection.Size, STV_DEFAULT, SHN_ABS, 0);
+ /*Value=*/DataSection.Size, NewSymbolVisibility, SHN_ABS,
+ 0);
}
std::unique_ptr<Object> BinaryELFBuilder::build() {
@@ -1255,10 +1255,9 @@ template <class ELFT> void ELFBuilder<ELFT>::findEhdrOffset() {
if (!ExtractPartition)
return;
- for (const SectionBase &Section : Obj.sections()) {
- if (Section.Type == SHT_LLVM_PART_EHDR &&
- Section.Name == *ExtractPartition) {
- EhdrOffset = Section.Offset;
+ for (const SectionBase &Sec : Obj.sections()) {
+ if (Sec.Type == SHT_LLVM_PART_EHDR && Sec.Name == *ExtractPartition) {
+ EhdrOffset = Sec.Offset;
return;
}
}
@@ -1287,15 +1286,12 @@ void ELFBuilder<ELFT>::readProgramHeaders(const ELFFile<ELFT> &HeadersFile) {
Seg.MemSize = Phdr.p_memsz;
Seg.Align = Phdr.p_align;
Seg.Index = Index++;
- for (SectionBase &Section : Obj.sections()) {
- if (sectionWithinSegment(Section, Seg)) {
- Seg.addSection(&Section);
- if (!Section.ParentSegment ||
- Section.ParentSegment->Offset > Seg.Offset) {
- Section.ParentSegment = &Seg;
- }
+ for (SectionBase &Sec : Obj.sections())
+ if (sectionWithinSegment(Sec, Seg)) {
+ Seg.addSection(&Sec);
+ if (!Sec.ParentSegment || Sec.ParentSegment->Offset > Seg.Offset)
+ Sec.ParentSegment = &Seg;
}
- }
}
auto &ElfHdr = Obj.ElfHdrSegment;
@@ -1531,7 +1527,7 @@ template <class ELFT> void ELFBuilder<ELFT>::readSectionHeaders() {
}
}
-template <class ELFT> void ELFBuilder<ELFT>::readSections() {
+template <class ELFT> void ELFBuilder<ELFT>::readSections(bool EnsureSymtab) {
// If a section index table exists we'll need to initialize it before we
// initialize the symbol table because the symbol table might need to
// reference it.
@@ -1544,16 +1540,37 @@ template <class ELFT> void ELFBuilder<ELFT>::readSections() {
if (Obj.SymbolTable) {
Obj.SymbolTable->initialize(Obj.sections());
initSymbolTable(Obj.SymbolTable);
+ } else if (EnsureSymtab) {
+ // Reuse the existing SHT_STRTAB section if exists.
+ StringTableSection *StrTab = nullptr;
+ for (auto &Sec : Obj.sections()) {
+ if (Sec.Type == ELF::SHT_STRTAB && !(Sec.Flags & SHF_ALLOC)) {
+ StrTab = static_cast<StringTableSection *>(&Sec);
+
+ // Prefer .strtab to .shstrtab.
+ if (Obj.SectionNames != &Sec)
+ break;
+ }
+ }
+ if (!StrTab)
+ StrTab = &Obj.addSection<StringTableSection>();
+
+ SymbolTableSection &SymTab = Obj.addSection<SymbolTableSection>();
+ SymTab.Name = ".symtab";
+ SymTab.Link = StrTab->Index;
+ SymTab.initialize(Obj.sections());
+ SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);
+ Obj.SymbolTable = &SymTab;
}
// Now that all sections and symbols have been added we can add
// relocations that reference symbols and set the link and info fields for
// relocation sections.
- for (auto &Section : Obj.sections()) {
- if (&Section == Obj.SymbolTable)
+ for (auto &Sec : Obj.sections()) {
+ if (&Sec == Obj.SymbolTable)
continue;
- Section.initialize(Obj.sections());
- if (auto RelSec = dyn_cast<RelocationSection>(&Section)) {
+ Sec.initialize(Obj.sections());
+ if (auto RelSec = dyn_cast<RelocationSection>(&Sec)) {
auto Shdr = unwrapOrError(ElfFile.sections()).begin() + RelSec->Index;
if (RelSec->Type == SHT_REL)
initRelocations(RelSec, Obj.SymbolTable,
@@ -1561,7 +1578,7 @@ template <class ELFT> void ELFBuilder<ELFT>::readSections() {
else
initRelocations(RelSec, Obj.SymbolTable,
unwrapOrError(ElfFile.relas(Shdr)));
- } else if (auto GroupSec = dyn_cast<GroupSection>(&Section)) {
+ } else if (auto GroupSec = dyn_cast<GroupSection>(&Sec)) {
initGroupSection(GroupSec);
}
}
@@ -1582,7 +1599,7 @@ template <class ELFT> void ELFBuilder<ELFT>::readSections() {
" is not a string table");
}
-template <class ELFT> void ELFBuilder<ELFT>::build() {
+template <class ELFT> void ELFBuilder<ELFT>::build(bool EnsureSymtab) {
readSectionHeaders();
findEhdrOffset();
@@ -1601,7 +1618,7 @@ template <class ELFT> void ELFBuilder<ELFT>::build() {
Obj.Entry = Ehdr.e_entry;
Obj.Flags = Ehdr.e_flags;
- readSections();
+ readSections(EnsureSymtab);
readProgramHeaders(HeadersFile);
}
@@ -1609,8 +1626,8 @@ Writer::~Writer() {}
Reader::~Reader() {}
-std::unique_ptr<Object> BinaryReader::create() const {
- return BinaryELFBuilder(MInfo.EMachine, MemBuf).build();
+std::unique_ptr<Object> BinaryReader::create(bool /*EnsureSymtab*/) const {
+ return BinaryELFBuilder(MemBuf, NewSymbolVisibility).build();
}
Expected<std::vector<IHexRecord>> IHexReader::parse() const {
@@ -1639,28 +1656,28 @@ Expected<std::vector<IHexRecord>> IHexReader::parse() const {
return std::move(Records);
}
-std::unique_ptr<Object> IHexReader::create() const {
+std::unique_ptr<Object> IHexReader::create(bool /*EnsureSymtab*/) const {
std::vector<IHexRecord> Records = unwrapOrError(parse());
return IHexELFBuilder(Records).build();
}
-std::unique_ptr<Object> ELFReader::create() const {
- auto Obj = llvm::make_unique<Object>();
+std::unique_ptr<Object> ELFReader::create(bool EnsureSymtab) const {
+ auto Obj = std::make_unique<Object>();
if (auto *O = dyn_cast<ELFObjectFile<ELF32LE>>(Bin)) {
ELFBuilder<ELF32LE> Builder(*O, *Obj, ExtractPartition);
- Builder.build();
+ Builder.build(EnsureSymtab);
return Obj;
} else if (auto *O = dyn_cast<ELFObjectFile<ELF64LE>>(Bin)) {
ELFBuilder<ELF64LE> Builder(*O, *Obj, ExtractPartition);
- Builder.build();
+ Builder.build(EnsureSymtab);
return Obj;
} else if (auto *O = dyn_cast<ELFObjectFile<ELF32BE>>(Bin)) {
ELFBuilder<ELF32BE> Builder(*O, *Obj, ExtractPartition);
- Builder.build();
+ Builder.build(EnsureSymtab);
return Obj;
} else if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(Bin)) {
ELFBuilder<ELF64BE> Builder(*O, *Obj, ExtractPartition);
- Builder.build();
+ Builder.build(EnsureSymtab);
return Obj;
}
error("invalid file type");
@@ -1693,7 +1710,7 @@ template <class ELFT> void ELFWriter<ELFT>::writeEhdr() {
Ehdr.e_ehsize = sizeof(Elf_Ehdr);
if (WriteSectionHeaders && Obj.sections().size() != 0) {
Ehdr.e_shentsize = sizeof(Elf_Shdr);
- Ehdr.e_shoff = Obj.SHOffset;
+ Ehdr.e_shoff = Obj.SHOff;
// """
// If the number of sections is greater than or equal to
// SHN_LORESERVE (0xff00), this member has the value zero and the actual
@@ -1732,7 +1749,7 @@ template <class ELFT> void ELFWriter<ELFT>::writeShdrs() {
// This reference serves to write the dummy section header at the begining
// of the file. It is not used for anything else
Elf_Shdr &Shdr =
- *reinterpret_cast<Elf_Shdr *>(Buf.getBufferStart() + Obj.SHOffset);
+ *reinterpret_cast<Elf_Shdr *>(Buf.getBufferStart() + Obj.SHOff);
Shdr.sh_name = 0;
Shdr.sh_type = SHT_NULL;
Shdr.sh_flags = 0;
@@ -1862,26 +1879,13 @@ void Object::sortSections() {
});
}
-static uint64_t alignToAddr(uint64_t Offset, uint64_t Addr, uint64_t Align) {
- // Calculate Diff such that (Offset + Diff) & -Align == Addr & -Align.
- if (Align == 0)
- Align = 1;
- auto Diff =
- static_cast<int64_t>(Addr % Align) - static_cast<int64_t>(Offset % Align);
- // We only want to add to Offset, however, so if Diff < 0 we can add Align and
- // (Offset + Diff) & -Align == Addr & -Align will still hold.
- if (Diff < 0)
- Diff += Align;
- return Offset + Diff;
-}
-
// Orders segments such that if x = y->ParentSegment then y comes before x.
static void orderSegments(std::vector<Segment *> &Segments) {
llvm::stable_sort(Segments, compareSegmentsByOffset);
}
// This function finds a consistent layout for a list of segments starting from
-// an Offset. It assumes that Segments have been sorted by OrderSegments and
+// an Offset. It assumes that Segments have been sorted by orderSegments and
// returns an Offset one past the end of the last segment.
static uint64_t layoutSegments(std::vector<Segment *> &Segments,
uint64_t Offset) {
@@ -1902,8 +1906,8 @@ static uint64_t layoutSegments(std::vector<Segment *> &Segments,
Seg->Offset =
Parent->Offset + Seg->OriginalOffset - Parent->OriginalOffset;
} else {
- Offset = alignToAddr(Offset, Seg->VAddr, Seg->Align);
- Seg->Offset = Offset;
+ Seg->Offset =
+ alignTo(Offset, std::max<uint64_t>(Seg->Align, 1), Seg->VAddr);
}
Offset = std::max(Offset, Seg->Offset + Seg->FileSize);
}
@@ -1925,17 +1929,17 @@ static uint64_t layoutSections(Range Sections, uint64_t Offset) {
// of the segment we can assign a new offset to the section. For sections not
// covered by segments we can just bump Offset to the next valid location.
uint32_t Index = 1;
- for (auto &Section : Sections) {
- Section.Index = Index++;
- if (Section.ParentSegment != nullptr) {
- auto Segment = *Section.ParentSegment;
- Section.Offset =
- Segment.Offset + (Section.OriginalOffset - Segment.OriginalOffset);
+ for (auto &Sec : Sections) {
+ Sec.Index = Index++;
+ if (Sec.ParentSegment != nullptr) {
+ auto Segment = *Sec.ParentSegment;
+ Sec.Offset =
+ Segment.Offset + (Sec.OriginalOffset - Segment.OriginalOffset);
} else {
- Offset = alignTo(Offset, Section.Align == 0 ? 1 : Section.Align);
- Section.Offset = Offset;
- if (Section.Type != SHT_NOBITS)
- Offset += Section.Size;
+ Offset = alignTo(Offset, Sec.Align == 0 ? 1 : Sec.Align);
+ Sec.Offset = Offset;
+ if (Sec.Type != SHT_NOBITS)
+ Offset += Sec.Size;
}
}
return Offset;
@@ -1971,16 +1975,16 @@ template <class ELFT> void ELFWriter<ELFT>::assignOffsets() {
// Offset so that SHOffset is valid.
if (WriteSectionHeaders)
Offset = alignTo(Offset, sizeof(Elf_Addr));
- Obj.SHOffset = Offset;
+ Obj.SHOff = Offset;
}
template <class ELFT> size_t ELFWriter<ELFT>::totalSize() const {
// We already have the section header offset so we can calculate the total
// size by just adding up the size of each section header.
if (!WriteSectionHeaders)
- return Obj.SHOffset;
+ return Obj.SHOff;
size_t ShdrCount = Obj.sections().size() + 1; // Includes null shdr.
- return Obj.SHOffset + ShdrCount * sizeof(Elf_Shdr);
+ return Obj.SHOff + ShdrCount * sizeof(Elf_Shdr);
}
template <class ELFT> Error ELFWriter<ELFT>::write() {
@@ -1995,6 +1999,25 @@ template <class ELFT> Error ELFWriter<ELFT>::write() {
return Buf.commit();
}
+static Error removeUnneededSections(Object &Obj) {
+ // We can remove an empty symbol table from non-relocatable objects.
+ // Relocatable objects typically have relocation sections whose
+ // sh_link field points to .symtab, so we can't remove .symtab
+ // even if it is empty.
+ if (Obj.isRelocatable() || Obj.SymbolTable == nullptr ||
+ !Obj.SymbolTable->empty())
+ return Error::success();
+
+ // .strtab can be used for section names. In such a case we shouldn't
+ // remove it.
+ auto *StrTab = Obj.SymbolTable->getStrTab() == Obj.SectionNames
+ ? nullptr
+ : Obj.SymbolTable->getStrTab();
+ return Obj.removeSections(false, [&](const SectionBase &Sec) {
+ return &Sec == Obj.SymbolTable || &Sec == StrTab;
+ });
+}
+
template <class ELFT> Error ELFWriter<ELFT>::finalize() {
// It could happen that SectionNames has been removed and yet the user wants
// a section header table output. We need to throw an error if a user tries
@@ -2004,6 +2027,8 @@ template <class ELFT> Error ELFWriter<ELFT>::finalize() {
"cannot write section header table because "
"section header string table was removed");
+ if (Error E = removeUnneededSections(Obj))
+ return E;
Obj.sortSections();
// We need to assign indexes before we perform layout because we need to know
@@ -2045,9 +2070,8 @@ template <class ELFT> Error ELFWriter<ELFT>::finalize() {
// Make sure we add the names of all the sections. Importantly this must be
// done after we decide to add or remove SectionIndexes.
if (Obj.SectionNames != nullptr)
- for (const auto &Section : Obj.sections()) {
- Obj.SectionNames->addString(Section.Name);
- }
+ for (const SectionBase &Sec : Obj.sections())
+ Obj.SectionNames->addString(Sec.Name);
initEhdrSegment();
@@ -2055,8 +2079,8 @@ template <class ELFT> Error ELFWriter<ELFT>::finalize() {
// Also, the output arch may not be the same as the input arch, so fix up
// size-related fields before doing layout calculations.
uint64_t Index = 0;
- auto SecSizer = llvm::make_unique<ELFSectionSizer<ELFT>>();
- for (auto &Sec : Obj.sections()) {
+ auto SecSizer = std::make_unique<ELFSectionSizer<ELFT>>();
+ for (SectionBase &Sec : Obj.sections()) {
Sec.Index = Index++;
Sec.accept(*SecSizer);
}
@@ -2082,40 +2106,36 @@ template <class ELFT> Error ELFWriter<ELFT>::finalize() {
// Finally now that all offsets and indexes have been set we can finalize any
// remaining issues.
- uint64_t Offset = Obj.SHOffset + sizeof(Elf_Shdr);
- for (SectionBase &Section : Obj.sections()) {
- Section.HeaderOffset = Offset;
+ uint64_t Offset = Obj.SHOff + sizeof(Elf_Shdr);
+ for (SectionBase &Sec : Obj.sections()) {
+ Sec.HeaderOffset = Offset;
Offset += sizeof(Elf_Shdr);
if (WriteSectionHeaders)
- Section.NameIndex = Obj.SectionNames->findIndex(Section.Name);
- Section.finalize();
+ Sec.NameIndex = Obj.SectionNames->findIndex(Sec.Name);
+ Sec.finalize();
}
if (Error E = Buf.allocate(totalSize()))
return E;
- SecWriter = llvm::make_unique<ELFSectionWriter<ELFT>>(Buf);
+ SecWriter = std::make_unique<ELFSectionWriter<ELFT>>(Buf);
return Error::success();
}
Error BinaryWriter::write() {
- for (auto &Section : Obj.sections())
- if (Section.Flags & SHF_ALLOC)
- Section.accept(*SecWriter);
+ for (const SectionBase &Sec : Obj.allocSections())
+ Sec.accept(*SecWriter);
return Buf.commit();
}
Error BinaryWriter::finalize() {
- // TODO: Create a filter range to construct OrderedSegments from so that this
- // code can be deduped with assignOffsets above. This should also solve the
- // todo below for LayoutSections.
// We need a temporary list of segments that has a special order to it
// so that we know that anytime ->ParentSegment is set that segment has
// already had it's offset properly set. We only want to consider the segments
// that will affect layout of allocated sections so we only add those.
std::vector<Segment *> OrderedSegments;
- for (SectionBase &Section : Obj.sections())
- if ((Section.Flags & SHF_ALLOC) != 0 && Section.ParentSegment != nullptr)
- OrderedSegments.push_back(Section.ParentSegment);
+ for (const SectionBase &Sec : Obj.allocSections())
+ if (Sec.ParentSegment != nullptr)
+ OrderedSegments.push_back(Sec.ParentSegment);
// For binary output, we're going to use physical addresses instead of
// virtual addresses, since a binary output is used for cases like ROM
@@ -2130,7 +2150,7 @@ Error BinaryWriter::finalize() {
llvm::stable_sort(OrderedSegments, compareSegmentsByPAddr);
// Because we add a ParentSegment for each section we might have duplicate
- // segments in OrderedSegments. If there were duplicates then LayoutSegments
+ // segments in OrderedSegments. If there were duplicates then layoutSegments
// would do very strange things.
auto End =
std::unique(std::begin(OrderedSegments), std::end(OrderedSegments));
@@ -2158,28 +2178,20 @@ Error BinaryWriter::finalize() {
}
}
- // TODO: generalize LayoutSections to take a range. Pass a special range
- // constructed from an iterator that skips values for which a predicate does
- // not hold. Then pass such a range to LayoutSections instead of constructing
- // AllocatedSections here.
- std::vector<SectionBase *> AllocatedSections;
- for (SectionBase &Section : Obj.sections())
- if (Section.Flags & SHF_ALLOC)
- AllocatedSections.push_back(&Section);
- layoutSections(make_pointee_range(AllocatedSections), Offset);
+ layoutSections(Obj.allocSections(), Offset);
// Now that every section has been laid out we just need to compute the total
// file size. This might not be the same as the offset returned by
- // LayoutSections, because we want to truncate the last segment to the end of
+ // layoutSections, because we want to truncate the last segment to the end of
// its last section, to match GNU objcopy's behaviour.
TotalSize = 0;
- for (SectionBase *Section : AllocatedSections)
- if (Section->Type != SHT_NOBITS)
- TotalSize = std::max(TotalSize, Section->Offset + Section->Size);
+ for (const SectionBase &Sec : Obj.allocSections())
+ if (Sec.Type != SHT_NOBITS)
+ TotalSize = std::max(TotalSize, Sec.Offset + Sec.Size);
if (Error E = Buf.allocate(TotalSize))
return E;
- SecWriter = llvm::make_unique<BinarySectionWriter>(Buf);
+ SecWriter = std::make_unique<BinarySectionWriter>(Buf);
return Error::success();
}
@@ -2259,17 +2271,17 @@ Error IHexWriter::finalize() {
// If any section we're to write has segment then we
// switch to using physical addresses. Otherwise we
// use section virtual address.
- for (auto &Section : Obj.sections())
- if (ShouldWrite(Section) && IsInPtLoad(Section)) {
+ for (const SectionBase &Sec : Obj.sections())
+ if (ShouldWrite(Sec) && IsInPtLoad(Sec)) {
UseSegments = true;
break;
}
- for (auto &Section : Obj.sections())
- if (ShouldWrite(Section) && (!UseSegments || IsInPtLoad(Section))) {
- if (Error E = checkSection(Section))
+ for (const SectionBase &Sec : Obj.sections())
+ if (ShouldWrite(Sec) && (!UseSegments || IsInPtLoad(Sec))) {
+ if (Error E = checkSection(Sec))
return E;
- Sections.insert(&Section);
+ Sections.insert(&Sec);
}
IHexSectionWriterBase LengthCalc(Buf);
diff --git a/tools/llvm-objcopy/ELF/Object.h b/tools/llvm-objcopy/ELF/Object.h
index f3df93b9662f..eeacb014e4dc 100644
--- a/tools/llvm-objcopy/ELF/Object.h
+++ b/tools/llvm-objcopy/ELF/Object.h
@@ -57,8 +57,8 @@ public:
: Sections(Secs) {}
SectionTableRef(const SectionTableRef &) = default;
- iterator begin() { return iterator(Sections.data()); }
- iterator end() { return iterator(Sections.data() + Sections.size()); }
+ iterator begin() const { return iterator(Sections.data()); }
+ iterator end() const { return iterator(Sections.data() + Sections.size()); }
size_t size() const { return Sections.size(); }
SectionBase *getSection(uint32_t Index, Twine ErrMsg);
@@ -863,7 +863,7 @@ public:
class Reader {
public:
virtual ~Reader();
- virtual std::unique_ptr<Object> create() const = 0;
+ virtual std::unique_ptr<Object> create(bool EnsureSymtab) const = 0;
};
using object::Binary;
@@ -873,7 +873,6 @@ using object::OwningBinary;
class BasicELFBuilder {
protected:
- uint16_t EMachine;
std::unique_ptr<Object> Obj;
void initFileHeader();
@@ -883,17 +882,18 @@ protected:
void initSections();
public:
- BasicELFBuilder(uint16_t EM)
- : EMachine(EM), Obj(llvm::make_unique<Object>()) {}
+ BasicELFBuilder() : Obj(std::make_unique<Object>()) {}
};
class BinaryELFBuilder : public BasicELFBuilder {
MemoryBuffer *MemBuf;
+ uint8_t NewSymbolVisibility;
void addData(SymbolTableSection *SymTab);
public:
- BinaryELFBuilder(uint16_t EM, MemoryBuffer *MB)
- : BasicELFBuilder(EM), MemBuf(MB) {}
+ BinaryELFBuilder(MemoryBuffer *MB, uint8_t NewSymbolVisibility)
+ : BasicELFBuilder(), MemBuf(MB),
+ NewSymbolVisibility(NewSymbolVisibility) {}
std::unique_ptr<Object> build();
};
@@ -905,7 +905,7 @@ class IHexELFBuilder : public BasicELFBuilder {
public:
IHexELFBuilder(const std::vector<IHexRecord> &Records)
- : BasicELFBuilder(ELF::EM_386), Records(Records) {}
+ : BasicELFBuilder(), Records(Records) {}
std::unique_ptr<Object> build();
};
@@ -926,7 +926,7 @@ private:
void initGroupSection(GroupSection *GroupSec);
void initSymbolTable(SymbolTableSection *SymTab);
void readSectionHeaders();
- void readSections();
+ void readSections(bool EnsureSymtab);
void findEhdrOffset();
SectionBase &makeSection(const Elf_Shdr &Shdr);
@@ -936,17 +936,17 @@ public:
: ElfFile(*ElfObj.getELFFile()), Obj(Obj),
ExtractPartition(ExtractPartition) {}
- void build();
+ void build(bool EnsureSymtab);
};
class BinaryReader : public Reader {
- const MachineInfo &MInfo;
MemoryBuffer *MemBuf;
+ uint8_t NewSymbolVisibility;
public:
- BinaryReader(const MachineInfo &MI, MemoryBuffer *MB)
- : MInfo(MI), MemBuf(MB) {}
- std::unique_ptr<Object> create() const override;
+ BinaryReader(MemoryBuffer *MB, const uint8_t NewSymbolVisibility)
+ : MemBuf(MB), NewSymbolVisibility(NewSymbolVisibility) {}
+ std::unique_ptr<Object> create(bool EnsureSymtab) const override;
};
class IHexReader : public Reader {
@@ -968,7 +968,7 @@ class IHexReader : public Reader {
public:
IHexReader(MemoryBuffer *MB) : MemBuf(MB) {}
- std::unique_ptr<Object> create() const override;
+ std::unique_ptr<Object> create(bool EnsureSymtab) const override;
};
class ELFReader : public Reader {
@@ -976,7 +976,7 @@ class ELFReader : public Reader {
Optional<StringRef> ExtractPartition;
public:
- std::unique_ptr<Object> create() const override;
+ std::unique_ptr<Object> create(bool EnsureSymtab) const override;
explicit ELFReader(Binary *B, Optional<StringRef> ExtractPartition)
: Bin(B), ExtractPartition(ExtractPartition) {}
};
@@ -990,6 +990,10 @@ private:
std::vector<SegPtr> Segments;
std::vector<SecPtr> RemovedSections;
+ static bool sectionIsAlloc(const SectionBase &Sec) {
+ return Sec.Flags & ELF::SHF_ALLOC;
+ };
+
public:
template <class T>
using Range = iterator_range<
@@ -1011,13 +1015,14 @@ public:
uint8_t OSABI;
uint8_t ABIVersion;
uint64_t Entry;
- uint64_t SHOffset;
+ uint64_t SHOff;
uint32_t Type;
uint32_t Machine;
uint32_t Version;
uint32_t Flags;
bool HadShdrs = true;
+ bool MustBeRelocatable = false;
StringTableSection *SectionNames = nullptr;
SymbolTableSection *SymbolTable = nullptr;
SectionIndexSection *SectionIndexTable = nullptr;
@@ -1027,6 +1032,13 @@ public:
ConstRange<SectionBase> sections() const {
return make_pointee_range(Sections);
}
+ iterator_range<
+ filter_iterator<pointee_iterator<std::vector<SecPtr>::const_iterator>,
+ decltype(&sectionIsAlloc)>>
+ allocSections() const {
+ return make_filter_range(make_pointee_range(Sections), sectionIsAlloc);
+ }
+
SectionBase *findSection(StringRef Name) {
auto SecIt =
find_if(Sections, [&](const SecPtr &Sec) { return Sec->Name == Name; });
@@ -1041,16 +1053,20 @@ public:
std::function<bool(const SectionBase &)> ToRemove);
Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);
template <class T, class... Ts> T &addSection(Ts &&... Args) {
- auto Sec = llvm::make_unique<T>(std::forward<Ts>(Args)...);
+ auto Sec = std::make_unique<T>(std::forward<Ts>(Args)...);
auto Ptr = Sec.get();
+ MustBeRelocatable |= isa<RelocationSection>(*Ptr);
Sections.emplace_back(std::move(Sec));
Ptr->Index = Sections.size();
return *Ptr;
}
Segment &addSegment(ArrayRef<uint8_t> Data) {
- Segments.emplace_back(llvm::make_unique<Segment>(Data));
+ Segments.emplace_back(std::make_unique<Segment>(Data));
return *Segments.back();
}
+ bool isRelocatable() const {
+ return (Type != ELF::ET_DYN && Type != ELF::ET_EXEC) || MustBeRelocatable;
+ }
};
} // end namespace elf