4 * (C) Copyright 1989-1995
12 * - change lkparea to use a_type == 0 as "virgin area" flag
13 * 02-Apr-98 JLH: add code to link 8051 data spaces
18 #if !defined(_MSC_VER)
25 * The module lkarea.c contains the functions which
26 * create and link together all area definitions read
27 * from the .rel file(s).
29 * lkarea.c contains the following functions:
35 * lkarea.c contains no global variables.
38 /*)Function VOID newarea()
40 * The function newarea() creates and/or modifies area
41 * and areax structures for each A directive read from
42 * the .rel file(s). The function lkparea() is called
43 * to find tha area structure associated with this name.
44 * If the area does not yet exist then a new area
45 * structure is created and linked to any existing
46 * linked area structures. The area flags are copied
47 * into the area flag variable. For each occurence of
48 * an A directive an areax structure is created and
49 * linked to the areax structures associated with this
50 * area. The size of this area section is placed into
51 * the areax structure. The flag value for all subsequent
52 * area definitions for the same area are compared and
53 * flagged as an error if they are not identical.
54 * The areax structure created for every occurence of
55 * an A directive is loaded with a pointer to the base
56 * area structure and a pointer to the associated
57 * head structure. And finally, a pointer to this
58 * areax structure is loaded into the list of areax
59 * structures in the head structure. Refer to lkdata.c
60 * for details of the structures and their linkage.
63 * areax **halp pointer to an array of pointers
64 * int i counter, loop variable, value
66 * int narea number of areas in this head structure
67 * areax * taxp pointer to an areax structure
71 * area *ap Pointer to the current
73 * areax *axp Pointer to the current
75 * head *hp Pointer to the current
77 * int lkerr error flag
80 * Addr_T eval() lkeval.c
81 * VOID exit() c_library
82 * int fprintf() c_library
83 * VOID getid() lklex.c
84 * VOID lkparea() lkarea.c
88 * The area and areax structures are created and
89 * linked with the appropriate head structures.
90 * Failure to allocate area or areax structure
91 * space will terminate the linker. Other internal
92 * errors most likely caused by corrupted .rel
93 * files will also terminate the linker.
97 * Create an area entry.
99 * A xxxxxx size nnnn flags mm
102 * | `------------- axp->a_size
103 * `------------------------- ap->a_id
109 register int i, narea;
123 axp->a_size = eval();
130 while (taxp->a_axp) {
138 /* if (i && (ap->a_flag != i)) { */
139 /* fprintf(stderr, "Conflicting flags in area %8s\n", id); */
144 * Place pointer in header area list
147 fprintf(stderr, "No header defined\n");
152 for (i=0; i < narea ;++i) {
153 if (halp[i] == NULL) {
158 fprintf(stderr, "Header area list overflow\n");
162 /*)Function VOID lkparea(id)
164 * char * id pointer to the area name string
166 * The function lkparea() searches the linked area structures
167 * for a name match. If the name is not found then an area
168 * structure is created. An areax structure is created and
169 * appended to the areax structures linked to the area structure.
170 * The associated base area and head structure pointers are
171 * loaded into the areax structure.
174 * area * tap pointer to an area structure
175 * areax * taxp pointer to an areax structure
178 * area *ap Pointer to the current
180 * area *areap The pointer to the first
181 * area structure of a linked list
182 * areax *axp Pointer to the current
186 * VOID * new() lksym()
187 * char * strcpy() c_library
188 * int symeq() lksym.c
191 * Area and/or areax structures are created.
192 * Failure to allocate space for created structures
193 * will terminate the linker.
200 register struct area *tap;
201 register struct areax *taxp;
204 axp = (struct areax *) new (sizeof(struct areax));
206 if (symeq(id, ap->a_id)) {
217 ap = (struct area *) new (sizeof(struct area));
229 strncpy(ap->a_id, id, NCPS);
233 /*)Function VOID lnkarea()
235 * The function lnkarea() resolves all area addresses.
236 * The function evaluates each area structure (and all
237 * the associated areax structures) in sequence. The
238 * linking process supports four (4) possible area types:
240 * ABS/OVR - All sections (each individual areax
241 * section) starts at the identical base
242 * area address overlaying all other
243 * areax sections for this area. The
244 * size of the area is largest of the area
247 * ABS/CON - All sections (each individual areax
248 * section) are concatenated with the
249 * first section starting at the base
250 * area address. The size of the area
251 * is the sum of the section sizes.
253 * NOTE: Multiple absolute (ABS) areas are
254 * never concatenated with each other,
255 * thus absolute area A and absolute area
256 * B will overlay each other if they begin
257 * at the same location (the default is
258 * always address 0 for absolute areas).
260 * REL/OVR - All sections (each individual areax
261 * section) starts at the identical base
262 * area address overlaying all other
263 * areax sections for this area. The
264 * size of the area is largest of the area
267 * REL/CON - All sections (each individual areax
268 * section) are concatenated with the
269 * first section starting at the base
270 * area address. The size of the area
271 * is the sum of the section sizes.
273 * NOTE: Relocatable (REL) areas ae always concatenated
274 * with each other, thus relocatable area B
275 * (defined after area A) will follow
276 * relocatable area A independent of the
277 * starting address of area A. Within a
278 * specific area each areax section may be
279 * overlayed or concatenated with other
283 * If a base address for an area is specified then the
284 * area will start at that address. Any relocatable
285 * areas defined subsequently will be concatenated to the
286 * previous relocatable area if it does not have a base
289 * The names s_<areaname> and l_<areaname> are created to
290 * define the starting address and length of each area.
293 * Addr_T rloc ;current relocation address
294 * char temp[] ;temporary string
295 * struct symbol *sp ;symbol structure
298 * area *ap Pointer to the current
300 * area *areap The pointer to the first
301 * area structure of a linked list
304 * int fprintf() c_library
305 * VOID lnksect() lkarea.c
306 * symbol *lkpsym() lksysm.c
307 * char * strncpy() c_library
308 * int symeq() lksysm.c
311 * All area and areax addresses and sizes are
312 * determined and saved in their respective
317 * Resolve all area addresses.
327 rloc[0] = rloc[1] = rloc[2] = rloc[3] = 0;
330 if (ap->a_flag&A_ABS) {
336 /* Determine memory space */
338 if (ap->a_flag & A_CODE) {
341 if (ap->a_flag & A_XDATA) {
344 if (ap->a_flag & A_BIT) {
348 * Relocatable sections
350 if (ap->a_type == 0) { /* JLH */
351 ap->a_addr = rloc[ locIndex ];
355 rloc[ locIndex ] = ap->a_addr + ap->a_size;
359 * Create symbols called:
360 * s_<areaname> the start address of the area
361 * l_<areaname> the length of the area
364 if (! symeq(ap->a_id, _abs_)) {
365 strncpy(temp+2,ap->a_id,NCPS-2);
369 sp = lkpsym(temp, 1);
370 sp->s_addr = ap->a_addr ;
371 /* sp->s_axp = ap->a_axp; JLH: was NULL; */
375 sp = lkpsym(temp, 1);
376 sp->s_addr = ap->a_size;
385 /*)Function VOID lnksect()
387 * area * tap pointer to an area structure
389 * The function lnksect() is the function called by
390 * lnkarea() to resolve the areax addresses. Refer
391 * to the function lnkarea() for more detail. Pageing
392 * boundary and length errors will be reported by this
396 * Addr_T size size of area
397 * Addr_T addr address of area
398 * areax * taxp pointer to an areax structure
401 * int lkerr error flag
407 * All area and areax addresses and sizes area determined
408 * and linked into the structures.
413 register struct area *tap;
415 register Addr_T size, addr;
416 register struct areax *taxp;
420 if ((tap->a_flag&A_PAG) && (addr & 0xFF)) {
422 "\n?ASlink-Warning-Paged Area %8s Boundary Error\n", tap->a_id);
426 if (tap->a_flag&A_OVR) {
432 if (taxp->a_size > size)
438 * Concatenated sections
442 addr += taxp->a_size;
443 size += taxp->a_size;
448 if ((tap->a_flag&A_PAG) && (size > 256)) {
450 "\n?ASlink-Warning-Paged Area %8s Length Error\n", tap->a_id);