4 * (C) Copyright 1989-1995
18 * The module lkarea.c contains the functions which
19 * create and link together all area definitions read
20 * from the .rel file(s).
22 * lkarea.c contains the following functions:
28 * lkarea.c contains no global variables.
31 /*)Function VOID newarea()
33 * The function newarea() creates and/or modifies area
34 * and areax structures for each A directive read from
35 * the .rel file(s). The function lkparea() is called
36 * to find tha area structure associated with this name.
37 * If the area does not yet exist then a new area
38 * structure is created and linked to any existing
39 * linked area structures. The area flags are copied
40 * into the area flag variable. For each occurence of
41 * an A directive an areax structure is created and
42 * linked to the areax structures associated with this
43 * area. The size of this area section is placed into
44 * the areax structure. The flag value for all subsequent
45 * area definitions for the same area are compared and
46 * flagged as an error if they are not identical.
47 * The areax structure created for every occurence of
48 * an A directive is loaded with a pointer to the base
49 * area structure and a pointer to the associated
50 * head structure. And finally, a pointer to this
51 * areax structure is loaded into the list of areax
52 * structures in the head structure. Refer to lkdata.c
53 * for details of the structures and their linkage.
56 * areax **halp pointer to an array of pointers
57 * int i counter, loop variable, value
59 * int narea number of areas in this head structure
60 * areax * taxp pointer to an areax structure
64 * area *ap Pointer to the current
66 * areax *axp Pointer to the current
68 * head *hp Pointer to the current
70 * int lkerr error flag
73 * Addr_T eval() lkeval.c
74 * VOID exit() c_library
75 * int fprintf() c_library
76 * VOID getid() lklex.c
77 * VOID lkparea() lkarea.c
81 * The area and areax structures are created and
82 * linked with the appropriate head structures.
83 * Failure to allocate area or areax structure
84 * space will terminate the linker. Other internal
85 * errors most likely caused by corrupted .rel
86 * files will also terminate the linker.
90 * Create an area entry.
92 * A xxxxxx size nnnn flags mm
95 * | `------------- axp->a_size
96 * `------------------------- ap->a_id
102 register int i, narea;
116 axp->a_size = eval();
123 while (taxp->a_axp) {
131 if (i && (ap->a_flag != i)) {
132 fprintf(stderr, "Conflicting flags in area %.8s\n", id);
137 * Place pointer in header area list
140 fprintf(stderr, "No header defined\n");
145 for (i=0; i < narea ;++i) {
146 if (halp[i] == NULL) {
151 fprintf(stderr, "Header area list overflow\n");
155 /*)Function VOID lkparea(id)
157 * char * id pointer to the area name string
159 * The function lkparea() searches the linked area structures
160 * for a name match. If the name is not found then an area
161 * structure is created. An areax structure is created and
162 * appended to the areax structures linked to the area structure.
163 * The associated base area and head structure pointers are
164 * loaded into the areax structure.
167 * area * tap pointer to an area structure
168 * areax * taxp pointer to an areax structure
171 * area *ap Pointer to the current
173 * area *areap The pointer to the first
174 * area structure of a linked list
175 * areax *axp Pointer to the current
179 * VOID * new() lksym()
180 * char * strcpy() c_library
181 * int symeq() lksym.c
184 * Area and/or areax structures are created.
185 * Failure to allocate space for created structures
186 * will terminate the linker.
193 register struct area *tap;
194 register struct areax *taxp;
197 axp = (struct areax *) new (sizeof(struct areax));
199 if (symeq(id, ap->a_id)) {
210 ap = (struct area *) new (sizeof(struct area));
222 strncpy(ap->a_id, id, NCPS);
225 /*)Function VOID lnkarea()
227 * The function lnkarea() resolves all area addresses.
228 * The function evaluates each area structure (and all
229 * the associated areax structures) in sequence. The
230 * linking process supports four (4) possible area types:
232 * ABS/OVR - All sections (each individual areax
233 * section) starts at the identical base
234 * area address overlaying all other
235 * areax sections for this area. The
236 * size of the area is largest of the area
239 * ABS/CON - All sections (each individual areax
240 * section) are concatenated with the
241 * first section starting at the base
242 * area address. The size of the area
243 * is the sum of the section sizes.
245 * NOTE: Multiple absolute (ABS) areas are
246 * never concatenated with each other,
247 * thus absolute area A and absolute area
248 * B will overlay each other if they begin
249 * at the same location (the default is
250 * always address 0 for absolute areas).
252 * REL/OVR - All sections (each individual areax
253 * section) starts at the identical base
254 * area address overlaying all other
255 * areax sections for this area. The
256 * size of the area is largest of the area
259 * REL/CON - All sections (each individual areax
260 * section) are concatenated with the
261 * first section starting at the base
262 * area address. The size of the area
263 * is the sum of the section sizes.
265 * NOTE: Relocatable (REL) areas ae always concatenated
266 * with each other, thus relocatable area B
267 * (defined after area A) will follow
268 * relocatable area A independent of the
269 * starting address of area A. Within a
270 * specific area each areax section may be
271 * overlayed or concatenated with other
275 * If a base address for an area is specified then the
276 * area will start at that address. Any relocatable
277 * areas defined subsequently will be concatenated to the
278 * previous relocatable area if it does not have a base
281 * The names s_<areaname> and l_<areaname> are created to
282 * define the starting address and length of each area.
285 * Addr_T rloc ;current relocation address
286 * char temp[] ;temporary string
287 * struct symbol *sp ;symbol structure
290 * area *ap Pointer to the current
292 * area *areap The pointer to the first
293 * area structure of a linked list
296 * int fprintf() c_library
297 * VOID lnksect() lkarea.c
298 * symbol *lkpsym() lksysm.c
299 * char * strncpy() c_library
300 * int symeq() lksysm.c
303 * All area and areax addresses and sizes are
304 * determined and saved in their respective
309 * Resolve all area addresses.
321 if (ap->a_flag&A_ABS) {
328 * Relocatable sections
333 rloc = ap->a_addr + ap->a_size;
337 * Create symbols called:
338 * s_<areaname> the start address of the area
339 * l_<areaname> the length of the area
342 if (! symeq(ap->a_id, _abs_)) {
343 strncpy(temp+2,ap->a_id,NCPS-2);
347 sp = lkpsym(temp, 1);
348 sp->s_addr = ap->a_addr;
353 sp = lkpsym(temp, 1);
354 sp->s_addr = ap->a_size;
362 /*)Function VOID lnksect()
364 * area * tap pointer to an area structure
366 * The function lnksect() is the function called by
367 * lnkarea() to resolve the areax addresses. Refer
368 * to the function lnkarea() for more detail. Pageing
369 * boundary and length errors will be reported by this
373 * Addr_T size size of area
374 * Addr_T addr address of area
375 * areax * taxp pointer to an areax structure
378 * int lkerr error flag
384 * All area and areax addresses and sizes area determined
385 * and linked into the structures.
390 register struct area *tap;
392 register Addr_T size, addr;
393 register struct areax *taxp;
397 if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
399 "\n?ASlink-Warning-Paged Area %.8s Boundary Error\n", tap->a_id);
403 if (tap->a_flag&A_OVR) {
409 if (taxp->a_size > size)
415 * Concatenated sections
419 addr += taxp->a_size;
420 size += taxp->a_size;
425 if ((tap->a_flag&A_PAG) && (size > 256)) {
427 "\n?ASlink-Warning-Paged Area %.8s Length Error\n", tap->a_id);