sh-nto optimization
Graeme Peterson
gp@qnx.com
Tue Aug 13 13:18:00 GMT 2002
Hi, all.
Here is a preliminary run at implementing the "--small-stubs"
optimization I mentioned in an earlier e-mail.
This is not meant as a patch yet. Please provide feedback.
Thanks.
GP
-------------- next part --------------
diff -rc3p -N src/bfd/elf32-sh.c src.qnx/bfd/elf32-sh.c
*** src/bfd/elf32-sh.c Sun Jul 7 05:10:39 2002
--- src.qnx/bfd/elf32-sh.c Tue Aug 13 12:31:48 2002
*************** static const bfd_byte elf_sh_pic_plt_ent
*** 3321,3332 ****
};
#endif /* old style PLT entries. */
static const bfd_byte *elf_sh_plt0_entry;
static const bfd_byte *elf_sh_plt_entry;
static const bfd_byte *elf_sh_pic_plt_entry;
/* Return size of a PLT entry. */
! #define elf_sh_sizeof_plt(info) PLT_ENTRY_SIZE
/* Return offset of the PLT0 address in an absolute PLT entry. */
#define elf_sh_plt_plt0_offset(info) 16
--- 3321,3373 ----
};
#endif /* old style PLT entries. */
+ /* Small PLT stuff without lazy binding. */
+
+ #define SMALL_PLT_ENTRY_SIZE 12
+
+ static const bfd_byte elf_sh_small_plt_entry_be[SMALL_PLT_ENTRY_SIZE] =
+ {
+ 0xd1, 0x01, /* mov.l 0f,r1 */
+ 0x61, 0x12, /* mov.l @r1,r1 */
+ 0x41, 0x2b, /* jmp @r1 */
+ 0x00, 0x09, /* nop */
+ 0, 0, 0, 0, /* 0: replaced with address of this symbol in .got. */
+ };
+
+ static const bfd_byte elf_sh_small_plt_entry_le[SMALL_PLT_ENTRY_SIZE] =
+ {
+ 0x01, 0xd1, /* mov.l 0f,r1 */
+ 0x12, 0x61, /* mov.l @r1,r1 */
+ 0x2b, 0x41, /* jmp @r1 */
+ 0x09, 0x00, /* nop */
+ 0, 0, 0, 0, /* 0: replaced with address of this symbol in .got. */
+ };
+
+ static const bfd_byte elf_sh_pic_small_plt_entry_be[SMALL_PLT_ENTRY_SIZE] =
+ {
+ 0xd0, 0x01, /* mov.l 1f,r0 */
+ 0x00, 0xce, /* mov.l @(r0,r12),r0 */
+ 0x40, 0x2b, /* jmp @r0 */
+ 0x00, 0x09, /* nop */
+ 0, 0, 0, 0, /* 1: replaced with address of this symbol in .got. */
+ };
+
+ static const bfd_byte elf_sh_pic_small_plt_entry_le[SMALL_PLT_ENTRY_SIZE] =
+ {
+ 0x01, 0xd0, /* mov.l 1f,r0 */
+ 0xce, 0x00, /* mov.l @(r0,r12),r0 */
+ 0x2b, 0x40, /* jmp @r0 */
+ 0x09, 0x00, /* nop */
+ 0, 0, 0, 0, /* 1: replaced with address of this symbol in .got. */
+ };
+
static const bfd_byte *elf_sh_plt0_entry;
static const bfd_byte *elf_sh_plt_entry;
static const bfd_byte *elf_sh_pic_plt_entry;
/* Return size of a PLT entry. */
! #define elf_sh_sizeof_plt(info) \
! (info->without_lazy_binding ? SMALL_PLT_ENTRY_SIZE : PLT_ENTRY_SIZE)
/* Return offset of the PLT0 address in an absolute PLT entry. */
#define elf_sh_plt_plt0_offset(info) 16
*************** static const bfd_byte *elf_sh_pic_plt_en
*** 3338,3347 ****
#define elf_sh_plt0_gotid_offset(info) 24
/* Return offset of the tempoline in PLT entry */
! #define elf_sh_plt_temp_offset(info) 8
/* Return offset of the symbol in PLT entry. */
! #define elf_sh_plt_symbol_offset(info) 20
/* Return offset of the relocation in PLT entry. */
#define elf_sh_plt_reloc_offset(info) 24
--- 3379,3388 ----
#define elf_sh_plt0_gotid_offset(info) 24
/* Return offset of the tempoline in PLT entry */
! #define elf_sh_plt_temp_offset(info) (info->without_lazy_binding ? 0 : 8)
/* Return offset of the symbol in PLT entry. */
! #define elf_sh_plt_symbol_offset(info) (info->without_lazy_binding ? 8 : 20)
/* Return offset of the relocation in PLT entry. */
#define elf_sh_plt_reloc_offset(info) 24
*************** sh_elf_finish_dynamic_symbol (output_bfd
*** 5470,5477 ****
/* Get the index in the procedure linkage table which
corresponds to this symbol. This is the index of this symbol
in all the symbols for which we are making plt entries. The
! first entry in the procedure linkage table is reserved. */
! plt_index = h->plt.offset / elf_sh_sizeof_plt (info) - 1;
/* Get the offset into the .got table of the entry that
corresponds to this function. Each .got entry is 4 bytes.
--- 5511,5523 ----
/* Get the index in the procedure linkage table which
corresponds to this symbol. This is the index of this symbol
in all the symbols for which we are making plt entries. The
! first entry in the procedure linkage table is reserved. Take
! into account that first .plt entry is the large size */
!
! if ( info->without_lazy_binding )
! plt_index = (h->plt.offset - PLT_ENTRY_SIZE)/ elf_sh_sizeof_plt (info);
! else
! plt_index = h->plt.offset / elf_sh_sizeof_plt (info) - 1;
/* Get the offset into the .got table of the entry that
corresponds to this function. Each .got entry is 4 bytes.
*************** sh_elf_finish_dynamic_symbol (output_bfd
*** 5487,5494 ****
{
if (elf_sh_plt_entry == NULL)
{
! elf_sh_plt_entry = (bfd_big_endian (output_bfd) ?
! elf_sh_plt_entry_be : elf_sh_plt_entry_le);
}
memcpy (splt->contents + h->plt.offset, elf_sh_plt_entry,
elf_sh_sizeof_plt (info));
--- 5533,5545 ----
{
if (elf_sh_plt_entry == NULL)
{
! if (info->without_lazy_binding)
! elf_sh_plt_entry = (bfd_big_endian (output_bfd) ?
! elf_sh_small_plt_entry_be :
! elf_sh_small_plt_entry_le);
! else
! elf_sh_plt_entry = (bfd_big_endian (output_bfd) ?
! elf_sh_plt_entry_be : elf_sh_plt_entry_le);
}
memcpy (splt->contents + h->plt.offset, elf_sh_plt_entry,
elf_sh_sizeof_plt (info));
*************** sh_elf_finish_dynamic_symbol (output_bfd
*** 5506,5530 ****
+ elf_sh_plt_plt0_offset (info)));
#else
bfd_put_32 (output_bfd,
! (sgot->output_section->vma
+ sgot->output_offset
+ got_offset),
(splt->contents + h->plt.offset
+ elf_sh_plt_symbol_offset (info)));
! bfd_put_32 (output_bfd,
! (splt->output_section->vma + splt->output_offset),
! (splt->contents + h->plt.offset
! + elf_sh_plt_plt0_offset (info)));
#endif
}
else
{
if (elf_sh_pic_plt_entry == NULL)
{
! elf_sh_pic_plt_entry = (bfd_big_endian (output_bfd) ?
! elf_sh_pic_plt_entry_be :
! elf_sh_pic_plt_entry_le);
}
memcpy (splt->contents + h->plt.offset, elf_sh_pic_plt_entry,
elf_sh_sizeof_plt (info));
--- 5557,5587 ----
+ elf_sh_plt_plt0_offset (info)));
#else
bfd_put_32 (output_bfd,
! (sgot->output_section->vma
+ sgot->output_offset
+ got_offset),
(splt->contents + h->plt.offset
+ elf_sh_plt_symbol_offset (info)));
! if (! info->without_lazy_binding)
! bfd_put_32 (output_bfd,
! (splt->output_section->vma + splt->output_offset),
! (splt->contents + h->plt.offset
! + elf_sh_plt_plt0_offset (info)));
#endif
}
else
{
if (elf_sh_pic_plt_entry == NULL)
{
! if (info->without_lazy_binding)
! elf_sh_pic_plt_entry = (bfd_big_endian (output_bfd) ?
! elf_sh_pic_small_plt_entry_be :
! elf_sh_pic_small_plt_entry_le);
! else
! elf_sh_pic_plt_entry = (bfd_big_endian (output_bfd) ?
! elf_sh_pic_plt_entry_be :
! elf_sh_pic_plt_entry_le);
}
memcpy (splt->contents + h->plt.offset, elf_sh_pic_plt_entry,
elf_sh_sizeof_plt (info));
*************** sh_elf_finish_dynamic_symbol (output_bfd
*** 5549,5566 ****
(splt->contents + h->plt.offset
+ elf_sh_plt_reloc_offset (info)));
#else
! bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rela),
! (splt->contents + h->plt.offset
! + elf_sh_plt_reloc_offset (info)));
#endif
/* Fill in the entry in the global offset table. */
! bfd_put_32 (output_bfd,
! (splt->output_section->vma
! + splt->output_offset
! + h->plt.offset
! + elf_sh_plt_temp_offset (info)),
! sgot->contents + got_offset);
/* Fill in the entry in the .rela.plt section. */
rel.r_offset = (sgot->output_section->vma
--- 5606,5625 ----
(splt->contents + h->plt.offset
+ elf_sh_plt_reloc_offset (info)));
#else
! if (! info->without_lazy_binding)
! bfd_put_32 (output_bfd, plt_index * sizeof (Elf32_External_Rela),
! (splt->contents + h->plt.offset
! + elf_sh_plt_reloc_offset (info)));
#endif
/* Fill in the entry in the global offset table. */
! if (! info->without_lazy_binding)
! bfd_put_32 (output_bfd,
! (splt->output_section->vma
! + splt->output_offset
! + h->plt.offset
! + elf_sh_plt_temp_offset (info)),
! sgot->contents + got_offset);
/* Fill in the entry in the .rela.plt section. */
rel.r_offset = (sgot->output_section->vma
*************** sh_elf_finish_dynamic_sections (output_b
*** 5754,5762 ****
{
if (elf_sh_pic_plt_entry == NULL)
{
! elf_sh_pic_plt_entry = (bfd_big_endian (output_bfd) ?
! elf_sh_pic_plt_entry_be :
! elf_sh_pic_plt_entry_le);
}
memcpy (splt->contents, elf_sh_pic_plt_entry,
elf_sh_sizeof_plt (info));
--- 5813,5826 ----
{
if (elf_sh_pic_plt_entry == NULL)
{
! if (info->without_lazy_binding)
! elf_sh_pic_plt_entry = (bfd_big_endian (output_bfd) ?
! elf_sh_pic_small_plt_entry_be :
! elf_sh_pic_small_plt_entry_le);
! else
! elf_sh_pic_plt_entry = (bfd_big_endian (output_bfd) ?
! elf_sh_pic_plt_entry_be :
! elf_sh_pic_plt_entry_le);
}
memcpy (splt->contents, elf_sh_pic_plt_entry,
elf_sh_sizeof_plt (info));
*************** sh_elf_reloc_type_class (rela)
*** 5877,5880 ****
--- 5941,5948 ----
#define elf_backend_want_plt_sym 0
#define elf_backend_got_header_size 12
#define elf_backend_plt_header_size PLT_ENTRY_SIZE
+
+ #ifndef ELF32_SH_C_INCLUDED
#include "elf32-target.h"
+ #endif
+
diff -rc3p -N src/include/bfdlink.h src.qnx/include/bfdlink.h
*** src/include/bfdlink.h Wed Aug 7 23:50:17 2002
--- src.qnx/include/bfdlink.h Tue Aug 13 12:09:51 2002
*************** struct bfd_link_info
*** 358,363 ****
--- 358,367 ----
/* Criteria for skipping symbols when detemining
whether to include an object from an archive. */
enum bfd_link_common_skip_ar_aymbols common_skip_ar_aymbols;
+
+ /* True if small plt stubs are to be used. Only supported currently
+ for sh4. */
+ boolean without_lazy_binding;
};
/* This structures holds a set of callback functions. These are
diff -rc3p -N src/ld/lexsup.c src.qnx/ld/lexsup.c
*** src/ld/lexsup.c Wed Aug 7 23:50:17 2002
--- src.qnx/ld/lexsup.c Tue Aug 13 14:33:25 2002
*************** int parsing_defsym = 0;
*** 132,137 ****
--- 132,138 ----
#define OPTION_SPARE_DYNAMIC_TAGS (OPTION_DISCARD_NONE + 1)
#define OPTION_NO_DEFINE_COMMON (OPTION_SPARE_DYNAMIC_TAGS + 1)
#define OPTION_NOSTDLIB (OPTION_NO_DEFINE_COMMON + 1)
+ #define OPTION_WITHOUT_LAZY_BINDING (OPTION_NOSTDLIB + 1)
/* The long options. This structure is used for both the option
parsing and the help text. */
*************** static const struct ld_option ld_options
*** 352,357 ****
--- 353,360 ----
'\0', NULL, N_("Create a shared library"), ONE_DASH },
{ {"Bshareable", no_argument, NULL, OPTION_SHARED }, /* FreeBSD. */
'\0', NULL, NULL, ONE_DASH },
+ { {"small-stubs", no_argument, NULL, OPTION_WITHOUT_LAZY_BINDING},
+ '\0', NULL, N_("Generate small PLT stubs (no lazy linking) if supported"), TWO_DASHES },
{ {"sort-common", no_argument, NULL, OPTION_SORT_COMMON},
'\0', NULL, N_("Sort common symbols by size"), TWO_DASHES },
{ {"sort_common", no_argument, NULL, OPTION_SORT_COMMON},
*************** parse_args (argc, argv)
*** 1135,1140 ****
--- 1138,1147 ----
case OPTION_FINI:
link_info.fini_function = optarg;
+ break;
+
+ case OPTION_WITHOUT_LAZY_BINDING:
+ link_info.without_lazy_binding = true;
break;
}
}
diff -rc3p -N src/ld/ldmain.c src.qnx/ld/ldmain.c
*** src/ld/ldmain.c Wed Aug 7 23:50:17 2002
--- src.qnx/ld/ldmain.c Tue Aug 13 12:06:15 2002
*************** main (argc, argv)
*** 266,271 ****
--- 266,272 ----
link_info.combreloc = true;
link_info.spare_dynamic_tags = 5;
link_info.common_skip_ar_aymbols = bfd_link_common_skip_none;
+ link_info.without_lazy_binding = false;
ldfile_add_arch ("");
More information about the Binutils
mailing list