--- /dev/null
+//
+// Snapshot.h
+// ld64
+//
+// Created by Josh Behnke on 8/25/11.
+// Copyright (c) 2011 Apple Inc. All rights reserved.
+//
+
+#ifndef ld64_Snapshot_h
+#define ld64_Snapshot_h
+#include <stdint.h>
+#include <string.h>
+#include <map>
+#include <vector>
+
+#include "ld.hpp"
+
+class Options;
+class SnapshotLogItem;
+
+class Snapshot {
+
+public:
+ static Snapshot *globalSnapshot;
+
+ typedef enum {
+ SNAPSHOT_DISABLED, // nothing is recorded
+ SNAPSHOT_DEBUG, // records: .o, .dylib, .framework, .a, and other data files
+ } SnapshotMode;
+
+ Snapshot();
+ ~Snapshot();
+
+ // Control the data captured in the snapshot
+ void setSnapshotMode(SnapshotMode mode);
+
+ // Use the basename of path to construct the snapshot name.
+ // Must be called prior to createSnapshot().
+ void setSnapshotName(const char *path);
+
+ // Set the directory in which the snapshot will be created.
+ // Must be called prior to createSnapshot().
+ void setSnapshotPath(const char *path);
+
+ // Stores the linker command line in the snapshot
+ void recordRawArgs(int argc, const char *argv[]);
+
+ // Adds one or more args to the snapshot link command.
+ // argIndex is the index in the original raw args vector to start adding args
+ // argCount is the count of args to copy from the raw args vector
+ // fileArg is the index relative to argIndex of a file arg. The file is copied into the
+ // snapshot and the path is fixed up in the snapshot link command. (skipped if fileArg==-1)
+ // recordRawArgs() must be called prior to the first call to addSnapshotLinkArg()
+ void addSnapshotLinkArg(int argIndex, int argCount=1, int fileArg=-1);
+
+ // record the -arch string
+ void recordArch(const char *arch);
+
+ // Stores an object file in the snapshot, using a unique name in an "objects" subdir.
+ void recordObjectFile(const char *path);
+
+ // Records symbol names used in dylibs. Does not store anything in the snapshot.
+ void recordDylibSymbol(ld::dylib::File* dylibFile, const char *name);
+
+ // Stores an archive (.a) file in the snapshot.
+ void recordArchive(const char *archiveFile);
+
+ // Copies the framework binary into the snapshot frameworks directory.
+ void recordSubUmbrella(const char *frameworkPath);
+
+ // Copies the library binary into the snapshot dylibs directory.
+ void recordSubLibrary(const char *dylibPath);
+
+ // Records arbitrary text messages into a log file in the snapshot.
+ // Used by the assertion failure machienery.
+ void recordAssertionMessage(const char *fmt, ...);
+
+ // Create the snapshot.
+ // Until this is called the snapshot operates lazily, storing minimal data in memory.
+ // When this is called the snapshot is created and any previously recorded data is
+ // immediately copied. Any subsequent additions to the snapshot are copied immediately.
+ void createSnapshot();
+
+ // Returns the snapshot root directory.
+ const char *rootDir() { return fRootDir; }
+
+private:
+
+ friend class SnapshotArchiveFileLog;
+
+ typedef std::vector<void(^)(void)> SnapshotLog;
+
+ struct strcompclass {
+ bool operator() (const char *a, const char *b) const { return ::strcmp(a, b) < 0; }
+ };
+ typedef std::vector<const char *> StringVector;
+ typedef std::map<const char *, int, strcompclass > DylibMap;
+ typedef std::map<const char *, const char *, strcompclass> PathMap;
+
+
+ // Write the current contents of the args vector to a file in the snapshot.
+ // If filename is NULL then "link_command" is used.
+ // This is used to write both the original and the "cooked" versions of the link command
+ void writeCommandLine(StringVector &args, const char *filename=NULL, bool includeCWD=false);
+
+ // Construct a path in the snapshot.
+ // buf is a sring buffer in which the path is constructed
+ // subdir is an optional subdirectory, and file is a file name
+ // Constructs the path <snapshot_root>/<subdir>/<file> in buf
+ void buildPath(char *buf, const char *subdir, const char *file);
+
+ // Similar to buildPath(), except this ensures the returned path
+ // does not reference an existing file in the snapshot.
+ // Performs uniquing by appending a count suffex to the path (ie .../file-XX)
+ void buildUniquePath(char *buf, const char *subdir, const char *file);
+
+ // Copies an arbitrary file to the snapshot. Subdir specifies an optional subdirectory name.
+ // Uses buildUniquePath to construct a unique path. If the result path is needed by the caller
+ // then a path buffer can be supplied in buf. Otherwise an internal buffer is used.
+ void copyFileToSnapshot(const char *sourcePath, const char *subdir, char *buf=NULL);
+
+ // Convert a full path to snapshot relative by constructing an interior pointer at the right offset.
+ const char *snapshotRelativePath(const char *path) { return path+strlen(fRootDir)+1; }
+
+ // returns true if the snapshot has not been created (by createSnapshot()) yet
+ bool isLazy() { return fRootDir == NULL; }
+
+ void addFrameworkArg(const char *framework);
+ void addDylibArg(const char *dylib);
+
+ SnapshotLog fLog; // log of events that recorded data in a snapshot prior to createSnapshot()
+ bool fRecordArgs; // record command line
+ bool fRecordObjects; // record .o files
+ bool fRecordDylibSymbols; // record referenced dylib/framework symbols
+ bool fRecordArchiveFiles; // record .a files
+ bool fRecordUmbrellaFiles; // record re-exported sub frameworks/dylibs
+ bool fRecordDataFiles; // record other data files
+ bool fFrameworkArgAdded;
+
+ const char *fSnapshotLocation; // parent directory of frootDir
+ const char *fSnapshotName; // a string to use in constructing the snapshot name
+ char *fRootDir; // root directory of the snapshot
+ int fFilelistFile; // file descriptor to the open text file used for the -filelist
+
+ StringVector fRawArgs; // stores the raw command line args
+ StringVector fArgs; // stores the "cooked" command line args
+ PathMap fPathMap; // mapping of original paths->snapshot paths for copied files
+
+ DylibMap fDylibSymbols; // map of dylib names to string vector containing referenced symbol names
+ StringVector *fCopiedArchives; // vector of .a files that have been copied to the snapshot
+};
+
+#endif