Compare commits

...

14 Commits

6
.gitignore vendored

@ -1,6 +1,8 @@
*~
test*
obj/
hexview
hexview-pgo
hexview-*
profile/
perf.*
flamegraph.svg

@ -1,14 +1,18 @@
SRC=$(wildcard src/*.cpp)
INCLUDE =include
_HX_FEAT?= -DFIXED_ROW_SIZE=24
CXXFLAGS?= -pipe -O3 -march=native
CXXFLAGS+= -flto -felide-constructors -fgraphite -fno-strict-aliasing -fno-exceptions -fomit-frame-pointer -fmerge-all-constants -fmodulo-sched -funswitch-loops -fsplit-loops
CXXFLAGS+= -Wall -pedantic --std=gnu++20 $(addprefix -I,$(INCLUDE))
LDFLAGS?= -O3 -flto
LDFLAGS+= -lfmt
CXXFLAGS_COMMON = -Wall -pedantic --std=gnu++20 $(addprefix -I,$(INCLUDE)) -felide-constructors -fno-strict-aliasing -fno-exceptions
LDFLAGS_COMMON = -lfmt
CXXFLAGS_DEFAULT = -pipe -O3 -march=native -fgraphite -flto
CXXFLAGS_RELEASE = -fomit-frame-pointer -fmerge-all-constants -fmodulo-sched -funswitch-loops -fsplit-loops
LDFLAGS_DEFAULT = -O3 -flto
CXXFLAGS_DEBUG = -DDEBUG -O0 -g
PROJ = hexview
PROJECT = hexview
OBJ = $(addprefix obj/,$(SRC:.cpp=.o))
@ -24,8 +28,14 @@ PROF_FLAGS = -fprofile-generate
###
.PHONY: all
all: | dirs $(PROJ)
.PHONY: release
release: | dirs $(PROJECT)-release
.PHONY: debug
debug: | dirs $(PROJECT)-debug
.PHONY: pgo
pgo: | dirs $(PROJECT)-pgo
dirs:
@mkdir -p obj/src
@ -37,38 +47,62 @@ obj/%.o: %.cpp
profile/%.o: %.cpp
$(CXX) -c $< $(_HX_FEAT) $(CXXFLAGS) $(PROF_FLAGS) -o $@ $(LDFLAGS) $(PROF_FLAGS)
$(PROJ): $(OBJ)
$(PROJECT)-release: CXXFLAGS?= $(CXXFLAGS_DEFAULT)
$(PROJECT)-release: LDFLAGS?= $(LDFLAGS_DEFAULT)
$(PROJECT)-release: CXXFLAGS+= $(CXXFLAGS_COMMON)
$(PROJECT)-release: CXXFLAGS+= $(CXXFLAGS_RELEASE)
$(PROJECT)-release: LDFLAGS := $(LDFLAGS_COMMON) $(LDFLAGS)
$(PROJECT)-release: $(OBJ)
$(CXX) $^ $(CXXFLAGS) -o $@ $(LDFLAGS)
strip $@
$(PROJECT)-debug: CXXFLAGS += $(CXXFLAGS_COMMON)
$(PROJECT)-debug: CXXFLAGS += $(CXXFLAGS_DEBUG)
$(PROJECT)-debug: LDFLAGS += $(LDFLAGS_COMMON)
$(PROJECT)-debug: $(OBJ)
$(CXX) $^ $(CXXFLAGS) -o $@ $(LDFLAGS)
pgo-generate: $(PGO_OBJ)
$(CXX) $^ $(CXXFLAGS) $(PROF_FLAGS) -o $@ $(LDFLAGS) $(PROF_FLAGS)
pgo-profile: pgo-generate
pgo-reset:
find ./profile -name \*.gcda -exec rm {} +
pgo-profile: | pgo-reset pgo-generate
for i in {1..$(PGO_ITERATIONS)}; do \
dd if=/dev/urandom of=./pgo-test bs=1024 count=$(PGO_DATASET_SIZE) >> /dev/null 2>&1; \
dd if=/dev/urandom of=/tmp/$(PROJECT)-pgo-test bs=1024 count=$(PGO_DATASET_SIZE) >> /dev/null 2>&1; \
printf "\rIteration $$i / $(PGO_ITERATIONS)"; \
./pgo-generate ./pgo-test > ./pgo-output; \
./pgo-generate /tmp/$(PROJECT)-pgo-test > /tmp/$(PROJECT)-pgo-output; \
done
@echo ""
rm ./pgo-test
rm ./pgo-output
rm /tmp/$(PROJECT)-pgo-test
rm /tmp/$(PROJECT)-pgo-output
rm pgo-generate
pgo-use: PROF_FLAGS = -fprofile-use -lgcov
pgo-use: CXXFLAGS?= $(CXXFLAGS_DEFAULT)
pgo-use: LDFLAGS?= $(LDFLAGS_DEFAULT)
pgo-use: CXXFLAGS+= $(CXXFLAGS_COMMON)
pgo-use: CXXFLAGS+= $(CXXFLAGS_RELEASE)
pgo-use: LDFLAGS := $(LDFLAGS_COMMON) -lgcov $(LDFLAGS)
pgo-use: PROF_FLAGS = -fprofile-use
pgo-use: $(PGO_OBJ)
$(CXX) $^ $(CXXFLAGS) $(PROF_FLAGS) -o $@ $(LDFLAGS) $(PROF_FLAGS)
$(PROJ)-pgo: | dirs pgo-profile
$(PROJECT)-pgo: CXXFLAGS?= $(CXXFLAGS_DEFAULT)
$(PROJECT)-pgo: LDFLAGS?= $(LDFLAGS_DEFAULT)
$(PROJECT)-pgo: CXXFLAGS+= $(CXXFLAGS_COMMON)
$(PROJECT)-pgo: CXXFLAGS+= $(CXXFLAGS_RELEASE)
$(PROJECT)-pgo: LDFLAGS := $(LDFLAGS_COMMON) $(LDFLAGS)
$(PROJECT)-pgo: | dirs pgo-profile
find ./profile -name \*.o -exec rm {} +
$(MAKE) pgo-use
mv pgo-use $@
strip $@
clean:
rm -f $(PROJ)
rm -f $(PROJ)-pgo
rm -f $(PROJECT)-{release,debug,pgo}
rm -rf obj
rm -rf profile
rm -f pgo-{test,output,generate}

@ -5,4 +5,42 @@
namespace hv {
/// Print a single screen
void print_screen(const span<unsigned char> bytes, unsigned long offset);
inline void lookup_hex_string(std::uint64_t x, char* s)
{
static const char digits[513] =
"000102030405060708090a0b0c0d0e0f"
"101112131415161718191a1b1c1d1e1f"
"202122232425262728292a2b2c2d2e2f"
"303132333435363738393a3b3c3d3e3f"
"404142434445464748494a4b4c4d4e4f"
"505152535455565758595a5b5c5d5e5f"
"606162636465666768696a6b6c6d6e6f"
"707172737475767778797a7b7c7d7e7f"
"808182838485868788898a8b8c8d8e8f"
"909192939495969798999a9b9c9d9e9f"
"a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
"b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
"c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
"d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
"e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
int i = 7;
const char *lut = (const char *)digits;
while (i >= 0)
{
int pos = (x & 0xFF) * 2;
char ch = lut[pos];
#ifdef DEBUG
if ( (i*2+1) >=16) std::terminate();
#endif
s[i * 2] = ch;
ch = lut[pos + 1];
s[i * 2 + 1] = ch;
x >>= 8;
i -= 1;
}
}
}

@ -1,5 +1,6 @@
#pragma once
#include <exception>
#include <cstdint>
#include <cmath>
@ -20,14 +21,14 @@ namespace hv
inline T& operator[](std::size_t index)
{
#ifdef DEBUG
if (index>=len) throw "tried to index out of bounds of array";
if (index>=len) std::terminate(); // "tried to index out of bounds of array";
#endif
return ptr[index];
}
inline const T& operator[](std::size_t index) const
{
#ifdef DEBUG
if (index>=len) throw "tried to index out of bounds of array";
if (index>=len) std::terminate(); // "tried to index out of bounds of array";
#endif
return ptr[index];
}
@ -35,12 +36,12 @@ namespace hv
inline span<T> slice(std::size_t off, std::size_t len)
{
len = std::min(this->len, len);
if(len+off>=len || len < off) throw "tried to index out of bounds of array";
if(len+off>=len || len < off) std::terminate(); // "tried to index out of bounds of array";
return span<T>(ptr+off, len-off);
}
inline span<T> slice(std::size_t off)
{
if(len+off>=len || len < off) throw "tried to index out of bounds of array";
if(len+off>=len || len < off) std::terminate(); // "tried to index out of bounds of array";
return span<T>(ptr+off, len-off);
}

@ -1,5 +1,6 @@
#include <fmt/format.h>
#include <span.hpp>
#include <hex.hpp>
const static constexpr char ascii_map[256] = {
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',
@ -20,7 +21,7 @@ const static constexpr char ascii_map[256] = {
'.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.', '.',
};
constexpr const char* hex_map[256] = {
constexpr const static char* hex_map[256] = {
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
@ -59,52 +60,80 @@ inline void hex02(std::uint8_t byte, char buffer[2])
buffer[1] =hex_map[byte][1];
}
template<int N>
template<std::size_t N>
inline __attribute__((always_inline)) void print_exact(const char* ar)
{
fwrite(ar, 1, N, stdout);
}
template<std::size_t N>
inline __attribute__((always_inline)) void print_exact(const char (&ar)[N])
{
fwrite(ar, N, 1, stdout);
}
inline static void u64_to_hex(std::uint64_t num, char* s)
{
hv::lookup_hex_string(num, s);
}
namespace hv {
void print_screen(const span<unsigned char> memory, unsigned long offset)
{
#ifndef FIXED_ROW_SIZE
#define S (const char*)
#define S (2+ROW_SZ)
#define P_EX(n, buf) fwrite(buf, 1, n, stdout)
int ROW_SZ = 24;
#else
#define S
#define P_EX(n, buf) print_exact(buf)
#endif
fmt::print("0x{:016x} ", offset);
char hxbuf[3];
char posbuf[3 + 16 + 2];
posbuf[0] = '\n';
posbuf[1] = '0';
posbuf[2] = 'x';
#ifdef DEBUG
std::memset(posbuf+3, '0', 16);
#endif
posbuf[3 + 16] = ' ';
posbuf[3 + 16 + 1] = ' ';
u64_to_hex(offset, posbuf+3);
prints(posbuf+1);
char hxbuf[3] = { ' ', ' ', ' ' };
std::size_t i=0;
char r_ascii[2 + ROW_SZ];
r_ascii[0] = ' ';
r_ascii[1] = ' ';
char* ascii = r_ascii + 2;
const auto memsize = memory.size();
hxbuf[2] = ' ';
for(;i<memory.size();i++) {
for(;i<memsize;i++) {
if (i && i % ROW_SZ == 0) { //TODO: Change to i +=16 so we don't have to branch here on every byte. Make sure to not overrun buffer tho
print_exact(r_ascii);
fmt::print("\n0x{:016x} ", i+offset);
P_EX(S, r_ascii);
u64_to_hex(i+offset, posbuf+3);
print_exact(posbuf);
}
unsigned char idx = memory[i];
hex02(idx, hxbuf);
print_exact(hxbuf);
ascii[i%ROW_SZ] = ascii_map[idx];
}
if (memory.size() % ROW_SZ != 0)
if (memsize % ROW_SZ != 0)
{
auto rest = memory.size() % ROW_SZ;
auto rest = memsize % ROW_SZ;
ascii[rest] = 0;
constexpr const char output[3] = { ' ', ' ', ' ' };
for(std::size_t j=0;j< ROW_SZ - rest;j++)
print_exact(output);
prints(r_ascii);
prints((const char*) r_ascii);
}
else {
print_exact(r_ascii);
P_EX(S, r_ascii);
}
}
}

Loading…
Cancel
Save