#include "sysdep.h"
#include "libbfd.h"
#include "seclet.h"
-/*doc*
+/*
+DOCDD
INODE
typedef arelent, howto manager, Relocations, Relocations
will be relative to this point - for example, a relocation
type which modifies the bottom two bytes of a four byte word
would not touch the first byte pointed to in a big endian
- world. @item addend The addend is a value provided by the back
- end to be added (!) to the relocation offset. Its
- interpretation is dependent upon the howto. For example, on
- the 68k the code:
+ world.
+
+ o addend
+
+ The addend is a value provided by the back end to be added (!)
+ to the relocation offset. Its interpretation is dependent upon
+ the howto. For example, on the 68k the code:
| char foo[];
information that BFD needs to know to tie up a back end's data.
CODE_FRAGMENT
+.struct symbol_cache_entry; {* Forward declaration *}
.
.typedef CONST struct reloc_howto_struct
.{
. unsigned int rightshift;
.
. {* The size of the item to be relocated - 0, is one byte, 1 is 2
-. bytes, 3 is four bytes. *}
-. unsigned int size;
+. bytes, 3 is four bytes. A -ve value indicates that the
+. result is to be subtracted from the data*}
+. int size;
.
. {* Now obsolete *}
. unsigned int bitsize;
. called rather than the normal function. This allows really
. strange relocation methods to be accomodated (eg, i960 callj
. instructions). *}
-. bfd_reloc_status_type (*special_function)();
+. bfd_reloc_status_type (*special_function)
+. PARAMS ((bfd *abfd,
+. arelent *reloc_entry,
+. struct symbol_cache_entry *symbol,
+. PTR data,
+. asection *input_section,
+. bfd *output_bfd));
.
. {* The textual name of the relocation type. *}
. char *name;
asymbol *symbol;
symbol = *( reloc_entry->sym_ptr_ptr);
+ if ((symbol->section == &bfd_abs_section)
+ && output_bfd != (bfd *)NULL)
+ {
+ reloc_entry->address += input_section->output_offset;
+
+ return bfd_reloc_ok;
+
+ }
+
if ((symbol->section == &bfd_und_section) && output_bfd == (bfd *)NULL) {
- flag = bfd_reloc_undefined;
- }
+ flag = bfd_reloc_undefined;
+ }
- if (howto->special_function){
- bfd_reloc_status_type cont;
- cont = howto->special_function(abfd,
- reloc_entry,
- symbol,
- data,
- input_section);
- if (cont != bfd_reloc_continue) return cont;
- }
+ if (howto->special_function) {
+ bfd_reloc_status_type cont;
+ cont = howto->special_function(abfd,
+ reloc_entry,
+ symbol,
+ data,
+ input_section,
+ output_bfd);
+ if (cont != bfd_reloc_continue) return cont;
+ }
/*
Work out which section the relocation is targetted at and the
if (symbol->section == &bfd_com_section) {
- relocation = 0;
- }
+ relocation = 0;
+ }
else {
- relocation = symbol->value;
- }
+ relocation = symbol->value;
+ }
reloc_target_output_section = symbol->section->output_section;
if (output_bfd && howto->partial_inplace==false) {
- output_base = 0;
- }
+ output_base = 0;
+ }
else {
- output_base = reloc_target_output_section->vma;
+ output_base = reloc_target_output_section->vma;
- }
+ }
relocation += output_base + symbol->section->output_offset;
input_section->output_section->vma + input_section->output_offset;
if (howto->pcrel_offset == true) {
- relocation -= reloc_entry->address;
- }
+ relocation -= reloc_entry->address;
+ }
}
- if (output_bfd!= (bfd *)NULL) {
- if ( howto->partial_inplace == false) {
- /*
- This is a partial relocation, and we want to apply the relocation
- to the reloc entry rather than the raw data. Modify the reloc
- inplace to reflect what we now know.
- */
- reloc_entry->addend = relocation ;
- reloc_entry->address += input_section->output_offset;
- return flag;
- }
- else
- {
- /* This is a partial relocation, but inplace, so modify the
- reloc record a bit.
-
- If we've relocated with a symbol with a section, change
- into a ref to the section belonging to the symbol
- */
- reloc_entry->addend = relocation ;
- reloc_entry->address += input_section->output_offset;
+ if (output_bfd!= (bfd *)NULL)
+ {
+ if ( howto->partial_inplace == false)
+ {
+ /*
+ This is a partial relocation, and we want to apply the relocation
+ to the reloc entry rather than the raw data. Modify the reloc
+ inplace to reflect what we now know.
+ */
+ reloc_entry->addend = relocation ;
+ reloc_entry->address += input_section->output_offset;
+ return flag;
+ }
+ else
+ {
+ /* This is a partial relocation, but inplace, so modify the
+ reloc record a bit.
+
+ If we've relocated with a symbol with a section, change
+ into a ref to the section belonging to the symbol
+ */
+ reloc_entry->address += input_section->output_offset;
+ if (abfd->xvec->flavour == bfd_target_coff_flavour)
+ {
+ relocation -= reloc_entry->addend;
+ reloc_entry->addend = 0;
+ }
+ else
+ {
+ reloc_entry->addend = relocation ;
}
}
+ }
else
{
-
- reloc_entry->addend = 0;
-}
+ reloc_entry->addend = 0;
+ }
-
/*
Either we are relocating all the way, or we don't want to apply
the relocation to the reloc entry (probably because there isn't
switch (howto->size)
{
- case 0:
- {
- char x = bfd_get_8(abfd, (char *)data + addr);
- DOIT(x);
- bfd_put_8(abfd,x, (unsigned char *) data + addr);
- }
+ case 0:
+ {
+ char x = bfd_get_8(abfd, (char *)data + addr);
+ DOIT(x);
+ bfd_put_8(abfd,x, (unsigned char *) data + addr);
+ }
break;
- case 1:
- {
- short x = bfd_get_16(abfd, (bfd_byte *)data + addr);
- DOIT(x);
- bfd_put_16(abfd, x, (unsigned char *)data + addr);
- }
+ case 1:
+ {
+ short x = bfd_get_16(abfd, (bfd_byte *)data + addr);
+ DOIT(x);
+ bfd_put_16(abfd, x, (unsigned char *)data + addr);
+ }
break;
- case 2:
- {
- long x = bfd_get_32(abfd, (bfd_byte *) data + addr);
- DOIT(x);
- bfd_put_32(abfd,x, (bfd_byte *)data + addr);
- }
+ case 2:
+ {
+ long x = bfd_get_32(abfd, (bfd_byte *) data + addr);
+ DOIT(x);
+ bfd_put_32(abfd,x, (bfd_byte *)data + addr);
+ }
+ break;
+ case -2:
+ {
+ long x = bfd_get_32(abfd, (bfd_byte *) data + addr);
+ relocation = -relocation;
+ DOIT(x);
+ bfd_put_32(abfd,x, (bfd_byte *)data + addr);
+ }
break;
- case 3:
+
+ case 3:
/* Do nothing */
break;
- default:
+ default:
return bfd_reloc_other;
}
/*
+DOCDD
INODE
howto manager, , typedef arelent, Relocations
CODE_FRAGMENT
.
.typedef enum bfd_reloc_code_real
+.
.{
. {* 16 bits wide, simple reloc *}
. BFD_RELOC_16,
. moment probably a 32 bit wide abs address, but the cpu can
. choose. *}
.
-. BFD_RELOC_CTOR
+. BFD_RELOC_CTOR,
+.
+. {* 32 bits wide, simple reloc *}
+. BFD_RELOC_32,
+. {* 32 bits, PC-relative *}
+. BFD_RELOC_32_PCREL,
+.
+. {* High 22 bits of 32-bit value; simple reloc. *}
+. BFD_RELOC_HI22,
+. {* Low 10 bits. *}
+. BFD_RELOC_LO10,
+.
+. {* Reloc types used for i960/b.out. *}
+. BFD_RELOC_24_PCREL,
+. BFD_RELOC_I960_CALLJ,
+.
+. BFD_RELOC_16_PCREL,
+. {* 32-bit pc-relative, shifted right 2 bits (i.e., 30-bit
+. word displacement, e.g. for SPARC) *}
+. BFD_RELOC_32_PCREL_S2,
+.
+. {* now for the sparc/elf codes *}
+. BFD_RELOC_NONE, {* actually used *}
+. BFD_RELOC_SPARC_WDISP22,
+. BFD_RELOC_SPARC22,
+. BFD_RELOC_SPARC13,
+. BFD_RELOC_SPARC_BASE13,
+. BFD_RELOC_SPARC_GOT10,
+. BFD_RELOC_SPARC_GOT13,
+. BFD_RELOC_SPARC_GOT22,
+. BFD_RELOC_SPARC_PC10,
+. BFD_RELOC_SPARC_PC22,
+. BFD_RELOC_SPARC_WPLT30,
+. BFD_RELOC_SPARC_COPY,
+. BFD_RELOC_SPARC_GLOB_DAT,
+. BFD_RELOC_SPARC_JMP_SLOT,
+. BFD_RELOC_SPARC_RELATIVE,
+. BFD_RELOC_SPARC_UA32,
+.
+. {* this one is a.out specific? *}
+. BFD_RELOC_SPARC_BASE22,
+.
+. {* this must be the highest numeric value *}
+. BFD_RELOC_UNUSED
. } bfd_reloc_code_real_type;
*/
SYNOPSIS
CONST struct reloc_howto_struct *
- bfd_reloc_type_lookup
- (CONST bfd_arch_info_type *arch, bfd_reloc_code_type code);
+ bfd_reloc_type_lookup (bfd *abfd, bfd_reloc_code_real_type code);
DESCRIPTION
This routine returns a pointer to a howto struct which when
CONST struct reloc_howto_struct *
-DEFUN(bfd_reloc_type_lookup,(arch, code),
- CONST bfd_arch_info_type *arch AND
- bfd_reloc_code_type code)
+DEFUN(bfd_reloc_type_lookup,(abfd, code),
+ bfd *abfd AND
+ bfd_reloc_code_real_type code)
{
- return arch->reloc_type_lookup(arch, code);
+ return BFD_SEND (abfd, reloc_type_lookup, (abfd, code));
}
static reloc_howto_type bfd_howto_32 =
SYNOPSIS
CONST struct reloc_howto_struct *bfd_default_reloc_type_lookup
(CONST struct bfd_arch_info *,
- bfd_reloc_code_type code);
+ bfd_reloc_code_real_type code);
DESCRIPTION
Provides a default relocation lookuperer for any architectue
CONST struct reloc_howto_struct *
DEFUN(bfd_default_reloc_type_lookup,(arch, code),
CONST struct bfd_arch_info *arch AND
- bfd_reloc_code_type code)
+ bfd_reloc_code_real_type code)
{
switch (code)
{
default:
BFD_FAIL();
}
-return (struct reloc_howto_struct *)NULL;
+return (CONST struct reloc_howto_struct *)NULL;
}
boolean bfd_generic_relax_section
(bfd *abfd,
asection *section,
- asymbol **symbols,
- struct bfd_seclet_struct *seclet);
+ asymbol **symbols);
DESCRIPTION
Provides default handling for relaxing for back ends which
- don't do relaxing - ie does nothing
+ don't do relaxing -- i.e., does nothing.
*/
boolean
-DEFUN(bfd_generic_relax_section,(abfd, section, symbols, seclet),
+DEFUN(bfd_generic_relax_section,(abfd, section, symbols),
bfd *abfd AND
asection *section AND
- asymbol **symbols AND
- struct bfd_seclet_struct *seclet)
+ asymbol **symbols)
{
return false;
SYNOPSIS
bfd_byte *
bfd_generic_get_relocated_section_contents(bfd *abfd,
- struct bfd_seclet_struct *seclet)
+ struct bfd_seclet_struct *seclet,
+ bfd_byte *data)
DESCRIPTION
Provides default handling of relocation effort for back ends
*/
bfd_byte *
-DEFUN(bfd_generic_get_relocated_section_contents,(abfd, seclet),
+DEFUN(bfd_generic_get_relocated_section_contents,(abfd, seclet, data),
bfd *abfd AND
- struct bfd_seclet_struct *seclet)
+ struct bfd_seclet_struct *seclet AND
+ bfd_byte *data)
{
extern bfd_error_vector_type bfd_error_vector;
-
-
- asymbol **symbols = 0;
/* Get enough memory to hold the stuff */
bfd *input_bfd = seclet->u.indirect.section->owner;
asection *input_section = seclet->u.indirect.section;
- bfd_byte *data = (bfd_byte *)malloc(input_section->_raw_size);
- bfd_byte *dst = data;
- bfd_byte *prev_dst = data;
- unsigned int gap = 0;
+
bfd_size_type reloc_size = bfd_get_reloc_upper_bound(input_bfd,
input_section);
- arelent **reloc_vector = (arelent **)malloc(reloc_size);
+ arelent **reloc_vector = (arelent **) alloca(reloc_size);
/* read in the section */
bfd_get_section_contents(input_bfd,
if (r != bfd_reloc_ok)
{
- asymbol *s;
-
switch (r)
{
case bfd_reloc_undefined:
}
}
- free((char *)reloc_vector);
+
return data;