aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm12/tools/llvm-objcopy/ELF
diff options
context:
space:
mode:
authororivej <orivej@yandex-team.ru>2022-02-10 16:44:49 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:44:49 +0300
commit718c552901d703c502ccbefdfc3c9028d608b947 (patch)
tree46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/libs/llvm12/tools/llvm-objcopy/ELF
parente9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff)
downloadydb-718c552901d703c502ccbefdfc3c9028d608b947.tar.gz
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/llvm12/tools/llvm-objcopy/ELF')
-rw-r--r--contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFConfig.cpp266
-rw-r--r--contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFConfig.h88
-rw-r--r--contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFObjcopy.cpp1556
-rw-r--r--contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFObjcopy.h72
-rw-r--r--contrib/libs/llvm12/tools/llvm-objcopy/ELF/Object.cpp4204
-rw-r--r--contrib/libs/llvm12/tools/llvm-objcopy/ELF/Object.h1926
6 files changed, 4056 insertions, 4056 deletions
diff --git a/contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFConfig.cpp b/contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFConfig.cpp
index 40993760ad..fcedf8ee11 100644
--- a/contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFConfig.cpp
+++ b/contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFConfig.cpp
@@ -1,133 +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
+//===- 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/contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFConfig.h b/contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFConfig.h
index 977efbc416..a51ac07546 100644
--- a/contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFConfig.h
+++ b/contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFConfig.h
@@ -1,44 +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
+//===- 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/contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFObjcopy.cpp b/contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
index c53a34bc46..6067ed6d26 100644
--- a/contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
+++ b/contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
@@ -1,592 +1,592 @@
-//===- ELFObjcopy.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 "ELFObjcopy.h"
-#include "Buffer.h"
-#include "CopyConfig.h"
-#include "Object.h"
-#include "llvm/ADT/BitmaskEnum.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/MC/MCTargetOptions.h"
-#include "llvm/Object/Binary.h"
-#include "llvm/Object/ELFObjectFile.h"
-#include "llvm/Object/ELFTypes.h"
-#include "llvm/Object/Error.h"
-#include "llvm/Option/Option.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Compression.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Memory.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <cstdlib>
-#include <functional>
-#include <iterator>
-#include <memory>
-#include <string>
-#include <system_error>
-#include <utility>
-
-namespace llvm {
-namespace objcopy {
-namespace elf {
-
-using namespace object;
-using namespace ELF;
-using SectionPred = std::function<bool(const SectionBase &Sec)>;
-
-static bool isDebugSection(const SectionBase &Sec) {
- return StringRef(Sec.Name).startswith(".debug") ||
- StringRef(Sec.Name).startswith(".zdebug") || Sec.Name == ".gdb_index";
-}
-
-static bool isDWOSection(const SectionBase &Sec) {
- return StringRef(Sec.Name).endswith(".dwo");
-}
-
-static bool onlyKeepDWOPred(const Object &Obj, const SectionBase &Sec) {
- // We can't remove the section header string table.
- if (&Sec == Obj.SectionNames)
- return false;
- // Short of keeping the string table we want to keep everything that is a DWO
- // section and remove everything else.
- return !isDWOSection(Sec);
-}
-
-uint64_t getNewShfFlags(SectionFlag AllFlags) {
- uint64_t NewFlags = 0;
- if (AllFlags & SectionFlag::SecAlloc)
- NewFlags |= ELF::SHF_ALLOC;
- if (!(AllFlags & SectionFlag::SecReadonly))
- NewFlags |= ELF::SHF_WRITE;
- if (AllFlags & SectionFlag::SecCode)
- NewFlags |= ELF::SHF_EXECINSTR;
- if (AllFlags & SectionFlag::SecMerge)
- NewFlags |= ELF::SHF_MERGE;
- if (AllFlags & SectionFlag::SecStrings)
- NewFlags |= ELF::SHF_STRINGS;
- if (AllFlags & SectionFlag::SecExclude)
- NewFlags |= ELF::SHF_EXCLUDE;
- return NewFlags;
-}
-
-static uint64_t getSectionFlagsPreserveMask(uint64_t OldFlags,
- uint64_t NewFlags) {
- // Preserve some flags which should not be dropped when setting flags.
- // Also, preserve anything OS/processor dependant.
- const uint64_t PreserveMask =
- (ELF::SHF_COMPRESSED | ELF::SHF_GROUP | ELF::SHF_LINK_ORDER |
- ELF::SHF_MASKOS | ELF::SHF_MASKPROC | ELF::SHF_TLS |
- ELF::SHF_INFO_LINK) &
- ~ELF::SHF_EXCLUDE;
- return (OldFlags & PreserveMask) | (NewFlags & ~PreserveMask);
-}
-
-static void setSectionFlagsAndType(SectionBase &Sec, SectionFlag Flags) {
- Sec.Flags = getSectionFlagsPreserveMask(Sec.Flags, getNewShfFlags(Flags));
-
- // In GNU objcopy, certain flags promote SHT_NOBITS to SHT_PROGBITS. This rule
- // may promote more non-ALLOC sections than GNU objcopy, but it is fine as
- // non-ALLOC SHT_NOBITS sections do not make much sense.
- if (Sec.Type == SHT_NOBITS &&
- (!(Sec.Flags & ELF::SHF_ALLOC) ||
- Flags & (SectionFlag::SecContents | SectionFlag::SecLoad)))
- Sec.Type = SHT_PROGBITS;
-}
-
-static ElfType getOutputElfType(const Binary &Bin) {
- // Infer output ELF type from the input ELF object
- if (isa<ELFObjectFile<ELF32LE>>(Bin))
- return ELFT_ELF32LE;
- if (isa<ELFObjectFile<ELF64LE>>(Bin))
- return ELFT_ELF64LE;
- if (isa<ELFObjectFile<ELF32BE>>(Bin))
- return ELFT_ELF32BE;
- if (isa<ELFObjectFile<ELF64BE>>(Bin))
- return ELFT_ELF64BE;
- llvm_unreachable("Invalid ELFType");
-}
-
-static ElfType getOutputElfType(const MachineInfo &MI) {
- // Infer output ELF type from the binary arch specified
- if (MI.Is64Bit)
- return MI.IsLittleEndian ? ELFT_ELF64LE : ELFT_ELF64BE;
- else
- return MI.IsLittleEndian ? ELFT_ELF32LE : ELFT_ELF32BE;
-}
-
-static std::unique_ptr<Writer> createELFWriter(const CopyConfig &Config,
- Object &Obj, Buffer &Buf,
- ElfType OutputElfType) {
- // Depending on the initial ELFT and OutputFormat we need a different Writer.
- switch (OutputElfType) {
- case ELFT_ELF32LE:
- return std::make_unique<ELFWriter<ELF32LE>>(Obj, Buf, !Config.StripSections,
- Config.OnlyKeepDebug);
- case ELFT_ELF64LE:
- return std::make_unique<ELFWriter<ELF64LE>>(Obj, Buf, !Config.StripSections,
- Config.OnlyKeepDebug);
- case ELFT_ELF32BE:
- return std::make_unique<ELFWriter<ELF32BE>>(Obj, Buf, !Config.StripSections,
- Config.OnlyKeepDebug);
- case ELFT_ELF64BE:
- return std::make_unique<ELFWriter<ELF64BE>>(Obj, Buf, !Config.StripSections,
- Config.OnlyKeepDebug);
- }
- llvm_unreachable("Invalid output format");
-}
-
-static std::unique_ptr<Writer> createWriter(const CopyConfig &Config,
- Object &Obj, Buffer &Buf,
- ElfType OutputElfType) {
- switch (Config.OutputFormat) {
- case FileFormat::Binary:
- return std::make_unique<BinaryWriter>(Obj, Buf);
- case FileFormat::IHex:
- return std::make_unique<IHexWriter>(Obj, Buf);
- default:
- return createELFWriter(Config, Obj, Buf, OutputElfType);
- }
-}
-
-template <class ELFT>
-static Expected<ArrayRef<uint8_t>>
-findBuildID(const CopyConfig &Config, const object::ELFFile<ELFT> &In) {
- auto PhdrsOrErr = In.program_headers();
- if (auto Err = PhdrsOrErr.takeError())
- return createFileError(Config.InputFilename, std::move(Err));
-
- for (const auto &Phdr : *PhdrsOrErr) {
- if (Phdr.p_type != PT_NOTE)
- continue;
- Error Err = Error::success();
- for (auto Note : In.notes(Phdr, Err))
- if (Note.getType() == NT_GNU_BUILD_ID && Note.getName() == ELF_NOTE_GNU)
- return Note.getDesc();
- if (Err)
- return createFileError(Config.InputFilename, std::move(Err));
- }
-
+//===- ELFObjcopy.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 "ELFObjcopy.h"
+#include "Buffer.h"
+#include "CopyConfig.h"
+#include "Object.h"
+#include "llvm/ADT/BitmaskEnum.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCTargetOptions.h"
+#include "llvm/Object/Binary.h"
+#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/ELFTypes.h"
+#include "llvm/Object/Error.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compression.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Memory.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdlib>
+#include <functional>
+#include <iterator>
+#include <memory>
+#include <string>
+#include <system_error>
+#include <utility>
+
+namespace llvm {
+namespace objcopy {
+namespace elf {
+
+using namespace object;
+using namespace ELF;
+using SectionPred = std::function<bool(const SectionBase &Sec)>;
+
+static bool isDebugSection(const SectionBase &Sec) {
+ return StringRef(Sec.Name).startswith(".debug") ||
+ StringRef(Sec.Name).startswith(".zdebug") || Sec.Name == ".gdb_index";
+}
+
+static bool isDWOSection(const SectionBase &Sec) {
+ return StringRef(Sec.Name).endswith(".dwo");
+}
+
+static bool onlyKeepDWOPred(const Object &Obj, const SectionBase &Sec) {
+ // We can't remove the section header string table.
+ if (&Sec == Obj.SectionNames)
+ return false;
+ // Short of keeping the string table we want to keep everything that is a DWO
+ // section and remove everything else.
+ return !isDWOSection(Sec);
+}
+
+uint64_t getNewShfFlags(SectionFlag AllFlags) {
+ uint64_t NewFlags = 0;
+ if (AllFlags & SectionFlag::SecAlloc)
+ NewFlags |= ELF::SHF_ALLOC;
+ if (!(AllFlags & SectionFlag::SecReadonly))
+ NewFlags |= ELF::SHF_WRITE;
+ if (AllFlags & SectionFlag::SecCode)
+ NewFlags |= ELF::SHF_EXECINSTR;
+ if (AllFlags & SectionFlag::SecMerge)
+ NewFlags |= ELF::SHF_MERGE;
+ if (AllFlags & SectionFlag::SecStrings)
+ NewFlags |= ELF::SHF_STRINGS;
+ if (AllFlags & SectionFlag::SecExclude)
+ NewFlags |= ELF::SHF_EXCLUDE;
+ return NewFlags;
+}
+
+static uint64_t getSectionFlagsPreserveMask(uint64_t OldFlags,
+ uint64_t NewFlags) {
+ // Preserve some flags which should not be dropped when setting flags.
+ // Also, preserve anything OS/processor dependant.
+ const uint64_t PreserveMask =
+ (ELF::SHF_COMPRESSED | ELF::SHF_GROUP | ELF::SHF_LINK_ORDER |
+ ELF::SHF_MASKOS | ELF::SHF_MASKPROC | ELF::SHF_TLS |
+ ELF::SHF_INFO_LINK) &
+ ~ELF::SHF_EXCLUDE;
+ return (OldFlags & PreserveMask) | (NewFlags & ~PreserveMask);
+}
+
+static void setSectionFlagsAndType(SectionBase &Sec, SectionFlag Flags) {
+ Sec.Flags = getSectionFlagsPreserveMask(Sec.Flags, getNewShfFlags(Flags));
+
+ // In GNU objcopy, certain flags promote SHT_NOBITS to SHT_PROGBITS. This rule
+ // may promote more non-ALLOC sections than GNU objcopy, but it is fine as
+ // non-ALLOC SHT_NOBITS sections do not make much sense.
+ if (Sec.Type == SHT_NOBITS &&
+ (!(Sec.Flags & ELF::SHF_ALLOC) ||
+ Flags & (SectionFlag::SecContents | SectionFlag::SecLoad)))
+ Sec.Type = SHT_PROGBITS;
+}
+
+static ElfType getOutputElfType(const Binary &Bin) {
+ // Infer output ELF type from the input ELF object
+ if (isa<ELFObjectFile<ELF32LE>>(Bin))
+ return ELFT_ELF32LE;
+ if (isa<ELFObjectFile<ELF64LE>>(Bin))
+ return ELFT_ELF64LE;
+ if (isa<ELFObjectFile<ELF32BE>>(Bin))
+ return ELFT_ELF32BE;
+ if (isa<ELFObjectFile<ELF64BE>>(Bin))
+ return ELFT_ELF64BE;
+ llvm_unreachable("Invalid ELFType");
+}
+
+static ElfType getOutputElfType(const MachineInfo &MI) {
+ // Infer output ELF type from the binary arch specified
+ if (MI.Is64Bit)
+ return MI.IsLittleEndian ? ELFT_ELF64LE : ELFT_ELF64BE;
+ else
+ return MI.IsLittleEndian ? ELFT_ELF32LE : ELFT_ELF32BE;
+}
+
+static std::unique_ptr<Writer> createELFWriter(const CopyConfig &Config,
+ Object &Obj, Buffer &Buf,
+ ElfType OutputElfType) {
+ // Depending on the initial ELFT and OutputFormat we need a different Writer.
+ switch (OutputElfType) {
+ case ELFT_ELF32LE:
+ return std::make_unique<ELFWriter<ELF32LE>>(Obj, Buf, !Config.StripSections,
+ Config.OnlyKeepDebug);
+ case ELFT_ELF64LE:
+ return std::make_unique<ELFWriter<ELF64LE>>(Obj, Buf, !Config.StripSections,
+ Config.OnlyKeepDebug);
+ case ELFT_ELF32BE:
+ return std::make_unique<ELFWriter<ELF32BE>>(Obj, Buf, !Config.StripSections,
+ Config.OnlyKeepDebug);
+ case ELFT_ELF64BE:
+ return std::make_unique<ELFWriter<ELF64BE>>(Obj, Buf, !Config.StripSections,
+ Config.OnlyKeepDebug);
+ }
+ llvm_unreachable("Invalid output format");
+}
+
+static std::unique_ptr<Writer> createWriter(const CopyConfig &Config,
+ Object &Obj, Buffer &Buf,
+ ElfType OutputElfType) {
+ switch (Config.OutputFormat) {
+ case FileFormat::Binary:
+ return std::make_unique<BinaryWriter>(Obj, Buf);
+ case FileFormat::IHex:
+ return std::make_unique<IHexWriter>(Obj, Buf);
+ default:
+ return createELFWriter(Config, Obj, Buf, OutputElfType);
+ }
+}
+
+template <class ELFT>
+static Expected<ArrayRef<uint8_t>>
+findBuildID(const CopyConfig &Config, const object::ELFFile<ELFT> &In) {
+ auto PhdrsOrErr = In.program_headers();
+ if (auto Err = PhdrsOrErr.takeError())
+ return createFileError(Config.InputFilename, std::move(Err));
+
+ for (const auto &Phdr : *PhdrsOrErr) {
+ if (Phdr.p_type != PT_NOTE)
+ continue;
+ Error Err = Error::success();
+ for (auto Note : In.notes(Phdr, Err))
+ if (Note.getType() == NT_GNU_BUILD_ID && Note.getName() == ELF_NOTE_GNU)
+ return Note.getDesc();
+ if (Err)
+ return createFileError(Config.InputFilename, std::move(Err));
+ }
+
return createFileError(Config.InputFilename,
createStringError(llvm::errc::invalid_argument,
"could not find build ID"));
-}
-
-static Expected<ArrayRef<uint8_t>>
-findBuildID(const CopyConfig &Config, const object::ELFObjectFileBase &In) {
- if (auto *O = dyn_cast<ELFObjectFile<ELF32LE>>(&In))
+}
+
+static Expected<ArrayRef<uint8_t>>
+findBuildID(const CopyConfig &Config, const object::ELFObjectFileBase &In) {
+ if (auto *O = dyn_cast<ELFObjectFile<ELF32LE>>(&In))
return findBuildID(Config, O->getELFFile());
- else if (auto *O = dyn_cast<ELFObjectFile<ELF64LE>>(&In))
+ else if (auto *O = dyn_cast<ELFObjectFile<ELF64LE>>(&In))
return findBuildID(Config, O->getELFFile());
- else if (auto *O = dyn_cast<ELFObjectFile<ELF32BE>>(&In))
+ else if (auto *O = dyn_cast<ELFObjectFile<ELF32BE>>(&In))
return findBuildID(Config, O->getELFFile());
- else if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(&In))
+ else if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(&In))
return findBuildID(Config, O->getELFFile());
-
- llvm_unreachable("Bad file format");
-}
-
-template <class... Ts>
+
+ llvm_unreachable("Bad file format");
+}
+
+template <class... Ts>
static Error makeStringError(std::error_code EC, const Twine &Msg,
Ts &&... Args) {
- std::string FullMsg = (EC.message() + ": " + Msg).str();
- return createStringError(EC, FullMsg.c_str(), std::forward<Ts>(Args)...);
-}
-
-#define MODEL_8 "%%%%%%%%"
-#define MODEL_16 MODEL_8 MODEL_8
-#define MODEL_32 (MODEL_16 MODEL_16)
-
-static Error linkToBuildIdDir(const CopyConfig &Config, StringRef ToLink,
- StringRef Suffix,
- ArrayRef<uint8_t> BuildIdBytes) {
- SmallString<128> Path = Config.BuildIdLinkDir;
- sys::path::append(Path, llvm::toHex(BuildIdBytes[0], /*LowerCase*/ true));
- if (auto EC = sys::fs::create_directories(Path))
- return createFileError(
- Path.str(),
- makeStringError(EC, "cannot create build ID link directory"));
-
- sys::path::append(Path,
- llvm::toHex(BuildIdBytes.slice(1), /*LowerCase*/ true));
- Path += Suffix;
- SmallString<128> TmpPath;
- // create_hard_link races so we need to link to a temporary path but
- // we want to make sure that we choose a filename that does not exist.
- // By using 32 model characters we get 128-bits of entropy. It is
- // unlikely that this string has ever existed before much less exists
- // on this disk or in the current working directory.
- // Additionally we prepend the original Path for debugging but also
- // because it ensures that we're linking within a directory on the same
- // partition on the same device which is critical. It has the added
- // win of yet further decreasing the odds of a conflict.
- sys::fs::createUniquePath(Twine(Path) + "-" + MODEL_32 + ".tmp", TmpPath,
- /*MakeAbsolute*/ false);
- if (auto EC = sys::fs::create_hard_link(ToLink, TmpPath)) {
- Path.push_back('\0');
- return makeStringError(EC, "cannot link '%s' to '%s'", ToLink.data(),
- Path.data());
- }
- // We then atomically rename the link into place which will just move the
- // link. If rename fails something is more seriously wrong so just return
- // an error.
- if (auto EC = sys::fs::rename(TmpPath, Path)) {
- Path.push_back('\0');
- return makeStringError(EC, "cannot link '%s' to '%s'", ToLink.data(),
- Path.data());
- }
- // If `Path` was already a hard-link to the same underlying file then the
- // temp file will be left so we need to remove it. Remove will not cause
- // an error by default if the file is already gone so just blindly remove
- // it rather than checking.
- if (auto EC = sys::fs::remove(TmpPath)) {
- TmpPath.push_back('\0');
- return makeStringError(EC, "could not remove '%s'", TmpPath.data());
- }
- return Error::success();
-}
-
-static Error splitDWOToFile(const CopyConfig &Config, const Reader &Reader,
- StringRef File, ElfType OutputElfType) {
+ std::string FullMsg = (EC.message() + ": " + Msg).str();
+ return createStringError(EC, FullMsg.c_str(), std::forward<Ts>(Args)...);
+}
+
+#define MODEL_8 "%%%%%%%%"
+#define MODEL_16 MODEL_8 MODEL_8
+#define MODEL_32 (MODEL_16 MODEL_16)
+
+static Error linkToBuildIdDir(const CopyConfig &Config, StringRef ToLink,
+ StringRef Suffix,
+ ArrayRef<uint8_t> BuildIdBytes) {
+ SmallString<128> Path = Config.BuildIdLinkDir;
+ sys::path::append(Path, llvm::toHex(BuildIdBytes[0], /*LowerCase*/ true));
+ if (auto EC = sys::fs::create_directories(Path))
+ return createFileError(
+ Path.str(),
+ makeStringError(EC, "cannot create build ID link directory"));
+
+ sys::path::append(Path,
+ llvm::toHex(BuildIdBytes.slice(1), /*LowerCase*/ true));
+ Path += Suffix;
+ SmallString<128> TmpPath;
+ // create_hard_link races so we need to link to a temporary path but
+ // we want to make sure that we choose a filename that does not exist.
+ // By using 32 model characters we get 128-bits of entropy. It is
+ // unlikely that this string has ever existed before much less exists
+ // on this disk or in the current working directory.
+ // Additionally we prepend the original Path for debugging but also
+ // because it ensures that we're linking within a directory on the same
+ // partition on the same device which is critical. It has the added
+ // win of yet further decreasing the odds of a conflict.
+ sys::fs::createUniquePath(Twine(Path) + "-" + MODEL_32 + ".tmp", TmpPath,
+ /*MakeAbsolute*/ false);
+ if (auto EC = sys::fs::create_hard_link(ToLink, TmpPath)) {
+ Path.push_back('\0');
+ return makeStringError(EC, "cannot link '%s' to '%s'", ToLink.data(),
+ Path.data());
+ }
+ // We then atomically rename the link into place which will just move the
+ // link. If rename fails something is more seriously wrong so just return
+ // an error.
+ if (auto EC = sys::fs::rename(TmpPath, Path)) {
+ Path.push_back('\0');
+ return makeStringError(EC, "cannot link '%s' to '%s'", ToLink.data(),
+ Path.data());
+ }
+ // If `Path` was already a hard-link to the same underlying file then the
+ // temp file will be left so we need to remove it. Remove will not cause
+ // an error by default if the file is already gone so just blindly remove
+ // it rather than checking.
+ if (auto EC = sys::fs::remove(TmpPath)) {
+ TmpPath.push_back('\0');
+ return makeStringError(EC, "could not remove '%s'", TmpPath.data());
+ }
+ return Error::success();
+}
+
+static Error splitDWOToFile(const CopyConfig &Config, const Reader &Reader,
+ StringRef File, ElfType OutputElfType) {
Expected<std::unique_ptr<Object>> DWOFile = Reader.create(false);
if (!DWOFile)
return DWOFile.takeError();
- auto OnlyKeepDWOPred = [&DWOFile](const SectionBase &Sec) {
+ auto OnlyKeepDWOPred = [&DWOFile](const SectionBase &Sec) {
return onlyKeepDWOPred(**DWOFile, Sec);
- };
+ };
if (Error E =
(*DWOFile)->removeSections(Config.AllowBrokenLinks, OnlyKeepDWOPred))
- return E;
- if (Config.OutputArch) {
+ return E;
+ if (Config.OutputArch) {
(*DWOFile)->Machine = Config.OutputArch.getValue().EMachine;
(*DWOFile)->OSABI = Config.OutputArch.getValue().OSABI;
- }
- FileBuffer FB(File);
+ }
+ FileBuffer FB(File);
std::unique_ptr<Writer> Writer =
createWriter(Config, **DWOFile, FB, OutputElfType);
- if (Error E = Writer->finalize())
- return E;
- return Writer->write();
-}
-
-static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
- Object &Obj) {
- for (auto &Sec : Obj.sections()) {
- if (Sec.Name == SecName) {
- if (Sec.Type == SHT_NOBITS)
- return createStringError(object_error::parse_failed,
- "cannot dump section '%s': it has no contents",
- SecName.str().c_str());
- Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
- FileOutputBuffer::create(Filename, Sec.OriginalData.size());
- if (!BufferOrErr)
- return BufferOrErr.takeError();
- std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);
- std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(),
- Buf->getBufferStart());
- if (Error E = Buf->commit())
- return E;
- return Error::success();
- }
- }
- return createStringError(object_error::parse_failed, "section '%s' not found",
- SecName.str().c_str());
-}
-
-static bool isCompressable(const SectionBase &Sec) {
- return !(Sec.Flags & ELF::SHF_COMPRESSED) &&
- StringRef(Sec.Name).startswith(".debug");
-}
-
+ if (Error E = Writer->finalize())
+ return E;
+ return Writer->write();
+}
+
+static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
+ Object &Obj) {
+ for (auto &Sec : Obj.sections()) {
+ if (Sec.Name == SecName) {
+ if (Sec.Type == SHT_NOBITS)
+ return createStringError(object_error::parse_failed,
+ "cannot dump section '%s': it has no contents",
+ SecName.str().c_str());
+ Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
+ FileOutputBuffer::create(Filename, Sec.OriginalData.size());
+ if (!BufferOrErr)
+ return BufferOrErr.takeError();
+ std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);
+ std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(),
+ Buf->getBufferStart());
+ if (Error E = Buf->commit())
+ return E;
+ return Error::success();
+ }
+ }
+ return createStringError(object_error::parse_failed, "section '%s' not found",
+ SecName.str().c_str());
+}
+
+static bool isCompressable(const SectionBase &Sec) {
+ return !(Sec.Flags & ELF::SHF_COMPRESSED) &&
+ StringRef(Sec.Name).startswith(".debug");
+}
+
static Error replaceDebugSections(
- Object &Obj, SectionPred &RemovePred,
+ Object &Obj, SectionPred &RemovePred,
function_ref<bool(const SectionBase &)> ShouldReplace,
function_ref<Expected<SectionBase *>(const SectionBase *)> AddSection) {
- // Build a list of the debug sections we are going to replace.
+ // Build a list of the debug sections we are going to replace.
// We can't call `AddSection` while iterating over sections,
- // because it would mutate the sections array.
- SmallVector<SectionBase *, 13> ToReplace;
- for (auto &Sec : Obj.sections())
+ // because it would mutate the sections array.
+ SmallVector<SectionBase *, 13> ToReplace;
+ for (auto &Sec : Obj.sections())
if (ShouldReplace(Sec))
- ToReplace.push_back(&Sec);
-
- // Build a mapping from original section to a new one.
- DenseMap<SectionBase *, SectionBase *> FromTo;
+ ToReplace.push_back(&Sec);
+
+ // Build a mapping from original section to a new one.
+ DenseMap<SectionBase *, SectionBase *> FromTo;
for (SectionBase *S : ToReplace) {
Expected<SectionBase *> NewSection = AddSection(S);
if (!NewSection)
return NewSection.takeError();
-
+
FromTo[S] = *NewSection;
}
- // Now we want to update the target sections of relocation
- // sections. Also we will update the relocations themselves
- // to update the symbol references.
- for (auto &Sec : Obj.sections())
- Sec.replaceSectionReferences(FromTo);
-
+ // Now we want to update the target sections of relocation
+ // sections. Also we will update the relocations themselves
+ // to update the symbol references.
+ for (auto &Sec : Obj.sections())
+ Sec.replaceSectionReferences(FromTo);
+
RemovePred = [ShouldReplace, RemovePred](const SectionBase &Sec) {
return ShouldReplace(Sec) || RemovePred(Sec);
- };
+ };
return Error::success();
-}
-
-static bool isUnneededSymbol(const Symbol &Sym) {
- return !Sym.Referenced &&
- (Sym.Binding == STB_LOCAL || Sym.getShndx() == SHN_UNDEF) &&
- Sym.Type != STT_SECTION;
-}
-
-static Error updateAndRemoveSymbols(const CopyConfig &Config, Object &Obj) {
- // TODO: update or remove symbols only if there is an option that affects
- // them.
- if (!Obj.SymbolTable)
- return Error::success();
-
- Obj.SymbolTable->updateSymbols([&](Symbol &Sym) {
- // Common and undefined symbols don't make sense as local symbols, and can
- // even cause crashes if we localize those, so skip them.
- if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF &&
- ((Config.LocalizeHidden &&
- (Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) ||
- Config.SymbolsToLocalize.matches(Sym.Name)))
- Sym.Binding = STB_LOCAL;
-
- // Note: these two globalize flags have very similar names but different
- // meanings:
- //
- // --globalize-symbol: promote a symbol to global
- // --keep-global-symbol: all symbols except for these should be made local
- //
- // If --globalize-symbol is specified for a given symbol, it will be
- // global in the output file even if it is not included via
- // --keep-global-symbol. Because of that, make sure to check
- // --globalize-symbol second.
- if (!Config.SymbolsToKeepGlobal.empty() &&
- !Config.SymbolsToKeepGlobal.matches(Sym.Name) &&
- Sym.getShndx() != SHN_UNDEF)
- Sym.Binding = STB_LOCAL;
-
- if (Config.SymbolsToGlobalize.matches(Sym.Name) &&
- Sym.getShndx() != SHN_UNDEF)
- 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 &&
- Sym.getShndx() != SHN_UNDEF)
- Sym.Binding = STB_WEAK;
-
- const auto I = Config.SymbolsToRename.find(Sym.Name);
- if (I != Config.SymbolsToRename.end())
- Sym.Name = std::string(I->getValue());
-
- if (!Config.SymbolsPrefix.empty() && Sym.Type != STT_SECTION)
- Sym.Name = (Config.SymbolsPrefix + Sym.Name).str();
- });
-
- // The purpose of this loop is to mark symbols referenced by sections
- // (like GroupSection or RelocationSection). This way, we know which
- // symbols are still 'needed' and which are not.
- if (Config.StripUnneeded || !Config.UnneededSymbolsToRemove.empty() ||
- !Config.OnlySection.empty()) {
- for (SectionBase &Sec : Obj.sections())
- Sec.markSymbols();
- }
-
- auto RemoveSymbolsPred = [&](const Symbol &Sym) {
- if (Config.SymbolsToKeep.matches(Sym.Name) ||
- (Config.KeepFileSymbols && Sym.Type == STT_FILE))
- return false;
-
- if ((Config.DiscardMode == DiscardType::All ||
- (Config.DiscardMode == DiscardType::Locals &&
- StringRef(Sym.Name).startswith(".L"))) &&
- Sym.Binding == STB_LOCAL && Sym.getShndx() != SHN_UNDEF &&
- Sym.Type != STT_FILE && Sym.Type != STT_SECTION)
- return true;
-
- if (Config.StripAll || Config.StripAllGNU)
- return true;
-
- if (Config.StripDebug && Sym.Type == STT_FILE)
- return true;
-
- if (Config.SymbolsToRemove.matches(Sym.Name))
- return true;
-
- if ((Config.StripUnneeded ||
- Config.UnneededSymbolsToRemove.matches(Sym.Name)) &&
- (!Obj.isRelocatable() || isUnneededSymbol(Sym)))
- return true;
-
- // We want to remove undefined symbols if all references have been stripped.
- if (!Config.OnlySection.empty() && !Sym.Referenced &&
- Sym.getShndx() == SHN_UNDEF)
- return true;
-
- return false;
- };
-
- return Obj.removeSymbols(RemoveSymbolsPred);
-}
-
-static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) {
- SectionPred RemovePred = [](const SectionBase &) { return false; };
-
- // Removes:
- if (!Config.ToRemove.empty()) {
- RemovePred = [&Config](const SectionBase &Sec) {
- return Config.ToRemove.matches(Sec.Name);
- };
- }
-
- if (Config.StripDWO || !Config.SplitDWO.empty())
- RemovePred = [RemovePred](const SectionBase &Sec) {
- return isDWOSection(Sec) || RemovePred(Sec);
- };
-
- if (Config.ExtractDWO)
- RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
- return onlyKeepDWOPred(Obj, Sec) || RemovePred(Sec);
- };
-
- if (Config.StripAllGNU)
- RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
- if (RemovePred(Sec))
- return true;
- if ((Sec.Flags & SHF_ALLOC) != 0)
- return false;
- if (&Sec == Obj.SectionNames)
- return false;
- switch (Sec.Type) {
- case SHT_SYMTAB:
- case SHT_REL:
- case SHT_RELA:
- case SHT_STRTAB:
- return true;
- }
- return isDebugSection(Sec);
- };
-
- if (Config.StripSections) {
- RemovePred = [RemovePred](const SectionBase &Sec) {
- return RemovePred(Sec) || Sec.ParentSegment == nullptr;
- };
- }
-
- if (Config.StripDebug || Config.StripUnneeded) {
- RemovePred = [RemovePred](const SectionBase &Sec) {
- return RemovePred(Sec) || isDebugSection(Sec);
- };
- }
-
- if (Config.StripNonAlloc)
- RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
- if (RemovePred(Sec))
- return true;
- if (&Sec == Obj.SectionNames)
- return false;
- return (Sec.Flags & SHF_ALLOC) == 0 && Sec.ParentSegment == nullptr;
- };
-
- if (Config.StripAll)
- RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
- if (RemovePred(Sec))
- return true;
- if (&Sec == Obj.SectionNames)
- return false;
- if (StringRef(Sec.Name).startswith(".gnu.warning"))
- return false;
- // We keep the .ARM.attribute section to maintain compatibility
- // with Debian derived distributions. This is a bug in their
- // patchset as documented here:
- // https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=943798
- if (Sec.Type == SHT_ARM_ATTRIBUTES)
- return false;
- if (Sec.ParentSegment != nullptr)
- return false;
- return (Sec.Flags & SHF_ALLOC) == 0;
- };
-
- if (Config.ExtractPartition || Config.ExtractMainPartition) {
- RemovePred = [RemovePred](const SectionBase &Sec) {
- if (RemovePred(Sec))
- return true;
- if (Sec.Type == SHT_LLVM_PART_EHDR || Sec.Type == SHT_LLVM_PART_PHDR)
- return true;
- return (Sec.Flags & SHF_ALLOC) != 0 && !Sec.ParentSegment;
- };
- }
-
- // Explicit copies:
- if (!Config.OnlySection.empty()) {
- RemovePred = [&Config, RemovePred, &Obj](const SectionBase &Sec) {
- // Explicitly keep these sections regardless of previous removes.
- if (Config.OnlySection.matches(Sec.Name))
- return false;
-
- // Allow all implicit removes.
- if (RemovePred(Sec))
- return true;
-
- // Keep special sections.
- if (Obj.SectionNames == &Sec)
- return false;
- if (Obj.SymbolTable == &Sec ||
- (Obj.SymbolTable && Obj.SymbolTable->getStrTab() == &Sec))
- return false;
-
- // Remove everything else.
- return true;
- };
- }
-
- if (!Config.KeepSection.empty()) {
- RemovePred = [&Config, RemovePred](const SectionBase &Sec) {
- // Explicitly keep these sections regardless of previous removes.
- if (Config.KeepSection.matches(Sec.Name))
- return false;
- // Otherwise defer to RemovePred.
- return RemovePred(Sec);
- };
- }
-
- // This has to be the last predicate assignment.
- // If the option --keep-symbol has been specified
- // and at least one of those symbols is present
- // (equivalently, the updated symbol table is not empty)
- // the symbol table and the string table should not be removed.
- if ((!Config.SymbolsToKeep.empty() || Config.KeepFileSymbols) &&
- Obj.SymbolTable && !Obj.SymbolTable->empty()) {
- RemovePred = [&Obj, RemovePred](const SectionBase &Sec) {
- if (&Sec == Obj.SymbolTable || &Sec == Obj.SymbolTable->getStrTab())
- return false;
- return RemovePred(Sec);
- };
- }
-
+}
+
+static bool isUnneededSymbol(const Symbol &Sym) {
+ return !Sym.Referenced &&
+ (Sym.Binding == STB_LOCAL || Sym.getShndx() == SHN_UNDEF) &&
+ Sym.Type != STT_SECTION;
+}
+
+static Error updateAndRemoveSymbols(const CopyConfig &Config, Object &Obj) {
+ // TODO: update or remove symbols only if there is an option that affects
+ // them.
+ if (!Obj.SymbolTable)
+ return Error::success();
+
+ Obj.SymbolTable->updateSymbols([&](Symbol &Sym) {
+ // Common and undefined symbols don't make sense as local symbols, and can
+ // even cause crashes if we localize those, so skip them.
+ if (!Sym.isCommon() && Sym.getShndx() != SHN_UNDEF &&
+ ((Config.LocalizeHidden &&
+ (Sym.Visibility == STV_HIDDEN || Sym.Visibility == STV_INTERNAL)) ||
+ Config.SymbolsToLocalize.matches(Sym.Name)))
+ Sym.Binding = STB_LOCAL;
+
+ // Note: these two globalize flags have very similar names but different
+ // meanings:
+ //
+ // --globalize-symbol: promote a symbol to global
+ // --keep-global-symbol: all symbols except for these should be made local
+ //
+ // If --globalize-symbol is specified for a given symbol, it will be
+ // global in the output file even if it is not included via
+ // --keep-global-symbol. Because of that, make sure to check
+ // --globalize-symbol second.
+ if (!Config.SymbolsToKeepGlobal.empty() &&
+ !Config.SymbolsToKeepGlobal.matches(Sym.Name) &&
+ Sym.getShndx() != SHN_UNDEF)
+ Sym.Binding = STB_LOCAL;
+
+ if (Config.SymbolsToGlobalize.matches(Sym.Name) &&
+ Sym.getShndx() != SHN_UNDEF)
+ 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 &&
+ Sym.getShndx() != SHN_UNDEF)
+ Sym.Binding = STB_WEAK;
+
+ const auto I = Config.SymbolsToRename.find(Sym.Name);
+ if (I != Config.SymbolsToRename.end())
+ Sym.Name = std::string(I->getValue());
+
+ if (!Config.SymbolsPrefix.empty() && Sym.Type != STT_SECTION)
+ Sym.Name = (Config.SymbolsPrefix + Sym.Name).str();
+ });
+
+ // The purpose of this loop is to mark symbols referenced by sections
+ // (like GroupSection or RelocationSection). This way, we know which
+ // symbols are still 'needed' and which are not.
+ if (Config.StripUnneeded || !Config.UnneededSymbolsToRemove.empty() ||
+ !Config.OnlySection.empty()) {
+ for (SectionBase &Sec : Obj.sections())
+ Sec.markSymbols();
+ }
+
+ auto RemoveSymbolsPred = [&](const Symbol &Sym) {
+ if (Config.SymbolsToKeep.matches(Sym.Name) ||
+ (Config.KeepFileSymbols && Sym.Type == STT_FILE))
+ return false;
+
+ if ((Config.DiscardMode == DiscardType::All ||
+ (Config.DiscardMode == DiscardType::Locals &&
+ StringRef(Sym.Name).startswith(".L"))) &&
+ Sym.Binding == STB_LOCAL && Sym.getShndx() != SHN_UNDEF &&
+ Sym.Type != STT_FILE && Sym.Type != STT_SECTION)
+ return true;
+
+ if (Config.StripAll || Config.StripAllGNU)
+ return true;
+
+ if (Config.StripDebug && Sym.Type == STT_FILE)
+ return true;
+
+ if (Config.SymbolsToRemove.matches(Sym.Name))
+ return true;
+
+ if ((Config.StripUnneeded ||
+ Config.UnneededSymbolsToRemove.matches(Sym.Name)) &&
+ (!Obj.isRelocatable() || isUnneededSymbol(Sym)))
+ return true;
+
+ // We want to remove undefined symbols if all references have been stripped.
+ if (!Config.OnlySection.empty() && !Sym.Referenced &&
+ Sym.getShndx() == SHN_UNDEF)
+ return true;
+
+ return false;
+ };
+
+ return Obj.removeSymbols(RemoveSymbolsPred);
+}
+
+static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) {
+ SectionPred RemovePred = [](const SectionBase &) { return false; };
+
+ // Removes:
+ if (!Config.ToRemove.empty()) {
+ RemovePred = [&Config](const SectionBase &Sec) {
+ return Config.ToRemove.matches(Sec.Name);
+ };
+ }
+
+ if (Config.StripDWO || !Config.SplitDWO.empty())
+ RemovePred = [RemovePred](const SectionBase &Sec) {
+ return isDWOSection(Sec) || RemovePred(Sec);
+ };
+
+ if (Config.ExtractDWO)
+ RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
+ return onlyKeepDWOPred(Obj, Sec) || RemovePred(Sec);
+ };
+
+ if (Config.StripAllGNU)
+ RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
+ if (RemovePred(Sec))
+ return true;
+ if ((Sec.Flags & SHF_ALLOC) != 0)
+ return false;
+ if (&Sec == Obj.SectionNames)
+ return false;
+ switch (Sec.Type) {
+ case SHT_SYMTAB:
+ case SHT_REL:
+ case SHT_RELA:
+ case SHT_STRTAB:
+ return true;
+ }
+ return isDebugSection(Sec);
+ };
+
+ if (Config.StripSections) {
+ RemovePred = [RemovePred](const SectionBase &Sec) {
+ return RemovePred(Sec) || Sec.ParentSegment == nullptr;
+ };
+ }
+
+ if (Config.StripDebug || Config.StripUnneeded) {
+ RemovePred = [RemovePred](const SectionBase &Sec) {
+ return RemovePred(Sec) || isDebugSection(Sec);
+ };
+ }
+
+ if (Config.StripNonAlloc)
+ RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
+ if (RemovePred(Sec))
+ return true;
+ if (&Sec == Obj.SectionNames)
+ return false;
+ return (Sec.Flags & SHF_ALLOC) == 0 && Sec.ParentSegment == nullptr;
+ };
+
+ if (Config.StripAll)
+ RemovePred = [RemovePred, &Obj](const SectionBase &Sec) {
+ if (RemovePred(Sec))
+ return true;
+ if (&Sec == Obj.SectionNames)
+ return false;
+ if (StringRef(Sec.Name).startswith(".gnu.warning"))
+ return false;
+ // We keep the .ARM.attribute section to maintain compatibility
+ // with Debian derived distributions. This is a bug in their
+ // patchset as documented here:
+ // https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=943798
+ if (Sec.Type == SHT_ARM_ATTRIBUTES)
+ return false;
+ if (Sec.ParentSegment != nullptr)
+ return false;
+ return (Sec.Flags & SHF_ALLOC) == 0;
+ };
+
+ if (Config.ExtractPartition || Config.ExtractMainPartition) {
+ RemovePred = [RemovePred](const SectionBase &Sec) {
+ if (RemovePred(Sec))
+ return true;
+ if (Sec.Type == SHT_LLVM_PART_EHDR || Sec.Type == SHT_LLVM_PART_PHDR)
+ return true;
+ return (Sec.Flags & SHF_ALLOC) != 0 && !Sec.ParentSegment;
+ };
+ }
+
+ // Explicit copies:
+ if (!Config.OnlySection.empty()) {
+ RemovePred = [&Config, RemovePred, &Obj](const SectionBase &Sec) {
+ // Explicitly keep these sections regardless of previous removes.
+ if (Config.OnlySection.matches(Sec.Name))
+ return false;
+
+ // Allow all implicit removes.
+ if (RemovePred(Sec))
+ return true;
+
+ // Keep special sections.
+ if (Obj.SectionNames == &Sec)
+ return false;
+ if (Obj.SymbolTable == &Sec ||
+ (Obj.SymbolTable && Obj.SymbolTable->getStrTab() == &Sec))
+ return false;
+
+ // Remove everything else.
+ return true;
+ };
+ }
+
+ if (!Config.KeepSection.empty()) {
+ RemovePred = [&Config, RemovePred](const SectionBase &Sec) {
+ // Explicitly keep these sections regardless of previous removes.
+ if (Config.KeepSection.matches(Sec.Name))
+ return false;
+ // Otherwise defer to RemovePred.
+ return RemovePred(Sec);
+ };
+ }
+
+ // This has to be the last predicate assignment.
+ // If the option --keep-symbol has been specified
+ // and at least one of those symbols is present
+ // (equivalently, the updated symbol table is not empty)
+ // the symbol table and the string table should not be removed.
+ if ((!Config.SymbolsToKeep.empty() || Config.KeepFileSymbols) &&
+ Obj.SymbolTable && !Obj.SymbolTable->empty()) {
+ RemovePred = [&Obj, RemovePred](const SectionBase &Sec) {
+ if (&Sec == Obj.SymbolTable || &Sec == Obj.SymbolTable->getStrTab())
+ return false;
+ return RemovePred(Sec);
+ };
+ }
+
if (Config.CompressionType != DebugCompressionType::None) {
if (Error Err = replaceDebugSections(
Obj, RemovePred, isCompressable,
@@ -595,7 +595,7 @@ static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) {
CompressedSection::create(*S, Config.CompressionType);
if (!NewSection)
return NewSection.takeError();
-
+
return &Obj.addSection<CompressedSection>(std::move(*NewSection));
}))
return Err;
@@ -610,156 +610,156 @@ static Error replaceAndRemoveSections(const CopyConfig &Config, Object &Obj) {
return Err;
}
- return Obj.removeSections(Config.AllowBrokenLinks, RemovePred);
-}
-
-// This function handles the high level operations of GNU objcopy including
-// handling command line options. It's important to outline certain properties
-// we expect to hold of the command line operations. Any operation that "keeps"
-// should keep regardless of a remove. Additionally any removal should respect
-// any previous removals. Lastly whether or not something is removed shouldn't
-// depend a) on the order the options occur in or b) on some opaque priority
-// system. The only priority is that keeps/copies overrule removes.
-static Error handleArgs(const CopyConfig &Config, Object &Obj,
- const Reader &Reader, ElfType OutputElfType) {
- if (Config.StripSwiftSymbols)
- return createStringError(llvm::errc::invalid_argument,
- "option not supported by llvm-objcopy for ELF");
- if (!Config.SplitDWO.empty())
- if (Error E =
- splitDWOToFile(Config, Reader, Config.SplitDWO, OutputElfType))
- return E;
-
- if (Config.OutputArch) {
- Obj.Machine = Config.OutputArch.getValue().EMachine;
- Obj.OSABI = Config.OutputArch.getValue().OSABI;
- }
-
- // Dump sections before add/remove for compatibility with GNU objcopy.
- for (StringRef Flag : Config.DumpSection) {
- StringRef SectionName;
- StringRef FileName;
- std::tie(SectionName, FileName) = Flag.split('=');
- if (Error E = dumpSectionToFile(SectionName, FileName, Obj))
- return E;
- }
-
- // It is important to remove the sections first. For example, we want to
- // remove the relocation sections before removing the symbols. That allows
- // us to avoid reporting the inappropriate errors about removing symbols
- // named in relocations.
- if (Error E = replaceAndRemoveSections(Config, Obj))
- return E;
-
- if (Error E = updateAndRemoveSymbols(Config, Obj))
- return E;
-
- 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;
- Sec.Name = std::string(SR.NewName);
- 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()) {
- 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.OnlyKeepDebug)
- for (auto &Sec : Obj.sections())
- if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE)
- Sec.Type = SHT_NOBITS;
-
- for (const auto &Flag : Config.AddSection) {
- std::pair<StringRef, StringRef> SecPair = Flag.split("=");
- StringRef SecName = SecPair.first;
- StringRef File = SecPair.second;
- ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
- MemoryBuffer::getFile(File);
- if (!BufOrErr)
- return createFileError(File, errorCodeToError(BufOrErr.getError()));
- std::unique_ptr<MemoryBuffer> Buf = std::move(*BufOrErr);
- ArrayRef<uint8_t> Data(
- reinterpret_cast<const uint8_t *>(Buf->getBufferStart()),
- Buf->getBufferSize());
- OwnedDataSection &NewSection =
- Obj.addSection<OwnedDataSection>(SecName, Data);
- if (SecName.startswith(".note") && SecName != ".note.GNU-stack")
- NewSection.Type = SHT_NOTE;
- }
-
- if (!Config.AddGnuDebugLink.empty())
- Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink,
- Config.GnuDebugLinkCRC32);
-
- // If the symbol table was previously removed, we need to create a new one
- // before adding new symbols.
+ return Obj.removeSections(Config.AllowBrokenLinks, RemovePred);
+}
+
+// This function handles the high level operations of GNU objcopy including
+// handling command line options. It's important to outline certain properties
+// we expect to hold of the command line operations. Any operation that "keeps"
+// should keep regardless of a remove. Additionally any removal should respect
+// any previous removals. Lastly whether or not something is removed shouldn't
+// depend a) on the order the options occur in or b) on some opaque priority
+// system. The only priority is that keeps/copies overrule removes.
+static Error handleArgs(const CopyConfig &Config, Object &Obj,
+ const Reader &Reader, ElfType OutputElfType) {
+ if (Config.StripSwiftSymbols)
+ return createStringError(llvm::errc::invalid_argument,
+ "option not supported by llvm-objcopy for ELF");
+ if (!Config.SplitDWO.empty())
+ if (Error E =
+ splitDWOToFile(Config, Reader, Config.SplitDWO, OutputElfType))
+ return E;
+
+ if (Config.OutputArch) {
+ Obj.Machine = Config.OutputArch.getValue().EMachine;
+ Obj.OSABI = Config.OutputArch.getValue().OSABI;
+ }
+
+ // Dump sections before add/remove for compatibility with GNU objcopy.
+ for (StringRef Flag : Config.DumpSection) {
+ StringRef SectionName;
+ StringRef FileName;
+ std::tie(SectionName, FileName) = Flag.split('=');
+ if (Error E = dumpSectionToFile(SectionName, FileName, Obj))
+ return E;
+ }
+
+ // It is important to remove the sections first. For example, we want to
+ // remove the relocation sections before removing the symbols. That allows
+ // us to avoid reporting the inappropriate errors about removing symbols
+ // named in relocations.
+ if (Error E = replaceAndRemoveSections(Config, Obj))
+ return E;
+
+ if (Error E = updateAndRemoveSymbols(Config, Obj))
+ return E;
+
+ 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;
+ Sec.Name = std::string(SR.NewName);
+ 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()) {
+ 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.OnlyKeepDebug)
+ for (auto &Sec : Obj.sections())
+ if (Sec.Flags & SHF_ALLOC && Sec.Type != SHT_NOTE)
+ Sec.Type = SHT_NOBITS;
+
+ for (const auto &Flag : Config.AddSection) {
+ std::pair<StringRef, StringRef> SecPair = Flag.split("=");
+ StringRef SecName = SecPair.first;
+ StringRef File = SecPair.second;
+ ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
+ MemoryBuffer::getFile(File);
+ if (!BufOrErr)
+ return createFileError(File, errorCodeToError(BufOrErr.getError()));
+ std::unique_ptr<MemoryBuffer> Buf = std::move(*BufOrErr);
+ ArrayRef<uint8_t> Data(
+ reinterpret_cast<const uint8_t *>(Buf->getBufferStart()),
+ Buf->getBufferSize());
+ OwnedDataSection &NewSection =
+ Obj.addSection<OwnedDataSection>(SecName, Data);
+ if (SecName.startswith(".note") && SecName != ".note.GNU-stack")
+ NewSection.Type = SHT_NOTE;
+ }
+
+ if (!Config.AddGnuDebugLink.empty())
+ Obj.addSection<GnuDebugLinkSection>(Config.AddGnuDebugLink,
+ Config.GnuDebugLinkCRC32);
+
+ // If the symbol table was previously removed, we need to create a new one
+ // before adding new symbols.
if (!Obj.SymbolTable && !Config.ELF->SymbolsToAdd.empty())
if (Error E = Obj.addNewSymbolTable())
return E;
-
- 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(
- SI.SymbolName, SI.Bind, SI.Type, Sec, Value, SI.Visibility,
- Sec ? (uint16_t)SYMBOL_SIMPLE_INDEX : (uint16_t)SHN_ABS, 0);
- }
-
+
+ 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(
+ SI.SymbolName, SI.Bind, SI.Type, Sec, Value, SI.Visibility,
+ Sec ? (uint16_t)SYMBOL_SIMPLE_INDEX : (uint16_t)SHN_ABS, 0);
+ }
+
// --set-section-flags works with sections added by --add-section.
if (!Config.SetSectionFlags.empty()) {
for (auto &Sec : Obj.sections()) {
@@ -771,98 +771,98 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj,
}
}
- if (Config.EntryExpr)
- Obj.Entry = Config.EntryExpr(Obj.Entry);
- return Error::success();
-}
-
-static Error writeOutput(const CopyConfig &Config, Object &Obj, Buffer &Out,
- ElfType OutputElfType) {
- std::unique_ptr<Writer> Writer =
- createWriter(Config, Obj, Out, OutputElfType);
- if (Error E = Writer->finalize())
- return E;
- return Writer->write();
-}
-
-Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In,
- Buffer &Out) {
- IHexReader Reader(&In);
+ if (Config.EntryExpr)
+ Obj.Entry = Config.EntryExpr(Obj.Entry);
+ return Error::success();
+}
+
+static Error writeOutput(const CopyConfig &Config, Object &Obj, Buffer &Out,
+ ElfType OutputElfType) {
+ std::unique_ptr<Writer> Writer =
+ createWriter(Config, Obj, Out, OutputElfType);
+ if (Error E = Writer->finalize())
+ return E;
+ return Writer->write();
+}
+
+Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In,
+ Buffer &Out) {
+ IHexReader Reader(&In);
Expected<std::unique_ptr<Object>> Obj = Reader.create(true);
if (!Obj)
return Obj.takeError();
- const ElfType OutputElfType =
+ const ElfType OutputElfType =
getOutputElfType(Config.OutputArch.getValueOr(MachineInfo()));
if (Error E = handleArgs(Config, **Obj, Reader, OutputElfType))
- return E;
+ return E;
return writeOutput(Config, **Obj, Out, OutputElfType);
-}
-
-Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
- Buffer &Out) {
- uint8_t NewSymbolVisibility =
- Config.ELF->NewSymbolVisibility.getValueOr((uint8_t)ELF::STV_DEFAULT);
- BinaryReader Reader(&In, NewSymbolVisibility);
+}
+
+Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
+ Buffer &Out) {
+ uint8_t NewSymbolVisibility =
+ Config.ELF->NewSymbolVisibility.getValueOr((uint8_t)ELF::STV_DEFAULT);
+ BinaryReader Reader(&In, NewSymbolVisibility);
Expected<std::unique_ptr<Object>> Obj = Reader.create(true);
if (!Obj)
return Obj.takeError();
-
- // Prefer OutputArch (-O<format>) if set, otherwise fallback to BinaryArch
- // (-B<arch>).
- const ElfType OutputElfType =
- getOutputElfType(Config.OutputArch.getValueOr(MachineInfo()));
+
+ // Prefer OutputArch (-O<format>) if set, otherwise fallback to BinaryArch
+ // (-B<arch>).
+ const ElfType OutputElfType =
+ getOutputElfType(Config.OutputArch.getValueOr(MachineInfo()));
if (Error E = handleArgs(Config, **Obj, Reader, OutputElfType))
- return E;
+ return E;
return writeOutput(Config, **Obj, Out, OutputElfType);
-}
-
-Error executeObjcopyOnBinary(const CopyConfig &Config,
- object::ELFObjectFileBase &In, Buffer &Out) {
- ELFReader Reader(&In, Config.ExtractPartition);
+}
+
+Error executeObjcopyOnBinary(const CopyConfig &Config,
+ object::ELFObjectFileBase &In, Buffer &Out) {
+ ELFReader Reader(&In, Config.ExtractPartition);
Expected<std::unique_ptr<Object>> Obj =
Reader.create(!Config.SymbolsToAdd.empty());
if (!Obj)
return Obj.takeError();
- // Prefer OutputArch (-O<format>) if set, otherwise infer it from the input.
- const ElfType OutputElfType =
- Config.OutputArch ? getOutputElfType(Config.OutputArch.getValue())
- : getOutputElfType(In);
- ArrayRef<uint8_t> BuildIdBytes;
-
- if (!Config.BuildIdLinkDir.empty()) {
- auto BuildIdBytesOrErr = findBuildID(Config, In);
- if (auto E = BuildIdBytesOrErr.takeError())
- return E;
- BuildIdBytes = *BuildIdBytesOrErr;
-
- if (BuildIdBytes.size() < 2)
- return createFileError(
- Config.InputFilename,
- createStringError(object_error::parse_failed,
- "build ID is smaller than two bytes"));
- }
-
- if (!Config.BuildIdLinkDir.empty() && Config.BuildIdLinkInput)
- if (Error E =
- linkToBuildIdDir(Config, Config.InputFilename,
- Config.BuildIdLinkInput.getValue(), BuildIdBytes))
- return E;
-
+ // Prefer OutputArch (-O<format>) if set, otherwise infer it from the input.
+ const ElfType OutputElfType =
+ Config.OutputArch ? getOutputElfType(Config.OutputArch.getValue())
+ : getOutputElfType(In);
+ ArrayRef<uint8_t> BuildIdBytes;
+
+ if (!Config.BuildIdLinkDir.empty()) {
+ auto BuildIdBytesOrErr = findBuildID(Config, In);
+ if (auto E = BuildIdBytesOrErr.takeError())
+ return E;
+ BuildIdBytes = *BuildIdBytesOrErr;
+
+ if (BuildIdBytes.size() < 2)
+ return createFileError(
+ Config.InputFilename,
+ createStringError(object_error::parse_failed,
+ "build ID is smaller than two bytes"));
+ }
+
+ if (!Config.BuildIdLinkDir.empty() && Config.BuildIdLinkInput)
+ if (Error E =
+ linkToBuildIdDir(Config, Config.InputFilename,
+ Config.BuildIdLinkInput.getValue(), BuildIdBytes))
+ return E;
+
if (Error E = handleArgs(Config, **Obj, Reader, OutputElfType))
- return createFileError(Config.InputFilename, std::move(E));
-
+ return createFileError(Config.InputFilename, std::move(E));
+
if (Error E = writeOutput(Config, **Obj, Out, OutputElfType))
- return createFileError(Config.InputFilename, std::move(E));
- if (!Config.BuildIdLinkDir.empty() && Config.BuildIdLinkOutput)
- if (Error E =
- linkToBuildIdDir(Config, Config.OutputFilename,
- Config.BuildIdLinkOutput.getValue(), BuildIdBytes))
- return createFileError(Config.OutputFilename, std::move(E));
-
- return Error::success();
-}
-
-} // end namespace elf
-} // end namespace objcopy
-} // end namespace llvm
+ return createFileError(Config.InputFilename, std::move(E));
+ if (!Config.BuildIdLinkDir.empty() && Config.BuildIdLinkOutput)
+ if (Error E =
+ linkToBuildIdDir(Config, Config.OutputFilename,
+ Config.BuildIdLinkOutput.getValue(), BuildIdBytes))
+ return createFileError(Config.OutputFilename, std::move(E));
+
+ return Error::success();
+}
+
+} // end namespace elf
+} // end namespace objcopy
+} // end namespace llvm
diff --git a/contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFObjcopy.h b/contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFObjcopy.h
index e13e237e29..619a0bd908 100644
--- a/contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFObjcopy.h
+++ b/contrib/libs/llvm12/tools/llvm-objcopy/ELF/ELFObjcopy.h
@@ -1,36 +1,36 @@
-//===- ELFObjcopy.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_ELFOBJCOPY_H
-#define LLVM_TOOLS_OBJCOPY_ELFOBJCOPY_H
-
-namespace llvm {
-class Error;
-class MemoryBuffer;
-
-namespace object {
-class ELFObjectFileBase;
-} // end namespace object
-
-namespace objcopy {
-struct CopyConfig;
-class Buffer;
-
-namespace elf {
-Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In,
- Buffer &Out);
-Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
- Buffer &Out);
-Error executeObjcopyOnBinary(const CopyConfig &Config,
- object::ELFObjectFileBase &In, Buffer &Out);
-
-} // end namespace elf
-} // end namespace objcopy
-} // end namespace llvm
-
-#endif // LLVM_TOOLS_OBJCOPY_ELFOBJCOPY_H
+//===- ELFObjcopy.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_ELFOBJCOPY_H
+#define LLVM_TOOLS_OBJCOPY_ELFOBJCOPY_H
+
+namespace llvm {
+class Error;
+class MemoryBuffer;
+
+namespace object {
+class ELFObjectFileBase;
+} // end namespace object
+
+namespace objcopy {
+struct CopyConfig;
+class Buffer;
+
+namespace elf {
+Error executeObjcopyOnIHex(const CopyConfig &Config, MemoryBuffer &In,
+ Buffer &Out);
+Error executeObjcopyOnRawBinary(const CopyConfig &Config, MemoryBuffer &In,
+ Buffer &Out);
+Error executeObjcopyOnBinary(const CopyConfig &Config,
+ object::ELFObjectFileBase &In, Buffer &Out);
+
+} // end namespace elf
+} // end namespace objcopy
+} // end namespace llvm
+
+#endif // LLVM_TOOLS_OBJCOPY_ELFOBJCOPY_H
diff --git a/contrib/libs/llvm12/tools/llvm-objcopy/ELF/Object.cpp b/contrib/libs/llvm12/tools/llvm-objcopy/ELF/Object.cpp
index 0ff82f951b..d3094d351b 100644
--- a/contrib/libs/llvm12/tools/llvm-objcopy/ELF/Object.cpp
+++ b/contrib/libs/llvm12/tools/llvm-objcopy/ELF/Object.cpp
@@ -1,551 +1,551 @@
-//===- Object.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 "Object.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/MC/MCTargetOptions.h"
+//===- Object.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 "Object.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Object/ELF.h"
-#include "llvm/Object/ELFObjectFile.h"
-#include "llvm/Support/Compression.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/Path.h"
-#include <algorithm>
-#include <cstddef>
-#include <cstdint>
-#include <iterator>
-#include <unordered_set>
-#include <utility>
-#include <vector>
-
-namespace llvm {
-namespace objcopy {
-namespace elf {
-
-using namespace object;
-using namespace ELF;
-
-template <class ELFT> void ELFWriter<ELFT>::writePhdr(const Segment &Seg) {
- uint8_t *B = Buf.getBufferStart() + Obj.ProgramHdrSegment.Offset +
- Seg.Index * sizeof(Elf_Phdr);
- Elf_Phdr &Phdr = *reinterpret_cast<Elf_Phdr *>(B);
- Phdr.p_type = Seg.Type;
- Phdr.p_flags = Seg.Flags;
- Phdr.p_offset = Seg.Offset;
- Phdr.p_vaddr = Seg.VAddr;
- Phdr.p_paddr = Seg.PAddr;
- Phdr.p_filesz = Seg.FileSize;
- Phdr.p_memsz = Seg.MemSize;
- Phdr.p_align = Seg.Align;
-}
-
-Error SectionBase::removeSectionReferences(
+#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Support/Compression.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/Path.h"
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <iterator>
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+namespace objcopy {
+namespace elf {
+
+using namespace object;
+using namespace ELF;
+
+template <class ELFT> void ELFWriter<ELFT>::writePhdr(const Segment &Seg) {
+ uint8_t *B = Buf.getBufferStart() + Obj.ProgramHdrSegment.Offset +
+ Seg.Index * sizeof(Elf_Phdr);
+ Elf_Phdr &Phdr = *reinterpret_cast<Elf_Phdr *>(B);
+ Phdr.p_type = Seg.Type;
+ Phdr.p_flags = Seg.Flags;
+ Phdr.p_offset = Seg.Offset;
+ Phdr.p_vaddr = Seg.VAddr;
+ Phdr.p_paddr = Seg.PAddr;
+ Phdr.p_filesz = Seg.FileSize;
+ Phdr.p_memsz = Seg.MemSize;
+ Phdr.p_align = Seg.Align;
+}
+
+Error SectionBase::removeSectionReferences(
bool, function_ref<bool(const SectionBase *)>) {
- return Error::success();
-}
-
+ return Error::success();
+}
+
Error SectionBase::removeSymbols(function_ref<bool(const Symbol &)>) {
- return Error::success();
-}
-
+ return Error::success();
+}
+
Error SectionBase::initialize(SectionTableRef) { return Error::success(); }
-void SectionBase::finalize() {}
-void SectionBase::markSymbols() {}
-void SectionBase::replaceSectionReferences(
- const DenseMap<SectionBase *, SectionBase *> &) {}
-void SectionBase::onRemove() {}
-
-template <class ELFT> void ELFWriter<ELFT>::writeShdr(const SectionBase &Sec) {
- uint8_t *B = Buf.getBufferStart() + Sec.HeaderOffset;
- Elf_Shdr &Shdr = *reinterpret_cast<Elf_Shdr *>(B);
- Shdr.sh_name = Sec.NameIndex;
- Shdr.sh_type = Sec.Type;
- Shdr.sh_flags = Sec.Flags;
- Shdr.sh_addr = Sec.Addr;
- Shdr.sh_offset = Sec.Offset;
- Shdr.sh_size = Sec.Size;
- Shdr.sh_link = Sec.Link;
- Shdr.sh_info = Sec.Info;
- Shdr.sh_addralign = Sec.Align;
- Shdr.sh_entsize = Sec.EntrySize;
-}
-
+void SectionBase::finalize() {}
+void SectionBase::markSymbols() {}
+void SectionBase::replaceSectionReferences(
+ const DenseMap<SectionBase *, SectionBase *> &) {}
+void SectionBase::onRemove() {}
+
+template <class ELFT> void ELFWriter<ELFT>::writeShdr(const SectionBase &Sec) {
+ uint8_t *B = Buf.getBufferStart() + Sec.HeaderOffset;
+ Elf_Shdr &Shdr = *reinterpret_cast<Elf_Shdr *>(B);
+ Shdr.sh_name = Sec.NameIndex;
+ Shdr.sh_type = Sec.Type;
+ Shdr.sh_flags = Sec.Flags;
+ Shdr.sh_addr = Sec.Addr;
+ Shdr.sh_offset = Sec.Offset;
+ Shdr.sh_size = Sec.Size;
+ Shdr.sh_link = Sec.Link;
+ Shdr.sh_info = Sec.Info;
+ Shdr.sh_addralign = Sec.Align;
+ Shdr.sh_entsize = Sec.EntrySize;
+}
+
template <class ELFT> Error ELFSectionSizer<ELFT>::visit(Section &) {
return Error::success();
}
-
+
template <class ELFT> Error ELFSectionSizer<ELFT>::visit(OwnedDataSection &) {
return Error::success();
}
-
+
template <class ELFT> Error ELFSectionSizer<ELFT>::visit(StringTableSection &) {
return Error::success();
}
-
-template <class ELFT>
+
+template <class ELFT>
Error ELFSectionSizer<ELFT>::visit(DynamicRelocationSection &) {
return Error::success();
}
-
-template <class ELFT>
+
+template <class ELFT>
Error ELFSectionSizer<ELFT>::visit(SymbolTableSection &Sec) {
- Sec.EntrySize = sizeof(Elf_Sym);
- Sec.Size = Sec.Symbols.size() * Sec.EntrySize;
- // Align to the largest field in Elf_Sym.
- Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word);
+ Sec.EntrySize = sizeof(Elf_Sym);
+ Sec.Size = Sec.Symbols.size() * Sec.EntrySize;
+ // Align to the largest field in Elf_Sym.
+ Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word);
return Error::success();
-}
-
-template <class ELFT>
+}
+
+template <class ELFT>
Error ELFSectionSizer<ELFT>::visit(RelocationSection &Sec) {
- Sec.EntrySize = Sec.Type == SHT_REL ? sizeof(Elf_Rel) : sizeof(Elf_Rela);
- Sec.Size = Sec.Relocations.size() * Sec.EntrySize;
- // Align to the largest field in Elf_Rel(a).
- Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word);
+ Sec.EntrySize = Sec.Type == SHT_REL ? sizeof(Elf_Rel) : sizeof(Elf_Rela);
+ Sec.Size = Sec.Relocations.size() * Sec.EntrySize;
+ // Align to the largest field in Elf_Rel(a).
+ Sec.Align = ELFT::Is64Bits ? sizeof(Elf_Xword) : sizeof(Elf_Word);
return Error::success();
-}
-
-template <class ELFT>
+}
+
+template <class ELFT>
Error ELFSectionSizer<ELFT>::visit(GnuDebugLinkSection &) {
return Error::success();
}
-
+
template <class ELFT> Error ELFSectionSizer<ELFT>::visit(GroupSection &Sec) {
- Sec.Size = sizeof(Elf_Word) + Sec.GroupMembers.size() * sizeof(Elf_Word);
+ Sec.Size = sizeof(Elf_Word) + Sec.GroupMembers.size() * sizeof(Elf_Word);
return Error::success();
-}
-
-template <class ELFT>
+}
+
+template <class ELFT>
Error ELFSectionSizer<ELFT>::visit(SectionIndexSection &) {
return Error::success();
}
-
+
template <class ELFT> Error ELFSectionSizer<ELFT>::visit(CompressedSection &) {
return Error::success();
}
-
-template <class ELFT>
+
+template <class ELFT>
Error ELFSectionSizer<ELFT>::visit(DecompressedSection &) {
return Error::success();
}
-
+
Error BinarySectionWriter::visit(const SectionIndexSection &Sec) {
return createStringError(errc::operation_not_permitted,
"cannot write symbol section index table '" +
Sec.Name + "' ");
-}
-
+}
+
Error BinarySectionWriter::visit(const SymbolTableSection &Sec) {
return createStringError(errc::operation_not_permitted,
"cannot write symbol table '" + Sec.Name +
"' out to binary");
-}
-
+}
+
Error BinarySectionWriter::visit(const RelocationSection &Sec) {
return createStringError(errc::operation_not_permitted,
"cannot write relocation section '" + Sec.Name +
"' out to binary");
-}
-
+}
+
Error BinarySectionWriter::visit(const GnuDebugLinkSection &Sec) {
return createStringError(errc::operation_not_permitted,
"cannot write '" + Sec.Name + "' out to binary");
-}
-
+}
+
Error BinarySectionWriter::visit(const GroupSection &Sec) {
return createStringError(errc::operation_not_permitted,
"cannot write '" + Sec.Name + "' out to binary");
-}
-
+}
+
Error SectionWriter::visit(const Section &Sec) {
- if (Sec.Type != SHT_NOBITS)
- llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset);
+ if (Sec.Type != SHT_NOBITS)
+ llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset);
return Error::success();
-}
-
-static bool addressOverflows32bit(uint64_t Addr) {
- // Sign extended 32 bit addresses (e.g 0xFFFFFFFF80000000) are ok
- return Addr > UINT32_MAX && Addr + 0x80000000 > UINT32_MAX;
-}
-
-template <class T> static T checkedGetHex(StringRef S) {
- T Value;
- bool Fail = S.getAsInteger(16, Value);
- assert(!Fail);
- (void)Fail;
- return Value;
-}
-
-// Fills exactly Len bytes of buffer with hexadecimal characters
-// representing value 'X'
-template <class T, class Iterator>
-static Iterator utohexstr(T X, Iterator It, size_t Len) {
- // Fill range with '0'
- std::fill(It, It + Len, '0');
-
- for (long I = Len - 1; I >= 0; --I) {
- unsigned char Mod = static_cast<unsigned char>(X) & 15;
- *(It + I) = hexdigit(Mod, false);
- X >>= 4;
- }
- assert(X == 0);
- return It + Len;
-}
-
-uint8_t IHexRecord::getChecksum(StringRef S) {
- assert((S.size() & 1) == 0);
- uint8_t Checksum = 0;
- while (!S.empty()) {
- Checksum += checkedGetHex<uint8_t>(S.take_front(2));
- S = S.drop_front(2);
- }
- return -Checksum;
-}
-
-IHexLineData IHexRecord::getLine(uint8_t Type, uint16_t Addr,
- ArrayRef<uint8_t> Data) {
- IHexLineData Line(getLineLength(Data.size()));
- assert(Line.size());
- auto Iter = Line.begin();
- *Iter++ = ':';
- Iter = utohexstr(Data.size(), Iter, 2);
- Iter = utohexstr(Addr, Iter, 4);
- Iter = utohexstr(Type, Iter, 2);
- for (uint8_t X : Data)
- Iter = utohexstr(X, Iter, 2);
- StringRef S(Line.data() + 1, std::distance(Line.begin() + 1, Iter));
- Iter = utohexstr(getChecksum(S), Iter, 2);
- *Iter++ = '\r';
- *Iter++ = '\n';
- assert(Iter == Line.end());
- return Line;
-}
-
-static Error checkRecord(const IHexRecord &R) {
- switch (R.Type) {
- case IHexRecord::Data:
- if (R.HexData.size() == 0)
- return createStringError(
- errc::invalid_argument,
- "zero data length is not allowed for data records");
- break;
- case IHexRecord::EndOfFile:
- break;
- case IHexRecord::SegmentAddr:
- // 20-bit segment address. Data length must be 2 bytes
- // (4 bytes in hex)
- if (R.HexData.size() != 4)
- return createStringError(
- errc::invalid_argument,
- "segment address data should be 2 bytes in size");
- break;
- case IHexRecord::StartAddr80x86:
- case IHexRecord::StartAddr:
- if (R.HexData.size() != 8)
- return createStringError(errc::invalid_argument,
- "start address data should be 4 bytes in size");
- // According to Intel HEX specification '03' record
- // only specifies the code address within the 20-bit
- // segmented address space of the 8086/80186. This
- // means 12 high order bits should be zeroes.
- if (R.Type == IHexRecord::StartAddr80x86 &&
- R.HexData.take_front(3) != "000")
- return createStringError(errc::invalid_argument,
- "start address exceeds 20 bit for 80x86");
- break;
- case IHexRecord::ExtendedAddr:
- // 16-31 bits of linear base address
- if (R.HexData.size() != 4)
- return createStringError(
- errc::invalid_argument,
- "extended address data should be 2 bytes in size");
- break;
- default:
- // Unknown record type
- return createStringError(errc::invalid_argument, "unknown record type: %u",
- static_cast<unsigned>(R.Type));
- }
- return Error::success();
-}
-
-// Checks that IHEX line contains valid characters.
-// This allows converting hexadecimal data to integers
-// without extra verification.
-static Error checkChars(StringRef Line) {
- assert(!Line.empty());
- if (Line[0] != ':')
- return createStringError(errc::invalid_argument,
- "missing ':' in the beginning of line.");
-
- for (size_t Pos = 1; Pos < Line.size(); ++Pos)
- if (hexDigitValue(Line[Pos]) == -1U)
- return createStringError(errc::invalid_argument,
- "invalid character at position %zu.", Pos + 1);
- return Error::success();
-}
-
-Expected<IHexRecord> IHexRecord::parse(StringRef Line) {
- assert(!Line.empty());
-
- // ':' + Length + Address + Type + Checksum with empty data ':LLAAAATTCC'
- if (Line.size() < 11)
- return createStringError(errc::invalid_argument,
- "line is too short: %zu chars.", Line.size());
-
- if (Error E = checkChars(Line))
- return std::move(E);
-
- IHexRecord Rec;
- size_t DataLen = checkedGetHex<uint8_t>(Line.substr(1, 2));
- if (Line.size() != getLength(DataLen))
- return createStringError(errc::invalid_argument,
- "invalid line length %zu (should be %zu)",
- Line.size(), getLength(DataLen));
-
- Rec.Addr = checkedGetHex<uint16_t>(Line.substr(3, 4));
- Rec.Type = checkedGetHex<uint8_t>(Line.substr(7, 2));
- Rec.HexData = Line.substr(9, DataLen * 2);
-
- if (getChecksum(Line.drop_front(1)) != 0)
- return createStringError(errc::invalid_argument, "incorrect checksum.");
- if (Error E = checkRecord(Rec))
- return std::move(E);
- return Rec;
-}
-
-static uint64_t sectionPhysicalAddr(const SectionBase *Sec) {
- Segment *Seg = Sec->ParentSegment;
- if (Seg && Seg->Type != ELF::PT_LOAD)
- Seg = nullptr;
- return Seg ? Seg->PAddr + Sec->OriginalOffset - Seg->OriginalOffset
- : Sec->Addr;
-}
-
-void IHexSectionWriterBase::writeSection(const SectionBase *Sec,
- ArrayRef<uint8_t> Data) {
- assert(Data.size() == Sec->Size);
- const uint32_t ChunkSize = 16;
- uint32_t Addr = sectionPhysicalAddr(Sec) & 0xFFFFFFFFU;
- while (!Data.empty()) {
- uint64_t DataSize = std::min<uint64_t>(Data.size(), ChunkSize);
- if (Addr > SegmentAddr + BaseAddr + 0xFFFFU) {
- if (Addr > 0xFFFFFU) {
- // Write extended address record, zeroing segment address
- // if needed.
- if (SegmentAddr != 0)
- SegmentAddr = writeSegmentAddr(0U);
- BaseAddr = writeBaseAddr(Addr);
- } else {
- // We can still remain 16-bit
- SegmentAddr = writeSegmentAddr(Addr);
- }
- }
- uint64_t SegOffset = Addr - BaseAddr - SegmentAddr;
- assert(SegOffset <= 0xFFFFU);
- DataSize = std::min(DataSize, 0x10000U - SegOffset);
- writeData(0, SegOffset, Data.take_front(DataSize));
- Addr += DataSize;
- Data = Data.drop_front(DataSize);
- }
-}
-
-uint64_t IHexSectionWriterBase::writeSegmentAddr(uint64_t Addr) {
- assert(Addr <= 0xFFFFFU);
- uint8_t Data[] = {static_cast<uint8_t>((Addr & 0xF0000U) >> 12), 0};
- writeData(2, 0, Data);
- return Addr & 0xF0000U;
-}
-
-uint64_t IHexSectionWriterBase::writeBaseAddr(uint64_t Addr) {
- assert(Addr <= 0xFFFFFFFFU);
- uint64_t Base = Addr & 0xFFFF0000U;
- uint8_t Data[] = {static_cast<uint8_t>(Base >> 24),
- static_cast<uint8_t>((Base >> 16) & 0xFF)};
- writeData(4, 0, Data);
- return Base;
-}
-
+}
+
+static bool addressOverflows32bit(uint64_t Addr) {
+ // Sign extended 32 bit addresses (e.g 0xFFFFFFFF80000000) are ok
+ return Addr > UINT32_MAX && Addr + 0x80000000 > UINT32_MAX;
+}
+
+template <class T> static T checkedGetHex(StringRef S) {
+ T Value;
+ bool Fail = S.getAsInteger(16, Value);
+ assert(!Fail);
+ (void)Fail;
+ return Value;
+}
+
+// Fills exactly Len bytes of buffer with hexadecimal characters
+// representing value 'X'
+template <class T, class Iterator>
+static Iterator utohexstr(T X, Iterator It, size_t Len) {
+ // Fill range with '0'
+ std::fill(It, It + Len, '0');
+
+ for (long I = Len - 1; I >= 0; --I) {
+ unsigned char Mod = static_cast<unsigned char>(X) & 15;
+ *(It + I) = hexdigit(Mod, false);
+ X >>= 4;
+ }
+ assert(X == 0);
+ return It + Len;
+}
+
+uint8_t IHexRecord::getChecksum(StringRef S) {
+ assert((S.size() & 1) == 0);
+ uint8_t Checksum = 0;
+ while (!S.empty()) {
+ Checksum += checkedGetHex<uint8_t>(S.take_front(2));
+ S = S.drop_front(2);
+ }
+ return -Checksum;
+}
+
+IHexLineData IHexRecord::getLine(uint8_t Type, uint16_t Addr,
+ ArrayRef<uint8_t> Data) {
+ IHexLineData Line(getLineLength(Data.size()));
+ assert(Line.size());
+ auto Iter = Line.begin();
+ *Iter++ = ':';
+ Iter = utohexstr(Data.size(), Iter, 2);
+ Iter = utohexstr(Addr, Iter, 4);
+ Iter = utohexstr(Type, Iter, 2);
+ for (uint8_t X : Data)
+ Iter = utohexstr(X, Iter, 2);
+ StringRef S(Line.data() + 1, std::distance(Line.begin() + 1, Iter));
+ Iter = utohexstr(getChecksum(S), Iter, 2);
+ *Iter++ = '\r';
+ *Iter++ = '\n';
+ assert(Iter == Line.end());
+ return Line;
+}
+
+static Error checkRecord(const IHexRecord &R) {
+ switch (R.Type) {
+ case IHexRecord::Data:
+ if (R.HexData.size() == 0)
+ return createStringError(
+ errc::invalid_argument,
+ "zero data length is not allowed for data records");
+ break;
+ case IHexRecord::EndOfFile:
+ break;
+ case IHexRecord::SegmentAddr:
+ // 20-bit segment address. Data length must be 2 bytes
+ // (4 bytes in hex)
+ if (R.HexData.size() != 4)
+ return createStringError(
+ errc::invalid_argument,
+ "segment address data should be 2 bytes in size");
+ break;
+ case IHexRecord::StartAddr80x86:
+ case IHexRecord::StartAddr:
+ if (R.HexData.size() != 8)
+ return createStringError(errc::invalid_argument,
+ "start address data should be 4 bytes in size");
+ // According to Intel HEX specification '03' record
+ // only specifies the code address within the 20-bit
+ // segmented address space of the 8086/80186. This
+ // means 12 high order bits should be zeroes.
+ if (R.Type == IHexRecord::StartAddr80x86 &&
+ R.HexData.take_front(3) != "000")
+ return createStringError(errc::invalid_argument,
+ "start address exceeds 20 bit for 80x86");
+ break;
+ case IHexRecord::ExtendedAddr:
+ // 16-31 bits of linear base address
+ if (R.HexData.size() != 4)
+ return createStringError(
+ errc::invalid_argument,
+ "extended address data should be 2 bytes in size");
+ break;
+ default:
+ // Unknown record type
+ return createStringError(errc::invalid_argument, "unknown record type: %u",
+ static_cast<unsigned>(R.Type));
+ }
+ return Error::success();
+}
+
+// Checks that IHEX line contains valid characters.
+// This allows converting hexadecimal data to integers
+// without extra verification.
+static Error checkChars(StringRef Line) {
+ assert(!Line.empty());
+ if (Line[0] != ':')
+ return createStringError(errc::invalid_argument,
+ "missing ':' in the beginning of line.");
+
+ for (size_t Pos = 1; Pos < Line.size(); ++Pos)
+ if (hexDigitValue(Line[Pos]) == -1U)
+ return createStringError(errc::invalid_argument,
+ "invalid character at position %zu.", Pos + 1);
+ return Error::success();
+}
+
+Expected<IHexRecord> IHexRecord::parse(StringRef Line) {
+ assert(!Line.empty());
+
+ // ':' + Length + Address + Type + Checksum with empty data ':LLAAAATTCC'
+ if (Line.size() < 11)
+ return createStringError(errc::invalid_argument,
+ "line is too short: %zu chars.", Line.size());
+
+ if (Error E = checkChars(Line))
+ return std::move(E);
+
+ IHexRecord Rec;
+ size_t DataLen = checkedGetHex<uint8_t>(Line.substr(1, 2));
+ if (Line.size() != getLength(DataLen))
+ return createStringError(errc::invalid_argument,
+ "invalid line length %zu (should be %zu)",
+ Line.size(), getLength(DataLen));
+
+ Rec.Addr = checkedGetHex<uint16_t>(Line.substr(3, 4));
+ Rec.Type = checkedGetHex<uint8_t>(Line.substr(7, 2));
+ Rec.HexData = Line.substr(9, DataLen * 2);
+
+ if (getChecksum(Line.drop_front(1)) != 0)
+ return createStringError(errc::invalid_argument, "incorrect checksum.");
+ if (Error E = checkRecord(Rec))
+ return std::move(E);
+ return Rec;
+}
+
+static uint64_t sectionPhysicalAddr(const SectionBase *Sec) {
+ Segment *Seg = Sec->ParentSegment;
+ if (Seg && Seg->Type != ELF::PT_LOAD)
+ Seg = nullptr;
+ return Seg ? Seg->PAddr + Sec->OriginalOffset - Seg->OriginalOffset
+ : Sec->Addr;
+}
+
+void IHexSectionWriterBase::writeSection(const SectionBase *Sec,
+ ArrayRef<uint8_t> Data) {
+ assert(Data.size() == Sec->Size);
+ const uint32_t ChunkSize = 16;
+ uint32_t Addr = sectionPhysicalAddr(Sec) & 0xFFFFFFFFU;
+ while (!Data.empty()) {
+ uint64_t DataSize = std::min<uint64_t>(Data.size(), ChunkSize);
+ if (Addr > SegmentAddr + BaseAddr + 0xFFFFU) {
+ if (Addr > 0xFFFFFU) {
+ // Write extended address record, zeroing segment address
+ // if needed.
+ if (SegmentAddr != 0)
+ SegmentAddr = writeSegmentAddr(0U);
+ BaseAddr = writeBaseAddr(Addr);
+ } else {
+ // We can still remain 16-bit
+ SegmentAddr = writeSegmentAddr(Addr);
+ }
+ }
+ uint64_t SegOffset = Addr - BaseAddr - SegmentAddr;
+ assert(SegOffset <= 0xFFFFU);
+ DataSize = std::min(DataSize, 0x10000U - SegOffset);
+ writeData(0, SegOffset, Data.take_front(DataSize));
+ Addr += DataSize;
+ Data = Data.drop_front(DataSize);
+ }
+}
+
+uint64_t IHexSectionWriterBase::writeSegmentAddr(uint64_t Addr) {
+ assert(Addr <= 0xFFFFFU);
+ uint8_t Data[] = {static_cast<uint8_t>((Addr & 0xF0000U) >> 12), 0};
+ writeData(2, 0, Data);
+ return Addr & 0xF0000U;
+}
+
+uint64_t IHexSectionWriterBase::writeBaseAddr(uint64_t Addr) {
+ assert(Addr <= 0xFFFFFFFFU);
+ uint64_t Base = Addr & 0xFFFF0000U;
+ uint8_t Data[] = {static_cast<uint8_t>(Base >> 24),
+ static_cast<uint8_t>((Base >> 16) & 0xFF)};
+ writeData(4, 0, Data);
+ return Base;
+}
+
void IHexSectionWriterBase::writeData(uint8_t, uint16_t,
- ArrayRef<uint8_t> Data) {
- Offset += IHexRecord::getLineLength(Data.size());
-}
-
+ ArrayRef<uint8_t> Data) {
+ Offset += IHexRecord::getLineLength(Data.size());
+}
+
Error IHexSectionWriterBase::visit(const Section &Sec) {
- writeSection(&Sec, Sec.Contents);
+ writeSection(&Sec, Sec.Contents);
return Error::success();
-}
-
+}
+
Error IHexSectionWriterBase::visit(const OwnedDataSection &Sec) {
- writeSection(&Sec, Sec.Data);
+ writeSection(&Sec, Sec.Data);
return Error::success();
-}
-
+}
+
Error IHexSectionWriterBase::visit(const StringTableSection &Sec) {
- // Check that sizer has already done its work
- assert(Sec.Size == Sec.StrTabBuilder.getSize());
- // We are free to pass an invalid pointer to writeSection as long
- // as we don't actually write any data. The real writer class has
- // to override this method .
- writeSection(&Sec, {nullptr, static_cast<size_t>(Sec.Size)});
+ // Check that sizer has already done its work
+ assert(Sec.Size == Sec.StrTabBuilder.getSize());
+ // We are free to pass an invalid pointer to writeSection as long
+ // as we don't actually write any data. The real writer class has
+ // to override this method .
+ writeSection(&Sec, {nullptr, static_cast<size_t>(Sec.Size)});
return Error::success();
-}
-
+}
+
Error IHexSectionWriterBase::visit(const DynamicRelocationSection &Sec) {
- writeSection(&Sec, Sec.Contents);
+ writeSection(&Sec, Sec.Contents);
return Error::success();
-}
-
-void IHexSectionWriter::writeData(uint8_t Type, uint16_t Addr,
- ArrayRef<uint8_t> Data) {
- IHexLineData HexData = IHexRecord::getLine(Type, Addr, Data);
- memcpy(Out.getBufferStart() + Offset, HexData.data(), HexData.size());
- Offset += HexData.size();
-}
-
+}
+
+void IHexSectionWriter::writeData(uint8_t Type, uint16_t Addr,
+ ArrayRef<uint8_t> Data) {
+ IHexLineData HexData = IHexRecord::getLine(Type, Addr, Data);
+ memcpy(Out.getBufferStart() + Offset, HexData.data(), HexData.size());
+ Offset += HexData.size();
+}
+
Error IHexSectionWriter::visit(const StringTableSection &Sec) {
- assert(Sec.Size == Sec.StrTabBuilder.getSize());
- std::vector<uint8_t> Data(Sec.Size);
- Sec.StrTabBuilder.write(Data.data());
- writeSection(&Sec, Data);
+ assert(Sec.Size == Sec.StrTabBuilder.getSize());
+ std::vector<uint8_t> Data(Sec.Size);
+ Sec.StrTabBuilder.write(Data.data());
+ writeSection(&Sec, Data);
return Error::success();
-}
-
+}
+
Error Section::accept(SectionVisitor &Visitor) const {
return Visitor.visit(*this);
}
-
+
Error Section::accept(MutableSectionVisitor &Visitor) {
return Visitor.visit(*this);
}
-
+
Error SectionWriter::visit(const OwnedDataSection &Sec) {
- llvm::copy(Sec.Data, Out.getBufferStart() + Sec.Offset);
+ llvm::copy(Sec.Data, Out.getBufferStart() + Sec.Offset);
return Error::success();
-}
-
-static constexpr std::array<uint8_t, 4> ZlibGnuMagic = {{'Z', 'L', 'I', 'B'}};
-
-static bool isDataGnuCompressed(ArrayRef<uint8_t> Data) {
- return Data.size() > ZlibGnuMagic.size() &&
- std::equal(ZlibGnuMagic.begin(), ZlibGnuMagic.end(), Data.data());
-}
-
-template <class ELFT>
-static std::tuple<uint64_t, uint64_t>
-getDecompressedSizeAndAlignment(ArrayRef<uint8_t> Data) {
- const bool IsGnuDebug = isDataGnuCompressed(Data);
- const uint64_t DecompressedSize =
- IsGnuDebug
- ? support::endian::read64be(Data.data() + ZlibGnuMagic.size())
- : reinterpret_cast<const Elf_Chdr_Impl<ELFT> *>(Data.data())->ch_size;
- const uint64_t DecompressedAlign =
- IsGnuDebug ? 1
- : reinterpret_cast<const Elf_Chdr_Impl<ELFT> *>(Data.data())
- ->ch_addralign;
-
- return std::make_tuple(DecompressedSize, DecompressedAlign);
-}
-
-template <class ELFT>
+}
+
+static constexpr std::array<uint8_t, 4> ZlibGnuMagic = {{'Z', 'L', 'I', 'B'}};
+
+static bool isDataGnuCompressed(ArrayRef<uint8_t> Data) {
+ return Data.size() > ZlibGnuMagic.size() &&
+ std::equal(ZlibGnuMagic.begin(), ZlibGnuMagic.end(), Data.data());
+}
+
+template <class ELFT>
+static std::tuple<uint64_t, uint64_t>
+getDecompressedSizeAndAlignment(ArrayRef<uint8_t> Data) {
+ const bool IsGnuDebug = isDataGnuCompressed(Data);
+ const uint64_t DecompressedSize =
+ IsGnuDebug
+ ? support::endian::read64be(Data.data() + ZlibGnuMagic.size())
+ : reinterpret_cast<const Elf_Chdr_Impl<ELFT> *>(Data.data())->ch_size;
+ const uint64_t DecompressedAlign =
+ IsGnuDebug ? 1
+ : reinterpret_cast<const Elf_Chdr_Impl<ELFT> *>(Data.data())
+ ->ch_addralign;
+
+ return std::make_tuple(DecompressedSize, DecompressedAlign);
+}
+
+template <class ELFT>
Error ELFSectionWriter<ELFT>::visit(const DecompressedSection &Sec) {
- const size_t DataOffset = isDataGnuCompressed(Sec.OriginalData)
- ? (ZlibGnuMagic.size() + sizeof(Sec.Size))
- : sizeof(Elf_Chdr_Impl<ELFT>);
-
- StringRef CompressedContent(
- reinterpret_cast<const char *>(Sec.OriginalData.data()) + DataOffset,
- Sec.OriginalData.size() - DataOffset);
-
- SmallVector<char, 128> DecompressedContent;
+ const size_t DataOffset = isDataGnuCompressed(Sec.OriginalData)
+ ? (ZlibGnuMagic.size() + sizeof(Sec.Size))
+ : sizeof(Elf_Chdr_Impl<ELFT>);
+
+ StringRef CompressedContent(
+ reinterpret_cast<const char *>(Sec.OriginalData.data()) + DataOffset,
+ Sec.OriginalData.size() - DataOffset);
+
+ SmallVector<char, 128> DecompressedContent;
if (Error Err = zlib::uncompress(CompressedContent, DecompressedContent,
static_cast<size_t>(Sec.Size)))
return createStringError(errc::invalid_argument,
"'" + Sec.Name + "': " + toString(std::move(Err)));
-
- uint8_t *Buf = Out.getBufferStart() + Sec.Offset;
- std::copy(DecompressedContent.begin(), DecompressedContent.end(), Buf);
+
+ uint8_t *Buf = Out.getBufferStart() + Sec.Offset;
+ std::copy(DecompressedContent.begin(), DecompressedContent.end(), Buf);
return Error::success();
-}
-
+}
+
Error BinarySectionWriter::visit(const DecompressedSection &Sec) {
return createStringError(errc::operation_not_permitted,
"cannot write compressed section '" + Sec.Name +
"' ");
-}
-
+}
+
Error DecompressedSection::accept(SectionVisitor &Visitor) const {
return Visitor.visit(*this);
-}
-
+}
+
Error DecompressedSection::accept(MutableSectionVisitor &Visitor) {
return Visitor.visit(*this);
-}
-
+}
+
Error OwnedDataSection::accept(SectionVisitor &Visitor) const {
return Visitor.visit(*this);
-}
-
+}
+
Error OwnedDataSection::accept(MutableSectionVisitor &Visitor) {
return Visitor.visit(*this);
-}
-
-void OwnedDataSection::appendHexData(StringRef HexData) {
- assert((HexData.size() & 1) == 0);
- while (!HexData.empty()) {
- Data.push_back(checkedGetHex<uint8_t>(HexData.take_front(2)));
- HexData = HexData.drop_front(2);
- }
- Size = Data.size();
-}
-
+}
+
+void OwnedDataSection::appendHexData(StringRef HexData) {
+ assert((HexData.size() & 1) == 0);
+ while (!HexData.empty()) {
+ Data.push_back(checkedGetHex<uint8_t>(HexData.take_front(2)));
+ HexData = HexData.drop_front(2);
+ }
+ Size = Data.size();
+}
+
Error BinarySectionWriter::visit(const CompressedSection &Sec) {
return createStringError(errc::operation_not_permitted,
"cannot write compressed section '" + Sec.Name +
"' ");
-}
-
-template <class ELFT>
+}
+
+template <class ELFT>
Error ELFSectionWriter<ELFT>::visit(const CompressedSection &Sec) {
- uint8_t *Buf = Out.getBufferStart() + Sec.Offset;
- if (Sec.CompressionType == DebugCompressionType::None) {
- std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(), Buf);
+ uint8_t *Buf = Out.getBufferStart() + Sec.Offset;
+ if (Sec.CompressionType == DebugCompressionType::None) {
+ std::copy(Sec.OriginalData.begin(), Sec.OriginalData.end(), Buf);
return Error::success();
- }
-
- if (Sec.CompressionType == DebugCompressionType::GNU) {
- const char *Magic = "ZLIB";
- memcpy(Buf, Magic, strlen(Magic));
- Buf += strlen(Magic);
- const uint64_t DecompressedSize =
- support::endian::read64be(&Sec.DecompressedSize);
- memcpy(Buf, &DecompressedSize, sizeof(DecompressedSize));
- Buf += sizeof(DecompressedSize);
- } else {
- Elf_Chdr_Impl<ELFT> Chdr;
- Chdr.ch_type = ELF::ELFCOMPRESS_ZLIB;
- Chdr.ch_size = Sec.DecompressedSize;
- Chdr.ch_addralign = Sec.DecompressedAlign;
- memcpy(Buf, &Chdr, sizeof(Chdr));
- Buf += sizeof(Chdr);
- }
-
- std::copy(Sec.CompressedData.begin(), Sec.CompressedData.end(), Buf);
+ }
+
+ if (Sec.CompressionType == DebugCompressionType::GNU) {
+ const char *Magic = "ZLIB";
+ memcpy(Buf, Magic, strlen(Magic));
+ Buf += strlen(Magic);
+ const uint64_t DecompressedSize =
+ support::endian::read64be(&Sec.DecompressedSize);
+ memcpy(Buf, &DecompressedSize, sizeof(DecompressedSize));
+ Buf += sizeof(DecompressedSize);
+ } else {
+ Elf_Chdr_Impl<ELFT> Chdr;
+ Chdr.ch_type = ELF::ELFCOMPRESS_ZLIB;
+ Chdr.ch_size = Sec.DecompressedSize;
+ Chdr.ch_addralign = Sec.DecompressedAlign;
+ memcpy(Buf, &Chdr, sizeof(Chdr));
+ Buf += sizeof(Chdr);
+ }
+
+ std::copy(Sec.CompressedData.begin(), Sec.CompressedData.end(), Buf);
return Error::success();
-}
-
+}
+
Expected<CompressedSection>
CompressedSection::create(const SectionBase &Sec,
DebugCompressionType CompressionType) {
@@ -564,87 +564,87 @@ CompressedSection::create(ArrayRef<uint8_t> CompressedData,
return CompressedSection(CompressedData, DecompressedSize, DecompressedAlign);
}
-CompressedSection::CompressedSection(const SectionBase &Sec,
+CompressedSection::CompressedSection(const SectionBase &Sec,
DebugCompressionType CompressionType,
Error &OutErr)
- : SectionBase(Sec), CompressionType(CompressionType),
- DecompressedSize(Sec.OriginalData.size()), DecompressedAlign(Sec.Align) {
+ : SectionBase(Sec), CompressionType(CompressionType),
+ DecompressedSize(Sec.OriginalData.size()), DecompressedAlign(Sec.Align) {
ErrorAsOutParameter EAO(&OutErr);
if (Error Err = zlib::compress(
- StringRef(reinterpret_cast<const char *>(OriginalData.data()),
- OriginalData.size()),
+ StringRef(reinterpret_cast<const char *>(OriginalData.data()),
+ OriginalData.size()),
CompressedData)) {
OutErr = createStringError(llvm::errc::invalid_argument,
"'" + Name + "': " + toString(std::move(Err)));
return;
}
-
- size_t ChdrSize;
- if (CompressionType == DebugCompressionType::GNU) {
- Name = ".z" + Sec.Name.substr(1);
- ChdrSize = sizeof("ZLIB") - 1 + sizeof(uint64_t);
- } else {
- Flags |= ELF::SHF_COMPRESSED;
- ChdrSize =
- std::max(std::max(sizeof(object::Elf_Chdr_Impl<object::ELF64LE>),
- sizeof(object::Elf_Chdr_Impl<object::ELF64BE>)),
- std::max(sizeof(object::Elf_Chdr_Impl<object::ELF32LE>),
- sizeof(object::Elf_Chdr_Impl<object::ELF32BE>)));
- }
- Size = ChdrSize + CompressedData.size();
- Align = 8;
-}
-
-CompressedSection::CompressedSection(ArrayRef<uint8_t> CompressedData,
- uint64_t DecompressedSize,
- uint64_t DecompressedAlign)
- : CompressionType(DebugCompressionType::None),
- DecompressedSize(DecompressedSize), DecompressedAlign(DecompressedAlign) {
- OriginalData = CompressedData;
-}
-
+
+ size_t ChdrSize;
+ if (CompressionType == DebugCompressionType::GNU) {
+ Name = ".z" + Sec.Name.substr(1);
+ ChdrSize = sizeof("ZLIB") - 1 + sizeof(uint64_t);
+ } else {
+ Flags |= ELF::SHF_COMPRESSED;
+ ChdrSize =
+ std::max(std::max(sizeof(object::Elf_Chdr_Impl<object::ELF64LE>),
+ sizeof(object::Elf_Chdr_Impl<object::ELF64BE>)),
+ std::max(sizeof(object::Elf_Chdr_Impl<object::ELF32LE>),
+ sizeof(object::Elf_Chdr_Impl<object::ELF32BE>)));
+ }
+ Size = ChdrSize + CompressedData.size();
+ Align = 8;
+}
+
+CompressedSection::CompressedSection(ArrayRef<uint8_t> CompressedData,
+ uint64_t DecompressedSize,
+ uint64_t DecompressedAlign)
+ : CompressionType(DebugCompressionType::None),
+ DecompressedSize(DecompressedSize), DecompressedAlign(DecompressedAlign) {
+ OriginalData = CompressedData;
+}
+
Error CompressedSection::accept(SectionVisitor &Visitor) const {
return Visitor.visit(*this);
-}
-
+}
+
Error CompressedSection::accept(MutableSectionVisitor &Visitor) {
return Visitor.visit(*this);
-}
-
-void StringTableSection::addString(StringRef Name) { StrTabBuilder.add(Name); }
-
-uint32_t StringTableSection::findIndex(StringRef Name) const {
- return StrTabBuilder.getOffset(Name);
-}
-
-void StringTableSection::prepareForLayout() {
- StrTabBuilder.finalize();
- Size = StrTabBuilder.getSize();
-}
-
+}
+
+void StringTableSection::addString(StringRef Name) { StrTabBuilder.add(Name); }
+
+uint32_t StringTableSection::findIndex(StringRef Name) const {
+ return StrTabBuilder.getOffset(Name);
+}
+
+void StringTableSection::prepareForLayout() {
+ StrTabBuilder.finalize();
+ Size = StrTabBuilder.getSize();
+}
+
Error SectionWriter::visit(const StringTableSection &Sec) {
- Sec.StrTabBuilder.write(Out.getBufferStart() + Sec.Offset);
+ Sec.StrTabBuilder.write(Out.getBufferStart() + Sec.Offset);
return Error::success();
-}
-
+}
+
Error StringTableSection::accept(SectionVisitor &Visitor) const {
return Visitor.visit(*this);
-}
-
+}
+
Error StringTableSection::accept(MutableSectionVisitor &Visitor) {
return Visitor.visit(*this);
-}
-
-template <class ELFT>
+}
+
+template <class ELFT>
Error ELFSectionWriter<ELFT>::visit(const SectionIndexSection &Sec) {
- uint8_t *Buf = Out.getBufferStart() + Sec.Offset;
- llvm::copy(Sec.Indexes, reinterpret_cast<Elf_Word *>(Buf));
+ uint8_t *Buf = Out.getBufferStart() + Sec.Offset;
+ llvm::copy(Sec.Indexes, reinterpret_cast<Elf_Word *>(Buf));
return Error::success();
-}
-
+}
+
Error SectionIndexSection::initialize(SectionTableRef SecTable) {
- Size = 0;
+ Size = 0;
Expected<SymbolTableSection *> Sec =
SecTable.getSectionOfType<SymbolTableSection>(
Link,
@@ -656,145 +656,145 @@ Error SectionIndexSection::initialize(SectionTableRef SecTable) {
return Sec.takeError();
setSymTab(*Sec);
- Symbols->setShndxTable(this);
+ Symbols->setShndxTable(this);
return Error::success();
-}
-
-void SectionIndexSection::finalize() { Link = Symbols->Index; }
-
+}
+
+void SectionIndexSection::finalize() { Link = Symbols->Index; }
+
Error SectionIndexSection::accept(SectionVisitor &Visitor) const {
return Visitor.visit(*this);
-}
-
+}
+
Error SectionIndexSection::accept(MutableSectionVisitor &Visitor) {
return Visitor.visit(*this);
-}
-
-static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine) {
- switch (Index) {
- case SHN_ABS:
- case SHN_COMMON:
- return true;
- }
-
- if (Machine == EM_AMDGPU) {
- return Index == SHN_AMDGPU_LDS;
- }
-
- if (Machine == EM_HEXAGON) {
- switch (Index) {
- case SHN_HEXAGON_SCOMMON:
- case SHN_HEXAGON_SCOMMON_1:
- case SHN_HEXAGON_SCOMMON_2:
- case SHN_HEXAGON_SCOMMON_4:
- case SHN_HEXAGON_SCOMMON_8:
- return true;
- }
- }
- return false;
-}
-
-// Large indexes force us to clarify exactly what this function should do. This
-// function should return the value that will appear in st_shndx when written
-// out.
-uint16_t Symbol::getShndx() const {
- if (DefinedIn != nullptr) {
- if (DefinedIn->Index >= SHN_LORESERVE)
- return SHN_XINDEX;
- return DefinedIn->Index;
- }
-
- if (ShndxType == SYMBOL_SIMPLE_INDEX) {
- // This means that we don't have a defined section but we do need to
- // output a legitimate section index.
- return SHN_UNDEF;
- }
-
- assert(ShndxType == SYMBOL_ABS || ShndxType == SYMBOL_COMMON ||
- (ShndxType >= SYMBOL_LOPROC && ShndxType <= SYMBOL_HIPROC) ||
- (ShndxType >= SYMBOL_LOOS && ShndxType <= SYMBOL_HIOS));
- return static_cast<uint16_t>(ShndxType);
-}
-
-bool Symbol::isCommon() const { return getShndx() == SHN_COMMON; }
-
-void SymbolTableSection::assignIndices() {
- uint32_t Index = 0;
- for (auto &Sym : Symbols)
- Sym->Index = Index++;
-}
-
-void SymbolTableSection::addSymbol(Twine Name, uint8_t Bind, uint8_t Type,
- SectionBase *DefinedIn, uint64_t Value,
- uint8_t Visibility, uint16_t Shndx,
- uint64_t SymbolSize) {
- Symbol Sym;
- Sym.Name = Name.str();
- Sym.Binding = Bind;
- Sym.Type = Type;
- Sym.DefinedIn = DefinedIn;
- if (DefinedIn != nullptr)
- DefinedIn->HasSymbol = true;
- if (DefinedIn == nullptr) {
- if (Shndx >= SHN_LORESERVE)
- Sym.ShndxType = static_cast<SymbolShndxType>(Shndx);
- else
- Sym.ShndxType = SYMBOL_SIMPLE_INDEX;
- }
- Sym.Value = Value;
- Sym.Visibility = Visibility;
- Sym.Size = SymbolSize;
- Sym.Index = Symbols.size();
- Symbols.emplace_back(std::make_unique<Symbol>(Sym));
- Size += this->EntrySize;
-}
-
-Error SymbolTableSection::removeSectionReferences(
+}
+
+static bool isValidReservedSectionIndex(uint16_t Index, uint16_t Machine) {
+ switch (Index) {
+ case SHN_ABS:
+ case SHN_COMMON:
+ return true;
+ }
+
+ if (Machine == EM_AMDGPU) {
+ return Index == SHN_AMDGPU_LDS;
+ }
+
+ if (Machine == EM_HEXAGON) {
+ switch (Index) {
+ case SHN_HEXAGON_SCOMMON:
+ case SHN_HEXAGON_SCOMMON_1:
+ case SHN_HEXAGON_SCOMMON_2:
+ case SHN_HEXAGON_SCOMMON_4:
+ case SHN_HEXAGON_SCOMMON_8:
+ return true;
+ }
+ }
+ return false;
+}
+
+// Large indexes force us to clarify exactly what this function should do. This
+// function should return the value that will appear in st_shndx when written
+// out.
+uint16_t Symbol::getShndx() const {
+ if (DefinedIn != nullptr) {
+ if (DefinedIn->Index >= SHN_LORESERVE)
+ return SHN_XINDEX;
+ return DefinedIn->Index;
+ }
+
+ if (ShndxType == SYMBOL_SIMPLE_INDEX) {
+ // This means that we don't have a defined section but we do need to
+ // output a legitimate section index.
+ return SHN_UNDEF;
+ }
+
+ assert(ShndxType == SYMBOL_ABS || ShndxType == SYMBOL_COMMON ||
+ (ShndxType >= SYMBOL_LOPROC && ShndxType <= SYMBOL_HIPROC) ||
+ (ShndxType >= SYMBOL_LOOS && ShndxType <= SYMBOL_HIOS));
+ return static_cast<uint16_t>(ShndxType);
+}
+
+bool Symbol::isCommon() const { return getShndx() == SHN_COMMON; }
+
+void SymbolTableSection::assignIndices() {
+ uint32_t Index = 0;
+ for (auto &Sym : Symbols)
+ Sym->Index = Index++;
+}
+
+void SymbolTableSection::addSymbol(Twine Name, uint8_t Bind, uint8_t Type,
+ SectionBase *DefinedIn, uint64_t Value,
+ uint8_t Visibility, uint16_t Shndx,
+ uint64_t SymbolSize) {
+ Symbol Sym;
+ Sym.Name = Name.str();
+ Sym.Binding = Bind;
+ Sym.Type = Type;
+ Sym.DefinedIn = DefinedIn;
+ if (DefinedIn != nullptr)
+ DefinedIn->HasSymbol = true;
+ if (DefinedIn == nullptr) {
+ if (Shndx >= SHN_LORESERVE)
+ Sym.ShndxType = static_cast<SymbolShndxType>(Shndx);
+ else
+ Sym.ShndxType = SYMBOL_SIMPLE_INDEX;
+ }
+ Sym.Value = Value;
+ Sym.Visibility = Visibility;
+ Sym.Size = SymbolSize;
+ Sym.Index = Symbols.size();
+ Symbols.emplace_back(std::make_unique<Symbol>(Sym));
+ Size += this->EntrySize;
+}
+
+Error SymbolTableSection::removeSectionReferences(
bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
- if (ToRemove(SectionIndexTable))
- SectionIndexTable = nullptr;
- if (ToRemove(SymbolNames)) {
- if (!AllowBrokenLinks)
- return createStringError(
- llvm::errc::invalid_argument,
- "string table '%s' cannot be removed because it is "
- "referenced by the symbol table '%s'",
- SymbolNames->Name.data(), this->Name.data());
- SymbolNames = nullptr;
- }
- return removeSymbols(
- [ToRemove](const Symbol &Sym) { return ToRemove(Sym.DefinedIn); });
-}
-
-void SymbolTableSection::updateSymbols(function_ref<void(Symbol &)> Callable) {
- std::for_each(std::begin(Symbols) + 1, std::end(Symbols),
- [Callable](SymPtr &Sym) { Callable(*Sym); });
- std::stable_partition(
- std::begin(Symbols), std::end(Symbols),
- [](const SymPtr &Sym) { return Sym->Binding == STB_LOCAL; });
- assignIndices();
-}
-
-Error SymbolTableSection::removeSymbols(
- function_ref<bool(const Symbol &)> ToRemove) {
- Symbols.erase(
- std::remove_if(std::begin(Symbols) + 1, std::end(Symbols),
- [ToRemove](const SymPtr &Sym) { return ToRemove(*Sym); }),
- std::end(Symbols));
- Size = Symbols.size() * EntrySize;
- assignIndices();
- return Error::success();
-}
-
-void SymbolTableSection::replaceSectionReferences(
- const DenseMap<SectionBase *, SectionBase *> &FromTo) {
- for (std::unique_ptr<Symbol> &Sym : Symbols)
- if (SectionBase *To = FromTo.lookup(Sym->DefinedIn))
- Sym->DefinedIn = To;
-}
-
+ if (ToRemove(SectionIndexTable))
+ SectionIndexTable = nullptr;
+ if (ToRemove(SymbolNames)) {
+ if (!AllowBrokenLinks)
+ return createStringError(
+ llvm::errc::invalid_argument,
+ "string table '%s' cannot be removed because it is "
+ "referenced by the symbol table '%s'",
+ SymbolNames->Name.data(), this->Name.data());
+ SymbolNames = nullptr;
+ }
+ return removeSymbols(
+ [ToRemove](const Symbol &Sym) { return ToRemove(Sym.DefinedIn); });
+}
+
+void SymbolTableSection::updateSymbols(function_ref<void(Symbol &)> Callable) {
+ std::for_each(std::begin(Symbols) + 1, std::end(Symbols),
+ [Callable](SymPtr &Sym) { Callable(*Sym); });
+ std::stable_partition(
+ std::begin(Symbols), std::end(Symbols),
+ [](const SymPtr &Sym) { return Sym->Binding == STB_LOCAL; });
+ assignIndices();
+}
+
+Error SymbolTableSection::removeSymbols(
+ function_ref<bool(const Symbol &)> ToRemove) {
+ Symbols.erase(
+ std::remove_if(std::begin(Symbols) + 1, std::end(Symbols),
+ [ToRemove](const SymPtr &Sym) { return ToRemove(*Sym); }),
+ std::end(Symbols));
+ Size = Symbols.size() * EntrySize;
+ assignIndices();
+ return Error::success();
+}
+
+void SymbolTableSection::replaceSectionReferences(
+ const DenseMap<SectionBase *, SectionBase *> &FromTo) {
+ for (std::unique_ptr<Symbol> &Sym : Symbols)
+ if (SectionBase *To = FromTo.lookup(Sym->DefinedIn))
+ Sym->DefinedIn = To;
+}
+
Error SymbolTableSection::initialize(SectionTableRef SecTable) {
- Size = 0;
+ Size = 0;
Expected<StringTableSection *> Sec =
SecTable.getSectionOfType<StringTableSection>(
Link,
@@ -807,58 +807,58 @@ Error SymbolTableSection::initialize(SectionTableRef SecTable) {
setStrTab(*Sec);
return Error::success();
-}
-
-void SymbolTableSection::finalize() {
- uint32_t MaxLocalIndex = 0;
- for (std::unique_ptr<Symbol> &Sym : Symbols) {
- Sym->NameIndex =
- SymbolNames == nullptr ? 0 : SymbolNames->findIndex(Sym->Name);
- if (Sym->Binding == STB_LOCAL)
- MaxLocalIndex = std::max(MaxLocalIndex, Sym->Index);
- }
- // Now we need to set the Link and Info fields.
- Link = SymbolNames == nullptr ? 0 : SymbolNames->Index;
- Info = MaxLocalIndex + 1;
-}
-
-void SymbolTableSection::prepareForLayout() {
- // Reserve proper amount of space in section index table, so we can
- // layout sections correctly. We will fill the table with correct
- // indexes later in fillShdnxTable.
- if (SectionIndexTable)
- SectionIndexTable->reserve(Symbols.size());
-
- // Add all of our strings to SymbolNames so that SymbolNames has the right
- // size before layout is decided.
- // If the symbol names section has been removed, don't try to add strings to
- // the table.
- if (SymbolNames != nullptr)
- for (std::unique_ptr<Symbol> &Sym : Symbols)
- SymbolNames->addString(Sym->Name);
-}
-
-void SymbolTableSection::fillShndxTable() {
- if (SectionIndexTable == nullptr)
- return;
- // Fill section index table with real section indexes. This function must
- // be called after assignOffsets.
- for (const std::unique_ptr<Symbol> &Sym : Symbols) {
- if (Sym->DefinedIn != nullptr && Sym->DefinedIn->Index >= SHN_LORESERVE)
- SectionIndexTable->addIndex(Sym->DefinedIn->Index);
- else
- SectionIndexTable->addIndex(SHN_UNDEF);
- }
-}
-
+}
+
+void SymbolTableSection::finalize() {
+ uint32_t MaxLocalIndex = 0;
+ for (std::unique_ptr<Symbol> &Sym : Symbols) {
+ Sym->NameIndex =
+ SymbolNames == nullptr ? 0 : SymbolNames->findIndex(Sym->Name);
+ if (Sym->Binding == STB_LOCAL)
+ MaxLocalIndex = std::max(MaxLocalIndex, Sym->Index);
+ }
+ // Now we need to set the Link and Info fields.
+ Link = SymbolNames == nullptr ? 0 : SymbolNames->Index;
+ Info = MaxLocalIndex + 1;
+}
+
+void SymbolTableSection::prepareForLayout() {
+ // Reserve proper amount of space in section index table, so we can
+ // layout sections correctly. We will fill the table with correct
+ // indexes later in fillShdnxTable.
+ if (SectionIndexTable)
+ SectionIndexTable->reserve(Symbols.size());
+
+ // Add all of our strings to SymbolNames so that SymbolNames has the right
+ // size before layout is decided.
+ // If the symbol names section has been removed, don't try to add strings to
+ // the table.
+ if (SymbolNames != nullptr)
+ for (std::unique_ptr<Symbol> &Sym : Symbols)
+ SymbolNames->addString(Sym->Name);
+}
+
+void SymbolTableSection::fillShndxTable() {
+ if (SectionIndexTable == nullptr)
+ return;
+ // Fill section index table with real section indexes. This function must
+ // be called after assignOffsets.
+ for (const std::unique_ptr<Symbol> &Sym : Symbols) {
+ if (Sym->DefinedIn != nullptr && Sym->DefinedIn->Index >= SHN_LORESERVE)
+ SectionIndexTable->addIndex(Sym->DefinedIn->Index);
+ else
+ SectionIndexTable->addIndex(SHN_UNDEF);
+ }
+}
+
Expected<const Symbol *>
SymbolTableSection::getSymbolByIndex(uint32_t Index) const {
- if (Symbols.size() <= Index)
+ if (Symbols.size() <= Index)
return createStringError(errc::invalid_argument,
"invalid symbol index: " + Twine(Index));
- return Symbols[Index].get();
-}
-
+ return Symbols[Index].get();
+}
+
Expected<Symbol *> SymbolTableSection::getSymbolByIndex(uint32_t Index) {
Expected<const Symbol *> Sym =
static_cast<const SymbolTableSection *>(this)->getSymbolByIndex(Index);
@@ -866,73 +866,73 @@ Expected<Symbol *> SymbolTableSection::getSymbolByIndex(uint32_t Index) {
return Sym.takeError();
return const_cast<Symbol *>(*Sym);
-}
-
-template <class ELFT>
+}
+
+template <class ELFT>
Error ELFSectionWriter<ELFT>::visit(const SymbolTableSection &Sec) {
- Elf_Sym *Sym = reinterpret_cast<Elf_Sym *>(Out.getBufferStart() + Sec.Offset);
- // Loop though symbols setting each entry of the symbol table.
- for (const std::unique_ptr<Symbol> &Symbol : Sec.Symbols) {
- Sym->st_name = Symbol->NameIndex;
- Sym->st_value = Symbol->Value;
- Sym->st_size = Symbol->Size;
- Sym->st_other = Symbol->Visibility;
- Sym->setBinding(Symbol->Binding);
- Sym->setType(Symbol->Type);
- Sym->st_shndx = Symbol->getShndx();
- ++Sym;
- }
+ Elf_Sym *Sym = reinterpret_cast<Elf_Sym *>(Out.getBufferStart() + Sec.Offset);
+ // Loop though symbols setting each entry of the symbol table.
+ for (const std::unique_ptr<Symbol> &Symbol : Sec.Symbols) {
+ Sym->st_name = Symbol->NameIndex;
+ Sym->st_value = Symbol->Value;
+ Sym->st_size = Symbol->Size;
+ Sym->st_other = Symbol->Visibility;
+ Sym->setBinding(Symbol->Binding);
+ Sym->setType(Symbol->Type);
+ Sym->st_shndx = Symbol->getShndx();
+ ++Sym;
+ }
return Error::success();
-}
-
+}
+
Error SymbolTableSection::accept(SectionVisitor &Visitor) const {
return Visitor.visit(*this);
-}
-
+}
+
Error SymbolTableSection::accept(MutableSectionVisitor &Visitor) {
return Visitor.visit(*this);
-}
-
-Error RelocationSection::removeSectionReferences(
+}
+
+Error RelocationSection::removeSectionReferences(
bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
- if (ToRemove(Symbols)) {
- if (!AllowBrokenLinks)
- return createStringError(
- llvm::errc::invalid_argument,
- "symbol table '%s' cannot be removed because it is "
- "referenced by the relocation section '%s'",
- Symbols->Name.data(), this->Name.data());
- Symbols = nullptr;
- }
-
- for (const Relocation &R : Relocations) {
- if (!R.RelocSymbol || !R.RelocSymbol->DefinedIn ||
- !ToRemove(R.RelocSymbol->DefinedIn))
- continue;
- return createStringError(llvm::errc::invalid_argument,
- "section '%s' cannot be removed: (%s+0x%" PRIx64
- ") has relocation against symbol '%s'",
- R.RelocSymbol->DefinedIn->Name.data(),
- SecToApplyRel->Name.data(), R.Offset,
- R.RelocSymbol->Name.c_str());
- }
-
- return Error::success();
-}
-
-template <class SymTabType>
+ if (ToRemove(Symbols)) {
+ if (!AllowBrokenLinks)
+ return createStringError(
+ llvm::errc::invalid_argument,
+ "symbol table '%s' cannot be removed because it is "
+ "referenced by the relocation section '%s'",
+ Symbols->Name.data(), this->Name.data());
+ Symbols = nullptr;
+ }
+
+ for (const Relocation &R : Relocations) {
+ if (!R.RelocSymbol || !R.RelocSymbol->DefinedIn ||
+ !ToRemove(R.RelocSymbol->DefinedIn))
+ continue;
+ return createStringError(llvm::errc::invalid_argument,
+ "section '%s' cannot be removed: (%s+0x%" PRIx64
+ ") has relocation against symbol '%s'",
+ R.RelocSymbol->DefinedIn->Name.data(),
+ SecToApplyRel->Name.data(), R.Offset,
+ R.RelocSymbol->Name.c_str());
+ }
+
+ return Error::success();
+}
+
+template <class SymTabType>
Error RelocSectionWithSymtabBase<SymTabType>::initialize(
- SectionTableRef SecTable) {
+ SectionTableRef SecTable) {
if (Link != SHN_UNDEF) {
Expected<SymTabType *> Sec = SecTable.getSectionOfType<SymTabType>(
- Link,
- "Link field value " + Twine(Link) + " in section " + Name +
- " is invalid",
- "Link field value " + Twine(Link) + " in section " + Name +
+ Link,
+ "Link field value " + Twine(Link) + " in section " + Name +
+ " is invalid",
+ "Link field value " + Twine(Link) + " in section " + Name +
" is not a symbol table");
if (!Sec)
return Sec.takeError();
-
+
setSymTab(*Sec);
}
@@ -945,467 +945,467 @@ Error RelocSectionWithSymtabBase<SymTabType>::initialize(
setSection(*Sec);
} else
- setSection(nullptr);
+ setSection(nullptr);
return Error::success();
-}
-
-template <class SymTabType>
-void RelocSectionWithSymtabBase<SymTabType>::finalize() {
- this->Link = Symbols ? Symbols->Index : 0;
-
- if (SecToApplyRel != nullptr)
- this->Info = SecToApplyRel->Index;
-}
-
-template <class ELFT>
+}
+
+template <class SymTabType>
+void RelocSectionWithSymtabBase<SymTabType>::finalize() {
+ this->Link = Symbols ? Symbols->Index : 0;
+
+ if (SecToApplyRel != nullptr)
+ this->Info = SecToApplyRel->Index;
+}
+
+template <class ELFT>
static void setAddend(Elf_Rel_Impl<ELFT, false> &, uint64_t) {}
-
-template <class ELFT>
-static void setAddend(Elf_Rel_Impl<ELFT, true> &Rela, uint64_t Addend) {
- Rela.r_addend = Addend;
-}
-
-template <class RelRange, class T>
-static void writeRel(const RelRange &Relocations, T *Buf) {
- for (const auto &Reloc : Relocations) {
- Buf->r_offset = Reloc.Offset;
- setAddend(*Buf, Reloc.Addend);
- Buf->setSymbolAndType(Reloc.RelocSymbol ? Reloc.RelocSymbol->Index : 0,
- Reloc.Type, false);
- ++Buf;
- }
-}
-
-template <class ELFT>
+
+template <class ELFT>
+static void setAddend(Elf_Rel_Impl<ELFT, true> &Rela, uint64_t Addend) {
+ Rela.r_addend = Addend;
+}
+
+template <class RelRange, class T>
+static void writeRel(const RelRange &Relocations, T *Buf) {
+ for (const auto &Reloc : Relocations) {
+ Buf->r_offset = Reloc.Offset;
+ setAddend(*Buf, Reloc.Addend);
+ Buf->setSymbolAndType(Reloc.RelocSymbol ? Reloc.RelocSymbol->Index : 0,
+ Reloc.Type, false);
+ ++Buf;
+ }
+}
+
+template <class ELFT>
Error ELFSectionWriter<ELFT>::visit(const RelocationSection &Sec) {
- uint8_t *Buf = Out.getBufferStart() + Sec.Offset;
- if (Sec.Type == SHT_REL)
- writeRel(Sec.Relocations, reinterpret_cast<Elf_Rel *>(Buf));
- else
- writeRel(Sec.Relocations, reinterpret_cast<Elf_Rela *>(Buf));
+ uint8_t *Buf = Out.getBufferStart() + Sec.Offset;
+ if (Sec.Type == SHT_REL)
+ writeRel(Sec.Relocations, reinterpret_cast<Elf_Rel *>(Buf));
+ else
+ writeRel(Sec.Relocations, reinterpret_cast<Elf_Rela *>(Buf));
return Error::success();
-}
-
+}
+
Error RelocationSection::accept(SectionVisitor &Visitor) const {
return Visitor.visit(*this);
-}
-
+}
+
Error RelocationSection::accept(MutableSectionVisitor &Visitor) {
return Visitor.visit(*this);
-}
-
-Error RelocationSection::removeSymbols(
- function_ref<bool(const Symbol &)> ToRemove) {
- for (const Relocation &Reloc : Relocations)
- if (Reloc.RelocSymbol && ToRemove(*Reloc.RelocSymbol))
- return createStringError(
- llvm::errc::invalid_argument,
- "not stripping symbol '%s' because it is named in a relocation",
- Reloc.RelocSymbol->Name.data());
- return Error::success();
-}
-
-void RelocationSection::markSymbols() {
- for (const Relocation &Reloc : Relocations)
- if (Reloc.RelocSymbol)
- Reloc.RelocSymbol->Referenced = true;
-}
-
-void RelocationSection::replaceSectionReferences(
- const DenseMap<SectionBase *, SectionBase *> &FromTo) {
- // Update the target section if it was replaced.
- if (SectionBase *To = FromTo.lookup(SecToApplyRel))
- SecToApplyRel = To;
-}
-
+}
+
+Error RelocationSection::removeSymbols(
+ function_ref<bool(const Symbol &)> ToRemove) {
+ for (const Relocation &Reloc : Relocations)
+ if (Reloc.RelocSymbol && ToRemove(*Reloc.RelocSymbol))
+ return createStringError(
+ llvm::errc::invalid_argument,
+ "not stripping symbol '%s' because it is named in a relocation",
+ Reloc.RelocSymbol->Name.data());
+ return Error::success();
+}
+
+void RelocationSection::markSymbols() {
+ for (const Relocation &Reloc : Relocations)
+ if (Reloc.RelocSymbol)
+ Reloc.RelocSymbol->Referenced = true;
+}
+
+void RelocationSection::replaceSectionReferences(
+ const DenseMap<SectionBase *, SectionBase *> &FromTo) {
+ // Update the target section if it was replaced.
+ if (SectionBase *To = FromTo.lookup(SecToApplyRel))
+ SecToApplyRel = To;
+}
+
Error SectionWriter::visit(const DynamicRelocationSection &Sec) {
- llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset);
+ llvm::copy(Sec.Contents, Out.getBufferStart() + Sec.Offset);
return Error::success();
-}
-
+}
+
Error DynamicRelocationSection::accept(SectionVisitor &Visitor) const {
return Visitor.visit(*this);
-}
-
+}
+
Error DynamicRelocationSection::accept(MutableSectionVisitor &Visitor) {
return Visitor.visit(*this);
-}
-
-Error DynamicRelocationSection::removeSectionReferences(
- bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
- if (ToRemove(Symbols)) {
- if (!AllowBrokenLinks)
- return createStringError(
- llvm::errc::invalid_argument,
- "symbol table '%s' cannot be removed because it is "
- "referenced by the relocation section '%s'",
- Symbols->Name.data(), this->Name.data());
- Symbols = nullptr;
- }
-
- // SecToApplyRel contains a section referenced by sh_info field. It keeps
- // a section to which the relocation section applies. When we remove any
- // sections we also remove their relocation sections. Since we do that much
- // earlier, this assert should never be triggered.
- assert(!SecToApplyRel || !ToRemove(SecToApplyRel));
- return Error::success();
-}
-
-Error Section::removeSectionReferences(
- bool AllowBrokenDependency,
- function_ref<bool(const SectionBase *)> ToRemove) {
- if (ToRemove(LinkSection)) {
- if (!AllowBrokenDependency)
- return createStringError(llvm::errc::invalid_argument,
- "section '%s' cannot be removed because it is "
- "referenced by the section '%s'",
- LinkSection->Name.data(), this->Name.data());
- LinkSection = nullptr;
- }
- return Error::success();
-}
-
-void GroupSection::finalize() {
- this->Info = Sym ? Sym->Index : 0;
- this->Link = SymTab ? SymTab->Index : 0;
-}
-
-Error GroupSection::removeSectionReferences(
- bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
- if (ToRemove(SymTab)) {
- if (!AllowBrokenLinks)
- return createStringError(
- llvm::errc::invalid_argument,
- "section '.symtab' cannot be removed because it is "
- "referenced by the group section '%s'",
- this->Name.data());
- SymTab = nullptr;
- Sym = nullptr;
- }
- llvm::erase_if(GroupMembers, ToRemove);
- return Error::success();
-}
-
-Error GroupSection::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
- if (ToRemove(*Sym))
- return createStringError(llvm::errc::invalid_argument,
- "symbol '%s' cannot be removed because it is "
- "referenced by the section '%s[%d]'",
- Sym->Name.data(), this->Name.data(), this->Index);
- return Error::success();
-}
-
-void GroupSection::markSymbols() {
- if (Sym)
- Sym->Referenced = true;
-}
-
-void GroupSection::replaceSectionReferences(
- const DenseMap<SectionBase *, SectionBase *> &FromTo) {
- for (SectionBase *&Sec : GroupMembers)
- if (SectionBase *To = FromTo.lookup(Sec))
- Sec = To;
-}
-
-void GroupSection::onRemove() {
- // As the header section of the group is removed, drop the Group flag in its
- // former members.
- for (SectionBase *Sec : GroupMembers)
- Sec->Flags &= ~SHF_GROUP;
-}
-
+}
+
+Error DynamicRelocationSection::removeSectionReferences(
+ bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
+ if (ToRemove(Symbols)) {
+ if (!AllowBrokenLinks)
+ return createStringError(
+ llvm::errc::invalid_argument,
+ "symbol table '%s' cannot be removed because it is "
+ "referenced by the relocation section '%s'",
+ Symbols->Name.data(), this->Name.data());
+ Symbols = nullptr;
+ }
+
+ // SecToApplyRel contains a section referenced by sh_info field. It keeps
+ // a section to which the relocation section applies. When we remove any
+ // sections we also remove their relocation sections. Since we do that much
+ // earlier, this assert should never be triggered.
+ assert(!SecToApplyRel || !ToRemove(SecToApplyRel));
+ return Error::success();
+}
+
+Error Section::removeSectionReferences(
+ bool AllowBrokenDependency,
+ function_ref<bool(const SectionBase *)> ToRemove) {
+ if (ToRemove(LinkSection)) {
+ if (!AllowBrokenDependency)
+ return createStringError(llvm::errc::invalid_argument,
+ "section '%s' cannot be removed because it is "
+ "referenced by the section '%s'",
+ LinkSection->Name.data(), this->Name.data());
+ LinkSection = nullptr;
+ }
+ return Error::success();
+}
+
+void GroupSection::finalize() {
+ this->Info = Sym ? Sym->Index : 0;
+ this->Link = SymTab ? SymTab->Index : 0;
+}
+
+Error GroupSection::removeSectionReferences(
+ bool AllowBrokenLinks, function_ref<bool(const SectionBase *)> ToRemove) {
+ if (ToRemove(SymTab)) {
+ if (!AllowBrokenLinks)
+ return createStringError(
+ llvm::errc::invalid_argument,
+ "section '.symtab' cannot be removed because it is "
+ "referenced by the group section '%s'",
+ this->Name.data());
+ SymTab = nullptr;
+ Sym = nullptr;
+ }
+ llvm::erase_if(GroupMembers, ToRemove);
+ return Error::success();
+}
+
+Error GroupSection::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
+ if (ToRemove(*Sym))
+ return createStringError(llvm::errc::invalid_argument,
+ "symbol '%s' cannot be removed because it is "
+ "referenced by the section '%s[%d]'",
+ Sym->Name.data(), this->Name.data(), this->Index);
+ return Error::success();
+}
+
+void GroupSection::markSymbols() {
+ if (Sym)
+ Sym->Referenced = true;
+}
+
+void GroupSection::replaceSectionReferences(
+ const DenseMap<SectionBase *, SectionBase *> &FromTo) {
+ for (SectionBase *&Sec : GroupMembers)
+ if (SectionBase *To = FromTo.lookup(Sec))
+ Sec = To;
+}
+
+void GroupSection::onRemove() {
+ // As the header section of the group is removed, drop the Group flag in its
+ // former members.
+ for (SectionBase *Sec : GroupMembers)
+ Sec->Flags &= ~SHF_GROUP;
+}
+
Error Section::initialize(SectionTableRef SecTable) {
- if (Link == ELF::SHN_UNDEF)
+ if (Link == ELF::SHN_UNDEF)
return Error::success();
Expected<SectionBase *> Sec =
- SecTable.getSection(Link, "Link field value " + Twine(Link) +
- " in section " + Name + " is invalid");
+ SecTable.getSection(Link, "Link field value " + Twine(Link) +
+ " in section " + Name + " is invalid");
if (!Sec)
return Sec.takeError();
LinkSection = *Sec;
- if (LinkSection->Type == ELF::SHT_SYMTAB)
- LinkSection = nullptr;
+ if (LinkSection->Type == ELF::SHT_SYMTAB)
+ LinkSection = nullptr;
return Error::success();
-}
-
-void Section::finalize() { this->Link = LinkSection ? LinkSection->Index : 0; }
-
-void GnuDebugLinkSection::init(StringRef File) {
- FileName = sys::path::filename(File);
- // The format for the .gnu_debuglink starts with the file name and is
- // followed by a null terminator and then the CRC32 of the file. The CRC32
- // should be 4 byte aligned. So we add the FileName size, a 1 for the null
- // byte, and then finally push the size to alignment and add 4.
- Size = alignTo(FileName.size() + 1, 4) + 4;
- // The CRC32 will only be aligned if we align the whole section.
- Align = 4;
- Type = OriginalType = ELF::SHT_PROGBITS;
- Name = ".gnu_debuglink";
- // For sections not found in segments, OriginalOffset is only used to
- // establish the order that sections should go in. By using the maximum
- // possible offset we cause this section to wind up at the end.
- OriginalOffset = std::numeric_limits<uint64_t>::max();
-}
-
-GnuDebugLinkSection::GnuDebugLinkSection(StringRef File,
- uint32_t PrecomputedCRC)
- : FileName(File), CRC32(PrecomputedCRC) {
- init(File);
-}
-
-template <class ELFT>
+}
+
+void Section::finalize() { this->Link = LinkSection ? LinkSection->Index : 0; }
+
+void GnuDebugLinkSection::init(StringRef File) {
+ FileName = sys::path::filename(File);
+ // The format for the .gnu_debuglink starts with the file name and is
+ // followed by a null terminator and then the CRC32 of the file. The CRC32
+ // should be 4 byte aligned. So we add the FileName size, a 1 for the null
+ // byte, and then finally push the size to alignment and add 4.
+ Size = alignTo(FileName.size() + 1, 4) + 4;
+ // The CRC32 will only be aligned if we align the whole section.
+ Align = 4;
+ Type = OriginalType = ELF::SHT_PROGBITS;
+ Name = ".gnu_debuglink";
+ // For sections not found in segments, OriginalOffset is only used to
+ // establish the order that sections should go in. By using the maximum
+ // possible offset we cause this section to wind up at the end.
+ OriginalOffset = std::numeric_limits<uint64_t>::max();
+}
+
+GnuDebugLinkSection::GnuDebugLinkSection(StringRef File,
+ uint32_t PrecomputedCRC)
+ : FileName(File), CRC32(PrecomputedCRC) {
+ init(File);
+}
+
+template <class ELFT>
Error ELFSectionWriter<ELFT>::visit(const GnuDebugLinkSection &Sec) {
- unsigned char *Buf = Out.getBufferStart() + Sec.Offset;
- Elf_Word *CRC =
- reinterpret_cast<Elf_Word *>(Buf + Sec.Size - sizeof(Elf_Word));
- *CRC = Sec.CRC32;
- llvm::copy(Sec.FileName, Buf);
+ unsigned char *Buf = Out.getBufferStart() + Sec.Offset;
+ Elf_Word *CRC =
+ reinterpret_cast<Elf_Word *>(Buf + Sec.Size - sizeof(Elf_Word));
+ *CRC = Sec.CRC32;
+ llvm::copy(Sec.FileName, Buf);
return Error::success();
-}
-
+}
+
Error GnuDebugLinkSection::accept(SectionVisitor &Visitor) const {
return Visitor.visit(*this);
-}
-
+}
+
Error GnuDebugLinkSection::accept(MutableSectionVisitor &Visitor) {
return Visitor.visit(*this);
-}
-
-template <class ELFT>
+}
+
+template <class ELFT>
Error ELFSectionWriter<ELFT>::visit(const GroupSection &Sec) {
- ELF::Elf32_Word *Buf =
- reinterpret_cast<ELF::Elf32_Word *>(Out.getBufferStart() + Sec.Offset);
- *Buf++ = Sec.FlagWord;
- for (SectionBase *S : Sec.GroupMembers)
- support::endian::write32<ELFT::TargetEndianness>(Buf++, S->Index);
+ ELF::Elf32_Word *Buf =
+ reinterpret_cast<ELF::Elf32_Word *>(Out.getBufferStart() + Sec.Offset);
+ *Buf++ = Sec.FlagWord;
+ for (SectionBase *S : Sec.GroupMembers)
+ support::endian::write32<ELFT::TargetEndianness>(Buf++, S->Index);
return Error::success();
-}
-
+}
+
Error GroupSection::accept(SectionVisitor &Visitor) const {
return Visitor.visit(*this);
-}
-
+}
+
Error GroupSection::accept(MutableSectionVisitor &Visitor) {
return Visitor.visit(*this);
-}
-
-// Returns true IFF a section is wholly inside the range of a 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 = Sec.Size ? Sec.Size : 1;
-
- if (Sec.Type == SHT_NOBITS) {
- if (!(Sec.Flags & SHF_ALLOC))
- return false;
-
- bool SectionIsTLS = Sec.Flags & SHF_TLS;
- bool SegmentIsTLS = Seg.Type == PT_TLS;
- if (SectionIsTLS != SegmentIsTLS)
- return false;
-
- return Seg.VAddr <= Sec.Addr &&
- Seg.VAddr + Seg.MemSize >= Sec.Addr + 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
-// range.
-static bool segmentOverlapsSegment(const Segment &Child,
- const Segment &Parent) {
-
- return Parent.OriginalOffset <= Child.OriginalOffset &&
- Parent.OriginalOffset + Parent.FileSize > Child.OriginalOffset;
-}
-
-static bool compareSegmentsByOffset(const Segment *A, const Segment *B) {
- // Any segment without a parent segment should come before a segment
- // that has a parent segment.
- if (A->OriginalOffset < B->OriginalOffset)
- return true;
- if (A->OriginalOffset > B->OriginalOffset)
- return false;
- return A->Index < B->Index;
-}
-
-void BasicELFBuilder::initFileHeader() {
- Obj->Flags = 0x0;
- Obj->Type = ET_REL;
- Obj->OSABI = ELFOSABI_NONE;
- Obj->ABIVersion = 0;
- Obj->Entry = 0x0;
- Obj->Machine = EM_NONE;
- Obj->Version = 1;
-}
-
-void BasicELFBuilder::initHeaderSegment() { Obj->ElfHdrSegment.Index = 0; }
-
-StringTableSection *BasicELFBuilder::addStrTab() {
- auto &StrTab = Obj->addSection<StringTableSection>();
- StrTab.Name = ".strtab";
-
- Obj->SectionNames = &StrTab;
- return &StrTab;
-}
-
-SymbolTableSection *BasicELFBuilder::addSymTab(StringTableSection *StrTab) {
- auto &SymTab = Obj->addSection<SymbolTableSection>();
-
- SymTab.Name = ".symtab";
- SymTab.Link = StrTab->Index;
-
- // The symbol table always needs a null symbol
- SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);
-
- Obj->SymbolTable = &SymTab;
- return &SymTab;
-}
-
+}
+
+// Returns true IFF a section is wholly inside the range of a 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 = Sec.Size ? Sec.Size : 1;
+
+ if (Sec.Type == SHT_NOBITS) {
+ if (!(Sec.Flags & SHF_ALLOC))
+ return false;
+
+ bool SectionIsTLS = Sec.Flags & SHF_TLS;
+ bool SegmentIsTLS = Seg.Type == PT_TLS;
+ if (SectionIsTLS != SegmentIsTLS)
+ return false;
+
+ return Seg.VAddr <= Sec.Addr &&
+ Seg.VAddr + Seg.MemSize >= Sec.Addr + 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
+// range.
+static bool segmentOverlapsSegment(const Segment &Child,
+ const Segment &Parent) {
+
+ return Parent.OriginalOffset <= Child.OriginalOffset &&
+ Parent.OriginalOffset + Parent.FileSize > Child.OriginalOffset;
+}
+
+static bool compareSegmentsByOffset(const Segment *A, const Segment *B) {
+ // Any segment without a parent segment should come before a segment
+ // that has a parent segment.
+ if (A->OriginalOffset < B->OriginalOffset)
+ return true;
+ if (A->OriginalOffset > B->OriginalOffset)
+ return false;
+ return A->Index < B->Index;
+}
+
+void BasicELFBuilder::initFileHeader() {
+ Obj->Flags = 0x0;
+ Obj->Type = ET_REL;
+ Obj->OSABI = ELFOSABI_NONE;
+ Obj->ABIVersion = 0;
+ Obj->Entry = 0x0;
+ Obj->Machine = EM_NONE;
+ Obj->Version = 1;
+}
+
+void BasicELFBuilder::initHeaderSegment() { Obj->ElfHdrSegment.Index = 0; }
+
+StringTableSection *BasicELFBuilder::addStrTab() {
+ auto &StrTab = Obj->addSection<StringTableSection>();
+ StrTab.Name = ".strtab";
+
+ Obj->SectionNames = &StrTab;
+ return &StrTab;
+}
+
+SymbolTableSection *BasicELFBuilder::addSymTab(StringTableSection *StrTab) {
+ auto &SymTab = Obj->addSection<SymbolTableSection>();
+
+ SymTab.Name = ".symtab";
+ SymTab.Link = StrTab->Index;
+
+ // The symbol table always needs a null symbol
+ SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);
+
+ Obj->SymbolTable = &SymTab;
+ return &SymTab;
+}
+
Error BasicELFBuilder::initSections() {
- for (SectionBase &Sec : Obj->sections())
+ for (SectionBase &Sec : Obj->sections())
if (Error Err = Sec.initialize(Obj->sections()))
return Err;
return Error::success();
-}
-
-void BinaryELFBuilder::addData(SymbolTableSection *SymTab) {
- auto Data = ArrayRef<uint8_t>(
- reinterpret_cast<const uint8_t *>(MemBuf->getBufferStart()),
- MemBuf->getBufferSize());
- auto &DataSection = Obj->addSection<Section>(Data);
- DataSection.Name = ".data";
- DataSection.Type = ELF::SHT_PROGBITS;
- DataSection.Size = Data.size();
- DataSection.Flags = ELF::SHF_ALLOC | ELF::SHF_WRITE;
-
- std::string SanitizedFilename = MemBuf->getBufferIdentifier().str();
- std::replace_if(std::begin(SanitizedFilename), std::end(SanitizedFilename),
- [](char C) { return !isalnum(C); }, '_');
- Twine Prefix = Twine("_binary_") + SanitizedFilename;
-
- SymTab->addSymbol(Prefix + "_start", STB_GLOBAL, STT_NOTYPE, &DataSection,
- /*Value=*/0, NewSymbolVisibility, 0, 0);
- SymTab->addSymbol(Prefix + "_end", STB_GLOBAL, STT_NOTYPE, &DataSection,
- /*Value=*/DataSection.Size, NewSymbolVisibility, 0, 0);
- SymTab->addSymbol(Prefix + "_size", STB_GLOBAL, STT_NOTYPE, nullptr,
- /*Value=*/DataSection.Size, NewSymbolVisibility, SHN_ABS,
- 0);
-}
-
+}
+
+void BinaryELFBuilder::addData(SymbolTableSection *SymTab) {
+ auto Data = ArrayRef<uint8_t>(
+ reinterpret_cast<const uint8_t *>(MemBuf->getBufferStart()),
+ MemBuf->getBufferSize());
+ auto &DataSection = Obj->addSection<Section>(Data);
+ DataSection.Name = ".data";
+ DataSection.Type = ELF::SHT_PROGBITS;
+ DataSection.Size = Data.size();
+ DataSection.Flags = ELF::SHF_ALLOC | ELF::SHF_WRITE;
+
+ std::string SanitizedFilename = MemBuf->getBufferIdentifier().str();
+ std::replace_if(std::begin(SanitizedFilename), std::end(SanitizedFilename),
+ [](char C) { return !isalnum(C); }, '_');
+ Twine Prefix = Twine("_binary_") + SanitizedFilename;
+
+ SymTab->addSymbol(Prefix + "_start", STB_GLOBAL, STT_NOTYPE, &DataSection,
+ /*Value=*/0, NewSymbolVisibility, 0, 0);
+ SymTab->addSymbol(Prefix + "_end", STB_GLOBAL, STT_NOTYPE, &DataSection,
+ /*Value=*/DataSection.Size, NewSymbolVisibility, 0, 0);
+ SymTab->addSymbol(Prefix + "_size", STB_GLOBAL, STT_NOTYPE, nullptr,
+ /*Value=*/DataSection.Size, NewSymbolVisibility, SHN_ABS,
+ 0);
+}
+
Expected<std::unique_ptr<Object>> BinaryELFBuilder::build() {
- initFileHeader();
- initHeaderSegment();
-
- SymbolTableSection *SymTab = addSymTab(addStrTab());
+ initFileHeader();
+ initHeaderSegment();
+
+ SymbolTableSection *SymTab = addSymTab(addStrTab());
if (Error Err = initSections())
return std::move(Err);
- addData(SymTab);
-
- return std::move(Obj);
-}
-
-// Adds sections from IHEX data file. Data should have been
-// fully validated by this time.
-void IHexELFBuilder::addDataSections() {
- OwnedDataSection *Section = nullptr;
- uint64_t SegmentAddr = 0, BaseAddr = 0;
- uint32_t SecNo = 1;
-
- for (const IHexRecord &R : Records) {
- uint64_t RecAddr;
- switch (R.Type) {
- case IHexRecord::Data:
- // Ignore empty data records
- if (R.HexData.empty())
- continue;
- RecAddr = R.Addr + SegmentAddr + BaseAddr;
- if (!Section || Section->Addr + Section->Size != RecAddr)
- // OriginalOffset field is only used to sort section properly, so
- // instead of keeping track of real offset in IHEX file, we use
- // section number.
- Section = &Obj->addSection<OwnedDataSection>(
- ".sec" + std::to_string(SecNo++), RecAddr,
- ELF::SHF_ALLOC | ELF::SHF_WRITE, SecNo);
- Section->appendHexData(R.HexData);
- break;
- case IHexRecord::EndOfFile:
- break;
- case IHexRecord::SegmentAddr:
- // 20-bit segment address.
- SegmentAddr = checkedGetHex<uint16_t>(R.HexData) << 4;
- break;
- case IHexRecord::StartAddr80x86:
- case IHexRecord::StartAddr:
- Obj->Entry = checkedGetHex<uint32_t>(R.HexData);
- assert(Obj->Entry <= 0xFFFFFU);
- break;
- case IHexRecord::ExtendedAddr:
- // 16-31 bits of linear base address
- BaseAddr = checkedGetHex<uint16_t>(R.HexData) << 16;
- break;
- default:
- llvm_unreachable("unknown record type");
- }
- }
-}
-
+ addData(SymTab);
+
+ return std::move(Obj);
+}
+
+// Adds sections from IHEX data file. Data should have been
+// fully validated by this time.
+void IHexELFBuilder::addDataSections() {
+ OwnedDataSection *Section = nullptr;
+ uint64_t SegmentAddr = 0, BaseAddr = 0;
+ uint32_t SecNo = 1;
+
+ for (const IHexRecord &R : Records) {
+ uint64_t RecAddr;
+ switch (R.Type) {
+ case IHexRecord::Data:
+ // Ignore empty data records
+ if (R.HexData.empty())
+ continue;
+ RecAddr = R.Addr + SegmentAddr + BaseAddr;
+ if (!Section || Section->Addr + Section->Size != RecAddr)
+ // OriginalOffset field is only used to sort section properly, so
+ // instead of keeping track of real offset in IHEX file, we use
+ // section number.
+ Section = &Obj->addSection<OwnedDataSection>(
+ ".sec" + std::to_string(SecNo++), RecAddr,
+ ELF::SHF_ALLOC | ELF::SHF_WRITE, SecNo);
+ Section->appendHexData(R.HexData);
+ break;
+ case IHexRecord::EndOfFile:
+ break;
+ case IHexRecord::SegmentAddr:
+ // 20-bit segment address.
+ SegmentAddr = checkedGetHex<uint16_t>(R.HexData) << 4;
+ break;
+ case IHexRecord::StartAddr80x86:
+ case IHexRecord::StartAddr:
+ Obj->Entry = checkedGetHex<uint32_t>(R.HexData);
+ assert(Obj->Entry <= 0xFFFFFU);
+ break;
+ case IHexRecord::ExtendedAddr:
+ // 16-31 bits of linear base address
+ BaseAddr = checkedGetHex<uint16_t>(R.HexData) << 16;
+ break;
+ default:
+ llvm_unreachable("unknown record type");
+ }
+ }
+}
+
Expected<std::unique_ptr<Object>> IHexELFBuilder::build() {
- initFileHeader();
- initHeaderSegment();
- StringTableSection *StrTab = addStrTab();
- addSymTab(StrTab);
+ initFileHeader();
+ initHeaderSegment();
+ StringTableSection *StrTab = addStrTab();
+ addSymTab(StrTab);
if (Error Err = initSections())
return std::move(Err);
- addDataSections();
-
- return std::move(Obj);
-}
-
-template <class ELFT> void ELFBuilder<ELFT>::setParentSegment(Segment &Child) {
- for (Segment &Parent : Obj.segments()) {
- // Every segment will overlap with itself but we don't want a segment to
- // be its own parent so we avoid that situation.
- if (&Child != &Parent && segmentOverlapsSegment(Child, Parent)) {
- // We want a canonical "most parental" segment but this requires
- // inspecting the ParentSegment.
- if (compareSegmentsByOffset(&Parent, &Child))
- if (Child.ParentSegment == nullptr ||
- compareSegmentsByOffset(&Parent, Child.ParentSegment)) {
- Child.ParentSegment = &Parent;
- }
- }
- }
-}
-
+ addDataSections();
+
+ return std::move(Obj);
+}
+
+template <class ELFT> void ELFBuilder<ELFT>::setParentSegment(Segment &Child) {
+ for (Segment &Parent : Obj.segments()) {
+ // Every segment will overlap with itself but we don't want a segment to
+ // be its own parent so we avoid that situation.
+ if (&Child != &Parent && segmentOverlapsSegment(Child, Parent)) {
+ // We want a canonical "most parental" segment but this requires
+ // inspecting the ParentSegment.
+ if (compareSegmentsByOffset(&Parent, &Child))
+ if (Child.ParentSegment == nullptr ||
+ compareSegmentsByOffset(&Parent, Child.ParentSegment)) {
+ Child.ParentSegment = &Parent;
+ }
+ }
+ }
+}
+
template <class ELFT> Error ELFBuilder<ELFT>::findEhdrOffset() {
- if (!ExtractPartition)
+ if (!ExtractPartition)
return Error::success();
-
- for (const SectionBase &Sec : Obj.sections()) {
- if (Sec.Type == SHT_LLVM_PART_EHDR && Sec.Name == *ExtractPartition) {
- EhdrOffset = Sec.Offset;
+
+ for (const SectionBase &Sec : Obj.sections()) {
+ if (Sec.Type == SHT_LLVM_PART_EHDR && Sec.Name == *ExtractPartition) {
+ EhdrOffset = Sec.Offset;
return Error::success();
- }
- }
+ }
+ }
return createStringError(errc::invalid_argument,
"could not find partition named '" +
*ExtractPartition + "'");
-}
-
-template <class ELFT>
+}
+
+template <class ELFT>
Error ELFBuilder<ELFT>::readProgramHeaders(const ELFFile<ELFT> &HeadersFile) {
- uint32_t Index = 0;
+ uint32_t Index = 0;
Expected<typename ELFFile<ELFT>::Elf_Phdr_Range> Headers =
HeadersFile.program_headers();
@@ -1413,114 +1413,114 @@ Error ELFBuilder<ELFT>::readProgramHeaders(const ELFFile<ELFT> &HeadersFile) {
return Headers.takeError();
for (const typename ELFFile<ELFT>::Elf_Phdr &Phdr : *Headers) {
- if (Phdr.p_offset + Phdr.p_filesz > HeadersFile.getBufSize())
+ if (Phdr.p_offset + Phdr.p_filesz > HeadersFile.getBufSize())
return createStringError(
errc::invalid_argument,
"program header with offset 0x" + Twine::utohexstr(Phdr.p_offset) +
" and file size 0x" + Twine::utohexstr(Phdr.p_filesz) +
" goes past the end of the file");
-
- ArrayRef<uint8_t> Data{HeadersFile.base() + Phdr.p_offset,
- (size_t)Phdr.p_filesz};
- Segment &Seg = Obj.addSegment(Data);
- Seg.Type = Phdr.p_type;
- Seg.Flags = Phdr.p_flags;
- Seg.OriginalOffset = Phdr.p_offset + EhdrOffset;
- Seg.Offset = Phdr.p_offset + EhdrOffset;
- Seg.VAddr = Phdr.p_vaddr;
- Seg.PAddr = Phdr.p_paddr;
- Seg.FileSize = Phdr.p_filesz;
- Seg.MemSize = Phdr.p_memsz;
- Seg.Align = Phdr.p_align;
- Seg.Index = Index++;
- 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;
- ElfHdr.Index = Index++;
- ElfHdr.OriginalOffset = ElfHdr.Offset = EhdrOffset;
-
+
+ ArrayRef<uint8_t> Data{HeadersFile.base() + Phdr.p_offset,
+ (size_t)Phdr.p_filesz};
+ Segment &Seg = Obj.addSegment(Data);
+ Seg.Type = Phdr.p_type;
+ Seg.Flags = Phdr.p_flags;
+ Seg.OriginalOffset = Phdr.p_offset + EhdrOffset;
+ Seg.Offset = Phdr.p_offset + EhdrOffset;
+ Seg.VAddr = Phdr.p_vaddr;
+ Seg.PAddr = Phdr.p_paddr;
+ Seg.FileSize = Phdr.p_filesz;
+ Seg.MemSize = Phdr.p_memsz;
+ Seg.Align = Phdr.p_align;
+ Seg.Index = Index++;
+ 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;
+ ElfHdr.Index = Index++;
+ ElfHdr.OriginalOffset = ElfHdr.Offset = EhdrOffset;
+
const typename ELFT::Ehdr &Ehdr = HeadersFile.getHeader();
- auto &PrHdr = Obj.ProgramHdrSegment;
- PrHdr.Type = PT_PHDR;
- PrHdr.Flags = 0;
- // The spec requires us to have p_vaddr % p_align == p_offset % p_align.
- // Whereas this works automatically for ElfHdr, here OriginalOffset is
- // always non-zero and to ensure the equation we assign the same value to
- // VAddr as well.
- PrHdr.OriginalOffset = PrHdr.Offset = PrHdr.VAddr = EhdrOffset + Ehdr.e_phoff;
- PrHdr.PAddr = 0;
- PrHdr.FileSize = PrHdr.MemSize = Ehdr.e_phentsize * Ehdr.e_phnum;
- // The spec requires us to naturally align all the fields.
- PrHdr.Align = sizeof(Elf_Addr);
- PrHdr.Index = Index++;
-
- // Now we do an O(n^2) loop through the segments in order to match up
- // segments.
- for (Segment &Child : Obj.segments())
- setParentSegment(Child);
- setParentSegment(ElfHdr);
- setParentSegment(PrHdr);
+ auto &PrHdr = Obj.ProgramHdrSegment;
+ PrHdr.Type = PT_PHDR;
+ PrHdr.Flags = 0;
+ // The spec requires us to have p_vaddr % p_align == p_offset % p_align.
+ // Whereas this works automatically for ElfHdr, here OriginalOffset is
+ // always non-zero and to ensure the equation we assign the same value to
+ // VAddr as well.
+ PrHdr.OriginalOffset = PrHdr.Offset = PrHdr.VAddr = EhdrOffset + Ehdr.e_phoff;
+ PrHdr.PAddr = 0;
+ PrHdr.FileSize = PrHdr.MemSize = Ehdr.e_phentsize * Ehdr.e_phnum;
+ // The spec requires us to naturally align all the fields.
+ PrHdr.Align = sizeof(Elf_Addr);
+ PrHdr.Index = Index++;
+
+ // Now we do an O(n^2) loop through the segments in order to match up
+ // segments.
+ for (Segment &Child : Obj.segments())
+ setParentSegment(Child);
+ setParentSegment(ElfHdr);
+ setParentSegment(PrHdr);
return Error::success();
-}
-
-template <class ELFT>
+}
+
+template <class ELFT>
Error ELFBuilder<ELFT>::initGroupSection(GroupSection *GroupSec) {
- if (GroupSec->Align % sizeof(ELF::Elf32_Word) != 0)
+ if (GroupSec->Align % sizeof(ELF::Elf32_Word) != 0)
return createStringError(errc::invalid_argument,
"invalid alignment " + Twine(GroupSec->Align) +
" of group section '" + GroupSec->Name + "'");
- SectionTableRef SecTable = Obj.sections();
- if (GroupSec->Link != SHN_UNDEF) {
- auto SymTab = SecTable.template getSectionOfType<SymbolTableSection>(
- GroupSec->Link,
- "link field value '" + Twine(GroupSec->Link) + "' in section '" +
- GroupSec->Name + "' is invalid",
- "link field value '" + Twine(GroupSec->Link) + "' in section '" +
- GroupSec->Name + "' is not a symbol table");
+ SectionTableRef SecTable = Obj.sections();
+ if (GroupSec->Link != SHN_UNDEF) {
+ auto SymTab = SecTable.template getSectionOfType<SymbolTableSection>(
+ GroupSec->Link,
+ "link field value '" + Twine(GroupSec->Link) + "' in section '" +
+ GroupSec->Name + "' is invalid",
+ "link field value '" + Twine(GroupSec->Link) + "' in section '" +
+ GroupSec->Name + "' is not a symbol table");
if (!SymTab)
return SymTab.takeError();
Expected<Symbol *> Sym = (*SymTab)->getSymbolByIndex(GroupSec->Info);
- if (!Sym)
+ if (!Sym)
return createStringError(errc::invalid_argument,
"info field value '" + Twine(GroupSec->Info) +
"' in section '" + GroupSec->Name +
"' is not a valid symbol index");
GroupSec->setSymTab(*SymTab);
GroupSec->setSymbol(*Sym);
- }
- if (GroupSec->Contents.size() % sizeof(ELF::Elf32_Word) ||
- GroupSec->Contents.empty())
+ }
+ if (GroupSec->Contents.size() % sizeof(ELF::Elf32_Word) ||
+ GroupSec->Contents.empty())
return createStringError(errc::invalid_argument,
"the content of the section " + GroupSec->Name +
" is malformed");
- const ELF::Elf32_Word *Word =
- reinterpret_cast<const ELF::Elf32_Word *>(GroupSec->Contents.data());
- const ELF::Elf32_Word *End =
- Word + GroupSec->Contents.size() / sizeof(ELF::Elf32_Word);
- GroupSec->setFlagWord(*Word++);
- for (; Word != End; ++Word) {
- uint32_t Index = support::endian::read32<ELFT::TargetEndianness>(Word);
+ const ELF::Elf32_Word *Word =
+ reinterpret_cast<const ELF::Elf32_Word *>(GroupSec->Contents.data());
+ const ELF::Elf32_Word *End =
+ Word + GroupSec->Contents.size() / sizeof(ELF::Elf32_Word);
+ GroupSec->setFlagWord(*Word++);
+ for (; Word != End; ++Word) {
+ uint32_t Index = support::endian::read32<ELFT::TargetEndianness>(Word);
Expected<SectionBase *> Sec = SecTable.getSection(
- Index, "group member index " + Twine(Index) + " in section '" +
+ Index, "group member index " + Twine(Index) + " in section '" +
GroupSec->Name + "' is invalid");
if (!Sec)
return Sec.takeError();
GroupSec->addMember(*Sec);
- }
+ }
return Error::success();
-}
-
-template <class ELFT>
+}
+
+template <class ELFT>
Error ELFBuilder<ELFT>::initSymbolTable(SymbolTableSection *SymTab) {
Expected<const Elf_Shdr *> Shdr = ElfFile.getSection(SymTab->Index);
if (!Shdr)
@@ -1530,27 +1530,27 @@ Error ELFBuilder<ELFT>::initSymbolTable(SymbolTableSection *SymTab) {
if (!StrTabData)
return StrTabData.takeError();
- ArrayRef<Elf_Word> ShndxData;
-
+ ArrayRef<Elf_Word> ShndxData;
+
Expected<typename ELFFile<ELFT>::Elf_Sym_Range> Symbols =
ElfFile.symbols(*Shdr);
if (!Symbols)
return Symbols.takeError();
for (const typename ELFFile<ELFT>::Elf_Sym &Sym : *Symbols) {
- SectionBase *DefSection = nullptr;
-
+ SectionBase *DefSection = nullptr;
+
Expected<StringRef> Name = Sym.getName(*StrTabData);
if (!Name)
return Name.takeError();
- if (Sym.st_shndx == SHN_XINDEX) {
- if (SymTab->getShndxTable() == nullptr)
+ if (Sym.st_shndx == SHN_XINDEX) {
+ if (SymTab->getShndxTable() == nullptr)
return createStringError(errc::invalid_argument,
"symbol '" + *Name +
"' has index SHN_XINDEX but no "
"SHT_SYMTAB_SHNDX section exists");
- if (ShndxData.data() == nullptr) {
+ if (ShndxData.data() == nullptr) {
Expected<const Elf_Shdr *> ShndxSec =
ElfFile.getSection(SymTab->getShndxTable()->Index);
if (!ShndxSec)
@@ -1567,61 +1567,61 @@ Error ELFBuilder<ELFT>::initSymbolTable(SymbolTableSection *SymTab) {
errc::invalid_argument,
"symbol section index table does not have the same number of "
"entries as the symbol table");
- }
+ }
Elf_Word Index = ShndxData[&Sym - Symbols->begin()];
Expected<SectionBase *> Sec = Obj.sections().getSection(
- Index,
+ Index,
"symbol '" + *Name + "' has invalid section index " + Twine(Index));
if (!Sec)
return Sec.takeError();
DefSection = *Sec;
- } else if (Sym.st_shndx >= SHN_LORESERVE) {
- if (!isValidReservedSectionIndex(Sym.st_shndx, Obj.Machine)) {
+ } else if (Sym.st_shndx >= SHN_LORESERVE) {
+ if (!isValidReservedSectionIndex(Sym.st_shndx, Obj.Machine)) {
return createStringError(
errc::invalid_argument,
"symbol '" + *Name +
"' has unsupported value greater than or equal "
"to SHN_LORESERVE: " +
Twine(Sym.st_shndx));
- }
- } else if (Sym.st_shndx != SHN_UNDEF) {
+ }
+ } else if (Sym.st_shndx != SHN_UNDEF) {
Expected<SectionBase *> Sec = Obj.sections().getSection(
Sym.st_shndx, "symbol '" + *Name +
- "' is defined has invalid section index " +
- Twine(Sym.st_shndx));
+ "' is defined has invalid section index " +
+ Twine(Sym.st_shndx));
if (!Sec)
return Sec.takeError();
DefSection = *Sec;
- }
-
+ }
+
SymTab->addSymbol(*Name, Sym.getBinding(), Sym.getType(), DefSection,
- Sym.getValue(), Sym.st_other, Sym.st_shndx, Sym.st_size);
- }
+ Sym.getValue(), Sym.st_other, Sym.st_shndx, Sym.st_size);
+ }
return Error::success();
-}
-
-template <class ELFT>
+}
+
+template <class ELFT>
static void getAddend(uint64_t &, const Elf_Rel_Impl<ELFT, false> &) {}
-
-template <class ELFT>
-static void getAddend(uint64_t &ToSet, const Elf_Rel_Impl<ELFT, true> &Rela) {
- ToSet = Rela.r_addend;
-}
-
-template <class T>
+
+template <class ELFT>
+static void getAddend(uint64_t &ToSet, const Elf_Rel_Impl<ELFT, true> &Rela) {
+ ToSet = Rela.r_addend;
+}
+
+template <class T>
static Error initRelocations(RelocationSection *Relocs,
SymbolTableSection *SymbolTable, T RelRange) {
- for (const auto &Rel : RelRange) {
- Relocation ToAdd;
- ToAdd.Offset = Rel.r_offset;
- getAddend(ToAdd.Addend, Rel);
- ToAdd.Type = Rel.getType(false);
-
- if (uint32_t Sym = Rel.getSymbol(false)) {
- if (!SymbolTable)
+ for (const auto &Rel : RelRange) {
+ Relocation ToAdd;
+ ToAdd.Offset = Rel.r_offset;
+ getAddend(ToAdd.Addend, Rel);
+ ToAdd.Type = Rel.getType(false);
+
+ if (uint32_t Sym = Rel.getSymbol(false)) {
+ if (!SymbolTable)
return createStringError(
errc::invalid_argument,
"'" + Relocs->Name + "': relocation references symbol with index " +
@@ -1631,22 +1631,22 @@ static Error initRelocations(RelocationSection *Relocs,
return SymByIndex.takeError();
ToAdd.RelocSymbol = *SymByIndex;
- }
-
- Relocs->addRelocation(ToAdd);
- }
+ }
+
+ Relocs->addRelocation(ToAdd);
+ }
return Error::success();
-}
-
+}
+
Expected<SectionBase *> SectionTableRef::getSection(uint32_t Index,
Twine ErrMsg) {
- if (Index == SHN_UNDEF || Index > Sections.size())
+ if (Index == SHN_UNDEF || Index > Sections.size())
return createStringError(errc::invalid_argument, ErrMsg);
- return Sections[Index - 1].get();
-}
-
-template <class T>
+ return Sections[Index - 1].get();
+}
+
+template <class T>
Expected<T *> SectionTableRef::getSectionOfType(uint32_t Index,
Twine IndexErrMsg,
Twine TypeErrMsg) {
@@ -1655,81 +1655,81 @@ Expected<T *> SectionTableRef::getSectionOfType(uint32_t Index,
return BaseSec.takeError();
if (T *Sec = dyn_cast<T>(*BaseSec))
- return Sec;
+ return Sec;
return createStringError(errc::invalid_argument, TypeErrMsg);
-}
-
-template <class ELFT>
+}
+
+template <class ELFT>
Expected<SectionBase &> ELFBuilder<ELFT>::makeSection(const Elf_Shdr &Shdr) {
- switch (Shdr.sh_type) {
- case SHT_REL:
- case SHT_RELA:
- if (Shdr.sh_flags & SHF_ALLOC) {
+ switch (Shdr.sh_type) {
+ case SHT_REL:
+ case SHT_RELA:
+ if (Shdr.sh_flags & SHF_ALLOC) {
if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
return Obj.addSection<DynamicRelocationSection>(*Data);
else
return Data.takeError();
- }
- return Obj.addSection<RelocationSection>();
- case SHT_STRTAB:
- // If a string table is allocated we don't want to mess with it. That would
- // mean altering the memory image. There are no special link types or
- // anything so we can just use a Section.
- if (Shdr.sh_flags & SHF_ALLOC) {
+ }
+ return Obj.addSection<RelocationSection>();
+ case SHT_STRTAB:
+ // If a string table is allocated we don't want to mess with it. That would
+ // mean altering the memory image. There are no special link types or
+ // anything so we can just use a Section.
+ if (Shdr.sh_flags & SHF_ALLOC) {
if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
return Obj.addSection<Section>(*Data);
else
return Data.takeError();
- }
- return Obj.addSection<StringTableSection>();
- case SHT_HASH:
- case SHT_GNU_HASH:
- // Hash tables should refer to SHT_DYNSYM which we're not going to change.
- // Because of this we don't need to mess with the hash tables either.
+ }
+ return Obj.addSection<StringTableSection>();
+ case SHT_HASH:
+ case SHT_GNU_HASH:
+ // Hash tables should refer to SHT_DYNSYM which we're not going to change.
+ // Because of this we don't need to mess with the hash tables either.
if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
return Obj.addSection<Section>(*Data);
else
return Data.takeError();
- case SHT_GROUP:
+ case SHT_GROUP:
if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
return Obj.addSection<GroupSection>(*Data);
else
return Data.takeError();
- case SHT_DYNSYM:
+ case SHT_DYNSYM:
if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
return Obj.addSection<DynamicSymbolTableSection>(*Data);
else
return Data.takeError();
- case SHT_DYNAMIC:
+ case SHT_DYNAMIC:
if (Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr))
return Obj.addSection<DynamicSection>(*Data);
else
return Data.takeError();
- case SHT_SYMTAB: {
- auto &SymTab = Obj.addSection<SymbolTableSection>();
- Obj.SymbolTable = &SymTab;
- return SymTab;
- }
- case SHT_SYMTAB_SHNDX: {
- auto &ShndxSection = Obj.addSection<SectionIndexSection>();
- Obj.SectionIndexTable = &ShndxSection;
- return ShndxSection;
- }
- case SHT_NOBITS:
+ case SHT_SYMTAB: {
+ auto &SymTab = Obj.addSection<SymbolTableSection>();
+ Obj.SymbolTable = &SymTab;
+ return SymTab;
+ }
+ case SHT_SYMTAB_SHNDX: {
+ auto &ShndxSection = Obj.addSection<SectionIndexSection>();
+ Obj.SectionIndexTable = &ShndxSection;
+ return ShndxSection;
+ }
+ case SHT_NOBITS:
return Obj.addSection<Section>(ArrayRef<uint8_t>());
- default: {
+ default: {
Expected<ArrayRef<uint8_t>> Data = ElfFile.getSectionContents(Shdr);
if (!Data)
return Data.takeError();
-
+
Expected<StringRef> Name = ElfFile.getSectionName(Shdr);
if (!Name)
return Name.takeError();
if (Name->startswith(".zdebug") || (Shdr.sh_flags & ELF::SHF_COMPRESSED)) {
- uint64_t DecompressedSize, DecompressedAlign;
- std::tie(DecompressedSize, DecompressedAlign) =
+ uint64_t DecompressedSize, DecompressedAlign;
+ std::tie(DecompressedSize, DecompressedAlign) =
getDecompressedSizeAndAlignment<ELFT>(*Data);
Expected<CompressedSection> NewSection =
CompressedSection::create(*Data, DecompressedSize, DecompressedAlign);
@@ -1737,25 +1737,25 @@ Expected<SectionBase &> ELFBuilder<ELFT>::makeSection(const Elf_Shdr &Shdr) {
return NewSection.takeError();
return Obj.addSection<CompressedSection>(std::move(*NewSection));
- }
-
+ }
+
return Obj.addSection<Section>(*Data);
- }
- }
-}
-
+ }
+ }
+}
+
template <class ELFT> Error ELFBuilder<ELFT>::readSectionHeaders() {
- uint32_t Index = 0;
+ uint32_t Index = 0;
Expected<typename ELFFile<ELFT>::Elf_Shdr_Range> Sections =
ElfFile.sections();
if (!Sections)
return Sections.takeError();
for (const typename ELFFile<ELFT>::Elf_Shdr &Shdr : *Sections) {
- if (Index == 0) {
- ++Index;
- continue;
- }
+ if (Index == 0) {
+ ++Index;
+ continue;
+ }
Expected<SectionBase &> Sec = makeSection(Shdr);
if (!Sec)
return Sec.takeError();
@@ -1777,68 +1777,68 @@ template <class ELFT> Error ELFBuilder<ELFT>::readSectionHeaders() {
Sec->Index = Index++;
Sec->OriginalIndex = Sec->Index;
Sec->OriginalData =
- ArrayRef<uint8_t>(ElfFile.base() + Shdr.sh_offset,
- (Shdr.sh_type == SHT_NOBITS) ? 0 : Shdr.sh_size);
- }
+ ArrayRef<uint8_t>(ElfFile.base() + Shdr.sh_offset,
+ (Shdr.sh_type == SHT_NOBITS) ? 0 : Shdr.sh_size);
+ }
return Error::success();
-}
-
+}
+
template <class ELFT> Error ELFBuilder<ELFT>::readSections(bool EnsureSymtab) {
uint32_t ShstrIndex = ElfFile.getHeader().e_shstrndx;
if (ShstrIndex == SHN_XINDEX) {
Expected<const Elf_Shdr *> Sec = ElfFile.getSection(0);
if (!Sec)
return Sec.takeError();
-
+
ShstrIndex = (*Sec)->sh_link;
}
- if (ShstrIndex == SHN_UNDEF)
- Obj.HadShdrs = false;
+ if (ShstrIndex == SHN_UNDEF)
+ Obj.HadShdrs = false;
else {
Expected<StringTableSection *> Sec =
- Obj.sections().template getSectionOfType<StringTableSection>(
- ShstrIndex,
- "e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " +
- " is invalid",
- "e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " +
- " does not reference a string table");
+ Obj.sections().template getSectionOfType<StringTableSection>(
+ ShstrIndex,
+ "e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " +
+ " is invalid",
+ "e_shstrndx field value " + Twine(ShstrIndex) + " in elf header " +
+ " does not reference a string table");
if (!Sec)
return Sec.takeError();
-
+
Obj.SectionNames = *Sec;
}
- // 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.
- if (Obj.SectionIndexTable)
+ // 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.
+ if (Obj.SectionIndexTable)
if (Error Err = Obj.SectionIndexTable->initialize(Obj.sections()))
return Err;
-
- // Now that all of the sections have been added we can fill out some extra
- // details about symbol tables. We need the symbol table filled out before
- // any relocations.
- if (Obj.SymbolTable) {
+
+ // Now that all of the sections have been added we can fill out some extra
+ // details about symbol tables. We need the symbol table filled out before
+ // any relocations.
+ if (Obj.SymbolTable) {
if (Error Err = Obj.SymbolTable->initialize(Obj.sections()))
return Err;
if (Error Err = initSymbolTable(Obj.SymbolTable))
return Err;
- } else if (EnsureSymtab) {
+ } else if (EnsureSymtab) {
if (Error Err = Obj.addNewSymbolTable())
return Err;
- }
-
- // 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.
+ }
+
+ // 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 (SectionBase &Sec : Obj.sections()) {
- if (&Sec == Obj.SymbolTable)
- continue;
+ if (&Sec == Obj.SymbolTable)
+ continue;
if (Error Err = Sec.initialize(Obj.sections()))
return Err;
- if (auto RelSec = dyn_cast<RelocationSection>(&Sec)) {
+ if (auto RelSec = dyn_cast<RelocationSection>(&Sec)) {
Expected<typename ELFFile<ELFT>::Elf_Shdr_Range> Sections =
ElfFile.sections();
if (!Sections)
@@ -1863,78 +1863,78 @@ template <class ELFT> Error ELFBuilder<ELFT>::readSections(bool EnsureSymtab) {
if (Error Err = initRelocations(RelSec, Obj.SymbolTable, *Relas))
return Err;
}
- } else if (auto GroupSec = dyn_cast<GroupSection>(&Sec)) {
+ } else if (auto GroupSec = dyn_cast<GroupSection>(&Sec)) {
if (Error Err = initGroupSection(GroupSec))
return Err;
- }
- }
+ }
+ }
return Error::success();
-}
-
+}
+
template <class ELFT> Error ELFBuilder<ELFT>::build(bool EnsureSymtab) {
if (Error E = readSectionHeaders())
return E;
if (Error E = findEhdrOffset())
return E;
-
- // The ELFFile whose ELF headers and program headers are copied into the
- // output file. Normally the same as ElfFile, but if we're extracting a
- // loadable partition it will point to the partition's headers.
+
+ // The ELFFile whose ELF headers and program headers are copied into the
+ // output file. Normally the same as ElfFile, but if we're extracting a
+ // loadable partition it will point to the partition's headers.
Expected<ELFFile<ELFT>> HeadersFile = ELFFile<ELFT>::create(toStringRef(
{ElfFile.base() + EhdrOffset, ElfFile.getBufSize() - EhdrOffset}));
if (!HeadersFile)
return HeadersFile.takeError();
-
+
const typename ELFFile<ELFT>::Elf_Ehdr &Ehdr = HeadersFile->getHeader();
- Obj.OSABI = Ehdr.e_ident[EI_OSABI];
- Obj.ABIVersion = Ehdr.e_ident[EI_ABIVERSION];
- Obj.Type = Ehdr.e_type;
- Obj.Machine = Ehdr.e_machine;
- Obj.Version = Ehdr.e_version;
- Obj.Entry = Ehdr.e_entry;
- Obj.Flags = Ehdr.e_flags;
-
+ Obj.OSABI = Ehdr.e_ident[EI_OSABI];
+ Obj.ABIVersion = Ehdr.e_ident[EI_ABIVERSION];
+ Obj.Type = Ehdr.e_type;
+ Obj.Machine = Ehdr.e_machine;
+ Obj.Version = Ehdr.e_version;
+ Obj.Entry = Ehdr.e_entry;
+ Obj.Flags = Ehdr.e_flags;
+
if (Error E = readSections(EnsureSymtab))
return E;
return readProgramHeaders(*HeadersFile);
-}
-
-Writer::~Writer() {}
-
-Reader::~Reader() {}
-
+}
+
+Writer::~Writer() {}
+
+Reader::~Reader() {}
+
Expected<std::unique_ptr<Object>>
BinaryReader::create(bool /*EnsureSymtab*/) const {
- return BinaryELFBuilder(MemBuf, NewSymbolVisibility).build();
-}
-
-Expected<std::vector<IHexRecord>> IHexReader::parse() const {
- SmallVector<StringRef, 16> Lines;
- std::vector<IHexRecord> Records;
- bool HasSections = false;
-
- MemBuf->getBuffer().split(Lines, '\n');
- Records.reserve(Lines.size());
- for (size_t LineNo = 1; LineNo <= Lines.size(); ++LineNo) {
- StringRef Line = Lines[LineNo - 1].trim();
- if (Line.empty())
- continue;
-
- Expected<IHexRecord> R = IHexRecord::parse(Line);
- if (!R)
- return parseError(LineNo, R.takeError());
- if (R->Type == IHexRecord::EndOfFile)
- break;
- HasSections |= (R->Type == IHexRecord::Data);
- Records.push_back(*R);
- }
- if (!HasSections)
- return parseError(-1U, "no sections");
-
- return std::move(Records);
-}
-
+ return BinaryELFBuilder(MemBuf, NewSymbolVisibility).build();
+}
+
+Expected<std::vector<IHexRecord>> IHexReader::parse() const {
+ SmallVector<StringRef, 16> Lines;
+ std::vector<IHexRecord> Records;
+ bool HasSections = false;
+
+ MemBuf->getBuffer().split(Lines, '\n');
+ Records.reserve(Lines.size());
+ for (size_t LineNo = 1; LineNo <= Lines.size(); ++LineNo) {
+ StringRef Line = Lines[LineNo - 1].trim();
+ if (Line.empty())
+ continue;
+
+ Expected<IHexRecord> R = IHexRecord::parse(Line);
+ if (!R)
+ return parseError(LineNo, R.takeError());
+ if (R->Type == IHexRecord::EndOfFile)
+ break;
+ HasSections |= (R->Type == IHexRecord::Data);
+ Records.push_back(*R);
+ }
+ if (!HasSections)
+ return parseError(-1U, "no sections");
+
+ return std::move(Records);
+}
+
Expected<std::unique_ptr<Object>>
IHexReader::create(bool /*EnsureSymtab*/) const {
Expected<std::vector<IHexRecord>> Records = parse();
@@ -1942,375 +1942,375 @@ IHexReader::create(bool /*EnsureSymtab*/) const {
return Records.takeError();
return IHexELFBuilder(*Records).build();
-}
-
+}
+
Expected<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);
+ auto Obj = std::make_unique<Object>();
+ if (auto *O = dyn_cast<ELFObjectFile<ELF32LE>>(Bin)) {
+ ELFBuilder<ELF32LE> Builder(*O, *Obj, ExtractPartition);
if (Error Err = Builder.build(EnsureSymtab))
return std::move(Err);
return std::move(Obj);
- } else if (auto *O = dyn_cast<ELFObjectFile<ELF64LE>>(Bin)) {
- ELFBuilder<ELF64LE> Builder(*O, *Obj, ExtractPartition);
+ } else if (auto *O = dyn_cast<ELFObjectFile<ELF64LE>>(Bin)) {
+ ELFBuilder<ELF64LE> Builder(*O, *Obj, ExtractPartition);
if (Error Err = Builder.build(EnsureSymtab))
return std::move(Err);
return std::move(Obj);
- } else if (auto *O = dyn_cast<ELFObjectFile<ELF32BE>>(Bin)) {
- ELFBuilder<ELF32BE> Builder(*O, *Obj, ExtractPartition);
+ } else if (auto *O = dyn_cast<ELFObjectFile<ELF32BE>>(Bin)) {
+ ELFBuilder<ELF32BE> Builder(*O, *Obj, ExtractPartition);
if (Error Err = Builder.build(EnsureSymtab))
return std::move(Err);
return std::move(Obj);
- } else if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(Bin)) {
- ELFBuilder<ELF64BE> Builder(*O, *Obj, ExtractPartition);
+ } else if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(Bin)) {
+ ELFBuilder<ELF64BE> Builder(*O, *Obj, ExtractPartition);
if (Error Err = Builder.build(EnsureSymtab))
return std::move(Err);
return std::move(Obj);
- }
+ }
return createStringError(errc::invalid_argument, "invalid file type");
-}
-
-template <class ELFT> void ELFWriter<ELFT>::writeEhdr() {
- Elf_Ehdr &Ehdr = *reinterpret_cast<Elf_Ehdr *>(Buf.getBufferStart());
- std::fill(Ehdr.e_ident, Ehdr.e_ident + 16, 0);
- Ehdr.e_ident[EI_MAG0] = 0x7f;
- Ehdr.e_ident[EI_MAG1] = 'E';
- Ehdr.e_ident[EI_MAG2] = 'L';
- Ehdr.e_ident[EI_MAG3] = 'F';
- Ehdr.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
- Ehdr.e_ident[EI_DATA] =
- ELFT::TargetEndianness == support::big ? ELFDATA2MSB : ELFDATA2LSB;
- Ehdr.e_ident[EI_VERSION] = EV_CURRENT;
- Ehdr.e_ident[EI_OSABI] = Obj.OSABI;
- Ehdr.e_ident[EI_ABIVERSION] = Obj.ABIVersion;
-
- Ehdr.e_type = Obj.Type;
- Ehdr.e_machine = Obj.Machine;
- Ehdr.e_version = Obj.Version;
- Ehdr.e_entry = Obj.Entry;
- // We have to use the fully-qualified name llvm::size
- // since some compilers complain on ambiguous resolution.
- Ehdr.e_phnum = llvm::size(Obj.segments());
- Ehdr.e_phoff = (Ehdr.e_phnum != 0) ? Obj.ProgramHdrSegment.Offset : 0;
- Ehdr.e_phentsize = (Ehdr.e_phnum != 0) ? sizeof(Elf_Phdr) : 0;
- Ehdr.e_flags = Obj.Flags;
- Ehdr.e_ehsize = sizeof(Elf_Ehdr);
- if (WriteSectionHeaders && Obj.sections().size() != 0) {
- Ehdr.e_shentsize = sizeof(Elf_Shdr);
- 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
- // number of section header table entries is contained in the sh_size field
- // of the section header at index 0.
- // """
- auto Shnum = Obj.sections().size() + 1;
- if (Shnum >= SHN_LORESERVE)
- Ehdr.e_shnum = 0;
- else
- Ehdr.e_shnum = Shnum;
- // """
- // If the section name string table section index is greater than or equal
- // to SHN_LORESERVE (0xff00), this member has the value SHN_XINDEX (0xffff)
- // and the actual index of the section name string table section is
- // contained in the sh_link field of the section header at index 0.
- // """
- if (Obj.SectionNames->Index >= SHN_LORESERVE)
- Ehdr.e_shstrndx = SHN_XINDEX;
- else
- Ehdr.e_shstrndx = Obj.SectionNames->Index;
- } else {
- Ehdr.e_shentsize = 0;
- Ehdr.e_shoff = 0;
- Ehdr.e_shnum = 0;
- Ehdr.e_shstrndx = 0;
- }
-}
-
-template <class ELFT> void ELFWriter<ELFT>::writePhdrs() {
- for (auto &Seg : Obj.segments())
- writePhdr(Seg);
-}
-
-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.SHOff);
- Shdr.sh_name = 0;
- Shdr.sh_type = SHT_NULL;
- Shdr.sh_flags = 0;
- Shdr.sh_addr = 0;
- Shdr.sh_offset = 0;
- // See writeEhdr for why we do this.
- uint64_t Shnum = Obj.sections().size() + 1;
- if (Shnum >= SHN_LORESERVE)
- Shdr.sh_size = Shnum;
- else
- Shdr.sh_size = 0;
- // See writeEhdr for why we do this.
- if (Obj.SectionNames != nullptr && Obj.SectionNames->Index >= SHN_LORESERVE)
- Shdr.sh_link = Obj.SectionNames->Index;
- else
- Shdr.sh_link = 0;
- Shdr.sh_info = 0;
- Shdr.sh_addralign = 0;
- Shdr.sh_entsize = 0;
-
- for (SectionBase &Sec : Obj.sections())
- writeShdr(Sec);
-}
-
+}
+
+template <class ELFT> void ELFWriter<ELFT>::writeEhdr() {
+ Elf_Ehdr &Ehdr = *reinterpret_cast<Elf_Ehdr *>(Buf.getBufferStart());
+ std::fill(Ehdr.e_ident, Ehdr.e_ident + 16, 0);
+ Ehdr.e_ident[EI_MAG0] = 0x7f;
+ Ehdr.e_ident[EI_MAG1] = 'E';
+ Ehdr.e_ident[EI_MAG2] = 'L';
+ Ehdr.e_ident[EI_MAG3] = 'F';
+ Ehdr.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
+ Ehdr.e_ident[EI_DATA] =
+ ELFT::TargetEndianness == support::big ? ELFDATA2MSB : ELFDATA2LSB;
+ Ehdr.e_ident[EI_VERSION] = EV_CURRENT;
+ Ehdr.e_ident[EI_OSABI] = Obj.OSABI;
+ Ehdr.e_ident[EI_ABIVERSION] = Obj.ABIVersion;
+
+ Ehdr.e_type = Obj.Type;
+ Ehdr.e_machine = Obj.Machine;
+ Ehdr.e_version = Obj.Version;
+ Ehdr.e_entry = Obj.Entry;
+ // We have to use the fully-qualified name llvm::size
+ // since some compilers complain on ambiguous resolution.
+ Ehdr.e_phnum = llvm::size(Obj.segments());
+ Ehdr.e_phoff = (Ehdr.e_phnum != 0) ? Obj.ProgramHdrSegment.Offset : 0;
+ Ehdr.e_phentsize = (Ehdr.e_phnum != 0) ? sizeof(Elf_Phdr) : 0;
+ Ehdr.e_flags = Obj.Flags;
+ Ehdr.e_ehsize = sizeof(Elf_Ehdr);
+ if (WriteSectionHeaders && Obj.sections().size() != 0) {
+ Ehdr.e_shentsize = sizeof(Elf_Shdr);
+ 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
+ // number of section header table entries is contained in the sh_size field
+ // of the section header at index 0.
+ // """
+ auto Shnum = Obj.sections().size() + 1;
+ if (Shnum >= SHN_LORESERVE)
+ Ehdr.e_shnum = 0;
+ else
+ Ehdr.e_shnum = Shnum;
+ // """
+ // If the section name string table section index is greater than or equal
+ // to SHN_LORESERVE (0xff00), this member has the value SHN_XINDEX (0xffff)
+ // and the actual index of the section name string table section is
+ // contained in the sh_link field of the section header at index 0.
+ // """
+ if (Obj.SectionNames->Index >= SHN_LORESERVE)
+ Ehdr.e_shstrndx = SHN_XINDEX;
+ else
+ Ehdr.e_shstrndx = Obj.SectionNames->Index;
+ } else {
+ Ehdr.e_shentsize = 0;
+ Ehdr.e_shoff = 0;
+ Ehdr.e_shnum = 0;
+ Ehdr.e_shstrndx = 0;
+ }
+}
+
+template <class ELFT> void ELFWriter<ELFT>::writePhdrs() {
+ for (auto &Seg : Obj.segments())
+ writePhdr(Seg);
+}
+
+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.SHOff);
+ Shdr.sh_name = 0;
+ Shdr.sh_type = SHT_NULL;
+ Shdr.sh_flags = 0;
+ Shdr.sh_addr = 0;
+ Shdr.sh_offset = 0;
+ // See writeEhdr for why we do this.
+ uint64_t Shnum = Obj.sections().size() + 1;
+ if (Shnum >= SHN_LORESERVE)
+ Shdr.sh_size = Shnum;
+ else
+ Shdr.sh_size = 0;
+ // See writeEhdr for why we do this.
+ if (Obj.SectionNames != nullptr && Obj.SectionNames->Index >= SHN_LORESERVE)
+ Shdr.sh_link = Obj.SectionNames->Index;
+ else
+ Shdr.sh_link = 0;
+ Shdr.sh_info = 0;
+ Shdr.sh_addralign = 0;
+ Shdr.sh_entsize = 0;
+
+ for (SectionBase &Sec : Obj.sections())
+ writeShdr(Sec);
+}
+
template <class ELFT> Error ELFWriter<ELFT>::writeSectionData() {
- for (SectionBase &Sec : Obj.sections())
- // Segments are responsible for writing their contents, so only write the
- // section data if the section is not in a segment. Note that this renders
- // sections in segments effectively immutable.
- if (Sec.ParentSegment == nullptr)
+ for (SectionBase &Sec : Obj.sections())
+ // Segments are responsible for writing their contents, so only write the
+ // section data if the section is not in a segment. Note that this renders
+ // sections in segments effectively immutable.
+ if (Sec.ParentSegment == nullptr)
if (Error Err = Sec.accept(*SecWriter))
return Err;
return Error::success();
-}
-
-template <class ELFT> void ELFWriter<ELFT>::writeSegmentData() {
- for (Segment &Seg : Obj.segments()) {
- size_t Size = std::min<size_t>(Seg.FileSize, Seg.getContents().size());
- std::memcpy(Buf.getBufferStart() + Seg.Offset, Seg.getContents().data(),
- Size);
- }
-
- // Iterate over removed sections and overwrite their old data with zeroes.
- for (auto &Sec : Obj.removedSections()) {
- Segment *Parent = Sec.ParentSegment;
- if (Parent == nullptr || Sec.Type == SHT_NOBITS || Sec.Size == 0)
- continue;
- uint64_t Offset =
- Sec.OriginalOffset - Parent->OriginalOffset + Parent->Offset;
- std::memset(Buf.getBufferStart() + Offset, 0, Sec.Size);
- }
-}
-
-template <class ELFT>
-ELFWriter<ELFT>::ELFWriter(Object &Obj, Buffer &Buf, bool WSH,
- bool OnlyKeepDebug)
- : Writer(Obj, Buf), WriteSectionHeaders(WSH && Obj.HadShdrs),
- OnlyKeepDebug(OnlyKeepDebug) {}
-
+}
+
+template <class ELFT> void ELFWriter<ELFT>::writeSegmentData() {
+ for (Segment &Seg : Obj.segments()) {
+ size_t Size = std::min<size_t>(Seg.FileSize, Seg.getContents().size());
+ std::memcpy(Buf.getBufferStart() + Seg.Offset, Seg.getContents().data(),
+ Size);
+ }
+
+ // Iterate over removed sections and overwrite their old data with zeroes.
+ for (auto &Sec : Obj.removedSections()) {
+ Segment *Parent = Sec.ParentSegment;
+ if (Parent == nullptr || Sec.Type == SHT_NOBITS || Sec.Size == 0)
+ continue;
+ uint64_t Offset =
+ Sec.OriginalOffset - Parent->OriginalOffset + Parent->Offset;
+ std::memset(Buf.getBufferStart() + Offset, 0, Sec.Size);
+ }
+}
+
+template <class ELFT>
+ELFWriter<ELFT>::ELFWriter(Object &Obj, Buffer &Buf, bool WSH,
+ bool OnlyKeepDebug)
+ : Writer(Obj, Buf), WriteSectionHeaders(WSH && Obj.HadShdrs),
+ OnlyKeepDebug(OnlyKeepDebug) {}
+
Error Object::removeSections(
bool AllowBrokenLinks, std::function<bool(const SectionBase &)> ToRemove) {
-
- auto Iter = std::stable_partition(
- std::begin(Sections), std::end(Sections), [=](const SecPtr &Sec) {
- if (ToRemove(*Sec))
- return false;
- if (auto RelSec = dyn_cast<RelocationSectionBase>(Sec.get())) {
- if (auto ToRelSec = RelSec->getSection())
- return !ToRemove(*ToRelSec);
- }
- return true;
- });
- if (SymbolTable != nullptr && ToRemove(*SymbolTable))
- SymbolTable = nullptr;
- if (SectionNames != nullptr && ToRemove(*SectionNames))
- SectionNames = nullptr;
- if (SectionIndexTable != nullptr && ToRemove(*SectionIndexTable))
- SectionIndexTable = nullptr;
- // Now make sure there are no remaining references to the sections that will
- // be removed. Sometimes it is impossible to remove a reference so we emit
- // an error here instead.
- std::unordered_set<const SectionBase *> RemoveSections;
- RemoveSections.reserve(std::distance(Iter, std::end(Sections)));
- for (auto &RemoveSec : make_range(Iter, std::end(Sections))) {
- for (auto &Segment : Segments)
- Segment->removeSection(RemoveSec.get());
- RemoveSec->onRemove();
- RemoveSections.insert(RemoveSec.get());
- }
-
- // For each section that remains alive, we want to remove the dead references.
- // This either might update the content of the section (e.g. remove symbols
- // from symbol table that belongs to removed section) or trigger an error if
- // a live section critically depends on a section being removed somehow
- // (e.g. the removed section is referenced by a relocation).
- for (auto &KeepSec : make_range(std::begin(Sections), Iter)) {
+
+ auto Iter = std::stable_partition(
+ std::begin(Sections), std::end(Sections), [=](const SecPtr &Sec) {
+ if (ToRemove(*Sec))
+ return false;
+ if (auto RelSec = dyn_cast<RelocationSectionBase>(Sec.get())) {
+ if (auto ToRelSec = RelSec->getSection())
+ return !ToRemove(*ToRelSec);
+ }
+ return true;
+ });
+ if (SymbolTable != nullptr && ToRemove(*SymbolTable))
+ SymbolTable = nullptr;
+ if (SectionNames != nullptr && ToRemove(*SectionNames))
+ SectionNames = nullptr;
+ if (SectionIndexTable != nullptr && ToRemove(*SectionIndexTable))
+ SectionIndexTable = nullptr;
+ // Now make sure there are no remaining references to the sections that will
+ // be removed. Sometimes it is impossible to remove a reference so we emit
+ // an error here instead.
+ std::unordered_set<const SectionBase *> RemoveSections;
+ RemoveSections.reserve(std::distance(Iter, std::end(Sections)));
+ for (auto &RemoveSec : make_range(Iter, std::end(Sections))) {
+ for (auto &Segment : Segments)
+ Segment->removeSection(RemoveSec.get());
+ RemoveSec->onRemove();
+ RemoveSections.insert(RemoveSec.get());
+ }
+
+ // For each section that remains alive, we want to remove the dead references.
+ // This either might update the content of the section (e.g. remove symbols
+ // from symbol table that belongs to removed section) or trigger an error if
+ // a live section critically depends on a section being removed somehow
+ // (e.g. the removed section is referenced by a relocation).
+ for (auto &KeepSec : make_range(std::begin(Sections), Iter)) {
if (Error E = KeepSec->removeSectionReferences(
AllowBrokenLinks, [&RemoveSections](const SectionBase *Sec) {
- return RemoveSections.find(Sec) != RemoveSections.end();
- }))
- return E;
- }
-
- // Transfer removed sections into the Object RemovedSections container for use
- // later.
- std::move(Iter, Sections.end(), std::back_inserter(RemovedSections));
- // Now finally get rid of them all together.
- Sections.erase(Iter, std::end(Sections));
- return Error::success();
-}
-
-Error Object::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
- if (SymbolTable)
- for (const SecPtr &Sec : Sections)
- if (Error E = Sec->removeSymbols(ToRemove))
- return E;
- return Error::success();
-}
-
+ return RemoveSections.find(Sec) != RemoveSections.end();
+ }))
+ return E;
+ }
+
+ // Transfer removed sections into the Object RemovedSections container for use
+ // later.
+ std::move(Iter, Sections.end(), std::back_inserter(RemovedSections));
+ // Now finally get rid of them all together.
+ Sections.erase(Iter, std::end(Sections));
+ return Error::success();
+}
+
+Error Object::removeSymbols(function_ref<bool(const Symbol &)> ToRemove) {
+ if (SymbolTable)
+ for (const SecPtr &Sec : Sections)
+ if (Error E = Sec->removeSymbols(ToRemove))
+ return E;
+ return Error::success();
+}
+
Error Object::addNewSymbolTable() {
- assert(!SymbolTable && "Object must not has a SymbolTable.");
-
- // Reuse an existing SHT_STRTAB section if it exists.
- StringTableSection *StrTab = nullptr;
- for (SectionBase &Sec : sections()) {
- if (Sec.Type == ELF::SHT_STRTAB && !(Sec.Flags & SHF_ALLOC)) {
- StrTab = static_cast<StringTableSection *>(&Sec);
-
- // Prefer a string table that is not the section header string table, if
- // such a table exists.
- if (SectionNames != &Sec)
- break;
- }
- }
- if (!StrTab)
- StrTab = &addSection<StringTableSection>();
-
- SymbolTableSection &SymTab = addSection<SymbolTableSection>();
- SymTab.Name = ".symtab";
- SymTab.Link = StrTab->Index;
+ assert(!SymbolTable && "Object must not has a SymbolTable.");
+
+ // Reuse an existing SHT_STRTAB section if it exists.
+ StringTableSection *StrTab = nullptr;
+ for (SectionBase &Sec : sections()) {
+ if (Sec.Type == ELF::SHT_STRTAB && !(Sec.Flags & SHF_ALLOC)) {
+ StrTab = static_cast<StringTableSection *>(&Sec);
+
+ // Prefer a string table that is not the section header string table, if
+ // such a table exists.
+ if (SectionNames != &Sec)
+ break;
+ }
+ }
+ if (!StrTab)
+ StrTab = &addSection<StringTableSection>();
+
+ SymbolTableSection &SymTab = addSection<SymbolTableSection>();
+ SymTab.Name = ".symtab";
+ SymTab.Link = StrTab->Index;
if (Error Err = SymTab.initialize(sections()))
return Err;
- SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);
-
- SymbolTable = &SymTab;
+ SymTab.addSymbol("", 0, 0, nullptr, 0, 0, 0, 0);
+
+ SymbolTable = &SymTab;
return Error::success();
-}
-
-void Object::sortSections() {
- // Use stable_sort to maintain the original ordering as closely as possible.
- llvm::stable_sort(Sections, [](const SecPtr &A, const SecPtr &B) {
- // Put SHT_GROUP sections first, since group section headers must come
- // before the sections they contain. This also matches what GNU objcopy
- // does.
- if (A->Type != B->Type &&
- (A->Type == ELF::SHT_GROUP || B->Type == ELF::SHT_GROUP))
- return A->Type == ELF::SHT_GROUP;
- // For all other sections, sort by offset order.
- return A->OriginalOffset < B->OriginalOffset;
- });
-}
-
-// 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
-// returns an Offset one past the end of the last segment.
-static uint64_t layoutSegments(std::vector<Segment *> &Segments,
- uint64_t Offset) {
- assert(llvm::is_sorted(Segments, compareSegmentsByOffset));
- // The only way a segment should move is if a section was between two
- // segments and that section was removed. If that section isn't in a segment
- // then it's acceptable, but not ideal, to simply move it to after the
- // segments. So we can simply layout segments one after the other accounting
- // for alignment.
- for (Segment *Seg : Segments) {
- // We assume that segments have been ordered by OriginalOffset and Index
- // such that a parent segment will always come before a child segment in
- // OrderedSegments. This means that the Offset of the ParentSegment should
- // already be set and we can set our offset relative to it.
- if (Seg->ParentSegment != nullptr) {
- Segment *Parent = Seg->ParentSegment;
- Seg->Offset =
- Parent->Offset + Seg->OriginalOffset - Parent->OriginalOffset;
- } else {
- Seg->Offset =
- alignTo(Offset, std::max<uint64_t>(Seg->Align, 1), Seg->VAddr);
- }
- Offset = std::max(Offset, Seg->Offset + Seg->FileSize);
- }
- return Offset;
-}
-
-// This function finds a consistent layout for a list of sections. It assumes
-// that the ->ParentSegment of each section has already been laid out. The
-// supplied starting Offset is used for the starting offset of any section that
-// does not have a ParentSegment. It returns either the offset given if all
-// sections had a ParentSegment or an offset one past the last section if there
-// was a section that didn't have a ParentSegment.
-template <class Range>
-static uint64_t layoutSections(Range Sections, uint64_t Offset) {
- // Now the offset of every segment has been set we can assign the offsets
- // of each section. For sections that are covered by a segment we should use
- // the segment's original offset and the section's original offset to compute
- // the offset from the start of the segment. Using the offset from the start
- // 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 &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, Sec.Align == 0 ? 1 : Sec.Align);
- Sec.Offset = Offset;
- if (Sec.Type != SHT_NOBITS)
- Offset += Sec.Size;
- }
- }
- return Offset;
-}
-
-// Rewrite sh_offset after some sections are changed to SHT_NOBITS and thus
-// occupy no space in the file.
-static uint64_t layoutSectionsForOnlyKeepDebug(Object &Obj, uint64_t Off) {
- uint32_t Index = 1;
- for (auto &Sec : Obj.sections()) {
- Sec.Index = Index++;
-
- auto *FirstSec = Sec.ParentSegment && Sec.ParentSegment->Type == PT_LOAD
- ? Sec.ParentSegment->firstSection()
- : nullptr;
-
- // The first section in a PT_LOAD has to have congruent offset and address
- // modulo the alignment, which usually equals the maximum page size.
- if (FirstSec && FirstSec == &Sec)
- Off = alignTo(Off, Sec.ParentSegment->Align, Sec.Addr);
-
- // sh_offset is not significant for SHT_NOBITS sections, but the congruence
- // rule must be followed if it is the first section in a PT_LOAD. Do not
- // advance Off.
- if (Sec.Type == SHT_NOBITS) {
- Sec.Offset = Off;
- continue;
- }
-
- if (!FirstSec) {
- // FirstSec being nullptr generally means that Sec does not have the
- // SHF_ALLOC flag.
- Off = Sec.Align ? alignTo(Off, Sec.Align) : Off;
- } else if (FirstSec != &Sec) {
- // The offset is relative to the first section in the PT_LOAD segment. Use
- // sh_offset for non-SHF_ALLOC sections.
- Off = Sec.OriginalOffset - FirstSec->OriginalOffset + FirstSec->Offset;
- }
- Sec.Offset = Off;
- Off += Sec.Size;
- }
- return Off;
-}
-
+}
+
+void Object::sortSections() {
+ // Use stable_sort to maintain the original ordering as closely as possible.
+ llvm::stable_sort(Sections, [](const SecPtr &A, const SecPtr &B) {
+ // Put SHT_GROUP sections first, since group section headers must come
+ // before the sections they contain. This also matches what GNU objcopy
+ // does.
+ if (A->Type != B->Type &&
+ (A->Type == ELF::SHT_GROUP || B->Type == ELF::SHT_GROUP))
+ return A->Type == ELF::SHT_GROUP;
+ // For all other sections, sort by offset order.
+ return A->OriginalOffset < B->OriginalOffset;
+ });
+}
+
+// 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
+// returns an Offset one past the end of the last segment.
+static uint64_t layoutSegments(std::vector<Segment *> &Segments,
+ uint64_t Offset) {
+ assert(llvm::is_sorted(Segments, compareSegmentsByOffset));
+ // The only way a segment should move is if a section was between two
+ // segments and that section was removed. If that section isn't in a segment
+ // then it's acceptable, but not ideal, to simply move it to after the
+ // segments. So we can simply layout segments one after the other accounting
+ // for alignment.
+ for (Segment *Seg : Segments) {
+ // We assume that segments have been ordered by OriginalOffset and Index
+ // such that a parent segment will always come before a child segment in
+ // OrderedSegments. This means that the Offset of the ParentSegment should
+ // already be set and we can set our offset relative to it.
+ if (Seg->ParentSegment != nullptr) {
+ Segment *Parent = Seg->ParentSegment;
+ Seg->Offset =
+ Parent->Offset + Seg->OriginalOffset - Parent->OriginalOffset;
+ } else {
+ Seg->Offset =
+ alignTo(Offset, std::max<uint64_t>(Seg->Align, 1), Seg->VAddr);
+ }
+ Offset = std::max(Offset, Seg->Offset + Seg->FileSize);
+ }
+ return Offset;
+}
+
+// This function finds a consistent layout for a list of sections. It assumes
+// that the ->ParentSegment of each section has already been laid out. The
+// supplied starting Offset is used for the starting offset of any section that
+// does not have a ParentSegment. It returns either the offset given if all
+// sections had a ParentSegment or an offset one past the last section if there
+// was a section that didn't have a ParentSegment.
+template <class Range>
+static uint64_t layoutSections(Range Sections, uint64_t Offset) {
+ // Now the offset of every segment has been set we can assign the offsets
+ // of each section. For sections that are covered by a segment we should use
+ // the segment's original offset and the section's original offset to compute
+ // the offset from the start of the segment. Using the offset from the start
+ // 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 &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, Sec.Align == 0 ? 1 : Sec.Align);
+ Sec.Offset = Offset;
+ if (Sec.Type != SHT_NOBITS)
+ Offset += Sec.Size;
+ }
+ }
+ return Offset;
+}
+
+// Rewrite sh_offset after some sections are changed to SHT_NOBITS and thus
+// occupy no space in the file.
+static uint64_t layoutSectionsForOnlyKeepDebug(Object &Obj, uint64_t Off) {
+ uint32_t Index = 1;
+ for (auto &Sec : Obj.sections()) {
+ Sec.Index = Index++;
+
+ auto *FirstSec = Sec.ParentSegment && Sec.ParentSegment->Type == PT_LOAD
+ ? Sec.ParentSegment->firstSection()
+ : nullptr;
+
+ // The first section in a PT_LOAD has to have congruent offset and address
+ // modulo the alignment, which usually equals the maximum page size.
+ if (FirstSec && FirstSec == &Sec)
+ Off = alignTo(Off, Sec.ParentSegment->Align, Sec.Addr);
+
+ // sh_offset is not significant for SHT_NOBITS sections, but the congruence
+ // rule must be followed if it is the first section in a PT_LOAD. Do not
+ // advance Off.
+ if (Sec.Type == SHT_NOBITS) {
+ Sec.Offset = Off;
+ continue;
+ }
+
+ if (!FirstSec) {
+ // FirstSec being nullptr generally means that Sec does not have the
+ // SHF_ALLOC flag.
+ Off = Sec.Align ? alignTo(Off, Sec.Align) : Off;
+ } else if (FirstSec != &Sec) {
+ // The offset is relative to the first section in the PT_LOAD segment. Use
+ // sh_offset for non-SHF_ALLOC sections.
+ Off = Sec.OriginalOffset - FirstSec->OriginalOffset + FirstSec->Offset;
+ }
+ Sec.Offset = Off;
+ Off += Sec.Size;
+ }
+ return Off;
+}
+
// Rewrite p_offset and p_filesz of non-PT_PHDR segments after sh_offset values
// have been updated.
-static uint64_t layoutSegmentsForOnlyKeepDebug(std::vector<Segment *> &Segments,
- uint64_t HdrEnd) {
- uint64_t MaxOffset = 0;
- for (Segment *Seg : Segments) {
+static uint64_t layoutSegmentsForOnlyKeepDebug(std::vector<Segment *> &Segments,
+ uint64_t HdrEnd) {
+ uint64_t MaxOffset = 0;
+ for (Segment *Seg : Segments) {
// An empty segment contains no section (see sectionWithinSegment). If it
// has a parent segment, copy the parent segment's offset field. This works
// for empty PT_TLS. We don't handle empty segments without a parent for
@@ -2318,377 +2318,377 @@ static uint64_t layoutSegmentsForOnlyKeepDebug(std::vector<Segment *> &Segments,
if (Seg->ParentSegment != nullptr && Seg->MemSize == 0)
Seg->Offset = Seg->ParentSegment->Offset;
- const SectionBase *FirstSec = Seg->firstSection();
- if (Seg->Type == PT_PHDR || !FirstSec)
- continue;
-
- uint64_t Offset = FirstSec->Offset;
- uint64_t FileSize = 0;
- for (const SectionBase *Sec : Seg->Sections) {
- uint64_t Size = Sec->Type == SHT_NOBITS ? 0 : Sec->Size;
- if (Sec->Offset + Size > Offset)
- FileSize = std::max(FileSize, Sec->Offset + Size - Offset);
- }
-
- // If the segment includes EHDR and program headers, don't make it smaller
- // than the headers.
- if (Seg->Offset < HdrEnd && HdrEnd <= Seg->Offset + Seg->FileSize) {
- FileSize += Offset - Seg->Offset;
- Offset = Seg->Offset;
- FileSize = std::max(FileSize, HdrEnd - Offset);
- }
-
- Seg->Offset = Offset;
- Seg->FileSize = FileSize;
- MaxOffset = std::max(MaxOffset, Offset + FileSize);
- }
- return MaxOffset;
-}
-
-template <class ELFT> void ELFWriter<ELFT>::initEhdrSegment() {
- Segment &ElfHdr = Obj.ElfHdrSegment;
- ElfHdr.Type = PT_PHDR;
- ElfHdr.Flags = 0;
- ElfHdr.VAddr = 0;
- ElfHdr.PAddr = 0;
- ElfHdr.FileSize = ElfHdr.MemSize = sizeof(Elf_Ehdr);
- ElfHdr.Align = 0;
-}
-
-template <class ELFT> void ELFWriter<ELFT>::assignOffsets() {
- // 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 its offset properly set.
- std::vector<Segment *> OrderedSegments;
- for (Segment &Segment : Obj.segments())
- OrderedSegments.push_back(&Segment);
- OrderedSegments.push_back(&Obj.ElfHdrSegment);
- OrderedSegments.push_back(&Obj.ProgramHdrSegment);
- orderSegments(OrderedSegments);
-
- uint64_t Offset;
- if (OnlyKeepDebug) {
- // For --only-keep-debug, the sections that did not preserve contents were
- // changed to SHT_NOBITS. We now rewrite sh_offset fields of sections, and
- // then rewrite p_offset/p_filesz of program headers.
- uint64_t HdrEnd =
- sizeof(Elf_Ehdr) + llvm::size(Obj.segments()) * sizeof(Elf_Phdr);
- Offset = layoutSectionsForOnlyKeepDebug(Obj, HdrEnd);
- Offset = std::max(Offset,
- layoutSegmentsForOnlyKeepDebug(OrderedSegments, HdrEnd));
- } else {
- // Offset is used as the start offset of the first segment to be laid out.
- // Since the ELF Header (ElfHdrSegment) must be at the start of the file,
- // we start at offset 0.
- Offset = layoutSegments(OrderedSegments, 0);
- Offset = layoutSections(Obj.sections(), Offset);
- }
- // If we need to write the section header table out then we need to align the
- // Offset so that SHOffset is valid.
- if (WriteSectionHeaders)
- Offset = alignTo(Offset, sizeof(Elf_Addr));
- 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.SHOff;
- size_t ShdrCount = Obj.sections().size() + 1; // Includes null shdr.
- return Obj.SHOff + ShdrCount * sizeof(Elf_Shdr);
-}
-
-template <class ELFT> Error ELFWriter<ELFT>::write() {
- // Segment data must be written first, so that the ELF header and program
- // header tables can overwrite it, if covered by a segment.
- writeSegmentData();
- writeEhdr();
- writePhdrs();
+ const SectionBase *FirstSec = Seg->firstSection();
+ if (Seg->Type == PT_PHDR || !FirstSec)
+ continue;
+
+ uint64_t Offset = FirstSec->Offset;
+ uint64_t FileSize = 0;
+ for (const SectionBase *Sec : Seg->Sections) {
+ uint64_t Size = Sec->Type == SHT_NOBITS ? 0 : Sec->Size;
+ if (Sec->Offset + Size > Offset)
+ FileSize = std::max(FileSize, Sec->Offset + Size - Offset);
+ }
+
+ // If the segment includes EHDR and program headers, don't make it smaller
+ // than the headers.
+ if (Seg->Offset < HdrEnd && HdrEnd <= Seg->Offset + Seg->FileSize) {
+ FileSize += Offset - Seg->Offset;
+ Offset = Seg->Offset;
+ FileSize = std::max(FileSize, HdrEnd - Offset);
+ }
+
+ Seg->Offset = Offset;
+ Seg->FileSize = FileSize;
+ MaxOffset = std::max(MaxOffset, Offset + FileSize);
+ }
+ return MaxOffset;
+}
+
+template <class ELFT> void ELFWriter<ELFT>::initEhdrSegment() {
+ Segment &ElfHdr = Obj.ElfHdrSegment;
+ ElfHdr.Type = PT_PHDR;
+ ElfHdr.Flags = 0;
+ ElfHdr.VAddr = 0;
+ ElfHdr.PAddr = 0;
+ ElfHdr.FileSize = ElfHdr.MemSize = sizeof(Elf_Ehdr);
+ ElfHdr.Align = 0;
+}
+
+template <class ELFT> void ELFWriter<ELFT>::assignOffsets() {
+ // 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 its offset properly set.
+ std::vector<Segment *> OrderedSegments;
+ for (Segment &Segment : Obj.segments())
+ OrderedSegments.push_back(&Segment);
+ OrderedSegments.push_back(&Obj.ElfHdrSegment);
+ OrderedSegments.push_back(&Obj.ProgramHdrSegment);
+ orderSegments(OrderedSegments);
+
+ uint64_t Offset;
+ if (OnlyKeepDebug) {
+ // For --only-keep-debug, the sections that did not preserve contents were
+ // changed to SHT_NOBITS. We now rewrite sh_offset fields of sections, and
+ // then rewrite p_offset/p_filesz of program headers.
+ uint64_t HdrEnd =
+ sizeof(Elf_Ehdr) + llvm::size(Obj.segments()) * sizeof(Elf_Phdr);
+ Offset = layoutSectionsForOnlyKeepDebug(Obj, HdrEnd);
+ Offset = std::max(Offset,
+ layoutSegmentsForOnlyKeepDebug(OrderedSegments, HdrEnd));
+ } else {
+ // Offset is used as the start offset of the first segment to be laid out.
+ // Since the ELF Header (ElfHdrSegment) must be at the start of the file,
+ // we start at offset 0.
+ Offset = layoutSegments(OrderedSegments, 0);
+ Offset = layoutSections(Obj.sections(), Offset);
+ }
+ // If we need to write the section header table out then we need to align the
+ // Offset so that SHOffset is valid.
+ if (WriteSectionHeaders)
+ Offset = alignTo(Offset, sizeof(Elf_Addr));
+ 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.SHOff;
+ size_t ShdrCount = Obj.sections().size() + 1; // Includes null shdr.
+ return Obj.SHOff + ShdrCount * sizeof(Elf_Shdr);
+}
+
+template <class ELFT> Error ELFWriter<ELFT>::write() {
+ // Segment data must be written first, so that the ELF header and program
+ // header tables can overwrite it, if covered by a segment.
+ writeSegmentData();
+ writeEhdr();
+ writePhdrs();
if (Error E = writeSectionData())
return E;
- if (WriteSectionHeaders)
- writeShdrs();
- 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
- // to do that.
- if (Obj.SectionNames == nullptr && WriteSectionHeaders)
- return createStringError(llvm::errc::invalid_argument,
- "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
- // if we need large indexes or not. We can assign indexes first and check as
- // we go to see if we will actully need large indexes.
- bool NeedsLargeIndexes = false;
- if (Obj.sections().size() >= SHN_LORESERVE) {
- SectionTableRef Sections = Obj.sections();
- NeedsLargeIndexes =
+ if (WriteSectionHeaders)
+ writeShdrs();
+ 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
+ // to do that.
+ if (Obj.SectionNames == nullptr && WriteSectionHeaders)
+ return createStringError(llvm::errc::invalid_argument,
+ "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
+ // if we need large indexes or not. We can assign indexes first and check as
+ // we go to see if we will actully need large indexes.
+ bool NeedsLargeIndexes = false;
+ if (Obj.sections().size() >= SHN_LORESERVE) {
+ SectionTableRef Sections = Obj.sections();
+ NeedsLargeIndexes =
any_of(drop_begin(Sections, SHN_LORESERVE),
[](const SectionBase &Sec) { return Sec.HasSymbol; });
- // TODO: handle case where only one section needs the large index table but
- // only needs it because the large index table hasn't been removed yet.
- }
-
- if (NeedsLargeIndexes) {
- // This means we definitely need to have a section index table but if we
- // already have one then we should use it instead of making a new one.
- if (Obj.SymbolTable != nullptr && Obj.SectionIndexTable == nullptr) {
- // Addition of a section to the end does not invalidate the indexes of
- // other sections and assigns the correct index to the new section.
- auto &Shndx = Obj.addSection<SectionIndexSection>();
- Obj.SymbolTable->setShndxTable(&Shndx);
- Shndx.setSymTab(Obj.SymbolTable);
- }
- } else {
- // Since we don't need SectionIndexTable we should remove it and all
- // references to it.
- if (Obj.SectionIndexTable != nullptr) {
- // We do not support sections referring to the section index table.
- if (Error E = Obj.removeSections(false /*AllowBrokenLinks*/,
- [this](const SectionBase &Sec) {
- return &Sec == Obj.SectionIndexTable;
- }))
- return E;
- }
- }
-
- // 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 SectionBase &Sec : Obj.sections())
- Obj.SectionNames->addString(Sec.Name);
-
- initEhdrSegment();
-
- // Before we can prepare for layout the indexes need to be finalized.
- // 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 = std::make_unique<ELFSectionSizer<ELFT>>();
- for (SectionBase &Sec : Obj.sections()) {
- Sec.Index = Index++;
+ // TODO: handle case where only one section needs the large index table but
+ // only needs it because the large index table hasn't been removed yet.
+ }
+
+ if (NeedsLargeIndexes) {
+ // This means we definitely need to have a section index table but if we
+ // already have one then we should use it instead of making a new one.
+ if (Obj.SymbolTable != nullptr && Obj.SectionIndexTable == nullptr) {
+ // Addition of a section to the end does not invalidate the indexes of
+ // other sections and assigns the correct index to the new section.
+ auto &Shndx = Obj.addSection<SectionIndexSection>();
+ Obj.SymbolTable->setShndxTable(&Shndx);
+ Shndx.setSymTab(Obj.SymbolTable);
+ }
+ } else {
+ // Since we don't need SectionIndexTable we should remove it and all
+ // references to it.
+ if (Obj.SectionIndexTable != nullptr) {
+ // We do not support sections referring to the section index table.
+ if (Error E = Obj.removeSections(false /*AllowBrokenLinks*/,
+ [this](const SectionBase &Sec) {
+ return &Sec == Obj.SectionIndexTable;
+ }))
+ return E;
+ }
+ }
+
+ // 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 SectionBase &Sec : Obj.sections())
+ Obj.SectionNames->addString(Sec.Name);
+
+ initEhdrSegment();
+
+ // Before we can prepare for layout the indexes need to be finalized.
+ // 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 = std::make_unique<ELFSectionSizer<ELFT>>();
+ for (SectionBase &Sec : Obj.sections()) {
+ Sec.Index = Index++;
if (Error Err = Sec.accept(*SecSizer))
return Err;
- }
-
- // The symbol table does not update all other sections on update. For
- // instance, symbol names are not added as new symbols are added. This means
- // that some sections, like .strtab, don't yet have their final size.
- if (Obj.SymbolTable != nullptr)
- Obj.SymbolTable->prepareForLayout();
-
- // Now that all strings are added we want to finalize string table builders,
- // because that affects section sizes which in turn affects section offsets.
- for (SectionBase &Sec : Obj.sections())
- if (auto StrTab = dyn_cast<StringTableSection>(&Sec))
- StrTab->prepareForLayout();
-
- assignOffsets();
-
- // layoutSections could have modified section indexes, so we need
- // to fill the index table after assignOffsets.
- if (Obj.SymbolTable != nullptr)
- Obj.SymbolTable->fillShndxTable();
-
- // Finally now that all offsets and indexes have been set we can finalize any
- // remaining issues.
- uint64_t Offset = Obj.SHOff + sizeof(Elf_Shdr);
- for (SectionBase &Sec : Obj.sections()) {
- Sec.HeaderOffset = Offset;
- Offset += sizeof(Elf_Shdr);
- if (WriteSectionHeaders)
- Sec.NameIndex = Obj.SectionNames->findIndex(Sec.Name);
- Sec.finalize();
- }
-
- if (Error E = Buf.allocate(totalSize()))
- return E;
- SecWriter = std::make_unique<ELFSectionWriter<ELFT>>(Buf);
- return Error::success();
-}
-
-Error BinaryWriter::write() {
- for (const SectionBase &Sec : Obj.allocSections())
+ }
+
+ // The symbol table does not update all other sections on update. For
+ // instance, symbol names are not added as new symbols are added. This means
+ // that some sections, like .strtab, don't yet have their final size.
+ if (Obj.SymbolTable != nullptr)
+ Obj.SymbolTable->prepareForLayout();
+
+ // Now that all strings are added we want to finalize string table builders,
+ // because that affects section sizes which in turn affects section offsets.
+ for (SectionBase &Sec : Obj.sections())
+ if (auto StrTab = dyn_cast<StringTableSection>(&Sec))
+ StrTab->prepareForLayout();
+
+ assignOffsets();
+
+ // layoutSections could have modified section indexes, so we need
+ // to fill the index table after assignOffsets.
+ if (Obj.SymbolTable != nullptr)
+ Obj.SymbolTable->fillShndxTable();
+
+ // Finally now that all offsets and indexes have been set we can finalize any
+ // remaining issues.
+ uint64_t Offset = Obj.SHOff + sizeof(Elf_Shdr);
+ for (SectionBase &Sec : Obj.sections()) {
+ Sec.HeaderOffset = Offset;
+ Offset += sizeof(Elf_Shdr);
+ if (WriteSectionHeaders)
+ Sec.NameIndex = Obj.SectionNames->findIndex(Sec.Name);
+ Sec.finalize();
+ }
+
+ if (Error E = Buf.allocate(totalSize()))
+ return E;
+ SecWriter = std::make_unique<ELFSectionWriter<ELFT>>(Buf);
+ return Error::success();
+}
+
+Error BinaryWriter::write() {
+ for (const SectionBase &Sec : Obj.allocSections())
if (Error Err = Sec.accept(*SecWriter))
return Err;
- return Buf.commit();
-}
-
-Error BinaryWriter::finalize() {
- // Compute the section LMA based on its sh_offset and the containing segment's
- // p_offset and p_paddr. Also compute the minimum LMA of all non-empty
- // sections as MinAddr. In the output, the contents between address 0 and
- // MinAddr will be skipped.
- uint64_t MinAddr = UINT64_MAX;
- for (SectionBase &Sec : Obj.allocSections()) {
- if (Sec.ParentSegment != nullptr)
- Sec.Addr =
- Sec.Offset - Sec.ParentSegment->Offset + Sec.ParentSegment->PAddr;
- if (Sec.Size > 0)
- MinAddr = std::min(MinAddr, Sec.Addr);
- }
-
- // 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
- // its last non-empty section, to match GNU objcopy's behaviour.
- TotalSize = 0;
- for (SectionBase &Sec : Obj.allocSections())
- if (Sec.Type != SHT_NOBITS && Sec.Size > 0) {
- Sec.Offset = Sec.Addr - MinAddr;
- TotalSize = std::max(TotalSize, Sec.Offset + Sec.Size);
- }
-
- if (Error E = Buf.allocate(TotalSize))
- return E;
- SecWriter = std::make_unique<BinarySectionWriter>(Buf);
- return Error::success();
-}
-
-bool IHexWriter::SectionCompare::operator()(const SectionBase *Lhs,
- const SectionBase *Rhs) const {
- return (sectionPhysicalAddr(Lhs) & 0xFFFFFFFFU) <
- (sectionPhysicalAddr(Rhs) & 0xFFFFFFFFU);
-}
-
-uint64_t IHexWriter::writeEntryPointRecord(uint8_t *Buf) {
- IHexLineData HexData;
- uint8_t Data[4] = {};
- // We don't write entry point record if entry is zero.
- if (Obj.Entry == 0)
- return 0;
-
- if (Obj.Entry <= 0xFFFFFU) {
- Data[0] = ((Obj.Entry & 0xF0000U) >> 12) & 0xFF;
- support::endian::write(&Data[2], static_cast<uint16_t>(Obj.Entry),
- support::big);
- HexData = IHexRecord::getLine(IHexRecord::StartAddr80x86, 0, Data);
- } else {
- support::endian::write(Data, static_cast<uint32_t>(Obj.Entry),
- support::big);
- HexData = IHexRecord::getLine(IHexRecord::StartAddr, 0, Data);
- }
- memcpy(Buf, HexData.data(), HexData.size());
- return HexData.size();
-}
-
-uint64_t IHexWriter::writeEndOfFileRecord(uint8_t *Buf) {
- IHexLineData HexData = IHexRecord::getLine(IHexRecord::EndOfFile, 0, {});
- memcpy(Buf, HexData.data(), HexData.size());
- return HexData.size();
-}
-
-Error IHexWriter::write() {
- IHexSectionWriter Writer(Buf);
- // Write sections.
- for (const SectionBase *Sec : Sections)
+ return Buf.commit();
+}
+
+Error BinaryWriter::finalize() {
+ // Compute the section LMA based on its sh_offset and the containing segment's
+ // p_offset and p_paddr. Also compute the minimum LMA of all non-empty
+ // sections as MinAddr. In the output, the contents between address 0 and
+ // MinAddr will be skipped.
+ uint64_t MinAddr = UINT64_MAX;
+ for (SectionBase &Sec : Obj.allocSections()) {
+ if (Sec.ParentSegment != nullptr)
+ Sec.Addr =
+ Sec.Offset - Sec.ParentSegment->Offset + Sec.ParentSegment->PAddr;
+ if (Sec.Size > 0)
+ MinAddr = std::min(MinAddr, Sec.Addr);
+ }
+
+ // 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
+ // its last non-empty section, to match GNU objcopy's behaviour.
+ TotalSize = 0;
+ for (SectionBase &Sec : Obj.allocSections())
+ if (Sec.Type != SHT_NOBITS && Sec.Size > 0) {
+ Sec.Offset = Sec.Addr - MinAddr;
+ TotalSize = std::max(TotalSize, Sec.Offset + Sec.Size);
+ }
+
+ if (Error E = Buf.allocate(TotalSize))
+ return E;
+ SecWriter = std::make_unique<BinarySectionWriter>(Buf);
+ return Error::success();
+}
+
+bool IHexWriter::SectionCompare::operator()(const SectionBase *Lhs,
+ const SectionBase *Rhs) const {
+ return (sectionPhysicalAddr(Lhs) & 0xFFFFFFFFU) <
+ (sectionPhysicalAddr(Rhs) & 0xFFFFFFFFU);
+}
+
+uint64_t IHexWriter::writeEntryPointRecord(uint8_t *Buf) {
+ IHexLineData HexData;
+ uint8_t Data[4] = {};
+ // We don't write entry point record if entry is zero.
+ if (Obj.Entry == 0)
+ return 0;
+
+ if (Obj.Entry <= 0xFFFFFU) {
+ Data[0] = ((Obj.Entry & 0xF0000U) >> 12) & 0xFF;
+ support::endian::write(&Data[2], static_cast<uint16_t>(Obj.Entry),
+ support::big);
+ HexData = IHexRecord::getLine(IHexRecord::StartAddr80x86, 0, Data);
+ } else {
+ support::endian::write(Data, static_cast<uint32_t>(Obj.Entry),
+ support::big);
+ HexData = IHexRecord::getLine(IHexRecord::StartAddr, 0, Data);
+ }
+ memcpy(Buf, HexData.data(), HexData.size());
+ return HexData.size();
+}
+
+uint64_t IHexWriter::writeEndOfFileRecord(uint8_t *Buf) {
+ IHexLineData HexData = IHexRecord::getLine(IHexRecord::EndOfFile, 0, {});
+ memcpy(Buf, HexData.data(), HexData.size());
+ return HexData.size();
+}
+
+Error IHexWriter::write() {
+ IHexSectionWriter Writer(Buf);
+ // Write sections.
+ for (const SectionBase *Sec : Sections)
if (Error Err = Sec->accept(Writer))
return Err;
-
- uint64_t Offset = Writer.getBufferOffset();
- // Write entry point address.
- Offset += writeEntryPointRecord(Buf.getBufferStart() + Offset);
- // Write EOF.
- Offset += writeEndOfFileRecord(Buf.getBufferStart() + Offset);
- assert(Offset == TotalSize);
- return Buf.commit();
-}
-
-Error IHexWriter::checkSection(const SectionBase &Sec) {
- uint64_t Addr = sectionPhysicalAddr(&Sec);
- if (addressOverflows32bit(Addr) || addressOverflows32bit(Addr + Sec.Size - 1))
- return createStringError(
- errc::invalid_argument,
+
+ uint64_t Offset = Writer.getBufferOffset();
+ // Write entry point address.
+ Offset += writeEntryPointRecord(Buf.getBufferStart() + Offset);
+ // Write EOF.
+ Offset += writeEndOfFileRecord(Buf.getBufferStart() + Offset);
+ assert(Offset == TotalSize);
+ return Buf.commit();
+}
+
+Error IHexWriter::checkSection(const SectionBase &Sec) {
+ uint64_t Addr = sectionPhysicalAddr(&Sec);
+ if (addressOverflows32bit(Addr) || addressOverflows32bit(Addr + Sec.Size - 1))
+ return createStringError(
+ errc::invalid_argument,
"Section '%s' address range [0x%llx, 0x%llx] is not 32 bit",
Sec.Name.c_str(), Addr, Addr + Sec.Size - 1);
- return Error::success();
-}
-
-Error IHexWriter::finalize() {
- bool UseSegments = false;
- auto ShouldWrite = [](const SectionBase &Sec) {
- return (Sec.Flags & ELF::SHF_ALLOC) && (Sec.Type != ELF::SHT_NOBITS);
- };
- auto IsInPtLoad = [](const SectionBase &Sec) {
- return Sec.ParentSegment && Sec.ParentSegment->Type == ELF::PT_LOAD;
- };
-
- // We can't write 64-bit addresses.
- if (addressOverflows32bit(Obj.Entry))
- return createStringError(errc::invalid_argument,
- "Entry point address 0x%llx overflows 32 bits.",
- Obj.Entry);
-
- // If any section we're to write has segment then we
- // switch to using physical addresses. Otherwise we
- // use section virtual address.
- for (const SectionBase &Sec : Obj.sections())
- if (ShouldWrite(Sec) && IsInPtLoad(Sec)) {
- UseSegments = true;
- break;
- }
-
- for (const SectionBase &Sec : Obj.sections())
- if (ShouldWrite(Sec) && (!UseSegments || IsInPtLoad(Sec))) {
- if (Error E = checkSection(Sec))
- return E;
- Sections.insert(&Sec);
- }
-
- IHexSectionWriterBase LengthCalc(Buf);
- for (const SectionBase *Sec : Sections)
+ return Error::success();
+}
+
+Error IHexWriter::finalize() {
+ bool UseSegments = false;
+ auto ShouldWrite = [](const SectionBase &Sec) {
+ return (Sec.Flags & ELF::SHF_ALLOC) && (Sec.Type != ELF::SHT_NOBITS);
+ };
+ auto IsInPtLoad = [](const SectionBase &Sec) {
+ return Sec.ParentSegment && Sec.ParentSegment->Type == ELF::PT_LOAD;
+ };
+
+ // We can't write 64-bit addresses.
+ if (addressOverflows32bit(Obj.Entry))
+ return createStringError(errc::invalid_argument,
+ "Entry point address 0x%llx overflows 32 bits.",
+ Obj.Entry);
+
+ // If any section we're to write has segment then we
+ // switch to using physical addresses. Otherwise we
+ // use section virtual address.
+ for (const SectionBase &Sec : Obj.sections())
+ if (ShouldWrite(Sec) && IsInPtLoad(Sec)) {
+ UseSegments = true;
+ break;
+ }
+
+ for (const SectionBase &Sec : Obj.sections())
+ if (ShouldWrite(Sec) && (!UseSegments || IsInPtLoad(Sec))) {
+ if (Error E = checkSection(Sec))
+ return E;
+ Sections.insert(&Sec);
+ }
+
+ IHexSectionWriterBase LengthCalc(Buf);
+ for (const SectionBase *Sec : Sections)
if (Error Err = Sec->accept(LengthCalc))
return Err;
-
- // We need space to write section records + StartAddress record
- // (if start adress is not zero) + EndOfFile record.
- TotalSize = LengthCalc.getBufferOffset() +
- (Obj.Entry ? IHexRecord::getLineLength(4) : 0) +
- IHexRecord::getLineLength(0);
- if (Error E = Buf.allocate(TotalSize))
- return E;
- return Error::success();
-}
-
-template class ELFBuilder<ELF64LE>;
-template class ELFBuilder<ELF64BE>;
-template class ELFBuilder<ELF32LE>;
-template class ELFBuilder<ELF32BE>;
-
-template class ELFWriter<ELF64LE>;
-template class ELFWriter<ELF64BE>;
-template class ELFWriter<ELF32LE>;
-template class ELFWriter<ELF32BE>;
-
-} // end namespace elf
-} // end namespace objcopy
-} // end namespace llvm
+
+ // We need space to write section records + StartAddress record
+ // (if start adress is not zero) + EndOfFile record.
+ TotalSize = LengthCalc.getBufferOffset() +
+ (Obj.Entry ? IHexRecord::getLineLength(4) : 0) +
+ IHexRecord::getLineLength(0);
+ if (Error E = Buf.allocate(TotalSize))
+ return E;
+ return Error::success();
+}
+
+template class ELFBuilder<ELF64LE>;
+template class ELFBuilder<ELF64BE>;
+template class ELFBuilder<ELF32LE>;
+template class ELFBuilder<ELF32BE>;
+
+template class ELFWriter<ELF64LE>;
+template class ELFWriter<ELF64BE>;
+template class ELFWriter<ELF32LE>;
+template class ELFWriter<ELF32BE>;
+
+} // end namespace elf
+} // end namespace objcopy
+} // end namespace llvm
diff --git a/contrib/libs/llvm12/tools/llvm-objcopy/ELF/Object.h b/contrib/libs/llvm12/tools/llvm-objcopy/ELF/Object.h
index 0205c2d4f3..8a0ceb67d7 100644
--- a/contrib/libs/llvm12/tools/llvm-objcopy/ELF/Object.h
+++ b/contrib/libs/llvm12/tools/llvm-objcopy/ELF/Object.h
@@ -1,79 +1,79 @@
-//===- Object.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_OBJECT_H
-#define LLVM_TOOLS_OBJCOPY_OBJECT_H
-
-#include "Buffer.h"
-#include "CopyConfig.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/MC/StringTableBuilder.h"
-#include "llvm/Object/ELFObjectFile.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include <cstddef>
-#include <cstdint>
-#include <functional>
-#include <memory>
-#include <set>
-#include <vector>
-
-namespace llvm {
-enum class DebugCompressionType;
-namespace objcopy {
-namespace elf {
-
-class SectionBase;
-class Section;
-class OwnedDataSection;
-class StringTableSection;
-class SymbolTableSection;
-class RelocationSection;
-class DynamicRelocationSection;
-class GnuDebugLinkSection;
-class GroupSection;
-class SectionIndexSection;
-class CompressedSection;
-class DecompressedSection;
-class Segment;
-class Object;
-struct Symbol;
-
-class SectionTableRef {
- MutableArrayRef<std::unique_ptr<SectionBase>> Sections;
-
-public:
- using iterator = pointee_iterator<std::unique_ptr<SectionBase> *>;
-
- explicit SectionTableRef(MutableArrayRef<std::unique_ptr<SectionBase>> Secs)
- : Sections(Secs) {}
- SectionTableRef(const SectionTableRef &) = default;
-
- iterator begin() const { return iterator(Sections.data()); }
- iterator end() const { return iterator(Sections.data() + Sections.size()); }
- size_t size() const { return Sections.size(); }
-
+//===- Object.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_OBJECT_H
+#define LLVM_TOOLS_OBJCOPY_OBJECT_H
+
+#include "Buffer.h"
+#include "CopyConfig.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/ELF.h"
+#include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/FileOutputBuffer.h"
+#include <cstddef>
+#include <cstdint>
+#include <functional>
+#include <memory>
+#include <set>
+#include <vector>
+
+namespace llvm {
+enum class DebugCompressionType;
+namespace objcopy {
+namespace elf {
+
+class SectionBase;
+class Section;
+class OwnedDataSection;
+class StringTableSection;
+class SymbolTableSection;
+class RelocationSection;
+class DynamicRelocationSection;
+class GnuDebugLinkSection;
+class GroupSection;
+class SectionIndexSection;
+class CompressedSection;
+class DecompressedSection;
+class Segment;
+class Object;
+struct Symbol;
+
+class SectionTableRef {
+ MutableArrayRef<std::unique_ptr<SectionBase>> Sections;
+
+public:
+ using iterator = pointee_iterator<std::unique_ptr<SectionBase> *>;
+
+ explicit SectionTableRef(MutableArrayRef<std::unique_ptr<SectionBase>> Secs)
+ : Sections(Secs) {}
+ SectionTableRef(const SectionTableRef &) = default;
+
+ iterator begin() const { return iterator(Sections.data()); }
+ iterator end() const { return iterator(Sections.data() + Sections.size()); }
+ size_t size() const { return Sections.size(); }
+
Expected<SectionBase *> getSection(uint32_t Index, Twine ErrMsg);
-
- template <class T>
+
+ template <class T>
Expected<T *> getSectionOfType(uint32_t Index, Twine IndexErrMsg,
Twine TypeErrMsg);
-};
-
-enum ElfType { ELFT_ELF32LE, ELFT_ELF64LE, ELFT_ELF32BE, ELFT_ELF64BE };
-
-class SectionVisitor {
-public:
- virtual ~SectionVisitor() = default;
-
+};
+
+enum ElfType { ELFT_ELF32LE, ELFT_ELF64LE, ELFT_ELF32BE, ELFT_ELF64BE };
+
+class SectionVisitor {
+public:
+ virtual ~SectionVisitor() = default;
+
virtual Error visit(const Section &Sec) = 0;
virtual Error visit(const OwnedDataSection &Sec) = 0;
virtual Error visit(const StringTableSection &Sec) = 0;
@@ -85,12 +85,12 @@ public:
virtual Error visit(const SectionIndexSection &Sec) = 0;
virtual Error visit(const CompressedSection &Sec) = 0;
virtual Error visit(const DecompressedSection &Sec) = 0;
-};
-
-class MutableSectionVisitor {
-public:
- virtual ~MutableSectionVisitor() = default;
-
+};
+
+class MutableSectionVisitor {
+public:
+ virtual ~MutableSectionVisitor() = default;
+
virtual Error visit(Section &Sec) = 0;
virtual Error visit(OwnedDataSection &Sec) = 0;
virtual Error visit(StringTableSection &Sec) = 0;
@@ -102,15 +102,15 @@ public:
virtual Error visit(SectionIndexSection &Sec) = 0;
virtual Error visit(CompressedSection &Sec) = 0;
virtual Error visit(DecompressedSection &Sec) = 0;
-};
-
-class SectionWriter : public SectionVisitor {
-protected:
- Buffer &Out;
-
-public:
- virtual ~SectionWriter() = default;
-
+};
+
+class SectionWriter : public SectionVisitor {
+protected:
+ Buffer &Out;
+
+public:
+ virtual ~SectionWriter() = default;
+
Error visit(const Section &Sec) override;
Error visit(const OwnedDataSection &Sec) override;
Error visit(const StringTableSection &Sec) override;
@@ -122,19 +122,19 @@ public:
virtual Error visit(const SectionIndexSection &Sec) override = 0;
virtual Error visit(const CompressedSection &Sec) override = 0;
virtual Error visit(const DecompressedSection &Sec) override = 0;
-
- explicit SectionWriter(Buffer &Buf) : Out(Buf) {}
-};
-
-template <class ELFT> class ELFSectionWriter : public SectionWriter {
-private:
- using Elf_Word = typename ELFT::Word;
- using Elf_Rel = typename ELFT::Rel;
- using Elf_Rela = typename ELFT::Rela;
- using Elf_Sym = typename ELFT::Sym;
-
-public:
- virtual ~ELFSectionWriter() {}
+
+ explicit SectionWriter(Buffer &Buf) : Out(Buf) {}
+};
+
+template <class ELFT> class ELFSectionWriter : public SectionWriter {
+private:
+ using Elf_Word = typename ELFT::Word;
+ using Elf_Rel = typename ELFT::Rel;
+ using Elf_Rela = typename ELFT::Rela;
+ using Elf_Sym = typename ELFT::Sym;
+
+public:
+ virtual ~ELFSectionWriter() {}
Error visit(const SymbolTableSection &Sec) override;
Error visit(const RelocationSection &Sec) override;
Error visit(const GnuDebugLinkSection &Sec) override;
@@ -142,19 +142,19 @@ public:
Error visit(const SectionIndexSection &Sec) override;
Error visit(const CompressedSection &Sec) override;
Error visit(const DecompressedSection &Sec) override;
-
- explicit ELFSectionWriter(Buffer &Buf) : SectionWriter(Buf) {}
-};
-
-template <class ELFT> class ELFSectionSizer : public MutableSectionVisitor {
-private:
- using Elf_Rel = typename ELFT::Rel;
- using Elf_Rela = typename ELFT::Rela;
- using Elf_Sym = typename ELFT::Sym;
- using Elf_Word = typename ELFT::Word;
- using Elf_Xword = typename ELFT::Xword;
-
-public:
+
+ explicit ELFSectionWriter(Buffer &Buf) : SectionWriter(Buf) {}
+};
+
+template <class ELFT> class ELFSectionSizer : public MutableSectionVisitor {
+private:
+ using Elf_Rel = typename ELFT::Rel;
+ using Elf_Rela = typename ELFT::Rela;
+ using Elf_Sym = typename ELFT::Sym;
+ using Elf_Word = typename ELFT::Word;
+ using Elf_Xword = typename ELFT::Xword;
+
+public:
Error visit(Section &Sec) override;
Error visit(OwnedDataSection &Sec) override;
Error visit(StringTableSection &Sec) override;
@@ -166,19 +166,19 @@ public:
Error visit(SectionIndexSection &Sec) override;
Error visit(CompressedSection &Sec) override;
Error visit(DecompressedSection &Sec) override;
-};
-
-#define MAKE_SEC_WRITER_FRIEND \
- friend class SectionWriter; \
- friend class IHexSectionWriterBase; \
- friend class IHexSectionWriter; \
- template <class ELFT> friend class ELFSectionWriter; \
- template <class ELFT> friend class ELFSectionSizer;
-
-class BinarySectionWriter : public SectionWriter {
-public:
- virtual ~BinarySectionWriter() {}
-
+};
+
+#define MAKE_SEC_WRITER_FRIEND \
+ friend class SectionWriter; \
+ friend class IHexSectionWriterBase; \
+ friend class IHexSectionWriter; \
+ template <class ELFT> friend class ELFSectionWriter; \
+ template <class ELFT> friend class ELFSectionSizer;
+
+class BinarySectionWriter : public SectionWriter {
+public:
+ virtual ~BinarySectionWriter() {}
+
Error visit(const SymbolTableSection &Sec) override;
Error visit(const RelocationSection &Sec) override;
Error visit(const GnuDebugLinkSection &Sec) override;
@@ -186,766 +186,766 @@ public:
Error visit(const SectionIndexSection &Sec) override;
Error visit(const CompressedSection &Sec) override;
Error visit(const DecompressedSection &Sec) override;
-
- explicit BinarySectionWriter(Buffer &Buf) : SectionWriter(Buf) {}
-};
-
-using IHexLineData = SmallVector<char, 64>;
-
-struct IHexRecord {
- // Memory address of the record.
- uint16_t Addr;
- // Record type (see below).
- uint16_t Type;
- // Record data in hexadecimal form.
- StringRef HexData;
-
- // Helper method to get file length of the record
- // including newline character
- static size_t getLength(size_t DataSize) {
- // :LLAAAATT[DD...DD]CC'
- return DataSize * 2 + 11;
- }
-
- // Gets length of line in a file (getLength + CRLF).
- static size_t getLineLength(size_t DataSize) {
- return getLength(DataSize) + 2;
- }
-
- // Given type, address and data returns line which can
- // be written to output file.
- static IHexLineData getLine(uint8_t Type, uint16_t Addr,
- ArrayRef<uint8_t> Data);
-
- // Parses the line and returns record if possible.
- // Line should be trimmed from whitespace characters.
- static Expected<IHexRecord> parse(StringRef Line);
-
- // Calculates checksum of stringified record representation
- // S must NOT contain leading ':' and trailing whitespace
- // characters
- static uint8_t getChecksum(StringRef S);
-
- enum Type {
- // Contains data and a 16-bit starting address for the data.
- // The byte count specifies number of data bytes in the record.
- Data = 0,
- // Must occur exactly once per file in the last line of the file.
- // The data field is empty (thus byte count is 00) and the address
- // field is typically 0000.
- EndOfFile = 1,
- // The data field contains a 16-bit segment base address (thus byte
- // count is always 02) compatible with 80x86 real mode addressing.
- // The address field (typically 0000) is ignored. The segment address
- // from the most recent 02 record is multiplied by 16 and added to each
- // subsequent data record address to form the physical starting address
- // for the data. This allows addressing up to one megabyte of address
- // space.
- SegmentAddr = 2,
- // or 80x86 processors, specifies the initial content of the CS:IP
- // registers. The address field is 0000, the byte count is always 04,
- // the first two data bytes are the CS value, the latter two are the
- // IP value.
- StartAddr80x86 = 3,
- // Allows for 32 bit addressing (up to 4GiB). The record's address field
- // is ignored (typically 0000) and its byte count is always 02. The two
- // data bytes (big endian) specify the upper 16 bits of the 32 bit
- // absolute address for all subsequent type 00 records
- ExtendedAddr = 4,
- // The address field is 0000 (not used) and the byte count is always 04.
- // The four data bytes represent a 32-bit address value. In the case of
- // 80386 and higher CPUs, this address is loaded into the EIP register.
- StartAddr = 5,
- // We have no other valid types
- InvalidType = 6
- };
-};
-
-// Base class for IHexSectionWriter. This class implements writing algorithm,
-// but doesn't actually write records. It is used for output buffer size
-// calculation in IHexWriter::finalize.
-class IHexSectionWriterBase : public BinarySectionWriter {
- // 20-bit segment address
- uint32_t SegmentAddr = 0;
- // Extended linear address
- uint32_t BaseAddr = 0;
-
- // Write segment address corresponding to 'Addr'
- uint64_t writeSegmentAddr(uint64_t Addr);
- // Write extended linear (base) address corresponding to 'Addr'
- uint64_t writeBaseAddr(uint64_t Addr);
-
-protected:
- // Offset in the output buffer
- uint64_t Offset = 0;
-
- void writeSection(const SectionBase *Sec, ArrayRef<uint8_t> Data);
- virtual void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data);
-
-public:
- explicit IHexSectionWriterBase(Buffer &Buf) : BinarySectionWriter(Buf) {}
-
- uint64_t getBufferOffset() const { return Offset; }
+
+ explicit BinarySectionWriter(Buffer &Buf) : SectionWriter(Buf) {}
+};
+
+using IHexLineData = SmallVector<char, 64>;
+
+struct IHexRecord {
+ // Memory address of the record.
+ uint16_t Addr;
+ // Record type (see below).
+ uint16_t Type;
+ // Record data in hexadecimal form.
+ StringRef HexData;
+
+ // Helper method to get file length of the record
+ // including newline character
+ static size_t getLength(size_t DataSize) {
+ // :LLAAAATT[DD...DD]CC'
+ return DataSize * 2 + 11;
+ }
+
+ // Gets length of line in a file (getLength + CRLF).
+ static size_t getLineLength(size_t DataSize) {
+ return getLength(DataSize) + 2;
+ }
+
+ // Given type, address and data returns line which can
+ // be written to output file.
+ static IHexLineData getLine(uint8_t Type, uint16_t Addr,
+ ArrayRef<uint8_t> Data);
+
+ // Parses the line and returns record if possible.
+ // Line should be trimmed from whitespace characters.
+ static Expected<IHexRecord> parse(StringRef Line);
+
+ // Calculates checksum of stringified record representation
+ // S must NOT contain leading ':' and trailing whitespace
+ // characters
+ static uint8_t getChecksum(StringRef S);
+
+ enum Type {
+ // Contains data and a 16-bit starting address for the data.
+ // The byte count specifies number of data bytes in the record.
+ Data = 0,
+ // Must occur exactly once per file in the last line of the file.
+ // The data field is empty (thus byte count is 00) and the address
+ // field is typically 0000.
+ EndOfFile = 1,
+ // The data field contains a 16-bit segment base address (thus byte
+ // count is always 02) compatible with 80x86 real mode addressing.
+ // The address field (typically 0000) is ignored. The segment address
+ // from the most recent 02 record is multiplied by 16 and added to each
+ // subsequent data record address to form the physical starting address
+ // for the data. This allows addressing up to one megabyte of address
+ // space.
+ SegmentAddr = 2,
+ // or 80x86 processors, specifies the initial content of the CS:IP
+ // registers. The address field is 0000, the byte count is always 04,
+ // the first two data bytes are the CS value, the latter two are the
+ // IP value.
+ StartAddr80x86 = 3,
+ // Allows for 32 bit addressing (up to 4GiB). The record's address field
+ // is ignored (typically 0000) and its byte count is always 02. The two
+ // data bytes (big endian) specify the upper 16 bits of the 32 bit
+ // absolute address for all subsequent type 00 records
+ ExtendedAddr = 4,
+ // The address field is 0000 (not used) and the byte count is always 04.
+ // The four data bytes represent a 32-bit address value. In the case of
+ // 80386 and higher CPUs, this address is loaded into the EIP register.
+ StartAddr = 5,
+ // We have no other valid types
+ InvalidType = 6
+ };
+};
+
+// Base class for IHexSectionWriter. This class implements writing algorithm,
+// but doesn't actually write records. It is used for output buffer size
+// calculation in IHexWriter::finalize.
+class IHexSectionWriterBase : public BinarySectionWriter {
+ // 20-bit segment address
+ uint32_t SegmentAddr = 0;
+ // Extended linear address
+ uint32_t BaseAddr = 0;
+
+ // Write segment address corresponding to 'Addr'
+ uint64_t writeSegmentAddr(uint64_t Addr);
+ // Write extended linear (base) address corresponding to 'Addr'
+ uint64_t writeBaseAddr(uint64_t Addr);
+
+protected:
+ // Offset in the output buffer
+ uint64_t Offset = 0;
+
+ void writeSection(const SectionBase *Sec, ArrayRef<uint8_t> Data);
+ virtual void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data);
+
+public:
+ explicit IHexSectionWriterBase(Buffer &Buf) : BinarySectionWriter(Buf) {}
+
+ uint64_t getBufferOffset() const { return Offset; }
Error visit(const Section &Sec) final;
Error visit(const OwnedDataSection &Sec) final;
Error visit(const StringTableSection &Sec) override;
Error visit(const DynamicRelocationSection &Sec) final;
- using BinarySectionWriter::visit;
-};
-
-// Real IHEX section writer
-class IHexSectionWriter : public IHexSectionWriterBase {
-public:
- IHexSectionWriter(Buffer &Buf) : IHexSectionWriterBase(Buf) {}
-
- void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data) override;
+ using BinarySectionWriter::visit;
+};
+
+// Real IHEX section writer
+class IHexSectionWriter : public IHexSectionWriterBase {
+public:
+ IHexSectionWriter(Buffer &Buf) : IHexSectionWriterBase(Buf) {}
+
+ void writeData(uint8_t Type, uint16_t Addr, ArrayRef<uint8_t> Data) override;
Error visit(const StringTableSection &Sec) override;
-};
-
-class Writer {
-protected:
- Object &Obj;
- Buffer &Buf;
-
-public:
- virtual ~Writer();
- virtual Error finalize() = 0;
- virtual Error write() = 0;
-
- Writer(Object &O, Buffer &B) : Obj(O), Buf(B) {}
-};
-
-template <class ELFT> class ELFWriter : public Writer {
-private:
- using Elf_Addr = typename ELFT::Addr;
- using Elf_Shdr = typename ELFT::Shdr;
- using Elf_Phdr = typename ELFT::Phdr;
- using Elf_Ehdr = typename ELFT::Ehdr;
-
- void initEhdrSegment();
-
- void writeEhdr();
- void writePhdr(const Segment &Seg);
- void writeShdr(const SectionBase &Sec);
-
- void writePhdrs();
- void writeShdrs();
+};
+
+class Writer {
+protected:
+ Object &Obj;
+ Buffer &Buf;
+
+public:
+ virtual ~Writer();
+ virtual Error finalize() = 0;
+ virtual Error write() = 0;
+
+ Writer(Object &O, Buffer &B) : Obj(O), Buf(B) {}
+};
+
+template <class ELFT> class ELFWriter : public Writer {
+private:
+ using Elf_Addr = typename ELFT::Addr;
+ using Elf_Shdr = typename ELFT::Shdr;
+ using Elf_Phdr = typename ELFT::Phdr;
+ using Elf_Ehdr = typename ELFT::Ehdr;
+
+ void initEhdrSegment();
+
+ void writeEhdr();
+ void writePhdr(const Segment &Seg);
+ void writeShdr(const SectionBase &Sec);
+
+ void writePhdrs();
+ void writeShdrs();
Error writeSectionData();
- void writeSegmentData();
-
- void assignOffsets();
-
- std::unique_ptr<ELFSectionWriter<ELFT>> SecWriter;
-
- size_t totalSize() const;
-
-public:
- virtual ~ELFWriter() {}
- bool WriteSectionHeaders;
-
- // For --only-keep-debug, select an alternative section/segment layout
- // algorithm.
- bool OnlyKeepDebug;
-
- Error finalize() override;
- Error write() override;
- ELFWriter(Object &Obj, Buffer &Buf, bool WSH, bool OnlyKeepDebug);
-};
-
-class BinaryWriter : public Writer {
-private:
- std::unique_ptr<BinarySectionWriter> SecWriter;
-
- uint64_t TotalSize = 0;
-
-public:
- ~BinaryWriter() {}
- Error finalize() override;
- Error write() override;
- BinaryWriter(Object &Obj, Buffer &Buf) : Writer(Obj, Buf) {}
-};
-
-class IHexWriter : public Writer {
- struct SectionCompare {
- bool operator()(const SectionBase *Lhs, const SectionBase *Rhs) const;
- };
-
- std::set<const SectionBase *, SectionCompare> Sections;
- size_t TotalSize = 0;
-
- Error checkSection(const SectionBase &Sec);
- uint64_t writeEntryPointRecord(uint8_t *Buf);
- uint64_t writeEndOfFileRecord(uint8_t *Buf);
-
-public:
- ~IHexWriter() {}
- Error finalize() override;
- Error write() override;
- IHexWriter(Object &Obj, Buffer &Buf) : Writer(Obj, Buf) {}
-};
-
-class SectionBase {
-public:
- std::string Name;
- Segment *ParentSegment = nullptr;
- uint64_t HeaderOffset = 0;
- uint32_t Index = 0;
-
+ void writeSegmentData();
+
+ void assignOffsets();
+
+ std::unique_ptr<ELFSectionWriter<ELFT>> SecWriter;
+
+ size_t totalSize() const;
+
+public:
+ virtual ~ELFWriter() {}
+ bool WriteSectionHeaders;
+
+ // For --only-keep-debug, select an alternative section/segment layout
+ // algorithm.
+ bool OnlyKeepDebug;
+
+ Error finalize() override;
+ Error write() override;
+ ELFWriter(Object &Obj, Buffer &Buf, bool WSH, bool OnlyKeepDebug);
+};
+
+class BinaryWriter : public Writer {
+private:
+ std::unique_ptr<BinarySectionWriter> SecWriter;
+
+ uint64_t TotalSize = 0;
+
+public:
+ ~BinaryWriter() {}
+ Error finalize() override;
+ Error write() override;
+ BinaryWriter(Object &Obj, Buffer &Buf) : Writer(Obj, Buf) {}
+};
+
+class IHexWriter : public Writer {
+ struct SectionCompare {
+ bool operator()(const SectionBase *Lhs, const SectionBase *Rhs) const;
+ };
+
+ std::set<const SectionBase *, SectionCompare> Sections;
+ size_t TotalSize = 0;
+
+ Error checkSection(const SectionBase &Sec);
+ uint64_t writeEntryPointRecord(uint8_t *Buf);
+ uint64_t writeEndOfFileRecord(uint8_t *Buf);
+
+public:
+ ~IHexWriter() {}
+ Error finalize() override;
+ Error write() override;
+ IHexWriter(Object &Obj, Buffer &Buf) : Writer(Obj, Buf) {}
+};
+
+class SectionBase {
+public:
+ std::string Name;
+ Segment *ParentSegment = nullptr;
+ uint64_t HeaderOffset = 0;
+ uint32_t Index = 0;
+
uint32_t OriginalIndex = 0;
- uint64_t OriginalFlags = 0;
- uint64_t OriginalType = ELF::SHT_NULL;
- uint64_t OriginalOffset = std::numeric_limits<uint64_t>::max();
-
- uint64_t Addr = 0;
- uint64_t Align = 1;
- uint32_t EntrySize = 0;
- uint64_t Flags = 0;
- uint64_t Info = 0;
- uint64_t Link = ELF::SHN_UNDEF;
- uint64_t NameIndex = 0;
- uint64_t Offset = 0;
- uint64_t Size = 0;
- uint64_t Type = ELF::SHT_NULL;
- ArrayRef<uint8_t> OriginalData;
+ uint64_t OriginalFlags = 0;
+ uint64_t OriginalType = ELF::SHT_NULL;
+ uint64_t OriginalOffset = std::numeric_limits<uint64_t>::max();
+
+ uint64_t Addr = 0;
+ uint64_t Align = 1;
+ uint32_t EntrySize = 0;
+ uint64_t Flags = 0;
+ uint64_t Info = 0;
+ uint64_t Link = ELF::SHN_UNDEF;
+ uint64_t NameIndex = 0;
+ uint64_t Offset = 0;
+ uint64_t Size = 0;
+ uint64_t Type = ELF::SHT_NULL;
+ ArrayRef<uint8_t> OriginalData;
bool HasSymbol = false;
-
- SectionBase() = default;
- SectionBase(const SectionBase &) = default;
-
- virtual ~SectionBase() = default;
-
+
+ SectionBase() = default;
+ SectionBase(const SectionBase &) = default;
+
+ virtual ~SectionBase() = default;
+
virtual Error initialize(SectionTableRef SecTable);
- virtual void finalize();
- // Remove references to these sections. The list of sections must be sorted.
- virtual Error
- removeSectionReferences(bool AllowBrokenLinks,
- function_ref<bool(const SectionBase *)> ToRemove);
- virtual Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);
+ virtual void finalize();
+ // Remove references to these sections. The list of sections must be sorted.
+ virtual Error
+ removeSectionReferences(bool AllowBrokenLinks,
+ function_ref<bool(const SectionBase *)> ToRemove);
+ virtual Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);
virtual Error accept(SectionVisitor &Visitor) const = 0;
virtual Error accept(MutableSectionVisitor &Visitor) = 0;
- virtual void markSymbols();
- virtual void
- replaceSectionReferences(const DenseMap<SectionBase *, SectionBase *> &);
- // Notify the section that it is subject to removal.
- virtual void onRemove();
-};
-
-class Segment {
-private:
- struct SectionCompare {
- bool operator()(const SectionBase *Lhs, const SectionBase *Rhs) const {
- // Some sections might have the same address if one of them is empty. To
- // fix this we can use the lexicographic ordering on ->Addr and the
+ virtual void markSymbols();
+ virtual void
+ replaceSectionReferences(const DenseMap<SectionBase *, SectionBase *> &);
+ // Notify the section that it is subject to removal.
+ virtual void onRemove();
+};
+
+class Segment {
+private:
+ struct SectionCompare {
+ bool operator()(const SectionBase *Lhs, const SectionBase *Rhs) const {
+ // Some sections might have the same address if one of them is empty. To
+ // fix this we can use the lexicographic ordering on ->Addr and the
// original index.
- if (Lhs->OriginalOffset == Rhs->OriginalOffset)
+ if (Lhs->OriginalOffset == Rhs->OriginalOffset)
return Lhs->OriginalIndex < Rhs->OriginalIndex;
- return Lhs->OriginalOffset < Rhs->OriginalOffset;
- }
- };
-
-public:
- uint32_t Type = 0;
- uint32_t Flags = 0;
- uint64_t Offset = 0;
- uint64_t VAddr = 0;
- uint64_t PAddr = 0;
- uint64_t FileSize = 0;
- uint64_t MemSize = 0;
- uint64_t Align = 0;
-
- uint32_t Index = 0;
- uint64_t OriginalOffset = 0;
- Segment *ParentSegment = nullptr;
- ArrayRef<uint8_t> Contents;
- std::set<const SectionBase *, SectionCompare> Sections;
-
- explicit Segment(ArrayRef<uint8_t> Data) : Contents(Data) {}
- Segment() = default;
-
- const SectionBase *firstSection() const {
- if (!Sections.empty())
- return *Sections.begin();
- return nullptr;
- }
-
- void removeSection(const SectionBase *Sec) { Sections.erase(Sec); }
- void addSection(const SectionBase *Sec) { Sections.insert(Sec); }
-
- ArrayRef<uint8_t> getContents() const { return Contents; }
-};
-
-class Section : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
-
- ArrayRef<uint8_t> Contents;
- SectionBase *LinkSection = nullptr;
-
-public:
- explicit Section(ArrayRef<uint8_t> Data) : Contents(Data) {}
-
+ return Lhs->OriginalOffset < Rhs->OriginalOffset;
+ }
+ };
+
+public:
+ uint32_t Type = 0;
+ uint32_t Flags = 0;
+ uint64_t Offset = 0;
+ uint64_t VAddr = 0;
+ uint64_t PAddr = 0;
+ uint64_t FileSize = 0;
+ uint64_t MemSize = 0;
+ uint64_t Align = 0;
+
+ uint32_t Index = 0;
+ uint64_t OriginalOffset = 0;
+ Segment *ParentSegment = nullptr;
+ ArrayRef<uint8_t> Contents;
+ std::set<const SectionBase *, SectionCompare> Sections;
+
+ explicit Segment(ArrayRef<uint8_t> Data) : Contents(Data) {}
+ Segment() = default;
+
+ const SectionBase *firstSection() const {
+ if (!Sections.empty())
+ return *Sections.begin();
+ return nullptr;
+ }
+
+ void removeSection(const SectionBase *Sec) { Sections.erase(Sec); }
+ void addSection(const SectionBase *Sec) { Sections.insert(Sec); }
+
+ ArrayRef<uint8_t> getContents() const { return Contents; }
+};
+
+class Section : public SectionBase {
+ MAKE_SEC_WRITER_FRIEND
+
+ ArrayRef<uint8_t> Contents;
+ SectionBase *LinkSection = nullptr;
+
+public:
+ explicit Section(ArrayRef<uint8_t> Data) : Contents(Data) {}
+
Error accept(SectionVisitor &Visitor) const override;
Error accept(MutableSectionVisitor &Visitor) override;
Error removeSectionReferences(
bool AllowBrokenLinks,
- function_ref<bool(const SectionBase *)> ToRemove) override;
+ function_ref<bool(const SectionBase *)> ToRemove) override;
Error initialize(SectionTableRef SecTable) override;
- void finalize() override;
-};
-
-class OwnedDataSection : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
-
- std::vector<uint8_t> Data;
-
-public:
- OwnedDataSection(StringRef SecName, ArrayRef<uint8_t> Data)
- : Data(std::begin(Data), std::end(Data)) {
- Name = SecName.str();
- Type = OriginalType = ELF::SHT_PROGBITS;
- Size = Data.size();
- OriginalOffset = std::numeric_limits<uint64_t>::max();
- }
-
- OwnedDataSection(const Twine &SecName, uint64_t SecAddr, uint64_t SecFlags,
- uint64_t SecOff) {
- Name = SecName.str();
- Type = OriginalType = ELF::SHT_PROGBITS;
- Addr = SecAddr;
- Flags = OriginalFlags = SecFlags;
- OriginalOffset = SecOff;
- }
-
- void appendHexData(StringRef HexData);
+ void finalize() override;
+};
+
+class OwnedDataSection : public SectionBase {
+ MAKE_SEC_WRITER_FRIEND
+
+ std::vector<uint8_t> Data;
+
+public:
+ OwnedDataSection(StringRef SecName, ArrayRef<uint8_t> Data)
+ : Data(std::begin(Data), std::end(Data)) {
+ Name = SecName.str();
+ Type = OriginalType = ELF::SHT_PROGBITS;
+ Size = Data.size();
+ OriginalOffset = std::numeric_limits<uint64_t>::max();
+ }
+
+ OwnedDataSection(const Twine &SecName, uint64_t SecAddr, uint64_t SecFlags,
+ uint64_t SecOff) {
+ Name = SecName.str();
+ Type = OriginalType = ELF::SHT_PROGBITS;
+ Addr = SecAddr;
+ Flags = OriginalFlags = SecFlags;
+ OriginalOffset = SecOff;
+ }
+
+ void appendHexData(StringRef HexData);
Error accept(SectionVisitor &Sec) const override;
Error accept(MutableSectionVisitor &Visitor) override;
-};
-
-class CompressedSection : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
-
- DebugCompressionType CompressionType;
- uint64_t DecompressedSize;
- uint64_t DecompressedAlign;
- SmallVector<char, 128> CompressedData;
-
-public:
+};
+
+class CompressedSection : public SectionBase {
+ MAKE_SEC_WRITER_FRIEND
+
+ DebugCompressionType CompressionType;
+ uint64_t DecompressedSize;
+ uint64_t DecompressedAlign;
+ SmallVector<char, 128> CompressedData;
+
+public:
static Expected<CompressedSection>
create(const SectionBase &Sec, DebugCompressionType CompressionType);
static Expected<CompressedSection> create(ArrayRef<uint8_t> CompressedData,
uint64_t DecompressedSize,
uint64_t DecompressedAlign);
-
- uint64_t getDecompressedSize() const { return DecompressedSize; }
- uint64_t getDecompressedAlign() const { return DecompressedAlign; }
-
+
+ uint64_t getDecompressedSize() const { return DecompressedSize; }
+ uint64_t getDecompressedAlign() const { return DecompressedAlign; }
+
Error accept(SectionVisitor &Visitor) const override;
Error accept(MutableSectionVisitor &Visitor) override;
-
- static bool classof(const SectionBase *S) {
- return (S->OriginalFlags & ELF::SHF_COMPRESSED) ||
- (StringRef(S->Name).startswith(".zdebug"));
- }
+
+ static bool classof(const SectionBase *S) {
+ return (S->OriginalFlags & ELF::SHF_COMPRESSED) ||
+ (StringRef(S->Name).startswith(".zdebug"));
+ }
private:
CompressedSection(const SectionBase &Sec,
DebugCompressionType CompressionType, Error &Err);
CompressedSection(ArrayRef<uint8_t> CompressedData, uint64_t DecompressedSize,
uint64_t DecompressedAlign);
-};
-
-class DecompressedSection : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
-
-public:
- explicit DecompressedSection(const CompressedSection &Sec)
- : SectionBase(Sec) {
- Size = Sec.getDecompressedSize();
- Align = Sec.getDecompressedAlign();
- Flags = OriginalFlags = (Flags & ~ELF::SHF_COMPRESSED);
- if (StringRef(Name).startswith(".zdebug"))
- Name = "." + Name.substr(2);
- }
-
+};
+
+class DecompressedSection : public SectionBase {
+ MAKE_SEC_WRITER_FRIEND
+
+public:
+ explicit DecompressedSection(const CompressedSection &Sec)
+ : SectionBase(Sec) {
+ Size = Sec.getDecompressedSize();
+ Align = Sec.getDecompressedAlign();
+ Flags = OriginalFlags = (Flags & ~ELF::SHF_COMPRESSED);
+ if (StringRef(Name).startswith(".zdebug"))
+ Name = "." + Name.substr(2);
+ }
+
Error accept(SectionVisitor &Visitor) const override;
Error accept(MutableSectionVisitor &Visitor) override;
-};
-
-// There are two types of string tables that can exist, dynamic and not dynamic.
-// In the dynamic case the string table is allocated. Changing a dynamic string
-// table would mean altering virtual addresses and thus the memory image. So
-// dynamic string tables should not have an interface to modify them or
-// reconstruct them. This type lets us reconstruct a string table. To avoid
-// this class being used for dynamic string tables (which has happened) the
-// classof method checks that the particular instance is not allocated. This
-// then agrees with the makeSection method used to construct most sections.
-class StringTableSection : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
-
- StringTableBuilder StrTabBuilder;
-
-public:
- StringTableSection() : StrTabBuilder(StringTableBuilder::ELF) {
- Type = OriginalType = ELF::SHT_STRTAB;
- }
-
- void addString(StringRef Name);
- uint32_t findIndex(StringRef Name) const;
- void prepareForLayout();
+};
+
+// There are two types of string tables that can exist, dynamic and not dynamic.
+// In the dynamic case the string table is allocated. Changing a dynamic string
+// table would mean altering virtual addresses and thus the memory image. So
+// dynamic string tables should not have an interface to modify them or
+// reconstruct them. This type lets us reconstruct a string table. To avoid
+// this class being used for dynamic string tables (which has happened) the
+// classof method checks that the particular instance is not allocated. This
+// then agrees with the makeSection method used to construct most sections.
+class StringTableSection : public SectionBase {
+ MAKE_SEC_WRITER_FRIEND
+
+ StringTableBuilder StrTabBuilder;
+
+public:
+ StringTableSection() : StrTabBuilder(StringTableBuilder::ELF) {
+ Type = OriginalType = ELF::SHT_STRTAB;
+ }
+
+ void addString(StringRef Name);
+ uint32_t findIndex(StringRef Name) const;
+ void prepareForLayout();
Error accept(SectionVisitor &Visitor) const override;
Error accept(MutableSectionVisitor &Visitor) override;
-
- static bool classof(const SectionBase *S) {
- if (S->OriginalFlags & ELF::SHF_ALLOC)
- return false;
- return S->OriginalType == ELF::SHT_STRTAB;
- }
-};
-
-// Symbols have a st_shndx field that normally stores an index but occasionally
-// stores a different special value. This enum keeps track of what the st_shndx
-// field means. Most of the values are just copies of the special SHN_* values.
-// SYMBOL_SIMPLE_INDEX means that the st_shndx is just an index of a section.
-enum SymbolShndxType {
- SYMBOL_SIMPLE_INDEX = 0,
- SYMBOL_ABS = ELF::SHN_ABS,
- SYMBOL_COMMON = ELF::SHN_COMMON,
- SYMBOL_LOPROC = ELF::SHN_LOPROC,
- SYMBOL_AMDGPU_LDS = ELF::SHN_AMDGPU_LDS,
- SYMBOL_HEXAGON_SCOMMON = ELF::SHN_HEXAGON_SCOMMON,
- SYMBOL_HEXAGON_SCOMMON_2 = ELF::SHN_HEXAGON_SCOMMON_2,
- SYMBOL_HEXAGON_SCOMMON_4 = ELF::SHN_HEXAGON_SCOMMON_4,
- SYMBOL_HEXAGON_SCOMMON_8 = ELF::SHN_HEXAGON_SCOMMON_8,
- SYMBOL_HIPROC = ELF::SHN_HIPROC,
- SYMBOL_LOOS = ELF::SHN_LOOS,
- SYMBOL_HIOS = ELF::SHN_HIOS,
- SYMBOL_XINDEX = ELF::SHN_XINDEX,
-};
-
-struct Symbol {
- uint8_t Binding;
- SectionBase *DefinedIn = nullptr;
- SymbolShndxType ShndxType;
- uint32_t Index;
- std::string Name;
- uint32_t NameIndex;
- uint64_t Size;
- uint8_t Type;
- uint64_t Value;
- uint8_t Visibility;
- bool Referenced = false;
-
- uint16_t getShndx() const;
- bool isCommon() const;
-};
-
-class SectionIndexSection : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
-
-private:
- std::vector<uint32_t> Indexes;
- SymbolTableSection *Symbols = nullptr;
-
-public:
- virtual ~SectionIndexSection() {}
- void addIndex(uint32_t Index) {
- assert(Size > 0);
+
+ static bool classof(const SectionBase *S) {
+ if (S->OriginalFlags & ELF::SHF_ALLOC)
+ return false;
+ return S->OriginalType == ELF::SHT_STRTAB;
+ }
+};
+
+// Symbols have a st_shndx field that normally stores an index but occasionally
+// stores a different special value. This enum keeps track of what the st_shndx
+// field means. Most of the values are just copies of the special SHN_* values.
+// SYMBOL_SIMPLE_INDEX means that the st_shndx is just an index of a section.
+enum SymbolShndxType {
+ SYMBOL_SIMPLE_INDEX = 0,
+ SYMBOL_ABS = ELF::SHN_ABS,
+ SYMBOL_COMMON = ELF::SHN_COMMON,
+ SYMBOL_LOPROC = ELF::SHN_LOPROC,
+ SYMBOL_AMDGPU_LDS = ELF::SHN_AMDGPU_LDS,
+ SYMBOL_HEXAGON_SCOMMON = ELF::SHN_HEXAGON_SCOMMON,
+ SYMBOL_HEXAGON_SCOMMON_2 = ELF::SHN_HEXAGON_SCOMMON_2,
+ SYMBOL_HEXAGON_SCOMMON_4 = ELF::SHN_HEXAGON_SCOMMON_4,
+ SYMBOL_HEXAGON_SCOMMON_8 = ELF::SHN_HEXAGON_SCOMMON_8,
+ SYMBOL_HIPROC = ELF::SHN_HIPROC,
+ SYMBOL_LOOS = ELF::SHN_LOOS,
+ SYMBOL_HIOS = ELF::SHN_HIOS,
+ SYMBOL_XINDEX = ELF::SHN_XINDEX,
+};
+
+struct Symbol {
+ uint8_t Binding;
+ SectionBase *DefinedIn = nullptr;
+ SymbolShndxType ShndxType;
+ uint32_t Index;
+ std::string Name;
+ uint32_t NameIndex;
+ uint64_t Size;
+ uint8_t Type;
+ uint64_t Value;
+ uint8_t Visibility;
+ bool Referenced = false;
+
+ uint16_t getShndx() const;
+ bool isCommon() const;
+};
+
+class SectionIndexSection : public SectionBase {
+ MAKE_SEC_WRITER_FRIEND
+
+private:
+ std::vector<uint32_t> Indexes;
+ SymbolTableSection *Symbols = nullptr;
+
+public:
+ virtual ~SectionIndexSection() {}
+ void addIndex(uint32_t Index) {
+ assert(Size > 0);
Indexes.push_back(Index);
+ }
+
+ void reserve(size_t NumSymbols) {
+ Indexes.reserve(NumSymbols);
+ Size = NumSymbols * 4;
}
-
- void reserve(size_t NumSymbols) {
- Indexes.reserve(NumSymbols);
- Size = NumSymbols * 4;
- }
- void setSymTab(SymbolTableSection *SymTab) { Symbols = SymTab; }
+ void setSymTab(SymbolTableSection *SymTab) { Symbols = SymTab; }
Error initialize(SectionTableRef SecTable) override;
- void finalize() override;
+ void finalize() override;
Error accept(SectionVisitor &Visitor) const override;
Error accept(MutableSectionVisitor &Visitor) override;
-
- SectionIndexSection() {
- Name = ".symtab_shndx";
- Align = 4;
- EntrySize = 4;
- Type = OriginalType = ELF::SHT_SYMTAB_SHNDX;
- }
-};
-
-class SymbolTableSection : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
-
- void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; }
- void assignIndices();
-
-protected:
- std::vector<std::unique_ptr<Symbol>> Symbols;
- StringTableSection *SymbolNames = nullptr;
- SectionIndexSection *SectionIndexTable = nullptr;
-
- using SymPtr = std::unique_ptr<Symbol>;
-
-public:
- SymbolTableSection() { Type = OriginalType = ELF::SHT_SYMTAB; }
-
- void addSymbol(Twine Name, uint8_t Bind, uint8_t Type, SectionBase *DefinedIn,
- uint64_t Value, uint8_t Visibility, uint16_t Shndx,
- uint64_t SymbolSize);
- void prepareForLayout();
- // An 'empty' symbol table still contains a null symbol.
- bool empty() const { return Symbols.size() == 1; }
- void setShndxTable(SectionIndexSection *ShndxTable) {
- SectionIndexTable = ShndxTable;
- }
- const SectionIndexSection *getShndxTable() const { return SectionIndexTable; }
- void fillShndxTable();
- const SectionBase *getStrTab() const { return SymbolNames; }
+
+ SectionIndexSection() {
+ Name = ".symtab_shndx";
+ Align = 4;
+ EntrySize = 4;
+ Type = OriginalType = ELF::SHT_SYMTAB_SHNDX;
+ }
+};
+
+class SymbolTableSection : public SectionBase {
+ MAKE_SEC_WRITER_FRIEND
+
+ void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; }
+ void assignIndices();
+
+protected:
+ std::vector<std::unique_ptr<Symbol>> Symbols;
+ StringTableSection *SymbolNames = nullptr;
+ SectionIndexSection *SectionIndexTable = nullptr;
+
+ using SymPtr = std::unique_ptr<Symbol>;
+
+public:
+ SymbolTableSection() { Type = OriginalType = ELF::SHT_SYMTAB; }
+
+ void addSymbol(Twine Name, uint8_t Bind, uint8_t Type, SectionBase *DefinedIn,
+ uint64_t Value, uint8_t Visibility, uint16_t Shndx,
+ uint64_t SymbolSize);
+ void prepareForLayout();
+ // An 'empty' symbol table still contains a null symbol.
+ bool empty() const { return Symbols.size() == 1; }
+ void setShndxTable(SectionIndexSection *ShndxTable) {
+ SectionIndexTable = ShndxTable;
+ }
+ const SectionIndexSection *getShndxTable() const { return SectionIndexTable; }
+ void fillShndxTable();
+ const SectionBase *getStrTab() const { return SymbolNames; }
Expected<const Symbol *> getSymbolByIndex(uint32_t Index) const;
Expected<Symbol *> getSymbolByIndex(uint32_t Index);
- void updateSymbols(function_ref<void(Symbol &)> Callable);
-
+ void updateSymbols(function_ref<void(Symbol &)> Callable);
+
Error removeSectionReferences(
bool AllowBrokenLinks,
- function_ref<bool(const SectionBase *)> ToRemove) override;
+ function_ref<bool(const SectionBase *)> ToRemove) override;
Error initialize(SectionTableRef SecTable) override;
- void finalize() override;
+ void finalize() override;
Error accept(SectionVisitor &Visitor) const override;
Error accept(MutableSectionVisitor &Visitor) override;
- Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
- void replaceSectionReferences(
- const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
-
- static bool classof(const SectionBase *S) {
- return S->OriginalType == ELF::SHT_SYMTAB;
- }
-};
-
-struct Relocation {
- Symbol *RelocSymbol = nullptr;
- uint64_t Offset;
- uint64_t Addend;
- uint32_t Type;
-};
-
-// All relocation sections denote relocations to apply to another section.
-// However, some relocation sections use a dynamic symbol table and others use
-// a regular symbol table. Because the types of the two symbol tables differ in
-// our system (because they should behave differently) we can't uniformly
-// represent all relocations with the same base class if we expose an interface
-// that mentions the symbol table type. So we split the two base types into two
-// different classes, one which handles the section the relocation is applied to
-// and another which handles the symbol table type. The symbol table type is
-// taken as a type parameter to the class (see RelocSectionWithSymtabBase).
-class RelocationSectionBase : public SectionBase {
-protected:
- SectionBase *SecToApplyRel = nullptr;
-
-public:
- const SectionBase *getSection() const { return SecToApplyRel; }
- void setSection(SectionBase *Sec) { SecToApplyRel = Sec; }
-
- static bool classof(const SectionBase *S) {
- return S->OriginalType == ELF::SHT_REL || S->OriginalType == ELF::SHT_RELA;
- }
-};
-
-// Takes the symbol table type to use as a parameter so that we can deduplicate
-// that code between the two symbol table types.
-template <class SymTabType>
-class RelocSectionWithSymtabBase : public RelocationSectionBase {
- void setSymTab(SymTabType *SymTab) { Symbols = SymTab; }
-
-protected:
- RelocSectionWithSymtabBase() = default;
-
- SymTabType *Symbols = nullptr;
-
-public:
+ Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
+ void replaceSectionReferences(
+ const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
+
+ static bool classof(const SectionBase *S) {
+ return S->OriginalType == ELF::SHT_SYMTAB;
+ }
+};
+
+struct Relocation {
+ Symbol *RelocSymbol = nullptr;
+ uint64_t Offset;
+ uint64_t Addend;
+ uint32_t Type;
+};
+
+// All relocation sections denote relocations to apply to another section.
+// However, some relocation sections use a dynamic symbol table and others use
+// a regular symbol table. Because the types of the two symbol tables differ in
+// our system (because they should behave differently) we can't uniformly
+// represent all relocations with the same base class if we expose an interface
+// that mentions the symbol table type. So we split the two base types into two
+// different classes, one which handles the section the relocation is applied to
+// and another which handles the symbol table type. The symbol table type is
+// taken as a type parameter to the class (see RelocSectionWithSymtabBase).
+class RelocationSectionBase : public SectionBase {
+protected:
+ SectionBase *SecToApplyRel = nullptr;
+
+public:
+ const SectionBase *getSection() const { return SecToApplyRel; }
+ void setSection(SectionBase *Sec) { SecToApplyRel = Sec; }
+
+ static bool classof(const SectionBase *S) {
+ return S->OriginalType == ELF::SHT_REL || S->OriginalType == ELF::SHT_RELA;
+ }
+};
+
+// Takes the symbol table type to use as a parameter so that we can deduplicate
+// that code between the two symbol table types.
+template <class SymTabType>
+class RelocSectionWithSymtabBase : public RelocationSectionBase {
+ void setSymTab(SymTabType *SymTab) { Symbols = SymTab; }
+
+protected:
+ RelocSectionWithSymtabBase() = default;
+
+ SymTabType *Symbols = nullptr;
+
+public:
Error initialize(SectionTableRef SecTable) override;
- void finalize() override;
-};
-
-class RelocationSection
- : public RelocSectionWithSymtabBase<SymbolTableSection> {
- MAKE_SEC_WRITER_FRIEND
-
- std::vector<Relocation> Relocations;
-
-public:
- void addRelocation(Relocation Rel) { Relocations.push_back(Rel); }
+ void finalize() override;
+};
+
+class RelocationSection
+ : public RelocSectionWithSymtabBase<SymbolTableSection> {
+ MAKE_SEC_WRITER_FRIEND
+
+ std::vector<Relocation> Relocations;
+
+public:
+ void addRelocation(Relocation Rel) { Relocations.push_back(Rel); }
Error accept(SectionVisitor &Visitor) const override;
Error accept(MutableSectionVisitor &Visitor) override;
Error removeSectionReferences(
bool AllowBrokenLinks,
- function_ref<bool(const SectionBase *)> ToRemove) override;
- Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
- void markSymbols() override;
- void replaceSectionReferences(
- const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
-
- static bool classof(const SectionBase *S) {
- if (S->OriginalFlags & ELF::SHF_ALLOC)
- return false;
- return S->OriginalType == ELF::SHT_REL || S->OriginalType == ELF::SHT_RELA;
- }
-};
-
-// TODO: The way stripping and groups interact is complicated
-// and still needs to be worked on.
-
-class GroupSection : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
- const SymbolTableSection *SymTab = nullptr;
- Symbol *Sym = nullptr;
- ELF::Elf32_Word FlagWord;
- SmallVector<SectionBase *, 3> GroupMembers;
-
-public:
- // TODO: Contents is present in several classes of the hierarchy.
- // This needs to be refactored to avoid duplication.
- ArrayRef<uint8_t> Contents;
-
- explicit GroupSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
-
- void setSymTab(const SymbolTableSection *SymTabSec) { SymTab = SymTabSec; }
- void setSymbol(Symbol *S) { Sym = S; }
- void setFlagWord(ELF::Elf32_Word W) { FlagWord = W; }
- void addMember(SectionBase *Sec) { GroupMembers.push_back(Sec); }
-
+ function_ref<bool(const SectionBase *)> ToRemove) override;
+ Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
+ void markSymbols() override;
+ void replaceSectionReferences(
+ const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
+
+ static bool classof(const SectionBase *S) {
+ if (S->OriginalFlags & ELF::SHF_ALLOC)
+ return false;
+ return S->OriginalType == ELF::SHT_REL || S->OriginalType == ELF::SHT_RELA;
+ }
+};
+
+// TODO: The way stripping and groups interact is complicated
+// and still needs to be worked on.
+
+class GroupSection : public SectionBase {
+ MAKE_SEC_WRITER_FRIEND
+ const SymbolTableSection *SymTab = nullptr;
+ Symbol *Sym = nullptr;
+ ELF::Elf32_Word FlagWord;
+ SmallVector<SectionBase *, 3> GroupMembers;
+
+public:
+ // TODO: Contents is present in several classes of the hierarchy.
+ // This needs to be refactored to avoid duplication.
+ ArrayRef<uint8_t> Contents;
+
+ explicit GroupSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
+
+ void setSymTab(const SymbolTableSection *SymTabSec) { SymTab = SymTabSec; }
+ void setSymbol(Symbol *S) { Sym = S; }
+ void setFlagWord(ELF::Elf32_Word W) { FlagWord = W; }
+ void addMember(SectionBase *Sec) { GroupMembers.push_back(Sec); }
+
Error accept(SectionVisitor &) const override;
Error accept(MutableSectionVisitor &Visitor) override;
- void finalize() override;
- Error removeSectionReferences(
- bool AllowBrokenLinks,
- function_ref<bool(const SectionBase *)> ToRemove) override;
- Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
- void markSymbols() override;
- void replaceSectionReferences(
- const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
- void onRemove() override;
-
- static bool classof(const SectionBase *S) {
- return S->OriginalType == ELF::SHT_GROUP;
- }
-};
-
-class DynamicSymbolTableSection : public Section {
-public:
- explicit DynamicSymbolTableSection(ArrayRef<uint8_t> Data) : Section(Data) {}
-
- static bool classof(const SectionBase *S) {
- return S->OriginalType == ELF::SHT_DYNSYM;
- }
-};
-
-class DynamicSection : public Section {
-public:
- explicit DynamicSection(ArrayRef<uint8_t> Data) : Section(Data) {}
-
- static bool classof(const SectionBase *S) {
- return S->OriginalType == ELF::SHT_DYNAMIC;
- }
-};
-
-class DynamicRelocationSection
- : public RelocSectionWithSymtabBase<DynamicSymbolTableSection> {
- MAKE_SEC_WRITER_FRIEND
-
-private:
- ArrayRef<uint8_t> Contents;
-
-public:
- explicit DynamicRelocationSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
-
+ void finalize() override;
+ Error removeSectionReferences(
+ bool AllowBrokenLinks,
+ function_ref<bool(const SectionBase *)> ToRemove) override;
+ Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove) override;
+ void markSymbols() override;
+ void replaceSectionReferences(
+ const DenseMap<SectionBase *, SectionBase *> &FromTo) override;
+ void onRemove() override;
+
+ static bool classof(const SectionBase *S) {
+ return S->OriginalType == ELF::SHT_GROUP;
+ }
+};
+
+class DynamicSymbolTableSection : public Section {
+public:
+ explicit DynamicSymbolTableSection(ArrayRef<uint8_t> Data) : Section(Data) {}
+
+ static bool classof(const SectionBase *S) {
+ return S->OriginalType == ELF::SHT_DYNSYM;
+ }
+};
+
+class DynamicSection : public Section {
+public:
+ explicit DynamicSection(ArrayRef<uint8_t> Data) : Section(Data) {}
+
+ static bool classof(const SectionBase *S) {
+ return S->OriginalType == ELF::SHT_DYNAMIC;
+ }
+};
+
+class DynamicRelocationSection
+ : public RelocSectionWithSymtabBase<DynamicSymbolTableSection> {
+ MAKE_SEC_WRITER_FRIEND
+
+private:
+ ArrayRef<uint8_t> Contents;
+
+public:
+ explicit DynamicRelocationSection(ArrayRef<uint8_t> Data) : Contents(Data) {}
+
Error accept(SectionVisitor &) const override;
Error accept(MutableSectionVisitor &Visitor) override;
- Error removeSectionReferences(
- bool AllowBrokenLinks,
- function_ref<bool(const SectionBase *)> ToRemove) override;
-
- static bool classof(const SectionBase *S) {
- if (!(S->OriginalFlags & ELF::SHF_ALLOC))
- return false;
- return S->OriginalType == ELF::SHT_REL || S->OriginalType == ELF::SHT_RELA;
- }
-};
-
-class GnuDebugLinkSection : public SectionBase {
- MAKE_SEC_WRITER_FRIEND
-
-private:
- StringRef FileName;
- uint32_t CRC32;
-
- void init(StringRef File);
-
-public:
- // If we add this section from an external source we can use this ctor.
- explicit GnuDebugLinkSection(StringRef File, uint32_t PrecomputedCRC);
+ Error removeSectionReferences(
+ bool AllowBrokenLinks,
+ function_ref<bool(const SectionBase *)> ToRemove) override;
+
+ static bool classof(const SectionBase *S) {
+ if (!(S->OriginalFlags & ELF::SHF_ALLOC))
+ return false;
+ return S->OriginalType == ELF::SHT_REL || S->OriginalType == ELF::SHT_RELA;
+ }
+};
+
+class GnuDebugLinkSection : public SectionBase {
+ MAKE_SEC_WRITER_FRIEND
+
+private:
+ StringRef FileName;
+ uint32_t CRC32;
+
+ void init(StringRef File);
+
+public:
+ // If we add this section from an external source we can use this ctor.
+ explicit GnuDebugLinkSection(StringRef File, uint32_t PrecomputedCRC);
Error accept(SectionVisitor &Visitor) const override;
Error accept(MutableSectionVisitor &Visitor) override;
-};
-
-class Reader {
-public:
- virtual ~Reader();
+};
+
+class Reader {
+public:
+ virtual ~Reader();
virtual Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const = 0;
-};
-
-using object::Binary;
-using object::ELFFile;
-using object::ELFObjectFile;
-using object::OwningBinary;
-
-class BasicELFBuilder {
-protected:
- std::unique_ptr<Object> Obj;
-
- void initFileHeader();
- void initHeaderSegment();
- StringTableSection *addStrTab();
- SymbolTableSection *addSymTab(StringTableSection *StrTab);
+};
+
+using object::Binary;
+using object::ELFFile;
+using object::ELFObjectFile;
+using object::OwningBinary;
+
+class BasicELFBuilder {
+protected:
+ std::unique_ptr<Object> Obj;
+
+ void initFileHeader();
+ void initHeaderSegment();
+ StringTableSection *addStrTab();
+ SymbolTableSection *addSymTab(StringTableSection *StrTab);
Error initSections();
-
-public:
- BasicELFBuilder() : Obj(std::make_unique<Object>()) {}
-};
-
-class BinaryELFBuilder : public BasicELFBuilder {
- MemoryBuffer *MemBuf;
- uint8_t NewSymbolVisibility;
- void addData(SymbolTableSection *SymTab);
-
-public:
- BinaryELFBuilder(MemoryBuffer *MB, uint8_t NewSymbolVisibility)
- : BasicELFBuilder(), MemBuf(MB),
- NewSymbolVisibility(NewSymbolVisibility) {}
-
+
+public:
+ BasicELFBuilder() : Obj(std::make_unique<Object>()) {}
+};
+
+class BinaryELFBuilder : public BasicELFBuilder {
+ MemoryBuffer *MemBuf;
+ uint8_t NewSymbolVisibility;
+ void addData(SymbolTableSection *SymTab);
+
+public:
+ BinaryELFBuilder(MemoryBuffer *MB, uint8_t NewSymbolVisibility)
+ : BasicELFBuilder(), MemBuf(MB),
+ NewSymbolVisibility(NewSymbolVisibility) {}
+
Expected<std::unique_ptr<Object>> build();
-};
-
-class IHexELFBuilder : public BasicELFBuilder {
- const std::vector<IHexRecord> &Records;
-
- void addDataSections();
-
-public:
- IHexELFBuilder(const std::vector<IHexRecord> &Records)
- : BasicELFBuilder(), Records(Records) {}
-
+};
+
+class IHexELFBuilder : public BasicELFBuilder {
+ const std::vector<IHexRecord> &Records;
+
+ void addDataSections();
+
+public:
+ IHexELFBuilder(const std::vector<IHexRecord> &Records)
+ : BasicELFBuilder(), Records(Records) {}
+
Expected<std::unique_ptr<Object>> build();
-};
-
-template <class ELFT> class ELFBuilder {
-private:
- using Elf_Addr = typename ELFT::Addr;
- using Elf_Shdr = typename ELFT::Shdr;
- using Elf_Word = typename ELFT::Word;
-
- const ELFFile<ELFT> &ElfFile;
- Object &Obj;
- size_t EhdrOffset = 0;
- Optional<StringRef> ExtractPartition;
-
- void setParentSegment(Segment &Child);
+};
+
+template <class ELFT> class ELFBuilder {
+private:
+ using Elf_Addr = typename ELFT::Addr;
+ using Elf_Shdr = typename ELFT::Shdr;
+ using Elf_Word = typename ELFT::Word;
+
+ const ELFFile<ELFT> &ElfFile;
+ Object &Obj;
+ size_t EhdrOffset = 0;
+ Optional<StringRef> ExtractPartition;
+
+ void setParentSegment(Segment &Child);
Error readProgramHeaders(const ELFFile<ELFT> &HeadersFile);
Error initGroupSection(GroupSection *GroupSec);
Error initSymbolTable(SymbolTableSection *SymTab);
@@ -953,149 +953,149 @@ private:
Error readSections(bool EnsureSymtab);
Error findEhdrOffset();
Expected<SectionBase &> makeSection(const Elf_Shdr &Shdr);
-
-public:
- ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj,
- Optional<StringRef> ExtractPartition)
+
+public:
+ ELFBuilder(const ELFObjectFile<ELFT> &ElfObj, Object &Obj,
+ Optional<StringRef> ExtractPartition)
: ElfFile(ElfObj.getELFFile()), Obj(Obj),
- ExtractPartition(ExtractPartition) {}
-
+ ExtractPartition(ExtractPartition) {}
+
Error build(bool EnsureSymtab);
-};
-
-class BinaryReader : public Reader {
- MemoryBuffer *MemBuf;
- uint8_t NewSymbolVisibility;
-
-public:
- BinaryReader(MemoryBuffer *MB, const uint8_t NewSymbolVisibility)
- : MemBuf(MB), NewSymbolVisibility(NewSymbolVisibility) {}
+};
+
+class BinaryReader : public Reader {
+ MemoryBuffer *MemBuf;
+ uint8_t NewSymbolVisibility;
+
+public:
+ BinaryReader(MemoryBuffer *MB, const uint8_t NewSymbolVisibility)
+ : MemBuf(MB), NewSymbolVisibility(NewSymbolVisibility) {}
Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;
-};
-
-class IHexReader : public Reader {
- MemoryBuffer *MemBuf;
-
- Expected<std::vector<IHexRecord>> parse() const;
- Error parseError(size_t LineNo, Error E) const {
- return LineNo == -1U
- ? createFileError(MemBuf->getBufferIdentifier(), std::move(E))
- : createFileError(MemBuf->getBufferIdentifier(), LineNo,
- std::move(E));
- }
- template <typename... Ts>
- Error parseError(size_t LineNo, char const *Fmt, const Ts &... Vals) const {
- Error E = createStringError(errc::invalid_argument, Fmt, Vals...);
- return parseError(LineNo, std::move(E));
- }
-
-public:
- IHexReader(MemoryBuffer *MB) : MemBuf(MB) {}
-
+};
+
+class IHexReader : public Reader {
+ MemoryBuffer *MemBuf;
+
+ Expected<std::vector<IHexRecord>> parse() const;
+ Error parseError(size_t LineNo, Error E) const {
+ return LineNo == -1U
+ ? createFileError(MemBuf->getBufferIdentifier(), std::move(E))
+ : createFileError(MemBuf->getBufferIdentifier(), LineNo,
+ std::move(E));
+ }
+ template <typename... Ts>
+ Error parseError(size_t LineNo, char const *Fmt, const Ts &... Vals) const {
+ Error E = createStringError(errc::invalid_argument, Fmt, Vals...);
+ return parseError(LineNo, std::move(E));
+ }
+
+public:
+ IHexReader(MemoryBuffer *MB) : MemBuf(MB) {}
+
Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;
-};
-
-class ELFReader : public Reader {
- Binary *Bin;
- Optional<StringRef> ExtractPartition;
-
-public:
+};
+
+class ELFReader : public Reader {
+ Binary *Bin;
+ Optional<StringRef> ExtractPartition;
+
+public:
Expected<std::unique_ptr<Object>> create(bool EnsureSymtab) const override;
- explicit ELFReader(Binary *B, Optional<StringRef> ExtractPartition)
- : Bin(B), ExtractPartition(ExtractPartition) {}
-};
-
-class Object {
-private:
- using SecPtr = std::unique_ptr<SectionBase>;
- using SegPtr = std::unique_ptr<Segment>;
-
- std::vector<SecPtr> Sections;
- 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<
- pointee_iterator<typename std::vector<std::unique_ptr<T>>::iterator>>;
-
- template <class T>
- using ConstRange = iterator_range<pointee_iterator<
- typename std::vector<std::unique_ptr<T>>::const_iterator>>;
-
- // It is often the case that the ELF header and the program header table are
- // not present in any segment. This could be a problem during file layout,
- // because other segments may get assigned an offset where either of the
- // two should reside, which will effectively corrupt the resulting binary.
- // Other than that we use these segments to track program header offsets
- // when they may not follow the ELF header.
- Segment ElfHdrSegment;
- Segment ProgramHdrSegment;
-
- uint8_t OSABI;
- uint8_t ABIVersion;
- uint64_t Entry;
- 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;
-
- void sortSections();
- SectionTableRef sections() { return SectionTableRef(Sections); }
- 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; });
- return SecIt == Sections.end() ? nullptr : SecIt->get();
- }
- SectionTableRef removedSections() { return SectionTableRef(RemovedSections); }
-
- Range<Segment> segments() { return make_pointee_range(Segments); }
- ConstRange<Segment> segments() const { return make_pointee_range(Segments); }
-
- Error removeSections(bool AllowBrokenLinks,
- 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 = 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;
- }
+ explicit ELFReader(Binary *B, Optional<StringRef> ExtractPartition)
+ : Bin(B), ExtractPartition(ExtractPartition) {}
+};
+
+class Object {
+private:
+ using SecPtr = std::unique_ptr<SectionBase>;
+ using SegPtr = std::unique_ptr<Segment>;
+
+ std::vector<SecPtr> Sections;
+ 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<
+ pointee_iterator<typename std::vector<std::unique_ptr<T>>::iterator>>;
+
+ template <class T>
+ using ConstRange = iterator_range<pointee_iterator<
+ typename std::vector<std::unique_ptr<T>>::const_iterator>>;
+
+ // It is often the case that the ELF header and the program header table are
+ // not present in any segment. This could be a problem during file layout,
+ // because other segments may get assigned an offset where either of the
+ // two should reside, which will effectively corrupt the resulting binary.
+ // Other than that we use these segments to track program header offsets
+ // when they may not follow the ELF header.
+ Segment ElfHdrSegment;
+ Segment ProgramHdrSegment;
+
+ uint8_t OSABI;
+ uint8_t ABIVersion;
+ uint64_t Entry;
+ 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;
+
+ void sortSections();
+ SectionTableRef sections() { return SectionTableRef(Sections); }
+ 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; });
+ return SecIt == Sections.end() ? nullptr : SecIt->get();
+ }
+ SectionTableRef removedSections() { return SectionTableRef(RemovedSections); }
+
+ Range<Segment> segments() { return make_pointee_range(Segments); }
+ ConstRange<Segment> segments() const { return make_pointee_range(Segments); }
+
+ Error removeSections(bool AllowBrokenLinks,
+ 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 = 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;
+ }
Error addNewSymbolTable();
- Segment &addSegment(ArrayRef<uint8_t> 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
-} // end namespace objcopy
-} // end namespace llvm
-
-#endif // LLVM_TOOLS_OBJCOPY_OBJECT_H
+ Segment &addSegment(ArrayRef<uint8_t> 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
+} // end namespace objcopy
+} // end namespace llvm
+
+#endif // LLVM_TOOLS_OBJCOPY_OBJECT_H