os_vm_address_t copy_core_bytes(int fd, os_vm_offset_t offset, os_vm_address_t addr, int len) { unsigned char buf[4096]; int c,x; int old_fd = lseek(fd, 0, SEEK_CUR); if(len & (4096-1)){ fprintf(stderr, "cant copy a slice of core because slice-length is not of page size(4096)\n"); exit(-1); } if(old_fd < 0){ fprintf(stderr, "cant perform lseek() on corefile\n"); } lseek(fd, offset, SEEK_SET); if(fd < 0){ fprintf(stderr, "cant perform lseek(%u,%lu,SEEK_SET) on corefile\n", fd, offset); } for(x = 0; x < len; x += 4096){ c = read(fd, buf, 4096); if(c != 4096){ fprintf(stderr, "cant read memory area from corefile at position %lu, got %d\n", offset + x, c); exit(-1); } memcpy(addr+x, buf, 4096); } os_flush_icache(addr, len); return addr; }
void arch_write_linkage_table_jmp(void* reloc_addr, void *target_addr) { /* ldr reg, [pc, #4] bx reg nop address BX is needed for thumb interworking, without it it could take just two words with ldr pc, [pc, #-4] address */ int* inst_ptr; unsigned inst; inst_ptr = (int*) reloc_addr; // ldr reg, [pc, #4] inst = 0xe59f0000 | LINKAGE_TEMP_REG << 12 | 4; *inst_ptr++ = inst; // bx reg inst = 0xe12fff10 | LINKAGE_TEMP_REG; *inst_ptr++ = inst; // nop aka mov r0, r0 inst = 0xe1a00000; *inst_ptr++ = inst; // address *inst_ptr++ = target_addr; os_flush_icache((os_vm_address_t) reloc_addr, (char*) inst_ptr - (char*) reloc_addr); }