⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ldrdf.c

📁 开源的nasm编译器源码,研究编译器原理很有帮且
💻 C
📖 第 1 页 / 共 3 页
字号:
}/* * symtab_add() * * inserts a symbol into the global symbol table, which associates symbol * names either with addresses, or a marker that the symbol hasn't been * resolved yet, or possibly that the symbol has been defined as * contained in a dynamic [load time/run time] linked library. * * segment = -1 => not yet defined * segment = -2 => defined as dll symbol * * If the symbol is already defined, and the new segment >= 0, then * if the original segment was < 0 the symbol is redefined, otherwise * a duplicate symbol warning is issued. If new segment == -1, this * routine won't change a previously existing symbol. It will change * to segment = -2 only if the segment was previously < 0. */void symtab_add(const char * symbol, int segment, long offset){    symtabEnt * ste;    ste = symtabFind(symtab, symbol);    if (ste)    {	if (ste->segment >= 0) {	    /*	     * symbol previously defined	     */	    if (segment < 0) return;	    fprintf (error_file, "warning: `%s' redefined\n", symbol);	    return;	}	/*	 * somebody wanted the symbol, and put an undefined symbol	 * marker into the table	 */	if (segment == -1) return;	/*	 * we have more information now - update the symbol's entry	 */	ste->segment = segment;	ste->offset = offset;	ste->flags = 0;	return;    }    /*     * this is the first declaration of this symbol     */    ste = malloc(sizeof(symtabEnt));    if (!ste) {	fprintf(stderr, "ldrdf: out of memory\n");	exit(1);    }    ste->name = strdup(symbol);    ste->segment = segment;    ste->offset = offset;    ste->flags = 0;    symtabInsert(symtab, ste);}/* * symtab_get() * * Retrieves the values associated with a symbol. Undefined symbols * are assumed to have -1:0 associated. Returns 1 if the symbol was * successfully located. */int symtab_get(const char * symbol, int * segment, long * offset){    symtabEnt * ste = symtabFind(symtab, symbol);    if (!ste) {	*segment = -1;	*offset = 0;	return 0;    }    else    {	*segment = ste->segment;	*offset = ste->offset;	return 1;    }}/* * add_library() * * checks that a library can be opened and is in the correct format, * then adds it to the linked list of libraries. */void add_library(const char * name){    if (rdl_verify(name)) {	rdl_perror("ldrdf", name);	errorcount++;	return;    }    if (! libraries)    {	lastlib = libraries = malloc(sizeof(*libraries));	if (! libraries) {	    fprintf(stderr, "ldrdf: out of memory\n");	    exit(1);	}    }    else    {	lastlib->next = malloc(sizeof(*libraries));	if (!lastlib->next) {	    fprintf(stderr, "ldrdf: out of memory\n");	    exit(1);	}	lastlib = lastlib->next;    }    lastlib->next = NULL;    if (rdl_open(lastlib, name)) {	rdl_perror("ldrdf", name);	errorcount++;	return;    }}/* * search_libraries() * * scans through the list of libraries, attempting to match symbols * defined in library modules against symbols that are referenced but * not defined (segment = -1 in the symbol table) * * returns 1 if any extra library modules are included, indicating that * another pass through the library list should be made (possibly). */int search_libraries(){    struct librarynode * cur;    rdffile f;    int     i;    void    * header;    int	    segment;    long    offset;    int	    doneanything = 0, pass = 1, keepfile;    rdfheaderrec * hr;    cur = libraries;    while (cur)    {	if (options.verbose > 2)	    printf("scanning library `%s', pass %d...\n", cur->name, pass);		for (i = 0; rdl_openmodule(cur, i, &f) == 0; i++)	{	    if (pass == 2 && lookformodule(f.name)) continue;	    if (options.verbose > 3)		printf("  looking in module `%s'\n", f.name);	    header = malloc(f.header_len);	    if (!header) {		fprintf(stderr, "ldrdf: not enough memory\n");		exit(1);	    }	    if (rdfloadseg(&f, RDOFF_HEADER, header)) {		rdfperror("ldrdf", f.name);		errorcount++;		return 0;	    }	    	    keepfile = 0;	    while ((hr = rdfgetheaderrec (&f)))	    {                /* We're only interested in exports, so skip others */		if (hr->type != RDFREC_GLOBAL) continue; 		/*		 * If the symbol is marked as SYM_GLOBAL, somebody will be		 * definitely interested in it..		 */		if ((hr->e.flags & SYM_GLOBAL) == 0) {		    /*		     * otherwise the symbol is just public. Find it in		     * the symbol table. If the symbol isn't defined, we		     * aren't interested, so go on to the next.		 * If it is defined as anything but -1, we're also not		 * interested. But if it is defined as -1, insert this		 * module into the list of modules to use, and go		 * immediately on to the next module...		 */		    if (!symtab_get(hr->e.label, &segment, &offset) || segment != -1)		    continue;    		}				doneanything = 1;		keepfile = 1;		/*		 * as there are undefined symbols, we can assume that		 * there are modules on the module list by the time		 * we get here.		 */		lastmodule->next = malloc(sizeof(*lastmodule->next));		if (!lastmodule->next) {		    fprintf(stderr, "ldrdf: not enough memory\n");		    exit(1);		}		lastmodule = lastmodule->next;		memcpy(&lastmodule->f, &f, sizeof(f));		lastmodule->name = strdup(f.name);                lastmodule->next = NULL;		processmodule(f.name, lastmodule);		break;	    }	    if (!keepfile) {              free(f.name);              f.name = NULL;              f.fp = NULL;             }	}	if (rdl_error != 0 && rdl_error != RDL_ENOTFOUND)	    rdl_perror("ldrdf", cur->name);	cur = cur->next;	if (cur == NULL && pass == 1) {	    cur = libraries;	    pass++;	}    }    return doneanything;}/* * write_output() * * this takes the linked list of modules, and walks through it, merging * all the modules into a single output module, and then writes this to a * file. */void write_output(const char * filename){    FILE          * f;    rdf_headerbuf * rdfheader;    struct modulenode * cur;    int		  i, availableseg, seg, localseg, isrelative;    void	  * header;    rdfheaderrec  * hr, newrec;    symtabEnt 	  * se;    segtab	  segs;    long	  offset;    byte 	  * data;    if ((f = fopen(filename, "wb"))==NULL) {	fprintf(stderr, "ldrdf: couldn't open %s for output\n", filename);	exit(1);    }    if ((rdfheader=rdfnewheader())==NULL) {	fprintf(stderr, "ldrdf: out of memory\n");	exit(1);    }        /*     * If '-g' option was given, first record in output file will be a     * `generic' record, filled with a given file content.     * This can be useful, for example, when constructing multiboot     * compliant kernels.     */    if (generic_rec_file) {	FILE *ff;    	if (options.verbose)	    printf("\nadding generic record from binary file %s\n", generic_rec_file);	        hr = (rdfheaderrec *) malloc(sizeof(struct GenericRec));	if ((ff = fopen(generic_rec_file, "r")) == NULL) {	    fprintf(stderr, "ldrdf: couldn't open %s for input\n", generic_rec_file);	    exit(1);	}	i = fread(hr->g.data, 1, sizeof(hr->g.data), ff);	fseek(ff, 0, SEEK_END);	if (ftell(ff) > sizeof(hr->g.data)) {	    fprintf (error_file, "warning: maximum generic record size is %d, rest of file ignored\n", sizeof(hr->g.data));	}	fclose(ff);	            hr->g.type = 0;        hr->g.reclen = i;        rdfaddheader(rdfheader,hr);        free(hr);    }    if (options.verbose)	printf ("\nbuilding output module (%d segments)\n", nsegs);    /*     * Allocate the memory for the segments. We may be better off     * building the output module one segment at a time when running     * under 16 bit DOS, but that would be a slower way of doing this.     * And you could always use DJGPP...     */    for (i = 0; i < nsegs; i++)    {	outputseg[i].data=NULL;	if(!outputseg[i].length) continue;	outputseg[i].data = malloc(outputseg[i].length);	if (!outputseg[i].data) {	    fprintf(stderr, "ldrdf: out of memory\n");	    exit(1);	}    }    /*     * initialise availableseg, used to allocate segment numbers for     * imported and exported labels...     */    availableseg = nsegs;    /*     * Step through the modules, performing required actions on each one     */    for (cur = modules; cur; cur=cur->next)    {	/*	 * Read the actual segment contents into the correct places in	 * the newly allocated segments	 */	for (i = 0; i < cur->f.nsegs; i++)	{	    int dest = cur->seginfo[i].dest_seg;	    if (dest == -1) continue;	    if (rdfloadseg(&cur->f, i, 			   outputseg[dest].data + cur->seginfo[i].reloc))	    {		rdfperror("ldrdf", cur->name);		exit(1);	    }	} 	/*	 * Perform fixups, and add new header records where required	 */	header = malloc(cur->f.header_len);	if (!header) {	    fprintf(stderr, "ldrdf: out of memory\n");	    exit(1);	}	if (cur->f.header_loc)	    rdfheaderrewind(&cur->f);	else	    if (rdfloadseg(&cur->f, RDOFF_HEADER, header))	    {		rdfperror("ldrdf", cur->name);		exit(1);	    }		/*	 * we need to create a local segment number -> location	 * table for the segments in this module.	 */	init_seglocations(&segs);	for (i = 0; i < cur->f.nsegs; i++)	{	    add_seglocation(&segs, cur->f.seg[i].number,			    cur->seginfo[i].dest_seg, cur->seginfo[i].reloc);	}	/*	 * and the BSS segment (doh!)	 */	add_seglocation (&segs, 2, 2, cur->bss_reloc);		while ((hr = rdfgetheaderrec(&cur->f)))	{	    switch(hr->type) {	    case RDFREC_RELOC: /* relocation record - need to do a fixup */		/*		 * First correct the offset stored in the segment from		 * the start of the segment (which may well have changed).		 *		 * To do this we add to the number stored the relocation		 * factor associated with the segment that contains the		 * target segment.		 *		 * The relocation could be a relative relocation, in which		 * case we have to first subtract the amount we've relocated		 * the containing segment by.		 */				if (!get_seglocation(&segs, hr->r.refseg, &seg, &offset))		{		    fprintf(stderr, "%s: reloc to undefined segment %04x\n",			    cur->name, (int) hr->r.refseg);		    errorcount++;		    break;		}		isrelative = (hr->r.segment & 64) == 64;		hr->r.segment &= 63;		if (hr->r.segment == 2 || 		    (localseg = rdffindsegment(&cur->f, hr->r.segment)) == -1)		{		    fprintf(stderr, "%s: reloc from %s segment (%d)\n", 			    cur->name,			    hr->r.segment == 2 ? "BSS" : "unknown",			    hr->r.segment);		    errorcount++;		    break;		}		if (hr->r.length != 1 && hr->r.length != 2 && hr->r.length!=4)		{		    fprintf(stderr, "%s: nonstandard length reloc "			    "(%d bytes)\n", cur->name, hr->r.length);		    errorcount++;		    break;		}		/* 		 * okay, now the relocation is in the segment pointed to by		 * cur->seginfo[localseg], and we know everything else is		 * okay to go ahead and do the relocation		 */		data = outputseg[cur->seginfo[localseg].dest_seg].data;		data += cur->seginfo[localseg].reloc + hr->r.offset;		/*		 * data now points to the reference that needs		 * relocation. Calculate the relocation factor.		 * Factor is:		 *      offset of referred object in segment [in offset]		 *	(- relocation of localseg, if ref is relative)		 * For simplicity, the result is stored in 'offset'.		 * Then add 'offset' onto the value at data.		 */				if (isrelative) offset -= cur->seginfo[localseg].reloc;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -