"I am a person who works hard and plays hard."

Yuan Wei
Second Year Graduate Student Department of Computer Science
University of Virginia Charlottesville, VA 22903
Email: yw3f@cs.virginia.edu


Source Code Analysis

Main Page   Compound List   File List   Compound Members   File Members  

loader.c

Go to the documentation of this file.
00001 /*
00002  * loader.c - program loader routines
00003  *
00004  * This file is a part of the SimpleScalar tool suite written by
00005  * Todd M. Austin as a part of the Multiscalar Research Project.
00006  *  
00007  * The tool suite is currently maintained by Doug Burger and Todd M. Austin.
00008  * 
00009  * Copyright (C) 1994, 1995, 1996, 1997, 1998 by Todd M. Austin
00010  *
00011  * This source file is distributed "as is" in the hope that it will be
00012  * useful.  The tool set comes with no warranty, and no author or
00013  * distributor accepts any responsibility for the consequences of its
00014  * use. 
00015  * 
00016  * Everyone is granted permission to copy, modify and redistribute
00017  * this tool set under the following conditions:
00018  * 
00019  *    This source code is distributed for non-commercial use only. 
00020  *    Please contact the maintainer for restrictions applying to 
00021  *    commercial use.
00022  *
00023  *    Permission is granted to anyone to make or distribute copies
00024  *    of this source code, either as received or modified, in any
00025  *    medium, provided that all copyright notices, permission and
00026  *    nonwarranty notices are preserved, and that the distributor
00027  *    grants the recipient permission for further redistribution as
00028  *    permitted by this document.
00029  *
00030  *    Permission is granted to distribute this file in compiled
00031  *    or executable form under the same conditions that apply for
00032  *    source code, provided that either:
00033  *
00034  *    A. it is accompanied by the corresponding machine-readable
00035  *       source code,
00036  *    B. it is accompanied by a written offer, with no time limit,
00037  *       to give anyone a machine-readable copy of the corresponding
00038  *       source code in return for reimbursement of the cost of
00039  *       distribution.  This written offer must permit verbatim
00040  *       duplication by anyone, or
00041  *    C. it is distributed by someone who received only the
00042  *       executable form, and is accompanied by a copy of the
00043  *       written offer of source code that they received concurrently.
00044  *
00045  * In other words, you are welcome to use, share and improve this
00046  * source file.  You are forbidden to forbid anyone else to use, share
00047  * and improve what you give them.
00048  *
00049  * INTERNET: dburger@cs.wisc.edu
00050  * US Mail:  1210 W. Dayton Street, Madison, WI 53706
00051  *
00052  * $Id: loader.c,v 1.1.1.1 2000/05/26 15:21:55 taustin Exp $
00053  *
00054  * $Log: loader.c,v $
00055  * Revision 1.1.1.1  2000/05/26 15:21:55  taustin
00056  * SimpleScalar Tool Set
00057  *
00058  *
00059  * Revision 1.9  1999/12/31 19:01:45  taustin
00060  * quad_t naming conflicts removed
00061  * cross-endian execution support added (w/ limited syscall support)
00062  *
00063  * Revision 1.8  1999/12/13 19:01:58  taustin
00064  * cross endian execution support added
00065  *
00066  * Revision 1.7  1998/08/27 16:57:46  taustin
00067  * implemented host interface description in host.h
00068  * added target interface support
00069  * added support for register and memory contexts
00070  * external event I/O (EIO) tracing and checkpointing added
00071  * improved loader error messages, e.g., loading Alpha binaries on
00072  *       PISA-configured simulator indicates such
00073  * fixed a BFD/non-BFD loader problem where tail padding in the text
00074  *       segment was not correctly allocated in simulator memory; when
00075  *       padding region happened to cross a page boundary the final text
00076  *       page has a NULL pointer in mem_table, resulting in a SEGV when
00077  *       trying to access it in intruction predecoding
00078  * instruction predecoding moved to loader module
00079  *
00080  * Revision 1.6  1997/04/16  22:09:05  taustin
00081  * added standalone loader support
00082  *
00083  * Revision 1.5  1997/03/11  01:12:39  taustin
00084  * updated copyright
00085  * swapping supported disabled until it can be tested further
00086  *
00087  * Revision 1.4  1997/01/06  15:59:22  taustin
00088  * stat_reg calls now do not initialize stat variable values
00089  * ld_prog_fname variable exported
00090  *
00091  * Revision 1.3  1996/12/27  15:51:28  taustin
00092  * updated comments
00093  *
00094  * Revision 1.1  1996/12/05  18:52:32  taustin
00095  * Initial revision
00096  *
00097  *
00098  */
00099 
00100 #include <stdio.h>
00101 #include <stdlib.h>
00102 
00103 #include "host.h"
00104 #include "misc.h"
00105 #include "machine.h"
00106 #include "endian.h"
00107 #include "regs.h"
00108 #include "memory.h"
00109 #include "sim.h"
00110 #include "eio.h"
00111 #include "loader.h"
00112 
00113 #ifdef BFD_LOADER
00114 #include <bfd.h>
00115 #else /* !BFD_LOADER */
00116 #include "target-pisa/ecoff.h"
00117 #endif /* BFD_LOADER */
00118 
00119 /* amount of tail padding added to all loaded text segments */
00120 #define TEXT_TAIL_PADDING 128
00121 
00122 /* program text (code) segment base */
00123 md_addr_t ld_text_base = 0;
00124 
00125 /* program text (code) size in bytes */
00126 unsigned int ld_text_size = 0;
00127 
00128 /* program initialized data segment base */
00129 md_addr_t ld_data_base = 0;
00130 
00131 /* program initialized ".data" and uninitialized ".bss" size in bytes */
00132 unsigned int ld_data_size = 0;
00133 
00134 /* top of the data segment */
00135 md_addr_t ld_brk_point = 0;
00136 
00137 /* program stack segment base (highest address in stack) */
00138 md_addr_t ld_stack_base = MD_STACK_BASE;
00139 
00140 /* program initial stack size */
00141 unsigned int ld_stack_size = 0;
00142 
00143 /* lowest address accessed on the stack */
00144 md_addr_t ld_stack_min = (md_addr_t)-1;
00145 
00146 /* program file name */
00147 char *ld_prog_fname = NULL;
00148 
00149 /* program entry point (initial PC) */
00150 md_addr_t ld_prog_entry = 0;
00151 
00152 /* program environment base address address */
00153 md_addr_t ld_environ_base = 0;
00154 
00155 /* target executable endian-ness, non-zero if big endian */
00156 int ld_target_big_endian;
00157 
00158 /* register simulator-specific statistics */
00159 void
00160 ld_reg_stats(struct stat_sdb_t *sdb)    /* stats data base */
00161 {
00162   stat_reg_addr(sdb, "ld_text_base",
00163                 "program text (code) segment base",
00164                 &ld_text_base, ld_text_base, "  0x%08p");
00165   stat_reg_uint(sdb, "ld_text_size",
00166                 "program text (code) size in bytes",
00167                 &ld_text_size, ld_text_size, NULL);
00168   stat_reg_addr(sdb, "ld_data_base",
00169                 "program initialized data segment base",
00170                 &ld_data_base, ld_data_base, "  0x%08p");
00171   stat_reg_uint(sdb, "ld_data_size",
00172                 "program init'ed `.data' and uninit'ed `.bss' size in bytes",
00173                 &ld_data_size, ld_data_size, NULL);
00174   stat_reg_addr(sdb, "ld_stack_base",
00175                 "program stack segment base (highest address in stack)",
00176                 &ld_stack_base, ld_stack_base, "  0x%08p");
00177   stat_reg_uint(sdb, "ld_stack_size",
00178                 "program initial stack size",
00179                 &ld_stack_size, ld_stack_size, NULL);
00180 #if 0 /* FIXME: broken... */
00181   stat_reg_addr(sdb, "ld_stack_min",
00182                 "program stack segment lowest address",
00183                 &ld_stack_min, ld_stack_min, "  0x%08p");
00184 #endif
00185   stat_reg_addr(sdb, "ld_prog_entry",
00186                 "program entry point (initial PC)",
00187                 &ld_prog_entry, ld_prog_entry, "  0x%08p");
00188   stat_reg_addr(sdb, "ld_environ_base",
00189                 "program environment base address address",
00190                 &ld_environ_base, ld_environ_base, "  0x%08p");
00191   stat_reg_int(sdb, "ld_target_big_endian",
00192                "target executable endian-ness, non-zero if big endian",
00193                &ld_target_big_endian, ld_target_big_endian, NULL);
00194 }
00195 
00196 
00197 /* load program text and initialized data into simulated virtual memory
00198    space and initialize program segment range variables */
00199 void
00200 ld_load_prog(char *fname,               /* program to load */
00201              int argc, char **argv,     /* simulated program cmd line args */
00202              char **envp,               /* simulated program environment */
00203              struct regs_t *regs,       /* registers to initialize for load */
00204              struct mem_t *mem,         /* memory space to load prog into */
00205              int zero_bss_segs)         /* zero uninit data segment? */
00206 {
00207   int i;
00208   word_t temp;
00209   md_addr_t sp, data_break = 0, null_ptr = 0, argv_addr, envp_addr;
00210 
00211   if (eio_valid(fname))
00212     {
00213       if (argc != 1)
00214         {
00215           fprintf(stderr, "error: EIO file has arguments\n");
00216           exit(1);
00217         }
00218 
00219       fprintf(stderr, "sim: loading EIO file: %s\n", fname);
00220 
00221       sim_eio_fname = mystrdup(fname);
00222 
00223       /* open the EIO file stream */
00224       sim_eio_fd = eio_open(fname);
00225 
00226       /* load initial state checkpoint */
00227       if (eio_read_chkpt(regs, mem, sim_eio_fd) != -1)
00228         fatal("bad initial checkpoint in EIO file");
00229 
00230       /* load checkpoint? */
00231       if (sim_chkpt_fname != NULL)
00232         {
00233           counter_t restore_icnt;
00234 
00235           FILE *chkpt_fd;
00236 
00237           fprintf(stderr, "sim: loading checkpoint file: %s\n",
00238                   sim_chkpt_fname);
00239 
00240           if (!eio_valid(sim_chkpt_fname))
00241             fatal("file `%s' does not appear to be a checkpoint file",
00242                   sim_chkpt_fname);
00243 
00244           /* open the checkpoint file */
00245           chkpt_fd = eio_open(sim_chkpt_fname);
00246 
00247           /* load the state image */
00248           restore_icnt = eio_read_chkpt(regs, mem, chkpt_fd);
00249 
00250           /* fast forward the baseline EIO trace to checkpoint location */
00251           myfprintf(stderr, "sim: fast forwarding to instruction %n\n",
00252                     restore_icnt);
00253           eio_fast_forward(sim_eio_fd, restore_icnt);
00254         }
00255 
00256       /* computed state... */
00257       ld_environ_base = regs->regs_R[MD_REG_SP];
00258       ld_prog_entry = regs->regs_PC;
00259 
00260       /* fini... */
00261       return;
00262     }
00263 #ifdef MD_CROSS_ENDIAN
00264   else
00265     {
00266       fatal("SimpleScalar/PISA only supports binary execution on\n"
00267             "       same-endian hosts, use EIO files on cross-endian hosts");
00268     }
00269 #endif /* MD_CROSS_ENDIAN */
00270 
00271 
00272   if (sim_chkpt_fname != NULL)
00273     fatal("checkpoints only supported while EIO tracing");
00274 
00275 #ifdef BFD_LOADER
00276 
00277   {
00278     bfd *abfd;
00279     asection *sect;
00280 
00281     /* set up a local stack pointer, this is where the argv and envp
00282        data is written into program memory */
00283     ld_stack_base = MD_STACK_BASE;
00284     sp = ROUND_DOWN(MD_STACK_BASE - MD_MAX_ENVIRON, sizeof(dfloat_t));
00285     ld_stack_size = ld_stack_base - sp;
00286 
00287     /* initial stack pointer value */
00288     ld_environ_base = sp;
00289 
00290     /* load the program into memory, try both endians */
00291     if (!(abfd = bfd_openr(argv[0], "ss-coff-big")))
00292       if (!(abfd = bfd_openr(argv[0], "ss-coff-little")))
00293         fatal("cannot open executable `%s'", argv[0]);
00294 
00295     /* this call is mainly for its side effect of reading in the sections.
00296        we follow the traditional behavior of `strings' in that we don't
00297        complain if we don't recognize a file to be an object file.  */
00298     if (!bfd_check_format(abfd, bfd_object))
00299       {
00300         bfd_close(abfd);
00301         fatal("cannot open executable `%s'", argv[0]);
00302       }
00303 
00304     /* record profile file name */
00305     ld_prog_fname = argv[0];
00306 
00307     /* record endian of target */
00308     ld_target_big_endian = abfd->xvec->byteorder_big_p;
00309 
00310     debug("processing %d sections in `%s'...",
00311           bfd_count_sections(abfd), argv[0]);
00312 
00313     /* read all sections in file */
00314     for (sect=abfd->sections; sect; sect=sect->next)
00315       {
00316         char *p;
00317 
00318         debug("processing section `%s', %d bytes @ 0x%08x...",
00319               bfd_section_name(abfd, sect), bfd_section_size(abfd, sect),
00320               bfd_section_vma(abfd, sect));
00321 
00322         /* read the section data, if allocated and loadable and non-NULL */
00323         if ((bfd_get_section_flags(abfd, sect) & SEC_ALLOC)
00324             && (bfd_get_section_flags(abfd, sect) & SEC_LOAD)
00325             && bfd_section_vma(abfd, sect)
00326             && bfd_section_size(abfd, sect))
00327           {
00328             /* allocate a section buffer */
00329             p = calloc(bfd_section_size(abfd, sect), sizeof(char));
00330             if (!p)
00331               fatal("cannot allocate %d bytes for section `%s'",
00332                     bfd_section_size(abfd, sect),
00333                     bfd_section_name(abfd, sect));
00334 
00335             if (!bfd_get_section_contents(abfd, sect, p, (file_ptr)0,
00336                                           bfd_section_size(abfd, sect)))
00337               fatal("could not read entire `%s' section from executable",
00338                     bfd_section_name(abfd, sect));
00339 
00340             /* copy program section it into simulator target memory */
00341             mem_bcopy(mem_access, mem, Write, bfd_section_vma(abfd, sect),
00342                       p, bfd_section_size(abfd, sect));
00343 
00344             /* release the section buffer */
00345             free(p);
00346           }
00347         /* zero out the section if it is loadable but not allocated in exec */
00348         else if (zero_bss_segs
00349                  && (bfd_get_section_flags(abfd, sect) & SEC_LOAD)
00350                  && bfd_section_vma(abfd, sect)
00351                  && bfd_section_size(abfd, sect))
00352           {
00353             /* zero out the section region */
00354             mem_bzero(mem_access, mem,
00355                       bfd_section_vma(abfd, sect),
00356                       bfd_section_size(abfd, sect));
00357           }
00358         else
00359           {
00360             /* else do nothing with this section, it's probably debug data */
00361             debug("ignoring section `%s' during load...",
00362                   bfd_section_name(abfd, sect));
00363           }
00364 
00365         /* expected text section */
00366         if (!strcmp(bfd_section_name(abfd, sect), ".text"))
00367           {
00368             /* .text section processing */
00369             ld_text_size =
00370               ((bfd_section_vma(abfd, sect) + bfd_section_size(abfd, sect))
00371                - MD_TEXT_BASE)
00372                 + /* for speculative fetches/decodes */TEXT_TAIL_PADDING;
00373 
00374             /* create tail padding and copy into simulator target memory */
00375             mem_bzero(mem_access, mem,
00376                       bfd_section_vma(abfd, sect)
00377                       + bfd_section_size(abfd, sect),
00378                       TEXT_TAIL_PADDING);
00379           }
00380         /* expected data sections */
00381         else if (!strcmp(bfd_section_name(abfd, sect), ".rdata")
00382                  || !strcmp(bfd_section_name(abfd, sect), ".data")
00383                  || !strcmp(bfd_section_name(abfd, sect), ".sdata")
00384                  || !strcmp(bfd_section_name(abfd, sect), ".bss")
00385                  || !strcmp(bfd_section_name(abfd, sect), ".sbss"))
00386           {
00387             /* data section processing */
00388             if (bfd_section_vma(abfd, sect) + bfd_section_size(abfd, sect) >
00389                 data_break)
00390               data_break = (bfd_section_vma(abfd, sect) +
00391                             bfd_section_size(abfd, sect));
00392           }
00393         else
00394           {
00395             /* what is this section??? */
00396             fatal("encountered unknown section `%s', %d bytes @ 0x%08x",
00397                   bfd_section_name(abfd, sect), bfd_section_size(abfd, sect),
00398                   bfd_section_vma(abfd, sect));
00399           }
00400       }
00401 
00402     /* compute data segment size from data break point */
00403     ld_text_base = MD_TEXT_BASE;
00404     ld_data_base = MD_DATA_BASE;
00405     ld_prog_entry = bfd_get_start_address(abfd);
00406     ld_data_size = data_break - ld_data_base;
00407 
00408     /* done with the executable, close it */
00409     if (!bfd_close(abfd))
00410       fatal("could not close executable `%s'", argv[0]);
00411   }
00412 
00413 #else /* !BFD_LOADER, i.e., standalone loader */
00414 
00415   {
00416     FILE *fobj;
00417     long floc;
00418     struct ecoff_filehdr fhdr;
00419     struct ecoff_aouthdr ahdr;
00420     struct ecoff_scnhdr shdr;
00421 
00422     /* set up a local stack pointer, this is where the argv and envp
00423        data is written into program memory */
00424     ld_stack_base = MD_STACK_BASE;
00425     sp = ROUND_DOWN(MD_STACK_BASE - MD_MAX_ENVIRON, sizeof(dfloat_t));
00426     ld_stack_size = ld_stack_base - sp;
00427 
00428     /* initial stack pointer value */
00429     ld_environ_base = sp;
00430 
00431     /* record profile file name */
00432     ld_prog_fname = argv[0];
00433 
00434     /* load the program into memory, try both endians */
00435 #if defined(__CYGWIN32__) || defined(_MSC_VER)
00436     fobj = fopen(argv[0], "rb");
00437 #else
00438     fobj = fopen(argv[0], "r");
00439 #endif
00440     if (!fobj)
00441       fatal("cannot open executable `%s'", argv[0]);
00442 
00443     if (fread(&fhdr, sizeof(struct ecoff_filehdr), 1, fobj) < 1)
00444       fatal("cannot read header from executable `%s'", argv[0]);
00445 
00446     /* record endian of target */
00447     if (fhdr.f_magic == ECOFF_EB_MAGIC)
00448       ld_target_big_endian = TRUE;
00449     else if (fhdr.f_magic == ECOFF_EL_MAGIC)
00450       ld_target_big_endian = FALSE;
00451     else if (fhdr.f_magic == ECOFF_EB_OTHER || fhdr.f_magic == ECOFF_EL_OTHER)
00452       fatal("PISA binary `%s' has wrong endian format", argv[0]);
00453     else if (fhdr.f_magic == ECOFF_ALPHAMAGIC)
00454       fatal("PISA simulator cannot run Alpha binary `%s'", argv[0]);
00455     else
00456       fatal("bad magic number in executable `%s' (not an executable?)",
00457             argv[0]);
00458 
00459     if (fread(&ahdr, sizeof(struct ecoff_aouthdr), 1, fobj) < 1)
00460       fatal("cannot read AOUT header from executable `%s'", argv[0]);
00461 
00462     data_break = MD_DATA_BASE + ahdr.dsize + ahdr.bsize;
00463 
00464 #if 0
00465     Data_start = ahdr.data_start;
00466     Data_size = ahdr.dsize;
00467     Bss_size = ahdr.bsize;
00468     Bss_start = ahdr.bss_start;
00469     Gp_value = ahdr.gp_value;
00470     Text_entry = ahdr.entry;
00471 #endif
00472 
00473     /* seek to the beginning of the first section header, the file header comes
00474        first, followed by the optional header (this is the aouthdr), the size
00475        of the aouthdr is given in Fdhr.f_opthdr */
00476     fseek(fobj, sizeof(struct ecoff_filehdr) + fhdr.f_opthdr, 0);
00477 
00478     debug("processing %d sections in `%s'...", fhdr.f_nscns, argv[0]);
00479 
00480     /* loop through the section headers */
00481     floc = ftell(fobj);
00482     for (i = 0; i < fhdr.f_nscns; i++)
00483       {
00484         char *p;
00485 
00486         if (fseek(fobj, floc, 0) == -1)
00487           fatal("could not reset location in executable");
00488         if (fread(&shdr, sizeof(struct ecoff_scnhdr), 1, fobj) < 1)
00489           fatal("could not read section %d from executable", i);
00490         floc = ftell(fobj);
00491 
00492         switch (shdr.s_flags)
00493           {
00494           case ECOFF_STYP_TEXT:
00495             ld_text_size = ((shdr.s_vaddr + shdr.s_size) - MD_TEXT_BASE) 
00496               + TEXT_TAIL_PADDING;
00497 
00498             p = calloc(shdr.s_size, sizeof(char));
00499             if (!p)
00500               fatal("out of virtual memory");
00501 
00502             if (fseek(fobj, shdr.s_scnptr, 0) == -1)
00503               fatal("could not read `.text' from executable", i);
00504             if (fread(p, shdr.s_size, 1, fobj) < 1)
00505               fatal("could not read text section from executable");
00506 
00507             /* copy program section into simulator target memory */
00508             mem_bcopy(mem_access, mem, Write, shdr.s_vaddr, p, shdr.s_size);
00509 
00510             /* create tail padding and copy into simulator target memory */
00511             mem_bzero(mem_access, mem,
00512                       shdr.s_vaddr + shdr.s_size, TEXT_TAIL_PADDING);
00513   
00514             /* release the section buffer */
00515             free(p);
00516 
00517 #if 0
00518             Text_seek = shdr.s_scnptr;
00519             Text_start = shdr.s_vaddr;
00520             Text_size = shdr.s_size / 4;
00521             /* there is a null routine after the supposed end of text */
00522             Text_size += 10;
00523             Text_end = Text_start + Text_size * 4;
00524             /* create_text_reloc(shdr.s_relptr, shdr.s_nreloc); */
00525 #endif
00526             break;
00527 
00528           case ECOFF_STYP_RDATA:
00529             /* The .rdata section is sometimes placed before the text
00530              * section instead of being contiguous with the .data section.
00531              */
00532 #if 0
00533             Rdata_start = shdr.s_vaddr;
00534             Rdata_size = shdr.s_size;
00535             Rdata_seek = shdr.s_scnptr;
00536 #endif
00537             /* fall through */
00538           case ECOFF_STYP_DATA:
00539 #if 0
00540             Data_seek = shdr.s_scnptr;
00541 #endif
00542             /* fall through */
00543           case ECOFF_STYP_SDATA:
00544 #if 0
00545             Sdata_seek = shdr.s_scnptr;
00546 #endif
00547 
00548             p = calloc(shdr.s_size, sizeof(char));
00549             if (!p)
00550               fatal("out of virtual memory");
00551 
00552             if (fseek(fobj, shdr.s_scnptr, 0) == -1)
00553               fatal("could not read `.text' from executable", i);
00554             if (fread(p, shdr.s_size, 1, fobj) < 1)
00555               fatal("could not read text section from executable");
00556 
00557             /* copy program section it into simulator target memory */
00558             mem_bcopy(mem_access, mem, Write, shdr.s_vaddr, p, shdr.s_size);
00559 
00560             /* release the section buffer */
00561             free(p);
00562 
00563             break;
00564 
00565           case ECOFF_STYP_BSS:
00566             break;
00567 
00568           case ECOFF_STYP_SBSS:
00569             break;
00570           }
00571       }
00572 
00573     /* compute data segment size from data break point */
00574     ld_text_base = MD_TEXT_BASE;
00575     ld_data_base = MD_DATA_BASE;
00576     ld_prog_entry = ahdr.entry;
00577     ld_data_size = data_break - ld_data_base;
00578 
00579     /* done with the executable, close it */
00580     if (fclose(fobj))
00581       fatal("could not close executable `%s'", argv[0]);
00582   }
00583 #endif /* BFD_LOADER */
00584 
00585   /* perform sanity checks on segment ranges */
00586   if (!ld_text_base || !ld_text_size)
00587     fatal("executable is missing a `.text' section");
00588   if (!ld_data_base || !ld_data_size)
00589     fatal("executable is missing a `.data' section");
00590   if (!ld_prog_entry)
00591     fatal("program entry point not specified");
00592 
00593   /* determine byte/words swapping required to execute on this host */
00594   sim_swap_bytes = (endian_host_byte_order() != endian_target_byte_order());
00595   if (sim_swap_bytes)
00596     {
00597 #if 0 /* FIXME: disabled until further notice... */
00598       /* cross-endian is never reliable, why this is so is beyond the scope
00599          of this comment, e-mail me for details... */
00600       fprintf(stderr, "sim: *WARNING*: swapping bytes to match host...\n");
00601       fprintf(stderr, "sim: *WARNING*: swapping may break your program!\n");
00602 #else
00603       fatal("binary endian does not match host endian");
00604 #endif
00605     }
00606   sim_swap_words = (endian_host_word_order() != endian_target_word_order());
00607   if (sim_swap_words)
00608     {
00609 #if 0 /* FIXME: disabled until further notice... */
00610       /* cross-endian is never reliable, why this is so is beyond the scope
00611          of this comment, e-mail me for details... */
00612       fprintf(stderr, "sim: *WARNING*: swapping words to match host...\n");
00613       fprintf(stderr, "sim: *WARNING*: swapping may break your program!\n");
00614 #else
00615       fatal("binary endian does not match host endian");
00616 #endif
00617     }
00618 
00619   /* write [argc] to stack */
00620   temp = MD_SWAPW(argc);
00621   mem_access(mem, Write, sp, &temp, sizeof(word_t));
00622   sp += sizeof(word_t);
00623 
00624   /* skip past argv array and NULL */
00625   argv_addr = sp;
00626   sp = sp + (argc + 1) * sizeof(md_addr_t);
00627 
00628   /* save space for envp array and NULL */
00629   envp_addr = sp;
00630   for (i=0; envp[i]; i++)
00631     sp += sizeof(md_addr_t);
00632   sp += sizeof(md_addr_t);
00633 
00634   /* fill in the argv pointer array and data */
00635   for (i=0; i<argc; i++)
00636     {
00637       /* write the argv pointer array entry */
00638       temp = MD_SWAPW(sp);
00639       mem_access(mem, Write, argv_addr + i*sizeof(md_addr_t),
00640                  &temp, sizeof(md_addr_t));
00641       /* and the data */
00642       mem_strcpy(mem_access, mem, Write, sp, argv[i]);
00643       sp += strlen(argv[i]) + 1;
00644     }
00645   /* terminate argv array with a NULL */
00646   mem_access(mem, Write, argv_addr + i*sizeof(md_addr_t),
00647              &null_ptr, sizeof(md_addr_t));
00648 
00649   /* write envp pointer array and data to stack */
00650   for (i = 0; envp[i]; i++)
00651     {
00652       /* write the envp pointer array entry */
00653       temp = MD_SWAPW(sp);
00654       mem_access(mem, Write, envp_addr + i*sizeof(md_addr_t),
00655                  &temp, sizeof(md_addr_t));
00656       /* and the data */
00657       mem_strcpy(mem_access, mem, Write, sp, envp[i]);
00658       sp += strlen(envp[i]) + 1;
00659     }
00660   /* terminate the envp array with a NULL */
00661   mem_access(mem, Write, envp_addr + i*sizeof(md_addr_t),
00662              &null_ptr, sizeof(md_addr_t));
00663 
00664   /* did we tromp off the stop of the stack? */
00665   if (sp > ld_stack_base)
00666     {
00667       /* we did, indicate to the user that MD_MAX_ENVIRON must be increased,
00668          alternatively, you can use a smaller environment, or fewer
00669          command line arguments */
00670       fatal("environment overflow, increase MD_MAX_ENVIRON in ss.h");
00671     }
00672 
00673   /* initialize the bottom of heap to top of data segment */
00674   ld_brk_point = ROUND_UP(ld_data_base + ld_data_size, MD_PAGE_SIZE);
00675 
00676   /* set initial minimum stack pointer value to initial stack value */
00677   ld_stack_min = regs->regs_R[MD_REG_SP];
00678 
00679   /* set up initial register state */
00680   regs->regs_R[MD_REG_SP] = ld_environ_base;
00681   regs->regs_PC = ld_prog_entry;
00682 
00683   debug("ld_text_base: 0x%08x  ld_text_size: 0x%08x",
00684         ld_text_base, ld_text_size);
00685   debug("ld_data_base: 0x%08x  ld_data_size: 0x%08x",
00686         ld_data_base, ld_data_size);
00687   debug("ld_stack_base: 0x%08x  ld_stack_size: 0x%08x",
00688         ld_stack_base, ld_stack_size);
00689   debug("ld_prog_entry: 0x%08x", ld_prog_entry);
00690 
00691   /* finally, predecode the text segment... */
00692   {
00693     md_addr_t addr;
00694     md_inst_t inst;
00695     enum md_fault_type fault;
00696 
00697     if (OP_MAX > 255)
00698       fatal("cannot perform fast decoding, too many opcodes");
00699 
00700     debug("sim: decoding text segment...");
00701     for (addr=ld_text_base;
00702          addr < (ld_text_base+ld_text_size);
00703          addr += sizeof(md_inst_t))
00704       {
00705         fault = mem_access(mem, Read, addr, &inst, sizeof(inst));
00706         if (fault != md_fault_none)
00707           fatal("could not read instruction memory");
00708         inst.a = (inst.a & ~0xff) | (word_t)MD_OP_ENUM(MD_OPFIELD(inst));
00709         fault = mem_access(mem, Write, addr, &inst, sizeof(inst));
00710         if (fault != md_fault_none)
00711           fatal("could not write instruction memory");
00712       }
00713   }
00714 }


UVa CS Department of Computer Science
School of Engineering, University of Virginia
151 Engineer's Way, P.O. Box 400740
Charlottesville, Virginia 22904-4740

(434) 982-2200  Fax: (434) 982-2214