kolibrios/programs/develop/libraries/menuetlibc/src/libmcoff/loadcoff.c
right-hearted 6496d04506 Adding menuetlibc back to its place in /programs/develop/libraries
This version of menuetlibc was taken from revision 4743, right before I made any changes

git-svn-id: svn://kolibrios.org@4973 a494cfbc-eb01-0410-851d-a64ba20cac60
2014-06-12 10:43:21 +00:00

191 lines
4.5 KiB
C

#include"mcoff.h"
#include<stdio.h>
#include<stdlib.h>
#include"string.h"
#undef MCOFF_MENUETOS
#define MCOFF_MENUETOS 0
#if (MCOFF_MENUETOS==1)
struct systree_blk {
unsigned long cmd,pos,blks;
void * data,* work;
char name[128];
} __attribute__((packed));
static char systree_work[16384];
static char temp_block[512];
static struct systree_blk sblk={
0,
0,
1,
NULL,
systree_work,
};
static unsigned long open_on_path(char * pth,char * name)
{
int l;
int d0,d1;
l=strlen(pth);
if(!pth)
{
sprintf(sblk.name,"%s",pth);
} else {
if(pth[l]!='/')
sprintf(sblk.name,"%s/%s",pth,name);
else
sprintf(sblk.name,"%s%s",pth,name);
}
sblk.data=&temp_block;
sblk.cmd=0;
sblk.pos=0;
sblk.blks=1;
sblk.work=systree_work;
__asm__ __volatile__("int $0x40":"=a"(d0),"=b"(d1):"0"(58),"1"((void *)&sblk));
if(d0!=0) return 0;
return d1;
}
#endif
coffobj_t * mcoff_load_file(char * fname)
{
coffobj_t * obj;
int i;
#if (MCOFF_MENUETOS==1)
unsigned long sz;
#endif
obj=(coffobj_t *)malloc(sizeof(coffobj_t));
if(!obj)
{
dprintf("malloc error1\n");
return NULL;
}
#if (MCOFF_MENUETOS==0)
FILE * f=fopen(fname,"rb");
if(!f)
{
dprintf("Unable to open file\n");
free(obj);
return NULL;
}
dprintf("File opened\n");
fseek(f,0,SEEK_END);
dprintf("After seek to end\n");
obj->co_filesize=ftell(f);
dprintf("After ftell\n");
fseek(f,0,SEEK_SET);
dprintf("After seek to start\n");
dprintf("File size is %u bytes\n",obj->co_filesize);
#else
/* Special actions for MenuetOS, because it doesn't support relative paths */
/* We just search some paths if it is relative */
if(fname[0]!='/')
{
sz=open_on_path("/RD/1",fname);
if(sz>64 && sz<0x1000000) goto OK; /* Max 16MB for DLL */
sz=open_on_path("/HD/1/MENUETOS",fname);
if(sz>64 && sz<0x1000000) goto OK; /* Max 16MB for DLL */
sz=open_on_path("/HD/1/MENUETOS/DLL",fname);
if(sz>64 && sz<0x1000000) goto OK; /* Max 16MB for DLL */
} else {
dprintf("Opening on std path\n");
sz=open_on_path("",fname);
if(sz>64 && sz<0x1000000) goto OK; /* Max 16MB for DLL */
}
free(obj);
return NULL;
OK:
obj->co_filesize=sz;
dprintf("File size is %u bytes\n",sz);
#endif
obj->co_loadptr=(char *)malloc((obj->co_filesize+511)&~511);
if(!obj->co_loadptr)
{
dprintf("Unable to create file memory\n");
#if (MCOFF_MENUETOS==0)
fclose(f);
#endif
free(obj);
return NULL;
}
dprintf("Memory allocated\n");
#if (MCOFF_MENUETOS==0)
dprintf("Before fread\n");
fread(obj->co_loadptr,1,obj->co_filesize,f);
dprintf("After fread\n");
fclose(f);
dprintf("After fclose\n");
#else
sblk.cmd=0;
sblk.pos=0;
sblk.blks=((sz+511)&~511)/512;
sblk.data=obj->co_loadptr;
sblk.work=systree_work;
{
int d0,d1;
__asm__ __volatile__("int $0x40":"=a"(d0),"=b"(d1):"0"(58),"1"((void *)&sblk));
}
dprintf("Done reading file\n");
#endif
dprintf("Checking file\n");
obj->co_loadaddr=(unsigned long)obj->co_loadptr;
obj->co_filehdr=(FILHDR *)obj->co_loadaddr;
/* Check if file is really COFF */
if(I386BADMAG(*obj->co_filehdr))
{
dprintf("bad magic\n");
NOREL:
free(obj->co_loadptr);
free(obj);
return NULL;
}
/* We don't support files with relocations stripped */
/* if(obj->co_filehdr->f_flags & F_RELFLG)
{
printf("No relocation info\n");
goto NOREL;
} */
/* Get into section table, symbol table and string table */
obj->co_sections=(SCNHDR *)(obj->co_loadaddr+FILHSZ+obj->co_filehdr->f_opthdr);
obj->co_symtab=(SYMENT *)(obj->co_loadaddr+obj->co_filehdr->f_symptr);
obj->co_strtab=(char *)(obj->co_loadaddr+obj->co_filehdr->f_symptr+
SYMESZ*obj->co_filehdr->f_nsyms);
/* Setup .bss section */
{
SCNHDR * h;
h=obj->co_sections;
dprintf("Looking for bss...\n");
for(i=0;i<obj->co_filehdr->f_nscns;i++,h++)
{
unsigned long r;
if((h->s_flags & 0xE0)!=0x80) continue;
r=h->s_size;
obj->co_bssptr=(char *)malloc(r);
obj->co_bsssize=r;
if(!obj->co_bssptr)
{
dprintf("Unable to alloc %u bytes for bss\n",r);
free(obj->co_loadptr);
free(obj);
return NULL;
}
obj->co_bssaddr=(unsigned long)obj->co_bssptr;
h->s_scnptr=obj->co_bssaddr-obj->co_loadaddr;
obj->co_bsssectnum=i+1; /* So we don't have to do it later */
dprintf("BSS size=%u bytes\n",obj->co_bsssize);
}
}
NOBSS:
/* File is COFF. Just return obj */
return obj;
}
void unload_coff_file(coffobj_t * obj)
{
if(!obj) return;
free(obj->co_loadptr);
return;
}