* Makefile.in: added relax, also made three stage go through a
[deliverable/binutils-gdb.git] / ld / relax.c
1
2
3 /*
4
5 new age linking
6
7
8 Tie together all the interseting blocks
9
10 */
11
12
13 #include "bfd.h"
14 #include "../bfd/seclet.h"
15 #include "coff/internal.h"
16 #include "sysdep.h"
17
18 #include "ldlang.h"
19 #include "ld.h"
20 #include "ldwrite.h"
21 #include "ldmisc.h"
22 #include "ldsym.h"
23 #include "ldgram.h"
24
25 static void
26 DEFUN(build_it,(statement),
27 lang_statement_union_type *statement)
28 {
29 switch (statement->header.type) {
30 case lang_fill_statement_enum:
31 {
32 #if 0
33 bfd_byte play_area[SHORT_SIZE];
34 unsigned int i;
35 bfd_putshort(output_bfd, statement->fill_statement.fill, play_area);
36 /* Write out all entire shorts */
37 for (i = 0;
38 i < statement->fill_statement.size - SHORT_SIZE + 1;
39 i+= SHORT_SIZE)
40 {
41 bfd_set_section_contents(output_bfd,
42 statement->fill_statement.output_section,
43 play_area,
44 statement->data_statement.output_offset +i,
45 SHORT_SIZE);
46
47 }
48
49 /* Now write any remaining byte */
50 if (i < statement->fill_statement.size)
51 {
52 bfd_set_section_contents(output_bfd,
53 statement->fill_statement.output_section,
54 play_area,
55 statement->data_statement.output_offset +i,
56 1);
57
58 }
59 #endif
60 }
61 break;
62 case lang_data_statement_enum:
63 {
64 abort();
65
66 #if 0
67 bfd_vma value = statement->data_statement.value;
68 bfd_byte play_area[LONG_SIZE];
69 unsigned int size = 0;
70 switch (statement->data_statement.type) {
71 case LONG:
72 bfd_put_32(output_bfd, value, play_area);
73 size = LONG_SIZE;
74 break;
75 case SHORT:
76 bfd_put_16(output_bfd, value, play_area);
77 size = SHORT_SIZE;
78 break;
79 case BYTE:
80 bfd_put_8(output_bfd, value, play_area);
81 size = BYTE_SIZE;
82 break;
83 }
84
85 bfd_set_section_contents(output_bfd,
86 statement->data_statement.output_section,
87 play_area,
88 statement->data_statement.output_vma,
89 size);
90
91
92 #endif
93
94 }
95 break;
96 case lang_input_section_enum:
97 {
98 /* Create a new seclet in the output section with this
99 attached */
100
101 asection *i = statement->input_section.section;
102
103 asection *output_section = i->output_section;
104
105 bfd_seclet_type *seclet = bfd_new_seclet(output_section->owner,output_section);
106
107 seclet->type = bfd_indirect_seclet;
108 seclet->u.indirect.section = i;
109 seclet->u.indirect.symbols = statement->input_section.ifile->asymbols;
110 seclet->size = bfd_get_section_size_before_reloc(i);
111 seclet->offset = i->output_offset;
112 seclet->next = 0;
113
114 }
115 break;
116
117 default:
118 /* All the other ones fall through */
119 ;
120
121 }
122
123
124
125 }
126
127
128 void
129 DEFUN(write_relaxnorel,(output_bfd),
130 bfd *output_bfd)
131 {
132 /* Tie up all the statements to generate an output bfd structure which
133 bfd can mull over */
134
135
136 lang_for_each_statement(build_it);
137
138 seclet_dump(output_bfd);
139
140 }
141
142
143
144 static void
145 DEFUN(perform_slip,(s, slip, input_section, value),
146 asymbol **s AND
147 unsigned int slip AND
148 asection *input_section AND
149 bfd_vma value)
150 {
151
152 /* Find all symbols past this point, and make them know
153 what's happened */
154 while (*s)
155 {
156 asymbol *p = *s;
157 if (p->section == input_section)
158 {
159 /* This was pointing into this section, so mangle it */
160 if (p->value > value)
161 {
162 p->value -=2;
163 }
164 }
165 s++;
166
167 }
168 }
169 static int
170 DEFUN(movb1,(input_section, symbols, r, shrink),
171 asection *input_section AND
172 asymbol **symbols AND
173 arelent *r AND
174 unsigned int shrink)
175 {
176
177
178 bfd_vma value = get_value(r, input_section);
179
180 if (value >= 0xff00)
181 {
182
183 /* Change the reloc type from 16bit, possible 8 to 8bit
184 possible 16 */
185 r->howto = r->howto + 1;
186 /* The place to relc moves back by one */
187 r->address -=1;
188
189 /* This will be two bytes smaller in the long run */
190 shrink +=2 ;
191 perform_slip(symbols, 2, input_section, r->address - shrink +1);
192
193
194 }
195 return shrink;
196 }
197
198 static int
199 DEFUN(jmp1,(input_section, symbols, r, shrink),
200 asection *input_section AND
201 asymbol **symbols AND
202 arelent *r AND
203 unsigned int shrink)
204 {
205
206
207 bfd_vma value = get_value(r, 0);
208
209 bfd_vma dot = input_section->output_section->vma +
210 input_section->output_offset + r->address;
211 bfd_vma gap;
212
213 /* See if the address we're looking at within 127 bytes of where
214 we are, if so then we can use a small branch rather than the
215 jump we were going to */
216
217 gap = value - (dot - shrink);
218
219
220 if (-120 < (long)gap && (long)gap < 120 )
221 {
222
223 /* Change the reloc type from 16bit, possible 8 to 8bit
224 possible 16 */
225 r->howto = r->howto + 1;
226 /* The place to relc moves back by one */
227 r->address -=1;
228
229 /* This will be two bytes smaller in the long run */
230 shrink +=2 ;
231 perform_slip(symbols, 2, input_section, r->address-shrink +1);
232
233
234 }
235 return shrink;
236 }
237
238
239 /* See if we can change the size of this section by shrinking the
240 relocations in it. If this happens, then we'll have to renumber the
241 symbols in it, and shift around the data too.
242 */
243 boolean
244 DEFUN(relax_section,(this_ptr),
245 lang_statement_union_type **this_ptr)
246 {
247
248 lang_input_section_type *is = &((*this_ptr)->input_section);
249 asection *i = is->section;
250
251
252 /* Get enough memory to hold the stuff */
253 bfd *input_bfd = i->owner;
254 asection *input_section = i;
255 int shrink = 0 ;
256 int new = 0;
257
258 bfd_size_type reloc_size = bfd_get_reloc_upper_bound(input_bfd,
259 input_section);
260 arelent **reloc_vector = (arelent **)ldmalloc(reloc_size);
261
262 /* Get the relocs and think about them */
263 if (bfd_canonicalize_reloc(input_bfd,
264 input_section,
265 reloc_vector,
266 is->ifile->asymbols) )
267 {
268 arelent **parent;
269 asymbol **symbols = is->ifile->asymbols;
270 for (parent = reloc_vector; *parent; parent++)
271 {
272 arelent *r = *parent;
273 switch (r->howto->type) {
274 case R_MOVB2:
275 case R_JMP2:
276
277 shrink+=2;
278 break;
279
280 case R_MOVB1:
281 shrink = movb1(input_section, symbols, r, shrink);
282 new = 1;
283
284 break;
285 case R_JMP1:
286 shrink = jmp1(input_section, symbols, r, shrink);
287 new = 1;
288
289 break;
290 }
291 }
292
293 }
294 input_section->_cooked_size -= shrink;
295 free((char *)reloc_vector);
296 return new;
297
298 }
299
This page took 0.034476 seconds and 4 git commands to generate.