Thread: Segfault when moving to linux

  1. #1
    Registered User
    Join Date
    Feb 2015
    Posts
    23

    Segfault when moving to linux

    Once again I'm having problems when I run my program developed in Windows on Linux. It won't even print the first printf(), it only returns a segmentation fault.

    Code:
    /*==========================================================
     *
     * Program Purpose: To implement a two pass assembler
     *
     *============================================================
     *
     * Date Started: 8 April 2015
     * Date Completed: April 2015
     *
     *============================================================
     *
     * Variable Dictionary:
     *
     *============================================================
     *
     * Input file(s): proj1b.dat
     * Output file(s): proj1b.out
     *
     *============================================================
     *
     * Sample input:
     *        .st              //start of assembly
     * STRT   LOD 0 R0 M10     //load the constant 10 into R0 (instr. is at offset 0)
     *        STO 0 R0 M8      //Store the value from R0 into location M8
     *        LOD 0 R1 M11     //load the constant 3 into R1
     *        SUB R0 R1 R0     //subtract R1 from R0 giving R0 (the result is 7)
     *        LOD 0 R3 M12     //load R3 with 2
     *        JGT 0 R0 EXIT    //jump on R0 greater than 0 to exit
     *        STO 0 R1 M9      //otherwise store in location M9
     * EXIT   HLT              //halt the program
     * M8     .dw 0            //storage area for constants and variables
     * M9     .dw 0
     * M10    .dw 10
     * M11    .dw 3
     * M12    .dw 2
     *        .nd             //end of assembly
     * 
     * Sample Output: 
     *============================================================
     */
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    
    //function declarations
    void buildSymbolTable();
    void buildInstructions();
    void formatOne(char* str, int offset);
    void formatTwo(char* str);
    int lookup(char* key);
    void dataDeclaration(char* str);
    void printBits(int width, int num);
    void output();
    
    
    //global variables
    int instrOffset[50]; //instruction offsets with memory addresses
    FILE *ofp;//file proj1b.dat
    
    
    int main(){
        
        printf("start");
            ofp = fopen("proj1b.out", "r+");
            printf("file opened");
            buildSymbolTable(); //first pass
            printf("SymbolTable built");
            buildInstructions(); //second pass
            printf("instructions built");
            output();
    
    
        output();
    
    
        return 0;
    }
    
    
    
    
    void buildSymbolTable(){
        //first pass through code
        FILE *ifp;
        FILE *ofp;
        ifp = fopen("proj1b.dat", "r"); //input file TODO: change to "../instr/proj1a.dat" before submitting
        ofp = fopen("symbolTable.dat", "w"); //output file
    
    
        char symbolTable[50][6] = {0};
    
    
        //validates file exists
        if (ifp == NULL)
        {
            perror("../instr/proj1b.dat");
            exit(0);
        }
        
        char str[100] = {0};//current line from file 
        int j = 0; //offset of current symbol
        int i = 0;
        while(fgets(str, sizeof(str), ifp) != NULL){
    
    
            if(!isspace(str[0])){
                for(i = 0; i < 6; i++){
                    if(!isspace(str[i])){
                        symbolTable[j][i] = str[i];
                    }
                }
                fprintf(ofp,"%-6s %d\n", symbolTable[j], j - 1);
    
    
            }
    
    
            j++;
        }
        
        fclose(ifp);
        fclose(ofp);
    }
    
    
    void buildInstructions(){
        FILE *ifp;
    
    
        ifp = fopen("proj1b.dat", "r"); //input file TODO: change to "../instr/proj1a.dat" before submitting
    
    
        
        //validates file(s) exists
        if (ifp == NULL)
        {
            perror("../instr/proj1b.dat");
            exit(0);
        }
        
        memset(instrOffset, -1, sizeof(instrOffset));//clear substr
        int addrIndex = -1; //index of address, for addresses with memory addresses
        int arrIndex = 0; //index of array
        
        char str[100] = {0};//current line from file 
        char substr[4] = {0};//line from file sans label and comments
        while(fgets(str, sizeof(str), ifp) != NULL){
            memset(substr, 0, sizeof(substr));//clear substr
            strncpy(substr, str+7, 3);//get first three chars
            substr[4] = '\0';//add null terminating char
            
            int format = -1; //0 if format 1, 1 if format 2
            
            //Format 1
            if(strcmp(substr, "LOD") == 0){
                fprintf(ofp, "0000");
                instrOffset[arrIndex] = addrIndex;
                
                formatOne(str, arrIndex);
                arrIndex++;
            }
            else if(strcmp(substr, "STO") == 0){
                fprintf(ofp, "0001");
                instrOffset[arrIndex] = addrIndex;
                
                formatOne(str, arrIndex);
                arrIndex++;
            }
            else if(strcmp(substr, "JMP") == 0){
                fprintf(ofp, "1001");
                instrOffset[arrIndex] = addrIndex;
                
                formatOne(str, arrIndex);
                arrIndex++;
            }
            else if(strcmp(substr, "JEQ") == 0){
                fprintf(ofp, "1010");
                instrOffset[arrIndex] = addrIndex;
                
                formatOne(str, arrIndex);
                arrIndex++;
            }
            else if(strcmp(substr, "JGT") == 0){
                fprintf(ofp, "1011");
                instrOffset[arrIndex] = addrIndex;
                
                formatOne(str, arrIndex);
                arrIndex++;
            }
            else if(strcmp(substr, "JLT") == 0){
                fprintf(ofp, "1100");
                formatOne(str, addrIndex);
                instrOffset[arrIndex] = addrIndex;
                arrIndex++;
                
    
    
            }
            
            //Format 2
            else if(strcmp(substr, "ADD") == 0){
                fprintf(ofp, "0010");
                formatTwo(str);
            }
            else if(strcmp(substr, "SUB") == 0){
                fprintf(ofp, "0011");
                formatTwo(str);
            }
            else if(strcmp(substr, "MOV") == 0){
                fprintf(ofp, "0100");
                formatTwo(str);
            }
            else if(strcmp(substr, "SAX") == 0){ 
                fprintf(ofp, "0101");
                formatTwo(str);
            }
            else if(strcmp(substr, "SHL") == 0){
                fprintf(ofp, "0110");
                formatTwo(str);
            }
            else if(strcmp(substr, "SHR") == 0){
                fprintf(ofp, "0111");
                formatTwo(str);
            }
            else if(strcmp(substr, "NOT") == 0){
                fprintf(ofp, "1000");
                formatTwo(str);
            }
            else if(strcmp(substr, "CLR") == 0){
                fprintf(ofp, "1110");
                formatTwo(str);
            }
            else if(strcmp(substr, "HLT") == 0){
                fprintf(ofp, "1111");
                formatTwo(str);
            }
            
            //.dw
            else if(strcmp(substr, ".dw") == 0){//.dw
                dataDeclaration(str);
            }
            
        
            fprintf(ofp, "\n");
            
            addrIndex++;
        }
        
        fclose(ofp);
        fclose(ifp);
    
    
    }
    
    
    int lookup(char* key){
        //looks up the location of the symbol in symbolTable.dat. 
        //If it is not in the file, returns -1 
        FILE *lookup;
        lookup = fopen("symbolTable.dat", "r"); 
        
        char str[100] = {0};//current line from file 
        char symbol[5] = {0};
        char num[4] = {0};//location
        int loc = -1;
        
        while(fgets(str, sizeof(str), lookup) != NULL){
            strncpy(symbol, str, 4);
            symbol[5] = '\0';
            if(strcmp(symbol, key) == 0){
                strncpy(num, str+7, 2);//get location
                num[4] = '\0';
                loc = strtol(num, NULL, 10);
            }
        }
        
        return loc;
    }
    
    
    void formatOne(char* str, int offset){
        FILE *und;
        und = fopen("undefinedTable.dat", "w");
        
        char flag[2] = {0};
        char reg[2] = {0};
        char mem[4] = {0};
        
        strncpy(flag, str+11, 1);//get flag
        flag[1] = '\0';//add null terminating char
        fprintf(ofp, "%s", flag);
        
        strncpy(reg, str+14, 1);//get reg
        reg[1] = '\0';//add null terminating char
        printBits(3, strtol(reg, NULL, 10));
        
        fprintf(ofp, "+");//indicates memory address
        
        strncpy(mem, str+16, 4);//get mem address
        mem[4] = '\0';//add null terminating char
        int pos = lookup(mem);
        
        if(pos != -1){
            printBits(8, pos);
        }
        else{
            printf("undefined: %s, pos: %d\n\n", mem, offset);
            fprintf(ofp, "UUUUUUUU");
            fprintf(und, "%s ", mem);
            fprintf(und, "%d\n", offset);
        }
        
        fclose(und);
    }
    
    
    void formatTwo(char* str){
        char rleft[2] = {0};
        char rlmid[2] = {0};
        char rrmid[2] = {0};
        char rright[2] = {0};
        
        strncpy(rleft, str+12, 1);//get rleft
        rleft[1] = '\0';//add null terminating char
        printBits(3, strtol(rleft, NULL, 10));
        
        strncpy(rlmid, str+15, 1);//get rlmid
        rlmid[1] = '\0';//add null terminating char
        printBits(3, strtol(rlmid, NULL, 10));
        
        strncpy(rrmid, str+18, 1);//get rrmid
        rrmid[1] = '\0';//add null terminating char
        printBits(3, strtol(rrmid, NULL, 10));
        
        strncpy(rright, str+21, 1);//get rright
        rright[1] = '\0';//add null terminating char
        printBits(3, strtol(rright, NULL, 10));
        
        
    }
    
    
    void dataDeclaration(char* str){
    
    
        char num[11];
        strncpy(num, str+11, 10);//get flag
        num[11] = '\0';//add null terminating char
        
        printBits(16, strtol(num, NULL, 10));
    }
    
    
    void printBits(int width, int num){
        //prints the bits of an int with width of int width (left padded with zeros) to proj1b.out
        int i = 0;
    
    
        for(i = width - 1; i >= 0; i--){
            if(num & (1 << i)){ //checks i-th bit (starting at 0)
                fprintf(ofp, "1");
            }
            else{
                fprintf(ofp, "0");
            }
        }
        
    
    
    }
    
    
    void output(){
        FILE *ifp;
        FILE *ofp;
        FILE *lookup;
        FILE *und;
    
    
        ifp = fopen("proj1b.dat", "r"); //input file TODO: change to "../instr/proj1a.dat" before submitting
        ofp = fopen("proj1b.out", "r");
        und = fopen("undefinedTable.dat", "r");
        lookup = fopen("symbolTable.dat", "r"); //input file
        
        char str[100] = {'\0'};//current line from assem file 
        char str2[19] = {'\0'};//current line from machine code file
        
        int chars = 0;//number of chars to print
        int j = 0;
        
        printf("OFFSET        ASM-INSTRUCTION         MACHINE-INSTRUCTION\n");
        
        while(fgets(str, sizeof(str), ifp) != NULL){
            chars = 25;
            
            //print offset
            printf("%-2d (0x%02x)     ", j, j);
            
            //print assem code
            int i = 0;
            while(str[i] != '/' && str[i] != '\n' && i < 22){
                printf("%c", str[i]);
                i++;
                chars--;
            }
            
            while(chars >= 0){
                printf(" ");
                chars--;
            }
            
            //print machine code
            fgets(str2, sizeof(str2), ofp);
            printf("%s", str2);
            
            printf("\n");
    
    
            j++;
        }
        
        //print symbol table
        printf("\nSYMBOL TABLE:\n");
        printf("SYMBOL LOCATION\n");
        while(fgets(str, sizeof(str), lookup) != NULL){
            printf("%s", str);
        }
        
        //print undefined table
        printf("\nUNDEFINED TABLE:\n");
        printf("SYMBOL LOCATION\n");
        while(fgets(str, sizeof(str), und) != NULL){
            printf("%s", str);
        }
        
        //print multiple table
        printf("\nMULTIPLE TABLE:\n");
        printf("SYMBOL LOCATION\n");
        
        //print instruction offsets with memory addresses
        printf("\nINSTRUCTION OFFSETS WITH MEMORY ADDRESSES\n");
        
        int ind = 0;
        for(ind = 0; ind < 50; ind++){
            if(instrOffset[ind] != -1){
                printf("%d ", instrOffset[ind]);
            }
        }
        
        fclose(ofp);
        fclose(ifp);
        fclose(lookup);
    }
    Here's proj1b.dat:
    Code:
           .st              //start of assembly
    STRT   LOD 0 R0 M10     //load the constant 10 into R0 (instr. is at offset 0)
           STO 0 R0 POOP      //Store the value from R0 into location M8
           LOD 0 R1 M11     //load the constant 3 into R1
           SUB R0 R1 R0     //subtract R1 from R0 giving R0 (the result is 7)
           LOD 0 R3 M12     //load R3 with 2
           JGT 0 R0 EXIT    //jump on R0 greater than 0 to exit
           STO 0 R1 M9      //otherwise store in location M9
    EXIT   HLT              //halt the program
    M8     .dw 0            //storage area for constants and variables
    M9     .dw 0
    M10    .dw 10
    M11    .dw 3
    M12    .dw 2
           .nd             //end of assembly
    proj1b.out also has to be in the directory with nothing in it.
    Last edited by PsylentKnight; 04-14-2015 at 09:05 PM.

  2. #2
    Registered Superuser nul's Avatar
    Join Date
    Nov 2014
    Location
    Earth
    Posts
    53
    Although it compiles with a few warnings, the printf("start") and printf("file opened") prints out fine for me on Debian.
    "Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away." -- Antoine de Saint-Exupery

  3. #3
    Registered User
    Join Date
    Feb 2015
    Posts
    23
    I'm not getting anything but a prompt "Segmentation fault". I've tried debugging using gdb and I found out that the symbol table is built but the program crashes when building the machine code at some point. The fgets() function is causing the segfault but can't figure out why.

  4. #4
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    How are you compiling on Linux?

    Hint: Run GDB to find where you're crashing (edit: try the "bt" command for more details)
    Last edited by Matticus; 04-14-2015 at 11:09 PM.

  5. #5
    Registered User
    Join Date
    Feb 2015
    Posts
    23
    gcc -o proj1b proj1b.c

    Edit: Ok I'm getting output now. Still working on nailing down the problem... at least I'm not flying blind anymore.
    Edit 2: Its crashing when it gets to line 11 of the input file:
    Code:
    M9     .dw 0
    Not sure why. I mean its identical to the previous line except that it doesn't have a comment.
    Last edited by PsylentKnight; 04-14-2015 at 10:50 PM.

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,664
    I counted half a dozen array bound errors.

    For example
    char num[11];
    strncpy(num, str+11, 10);//get flag
    num[11] = '\0';//add null terminating char


    If you have array[X], the last valid index is X-1, not X


    Also, use the -g flag when compiling if you want a better debug experience.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Feb 2015
    Posts
    23
    Thank you! I don't know why I did that... I set the last char of the array correctly in some cases but not in others. For some reason lines 11-14 of the input file aren't being read, but it doesn't crash anymore.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Segfault
    By Clayton Cuteri in forum C Programming
    Replies: 6
    Last Post: 02-20-2013, 11:41 PM
  2. Segfault... Why?
    By jonheese in forum C Programming
    Replies: 14
    Last Post: 11-21-2011, 06:02 PM
  3. Segfault
    By Triumph in forum C Programming
    Replies: 5
    Last Post: 04-10-2009, 02:24 AM
  4. Sometimes segfault, sometimes not
    By jcafaro10 in forum C Programming
    Replies: 18
    Last Post: 04-07-2009, 06:53 PM
  5. Segfault with C sockets on Linux
    By arti_valekar in forum C Programming
    Replies: 3
    Last Post: 02-16-2005, 02:25 AM