?? loader.c.svn-base
字號:
/*
* loader.c - program loader routines
* written by fenghao 2004/4/4
*/
#include <stdio.h>
#include <stdlib.h>
#include "host.h"
#include "misc.h"
#include "machine.h"
#include "endian.h"
#include "regs.h"
#include "memory.h"
#include "sim.h"
#include "eio.h"
#include "loader.h"
#ifdef BFD_LOADER
#include <bfd.h>
#else /* !BFD_LOADER */
#include "target-mips/ecoff.h"
#endif /* BFD_LOADER */
/* amount of segment alignment to all loadable segment */
#define SEGMENT_ALIGNMENT_PADDING \
(elf_phdr.p_align - (elf_phdr.p_memsz & 0x111))
/* size of the .text section header */
unsigned text_section_size = 0;
/* amount of tail padding added to all loaded text segments */
#define TEXT_TAIL_PADDING 128
/* program text (code) segment base */
md_addr_t ld_text_base = 0;
/* program text (code) size in bytes */
unsigned int ld_text_size = 0;
/* program initialized data segment base */
md_addr_t ld_data_base = 0;
/* program initialized ".data" and uninitialized ".bss" size in bytes */
unsigned int ld_data_size = 0;
/* top of the data segment */
md_addr_t ld_brk_point = 0;
/* program stack segment base (highest address in stack) */
md_addr_t ld_stack_base = MD_STACK_BASE;
/* program initial stack size */
unsigned int ld_stack_size = 0;
/* lowest address accessed on the stack */
md_addr_t ld_stack_min = (md_addr_t)-1;
/* program file name */
char *ld_prog_fname = NULL;
/* program entry point (initial PC) */
md_addr_t ld_prog_entry = 0;
/* program environment base address address */
md_addr_t ld_environ_base = 0;
/* target executable endian-ness, non-zero if big endian */
int ld_target_big_endian;
/* register simulator-specific statistics */
void
ld_reg_stats(struct stat_sdb_t *sdb) /* stats data base */
{
stat_reg_addr(sdb, "ld_text_base",
"program text (code) segment base",
&ld_text_base, ld_text_base, " 0x%08p");
stat_reg_uint(sdb, "ld_text_size",
"program text (code) size in bytes",
&ld_text_size, ld_text_size, NULL);
stat_reg_addr(sdb, "ld_data_base",
"program initialized data segment base",
&ld_data_base, ld_data_base, " 0x%08p");
stat_reg_uint(sdb, "ld_data_size",
"program init'ed `.data' and uninit'ed `.bss' size in bytes",
&ld_data_size, ld_data_size, NULL);
stat_reg_addr(sdb, "ld_stack_base",
"program stack segment base (highest address in stack)",
&ld_stack_base, ld_stack_base, " 0x%08p");
stat_reg_uint(sdb, "ld_stack_size",
"program initial stack size",
&ld_stack_size, ld_stack_size, NULL);
#if 0 /* FIXME: broken... */
stat_reg_addr(sdb, "ld_stack_min",
"program stack segment lowest address",
&ld_stack_min, ld_stack_min, " 0x%08p");
#endif
stat_reg_addr(sdb, "ld_prog_entry",
"program entry point (initial PC)",
&ld_prog_entry, ld_prog_entry, " 0x%08p");
stat_reg_addr(sdb, "ld_environ_base",
"program environment base address address",
&ld_environ_base, ld_environ_base, " 0x%08p");
stat_reg_int(sdb, "ld_target_big_endian",
"target executable endian-ness, non-zero if big endian",
&ld_target_big_endian, ld_target_big_endian, NULL);
}
/* load program text and initialized data into simulated virtual memory
space and initialize program segment range variables */
void
ld_load_prog(char *fname, /* program to load */
int argc, char **argv, /* simulated program cmd line args */
char **envp, /* simulated program environment */
struct regs_t *regs, /* registers to initialize for load */
struct mem_t *mem, /* memory space to load prog into */
int zero_bss_segs) /* zero uninit data segment? */
{
int i;
word_t temp;
md_addr_t sp, data_break = 0, null_ptr = 0, argv_addr, envp_addr;
if (eio_valid(fname))
{
if (argc != 1)
{
fprintf(stderr, "error: EIO file has arguments\n");
exit(1);
}
fprintf(stderr, "sim: loading EIO file: %s\n", fname);
sim_eio_fname = mystrdup(fname);
/* open the EIO file stream */
sim_eio_fd = eio_open(fname);
/* load initial state checkpoint */
if (eio_read_chkpt(regs, mem, sim_eio_fd) != -1)
fatal("bad initial checkpoint in EIO file");
/* load checkpoint? */
if (sim_chkpt_fname != NULL)
{
counter_t restore_icnt;
FILE *chkpt_fd;
fprintf(stderr, "sim: loading checkpoint file: %s\n",
sim_chkpt_fname);
if (!eio_valid(sim_chkpt_fname))
fatal("file `%s' does not appear to be a checkpoint file",
sim_chkpt_fname);
/* open the checkpoint file */
chkpt_fd = eio_open(sim_chkpt_fname);
/* load the state image */
restore_icnt = eio_read_chkpt(regs, mem, chkpt_fd);
/* fast forward the baseline EIO trace to checkpoint location */
myfprintf(stderr, "sim: fast forwarding to instruction %n\n",
restore_icnt);
eio_fast_forward(sim_eio_fd, restore_icnt);
}
/* computed state... */
ld_environ_base = regs->regs_R[MD_REG_SP];
ld_prog_entry = regs->regs_PC;
/* fini... */
return;
}
#ifdef MD_CROSS_ENDIAN
else
{
fatal("SimpleScalar/MIPS only supports binary execution on\n"
" same-endian hosts, use EIO files on cross-endian hosts");
}
#endif /* MD_CROSS_ENDIAN */
if (sim_chkpt_fname != NULL)
fatal("checkpoints only supported while EIO tracing");
#ifdef BFD_LOADER
{
bfd *abfd;
asection *sect;
/* set up a local stack pointer, this is where the argv and envp
data is written into program memory */
ld_stack_base = MD_STACK_BASE;
sp = ROUND_DOWN(MD_STACK_BASE - MD_MAX_ENVIRON, sizeof(dfloat_t));
ld_stack_size = ld_stack_base - sp;
/* initial stack pointer value */
ld_environ_base = sp;
/* load the program into memory, try both endians */
if (!(abfd = bfd_openr(argv[0], "ss-coff-big")))
if (!(abfd = bfd_openr(argv[0], "ss-coff-little")))
fatal("cannot open executable `%s'", argv[0]);
/* this call is mainly for its side effect of reading in the sections.
we follow the traditional behavior of `strings' in that we don't
complain if we don't recognize a file to be an object file. */
if (!bfd_check_format(abfd, bfd_object))
{
bfd_close(abfd);
fatal("cannot open executable `%s'", argv[0]);
}
/* record profile file name */
ld_prog_fname = argv[0];
/* record endian of target */
ld_target_big_endian = abfd->xvec->byteorder_big_p;
debug("processing %d sections in `%s'...",
bfd_count_sections(abfd), argv[0]);
/* read all sections in file */
for (sect=abfd->sections; sect; sect=sect->next)
{
char *p;
debug("processing section `%s', %d bytes @ 0x%08x...",
bfd_section_name(abfd, sect), bfd_section_size(abfd, sect),
bfd_section_vma(abfd, sect));
/* read the section data, if allocated and loadable and non-NULL */
if ((bfd_get_section_flags(abfd, sect) & SEC_ALLOC)
&& (bfd_get_section_flags(abfd, sect) & SEC_LOAD)
&& bfd_section_vma(abfd, sect)
&& bfd_section_size(abfd, sect))
{
/* allocate a section buffer */
p = calloc(bfd_section_size(abfd, sect), sizeof(char));
if (!p)
fatal("cannot allocate %d bytes for section `%s'",
bfd_section_size(abfd, sect),
bfd_section_name(abfd, sect));
if (!bfd_get_section_contents(abfd, sect, p, (file_ptr)0,
bfd_section_size(abfd, sect)))
fatal("could not read entire `%s' section from executable",
bfd_section_name(abfd, sect));
/* copy program section it into simulator target memory */
mem_bcopy(mem_access, mem, Write, bfd_section_vma(abfd, sect),
p, bfd_section_size(abfd, sect));
/* release the section buffer */
free(p);
}
/* zero out the section if it is loadable but not allocated in exec */
else if (zero_bss_segs
&& (bfd_get_section_flags(abfd, sect) & SEC_LOAD)
&& bfd_section_vma(abfd, sect)
&& bfd_section_size(abfd, sect))
{
/* zero out the section region */
mem_bzero(mem_access, mem,
bfd_section_vma(abfd, sect),
bfd_section_size(abfd, sect));
}
else
{
/* else do nothing with this section, it's probably debug data */
debug("ignoring section `%s' during load...",
bfd_section_name(abfd, sect));
}
/* expected text section */
if (!strcmp(bfd_section_name(abfd, sect), ".text"))
{
/* .text section processing */
ld_text_size =
((bfd_section_vma(abfd, sect) + bfd_section_size(abfd, sect))
- MD_TEXT_BASE)
+ /* for speculative fetches/decodes */TEXT_TAIL_PADDING;
/* create tail padding and copy into simulator target memory */
mem_bzero(mem_access, mem,
bfd_section_vma(abfd, sect)
+ bfd_section_size(abfd, sect),
TEXT_TAIL_PADDING);
}
/* expected data sections */
else if (!strcmp(bfd_section_name(abfd, sect), ".rdata")
|| !strcmp(bfd_section_name(abfd, sect), ".data")
|| !strcmp(bfd_section_name(abfd, sect), ".sdata")
|| !strcmp(bfd_section_name(abfd, sect), ".bss")
|| !strcmp(bfd_section_name(abfd, sect), ".sbss"))
{
/* 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]);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -