#ifndef _H_MACHOPLUSPLUS
#define _H_MACHOPLUSPLUS
#include <mach-o/loader.h>
#include <mach-o/fat.h>
#include <mach-o/arch.h>
#include <security_utilities/globalizer.h>
#include <security_utilities/endian.h>
#include <security_utilities/unix++.h>
#include <security_utilities/cfutilities.h>
namespace Security {
class Architecture : public std::pair<cpu_type_t, cpu_subtype_t> {
typedef std::pair<cpu_type_t, cpu_subtype_t> _Pair;
public:
Architecture() { }
explicit Architecture(cpu_type_t type, cpu_subtype_t sub = CPU_SUBTYPE_MULTIPLE)
: std::pair<cpu_type_t, cpu_subtype_t>(type, sub) { }
Architecture(const fat_arch &archInFile);
cpu_type_t cpuType() const { return this->first; }
cpu_subtype_t cpuSubtype() const { return this->second; }
const char *name() const;
static const cpu_type_t none = 0;
operator bool () const { return cpuType() != none; }
bool operator ! () const { return cpuType() == none; }
public:
friend bool operator == (const Architecture &a1, const Architecture &a2)
{ return _Pair(a1) == _Pair(a2); }
friend bool operator < (const Architecture &a1, const Architecture &a2)
{ return _Pair(a1) < _Pair(a2); }
bool matches(const Architecture &templ) const
{ return first == templ.first && (second == templ.second || templ.second == 0 || templ.second == CPU_SUBTYPE_MULTIPLE); }
public:
static Architecture local();
};
class MachO : public UnixPlusPlus::FileDesc {
public:
MachO(FileDesc fd, size_t offset = 0, size_t length = 0);
~MachO();
size_t offset() const { return mOffset; }
size_t length() const { return mLength; }
template <class T>
T flip(T value) const
{ return mFlip ? Security::flip(value) : value; }
bool isFlipped() const { return mFlip; }
bool is64() const { return m64; }
Architecture architecture() const;
uint32_t type() const;
uint32_t flags() const;
const load_command *loadCommands() const { return mCommands; }
const load_command *nextCommand(const load_command *command) const;
const segment_command *findSegment(const char *segname) const;
const section *findSection(const char *segname, const char *sectname) const;
const linkedit_data_command *findCodeSignature() const;
size_t signingOffset() const; size_t signingLength() const; size_t signingExtent() const;
void seek(size_t offset); CFDataRef dataAt(size_t offset, size_t size);
private:
size_t mOffset; size_t mLength; bool m64; bool mFlip; mach_header mHeader; load_command *mCommands; load_command *mEndCommands; };
class Universal : public UnixPlusPlus::FileDesc {
public:
Universal(FileDesc fd);
~Universal();
MachO *architecture() const; MachO *architecture(const Architecture &arch) const;
size_t archOffset() const; size_t archOffset(const Architecture &arch) const;
typedef std::set<Architecture> Architectures;
void architectures(Architectures &archs);
bool isUniversal() const { return mArchList != NULL; }
Architecture bestNativeArch() const;
public:
static uint32_t typeOf(FileDesc fd);
private:
const fat_arch *findArch(const Architecture &arch) const;
MachO *findImage(const Architecture &arch) const;
private:
fat_arch *mArchList; unsigned mArchCount; Architecture mThinArch; };
}
#endif // !_H_MACHOPLUSPLUS