4 * (C) Copyright 1989-1995
19 * The module lkarea.c contains the functions which
20 * create and link together all area definitions read
21 * from the .rel file(s).
23 * lkarea.c contains the following functions:
29 * lkarea.c contains no global variables.
32 /*)Function VOID newarea()
34 * The function newarea() creates and/or modifies area
35 * and areax structures for each A directive read from
36 * the .rel file(s). The function lkparea() is called
37 * to find tha area structure associated with this name.
38 * If the area does not yet exist then a new area
39 * structure is created and linked to any existing
40 * linked area structures. The area flags are copied
41 * into the area flag variable. For each occurence of
42 * an A directive an areax structure is created and
43 * linked to the areax structures associated with this
44 * area. The size of this area section is placed into
45 * the areax structure. The flag value for all subsequent
46 * area definitions for the same area are compared and
47 * flagged as an error if they are not identical.
48 * The areax structure created for every occurence of
49 * an A directive is loaded with a pointer to the base
50 * area structure and a pointer to the associated
51 * head structure. And finally, a pointer to this
52 * areax structure is loaded into the list of areax
53 * structures in the head structure. Refer to lkdata.c
54 * for details of the structures and their linkage.
57 * areax **halp pointer to an array of pointers
58 * int i counter, loop variable, value
60 * int narea number of areas in this head structure
61 * areax * taxp pointer to an areax structure
65 * area *ap Pointer to the current
67 * areax *axp Pointer to the current
69 * head *hp Pointer to the current
71 * int lkerr error flag
74 * addr_t eval() lkeval.c
75 * VOID exit() c_library
76 * int fprintf() c_library
77 * VOID getid() lklex.c
78 * VOID lkparea() lkarea.c
82 * The area and areax structures are created and
83 * linked with the appropriate head structures.
84 * Failure to allocate area or areax structure
85 * space will terminate the linker. Other internal
86 * errors most likely caused by corrupted .rel
87 * files will also terminate the linker.
91 * Create an area entry.
93 * A xxxxxx size nnnn flags mm
96 * | `------------- axp->a_size
97 * `------------------------- ap->a_id
117 axp->a_size = eval();
124 while (taxp->a_axp) {
132 if (i && (ap->a_flag != i)) {
133 fprintf(stderr, "Conflicting flags in area %.8s\n", id);
138 * Place pointer in header area list
141 fprintf(stderr, "No header defined\n");
146 for (i=0; i < narea ;++i) {
147 if (halp[i] == NULL) {
152 fprintf(stderr, "Header area list overflow\n");
156 /*)Function VOID lkparea(id)
158 * char * id pointer to the area name string
160 * The function lkparea() searches the linked area structures
161 * for a name match. If the name is not found then an area
162 * structure is created. An areax structure is created and
163 * appended to the areax structures linked to the area structure.
164 * The associated base area and head structure pointers are
165 * loaded into the areax structure.
168 * area * tap pointer to an area structure
169 * areax * taxp pointer to an areax structure
172 * area *ap Pointer to the current
174 * area *areap The pointer to the first
175 * area structure of a linked list
176 * areax *axp Pointer to the current
180 * VOID * new() lksym()
181 * char * strcpy() c_library
182 * int symeq() lksym.c
185 * Area and/or areax structures are created.
186 * Failure to allocate space for created structures
187 * will terminate the linker.
194 register struct area *tap;
195 register struct areax *taxp;
198 axp = (struct areax *) new (sizeof(struct areax));
200 if (symeq(id, ap->a_id)) {
211 ap = (struct area *) new (sizeof(struct area));
223 strncpy(ap->a_id, id, NCPS);
226 /*)Function VOID lnkarea()
228 * The function lnkarea() resolves all area addresses.
229 * The function evaluates each area structure (and all
230 * the associated areax structures) in sequence. The
231 * linking process supports four (4) possible area types:
233 * ABS/OVR - All sections (each individual areax
234 * section) starts at the identical base
235 * area address overlaying all other
236 * areax sections for this area. The
237 * size of the area is largest of the area
240 * ABS/CON - All sections (each individual areax
241 * section) are concatenated with the
242 * first section starting at the base
243 * area address. The size of the area
244 * is the sum of the section sizes.
246 * NOTE: Multiple absolute (ABS) areas are
247 * never concatenated with each other,
248 * thus absolute area A and absolute area
249 * B will overlay each other if they begin
250 * at the same location (the default is
251 * always address 0 for absolute areas).
253 * REL/OVR - All sections (each individual areax
254 * section) starts at the identical base
255 * area address overlaying all other
256 * areax sections for this area. The
257 * size of the area is largest of the area
260 * REL/CON - All sections (each individual areax
261 * section) are concatenated with the
262 * first section starting at the base
263 * area address. The size of the area
264 * is the sum of the section sizes.
266 * NOTE: Relocatable (REL) areas ae always concatenated
267 * with each other, thus relocatable area B
268 * (defined after area A) will follow
269 * relocatable area A independent of the
270 * starting address of area A. Within a
271 * specific area each areax section may be
272 * overlayed or concatenated with other
276 * If a base address for an area is specified then the
277 * area will start at that address. Any relocatable
278 * areas defined subsequently will be concatenated to the
279 * previous relocatable area if it does not have a base
282 * The names s_<areaname> and l_<areaname> are created to
283 * define the starting address and length of each area.
286 * addr_t rloc ;current relocation address
287 * char temp[] ;temporary string
288 * struct symbol *sp ;symbol structure
291 * area *ap Pointer to the current
293 * area *areap The pointer to the first
294 * area structure of a linked list
297 * int fprintf() c_library
298 * VOID lnksect() lkarea.c
299 * symbol *lkpsym() lksysm.c
300 * char * strncpy() c_library
301 * int symeq() lksysm.c
304 * All area and areax addresses and sizes are
305 * determined and saved in their respective
310 * Resolve all area addresses.
322 if (ap->a_flag&A_ABS) {
329 * Relocatable sections
334 rloc = ap->a_addr + ap->a_size;
338 * Create symbols called:
339 * s_<areaname> the start address of the area
340 * l_<areaname> the length of the area
343 if (! symeq(ap->a_id, _abs_)) {
344 strncpy(temp+2,ap->a_id,NCPS-2);
348 sp = lkpsym(temp, 1);
349 sp->s_addr = ap->a_addr;
354 sp = lkpsym(temp, 1);
355 sp->s_addr = ap->a_size;
363 /*)Function VOID lnksect()
365 * area * tap pointer to an area structure
367 * The function lnksect() is the function called by
368 * lnkarea() to resolve the areax addresses. Refer
369 * to the function lnkarea() for more detail. Pageing
370 * boundary and length errors will be reported by this
374 * addr_t size size of area
375 * addr_t addr address of area
376 * areax * taxp pointer to an areax structure
379 * int lkerr error flag
385 * All area and areax addresses and sizes area determined
386 * and linked into the structures.
391 register struct area *tap;
393 register addr_t size, addr;
394 register struct areax *taxp;
398 if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
400 "\n?ASlink-Warning-Paged Area %.8s Boundary Error\n", tap->a_id);
404 if (tap->a_flag&A_OVR) {
410 if (taxp->a_size > size)
416 * Concatenated sections
420 addr += taxp->a_size;
421 size += taxp->a_size;
426 if ((tap->a_flag&A_PAG) && (size > 256)) {
428 "\n?ASlink-Warning-Paged Area %.8s Length Error\n", tap->a_id);