Пример #1
0
//
// Set up the initial program binary, stack, and processor flags
// for a user process.
// This function is ONLY called during kernel initialization,
// before running the first user-mode environment.
//
// This function loads all loadable segments from the ELF binary image
// into the environment's user memory, starting at the appropriate
// virtual addresses indicated in the ELF program header.
// At the same time it clears to zero any portions of these segments
// that are marked in the program header as being mapped
// but not actually present in the ELF file - i.e., the program's bss section.
//
// All this is very similar to what our boot loader does, except the boot
// loader also needs to read the code from disk.  Take a look at
// boot/main.c to get ideas.
//
// Finally, this function maps one page for the program's initial stack.
//
// load_icode panics if it encounters problems.
//  - How might load_icode fail?  What might be wrong with the given input?
//
static void
load_icode(struct Env *e, uint8_t *binary, size_t size)
{
  struct Proghdr *ph, *eph;
  struct Elf *hdr = (struct Elf *)binary;

  // is this a valid ELF?
  if (hdr->e_magic != ELF_MAGIC)
    panic("load_icode: Invalid binary.");

  //  Load each program segment into virtual memory
  //  at the address specified in the ELF section header.
  ph = (struct Proghdr *) ((uint8_t *) hdr + hdr->e_phoff);
  eph = ph + hdr->e_phnum;

  //  Loading the segments is much simpler if you can move data
  //  directly into the virtual addresses stored in the ELF binary.
  lcr3(e->env_cr3);
  for (; ph < eph; ph++) {
  //  You should only load segments with ph->p_type == ELF_PROG_LOAD.
    if (ph->p_type != ELF_PROG_LOAD)
      continue;
    
  //  (The ELF header should have ph->p_filesz <= ph->p_memsz.)
    if (ph->p_filesz > ph->p_memsz)
      panic("load_icode: file size larger than memory size.");
    
  //  Each segment's virtual address can be found in ph->p_va
  //  and its size in memory can be found in ph->p_memsz.
  //  The ph->p_filesz bytes from the ELF binary, starting at
  //  'binary + ph->p_offset', should be copied to virtual address
  //  ph->p_va.  Any remaining memory bytes should be cleared to zero.
  //
  //  All page protection bits should be user read/write for now.
  //  ELF segments are not necessarily page-aligned, but you can
  //  assume for this function that no two segments will touch
  //  the same virtual page.
    segment_alloc(e, (void *)ph->p_va, ph->p_memsz);
    memmove((void *)ph->p_va, binary + ph->p_offset, ph->p_filesz);
    memset((void *) ph->p_va + ph->p_filesz, 0, ph->p_memsz - ph->p_filesz);
  }
  lcr3(boot_cr3);

  //  You must also do something with the program's entry point,
  //  to make sure that the environment starts executing there.
  e->env_tf.tf_eip = hdr->e_entry;

  // Now map one page for the program's initial stack
  // at virtual address USTACKTOP - PGSIZE.
  segment_alloc(e, (void *)USTACKTOP - PGSIZE, PGSIZE);
}
Пример #2
0
static segment *
create_seg (seqnum seq, seglen len, u_short this_ip_id)
{
  segment *pseg;

  //pseg = (segment *) MallocZ (sizeof (segment));
  if (threaded)
    {
#ifdef DEBUG_THREAD
      fprintf (fp_stdout, "\n\nRichiesto blocco thread TTP\n");
#endif
      pthread_mutex_lock (&ttp_lock_mutex);
#ifdef DEBUG_THREAD
      fprintf (fp_stdout, "\n\nOttenuto blocco thread TTP\n");
#endif
    }

  pseg = (segment *) segment_alloc ();

  if (threaded)
    {
#ifdef DEBUG_THREAD
      fprintf (fp_stdout, "\n\nRichiesto sblocco thread TTP\n");
#endif
      pthread_mutex_unlock (&ttp_lock_mutex);
#ifdef DEBUG_THREAD
      fprintf (fp_stdout, "\n\nOttenuto sblocco thread TTP\n");
#endif
    }

  pseg->time = current_time;
  pseg->seq_firstbyte = seq;
  pseg->seq_lastbyte = seq + len - 1;
  /* LM start */
  pseg->ip_id = this_ip_id;
  /* LM stop */
  return (pseg);
}
Пример #3
0
Файл: env.c Проект: ichaos/jos
//
// Set up the initial program binary, stack, and processor flags
// for a user process.
// This function is ONLY called during kernel initialization,
// before running the first user-mode environment.
//
// This function loads all loadable segments from the ELF binary image
// into the environment's user memory, starting at the appropriate
// virtual addresses indicated in the ELF program header.
// At the same time it clears to zero any portions of these segments
// that are marked in the program header as being mapped
// but not actually present in the ELF file - i.e., the program's bss section.
//
// All this is very similar to what our boot loader does, except the boot
// loader also needs to read the code from disk.  Take a look at
// boot/main.c to get ideas.
//
// Finally, this function maps one page for the program's initial stack.
//
// load_icode panics if it encounters problems.
//  - How might load_icode fail?  What might be wrong with the given input?
//
static void
load_icode(struct Env *e, uint8_t *binary, size_t size)
{
    // Hints:
    //  Load each program segment into virtual memory
    //  at the address specified in the ELF section header.
    //  You should only load segments with ph->p_type == ELF_PROG_LOAD.
    //  Each segment's virtual address can be found in ph->p_va
    //  and its size in memory can be found in ph->p_memsz.
    //  The ph->p_filesz bytes from the ELF binary, starting at
    //  'binary + ph->p_offset', should be copied to virtual address
    //  ph->p_va.  Any remaining memory bytes should be cleared to zero.
    //  (The ELF header should have ph->p_filesz <= ph->p_memsz.)
    //
    //  All page protection bits should be user read/write for now.
    //  ELF segments are not necessarily page-aligned, but you can
    //  assume for this function that no two segments will touch
    //  the same virtual page.
    //
    //  You may find a function like segment_alloc useful.
    //
    //  Loading the segments is much simpler if you can move data
    //  directly into the virtual addresses stored in the ELF binary.
    //  So which page directory should be in force during
    //  this function?
    //
    // Hint:
    //  You must also do something with the program's entry point,
    //  to make sure that the environment starts executing there.
    //  What?  (See env_run() and env_pop_tf() below.)

    // LAB 3: Your code here.
    struct Proghdr *ph, *eph;

    struct Elf *elfhdr;
    elfhdr = (struct Elf *)binary;
    if (elfhdr->e_magic != ELF_MAGIC)
        panic("load_icode : invalid elf file.\n");//unvalid elf file;
    ph = (struct Proghdr *) (binary + elfhdr->e_phoff);
    eph = ph + elfhdr->e_phnum;
    lcr3(e->env_cr3);//cprintf("lcr3(e->env_cr3) is done.\n");
    for(; ph < eph; ph++) {
        if(ph->p_type == ELF_PROG_LOAD) {
            segment_alloc(e, (void *)ph->p_va, ph->p_memsz);
            //cprintf("(void *)ph->p_va is %x and (binary+ph->p_offset) is %x\n",(void *)ph->p_va, (binary+ph->p_offset));
            memmove((void *)ph->p_va, (void *)(binary+ph->p_offset), ph->p_filesz);
            //cprintf("%x\n",*(int *)ph->p_va);
            //cprintf("%x\n",*(int *)(binary+ph->p_offset));
            //cprintf("here;\n");
            memset((void *)(ph->p_va+ph->p_filesz), 0,
                   (ph->p_memsz-ph->p_filesz));
        }
        //cprintf("here;\n");
    }
    //cprintf("elfhdr->e_entry is %x\n",*(int *)(elfhdr->e_entry));
    lcr3(boot_cr3);//cprintf("lcr3(%x) is done.\n",boot_cr3);

    // Now map one page for the program's initial stack
    // at virtual address USTACKTOP - PGSIZE.
    struct Page* user_stack;
    //user_stack = boot_alloc(PGSIZE, PGSIZE);
    page_alloc(&user_stack);
    page_insert(e->env_pgdir, user_stack, (void *)(USTACKTOP - PGSIZE),
                PTE_USER);
    //cprintf("before elfhdr->e_entry is %x\n",elfhdr->e_entry);
    //elfhdr->e_entry &= 0xFFFFFF;
    e->env_tf.tf_eip = elfhdr->e_entry;
    e->env_tf.tf_esp = USTACKTOP;
    //((void (*)(void)) (elfhdr->e_entry & 0xFFFFFF))();
    //cprintf("after elfhdr->e_entry\n");
    //lcr3(boot_cr3);
    // LAB 3: Your code here.
}
Пример #4
0
//
// Set up the initial program binary, stack, and processor flags
// for a user process.
// This function is ONLY called during kernel initialization,
// before running the first user-mode environment.
//
// This function loads all loadable segments from the ELF binary image
// into the environment's user memory, starting at the appropriate
// virtual addresses indicated in the ELF program header.
// At the same time it clears to zero any portions of these segments
// that are marked in the program header as being mapped
// but not actually present in the ELF file - i.e., the program's bss section.
//
// All this is very similar to what our boot loader does, except the boot
// loader also needs to read the code from disk.  Take a look at
// boot/main.c to get ideas.
//
// Finally, this function maps one page for the program's initial stack.
//
// load_icode panics if it encounters problems.
//  - How might load_icode fail?  What might be wrong with the given input?
//
static void
load_icode(struct Env *e, uint8_t *binary, size_t size)
{
	// Hints: 
	//  Load each program segment into virtual memory
	//  at the address specified in the ELF section header.
	//  You should only load segments with ph->p_type == ELF_PROG_LOAD.
	//  Each segment's virtual address can be found in ph->p_va
	//  and its size in memory can be found in ph->p_memsz.
	//  The ph->p_filesz bytes from the ELF binary, starting at
	//  'binary + ph->p_offset', should be copied to virtual address
	//  ph->p_va.  Any remaining memory bytes should be cleared to zero.
	//  (The ELF header should have ph->p_filesz <= ph->p_memsz.)
	//  Use functions from the previous lab to allocate and map pages.
	//
	//  All page protection bits should be user read/write for now.
	//  ELF segments are not necessarily page-aligned, but you can
	//  assume for this function that no two segments will touch
	//  the same virtual page.
	//
	//  You may find a function like segment_alloc useful.
	//
	//  Loading the segments is much simpler if you can move data
	//  directly into the virtual addresses stored in the ELF binary.
	//  So which page directory should be in force during
	//  this function?
	//
	// Hint:
	//  You must also do something with the program's entry point,
	//  to make sure that the environment starts executing there.
	//  What?  (See env_run() and env_pop_tf() below.)

	// LAB 3: Your code here.

	// Now map one page for the program's initial stack
	// at virtual address USTACKTOP - PGSIZE.

	// LAB 3: Your code here.
    struct Elf *env_elf = (struct Elf*)binary;//turn the binary to Elf
    struct Proghdr *ph, *eph;
    if(env_elf->e_magic != ELF_MAGIC){
        panic("load_icode: this is not a elf file\n");
    }
    ph = (struct Proghdr*)((uint8_t *)env_elf + env_elf->e_phoff);//
    eph = ph + env_elf->e_phnum;

    lcr3(e->env_cr3);
    for(;ph<eph;ph++){
        if(ph->p_type == ELF_PROG_LOAD){// must elf_prog_load
            segment_alloc(e, (void *)ph->p_va, ph->p_memsz);//get the vm for e
            memset((void *)ph->p_va, 0, ph->p_memsz);//reset it clearly
            memmove((void *)ph->p_va, binary+ph->p_offset, ph->p_filesz);//copy to it
        }
    }

    lcr3(boot_cr3);

    e->env_tf.tf_eip = env_elf->e_entry;
 /*   struct Page *pg;
    if(page_alloc(&pg)!=0){
        cprintf("page alloc failed\n");
        return ;
    }
    page_insert(e->env_pgdir, pg, (void *)(USTACKTOP - PGSIZE), PTE_U|PTE_W);
*/
    segment_alloc(e, (void *)(USTACKTOP - PGSIZE), PGSIZE);
    //lcr3(boot_cr3);
    //can we just use segment_alloc replace the paga_alloc?
}
Пример #5
0
//
// Set up the initial program binary, stack, and processor flags
// for a user process.
// This function is ONLY called during kernel initialization,
// before running the first user-mode environment.
//
// This function loads all loadable segments from the ELF binary image
// into the environment's user memory, starting at the appropriate
// virtual addresses indicated in the ELF program header.
// At the same time it clears to zero any portions of these segments
// that are marked in the program header as being mapped
// but not actually present in the ELF file - i.e., the program's bss section.
//
// All this is very similar to what our boot loader does, except the boot
// loader also needs to read the code from disk.  Take a look at
// boot/main.c to get ideas.
//
// Finally, this function maps one page for the program's initial stack.
//
// load_icode panics if it encounters problems.
//  - How might load_icode fail?  What might be wrong with the given input?
//
static void
load_icode(struct Env *e, uint8_t *binary, size_t size)
{
	// Hints: 
	//  Load each program segment into virtual memory
	//  at the address specified in the ELF section header.
	//  You should only load segments with ph->p_type == ELF_PROG_LOAD.
	//  Each segment's virtual address can be found in ph->p_va
	//  and its size in memory can be found in ph->p_memsz.
	//  The ph->p_filesz bytes from the ELF binary, starting at
	//  'binary + ph->p_offset', should be copied to virtual address
	//  ph->p_va.  Any remaining memory bytes should be cleared to zero.
	//  (The ELF header should have ph->p_filesz <= ph->p_memsz.)
	//  Use functions from the previous lab to allocate and map pages.
	//
	//  All page protection bits should be user read/write for now.
	//  ELF segments are not necessarily page-aligned, but you can
	//  assume for this function that no two segments will touch
	//  the same virtual page.
	//
	//  You may find a function like segment_alloc useful.
	//
	//  Loading the segments is much simpler if you can move data
	//  directly into the virtual addresses stored in the ELF binary.
	//  So which page directory should be in force during
	//  this function?
	//
	// Hint:
	//  You must also do something with the program's entry point,
	//  to make sure that the environment starts executing there.
	//  What?  (See env_run() and env_pop_tf() below.)

	// LAB 3: Your code here.
	struct Proghdr *ph, *eph;
	struct Elf *elfhdr = (struct Elf *)binary;
	struct Page *page;
	int copy_size, copy_count;
	uintptr_t page_offset; 
	void *copy_to, *copy_from;

	// is this a valid ELF?
	if (elfhdr->e_magic != ELF_MAGIC)
		panic("Bad ELF Format in kern/env.c/load_icode()!\n");

	// load each program segment (ignores ph flags)
	ph = (struct Proghdr *) ((uint8_t *) elfhdr + elfhdr->e_phoff);
	eph = ph + elfhdr->e_phnum;
	for (; ph < eph; ph ++) {
		if (ph->p_type == ELF_PROG_LOAD) {
			// allocate memory in the Env's page table
			segment_alloc(e, (void *)ph->p_va, ph->p_memsz);

			// copy binary+ph->offset, length: ph->p_filesz to ph->p_va in the Env's page table
			void *copy_ptr = binary + ph->p_offset;

			for (copy_count = 0; copy_count < ph->p_filesz; ) {
				if (NULL == (page = page_lookup(e->env_pgdir, (void *)(ph->p_va + copy_count), NULL))) {
					panic("Page cannot be find\n");
				}

				// calculate copy_size and copy_to according to start add.
				// the first time the p_va maybe not at the beginning of a page
				// if p_va+copy_count is at the beginning of a page, copy_size is PGSIZE
				page_offset = PGOFF(ph->p_va + copy_count);
				copy_size = PGSIZE - page_offset;

				// fix copy_size and copy_to according to end add.
				// if the end is within this page
				if (copy_count + copy_size > ph->p_filesz) {
					copy_size = ph->p_filesz - copy_count;
				}

				copy_from = copy_ptr + copy_count;
				copy_to = page2kva(page) + page_offset;

				memmove(copy_to, copy_from, copy_size);

				copy_count += copy_size;
			}

			if (copy_count != ph->p_filesz) 
				panic("Unequal of copy_count and ph->p_filesz\n");
			// set p_filesz to p_memsz zero
			for ( ; copy_count < ph->p_memsz; ) {
				if (NULL == (page = page_lookup(e->env_pgdir, (void *)(ph->p_va + copy_count), NULL))) {
					panic("Page cannot be find\n");
				}

				// calculate copy_size and copy_to according to start add.
				// the first time the p_va maybe not at the beginning of a page
				// if p_va+copy_count is at the beginning of a page, copy_size is PGSIZE
				page_offset = PGOFF(ph->p_va + copy_count);
				copy_size = PGSIZE - page_offset;

				// fix copy_size and copy_to according to end add.
				// if the end is within this page
				if (copy_count + copy_size > ph->p_memsz) {
					copy_size = ph->p_memsz - copy_count;
				}

				copy_to = page2kva(page) + page_offset;

				memset(copy_to, 0, copy_size);

				copy_count += copy_size;
			}

			if (copy_count != ph->p_memsz) 
				panic("Unequal of copy_count and ph->p_filesz\n");
		}
	}

	// Now map one page for the program's initial stack
	// at virtual address USTACKTOP - PGSIZE.

	// LAB 3: Your code here.
	segment_alloc(e, (uintptr_t *)(USTACKTOP - PGSIZE), PGSIZE);

	// Set the program's entry point e->env_tf.tf_eip
	e->env_tf.tf_eip = elfhdr->e_entry;
}
Пример #6
0
int compile_varspace( VARSPACE * n, segment * data, int additive, int copies, int padding, VARSPACE ** collision, int alignment, int duplicateignore )
{
    int i, j, total_count, last_count = 0 ;
    int base_offset = data->current ;
    int total_length ;
    int size, count ;
    int code ;
    expresion_result res ;
    VARIABLE * var ;
    int unsigned_prefix = 0;
    int signed_prefix = 0;

    BASETYPE basetype = TYPE_UNDEFINED ;
    TYPEDEF type, typeaux;
    segment * segm = NULL ;
    PROCDEF * proc = NULL;

    /* Backup vars */
    BASETYPE basetypeb = TYPE_UNDEFINED ;
    TYPEDEF typeb;
    segment * segmb = NULL ;

    /* Initialize some stuffs */

    type = typedef_new( TYPE_UNDEFINED ) ;
    typeb = typedef_new( TYPE_UNDEFINED ) ;

    for ( ;; )
    {
        if ( n->reserved == n->count ) varspace_alloc( n, 16 ) ;

        if ( alignment && ( n->size % alignment ) > 0 )
        {
            int extra = alignment - ( n->size % alignment );
            if ( n->reserved <= n->count + extra )
            {
                varspace_alloc( n, extra + 16 );
            }
            if ( data->reserved <= data->current + extra )
            {
                segment_alloc( data, extra + 16 );
            }
            n->size += extra;
            data->current += extra;
        }

        token_next() ;

        /* Se salta comas y puntos y coma */

        if ( token.type == NOTOKEN ) break ;

        if ( token.type != IDENTIFIER ) compile_error( MSG_INCOMP_TYPE ) ;

        if ( token.code == identifier_comma )
        {
            basetype = basetypeb ;
            type = typeb ;

            segm = segmb ;

            continue ;
        }
        else if ( token.code == identifier_semicolon )
        {
            basetype = TYPE_UNDEFINED ;
            set_type( &type, TYPE_UNDEFINED ) ;

            basetypeb = basetype ;
            typeb = type ;

            segm = NULL ;
            proc = NULL ;

            continue ;
        }
        else if ( token.code == identifier_end )
        {
            break ;
        }

        /* "Unsigned" */

        if ( token.code == identifier_unsigned )
        {
            unsigned_prefix = 1;
            token_next();
        }
        else if ( token.code == identifier_signed )
        {
            signed_prefix = 1;
            token_next();
        }

        /* Tipos de datos básicos */

        if ( token.code == identifier_dword )
        {
            basetype = signed_prefix ? TYPE_INT : TYPE_DWORD ;
            signed_prefix = unsigned_prefix = 0;
            token_next() ;
        }
        else if ( token.code == identifier_word )
        {
            basetype = signed_prefix ? TYPE_SHORT : TYPE_WORD ;
            signed_prefix = unsigned_prefix = 0;
            token_next() ;
        }
        else if ( token.code == identifier_byte )
        {
            basetype = signed_prefix ? TYPE_SBYTE : TYPE_BYTE ;
            signed_prefix = unsigned_prefix = 0;
            token_next() ;
        }
        else if ( token.code == identifier_int )
        {
            basetype = unsigned_prefix ? TYPE_DWORD : TYPE_INT;
            signed_prefix = unsigned_prefix = 0;
            token_next() ;
        }
        else if ( token.code == identifier_short )
        {
            basetype = unsigned_prefix ? TYPE_WORD : TYPE_SHORT;
            signed_prefix = unsigned_prefix = 0;
            token_next() ;
        }
        else if ( token.code == identifier_char )
        {
            basetype = TYPE_CHAR ;
            token_next() ;
        }
        else if ( token.code == identifier_float )
        {
            basetype = TYPE_FLOAT ;
            token_next() ;
        }
        else if ( token.code == identifier_string )
        {
            basetype = TYPE_STRING ;
            token_next() ;
        }
        else
        {
            if ( !proc && ( proc = procdef_search( token.code ) ) )    /* Variables tipo proceso, Splinter */
            {
                basetype = TYPE_INT ;
                token_next();
            }
            else
            {
                if (
                    token.type == IDENTIFIER &&
                    token.code >= reserved_words &&
                    !segment_by_name( token.code ) )
                {
                    int code = token.code;
                    token_next();
                    if ( token.type == IDENTIFIER && token.code >= reserved_words )
                    {
                        proc = procdef_new( procdef_getid(), code );
                        basetype = TYPE_INT ;
                    }
                    else
                    {
                        token_back();
                    }
                }
            }
        }

        if ( signed_prefix || unsigned_prefix ) compile_error( MSG_INVALID_TYPE );
        if ( basetype != TYPE_STRUCT ) type = typedef_new( basetype ) ;
        if ( basetype == TYPE_UNDEFINED ) type = typedef_new( TYPE_INT ) ;

        /* Tipos de datos definidos por el usuario */
        if ( basetype != TYPE_STRUCT && ( segm = segment_by_name( token.code ) ) )
        {
            basetype = TYPE_STRUCT ;
            type = * typedef_by_name( token.code ) ;
            token_next() ;
        }

        if ( token.type == IDENTIFIER && token.code == identifier_struct )
        {
            type.chunk[0].type = TYPE_STRUCT ;
            type.chunk[0].count = 1 ;
            type.depth = 1 ;
            token_next() ;
            segm = 0 ;
        }

        basetypeb = basetype ;
        typeb = type ;
        segmb = segm ;

        /* Tipos de datos derivados */
        while ( token.type == IDENTIFIER && ( token.code == identifier_pointer || token.code == identifier_multiply ) )
        {
            type = typedef_enlarge( type ) ;
            type.chunk[0].type = TYPE_POINTER ;
            basetype = TYPE_POINTER ;
            segm = NULL ;
            token_next() ;
        }

        /* Nombre del dato */

        if ( token.type != IDENTIFIER ) compile_error( MSG_IDENTIFIER_EXP ) ;

        if ( token.code < reserved_words )
        {
            if ( proc ) compile_error( MSG_VARIABLE_ERROR );
            token_back() ;
            break ;
        }

        if (( var = varspace_search( n, token.code ) ) )
        {
            if ( duplicateignore )
            {
                int skip_all_until_semicolon = 0;
                int skip_equal = 0;

                if ( debug ) compile_warning( 0, MSG_VARIABLE_REDECLARE ) ;

                for ( ;; )
                {
                    token_next() ;

                    /* Se salta todo hasta el puntos y coma o en el end o la coma si no hay asignacion */

                    if ( token.type == NOTOKEN ) break ;

                    if ( token.type == IDENTIFIER )
                    {
                        if ( !skip_equal && token.code == identifier_equal )
                        {
                            skip_all_until_semicolon = 1;
                            continue;
                        }

                        if ( !skip_all_until_semicolon && token.code == identifier_comma ) break;
                        if ( token.code == identifier_semicolon ) break ;
                        if ( token.code == identifier_end ) break ;
                    }
                }
                token_back();
                continue;
            }
            else
                compile_error( MSG_VARIABLE_REDECLARE ) ;
        }

        /* (2006/11/19 19:34 GMT-03:00, Splinter - [email protected]) */
        if ( collision )
            for ( i = 0; collision[i];i++ )
                if ( varspace_search( collision[i], token.code ) ) compile_error( MSG_VARIABLE_REDECLARE ) ;
        /* (2006/11/19 19:34 GMT-03:00, Splinter - [email protected]) */

        if ( constants_search( token.code ) ) compile_error( MSG_CONSTANT_REDECLARED_AS_VARIABLE ) ;

        code = token.code ;
        n->vars[n->count].code = token.code ;
        n->vars[n->count].offset = data->current;

        /* Non-additive STRUCT; use zero-based member offsets */

        if ( !additive ) n->vars[n->count].offset -= base_offset;

        token_next() ;

        /* Compila una estructura no predefinida */

        if ( !segm && typedef_is_struct( type ) )
        {
            VARSPACE * members ;

            type.chunk[0].count = 1 ;
            count = 1 ;
            while ( token.type == IDENTIFIER && token.code == identifier_leftb )
            {
                res = compile_expresion( 1, 0, 0, TYPE_INT ) ;
                if ( !typedef_is_integer( res.type ) ) compile_error( MSG_INTEGER_REQUIRED ) ;
                count *= res.value + 1 ;
                type = typedef_enlarge( type ) ;
                type.chunk[0].type  = TYPE_ARRAY ;
                type.chunk[0].count = res.value + 1 ;
                token_next() ;
                if ( token.type != IDENTIFIER || token.code != identifier_rightb ) compile_error( MSG_EXPECTED, "]" ) ;
                token_next() ;
            }
            token_back() ;

            /* Da la vuelta a los índices [10][5] -> [5][10] */

            for ( i = 0 ; i < type.depth ; i++ ) if ( type.chunk[i].type != TYPE_ARRAY ) break ;
            i--;
            for ( j = 0 ; j <= i ; j++ ) typeaux.chunk[ j ] = type.chunk[ i - j ];
            for ( j = 0 ; j <= i ; j++ ) type.chunk[ j ]    = typeaux.chunk[ j ];

            members = ( VARSPACE * )calloc( 1, sizeof( VARSPACE ) ) ;
            if ( !members )
            {
                fprintf( stdout, "compile_varspace: out of memory\n" ) ;
                exit( 1 ) ;
            }
            varspace_init( members ) ;

            size = compile_varspace( members, data, 0, count, 0, NULL, 0, duplicateignore ) ;

            type.varspace = members ;

            token_next() ;
            if ( token.type == IDENTIFIER && token.code == identifier_equal )
            {
                i = data->current ;
                data->current = n->vars[n->count].offset ;
                compile_struct_data( members, data, count, 0 );
                data->current = i ;
            }
            else
            {
                token_back() ;
            }

            for ( i = 0 ; i < members->stringvar_count ; i++ )
                varspace_varstring( n, members->stringvars[i] ) ;

            n->size += typedef_size( type ) ;
            n->vars[n->count].type = type ;
            n->count++ ;

            continue ;  /* No ; */

        }
        else if ( token.type == IDENTIFIER && token.code == identifier_leftb ) /* Compila un array */
        {
            total_count = 1 ;

            while ( token.type == IDENTIFIER && token.code == identifier_leftb )
            {
                if ( type.depth == MAX_TYPECHUNKS ) compile_error( MSG_TOO_MANY_AL ) ;

                type = typedef_enlarge( type ) ;
                type.chunk[0].type = TYPE_ARRAY ;

                token_next() ;
                if ( token.type == IDENTIFIER && token.code == identifier_rightb )
                {
                    type.chunk[0].count = 0 ;
                    if ( total_count != 1 ) compile_error( MSG_VTA ) ;
                    total_count = 0 ;
                    last_count = 0 ;
                }
                else
                {
                    token_back() ;
                    res = compile_expresion( 1, 0, 0, TYPE_DWORD ) ;
                    if ( !total_count ) compile_error( MSG_VTA ) ;
                    total_count *= res.value + 1 ;
                    last_count = res.value + 1 ;
                    type.chunk[0].count = res.value + 1 ;
                    token_next() ;
                    if ( token.type != IDENTIFIER || token.code != identifier_rightb ) compile_error( MSG_EXPECTED, "]" ) ;
                }

                token_next() ;
            }

            /* Da la vuelta a los índices [10][5] -> [5][10] */

            for ( i = 0 ; i < type.depth ; i++ ) if ( type.chunk[i].type != TYPE_ARRAY ) break ;
            i--;
            for ( j = 0 ; j <= i ; j++ ) typeaux.chunk[ j ] = type.chunk[ i - j ];
            for ( j = 0 ; j <= i ; j++ ) type.chunk[ j ]    = typeaux.chunk[ j ];

            if ( segm && token.type == IDENTIFIER && token.code == identifier_equal )
            {
                for ( i = 0 ; i < total_count ; i++ ) segment_add_from( data, segm ) ;
                i = data->current ;
                data->current = n->vars[n->count].offset ;
                compile_struct_data( type.varspace, data, typedef_count( type ), 0 );

                if ( !type.chunk[0].count )
                    type.chunk[0].count = ( data->current - i ) / typedef_size( typeb );
                else
                    data->current = i; /* Solo si ya habia sido alocada */

            }
            else if ( token.type == IDENTIFIER && token.code == identifier_equal )
            {
                /* if (basetype == TYPE_UNDEFINED) basetype = TYPE_INT; */
                i = compile_array_data( n, data, total_count, last_count, &basetype ) ;
                assert( basetype != TYPE_UNDEFINED ) ;
                set_type( &type, basetype ) ;
                if ( total_count == 0 )
                {
                    type.chunk[0].count = i;
                }
                else if ( i < total_count )
                {
                    for ( ; i < total_count; i++ )
                    {
                        if ( basetype == TYPE_STRING ) varspace_varstring( n, data->current ) ;
                        segment_add_as( data, 0, basetype ) ;
                    }
                }
            }
            else if ( segm )
            {
                int string_offset = 0, j;

                if ( total_count == 0 ) compile_error( MSG_EXPECTED, "=" ) ;

                for ( i = 0; i < total_count; i++ )
                {
                    segment_add_from( data, segm ) ;
                    for ( j = 0; j < type.varspace->stringvar_count; j++ )
                        varspace_varstring( n, type.varspace->stringvars[j] + string_offset );
                    string_offset += type.varspace->size;
                }
                token_back() ;
            }
            else
            {
                if ( basetype == TYPE_UNDEFINED )
                {
                    basetype = TYPE_INT;
                    set_type( &type, basetype ) ;
                }

                if ( type.chunk[0].count == 0 ) compile_error( MSG_EXPECTED, "=" ) ;

                for ( i = 0; i < total_count; i++ )
                {
                    if ( basetype == TYPE_STRING ) varspace_varstring( n, data->current ) ;
                    segment_add_as( data, 0, basetype ) ;
                }
                token_back() ;
            }
        }
        else if ( segm && token.type == IDENTIFIER && token.code == identifier_equal ) /* Compila una asignación de valores por defecto */
        {
            segment_add_from( data, segm ) ;
            i = data->current ;
            data->current = n->vars[n->count].offset ;
            if ( !additive ) data->current += base_offset;
            compile_struct_data( type.varspace, data, 1, 0 );
            data->current = i ;

        }
        else if ( token.type == IDENTIFIER && token.code == identifier_equal )
        {
            res = compile_expresion( 1, 0, 0, basetype ) ;

            if ( basetype == TYPE_UNDEFINED )
            {
                basetype = typedef_base( res.type ) ;
                if ( basetype == TYPE_UNDEFINED ) compile_error( MSG_INCOMP_TYPE ) ;
                set_type( &type, basetype ) ;
            }

            if ( basetype == TYPE_FLOAT )
            {
                segment_add_as( data, *( int * )&res.fvalue, basetype ) ;
            }
            else
            {
                if ( basetype == TYPE_STRING ) varspace_varstring( n, data->current ) ;
                segment_add_as( data, res.value, basetype ) ;
            }

        }
        else if ( !segm ) /* Asigna valores por defecto (0) */
        {
            if ( basetype == TYPE_UNDEFINED )
            {
                basetype = TYPE_INT;
                set_type( &type, basetype ) ;
            }

            if ( basetype == TYPE_STRING ) varspace_varstring( n, data->current ) ;
            segment_add_as( data, 0, basetype ) ;
            token_back() ;

        }
        else
        {
            if ( typedef_is_struct( type ) )
                for ( i = 0 ; i < type.varspace->stringvar_count ; i++ )
                    varspace_varstring( n, type.varspace->stringvars[i] + n->size );
            segment_add_from( data, segm ) ;
            token_back() ;
        }

        n->size += typedef_size( type ) ;
        n->vars[n->count].type = type ;

        /* Variables tipo proceso, asigno varspace al tipo. Splinter */
        if ( proc ) n->vars[n->count].type.varspace = proc->pubvars;

        n->count++ ;

        token_next() ;

        if ( token.type == IDENTIFIER && token.code == identifier_comma )
        {
            token_back() ;
            continue ;
        }

        if ( token.type == IDENTIFIER && token.code == identifier_semicolon )
        {
            token_back() ;
            continue ;
        }

        compile_error( MSG_EXPECTED, ";" ) ;
        token_back() ;
        break ;
    }

    if ( padding && ( data->current % padding ) > 0 )
    {
        padding -= data->current % padding;
        data->current += padding;
        n->size += padding;

        if ( data->reserved <= data->current )
            segment_alloc( data, data->reserved - data->current + 32 );
    }

    n->last_offset = data->current ;
    total_length = data->current - base_offset ;

    /* n->size *= copies ; */
    while ( copies-- > 1 )
    {
        int i ;

        for ( i = 0 ; i < n->stringvar_count ; i++ )
        {
            if ( n->stringvars[i] >= base_offset && n->stringvars[i] < base_offset + total_length )
            {
                varspace_varstring( n, n->stringvars[i] - base_offset + data->current ) ;
            }
        }

        segment_copy( data, base_offset, total_length ) ;
        base_offset += total_length ;
    }

    return total_length ;
}
Пример #7
0
//
// Set up the initial program binary, stack, and processor flags
// for a user process.
// This function is ONLY called during kernel initialization,
// before running the first user-mode environment.
//
// This function loads all loadable segments from the ELF binary image
// into the environment's user memory, starting at the appropriate
// virtual addresses indicated in the ELF program header.
// At the same time it clears to zero any portions of these segments
// that are marked in the program header as being mapped
// but not actually present in the ELF file - i.e., the program's bss section.
//
// All this is very similar to what our boot loader does, except the boot
// loader also needs to read the code from disk.  Take a look at
// boot/main.c to get ideas.
//
// Finally, this function maps one page for the program's initial stack.
//
// load_icode panics if it encounters problems.
//  - How might load_icode fail?  What might be wrong with the given input?
//
static void
load_icode(struct Env *e, uint8_t *binary, size_t size)
{
	// Hints: 
	//  Load each program segment into virtual memory
	//  at the address specified in the ELF section header.
	//  You should only load segments with ph->p_type == ELF_PROG_LOAD.
	//  Each segment's virtual address can be found in ph->p_va
	//  and its size in memory can be found in ph->p_memsz.
	//  The ph->p_filesz bytes from the ELF binary, starting at
	//  'binary + ph->p_offset', should be copied to virtual address
	//  ph->p_va.  Any remaining memory bytes should be cleared to zero.
	//  (The ELF header should have ph->p_filesz <= ph->p_memsz.)
	//  Use functions from the previous lab to allocate and map pages.
	//
	//  All page protection bits should be user read/write for now.
	//  ELF segments are not necessarily page-aligned, but you can
	//  assume for this function that no two segments will touch
	//  the same virtual page.
	//
	//  You may find a function like segment_alloc useful.
	//
	//  Loading the segments is much simpler if you can move data
	//  directly into the virtual addresses stored in the ELF binary.
	//  So which page directory should be in force during
	//  this function?
	//
	// Hint:
	//  You must also do something with the program's entry point,
	//  to make sure that the environment starts executing there.
	//  What?  (See env_run() and env_pop_tf() below.)

	// LAB 3: Your code here.
	struct Elf *env_elf = (struct Elf *)binary;
	struct Proghdr *ph, *eph;
	struct Page *pg;
	uint32_t old_cr3;

	// store the current cr3 and 
	// switch cr3 to the pgdir of the env
	old_cr3 = rcr3();
	lcr3(PADDR(e->env_pgdir));
	if(env_elf->e_magic != ELF_MAGIC){
		panic("elf header's magic is not correct\n");
	}
	ph = (struct Proghdr *)((uint8_t *)env_elf + env_elf->e_phoff);
	eph = ph + env_elf->e_phnum;
	
	for( ; ph < eph; ph++){
		if(ph->p_type == ELF_PROG_LOAD){
			segment_alloc(e, (void *)ph->p_va, ph->p_memsz);
			// cprintf("load_icode segment_alloc succeeded!\n");
			memset((void *)ph->p_va, 0, ph->p_memsz);
			memmove((void*)ph->p_va, (void *)((uint32_t) env_elf + ph->p_offset), ph->p_filesz);
		}
	}
	// cprintf("load_icode while loop succeeded!\n");
	e->env_tf.tf_eip = env_elf->e_entry;
	// cprintf("load_icode program entry point: %x\n", elf->e_entry);

	// Now map one page for the program's initial stack
	// at virtual address USTACKTOP - PGSIZE.

	// LAB 3: Your code here.
	if(page_alloc(&pg) != 0){
		panic("load_icode page_alloc fail!!!\n");
	}
	if(page_insert(e->env_pgdir, pg, (void *)(USTACKTOP - PGSIZE), PTE_U|PTE_W) != 0){
		panic("load_icode page_insert fail!!!\n");
	}

	lcr3(old_cr3);
	//cprintf("load_icode success!\n");
}
Пример #8
0
//
// Set up the initial program binary, stack, and processor flags
// for a user process.
// This function is ONLY called during kernel initialization,
// before running the first user-mode environment.
//
// This function loads all loadable segments from the ELF binary image
// into the environment's user memory, starting at the appropriate
// virtual addresses indicated in the ELF program header.
// At the same time it clears to zero any portions of these segments
// that are marked in the program header as being mapped
// but not actually present in the ELF file - i.e., the program's bss section.
//
// All this is very similar to what our boot loader does, except the boot
// loader also needs to read the code from disk.  Take a look at
// boot/main.c to get ideas.
//
// Finally, this function maps one page for the program's initial stack.
//
// load_icode panics if it encounters problems.
//  - How might load_icode fail?  What might be wrong with the given input?
//  
static void
load_icode(struct Env *e, uint8_t *binary, size_t size)
{
	// Hints: 
	//  Load each program segment into virtual memory
	//  at the address specified in the ELF section header.
	//  You should only load segments with ph->p_type == ELF_PROG_LOAD.
	//  Each segment's virtual address can be found in ph->p_va
	//  and its size in memory can be found in ph->p_memsz.
	//  The ph->p_filesz bytes from the ELF binary, starting at
	//  'binary + ph->p_offset', should be copied to virtual address
	//  ph->p_va.  Any remaining memory bytes should be cleared to zero.
	//  (The ELF header should have ph->p_filesz <= ph->p_memsz.)               /* p_filesz <= ph->memsz ,sunus*/
	//  Use functions from the previous lab to allocate and map pages.
	//
	//  All page protection bits should be user read/write for now.
	//  ELF segments are not necessarily page-aligned, but you can
	//  assume for this function that no two segments will touch
	//  the same virtual page.
	//
	//  You may find a function like segment_alloc useful.
	//
	//  Loading the segments is much simpler if you can move data
	//  directly into the virtual addresses stored in the ELF binary.
	//  So which page directory should be in force during
	//  this function?
	//
	//  You must also do something with the program's entry point,    /* TO BE CODED!*/
	//  to make sure that the environment starts executing there.	  /* DEC 10,2010 */
	//  What?  (See env_run() and env_pop_tf() below.)		  /* sunus */

	// LAB 3: Your code here.

    	//DEC 09,2010 sunus
    
    	struct Proghdr *ph,*eph;
	struct Elf *env_elf;
	struct Page *pstack;
	env_elf = (struct Elf *)binary;
	assert(env_elf->e_magic == ELF_MAGIC);
	ph = (struct Proghdr *)((uint8_t *)binary + env_elf->e_phoff);
	eph = ph +  env_elf->e_phnum;
	for( ; ph < eph ; ph++)
	  {
	    if(ph->p_type == ELF_PROG_LOAD)
	      {
		segment_alloc(e, (void *)ph->p_va,ph->p_memsz);
		memmove((void *)ph->p_va, (void *)(binary + ph->p_offset), ph->p_filesz);
		memset(((void *)ph->p_va + ph->p_filesz), 0, (ph->p_memsz - ph->p_filesz)); // .bss matters
	      }
	  }

	// Now map one page for the program's initial stack
	// at virtual address USTACKTOP - PGSIZE.


	// LAB 3: Your code here.
	//DEC 10,2010,sunus
	assert(page_alloc(&pstack) == 0);
	assert(page_insert(e->env_pgdir, pstack,(void *)(USTACKTOP - PGSIZE), PTE_U|PTE_W) == 0);
	return ;
}
Пример #9
0
//
// Set up the initial program binary, stack, and processor flags
// for a user process.
// This function is ONLY called during kernel initialization,
// before running the first user-mode environment.
//
// This function loads all loadable segments from the ELF binary image
// into the environment's user memory, starting at the appropriate
// virtual addresses indicated in the ELF program header.
// At the same time it clears to zero any portions of these segments
// that are marked in the program header as being mapped
// but not actually present in the ELF file - i.e., the program's bss section.
//
// All this is very similar to what our boot loader does, except the boot
// loader also needs to read the code from disk.  Take a look at
// boot/main.c to get ideas.
//
// Finally, this function maps one page for the program's initial stack.
//
// load_icode panics if it encounters problems.
//  - How might load_icode fail?  What might be wrong with the given input?
//
static void
load_icode(struct Env *e, uint8_t *binary, size_t size)
{
    struct Elf *elf = (struct Elf *)binary;
    struct Proghdr *ph, *eph;
	// Hints: 
	//  Load each program segment into virtual memory
	//  at the address specified in the ELF section header.
	//  You should only load segments with ph->p_type == ELF_PROG_LOAD.
	//  Each segment's virtual address can be found in ph->p_va
	//  and its size in memory can be found in ph->p_memsz.
	//  The ph->p_filesz bytes from the ELF binary, starting at
	//  'binary + ph->p_offset', should be copied to virtual address
	//  ph->p_va.  Any remaining memory bytes should be cleared to zero.
	//  (The ELF header should have ph->p_filesz <= ph->p_memsz.)
	//  Use functions from the previous lab to allocate and map pages.
	//
	//  All page protection bits should be user read/write for now.
	//  ELF segments are not necessarily page-aligned, but you can
	//  assume for this function that no two segments will touch
	//  the same virtual page.
	//
	//  You may find a function like segment_alloc useful.
	//
	//  Loading the segments is much simpler if you can move data
	//  directly into the virtual addresses stored in the ELF binary.
	//  So which page directory should be in force during
	//  this function?
	//
	//  You must also do something with the program's entry point,
	//  to make sure that the environment starts executing there.
	//  What?  (See env_run() and env_pop_tf() below.)

	// LAB 3: Your code here.

	// Now map one page for the program's initial stack
	// at virtual address USTACKTOP - PGSIZE.

	// LAB 3: Your code here.
    if (elf && elf->e_magic == ELF_MAGIC) {
    //  Load each program segment into virtual memory
	//  at the address specified in the ELF section header.
	//  You should only load segments with ph->p_type == ELF_PROG_LOAD.
	//  Each segment's virtual address can be found in ph->p_va
	//  and its size in memory can be found in ph->p_memsz.
	//  The ph->p_filesz bytes from the ELF binary, starting at
	//  'binary + ph->p_offset', should be copied to virtual address
	//  ph->p_va.  Any remaining memory bytes should be cleared to zero.
	//  (The ELF header should have ph->p_filesz <= ph->p_memsz.)
	//  Use functions from the previous lab to allocate and map pages.
        ph  = (struct Proghdr *)((uint8_t *)elf + elf->e_phoff);
        eph = ph + elf->e_phnum;
        for(;ph < eph; ph++) {
            if (ph->p_type == ELF_PROG_LOAD) {
                segment_alloc(e, (void *)ph->p_va, ph->p_memsz);
                lcr3(PADDR((uint32_t)e->env_pgdir));
                memmove((void *)ph->p_va, (void *)((uint8_t *)elf + ph->p_offset), ph->p_filesz);
                if (ph->p_filesz < ph->p_memsz) {
                    memset((void *)(ph->p_va + ph->p_filesz), 0, ph->p_memsz-ph->p_filesz);
                }
                lcr3(boot_cr3);
            }
        }
        segment_alloc(e, (void *)(USTACKTOP-PGSIZE), PGSIZE);
        e->env_tf.tf_eip    = elf->e_entry;
        e->env_tf.tf_esp    = USTACKTOP;
    } else {
        panic("Invalid Binary");
    }
}
Пример #10
0
Файл: env.c Проект: gzs715/JOS
//
// Set up the initial program binary, stack, and processor flags
// for a user process.
// This function is ONLY called during kernel initialization,
// before running the first user-mode environment.
//
// This function loads all loadable segments from the ELF binary image
// into the environment's user memory, starting at the appropriate
// virtual addresses indicated in the ELF program header.
// At the same time it clears to zero any portions of these segments
// that are marked in the program header as being mapped
// but not actually present in the ELF file - i.e., the program's bss section.
//
// All this is very similar to what our boot loader does, except the boot
// loader also needs to read the code from disk.  Take a look at
// boot/main.c to get ideas.
//
// Finally, this function maps one page for the program's initial stack.
//
// load_icode panics if it encounters problems.
//  - How might load_icode fail?  What might be wrong with the given input?
//
static void
load_icode(struct Env *e, uint8_t *binary, size_t size)
{
	// Hints: 
	//  Load each program segment into virtual memory
	//  at the address specified in the ELF section header.
	//  You should only load segments with ph->p_type == ELF_PROG_LOAD.
	//  Each segment's virtual address can be found in ph->p_va
	//  and its size in memory can be found in ph->p_memsz.
	//  The ph->p_filesz bytes from the ELF binary, starting at
	//  'binary + ph->p_offset', should be copied to virtual address
	//  ph->p_va.  Any remaining memory bytes should be cleared to zero.
	//  (The ELF header should have ph->p_filesz <= ph->p_memsz.)
	//  Use functions from the previous lab to allocate and map pages.
	//
	//  All page protection bits should be user read/write for now.
	//  ELF segments are not necessarily page-aligned, but you can
	//  assume for this function that no two segments will touch
	//  the same virtual page.
	//
	//  You may find a function like segment_alloc useful.
	//
	//  Loading the segments is much simpler if you can move data
	//  directly into the virtual addresses stored in the ELF binary.
	//  So which page directory should be in force during
	//  this function?
	//
	// Hint:
	//  You must also do something with the program's entry point,
	//  to make sure that the environment starts executing there.
	//  What?  (See env_run() and env_pop_tf() below.)

	// LAB 3: Your code here.
	//cprintf("Begin to load icode\n");
	struct Proghdr *ph, *eph;
	ph = (struct Proghdr *) (binary + ((struct Elf *)binary)->e_phoff);
	eph = ph + ((struct Elf *)binary)->e_phnum;
	lcr3(e->env_cr3);
	while (ph < eph)
	{
		if(ph->p_type == ELF_PROG_LOAD)
		{
			segment_alloc(e, (void*)ph->p_va,ph->p_memsz);			
			memcpy((void *)ph->p_va, binary + ph->p_offset, ph->p_filesz);
			memset((void *)(ph->p_va + ph->p_filesz), 0x0, ph->p_memsz - ph->p_filesz);
		}
		ph++;
	}	
	//lcr3(boot_cr3);	
	//cprintf("segment copy success\n");

	// Now map one page for the program's initial stack
	// at virtual address USTACKTOP - PGSIZE.

	// LAB 3: Your code here.
	struct Page * user_stack; 
	if(page_alloc(&user_stack) == -E_NO_MEM)
		panic("No memory to alloc for user stack");
	page_insert(e->env_pgdir, user_stack, (void *)(USTACKTOP - PGSIZE),PTE_W|PTE_U|PTE_P);
	e->env_tf.tf_eip = ((struct Elf*)binary)->e_entry;
	
}
Пример #11
0
//
// Set up the initial program binary, stack, and processor flags
// for a user process.
//
// This function loads all loadable segments from the ELF binary image
// into the environment's user memory, starting at the appropriate
// virtual addresses indicated in the ELF program header.
// It also clears to zero any portions of these segments
// that are marked in the program header as being mapped
// but not actually present in the ELF file -- i.e., the program's bss section.
//
// Finally, this function maps one page for the program's initial stack.
//
// load_elf panics if it encounters problems.
//  - How might load_elf fail?  What might be wrong with the given input?
//
static void
load_elf(struct Env *e, uint8_t *binary, size_t size)
{
	struct Elf *elf = (struct Elf *) binary;
	// Load each program segment into environment 'e's virtual memory
	// at the address specified in the ELF section header.
	// Only load segments with ph->p_type == ELF_PROG_LOAD.
	// Each segment's virtual address can be found in ph->p_va
	// and its size in memory can be found in ph->p_memsz.
	// The ph->p_filesz bytes from the ELF binary, starting at
	// 'binary + ph->p_offset', should be copied to virtual address
	// ph->p_va.  Any remaining memory bytes should be cleared to zero.
	// (The ELF header should have ph->p_filesz <= ph->p_memsz.)
	// Use functions from the previous lab to allocate and map pages.
	//
	// All page protection bits should be user read/write for now.
	// ELF segments are not necessarily page-aligned, but you can
	// assume for this function that no two segments will touch
	// the same virtual page.
	//
	// You may find a function like segment_alloc useful.
	//
	// Loading the segments is much simpler if you can move data
	// directly into the virtual addresses stored in the ELF binary.
	// So which page directory should be in force during
	// this function?
	//
	// All this is very similar to what our boot loader does, except the
	// boot loader reads the code from disk and doesn't check whether
	// segments are loadable.  Take a look at boot/main.c to get ideas.
	//
	// You must also store the program's entry point somewhere,
	// to make sure that the environment starts executing at that point.
	// See env_run() and env_iret() below.
    

	// LAB 3: Your code here.
    lcr3(PADDR(e->env_pgdir));

    if (elf->e_magic != ELF_MAGIC)
        panic("Invalid Elf Magic");
    struct Proghdr *ph = (struct Proghdr *) ((uint8_t *) elf + elf->e_phoff);
    int ph_num = elf->e_phnum;

    // iterate over all program headers
    for (; --ph_num >= 0; ph++) 
        if (ph->p_type == ELF_PROG_LOAD)
        {
            segment_alloc(e, ph->p_va, ph->p_memsz);
            // copy data from binary to address space
            memmove((void *)ph->p_va, binary + ph->p_offset, ph->p_filesz);
        }

    // set entry point for new env
    e->env_tf.tf_eip = elf->e_entry;
    e->env_tf.tf_esp = USTACKTOP;
	// Now map one page for the program's initial stack
	// at virtual address USTACKTOP - PGSIZE.
	// (What should the permissions be?)
    struct Page *p;
    if ((p = page_alloc()) == NULL || page_insert(e->env_pgdir, p, USTACKTOP-PGSIZE, PTE_U|PTE_W|PTE_P))
        panic("segment_alloc: Can't allocate page");
    memset(page2kva(p), 0, PGSIZE);
}
Пример #12
0
//
// Set up the initial program binary, stack, and processor flags
// for a user process.
// This function is ONLY called during kernel initialization,
// before running the first user-mode environment.
//
// This function loads all loadable segments from the ELF binary image
// into the environment's user memory, starting at the appropriate
// virtual addresses indicated in the ELF program header.
// At the same time it clears to zero any portions of these segments
// that are marked in the program header as being mapped
// but not actually present in the ELF file - i.e., the program's bss section.
//
// All this is very similar to what our boot loader does, except the boot
// loader also needs to read the code from disk.  Take a look at
// boot/main.c to get ideas.
//
// Finally, this function maps one page for the program's initial stack.
//
// load_icode panics if it encounters problems.
//  - How might load_icode fail?  What might be wrong with the given input?
//
static void
load_icode(struct Env *e, uint8_t *binary, size_t size)
{
	// Hints: 
	//  Load each program segment into virtual memory
	//  at the address specified in the ELF section header.
	//  You should only load segments with ph->p_type == ELF_PROG_LOAD.
	//  Each segment's virtual address can be found in ph->p_va
	//  and its size in memory can be found in ph->p_memsz.
	//  The ph->p_filesz bytes from the ELF binary, starting at
	//  'binary + ph->p_offset', should be copied to virtual address
	//  ph->p_va.  Any remaining memory bytes should be cleared to zero.
	//  (The ELF header should have ph->p_filesz <= ph->p_memsz.)
	//  Use functions from the previous lab to allocate and map pages.
	//
	//  All page protection bits should be user read/write for now.
	//  ELF segments are not necessarily page-aligned, but you can
	//  assume for this function that no two segments will touch
	//  the same virtual page.
	//
	//  You may find a function like segment_alloc useful.
	//
	//  Loading the segments is much simpler if you can move data
	//  directly into the virtual addresses stored in the ELF binary.
	//  So which page directory should be in force during
	//  this function?
	//
	// Hint:
	//  You must also do something with the program's entry point,
	//  to make sure that the environment starts executing there.
	//  What?  (See env_run() and env_pop_tf() below.)

	// LAB 3: Your code here.


	struct Proghdr *ph, *eph; 
	struct Elf * header = (struct Elf *)binary;
	int i;
	uint32_t cr3;
	
	//switch to environment's page directory
	// (kernel part of which is the same as kernel's page directory's (except vpt, hm)) -ren
	cr3 = rcr3(); 
	lcr3(e->env_cr3);
	
	// is this a valid ELF?
	if (header->e_magic != ELF_MAGIC)
		panic("load_icode - magic number is bad!");

	
	ph = (struct Proghdr *) (binary + header->e_phoff);
	eph = ph + header->e_phnum;
		

	for (; ph < eph; ph++){
		
		if (ph->p_type == ELF_PROG_LOAD){
					
			segment_alloc(e, (void *)ph->p_va, (size_t) ph->p_memsz);			
			memset( (void *) ph->p_va, 0, ph->p_memsz);	
			memcpy( (void *) ph->p_va, binary + ph->p_offset, ph->p_filesz);	
		}
	}
	
	
	e->env_tf.tf_eip=header->e_entry;
	//what about processor flags? (don't know) - ren
	//e->env_tf.tf_eflags 	
	
	// Now map one page for the program's initial stack
	// at virtual address USTACKTOP - PGSIZE.

	// LAB 3: Your code here.
	
	segment_alloc(e, (void *)USTACKTOP - PGSIZE, PGSIZE);

	
	
	//switch back to kernel's page directory - ren
	lcr3(cr3);
}