Pristine Ack-5.5
[Ack-5.5.git] / util / led / extract.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: extract.c,v 3.11 1994/06/24 10:34:40 ceriel Exp $";
7 #endif
8
9 #include <out.h>
10 #include "const.h"
11 #include "debug.h"
12 #include "defs.h"
13 #include "memory.h"
14 #include "orig.h"
15 #include "scan.h"
16
17 static          get_names();
18 static          process();
19 static          getexternal();
20 static          redefine();
21 static          transfer();
22
23 extern ind_t savechar();
24 /*
25  * Get section sizes and symboltable information from present module.
26  */
27 extract()
28 {
29         struct outhead  head;
30
31         get_modul();
32         /*
33          * Copy head because we need it so often but it can change place,
34          * so we can't trust a pointer to it.
35          */
36         head = *(struct outhead *)modulptr(IND_HEAD);
37         get_names(&head);
38         process(&head);
39         skip_modul(&head);
40 }
41
42 unsigned short  NLocals = 0;    /* Number of local names to be saved. */
43 unsigned short  NGlobals = 0;   /* Number of global names. */
44
45 /*
46  * Walk through the nametable of this module, counting the locals that must
47  * appear in the final output file if this module is linked.
48  * That number will be returned.
49  */
50 static
51 get_names(head)
52         register struct outhead *head;
53 {
54         register int    nnames;
55         register ind_t  nameindex, charindex;
56         register ind_t  charoff;
57         extern int      flagword;
58
59         nnames = head->oh_nname;
60         nameindex = IND_NAME(*head);
61         charindex = IND_CHAR(*head);
62         charoff = OFF_CHAR(*head);
63         while (nnames--) {
64                 struct outname          name;   /* A local copy. */
65                 /*
66                  * Because savelocal/getexternal might relocate the modules
67                  * we have to compute the core addresses again.
68                  */
69                 name = *(struct outname *)modulptr(nameindex);
70                 /*
71                  * Change the offset in file into an offset in the memory area.
72                  * There will always be at least a header before the string
73                  * area, so we don't have to be afraid to confuse "no name"
74                  * with "the first name".
75                  */
76                 if (name.on_foff) {
77                         if (name.on_foff < charoff ||
78                             name.on_foff >= charoff+head->oh_nchar) {
79                                 fatal("illegal offset in name");
80                         }
81                         name.on_foff += charindex - charoff;
82                 }
83                 namerelocate(&name);
84                 if ((name.on_type & S_TYP) == S_CRS) {
85                         name.on_valu += charindex - charoff;
86                         name.on_valu = savechar(ALLOGCHR, (ind_t)name.on_valu);
87                 }
88                 if (name.on_type & S_EXT) {
89                         getexternal(&name);
90                 } else {
91                         /*
92                          * The only thing we want to know about locals is
93                          * whether they must appear in the output file.
94                          */
95                         if (!(flagword & SFLAG) && mustsavelocal(&name)) {
96                                 NLocals++;
97                                 savelocal(&name);
98                         }
99                 }
100                 nameindex += sizeof(struct outname);
101         }
102 }
103
104 extern struct orig      relorig[];
105
106 static
107 process(head)
108         register struct outhead *head;
109 {
110         register struct outsect *sects;
111         register struct outsect *outsp;
112         register int            nsect;
113         register struct orig    *orig = relorig;
114         extern struct outhead   outhead;
115         extern struct outsect   outsect[];
116
117         outhead.oh_nrelo += head->oh_nrelo;
118         outhead.oh_nemit += head->oh_nemit;
119         if (head->oh_nsect > outhead.oh_nsect)
120                 outhead.oh_nsect = head->oh_nsect;
121         sects = (struct outsect *)modulptr(IND_SECT(*head));
122         nsect = head->oh_nsect;
123         outsp = outsect;
124         while (nsect--) {
125                 if (sects->os_flen) {
126                         /* contains non-zero stuff */
127                         outhead.oh_nemit += outsp->os_size - outsp->os_flen;
128                         outsp->os_flen = outsp->os_size + sects->os_flen;
129                 }
130                 else {
131                         outsp->os_flen += sects->os_flen;
132                 }
133                 outsp->os_size += sects->os_size;
134                 /*
135                  * Add all flen's and all (size - flen == zero)'s of
136                  * preceding sections with the same number.
137                  */
138                 orig->org_size = outsp->os_size;
139                 orig++; outsp++; sects++;
140         }
141 }
142
143 /*
144  * Add relocation constant for names in user defined sections.
145  * The value of a common name indicates a size instead of an offset,
146  * and hence shouldn't be relocated.
147  * Otherwise we just add the accumulated size of all normal parts in preceding
148  * sections with the same size.
149  */
150 namerelocate(name)
151         register struct outname *name;
152 {
153         register int    type = name->on_type;
154         register int    sct = type & S_TYP;
155
156         if (sct == S_UND || sct == S_ABS || sct == S_CRS)
157                 return;
158         if (type & S_COM) {
159                 if ( ! (type&S_EXT) ) fatal("local commons should be handled by the assembler") ;
160                 return;
161         }
162
163         name->on_valu += relorig[(type & S_TYP) - S_MIN].org_size;
164 }
165
166 /*
167  * If we see this name for the first time, we must remember it for
168  * we might need it later on. Otherwise it must confirm to what we already
169  * know about it, and eventually add to that knowledge.
170  */
171 static
172 getexternal(name)
173         register struct outname *name;
174 {
175         register char           *string;
176         register int            h;
177         register struct outname *old;
178         extern int              hash();
179         extern struct outname   *searchname();
180
181         string = modulptr((ind_t)name->on_foff);
182         h = hash(string);
183         old = searchname(string, h);
184         if (old == (struct outname *)0) {
185                 NGlobals++;
186                 entername(name, h);
187                 if (ISUNDEFINED(name)) {
188                         verbose("requires %s", string, 0, 0, 0);
189                 }
190         } else if (!ISUNDEFINED(name)) {
191                 if (ISUNDEFINED(old)) {
192                         name->on_mptr = string; /* Just for convenience. */
193                         transfer(name, old);
194                 } else {
195                         name->on_mptr = string; /* Just for convenience. */
196                         redefine(name, old);
197                 }
198         }
199 }
200
201 /*
202  * Handle the redefinition of `new' in the current module.
203  * A name can be defined in three ways, in increasing priority:
204  *      undefined,
205  *      common,
206  *      defined in a section.
207  * A name may become "higher" when defined, but not "lower".
208  * A redefinition as common is allowed. It is ignored, but a warning is given
209  * when the desired section of `new' doesn't correspond with the section of
210  * `old'. If a common definition is given again for a name, we take the
211  * greatest value so that the common declared name always has enough space.
212  * If a common is defined as a not-common, the old definition is ignored.
213  */
214 static
215 redefine(new, old)
216         register struct outname *new, *old;
217 {
218         if (!ISCOMMON(old)) {
219                 if (!ISCOMMON(new))
220                         error("%s: multiply defined", new->on_mptr);
221                 /*
222                 else if ((new->on_type & S_TYP) != (old->on_type & S_TYP))
223                         warning("%s: sections differ", new->on_mptr);
224                 */
225         } else {
226                 /* `Old' is common. */
227                 if (ISCOMMON(new)) {
228                         if ((new->on_type & S_TYP) != (old->on_type & S_TYP))
229                                 warning("%s: sections differ", new->on_mptr);
230
231                         if (new->on_valu > old->on_valu)
232                                 old->on_valu = new->on_valu;
233                 } else {
234                         transfer(new, old);
235                 }
236         }
237 }
238
239 /*
240  * Transfer things we want to know from `src' to `dst'.
241  */
242 static
243 transfer(src, dst)
244         register struct outname *src, *dst;
245 {
246         debug("%s defined here\n", src->on_mptr, 0, 0, 0);
247         dst->on_valu = src->on_valu;
248         dst->on_type = src->on_type;
249         dst->on_desc = src->on_desc;
250 }