2017-11-02 05:16:06 +08:00
|
|
|
//===- llvm-objcopy.cpp ---------------------------------------------------===//
|
2017-08-01 08:33:58 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
2017-08-01 08:33:58 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2017-11-02 05:16:06 +08:00
|
|
|
|
2020-10-24 22:35:55 +08:00
|
|
|
#include "llvm-objcopy.h"
|
2020-01-30 09:30:57 +08:00
|
|
|
#include "COFF/COFFObjcopy.h"
|
2018-10-12 06:33:50 +08:00
|
|
|
#include "CopyConfig.h"
|
2018-10-30 05:22:58 +08:00
|
|
|
#include "ELF/ELFObjcopy.h"
|
2019-02-02 08:38:07 +08:00
|
|
|
#include "MachO/MachOObjcopy.h"
|
2020-01-30 09:30:57 +08:00
|
|
|
#include "wasm/WasmObjcopy.h"
|
2018-10-12 06:33:50 +08:00
|
|
|
|
2017-11-02 05:16:06 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2018-08-02 00:23:22 +08:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2017-11-02 05:16:06 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/ADT/Twine.h"
|
2020-10-24 22:35:55 +08:00
|
|
|
#include "llvm/BinaryFormat/ELF.h"
|
2018-07-07 01:51:03 +08:00
|
|
|
#include "llvm/Object/Archive.h"
|
|
|
|
#include "llvm/Object/ArchiveWriter.h"
|
2017-11-02 05:16:06 +08:00
|
|
|
#include "llvm/Object/Binary.h"
|
2018-12-19 15:24:38 +08:00
|
|
|
#include "llvm/Object/COFF.h"
|
2017-11-02 05:16:06 +08:00
|
|
|
#include "llvm/Object/ELFObjectFile.h"
|
|
|
|
#include "llvm/Object/ELFTypes.h"
|
|
|
|
#include "llvm/Object/Error.h"
|
2019-02-02 08:38:07 +08:00
|
|
|
#include "llvm/Object/MachO.h"
|
2020-10-06 18:41:19 +08:00
|
|
|
#include "llvm/Object/MachOUniversal.h"
|
2020-01-30 09:30:57 +08:00
|
|
|
#include "llvm/Object/Wasm.h"
|
2018-04-24 13:43:32 +08:00
|
|
|
#include "llvm/Option/Arg.h"
|
|
|
|
#include "llvm/Option/ArgList.h"
|
|
|
|
#include "llvm/Option/Option.h"
|
2017-11-02 05:16:06 +08:00
|
|
|
#include "llvm/Support/Casting.h"
|
2019-09-14 09:14:43 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2020-10-24 22:35:55 +08:00
|
|
|
#include "llvm/Support/Errc.h"
|
2017-11-02 05:16:06 +08:00
|
|
|
#include "llvm/Support/Error.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#include "llvm/Support/ErrorOr.h"
|
2020-03-12 06:39:28 +08:00
|
|
|
#include "llvm/Support/Host.h"
|
2018-04-14 02:26:06 +08:00
|
|
|
#include "llvm/Support/InitLLVM.h"
|
[llvm-objcopy] Add support for -I binary -B <arch>.
Summary:
The -I (--input-target) and -B (--binary-architecture) flags exist but are currently silently ignored. This adds support for -I binary for architectures i386, x86-64 (and alias i386:x86-64), arm, aarch64, sparc, and ppc (powerpc:common64). This is largely based on D41687.
This is done by implementing an additional subclass of Reader, BinaryReader, which works by interpreting the input file as contents for .data field, sets up a synthetic header, and adds additional sections/symbols (e.g. _binary__tmp_data_txt_start).
Reviewers: jakehehrlich, alexshap, jhenderson, javed.absar
Reviewed By: jhenderson
Subscribers: jyknight, nemanjai, kbarton, fedor.sergeev, jrtc27, kristof.beyls, paulsemel, llvm-commits
Differential Revision: https://reviews.llvm.org/D50343
llvm-svn: 340070
2018-08-18 02:51:11 +08:00
|
|
|
#include "llvm/Support/Memory.h"
|
2018-05-08 03:32:09 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
2018-08-17 02:29:40 +08:00
|
|
|
#include "llvm/Support/Process.h"
|
2020-10-24 22:35:55 +08:00
|
|
|
#include "llvm/Support/SmallVectorMemoryBuffer.h"
|
2019-09-14 09:14:43 +08:00
|
|
|
#include "llvm/Support/StringSaver.h"
|
2018-08-10 06:52:03 +08:00
|
|
|
#include "llvm/Support/WithColor.h"
|
2017-11-02 05:16:06 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstdlib>
|
2017-08-01 08:33:58 +08:00
|
|
|
#include <memory>
|
|
|
|
#include <string>
|
|
|
|
#include <system_error>
|
2017-11-02 05:16:06 +08:00
|
|
|
#include <utility>
|
2017-08-01 08:33:58 +08:00
|
|
|
|
2018-07-18 08:10:51 +08:00
|
|
|
namespace llvm {
|
|
|
|
namespace objcopy {
|
|
|
|
|
2020-10-24 22:35:55 +08:00
|
|
|
Error writeToFile(StringRef OutputFileName,
|
2021-03-12 21:31:35 +08:00
|
|
|
std::function<Error(raw_ostream &)> Write) {
|
2020-10-24 22:35:55 +08:00
|
|
|
if (OutputFileName == "-")
|
|
|
|
return Write(outs());
|
|
|
|
|
|
|
|
if (OutputFileName == "/dev/null") {
|
|
|
|
raw_null_ostream Out;
|
|
|
|
return Write(Out);
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned Mode = sys::fs::all_read | sys::fs::all_write | sys::fs::all_exe;
|
|
|
|
Expected<sys::fs::TempFile> Temp =
|
|
|
|
sys::fs::TempFile::create(OutputFileName + ".temp-objcopy-%%%%%%", Mode);
|
|
|
|
if (!Temp)
|
|
|
|
return createFileError(OutputFileName, Temp.takeError());
|
|
|
|
|
|
|
|
raw_fd_ostream Out(Temp->FD, false);
|
|
|
|
|
|
|
|
if (Error E = Write(Out)) {
|
|
|
|
if (Error DiscardError = Temp->discard())
|
|
|
|
return joinErrors(std::move(E), std::move(DiscardError));
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
Out.flush();
|
|
|
|
|
|
|
|
return Temp->keep(OutputFileName);
|
|
|
|
}
|
|
|
|
|
2018-07-18 08:10:51 +08:00
|
|
|
// The name this program was invoked as.
|
|
|
|
StringRef ToolName;
|
|
|
|
|
2019-06-18 08:39:10 +08:00
|
|
|
ErrorSuccess reportWarning(Error E) {
|
|
|
|
assert(E);
|
2019-08-20 23:00:07 +08:00
|
|
|
WithColor::warning(errs(), ToolName) << toString(std::move(E)) << '\n';
|
2019-06-18 08:39:10 +08:00
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
2020-10-23 14:13:49 +08:00
|
|
|
static Expected<DriverConfig> getDriverConfig(ArrayRef<const char *> Args) {
|
|
|
|
StringRef Stem = sys::path::stem(ToolName);
|
|
|
|
auto Is = [=](StringRef Tool) {
|
|
|
|
// We need to recognize the following filenames:
|
|
|
|
//
|
|
|
|
// llvm-objcopy -> objcopy
|
|
|
|
// strip-10.exe -> strip
|
|
|
|
// powerpc64-unknown-freebsd13-objcopy -> objcopy
|
|
|
|
// llvm-install-name-tool -> install-name-tool
|
|
|
|
auto I = Stem.rfind_lower(Tool);
|
|
|
|
return I != StringRef::npos &&
|
|
|
|
(I + Tool.size() == Stem.size() || !isAlnum(Stem[I + Tool.size()]));
|
|
|
|
};
|
|
|
|
|
|
|
|
if (Is("bitcode-strip") || Is("bitcode_strip"))
|
|
|
|
return parseBitcodeStripOptions(Args);
|
|
|
|
else if (Is("strip"))
|
|
|
|
return parseStripOptions(Args, reportWarning);
|
|
|
|
else if (Is("install-name-tool") || Is("install_name_tool"))
|
|
|
|
return parseInstallNameToolOptions(Args);
|
|
|
|
else
|
|
|
|
return parseObjcopyOptions(Args, reportWarning);
|
|
|
|
}
|
|
|
|
|
2018-07-18 08:10:51 +08:00
|
|
|
} // end namespace objcopy
|
2018-10-25 06:49:06 +08:00
|
|
|
} // end namespace llvm
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
using namespace llvm::object;
|
|
|
|
using namespace llvm::objcopy;
|
|
|
|
|
2018-07-07 01:51:03 +08:00
|
|
|
// For regular archives this function simply calls llvm::writeArchive,
|
|
|
|
// For thin archives it writes the archive file itself as well as its members.
|
2018-07-17 06:17:05 +08:00
|
|
|
static Error deepWriteArchive(StringRef ArcName,
|
|
|
|
ArrayRef<NewArchiveMember> NewMembers,
|
|
|
|
bool WriteSymtab, object::Archive::Kind Kind,
|
|
|
|
bool Deterministic, bool Thin) {
|
2019-02-02 01:08:07 +08:00
|
|
|
if (Error E = writeArchive(ArcName, NewMembers, WriteSymtab, Kind,
|
|
|
|
Deterministic, Thin))
|
|
|
|
return createFileError(ArcName, std::move(E));
|
|
|
|
|
|
|
|
if (!Thin)
|
|
|
|
return Error::success();
|
|
|
|
|
2018-07-07 01:51:03 +08:00
|
|
|
for (const NewArchiveMember &Member : NewMembers) {
|
2020-10-24 22:35:55 +08:00
|
|
|
// For regular files (as is the case for deepWriteArchive),
|
|
|
|
// FileOutputBuffer::create will return OnDiskBuffer.
|
2018-07-07 01:51:03 +08:00
|
|
|
// OnDiskBuffer uses a temporary file and then renames it. So in reality
|
|
|
|
// there is no inefficiency / duplicated in-memory buffers in this case. For
|
|
|
|
// now in-memory buffers can not be completely avoided since
|
|
|
|
// NewArchiveMember still requires them even though writeArchive does not
|
|
|
|
// write them on disk.
|
2021-03-12 21:31:35 +08:00
|
|
|
Expected<std::unique_ptr<FileOutputBuffer>> FB =
|
|
|
|
FileOutputBuffer::create(Member.MemberName, Member.Buf->getBufferSize(),
|
|
|
|
FileOutputBuffer::F_executable);
|
2020-10-24 22:35:55 +08:00
|
|
|
if (!FB)
|
|
|
|
return FB.takeError();
|
2018-07-07 01:51:03 +08:00
|
|
|
std::copy(Member.Buf->getBufferStart(), Member.Buf->getBufferEnd(),
|
2020-10-24 22:35:55 +08:00
|
|
|
(*FB)->getBufferStart());
|
|
|
|
if (Error E = (*FB)->commit())
|
2018-07-07 01:51:03 +08:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
2019-06-13 17:56:14 +08:00
|
|
|
/// The function executeObjcopyOnIHex does the dispatch based on the format
|
|
|
|
/// of the output specified by the command line options.
|
[llvm-objcopy] Refactor ELF-specific config out to ELFCopyConfig. NFC.
Summary:
This patch splits the command-line parsing into two phases:
First, parse cross-platform options and leave ELF-specific options unparsed.
Second, in the ELF implementation, parse ELF-specific options and construct ELFCopyConfig.
Reviewers: espindola, alexshap, rupprecht, jhenderson, jakehehrlich, MaskRay
Reviewed By: alexshap, jhenderson, jakehehrlich, MaskRay
Subscribers: mgorny, emaste, arichardson, jakehehrlich, MaskRay, abrachet, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D67139
llvm-svn: 372712
2019-09-24 17:38:23 +08:00
|
|
|
static Error executeObjcopyOnIHex(CopyConfig &Config, MemoryBuffer &In,
|
2020-10-24 22:35:55 +08:00
|
|
|
raw_ostream &Out) {
|
2019-06-13 17:56:14 +08:00
|
|
|
// TODO: support output formats other than ELF.
|
[llvm-objcopy] Refactor ELF-specific config out to ELFCopyConfig. NFC.
Summary:
This patch splits the command-line parsing into two phases:
First, parse cross-platform options and leave ELF-specific options unparsed.
Second, in the ELF implementation, parse ELF-specific options and construct ELFCopyConfig.
Reviewers: espindola, alexshap, rupprecht, jhenderson, jakehehrlich, MaskRay
Reviewed By: alexshap, jhenderson, jakehehrlich, MaskRay
Subscribers: mgorny, emaste, arichardson, jakehehrlich, MaskRay, abrachet, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D67139
llvm-svn: 372712
2019-09-24 17:38:23 +08:00
|
|
|
if (Error E = Config.parseELFConfig())
|
|
|
|
return E;
|
2019-06-13 17:56:14 +08:00
|
|
|
return elf::executeObjcopyOnIHex(Config, In, Out);
|
|
|
|
}
|
|
|
|
|
2018-10-25 06:49:06 +08:00
|
|
|
/// The function executeObjcopyOnRawBinary does the dispatch based on the format
|
|
|
|
/// of the output specified by the command line options.
|
[llvm-objcopy] Refactor ELF-specific config out to ELFCopyConfig. NFC.
Summary:
This patch splits the command-line parsing into two phases:
First, parse cross-platform options and leave ELF-specific options unparsed.
Second, in the ELF implementation, parse ELF-specific options and construct ELFCopyConfig.
Reviewers: espindola, alexshap, rupprecht, jhenderson, jakehehrlich, MaskRay
Reviewed By: alexshap, jhenderson, jakehehrlich, MaskRay
Subscribers: mgorny, emaste, arichardson, jakehehrlich, MaskRay, abrachet, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D67139
llvm-svn: 372712
2019-09-24 17:38:23 +08:00
|
|
|
static Error executeObjcopyOnRawBinary(CopyConfig &Config, MemoryBuffer &In,
|
2020-10-24 22:35:55 +08:00
|
|
|
raw_ostream &Out) {
|
2019-07-05 13:28:38 +08:00
|
|
|
switch (Config.OutputFormat) {
|
|
|
|
case FileFormat::ELF:
|
|
|
|
// FIXME: Currently, we call elf::executeObjcopyOnRawBinary even if the
|
|
|
|
// output format is binary/ihex or it's not given. This behavior differs from
|
|
|
|
// GNU objcopy. See https://bugs.llvm.org/show_bug.cgi?id=42171 for details.
|
|
|
|
case FileFormat::Binary:
|
|
|
|
case FileFormat::IHex:
|
|
|
|
case FileFormat::Unspecified:
|
[llvm-objcopy] Refactor ELF-specific config out to ELFCopyConfig. NFC.
Summary:
This patch splits the command-line parsing into two phases:
First, parse cross-platform options and leave ELF-specific options unparsed.
Second, in the ELF implementation, parse ELF-specific options and construct ELFCopyConfig.
Reviewers: espindola, alexshap, rupprecht, jhenderson, jakehehrlich, MaskRay
Reviewed By: alexshap, jhenderson, jakehehrlich, MaskRay
Subscribers: mgorny, emaste, arichardson, jakehehrlich, MaskRay, abrachet, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D67139
llvm-svn: 372712
2019-09-24 17:38:23 +08:00
|
|
|
if (Error E = Config.parseELFConfig())
|
|
|
|
return E;
|
2019-07-05 13:28:38 +08:00
|
|
|
return elf::executeObjcopyOnRawBinary(Config, In, Out);
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("unsupported output format");
|
2018-10-25 06:49:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// The function executeObjcopyOnBinary does the dispatch based on the format
|
|
|
|
/// of the input binary (ELF, MachO or COFF).
|
[llvm-objcopy] Refactor ELF-specific config out to ELFCopyConfig. NFC.
Summary:
This patch splits the command-line parsing into two phases:
First, parse cross-platform options and leave ELF-specific options unparsed.
Second, in the ELF implementation, parse ELF-specific options and construct ELFCopyConfig.
Reviewers: espindola, alexshap, rupprecht, jhenderson, jakehehrlich, MaskRay
Reviewed By: alexshap, jhenderson, jakehehrlich, MaskRay
Subscribers: mgorny, emaste, arichardson, jakehehrlich, MaskRay, abrachet, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D67139
llvm-svn: 372712
2019-09-24 17:38:23 +08:00
|
|
|
static Error executeObjcopyOnBinary(CopyConfig &Config, object::Binary &In,
|
2020-10-24 22:35:55 +08:00
|
|
|
raw_ostream &Out) {
|
[llvm-objcopy] Refactor ELF-specific config out to ELFCopyConfig. NFC.
Summary:
This patch splits the command-line parsing into two phases:
First, parse cross-platform options and leave ELF-specific options unparsed.
Second, in the ELF implementation, parse ELF-specific options and construct ELFCopyConfig.
Reviewers: espindola, alexshap, rupprecht, jhenderson, jakehehrlich, MaskRay
Reviewed By: alexshap, jhenderson, jakehehrlich, MaskRay
Subscribers: mgorny, emaste, arichardson, jakehehrlich, MaskRay, abrachet, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D67139
llvm-svn: 372712
2019-09-24 17:38:23 +08:00
|
|
|
if (auto *ELFBinary = dyn_cast<object::ELFObjectFileBase>(&In)) {
|
|
|
|
if (Error E = Config.parseELFConfig())
|
|
|
|
return E;
|
2018-10-25 06:49:06 +08:00
|
|
|
return elf::executeObjcopyOnBinary(Config, *ELFBinary, Out);
|
[llvm-objcopy] Refactor ELF-specific config out to ELFCopyConfig. NFC.
Summary:
This patch splits the command-line parsing into two phases:
First, parse cross-platform options and leave ELF-specific options unparsed.
Second, in the ELF implementation, parse ELF-specific options and construct ELFCopyConfig.
Reviewers: espindola, alexshap, rupprecht, jhenderson, jakehehrlich, MaskRay
Reviewed By: alexshap, jhenderson, jakehehrlich, MaskRay
Subscribers: mgorny, emaste, arichardson, jakehehrlich, MaskRay, abrachet, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D67139
llvm-svn: 372712
2019-09-24 17:38:23 +08:00
|
|
|
} else if (auto *COFFBinary = dyn_cast<object::COFFObjectFile>(&In))
|
2018-12-19 15:24:38 +08:00
|
|
|
return coff::executeObjcopyOnBinary(Config, *COFFBinary, Out);
|
2019-02-02 08:38:07 +08:00
|
|
|
else if (auto *MachOBinary = dyn_cast<object::MachOObjectFile>(&In))
|
|
|
|
return macho::executeObjcopyOnBinary(Config, *MachOBinary, Out);
|
2020-10-06 18:41:19 +08:00
|
|
|
else if (auto *MachOUniversalBinary =
|
|
|
|
dyn_cast<object::MachOUniversalBinary>(&In))
|
|
|
|
return macho::executeObjcopyOnMachOUniversalBinary(
|
|
|
|
Config, *MachOUniversalBinary, Out);
|
2020-01-30 09:30:57 +08:00
|
|
|
else if (auto *WasmBinary = dyn_cast<object::WasmObjectFile>(&In))
|
|
|
|
return objcopy::wasm::executeObjcopyOnBinary(Config, *WasmBinary, Out);
|
2018-10-25 06:49:06 +08:00
|
|
|
else
|
2019-01-30 22:36:53 +08:00
|
|
|
return createStringError(object_error::invalid_file_type,
|
2019-06-14 10:04:02 +08:00
|
|
|
"unsupported object file format");
|
2018-10-25 06:49:06 +08:00
|
|
|
}
|
|
|
|
|
2020-10-06 18:41:19 +08:00
|
|
|
namespace llvm {
|
|
|
|
namespace objcopy {
|
|
|
|
|
|
|
|
Expected<std::vector<NewArchiveMember>>
|
|
|
|
createNewArchiveMembers(CopyConfig &Config, const Archive &Ar) {
|
2018-07-07 01:51:03 +08:00
|
|
|
std::vector<NewArchiveMember> NewArchiveMembers;
|
|
|
|
Error Err = Error::success();
|
|
|
|
for (const Archive::Child &Child : Ar.children(Err)) {
|
|
|
|
Expected<StringRef> ChildNameOrErr = Child.getName();
|
|
|
|
if (!ChildNameOrErr)
|
2019-02-02 01:08:07 +08:00
|
|
|
return createFileError(Ar.getFileName(), ChildNameOrErr.takeError());
|
2018-07-07 01:51:03 +08:00
|
|
|
|
2019-05-08 21:28:58 +08:00
|
|
|
Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
|
|
|
|
if (!ChildOrErr)
|
|
|
|
return createFileError(Ar.getFileName() + "(" + *ChildNameOrErr + ")",
|
|
|
|
ChildOrErr.takeError());
|
|
|
|
|
2020-10-24 22:35:55 +08:00
|
|
|
SmallVector<char, 0> Buffer;
|
|
|
|
raw_svector_ostream MemStream(Buffer);
|
|
|
|
|
|
|
|
if (Error E = executeObjcopyOnBinary(Config, *ChildOrErr->get(), MemStream))
|
2020-10-06 18:41:19 +08:00
|
|
|
return std::move(E);
|
2018-07-07 01:51:03 +08:00
|
|
|
|
|
|
|
Expected<NewArchiveMember> Member =
|
2018-11-02 01:36:37 +08:00
|
|
|
NewArchiveMember::getOldMember(Child, Config.DeterministicArchives);
|
2018-07-07 01:51:03 +08:00
|
|
|
if (!Member)
|
2019-02-02 01:08:07 +08:00
|
|
|
return createFileError(Ar.getFileName(), Member.takeError());
|
2020-10-24 22:35:55 +08:00
|
|
|
|
|
|
|
Member->Buf = std::make_unique<SmallVectorMemoryBuffer>(
|
|
|
|
std::move(Buffer), ChildNameOrErr.get());
|
2018-07-07 01:51:03 +08:00
|
|
|
Member->MemberName = Member->Buf->getBufferIdentifier();
|
|
|
|
NewArchiveMembers.push_back(std::move(*Member));
|
|
|
|
}
|
|
|
|
if (Err)
|
2019-02-02 01:08:07 +08:00
|
|
|
return createFileError(Config.InputFilename, std::move(Err));
|
2020-10-06 18:41:19 +08:00
|
|
|
return std::move(NewArchiveMembers);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // end namespace objcopy
|
|
|
|
} // end namespace llvm
|
2019-02-02 01:08:07 +08:00
|
|
|
|
2020-10-06 18:41:19 +08:00
|
|
|
static Error executeObjcopyOnArchive(CopyConfig &Config,
|
|
|
|
const object::Archive &Ar) {
|
|
|
|
Expected<std::vector<NewArchiveMember>> NewArchiveMembersOrErr =
|
|
|
|
createNewArchiveMembers(Config, Ar);
|
|
|
|
if (!NewArchiveMembersOrErr)
|
|
|
|
return NewArchiveMembersOrErr.takeError();
|
|
|
|
return deepWriteArchive(Config.OutputFilename, *NewArchiveMembersOrErr,
|
2019-02-02 01:08:07 +08:00
|
|
|
Ar.hasSymbolTable(), Ar.kind(),
|
|
|
|
Config.DeterministicArchives, Ar.isThin());
|
2018-07-07 01:51:03 +08:00
|
|
|
}
|
|
|
|
|
[llvm-objcopy] Change handling of output file permissions
Summary: Address bug [[ https://bugs.llvm.org/show_bug.cgi?id=42082 | 42082 ]] where files were always outputted with 0775 permissions. Now, the output file is given either 0666 or 0777 if the object is executable.
Reviewers: espindola, alexshap, rupprecht, jhenderson, jakehehrlich, MaskRay
Reviewed By: rupprecht, jhenderson, jakehehrlich, MaskRay
Subscribers: emaste, arichardson, jakehehrlich, MaskRay, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D62718
llvm-svn: 365162
2019-07-05 06:45:27 +08:00
|
|
|
static Error restoreStatOnFile(StringRef Filename,
|
|
|
|
const sys::fs::file_status &Stat,
|
2021-02-25 03:10:09 +08:00
|
|
|
const CopyConfig &Config) {
|
2018-08-17 02:29:40 +08:00
|
|
|
int FD;
|
|
|
|
|
[llvm-objcopy] Change handling of output file permissions
Summary: Address bug [[ https://bugs.llvm.org/show_bug.cgi?id=42082 | 42082 ]] where files were always outputted with 0775 permissions. Now, the output file is given either 0666 or 0777 if the object is executable.
Reviewers: espindola, alexshap, rupprecht, jhenderson, jakehehrlich, MaskRay
Reviewed By: rupprecht, jhenderson, jakehehrlich, MaskRay
Subscribers: emaste, arichardson, jakehehrlich, MaskRay, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D62718
llvm-svn: 365162
2019-07-05 06:45:27 +08:00
|
|
|
// Writing to stdout should not be treated as an error here, just
|
|
|
|
// do not set access/modification times or permissions.
|
|
|
|
if (Filename == "-")
|
|
|
|
return Error::success();
|
|
|
|
|
2018-08-30 07:21:56 +08:00
|
|
|
if (auto EC =
|
|
|
|
sys::fs::openFileForWrite(Filename, FD, sys::fs::CD_OpenExisting))
|
2019-02-22 01:05:19 +08:00
|
|
|
return createFileError(Filename, EC);
|
2018-08-17 02:29:40 +08:00
|
|
|
|
2021-02-25 03:10:09 +08:00
|
|
|
if (Config.PreserveDates)
|
[llvm-objcopy] Change handling of output file permissions
Summary: Address bug [[ https://bugs.llvm.org/show_bug.cgi?id=42082 | 42082 ]] where files were always outputted with 0775 permissions. Now, the output file is given either 0666 or 0777 if the object is executable.
Reviewers: espindola, alexshap, rupprecht, jhenderson, jakehehrlich, MaskRay
Reviewed By: rupprecht, jhenderson, jakehehrlich, MaskRay
Subscribers: emaste, arichardson, jakehehrlich, MaskRay, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D62718
llvm-svn: 365162
2019-07-05 06:45:27 +08:00
|
|
|
if (auto EC = sys::fs::setLastAccessAndModificationTime(
|
|
|
|
FD, Stat.getLastAccessedTime(), Stat.getLastModificationTime()))
|
|
|
|
return createFileError(Filename, EC);
|
|
|
|
|
2019-07-11 18:17:59 +08:00
|
|
|
sys::fs::file_status OStat;
|
|
|
|
if (std::error_code EC = sys::fs::status(FD, OStat))
|
2019-02-22 01:05:19 +08:00
|
|
|
return createFileError(Filename, EC);
|
2021-02-25 03:10:09 +08:00
|
|
|
if (OStat.type() == sys::fs::file_type::regular_file) {
|
|
|
|
sys::fs::perms Perm = Stat.permissions();
|
|
|
|
if (Config.InputFilename != Config.OutputFilename)
|
|
|
|
Perm = static_cast<sys::fs::perms>(Perm & ~sys::fs::getUmask() & ~06000);
|
2019-07-11 18:17:59 +08:00
|
|
|
#ifdef _WIN32
|
2021-02-25 03:10:09 +08:00
|
|
|
if (auto EC = sys::fs::setPermissions(Filename, Perm))
|
2019-07-11 18:17:59 +08:00
|
|
|
#else
|
2021-02-25 03:10:09 +08:00
|
|
|
if (auto EC = sys::fs::setPermissions(FD, Perm))
|
2019-07-11 18:17:59 +08:00
|
|
|
#endif
|
|
|
|
return createFileError(Filename, EC);
|
2021-03-12 21:31:35 +08:00
|
|
|
|
|
|
|
#ifndef _WIN32
|
|
|
|
// Keep ownership if llvm-objcopy is called under root.
|
|
|
|
if (Config.InputFilename == Config.OutputFilename && OStat.getUser() == 0)
|
|
|
|
sys::fs::changeFileOwnership(FD, Stat.getUser(), Stat.getGroup());
|
|
|
|
#endif
|
2021-02-25 03:10:09 +08:00
|
|
|
}
|
2018-08-17 02:29:40 +08:00
|
|
|
|
|
|
|
if (auto EC = sys::Process::SafelyCloseFileDescriptor(FD))
|
2019-02-22 01:05:19 +08:00
|
|
|
return createFileError(Filename, EC);
|
|
|
|
|
|
|
|
return Error::success();
|
2018-08-17 02:29:40 +08:00
|
|
|
}
|
|
|
|
|
2018-10-25 06:49:06 +08:00
|
|
|
/// The function executeObjcopy does the higher level dispatch based on the type
|
|
|
|
/// of input (raw binary, archive or single object file) and takes care of the
|
|
|
|
/// format-agnostic modifications, i.e. preserving dates.
|
[llvm-objcopy] Refactor ELF-specific config out to ELFCopyConfig. NFC.
Summary:
This patch splits the command-line parsing into two phases:
First, parse cross-platform options and leave ELF-specific options unparsed.
Second, in the ELF implementation, parse ELF-specific options and construct ELFCopyConfig.
Reviewers: espindola, alexshap, rupprecht, jhenderson, jakehehrlich, MaskRay
Reviewed By: alexshap, jhenderson, jakehehrlich, MaskRay
Subscribers: mgorny, emaste, arichardson, jakehehrlich, MaskRay, abrachet, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D67139
llvm-svn: 372712
2019-09-24 17:38:23 +08:00
|
|
|
static Error executeObjcopy(CopyConfig &Config) {
|
2018-08-17 02:29:40 +08:00
|
|
|
sys::fs::file_status Stat;
|
[llvm-objcopy] Change handling of output file permissions
Summary: Address bug [[ https://bugs.llvm.org/show_bug.cgi?id=42082 | 42082 ]] where files were always outputted with 0775 permissions. Now, the output file is given either 0666 or 0777 if the object is executable.
Reviewers: espindola, alexshap, rupprecht, jhenderson, jakehehrlich, MaskRay
Reviewed By: rupprecht, jhenderson, jakehehrlich, MaskRay
Subscribers: emaste, arichardson, jakehehrlich, MaskRay, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D62718
llvm-svn: 365162
2019-07-05 06:45:27 +08:00
|
|
|
if (Config.InputFilename != "-") {
|
2018-08-17 02:29:40 +08:00
|
|
|
if (auto EC = sys::fs::status(Config.InputFilename, Stat))
|
2019-02-22 01:05:19 +08:00
|
|
|
return createFileError(Config.InputFilename, EC);
|
[llvm-objcopy] Change handling of output file permissions
Summary: Address bug [[ https://bugs.llvm.org/show_bug.cgi?id=42082 | 42082 ]] where files were always outputted with 0775 permissions. Now, the output file is given either 0666 or 0777 if the object is executable.
Reviewers: espindola, alexshap, rupprecht, jhenderson, jakehehrlich, MaskRay
Reviewed By: rupprecht, jhenderson, jakehehrlich, MaskRay
Subscribers: emaste, arichardson, jakehehrlich, MaskRay, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D62718
llvm-svn: 365162
2019-07-05 06:45:27 +08:00
|
|
|
} else {
|
|
|
|
Stat.permissions(static_cast<sys::fs::perms>(0777));
|
|
|
|
}
|
2018-08-17 02:29:40 +08:00
|
|
|
|
2021-03-12 06:31:06 +08:00
|
|
|
std::function<Error(raw_ostream & OutFile)> ObjcopyFunc;
|
2019-06-13 17:56:14 +08:00
|
|
|
|
2021-03-12 06:31:06 +08:00
|
|
|
OwningBinary<llvm::object::Binary> BinaryHolder;
|
|
|
|
std::unique_ptr<MemoryBuffer> MemoryBufferHolder;
|
|
|
|
|
|
|
|
if (Config.InputFormat == FileFormat::Binary ||
|
|
|
|
Config.InputFormat == FileFormat::IHex) {
|
|
|
|
ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
|
|
|
|
MemoryBuffer::getFileOrSTDIN(Config.InputFilename);
|
[llvm-objcopy] Add support for -I binary -B <arch>.
Summary:
The -I (--input-target) and -B (--binary-architecture) flags exist but are currently silently ignored. This adds support for -I binary for architectures i386, x86-64 (and alias i386:x86-64), arm, aarch64, sparc, and ppc (powerpc:common64). This is largely based on D41687.
This is done by implementing an additional subclass of Reader, BinaryReader, which works by interpreting the input file as contents for .data field, sets up a synthetic header, and adds additional sections/symbols (e.g. _binary__tmp_data_txt_start).
Reviewers: jakehehrlich, alexshap, jhenderson, javed.absar
Reviewed By: jhenderson
Subscribers: jyknight, nemanjai, kbarton, fedor.sergeev, jrtc27, kristof.beyls, paulsemel, llvm-commits
Differential Revision: https://reviews.llvm.org/D50343
llvm-svn: 340070
2018-08-18 02:51:11 +08:00
|
|
|
if (!BufOrErr)
|
2019-02-22 01:05:19 +08:00
|
|
|
return createFileError(Config.InputFilename, BufOrErr.getError());
|
2021-03-12 06:31:06 +08:00
|
|
|
MemoryBufferHolder = std::move(*BufOrErr);
|
|
|
|
|
|
|
|
if (Config.InputFormat == FileFormat::Binary)
|
|
|
|
ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
|
|
|
|
// Handle FileFormat::Binary.
|
|
|
|
return executeObjcopyOnRawBinary(Config, *MemoryBufferHolder, OutFile);
|
|
|
|
};
|
|
|
|
else
|
|
|
|
ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
|
|
|
|
// Handle FileFormat::IHex.
|
|
|
|
return executeObjcopyOnIHex(Config, *MemoryBufferHolder, OutFile);
|
|
|
|
};
|
[llvm-objcopy] Add support for -I binary -B <arch>.
Summary:
The -I (--input-target) and -B (--binary-architecture) flags exist but are currently silently ignored. This adds support for -I binary for architectures i386, x86-64 (and alias i386:x86-64), arm, aarch64, sparc, and ppc (powerpc:common64). This is largely based on D41687.
This is done by implementing an additional subclass of Reader, BinaryReader, which works by interpreting the input file as contents for .data field, sets up a synthetic header, and adds additional sections/symbols (e.g. _binary__tmp_data_txt_start).
Reviewers: jakehehrlich, alexshap, jhenderson, javed.absar
Reviewed By: jhenderson
Subscribers: jyknight, nemanjai, kbarton, fedor.sergeev, jrtc27, kristof.beyls, paulsemel, llvm-commits
Differential Revision: https://reviews.llvm.org/D50343
llvm-svn: 340070
2018-08-18 02:51:11 +08:00
|
|
|
} else {
|
|
|
|
Expected<OwningBinary<llvm::object::Binary>> BinaryOrErr =
|
|
|
|
createBinary(Config.InputFilename);
|
|
|
|
if (!BinaryOrErr)
|
2019-02-22 01:05:19 +08:00
|
|
|
return createFileError(Config.InputFilename, BinaryOrErr.takeError());
|
2021-03-12 06:31:06 +08:00
|
|
|
BinaryHolder = std::move(*BinaryOrErr);
|
[llvm-objcopy] Add support for -I binary -B <arch>.
Summary:
The -I (--input-target) and -B (--binary-architecture) flags exist but are currently silently ignored. This adds support for -I binary for architectures i386, x86-64 (and alias i386:x86-64), arm, aarch64, sparc, and ppc (powerpc:common64). This is largely based on D41687.
This is done by implementing an additional subclass of Reader, BinaryReader, which works by interpreting the input file as contents for .data field, sets up a synthetic header, and adds additional sections/symbols (e.g. _binary__tmp_data_txt_start).
Reviewers: jakehehrlich, alexshap, jhenderson, javed.absar
Reviewed By: jhenderson
Subscribers: jyknight, nemanjai, kbarton, fedor.sergeev, jrtc27, kristof.beyls, paulsemel, llvm-commits
Differential Revision: https://reviews.llvm.org/D50343
llvm-svn: 340070
2018-08-18 02:51:11 +08:00
|
|
|
|
2021-03-12 06:31:06 +08:00
|
|
|
if (Archive *Ar = dyn_cast<Archive>(BinaryHolder.getBinary())) {
|
|
|
|
// Handle Archive.
|
2019-01-30 22:36:53 +08:00
|
|
|
if (Error E = executeObjcopyOnArchive(Config, *Ar))
|
2019-02-22 01:05:19 +08:00
|
|
|
return E;
|
[llvm-objcopy] Add support for -I binary -B <arch>.
Summary:
The -I (--input-target) and -B (--binary-architecture) flags exist but are currently silently ignored. This adds support for -I binary for architectures i386, x86-64 (and alias i386:x86-64), arm, aarch64, sparc, and ppc (powerpc:common64). This is largely based on D41687.
This is done by implementing an additional subclass of Reader, BinaryReader, which works by interpreting the input file as contents for .data field, sets up a synthetic header, and adds additional sections/symbols (e.g. _binary__tmp_data_txt_start).
Reviewers: jakehehrlich, alexshap, jhenderson, javed.absar
Reviewed By: jhenderson
Subscribers: jyknight, nemanjai, kbarton, fedor.sergeev, jrtc27, kristof.beyls, paulsemel, llvm-commits
Differential Revision: https://reviews.llvm.org/D50343
llvm-svn: 340070
2018-08-18 02:51:11 +08:00
|
|
|
} else {
|
2021-03-12 06:31:06 +08:00
|
|
|
// Handle llvm::object::Binary.
|
|
|
|
ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
|
|
|
|
return executeObjcopyOnBinary(Config, *BinaryHolder.getBinary(),
|
|
|
|
OutFile);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ObjcopyFunc) {
|
|
|
|
if (Config.SplitDWO.empty()) {
|
|
|
|
// Apply transformations described by Config and store result into
|
|
|
|
// Config.OutputFilename using specified ObjcopyFunc function.
|
|
|
|
if (Error E = writeToFile(Config.OutputFilename, ObjcopyFunc))
|
|
|
|
return E;
|
|
|
|
} else {
|
|
|
|
Config.ExtractDWO = true;
|
|
|
|
Config.StripDWO = false;
|
|
|
|
// Copy .dwo tables from the Config.InputFilename into Config.SplitDWO
|
|
|
|
// file using specified ObjcopyFunc function.
|
|
|
|
if (Error E = writeToFile(Config.SplitDWO, ObjcopyFunc))
|
|
|
|
return E;
|
|
|
|
Config.ExtractDWO = false;
|
|
|
|
Config.StripDWO = true;
|
|
|
|
// Apply transformations described by Config, remove .dwo tables and
|
|
|
|
// store result into Config.OutputFilename using specified ObjcopyFunc
|
|
|
|
// function.
|
|
|
|
if (Error E = writeToFile(Config.OutputFilename, ObjcopyFunc))
|
2019-02-22 01:05:19 +08:00
|
|
|
return E;
|
[llvm-objcopy] Add support for -I binary -B <arch>.
Summary:
The -I (--input-target) and -B (--binary-architecture) flags exist but are currently silently ignored. This adds support for -I binary for architectures i386, x86-64 (and alias i386:x86-64), arm, aarch64, sparc, and ppc (powerpc:common64). This is largely based on D41687.
This is done by implementing an additional subclass of Reader, BinaryReader, which works by interpreting the input file as contents for .data field, sets up a synthetic header, and adds additional sections/symbols (e.g. _binary__tmp_data_txt_start).
Reviewers: jakehehrlich, alexshap, jhenderson, javed.absar
Reviewed By: jhenderson
Subscribers: jyknight, nemanjai, kbarton, fedor.sergeev, jrtc27, kristof.beyls, paulsemel, llvm-commits
Differential Revision: https://reviews.llvm.org/D50343
llvm-svn: 340070
2018-08-18 02:51:11 +08:00
|
|
|
}
|
2018-08-17 02:29:40 +08:00
|
|
|
}
|
2018-07-07 01:51:03 +08:00
|
|
|
|
2021-02-25 03:10:09 +08:00
|
|
|
if (Error E = restoreStatOnFile(Config.OutputFilename, Stat, Config))
|
[llvm-objcopy] Change handling of output file permissions
Summary: Address bug [[ https://bugs.llvm.org/show_bug.cgi?id=42082 | 42082 ]] where files were always outputted with 0775 permissions. Now, the output file is given either 0666 or 0777 if the object is executable.
Reviewers: espindola, alexshap, rupprecht, jhenderson, jakehehrlich, MaskRay
Reviewed By: rupprecht, jhenderson, jakehehrlich, MaskRay
Subscribers: emaste, arichardson, jakehehrlich, MaskRay, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D62718
llvm-svn: 365162
2019-07-05 06:45:27 +08:00
|
|
|
return E;
|
|
|
|
|
|
|
|
if (!Config.SplitDWO.empty()) {
|
|
|
|
Stat.permissions(static_cast<sys::fs::perms>(0666));
|
2021-02-25 03:10:09 +08:00
|
|
|
if (Error E = restoreStatOnFile(Config.SplitDWO, Stat, Config))
|
2019-02-22 01:05:19 +08:00
|
|
|
return E;
|
2018-08-17 02:29:40 +08:00
|
|
|
}
|
2019-02-22 01:05:19 +08:00
|
|
|
|
|
|
|
return Error::success();
|
2018-07-07 01:51:03 +08:00
|
|
|
}
|
|
|
|
|
2019-11-20 15:30:52 +08:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
2017-08-01 08:33:58 +08:00
|
|
|
int main(int argc, char **argv) {
|
2018-04-14 02:26:06 +08:00
|
|
|
InitLLVM X(argc, argv);
|
2017-08-01 08:33:58 +08:00
|
|
|
ToolName = argv[0];
|
2020-03-22 14:39:01 +08:00
|
|
|
|
2019-09-14 09:14:43 +08:00
|
|
|
// Expand response files.
|
|
|
|
// TODO: Move these lines, which are copied from lib/Support/CommandLine.cpp,
|
|
|
|
// into a separate function in the CommandLine library and call that function
|
|
|
|
// here. This is duplicated code.
|
|
|
|
SmallVector<const char *, 20> NewArgv(argv, argv + argc);
|
|
|
|
BumpPtrAllocator A;
|
|
|
|
StringSaver Saver(A);
|
|
|
|
cl::ExpandResponseFiles(Saver,
|
|
|
|
Triple(sys::getProcessTriple()).isOSWindows()
|
|
|
|
? cl::TokenizeWindowsCommandLine
|
|
|
|
: cl::TokenizeGNUCommandLine,
|
|
|
|
NewArgv);
|
|
|
|
|
|
|
|
auto Args = makeArrayRef(NewArgv).drop_front();
|
2020-10-23 14:13:49 +08:00
|
|
|
Expected<DriverConfig> DriverConfig = getDriverConfig(Args);
|
|
|
|
|
2019-02-22 01:05:19 +08:00
|
|
|
if (!DriverConfig) {
|
|
|
|
logAllUnhandledErrors(DriverConfig.takeError(),
|
|
|
|
WithColor::error(errs(), ToolName));
|
|
|
|
return 1;
|
|
|
|
}
|
[llvm-objcopy] Refactor ELF-specific config out to ELFCopyConfig. NFC.
Summary:
This patch splits the command-line parsing into two phases:
First, parse cross-platform options and leave ELF-specific options unparsed.
Second, in the ELF implementation, parse ELF-specific options and construct ELFCopyConfig.
Reviewers: espindola, alexshap, rupprecht, jhenderson, jakehehrlich, MaskRay
Reviewed By: alexshap, jhenderson, jakehehrlich, MaskRay
Subscribers: mgorny, emaste, arichardson, jakehehrlich, MaskRay, abrachet, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D67139
llvm-svn: 372712
2019-09-24 17:38:23 +08:00
|
|
|
for (CopyConfig &CopyConfig : DriverConfig->CopyConfigs) {
|
2019-02-22 01:05:19 +08:00
|
|
|
if (Error E = executeObjcopy(CopyConfig)) {
|
|
|
|
logAllUnhandledErrors(std::move(E), WithColor::error(errs(), ToolName));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2017-08-01 08:33:58 +08:00
|
|
|
}
|