These changes make shared library support work again on 386 COFF

systems.

	* coffcode.h (styp_to_sec_flags): Set SEC_SHARED_LIBRARY for a
	STYP_NOLOAD | STYP_BSS section.  Don't set SEC_NEVER_LOAD for a
	STYP_INFO section.
	(coff_compute_section_file_positions): Force vma and lma of _LIB
	section to be zero.
	(coff_set_section_contents): Count number of entries in new lma
	field, not in vma.
	* coffgen.c (make_a_section_from_file): Force lineno_count of
	SEC_SHARED_LIBRARY section to be zero, since it is non-zero on the
	SCO 3.2v4 shared library.
	* seclet.c (rel): Copy over any section with contents, not just
	loadable sections.

	* coff-mips.c (ecoff_make_empty_symbol): Zero out newly allocated
	symbol.
This commit is contained in:
Ian Lance Taylor 1993-04-06 00:53:41 +00:00
parent d802b9481b
commit 46bc1bf6ba
3 changed files with 132 additions and 63 deletions

View File

@ -1,5 +1,21 @@
Mon Apr 5 12:07:12 1993 Ian Lance Taylor (ian@cygnus.com)
* coffcode.h (styp_to_sec_flags): Set SEC_SHARED_LIBRARY for a
STYP_NOLOAD | STYP_BSS section. Don't set SEC_NEVER_LOAD for a
STYP_INFO section.
(coff_compute_section_file_positions): Force vma and lma of _LIB
section to be zero.
(coff_set_section_contents): Count number of entries in new lma
field, not in vma.
* coffgen.c (make_a_section_from_file): Force lineno_count of
SEC_SHARED_LIBRARY section to be zero, since it is non-zero on the
SCO 3.2v4 shared library.
* seclet.c (rel): Copy over any section with contents, not just
loadable sections.
* coff-mips.c (ecoff_make_empty_symbol): Zero out newly allocated
symbol.
* coff-i386.c (coff_i386_reloc): New function, to generate
relocateable output correctly.
(howto_table): Use coff_i386_reloc for all reloc types.

View File

@ -59,12 +59,6 @@ typedef struct ecoff_symbol_struct
macro is only ever applied to an asymbol. */
#define ecoffsymbol(asymbol) ((ecoff_symbol_type *) (&((asymbol)->the_bfd)))
/* This is a hack borrowed from coffcode.h; we need to save the index
of a symbol when we write it out so that can set the symbol index
correctly when we write out the relocs. */
#define ecoff_get_sym_index(symbol) ((unsigned long) (symbol)->udata)
#define ecoff_set_sym_index(symbol, idx) ((symbol)->udata = (PTR) (idx))
/* The page boundary used to align sections in the executable file. */
#define PAGE_SIZE 0x2000
@ -122,6 +116,12 @@ static bfd_reloc_status_type ecoff_refhi_reloc PARAMS ((bfd *abfd,
PTR data,
asection *section,
bfd *output_bfd));
static bfd_reloc_status_type ecoff_reflo_reloc PARAMS ((bfd *abfd,
arelent *reloc,
asymbol *symbol,
PTR data,
asection *section,
bfd *output_bfd));
static bfd_reloc_status_type ecoff_gprel_reloc PARAMS ((bfd *abfd,
arelent *reloc,
asymbol *symbol,
@ -264,7 +264,7 @@ ecoff_mkobject (abfd)
bfd *abfd;
{
abfd->tdata.ecoff_obj_data = ((struct ecoff_tdata *)
bfd_zalloc (abfd, sizeof(ecoff_data_type)));
bfd_zalloc (abfd, sizeof (ecoff_data_type)));
if (abfd->tdata.ecoff_obj_data == NULL)
{
bfd_error = no_memory;
@ -294,6 +294,7 @@ ecoff_mkobject_hook (abfd, filehdr, aouthdr)
return NULL;
ecoff = ecoff_data (abfd);
ecoff->gp_size = 8;
ecoff->sym_filepos = internal_f->f_symptr;
if (internal_a != (struct internal_aouthdr *) NULL)
@ -618,6 +619,7 @@ ecoff_make_empty_symbol (abfd)
bfd_error = no_memory;
return (asymbol *) NULL;
}
memset (new, 0, sizeof *new);
new->symbol.section = (asection *) NULL;
new->fdr = (FDR *) NULL;
new->local = false;
@ -648,7 +650,13 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext)
case stLabel:
case stProc:
case stStaticProc:
break;
case stNil:
if (MIPS_IS_STAB (ecoff_sym))
{
asym->flags = BSF_DEBUGGING;
return;
}
break;
default:
asym->flags = BSF_DEBUGGING;
@ -724,14 +732,10 @@ ecoff_set_symbol_info (abfd, ecoff_sym, asym, ext)
asym->flags = BSF_DEBUGGING;
break;
case scCommon:
/* FIXME: We should take a -G argument, which gives the maximum
size of objects to be put in the small common section. Until
we do, we put objects of sizes up to 8 in the small common
section. The assembler should do this for us, but the native
assembler seems to get confused. */
if (asym->value > 8)
if (asym->value > ecoff_data (abfd)->gp_size)
{
asym->section = &bfd_com_section;
asym->flags = 0;
break;
}
/* Fall through. */
@ -1491,10 +1495,11 @@ ecoff_swap_reloc_out (abfd, src, dst)
/* ECOFF relocs are either against external symbols, or against
sections. If we are producing relocateable output, and the reloc
is against an external symbol, the resulting reloc will also be
against the same symbol. In such a case, we don't want to change
anything about the way the reloc is handled, since it will all be
done at final link time. Rather than put special case code into
is against an external symbol, and nothing has given us any
additional addend, the resulting reloc will also be against the
same symbol. In such a case, we don't want to change anything
about the way the reloc is handled, since it will all be done at
final link time. Rather than put special case code into
bfd_perform_relocation, all the reloc types use this howto
function. It just short circuits the reloc if producing
relocateable output against an external symbol. */
@ -1514,7 +1519,8 @@ ecoff_generic_reloc (abfd,
bfd *output_bfd;
{
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0)
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& reloc_entry->addend == 0)
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
@ -1523,9 +1529,14 @@ ecoff_generic_reloc (abfd,
return bfd_reloc_continue;
}
/* Do a REFHI relocation. The next reloc must be the corresponding
REFLO. This has to be done in a function so that carry is handled
correctly. */
/* Do a REFHI relocation. This has to be done in combination with a
REFLO reloc, because there is a carry from the REFLO to the REFHI.
Here we just save the information we need; we do the actual
relocation when we see the REFLO. ECOFF requires that the REFLO
immediately follow the REFHI, so this ought to work. */
static bfd_byte *ecoff_refhi_addr;
static bfd_vma ecoff_refhi_addend;
static bfd_reloc_status_type
ecoff_refhi_reloc (abfd,
@ -1542,16 +1553,13 @@ ecoff_refhi_reloc (abfd,
bfd *output_bfd;
{
bfd_reloc_status_type ret;
arelent *rello;
bfd_vma relocation;
unsigned long insn;
unsigned long val;
unsigned long vallo;
/* If we're relocating, and this an external symbol, we don't want
to change anything. */
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0)
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& reloc_entry->addend == 0)
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
@ -1562,10 +1570,6 @@ ecoff_refhi_reloc (abfd,
&& output_bfd == (bfd *) NULL)
ret = bfd_reloc_undefined;
rello = reloc_entry + 1;
BFD_ASSERT (rello->howto->type == ECOFF_R_REFLO
&& *rello->sym_ptr_ptr == *reloc_entry->sym_ptr_ptr);
if (bfd_is_com_section (symbol->section))
relocation = 0;
else
@ -1578,23 +1582,9 @@ ecoff_refhi_reloc (abfd,
if (reloc_entry->address > input_section->_cooked_size)
return bfd_reloc_outofrange;
insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
vallo = bfd_get_32 (abfd, (bfd_byte *) data + rello->address) & 0xffff;
val = ((insn & 0xffff) << 16) + vallo;
val += relocation;
/* The low order 16 bits are always treated as a signed value.
Therefore, a negative value in the low order bits requires an
adjustment in the high order bits. We need to make this
adjustment in two ways: once for the bits we took from the data,
and once for the bits we are putting back in to the data. */
if ((vallo & 0x8000) != 0)
val -= 0x10000;
if ((val & 0x8000) != 0)
val += 0x10000;
insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
/* Save the information, and let REFLO do the actual relocation. */
ecoff_refhi_addr = (bfd_byte *) data + reloc_entry->address;
ecoff_refhi_addend = relocation;
if (output_bfd != (bfd *) NULL)
reloc_entry->address += input_section->output_offset;
@ -1602,6 +1592,61 @@ ecoff_refhi_reloc (abfd,
return ret;
}
/* Do a REFLO relocation. This is a straightforward 16 bit inplace
relocation; this function exists in order to do the REFHI
relocation described above. */
static bfd_reloc_status_type
ecoff_reflo_reloc (abfd,
reloc_entry,
symbol,
data,
input_section,
output_bfd)
bfd *abfd;
arelent *reloc_entry;
asymbol *symbol;
PTR data;
asection *input_section;
bfd *output_bfd;
{
if (ecoff_refhi_addr != (bfd_byte *) NULL)
{
unsigned long insn;
unsigned long val;
unsigned long vallo;
/* Do the REFHI relocation. Note that we actually don't need to
know anything about the REFLO itself, except where to find
the low 16 bits of the addend needed by the REFHI. */
insn = bfd_get_32 (abfd, ecoff_refhi_addr);
vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address)
& 0xffff);
val = ((insn & 0xffff) << 16) + vallo;
val += ecoff_refhi_addend;
/* The low order 16 bits are always treated as a signed value.
Therefore, a negative value in the low order bits requires an
adjustment in the high order bits. We need to make this
adjustment in two ways: once for the bits we took from the
data, and once for the bits we are putting back in to the
data. */
if ((vallo & 0x8000) != 0)
val -= 0x10000;
if ((val & 0x8000) != 0)
val += 0x10000;
insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff);
bfd_put_32 (abfd, insn, ecoff_refhi_addr);
ecoff_refhi_addr = (bfd_byte *) NULL;
}
/* Now do the REFLO reloc in the usual way. */
return ecoff_generic_reloc (abfd, reloc_entry, symbol, data,
input_section, output_bfd);
}
/* Do a GPREL relocation. This is a 16 bit value which must become
the offset from the gp register. */
@ -1624,10 +1669,13 @@ ecoff_gprel_reloc (abfd,
unsigned long val;
unsigned long insn;
/* If we're relocating, and this an external symbol, we don't want
to change anything. */
/* If we're relocating, and this is an external symbol with no
addend, we don't want to change anything. We will only have an
addend if this is a newly created reloc, not read from an ECOFF
file. */
if (output_bfd != (bfd *) NULL
&& (symbol->flags & BSF_SECTION_SYM) == 0)
&& (symbol->flags & BSF_SECTION_SYM) == 0
&& reloc_entry->addend == 0)
{
reloc_entry->address += input_section->output_offset;
return bfd_reloc_ok;
@ -1648,8 +1696,11 @@ ecoff_gprel_reloc (abfd,
/* We have to figure out the gp value, so that we can adjust the
symbol value correctly. We look up the symbol _gp in the output
BFD. If we can't find it, we're stuck. We cache it in the ECOFF
target data. */
if (ecoff_data (output_bfd)->gp == 0)
target data. We don't need to adjust the symbol value for an
external symbol if we are producing relocateable output. */
if (ecoff_data (output_bfd)->gp == 0
&& (relocateable == false
|| (symbol->flags & BSF_SECTION_SYM) != 0))
{
if (relocateable != false)
{
@ -1703,15 +1754,17 @@ ecoff_gprel_reloc (abfd,
insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address);
/* Set val to the offset into the section (if we are relocating
against an external symbol, insn & 0xffff will be zero and so
will reloc_entry->addend). */
/* Set val to the offset into the section or symbol. */
val = ((insn & 0xffff) + reloc_entry->addend) & 0xffff;
if (val & 0x8000)
val -= 0x10000;
/* Adjust val for the final section location and GP value. */
val += (relocation - ecoff_data (output_bfd)->gp);
/* Adjust val for the final section location and GP value. If we
are producing relocateable output, we don't want to do this for
an external symbol. */
if (relocateable == false
|| (symbol->flags & BSF_SECTION_SYM) != 0)
val += relocation - ecoff_data (output_bfd)->gp;
insn = (insn &~ 0xffff) | (val & 0xffff);
bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address);
@ -1822,7 +1875,7 @@ static reloc_howto_type ecoff_howto_table[] =
0, /* bitpos */
false, /* absolute (obsolete) */
true, /* complain_on_overflow */
ecoff_generic_reloc, /* special_function */
ecoff_reflo_reloc, /* special_function */
"REFLO", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
@ -2041,6 +2094,9 @@ ecoff_bfd_reloc_type_lookup (abfd, code)
case BFD_RELOC_LO16:
ecoff_type = ECOFF_R_REFLO;
break;
case BFD_RELOC_MIPS_GPREL:
ecoff_type = ECOFF_R_GPREL;
break;
default:
return (CONST struct reloc_howto_struct *) NULL;
}

View File

@ -79,10 +79,7 @@ DEFUN(rel,(abfd, seclet, output_section, data, relocateable),
PTR data AND
boolean relocateable)
{
if (output_section->flags & SEC_HAS_CONTENTS
&& !(output_section->flags & SEC_NEVER_LOAD)
&& (output_section->flags & SEC_LOAD)
if ((output_section->flags & SEC_HAS_CONTENTS) != 0
&& seclet->size)
{
data = (PTR) bfd_get_relocated_section_contents(abfd, seclet, data,