301
|
1 /*
|
|
2 link.c
|
|
3 Copyright © 2009 William Astle
|
|
4
|
|
5 This file is part of LWLINK.
|
|
6
|
|
7 LWLINK is free software: you can redistribute it and/or modify it under the
|
|
8 terms of the GNU General Public License as published by the Free Software
|
|
9 Foundation, either version 3 of the License, or (at your option) any later
|
|
10 version.
|
|
11
|
|
12 This program is distributed in the hope that it will be useful, but WITHOUT
|
|
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
15 more details.
|
|
16
|
|
17 You should have received a copy of the GNU General Public License along with
|
|
18 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
19
|
|
20
|
|
21 Resolve section and symbol addresses; handle incomplete references
|
|
22 */
|
|
23
|
|
24 #ifdef HAVE_CONFIG_H
|
|
25 #include "config.h"
|
|
26 #endif
|
|
27
|
|
28 #include <stdlib.h>
|
|
29
|
|
30 #include "lwlink.h"
|
|
31 #include "util.h"
|
|
32
|
|
33 struct section_list
|
|
34 {
|
|
35 section_t *ptr; // ptr to section structure
|
|
36 int forceaddr; // was this force to an address by the link script?
|
|
37 };
|
|
38
|
|
39 static struct section_list *sectlist = NULL;
|
|
40 static int nsects = 0;
|
|
41
|
|
42 // work out section load order and resolve base addresses for each section
|
|
43 // make a list of sections to load in order
|
|
44 void resolve_sections(void)
|
|
45 {
|
|
46 int laddr = 0;
|
|
47 int ln, sn, fn;
|
|
48
|
|
49 for (ln = 0; ln < linkscript.nlines; ln++)
|
|
50 {
|
|
51 if (linkscript.lines[ln].sectname)
|
|
52 {
|
|
53 int f = 0;
|
|
54 // named section
|
|
55 // look for all instances of a section by the specified name
|
|
56 // and resolve base addresses and add to the list
|
|
57 for (fn = 0; fn < ninputfiles; fn++)
|
|
58 {
|
|
59 for (sn = 0; sn < inputfiles[fn] -> nsections; sn++)
|
|
60 {
|
|
61 if (!strcmp(linkscript.lines[ln].sectname, inputfiles[fn] -> sections[sn].name))
|
|
62 {
|
|
63 // we have a match
|
|
64 sectlist = lw_realloc(sectlist, sizeof(struct section_list) * (nsects + 1));
|
|
65 sectlist[nsects].ptr = &(inputfiles[fn] -> sections[sn]);
|
|
66
|
|
67 inputfiles[fn] -> sections[sn].processed = 1;
|
|
68 if (!f && linkscript.lines[ln].loadat >= 0)
|
|
69 {
|
|
70 f = 1;
|
|
71 sectlist[nsects].forceaddr = 1;
|
|
72 laddr = linkscript.lines[ln].loadat;
|
|
73 }
|
|
74 else
|
|
75 {
|
|
76 sectlist[nsects].forceaddr = 0;
|
|
77 }
|
|
78 inputfiles[fn] -> sections[sn].loadaddress = laddr;
|
|
79 nsects++;
|
|
80 }
|
|
81 }
|
|
82 }
|
|
83 }
|
|
84 else
|
|
85 {
|
|
86 // wildcard section
|
|
87 // look for all sections not yet processed that match flags
|
|
88
|
|
89 int f = 0;
|
|
90 int fn0, sn0;
|
|
91 char *sname;
|
|
92
|
|
93 // named section
|
|
94 // look for all instances of a section by the specified name
|
|
95 // and resolve base addresses and add to the list
|
|
96 for (fn0 = 0; fn0 < ninputfiles; fn0++)
|
|
97 {
|
|
98 for (sn0 = 0; sn0 < inputfiles[fn0] -> nsections; sn0++)
|
|
99 {
|
|
100 // ignore if the "no flags" bit says to
|
|
101 if (linkscript.lines[ln].noflags && (inputfiles[fn0] -> sections[sn0].flags & linkscript.lines[ln].noflags))
|
|
102 continue;
|
|
103 // ignore unless the yes flags tell us not to
|
|
104 if (linkscript.lines[ln].yesflags && (inputfiles[fn0] -> sections[sn0].flags & linkscript.lines[ln].yesflags == 0))
|
|
105 continue;
|
|
106 if (inputfiles[fn0] -> sections[sn0].processed == 0)
|
|
107 {
|
|
108 sname = inputfiles[fn0] -> sections[sn0].name;
|
|
109 for (fn = 0; fn < ninputfiles; fn++)
|
|
110 {
|
|
111 for (sn = 0; sn < inputfiles[fn] -> nsections; sn++)
|
|
112 {
|
|
113 if (!strcmp(sname, inputfiles[fn] -> sections[sn].name))
|
|
114 {
|
|
115 // we have a match
|
|
116 sectlist = lw_realloc(sectlist, sizeof(struct section_list) * (nsects + 1));
|
|
117 sectlist[nsects].ptr = &(inputfiles[fn] -> sections[sn]);
|
|
118
|
|
119 inputfiles[fn] -> sections[sn].processed = 1;
|
|
120 if (!f && linkscript.lines[ln].loadat >= 0)
|
|
121 {
|
|
122 f = 1;
|
|
123 sectlist[nsects].forceaddr = 1;
|
|
124 laddr = linkscript.lines[ln].loadat;
|
|
125 }
|
|
126 else
|
|
127 {
|
|
128 sectlist[nsects].forceaddr = 0;
|
|
129 }
|
|
130 inputfiles[fn] -> sections[sn].loadaddress = laddr;
|
|
131 nsects++;
|
|
132 }
|
|
133 }
|
|
134 }
|
|
135 }
|
|
136 }
|
|
137 }
|
|
138 }
|
|
139 }
|
|
140
|
|
141 // theoretically, all the base addresses are set now
|
|
142 }
|