1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 11:02:59 +02:00

[llvm-lipo] Add support for -arch

Add support for -arch.

Differential revision: https://reviews.llvm.org/D68116

Test plan: make check-all

llvm-svn: 373132
This commit is contained in:
Alexander Shaposhnikov 2019-09-27 22:33:18 +00:00
parent 59afa86678
commit 5d5e87b41e
4 changed files with 68 additions and 44 deletions

View File

@ -0,0 +1,17 @@
# RUN: yaml2obj %p/Inputs/i386-slice.yaml > %t-i386.o
# RUN: yaml2obj %p/Inputs/x86_64-slice.yaml > %t-x86_64.o
# RUN: llvm-lipo %t-i386.o %t-x86_64.o -create -output %t-universal.o
# RUN: llvm-lipo %t-i386.o -arch x86_64 %t-x86_64.o -create -output %t-universal-1.o
# RUN: cmp %t-universal.o %t-universal-1.o
# RUN: llvm-lipo -arch i386 %t-i386.o -arch x86_64 %t-x86_64.o -create -output %t-universal-2.o
# RUN: cmp %t-universal.o %t-universal-2.o
#
# RUN: not llvm-lipo -arch armv7 %t-i386.o -arch x86_64 %t-x86_64.o -create -output /dev/null 2>&1 | FileCheck --check-prefix=ARCH_NOT_MATCHED %s
# ARCH_NOT_MATCHED: error: specified architecture: armv7 for file: {{.*}} does not match the file's architecture (i386)
#
# # RUN: not llvm-lipo -arch i3866 %t-32.o -create -o /dev/null 2>&1 | FileCheck --check-prefix=INVALID_ARCH %s
# INVALID_ARCH: error: Invalid architecture: i3866
#
# RUN: not llvm-lipo -arch i386 %t-33.o -create -o /dev/null 2>&1 | FileCheck --check-prefix=INVALID_FILE %s
# INVALID_FILE: {{[nN]}}o such file or directory

View File

@ -5,20 +5,20 @@
# RUN: not llvm-lipo %t-universal.o -replace %t-32.o 2>&1 | FileCheck --check-prefix=MISSING_ARG %s
# MISSING_ARG: error: replace is missing an argument: expects -replace arch_type file_name
# RUN: not llvm-lipo %t-universal.o -replace %t-32.o i386 2>&1 | FileCheck --check-prefix=OUTPUT_FILE %s
# RUN: not llvm-lipo %t-universal.o -replace i386 %t-32.o 2>&1 | FileCheck --check-prefix=OUTPUT_FILE %s
# OUTPUT_FILE: error: replace expects a single output file to be specified
# RUN: not llvm-lipo %t-universal.o %t-universal.o -replace %t-32.o i386 -o %t.o 2>&1 | FileCheck --check-prefix=INPUT_ARGS %s
# RUN: not llvm-lipo %t-universal.o %t-universal.o -replace i386 %t-32.o -o %t.o 2>&1 | FileCheck --check-prefix=INPUT_ARGS %s
# INPUT_ARGS: error: replace expects a single input file
# RUN: not llvm-lipo %t-universal.o -replace %t-32.o i386 -o %t.o 2>&1 | FileCheck --check-prefix=INVALID_FILE %s
# INVALID_FILE: error: 'i386': {{[nN]}}o such file or directory
# RUN: not llvm-lipo %t-universal.o -replace i386 %t-33.o -o %t.o 2>&1 | FileCheck --check-prefix=INVALID_FILE %s
# INVALID_FILE: {{[nN]}}o such file or directory
# RUN: not llvm-lipo %t-universal.o -replace i3866 %t-32.o -o %t.o 2>&1 | FileCheck --check-prefix=INVALID_ARCH %s
# INVALID_ARCH: error: Invalid architecture: i3866
# RUN: not llvm-lipo %t-universal.o -replace arm64 %t-32.o -o %t.o 2>&1 | FileCheck --check-prefix=ARCH_NOT_MATCHED %s
# ARCH_NOT_MATCHED: error: specified architecture: arm64 for replacement file: {{.*}} does not match the file's architecture
# ARCH_NOT_MATCHED: error: specified architecture: arm64 for file: {{.*}} does not match the file's architecture (i386)
# RUN: not llvm-lipo %t-universal.o -replace arm64 %t-arm64.o -o %t.o 2>&1 | FileCheck --check-prefix=ARCH_NOT_IN_INPUT %s
# ARCH_NOT_IN_INPUT: error: -replace arm64 <file_name> specified but fat file: {{.*}} does not contain that architecture

View File

@ -12,6 +12,10 @@ def segalign
"architecture when creating a universal binary file. The "
"alignment is a hexadecimal number that is a power of 2.">;
def arch
: MultiArg<["-", "--"], "arch", 2>,
HelpText<"Specifies the architecture and the corresponding input file">;
def action_group : OptionGroup<"action group">;
def verify_arch

View File

@ -86,15 +86,15 @@ enum class LipoAction {
ReplaceArch,
};
struct Replacement {
StringRef ArchType;
struct InputFile {
Optional<StringRef> ArchType;
StringRef FileName;
};
struct Config {
SmallVector<std::string, 1> InputFiles;
SmallVector<InputFile, 1> InputFiles;
SmallVector<std::string, 1> VerifyArchList;
SmallVector<Replacement, 1> Replacements;
SmallVector<InputFile, 1> ReplacementFiles;
StringMap<const uint32_t> SegmentAlignments;
std::string ThinArchType;
std::string OutputFile;
@ -301,7 +301,15 @@ static Config parseLipoOptions(ArrayRef<const char *> ArgsArr) {
reportError("unknown argument '" + Arg->getAsString(InputArgs) + "'");
for (auto Arg : InputArgs.filtered(LIPO_INPUT))
C.InputFiles.push_back(Arg->getValue());
C.InputFiles.push_back({None, Arg->getValue()});
for (auto Arg : InputArgs.filtered(LIPO_arch)) {
validateArchitectureName(Arg->getValue(0));
if (!Arg->getValue(1))
reportError(
"arch is missing an argument: expects -arch arch_type file_name");
C.InputFiles.push_back({StringRef(Arg->getValue(0)), Arg->getValue(1)});
}
if (C.InputFiles.empty())
reportError("at least one input file should be specified");
@ -402,8 +410,9 @@ static Config parseLipoOptions(ArrayRef<const char *> ArgsArr) {
reportError(
"replace is missing an argument: expects -replace arch_type "
"file_name");
C.Replacements.push_back(
Replacement{Action->getValue(0), Action->getValue(1)});
validateArchitectureName(Action->getValue(0));
C.ReplacementFiles.push_back(
{StringRef(Action->getValue(0)), Action->getValue(1)});
}
if (C.OutputFile.empty())
@ -419,16 +428,25 @@ static Config parseLipoOptions(ArrayRef<const char *> ArgsArr) {
}
static SmallVector<OwningBinary<Binary>, 1>
readInputBinaries(ArrayRef<std::string> InputFiles) {
readInputBinaries(ArrayRef<InputFile> InputFiles) {
SmallVector<OwningBinary<Binary>, 1> InputBinaries;
for (StringRef InputFile : InputFiles) {
Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(InputFile);
for (const InputFile &IF : InputFiles) {
Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(IF.FileName);
if (!BinaryOrErr)
reportError(InputFile, BinaryOrErr.takeError());
if (!BinaryOrErr->getBinary()->isArchive() &&
!BinaryOrErr->getBinary()->isMachO() &&
!BinaryOrErr->getBinary()->isMachOUniversalBinary())
reportError("File " + InputFile + " has unsupported binary format");
reportError(IF.FileName, BinaryOrErr.takeError());
const Binary *B = BinaryOrErr->getBinary();
if (!B->isArchive() && !B->isMachO() && !B->isMachOUniversalBinary())
reportError("File " + IF.FileName + " has unsupported binary format");
if (IF.ArchType && (B->isMachO() || B->isArchive())) {
const auto ArchType =
B->isMachO() ? Slice(cast<MachOObjectFile>(B)).getArchString()
: Slice(cast<Archive>(B)).getArchString();
if (Triple(*IF.ArchType).getArch() != Triple(ArchType).getArch())
reportError("specified architecture: " + *IF.ArchType +
" for file: " + B->getFileName() +
" does not match the file's architecture (" + ArchType +
")");
}
InputBinaries.push_back(std::move(*BinaryOrErr));
}
return InputBinaries;
@ -716,32 +734,20 @@ static void createUniversalBinary(ArrayRef<OwningBinary<Binary>> InputBinaries,
static StringMap<Slice>
buildReplacementSlices(ArrayRef<OwningBinary<Binary>> ReplacementBinaries,
const StringMap<const uint32_t> &Alignments,
ArrayRef<Replacement> Replacements) {
assert(ReplacementBinaries.size() == Replacements.size() &&
"Number of replacment binaries does not match the number of "
"replacements");
const StringMap<const uint32_t> &Alignments) {
StringMap<Slice> Slices;
// populates StringMap of slices to replace with; error checks for mismatched
// replace flag args, fat files, and duplicate arch_types
for (size_t Index = 0, Size = Replacements.size(); Index < Size; ++Index) {
StringRef ReplacementArch = Replacements[Index].ArchType;
const Binary *ReplacementBinary = ReplacementBinaries[Index].getBinary();
validateArchitectureName(ReplacementArch);
for (const auto &OB : ReplacementBinaries) {
const Binary *ReplacementBinary = OB.getBinary();
auto O = dyn_cast<MachOObjectFile>(ReplacementBinary);
if (!O)
reportError("replacement file: " + ReplacementBinary->getFileName() +
" is a fat file (must be a thin file)");
if (O->getArch() != Triple(ReplacementArch).getArch())
reportError("specified architecture: " + ReplacementArch +
" for replacement file: " + ReplacementBinary->getFileName() +
" does not match the file's architecture");
auto Entry = Slices.try_emplace(ReplacementArch, Slice(O));
Slice S(O);
auto Entry = Slices.try_emplace(S.getArchString(), S);
if (!Entry.second)
reportError("-replace " + ReplacementArch +
reportError("-replace " + S.getArchString() +
" <file_name> specified multiple times: " +
Entry.first->second.getBinary()->getFileName() + ", " +
O->getFileName());
@ -756,7 +762,7 @@ LLVM_ATTRIBUTE_NORETURN
static void replaceSlices(ArrayRef<OwningBinary<Binary>> InputBinaries,
const StringMap<const uint32_t> &Alignments,
StringRef OutputFileName,
ArrayRef<Replacement> Replacements) {
ArrayRef<InputFile> ReplacementFiles) {
assert(InputBinaries.size() == 1 && "Incorrect number of input binaries");
assert(!OutputFileName.empty() && "Replace expects a single output file");
@ -765,14 +771,11 @@ static void replaceSlices(ArrayRef<OwningBinary<Binary>> InputBinaries,
InputBinaries.front().getBinary()->getFileName() +
" must be a fat file when the -replace option is specified");
SmallVector<std::string, 1> ReplacementFiles;
for (const auto &R : Replacements)
ReplacementFiles.push_back(R.FileName);
SmallVector<OwningBinary<Binary>, 1> ReplacementBinaries =
readInputBinaries(ReplacementFiles);
StringMap<Slice> ReplacementSlices =
buildReplacementSlices(ReplacementBinaries, Alignments, Replacements);
buildReplacementSlices(ReplacementBinaries, Alignments);
SmallVector<std::unique_ptr<MachOObjectFile>, 2> ExtractedObjects;
SmallVector<Slice, 2> Slices =
buildSlices(InputBinaries, Alignments, ExtractedObjects);
@ -820,7 +823,7 @@ int main(int argc, char **argv) {
break;
case LipoAction::ReplaceArch:
replaceSlices(InputBinaries, C.SegmentAlignments, C.OutputFile,
C.Replacements);
C.ReplacementFiles);
break;
}
return EXIT_SUCCESS;