loader.c
来自「一个很有名的硬件模拟器。可以模拟CPU」· C语言 代码 · 共 690 行 · 第 1/2 页
C
690 行
{ /* data section processing */ if (bfd_section_vma(abfd, sect) + bfd_section_size(abfd, sect) > data_break) data_break = (bfd_section_vma(abfd, sect) + bfd_section_size(abfd, sect)); } else { /* what is this section??? */ fatal("encountered unknown section `%s', %d bytes @ 0x%08x", bfd_section_name(abfd, sect), bfd_section_size(abfd, sect), bfd_section_vma(abfd, sect)); } } /* compute data segment size from data break point */ ld_text_base = MD_TEXT_BASE; ld_data_base = MD_DATA_BASE; ld_prog_entry = bfd_get_start_address(abfd); ld_data_size = data_break - ld_data_base; /* done with the executable, close it */ if (!bfd_close(abfd)) fatal("could not close executable `%s'", argv[0]); }#else /* !BFD_LOADER, i.e., standalone loader */ { FILE *fobj; long floc; struct ecoff_filehdr fhdr; struct ecoff_aouthdr ahdr; struct ecoff_scnhdr shdr; /* record profile file name */ ld_prog_fname = argv[0]; /* load the program into memory, try both endians */#if defined(__CYGWIN32__) || defined(_MSC_VER) fobj = fopen(argv[0], "rb");#else fobj = fopen(argv[0], "r");#endif if (!fobj) fatal("cannot open executable `%s'", argv[0]); if (fread(&fhdr, sizeof(struct ecoff_filehdr), 1, fobj) < 1) fatal("cannot read header from executable `%s'", argv[0]); /* record endian of target */ if (fhdr.f_magic == MD_SWAPH(ECOFF_ALPHAMAGIC)) ld_target_big_endian = FALSE; else if (fhdr.f_magic == MD_SWAPH(ECOFF_EB_MAGIC) || fhdr.f_magic == MD_SWAPH(ECOFF_EL_MAGIC) || fhdr.f_magic == MD_SWAPH(ECOFF_EB_OTHER) || fhdr.f_magic == MD_SWAPH(ECOFF_EL_OTHER)) fatal("Alpha simulator cannot run PISA binary `%s'", argv[0]); else fatal("bad magic number in executable `%s' (not an executable)", argv[0]); if (fread(&ahdr, sizeof(struct ecoff_aouthdr), 1, fobj) < 1) fatal("cannot read AOUT header from executable `%s'", argv[0]); ld_text_base = MD_SWAPQ(ahdr.text_start); ld_text_size = MD_SWAPQ(ahdr.tsize); ld_prog_entry = MD_SWAPQ(ahdr.entry); ld_data_base = MD_SWAPQ(ahdr.data_start); ld_data_size = MD_SWAPQ(ahdr.dsize) + MD_SWAPQ(ahdr.bsize); regs->regs_R[MD_REG_GP] = MD_SWAPQ(ahdr.gp_value); /* compute data segment size from data break point */ data_break = ld_data_base + ld_data_size; /* seek to the beginning of the first section header, the file header comes first, followed by the optional header (this is the aouthdr), the size of the aouthdr is given in Fdhr.f_opthdr */ fseek(fobj, sizeof(struct ecoff_filehdr) + MD_SWAPH(fhdr.f_opthdr), 0); debug("processing %d sections in `%s'...", MD_SWAPH(fhdr.f_nscns), argv[0]); /* loop through the section headers */ floc = ftell(fobj); for (i = 0; i < MD_SWAPH(fhdr.f_nscns); i++) { char *p; if (fseek(fobj, floc, 0) == -1) fatal("could not reset location in executable"); if (fread(&shdr, sizeof(struct ecoff_scnhdr), 1, fobj) < 1) fatal("could not read section %d from executable", i); floc = ftell(fobj); switch (MD_SWAPW(shdr.s_flags)) { case ECOFF_STYP_TEXT: p = calloc(MD_SWAPQ(shdr.s_size), sizeof(char)); if (!p) fatal("out of virtual memory"); if (fseek(fobj, MD_SWAPQ(shdr.s_scnptr), 0) == -1) fatal("could not read `.text' from executable", i); if (fread(p, MD_SWAPQ(shdr.s_size), 1, fobj) < 1) fatal("could not read text section from executable"); /* copy program section into simulator target memory */ mem_bcopy(mem_access, mem, Write, MD_SWAPQ(shdr.s_vaddr), p, MD_SWAPQ(shdr.s_size));#if 0 /* create tail padding and copy into simulator target memory */ mem_bzero(mem_access, mem, MD_SWAPQ(shdr.s_vaddr) + MD_SWAPQ(shdr.s_size), TEXT_TAIL_PADDING);#endif /* release the section buffer */ free(p);#if 0 Text_seek = MD_SWAPQ(shdr.s_scnptr); Text_start = MD_SWAPQ(shdr.s_vaddr); Text_size = MD_SWAPQ(shdr.s_size) / 4; /* there is a null routine after the supposed end of text */ Text_size += 10; Text_end = Text_start + Text_size * 4; /* create_text_reloc(shdr.s_relptr, shdr.s_nreloc); */#endif break; case ECOFF_STYP_INIT: case ECOFF_STYP_FINI: if (MD_SWAPQ(shdr.s_size) > 0) { p = calloc(MD_SWAPQ(shdr.s_size), sizeof(char)); if (!p) fatal("out of virtual memory"); if (fseek(fobj, MD_SWAPQ(shdr.s_scnptr), 0) == -1) fatal("could not read `.text' from executable", i); if (fread(p, MD_SWAPQ(shdr.s_size), 1, fobj) < 1) fatal("could not read text section from executable"); /* copy program section into simulator target memory */ mem_bcopy(mem_access, mem, Write, MD_SWAPQ(shdr.s_vaddr), p, MD_SWAPQ(shdr.s_size)); /* release the section buffer */ free(p); } else warn("section `%s' is empty...", shdr.s_name); break; case ECOFF_STYP_LITA: case ECOFF_STYP_LIT8: case ECOFF_STYP_LIT4: case ECOFF_STYP_XDATA: case ECOFF_STYP_PDATA: case ECOFF_STYP_RCONST: /* fall through */ case ECOFF_STYP_RDATA: /* The .rdata section is sometimes placed before the text * section instead of being contiguous with the .data section. */#if 0 Rdata_start = MD_SWAPQ(shdr.s_vaddr); Rdata_size = MD_SWAPQ(shdr.s_size); Rdata_seek = MD_SWAPQ(shdr.s_scnptr);#endif /* fall through */ case ECOFF_STYP_DATA:#if 0 Data_seek = MD_SWAPQ(shdr.s_scnptr);#endif /* fall through */ case ECOFF_STYP_SDATA:#if 0 Sdata_seek = MD_SWAPQ(shdr.s_scnptr);#endif if (MD_SWAPQ(shdr.s_size) > 0) { p = calloc(MD_SWAPQ(shdr.s_size), sizeof(char)); if (!p) fatal("out of virtual memory"); if (fseek(fobj, MD_SWAPQ(shdr.s_scnptr), 0) == -1) fatal("could not read `.text' from executable", i); if (fread(p, MD_SWAPQ(shdr.s_size), 1, fobj) < 1) fatal("could not read text section from executable"); /* copy program section it into simulator target memory */ mem_bcopy(mem_access, mem, Write, MD_SWAPQ(shdr.s_vaddr), p, MD_SWAPQ(shdr.s_size)); /* release the section buffer */ free(p); } else warn("section `%s' is empty...", shdr.s_name); break; case ECOFF_STYP_BSS: case ECOFF_STYP_SBSS: /* no data to read... */ break; default: warn("section `%s' ignored...", shdr.s_name); } } /* done with the executable, close it */ if (fclose(fobj)) fatal("could not close executable `%s'", argv[0]); }#endif /* BFD_LOADER */ /* perform sanity checks on segment ranges */ if (!ld_text_base || !ld_text_size) fatal("executable is missing a `.text' section"); if (!ld_data_base || !ld_data_size) fatal("executable is missing a `.data' section"); if (!ld_prog_entry) fatal("program entry point not specified"); /* determine byte/words swapping required to execute on this host */ sim_swap_bytes = (endian_host_byte_order() != endian_target_byte_order()); if (sim_swap_bytes) {#if 0 /* FIXME: disabled until further notice... */ /* cross-endian is never reliable, why this is so is beyond the scope of this comment, e-mail me for details... */ fprintf(stderr, "sim: *WARNING*: swapping bytes to match host...\n"); fprintf(stderr, "sim: *WARNING*: swapping may break your program!\n"); /* #else */ fatal("binary endian does not match host endian");#endif } sim_swap_words = (endian_host_word_order() != endian_target_word_order()); if (sim_swap_words) {#if 0 /* FIXME: disabled until further notice... */ /* cross-endian is never reliable, why this is so is beyond the scope of this comment, e-mail me for details... */ fprintf(stderr, "sim: *WARNING*: swapping words to match host...\n"); fprintf(stderr, "sim: *WARNING*: swapping may break your program!\n"); /* #else */ fatal("binary endian does not match host endian");#endif } /* set up a local stack pointer, this is where the argv and envp data is written into program memory */ ld_stack_base = ld_text_base - (409600+4096);#if 0 sp = ROUND_DOWN(ld_stack_base - MD_MAX_ENVIRON, sizeof(MD_DOUBLE_TYPE));#endif sp = ld_stack_base - MD_MAX_ENVIRON; ld_stack_size = ld_stack_base - sp; /* initial stack pointer value */ ld_environ_base = sp; /* write [argc] to stack */ temp = MD_SWAPQ(argc); mem_access(mem, Write, sp, &temp, sizeof(qword_t)); regs->regs_R[MD_REG_A0] = temp; sp += sizeof(qword_t); /* skip past argv array and NULL */ argv_addr = sp; regs->regs_R[MD_REG_A1] = argv_addr; sp = sp + (argc + 1) * sizeof(md_addr_t); /* save space for envp array and NULL */ envp_addr = sp; for (i=0; envp[i]; i++) sp += sizeof(md_addr_t); sp += sizeof(md_addr_t); /* fill in the argv pointer array and data */ for (i=0; i<argc; i++) { /* write the argv pointer array entry */ temp = MD_SWAPQ(sp); mem_access(mem, Write, argv_addr + i*sizeof(md_addr_t), &temp, sizeof(md_addr_t)); /* and the data */ mem_strcpy(mem_access, mem, Write, sp, argv[i]); sp += strlen(argv[i])+1; } /* terminate argv array with a NULL */ mem_access(mem, Write, argv_addr + i*sizeof(md_addr_t), &null_ptr, sizeof(md_addr_t)); /* write envp pointer array and data to stack */ for (i = 0; envp[i]; i++) { /* write the envp pointer array entry */ temp = MD_SWAPQ(sp); mem_access(mem, Write, envp_addr + i*sizeof(md_addr_t), &temp, sizeof(md_addr_t)); /* and the data */ mem_strcpy(mem_access, mem, Write, sp, envp[i]); sp += strlen(envp[i]) + 1; } /* terminate the envp array with a NULL */ mem_access(mem, Write, envp_addr + i*sizeof(md_addr_t), &null_ptr, sizeof(md_addr_t)); /* did we tromp off the stop of the stack? */ if (sp > ld_stack_base) { /* we did, indicate to the user that MD_MAX_ENVIRON must be increased, alternatively, you can use a smaller environment, or fewer command line arguments */ fatal("environment overflow, increase MD_MAX_ENVIRON in alpha.h"); } /* initialize the bottom of heap to top of data segment */ ld_brk_point = ROUND_UP(ld_data_base + ld_data_size, MD_PAGE_SIZE); /* set initial minimum stack pointer value to initial stack value */ ld_stack_min = regs->regs_R[MD_REG_SP]; regs->regs_R[MD_REG_SP] = ld_environ_base; regs->regs_PC = ld_prog_entry; debug("ld_text_base: 0x%08x ld_text_size: 0x%08x", ld_text_base, ld_text_size); debug("ld_data_base: 0x%08x ld_data_size: 0x%08x", ld_data_base, ld_data_size); debug("ld_stack_base: 0x%08x ld_stack_size: 0x%08x", ld_stack_base, ld_stack_size); debug("ld_prog_entry: 0x%08x", ld_prog_entry);}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?