diff options
author | Steve Chamberlain <sac@cygnus> | 1992-05-01 20:00:26 +0000 |
---|---|---|
committer | Steve Chamberlain <sac@cygnus> | 1992-05-01 20:00:26 +0000 |
commit | 859f11ffd8ff43fd7014b5c04d4a1294e7328066 (patch) | |
tree | 540f2ad6fb736c90057c55e94d2b46c5dfb8503c /bfd/coff-a29k.c | |
parent | 7e7e2d40c1404de249d9f071d859d8c376e92bda (diff) | |
download | gdb-859f11ffd8ff43fd7014b5c04d4a1294e7328066.zip gdb-859f11ffd8ff43fd7014b5c04d4a1294e7328066.tar.gz gdb-859f11ffd8ff43fd7014b5c04d4a1294e7328066.tar.bz2 |
* coff-a29k.c: various changes to the way relocations work to cope
with the "new order" and latent bugs.
* coffcode.h: lint
Diffstat (limited to 'bfd/coff-a29k.c')
-rw-r--r-- | bfd/coff-a29k.c | 272 |
1 files changed, 141 insertions, 131 deletions
diff --git a/bfd/coff-a29k.c b/bfd/coff-a29k.c index c5b79d9..5ec48aa 100644 --- a/bfd/coff-a29k.c +++ b/bfd/coff-a29k.c @@ -44,19 +44,17 @@ asymbol *symbol; { long relocation = 0; - if (symbol != (asymbol *)NULL) { - if (symbol->section == &bfd_com_section) - { - - relocation = 0; - } else { - relocation = symbol->value; - } - if (symbol->section != (asection *)NULL) { - relocation += symbol->section->output_section->vma + - symbol->section->output_offset; - } + if (symbol->section == &bfd_com_section) + { + relocation = 0; } + else + { + relocation = symbol->value + + symbol->section->output_section->vma + + symbol->section->output_offset; + } + return(relocation); } @@ -70,132 +68,145 @@ DEFUN(a29k_reloc,(abfd, reloc_entry, symbol_in, data, input_section), PTR data AND asection *input_section) { - /* the consth relocation comes in two parts, we have to remember - the state between calls, in these variables */ - static boolean part1_consth_active = false; - static unsigned long part1_consth_value; - - unsigned long insn; - unsigned long sym_value; - unsigned long unsigned_value; - unsigned short r_type; - long signed_value; - + /* the consth relocation comes in two parts, we have to remember + the state between calls, in these variables */ + static boolean part1_consth_active = false; + static unsigned long part1_consth_value; + + unsigned long insn; + unsigned long sym_value; + unsigned long unsigned_value; + unsigned short r_type; + long signed_value; + + unsigned long addr = reloc_entry->address + input_section->vma; + bfd_byte *hit_data =addr + (bfd_byte *)(data); - r_type = reloc_entry->howto->type; + r_type = reloc_entry->howto->type; - /* FIXME: Do we need to check for partial linking here */ - if (symbol_in && (symbol_in->section == &bfd_und_section)) + /* FIXME: Do we need to check for partial linking here */ + if (symbol_in && (symbol_in->section == &bfd_und_section)) + { + /* Keep the state machine happy in case we're called again */ + if (r_type == R_IHIHALF) { - /* Keep the state machine happy in case we're called again */ - if (r_type == R_IHIHALF) - { - part1_consth_active = true; - part1_consth_value = 0; - } - return(bfd_reloc_undefined); + part1_consth_active = true; + part1_consth_value = 0; } + return(bfd_reloc_undefined); + } - if ((part1_consth_active) && (r_type != R_IHCONST)) - { - fprintf(stderr,"Relocation problem : "); - fprintf(stderr,"Missing IHCONST in module %s\n",abfd->filename); - part1_consth_active = false; - return(bfd_reloc_dangerous); - } + if ((part1_consth_active) && (r_type != R_IHCONST)) + { + fprintf(stderr,"Relocation problem : "); + fprintf(stderr,"Missing IHCONST in module %s\n",abfd->filename); + part1_consth_active = false; + return(bfd_reloc_dangerous); + } - insn = bfd_get_32(abfd, (bfd_byte *)data + reloc_entry->address); - sym_value = get_symbol_value(symbol_in); - switch (r_type) + sym_value = get_symbol_value(symbol_in); + + switch (r_type) + { + case R_IREL: + insn = bfd_get_32(abfd, hit_data); + /* Take the value in the field and sign extend it */ + signed_value = EXTRACT_HWORD(insn) << 2; + signed_value = SIGN_EXTEND_HWORD(signed_value); + signed_value += sym_value + reloc_entry->addend; + if ((signed_value&~0x3ffff) == 0) + { /* Absolute jmp/call */ + insn |= (1<<24); /* Make it absolute */ + /* FIXME: Should we change r_type to R_IABS */ + signed_value /= 2; + } + else { - case R_IREL: - /* Take the value in the field and sign extend it */ - signed_value = EXTRACT_HWORD(insn) << 2; - signed_value = SIGN_EXTEND_HWORD(signed_value); - signed_value += sym_value + reloc_entry->addend; - if ((signed_value&~0x3ffff) == 0) - { /* Absolute jmp/call */ - insn |= (1<<24); /* Make it absolute */ - /* FIXME: Should we change r_type to R_IABS */ - signed_value /= 2; - } - else - { - /* Relative jmp/call, so subtract from the value the - address of the place we're coming from */ - signed_value -= reloc_entry->address + - input_section->output_section->vma + - input_section->output_offset; - if (signed_value>0x1ffff || signed_value<-0x20000) - return(bfd_reloc_outofrange); - - signed_value /= 2; - } - insn = INSERT_HWORD(insn, signed_value); - break; - case R_ILOHALF: - unsigned_value = EXTRACT_HWORD(insn); - unsigned_value += sym_value + reloc_entry->addend; - insn = INSERT_HWORD(insn, unsigned_value); - break; - case R_IHIHALF: - /* consth, part 1 - Just get the symbol value that is referenced */ - part1_consth_active = true; - part1_consth_value = sym_value + reloc_entry->addend; - /* Don't modify insn until R_IHCONST */ - return(bfd_reloc_ok); - break; - case R_IHCONST: - /* consth, part 2 - Now relocate the reference */ - if (part1_consth_active == false) { - fprintf(stderr,"Relocation problem : "); - fprintf(stderr,"IHIHALF missing in module %s\n", - abfd->filename); - return(bfd_reloc_dangerous); - } - /* sym_ptr_ptr = r_symndx, in coff_slurp_reloc_table() */ - unsigned_value = 0; /*EXTRACT_HWORD(insn) << 16;*/ - unsigned_value += reloc_entry->addend; /* r_symndx */ - unsigned_value += part1_consth_value; - unsigned_value = unsigned_value >> 16; - insn = INSERT_HWORD(insn, unsigned_value); - part1_consth_active = false; - break; - case R_BYTE: - unsigned_value = (insn >> 24) + sym_value + reloc_entry->addend; - if (unsigned_value & 0xffffff00) { - fprintf(stderr,"Relocation problem : "); - fprintf(stderr,"byte value too large in module %s\n", - abfd->filename); - return(bfd_reloc_overflow); - } - insn = (insn & 0x00ffffff) | (unsigned_value << 24); - break; - case R_HWORD: - unsigned_value = (insn >> 16) + sym_value + reloc_entry->addend; - if (unsigned_value & 0xffff0000) { - fprintf(stderr,"Relocation problem : "); - fprintf(stderr,"hword value too large in module %s\n", - abfd->filename); - return(bfd_reloc_overflow); - } - insn = (insn & 0x0000ffff) | (unsigned_value<<16); - break; - case R_WORD: - insn += sym_value + reloc_entry->addend; - break; - default: - fprintf(stderr,"Relocation problem : "); - fprintf(stderr,"Unrecognized reloc type %d, in module %s\n", - r_type,abfd->filename); - return (bfd_reloc_dangerous); + /* Relative jmp/call, so subtract from the value the + address of the place we're coming from */ + signed_value -= reloc_entry->address + + input_section->output_section->vma + + input_section->output_offset; + if (signed_value>0x1ffff || signed_value<-0x20000) + return(bfd_reloc_outofrange); + + signed_value /= 2; + } + insn = INSERT_HWORD(insn, signed_value); + bfd_put_32(abfd, insn ,hit_data); + break; + case R_ILOHALF: + insn = bfd_get_32(abfd, hit_data); + unsigned_value = EXTRACT_HWORD(insn); + unsigned_value += sym_value + reloc_entry->addend; + insn = INSERT_HWORD(insn, unsigned_value); + bfd_put_32(abfd, insn, hit_data); + break; + case R_IHIHALF: + insn = bfd_get_32(abfd, hit_data); + /* consth, part 1 + Just get the symbol value that is referenced */ + part1_consth_active = true; + part1_consth_value = sym_value + reloc_entry->addend; + /* Don't modify insn until R_IHCONST */ + break; + case R_IHCONST: + insn = bfd_get_32(abfd, hit_data); + /* consth, part 2 + Now relocate the reference */ + if (part1_consth_active == false) { + fprintf(stderr,"Relocation problem : "); + fprintf(stderr,"IHIHALF missing in module %s\n", + abfd->filename); + return(bfd_reloc_dangerous); + } + /* sym_ptr_ptr = r_symndx, in coff_slurp_reloc_table() */ + unsigned_value = 0; /*EXTRACT_HWORD(insn) << 16;*/ + unsigned_value += reloc_entry->addend; /* r_symndx */ + unsigned_value += part1_consth_value; + unsigned_value = unsigned_value >> 16; + insn = INSERT_HWORD(insn, unsigned_value); + part1_consth_active = false; + bfd_put_32(abfd, insn, hit_data); + break; + case R_BYTE: + insn = bfd_get_8(abfd, hit_data); + unsigned_value = insn + sym_value + reloc_entry->addend; + if (unsigned_value & 0xffffff00) { + fprintf(stderr,"Relocation problem : "); + fprintf(stderr,"byte value too large in module %s\n", + abfd->filename); + return(bfd_reloc_overflow); } + bfd_put_8(abfd, insn, hit_data); + break; + case R_HWORD: + insn = bfd_get_16(abfd, hit_data); + unsigned_value = insn + sym_value + reloc_entry->addend; + if (unsigned_value & 0xffff0000) { + fprintf(stderr,"Relocation problem : "); + fprintf(stderr,"hword value too large in module %s\n", + abfd->filename); + return(bfd_reloc_overflow); + } + + bfd_put_16(abfd, insn, hit_data); + break; + case R_WORD: + insn = bfd_get_32(abfd, hit_data); + insn += sym_value + reloc_entry->addend; + bfd_put_32(abfd, insn, hit_data); + break; + default: + fprintf(stderr,"Relocation problem : "); + fprintf(stderr,"Unrecognized reloc type %d, in module %s\n", + r_type,abfd->filename); + return (bfd_reloc_dangerous); + } - bfd_put_32(abfd, insn, (bfd_byte *)data + reloc_entry->address); - return(bfd_reloc_ok); + + return(bfd_reloc_ok); } /* type rightshift @@ -259,17 +270,16 @@ static void DEFUN(reloc_processing,(relent,reloc, symbols, abfd, section) , if (ptr && ptr->the_bfd == abfd - && ptr->section != (asection *) NULL + && ((ptr->flags & BSF_OLD_COMMON)== 0)) { - relent->addend = -(ptr->section->vma + ptr->value); + relent->addend = 0; } else { relent->addend = 0; } relent->address-= section->vma; -/* relent->section = 0;*/ } } |