mirror of
https://github.com/QuasarApp/macdependency.git
synced 2025-05-11 02:39:34 +00:00
Add uuid, dylinker commands, file size > 32bit accepted, fix user home directory detection, add file type for kernel extension, some refactorings
This commit is contained in:
parent
56090db6ad
commit
0d586e75f0
MacDependency/MacDependency.xcodeproj
MachO
MachO.xcodeproj
dylinkercommand.cppdylinkercommand.hdynamicloader.cppdynamicloader.hinternalfile.cppinternalfile.hloadcommand.cppmacho.cppmacho.hmachoarchitecture.cppmachoarchitecture.hmachofile.cppmachofile.hmachoheader.cppmachoheader.hrpathcommand.cpprpathcommand.hsymboltableentry.huuidcommand.cppuuidcommand.h@ -264,7 +264,11 @@
|
||||
};
|
||||
buildConfigurationList = C05733CB08A9546B00998B17 /* Build configuration list for PBXProject "MacDependency" */;
|
||||
compatibilityVersion = "Xcode 3.1";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 2A37F4AAFDCFA73011CA2CEA /* MacDependency */;
|
||||
projectDirPath = "";
|
||||
projectReferences = (
|
||||
@ -400,6 +404,7 @@
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = "$(HOME)/Applications";
|
||||
PRODUCT_NAME = MacDependency;
|
||||
SDKROOT = macosx10.6;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@ -419,7 +424,7 @@
|
||||
INFOPLIST_FILE = Info.plist;
|
||||
INSTALL_PATH = "$(HOME)/Applications";
|
||||
PRODUCT_NAME = MacDependency;
|
||||
SDKROOT = macosx10.5;
|
||||
SDKROOT = macosx10.6;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@ -430,6 +435,7 @@
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
GCC_VERSION = "";
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
@ -445,6 +451,7 @@
|
||||
GCC_WARN_UNUSED_LABEL = YES;
|
||||
GCC_WARN_UNUSED_VALUE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.5;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PREBINDING = NO;
|
||||
SDKROOT = macosx10.5;
|
||||
@ -456,8 +463,10 @@
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_VERSION = "";
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.5;
|
||||
PREBINDING = NO;
|
||||
SDKROOT = macosx10.5;
|
||||
};
|
||||
|
@ -50,6 +50,10 @@
|
||||
8E49393F100AA468004B7E53 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E49393E100AA468004B7E53 /* CoreFoundation.framework */; };
|
||||
8E8C73E1106AA95D0037CF19 /* libboost_filesystem.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E8C73DF106AA95D0037CF19 /* libboost_filesystem.a */; };
|
||||
8E8C73E2106AA95D0037CF19 /* libboost_system.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8E8C73E0106AA95D0037CF19 /* libboost_system.a */; };
|
||||
8EA3DFF411AFD3790093CD87 /* uuidcommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8EA3DFF211AFD3790093CD87 /* uuidcommand.cpp */; };
|
||||
8EA3DFF511AFD3790093CD87 /* uuidcommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 8EA3DFF311AFD3790093CD87 /* uuidcommand.h */; };
|
||||
8EA3E17A11B12B5A0093CD87 /* dylinkercommand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8EA3E17811B12B5A0093CD87 /* dylinkercommand.cpp */; };
|
||||
8EA3E17B11B12B5A0093CD87 /* dylinkercommand.h in Headers */ = {isa = PBXBuildFile; fileRef = 8EA3E17911B12B5A0093CD87 /* dylinkercommand.h */; };
|
||||
8ED32FDE100B99EC00EBF623 /* machocache.h in Headers */ = {isa = PBXBuildFile; fileRef = 8ED32FDC100B99EC00EBF623 /* machocache.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8ED32FDF100B99EC00EBF623 /* machocache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8ED32FDD100B99EC00EBF623 /* machocache.cpp */; };
|
||||
/* End PBXBuildFile section */
|
||||
@ -103,6 +107,10 @@
|
||||
8E49393E100AA468004B7E53 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
|
||||
8E8C73DF106AA95D0037CF19 /* libboost_filesystem.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libboost_filesystem.a; path = /usr/local/lib/static/libboost_filesystem.a; sourceTree = "<absolute>"; };
|
||||
8E8C73E0106AA95D0037CF19 /* libboost_system.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libboost_system.a; path = /usr/local/lib/static/libboost_system.a; sourceTree = "<absolute>"; };
|
||||
8EA3DFF211AFD3790093CD87 /* uuidcommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = uuidcommand.cpp; sourceTree = "<group>"; };
|
||||
8EA3DFF311AFD3790093CD87 /* uuidcommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = uuidcommand.h; sourceTree = "<group>"; };
|
||||
8EA3E17811B12B5A0093CD87 /* dylinkercommand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dylinkercommand.cpp; sourceTree = "<group>"; };
|
||||
8EA3E17911B12B5A0093CD87 /* dylinkercommand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dylinkercommand.h; sourceTree = "<group>"; };
|
||||
8ED32FDC100B99EC00EBF623 /* machocache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = machocache.h; sourceTree = "<group>"; };
|
||||
8ED32FDD100B99EC00EBF623 /* machocache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = machocache.cpp; sourceTree = "<group>"; };
|
||||
D2F7E79907B2D74100F64583 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = /System/Library/Frameworks/CoreData.framework; sourceTree = "<absolute>"; };
|
||||
@ -163,6 +171,10 @@
|
||||
08FB77AEFE84172EC02AAC07 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
8EA3E17811B12B5A0093CD87 /* dylinkercommand.cpp */,
|
||||
8EA3E17911B12B5A0093CD87 /* dylinkercommand.h */,
|
||||
8EA3DFF211AFD3790093CD87 /* uuidcommand.cpp */,
|
||||
8EA3DFF311AFD3790093CD87 /* uuidcommand.h */,
|
||||
8E131512100F7C6B00367510 /* demangler.cpp */,
|
||||
8E131513100F7C6B00367510 /* demangler.h */,
|
||||
8E131514100F7C6B00367510 /* dylibcommand.cpp */,
|
||||
@ -264,6 +276,8 @@
|
||||
8E131557100F7C6B00367510 /* symboltableentry32.h in Headers */,
|
||||
8E131572100F7DB600367510 /* symboltableentry64.h in Headers */,
|
||||
8E212E93101237A50078924A /* machodemangleexception.h in Headers */,
|
||||
8EA3DFF511AFD3790093CD87 /* uuidcommand.h in Headers */,
|
||||
8EA3E17B11B12B5A0093CD87 /* dylinkercommand.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -296,7 +310,11 @@
|
||||
isa = PBXProject;
|
||||
buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "MachO" */;
|
||||
compatibilityVersion = "Xcode 3.1";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = 0867D691FE84028FC02AAC07 /* MachO */;
|
||||
productRefGroup = 034768DFFF38A50411DB9C8B /* Products */;
|
||||
projectDirPath = "";
|
||||
@ -343,6 +361,8 @@
|
||||
8E131556100F7C6B00367510 /* symboltableentry32.cpp in Sources */,
|
||||
8E131571100F7DB600367510 /* symboltableentry64.cpp in Sources */,
|
||||
8E212E94101237A50078924A /* machodemangleexception.cpp in Sources */,
|
||||
8EA3DFF411AFD3790093CD87 /* uuidcommand.cpp in Sources */,
|
||||
8EA3E17A11B12B5A0093CD87 /* dylinkercommand.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -387,6 +407,7 @@
|
||||
LIBRARY_SEARCH_PATHS = /usr/local/lib/static;
|
||||
OTHER_LDFLAGS = "-Wl,-search_paths_first";
|
||||
PRODUCT_NAME = MachO;
|
||||
SDKROOT = macosx10.6;
|
||||
WRAPPER_EXTENSION = framework;
|
||||
};
|
||||
name = Debug;
|
||||
@ -409,6 +430,7 @@
|
||||
LIBRARY_SEARCH_PATHS = /usr/local/lib/static;
|
||||
OTHER_LDFLAGS = "-Wl,-search_paths_first";
|
||||
PRODUCT_NAME = MachO;
|
||||
SDKROOT = macosx10.6;
|
||||
WRAPPER_EXTENSION = framework;
|
||||
};
|
||||
name = Release;
|
||||
@ -419,6 +441,7 @@
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
DEPLOYMENT_LOCATION = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_INLINES_ARE_PRIVATE_EXTERN = NO;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
@ -433,7 +456,6 @@
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
PREBINDING = NO;
|
||||
|
21
MachO/dylinkercommand.cpp
Normal file
21
MachO/dylinkercommand.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "dylinkercommand.h"
|
||||
#include "machofile.h"
|
||||
#include "machoheader.h"
|
||||
#include <sstream>
|
||||
|
||||
DylinkerCommand::DylinkerCommand(MachOHeader* header) :
|
||||
LoadCommand(header) {
|
||||
file.readBytes((char*)&command, sizeof(command));
|
||||
}
|
||||
|
||||
DylinkerCommand::~DylinkerCommand() {
|
||||
}
|
||||
|
||||
unsigned int DylinkerCommand::getSize() const {
|
||||
return file.getUint32(command.cmdsize);
|
||||
}
|
||||
|
||||
string DylinkerCommand::getName() const {
|
||||
return string(getLcDataString(command.name.offset));
|
||||
}
|
||||
|
19
MachO/dylinkercommand.h
Normal file
19
MachO/dylinkercommand.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef DYLINKERCOMMAND_H
|
||||
#define DYLINKERCOMMAND_H
|
||||
|
||||
#include "macho_global.h"
|
||||
#include "loadcommand.h"
|
||||
class EXPORT DylinkerCommand : public LoadCommand
|
||||
{
|
||||
public:
|
||||
DylinkerCommand(MachOHeader* header);
|
||||
virtual ~DylinkerCommand();
|
||||
virtual unsigned int getSize() const;
|
||||
virtual unsigned int getStructureSize() const { return sizeof(command); }
|
||||
string getName() const;
|
||||
private:
|
||||
dylinker_command command;
|
||||
|
||||
};
|
||||
|
||||
#endif // DYLINKERCOMMAND_H
|
@ -3,29 +3,31 @@
|
||||
#include "machoarchitecture.h"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <pwd.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
This class emulates the search path mechanism of dyld
|
||||
http://developer.apple.com/documentation/Darwin/Reference/Manpages/man1/dyld.1.html
|
||||
Unfortunately the several documents from apple contradict each other. Therefore I analyzed the source of the original dyld
|
||||
http://www.opensource.apple.com/source/dyld/dyld-97.1/src/dyld.cpp
|
||||
*/
|
||||
This class emulates the search path mechanism of dyld
|
||||
http://developer.apple.com/documentation/Darwin/Reference/Manpages/man1/dyld.1.html
|
||||
Unfortunately the several documents from apple contradict each other. Therefore I analyzed the source of the original dyld
|
||||
http://www.opensource.apple.com/source/dyld/dyld-97.1/src/dyld.cpp
|
||||
*/
|
||||
|
||||
const char* DynamicLoader::EnvironmentPathVariable::PATHS_SEPARATOR = ";";
|
||||
const char* DynamicLoader::EnvironmentPathVariable::HOME_PATH = getenv("HOME");
|
||||
const char DynamicLoader::EnvironmentPathVariable::PATHS_SEPARATOR[] = ":";
|
||||
|
||||
DynamicLoader::EnvironmentPathVariable::EnvironmentPathVariable() {
|
||||
// default constructor (should not be used explicitly)
|
||||
// never call that explicitly
|
||||
}
|
||||
|
||||
DynamicLoader::EnvironmentPathVariable::EnvironmentPathVariable(const string& name, const StringList& defaultValues)
|
||||
DynamicLoader::EnvironmentPathVariable::EnvironmentPathVariable(const char* homePath, const string& name, const StringList& defaultValues)
|
||||
{
|
||||
this->homePath = homePath;
|
||||
const char* envValue = getenv(name.c_str());
|
||||
string values;
|
||||
if (envValue) {
|
||||
values = envValue;
|
||||
}
|
||||
|
||||
|
||||
if (!values.empty()) {
|
||||
size_t start = 0;
|
||||
size_t end;
|
||||
@ -40,7 +42,7 @@ DynamicLoader::EnvironmentPathVariable::EnvironmentPathVariable(const string& na
|
||||
|
||||
void DynamicLoader::EnvironmentPathVariable::setPaths(const StringList& paths) {
|
||||
this->paths = paths;
|
||||
|
||||
|
||||
for (StringList::iterator it = this->paths.begin(); it!=this->paths.end(); ++it) {
|
||||
replaceHomeDirectory(*it);
|
||||
}
|
||||
@ -52,12 +54,12 @@ void DynamicLoader::EnvironmentPathVariable::addPath(const string& path) {
|
||||
}
|
||||
|
||||
bool DynamicLoader::EnvironmentPathVariable::replaceHomeDirectory(string& path) {
|
||||
size_t homePos = path.find("~");
|
||||
if (homePos != string::npos) {
|
||||
path.replace(homePos, 1, HOME_PATH);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
size_t homePos = path.find("~/");
|
||||
if (homePos != string::npos) {
|
||||
path.replace(homePos, 1, homePath);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DynamicLoader::EnvironmentPathVariable::isEmpty() const {
|
||||
@ -86,10 +88,10 @@ const char* DynamicLoader::PLACEHOLDERS[DynamicLoader::NumPlaceholders] = {
|
||||
const char* DynamicLoader::PATH_SEPARATOR = "/";
|
||||
|
||||
const char* DynamicLoader::DEFAULT_FRAMEWORK_PATH[] = {
|
||||
"~/Library/Frameworks",
|
||||
"/Library/Frameworks",
|
||||
"/Network/Library/Frameworks",
|
||||
"/System/Library/Frameworks"
|
||||
"~/Library/Frameworks",
|
||||
"/Library/Frameworks",
|
||||
"/Network/Library/Frameworks",
|
||||
"/System/Library/Frameworks"
|
||||
};
|
||||
|
||||
const char* DynamicLoader::DEFAULT_LIBRARY_PATH[] = {
|
||||
@ -111,9 +113,28 @@ const StringList DynamicLoader::ENVIRONMENT_VARIABLE_DEFAULT_VALUES[DynamicLoade
|
||||
|
||||
DynamicLoader::DynamicLoader()
|
||||
{
|
||||
homePath = strdup(getUserHomeDirectory());
|
||||
// init/read out some variables
|
||||
for (unsigned int i=0; i < NumEnvironmentVariables; i++) {
|
||||
environmentVariables[i] = EnvironmentPathVariable(ENVIRONMENT_VARIABLE_NAMES[i], ENVIRONMENT_VARIABLE_DEFAULT_VALUES[i]);
|
||||
environmentVariables[i] = EnvironmentPathVariable(homePath, ENVIRONMENT_VARIABLE_NAMES[i], ENVIRONMENT_VARIABLE_DEFAULT_VALUES[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DynamicLoader::~DynamicLoader() {
|
||||
free((void*)homePath);
|
||||
}
|
||||
|
||||
const char* DynamicLoader::getUserHomeDirectory() const {
|
||||
struct passwd* pwd = getpwuid(getuid());
|
||||
if (pwd)
|
||||
{
|
||||
return pwd->pw_dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
// try the $HOME environment variable
|
||||
return getenv("HOME");
|
||||
}
|
||||
}
|
||||
|
||||
@ -123,8 +144,6 @@ string DynamicLoader::replacePlaceholder(const string& name, const MachOArchitec
|
||||
resolvedName.replace(0, strlen(PLACEHOLDERS[ExecutablePath]), architecture->getFile()->getExecutablePath());
|
||||
} else if (name.find(PLACEHOLDERS[LoaderPath]) == 0) {
|
||||
resolvedName.replace(0, strlen(PLACEHOLDERS[LoaderPath]), architecture->getFile()->getPath());
|
||||
} else {
|
||||
return string();
|
||||
}
|
||||
return resolvedName;
|
||||
}
|
||||
@ -138,75 +157,73 @@ string DynamicLoader::getPathname(const string& name, const MachOArchitecture* a
|
||||
} else {
|
||||
simpleName = name;
|
||||
}
|
||||
|
||||
|
||||
// try LD_LIBRARY_PATH
|
||||
string pathName;
|
||||
pathName = getExistingPathname(simpleName, environmentVariables[LdLibraryPath]);
|
||||
pathName = getExistingPathname(simpleName, environmentVariables[LdLibraryPath], workingPath);
|
||||
if (!pathName.empty())
|
||||
return pathName;
|
||||
|
||||
|
||||
string frameworkName = getFrameworkName(name);
|
||||
if (!frameworkName.empty()) {
|
||||
// strip the already contained suffix
|
||||
pathName = getExistingPathname(frameworkName, environmentVariables[DyldFrameworkPath]);
|
||||
pathName = getExistingPathname(frameworkName, environmentVariables[DyldFrameworkPath], workingPath);
|
||||
if (!pathName.empty())
|
||||
return pathName;
|
||||
}
|
||||
|
||||
pathName = getExistingPathname(simpleName, environmentVariables[DyldLibraryPath]);
|
||||
|
||||
pathName = getExistingPathname(simpleName, environmentVariables[DyldLibraryPath], workingPath);
|
||||
if (!pathName.empty())
|
||||
return pathName;
|
||||
|
||||
|
||||
// resolve placeholder
|
||||
string resolvedName = replacePlaceholder(name, architecture);
|
||||
if (!resolvedName.empty()) {
|
||||
pathName = getExistingPathname(resolvedName);
|
||||
pathName = getExistingPathname(resolvedName, workingPath);
|
||||
if (!pathName.empty())
|
||||
return pathName;
|
||||
}
|
||||
|
||||
if (name.find(PLACEHOLDERS[RPath]) == 0) {
|
||||
|
||||
if (name.find(PLACEHOLDERS[Rpath]) == 0) {
|
||||
// substitute @rpath with all -rpath paths up the load chain
|
||||
std::vector<string*> rPaths = architecture->getRPaths();
|
||||
|
||||
for (std::vector<string*>::iterator it = rPaths.begin(); it != rPaths.end(); ++it) {
|
||||
std::vector<string*> rpaths = architecture->getRpaths();
|
||||
|
||||
for (std::vector<string*>::iterator it = rpaths.begin(); it != rpaths.end(); ++it) {
|
||||
// rpath may contain @loader_path or @executable_path
|
||||
string rpath = replacePlaceholder((**it), architecture);
|
||||
resolvedName = name;
|
||||
resolvedName.replace(0, strlen(PLACEHOLDERS[RPath]), (**it));
|
||||
pathName = getExistingPathname(resolvedName);
|
||||
resolvedName.replace(0, strlen(PLACEHOLDERS[Rpath]), rpath);
|
||||
pathName = getExistingPathname(resolvedName, workingPath);
|
||||
if (!pathName.empty())
|
||||
return pathName;
|
||||
}
|
||||
|
||||
|
||||
// after checking against all stored rpaths substitute @rpath with LD_LIBRARY_PATH (if it is set)
|
||||
EnvironmentPathVariable ldLibraryPaths = environmentVariables[LdLibraryPath];
|
||||
if (!ldLibraryPaths.isEmpty()) {
|
||||
for (StringList::const_iterator it = ldLibraryPaths.getPaths().begin(); it != ldLibraryPaths.getPaths().end(); ++it) {
|
||||
resolvedName = name;
|
||||
resolvedName.replace(0, strlen(PLACEHOLDERS[RPath]), (*it));
|
||||
pathName = getExistingPathname(resolvedName);
|
||||
resolvedName.replace(0, strlen(PLACEHOLDERS[Rpath]), (*it));
|
||||
pathName = getExistingPathname(resolvedName, workingPath);
|
||||
if (!pathName.empty())
|
||||
return pathName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check pure path (either absolute or relative to working directory)
|
||||
if (name.find(PATH_SEPARATOR) == 0) {
|
||||
pathName = getExistingPathname(name);
|
||||
} else {
|
||||
pathName = getExistingPathname(name, workingPath);
|
||||
}
|
||||
pathName = getExistingPathname(name, workingPath);
|
||||
if (!pathName.empty())
|
||||
return pathName;
|
||||
|
||||
|
||||
// try fallbacks (or its defaults)
|
||||
if (!frameworkName.empty()) {
|
||||
pathName = getExistingPathname(frameworkName, environmentVariables[DyldFallbackFrameworkPath]);
|
||||
pathName = getExistingPathname(frameworkName, environmentVariables[DyldFallbackFrameworkPath], workingPath);
|
||||
if (!pathName.empty())
|
||||
return pathName;
|
||||
}
|
||||
|
||||
return getExistingPathname(name, environmentVariables[DyldFallbackLibraryPath]);
|
||||
|
||||
return getExistingPathname(name, environmentVariables[DyldFallbackLibraryPath], workingPath);
|
||||
}
|
||||
|
||||
// returns the name is of a framework without any preceeding path information if name specifies a framework, otherwise an invalid string
|
||||
@ -215,21 +232,21 @@ string DynamicLoader::getFrameworkName(const string& name, const bool strippedSu
|
||||
if (name.find(".framework/") == string::npos) {
|
||||
return string();
|
||||
}
|
||||
|
||||
|
||||
/* first look for the form Foo.framework/Foo
|
||||
next look for the form Foo.framework/Versions/A/Foo
|
||||
A and Foo are arbitrary strings without a slash */
|
||||
|
||||
next look for the form Foo.framework/Versions/A/Foo
|
||||
A and Foo are arbitrary strings without a slash */
|
||||
|
||||
// get Foo (part after last slash)
|
||||
size_t lastSlashPosition = name.rfind(PATH_SEPARATOR);
|
||||
if (lastSlashPosition == string::npos || lastSlashPosition == name.length() -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const string foo = name.substr(lastSlashPosition+1);
|
||||
const string frameworkPart = foo+".framework/";
|
||||
const string framework = frameworkPart + foo;
|
||||
|
||||
|
||||
if (endsWith(name, framework)) {
|
||||
// strip first part
|
||||
return framework;
|
||||
@ -257,18 +274,18 @@ string DynamicLoader::getFrameworkName(const string& name, const bool strippedSu
|
||||
return string();
|
||||
}
|
||||
|
||||
string DynamicLoader::getExistingPathname(const string& name, const EnvironmentPathVariable& environmentPathVariable) const {
|
||||
string DynamicLoader::getExistingPathname(const string& name, const EnvironmentPathVariable& environmentPathVariable, const string& workingPath) const {
|
||||
string result;
|
||||
const StringList directories = environmentPathVariable.getPaths();
|
||||
for (StringList::const_iterator it = directories.begin(); it != directories.end(); ++it) {
|
||||
result = getExistingPathname(name, *it);
|
||||
result = getExistingPathname(name, *it, workingPath);
|
||||
if (!result.empty())
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
string DynamicLoader::getExistingPathname(const string& file, const string& directory) const {
|
||||
string DynamicLoader::getExistingPathname(const string& file, const string& directory, const string& workingPath) const {
|
||||
string name = file;
|
||||
if (!directory.empty()) {
|
||||
if (!endsWith(directory, "/")) {
|
||||
@ -277,34 +294,42 @@ string DynamicLoader::getExistingPathname(const string& file, const string& dire
|
||||
name = directory + file;
|
||||
}
|
||||
}
|
||||
return getExistingPathname(name);
|
||||
return getExistingPathname(name, workingPath);
|
||||
}
|
||||
|
||||
string DynamicLoader::getExistingPathname(const string& name) const {
|
||||
|
||||
string DynamicLoader::getExistingPathname(const string& name, const string& workingPath, bool withSuffix) const {
|
||||
|
||||
boost::filesystem::path path;
|
||||
|
||||
// complete path
|
||||
string usedName = name;
|
||||
bool tryAgainWithoutSuffix = false;
|
||||
|
||||
// first try with suffix
|
||||
if (!environmentVariables[DyldImageSuffix].isEmpty()) {
|
||||
if (withSuffix && !environmentVariables[DyldImageSuffix].isEmpty()) {
|
||||
// only one suffix is considered
|
||||
const string suffix = environmentVariables[DyldImageSuffix].getPaths().front();
|
||||
string nameWithSuffix = name;
|
||||
// where should we append suffix?
|
||||
if (endsWith(name, ".dylib")) {
|
||||
nameWithSuffix.insert(name.rfind("."), suffix);
|
||||
usedName.insert(name.rfind("."), suffix);
|
||||
} else {
|
||||
nameWithSuffix += suffix;
|
||||
usedName += suffix;
|
||||
}
|
||||
|
||||
path = nameWithSuffix;
|
||||
if (boost::filesystem::exists(path)) {
|
||||
return nameWithSuffix;
|
||||
}
|
||||
}
|
||||
|
||||
// then without suffix
|
||||
path = name;
|
||||
if (boost::filesystem::exists(path)) {
|
||||
return name;
|
||||
}
|
||||
tryAgainWithoutSuffix = true;
|
||||
}
|
||||
|
||||
path = usedName;
|
||||
// complete path (with working directory)
|
||||
path = boost::filesystem::complete(path, workingPath);
|
||||
|
||||
if (boost::filesystem::exists(path)) {
|
||||
return path.file_string();
|
||||
} else {
|
||||
// try without suffix
|
||||
if (tryAgainWithoutSuffix) {
|
||||
return getExistingPathname(name, workingPath, false);
|
||||
}
|
||||
}
|
||||
return string();
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ class DynamicLoader
|
||||
{
|
||||
public:
|
||||
DynamicLoader();
|
||||
virtual ~DynamicLoader() {}
|
||||
virtual ~DynamicLoader();
|
||||
|
||||
string replacePlaceholder(const string& name, const MachOArchitecture* architecture) const;
|
||||
string getPathname(const string& name, const MachOArchitecture* architecture, const string& workingDirectory) const;
|
||||
@ -20,21 +20,21 @@ public:
|
||||
private:
|
||||
class EnvironmentPathVariable
|
||||
{
|
||||
|
||||
public:
|
||||
EnvironmentPathVariable();
|
||||
EnvironmentPathVariable(const string& name, const StringList& defaultValues = StringList());
|
||||
EnvironmentPathVariable(const char* homePath, const string& name, const StringList& defaultValues = StringList());
|
||||
|
||||
bool isEmpty() const;
|
||||
const StringList& getPaths() const { return paths; }
|
||||
|
||||
private:
|
||||
|
||||
void setPaths(const StringList& paths);
|
||||
void addPath(const string& path);
|
||||
bool replaceHomeDirectory(string& path);
|
||||
StringList paths;
|
||||
static const char* PATHS_SEPARATOR;
|
||||
static const char* HOME_PATH;
|
||||
static const char PATHS_SEPARATOR[];
|
||||
const char* homePath;
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -50,7 +50,7 @@ private:
|
||||
enum Placeholder {
|
||||
ExecutablePath,
|
||||
LoaderPath,
|
||||
RPath,
|
||||
Rpath,
|
||||
NumPlaceholders
|
||||
};
|
||||
|
||||
@ -61,13 +61,16 @@ private:
|
||||
|
||||
static const char* DEFAULT_FRAMEWORK_PATH[];
|
||||
static const char* DEFAULT_LIBRARY_PATH[];
|
||||
const char* homePath;
|
||||
|
||||
EnvironmentPathVariable environmentVariables[NumEnvironmentVariables];
|
||||
|
||||
string getFrameworkName(const string& name, const bool strippedSuffix = false) const;
|
||||
string getExistingPathname(const string& name, const EnvironmentPathVariable& environmentPathVariable) const;
|
||||
string getExistingPathname(const string& name, const string& directory) const;
|
||||
string getExistingPathname(const string& name) const;
|
||||
const char* getUserHomeDirectory() const;
|
||||
|
||||
string getExistingPathname(const string& name, const EnvironmentPathVariable& environmentPathVariable, const string& workingPath) const;
|
||||
string getExistingPathname(const string& name, const string& directory, const string& workingPath) const;
|
||||
string getExistingPathname(const string& name, const string& workingPath, bool withSuffix=true) const;
|
||||
|
||||
static bool endsWith(const string& str, const string& substr);
|
||||
};
|
||||
|
@ -65,7 +65,7 @@ string InternalFile::getTitle() const {
|
||||
return filename.filename();
|
||||
}
|
||||
|
||||
long long int InternalFile::getSize() const {
|
||||
unsigned long long InternalFile::getSize() const {
|
||||
return file_size(filename);
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ public:
|
||||
string getPath() const;
|
||||
string getName() const;
|
||||
string getTitle() const;
|
||||
long long int getSize() const;
|
||||
unsigned long long getSize() const;
|
||||
bool seek(long long int position);
|
||||
streamsize read(char* buffer, streamsize size);
|
||||
long long int getPosition();
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include "genericcommand.h"
|
||||
#include "symboltablecommand.h"
|
||||
#include "rpathcommand.h"
|
||||
#include "uuidcommand.h"
|
||||
#include "dylinkercommand.h"
|
||||
#include "machoexception.h"
|
||||
#include "machoheader.h"
|
||||
#include "/usr/include/mach-o/loader.h"
|
||||
@ -11,6 +13,12 @@ LoadCommand* LoadCommand::getLoadCommand(unsigned int cmd, MachOHeader* header)
|
||||
|
||||
LoadCommand* loadCommand;
|
||||
switch(cmd) {
|
||||
case LC_LOAD_DYLINKER:
|
||||
loadCommand = new DylinkerCommand(header);
|
||||
break;
|
||||
case LC_UUID:
|
||||
loadCommand = new UuidCommand(header);
|
||||
break;
|
||||
case LC_LAZY_LOAD_DYLIB: // dependency is loaded when it is needed
|
||||
loadCommand = new DylibCommand(header, DylibCommand::DependencyDelayed);
|
||||
break;
|
||||
@ -28,7 +36,7 @@ LoadCommand* LoadCommand::getLoadCommand(unsigned int cmd, MachOHeader* header)
|
||||
loadCommand = new SymbolTableCommand(header);
|
||||
break;
|
||||
case LC_RPATH:
|
||||
loadCommand = new RPathCommand(header);
|
||||
loadCommand = new RpathCommand(header);
|
||||
break;
|
||||
default:
|
||||
loadCommand = new GenericCommand(header);
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include <mach-o/fat.h>
|
||||
|
||||
// see http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
|
||||
// for MachO specification
|
||||
|
||||
// static variables
|
||||
Demangler* MachO::demangler = 0;
|
||||
@ -143,7 +145,7 @@ MachOArchitecture* MachO::getHostCompatibleArchitecture() const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
long long int MachO::getSize() const {
|
||||
unsigned long long MachO::getSize() const {
|
||||
return file->getSize();
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ public:
|
||||
MachOArchitecturesIterator getArchitecturesEnd();
|
||||
MachOArchitecture* getCompatibleArchitecture(MachOArchitecture* destArchitecture) const;
|
||||
MachOArchitecture* getHostCompatibleArchitecture() const;
|
||||
long long int getSize() const;
|
||||
unsigned long long getSize() const;
|
||||
time_t getLastModificationTime() const;
|
||||
string getVersion() const;
|
||||
string getName() const;
|
||||
|
@ -5,12 +5,14 @@
|
||||
#include "dylibcommand.h"
|
||||
#include "machoexception.h"
|
||||
#include "rpathcommand.h"
|
||||
#include "uuidcommand.h"
|
||||
#include "dylinkercommand.h"
|
||||
#include "macho.h"
|
||||
#include "dynamicloader.h"
|
||||
|
||||
|
||||
MachOArchitecture::MachOArchitecture(MachOFile& file, uint32_t magic, unsigned int size) :
|
||||
header(MachOHeader::getHeader(file, magic)), file(header->getFile()), size(size), hasReadLoadCommands(false), parent(0), dynamicLibIdCommand(0)
|
||||
header(MachOHeader::getHeader(file, magic)), file(header->getFile()), size(size), hasReadLoadCommands(false), parent(0), dynamicLibIdCommand(0), uuid(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -26,12 +28,17 @@ string MachOArchitecture::getResolvedName(const string& name, const string& work
|
||||
return name;
|
||||
}
|
||||
|
||||
std::vector<string*> MachOArchitecture::getRPaths() const {
|
||||
std::vector<string*> MachOArchitecture::getRpaths(bool recursively) const {
|
||||
// try to get it from the parent (recursively)
|
||||
std::vector<string*> prevRPaths = parent?(std::vector<string*>(parent->getRPaths())):(std::vector<string*>());
|
||||
std::vector<string*> prevRpaths;
|
||||
if (recursively && parent) {
|
||||
prevRpaths = parent->getRpaths(recursively);
|
||||
} else {
|
||||
prevRpaths = std::vector<string*>();
|
||||
}
|
||||
// add own rpaths to the end
|
||||
prevRPaths.insert(prevRPaths.end(), rPaths.begin(), rPaths.end());
|
||||
return prevRPaths;
|
||||
prevRpaths.insert(prevRpaths.end(), rpaths.begin(), rpaths.end());
|
||||
return prevRpaths;
|
||||
}
|
||||
|
||||
void MachOArchitecture::readLoadCommands() const {
|
||||
@ -44,21 +51,37 @@ void MachOArchitecture::readLoadCommands() const {
|
||||
|
||||
file.seek(commandOffset);
|
||||
LoadCommand* loadCommand = LoadCommand::getLoadCommand(cmd, header);
|
||||
DylibCommand* dylibCommand = dynamic_cast<DylibCommand*>(loadCommand);
|
||||
|
||||
// for dylibCommand...
|
||||
DylibCommand* dylibCommand = dynamic_cast<DylibCommand*>(loadCommand);
|
||||
if (dylibCommand != 0 && dylibCommand->isId()) {
|
||||
dynamicLibIdCommand = dylibCommand;
|
||||
}
|
||||
|
||||
RPathCommand* rPathCommand = dynamic_cast<RPathCommand*>(loadCommand);
|
||||
if (rPathCommand != 0) {
|
||||
// for rpath command...
|
||||
RpathCommand* rpathCommand = dynamic_cast<RpathCommand*>(loadCommand);
|
||||
if (rpathCommand != 0) {
|
||||
// try to replace placeholder
|
||||
string resolvedRPath = MachO::dynamicLoader->replacePlaceholder(rPathCommand->getPath(), this);
|
||||
if (resolvedRPath.empty()) {
|
||||
resolvedRPath = rPathCommand->getPath();
|
||||
string resolvedRpath = MachO::dynamicLoader->replacePlaceholder(rpathCommand->getPath(), this);
|
||||
if (resolvedRpath.empty()) {
|
||||
resolvedRpath = rpathCommand->getPath();
|
||||
}
|
||||
rPaths.push_back(new string(resolvedRPath));
|
||||
rpaths.push_back(new string(resolvedRpath));
|
||||
}
|
||||
loadCommands.push_back(loadCommand);
|
||||
|
||||
// for uuid command...
|
||||
UuidCommand* uuidCommand = dynamic_cast<UuidCommand*>(loadCommand);
|
||||
if (uuidCommand != 0) {
|
||||
uuid = uuidCommand->getUuid();
|
||||
}
|
||||
|
||||
// for dylinker command
|
||||
DylinkerCommand* dylinkerCommand = dynamic_cast<DylinkerCommand*>(loadCommand);
|
||||
if (dylinkerCommand != 0) {
|
||||
dylinker = dylinkerCommand->getName();
|
||||
}
|
||||
|
||||
loadCommands.push_back(loadCommand);
|
||||
file.seek(commandOffset + loadCommand->getSize());
|
||||
}
|
||||
hasReadLoadCommands = true;
|
||||
@ -74,8 +97,8 @@ MachOArchitecture::~MachOArchitecture() {
|
||||
delete *it;
|
||||
}
|
||||
|
||||
for (std::vector<string*>::iterator it2 = rPaths.begin();
|
||||
it2 != rPaths.end();
|
||||
for (std::vector<string*>::iterator it2 = rpaths.begin();
|
||||
it2 != rpaths.end();
|
||||
++it2)
|
||||
{
|
||||
delete *it2;
|
||||
@ -86,5 +109,9 @@ unsigned int MachOArchitecture::getSize() const {
|
||||
return size;
|
||||
}
|
||||
|
||||
const uint8_t* MachOArchitecture::getUuid() const {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -28,10 +28,11 @@ public:
|
||||
unsigned int getSize() const;
|
||||
void initParentArchitecture(const MachOArchitecture* parent);
|
||||
const MachOFile* getFile() const { return &file; }
|
||||
|
||||
std::vector<string*> getRPaths() const;
|
||||
std::string getDynamicLinker() const { return dylinker; }
|
||||
std::vector<string*> getRpaths(bool recursively = true) const;
|
||||
string getResolvedName(const string& name, const string& workingPath) const;
|
||||
|
||||
const uint8_t* getUuid() const;
|
||||
|
||||
private:
|
||||
MachOHeader* header;
|
||||
MachOFile& file;
|
||||
@ -40,9 +41,12 @@ private:
|
||||
void readLoadCommands() const;
|
||||
const MachOArchitecture* parent; // architecture from which this architecture was loaded
|
||||
|
||||
// all those are mutable, because they are initialized not in the constructor, but in the readLoadCommands method
|
||||
mutable LoadCommands loadCommands;
|
||||
mutable DylibCommand* dynamicLibIdCommand;
|
||||
mutable std::vector<string*> rPaths;
|
||||
mutable std::vector<string*> rpaths;
|
||||
mutable const uint8_t* uuid;
|
||||
mutable std::string dylinker;
|
||||
};
|
||||
|
||||
#endif // MACHOARCHITECTURE_H
|
||||
|
@ -30,7 +30,7 @@ string MachOFile::getName() const {
|
||||
return filename;
|
||||
}
|
||||
string MachOFile::getTitle() const { return file->getTitle(); }
|
||||
long long int MachOFile::getSize() const { return file->getSize(); }
|
||||
unsigned long long MachOFile::getSize() const { return file->getSize(); }
|
||||
time_t MachOFile::getLastModificationTime() const { return file->getLastModificationTime(); }
|
||||
|
||||
uint32_t MachOFile::readUint32() {
|
||||
|
@ -23,7 +23,7 @@ public:
|
||||
string getPath() const;
|
||||
string getName() const;
|
||||
string getTitle() const;
|
||||
long long int getSize() const;
|
||||
unsigned long long getSize() const;
|
||||
void seek(long long int offset) { position = offset; }
|
||||
long long int getPosition() const { return position; }
|
||||
const string& getExecutablePath() const { return executablePath; }
|
||||
|
@ -43,7 +43,7 @@ MachOHeader::CpuType MachOHeader::getHostCpuType() {
|
||||
mach_port_t hostPort = mach_host_self();
|
||||
kern_return_t result = host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&info, &count);
|
||||
mach_port_deallocate(mach_task_self(), hostPort);
|
||||
if ( result != KERN_SUCCESS )
|
||||
if (result != KERN_SUCCESS)
|
||||
throw "host_info() failed";
|
||||
//sHostCPUsubtype = info.cpu_subtype;
|
||||
return getCpuType(info.cpu_type);
|
||||
@ -73,8 +73,7 @@ MachOHeader::CpuType MachOHeader::getCpuType(unsigned int cpu) {
|
||||
MachOHeader::FileType MachOHeader::getFileType() const {
|
||||
unsigned int fileType = getInternalFileType();
|
||||
if (fileType > NumFileTypes || fileType < 1) {
|
||||
throw MachOException("Invalid file type");
|
||||
return NumFileTypes;
|
||||
}
|
||||
return static_cast<FileType>(fileType-1);
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,8 @@ public:
|
||||
FileTypeBundle, /* dynamically bound bundle file */
|
||||
FileTypeDylibStub, /* shared library stub for static linking only, no section contents */
|
||||
FileTypeDsym, /* companion file with only debug sections */
|
||||
NumFileTypes
|
||||
FileTypeKextBundle, /* x86 64 kext bundle */
|
||||
NumFileTypes /* stands also for unknown types */
|
||||
};
|
||||
FileType getFileType() const;
|
||||
virtual CpuType getCpuType() const = 0;
|
||||
|
@ -2,19 +2,19 @@
|
||||
#include "machofile.h"
|
||||
#include "machoheader.h"
|
||||
|
||||
RPathCommand::RPathCommand(MachOHeader* header) :
|
||||
RpathCommand::RpathCommand(MachOHeader* header) :
|
||||
LoadCommand(header)
|
||||
{
|
||||
file.readBytes((char*)&command, sizeof(command));
|
||||
}
|
||||
|
||||
RPathCommand::~RPathCommand() {
|
||||
RpathCommand::~RpathCommand() {
|
||||
}
|
||||
|
||||
unsigned int RPathCommand::getSize() const {
|
||||
unsigned int RpathCommand::getSize() const {
|
||||
return file.getUint32(command.cmdsize);
|
||||
}
|
||||
|
||||
const char* RPathCommand::getPath() const {
|
||||
const char* RpathCommand::getPath() const {
|
||||
return getLcDataString(command.path.offset);
|
||||
}
|
||||
|
@ -4,11 +4,11 @@
|
||||
#include "MachO_global.h"
|
||||
#include "loadcommand.h"
|
||||
|
||||
class EXPORT RPathCommand : public LoadCommand
|
||||
class EXPORT RpathCommand : public LoadCommand
|
||||
{
|
||||
public:
|
||||
RPathCommand(MachOHeader* header);
|
||||
virtual ~RPathCommand();
|
||||
RpathCommand(MachOHeader* header);
|
||||
virtual ~RpathCommand();
|
||||
|
||||
virtual unsigned int getSize() const;
|
||||
virtual unsigned int getStructureSize() const { return sizeof(command); }
|
||||
|
@ -30,7 +30,4 @@ protected:
|
||||
char* stringTable;
|
||||
};
|
||||
|
||||
|
||||
//QDebug &operator<<(QDebug &dbg, const SymbolTableEntry &symbolTable);
|
||||
|
||||
#endif // SYMBOLTABLEENTRY_H
|
||||
|
22
MachO/uuidcommand.cpp
Normal file
22
MachO/uuidcommand.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#include "uuidcommand.h"
|
||||
#include "machofile.h"
|
||||
#include "machoheader.h"
|
||||
#include <sstream>
|
||||
|
||||
UuidCommand::UuidCommand(MachOHeader* header) :
|
||||
LoadCommand(header)
|
||||
{
|
||||
file.readBytes((char*)&command, sizeof(command));
|
||||
}
|
||||
|
||||
UuidCommand::~UuidCommand() {
|
||||
}
|
||||
|
||||
unsigned int UuidCommand::getSize() const {
|
||||
return file.getUint32(command.cmdsize);
|
||||
}
|
||||
|
||||
const uint8_t* UuidCommand::getUuid() const {
|
||||
return command.uuid;
|
||||
}
|
||||
|
20
MachO/uuidcommand.h
Normal file
20
MachO/uuidcommand.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef UUIDCOMMAND_H
|
||||
#define UUIDCOMMAND_H
|
||||
|
||||
#include "macho_global.h"
|
||||
#include "loadcommand.h"
|
||||
class EXPORT UuidCommand : public LoadCommand
|
||||
{
|
||||
public:
|
||||
UuidCommand(MachOHeader* header);
|
||||
virtual ~UuidCommand();
|
||||
virtual unsigned int getSize() const;
|
||||
virtual unsigned int getStructureSize() const { return sizeof(command); }
|
||||
const uint8_t* getUuid() const;
|
||||
|
||||
private:
|
||||
uuid_command command;
|
||||
|
||||
};
|
||||
|
||||
#endif // UUIDCOMMAND_H
|
Loading…
x
Reference in New Issue
Block a user