// // 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); }
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); }
// // 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. }
// // 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? }
// // 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; }
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 ; }
// // 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"); }
// // 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 ; }
// // 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"); } }
// // 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; }
// // 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); }
// // 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); }