#include #include #include #include #include #include #include "tool.h" #include "link.h" #include #include #include #define ALLOC_MODULE 5000 #ifdef USE_NM # ifndef NM_ABSPATH # define NM_ABSPATH "/usr/bin/nm" # endif /* * BFD-support (esp. for Alpha) added by: * Manabe Takashi */ #ifndef __alpha__ /* * Check if the module is an a.out module, so that we can skip * the first '_'. We now use a unified ELF-like symbol table format */ static int is_a_out(const char *objname) // 1 == a.out, 0 == ELF { int fd; char buf[4]; int a_out = 1; //if open fails, the following call to mod_open fails too if ((fd = open(objname, O_RDONLY)) > 0) { if (read(fd, buf, 4) == 4) { if (buf[0] == 0177 && strncmp(buf +1, "ELF", 3) == 0) a_out = 0; } close(fd); } return a_out; } #endif /* Ouvre le fichier et retourne NULL si erreur. */ static FILE *module_open (const char *objname) { FILE *ret = NULL; struct stat buf; if (stat (objname,&buf) != -1){ char cmd[300]; sprintf (cmd, NM_ABSPATH " -p %s",objname); ret = popen_err (cmd,"r",0); }else{ depmod_error ("%s does not exist",objname); } return ret; } #endif /* GŠre la liste de tous les modules rencontr‚ durant le link */ PUBLIC MODULES::MODULES() { /* #Sp‚cification: librairies / nombre maximum Un nombre maximum de 255 librairie est permis pour le link */ tblibs = (char**)malloc_err (255*sizeof(char*),1); nblib = 0; tbmod = (MODULE*)malloc_err (ALLOC_MODULE*sizeof(MODULE),1); nbmod = 0; } /* Finalise l'information sur un module. */ PRIVATE void MODULES::setmod ( MODULE *mod, SYMBOL *tbpub[], int nbpub, SYMBOL *tbext[], int nbext, int module_requis) { mod->is_load = module_requis; mod->pub.nb = nbpub; mod->ext.nb = nbext; if (nbpub > 0){ int size = nbpub*sizeof(SYMBOL*); mod->pub.tb = (SYMBOL**)malloc_err(size,1); memcpy (mod->pub.tb,tbpub,size); }else{ mod->pub.tb = NULL; } if (nbext > 0){ int size = nbext*sizeof(SYMBOL*); mod->ext.tb = (SYMBOL**)malloc_err(size,1); memcpy (mod->ext.tb,tbext,size); if (module_requis){ SYMBOL **ptext = mod->ext.tb; for (int i=0; irequis = 1; } }else{ mod->ext.tb = NULL; } } /* Create a module entry in the list of module. This module generally do not is not related to any real file. */ PUBLIC MODULE *MODULES::setdummy (const char *name) { MODULE *mod = tbmod+nbmod++; mod->name = alloctxt_add (name); mod->lib = -1; mod->is_load = 0; mod->pub.nb = mod->ext.nb = 0; mod->ext.tb = NULL; mod->pub.tb = NULL; return mod; } /* Lit les symboles d'un objet et enregistre dans syms Retourne -1 si erreur. */ PUBLIC int MODULES::loadobj(SYMBOLS &syms, const char *objname) { MODULE *mod = tbmod+nbmod++; mod->name = alloctxt_add (objname); mod->lib = -1; #ifndef USE_NM return load_obj(syms, objname, mod); #else int ret = -1; #ifdef __alpha__ int skip_us = 0; // no need to skip #else int skip_us = is_a_out(objname); // 1 == a.out, 0 == ELF #endif FILE *fin = module_open (objname); if (fin != NULL){ SYMBOL *tbext[5000]; int nbext = 0; SYMBOL *tbpub[5000]; int nbpub = 0; int module_requis=0; ret = 0; char rbuf[200]; while (fgets(rbuf,sizeof(rbuf)-1,fin)!=NULL){ char buf[200]; str_strip (rbuf,buf); char *name = buf; if (buf[0] == ' ') { while (*name == ' ' || *name == '\t') name ++; name += 2; // skip '[CUTtdD] ' } else { while (*name != ' ' && *name) name ++; name += 3; // skip ' [CUTtdD] ' } if (skip_us) { if (*name != '_') continue; name ++; } if (buf[0] == ' '){ tbext[nbext++] = syms.add (name,NULL,SYM_REQUIS ,module_requis,0); }else if (isxdigit(buf[0])){ tbpub[nbpub++] = syms.add (name,mod,SYM_DEFINI ,module_requis,buf[9] == 'C'); }else{ break; } } pclose (fin); setmod (mod,tbpub,nbpub,tbext,nbext,1); } return ret; #endif } /* Affiche la liste des modules qui necessite un symbole (indefini). */ PUBLIC void MODULES::showundef (SYMBOL *undef, FILE *fout) { MODULE *ptmod = tbmod; int nb = 0; for (int i=0; iis_load){ SYMBOL **ptext = ptmod->ext.tb; int nbext = ptmod->ext.nb; for (int e=0; ename); nb = 1; } if (ptmod->lib == -1){ fprintf (fout,"\t %s\n",ptmod->name); }else{ fprintf (fout,"\t %s(%s)\n",ptmod->name ,tblibs[ptmod->lib]); } break; } } } } } /* Affiche la liste des symboles non d‚finies. Retourne le nombre trouv‚ ou 0 si ok. */ PUBLIC int MODULES::findundef (FILE *fout) { MODULE *ptmod = tbmod; int ret = 0; for (int i=0; iis_load){ SYMBOL **ptext = ptmod->ext.tb; int nbext = ptmod->ext.nb; for (int e=0; edefini){ if (ret == 0){ fprintf (fout,"Undefined symbols:\n"); } showundef (*ptext,fout); (*ptext)->defini = 1; // Evite de rementionner // le symbole ret++; } } } } return ret; } /* Affiche la liste des modules qui seront inclus dans l'ex‚cutable Retourne le nombre de modules trouv‚s. */ PUBLIC int MODULES::showload (FILE *fout) { MODULE *ptmod = tbmod; int ret = 0; for (int i=0; iis_load){ ret++; fprintf (fout,"%s ",ptmod->name); } } if (ret) fprintf (fout,"\n"); return ret; } /* Affiche la liste de tous les modules en m‚moire. Utilis‚ pour d‚bug */ PUBLIC void MODULES::showall (FILE *fout) { MODULE *ptmod = tbmod; for (int i=0; iname,ptmod->is_load); SYMBOL **ptpub = ptmod->pub.tb; int nbpub = ptmod->pub.nb; int e; for (e=0; ename,ptsym->requis ,ptsym->defini,ptsym->vue_avant ,ptsym->is_common,ptsym->force); } SYMBOL **ptext = ptmod->ext.tb; int nbext = ptmod->ext.nb; for (e=0; ename,(*ptext)->defini); } } } static int cmp (const void *p1, const void *p2) { MODULE *pt1 = *(MODULE**)p1; MODULE *pt2 = *(MODULE**)p2; return strcmp(pt1->name,pt2->name); } /* Format the dependancy list of a module into a simple makefile */ PUBLIC void MODULES::prtdepend ( FILE *fout, const char *dontcare, // Module we don't want to know about // in the dependancy lists int verbose, // Print all module visited int showerror) // Shows undefined symbol { MODULE **tbdep = new MODULE*[nbmod]; MODULE *ptmod = tbmod; for (int i=0; iname,dontcare)!=0){ SYMBOL **ptext = ptmod->ext.tb; int nbext = ptmod->ext.nb; int nbdepmod = 0; int nberr = 0; for (int e=0; emodule; if (mod==NULL){ if (nberr == 0){ depmod_error ("*** Unresolved symbols in module %s" ,ptmod->name); } if (showerror){ depmod_error ("\t%s",(*ptext)->name); } nberr++; }else{ if (strcmp(mod->name,dontcare)!=0){ int m; for (m=0; mname); // Sort so it is nicer to look at :-) qsort(tbdep,nbdepmod,sizeof(MODULE*),cmp); fprintf (fout,"%s:",ptmod->name); for (int m=0; mname); } fprintf (fout,"\n\n"); } } delete [] tbdep; } #ifdef TEST int main (int argc, char *argv[]) { if (argc > 1){ SYMBOLS syms; MODULES mods; for (int i=1; i