Files
lifting-bits-remill/remill/OS/FileSystem.cpp
T
Peter Goodman b96aec8fd8 Issue 137 lift bin ls (#155)
* [WIP] Float Instructions for /bin/ls (#146)

* Added bunch of float instructions required by `ls`

Not all variants implemented but should follow same structure

* FADD
* FMUL
* FMOV
* FCVTZU
* FCMPE

Fixed bugs with FMOV_n_to_n

Implemented FMOV_D64 variant

Fixed up FADD, need to doublecheck edgecases

FMUL Added

Weird interaction with checking for denormalized output
fpclassify(prod) gives you FP_SUBNORMAL, but in the native code
the idc bit on SR and FPSR is not set so commented out for now

FCVTZU added - FPSR flags not being caught and set

Type fix In<float64_t>

Fixes for FCVTZU

Added FCMPE Sn

Cleanup testing

* Check unallocated encoding for float insts

* Minor modifications.

* Trying to wrap up some fpu operations inside of a function that can test the inputs and outputs.

* Semantics, but no tests, for some variants of FMUL, FADD, and FDIV.

* Tests for FDIV and FSUB. Additional tests for FADD and FMUL.

* Minor tweak.

* Minor tweak to using fetestexcept only once

* Added UNTESTED implementation of mrs with fpsr.

* FMOV vector instructions, some fixes (#149)

* FMOV vector instructions, some fixes

* More tests for FMOV_VECTOR

* Fix to STRH isel, uses the wrong semantics. Minor modification to add DEF_CONDs to the ForEachIsel iterator.

* Various instructions for aarch64 lifting WIP

* Tests working except where commented

Specifically STRH test throws some lifter error
FCVT has issues with flag determiniation

* Bug fix with oxc fpsr bit in print state

* FCVTS, FMOV_S, FMOV_D

* FNEG, FMADD_S/D

For FMADD still seeing weird issues with flag setting on multiplication
step when using denormals as factor, look into later

* More precise definition of segment selectors. Directory traversal utility function.

* Minor tweaks to existing APIs.

* FMADD has a bug with one type

* Fixed reimport of test

* Semantics and tests for BICS.

* Minor fix to tests.

* Semantics and tests for integer REV instructions.

* Minor fix.

* Minor fixes, forgot an ISEL.

* Tests for MOVK.

* Tests for MOVZ.

* Forgot test file.

* More STR-related tests.

* Minor fix

* Minor fix

* Post-decoder fixes for STR.

* Minor fix?

* Semantics and tests for general simd DUP.

* Minor fix for arrangement specifier. Found a possible bug in capstone/keystone.

* Wrong isel in test

* Semantics and tests for simd ADD and SUB.

* Semantics and tests for LD1_ASISDLSEP_I2_I2

* Whoops, forgot TEST_INPUTS to test.

* Semantics and tests for LD1_ASISDLSEP_I1_I1

* Used wrong isel names in tests.

* Tests and semantics for two more variants of post-index LD1

* Minor fix

* Minor fix to a check for large op sizes. Regenerated AArch64 Extract.cpp, ordering extractors by most constrained first. I observed an issue where LD1_ASISDLSEP_I3_I3 was incorrectly extracted as LD1_ASISDLSEP_R3_R3.

* Minor fix of a decoder routine for loading multiple structures.

* Semantics and tests for RBIT, SMOV, and UMOV. Also semantics, but NO tests for a large number of SIMD instructions.

* Tests for simd smax, smin, umax, umin.

* Tests for sminp, smaxp, uminp, umaxp.

* Tests for ADDP.

* Tests for the simd vector register of cmeq, cmgt, and cmge.

* Minor fix.

* Tests for cmeq, cmgt, and cmge that compare a vector against zero.
2017-11-04 15:52:23 -04:00

192 lines
4.8 KiB
C++

/*
* Copyright (c) 2017 Trail of Bits, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <glog/logging.h>
#include <algorithm>
#include <dirent.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <vector>
#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;
}
}
// Iterator over a directory.
void ForEachFileInDirectory(const std::string &dir_name,
DirectoryVisitor visitor) {
std::vector<std::string> paths;
auto dir = opendir(dir_name.c_str());
CHECK(dir != nullptr)
<< "Could not list the " << dir_name << " directory";
while (auto ent = readdir(dir)) {
if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) {
continue;
}
std::stringstream ss;
ss << dir_name << "/" << ent->d_name;
paths.push_back(ss.str());
}
closedir(dir);
for (const auto &path : paths) {
if (!visitor(path)) {
break;
}
}
}
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