Pristine Ack-5.5
[Ack-5.5.git] / util / led / finish.c
1 /*
2  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3  * See the copyright notice in the ACK home directory, in the file "Copyright".
4  */
5 #ifndef lint
6 static char rcsid[] = "$Id: finish.c,v 3.9 1994/06/24 10:34:44 ceriel Exp $";
7 #endif
8
9 #include <out.h>
10 #include "const.h"
11 #include "defs.h"
12 #include "memory.h"
13 #include "orig.h"
14 #include "scan.h"
15
16 extern bool     incore;
17 extern unsigned short   NLocals;
18 extern int      flagword;
19 extern struct outname   *searchname();
20
21 static          adjust_names();
22 static          handle_relos();
23 static          put_locals();
24 static          compute_origins();
25
26 /*
27  * We know all there is to know about the current module.
28  * Now we relocate the values in the emitted bytes and write
29  * those to the final output file. Then we compute the relative origins
30  * for the next module.
31  */
32 finish()
33 {
34         struct outhead  *head;
35         struct outsect  *sects;
36         struct outname  *names;
37         char            *chars;
38
39         get_modul();
40         head = (struct outhead *)modulptr(IND_HEAD);
41         sects = (struct outsect *)modulptr(IND_SECT(*head));
42         names = (struct outname *)modulptr(IND_NAME(*head));
43         chars = (char *)modulptr(IND_CHAR(*head));
44         adjust_names(names, head, chars);
45         handle_relos(head, sects, names);
46         if (!incore && !(flagword & SFLAG)) {
47                 put_locals(names, head->oh_nname);
48 #ifdef SYMDBUG
49                 put_dbug(OFF_DBUG(*head));
50 #endif /* SYMDBUG */
51         }
52         compute_origins(sects, head->oh_nsect);
53         skip_modul(head);
54 }
55
56 /*
57  * Adjust all local names for the move into core.
58  */
59 static
60 adjust_names(name, head, chars)
61         register struct outname *name;
62         struct outhead          *head;
63         register char           *chars;
64 {
65         register int            cnt;
66         register long           charoff;
67         struct outname          *base = name;
68
69         cnt = head->oh_nname;
70         charoff = OFF_CHAR(*head);
71         while (cnt--) {
72                 if (name->on_foff != (long)0)
73                         name->on_mptr = chars + (ind_t)(name->on_foff - charoff);
74                 name++;
75         }
76         if (! incore) {
77                 do_crs(base, head->oh_nname);
78         }
79 }
80
81 do_crs(base, count)
82         struct outname  *base;
83         unsigned        count;
84 {
85         register struct outname *name = base;
86
87         while (count--) {
88                 if ((name->on_type & S_TYP) == S_CRS) {
89                         char *s;
90                         struct outname *p;
91
92                         s = address(ALLOGCHR, (ind_t) name->on_valu);
93                         p = searchname(s, hash(s));
94
95                         if (flagword & RFLAG) {
96                                 name->on_valu = NLocals + (p -
97                                         (struct outname *)
98                                           address(ALLOGLOB, (ind_t) 0));
99                         }
100                         else {
101                                 name->on_valu = p->on_valu;
102                                 name->on_type &= ~S_TYP;
103                                 name->on_type |= (p->on_type & S_TYP);
104                         }
105                 }
106                 name++;
107         }
108 }
109
110 /*
111  * If all sections are in core, we can access them randomly, so we need only
112  * scan the relocation table once. Otherwise we must for each section scan
113  * the relocation table again, because the relocation entries of one section
114  * need not be consecutive.
115  */
116 static
117 handle_relos(head, sects, names)
118         struct outhead          *head;
119         struct outsect          *sects;
120         struct outname          *names;
121 {
122         register struct outrelo *relo;
123         register int            sectindex;
124         register int            nrelo;
125         register char           *emit;
126         extern char             *getemit();
127         extern struct outrelo   *nextrelo();
128         static long zeros[MAXSECT];
129
130         if (incore) {
131                 nrelo = head->oh_nrelo; sectindex = -1;
132                 startrelo(head); relo = nextrelo();
133                 while (nrelo--) {
134                         if (sectindex != relo->or_sect - S_MIN) {
135                                 sectindex = relo->or_sect - S_MIN;
136                                 emit = getemit(head, sects, sectindex);
137                         }
138                         relocate(head, emit, names, relo, 0L);
139                         relo++;
140                 }
141         } else {
142                 for (sectindex = 0; sectindex < head->oh_nsect; sectindex++) {
143                         if (sects[sectindex].os_flen) {
144                                 wrt_nulls(sectindex, zeros[sectindex]);
145                                 zeros[sectindex] = 0;
146                                 emit = getemit(head, sects, sectindex);
147                                 if (emit) {
148                                     nrelo = head->oh_nrelo; startrelo(head);
149                                     while (nrelo--) {
150                                         relo = nextrelo();
151                                         if (relo->or_sect - S_MIN == sectindex) {
152                                                 relocate(head,emit,names,relo,0L);
153                                                 /*
154                                                  * Write out the (probably changed)
155                                                  * relocation information.
156                                                  */
157                                                 if (flagword & (RFLAG|CFLAG))
158                                                         wr_relo(relo, 1);
159                                         }
160                                     }
161                                     wrt_emit(emit, sectindex,
162                                         sects[sectindex].os_flen);
163                                 }
164                                 else {
165                                     long sz = sects[sectindex].os_flen;
166                                     long sf = 0;
167                                     long blksz;
168                                     char *getblk();
169
170                                     emit = getblk(sz, &blksz, sectindex);
171                                     while (sz) {
172                                         long sz2 = sz > blksz ? blksz : sz;
173
174                                         rd_emit(emit, sz2);
175                                         nrelo = head->oh_nrelo; startrelo(head);
176                                         while (nrelo--) {
177                                             relo = nextrelo();
178                                             if (relo->or_sect-S_MIN==sectindex
179                                                 &&
180                                                 relo->or_addr >= sf
181                                                 &&
182                                                 relo->or_addr < sf + sz2){
183                                                 relocate(head,emit,names,relo,
184                                                          sf);
185                                                 /*
186                                                  * Write out the (probably changed)
187                                                  * relocation information.
188                                                  */
189                                                 if (flagword & (RFLAG|CFLAG))
190                                                         wr_relo(relo, 1);
191                                             }
192                                         }
193                                         wrt_emit(emit, sectindex, sz2);
194                                         sz -= sz2;
195                                         sf += sz2;
196                                     }
197                                 }
198                                 endemit(emit);
199                         }
200                         zeros[sectindex] += sects[sectindex].os_size -
201                                             sects[sectindex].os_flen;
202                 }
203         }
204 }
205
206 /*
207  * Write out the local names that must be saved.
208  */
209 static
210 put_locals(name, nnames)
211         struct outname          *name;
212         register unsigned       nnames;
213 {
214         register struct outname *oname = name;
215         register struct outname *iname = oname;
216
217         while (nnames--) {
218                 if ((iname->on_type & S_EXT) == 0 && mustsavelocal(iname)) {
219                         namerelocate(iname);
220                         addbase(iname);
221                         wrt_name(iname, 0);
222                         *oname++ = *iname;
223                 }
224                 iname++;
225         }
226         wr_name(name, (unsigned int) (oname - name));
227 }
228
229 /*
230  * Add all flen's and all (size - flen == zero)'s of preceding sections
231  * with the same number.
232  */
233 static
234 compute_origins(sect, nsect)
235         register struct outsect *sect;
236         register unsigned       nsect;
237 {
238         extern struct orig      relorig[];
239         register struct orig    *orig = relorig;
240
241         while (nsect--) {
242
243                 orig->org_size += sect->os_size;
244                 orig++; sect++;
245         }
246 }
247 #ifdef SYMDBUG
248
249 /*
250  * Write out what is after the string area. This is likely to be
251  * debugging information.
252  */
253 static
254 put_dbug(offdbug)
255         long            offdbug;
256 {
257         char            buf[512];
258         register int    nbytes;
259         register long   dbugsize;
260         extern long     objectsize;
261
262         dbugsize = objectsize - offdbug;
263         while (dbugsize) {
264                 nbytes = dbugsize > 512 ? 512 : dbugsize;
265                 rd_dbug(buf, (long)nbytes);
266                 wr_dbug(buf, (long) nbytes);
267                 dbugsize -= nbytes;
268         }
269 }
270 #endif /* SYMDBUG */