mirror of
https://github.com/lifting-bits/remill
synced 2026-06-21 13:56:07 +00:00
b96aec8fd8
* [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.
192 lines
4.8 KiB
C++
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
|