correct handling for placeholders @loader_path and @executable_path by really relying on the directory of the according file (and not the filename itself)

This commit is contained in:
Konrad Windszus 2016-12-04 16:32:17 +01:00
parent 66202abd66
commit 2004b7a99c
7 changed files with 114 additions and 122 deletions

View File

@ -142,7 +142,7 @@ std::string DynamicLoader::replacePlaceholder(const std::string& name, const Mac
if (name.find(PLACEHOLDERS[ExecutablePath]) == 0) {
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());
resolvedName.replace(0, strlen(PLACEHOLDERS[LoaderPath]), architecture->getFile()->getDirectory());
}
return resolvedName;
}

View File

@ -3,31 +3,31 @@
// use reference counting to reuse files for all used architectures
InternalFile* InternalFile::create(InternalFile* file) {
file->counter++;
return file;
file->counter++;
return file;
}
InternalFile* InternalFile::create(const std::string& filename) {
return new InternalFile(filename);
return new InternalFile(filename);
}
void InternalFile::release() {
counter--;
if (counter < 1) {
delete this;
}
counter--;
if (counter < 1) {
delete this;
}
}
InternalFile::InternalFile(const std::string& filename) :
filename(filename), counter(1)
filename(filename), counter(1)
{
// open file handle
file.open(this->filename, std::ios_base::in | std::ios_base::binary);
if (file.fail()) {
std::ostringstream error;
error << "Couldn't open file '" << filename << "'.";
throw MachOException(error.str());
}
// open file handle
file.open(this->filename, std::ios_base::in | std::ios_base::binary);
if (file.fail()) {
std::ostringstream error;
error << "Couldn't open file '" << filename << "'.";
throw MachOException(error.str());
}
struct stat buffer;
if (stat(filename.c_str(), &buffer) >= 0) {
@ -38,12 +38,7 @@ InternalFile::InternalFile(const std::string& filename) :
// destructor is private since we use reference counting mechanism
InternalFile::~InternalFile() {
file.close();
}
std::string InternalFile::getPath() const {
return filename;
file.close();
}
/* returns whole filename (including path)*/
@ -58,7 +53,7 @@ std::string InternalFile::getName() const {
/* returns filename without path */
std::string InternalFile::getTitle() const {
return filename;
return filename;
}
unsigned long long InternalFile::getSize() const {
@ -66,27 +61,27 @@ unsigned long long InternalFile::getSize() const {
}
bool InternalFile::seek(long long int position) {
file.seekg(position, std::ios_base::beg);
if (file.fail()) {
file.clear();
return false;
}
return true;
file.seekg(position, std::ios_base::beg);
if (file.fail()) {
file.clear();
return false;
}
return true;
}
std::streamsize InternalFile::read(char* buffer, std::streamsize size) {
file.read(buffer, size);
if (file.fail()) {
file.clear();
return file.gcount();
}
// TODO: handle badbit
return size;
file.read(buffer, size);
if (file.fail()) {
file.clear();
return file.gcount();
}
// TODO: handle badbit
return size;
}
long long int InternalFile::getPosition() {
return file.tellg();
}
return file.tellg();
}
time_t InternalFile::getLastModificationTime() const {
return _lastWriteTime;

View File

@ -13,7 +13,7 @@ public:
static InternalFile* create(const std::string& filename);
void release();
std::string getPath() const;
std::string getFolder() const;
std::string getName() const;
std::string getTitle() const;
unsigned long long getSize() const;

View File

@ -204,10 +204,6 @@ std::string MachO::extractStringFromCFStringRef(CFStringRef cfStringRef) {
return string;
}
std::string MachO::getPath() const {
return file->getPath();
}
std::string MachO::getFileName() const {
std::string filename = file->getName();
return filename;

View File

@ -27,9 +27,7 @@ public:
time_t getLastModificationTime() const;
std::string getVersion() const;
std::string getName() const;
//sQIcon getIcon() const;*/
const MachO* getParent() { return parent;}
std::string getPath() const;
static DynamicLoader* dynamicLoader;
static int referenceCounter;
private:

View File

@ -3,100 +3,102 @@
#include "internalfile.h"
MachOFile::MachOFile(const std::string& filename,const MachOFile* parent, bool reversedByteOrder) :
file(InternalFile::create(filename)), position(0), reversedByteOrder(reversedByteOrder), parent(parent)
file(InternalFile::create(filename)), position(0), reversedByteOrder(reversedByteOrder), parent(parent)
{
if (parent) {
executablePath = parent->executablePath;
} else {
executablePath = getPath();
}
if (parent) {
executablePath = parent->executablePath;
} else {
executablePath = getDirectory();
}
}
MachOFile::MachOFile(const MachOFile& file, bool reversedByteOrder) :
file(InternalFile::create(file.file)), position(file.position), reversedByteOrder(reversedByteOrder), parent(file.parent), executablePath(file.executablePath)
file(InternalFile::create(file.file)), position(file.position), reversedByteOrder(reversedByteOrder), parent(file.parent), executablePath(file.executablePath)
{
}
MachOFile::~MachOFile() {
file->release();
}
std::string MachOFile::getPath() const {
return file->getPath();
file->release();
}
std::string MachOFile::getName() const {
std::string filename = file->getName();
return filename;
std::string filename = file->getName();
return filename;
}
std::string MachOFile::getDirectory() const {
size_t found = file->getName().find_last_of("/");
return(file->getName().substr(0, found));
}
std::string MachOFile::getTitle() const { return file->getTitle(); }
unsigned long long MachOFile::getSize() const { return file->getSize(); }
time_t MachOFile::getLastModificationTime() const { return file->getLastModificationTime(); }
uint32_t MachOFile::readUint32() {
unsigned int temp;
readBytes((char*)&temp, sizeof(temp));
return getUint32(temp);
unsigned int temp;
readBytes((char*)&temp, sizeof(temp));
return getUint32(temp);
}
uint32_t MachOFile::readUint32LE() {
unsigned int temp;
readBytes((char*)&temp, sizeof(temp));
return getUint32LE(temp);
unsigned int temp;
readBytes((char*)&temp, sizeof(temp));
return getUint32LE(temp);
}
uint32_t MachOFile::readUint32BE() {
unsigned int temp;
readBytes((char*)&temp, sizeof(temp));
return getUint32BE(temp);
unsigned int temp;
readBytes((char*)&temp, sizeof(temp));
return getUint32BE(temp);
}
uint32_t MachOFile::getUint32BE(uint32_t data) {
return convertByteOrder((char*)&data, true, sizeof(data));
return convertByteOrder((char*)&data, true, sizeof(data));
}
uint32_t MachOFile::getUint32LE(uint32_t data) {
return convertByteOrder((char*)&data, false, sizeof(data));
return convertByteOrder((char*)&data, false, sizeof(data));
}
void MachOFile::readBytes(char* result, size_t size) {
if (file->getPosition() != position) {
file->seek(position);
}
if (file->read(result, size) != size)
throw MachOException("File '" + file->getName() + "' not big enough. Probably no valid Mach-O!");
position += size;
if (file->getPosition() != position) {
file->seek(position);
}
if (file->read(result, size) != size)
throw MachOException("File '" + file->getName() + "' not big enough. Probably no valid Mach-O!");
position += size;
}
// convert from big endian or little endian to native format (Intel=little endian) and return as unsigned int (32bit)
unsigned int MachOFile::convertByteOrder(char* data, bool isBigEndian, unsigned int numberOfBytes) {
assert(numberOfBytes> 0);
assert(numberOfBytes <= 4); // max 4 byte
assert(numberOfBytes> 0);
assert(numberOfBytes <= 4); // max 4 byte
unsigned int result = 0;
unsigned int result = 0;
// big endian extract (most significant byte first) (will work on little and big-endian computers)
unsigned int numberOfShifts = isBigEndian ? numberOfBytes - 1 : 0;
// big endian extract (most significant byte first) (will work on little and big-endian computers)
unsigned int numberOfShifts = isBigEndian ? numberOfBytes - 1 : 0;
for (unsigned int n = 0; n < numberOfBytes; n++) {
result |= static_cast<unsigned char>(data[n]) << (8 * numberOfShifts); // the bit shift will do the correct byte order for you
numberOfShifts += isBigEndian ? -1 : +1;
}
return result;
for (unsigned int n = 0; n < numberOfBytes; n++) {
result |= static_cast<unsigned char>(data[n]) << (8 * numberOfShifts); // the bit shift will do the correct byte order for you
numberOfShifts += isBigEndian ? -1 : +1;
}
return result;
}
uint32_t MachOFile::reverseByteOrder(uint32_t data) {
char* sourceData = (char*)&data;
uint32_t result;
char* destData = (char*)&result;
char* sourceData = (char*)&data;
uint32_t result;
char* destData = (char*)&result;
destData[3] = sourceData[0];
destData[2] = sourceData[1];
destData[1] = sourceData[2];
destData[0] = sourceData[3];
destData[3] = sourceData[0];
destData[2] = sourceData[1];
destData[1] = sourceData[2];
destData[0] = sourceData[3];
return result;
return result;
}

View File

@ -20,7 +20,7 @@ public:
uint32_t getUint32(unsigned int data) const {return (reversedByteOrder?reverseByteOrder(data):data);}
static uint32_t getUint32LE(uint32_t data);
static uint32_t getUint32BE(uint32_t data);
std::string getPath() const;
std::string getDirectory() const;
std::string getName() const;
std::string getTitle() const;
unsigned long long getSize() const;
@ -32,6 +32,7 @@ public:
private:
static unsigned int convertByteOrder(char* data, bool isBigEndian, unsigned int numberOfBytes);
static unsigned int reverseByteOrder(unsigned int data);
static std::string getDirectory(const std::string& path);
InternalFile* file;
long long int position;