Add building on macOS (#224)

* build OK macOS

* add macOS building instructions

* change return type of func_8000546C

* prevent gitattributes from removing CRLF from ido binaries
This commit is contained in:
tehzz 2022-06-15 20:26:03 -04:00 committed by GitHub
parent 491f37be4d
commit 0f0ff04779
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 294 additions and 136 deletions

23
.gitattributes vendored
View File

@ -1 +1,22 @@
* text eol=lf
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto
# force C files to unix endings regardless of host platform
# for compatibility with IDO cc
*.c text eol=lf diff=c
*.h text eol=lf diff=c
# List text files in case git doesn't characterize correctly
*.s text
*.in text
*.js text
*.md text
*.py text diff=python
*.sh text
*.ld text
*.inc text
*.txt text
*.json text
*.yaml text
*.toml text
*.rs text diff=rust

View File

@ -20,6 +20,10 @@ ifeq ($(VERSION),us)
TARGET := mk64.us
endif
### Utility Functions ###
# Returns the path to the command $(1) if exists. Otherwise returns an empty string.
find-command = $(shell which $(1) 2>/dev/null)
################ Target Executable and Sources ###############
# BUILD_DIR is location where all build artifacts are placed
@ -110,29 +114,36 @@ TOOLS_DIR := tools
ifeq ($(USE_QEMU_IRIX),1)
# Verify that qemu-irix exists
QEMU_IRIX := $(shell which qemu-irix)
ifeq (, $(QEMU_IRIX))
QEMU_IRIX := $(call find-command,qemu-irix)
ifeq (,$(QEMU_IRIX))
$(error Using the IDO compiler requires qemu-irix. Please install qemu-irix package or set the QEMU_IRIX environment variable to the full qemu-irix binary path)
endif
endif
ifeq ($(USE_QEMU_IRIX),1)
IRIX_ROOT := $(TOOLS_DIR)/ido5.3_compiler
CC := $(QEMU_IRIX) -silent -L $(IRIX_ROOT) $(IRIX_ROOT)/usr/bin/cc
CC := $(QEMU_IRIX) -silent -L $(IRIX_ROOT) $(IRIX_ROOT)/usr/bin/cc
else
IDO_ROOT := tools/ido5.3_recomp
CC := $(IDO_ROOT)/cc
CC := $(IDO_ROOT)/cc
endif
AS := $(CROSS)as
CPP := cpp -P -Wno-trigraphs
LD := $(CROSS)ld
AR := $(CROSS)ar
OBJDUMP := $(CROSS)objdump
OBJCOPY := $(CROSS)objcopy
PYTHON := python3
# Prefer clang as C preprocessor if installed on the system
ifneq (,$(call find-command,clang))
CPP := clang
CPPFLAGS := -E -P -x c -Wno-trigraphs
else
CPP := cpp
CPPFLAGS := -P -Wno-trigraphs
endif
MIPSISET := -mips2 -32
OPT_FLAGS := -O2
@ -466,7 +477,7 @@ $(GLOBAL_ASM_O_FILES): CC := $(PYTHON) tools/asm_processor/build.py $(CC) -- $(A
$(GLOBAL_ASM_AUDIO_O_FILES): CC := $(PYTHON) tools/asm_processor/build.py $(CC) -- $(AS) $(ASFLAGS) --
$(BUILD_DIR)/$(LD_SCRIPT): $(LD_SCRIPT) #repeat for other files
$(CPP) $(VERSION_CFLAGS) -DBUILD_DIR=$(BUILD_DIR) -MMD -MP -MT $@ -MF $@.d -o $@ $<
$(CPP) $(CPPFLAGS) $(VERSION_CFLAGS) -DBUILD_DIR=$(BUILD_DIR) -MMD -MP -MT $@ -MF $@.d -o $@ $<
#################### Libultra #####################

View File

@ -49,14 +49,25 @@ Compiling on Windows requires `MSYS2 MinGW x64`. The setup process is a tad inte
[Instructions here](docs/BUILD_WINDOWS.md)
#### macOS
Install [Homebrew](https://brew.sh), then install the following dependencies:
```
brew update
brew install python3 capstone coreutils make pkg-config tehzz/n64-dev/mips64-elf-binutils
```
When building, use `gmake` to ensure that homebrew `make` is used instead of the old, macOS system `make`.
## Building
Place a US version of Mario Kart 64 called `baserom.us.z64` into the project folder for asset extraction.
Run the following commands after pulling:
* make -C tools
* make
```bash
make -C tools
make
```
## Progress

View File

@ -237,7 +237,7 @@ void func_80005310(void) {
}
}
s32 func_8000546C(void) {
void func_8000546C(void) {
u32 temp_a0;
u32 temp_a1;
UNUSED u16 unk;

View File

@ -1,62 +1,62 @@
#!/usr/bin/env python3
import os, sys
# ./gfx.py input_file_no_extension startHex
if (sys.argv[1] == "-h" or sys.argv[1] == ""):
print("How to use: ")
print("Create copy of .bin named: filename_copy.bin")
print("./gfx.py input_file_no_extension startHex iterations symbol_name")
print("iterations are in 0x10")
sys.exit(0)
# make sure to copy the .bin file and name it: filename_copy.bin
# copy of bin to prevent read/write conflicts between gfxdis and python
# Did it this way without testing. Just assumed there would be conflicts
# startHex no 0x
debug = False
execStr = "./gfxdis.f3dex -f "+sys.argv[1]+".bin -a "
start = int(sys.argv[2], 16)
r = open(sys.argv[1]+"_copy.bin", "rb")
r.seek(start)
bRunIt = True
it = int(sys.argv[3]) * 2 # iterations. *2 for 16 bytes per line
i = 0
calls = 0
offset = int(0)
for i in range(it):
if bRunIt:
if (len(sys.argv) > 4): # if symbol_name arg exists
print("Gfx "+sys.argv[4]+str(hex(offset+start).split('x')[-1].upper())+"[] = ")
os.system(execStr+hex(offset+start))
if debug:
print((execStr+hex(offset+start)))
bRunIt = False
calls += 1
r.seek(start+offset)
data = r.read(4).hex().upper()
if data == "B8000000":
bRunIt = True
if debug:
print("Running next: "+hex(offset+start))
if str(data) == "00000000":
print("Found no DL command");
break;
offset += 8
print("Program exited at: "+hex(offset+start))
print("Ran gfxdis "+str(calls)+ " times.")
#!/usr/bin/env python3
import os, sys
# ./gfx.py input_file_no_extension startHex
if (sys.argv[1] == "-h" or sys.argv[1] == ""):
print("How to use: ")
print("Create copy of .bin named: filename_copy.bin")
print("./gfx.py input_file_no_extension startHex iterations symbol_name")
print("iterations are in 0x10")
sys.exit(0)
# make sure to copy the .bin file and name it: filename_copy.bin
# copy of bin to prevent read/write conflicts between gfxdis and python
# Did it this way without testing. Just assumed there would be conflicts
# startHex no 0x
debug = False
execStr = "./gfxdis.f3dex -f "+sys.argv[1]+".bin -a "
start = int(sys.argv[2], 16)
r = open(sys.argv[1]+"_copy.bin", "rb")
r.seek(start)
bRunIt = True
it = int(sys.argv[3]) * 2 # iterations. *2 for 16 bytes per line
i = 0
calls = 0
offset = int(0)
for i in range(it):
if bRunIt:
if (len(sys.argv) > 4): # if symbol_name arg exists
print("Gfx "+sys.argv[4]+str(hex(offset+start).split('x')[-1].upper())+"[] = ")
os.system(execStr+hex(offset+start))
if debug:
print((execStr+hex(offset+start)))
bRunIt = False
calls += 1
r.seek(start+offset)
data = r.read(4).hex().upper()
if data == "B8000000":
bRunIt = True
if debug:
print("Running next: "+hex(offset+start))
if str(data) == "00000000":
print("Found no DL command");
break;
offset += 8
print("Program exited at: "+hex(offset+start))
print("Ran gfxdis "+str(calls)+ " times.")
r.close()

View File

@ -9,7 +9,34 @@ acpp: OPT_CFLAGS := -O2
RECOMP := recomp
#ugen_c.c: RECOMP_FLAGS := --conservative
# determine host OS for flags
UNAME_S := $(shell uname -s)
UNAME_P := $(shell uname -p)
ifeq ($(UNAME_S),Darwin)
HOST_OS := macOS
else ifeq ($(UNAME_S),Linux)
HOST_OS := linux
else ifeq ($(OS),Windows_NT)
HOST_OS := cygwin
else
$(error Unsupported host OS for Makefile)
endif
CFLAGS := -fno-strict-aliasing -Wno-tautological-compare
CLIBS := -lm
ifeq ($(HOST_OS),macOS)
CFLAGS += -Wno-deprecated-declarations
ifeq (,$(findstring arm,$(shell uname -p)))
# only add flags on x86_64 macOS
CFLAGS += -fno-pie
endif
else
CFLAGS += -no-pie
endif
ugen_c.c: RECOMP_FLAGS := --conservative
all: cc cfe uopt ugen as1 acpp copt ujoin uld umerge usplit err.english.cc
@ -17,10 +44,10 @@ 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 -Dugen53 -Wno-switch `pkg-config --cflags --libs capstone`
$(CXX) $^ -o $@ -std=c++11 -O2 -Wno-switch `pkg-config --cflags --libs capstone`
libc_impl.o: libc_impl.c libc_impl.h
$(CC) $< -c -fno-strict-aliasing -O2 -DIDO53
$(CC) $< -c -O2 -DIDO53 $(CFLAGS)
err.english.cc: $(IRIX_ROOT)/usr/lib/err.english.cc
cp $^ $@
@ -29,9 +56,10 @@ cc_c.c: $(IRIX_ROOT)/usr/bin/cc $(RECOMP)
./$(RECOMP) $< > $@
%_c.c: $(IRIX_ROOT)/usr/lib/% $(RECOMP)
./$(RECOMP) $< > $@
./$(RECOMP) $(RECOMP_FLAGS) $< > $@
%: %_c.c libc_impl.o
$(CC) libc_impl.o $< -o $@ $(OPT_CFLAGS) -fno-strict-aliasing -lm -no-pie
$(CC) libc_impl.o $< -o $@ $(OPT_CFLAGS) $(CFLAGS) $(CLIBS)
.PHONY: all clean
.DEFAULT_TARGET := all

0
tools/ido5.3_recomp/elf.h Normal file → Executable file
View File

0
tools/ido5.3_recomp/helpers.h Normal file → Executable file
View File

93
tools/ido5.3_recomp/libc_impl.c Normal file → Executable file
View File

@ -16,8 +16,10 @@
#ifdef __CYGWIN__
#include <windows.h>
#endif
#ifdef __APPLE__
#include <mach-o/dyld.h>
#include <mach-o/dyld.h>
#include <mach/vm_page_size.h>
#endif
#include <sys/mman.h>
@ -186,21 +188,39 @@ static char bin_dir[PATH_MAX + 1];
#endif
static int g_file_max = 3;
#ifdef __CYGWIN__
/* Compilation Target/Emulation Host Page Size Determination */
#if defined(__CYGWIN__) || (defined(__linux__) && defined(__aarch64__))
#define RUNTIME_PAGESIZE
/* ARM64 linux can have page sizes of 4kb, 16kb, or 64kb */
/* Set in main before running the translated code */
static size_t g_Pagesize;
#endif
#define TRUNC_PAGE(x) ((x) & ~(g_Pagesize - 1))
#define ROUND_PAGE(x) (TRUNC_PAGE((x) + (g_Pagesize - 1)))
#elif defined(__APPLE__)
/* https://developer.apple.com/documentation/apple-silicon/addressing-architectural-differences-in-your-macos-code */
#define TRUNC_PAGE(x) (trunc_page((x)))
#define ROUND_PAGE(x) (round_page((x)))
#else
/* A fixed 4KB page size for x64 linux (is there anything else?) */
#define TRUNC_PAGE(x) ((x) & ~(0x1000 - 1))
#define ROUND_PAGE(x) (TRUNC_PAGE((x) + (0x1000 - 1)))
#endif /* PageSize Macros */
static uint8_t *memory_map(size_t length)
{
#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);
#else
uint8_t *mem = mmap(0, length, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
#endif
assert(TRUNC_PAGE((uintptr_t)mem) == (uintptr_t)mem);
if (mem == MAP_FAILED) {
perror("mmap");
perror("mmap (memory_map)");
exit(1);
}
return mem;
@ -210,20 +230,26 @@ 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);
// `start` will be passed to mmap,
// so it has to be host aligned in order to keep the guest's pages valid
assert(start == TRUNC_PAGE(start));
#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);
uintptr_t _start = TRUNC_PAGE((uintptr_t)mem + start);
uintptr_t _end = ROUND_PAGE((uintptr_t)mem + end);
if(mprotect((void*)_start, _end - _start, PROT_READ | PROT_WRITE) < 0) {
perror("mprotect");
perror("mprotect (memory_allocate)");
exit(1);
}
#else
if (mmap(mem + start, end - start, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == MAP_FAILED) {
perror("mmap");
void *addr = (void *)TRUNC_PAGE((uintptr_t)mem + start);
size_t len = end - start;
if (mmap(addr, len, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == MAP_FAILED) {
perror("mmap (memory_allocate)");
exit(1);
}
#endif
#endif /* __CYGWIN__ */
}
static void memory_unmap(uint8_t *mem, size_t length)
@ -273,6 +299,9 @@ int main(int argc, char *argv[]) {
int ret;
find_bin_dir();
#ifdef RUNTIME_PAGESIZE
g_Pagesize = sysconf(_SC_PAGESIZE);
#endif /* RUNTIME_PAGESIZE */
uint8_t *mem = memory_map(MEM_REGION_SIZE);
mem -= MEM_REGION_START;
@ -287,7 +316,11 @@ int main(int argc, char *argv[]) {
void mmap_initial_data_range(uint8_t *mem, uint32_t start, uint32_t end) {
custom_libc_data_addr = end;
#ifdef __APPLE__
end += vm_page_size;
#else
end += 4096;
#endif /* __APPLE__ */
memory_allocate(mem, start, end);
cur_sbrk = end;
}
@ -331,8 +364,9 @@ static uint32_t strcpy2(uint8_t *mem, uint32_t dest_addr, uint32_t src_addr) {
uint32_t wrapper_sbrk(uint8_t *mem, int increment) {
uint32_t old = cur_sbrk;
memory_allocate(mem, old, (old + increment));
cur_sbrk += increment;
size_t alignedInc = ROUND_PAGE(old + increment) - old;
memory_allocate(mem, old, old + alignedInc);
cur_sbrk += alignedInc;
return old;
}
@ -434,10 +468,10 @@ uint32_t wrapper_malloc(uint8_t *mem, uint32_t size) {
uint32_t sbrk_request = 0x10000;
if (8 + item_size > sbrk_request) {
sbrk_request = 8 + item_size;
sbrk_request = (sbrk_request + 0xfff) & ~0xfff;
sbrk_request = ROUND_PAGE(sbrk_request);
}
uint32_t left_over = sbrk_request % (8 + item_size);
sbrk_request -= left_over & ~0xfff;
sbrk_request -= left_over & ~(4096 - 1);
mem_allocated += sbrk_request;
++num_sbrks;
node_ptr = wrapper_sbrk(mem, sbrk_request);
@ -988,6 +1022,30 @@ uint32_t wrapper_strtoul(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr,
return res;
}
uint64_t wrapper_strtoll(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr, int base) {
STRING(nptr)
char *endptr = NULL;
uint64_t res = strtoll(nptr, endptr_addr != 0 ? &endptr : NULL, base);
if(endptr != NULL) {
MEM_U32(endptr_addr) = nptr_addr + (uint32_t)(endptr - nptr);
}
return res;
}
uint64_t wrapper_strtoull(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr, int base) {
STRING(nptr)
char *endptr = NULL;
uint64_t res = strtoull(nptr, endptr_addr != 0 ? &endptr : NULL, base);
if(endptr != NULL) {
MEM_U32(endptr_addr) = nptr_addr + (uint32_t)(endptr - nptr);
}
return res;
}
double wrapper_strtod(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr) {
STRING(nptr)
char *endptr = NULL;
@ -1336,7 +1394,7 @@ int wrapper_ftell(uint8_t *mem, uint32_t fp_addr) {
return res;
}
int wrapper_rewind(uint8_t *mem, uint32_t fp_addr) {
void 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;
@ -1787,6 +1845,7 @@ 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) {

4
tools/ido5.3_recomp/libc_impl.h Normal file → Executable file
View File

@ -31,6 +31,8 @@ int wrapper_atol(uint8_t *mem, uint32_t nptr_addr);
double wrapper_atof(uint8_t *mem, uint32_t nptr_addr);
int wrapper_strtol(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr, int base);
uint32_t wrapper_strtoul(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr, int base);
uint64_t wrapper_strtoll(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr, int base);
uint64_t wrapper_strtoull(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr, int base);
double wrapper_strtod(uint8_t *mem, uint32_t nptr_addr, uint32_t endptr_addr);
uint32_t wrapper_strchr(uint8_t *mem, uint32_t str_addr, int c);
uint32_t wrapper_strrchr(uint8_t *mem, uint32_t str_addr, int c);
@ -49,7 +51,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);
int wrapper_rewind(uint8_t *mem, uint32_t fp_addr);
void 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);

106
tools/ido5.3_recomp/recomp.cpp Normal file → Executable file
View File

@ -3,35 +3,30 @@
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <unistd.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"
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windows.h>
#endif /* _WIN32 && !__CYGWIN__ */
#define INSPECT_FUNCTION_POINTERS 0 // set this to 1 when testing a new program, to verify that no false function pointers are found
#ifndef TRACE
#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]))
@ -81,6 +76,8 @@ struct Function {
bool referenced_by_function_pointer;
};
static bool conservative;
static csh handle;
static const uint8_t *text_section;
@ -153,6 +150,8 @@ static const struct {
{"atof", "dp"},
{"strtol", "ippi"},
{"strtoul", "uppi"},
{"strtoll", "lppi"},
{"strtoull", "jppi"},
{"strtod", "dpp"},
{"strchr", "ppi"},
{"strrchr", "ppi"},
@ -170,7 +169,7 @@ static const struct {
{"freopen", "pppp"},
{"fclose", "ip"},
{"ftell", "ip"},
{"rewind", "ip"},
{"rewind", "vp"},
{"fseek", "ipii"},
{"lseek", "iiii"},
{"fflush", "ip"},
@ -286,24 +285,31 @@ static const struct {
static void disassemble(void) {
csh handle;
cs_insn *disasm;
static size_t disasm_size;
size_t disasm_size = 0;
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);
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));
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;
}
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, cur_disasm_size);
}
cs_free(disasm, disasm_size);
cs_close(&handle);
{
@ -340,7 +346,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 = MAX(0, offset - MAX_LOOKBACK);
int end_search = std::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) {
@ -427,7 +433,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 = MAX(0, offset - MAX_LOOKBACK);
int end_search = std::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) {
@ -1640,7 +1646,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 && !ugen53) {
if (!insn.is_jump && !conservative) {
switch (insn_to_type(insn)) {
case TYPE_1S:
if (!(insn.f_livein & map_reg(insn.operands[0].reg))) {
@ -2160,6 +2166,12 @@ static void dump_instr(int i) {
printf("lo = %s * %s;\n", r(insn.operands[0].reg), r(insn.operands[1].reg));
printf("hi = (uint32_t)((uint64_t)%s * (uint64_t)%s >> 32);\n", r(insn.operands[0].reg), r(insn.operands[1].reg));
break;
case MIPS_INS_SQRT:
printf("%s = sqrtf(%s);\n", fr(insn.operands[0].reg), fr(insn.operands[1].reg));
break;
//case MIPS_INS_FSQRT:
// printf("%s = sqrtf(%s);\n", wr(insn.operands[0].reg), wr(insn.operands[1].reg));
// break;
case MIPS_INS_NEGU:
printf("%s = -%s;\n", r(insn.operands[0].reg), r(insn.operands[1].reg));
break;
@ -2338,27 +2350,35 @@ static void dump_c(void) {
uint32_t max_addr = 0;
if (data_section_len > 0) {
min_addr = MIN(min_addr, data_vaddr);
max_addr = MAX(max_addr, data_vaddr + data_section_len);
min_addr = std::min(min_addr, data_vaddr);
max_addr = std::max(max_addr, data_vaddr + data_section_len);
}
if (rodata_section_len > 0) {
min_addr = MIN(min_addr, rodata_vaddr);
max_addr = MAX(max_addr, rodata_vaddr + rodata_section_len);
min_addr = std::min(min_addr, rodata_vaddr);
max_addr = std::max(max_addr, rodata_vaddr + rodata_section_len);
}
if (bss_section_len) {
min_addr = MIN(min_addr, bss_vaddr);
max_addr = MAX(max_addr, bss_vaddr + 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_addr & ~0xfff;
max_addr = (max_addr + 0xfff) & ~0xfff;
// get pagesize at runtime
#if defined(_WIN32) && !defined(__CYGWIN__)
SYSTEM_INFO si;
GetSystemInfo(&si);
uint32_t page_size = si.dwPageSize;
#else
uint32_t page_size = sysconf(_SC_PAGESIZE);
#endif /* _WIN32 && !__CYGWIN__ */
min_addr = min_addr & ~(page_size - 1);
max_addr = (max_addr + (page_size - 1)) & ~(page_size - 1);
uint32_t stack_bottom = min_addr;
min_addr -= 1 * 1024 * 1024; // 1 MB stack
stack_bottom -= 16; // for main's stack frame
printf("#include \"header.h\"\n");
if (ugen53) {
if (conservative) {
printf("static uint32_t s0, s1, s2, s3, s4, s5, s6, s7, fp;\n");
}
printf("static const uint32_t rodata[] = {\n");
@ -2486,7 +2506,7 @@ static void dump_c(void) {
dump_function_signature(f, start_addr);
printf(" {\n");
printf("const uint32_t zero = 0;\n");
if (!ugen53) {
if (!conservative) {
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");
@ -2911,8 +2931,14 @@ 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(argv[1], &data);
size_t len = read_file(filename, &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);