Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!linus!decvax!harpo!floyd!vax135!cornell!uw-beaver!ubc-visi!sfucmpt!kurn From: kurn@sfucmpt (Andrew Kurn) Newsgroups: net.unix-wizards Subject: (minor) ld buf Message-ID: <160@sfucmpt.UUCP> Date: Sat, 8-Oct-83 19:19:47 EDT Article-I.D.: sfucmpt.160 Posted: Sat Oct 8 19:19:47 1983 Date-Received: Wed, 12-Oct-83 21:48:20 EDT Lines: 208 I have recently had reason to investigate the behavior of ld, the loader. I would like to take this opportunity to share with you all the results of that work. When the loader is processing an archive trying to resolve undefined symbols it treats symbols defined in Text and Data segments in the expected manner. If one of these resolves a previously undefined reference, the member is loaded. However, when it sees a COMMON symbol which increases the size of the named COMMON block above what had previously been known, it notes the new size INDEPENDENTLY of whether or not it loads the current member. That is, a change in the size of a COMMON block is not taken as a reason to load the member. This may be thought of as the mildest kind of bug. C programmers are perhaps wondering what this might have to do with them. A little. It contrives to come about that the C compiler calls global declarations without initialization (int a; vs. int a=14;) a named COMMON block. Thus, despite the fact that brother Kernighan and brother Ritchie tell you that you must define storage for a global variable exactly once, you can get away with multiple definitions as long as none are initialized. OK, you say. Well yes, BUT: It gives rise to an obscure problem, which is the reason for all this. When running the loader with -M it is supposed to give you the names of all the members from an archive which it uses in the core load. Since in its opinion, it never loads a member which does nothing but define COMMON, it does not mention it in the list. Thus the list may be incomplete. No one in a million years would ever get hurt by this bug, you say, but, of course, I've been stung by this problem. Now it's conceivable that some turkey out there in terminal land depends on this quirky behavior, so I haven't felt free to change the actual action of the loader. My fix is to add a flag to the command line which reports it whenever the loader increases a COMMON block without loading the current module. The flag is -C The output thus created is mixed in with the -M output but may be distinguished since those lines begin with "C". Replies by mail! --- to sfucmpt!kurn KEEPERS OF UNIX: Please add a word about this problem to the manual page!!! (For those of you who still remember things like the 1620, the title of this piece is "How Far the Vestiges of Fortran Pursue Us".) Andrew Kurn Simon Fraser U. Canada Herewith are the changes to ld.c: *** ld.C Tue Oct 4 20:52:57 1983 --- ld.c Sat Oct 8 13:21:54 1983 *************** *** 218,223 int arflag; /* original copy of rflag */ int sflag; /* discard all symbols */ int Mflag; /* print rudimentary load map */ int nflag; /* pure procedure */ int dflag; /* define common even with rflag */ int zflag; /* demand paged */ --- 218,224 ----- int arflag; /* original copy of rflag */ int sflag; /* discard all symbols */ int Mflag; /* print rudimentary load map */ + int Cflag; /* mention modules which (only) define common -AK*/ int nflag; /* pure procedure */ int dflag; /* define common even with rflag */ int zflag; /* demand paged */ *************** *** 400,405 case 'M': Mflag++; continue; case 'x': xflag++; continue; --- 401,409 ----- case 'M': Mflag++; continue; + case 'C': /*-AK*/ + Cflag++; + continue; case 'x': xflag++; continue; *************** *** 566,572 int kind; kind = getfile(cp); ! if (Mflag) printf("%s\n", filname); switch (kind) { --- 570,576 ----- int kind; kind = getfile(cp); ! if (Mflag || (Cflag && kind)) printf("%s\n", filname); switch (kind) { *************** *** 727,732 register struct nlist *sp; struct nlist *savnext; int ndef, nlocal, type, size, nsymt; register int i; off_t maxoff; struct stat stb; --- 731,737 ----- register struct nlist *sp; struct nlist *savnext; int ndef, nlocal, type, size, nsymt; + int ncom; register int i; off_t maxoff; struct stat stb; *************** *** 747,752 error(1, "too small (old format .o?)"); ctrel = tsize; cdrel += dsize; cbrel += bsize; ndef = 0; nlocal = sizeof(cursym); savnext = nextsym; loc += N_SYMOFF(filhdr); --- 752,758 ----- error(1, "too small (old format .o?)"); ctrel = tsize; cdrel += dsize; cbrel += bsize; ndef = 0; + ncom = 0; nlocal = sizeof(cursym); savnext = nextsym; loc += N_SYMOFF(filhdr); *************** *** 780,785 continue; if (cursym.n_type == N_EXT+N_UNDF) { if (cursym.n_value > sp->n_value) sp->n_value = cursym.n_value; continue; } --- 786,792 ----- continue; if (cursym.n_type == N_EXT+N_UNDF) { if (cursym.n_value > sp->n_value) + { sp->n_value = cursym.n_value; ncom++; /* size of named common has */ } /* been increased -AK*/ *************** *** 781,786 if (cursym.n_type == N_EXT+N_UNDF) { if (cursym.n_value > sp->n_value) sp->n_value = cursym.n_value; continue; } if (sp->n_value != 0 && cursym.n_type == N_EXT+N_TEXT) --- 788,795 ----- if (cursym.n_value > sp->n_value) { sp->n_value = cursym.n_value; + ncom++; /* size of named common has */ + } /* been increased -AK*/ continue; } if (sp->n_value != 0 && cursym.n_type == N_EXT+N_TEXT) *************** *** 805,810 } free(curstr); return (1); } /* * No symbols defined by this library member. --- 814,826 ----- } free(curstr); return (1); + } + if (ncom && Cflag && libflg){ + /* + * Although not loaded, this member has caused common + * allocation to increase. -AK + */ + printf("C\t%s\n", archdr.ar_name); } /* * No symbols defined by this library member.