1 /* This module is part of BFD */
4 /* The intention is that one day, all the code which uses sections
5 will change and use seclets instead - maybe seglet would have been
8 Anyway, a seclet contains enough info to be able to describe an
9 area of output memory in one go.
11 The only description so far catered for is that of the
12 <<bfd_indirect_seclet>>, which is a select which points to a
13 <<section>> and the <<asymbols>> associated with the section, so
14 that relocation can be done when needed.
16 One day there will be more types - they will at least migrate from
17 the linker's data structures - also there could be extra stuff,
18 like a bss seclet, which descibes a lump of memory as containing
19 zeros compactly, without the horrible SEC_* flag cruft.
28 #include "coff/internal.h"
30 DEFUN(bfd_new_seclet
,(abfd
, section
),
34 bfd_seclet_type
*n
= (bfd_seclet_type
*)bfd_alloc(abfd
, sizeof(bfd_seclet_type
));
35 if (section
->seclets_tail
!= (bfd_seclet_type
*)NULL
) {
36 section
->seclets_tail
->next
= n
;
40 section
->seclets_head
= n
;
42 section
->seclets_tail
= n
;
51 #define MAX_ERRORS_IN_A_ROW 10
52 extern bfd_error_vector_type bfd_error_vector
;
54 DEFUN(get_value
,(reloc
, seclet
),
56 bfd_seclet_type
*seclet
)
59 if (reloc
->sym_ptr_ptr
)
61 asymbol
*symbol
= *(reloc
->sym_ptr_ptr
);
64 /* A symbol holds a pointer to a section, and an offset from the
65 base of the section. To relocate, we find where the section will
66 live in the output and add that in */
68 if (symbol
->section
== (asection
*)NULL
)
70 /* Ouch, this is an undefined symbol.. */
71 bfd_error_vector
.undefined_symbol(reloc
, seclet
);
72 value
= symbol
->value
;
76 value
= symbol
->value
+
77 symbol
->section
->output_offset
+
78 symbol
->section
->output_section
->vma
;
87 /* Add the value contained in the relocation */
88 value
+= (short)((reloc
->addend
) & 0xffff);
96 DEFUN(foo_bfd_get_relocated_section_contents
,(seclet
),
97 bfd_seclet_type
*seclet
)
100 asymbol
**symbols
= 0;
101 extern bfd
*output_bfd
;
104 /* Get enough memory to hold the stuff */
105 bfd
*input_bfd
= seclet
->u
.indirect
.section
->owner
;
106 asection
*input_section
= seclet
->u
.indirect
.section
;
108 char *data
= malloc(input_section
->_raw_size
);
110 char *prev_dst
= data
;
111 unsigned int gap
= 0;
113 bfd_size_type reloc_size
= bfd_get_reloc_upper_bound(input_bfd
,
115 arelent
**reloc_vector
= (arelent
**)ldmalloc(reloc_size
);
118 /* read in the section */
119 bfd_get_section_contents(input_bfd
,
123 input_section
->_raw_size
);
126 if (bfd_canonicalize_reloc(input_bfd
,
129 seclet
->u
.indirect
.symbols
) )
131 arelent
**parent
= reloc_vector
;
136 unsigned int dst_address
= 0;
137 unsigned int src_address
= 0;
141 /* Find how long a run we can do */
142 while (dst_address
< seclet
->size
)
148 /* Note that the relaxing didn't tie up the addresses in the
149 relocation, so we use the original address to work out the
150 run of non-relocated data */
151 run
= reloc
->address
- src_address
;
157 run
= seclet
->size
- dst_address
;
160 for (idx
= 0; idx
< run
; idx
++)
162 data
[dst_address
++] = data
[src_address
++];
165 /* Now do the relocation */
169 switch (reloc
->howto
->type
)
172 /* Speciial relaxed type */
174 bfd_vma dot
= seclet
->offset
+ dst_address
+ seclet
->u
.indirect
.section
->output_section
->vma
;
175 int gap
= get_value(reloc
,seclet
)-dot
-1;
176 if ((gap
& ~0xff ) != 0 &&((gap
& 0xff00)!= 0xff00)) abort();
178 bfd_put_8(abfd
,gap
, data
+dst_address
);
180 switch (data
[dst_address
-1])
185 bfd_put_8(abfd
, 0x55, data
+dst_address
-1);
189 bfd_put_8(abfd
, 0x40, data
+dst_address
-1);
208 /* Special relaxed type, there will be a gap between where we
209 get stuff from and where we put stuff to now
211 for a mov.b @aa:16 -> mov.b @aa:8
212 opcode 0x6a 0x0y offset
215 if (data
[dst_address
-1] != 0x6a)
217 switch (data
[dst_address
] & 0xf0)
221 data
[dst_address
-1] = (data
[src_address
] & 0xf) | 0x20;
225 data
[dst_address
-1] = (data
[src_address
] & 0xf) | 0x30;
231 /* the offset must fit ! after all, what was all the relaxing
234 bfd_put_8(abfd
, get_value(reloc
, seclet
), data
+ dst_address
);
236 /* Note the magic - src goes up by two bytes, but dst by only
245 bfd_vma dot
= seclet
->offset
+ dst_address
+ seclet
->u
.indirect
.section
->output_section
->vma
;
246 int gap
= get_value(reloc
,seclet
)-dot
;
247 if (gap
> 127 || gap
< -128)
249 bfd_error_vector
.reloc_value_truncated(reloc
, seclet
);
252 bfd_put_8(abfd
,gap
, data
+dst_address
);
261 unsigned int gap
=get_value(reloc
,seclet
);
264 bfd_error_vector
.reloc_value_truncated(reloc
, seclet
);
267 bfd_put_8(abfd
, gap
, data
+dst_address
);
275 /* A relword which would have like to have been a pcrel */
277 /* A relword which would like to have been modified but
280 bfd_put_16(abfd
, get_value(reloc
,seclet
), data
+dst_address
);
291 free((char *)reloc_vector
);
297 DEFUN(rel
,(abfd
, seclet
, output_section
),
299 bfd_seclet_type
*seclet AND
300 asection
*output_section
)
303 if (output_section
->flags
& SEC_HAS_CONTENTS
)
306 data
= bfd_get_relocated_section_contents(abfd
, seclet
);
308 if(bfd_set_section_contents(abfd
,
312 seclet
->size
) == false)
326 DEFUN(seclet_dump_seclet
,(abfd
, seclet
, section
),
328 bfd_seclet_type
*seclet AND
331 switch (seclet
->type
)
334 case bfd_indirect_seclet
:
335 /* The contents of this section come from another one somewhere
337 rel(abfd
, seclet
, section
);
351 DEFUN(seclet_dump
,(abfd
),
354 /* Write all the seclets on the bfd out, relocate etc according to the
357 asection
*o
= abfd
->sections
;
358 while (o
!= (asection
*)NULL
)
360 bfd_seclet_type
*p
= o
->seclets_head
;
361 while (p
!= (bfd_seclet_type
*)NULL
)
363 seclet_dump_seclet(abfd
, p
, o
);