]>
Commit | Line | Data |
---|---|---|
c618de01 SC |
1 | /* BFD support for handling relocation entries. |
2 | Copyright (C) 1990-1991 Free Software Foundation, Inc. | |
3 | Written by Cygnus Support. | |
4 | ||
5 | This file is part of BFD, the Binary File Descriptor library. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
20 | ||
985fca12 SC |
21 | /*doc* |
22 | @section Relocations | |
23 | ||
6724ff46 | 24 | BFD maintains relocations in much the same was as it maintains |
985fca12 SC |
25 | symbols; they are left alone until required, then read in en-mass and |
26 | traslated into an internal form. There is a common routine | |
27 | @code{bfd_perform_relocation} which acts upon the canonical form to to | |
28 | the actual fixup. | |
29 | ||
30 | Note that relocations are maintained on a per section basis, whilst | |
6724ff46 | 31 | symbols are maintained on a per BFD basis. |
985fca12 | 32 | |
6724ff46 | 33 | All a back end has to do to fit the BFD interface is to create as many |
985fca12 SC |
34 | @code{struct reloc_cache_entry} as there are relocations in a |
35 | particuar section, and fill in the right bits: | |
36 | ||
37 | @menu | |
38 | * typedef arelent:: | |
39 | * reloc handling functions:: | |
40 | @end menu | |
41 | ||
42 | */ | |
43 | #include "sysdep.h" | |
44 | #include "bfd.h" | |
45 | #include "libbfd.h" | |
46 | /*doc | |
c618de01 | 47 | @node typedef arelent, Relocations, reloc handling functions, Relocations |
985fca12 SC |
48 | @section typedef arelent |
49 | ||
50 | ||
51 | */ | |
52 | ||
53 | /*proto* bfd_perform_relocation | |
54 | The relocation routine returns as a status an enumerated type: | |
55 | ||
56 | *+++ | |
57 | ||
58 | $typedef enum bfd_reloc_status { | |
59 | No errors detected | |
60 | ||
61 | $ bfd_reloc_ok, | |
62 | ||
63 | The relocation was performed, but there was an overflow. | |
64 | ||
65 | $ bfd_reloc_overflow, | |
66 | ||
67 | The address to relocate was not within the section supplied | |
68 | ||
69 | $ bfd_reloc_outofrange, | |
70 | ||
71 | Used by special functions | |
72 | ||
73 | $ bfd_reloc_continue, | |
74 | ||
75 | Unused | |
76 | ||
77 | $ bfd_reloc_notsupported, | |
78 | ||
79 | Unsupported relocation size requested. | |
80 | ||
81 | $ bfd_reloc_other, | |
82 | ||
83 | The symbol to relocate against was undefined. | |
84 | ||
85 | $ bfd_reloc_undefined, | |
86 | ||
d0a27c3b | 87 | The relocation was performed, but may not be ok - presently generated |
985fca12 SC |
88 | only when linking i960 coff files with i960 b.out symbols. |
89 | ||
90 | $ bfd_reloc_dangerous | |
91 | $ } | |
92 | $ bfd_reloc_status_enum_type; | |
93 | ||
94 | *--- | |
95 | ||
96 | */ | |
97 | ||
98 | /*proto* | |
99 | ||
100 | *+++ | |
101 | ||
102 | $typedef struct reloc_cache_entry | |
103 | ${ | |
104 | ||
105 | A pointer into the canonical table of pointers | |
106 | ||
107 | $ struct symbol_cache_entry **sym_ptr_ptr; | |
108 | ||
109 | offset in section | |
110 | ||
111 | $ rawdata_offset address; | |
112 | ||
113 | addend for relocation value | |
114 | ||
115 | $ bfd_vma addend; | |
116 | ||
117 | if sym is null this is the section | |
118 | ||
119 | $ struct sec *section; | |
120 | ||
121 | Pointer to how to perform the required relocation | |
122 | ||
41f50af0 | 123 | $ CONST struct reloc_howto_struct *howto; |
985fca12 SC |
124 | $} arelent; |
125 | ||
126 | *--- | |
127 | ||
128 | */ | |
129 | ||
130 | /*doc* | |
131 | @table @code | |
132 | @item sym_ptr_ptr | |
06d75160 | 133 | The symbol table pointer points to a pointer to the symbol associated with the |
d0a27c3b | 134 | relocation request. This would naturally be the pointer into the table |
985fca12 SC |
135 | returned by the back end's get_symtab action. @xref{Symbols}. The |
136 | symbol is referenced through a pointer to a pointer so that tools like | |
06d75160 | 137 | the linker can fix up all the symbols of the same name by modifying |
985fca12 | 138 | only one pointer. The relocation routine looks in the symbol and uses |
188d6d22 | 139 | the base of the section the symbol is attached to and the value of |
985fca12 SC |
140 | the symbol as the initial relocation offset. If the symbol pointer is |
141 | zero, then the section provided is looked up. | |
142 | @item address | |
143 | The address field gives the offset in bytes from the base of the | |
144 | section data which owns the relocation record to the first byte of | |
145 | relocatable information. The actual data relocated will be relative to | |
146 | this point - for example, a relocation type which modifies the bottom | |
147 | two bytes of a four byte word would not touch the first byte pointed | |
148 | to in a big endian world. | |
149 | @item addend | |
150 | The addend is a value provided by the back end to be added (!) to the | |
d0a27c3b | 151 | relocation offset. Its interpretation is dependent upon the howto. |
985fca12 SC |
152 | For example, on the 68k the code: |
153 | ||
154 | *+ | |
155 | char foo[]; | |
156 | main() | |
157 | { | |
158 | return foo[0x12345678]; | |
159 | } | |
160 | *- | |
161 | Could be compiled into: | |
162 | ||
163 | *+ | |
164 | linkw fp,#-4 | |
165 | moveb @@#12345678,d0 | |
166 | extbl d0 | |
167 | unlk fp | |
168 | rts | |
169 | *- | |
170 | ||
171 | This could create a reloc pointing to foo, but leave the offset in the data | |
172 | (something like) | |
173 | ||
174 | *+ | |
175 | RELOCATION RECORDS FOR [.text]: | |
176 | OFFSET TYPE VALUE | |
177 | 00000006 32 _foo | |
178 | ||
179 | 00000000 4e56 fffc ; linkw fp,#-4 | |
180 | 00000004 1039 1234 5678 ; moveb @@#12345678,d0 | |
181 | 0000000a 49c0 ; extbl d0 | |
182 | 0000000c 4e5e ; unlk fp | |
183 | 0000000e 4e75 ; rts | |
184 | *- | |
185 | Using coff and an 88k, some instructions don't have enough space in them to | |
186 | represent the full address range, and pointers have to be loaded in | |
187 | two parts. So you'd get something like: | |
188 | ||
189 | *+ | |
190 | or.u r13,r0,hi16(_foo+0x12345678) | |
191 | ld.b r2,r13,lo16(_foo+0x12345678) | |
192 | jmp r1 | |
193 | *- | |
194 | This whould create two relocs, both pointing to _foo, and with 0x12340000 | |
195 | in their addend field. The data would consist of: | |
196 | ||
197 | *+ | |
198 | ||
199 | RELOCATION RECORDS FOR [.text]: | |
200 | OFFSET TYPE VALUE | |
201 | 00000002 HVRT16 _foo+0x12340000 | |
202 | 00000006 LVRT16 _foo+0x12340000 | |
203 | ||
204 | 00000000 5da05678 ; or.u r13,r0,0x5678 | |
205 | 00000004 1c4d5678 ; ld.b r2,r13,0x5678 | |
206 | 00000008 f400c001 ; jmp r1 | |
207 | *- | |
208 | The relocation routine digs out the value from the data, adds it to | |
209 | the addend to get the original offset and then adds the value of _foo. | |
210 | Note that all 32 bits have to be kept around somewhere, to cope with | |
211 | carry from bit 15 to bit 16. | |
212 | ||
213 | On further example is the sparc and the a.out format. The sparc has a | |
214 | similar problem to the 88k, in that some instructions don't have | |
215 | room for an entire offset, but on the sparc the parts are created odd | |
216 | sized lumps. The designers of the a.out format chose not to use the | |
217 | data within the section for storing part of the offset; all the offset | |
218 | is kept within the reloc. Any thing in the data should be ignored. | |
219 | ||
220 | *+ | |
221 | save %sp,-112,%sp | |
222 | sethi %hi(_foo+0x12345678),%g2 | |
223 | ldsb [%g2+%lo(_foo+0x12345678)],%i0 | |
224 | ret | |
225 | restore | |
226 | *- | |
227 | Both relocs contains a pointer to foo, and the offsets would contain junk. | |
228 | ||
229 | *+ | |
230 | RELOCATION RECORDS FOR [.text]: | |
231 | OFFSET TYPE VALUE | |
232 | 00000004 HI22 _foo+0x12345678 | |
233 | 00000008 LO10 _foo+0x12345678 | |
234 | ||
235 | 00000000 9de3bf90 ; save %sp,-112,%sp | |
236 | 00000004 05000000 ; sethi %hi(_foo+0),%g2 | |
237 | 00000008 f048a000 ; ldsb [%g2+%lo(_foo+0)],%i0 | |
238 | 0000000c 81c7e008 ; ret | |
239 | 00000010 81e80000 ; restore | |
240 | *- | |
241 | @item section | |
242 | The section field is only used when the symbol pointer field is null. | |
243 | It supplies the section into which the data should be relocated. The | |
244 | field's main use comes from assemblers which do most of the symbol fixups | |
245 | themselves; an assembler may take an internal reference to a label, | |
246 | but since it knows where the label is, it can turn the relocation | |
247 | request from a symbol lookup into a section relative relocation - the | |
248 | relocation emitted has no symbol, just a section to relocate against. | |
249 | ||
250 | I'm not sure what it means when both a symbol pointer an a section | |
251 | pointer are present. Some formats use this sort of mechanism to | |
6724ff46 | 252 | describe PIC relocations, but BFD can't to that sort of thing yet. |
985fca12 SC |
253 | @item howto |
254 | The howto field can be imagined as a relocation instruction. It is a | |
255 | pointer to a struct which contains information on what to do with all | |
256 | the other information in the reloc record and data section. A back end | |
257 | would normally have a relocation instruction set and turn relocations | |
258 | into pointers to the correct structure on input - but it would be | |
259 | possible to create each howto field on demand. | |
260 | @end table | |
261 | */ | |
262 | ||
263 | ||
264 | /*proto* reloc_howto_type | |
265 | The @code{reloc_howto_type} is a structure which contains all the | |
6724ff46 | 266 | information that BFD needs to know to tie up a back end's data. |
985fca12 SC |
267 | |
268 | *+++ | |
269 | ||
270 | $typedef CONST struct reloc_howto_struct | |
271 | ${ | |
272 | The type field has mainly a documetary use - the back end can to what | |
273 | it wants with it, though the normally the back end's external idea of | |
274 | what a reloc number would be would be stored in this field. For | |
275 | example, the a PC relative word relocation in a coff environment would | |
276 | have the type 023 - because that's what the outside world calls a | |
277 | R_PCRWORD reloc. | |
278 | ||
279 | $ unsigned int type; | |
280 | ||
281 | The value the final relocation is shifted right by. This drops | |
282 | unwanted data from the relocation. | |
283 | ||
284 | $ unsigned int rightshift; | |
285 | ||
286 | The size of the item to be relocated - 0, is one byte, 1 is 2 bytes, 3 | |
287 | is four bytes. | |
288 | ||
289 | $ unsigned int size; | |
290 | ||
291 | Now obsolete | |
292 | ||
293 | $ unsigned int bitsize; | |
294 | ||
295 | Notes that the relocation is relative to the location in the data | |
296 | section of the addend. The relocation function will subtract from the | |
297 | relocation value the address of the location being relocated. | |
298 | ||
299 | $ boolean pc_relative; | |
300 | ||
301 | Now obsolete | |
302 | ||
303 | $ unsigned int bitpos; | |
304 | ||
305 | Now obsolete | |
306 | ||
307 | $ boolean absolute; | |
308 | ||
309 | Causes the relocation routine to return an error if overflow is | |
310 | detected when relocating. | |
311 | ||
312 | $ boolean complain_on_overflow; | |
313 | ||
314 | If this field is non null, then the supplied function is called rather | |
315 | than the normal function. This allows really strange relocation | |
316 | methods to be accomodated (eg, i960 callj instructions). | |
317 | ||
318 | $ bfd_reloc_status_enum_type (*special_function)(); | |
319 | ||
320 | The textual name of the relocation type. | |
321 | ||
322 | $ char *name; | |
323 | ||
324 | When performing a partial link, some formats must modify the | |
325 | relocations rather than the data - this flag signals this. | |
326 | ||
327 | $ boolean partial_inplace; | |
328 | ||
329 | The src_mask is used to select what parts of the read in data are to | |
330 | be used in the relocation sum. Eg, if this was an 8 bit bit of data | |
331 | which we read and relocated, this would be 0x000000ff. When we have | |
332 | relocs which have an addend, such as sun4 extended relocs, the value | |
333 | in the offset part of a relocating field is garbage so we never use | |
334 | it. In this case the mask would be 0x00000000. | |
335 | ||
336 | $ bfd_word src_mask; | |
337 | The dst_mask is what parts of the instruction are replaced into the | |
338 | instruction. In most cases src_mask == dst_mask, except in the above | |
339 | special case, where dst_mask would be 0x000000ff, and src_mask would | |
340 | be 0x00000000. | |
341 | ||
342 | $ bfd_word dst_mask; | |
343 | ||
344 | When some formats create PC relative instructions, they leave the | |
345 | value of the pc of the place being relocated in the offset slot of the | |
346 | instruction, so that a PC relative relocation can be made just by | |
347 | adding in an ordinary offset (eg sun3 a.out). Some formats leave the | |
348 | displacement part of an instruction empty (eg m88k bcs), this flag | |
349 | signals the fact. | |
350 | ||
351 | $ boolean pcrel_offset; | |
352 | $} reloc_howto_type; | |
353 | *--- | |
354 | ||
355 | */ | |
356 | ||
357 | /*proto* HOWTO | |
358 | The HOWTO define is horrible and will go away. | |
359 | *+ | |
360 | #define HOWTO(C, R,S,B, P, BI, ABS, O, SF, NAME, INPLACE, MASKSRC, MASKDST, PC) \ | |
361 | {(unsigned)C,R,S,B, P, BI, ABS,O,SF,NAME,INPLACE,MASKSRC,MASKDST,PC} | |
362 | *- | |
363 | ||
e5683622 SC |
364 | And will be replaced with the totally magic way. But for the moment, |
365 | we are compatible, so do it this way.. | |
366 | ||
367 | *+ | |
b2c91bd9 | 368 | #define NEWHOWTO( FUNCTION, NAME,SIZE,REL,IN) HOWTO(0,0,SIZE,0,REL,0,false,false,FUNCTION, NAME,false,0,0,IN) |
e5683622 SC |
369 | *- |
370 | ||
371 | Helper routine to turn a symbol into a relocation value. | |
372 | ||
373 | *+ | |
374 | ||
375 | ||
376 | #define HOWTO_PREPARE(relocation, symbol) \ | |
377 | { \ | |
378 | if (symbol != (asymbol *)NULL) { \ | |
379 | if (symbol->flags & BSF_FORT_COMM) { \ | |
380 | relocation = 0; \ | |
381 | } \ | |
382 | else { \ | |
383 | relocation = symbol->value; \ | |
384 | } \ | |
385 | } \ | |
386 | if (symbol->section != (asection *)NULL) { \ | |
387 | relocation += symbol->section->output_section->vma + \ | |
388 | symbol->section->output_offset; \ | |
389 | } \ | |
390 | } | |
391 | *- | |
985fca12 SC |
392 | */ |
393 | ||
394 | /*proto* reloc_chain | |
395 | *+ | |
396 | typedef unsigned char bfd_byte; | |
397 | ||
398 | typedef struct relent_chain { | |
399 | arelent relent; | |
400 | struct relent_chain *next; | |
401 | } arelent_chain; | |
402 | ||
403 | *- | |
404 | ||
405 | */ | |
406 | ||
407 | ||
408 | ||
409 | /*proto* | |
410 | If an output_bfd is supplied to this function the generated image | |
411 | will be relocatable, the relocations are copied to the output file | |
412 | after they have been changed to reflect the new state of the world. | |
413 | There are two ways of reflecting the results of partial linkage in an | |
414 | output file; by modifying the output data in place, and by modifying | |
415 | the relocation record. Some native formats (eg basic a.out and basic | |
416 | coff) have no way of specifying an addend in the relocation type, so | |
417 | the addend has to go in the output data. This is no big deal since in | |
418 | these formats the output data slot will always be big enough for the | |
419 | addend. Complex reloc types with addends were invented to solve just | |
420 | this problem. | |
421 | *; PROTO(bfd_reloc_status_enum_type, | |
422 | bfd_perform_relocation, | |
423 | (bfd * abfd, | |
424 | arelent *reloc_entry, | |
425 | PTR data, | |
426 | asection *input_section, | |
427 | bfd *output_bfd)); | |
428 | */ | |
429 | ||
430 | ||
431 | bfd_reloc_status_enum_type | |
432 | DEFUN(bfd_perform_relocation,(abfd, | |
433 | reloc_entry, | |
434 | data, | |
435 | input_section, | |
436 | output_bfd), | |
437 | bfd *abfd AND | |
438 | arelent *reloc_entry AND | |
439 | PTR data AND | |
440 | asection *input_section AND | |
441 | bfd *output_bfd) | |
442 | { | |
443 | bfd_vma relocation; | |
444 | bfd_reloc_status_enum_type flag = bfd_reloc_ok; | |
445 | bfd_vma addr = reloc_entry->address ; | |
446 | bfd_vma output_base = 0; | |
447 | reloc_howto_type *howto = reloc_entry->howto; | |
448 | asection *reloc_target_output_section; | |
449 | asection *reloc_target_input_section; | |
450 | asymbol *symbol; | |
451 | ||
452 | if (reloc_entry->sym_ptr_ptr) { | |
453 | symbol = *( reloc_entry->sym_ptr_ptr); | |
454 | if ((symbol->flags & BSF_UNDEFINED) && output_bfd == (bfd *)NULL) { | |
455 | flag = bfd_reloc_undefined; | |
456 | } | |
457 | } | |
458 | else { | |
459 | symbol = (asymbol*)NULL; | |
460 | } | |
461 | ||
462 | if (howto->special_function){ | |
463 | bfd_reloc_status_enum_type cont; | |
464 | cont = howto->special_function(abfd, | |
465 | reloc_entry, | |
466 | symbol, | |
467 | data, | |
468 | input_section); | |
469 | if (cont != bfd_reloc_continue) return cont; | |
470 | } | |
471 | ||
472 | /* | |
473 | Work out which section the relocation is targetted at and the | |
474 | initial relocation command value. | |
475 | */ | |
476 | ||
477 | ||
478 | if (symbol != (asymbol *)NULL){ | |
479 | if (symbol->flags & BSF_FORT_COMM) { | |
480 | relocation = 0; | |
481 | } | |
482 | else { | |
483 | relocation = symbol->value; | |
484 | } | |
485 | if (symbol->section != (asection *)NULL) | |
486 | { | |
487 | reloc_target_input_section = symbol->section; | |
488 | } | |
489 | else { | |
490 | reloc_target_input_section = (asection *)NULL; | |
491 | } | |
492 | } | |
493 | else if (reloc_entry->section != (asection *)NULL) | |
494 | { | |
495 | relocation = 0; | |
496 | reloc_target_input_section = reloc_entry->section; | |
497 | } | |
498 | else { | |
499 | relocation = 0; | |
500 | reloc_target_input_section = (asection *)NULL; | |
501 | } | |
502 | ||
503 | ||
504 | if (reloc_target_input_section != (asection *)NULL) { | |
505 | ||
506 | reloc_target_output_section = | |
507 | reloc_target_input_section->output_section; | |
508 | ||
509 | if (output_bfd && howto->partial_inplace==false) { | |
510 | output_base = 0; | |
511 | } | |
512 | else { | |
513 | output_base = reloc_target_output_section->vma; | |
514 | ||
515 | } | |
516 | ||
517 | relocation += output_base + reloc_target_input_section->output_offset; | |
518 | } | |
519 | ||
520 | relocation += reloc_entry->addend ; | |
521 | ||
522 | ||
523 | if(reloc_entry->address > (bfd_vma)(input_section->size)) | |
524 | { | |
525 | return bfd_reloc_outofrange; | |
526 | } | |
527 | ||
528 | ||
529 | if (howto->pc_relative == true) | |
530 | { | |
531 | /* | |
532 | Anything which started out as pc relative should end up that | |
c618de01 SC |
533 | way too. |
534 | ||
535 | There are two ways we can see a pcrel instruction. Sometimes | |
536 | the pcrel displacement has been partially calculated, it | |
537 | includes the distance from the start of the section to the | |
538 | instruction in it (eg sun3), and sometimes the field is | |
539 | totally blank - eg m88kbcs. | |
540 | */ | |
985fca12 SC |
541 | |
542 | ||
543 | relocation -= | |
d0a27c3b | 544 | input_section->output_section->vma + input_section->output_offset; |
985fca12 SC |
545 | |
546 | if (howto->pcrel_offset == true) { | |
547 | relocation -= reloc_entry->address; | |
548 | } | |
549 | ||
550 | } | |
551 | ||
552 | if (output_bfd!= (bfd *)NULL) { | |
553 | if ( howto->partial_inplace == false) { | |
554 | /* | |
555 | This is a partial relocation, and we want to apply the relocation | |
c618de01 SC |
556 | to the reloc entry rather than the raw data. Modify the reloc |
557 | inplace to reflect what we now know. | |
558 | */ | |
985fca12 SC |
559 | reloc_entry->addend = relocation ; |
560 | reloc_entry->section = reloc_target_input_section; | |
561 | if (reloc_target_input_section != (asection *)NULL) { | |
562 | /* If we know the output section we can forget the symbol */ | |
563 | reloc_entry->sym_ptr_ptr = (asymbol**)NULL; | |
564 | } | |
565 | reloc_entry->address += | |
566 | input_section->output_offset; | |
567 | return flag; | |
568 | } | |
569 | else | |
570 | { | |
571 | /* This is a partial relocation, but inplace, so modify the | |
c618de01 SC |
572 | reloc record a bit. |
573 | ||
574 | If we've relocated with a symbol with a section, change | |
575 | into a ref to the section belonging to the symbol | |
576 | */ | |
577 | ||
578 | if (symbol != (asymbol *)NULL && reloc_target_input_section != (asection *)NULL) | |
579 | { | |
580 | reloc_entry->section = reloc_target_input_section; | |
581 | reloc_entry->sym_ptr_ptr = (asymbol **)NULL; | |
582 | } | |
985fca12 SC |
583 | |
584 | } | |
585 | } | |
586 | ||
587 | reloc_entry->addend = 0; | |
588 | ||
589 | ||
590 | /* | |
591 | Either we are relocating all the way, or we don't want to apply | |
592 | the relocation to the reloc entry (probably because there isn't | |
593 | any room in the output format to describe addends to relocs) | |
594 | */ | |
595 | relocation >>= howto->rightshift; | |
596 | ||
597 | /* Shift everything up to where it's going to be used */ | |
598 | ||
599 | relocation <<= howto->bitpos; | |
600 | ||
601 | /* Wait for the day when all have the mask in them */ | |
602 | ||
603 | /* What we do: | |
604 | i instruction to be left alone | |
605 | o offset within instruction | |
606 | r relocation offset to apply | |
607 | S src mask | |
608 | D dst mask | |
609 | N ~dst mask | |
610 | A part 1 | |
611 | B part 2 | |
612 | R result | |
613 | ||
614 | Do this: | |
615 | i i i i i o o o o o from bfd_get<size> | |
616 | and S S S S S to get the size offset we want | |
617 | + r r r r r r r r r r to get the final value to place | |
618 | and D D D D D to chop to right size | |
619 | ----------------------- | |
620 | A A A A A | |
621 | And this: | |
622 | ... i i i i i o o o o o from bfd_get<size> | |
623 | and N N N N N get instruction | |
624 | ----------------------- | |
625 | ... B B B B B | |
626 | ||
627 | And then: | |
628 | B B B B B | |
629 | or A A A A A | |
630 | ----------------------- | |
631 | R R R R R R R R R R put into bfd_put<size> | |
632 | */ | |
633 | ||
634 | #define DOIT(x) \ | |
635 | x = ( (x & ~howto->dst_mask) | (((x & howto->src_mask) + relocation) & howto->dst_mask)) | |
636 | ||
637 | switch (howto->size) | |
638 | { | |
639 | case 0: | |
640 | { | |
641 | char x = bfd_get_8(abfd, (char *)data + addr); | |
642 | DOIT(x); | |
643 | bfd_put_8(abfd,x, (unsigned char *) data + addr); | |
644 | } | |
645 | break; | |
646 | ||
647 | case 1: | |
648 | { | |
649 | short x = bfd_get_16(abfd, (bfd_byte *)data + addr); | |
650 | DOIT(x); | |
651 | bfd_put_16(abfd, x, (unsigned char *)data + addr); | |
652 | } | |
653 | break; | |
654 | case 2: | |
655 | { | |
656 | long x = bfd_get_32(abfd, (bfd_byte *) data + addr); | |
657 | DOIT(x); | |
658 | bfd_put_32(abfd,x, (bfd_byte *)data + addr); | |
659 | } | |
660 | break; | |
661 | case 3: | |
c618de01 | 662 | |
985fca12 SC |
663 | /* Do nothing */ |
664 | break; | |
665 | default: | |
666 | return bfd_reloc_other; | |
667 | } | |
668 | ||
669 | return flag; | |
670 | } | |
c618de01 SC |
671 | |
672 | ||
2cf44d7b SC |
673 | |
674 | /*doc* | |
675 | ||
676 | @section The howto manager | |
677 | ||
678 | ||
679 | When an application wants to create a relocation, but doesn't know | |
680 | what the target machine might call it, it can find out by using this | |
681 | bit of code. | |
682 | ||
683 | */ | |
684 | ||
685 | /*proto* bfd_reloc_code_enum_type | |
686 | ||
687 | *+++ | |
688 | ||
689 | $typedef enum | |
690 | ${ | |
691 | ||
692 | 16 bits wide, simple reloc | |
693 | ||
694 | $ BFD_RELOC_16, | |
695 | ||
696 | 8 bits wide, but used to form an address like 0xffnn | |
697 | ||
698 | $ BFD_RELOC_8_FFnn, | |
699 | ||
700 | 8 bits wide, simple | |
701 | ||
702 | $ BFD_RELOC_8, | |
703 | ||
704 | 8 bits wide, pc relative | |
705 | ||
706 | $ BFD_RELOC_8_PCREL | |
707 | $ } bfd_reloc_code_enum_real_type; | |
708 | ||
709 | *--- | |
710 | ||
711 | */ | |
712 | ||
713 | ||
714 | ||
715 | /*proto* bfd_reloc_type_lookup | |
716 | This routine returns a pointer to a howto struct which when invoked, | |
717 | will perform the supplied relocation on data from the architecture | |
718 | noted. | |
719 | ||
720 | [Note] This function will go away. | |
721 | ||
722 | *; PROTO(CONST struct reloc_howto_struct *, | |
723 | bfd_reloc_type_lookup, | |
724 | (CONST bfd_arch_info_struct_type *arch, bfd_reloc_code_enum_type code)); | |
725 | */ | |
726 | ||
727 | ||
728 | CONST struct reloc_howto_struct * | |
729 | DEFUN(bfd_reloc_type_lookup,(arch, code), | |
730 | CONST bfd_arch_info_struct_type *arch AND | |
731 | bfd_reloc_code_enum_type code) | |
732 | { | |
733 | return arch->reloc_type_lookup(arch, code); | |
734 | } | |
735 | ||
736 | ||
737 |