📄 ldrdf.c
字号:
/* ldrdf.c RDOFF Object File linker/loader main program
*
* The Netwide Assembler is copyright (C) 1996 Simon Tatham and
* Julian Hall. All rights reserved. The software is
* redistributable under the licence given in the file "Licence"
* distributed in the NASM archive.
*/
/* TODO: Make the system skip a module (other than the first) if none
* of the other specified modules contain a reference to it.
* May require the system to make an extra pass of the modules to be
* loaded eliminating those that aren't required.
*
* Support all the existing documented options...
*
* Support libaries (.a files - requires a 'ranlib' type utility)
* (I think I've got this working, so I've upped the version)
*
* -s option to strip resolved symbols from exports. (Could make this an
* external utility)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rdoff.h"
#include "nasmlib.h"
#include "symtab.h"
#include "collectn.h"
#include "rdlib.h"
#define LDRDF_VERSION "0.30"
/* global variables - those to set options: */
int verbose = 0; /* reflects setting of command line switch */
int align = 16;
int errors = 0; /* set by functions to cause halt after current
stage of processing */
/* the linked list of modules that must be loaded & linked */
struct modulenode {
rdffile f; /* the file */
long coderel; /* module's code relocation factor */
long datarel; /* module's data relocation factor */
long bssrel; /* module's bss data reloc. factor */
void * header; /* header location, if loaded */
char * name; /* filename */
struct modulenode *next;
};
#define newstr(str) strcpy(malloc(strlen(str) + 1),str)
#define newstrcat(s1,s2) strcat(strcpy(malloc(strlen(s1)+strlen(s2)+1),s1),s2)
struct modulenode *modules = NULL,*lastmodule = NULL;
/* the linked list of libraries to be searched for missing imported
symbols */
struct librarynode * libraries = NULL, * lastlib = NULL;
void *symtab; /* The symbol table */
rdf_headerbuf * newheader ; /* New header to be written to output */
/* loadmodule - find the characteristics of a module and add it to the
* list of those being linked together */
void loadmodule(char *filename)
{
struct modulenode *prev;
if (! modules) {
modules = malloc(sizeof(struct modulenode));
lastmodule = modules;
prev = NULL;
}
else {
lastmodule->next = malloc(sizeof(struct modulenode));
prev = lastmodule;
lastmodule = lastmodule->next;
}
if (! lastmodule) {
fputs("ldrdf: not enough memory\n",stderr);
exit(1);
}
if (rdfopen(&lastmodule->f,filename)) {
rdfperror("ldrdf",filename);
exit(1);
}
lastmodule->header = NULL; /* header hasn't been loaded */
lastmodule->name = filename;
lastmodule->next = NULL;
if (prev) {
lastmodule->coderel = prev->coderel + prev->f.code_len;
if (lastmodule->coderel % align != 0)
lastmodule->coderel += align - (lastmodule->coderel % align);
lastmodule->datarel = prev->datarel + prev->f.data_len;
if (lastmodule->datarel % align != 0)
lastmodule->datarel += align - (lastmodule->datarel % align);
}
else {
lastmodule->coderel = 0;
lastmodule->datarel = 0;
}
if (verbose)
printf("%s code = %08lx (+%04lx), data = %08lx (+%04lx)\n",filename,
lastmodule->coderel,lastmodule->f.code_len,
lastmodule->datarel,lastmodule->f.data_len);
lastmodule->header = malloc(lastmodule->f.header_len);
if (!lastmodule->header) {
fprintf(stderr,"ldrdf: out of memory\n");
exit(1);
}
if (rdfloadseg(&lastmodule->f,RDOFF_HEADER,lastmodule->header))
{
rdfperror("ldrdf",filename);
exit(1);
}
}
/* load_library add a library to list of libraries to search
* for undefined symbols
*/
void load_library(char * name)
{
if (verbose)
printf("adding library %s to search path\n",name);
if (! lastlib) {
lastlib = libraries = malloc(sizeof(struct librarynode));
}
else
{
lastlib->next = malloc(sizeof(struct librarynode));
lastlib = lastlib->next;
}
if (! lastlib) {
fprintf(stderr, "ldrdf: out of memory\n");
exit(1);
}
strcpy (lastlib->name = malloc (1+strlen(name)), name);
lastlib->fp = NULL;
lastlib->referenced = 0;
lastlib->next = NULL;
}
/* build_symbols() step through each module's header, and locate
* exported symbols, placing them in a global table
*/
long bsslength;
void mod_addsymbols(struct modulenode * mod)
{
rdfheaderrec *r;
symtabEnt e;
long cbBss;
mod->bssrel = bsslength;
cbBss = 0;
rdfheaderrewind(&mod->f);
while ((r = rdfgetheaderrec(&mod->f)))
{
if (r->type == 5) /* Allocate BSS */
cbBss += r->b.amount;
if (r->type != 3) continue; /* ignore all but export recs */
e.segment = r->e.segment;
e.offset = r->e.offset +
(e.segment == 0 ? mod->coderel : /* 0 -> code */
e.segment == 1 ? mod->datarel : /* 1 -> data */
mod->bssrel) ; /* 2 -> bss */
e.flags = 0;
e.name = malloc(strlen(r->e.label) + 1);
if (! e.name)
{
fprintf(stderr,"ldrdf: out of memory\n");
exit(1);
}
strcpy(e.name,r->e.label);
symtabInsert(symtab,&e);
}
bsslength += cbBss;
}
void build_symbols()
{
struct modulenode *mod;
if (verbose) printf("building global symbol table:\n");
newheader = rdfnewheader();
symtab = symtabNew();
bsslength = 0; /* keep track of location of BSS symbols */
for (mod = modules; mod; mod = mod->next)
{
mod_addsymbols( mod );
}
if (verbose)
{
symtabDump(symtab,stdout);
printf("BSS length = %ld bytes\n\n",bsslength);
}
}
/* scan_libraries() search through headers of modules for undefined
* symbols, and scan libraries for those symbols,
* adding library modules found to list of modules
* to load. */
void scan_libraries(void)
{
struct modulenode * mod, * nm;
struct librarynode * lib;
rdfheaderrec * r;
int found;
char * tmp;
if (verbose) printf("Scanning libraries for unresolved symbols...\n");
mod = modules;
while (mod)
{
rdfheaderrewind(&mod->f);
while ((r = rdfgetheaderrec(&mod->f)))
{
if (r->type != 2) continue; /* not an import record */
if ( symtabFind (symtab,r->i.label) )
continue; /* symbol already defined */
/* okay, we have an undefined symbol... step through
the libraries now */
if (verbose >= 2) {
printf("undefined symbol '%s'...",r->i.label);
fflush(stdout);
}
lib = libraries;
found = 0;
tmp = newstr(r->i.label);
while (! found && lib)
{
/* move this to an outer loop...! */
nm = malloc(sizeof(struct modulenode));
if (rdl_searchlib(lib,tmp,&nm->f))
{ /* found a module in the library */
/* create a modulenode for it */
if (! nm) {
fprintf(stderr,"ldrdf: out of memory\n");
exit(1);
}
nm->name = newstrcat(lib->name,nm->f.name);
if (verbose >= 2) printf("found in '%s'\n",nm->name);
nm->coderel = lastmodule->coderel + lastmodule->f.code_len;
if (nm->coderel % align != 0)
nm->coderel += align - (nm->coderel % align);
nm->datarel = lastmodule->datarel + lastmodule->f.data_len;
if (nm->datarel % align != 0)
nm->datarel += align - (nm->datarel % align);
nm->header = malloc(nm->f.header_len);
if (! nm->header)
{
fprintf(stderr,"ldrdf: out of memory\n");
exit(1);
}
if (rdfloadseg(&nm->f,RDOFF_HEADER,nm->header))
{
rdfperror("ldrdf",nm->name);
exit(1);
}
nm->next = NULL;
found = 1;
lastmodule->next = nm;
lastmodule = nm;
if (verbose)
printf("%s code = %08lx (+%04lx), data = %08lx "
"(+%04lx)\n",lastmodule->name,
lastmodule->coderel,lastmodule->f.code_len,
lastmodule->datarel,lastmodule->f.data_len);
/* add the module's info to the symbol table */
mod_addsymbols(nm);
}
else
{
if (rdl_error) {
rdl_perror("ldrdf",lib->name);
exit(1);
}
free(nm);
}
lib = lib->next;
}
free(tmp);
if (!found && verbose >= 2) printf("not found\n");
}
mod = mod->next;
}
}
/* load_segments() allocates memory for & loads the code & data segs
* from the RDF modules
*/
char *text,*data;
long textlength,datalength;
void load_segments(void)
{
struct modulenode *mod;
if (!modules) {
fprintf(stderr,"ldrdf: nothing to do\n");
exit(0);
}
if (!lastmodule) {
fprintf(stderr,"ldrdf: panic: module list exists, but lastmodule=NULL\n");
exit(3);
}
if (verbose)
printf("loading modules into memory\n");
/* The following stops 16 bit DOS from crashing whilst attempting to
work using segments > 64K */
if (sizeof(int) == 2) { /* expect a 'code has no effect' warning on 32 bit
platforms... */
if (lastmodule->coderel + lastmodule->f.code_len > 65535 ||
lastmodule->datarel + lastmodule->f.data_len > 65535) {
fprintf(stderr,"ldrdf: segment length has exceeded 64K; use a 32 bit "
"version.\nldrdf: code size = %05lx, data size = %05lx\n",
lastmodule->coderel + lastmodule->f.code_len,
lastmodule->datarel + lastmodule->f.data_len);
exit(1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -