This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH] (version 2) Change MIPS linker stubs to allow for more than 2^15 symbols.
- From: David Daney <ddaney at avtrex dot com>
- To: binutils at sourceware dot org
- Cc: Thiemo Seufer <ths at networkno dot de>
- Date: Thu, 08 Jun 2006 16:53:55 -0700
- Subject: Re: [PATCH] (version 2) Change MIPS linker stubs to allow for more than 2^15 symbols.
- References: <4488A29D.5040100@avtrex.com> <20060608230248.GE25431@networkno.de>
Thiemo Seufer wrote:
Formatting. Otherwise ok for trunk.
Committed this version:
2006-06-08 David Daney <ddaney@avtrex.com>
* elfxx-mips.c (STUB_LI16): Removed.
(STUB_LUI): New macro.
(STUB_LI16U): Ditto.
(STUB_LI16S): Ditto.
(MIPS_FUNCTION_STUB_SIZE): Rewrote to take info parameter.
(_bfd_mips_elf_adjust_dynamic_symbol): Pass info parameter to
MIPS_FUNCTION_STUB_SIZE.
(_bfd_mips_elf_always_size_sections): Ditto.
(_bfd_mips_elf_size_dynamic_sections): Ditto.
(_bfd_mips_elf_finish_dynamic_sections): Ditto.
(_bfd_mips_elf_finish_dynamic_symbol): Rewrote stub generation
to allow larger symbol table indexes.
? doc/bfd.info
Index: ChangeLog
===================================================================
RCS file: /cvs/src/src/bfd/ChangeLog,v
retrieving revision 1.3541
diff -c -p -r1.3541 ChangeLog
*** ChangeLog 7 Jun 2006 15:38:00 -0000 1.3541
--- ChangeLog 8 Jun 2006 23:50:16 -0000
***************
*** 1,3 ****
--- 1,18 ----
+ 2006-06-08 David Daney <ddaney@avtrex.com>
+
+ * elfxx-mips.c (STUB_LI16): Removed.
+ (STUB_LUI): New macro.
+ (STUB_LI16U): Ditto.
+ (STUB_LI16S): Ditto.
+ (MIPS_FUNCTION_STUB_SIZE): Rewrote to take info parameter.
+ (_bfd_mips_elf_adjust_dynamic_symbol): Pass info parameter to
+ MIPS_FUNCTION_STUB_SIZE.
+ (_bfd_mips_elf_always_size_sections): Ditto.
+ (_bfd_mips_elf_size_dynamic_sections): Ditto.
+ (_bfd_mips_elf_finish_dynamic_sections): Ditto.
+ (_bfd_mips_elf_finish_dynamic_symbol): Rewrote stub generation
+ to allow larger symbol table indexes.
+
2006-06-07 Joseph S. Myers <joseph@codesourcery.com>
* po/Make-in (pdf, ps): New dummy targets.
Index: elfxx-mips.c
===================================================================
RCS file: /cvs/src/src/bfd/elfxx-mips.c,v
retrieving revision 1.169
diff -c -p -r1.169 elfxx-mips.c
*** elfxx-mips.c 22 May 2006 15:06:22 -0000 1.169
--- elfxx-mips.c 8 Jun 2006 23:50:20 -0000
*************** static bfd *reldyn_sorting_bfd;
*** 623,642 ****
#define MIPS_ELF_GOT_MAX_SIZE(INFO) (ELF_MIPS_GP_OFFSET (INFO) + 0x7fff)
/* Instructions which appear in a stub. */
! #define STUB_LW(abfd) \
! ((ABI_64_P (abfd) \
! ? 0xdf998010 /* ld t9,0x8010(gp) */ \
! : 0x8f998010)) /* lw t9,0x8010(gp) */
! #define STUB_MOVE(abfd) \
! ((ABI_64_P (abfd) \
! ? 0x03e0782d /* daddu t7,ra */ \
! : 0x03e07821)) /* addu t7,ra */
! #define STUB_JALR 0x0320f809 /* jalr t9,ra */
! #define STUB_LI16(abfd) \
! ((ABI_64_P (abfd) \
! ? 0x64180000 /* daddiu t8,zero,0 */ \
! : 0x24180000)) /* addiu t8,zero,0 */
! #define MIPS_FUNCTION_STUB_SIZE (16)
/* The name of the dynamic interpreter. This is put in the .interp
section. */
--- 623,648 ----
#define MIPS_ELF_GOT_MAX_SIZE(INFO) (ELF_MIPS_GP_OFFSET (INFO) + 0x7fff)
/* Instructions which appear in a stub. */
! #define STUB_LW(abfd) \
! ((ABI_64_P (abfd) \
! ? 0xdf998010 /* ld t9,0x8010(gp) */ \
! : 0x8f998010)) /* lw t9,0x8010(gp) */
! #define STUB_MOVE(abfd) \
! ((ABI_64_P (abfd) \
! ? 0x03e0782d /* daddu t7,ra */ \
! : 0x03e07821)) /* addu t7,ra */
! #define STUB_LUI(VAL) (0x3c180000 + (VAL)) /* lui t8,VAL */
! #define STUB_JALR 0x0320f809 /* jalr t9,ra */
! #define STUB_LI16U(VAL) (0x34180000 + (VAL)) /* ori t8,zero,VAL unsigned*/
! #define STUB_LI16S(abfd, VAL) \
! ((ABI_64_P (abfd) \
! ? (0x64180000 + (VAL)) /* daddiu t8,zero,VAL sign extended */ \
! : (0x24180000 + (VAL)))) /* addiu t8,zero,VAL sign extended */
!
! #define MIPS_FUNCTION_STUB_SIZE(INFO) \
! (elf_hash_table (INFO)->dynsymcount > 65536 ? 20 : 16)
!
! #define MIPS_FUNCTION_STUB_MAX_SIZE 20
/* The name of the dynamic interpreter. This is put in the .interp
section. */
*************** _bfd_mips_elf_adjust_dynamic_symbol (str
*** 6877,6883 ****
h->plt.offset = s->size;
/* Make room for this stub code. */
! s->size += MIPS_FUNCTION_STUB_SIZE;
/* The last half word of the stub will be filled with the index
of this symbol in .dynsym section. */
--- 6883,6889 ----
h->plt.offset = s->size;
/* Make room for this stub code. */
! s->size += MIPS_FUNCTION_STUB_SIZE (info);
/* The last half word of the stub will be filled with the index
of this symbol in .dynsym section. */
*************** _bfd_mips_elf_always_size_sections (bfd
*** 7142,7148 ****
/* In the worst case, we'll get one stub per dynamic symbol, plus
one to account for the dummy entry at the end required by IRIX
rld. */
! loadable_size += MIPS_FUNCTION_STUB_SIZE * (i + 1);
if (htab->is_vxworks)
/* There's no need to allocate page entries for VxWorks; R_MIPS_GOT16
--- 7148,7154 ----
/* In the worst case, we'll get one stub per dynamic symbol, plus
one to account for the dummy entry at the end required by IRIX
rld. */
! loadable_size += MIPS_FUNCTION_STUB_SIZE (info) * (i + 1);
if (htab->is_vxworks)
/* There's no need to allocate page entries for VxWorks; R_MIPS_GOT16
*************** _bfd_mips_elf_size_dynamic_sections (bfd
*** 7360,7366 ****
{
/* IRIX rld assumes that the function stub isn't at the end
of .text section. So put a dummy. XXX */
! s->size += MIPS_FUNCTION_STUB_SIZE;
}
else if (! info->shared
&& ! mips_elf_hash_table (info)->use_rld_obj_head
--- 7366,7372 ----
{
/* IRIX rld assumes that the function stub isn't at the end
of .text section. So put a dummy. XXX */
! s->size += MIPS_FUNCTION_STUB_SIZE (info);
}
else if (! info->shared
&& ! mips_elf_hash_table (info)->use_rld_obj_head
*************** _bfd_mips_elf_finish_dynamic_symbol (bfd
*** 7997,8009 ****
asection *sgot;
struct mips_got_info *g, *gg;
const char *name;
dynobj = elf_hash_table (info)->dynobj;
if (h->plt.offset != MINUS_ONE)
{
asection *s;
! bfd_byte stub[MIPS_FUNCTION_STUB_SIZE];
/* This symbol has a stub. Set it up. */
--- 8003,8016 ----
asection *sgot;
struct mips_got_info *g, *gg;
const char *name;
+ int idx;
dynobj = elf_hash_table (info)->dynobj;
if (h->plt.offset != MINUS_ONE)
{
asection *s;
! bfd_byte stub[MIPS_FUNCTION_STUB_MAX_SIZE];
/* This symbol has a stub. Set it up. */
*************** _bfd_mips_elf_finish_dynamic_symbol (bfd
*** 8013,8030 ****
MIPS_ELF_STUB_SECTION_NAME (dynobj));
BFD_ASSERT (s != NULL);
! /* FIXME: Can h->dynindx be more than 64K? */
! if (h->dynindx & 0xffff0000)
return FALSE;
/* Fill the stub. */
! bfd_put_32 (output_bfd, STUB_LW (output_bfd), stub);
! bfd_put_32 (output_bfd, STUB_MOVE (output_bfd), stub + 4);
! bfd_put_32 (output_bfd, STUB_JALR, stub + 8);
! bfd_put_32 (output_bfd, STUB_LI16 (output_bfd) + h->dynindx, stub + 12);
BFD_ASSERT (h->plt.offset <= s->size);
! memcpy (s->contents + h->plt.offset, stub, MIPS_FUNCTION_STUB_SIZE);
/* Mark the symbol as undefined. plt.offset != -1 occurs
only for the referenced symbol. */
--- 8020,8060 ----
MIPS_ELF_STUB_SECTION_NAME (dynobj));
BFD_ASSERT (s != NULL);
! BFD_ASSERT ((MIPS_FUNCTION_STUB_SIZE (info) == 20)
! || (h->dynindx <= 65536));
!
! /* Values up to 2^31 - 1 are allowed. Larger values would cause
! sign extension at runtime in the stub, resulting in a
! negative index value. */
! if (h->dynindx & 0x80000000)
return FALSE;
/* Fill the stub. */
! idx = 0;
! bfd_put_32 (output_bfd, STUB_LW (output_bfd), stub + idx);
! idx += 4;
! bfd_put_32 (output_bfd, STUB_MOVE (output_bfd), stub + idx);
! idx += 4;
! if (MIPS_FUNCTION_STUB_SIZE (info) == 20)
! {
! bfd_put_32 (output_bfd, STUB_LUI ((h->dynindx >> 16 ) & 0xffff),
! stub + idx);
! idx += 4;
! }
! bfd_put_32 (output_bfd, STUB_JALR, stub + idx);
! idx += 4;
+ /* If a large stub is not required and sign extension is not a
+ problem, then use legacy code in the stub. */
+ if ((MIPS_FUNCTION_STUB_SIZE (info) == 20) || (h->dynindx & 0xffff8000))
+ bfd_put_32 (output_bfd, STUB_LI16U (h->dynindx & 0xffff), stub + idx);
+ else
+ bfd_put_32 (output_bfd,
+ STUB_LI16S (output_bfd, h->dynindx & 0xffff), stub + idx);
+
BFD_ASSERT (h->plt.offset <= s->size);
! memcpy (s->contents + h->plt.offset,
! stub, MIPS_FUNCTION_STUB_SIZE (info));
/* Mark the symbol as undefined. plt.offset != -1 occurs
only for the referenced symbol. */
*************** _bfd_mips_elf_finish_dynamic_sections (b
*** 8827,8836 ****
{
file_ptr dummy_offset;
! BFD_ASSERT (s->size >= MIPS_FUNCTION_STUB_SIZE);
! dummy_offset = s->size - MIPS_FUNCTION_STUB_SIZE;
memset (s->contents + dummy_offset, 0,
! MIPS_FUNCTION_STUB_SIZE);
}
}
}
--- 8857,8866 ----
{
file_ptr dummy_offset;
! BFD_ASSERT (s->size >= MIPS_FUNCTION_STUB_SIZE (info));
! dummy_offset = s->size - MIPS_FUNCTION_STUB_SIZE (info);
memset (s->contents + dummy_offset, 0,
! MIPS_FUNCTION_STUB_SIZE (info));
}
}
}