Files
lifting-bits-remill/remill/OS/FileSystem.cpp
T
Peter Goodman 7dd87902ea Vmill (#106)
* Initial commit of x86 program snapshotter. Haven't yet figured out how to save a core dump to a specific file.

Now finds and saves core dumps (in a sketchy way).

Kind of but didn't really fix remill-disass with core dumps. It almost seems like a bunch of stuff is missing from within a core dump. It may be the case that it will be simpler to use binary ninja directly on snapshot files.

Working toward the executor.

Have snapshot creation and loading working. Next up: decoding the first few instructions!

Starting to serverize remill and setting up lines of communicating between vmill and remill. Going to move on to finally implementing remill-opt.

Changed a bazillon things.

Fixed the dead register backward data-flow analysis.

Fixed soem bugs, added GEP re-association, working toward inserting stores that will kill values.

Got interprocedual dead store elimination working! :-D

Finally...dead store elimination

remill-opt is done.

Added Lifter interface

Spec'ing out the translation engine.

Got the dynamic decoder working!

Got bitcode caching working

Added caching layer for bytecode compilation.

Decided on how to access reg state and allocas in functions. The bytecode will treat the state struct and the alloca'd data as a contiguous, opaque, byte-addressible area.

Compiler seems to work

Refactor

Great progress...goodnight

Made it up to the first syscall

Fixed call to a hypercall intrinsics

Bug fixes, minor change to the CFG proto.

Refacotorings and changes

* Switching to trying nativeexec, and made memory32 map snapshot into low 32-bits of address space, preserving original addresses of program.

* About to make some interesting changes, so save save save

* Refactor done, now time to produce shared libraries

* Got initial execution of some stuff in PHP working.. it either seems like the code is in an infinite loop, or just horribly slow, not sure. Otherwise, amazing progress.

* Got initial compiling to a runtime dynamic library working

* Separated most DEF_ISEL_SEMs and tests still pass. Goodnight!

* Got incremental optimization and compilation working.

* Got caching of the bitcode file to disk working and periodically collapsing the shared libraries into a single library. OUT.

* Fixed some bugs

* Commit before the storm

* Made the JIT work again, still not that fast though.

* Minor logging fix

* Log an error that we're executing a missing instruction.

* JIT compile the whole module first, then incrementally JIT compile function partitions. Also, link in libm.

* Added new syscall

* Added breakpoint sync hypercall, useful for testing.

* Got a php5.4 unserialize bug to reproduce. Added remill-pinshot, which will use PIN to take a snapshot and print out a register trace. This is useful for debugging divergences. Fixed up the semantics of some instructions, and added semantics and tests for PSRLDQ.

* Simplifications to remill that removes all the various basic block arrays, and uses meta-data instead.

* Made cmake take over the test system

* Working on mega refactor to eventually permit klee support

* Made all semantics code return memory pointer; I think this makes LLVM's optimizer a bit happier. Made the __remill_sub_N things into global constants, referencing the actual functions, that have private linkage. Slowly getting back in the direction of execution. I've got some bitcode translation working (with a hard-coded address for my local php version). The address space stuff seems to work so far.

* Missing files.

* Other minor fixes

* rtti-related fixes for gtest

* minor travis config change

* minor travis config change

* sendfile no longer needed

* Disable building vmill on non-linux platforms

* Disable 32-bit test builds on macOS.

* Trying to get symbol names on mac right.

* Minor fix to save state code for tests, disable testing on macOS builds because of symbol mismatches in gtest.

* Fixup remill-disass to use the simplified proto structure. Something may be wrong with remill-opt, or installing remill opt. Remove caching from travis.
2017-03-23 15:49:33 -04:00

151 lines
3.7 KiB
C++

/* Copyright 2016 Peter Goodman (peter@trailofbits.com), all rights reserved. */
#include <glog/logging.h>
#include <algorithm>
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include "remill/OS/FileSystem.h"
#ifdef __APPLE__
# ifndef _DARWIN_USE_64_BIT_INODE
# define _DARWIN_USE_64_BIT_INODE 1
# endif
# define stat64 stat
# define fstat64 fstat
#endif
namespace remill {
// Try to create a directory. Returns `true` if the directory was created or
// exists.
bool TryCreateDirectory(const std::string &dir_name) {
mkdir(dir_name.c_str(), 0777); // Ignore errors.
if (auto d = opendir(dir_name.c_str())) {
closedir(d);
return true;
} else {
return false;
}
}
std::string CurrentWorkingDirectory(void) {
char result[PATH_MAX] = {};
auto res = getcwd(result, PATH_MAX);
CHECK(res)
<< "Could not determine current working directory: " << strerror(errno);
return std::string(result);
}
bool FileExists(const std::string &path) {
if (-1 == access(path.c_str(), F_OK)) {
return false;
}
struct stat64 file_info = {};
return stat64(path.c_str(), &file_info) == 0 &&
(S_ISREG(file_info.st_mode) ||
S_ISFIFO(file_info.st_mode));
}
uint64_t FileSize(int fd) {
struct stat64 file_info;
CHECK(!fstat64(fd, &file_info))
<< "Cannot stat FD " << fd << ": " << strerror(errno);
return static_cast<uint64_t>(file_info.st_size);
}
uint64_t FileSize(const std::string &path, int fd) {
struct stat64 file_info;
CHECK(!fstat64(fd, &file_info))
<< "Cannot stat " << path << ": " << strerror(errno);
return static_cast<uint64_t>(file_info.st_size);
}
uint64_t FileSize(const std::string &path) {
struct stat64 file_info;
CHECK(!stat64(path.c_str(), &file_info))
<< "Cannot stat " << path << ": " << strerror(errno);
return static_cast<uint64_t>(file_info.st_size);
}
void RemoveFile(const std::string &path) {
unlink(path.c_str());
}
void RenameFile(const std::string &from_path, const std::string &to_path) {
rename(from_path.c_str(), to_path.c_str());
}
namespace {
enum : size_t {
kCopyDataSize = 4096ULL
};
static uint8_t gCopyData[kCopyDataSize];
} // namespace
void CopyFile(const std::string &from_path, const std::string &to_path) {
unlink(to_path.c_str());
auto from_fd = open(from_path.c_str(), O_RDONLY);
CHECK(-1 != from_fd)
<< "Unable to open source file " << from_path
<< " for copying: " << strerror(errno);
auto to_fd = open(to_path.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 0666);
CHECK(-1 != to_fd)
<< "Unable to open destination file " << to_path
<< " for copying: " << strerror(errno);
auto file_size = FileSize(from_path);
int errno_copy = 0;
do {
auto num_read = read(
from_fd, &(gCopyData[0]), std::min<size_t>(kCopyDataSize, file_size));
if (-1 == num_read) {
errno_copy = errno;
break;
}
auto num_written = write(
to_fd, &(gCopyData[0]), static_cast<size_t>(num_read));
if (num_written != num_read) {
errno_copy = errno;
break;
}
file_size -= static_cast<size_t>(num_written);
} while (file_size);
close(from_fd);
close(to_fd);
if (errno_copy) {
unlink(to_path.c_str());
LOG(FATAL)
<< "Unable to copy all data read from " << from_path
<< " to " << to_path << ": " << strerror(errno_copy);
}
}
void HardLinkOrCopyFile(const std::string &from_path,
const std::string &to_path) {
unlink(to_path.c_str());
if (!link(from_path.c_str(), to_path.c_str())) {
return;
}
DLOG(WARNING)
<< "Unable to link " << to_path << " to "
<< from_path << ": " << strerror(errno);
CopyFile(from_path, to_path);
}
} // namespace remill