diff options
Diffstat (limited to 'bfd/coffcode.h')
-rw-r--r-- | bfd/coffcode.h | 492 |
1 files changed, 459 insertions, 33 deletions
diff --git a/bfd/coffcode.h b/bfd/coffcode.h index 3662269..7862f84 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -18,6 +18,10 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* +Most of this hacked by Steve Chamberlain, + sac@cygnus.com +*/ /* SECTION @@ -256,7 +260,10 @@ CODE_FRAGMENT */ -/* Most of this hacked by Steve Chamberlain, steve@cygnus.com */ +#include "seclet.h" +extern bfd_error_vector_type bfd_error_vector; + + #define PUTWORD bfd_h_put_32 @@ -882,11 +889,17 @@ DEFUN(coff_new_section_hook,(abfd_ignore, section), return true; } +static asection bfd_debug_section = +{ "*DEBUG*" }; + + + static void DEFUN(make_abs_section,(abfd), bfd *abfd) { - abort(); + + } @@ -965,7 +978,7 @@ DEFUN(coff_mkobject,(abfd), return false; } coff_data(abfd)->relocbase = 0; - make_abs_section(abfd); +/* make_abs_section(abfd);*/ return true; } @@ -1379,10 +1392,13 @@ DEFUN(coff_mangle_symbols,(bfd_ptr), if (a->fix_tag) { a->u.auxent.x_sym.x_tagndx.l = a->u.auxent.x_sym.x_tagndx.p->offset; + a->fix_tag = 0; } if (a->fix_end) { a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l = a->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p->offset; + a->fix_end = 0; + } } @@ -1456,20 +1472,37 @@ unsigned int written) int class = native->u.syment.n_sclass; SYMENT buf; unsigned int j; - native->u.syment.n_scnum = symbol->section->output_section->target_index; + if (symbol->section == &bfd_abs_section) + { + native->u.syment.n_scnum = N_ABS; + } + else if (symbol->section == &bfd_debug_section) + { + native->u.syment.n_scnum = N_DEBUG; + } + else if (symbol->section == &bfd_und_section) + { + native->u.syment.n_scnum = N_UNDEF; + } + else + { + native->u.syment.n_scnum = + symbol->section->output_section->target_index; + } + coff_fix_symbol_name(abfd, symbol, native); coff_swap_sym_out(abfd, &native->u.syment, &buf); bfd_write((PTR)& buf, 1, SYMESZ, abfd); for (j = 0; j != native->u.syment.n_numaux; j++) - { - AUXENT buf1; - bzero((PTR)&buf, AUXESZ); - coff_swap_aux_out(abfd, - &( (native + j + 1)->u.auxent), type, class, &buf1); - bfd_write((PTR) (&buf1), 1, AUXESZ, abfd); - } + { + AUXENT buf1; + bzero((PTR)&buf, AUXESZ); + coff_swap_aux_out(abfd, + &( (native + j + 1)->u.auxent), type, class, &buf1); + bfd_write((PTR) (&buf1), 1, AUXESZ, abfd); + } /* Reuse somewhere in the symbol to keep the index */ @@ -1496,7 +1529,8 @@ DEFUN(coff_write_alien_symbol,(abfd, symbol, written), #ifdef I960 native->u.syment.n_flags = 0; #endif - if (symbol->section == &bfd_und_section) { + if (symbol->section == &bfd_und_section) + { native->u.syment.n_scnum = N_UNDEF; native->u.syment.n_value = symbol->value; } @@ -2033,7 +2067,7 @@ DEFUN(coff_compute_section_file_positions,(abfd), old_sofar= sofar; sofar = BFD_ALIGN(sofar, 1 << current->alignment_power); if (previous != (asection *)NULL) { - previous->_cooked_size += sofar - old_sofar; + previous->_raw_size += sofar - old_sofar; } } @@ -2046,7 +2080,7 @@ DEFUN(coff_compute_section_file_positions,(abfd), current->filepos = sofar; /* make sure that this section is of the right size too */ - old_sofar = sofar += current->_cooked_size; + old_sofar = sofar += current->_raw_size; sofar = BFD_ALIGN(sofar, 1 << current->alignment_power); current->_raw_size += sofar - old_sofar ; @@ -2091,15 +2125,13 @@ DEFUN(coff_write_object_contents,(abfd), for (current = abfd->sections; current != (asection *)NULL; current = current->next) { - if (current->name[0] != '*') - { current->target_index = count; - count++; - } } + + if(abfd->output_has_begun == false) { coff_compute_section_file_positions(abfd); } @@ -2195,12 +2227,12 @@ DEFUN(coff_write_object_contents,(abfd), strncpy(&(section.s_name[0]), current->name, 8); section.s_vaddr = current->vma + pad; section.s_paddr = current->vma + pad; - section.s_size = current->_cooked_size - pad; + section.s_size = current->_raw_size - pad; /* If this section has no size or is unloadable then the scnptr will be 0 too */ - if (current->_cooked_size - pad == 0 || + if (current->_raw_size - pad == 0 || (current->flags & SEC_LOAD) == 0) { section.s_scnptr = 0; } @@ -2359,15 +2391,15 @@ DEFUN(coff_write_object_contents,(abfd), } #endif /* NO_COFF_SYMBOLS */ if (text_sec) { - internal_a.tsize = bfd_get_section_size_after_reloc(text_sec); + internal_a.tsize = bfd_get_section_size_before_reloc(text_sec); internal_a.text_start = internal_a.tsize ? text_sec->vma : 0; } if (data_sec) { - internal_a.dsize = bfd_get_section_size_after_reloc(data_sec); + internal_a.dsize = bfd_get_section_size_before_reloc(data_sec); internal_a.data_start = internal_a.dsize ? data_sec->vma : 0; } if (bss_sec) { - internal_a.bsize = bfd_get_section_size_after_reloc(bss_sec); + internal_a.bsize = bfd_get_section_size_before_reloc(bss_sec); } internal_a.entry = bfd_get_start_address(abfd); @@ -2411,14 +2443,15 @@ combined_entry_type *auxent) /* Otherwise patch up */ if (ISFCN(type) || ISTAG(class) || class == C_BLOCK) { - auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p = table_base + - auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l; - auxent->fix_end = 1; - } + auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.p = table_base + + auxent->u.auxent.x_sym.x_fcnary.x_fcn.x_endndx.l; + auxent->fix_end = 1; + } if (auxent->u.auxent.x_sym.x_tagndx.l != 0) { - auxent->u.auxent.x_sym.x_tagndx.p = table_base + auxent->u.auxent.x_sym.x_tagndx.l; - auxent->fix_tag = 1; - } + auxent->u.auxent.x_sym.x_tagndx.p = + table_base + auxent->u.auxent.x_sym.x_tagndx.l; + auxent->fix_tag = 1; + } } #endif /* NO_COFF_SYMBOLS */ @@ -2753,6 +2786,20 @@ DEFUN(section_from_bfd_index,(abfd, index), int index) { struct sec *answer = abfd->sections; + + if (index == N_ABS) + { + return &bfd_abs_section; + } + if (index == N_UNDEF) + { + return &bfd_und_section; + } + if(index == N_DEBUG) + { + return &bfd_debug_section; + + } while (answer) { if (answer->target_index == index) @@ -3033,7 +3080,7 @@ DEFUN(coff_slurp_symbol_table,(abfd), break; } - BFD_ASSERT(dst->symbol.flags != 0); +/* BFD_ASSERT(dst->symbol.flags != 0);*/ dst->native = src; @@ -3446,6 +3493,384 @@ DEFUN(coff_sizeof_headers,(abfd, reloc), return size; } +static bfd_vma +DEFUN(get_value,(reloc, seclet), + arelent *reloc AND + bfd_seclet_type *seclet) +{ + bfd_vma value; + asymbol *symbol = *(reloc->sym_ptr_ptr); + /* A symbol holds a pointer to a section, and an offset from the + base of the section. To relocate, we find where the section will + live in the output and add that in */ + + if (symbol->section == &bfd_und_section) + { + /* Ouch, this is an undefined symbol.. */ + bfd_error_vector.undefined_symbol(reloc, seclet); + value = symbol->value; + } + else + { + value = symbol->value + + symbol->section->output_offset + + symbol->section->output_section->vma; + } + + + /* Add the value contained in the relocation */ + value += (short)((reloc->addend) & 0xffff); + + return value; +} + +static void +DEFUN(perform_slip,(s, slip, input_section, value), + asymbol **s AND + unsigned int slip AND + asection *input_section AND + bfd_vma value) +{ + + /* Find all symbols past this point, and make them know + what's happened */ + while (*s) + { + asymbol *p = *s; + if (p->section == input_section) + { + /* This was pointing into this section, so mangle it */ + if (p->value > value) + { + p->value -=2; + } + } + s++; + + } +} +static int +DEFUN(movb1,(input_section, symbols, r, shrink), + asection *input_section AND + asymbol **symbols AND + arelent *r AND + unsigned int shrink) +{ + bfd_vma value = get_value(r,0); + + if (value >= 0xff00) + { + + /* Change the reloc type from 16bit, possible 8 to 8bit + possible 16 */ + r->howto = r->howto + 1; + /* The place to relc moves back by one */ + r->address -=1; + + /* This will be two bytes smaller in the long run */ + shrink +=2 ; + perform_slip(symbols, 2, input_section, r->address - shrink +1); + + + } + return shrink; +} + +static int +DEFUN(jmp1,(input_section, symbols, r, shrink), + asection *input_section AND + asymbol **symbols AND + arelent *r AND + unsigned int shrink) +{ + + + bfd_vma value = get_value(r, 0); + + bfd_vma dot = input_section->output_section->vma + + input_section->output_offset + r->address; + bfd_vma gap; + + /* See if the address we're looking at within 127 bytes of where + we are, if so then we can use a small branch rather than the + jump we were going to */ + + gap = value - (dot - shrink); + + + if (-120 < (long)gap && (long)gap < 120 ) + { + + /* Change the reloc type from 16bit, possible 8 to 8bit + possible 16 */ + r->howto = r->howto + 1; + /* The place to relc moves back by one */ + r->address -=1; + + /* This will be two bytes smaller in the long run */ + shrink +=2 ; + perform_slip(symbols, 2, input_section, r->address-shrink +1); + + + } + return shrink; +} + +extern boolean +DEFUN(bfd_coff_relax_section,(abfd, i, symbols, seclet), + bfd *abfd AND + asection *i AND + asymbol **symbols AND + bfd_seclet_type *seclet) +{ + + /* Get enough memory to hold the stuff */ + bfd *input_bfd = i->owner; + asection *input_section = i; + int shrink = 0 ; + int new = 0; + + bfd_size_type reloc_size = bfd_get_reloc_upper_bound(input_bfd, + input_section); + arelent **reloc_vector = (arelent **)bfd_xmalloc(reloc_size); + + /* Get the relocs and think about them */ + if (bfd_canonicalize_reloc(input_bfd, + input_section, + reloc_vector, + symbols)) + { + arelent **parent; + for (parent = reloc_vector; *parent; parent++) + { + arelent *r = *parent; + switch (r->howto->type) { + case R_MOVB2: + case R_JMP2: + + shrink+=2; + break; + + case R_MOVB1: + shrink = movb1(input_section, symbols, r, shrink); + new = 1; + + break; + case R_JMP1: + shrink = jmp1(input_section, symbols, r, shrink); + new = 1; + + break; + } + } + + } + input_section->_cooked_size -= shrink; + free((char *)reloc_vector); + return new; +} + +static bfd_byte * +DEFUN(bfd_coff_get_relocated_section_contents,(in_abfd, seclet), + bfd *in_abfd AND + bfd_seclet_type *seclet) + +{ + asymbol **symbols = 0; + extern bfd *output_bfd; + + /* Get enough memory to hold the stuff */ + bfd *input_bfd = seclet->u.indirect.section->owner; + asection *input_section = seclet->u.indirect.section; + + char *data = malloc(input_section->_raw_size); + char *dst = data; + char *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 **)bfd_xmalloc(reloc_size); + + /* read in the section */ + bfd_get_section_contents(input_bfd, + input_section, + data, + 0, + input_section->_raw_size); + + + if (bfd_canonicalize_reloc(input_bfd, + input_section, + reloc_vector, + seclet->u.indirect.symbols) ) + { + arelent **parent = reloc_vector; + arelent *reloc ; + + + + unsigned int dst_address = 0; + unsigned int src_address = 0; + unsigned int run; + unsigned int idx; + + /* Find how long a run we can do */ + while (dst_address < seclet->size) + { + + reloc = *parent; + if (reloc) + { + /* Note that the relaxing didn't tie up the addresses in the + relocation, so we use the original address to work out the + run of non-relocated data */ + run = reloc->address - src_address; + parent++; + + } + else + { + run = seclet->size - dst_address; + } + /* Copy the bytes */ + for (idx = 0; idx < run; idx++) + { + data[dst_address++] = data[src_address++]; + } + + /* Now do the relocation */ + + if (reloc) + { + switch (reloc->howto->type) + { + case R_JMP2: + /* Speciial relaxed type */ + { + bfd_vma dot = seclet->offset + dst_address + seclet->u.indirect.section->output_section->vma; + int gap = get_value(reloc,seclet)-dot-1; + if ((gap & ~0xff ) != 0 &&((gap & 0xff00)!= 0xff00)) abort(); + + bfd_put_8(in_abfd,gap, data+dst_address); + + switch (data[dst_address-1]) + { + + case 0x5e: + /* jsr -> bsr */ + bfd_put_8(in_abfd, 0x55, data+dst_address-1); + break; + case 0x5a: + /* jmp ->bra */ + bfd_put_8(in_abfd, 0x40, data+dst_address-1); + break; + + default: + abort(); + + } + + + + + dst_address++; + src_address+=3; + + break; + } + + + case R_MOVB2: + /* Special relaxed type, there will be a gap between where we + get stuff from and where we put stuff to now + + for a mov.b @aa:16 -> mov.b @aa:8 + opcode 0x6a 0x0y offset + -> 0x2y off + */ + if (data[dst_address-1] != 0x6a) + abort(); + switch (data[dst_address] & 0xf0) + { + case 0x00: + /* Src is memory */ + data[dst_address-1] = (data[src_address] & 0xf) | 0x20; + break; + case 0x80: + /* Src is reg */ + data[dst_address-1] = (data[src_address] & 0xf) | 0x30; + break; + default: + abort(); + } + + /* the offset must fit ! after all, what was all the relaxing + about ? */ + + bfd_put_8(in_abfd, get_value(reloc, seclet), data + dst_address); + + /* Note the magic - src goes up by two bytes, but dst by only + one */ + dst_address+=1; + src_address+=3; + + break; + /* PCrel 8 bits */ + case R_PCRBYTE: + { + bfd_vma dot = seclet->offset + dst_address + seclet->u.indirect.section->output_section->vma; + int gap = get_value(reloc,seclet)-dot; + if (gap > 127 || gap < -128) + { + bfd_error_vector.reloc_value_truncated(reloc, seclet); + } + + bfd_put_8(in_abfd,gap, data+dst_address); + dst_address++; + src_address++; + + break; + } + + case R_RELBYTE: + { + unsigned int gap =get_value(reloc,seclet); + if (gap > 256) + { + bfd_error_vector.reloc_value_truncated(reloc, seclet); + } + + bfd_put_8(in_abfd, gap, data+dst_address); + dst_address+=1; + src_address+=1; + + + } + break; + case R_JMP1: + /* A relword which would have like to have been a pcrel */ + case R_MOVB1: + /* A relword which would like to have been modified but + didn't make it */ + case R_RELWORD: + bfd_put_16(in_abfd, get_value(reloc,seclet), data+dst_address); + dst_address+=2; + src_address+=2; + break; + + default: + abort(); + } + } + } + } + free((char *)reloc_vector); + return data; + +} + #define coff_core_file_failing_command _bfd_dummy_core_file_failing_command #define coff_core_file_failing_signal _bfd_dummy_core_file_failing_signal @@ -3461,5 +3886,6 @@ DEFUN(coff_sizeof_headers,(abfd, reloc), #define coff_bfd_debug_info_start bfd_void #define coff_bfd_debug_info_end bfd_void #define coff_bfd_debug_info_accumulate (PROTO(void,(*),(bfd*, struct sec *))) bfd_void -#define coff_bfd_get_relocated_section_contents \ - bfd_generic_get_relocated_section_contents +#define coff_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents +#define coff_bfd_relax_section bfd_generic_relax_section + |