Add MSYS2 MinGW x64 Support (#108)

* Added MSYS2 MinGW x64 Support
* Updated recomp
* Updated tools
This commit is contained in:
MegaMech
2021-12-20 20:33:42 -07:00
committed by GitHub
parent cdb3ca63aa
commit 48a06f2fa5
15 changed files with 336 additions and 86 deletions
+2 -1
View File
@@ -29,7 +29,8 @@ del compile_args[out_ind]
in_dir = os.path.split(os.path.realpath(in_file))[0]
opt_flags = [x for x in compile_args if x in ['-g', '-O2', '-framepointer']]
preprocessed_file = tempfile.NamedTemporaryFile(prefix='preprocessed', suffix='.c')
preprocessed_file = tempfile.NamedTemporaryFile(prefix='preprocessed', suffix='.c', delete=False)
subprocess.check_call(asm_processor + opt_flags + [in_file], stdout=preprocessed_file)
subprocess.check_call(compiler + compile_args + ['-I', in_dir, '-o', out_file, preprocessed_file.name])
+20 -2
View File
@@ -4,6 +4,11 @@
#include <stdint.h>
#include <stdbool.h>
#if defined(_WIN32) || defined(_WIN64)
#include <io.h>
#include <fcntl.h>
#endif
#define EI_DATA 5
#define EI_NIDENT 16
@@ -179,6 +184,17 @@ static bool elf_get_section_range(uint8_t *file, const char *searched_name, uint
return false;
}
static FILE *mio0_open_out_file(const char *out_file) {
if (strcmp(out_file, "-") == 0) {
#if defined(_WIN32) || defined(_WIN64)
_setmode(_fileno(stdout), _O_BINARY);
#endif
return stdout;
} else {
return fopen(out_file, "wb");
}
}
int main(int argc, char *argv[]) {
if (argc < 3) {
fprintf(stderr, "Usage: %s INFILE OUTFILE\n", argv[0]);
@@ -299,9 +315,11 @@ int main(int argc, char *argv[]) {
}
}
FILE *out = fopen(argv[2], "wb");
FILE *out = mio0_open_out_file(argv[2]);
fwrite(file + data_offset, 1, new_size, out);
fclose(out);
if (out != stdout) {
fclose(out);
}
free(file);
return 0;
+4 -4
View File
@@ -9,7 +9,7 @@ acpp: OPT_CFLAGS := -O2
RECOMP := recomp
ugen_c.c: RECOMP_FLAGS := --conservative
#ugen_c.c: RECOMP_FLAGS := --conservative
all: cc cfe uopt ugen as1 acpp copt ujoin uld umerge usplit err.english.cc
@@ -17,7 +17,7 @@ clean:
$(RM) cc* cfe* uopt* ugen* as1* acpp* copt* ujoin* uld* umerge* usplit* err.english.cc $(RECOMP) libc_impl.o
$(RECOMP): recomp.cpp
$(CXX) $^ -o $@ -std=c++11 -O2 -Wno-switch `pkg-config --cflags --libs capstone`
$(CXX) $^ -o $@ -std=c++11 -O2 -Dugen53 -Wno-switch `pkg-config --cflags --libs capstone`
libc_impl.o: libc_impl.c libc_impl.h
$(CC) $< -c -fno-strict-aliasing -O2 -DIDO53
@@ -26,10 +26,10 @@ err.english.cc: $(IRIX_ROOT)/usr/lib/err.english.cc
cp $^ $@
cc_c.c: $(IRIX_ROOT)/usr/bin/cc $(RECOMP)
./$(RECOMP) $(RECOMP_FLAGS) $< > $@
./$(RECOMP) $< > $@
%_c.c: $(IRIX_ROOT)/usr/lib/% $(RECOMP)
./$(RECOMP) $(RECOMP_FLAGS) $< > $@
./$(RECOMP) $< > $@
%: %_c.c libc_impl.o
$(CC) libc_impl.o $< -o $@ $(OPT_CFLAGS) -fno-strict-aliasing -lm -no-pie
+36 -9
View File
@@ -43,7 +43,7 @@
param[i] = MEM_S8(param##_addr + i); \
}
#if !defined(IDO53) && !defined(IDO71)
#if !defined(IDO53) && !defined(IDO71) && !defined(IDO72)
#define IDO71
#endif
@@ -68,6 +68,15 @@
#define LIBC_SIZE 0x3000
#endif
#ifdef IDO72
// IDO 7.2
#define IOB_ADDR 0x0fb49454
#define ERRNO_ADDR 0x0fb49290
#define CTYPE_ADDR 0x0fb46db0
#define LIBC_ADDR 0x0fb46000
#define LIBC_SIZE 0x4000
#endif
#define STDIN_ADDR IOB_ADDR
#define STDOUT_ADDR (IOB_ADDR + 0x10)
#define STDERR_ADDR (IOB_ADDR + 0x20)
@@ -177,13 +186,13 @@ static char bin_dir[PATH_MAX + 1];
#endif
static int g_file_max = 3;
#if defined(__CYGWIN__) || defined(__APPLE__)
#ifdef __CYGWIN__
static size_t g_Pagesize;
#endif
static uint8_t *memory_map(size_t length)
{
#if defined(__CYGWIN__) || defined(__APPLE__)
#ifdef __CYGWIN__
uint8_t *mem = mmap(0, length, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);
g_Pagesize = sysconf(_SC_PAGESIZE);
assert(((uintptr_t)mem & (g_Pagesize-1)) == 0);
@@ -201,7 +210,7 @@ static void memory_allocate(uint8_t *mem, uint32_t start, uint32_t end)
{
assert(start >= MEM_REGION_START);
assert(end <= MEM_REGION_START + MEM_REGION_SIZE);
#if defined(__CYGWIN__) || defined(__APPLE__)
#ifdef __CYGWIN__
uintptr_t _start = ((uintptr_t)mem + start) & ~(g_Pagesize-1);
uintptr_t _end = ((uintptr_t)mem + end + (g_Pagesize-1)) & ~(g_Pagesize-1);
@@ -1327,7 +1336,7 @@ int wrapper_ftell(uint8_t *mem, uint32_t fp_addr) {
return res;
}
void wrapper_rewind(uint8_t *mem, uint32_t fp_addr) {
int wrapper_rewind(uint8_t *mem, uint32_t fp_addr) {
(void)wrapper_fseek(mem, fp_addr, 0, SEEK_SET);
struct FILE_irix *f = (struct FILE_irix *)&MEM_U32(fp_addr);
f->_flag &= ~IOERR;
@@ -1778,7 +1787,6 @@ int wrapper_setvbuf(uint8_t *mem, uint32_t fp_addr, uint32_t buf_addr, int mode,
f->_ptr_addr = buf_addr;
f->_cnt = 0;
bufendtab[(fp_addr - IOB_ADDR) / sizeof(struct FILE_irix)] = size;
return 0;
}
int wrapper___semgetc(uint8_t *mem, uint32_t fp_addr) {
@@ -2181,8 +2189,15 @@ int wrapper_pathconf(uint8_t *mem, uint32_t path_addr, int name) {
}
uint32_t wrapper_getenv(uint8_t *mem, uint32_t name_addr) {
// Return null for everything, for now
return 0;
STRING(name);
const char *value = getenv(name);
if (value == NULL) {
return 0;
}
size_t value_size = strlen(value) + 1;
uint32_t buf_addr = wrapper_malloc(mem, value_size);
strcpy1(mem, buf_addr, value);
return buf_addr;
}
uint32_t wrapper_gettxt(uint8_t *mem, uint32_t msgid_addr, uint32_t default_str_addr) {
@@ -2355,7 +2370,19 @@ int wrapper_mkstemp(uint8_t *mem, uint32_t name_addr) {
uint32_t wrapper_tmpfile(uint8_t *mem) {
// create and fopen a temporary file that is removed when the program exits
char name[] = "/tmp/copt_temp_XXXXXX";
const char *tmpdir = getenv("TMPDIR");
if (tmpdir == NULL) {
tmpdir = "/tmp";
}
char name[PATH_MAX + 1] = {0};
int n = snprintf(name, sizeof(name), "%s/copt_temp_XXXXXX", tmpdir);
if (n < 0 || n >= sizeof(name)) {
// This isn't the best errno code, but it is one that can be returned by tmpfile
MEM_U32(ERRNO_ADDR) = EACCES;
return 0;
}
int fd = mkstemp(name);
if (fd < 0) {
MEM_U32(ERRNO_ADDR) = errno;
+1 -1
View File
@@ -49,7 +49,7 @@ uint32_t wrapper_freopen(uint8_t *mem, uint32_t path_addr, uint32_t mode_addr, u
int wrapper_fclose(uint8_t *mem, uint32_t fp_addr);
int wrapper_fflush(uint8_t *mem, uint32_t fp_addr);
int wrapper_ftell(uint8_t *mem, uint32_t fp_addr);
void wrapper_rewind(uint8_t *mem, uint32_t fp_addr);
int wrapper_rewind(uint8_t *mem, uint32_t fp_addr);
int wrapper_fseek(uint8_t *mem, uint32_t fp_addr, int offset, int origin);
int wrapper_lseek(uint8_t *mem, int fd, int offset, int whence);
int wrapper_dup(uint8_t *mem, int fd);
+38 -43
View File
@@ -4,13 +4,16 @@
#include <string.h>
#include <inttypes.h>
#include <algorithm>
#include <map>
#include <set>
#include <vector>
#include <string>
#if defined(_WIN32) || defined(_WIN64)
#include <capstone/capstone.h>
#else
#include <capstone.h>
#endif
#include "elf.h"
@@ -20,8 +23,15 @@
#define TRACE 0
#endif
#ifndef ugen53
#define ugen53 0
#endif
#define LABELS_64_BIT 1
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define u32be(x) (uint32_t)(((x & 0xff) << 24) + ((x & 0xff00) << 8) + ((x & 0xff0000) >> 8) + ((uint32_t)(x) >> 24))
#define u16be(x) (uint16_t)(((x & 0xff) << 8) + ((x & 0xff00) >> 8))
#define read_u32_be(buf) (uint32_t)(((buf)[0] << 24) + ((buf)[1] << 16) + ((buf)[2] << 8) + ((buf)[3]))
@@ -71,8 +81,6 @@ struct Function {
bool referenced_by_function_pointer;
};
static bool conservative;
static csh handle;
static const uint8_t *text_section;
@@ -162,7 +170,7 @@ static const struct {
{"freopen", "pppp"},
{"fclose", "ip"},
{"ftell", "ip"},
{"rewind", "vp"},
{"rewind", "ip"},
{"fseek", "ipii"},
{"lseek", "iiii"},
{"fflush", "ip"},
@@ -278,31 +286,24 @@ static const struct {
static void disassemble(void) {
csh handle;
cs_insn *disasm;
size_t disasm_size = 0;
static size_t disasm_size;
assert(cs_open(CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS64 | CS_MODE_BIG_ENDIAN), &handle) == CS_ERR_OK);
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
insns.reserve(1 + text_section_len / sizeof(uint32_t)); // +1 for dummy instruction
while (text_section_len > disasm_size * sizeof(uint32_t)) {
size_t disasm_len = disasm_size * sizeof(uint32_t);
size_t remaining = text_section_len - disasm_len;
size_t current_len = std::min<size_t>(remaining, 1024);
size_t cur_disasm_size = cs_disasm(handle, &text_section[disasm_len], current_len, text_vaddr + disasm_len, 0, &disasm);
disasm_size += cur_disasm_size;
for (size_t i = 0; i < cur_disasm_size; i++) {
insns.push_back(Insn());
Insn& insn = insns.back();
insn.id = disasm[i].id;
insn.mnemonic = disasm[i].mnemonic;
insn.op_str = disasm[i].op_str;
if (disasm[i].detail != nullptr && disasm[i].detail->mips.op_count > 0) {
insn.op_count = disasm[i].detail->mips.op_count;
memcpy(insn.operands, disasm[i].detail->mips.operands, sizeof(insn.operands));
}
insn.is_jump = cs_insn_group(handle, &disasm[i], MIPS_GRP_JUMP) || insn.id == MIPS_INS_JAL || insn.id == MIPS_INS_BAL || insn.id == MIPS_INS_JALR;
insn.linked_insn = -1;
disasm_size = cs_disasm(handle, text_section, text_section_len, text_vaddr, 0, &disasm);
for (size_t i = 0; i < disasm_size; i++) {
insns.push_back(Insn());
Insn& insn = insns.back();
insn.id = disasm[i].id;
insn.mnemonic = disasm[i].mnemonic;
insn.op_str = disasm[i].op_str;
if (disasm[i].detail != nullptr && disasm[i].detail->mips.op_count > 0) {
insn.op_count = disasm[i].detail->mips.op_count;
memcpy(insn.operands, disasm[i].detail->mips.operands, sizeof(insn.operands));
}
cs_free(disasm, cur_disasm_size);
insn.is_jump = cs_insn_group(handle, &disasm[i], MIPS_GRP_JUMP) || insn.id == MIPS_INS_JAL || insn.id == MIPS_INS_BAL || insn.id == MIPS_INS_JALR;
insn.linked_insn = -1;
}
cs_free(disasm, disasm_size);
cs_close(&handle);
{
@@ -339,7 +340,7 @@ static void link_with_lui(int offset, uint32_t reg, int mem_imm)
#define MAX_LOOKBACK 128
// don't attempt to compute addresses for zero offset
// end search after some sane max number of instructions
int end_search = std::max(0, offset - MAX_LOOKBACK);
int end_search = MAX(0, offset - MAX_LOOKBACK);
for (int search = offset - 1; search >= end_search; search--) {
// use an `if` instead of `case` block to allow breaking out of the `for` loop
if (insns[search].id == MIPS_INS_LUI) {
@@ -426,7 +427,7 @@ static void link_with_lui(int offset, uint32_t reg, int mem_imm)
static void link_with_jalr(int offset)
{
// end search after some sane max number of instructions
int end_search = std::max(0, offset - MAX_LOOKBACK);
int end_search = MAX(0, offset - MAX_LOOKBACK);
for (int search = offset - 1; search >= end_search; search--) {
if (insns[search].operands[0].reg == MIPS_REG_T9) {
if (insns[search].id == MIPS_INS_LW || insns[search].id == MIPS_INS_LI) {
@@ -1639,7 +1640,7 @@ static void dump_instr(int i) {
printf("++cnt; printf(\"pc=0x%08x%s%s\\n\"); ", text_vaddr + i * 4, symbol_name ? " " : "", symbol_name ? symbol_name : "");
}
Insn& insn = insns[i];
if (!insn.is_jump && !conservative) {
if (!insn.is_jump && !ugen53) {
switch (insn_to_type(insn)) {
case TYPE_1S:
if (!(insn.f_livein & map_reg(insn.operands[0].reg))) {
@@ -2337,16 +2338,16 @@ static void dump_c(void) {
uint32_t max_addr = 0;
if (data_section_len > 0) {
min_addr = std::min(min_addr, data_vaddr);
max_addr = std::max(max_addr, data_vaddr + data_section_len);
min_addr = MIN(min_addr, data_vaddr);
max_addr = MAX(max_addr, data_vaddr + data_section_len);
}
if (rodata_section_len > 0) {
min_addr = std::min(min_addr, rodata_vaddr);
max_addr = std::max(max_addr, rodata_vaddr + rodata_section_len);
min_addr = MIN(min_addr, rodata_vaddr);
max_addr = MAX(max_addr, rodata_vaddr + rodata_section_len);
}
if (bss_section_len) {
min_addr = std::min(min_addr, bss_vaddr);
max_addr = std::max(max_addr, bss_vaddr + bss_section_len);
min_addr = MIN(min_addr, bss_vaddr);
max_addr = MAX(max_addr, bss_vaddr + bss_section_len);
}
min_addr = min_addr & ~0xfff;
@@ -2357,7 +2358,7 @@ static void dump_c(void) {
stack_bottom -= 16; // for main's stack frame
printf("#include \"header.h\"\n");
if (conservative) {
if (ugen53) {
printf("static uint32_t s0, s1, s2, s3, s4, s5, s6, s7, fp;\n");
}
printf("static const uint32_t rodata[] = {\n");
@@ -2485,7 +2486,7 @@ static void dump_c(void) {
dump_function_signature(f, start_addr);
printf(" {\n");
printf("const uint32_t zero = 0;\n");
if (!conservative) {
if (!ugen53) {
printf("uint32_t at = 0, v1 = 0, t0 = 0, t1 = 0, t2 = 0,\n");
printf("t3 = 0, t4 = 0, t5 = 0, t6 = 0, t7 = 0, s0 = 0, s1 = 0, s2 = 0, s3 = 0, s4 = 0, s5 = 0,\n");
printf("s6 = 0, s7 = 0, t8 = 0, t9 = 0, gp = 0, fp = 0, s8 = 0, ra = 0;\n");
@@ -2910,14 +2911,8 @@ size_t read_file(const char *file_name, uint8_t **data) {
}
int main(int argc, char *argv[]) {
const char *filename = argv[1];
if (strcmp(filename, "--conservative") == 0) {
conservative = true;
filename = argv[2];
}
uint8_t *data;
size_t len = read_file(filename, &data);
size_t len = read_file(argv[1], &data);
parse_elf(data, len);
assert(cs_open(CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS64 | CS_MODE_BIG_ENDIAN), &handle) == CS_ERR_OK);
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+4 -1
View File
@@ -8,7 +8,6 @@
#include "libmio0.h"
#include "utils.h"
// defines
#define MIO0_VERSION "0.1"
@@ -271,6 +270,7 @@ int mio0_encode(const unsigned char *in, unsigned int length, unsigned char *out
// compute final sizes and offsets
// +7 so int division accounts for all bits
bit_length = ((bit_idx + 7) / 8);
// compressed data after control bits and aligned to 4-byte boundary
comp_offset = ALIGN(MIO0_HEADER_LENGTH + bit_length, 4);
uncomp_offset = comp_offset + comp_idx;
@@ -282,7 +282,10 @@ int mio0_encode(const unsigned char *in, unsigned int length, unsigned char *out
write_u32_be(&out[8], comp_offset);
write_u32_be(&out[12], uncomp_offset);
// output data
memset(&out[MIO0_HEADER_LENGTH], 0, MIO0_HEADER_LENGTH + bit_length);
memcpy(&out[MIO0_HEADER_LENGTH], bit_buf, bit_length);
//print_hex(bit_buf, bit_length);
memcpy(&out[comp_offset], comp_buf, comp_idx);
memcpy(&out[uncomp_offset], uncomp_buf, uncomp_idx);
+4
View File
@@ -3,6 +3,10 @@
#include "libtkmk00.h"
#include "utils.h"
#if defined(_WIN32) || defined(_WIN64)
#include <io.h>
#include <fcntl.h>
#endif
#define TKMK00_VERSION "0.1"
+9 -7
View File
@@ -238,6 +238,7 @@ int ia2raw(uint8_t *raw, const ia *img, int width, int height, int depth)
{
int size = (width * height * depth + 7) / 8;
INFO("Converting IA%d %dx%d to raw\n", depth, width, height);
memset(raw, 0, size);
switch (depth) {
case 16:
@@ -290,6 +291,7 @@ int i2raw(uint8_t *raw, const ia *img, int width, int height, int depth)
{
int size = (width * height * depth + 7) / 8;
INFO("Converting I%d %dx%d to raw\n", depth, width, height);
memset(raw, 0, size);
switch (depth) {
case 8:
@@ -849,11 +851,11 @@ int main(int argc, char *argv[])
if (config.mode == MODE_IMPORT) {
if (0 == strcmp("-", config.bin_filename)) {
bin_fp = stdout;
} else {
} else {
if (config.bin_truncate) {
bin_fp = fopen(config.bin_filename, "w");
bin_fp = fopen(config.bin_filename, "wb");
} else {
bin_fp = fopen(config.bin_filename, "r+");
bin_fp = fopen(config.bin_filename, "r+b");
}
}
if (!bin_fp) {
@@ -904,9 +906,9 @@ int main(int argc, char *argv[])
int pal_length;
if (config.pal_truncate) {
pal_fp = fopen(config.pal_filename, "w");
pal_fp = fopen(config.pal_filename, "wb");
} else {
pal_fp = fopen(config.pal_filename, "r+");
pal_fp = fopen(config.pal_filename, "r+b");
}
if (!pal_fp) {
ERROR("Error opening \"%s\"\n", config.pal_filename);
@@ -988,7 +990,7 @@ int main(int argc, char *argv[])
ERROR("Error: must set position width and height for export\n");
return EXIT_FAILURE;
}
bin_fp = fopen(config.bin_filename, "r");
bin_fp = fopen(config.bin_filename, "rb");
if (!bin_fp) {
ERROR("Error opening \"%s\"\n", config.bin_filename);
return -1;
@@ -1025,7 +1027,7 @@ int main(int argc, char *argv[])
INFO("Extracting %s offset 0x%X, pal.offset 0x%0X, pal.format %s\n", format2str(&config.format),
config.bin_offset, config.pal_offset, format2str(&config.pal_format));
pal_fp = fopen(config.pal_filename, "r");
pal_fp = fopen(config.pal_filename, "rb");
if (!pal_fp) {
ERROR("Error opening \"%s\"\n", config.bin_filename);
return EXIT_FAILURE;
+36 -12
View File
@@ -61,24 +61,48 @@ int fprint_write_output(FILE *fp, write_encoding encoding, const uint8_t *raw, i
int flength = 0;
const encoding_format *fmt = &enc_fmt[encoding];
switch (encoding) {
case ENCODING_RAW:
flength = fwrite(raw, 1, length, fp);
break;
case ENCODING_U8:
case ENCODING_U16:
case ENCODING_U32:
case ENCODING_U64:
case ENCODING_RAW:
flength = fwrite(raw, 1, length, fp);
break;
case ENCODING_U8:
case ENCODING_U16:
case ENCODING_U32:
case ENCODING_U64:
for (int w = 0; w < length; w += fmt->bytes_per_val) {
flength += fprintf(fp, "0x");
for (int b = 0; b < fmt->bytes_per_val; b++) {
int off = w + b;
flength += fprintf(fp, "%02x", off < length ? raw[off] : 0x00);
int off = w + b;
flength += fprintf(fp, "%02x", off < length ? raw[off] : 0x00);
}
flength += fprintf(fp, "%s%c", fmt->suffix, (w < length - fmt->bytes_per_val) ? ',' : '\n');
}
break;
}
break;
}
return flength;
}
void fprint_hex(FILE *fp, const unsigned char *buf, int length)
{
int i;
for (i = 0; i < length; i++) {
fprint_byte(fp, buf[i]);
fputc(' ', fp);
}
return flength;
}
void fprint_hex_source(FILE *fp, const unsigned char *buf, int length)
{
int i;
for (i = 0; i < length; i++) {
if (i > 0) fputs(", ", fp);
fputs("0x", fp);
fprint_byte(fp, buf[i]);
}
}
void print_hex(const unsigned char *buf, int length)
{
fprint_hex(stdout, buf, length);
}
void swap_bytes(unsigned char *data, long length)
+15 -3
View File
@@ -40,6 +40,15 @@
(buf)[1] = ((val)) & 0xFF; \
} while(0)
// print nibbles and bytes
#define fprint_nibble(FP, NIB_) fputc((NIB_) < 10 ? ('0' + (NIB_)) : ('A' + (NIB_) - 0xA), FP)
#define fprint_byte(FP, BYTE_) do { \
fprint_nibble(FP, (BYTE_) >> 4); \
fprint_nibble(FP, (BYTE_) & 0x0F); \
} while(0)
#define print_nibble(NIB_) fprint_nibble(stdout, NIB_)
#define print_byte(BYTE_) fprint_byte(stdout, BYTE_)
// Windows compatibility
#if defined(_MSC_VER) || defined(__MINGW32__)
#include <direct.h>
@@ -72,6 +81,7 @@ extern int g_verbosity;
#define ERROR(...) fprintf(stderr, __VA_ARGS__)
#define INFO(...) if (g_verbosity) printf(__VA_ARGS__)
#define INFO_HEX(...) if (g_verbosity) print_hex(__VA_ARGS__)
// functions
@@ -85,12 +95,14 @@ float read_f32_be(unsigned char *buf);
// returns 1 if val is power of 2, 0 otherwise
int is_power2(unsigned int val);
// print buffer as raw binary, hex u8, hex u16, hex u32, hex u64. pads to encoding size
// print buffer as hex bytes
// fp: file pointer
// encoding: encoding type to use (see write_encoding)
// buf: buffer to read bytes from
// length: length of buffer to print
int fprint_write_output(FILE *fp, write_encoding encoding, const uint8_t *buf, int length);
int fprint_write_output(FILE *fp, write_encoding, const uint8_t *buf, int length);
void fprint_hex(FILE *fp, const unsigned char *buf, int length);
void fprint_hex_source(FILE *fp, const unsigned char *buf, int length);
extern void print_hex(const unsigned char *buf, int length);
// perform byteswapping to convert from v64 to z64 ordering
void swap_bytes(unsigned char *data, long length);