blob: b72d90af91e0eb0223c0b0011bae080b84df93cb [file] [log] [blame]
Adrien Destugues69a6e722017-06-03 10:17:17 +02001From f28f97241c95b6434d9a326d8349f25cd16bebfb Mon Sep 17 00:00:00 2001
2From: Adrien Destugues <pulkomandy@pulkomandy.tk>
3Date: Fri, 22 Jan 2016 21:01:19 +0100
4Subject: Import Kevin Thacker patch for runtime relocation support.
5
6
7diff --git a/sdas/linksrc/Makefile.in b/sdas/linksrc/Makefile.in
8index 56537a5..35f1922 100644
9--- a/sdas/linksrc/Makefile.in
10+++ b/sdas/linksrc/Makefile.in
11@@ -47,7 +47,7 @@ ASXXLIBSRC = strcmpi.c
PulkoMandy2aeca062014-06-28 23:18:25 +020012 SRC = lk_readnl.c lkaomf51.c lkar.c lkarea.c lkdata.c lkelf.c lkeval.c \
13 lkhead.c lklex.c lklib.c lklibr.c lklist.c lkmain.c lkmem.c \
14 lknoice.c lkout.c lkrel.c lkrloc.c lkrloc3.c lks19.c lksdcclib.c \
15- lksym.c sdld.c lksdcdb.c lkbank.c
16+ lksym.c sdld.c lksdcdb.c lkbank.c lkrrel.c
17
18 LKSOURCES = $(SRC) $(ASXXLIBSRC:%.c=$(ASXXLIB)/%.c)
19
Adrien Destugues69a6e722017-06-03 10:17:17 +020020diff --git a/sdas/linksrc/aslink.h b/sdas/linksrc/aslink.h
21index e0865f8..d9f6316 100644
22--- a/sdas/linksrc/aslink.h
23+++ b/sdas/linksrc/aslink.h
24@@ -1033,6 +1033,8 @@ extern int yflag; /* -y, enable SDCC Debug output
PulkoMandy2aeca062014-06-28 23:18:25 +020025 */
26 #endif
27
28+extern int hflag; /* Generate relocatable executable
29+ */
30 extern int pflag; /* print linker command file flag
31 */
32 extern int uflag; /* Listing relocation flag
Adrien Destugues69a6e722017-06-03 10:17:17 +020033diff --git a/sdas/linksrc/lkdata.c b/sdas/linksrc/lkdata.c
34index bb83900..bfaa197 100644
35--- a/sdas/linksrc/lkdata.c
36+++ b/sdas/linksrc/lkdata.c
37@@ -66,6 +66,9 @@ int oflag; /* Output file type flag
PulkoMandy2aeca062014-06-28 23:18:25 +020038 int objflg; /* Linked file/library object output flag
39 */
40
41+int hflag; /* Generate relocatable executable
42+ */
43+
44 #if NOICE
45 int jflag; /* NoICE output flag
46 */
Adrien Destugues69a6e722017-06-03 10:17:17 +020047diff --git a/sdas/linksrc/lkmain.c b/sdas/linksrc/lkmain.c
48index 1cc7a45..9d6f916 100644
49--- a/sdas/linksrc/lkmain.c
50+++ b/sdas/linksrc/lkmain.c
51@@ -233,6 +233,7 @@ main(int argc, char *argv[])
PulkoMandy2aeca062014-06-28 23:18:25 +020052 startp->f_idp = "";
53
54 pflag = 1;
55+ hflag = 0;
56
57 for(i=1; i<argc; i++) {
58 ip = ib;
Adrien Destugues69a6e722017-06-03 10:17:17 +020059@@ -960,6 +961,11 @@ parse()
PulkoMandy2aeca062014-06-28 23:18:25 +020060 }
61 return(0);
62
63+ case 'h':
64+ case 'H':
65+ hflag = 1;
66+ break;
67+
68 case 'I':
69 if (is_sdld() && !(TARGET_IS_Z80 || TARGET_IS_GB)) {
70 iramsav();
Adrien Destugues69a6e722017-06-03 10:17:17 +020071diff --git a/sdas/linksrc/lkrloc3.c b/sdas/linksrc/lkrloc3.c
72index cf184f2..6f11cdc 100644
73--- a/sdas/linksrc/lkrloc3.c
74+++ b/sdas/linksrc/lkrloc3.c
PulkoMandy2aeca062014-06-28 23:18:25 +020075@@ -31,6 +31,7 @@
76 */
77
78 #include "aslink.h"
79+#include "lkrrel.h"
80
81 /*)Module lkrloc3.c
82 *
Adrien Destugues69a6e722017-06-03 10:17:17 +020083@@ -332,6 +333,9 @@ relr3(void)
PulkoMandy2aeca062014-06-28 23:18:25 +020084 * Do remaining relocations
85 */
86 while (more()) {
87+ int output_relocation_record;
88+ int raddr;
89+
90 error = 0;
91 mode = (int) eval();
92
Adrien Destugues69a6e722017-06-03 10:17:17 +020093@@ -390,6 +394,95 @@ relr3(void)
PulkoMandy2aeca062014-06-28 23:18:25 +020094 reli -= paga + pags;
95 }
96
97+ /* KevT 28-05-2005 */
98+
99+ if (hflag)
100+ {
101+ output_relocation_record = 0;
102+ if (mode & R3_SYM)
103+ {
104+ /* If the symbol is defined in a absolute area, then we do not
105+ output a record. This allows us to reference absolute addresses
106+ in our code, but it can still be relocated */
107+
108+ /* If the symbol is relative, it is within our relocatable program */
109+
110+ /* printf("Symbol: %s\n",s[rindex]->s_id); */
111+ if ((s[rindex]->s_axp->a_bap->a_flag & A4_ABS)==0)
112+ {
113+ output_relocation_record=1;
114+ }
115+ }
116+ else
117+ {
118+ /* If the area is absolute then we do not output a record.
119+ This allows us to reference absolute memory, but still the code
120+ can be relocated. */
121+ /* If the area is relative, it refers to data that is part of the
122+ relocatable program */
123+
124+ /* printf("Area: %s\n",a[rindex]->a_bap->a_id); */
125+ if ((a[rindex]->a_bap->a_flag & A4_ABS)==0)
126+ {
127+ output_relocation_record=1;
128+ }
129+ }
130+
131+ if (output_relocation_record)
132+ {
133+ a_uint relocate_address = pc+(rtp-rtofst);
134+ if (hilo)
135+ {
136+ raddr = reli + ((rtval[rtp]&0x0ff)<<8) + (rtval[rtp+1]&0x0ff);
137+ }
138+ else
139+ {
140+ raddr = reli + ((rtval[rtp+1]&0x0ff)<<8) + (rtval[rtp]&0x0ff);
141+ }
142+ /*printf("Relocation modify address: %04x\n",relocate_address); */
143+ /*printf("Relocation address: %04x\n",raddr); */
144+ if (mode & R3_BYTE)
145+ {
146+ if (mode & R3_BYTX)
147+ {
148+ if (mode & R3_MSB)
149+ {
150+
151+relrec8hi(relocate_address,raddr);
152+ }
153+ else
154+ {
155+
156+relrec8lo(relocate_address,raddr);
157+ }
158+ }
159+ else
160+ {
161+ printf("not supported");
162+ }
163+ }
164+ else
165+ {
166+ if (mode & R3_BYTX)
167+ {
168+ if (mode & R3_MSB)
169+ {
170+ printf("not supported");
171+ }
172+ else
173+ {
174+ printf("not supported");
175+ }
176+ }
177+ else
178+ {
179+ relrec16(relocate_address);
180+ }
181+ }
182+ }
183+ }
184+
185+
186 /*
187 * R3_BYTE or R3_WORD operation
188 */
Adrien Destugues69a6e722017-06-03 10:17:17 +0200189@@ -755,6 +848,12 @@ rele3()
PulkoMandy2aeca062014-06-28 23:18:25 +0200190 if (uflag != 0) {
191 lkulist(0);
192 }
193+
194+ /* output relocation data */
195+ if (hflag) {
196+ relrecwrite();
197+ }
198+
199 if (oflag != 0) {
200 lkflush();
201 lkfclose();
Adrien Destugues69a6e722017-06-03 10:17:17 +0200202diff --git a/sdas/linksrc/lkrrel.c b/sdas/linksrc/lkrrel.c
203new file mode 100644
204index 0000000..e9e8383
205--- /dev/null
206+++ b/sdas/linksrc/lkrrel.c
PulkoMandy2aeca062014-06-28 23:18:25 +0200207@@ -0,0 +1,251 @@
208+/* (c) Kevin Thacker, May 2005 */
209+#include <stdio.h>
210+#include <string.h>
211+#include <stdlib.h>
212+#include "aslink.h"
213+#include "lkrrel.h"
214+
215+struct relrechead
216+{
217+ int count;
218+ struct relrec *head;
219+};
220+
221+/* 16-bit values, add full 16-bit base address */
222+
223+static struct relrechead head16= {0,NULL};
224+/* 8-bit, but add high byte of 16-bit base address */
225+static struct relrechead head8hi = {0,NULL};
226+/* 8-bit, but add low byte of 16-bit base address */
227+static struct relrechead head8lo = {0,NULL};
228+
229+/* internal; free's list */
230+static void relrecfree(struct relrechead *head)
231+{
232+ struct relrec *cur = head->head;
233+
234+ while (cur!=NULL)
235+ {
236+ struct relrec *next = cur->next;
237+ free(cur);
238+
239+ cur = next;
240+ }
241+}
242+
243+/* free relocation record list; e.g. on exit */
244+void freerelrec()
245+{
246+ relrecfree(&head16);
247+ relrecfree(&head8hi);
248+ relrecfree(&head8lo);
249+}
250+
251+/* internal; allocate a relocation record */
252+static void newrelrec(struct relrechead *head, a_uint addr, a_uint symaddr)
253+{
254+ struct relrec *rec;
255+
256+ rec = (struct relrec *) malloc(sizeof(struct relrec));
257+
258+ /* error if allocation failed */
259+ if (rec==NULL)
260+ return;
261+
262+ rec->addr = addr;
263+ rec->symaddr = symaddr;
264+
265+ /* add to start of list */
266+ rec->next = head->head;
267+ head->head = rec;
268+ head->count++;
269+}
270+
271+/* add item to 16-bit relocation record list */
272+void relrec16(a_uint addr)
273+{
274+ newrelrec(&head16, addr,0);
275+}
276+
277+/* add item to 8-bit (high) relocation record list */
278+void relrec8hi(a_uint addr, a_uint symaddr)
279+{
280+ newrelrec(&head8hi, addr,symaddr);
281+}
282+
283+/* add address to 8-bit (low) relocation list */
284+void relrec8lo(a_uint addr, a_uint symaddr)
285+{
286+ newrelrec(&head8lo, addr,symaddr);
287+}
288+
289+/* internal; compare two addresses within two relocate records */
290+static int relreccompare(const void *a, const void *b)
291+{
292+ const struct relrec *relreca = (const struct relrec *)a;
293+ const struct relrec *relrecb = (const struct relrec *)b;
294+
295+ return (relreca->addr-relrecb->addr);
296+}
297+
298+/* sort a list of relocate records and return an array of the records */
299+static struct relrec *relrecsort(struct relrechead *head)
300+{
301+ int count;
302+ struct relrec *reclist;
303+ struct relrec *cur;
304+
305+ if (head->count==0)
306+ return NULL;
307+
308+ /* allocate list to hold all items */
309+ reclist = (struct relrec *)malloc(sizeof(struct relrec)*head->count);
310+
311+ if (reclist==NULL)
312+ return NULL;
313+
314+ /* fill list */
315+ count = 0;
316+ cur = head->head;
317+ while (cur!=NULL)
318+ {
319+ memcpy(&reclist[count],cur,sizeof(struct relrec));
320+ count++;
321+ cur = cur->next;
322+ }
323+
324+ /* sort into ascending address order */
325+ qsort(reclist, count, sizeof(struct relrec),relreccompare);
326+
327+ return reclist;
328+}
329+
330+int outbyte(int addr, char byte)
331+{
332+ rtval[0] = addr&0x0ff;
333+ rtval[1] = (addr>>8)&0x0ff;
334+ rtval[2] = byte&0x0ff;
335+ addr+=1;
336+ rtflg[0] = 1;
337+ rtflg[1] = 1;
338+ rtflg[2] = 1;
339+ rtcnt = 3;
Adrien Destugues69a6e722017-06-03 10:17:17 +0200340+ ixx(1);
PulkoMandy2aeca062014-06-28 23:18:25 +0200341+ return addr;
342+}
343+
344+void relrecwritelist1(struct relrechead *list,int *addrptr)
345+{
346+ int i;
347+ struct relrec *relreclist;
348+ int addr;
349+
350+ addr = *addrptr;
351+
352+ relreclist = relrecsort(list);
353+
354+ if (relreclist!=NULL)
355+ {
356+ int prevaddr = 0;
357+ for (i=0; i<list->count; i++)
358+ {
359+ struct relrec *cur = &relreclist[i];
360+
361+ int delta = cur->addr-prevaddr;
362+
363+ if (delta>254)
364+ {
365+ int largedelta = delta-1;
366+ addr = outbyte(addr,0x0ff);
367+ addr = outbyte(addr,largedelta&0x0ff);
368+ addr = outbyte(addr,(largedelta>>8)&0x0ff);
369+ delta = 1;
370+ }
371+ prevaddr = cur->addr;
372+ addr = outbyte(addr,delta&0x0ff);
373+ }
374+
375+ free(relreclist);
376+ }
377+
378+ addr = outbyte(addr, 0);
379+
380+ *addrptr = addr;
381+
382+}
383+
384+void relrecwritelist2(struct relrechead *list,int *addrptr)
385+{
386+ int i;
387+ struct relrec *relreclist;
388+ int addr;
389+
390+ addr = *addrptr;
391+
392+ relreclist = relrecsort(list);
393+
394+ if (relreclist!=NULL)
395+ {
396+ int prevaddr = 0;
397+ for (i=0; i<list->count; i++)
398+ {
399+ struct relrec *cur = &relreclist[i];
400+ int delta = cur->addr-prevaddr;
401+ prevaddr = cur->addr;
402+
403+ if (delta>254)
404+ {
405+ int largedelta = delta-1;
406+ addr = outbyte(addr,0x0ff);
407+ addr = outbyte(addr,largedelta&0x0ff);
408+ addr = outbyte(addr,(largedelta>>8)&0x0ff);
409+ delta = 1;
410+ }
411+
412+ addr = outbyte(addr,delta&0x0ff);
413+ addr = outbyte(addr,cur->symaddr&0x0ff);
414+ }
415+
416+ free(relreclist);
417+ }
418+
419+ addr = outbyte(addr,0);
420+
421+ *addrptr = addr;
422+
423+}
424+
425+
426+void relrecwrite()
427+{
428+ int areasize = 0;
429+
430+ struct area *cur = areap;
431+ while (cur!=NULL)
432+ {
433+ areasize+=cur->a_size;
434+ cur=cur->a_ap;
435+ }
436+
Adrien Destugues69a6e722017-06-03 10:17:17 +0200437+ //printf("total length before relocation records: %04x\n",areasize);
PulkoMandy2aeca062014-06-28 23:18:25 +0200438+
439+ /* re-write offset to relocation records */
440+ rtval[0] = 0;
441+ rtval[1] = 0;
442+ rtval[2] = areasize&0x0ff;
443+ rtval[3] = (areasize>>8)&0x0ff;
444+ rtflg[0] = 1;
445+ rtflg[1] = 1;
446+ rtflg[2] = 1;
447+ rtflg[3] = 1;
448+ rtcnt = 4;
Adrien Destugues69a6e722017-06-03 10:17:17 +0200449+ ixx(1);
PulkoMandy2aeca062014-06-28 23:18:25 +0200450+
451+
452+ int addr = areasize;
453+
454+
455+ relrecwritelist1(&head16,&addr);
456+ relrecwritelist1(&head8lo,&addr);
457+ relrecwritelist2(&head8hi,&addr);
458+}
Adrien Destugues69a6e722017-06-03 10:17:17 +0200459diff --git a/sdas/linksrc/lkrrel.h b/sdas/linksrc/lkrrel.h
460new file mode 100644
461index 0000000..ca1cfd4
462--- /dev/null
463+++ b/sdas/linksrc/lkrrel.h
PulkoMandy2aeca062014-06-28 23:18:25 +0200464@@ -0,0 +1,17 @@
465+/* relocation record */
466+struct relrec
467+{
468+ /* next item */
469+ struct relrec *next;
470+
471+ /* address of relocate */
472+ a_uint addr;
473+
474+ a_uint symaddr;
475+};
476+
477+void relrec16(a_uint addr);
478+void relrec8lo(a_uint addr, a_uint symaddr);
479+void relrec8hi(a_uint addr, a_uint symaddr);
480+void freerelrec();
481+void relrecwrite();
Adrien Destugues69a6e722017-06-03 10:17:17 +0200482--
4832.7.0
484
485