diff --git a/CMakeLists.txt b/CMakeLists.txt index 0451980..08c776f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/include/fxos/disassembly.h b/include/fxos/disassembly.h index 965dd8d..562fea8 100644 --- a/include/fxos/disassembly.h +++ b/include/fxos/disassembly.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -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 diff --git a/include/fxos/errors.h b/include/fxos/errors.h index 0be8152..8fd74b1 100644 --- a/include/fxos/errors.h +++ b/include/fxos/errors.h @@ -17,7 +17,7 @@ #ifndef LIBFXOS_ERRORS_H #define LIBFXOS_ERRORS_H -#include +#include #include #include diff --git a/include/fxos/log.h b/include/fxos/log.h index cea912b..6866dce 100644 --- a/include/fxos/log.h +++ b/include/fxos/log.h @@ -5,7 +5,7 @@ #ifndef FXOS_LOG_H #define FXOS_LOG_H -#include +#include namespace FxOS::Log { diff --git a/include/fxos/os.h b/include/fxos/os.h index e8641ac..8343824 100644 --- a/include/fxos/os.h +++ b/include/fxos/os.h @@ -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 +#include +#include #include #include diff --git a/include/fxos/util.h b/include/fxos/util.h deleted file mode 100644 index c9f19ba..0000000 --- a/include/fxos/util.h +++ /dev/null @@ -1,115 +0,0 @@ -//--- -// fxos.util: Utility functions -//--- - -#ifndef LIBFXOS_UTIL_H -#define LIBFXOS_UTIL_H - -#include -#include -#include -#include -#include -#include -#include - -/* Format a string with printf() syntax */ -template -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 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 -auto format_convert(T&& t) -{ - if constexpr(std::is_same>, - std::string>::value) - { - return std::forward(t).c_str(); - } - else - { - return std::forward(t); - } -} - -/* String formatting with std::string support in %s */ -template -std::string format(std::string const &format, Args && ... args) -{ - return format_do(format, format_convert(std::forward(args))...); -} - -/* Format a string with colors */ -std::string colors(std::string str); - -/* An object extracted from a target, which has a virtual address */ -template -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 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 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 */ diff --git a/include/fxos/util/Addressable.h b/include/fxos/util/Addressable.h new file mode 100644 index 0000000..7a61f8f --- /dev/null +++ b/include/fxos/util/Addressable.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 + +/* An object extracted from a target, which has a virtual address */ +template +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 */ diff --git a/include/fxos/util/Buffer.h b/include/fxos/util/Buffer.h new file mode 100644 index 0000000..d8c9915 --- /dev/null +++ b/include/fxos/util/Buffer.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 +#include +#include + +/* 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 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 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 */ diff --git a/include/fxos/util/Timer.h b/include/fxos/util/Timer.h new file mode 100644 index 0000000..ae3c278 --- /dev/null +++ b/include/fxos/util/Timer.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 +#include +#include + +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 */ diff --git a/include/fxos/util/format.h b/include/fxos/util/format.h new file mode 100644 index 0000000..960cdec --- /dev/null +++ b/include/fxos/util/format.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 +#include +#include +#include +#include + +/* Format a string with printf() syntax */ +template +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 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 +auto format_convert(T&& t) +{ + if constexpr(std::is_same>, + std::string>::value) + return std::forward(t).c_str(); + else + return std::forward(t); +} + +/* String formatting with std::string support in %s */ +template +std::string format(std::string const &format, Args && ... args) +{ + return format_do(format, format_convert(std::forward(args))...); +} + +#endif /* FXOS_UTIL_FORMAT_H */ diff --git a/include/fxos/vspace.h b/include/fxos/vspace.h index 72891db..ca44885 100644 --- a/include/fxos/vspace.h +++ b/include/fxos/vspace.h @@ -6,9 +6,10 @@ #define LIBFXOS_VSPACE_H #include -#include #include #include +#include +#include #include #include diff --git a/lib/disassembly.cpp b/lib/disassembly.cpp index 938c90a..bb94aa4 100644 --- a/lib/disassembly.cpp +++ b/lib/disassembly.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include diff --git a/lib/domains/relconst.cpp b/lib/domains/relconst.cpp index f8ee80b..dcecbd7 100644 --- a/lib/domains/relconst.cpp +++ b/lib/domains/relconst.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include diff --git a/lib/lang.cpp b/lib/lang.cpp index 5f70500..54c69de 100644 --- a/lib/lang.cpp +++ b/lib/lang.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include diff --git a/lib/load-asm.l b/lib/load-asm.l index 90b7916..53e4a6b 100644 --- a/lib/load-asm.l +++ b/lib/load-asm.l @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include diff --git a/lib/os.cpp b/lib/os.cpp index de8fc14..1a16504 100644 --- a/lib/os.cpp +++ b/lib/os.cpp @@ -2,6 +2,7 @@ #include #include +#include #include 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; diff --git a/lib/passes/print.cpp b/lib/passes/print.cpp index 7d838b9..3a3087d 100644 --- a/lib/passes/print.cpp +++ b/lib/passes/print.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include diff --git a/lib/semantics.cpp b/lib/semantics.cpp index 5a2da14..e75cfb1 100644 --- a/lib/semantics.cpp +++ b/lib/semantics.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include diff --git a/lib/util.cpp b/lib/util.cpp deleted file mode 100644 index 82854ee..0000000 --- a/lib/util.cpp +++ /dev/null @@ -1,143 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace fs = std::filesystem; - -std::string colors(std::string str) -{ - std::map 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(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(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 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); -} diff --git a/lib/util/Buffer.cpp b/lib/util/Buffer.cpp new file mode 100644 index 0000000..d92e61b --- /dev/null +++ b/lib/util/Buffer.cpp @@ -0,0 +1,97 @@ +//---------------------------------------------------------------------------// +// 1100101 |_ mov #0, r4 __ // +// 11 |_ <0xb380 %5c4> / _|_ _____ ___ // +// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< // +// |_ base# + offset |_| /_\_\___/__/ // +//---------------------------------------------------------------------------// + +#include +#include +#include +#include + +#include +#include +#include + +#include +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(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(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 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; +} diff --git a/lib/util/Timer.cpp b/lib/util/Timer.cpp new file mode 100644 index 0000000..1b92f39 --- /dev/null +++ b/lib/util/Timer.cpp @@ -0,0 +1,53 @@ +//---------------------------------------------------------------------------// +// 1100101 |_ mov #0, r4 __ // +// 11 |_ <0xb380 %5c4> / _|_ _____ ___ // +// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< // +// |_ base# + offset |_| /_\_\___/__/ // +//---------------------------------------------------------------------------// + +#include +#include + +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); +} diff --git a/shell/d.cpp b/shell/d.cpp index b1728fd..83da042 100644 --- a/shell/d.cpp +++ b/shell/d.cpp @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include #include @@ -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()); } } diff --git a/shell/i.cpp b/shell/i.cpp index 49802d3..2a8e87e 100644 --- a/shell/i.cpp +++ b/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();