2017-11-01 22:16:06 +01:00
|
|
|
//===- llvm-objcopy.cpp ---------------------------------------------------===//
|
2017-08-01 02:33:58 +02:00
|
|
|
//
|
2019-01-19 09:50:56 +01: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 02:33:58 +02:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2017-11-01 22:16:06 +01:00
|
|
|
|
2020-10-24 16:35:55 +02:00
|
|
|
#include "llvm-objcopy.h"
|
2021-04-23 13:19:11 +02:00
|
|
|
#include "COFF/COFFConfig.h"
|
2020-01-30 02:30:57 +01:00
|
|
|
#include "COFF/COFFObjcopy.h"
|
2021-04-23 13:19:11 +02:00
|
|
|
#include "CommonConfig.h"
|
|
|
|
#include "ConfigManager.h"
|
|
|
|
#include "ELF/ELFConfig.h"
|
2018-10-29 22:22:58 +01:00
|
|
|
#include "ELF/ELFObjcopy.h"
|
2021-04-23 13:19:11 +02:00
|
|
|
#include "MachO/MachOConfig.h"
|
2019-02-02 01:38:07 +01:00
|
|
|
#include "MachO/MachOObjcopy.h"
|
2021-04-23 13:19:11 +02:00
|
|
|
#include "wasm/WasmConfig.h"
|
2020-01-30 02:30:57 +01:00
|
|
|
#include "wasm/WasmObjcopy.h"
|
2018-10-12 00:33:50 +02:00
|
|
|
|
2017-11-01 22:16:06 +01:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2018-08-01 18:23:22 +02:00
|
|
|
#include "llvm/ADT/SmallVector.h"
|
2017-11-01 22:16:06 +01:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/ADT/Twine.h"
|
2020-10-24 16:35:55 +02:00
|
|
|
#include "llvm/BinaryFormat/ELF.h"
|
2018-07-06 19:51:03 +02:00
|
|
|
#include "llvm/Object/Archive.h"
|
|
|
|
#include "llvm/Object/ArchiveWriter.h"
|
2017-11-01 22:16:06 +01:00
|
|
|
#include "llvm/Object/Binary.h"
|
2018-12-19 08:24:38 +01:00
|
|
|
#include "llvm/Object/COFF.h"
|
2017-11-01 22:16:06 +01:00
|
|
|
#include "llvm/Object/ELFObjectFile.h"
|
|
|
|
#include "llvm/Object/ELFTypes.h"
|
|
|
|
#include "llvm/Object/Error.h"
|
2019-02-02 01:38:07 +01:00
|
|
|
#include "llvm/Object/MachO.h"
|
2020-10-06 12:41:19 +02:00
|
|
|
#include "llvm/Object/MachOUniversal.h"
|
2020-01-30 02:30:57 +01:00
|
|
|
#include "llvm/Object/Wasm.h"
|
2018-04-24 07:43:32 +02:00
|
|
|
#include "llvm/Option/Arg.h"
|
|
|
|
#include "llvm/Option/ArgList.h"
|
|
|
|
#include "llvm/Option/Option.h"
|
2017-11-01 22:16:06 +01:00
|
|
|
#include "llvm/Support/Casting.h"
|
2019-09-14 03:14:43 +02:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2020-10-24 16:35:55 +02:00
|
|
|
#include "llvm/Support/Errc.h"
|
2017-11-01 22:16:06 +01:00
|
|
|
#include "llvm/Support/Error.h"
|
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
|
|
|
#include "llvm/Support/ErrorOr.h"
|
2020-03-11 23:39:28 +01:00
|
|
|
#include "llvm/Support/Host.h"
|
2018-04-13 20:26:06 +02: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-17 20:51:11 +02:00
|
|
|
#include "llvm/Support/Memory.h"
|
2018-05-07 21:32:09 +02:00
|
|
|
#include "llvm/Support/Path.h"
|
2018-08-16 20:29:40 +02:00
|
|
|
#include "llvm/Support/Process.h"
|
2020-10-24 16:35:55 +02:00
|
|
|
#include "llvm/Support/SmallVectorMemoryBuffer.h"
|
2019-09-14 03:14:43 +02:00
|
|
|
#include "llvm/Support/StringSaver.h"
|
2018-08-10 00:52:03 +02:00
|
|
|
#include "llvm/Support/WithColor.h"
|
2017-11-01 22:16:06 +01:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
|
|
|
#include <cstdlib>
|
2017-08-01 02:33:58 +02:00
|
|
|
#include <memory>
|
|
|
|
#include <string>
|
|
|
|
#include <system_error>
|
2017-11-01 22:16:06 +01:00
|
|
|
#include <utility>
|
2017-08-01 02:33:58 +02:00
|
|
|
|
2018-07-18 02:10:51 +02:00
|
|
|
namespace llvm {
|
|
|
|
namespace objcopy {
|
|
|
|
|
|
|
|
// The name this program was invoked as.
|
|
|
|
StringRef ToolName;
|
|
|
|
|
2019-06-18 02:39:10 +02:00
|
|
|
ErrorSuccess reportWarning(Error E) {
|
|
|
|
assert(E);
|
2019-08-20 17:00:07 +02:00
|
|
|
WithColor::warning(errs(), ToolName) << toString(std::move(E)) << '\n';
|
2019-06-18 02:39:10 +02:00
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
2020-10-23 08:13:49 +02: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 02:10:51 +02:00
|
|
|
} // end namespace objcopy
|
2018-10-25 00:49:06 +02:00
|
|
|
} // end namespace llvm
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
using namespace llvm::object;
|
|
|
|
using namespace llvm::objcopy;
|
|
|
|
|
2018-07-06 19:51:03 +02: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 00:17:05 +02:00
|
|
|
static Error deepWriteArchive(StringRef ArcName,
|
|
|
|
ArrayRef<NewArchiveMember> NewMembers,
|
|
|
|
bool WriteSymtab, object::Archive::Kind Kind,
|
|
|
|
bool Deterministic, bool Thin) {
|
2019-02-01 18:08:07 +01:00
|
|
|
if (Error E = writeArchive(ArcName, NewMembers, WriteSymtab, Kind,
|
|
|
|
Deterministic, Thin))
|
|
|
|
return createFileError(ArcName, std::move(E));
|
|
|
|
|
|
|
|
if (!Thin)
|
|
|
|
return Error::success();
|
|
|
|
|
2018-07-06 19:51:03 +02:00
|
|
|
for (const NewArchiveMember &Member : NewMembers) {
|
2020-10-24 16:35:55 +02:00
|
|
|
// For regular files (as is the case for deepWriteArchive),
|
|
|
|
// FileOutputBuffer::create will return OnDiskBuffer.
|
2018-07-06 19:51:03 +02: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 14:31:35 +01:00
|
|
|
Expected<std::unique_ptr<FileOutputBuffer>> FB =
|
|
|
|
FileOutputBuffer::create(Member.MemberName, Member.Buf->getBufferSize(),
|
|
|
|
FileOutputBuffer::F_executable);
|
2020-10-24 16:35:55 +02:00
|
|
|
if (!FB)
|
|
|
|
return FB.takeError();
|
2018-07-06 19:51:03 +02:00
|
|
|
std::copy(Member.Buf->getBufferStart(), Member.Buf->getBufferEnd(),
|
2020-10-24 16:35:55 +02:00
|
|
|
(*FB)->getBufferStart());
|
|
|
|
if (Error E = (*FB)->commit())
|
2018-07-06 19:51:03 +02:00
|
|
|
return E;
|
|
|
|
}
|
|
|
|
return Error::success();
|
|
|
|
}
|
|
|
|
|
2019-06-13 11:56:14 +02:00
|
|
|
/// The function executeObjcopyOnIHex does the dispatch based on the format
|
|
|
|
/// of the output specified by the command line options.
|
2021-04-23 13:19:11 +02:00
|
|
|
static Error executeObjcopyOnIHex(ConfigManager &ConfigMgr, MemoryBuffer &In,
|
2020-10-24 16:35:55 +02:00
|
|
|
raw_ostream &Out) {
|
2019-06-13 11:56:14 +02:00
|
|
|
// TODO: support output formats other than ELF.
|
2021-04-23 13:19:11 +02:00
|
|
|
Expected<const ELFConfig &> ELFConfig = ConfigMgr.getELFConfig();
|
|
|
|
if (!ELFConfig)
|
|
|
|
return ELFConfig.takeError();
|
|
|
|
|
|
|
|
return elf::executeObjcopyOnIHex(ConfigMgr.getCommonConfig(), *ELFConfig, In,
|
|
|
|
Out);
|
2019-06-13 11:56:14 +02:00
|
|
|
}
|
|
|
|
|
2018-10-25 00:49:06 +02:00
|
|
|
/// The function executeObjcopyOnRawBinary does the dispatch based on the format
|
|
|
|
/// of the output specified by the command line options.
|
2021-04-23 13:19:11 +02:00
|
|
|
static Error executeObjcopyOnRawBinary(ConfigManager &ConfigMgr,
|
|
|
|
MemoryBuffer &In, raw_ostream &Out) {
|
|
|
|
const CommonConfig &Config = ConfigMgr.getCommonConfig();
|
2019-07-05 07:28:38 +02: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:
|
2021-04-23 13:19:11 +02:00
|
|
|
Expected<const ELFConfig &> ELFConfig = ConfigMgr.getELFConfig();
|
|
|
|
if (!ELFConfig)
|
|
|
|
return ELFConfig.takeError();
|
|
|
|
|
|
|
|
return elf::executeObjcopyOnRawBinary(Config, *ELFConfig, In, Out);
|
2019-07-05 07:28:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
llvm_unreachable("unsupported output format");
|
2018-10-25 00:49:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// The function executeObjcopyOnBinary does the dispatch based on the format
|
|
|
|
/// of the input binary (ELF, MachO or COFF).
|
2021-04-23 13:19:11 +02:00
|
|
|
static Error executeObjcopyOnBinary(const MultiFormatConfig &Config,
|
|
|
|
object::Binary &In, 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 11:38:23 +02:00
|
|
|
if (auto *ELFBinary = dyn_cast<object::ELFObjectFileBase>(&In)) {
|
2021-04-23 13:19:11 +02:00
|
|
|
Expected<const ELFConfig &> ELFConfig = Config.getELFConfig();
|
|
|
|
if (!ELFConfig)
|
|
|
|
return ELFConfig.takeError();
|
|
|
|
|
|
|
|
return elf::executeObjcopyOnBinary(Config.getCommonConfig(), *ELFConfig,
|
|
|
|
*ELFBinary, Out);
|
|
|
|
} else if (auto *COFFBinary = dyn_cast<object::COFFObjectFile>(&In)) {
|
|
|
|
Expected<const COFFConfig &> COFFConfig = Config.getCOFFConfig();
|
|
|
|
if (!COFFConfig)
|
|
|
|
return COFFConfig.takeError();
|
|
|
|
|
|
|
|
return coff::executeObjcopyOnBinary(Config.getCommonConfig(), *COFFConfig,
|
|
|
|
*COFFBinary, Out);
|
|
|
|
} else if (auto *MachOBinary = dyn_cast<object::MachOObjectFile>(&In)) {
|
|
|
|
Expected<const MachOConfig &> MachOConfig = Config.getMachOConfig();
|
|
|
|
if (!MachOConfig)
|
|
|
|
return MachOConfig.takeError();
|
|
|
|
|
|
|
|
return macho::executeObjcopyOnBinary(Config.getCommonConfig(), *MachOConfig,
|
|
|
|
*MachOBinary, Out);
|
|
|
|
} else if (auto *MachOUniversalBinary =
|
|
|
|
dyn_cast<object::MachOUniversalBinary>(&In)) {
|
2020-10-06 12:41:19 +02:00
|
|
|
return macho::executeObjcopyOnMachOUniversalBinary(
|
|
|
|
Config, *MachOUniversalBinary, Out);
|
2021-04-23 13:19:11 +02:00
|
|
|
} else if (auto *WasmBinary = dyn_cast<object::WasmObjectFile>(&In)) {
|
|
|
|
Expected<const WasmConfig &> WasmConfig = Config.getWasmConfig();
|
|
|
|
if (!WasmConfig)
|
|
|
|
return WasmConfig.takeError();
|
|
|
|
|
|
|
|
return objcopy::wasm::executeObjcopyOnBinary(Config.getCommonConfig(),
|
|
|
|
*WasmConfig, *WasmBinary, Out);
|
|
|
|
} else
|
2019-01-30 15:36:53 +01:00
|
|
|
return createStringError(object_error::invalid_file_type,
|
2019-06-14 04:04:02 +02:00
|
|
|
"unsupported object file format");
|
2018-10-25 00:49:06 +02:00
|
|
|
}
|
|
|
|
|
2020-10-06 12:41:19 +02:00
|
|
|
namespace llvm {
|
|
|
|
namespace objcopy {
|
|
|
|
|
|
|
|
Expected<std::vector<NewArchiveMember>>
|
2021-04-23 13:19:11 +02:00
|
|
|
createNewArchiveMembers(const MultiFormatConfig &Config, const Archive &Ar) {
|
2018-07-06 19:51:03 +02: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-01 18:08:07 +01:00
|
|
|
return createFileError(Ar.getFileName(), ChildNameOrErr.takeError());
|
2018-07-06 19:51:03 +02:00
|
|
|
|
2019-05-08 15:28:58 +02:00
|
|
|
Expected<std::unique_ptr<Binary>> ChildOrErr = Child.getAsBinary();
|
|
|
|
if (!ChildOrErr)
|
|
|
|
return createFileError(Ar.getFileName() + "(" + *ChildNameOrErr + ")",
|
|
|
|
ChildOrErr.takeError());
|
|
|
|
|
2020-10-24 16:35:55 +02:00
|
|
|
SmallVector<char, 0> Buffer;
|
|
|
|
raw_svector_ostream MemStream(Buffer);
|
|
|
|
|
|
|
|
if (Error E = executeObjcopyOnBinary(Config, *ChildOrErr->get(), MemStream))
|
2020-10-06 12:41:19 +02:00
|
|
|
return std::move(E);
|
2018-07-06 19:51:03 +02:00
|
|
|
|
2021-04-23 13:19:11 +02:00
|
|
|
Expected<NewArchiveMember> Member = NewArchiveMember::getOldMember(
|
|
|
|
Child, Config.getCommonConfig().DeterministicArchives);
|
2018-07-06 19:51:03 +02:00
|
|
|
if (!Member)
|
2019-02-01 18:08:07 +01:00
|
|
|
return createFileError(Ar.getFileName(), Member.takeError());
|
2020-10-24 16:35:55 +02:00
|
|
|
|
|
|
|
Member->Buf = std::make_unique<SmallVectorMemoryBuffer>(
|
|
|
|
std::move(Buffer), ChildNameOrErr.get());
|
2018-07-06 19:51:03 +02:00
|
|
|
Member->MemberName = Member->Buf->getBufferIdentifier();
|
|
|
|
NewArchiveMembers.push_back(std::move(*Member));
|
|
|
|
}
|
|
|
|
if (Err)
|
2021-04-23 13:19:11 +02:00
|
|
|
return createFileError(Config.getCommonConfig().InputFilename,
|
|
|
|
std::move(Err));
|
2020-10-06 12:41:19 +02:00
|
|
|
return std::move(NewArchiveMembers);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // end namespace objcopy
|
|
|
|
} // end namespace llvm
|
2019-02-01 18:08:07 +01:00
|
|
|
|
2021-04-23 13:19:11 +02:00
|
|
|
static Error executeObjcopyOnArchive(const ConfigManager &ConfigMgr,
|
2020-10-06 12:41:19 +02:00
|
|
|
const object::Archive &Ar) {
|
|
|
|
Expected<std::vector<NewArchiveMember>> NewArchiveMembersOrErr =
|
2021-04-23 13:19:11 +02:00
|
|
|
createNewArchiveMembers(ConfigMgr, Ar);
|
2020-10-06 12:41:19 +02:00
|
|
|
if (!NewArchiveMembersOrErr)
|
|
|
|
return NewArchiveMembersOrErr.takeError();
|
2021-04-23 13:19:11 +02:00
|
|
|
const CommonConfig &Config = ConfigMgr.getCommonConfig();
|
2020-10-06 12:41:19 +02:00
|
|
|
return deepWriteArchive(Config.OutputFilename, *NewArchiveMembersOrErr,
|
2019-02-01 18:08:07 +01:00
|
|
|
Ar.hasSymbolTable(), Ar.kind(),
|
|
|
|
Config.DeterministicArchives, Ar.isThin());
|
2018-07-06 19:51:03 +02: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 00:45:27 +02:00
|
|
|
static Error restoreStatOnFile(StringRef Filename,
|
|
|
|
const sys::fs::file_status &Stat,
|
2021-04-23 13:19:11 +02:00
|
|
|
const ConfigManager &ConfigMgr) {
|
2018-08-16 20:29:40 +02:00
|
|
|
int FD;
|
2021-04-23 13:19:11 +02:00
|
|
|
const CommonConfig &Config = ConfigMgr.getCommonConfig();
|
2018-08-16 20:29:40 +02: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 00:45:27 +02: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 01:21:56 +02:00
|
|
|
if (auto EC =
|
|
|
|
sys::fs::openFileForWrite(Filename, FD, sys::fs::CD_OpenExisting))
|
2019-02-21 18:05:19 +01:00
|
|
|
return createFileError(Filename, EC);
|
2018-08-16 20:29:40 +02:00
|
|
|
|
2021-02-24 20:10:09 +01: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 00:45:27 +02:00
|
|
|
if (auto EC = sys::fs::setLastAccessAndModificationTime(
|
|
|
|
FD, Stat.getLastAccessedTime(), Stat.getLastModificationTime()))
|
|
|
|
return createFileError(Filename, EC);
|
|
|
|
|
2019-07-11 12:17:59 +02:00
|
|
|
sys::fs::file_status OStat;
|
|
|
|
if (std::error_code EC = sys::fs::status(FD, OStat))
|
2019-02-21 18:05:19 +01:00
|
|
|
return createFileError(Filename, EC);
|
2021-02-24 20:10:09 +01:00
|
|
|
if (OStat.type() == sys::fs::file_type::regular_file) {
|
2021-04-12 13:27:14 +02: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-24 20:10:09 +01:00
|
|
|
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 12:17:59 +02:00
|
|
|
#ifdef _WIN32
|
2021-02-24 20:10:09 +01:00
|
|
|
if (auto EC = sys::fs::setPermissions(Filename, Perm))
|
2019-07-11 12:17:59 +02:00
|
|
|
#else
|
2021-02-24 20:10:09 +01:00
|
|
|
if (auto EC = sys::fs::setPermissions(FD, Perm))
|
2019-07-11 12:17:59 +02:00
|
|
|
#endif
|
|
|
|
return createFileError(Filename, EC);
|
2021-02-24 20:10:09 +01:00
|
|
|
}
|
2018-08-16 20:29:40 +02:00
|
|
|
|
|
|
|
if (auto EC = sys::Process::SafelyCloseFileDescriptor(FD))
|
2019-02-21 18:05:19 +01:00
|
|
|
return createFileError(Filename, EC);
|
|
|
|
|
|
|
|
return Error::success();
|
2018-08-16 20:29:40 +02:00
|
|
|
}
|
|
|
|
|
2018-10-25 00:49:06 +02: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.
|
2021-04-23 13:19:11 +02:00
|
|
|
static Error executeObjcopy(ConfigManager &ConfigMgr) {
|
|
|
|
CommonConfig &Config = ConfigMgr.Common;
|
|
|
|
|
2018-08-16 20:29:40 +02: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 00:45:27 +02:00
|
|
|
if (Config.InputFilename != "-") {
|
2018-08-16 20:29:40 +02:00
|
|
|
if (auto EC = sys::fs::status(Config.InputFilename, Stat))
|
2019-02-21 18:05:19 +01: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 00:45:27 +02:00
|
|
|
} else {
|
|
|
|
Stat.permissions(static_cast<sys::fs::perms>(0777));
|
|
|
|
}
|
2018-08-16 20:29:40 +02:00
|
|
|
|
2021-03-11 23:31:06 +01:00
|
|
|
std::function<Error(raw_ostream & OutFile)> ObjcopyFunc;
|
2019-06-13 11:56:14 +02:00
|
|
|
|
2021-03-11 23:31:06 +01: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-17 20:51:11 +02:00
|
|
|
if (!BufOrErr)
|
2019-02-21 18:05:19 +01:00
|
|
|
return createFileError(Config.InputFilename, BufOrErr.getError());
|
2021-03-11 23:31:06 +01:00
|
|
|
MemoryBufferHolder = std::move(*BufOrErr);
|
|
|
|
|
|
|
|
if (Config.InputFormat == FileFormat::Binary)
|
|
|
|
ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
|
|
|
|
// Handle FileFormat::Binary.
|
2021-04-23 13:19:11 +02:00
|
|
|
return executeObjcopyOnRawBinary(ConfigMgr, *MemoryBufferHolder,
|
|
|
|
OutFile);
|
2021-03-11 23:31:06 +01:00
|
|
|
};
|
|
|
|
else
|
|
|
|
ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
|
|
|
|
// Handle FileFormat::IHex.
|
2021-04-23 13:19:11 +02:00
|
|
|
return executeObjcopyOnIHex(ConfigMgr, *MemoryBufferHolder, OutFile);
|
2021-03-11 23:31:06 +01:00
|
|
|
};
|
[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-17 20:51:11 +02:00
|
|
|
} else {
|
|
|
|
Expected<OwningBinary<llvm::object::Binary>> BinaryOrErr =
|
|
|
|
createBinary(Config.InputFilename);
|
|
|
|
if (!BinaryOrErr)
|
2019-02-21 18:05:19 +01:00
|
|
|
return createFileError(Config.InputFilename, BinaryOrErr.takeError());
|
2021-03-11 23:31:06 +01: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-17 20:51:11 +02:00
|
|
|
|
2021-03-11 23:31:06 +01:00
|
|
|
if (Archive *Ar = dyn_cast<Archive>(BinaryHolder.getBinary())) {
|
|
|
|
// Handle Archive.
|
2021-04-23 13:19:11 +02:00
|
|
|
if (Error E = executeObjcopyOnArchive(ConfigMgr, *Ar))
|
2019-02-21 18:05:19 +01: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-17 20:51:11 +02:00
|
|
|
} else {
|
2021-03-11 23:31:06 +01:00
|
|
|
// Handle llvm::object::Binary.
|
|
|
|
ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
|
2021-04-23 13:19:11 +02:00
|
|
|
return executeObjcopyOnBinary(ConfigMgr, *BinaryHolder.getBinary(),
|
2021-03-11 23:31:06 +01:00
|
|
|
OutFile);
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ObjcopyFunc) {
|
|
|
|
if (Config.SplitDWO.empty()) {
|
|
|
|
// Apply transformations described by Config and store result into
|
|
|
|
// Config.OutputFilename using specified ObjcopyFunc function.
|
2021-03-04 10:51:30 +01:00
|
|
|
if (Error E = writeToOutput(Config.OutputFilename, ObjcopyFunc))
|
2021-03-11 23:31:06 +01:00
|
|
|
return E;
|
|
|
|
} else {
|
|
|
|
Config.ExtractDWO = true;
|
|
|
|
Config.StripDWO = false;
|
|
|
|
// Copy .dwo tables from the Config.InputFilename into Config.SplitDWO
|
|
|
|
// file using specified ObjcopyFunc function.
|
2021-03-04 10:51:30 +01:00
|
|
|
if (Error E = writeToOutput(Config.SplitDWO, ObjcopyFunc))
|
2021-03-11 23:31:06 +01:00
|
|
|
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.
|
2021-03-04 10:51:30 +01:00
|
|
|
if (Error E = writeToOutput(Config.OutputFilename, ObjcopyFunc))
|
2019-02-21 18:05:19 +01: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-17 20:51:11 +02:00
|
|
|
}
|
2018-08-16 20:29:40 +02:00
|
|
|
}
|
2018-07-06 19:51:03 +02:00
|
|
|
|
2021-04-23 13:19:11 +02:00
|
|
|
if (Error E = restoreStatOnFile(Config.OutputFilename, Stat, ConfigMgr))
|
[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 00:45:27 +02:00
|
|
|
return E;
|
|
|
|
|
|
|
|
if (!Config.SplitDWO.empty()) {
|
|
|
|
Stat.permissions(static_cast<sys::fs::perms>(0666));
|
2021-04-23 13:19:11 +02:00
|
|
|
if (Error E = restoreStatOnFile(Config.SplitDWO, Stat, ConfigMgr))
|
2019-02-21 18:05:19 +01:00
|
|
|
return E;
|
2018-08-16 20:29:40 +02:00
|
|
|
}
|
2019-02-21 18:05:19 +01:00
|
|
|
|
|
|
|
return Error::success();
|
2018-07-06 19:51:03 +02:00
|
|
|
}
|
|
|
|
|
2019-11-20 08:30:52 +01:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
2017-08-01 02:33:58 +02:00
|
|
|
int main(int argc, char **argv) {
|
2018-04-13 20:26:06 +02:00
|
|
|
InitLLVM X(argc, argv);
|
2017-08-01 02:33:58 +02:00
|
|
|
ToolName = argv[0];
|
2020-03-22 07:39:01 +01:00
|
|
|
|
2019-09-14 03:14:43 +02: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 08:13:49 +02:00
|
|
|
Expected<DriverConfig> DriverConfig = getDriverConfig(Args);
|
|
|
|
|
2019-02-21 18:05:19 +01:00
|
|
|
if (!DriverConfig) {
|
|
|
|
logAllUnhandledErrors(DriverConfig.takeError(),
|
|
|
|
WithColor::error(errs(), ToolName));
|
|
|
|
return 1;
|
|
|
|
}
|
2021-04-23 13:19:11 +02:00
|
|
|
for (ConfigManager &ConfigMgr : DriverConfig->CopyConfigs) {
|
|
|
|
if (Error E = executeObjcopy(ConfigMgr)) {
|
2019-02-21 18:05:19 +01:00
|
|
|
logAllUnhandledErrors(std::move(E), WithColor::error(errs(), ToolName));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2017-08-01 02:33:58 +02:00
|
|
|
}
|