Skip to content

Commit

Permalink
Fix page size issue (#33)
Browse files Browse the repository at this point in the history
* Debug workflow

* Test minimal build.yml

* Slightly less minimal

* debug print 1

* Debug prints 2

* Try and run it in the build

* Get build to finish, upload binary instead of archive

* Remove page size calculation from recomp binary

* Revert build.yml and Makefile

* Add some assert comments

* Remove debugging stuff

* Update build.yml

* Remove previous page size code
  • Loading branch information
EllipticEllipsis authored Oct 22, 2022
1 parent 7e0b14a commit 5048ce5
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 50 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:

name: Recompiling ido ${{ matrix.ido }} for ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3

# Ubuntu
- name: Install dependencies (Ubuntu)
Expand Down Expand Up @@ -84,7 +84,7 @@ jobs:
tar -czvf ../../../ido-${{ matrix.ido }}-recomp-${{ matrix.os }}.tar.gz *
- name: Upload archive
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
with:
name: ido-${{ matrix.ido }}-recomp-${{ matrix.os }}
path: |
Expand Down
4 changes: 2 additions & 2 deletions libc_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ static uint8_t *memory_map(size_t length)
uint8_t *mem = mmap(0, length, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
#endif

assert(TRUNC_PAGE((uintptr_t)mem) == (uintptr_t)mem);
assert(TRUNC_PAGE((uintptr_t)mem) == (uintptr_t)mem && "Page size too small, try increasing `page_size` in recomp.cpp");
if (mem == MAP_FAILED) {
perror("mmap (memory_map)");
exit(1);
Expand All @@ -233,7 +233,7 @@ static void memory_allocate(uint8_t *mem, uint32_t start, uint32_t end)
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));
assert(start == TRUNC_PAGE(start) && "Page size too small, try increasing `page_size` in recomp.cpp");
#ifdef __CYGWIN__
uintptr_t _start = TRUNC_PAGE((uintptr_t)mem + start);
uintptr_t _end = ROUND_PAGE((uintptr_t)mem + end);
Expand Down
84 changes: 38 additions & 46 deletions recomp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,14 +529,12 @@ void link_with_lui(int offset, rabbitizer::Registers::Cpu::GprO32 reg, int mem_i

// Patch instruction to have offset 0
switch (insns[offset].instruction.getUniqueId()) {
case rabbitizer::InstrId::UniqueId::cpu_addiu:
{
rabbitizer::Registers::Cpu::GprO32 dst_reg =
insns[offset].instruction.GetO32_rt();
insns[offset].patchInstruction(rabbitizer::InstrId::UniqueId::cpu_move);
// Patch the destination register too
insns[offset].instruction.Set_rd(dst_reg);
}
case rabbitizer::InstrId::UniqueId::cpu_addiu: {
rabbitizer::Registers::Cpu::GprO32 dst_reg = insns[offset].instruction.GetO32_rt();
insns[offset].patchInstruction(rabbitizer::InstrId::UniqueId::cpu_move);
// Patch the destination register too
insns[offset].instruction.Set_rd(dst_reg);
}

if (addr >= text_vaddr && addr < text_vaddr + text_section_len) {
add_function(addr);
Expand Down Expand Up @@ -583,7 +581,7 @@ void link_with_lui(int offset, rabbitizer::Registers::Cpu::GprO32 reg, int mem_i
continue;
}
}
loop_end:;
loop_end:;
}

// for a given `jalr t9`, find the matching t9 load
Expand Down Expand Up @@ -904,33 +902,31 @@ void pass1(void) {
case rabbitizer::InstrId::UniqueId::cpu_lwc1:
case rabbitizer::InstrId::UniqueId::cpu_lwc2:
case rabbitizer::InstrId::UniqueId::cpu_swc1:
case rabbitizer::InstrId::UniqueId::cpu_swc2:
{
rabbitizer::Registers::Cpu::GprO32 mem_rs = insns[i].instruction.GetO32_rs();
int32_t mem_imm = insns[i].instruction.getProcessedImmediate();

if (mem_rs == rabbitizer::Registers::Cpu::GprO32::GPR_O32_gp) {
unsigned int got_entry = (mem_imm + gp_value_adj) / sizeof(unsigned int);

if (got_entry >= got_locals.size()) {
got_entry -= got_locals.size();
if (got_entry < got_globals.size()) {
assert(insn.instruction.getUniqueId() == rabbitizer::InstrId::UniqueId::cpu_lw);
unsigned int dest_vaddr = got_globals[got_entry];

insns[i].is_global_got_memop = true;
insns[i].linked_value = dest_vaddr;

// patch to LA
insns[i].lila_dst_reg = get_dest_reg(insns[i]);
insns[i].patchAddress(UniqueId_cpu_la, dest_vaddr);
}
case rabbitizer::InstrId::UniqueId::cpu_swc2: {
rabbitizer::Registers::Cpu::GprO32 mem_rs = insns[i].instruction.GetO32_rs();
int32_t mem_imm = insns[i].instruction.getProcessedImmediate();

if (mem_rs == rabbitizer::Registers::Cpu::GprO32::GPR_O32_gp) {
unsigned int got_entry = (mem_imm + gp_value_adj) / sizeof(unsigned int);

if (got_entry >= got_locals.size()) {
got_entry -= got_locals.size();
if (got_entry < got_globals.size()) {
assert(insn.instruction.getUniqueId() == rabbitizer::InstrId::UniqueId::cpu_lw);
unsigned int dest_vaddr = got_globals[got_entry];

insns[i].is_global_got_memop = true;
insns[i].linked_value = dest_vaddr;

// patch to LA
insns[i].lila_dst_reg = get_dest_reg(insns[i]);
insns[i].patchAddress(UniqueId_cpu_la, dest_vaddr);
}
} else {
link_with_lui(i, mem_rs, mem_imm);
}
} else {
link_with_lui(i, mem_rs, mem_imm);
}
break;
} break;

case rabbitizer::InstrId::UniqueId::cpu_addiu:
case rabbitizer::InstrId::UniqueId::cpu_ori: {
Expand All @@ -943,9 +939,8 @@ void pass1(void) {
insns[i].lila_dst_reg = get_dest_reg(insns[i]);
insns[i].patchInstruction(UniqueId_cpu_li);
insns[i].patchImmediate(imm);
} else if (rt !=
rabbitizer::Registers::Cpu::GprO32::GPR_O32_gp) { // only look for LUI if rt and rs are the
// same
} else if (rt != rabbitizer::Registers::Cpu::GprO32::GPR_O32_gp) { // only look for LUI if rt and rs are
// the same
link_with_lui(i, rs, imm);
}
} break;
Expand Down Expand Up @@ -3043,20 +3038,17 @@ void dump_c(void) {
max_addr = std::max(max_addr, bss_vaddr + bss_section_len);
}

// 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__ */
// 64 kB. Supposedly the worst-case smallest permitted page size, increase if necessary.
// Ensures the hardcoded min_addr and max_addr are sufficiently aligned for the machine running the
// recompiled binaries (and not just the one doing the original recomp build).
uint32_t page_size = 0x10000;

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
min_addr -= 0x100000; // 1 MB stack
stack_bottom -= 0x10; // for main's stack frame

printf("#include \"header.h\"\n");

Expand Down

0 comments on commit 5048ce5

Please sign in to comment.