Merge branch 'upstream'
[nativeclient.git] / ncv / ncrewrite.c
blob9cda600f44c737b7def40632846634eb73f6742f
2 #include <assert.h>
3 #include <fcntl.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <sys/mman.h>
7 #include <sys/stat.h>
8 #include <unistd.h>
10 #include "native_client/include/elf.h"
11 #include "native_client/ncv/ncdecode.h"
14 static int write_nops = 0;
16 static void handle_instruction(const struct NCDecoderState *mstate)
18 /* Rewrites
19 nop; nop; nop
20 jmp *%reg
22 and $0xffffffe0, %reg
23 jmp *%reg
25 if(mstate->opinfo->insttype == NACLi_INDIRECT) {
26 unsigned char and_instr[3] = {
27 0x83, /* "and" opcode */
28 0xe0 | modrm_rm(mstate->inst.maddr[1]), /* operand */
29 0xe0, /* alignment mask, constant ~31 */
32 if((PreviousInst(mstate, -1) != NULL &&
33 memcmp(mstate->inst.maddr - 3, and_instr, 3) == 0) ||
34 (PreviousInst(mstate, -3) != NULL &&
35 mstate->inst.maddr[-3] == 0x90 &&
36 mstate->inst.maddr[-2] == 0x90 &&
37 mstate->inst.maddr[-1] == 0x90)) {
38 if(write_nops)
39 memset(mstate->inst.maddr - 3, 0x90, 3);
40 else
41 memcpy(mstate->inst.maddr - 3, and_instr, 3);
43 else {
44 fprintf(stderr, "%08x: cannot rewrite\n", mstate->inst.vaddr);
49 static void fixup_file(const char *filename)
51 int fd = open(filename, O_RDWR);
52 if(fd < 0) {
53 perror("open");
54 exit(1);
56 struct stat st;
57 if(fstat(fd, &st) < 0) {
58 perror("fstat");
59 exit(1);
61 unsigned char *data = mmap(NULL, st.st_size, PROT_READ | PROT_WRITE,
62 MAP_SHARED, fd, 0);
63 if(data == MAP_FAILED) {
64 perror("mmap");
65 exit(1);
67 if(close(fd) < 0) {
68 perror("close");
69 exit(1);
71 Elf32_Ehdr *header = (Elf32_Ehdr *) data;
72 assert(memcmp(header->e_ident, ELFMAG, strlen(ELFMAG)) == 0);
73 int i;
74 for(i = 0; i < header->e_shnum; i++) {
75 Elf32_Shdr *section = (Elf32_Shdr *) (data + header->e_shoff +
76 header->e_shentsize * i);
77 if((section->sh_flags & SHF_EXECINSTR) != 0) {
78 NCDecodeSegment(data + section->sh_offset, section->sh_addr,
79 section->sh_size, NULL);
82 if(munmap(data, st.st_size) < 0) {
83 perror("munmap");
84 exit(1);
88 int main(int argc, const char *argv[])
90 int i;
91 NCDecodeRegisterCallbacks(handle_instruction, NULL, NULL, NULL);
92 for(i = 1; i < argc; i++) {
93 const char *arg = argv[i];
94 if(strcmp(arg, "--nop") == 0)
95 write_nops = 1;
96 else
97 fixup_file(arg);
99 return 0;