refactor library utils
This commit is contained in:
parent
36fc94bf16
commit
36fe7fcff4
|
@ -8,7 +8,8 @@ add_compile_options(-Wall -Wextra -D_GNU_SOURCE -std=c++17 -O0 -g)
|
|||
# fxos core
|
||||
#---
|
||||
|
||||
flex_target(LoadAsm lib/load-asm.l "${CMAKE_CURRENT_BINARY_DIR}/load-asm.yy.cpp" COMPILE_FLAGS -s)
|
||||
flex_target(LoadAsm lib/load-asm.l
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/load-asm.yy.cpp" COMPILE_FLAGS -s)
|
||||
|
||||
set(fxos_core_SOURCES
|
||||
lib/disassembly.cpp
|
||||
|
@ -23,8 +24,10 @@ set(fxos_core_SOURCES
|
|||
lib/passes/syscall.cpp
|
||||
lib/semantics.cpp
|
||||
lib/symbols.cpp
|
||||
lib/util.cpp
|
||||
lib/vspace.cpp)
|
||||
lib/vspace.cpp
|
||||
|
||||
lib/util/Buffer.cpp
|
||||
lib/util/Timer.cpp)
|
||||
|
||||
add_library(fxos-core ${fxos_core_SOURCES} ${FLEX_LoadAsm_OUTPUTS})
|
||||
target_include_directories(fxos-core PUBLIC include)
|
||||
|
@ -33,8 +36,8 @@ target_include_directories(fxos-core PUBLIC include)
|
|||
# fxos shell
|
||||
#---
|
||||
|
||||
flex_target(Lexer shell/lexer.l "${CMAKE_CURRENT_BINARY_DIR}/lexer.yy.cpp"
|
||||
COMPILE_FLAGS -s)
|
||||
flex_target(Lexer shell/lexer.l
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/lexer.yy.cpp" COMPILE_FLAGS -s)
|
||||
|
||||
set(fxos_shell_SOURCES
|
||||
shell/main.cpp
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <fxos/lang.h>
|
||||
#include <fxos/vspace.h>
|
||||
#include <fxos/semantics.h>
|
||||
#include <fxos/util/Buffer.h>
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
|
@ -85,7 +86,8 @@ struct ConcreteInstruction
|
|||
|
||||
/* Whether this instruction is:
|
||||
-> Terminal, ie. has no successors and is the end of the function.
|
||||
-> An unconditional jump of target [jmptarget].
|
||||
-> An unconditional jump of target [jmptarget]. This is the case for eg.
|
||||
bt, but not bt.s; rather the successor of bt.s is the jump.
|
||||
-> A conditional jump that can hit [jmptarget] and pc+2.
|
||||
If delayslot==false, these attributes are set when analyzing this
|
||||
instruction. If delayslot==true, they are set when the preceding
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#ifndef LIBFXOS_ERRORS_H
|
||||
#define LIBFXOS_ERRORS_H
|
||||
|
||||
#include <fxos/util.h>
|
||||
#include <fxos/util/format.h>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#ifndef FXOS_LOG_H
|
||||
#define FXOS_LOG_H
|
||||
|
||||
#include <fxos/util.h>
|
||||
#include <fxos/util/format.h>
|
||||
|
||||
namespace FxOS::Log {
|
||||
|
||||
|
|
|
@ -1,11 +1,24 @@
|
|||
//---
|
||||
// fxos.os: Operating system models and primitives
|
||||
//
|
||||
// This header describes a structure called [OS] which can be attached to a
|
||||
// virtual space and gives information about the operating system.
|
||||
//
|
||||
// The OS structure can only be created for virtual spaces that have a mapping
|
||||
// over ROM and if the OS is recognised. The OS structure requires the whole OS
|
||||
// code to be mapped and cannot provide partial information. If a mapping is
|
||||
// added to a virtual space, any existing OS structure is discarded.
|
||||
//
|
||||
// To access OS information for a virtual space, you should use
|
||||
// VirtualSpace::os_analysis(), which caches results and doesn't raise
|
||||
// exceptions.
|
||||
//---
|
||||
|
||||
#ifndef LIBFXOS_OS_H
|
||||
#define LIBFXOS_OS_H
|
||||
|
||||
#include <fxos/util.h>
|
||||
#include <fxos/util/Addressable.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
//---
|
||||
// fxos.util: Utility functions
|
||||
//---
|
||||
|
||||
#ifndef LIBFXOS_UTIL_H
|
||||
#define LIBFXOS_UTIL_H
|
||||
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include <vector>
|
||||
|
||||
/* Format a string with printf() syntax */
|
||||
template<typename ... Args>
|
||||
std::string format_do(std::string const &format, Args && ... args)
|
||||
{
|
||||
/* Reserve space for snprintf() to put its NUL */
|
||||
size_t size = snprintf(nullptr, 0, format.c_str(), args ...) + 1;
|
||||
|
||||
std::unique_ptr<char[]> buf(new char[size]);
|
||||
snprintf(buf.get(), size, format.c_str(), args ...);
|
||||
|
||||
/* Remove the NUL from the string */
|
||||
return std::string(buf.get(), buf.get() + size - 1);
|
||||
}
|
||||
|
||||
/* Convert std::string to char * when printing (@Zitrax on Github) */
|
||||
template<typename T>
|
||||
auto format_convert(T&& t)
|
||||
{
|
||||
if constexpr(std::is_same<std::remove_cv_t<std::remove_reference_t<T>>,
|
||||
std::string>::value)
|
||||
{
|
||||
return std::forward<T>(t).c_str();
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::forward<T>(t);
|
||||
}
|
||||
}
|
||||
|
||||
/* String formatting with std::string support in %s */
|
||||
template<typename ... Args>
|
||||
std::string format(std::string const &format, Args && ... args)
|
||||
{
|
||||
return format_do(format, format_convert(std::forward<Args>(args))...);
|
||||
}
|
||||
|
||||
/* Format a string with colors */
|
||||
std::string colors(std::string str);
|
||||
|
||||
/* An object extracted from a target, which has a virtual address */
|
||||
template<typename T>
|
||||
struct Addressable
|
||||
{
|
||||
/* Value */
|
||||
T value;
|
||||
/* Original virtual address */
|
||||
uint32_t address;
|
||||
|
||||
Addressable() = default;
|
||||
Addressable(T value): value(value), address(-1) {}
|
||||
Addressable(uint32_t addr, T value): value(value), address(addr) {}
|
||||
|
||||
/* Implicitly decay to the base type */
|
||||
operator T () const { return value; }
|
||||
|
||||
/* Return the address when using [&] */
|
||||
uint32_t operator & () const { return address; }
|
||||
};
|
||||
|
||||
/* An RAII contiguous memory buffer */
|
||||
class Buffer
|
||||
{
|
||||
public:
|
||||
/* Empty buffer with size 0 and no pointer */
|
||||
Buffer();
|
||||
|
||||
/* Empty buffer initialized with given byte */
|
||||
Buffer(size_t size, int fill=0x00);
|
||||
|
||||
/* Buffer initialized from file, reading the given size from the
|
||||
beginning of the file. If the file is smaller than the specified
|
||||
size, the buffer is padded.
|
||||
|
||||
If this constructor is used, the file path is remembered. */
|
||||
Buffer(std::string filepath, ssize_t size=-1, int fill=0x00);
|
||||
|
||||
/* Buffer initialized from file by looking in one of the specified
|
||||
directories only. */
|
||||
Buffer(std::string filepath, std::vector<std::string> const &folders,
|
||||
ssize_t size=-1, int fill=0x00);
|
||||
|
||||
/* Create a buffer by copying and resizing another buffer */
|
||||
Buffer(Buffer const &other, size_t new_size, int fill=0x00);
|
||||
|
||||
/* Buffer size */
|
||||
size_t size;
|
||||
/* Data */
|
||||
std::shared_ptr<char> data;
|
||||
/* File path, when constructed from file */
|
||||
std::string path;
|
||||
};
|
||||
|
||||
/* Generic timer which returns times in ns using CLOCK_REALTIME */
|
||||
struct timespec timer_start(void);
|
||||
long long timer_end(struct timespec start);
|
||||
|
||||
/* Format ns durations to us, ms or s depending on the value */
|
||||
std::string timer_format(long long duration);
|
||||
|
||||
#endif /* LIBFXOS_UTIL_H */
|
|
@ -0,0 +1,40 @@
|
|||
//---------------------------------------------------------------------------//
|
||||
// 1100101 |_ mov #0, r4 __ //
|
||||
// 11 |_ <0xb380 %5c4> / _|_ _____ ___ //
|
||||
// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< //
|
||||
// |_ base# + offset |_| /_\_\___/__/ //
|
||||
//---------------------------------------------------------------------------//
|
||||
// fxos/util/Addressable: Object wrapper with both a value and an address
|
||||
//
|
||||
// This object is returned by memory access primitives. It contains both the
|
||||
// value and the accessed address, which is useful when tracking particular
|
||||
// blocks of memory within the OS (eg. checksum addresses). See for instance
|
||||
// OS::compute_checksum() for a use case.
|
||||
//
|
||||
// The value is accessed with [.value] or implicitly by conversion to the
|
||||
// underlying type, and the address is accessed with [.address].
|
||||
//---
|
||||
|
||||
#ifndef FXOS_UTIL_ADDRESSABLE_H
|
||||
#define FXOS_UTIL_ADDRESSABLE_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
/* An object extracted from a target, which has a virtual address */
|
||||
template<typename T>
|
||||
struct Addressable
|
||||
{
|
||||
/* Value */
|
||||
T value;
|
||||
/* Original virtual address */
|
||||
uint32_t address;
|
||||
|
||||
Addressable() = default;
|
||||
Addressable(T value): value(value), address(-1) {}
|
||||
Addressable(uint32_t addr, T value): value(value), address(addr) {}
|
||||
|
||||
/* Implicitly decay to the base type */
|
||||
operator T () const { return value; }
|
||||
};
|
||||
|
||||
#endif /* FXOS_UTIL_ADDRESSABLE_H */
|
|
@ -0,0 +1,57 @@
|
|||
//---------------------------------------------------------------------------//
|
||||
// 1100101 |_ mov #0, r4 __ //
|
||||
// 11 |_ <0xb380 %5c4> / _|_ _____ ___ //
|
||||
// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< //
|
||||
// |_ base# + offset |_| /_\_\___/__/ //
|
||||
//---------------------------------------------------------------------------//
|
||||
// fxos/util/Buffer: Generic RAII buffer to load files and data
|
||||
//
|
||||
// The Buffer object can be used to load files in buffers of fixed sizes and
|
||||
// supports some resizing operations. Its main uses are to load files mapped
|
||||
// to virtual space regions with a size that fits the declared region, and to
|
||||
// load data files in an RAII fashion.
|
||||
//---
|
||||
|
||||
#ifndef FXOS_UTIL_BUFFER_H
|
||||
#define FXOS_UTIL_BUFFER_H
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
/* An RAII contiguous memory buffer */
|
||||
struct Buffer
|
||||
{
|
||||
/* Empty buffer with size 0 and no pointer */
|
||||
Buffer();
|
||||
|
||||
/* Empty buffer initialized with given byte */
|
||||
Buffer(size_t size, int fill=0x00);
|
||||
|
||||
/* Buffer initialized from file, reading the given size from the
|
||||
beginning of the file. If the file is smaller than the specified
|
||||
size, the buffer is padded.
|
||||
|
||||
If this constructor is used, the file path is remembered. */
|
||||
Buffer(std::string const &filepath, ssize_t size=-1, int fill=0x00);
|
||||
|
||||
/* Buffer initialized from file by looking in one of the specified
|
||||
directories only. */
|
||||
Buffer(std::string filepath, std::vector<std::string> const &folders,
|
||||
ssize_t size=-1, int fill=0x00);
|
||||
|
||||
/* Create a buffer by copying and resizing another buffer */
|
||||
Buffer(Buffer const &other, size_t new_size, int fill=0x00);
|
||||
|
||||
/* Buffer size */
|
||||
size_t size;
|
||||
/* Data */
|
||||
std::shared_ptr<char> data;
|
||||
/* File path, when constructed from file */
|
||||
std::string path;
|
||||
|
||||
private:
|
||||
void loadFromFile(std::string const &path, ssize_t size, int fill);
|
||||
};
|
||||
|
||||
#endif /* FXOS_UTIL_BUFFER_H */
|
|
@ -0,0 +1,44 @@
|
|||
//---------------------------------------------------------------------------//
|
||||
// 1100101 |_ mov #0, r4 __ //
|
||||
// 11 |_ <0xb380 %5c4> / _|_ _____ ___ //
|
||||
// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< //
|
||||
// |_ base# + offset |_| /_\_\___/__/ //
|
||||
//---------------------------------------------------------------------------//
|
||||
// fxos/util/Timer: A sime CLOCK_REALTIME timer to check performance metrics
|
||||
//
|
||||
// The Timer object can be used to accumulate measures of CLOCK_REALTIME for
|
||||
// basic estimations of performance metrics.
|
||||
//---
|
||||
|
||||
#ifndef FXOS_UTIL_TIMER_H
|
||||
#define FXOS_UTIL_TIMER_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
|
||||
struct Timer
|
||||
{
|
||||
/* New timer with a total count of 0 */
|
||||
Timer();
|
||||
|
||||
/* Current count in nanoseconds */
|
||||
uint64_t time_ns;
|
||||
/* True when running, time when the timer started running */
|
||||
bool running;
|
||||
struct timespec start_time;
|
||||
/* Run depth (for recursive functions) */
|
||||
int depth;
|
||||
|
||||
/* Start and stop counting. Make sure start/stop calls match in pairs */
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
/* String representation of time */
|
||||
std::string format_time() const;
|
||||
|
||||
/* Same function for external measures, if ever needed */
|
||||
static std::string format_time(uint64_t time_ns);
|
||||
};
|
||||
|
||||
#endif /* FXOS_UTIL_TIMER_H */
|
|
@ -0,0 +1,54 @@
|
|||
//---------------------------------------------------------------------------//
|
||||
// 1100101 |_ mov #0, r4 __ //
|
||||
// 11 |_ <0xb380 %5c4> / _|_ _____ ___ //
|
||||
// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< //
|
||||
// |_ base# + offset |_| /_\_\___/__/ //
|
||||
//---------------------------------------------------------------------------//
|
||||
// fxos/util/format: printf()-style format for std::string
|
||||
//
|
||||
// This header provides the format() function which is essentially sprintf()
|
||||
// returning std::string and converting std::string arguments to char *.
|
||||
//---
|
||||
|
||||
#ifndef FXOS_UTIL_FORMAT_H
|
||||
#define FXOS_UTIL_FORMAT_H
|
||||
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <cstdio>
|
||||
|
||||
/* Format a string with printf() syntax */
|
||||
template<typename ... Args>
|
||||
std::string format_do(std::string const &format, Args && ... args)
|
||||
{
|
||||
/* Reserve space for snprintf() to put its NUL */
|
||||
size_t size = snprintf(nullptr, 0, format.c_str(), args ...) + 1;
|
||||
|
||||
std::unique_ptr<char[]> buf(new char[size]);
|
||||
snprintf(buf.get(), size, format.c_str(), args ...);
|
||||
|
||||
/* Remove the NUL from the string */
|
||||
return std::string(buf.get(), buf.get() + size - 1);
|
||||
}
|
||||
|
||||
/* Convert std::string to char * when printing (by @Zitrax on Github) */
|
||||
template<typename T>
|
||||
auto format_convert(T&& t)
|
||||
{
|
||||
if constexpr(std::is_same<std::remove_cv_t<std::remove_reference_t<T>>,
|
||||
std::string>::value)
|
||||
return std::forward<T>(t).c_str();
|
||||
else
|
||||
return std::forward<T>(t);
|
||||
}
|
||||
|
||||
/* String formatting with std::string support in %s */
|
||||
template<typename ... Args>
|
||||
std::string format(std::string const &format, Args && ... args)
|
||||
{
|
||||
return format_do(format, format_convert(std::forward<Args>(args))...);
|
||||
}
|
||||
|
||||
#endif /* FXOS_UTIL_FORMAT_H */
|
|
@ -6,9 +6,10 @@
|
|||
#define LIBFXOS_VSPACE_H
|
||||
|
||||
#include <fxos/memory.h>
|
||||
#include <fxos/util.h>
|
||||
#include <fxos/os.h>
|
||||
#include <fxos/symbols.h>
|
||||
#include <fxos/util/Buffer.h>
|
||||
#include <fxos/util/Addressable.h>
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <fxos/disassembly.h>
|
||||
#include <stdexcept>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <array>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <fxos/domains.h>
|
||||
#include <fxos/util.h>
|
||||
#include <fxos/util/format.h>
|
||||
#include <fxos/lang.h>
|
||||
#include <stdexcept>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <fxos/lang.h>
|
||||
#include <fxos/util.h>
|
||||
#include <fxos/util/format.h>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include <fxos/lang.h>
|
||||
#include <fxos/disassembly.h>
|
||||
#include <fxos/errors.h>
|
||||
#include <fxos/util.h>
|
||||
#include <fxos/util/format.h>
|
||||
|
||||
#include <cstdarg>
|
||||
#include <string>
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <fxos/vspace.h>
|
||||
#include <fxos/memory.h>
|
||||
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
|
||||
namespace FxOS {
|
||||
|
@ -205,7 +206,7 @@ static uint32_t accumulate_range(VirtualSpace const &m_space,
|
|||
uint32_t OS::compute_checksum() const
|
||||
{
|
||||
if(this->type == FX) {
|
||||
return accumulate_range(m_space, 0x80010000, &this->checksum);
|
||||
return accumulate_range(m_space, 0x80010000, this->checksum.address);
|
||||
}
|
||||
else if(this->type == CG) {
|
||||
if(this->version_lt(2, 2, 0)) {
|
||||
|
@ -214,7 +215,8 @@ uint32_t OS::compute_checksum() const
|
|||
}
|
||||
else {
|
||||
return accumulate_range(m_space, 0x80020000, 0x80b20000)
|
||||
+ accumulate_range(m_space, this->footer+8, &this->checksum);
|
||||
+ accumulate_range(m_space, this->footer+8,
|
||||
this->checksum.address);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <fxos/disasm-passes/print.h>
|
||||
#include <fxos/disassembly.h>
|
||||
#include <fxos/util/format.h>
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include <fxos/semantics.h>
|
||||
#include <fxos/util.h>
|
||||
#include <fxos/util/format.h>
|
||||
|
||||
#include <exception>
|
||||
|
||||
|
|
143
lib/util.cpp
143
lib/util.cpp
|
@ -1,143 +0,0 @@
|
|||
#include <fxos/util.h>
|
||||
#include <filesystem>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <map>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
std::string colors(std::string str)
|
||||
{
|
||||
std::map<int, std::string> colors = {
|
||||
// Gray, Red, Green, Yello, Blue, Magenta, Cyan, White
|
||||
{'A',"30;1"}, {'R',"31;1"}, {'G',"32;1"}, {'Y',"33;1"},
|
||||
{'B',"34;1"}, {'M',"35;1"}, {'C',"36;1"}, {'W',"37;1"},
|
||||
// Same but without bold
|
||||
{'a',"30"}, {'r',"31"}, {'g',"32"}, {'y',"33"},
|
||||
{'b',"34"}, {'m',"35"}, {'c',"36"}, {'w',"37"},
|
||||
// Italic, parameter shortcut
|
||||
{'i',"3"}, {'P',"32m\x1b[3"},
|
||||
};
|
||||
bool show = isatty(STDOUT_FILENO);
|
||||
|
||||
for(size_t i = 0; i < str.size() - 2; i++) {
|
||||
if(str[i] == '<' && str[i+1] == '>')
|
||||
str.replace(i, 2, show ? "\x1b[0m" : "");
|
||||
else if(str[i] == '<' && str[i+2] == '>' && colors.count(str[i+1]))
|
||||
str.replace(i, 3, show ? "\x1b[" + colors[str[i+1]] + "m" : "");
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
Buffer::Buffer():
|
||||
size {0}, data {nullptr}, path {"(none)"}
|
||||
{
|
||||
}
|
||||
|
||||
/* Empty buffer initialized with given byte */
|
||||
Buffer::Buffer(size_t bufsize, int fill)
|
||||
{
|
||||
size = bufsize;
|
||||
char *buffer = new char[size];
|
||||
memset(buffer, fill, size);
|
||||
|
||||
data = std::shared_ptr<char>(buffer);
|
||||
path = "(anonymous)";
|
||||
}
|
||||
|
||||
/* Buffer initialized from file */
|
||||
Buffer::Buffer(std::string filepath, ssize_t bufsize, int fill)
|
||||
{
|
||||
char const *path = filepath.c_str();
|
||||
|
||||
int fd = open(path, O_RDONLY);
|
||||
if(!fd) throw std::runtime_error(format("cannot open '%s'", path));
|
||||
|
||||
struct stat statbuf;
|
||||
ssize_t x = fstat(fd, &statbuf);
|
||||
|
||||
if(x < 0)
|
||||
{
|
||||
close(fd);
|
||||
throw std::runtime_error(format("cannot stat '%s'", path));
|
||||
}
|
||||
|
||||
size = (bufsize < 0) ? statbuf.st_size : bufsize;
|
||||
size_t size_to_read = std::min(size, (size_t)statbuf.st_size);
|
||||
|
||||
/* Read buffer and fill whatever is left */
|
||||
data = std::shared_ptr<char>(new char[size]);
|
||||
memset(data.get(), fill, size);
|
||||
x = read(fd, data.get(), size_to_read);
|
||||
|
||||
close(fd);
|
||||
if(x != (ssize_t)size_to_read)
|
||||
{
|
||||
throw std::runtime_error(format(
|
||||
"error while reading '%s'", path));
|
||||
}
|
||||
|
||||
this->path = filepath;
|
||||
}
|
||||
|
||||
Buffer::Buffer(std::string filepath, std::vector<std::string> const &folders,
|
||||
ssize_t size, int fill):
|
||||
Buffer()
|
||||
{
|
||||
for(auto &f: folders)
|
||||
{
|
||||
fs::path p = fs::path(f) / fs::path(filepath);
|
||||
if(fs::exists(p))
|
||||
{
|
||||
/* Hopefully this will use the move assignment */
|
||||
*this = Buffer(p, size, fill);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
char const *path = filepath.c_str();
|
||||
throw std::runtime_error(format("cannot find '%s' in library", path));
|
||||
}
|
||||
|
||||
/* Create a buffer by copying and resizing another buffer */
|
||||
Buffer::Buffer(Buffer const &other, size_t new_size, int fill):
|
||||
Buffer(new_size, fill)
|
||||
{
|
||||
memcpy(data.get(), other.data.get(), std::min(new_size, other.size));
|
||||
this->path = other.path;
|
||||
}
|
||||
|
||||
/* Generic timer which returns times in ns using CLOCK_REALTIME */
|
||||
struct timespec timer_start(void)
|
||||
{
|
||||
struct timespec start;
|
||||
clock_gettime(CLOCK_REALTIME, &start);
|
||||
return start;
|
||||
}
|
||||
long long timer_end(struct timespec start)
|
||||
{
|
||||
struct timespec end;
|
||||
clock_gettime(CLOCK_REALTIME, &end);
|
||||
|
||||
long long ns = 1000000000 * (end.tv_sec - start.tv_sec);
|
||||
ns += end.tv_nsec - start.tv_nsec;
|
||||
return ns;
|
||||
}
|
||||
|
||||
/* Format ns durations to us, ms or s depending on the value */
|
||||
std::string timer_format(long long duration)
|
||||
{
|
||||
if(duration < 2000) return format("%lld ns", duration);
|
||||
duration /= 1000;
|
||||
if(duration < 2000) return format("%lld us", duration);
|
||||
duration /= 1000;
|
||||
if(duration < 2000) return format("%lld ms", duration);
|
||||
duration /= 1000;
|
||||
return format("%lld s", duration);
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
//---------------------------------------------------------------------------//
|
||||
// 1100101 |_ mov #0, r4 __ //
|
||||
// 11 |_ <0xb380 %5c4> / _|_ _____ ___ //
|
||||
// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< //
|
||||
// |_ base# + offset |_| /_\_\___/__/ //
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#include <fxos/util/Buffer.h>
|
||||
#include <fxos/util/format.h>
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
Buffer::Buffer():
|
||||
size {0}, data {nullptr}, path {"(none)"}
|
||||
{
|
||||
}
|
||||
|
||||
/* Empty buffer initialized with given byte */
|
||||
Buffer::Buffer(size_t bufsize, int fill)
|
||||
{
|
||||
this->size = bufsize;
|
||||
// TODO: Buffer(size, fill) -> use std::make_unique<>
|
||||
char *buffer = new char[size];
|
||||
memset(buffer, fill, size);
|
||||
|
||||
this->data = std::shared_ptr<char>(buffer);
|
||||
this->path = "(anonymous)";
|
||||
}
|
||||
|
||||
/* Buffer initialized from file */
|
||||
void Buffer::loadFromFile(std::string const &filepath, ssize_t bufsize,
|
||||
int fill)
|
||||
{
|
||||
char const *path = filepath.c_str();
|
||||
|
||||
int fd = open(path, O_RDONLY);
|
||||
if(!fd) throw std::runtime_error(format("cannot open '%s'", path));
|
||||
|
||||
struct stat statbuf;
|
||||
if(fstat(fd, &statbuf) < 0) {
|
||||
close(fd);
|
||||
throw std::runtime_error(format("cannot stat '%s'", path));
|
||||
}
|
||||
|
||||
this->size = (bufsize < 0) ? statbuf.st_size : bufsize;
|
||||
size_t size_to_read = std::min(size, (size_t)statbuf.st_size);
|
||||
|
||||
/* Read buffer and fill whatever is left */
|
||||
// TODO: use make_unique<>
|
||||
this->data = std::shared_ptr<char>(new char[size]);
|
||||
memset(this->data.get(), fill, size);
|
||||
ssize_t x = read(fd, this->data.get(), size_to_read);
|
||||
|
||||
close(fd);
|
||||
if(x != (ssize_t)size_to_read)
|
||||
throw std::runtime_error(format("error while reading '%s'", path));
|
||||
|
||||
this->path = filepath;
|
||||
}
|
||||
|
||||
/* Buffer initialized from file */
|
||||
Buffer::Buffer(std::string const &filepath, ssize_t bufsize, int fill):
|
||||
Buffer()
|
||||
{
|
||||
this->loadFromFile(filepath, bufsize, fill);
|
||||
}
|
||||
|
||||
Buffer::Buffer(std::string filepath, std::vector<std::string> const &folders,
|
||||
ssize_t size, int fill):
|
||||
Buffer()
|
||||
{
|
||||
for(auto const &f: folders) {
|
||||
fs::path p = fs::path(f) / fs::path(filepath);
|
||||
if(fs::exists(p)) {
|
||||
this->loadFromFile(p, size, fill);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
char const *path = filepath.c_str();
|
||||
throw std::runtime_error(format("cannot find '%s' in library", path));
|
||||
}
|
||||
|
||||
/* Create a buffer by copying and resizing another buffer */
|
||||
Buffer::Buffer(Buffer const &other, size_t new_size, int fill):
|
||||
Buffer(new_size, fill)
|
||||
{
|
||||
memcpy(this->data.get(), other.data.get(), std::min(new_size, other.size));
|
||||
this->path = other.path;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
//---------------------------------------------------------------------------//
|
||||
// 1100101 |_ mov #0, r4 __ //
|
||||
// 11 |_ <0xb380 %5c4> / _|_ _____ ___ //
|
||||
// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< //
|
||||
// |_ base# + offset |_| /_\_\___/__/ //
|
||||
//---------------------------------------------------------------------------//
|
||||
|
||||
#include <fxos/util/Timer.h>
|
||||
#include <fxos/util/format.h>
|
||||
|
||||
Timer::Timer():
|
||||
time_ns {0}, running {false}, start_time {}, depth {0}
|
||||
{
|
||||
}
|
||||
|
||||
void Timer::start(void)
|
||||
{
|
||||
if(this->depth++ == 0) {
|
||||
this->running = true;
|
||||
clock_gettime(CLOCK_REALTIME, &this->start_time);
|
||||
}
|
||||
}
|
||||
|
||||
void Timer::stop(void)
|
||||
{
|
||||
if(--this->depth == 0) {
|
||||
this->running = false;
|
||||
struct timespec end;
|
||||
clock_gettime(CLOCK_REALTIME, &end);
|
||||
|
||||
this->time_ns += 1000000000 * (end.tv_sec - this->start_time.tv_sec)
|
||||
+ (end.tv_nsec - this->start_time.tv_nsec);
|
||||
|
||||
this->start_time.tv_sec = 0;
|
||||
this->start_time.tv_nsec = 0;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Timer::format_time(uint64_t time_ns)
|
||||
{
|
||||
if(time_ns < 2000) return format("%lld ns", time_ns);
|
||||
time_ns /= 1000;
|
||||
if(time_ns < 2000) return format("%lld us", time_ns);
|
||||
time_ns /= 1000;
|
||||
if(time_ns < 2000) return format("%lld ms", time_ns);
|
||||
time_ns /= 1000;
|
||||
return format("%lld s", time_ns);
|
||||
}
|
||||
|
||||
std::string Timer::format_time() const
|
||||
{
|
||||
return Timer::format_time(this->time_ns);
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
#include <fmt/core.h>
|
||||
|
||||
#include <fxos/disassembly.h>
|
||||
#include <fxos/util.h>
|
||||
#include <fxos/util/Timer.h>
|
||||
#include <fxos/log.h>
|
||||
#include <fxos/disasm-passes/cfg.h>
|
||||
#include <fxos/disasm-passes/pcrel.h>
|
||||
|
@ -18,7 +18,8 @@ static void disassemble(Session &session, Disassembly &disasm,
|
|||
{
|
||||
for(auto pass: passes)
|
||||
{
|
||||
auto start = timer_start();
|
||||
Timer timer;
|
||||
timer.start();
|
||||
log(LOG "Running pass %s...\\", pass);
|
||||
|
||||
if(pass == "cfg")
|
||||
|
@ -53,7 +54,8 @@ static void disassemble(Session &session, Disassembly &disasm,
|
|||
|
||||
p.run();
|
||||
}
|
||||
log(LOG "%s", timer_format(timer_end(start)));
|
||||
timer.stop();
|
||||
log(LOG "%s", timer.format_time());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
12
shell/i.cpp
12
shell/i.cpp
|
@ -58,10 +58,10 @@ void _io(Session &session, std::string name)
|
|||
|
||||
printf(info_str, (os->type == OS::FX ? "FX" : "CG"),
|
||||
os->version_major, os->version_minor, os->version_patch,
|
||||
&os->bootcode_timestamp, os->bootcode_timestamp.value.c_str(),
|
||||
&os->bootcode_checksum, os->bootcode_checksum,
|
||||
&os->serial_number, os->serial_number.value.c_str(),
|
||||
&os->version, os->version.value.c_str());
|
||||
os->bootcode_timestamp.address, os->bootcode_timestamp.value.c_str(),
|
||||
os->bootcode_checksum.address, os->bootcode_checksum,
|
||||
os->serial_number.address, os->serial_number.value.c_str(),
|
||||
os->version.address, os->version.value.c_str());
|
||||
|
||||
if(os->footer == (uint32_t)-1)
|
||||
{
|
||||
|
@ -70,8 +70,8 @@ void _io(Session &session, std::string name)
|
|||
else
|
||||
{
|
||||
printf(footer_str, os->footer, os->langdata,
|
||||
&os->timestamp, os->timestamp.value.c_str(),
|
||||
&os->checksum, os->checksum, os->computed_checksum);
|
||||
os->timestamp.address, os->timestamp.value.c_str(),
|
||||
os->checksum.address, os->checksum, os->computed_checksum);
|
||||
}
|
||||
|
||||
uint32_t syscall_table = os->syscall_table_address();
|
||||
|
|
Loading…
Reference in New Issue