New entry point in the transfer vector - bfd_relax_section.

* aout-target.h: add to vector, call generic_relax
	* bfd-in.h: add to vector
	* bfd.c: add #define for vector
	* bout.c: add to vector, call generic_relax
	* coffcode.h: add to vector, also now has coff specific relax code
	for the relaxable H8/300 relocs. Also clean up abs section cruft.
	* elf.c: call generic_relax
	* ieee.c: call new vector, clean up some bugs due to the creation
	of bfd_abs_section
	* libbfd.h: add bfd_generic_relax_section EXFUN
	* oasys.c: call generic_relax
	* reloc.c: implement generic_relax
	* seclet.c: moved much of this into coffcode.h
	* srec.c: call generic_relax
	* targets.c: define new transfer vector
This commit is contained in:
Steve Chamberlain 1992-01-28 06:01:25 +00:00
parent 9ce31b6601
commit 6590a8c953
4 changed files with 485 additions and 274 deletions

View File

@ -1,3 +1,25 @@
Mon Jan 27 19:44:08 1992 Steve Chamberlain (sac at rtl.cygnus.com)
New entry point in the transfer vector - bfd_relax_section.
* aout-target.h: add to vector, call generic_relax
* bfd-in.h: add to vector
* bfd.c: add #define for vector
* bout.c: add to vector, call generic_relax
* coffcode.h: add to vector, also now has coff specific relax code
for the relaxable H8/300 relocs. Also clean up abs section cruft.
* elf.c: call generic_relax
* ieee.c: call new vector, clean up some bugs due to the creation
of bfd_abs_section
* libbfd.h: add bfd_generic_relax_section EXFUN
* oasys.c: call generic_relax
* reloc.c: implement generic_relax
* seclet.c: moved much of this into coffcode.h
* srec.c: call generic_relax
* targets.c: define new transfer vector
Fri Jan 24 14:40:17 1992 Steve Chamberlain (sac at rtl.cygnus.com)
* everything: now modified to use smaller reloc type. Self hosts

View File

@ -573,6 +573,10 @@ DESCRIPTION
.
.#define bfd_get_relocated_section_contents(abfd, seclet) \
. BFD_SEND (abfd, _bfd_get_relocated_section_contents, (abfd, seclet))
.
.#define bfd_relax_section(abfd, section, symbols) \
. BFD_SEND (abfd, _bfd_relax_section, (abfd, section, symbols))
*/

View File

@ -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

View File

@ -50,248 +50,7 @@ DEFUN(bfd_new_seclet,(abfd, section),
#define MAX_ERRORS_IN_A_ROW 10
extern bfd_error_vector_type bfd_error_vector;
bfd_vma
DEFUN(get_value,(reloc, seclet),
arelent *reloc AND
bfd_seclet_type *seclet)
{
bfd_vma value;
if (reloc->sym_ptr_ptr)
{
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 == (asection *)NULL)
{
/* 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;
}
}
else
{
value = 0;
}
/* Add the value contained in the relocation */
value += (short)((reloc->addend) & 0xffff);
return value;
}
static char *
DEFUN(foo_bfd_get_relocated_section_contents,(seclet),
bfd_seclet_type *seclet)
{
asymbol **symbols = 0;
extern bfd *output_bfd;
bfd *abfd;
/* 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 **)ldmalloc(reloc_size);
abfd = output_bfd;
/* 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(abfd,gap, data+dst_address);
switch (data[dst_address-1])
{
case 0x5e:
/* jsr -> bsr */
bfd_put_8(abfd, 0x55, data+dst_address-1);
break;
case 0x5a:
/* jmp ->bra */
bfd_put_8(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(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(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(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(abfd, get_value(reloc,seclet), data+dst_address);
dst_address+=2;
src_address+=2;
break;
default:
abort();
}
}
}
}
free((char *)reloc_vector);
return data;
}
void
DEFUN(rel,(abfd, seclet, output_section),