/***************************************************************************** Code snippet to load DJGPP COFF executables. This code is public domain (no copyright). You can do whatever you want with it. EXPORTS: int load_dj_exec(task_t *task, unsigned char *image, unsigned *entry); *****************************************************************************/ /* flags used to describe task memory sections */ #define SF_ZERO 0x10 /* BSS */ #define SF_LOAD 0x08 /* load from file */ #define SF_READ 0x04 /* readable */ #define SF_WRITE 0x02 /* writable */ #define SF_EXEC 0x01 /* executable */ #define SF_BSS (SF_ZERO | SF_READ | SF_WRITE) /* user-defined task structure, used here as tramp data for add_section() */ typedef struct { char whatever; } task_t; /* user-defined function to add memory section to task should return 0 if success, <0 if error */ int add_section(task_t *task, unsigned flags, unsigned long adr, unsigned long size, unsigned long offset); #if defined(__GNUC__) #define __PACKED__ __attribute__((packed)) #else #define __PACKED__ /* nothing */ #endif /* or use STDINT.H, if you have it... */ typedef unsigned short uint16_t; typedef unsigned long uint32_t; typedef struct { uint16_t magic __PACKED__; uint16_t num_sects __PACKED__; uint32_t time_date __PACKED__; uint32_t symtab_offset __PACKED__; uint32_t num_syms __PACKED__; uint16_t aout_size __PACKED__; uint16_t file_flags __PACKED__; } coff_file_t; /* 20 bytes; same as Win32 PE COFF */ typedef struct { uint16_t magic __PACKED__; uint16_t version __PACKED__; uint32_t code_size __PACKED__; uint32_t data_size __PACKED__; uint32_t bss_size __PACKED__; uint32_t entry __PACKED__; uint32_t code_offset __PACKED__; uint32_t data_offset __PACKED__; } dj_aout_t; /* 28 bytes */ typedef struct { char name[8] __PACKED__; uint32_t phys_adr __PACKED__; uint32_t virt_adr __PACKED__; uint32_t size __PACKED__; uint32_t offset __PACKED__; uint32_t relocs_offset __PACKED__; uint32_t line_nums_offset __PACKED__; uint16_t num_relocs __PACKED__; uint16_t num_line_nums __PACKED__; uint32_t flags __PACKED__; } dj_sect_t; /***************************************************************************** Creates task from memory-mapped DJGPP COFF executable file at address 'image'. Returns: +1 if file is not valid DJGPP COFF 0 if success (*entry set to entry point) <0 if error from add_section() If your OS has file I/O code, you could replace 'unsigned char *image' with a file handle, make 'coff', 'aout', and 'sect' actual structs (instead of pointers), seek and read from the file, etc. *****************************************************************************/ int load_dj_exec(task_t *task, unsigned char *image, unsigned *entry) { coff_file_t *coff; dj_aout_t *aout; dj_sect_t *sect; int i, s, flags; /* validate headers */ coff = (coff_file_t *)image; image += sizeof(coff_file_t); aout = (dj_aout_t *)image; image += sizeof(dj_aout_t); if(coff->magic != 0x014C || coff->aout_size != 28 || aout->magic != 0x010B) return 1; /* get entry point */ (*entry) = aout->entry; /* read section headers */ for(s = 0; s < coff->num_sects; s++) { sect = (dj_sect_t *)(image + sizeof(dj_sect_t) * s); /* code */ if((sect->flags & 0xE0) == 0x20) flags = SF_LOAD | SF_READ | SF_EXEC; /* data */ else if((sect->flags & 0xE0) == 0x40) flags = SF_LOAD | SF_READ | SF_WRITE; /* BSS */ else if((sect->flags & 0xE0) == 0x80) flags = SF_ZERO | SF_READ | SF_WRITE; /* ignore anything else */ else continue; i = add_section(task, flags, sect->virt_adr, sect->size, sect->offset); if(i != 0) return i; } return 0; }