Created
October 14, 2015 18:57
-
-
Save cr1901/3fef6d6755191a4024c1 to your computer and use it in GitHub Desktop.
OMF-LD Pattern Match
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <stddef.h> | |
| #define CHAR_ARRAY_2_SHORT_LE(_x) ((_x)[0] << 0) | ((_x)[1] << 8) | |
| static char string_buf[256]; | |
| static char record_buf[1024]; | |
| typedef struct omf_record | |
| { | |
| union | |
| { | |
| struct header | |
| { | |
| unsigned char strlen; | |
| char * strname; | |
| }theadr; | |
| struct header lheadr; | |
| struct | |
| { | |
| unsigned char type; | |
| unsigned char class; | |
| char * string; | |
| }coment; | |
| }fields; | |
| enum | |
| { | |
| THEADR = 0x80, | |
| LHEADR = 0x82, | |
| COMENT = 0x88, | |
| MODEND = 0x8A, | |
| EXTDEF = 0x8C, | |
| PUBDEF = 0x90, | |
| LNAMES = 0x96, | |
| SEGDEF = 0x98, | |
| GRPDEF = 0x9A, | |
| FIXUPP = 0x9C, | |
| LEDATA = 0xA0, | |
| LIDATA = 0xA2, | |
| LEXTDEF = 0xB4, | |
| LPUBDEF = 0xB6, | |
| ALIAS = 0xC6, | |
| OOB_LIBHEADER = 0xF0, | |
| OOB_LIBEND = 0xF1 | |
| }type; | |
| unsigned short length; | |
| unsigned char checksum; | |
| }OMF_RECORD; | |
| int get_new_record(FILE * omf_file, OMF_RECORD * rec); | |
| int main(int argc, char * argv[]) | |
| { | |
| /* Check if valid OMF modules */ | |
| /* Create symbol table- figure out whether all symbols are defined. */ | |
| /* Write actual code/data segments into either temp file or memmapped file. */ | |
| /* Construct program header */ | |
| /* Concatenate */ | |
| FILE * curr_module; | |
| OMF_RECORD curr_rec; | |
| int lib_mode = 0; | |
| if(argc < 2 || (curr_module = fopen(argv[1], "rb")) == NULL) | |
| { | |
| return EXIT_FAILURE; | |
| } | |
| printf("OBJ stats:\n"); | |
| while(get_new_record(curr_module, &curr_rec) >= 0) | |
| { | |
| if(curr_rec.type == THEADR) | |
| { | |
| printf("Obj Name: %s\n", curr_rec.fields.theadr.strname); | |
| } | |
| else if(curr_rec.type == LHEADR) | |
| { | |
| printf("Library Name: %s\n", curr_rec.fields.lheadr.strname); | |
| } | |
| else if(curr_rec.type == COMENT) | |
| { | |
| printf("Comment class: %X, string: %s\n", \ | |
| curr_rec.fields.coment.class, curr_rec.fields.coment.string); | |
| } | |
| else if(curr_rec.type == MODEND) | |
| { | |
| if(lib_mode) | |
| { | |
| unsigned long curr_pos = ftell(curr_module); | |
| fseek(curr_module, ((16 - (curr_pos % 16)) % 16), SEEK_CUR); | |
| } | |
| } | |
| else if(curr_rec.type == OOB_LIBHEADER) | |
| { | |
| printf("Found Out-of-Band Library Header...\n"); | |
| lib_mode = 1; | |
| } | |
| else if(curr_rec.type == OOB_LIBEND) | |
| { | |
| printf("Found Out-of-Band Library End... breaking!\n"); | |
| break; | |
| } | |
| } | |
| if(curr_rec.type == MODEND) | |
| { | |
| printf("End of file reached. Parse okay.\n"); | |
| return EXIT_SUCCESS; | |
| } | |
| else | |
| { | |
| return EXIT_FAILURE; | |
| } | |
| } | |
| int store_symbol(char * name, long unsigned int address) | |
| { | |
| (void) name; | |
| (void) address; | |
| return 0; | |
| } | |
| long unsigned int get_symbol_address(char * name) | |
| { | |
| (void) name; | |
| return 0uL; | |
| } | |
| /* int try_read(FILE * fp, */ | |
| /* Convert string with known size (<= 255) to null-terminated C string. */ | |
| unsigned short pstrcpy(char * dest, char * src) | |
| { | |
| unsigned char str_length = src[0]; | |
| memcpy(dest, &src[1], str_length); | |
| dest[str_length] = '\0'; | |
| return str_length; | |
| } | |
| /* If function fails, file pointer is not modified, and rec is last successfully parsed. */ | |
| int get_new_record(FILE * omf_file, OMF_RECORD * rec) | |
| { | |
| long int initial_fpos; | |
| unsigned char buf[3]; | |
| initial_fpos = ftell(omf_file); | |
| if(!fread(buf, 3, 1, omf_file)) | |
| { | |
| /* Don't even bother checking- | |
| something went seriously wrong. */ | |
| fseek(omf_file, initial_fpos, SEEK_SET); | |
| return -1; | |
| } | |
| rec->type = buf[0]; | |
| rec->length = CHAR_ARRAY_2_SHORT_LE(&buf[1]); | |
| if(rec->length > 1024) | |
| { | |
| fprintf(stderr, "Records > 1024 not yet supported.\n" | |
| "Record type %X\n", rec->type); | |
| return -2; | |
| } | |
| if(!fread(record_buf, rec->length, 1, omf_file)) | |
| { | |
| fseek(omf_file, initial_fpos, SEEK_SET); | |
| return -1; | |
| } | |
| rec->checksum = record_buf[rec->length]; | |
| /* We are at the start of the actual record if we got here... */ | |
| switch(rec->type) | |
| { | |
| int rc = 0; | |
| case THEADR: | |
| rec->fields.theadr.strlen = \ | |
| pstrcpy(string_buf, record_buf); | |
| rec->fields.theadr.strname = string_buf; | |
| break; | |
| case LHEADR: | |
| rec->fields.lheadr.strlen = \ | |
| pstrcpy(string_buf, record_buf); | |
| rec->fields.lheadr.strname = string_buf; | |
| break; | |
| case COMENT: | |
| rec->fields.coment.type = record_buf[0]; | |
| rec->fields.coment.class = record_buf[1]; | |
| memcpy(string_buf, &record_buf[2], rec->length - 3); | |
| string_buf[rec->length - 3] = '\0'; /* Some compilers do not null-terminate comments (Watcom). */ | |
| break; | |
| case MODEND: | |
| break; | |
| case EXTDEF: | |
| break; | |
| case PUBDEF: | |
| break; | |
| case LNAMES: | |
| break; | |
| case SEGDEF: | |
| break; | |
| case GRPDEF: | |
| break; | |
| case FIXUPP: | |
| break; | |
| case LEDATA: | |
| break; | |
| case LIDATA: | |
| break; | |
| case LEXTDEF: | |
| break; | |
| case LPUBDEF: | |
| break; | |
| case ALIAS: | |
| break; | |
| case OOB_LIBHEADER: | |
| break; | |
| case OOB_LIBEND: | |
| break; | |
| default: | |
| fprintf(stderr, "Undefined record type: %X!\n", rec->type); | |
| rc = -1; | |
| if(rc) | |
| { | |
| return rc; | |
| } | |
| } | |
| return 0; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment