mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-01 13:20:25 +00:00
Reorganize the cpio archiver as CpioFile class. NFC.
This code separates the code to create cpio archive from the driver. llvm-svn: 269593
This commit is contained in:
parent
6c7bddb28b
commit
fe65877c76
@ -48,7 +48,6 @@ struct Configuration {
|
||||
llvm::StringRef SoName;
|
||||
llvm::StringRef Sysroot;
|
||||
std::string RPath;
|
||||
std::string Reproduce;
|
||||
std::vector<llvm::StringRef> DynamicList;
|
||||
std::vector<llvm::StringRef> SearchPaths;
|
||||
std::vector<llvm::StringRef> Undefined;
|
||||
|
@ -114,7 +114,8 @@ void LinkerDriver::addFile(StringRef Path) {
|
||||
return;
|
||||
MemoryBufferRef MBRef = *Buffer;
|
||||
|
||||
maybeCopyInputFile(Path, MBRef.getBuffer());
|
||||
if (Cpio)
|
||||
Cpio->append(relativeToRoot(Path), MBRef.getBuffer());
|
||||
|
||||
switch (identify_magic(MBRef.getBuffer())) {
|
||||
case file_magic::unknown:
|
||||
@ -252,15 +253,12 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
|
||||
readConfigs(Args);
|
||||
initLLVM(Args);
|
||||
|
||||
if (!Config->Reproduce.empty()) {
|
||||
std::error_code EC;
|
||||
std::string File = Config->Reproduce + ".cpio";
|
||||
ReproduceArchive = llvm::make_unique<raw_fd_ostream>(File, EC, fs::F_None);
|
||||
if (EC) {
|
||||
error(EC, "--reproduce: failed to open " + File);
|
||||
return;
|
||||
}
|
||||
createResponseFile(Args);
|
||||
if (auto *Arg = Args.getLastArg(OPT_reproduce)) {
|
||||
// Note that --reproduce is a debug option so you can ignore it
|
||||
// if you are trying to understand the whole picture of the code.
|
||||
Cpio.reset(CpioFile::create(Arg->getValue()));
|
||||
if (Cpio)
|
||||
Cpio->append("response.txt", createResponseFile(Args));
|
||||
}
|
||||
|
||||
createFiles(Args);
|
||||
@ -340,7 +338,6 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
|
||||
Config->Fini = getString(Args, OPT_fini, "_fini");
|
||||
Config->Init = getString(Args, OPT_init, "_init");
|
||||
Config->OutputFile = getString(Args, OPT_o);
|
||||
Config->Reproduce = getString(Args, OPT_reproduce);
|
||||
Config->SoName = getString(Args, OPT_soname);
|
||||
Config->Sysroot = getString(Args, OPT_sysroot);
|
||||
|
||||
|
@ -23,16 +23,15 @@ namespace elf {
|
||||
|
||||
extern class LinkerDriver *Driver;
|
||||
|
||||
class CpioFile;
|
||||
|
||||
class LinkerDriver {
|
||||
public:
|
||||
void main(ArrayRef<const char *> Args);
|
||||
void addFile(StringRef Path);
|
||||
void addLibrary(StringRef Name);
|
||||
llvm::LLVMContext Context;
|
||||
|
||||
// for --reproduce
|
||||
std::unique_ptr<llvm::raw_fd_ostream> ReproduceArchive;
|
||||
llvm::StringSet<> IncludedFiles;
|
||||
llvm::LLVMContext Context; // to parse bitcode ifles
|
||||
std::unique_ptr<CpioFile> Cpio; // for reproduce
|
||||
|
||||
private:
|
||||
std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef MB);
|
||||
@ -70,12 +69,37 @@ enum {
|
||||
#undef OPTION
|
||||
};
|
||||
|
||||
// This is the class to create a .cpio file for --reproduce.
|
||||
//
|
||||
// If "--reproduce foo" is given, we create a file "foo.cpio" and
|
||||
// copy all input files to the archive, along with a response file
|
||||
// to re-run the same command with the same inputs.
|
||||
// It is useful for reporting issues to LLD developers.
|
||||
//
|
||||
// Cpio as a file format is a deliberate choice. It's standardized in
|
||||
// POSIX and very easy to create. cpio command is available virtually
|
||||
// on all Unix systems. See
|
||||
// http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_07
|
||||
// for the format details.
|
||||
class CpioFile {
|
||||
public:
|
||||
static CpioFile *create(StringRef OutputPath);
|
||||
void append(StringRef Path, StringRef Data);
|
||||
|
||||
private:
|
||||
CpioFile(std::unique_ptr<llvm::raw_fd_ostream> OS, StringRef Basename);
|
||||
|
||||
std::unique_ptr<llvm::raw_fd_ostream> OS;
|
||||
llvm::StringSet<> Seen;
|
||||
std::string Basename;
|
||||
};
|
||||
|
||||
void printHelp(const char *Argv0);
|
||||
void printVersion();
|
||||
std::vector<uint8_t> parseHexstring(StringRef S);
|
||||
|
||||
void createResponseFile(const llvm::opt::InputArgList &Args);
|
||||
void maybeCopyInputFile(StringRef Path, StringRef Buffer);
|
||||
std::string createResponseFile(const llvm::opt::InputArgList &Args);
|
||||
std::string relativeToRoot(StringRef Path);
|
||||
|
||||
std::string findFromSearchPaths(StringRef Path);
|
||||
std::string searchLibrary(StringRef Path);
|
||||
|
@ -107,7 +107,7 @@ std::vector<uint8_t> elf::parseHexstring(StringRef S) {
|
||||
// Makes a given pathname an absolute path first, and then remove
|
||||
// beginning /. For example, "../foo.o" is converted to "home/john/foo.o",
|
||||
// assuming that the current directory is "/home/john/bar".
|
||||
static std::string relativeToRoot(StringRef Path) {
|
||||
std::string elf::relativeToRoot(StringRef Path) {
|
||||
SmallString<128> Abs = Path;
|
||||
if (std::error_code EC = fs::make_absolute(Abs))
|
||||
fatal("make_absolute failed: " + EC.message());
|
||||
@ -127,22 +127,26 @@ static std::string relativeToRoot(StringRef Path) {
|
||||
return Res.str();
|
||||
}
|
||||
|
||||
static std::string getDestPath(StringRef Path) {
|
||||
std::string Relpath = relativeToRoot(Path);
|
||||
SmallString<128> Dest;
|
||||
path::append(Dest, path::filename(Config->Reproduce), Relpath);
|
||||
return Dest.str();
|
||||
CpioFile::CpioFile(std::unique_ptr<llvm::raw_fd_ostream> OS, StringRef S)
|
||||
: OS(std::move(OS)), Basename(S) {}
|
||||
|
||||
CpioFile *CpioFile::create(StringRef OutputPath) {
|
||||
std::string Path = (OutputPath + ".cpio").str();
|
||||
std::error_code EC;
|
||||
auto OS = llvm::make_unique<raw_fd_ostream>(Path, EC, fs::F_None);
|
||||
if (EC) {
|
||||
error(EC, "--reproduce: failed to open " + Path);
|
||||
return nullptr;
|
||||
}
|
||||
return new CpioFile(std::move(OS), path::filename(OutputPath));
|
||||
}
|
||||
|
||||
static void maybePrintCpioMemberAux(raw_fd_ostream &OS, StringRef Path,
|
||||
StringRef Data) {
|
||||
OS << "070707"; // c_magic
|
||||
|
||||
// The c_dev/c_ino pair should be unique according to the spec, but no one
|
||||
// seems to care.
|
||||
OS << "000000"; // c_dev
|
||||
OS << "000000"; // c_ino
|
||||
|
||||
static void writeMember(raw_fd_ostream &OS, StringRef Path, StringRef Data) {
|
||||
// The c_dev/c_ino pair should be unique according to the spec,
|
||||
// but no one seems to care.
|
||||
OS << "070707"; // c_magic
|
||||
OS << "000000"; // c_dev
|
||||
OS << "000000"; // c_ino
|
||||
OS << "100664"; // c_mode: C_ISREG | rw-rw-r--
|
||||
OS << "000000"; // c_uid
|
||||
OS << "000000"; // c_gid
|
||||
@ -155,28 +159,22 @@ static void maybePrintCpioMemberAux(raw_fd_ostream &OS, StringRef Path,
|
||||
OS << Data; // c_filedata
|
||||
}
|
||||
|
||||
static void maybePrintCpioMember(StringRef Path, StringRef Data) {
|
||||
if (Config->Reproduce.empty())
|
||||
void CpioFile::append(StringRef Path, StringRef Data) {
|
||||
if (!Seen.insert(Path).second)
|
||||
return;
|
||||
|
||||
if (!Driver->IncludedFiles.insert(Path).second)
|
||||
return;
|
||||
raw_fd_ostream &OS = *Driver->ReproduceArchive;
|
||||
maybePrintCpioMemberAux(OS, Path, Data);
|
||||
// Construct an in-archive filename so that /home/foo/bar is stored
|
||||
// as baz/home/foo/bar where baz is the basename of the output file.
|
||||
// (i.e. in that case we are creating baz.cpio.)
|
||||
SmallString<128> Fullpath;
|
||||
path::append(Fullpath, Basename, Path);
|
||||
writeMember(*OS, Fullpath, Data);
|
||||
|
||||
// Print the trailer and seek back. This way we have a valid archive if we
|
||||
// crash.
|
||||
// See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_11
|
||||
// for the format details.
|
||||
uint64_t Pos = OS.tell();
|
||||
maybePrintCpioMemberAux(OS, "TRAILER!!!", "");
|
||||
OS.seek(Pos);
|
||||
}
|
||||
|
||||
// Write file Src with content Data to the archive.
|
||||
void elf::maybeCopyInputFile(StringRef Src, StringRef Data) {
|
||||
std::string Dest = getDestPath(Src);
|
||||
maybePrintCpioMember(Dest, Data);
|
||||
// Print the trailer and seek back.
|
||||
// This way we have a valid archive if we crash.
|
||||
uint64_t Pos = OS->tell();
|
||||
writeMember(*OS, "TRAILER!!!", "");
|
||||
OS->seek(Pos);
|
||||
}
|
||||
|
||||
// Quote a given string if it contains a space character.
|
||||
@ -202,15 +200,13 @@ static std::string stringize(opt::Arg *Arg) {
|
||||
return K + " " + V;
|
||||
}
|
||||
|
||||
// Copies all input files to Config->Reproduce directory and
|
||||
// create a response file as "response.txt", so that you can re-run
|
||||
// the same command with the same inputs just by executing
|
||||
// "ld.lld @response.txt". Used by --reproduce. This feature is
|
||||
// supposed to be used by users to report an issue to LLD developers.
|
||||
void elf::createResponseFile(const opt::InputArgList &Args) {
|
||||
// Reconstructs command line arguments so that so that you can re-run
|
||||
// the same command with the same inputs. This is for --reproduce.
|
||||
std::string elf::createResponseFile(const opt::InputArgList &Args) {
|
||||
SmallString<0> Data;
|
||||
raw_svector_ostream OS(Data);
|
||||
// Copy the command line to response.txt while rewriting paths.
|
||||
|
||||
// Copy the command line to the output while rewriting paths.
|
||||
for (auto *Arg : Args) {
|
||||
switch (Arg->getOption().getID()) {
|
||||
case OPT_reproduce:
|
||||
@ -230,10 +226,7 @@ void elf::createResponseFile(const opt::InputArgList &Args) {
|
||||
OS << stringize(Arg) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
SmallString<128> Dest;
|
||||
path::append(Dest, path::filename(Config->Reproduce), "response.txt");
|
||||
maybePrintCpioMember(Dest, Data);
|
||||
return Data.str();
|
||||
}
|
||||
|
||||
std::string elf::findFromSearchPaths(StringRef Path) {
|
||||
|
@ -394,8 +394,9 @@ MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) {
|
||||
"could not get the buffer for the member defining symbol " +
|
||||
Sym->getName());
|
||||
|
||||
if (C.getParent()->isThin())
|
||||
maybeCopyInputFile(check(C.getFullName()), Ret.getBuffer());
|
||||
if (C.getParent()->isThin() && Driver->Cpio)
|
||||
Driver->Cpio->append(relativeToRoot(check(C.getFullName())),
|
||||
Ret.getBuffer());
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user