This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: [PATCH] Utilize Blackfin L1 SRAM
Jonathan S. Shapiro wrote:
On Mon, 2008-07-14 at 10:55 +0800, Jie Zhang wrote:
Oh, I understand what Jonathan said now. But using objcopy is not
convenient. It needs to figure out what sections needs to be renamed. It
needs to change Makefile rules. People use "coarse grained method" to
put applications into L1 SRAM because it's convenient, i.e. adding two
or three options in LDFLAGS in Makeifle is enough.
Jie:
In the end, this isn't my decision, so I'm not going to post on it after
this note, but I think you are making a mistake with this patch.
Basically, you are introducing a hack to do exactly what the current
emulation templates are *designed* to do. Adding a second way to do a
rare case is almost always a bad idea.
I don't think I'm making a mistake with this patch. Maybe I should have
broken the patch into smaller ones. So I split it and attached the
resulted three patches in this email.
binutils-ld-bfin-special-sections.diff is for fine grained control to
put code and data into L1 SRAM. GCC puts code and data into special
sections if they have specific attributes: l1_text, l1_data, l1_data_A,
and l1_data_B. This is a Blackfin specific patch. And from the
discussion of this thread, I think no one think this is a bad one. So
I'm going to commit it soon.
The other two patches will be explained below.
We have a similar situation in Coyotos. We have a small linkage model
and a large linkage model, because we use the small address space
multiplexing tricks from L4 and EROS. The main difference between the
two models is where the text start address is (stack address also
changes, but we do not handle that from LD). We solved the problem by
adding a pair of coyotos-specific linker scripts. For example, our ARM
target has:
ld/emulparams/armelf_coyotos.sh # basically armelf.sh
ld/emulparams/armelf_coyotos_small.sh
[snip]
These changes have exactly the same effect as the change that you are
proposing, which is to handle it all with a single option. The
difference is that our approach works within the designed mechanisms of
ld, while yours does not.
I know how to implement this, and the implementation is simple and easy.
But maintaining the customized linker scripts will be a burden. Each
time the generic ELF linker script changes, like adding new section
names, you have to change the customized scripts accordingly.
From the other side, _bfd_elf_map_sections_to_segments assumes that
read only data can be put into the same segment with the code and they
can be loaded together. But this assumption is not true for Blackfin.
Read only data cannot be put into the same segment with the code if you
want to put the code into L1 instruction SRAM of Blackfin. Adding
--sep-code will tell ld not to put them together.
This is what binutils-ld-option-sep-code.diff does. It just solves the
problem at the place where the problem occurs. Putting code and read
only data together uses the nature that they can/should be read only on
most targets. But Blackfin goes further that code can be even not
readable as long as it can be fetched by execution unit of processor. I
think it's natural to add this option for processors like Blackfin.
I think this is the controversial one.
The last patch, binutils-ld-bfin-option-code-ddata-in-l1.diff, depends
on --sep-code option. This patch adds flags to execuables and shared
libraries, such that loader will know people want them to be put into L1
SRAM. Since code will go into L1 instruction SRAM, which is not
readable, we have to use --sep-code to put code and data into two
seperate segments.
Given this, my strong recommendation to Daniel is to reject this patch
because it will create an ongoing maintenance burden and it achieves
absolutely nothing beyond what the existing mechanisms already provide.
The maintenance burden is mainly added by
binutils-ld-option-sep-code.diff, which is target independent. I will
maintain blackfin target specific ones. So I think the added maintenance
burden is not much.
I wait for more comments.
Jie
bfd/
* elf32-bfin.c (elf32_bfin_special_sections[]): New.
(elf_backend_special_sections): Define.
ld/
* emulparams/elf32bfinfd.sh (OTHER_SECTIONS): Define.
Index: bfd/elf32-bfin.c
===================================================================
--- bfd/elf32-bfin.c.orig 2008-07-15 11:42:36.000000000 +0800
+++ bfd/elf32-bfin.c 2008-07-15 12:22:17.000000000 +0800
@@ -5572,6 +5572,14 @@
free (internal_relocs);
return FALSE;
}
+
+struct bfd_elf_special_section const elf32_bfin_special_sections[] =
+{
+ { ".l1.text", 8, -2, SHT_PROGBITS, SHF_ALLOC + SHF_EXECINSTR },
+ { ".l1.data", 8, -2, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+ { NULL, 0, 0, 0, 0 }
+};
+
#define TARGET_LITTLE_SYM bfd_elf32_bfin_vec
#define TARGET_LITTLE_NAME "elf32-bfin"
@@ -5620,6 +5628,7 @@
elf32_bfin_print_private_bfd_data
#define elf_backend_reloc_type_class elf32_bfin_reloc_type_class
#define elf_backend_can_gc_sections 1
+#define elf_backend_special_sections elf32_bfin_special_sections
#define elf_backend_can_refcount 1
#define elf_backend_want_got_plt 0
#define elf_backend_plt_readonly 1
Index: ld/emulparams/elf32bfinfd.sh
===================================================================
--- ld/emulparams/elf32bfinfd.sh.orig 2008-07-15 11:42:36.000000000 +0800
+++ ld/emulparams/elf32bfinfd.sh 2008-07-15 12:22:17.000000000 +0800
@@ -14,3 +14,23 @@
${RELOCATING+__ROFIXUP_END__ = .;}
}
"
+# 0xff700000, 0xff800000, 0xff900000 and 0xffa00000 are also used in
+# Dynamic linker and linux kernel. They need to be keep synchronized.
+OTHER_SECTIONS="
+ .l1.data 0xff700000 :
+ {
+ *(.l1.data)
+ }
+ .l1.data.A 0xff800000 :
+ {
+ *(.l1.data.A)
+ }
+ .l1.data.B 0xff900000 :
+ {
+ *(.l1.data.B)
+ }
+ .l1.text 0xffa00000 :
+ {
+ *(.l1.text)
+ }
+"
bfd/
* elf.c (_bfd_elf_map_sections_to_segments): Don't put
executable sections into the same segment with other
read only sections if --sep-code.
include/
* bfdlink.h (struct bfd_link_info): Add sep_code member
variable.
ld/
* ld.texinfo: Document --sep-code.
* ldmain.c (main): Initialize link_info.sep_code.
* lexsup.c (enum option_values): Add OPTION_SEP_CODE.
(ld_options[]): Add --sep-code.
(parse_args): Deal with --sep-code.
Index: bfd/elf.c
===================================================================
--- bfd/elf.c.orig 2008-07-15 11:42:36.000000000 +0800
+++ bfd/elf.c 2008-07-15 12:23:03.000000000 +0800
@@ -3605,6 +3605,7 @@
asection **hdrpp;
bfd_boolean phdr_in_segment = TRUE;
bfd_boolean writable;
+ bfd_boolean executable;
int tls_count = 0;
asection *first_tls = NULL;
asection *dynsec, *eh_frame_hdr;
@@ -3676,6 +3677,7 @@
phdr_index = 0;
maxpagesize = bed->maxpagesize;
writable = FALSE;
+ executable = FALSE;
dynsec = bfd_get_section_by_name (abfd, ".dynamic");
if (dynsec != NULL
&& (dynsec->flags & SEC_LOAD) == 0)
@@ -3757,6 +3759,14 @@
ends precisely on a page boundary. */
new_segment = TRUE;
}
+ else if (info->sep_code
+ && ((! executable && (hdr->flags & SEC_CODE) != 0)
+ || (executable && (hdr->flags & SEC_CODE) == 0)))
+ {
+ /* We don't want to put a executable section in a non-executable
+ segment. */
+ new_segment = TRUE;
+ }
else
{
/* Otherwise, we can use the same segment. */
@@ -3771,6 +3781,8 @@
{
if ((hdr->flags & SEC_READONLY) == 0)
writable = TRUE;
+ if ((hdr->flags & SEC_CODE) != 0)
+ executable = TRUE;
last_hdr = hdr;
/* .tbss sections effectively have zero size. */
if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD))
@@ -3796,6 +3808,11 @@
else
writable = FALSE;
+ if ((hdr->flags & SEC_CODE) != 0)
+ executable = TRUE;
+ else
+ executable = FALSE;
+
last_hdr = hdr;
/* .tbss sections effectively have zero size. */
if ((hdr->flags & (SEC_THREAD_LOCAL | SEC_LOAD)) != SEC_THREAD_LOCAL)
Index: include/bfdlink.h
===================================================================
--- include/bfdlink.h.orig 2008-07-15 11:42:36.000000000 +0800
+++ include/bfdlink.h 2008-07-15 12:23:03.000000000 +0800
@@ -346,6 +346,9 @@
/* Non-NULL if .note.gnu.build-id section should be created. */
char *emit_note_gnu_build_id;
+ /* TRUE if putting code into separate segment. */
+ unsigned int sep_code: 1;
+
/* What to do with unresolved symbols in an object file.
When producing executables the default is GENERATE_ERROR.
When producing shared libraries the default is IGNORE. The
Index: ld/ld.texinfo
===================================================================
--- ld/ld.texinfo.orig 2008-07-15 11:42:36.000000000 +0800
+++ ld/ld.texinfo 2008-07-15 12:23:03.000000000 +0800
@@ -825,6 +825,11 @@
followed by a directory name, rather than a file name, it is treated as
the @option{-rpath} option.
+@kindex --sep-code
+@cindex input files, displaying
+@itemx --sep-code
+Put code in a seperate segment, not along with other read only data.
+
@kindex -s
@kindex --strip-all
@cindex strip all symbols
Index: ld/ldmain.c
===================================================================
--- ld/ldmain.c.orig 2008-07-15 11:42:36.000000000 +0800
+++ ld/ldmain.c 2008-07-15 12:23:03.000000000 +0800
@@ -277,6 +277,7 @@
link_info.pei386_auto_import = -1;
link_info.spare_dynamic_tags = 5;
link_info.path_separator = ':';
+ link_info.sep_code = FALSE;
ldfile_add_arch ("");
emulation = get_emulation (argc, argv);
Index: ld/lexsup.c
===================================================================
--- ld/lexsup.c.orig 2008-07-15 11:42:36.000000000 +0800
+++ ld/lexsup.c 2008-07-15 12:23:03.000000000 +0800
@@ -92,6 +92,7 @@
OPTION_RETAIN_SYMBOLS_FILE,
OPTION_RPATH,
OPTION_RPATH_LINK,
+ OPTION_SEP_CODE,
OPTION_SHARED,
OPTION_SONAME,
OPTION_SORT_COMMON,
@@ -477,6 +478,8 @@
'\0', NULL, N_("Create a position independent executable"), ONE_DASH },
{ {"pic-executable", no_argument, NULL, OPTION_PIE},
'\0', NULL, NULL, TWO_DASHES },
+ { {"sep-code", no_argument, NULL, OPTION_SEP_CODE},
+ '\0', NULL, N_("Put code into separate segment"), TWO_DASHES },
{ {"sort-common", optional_argument, NULL, OPTION_SORT_COMMON},
'\0', N_("[=ascending|descending]"),
N_("Sort common symbols by alignment [in specified order]"),
@@ -1143,6 +1146,9 @@
else
einfo (_("%P%F: -pie not supported\n"));
break;
+ case OPTION_SEP_CODE:
+ link_info.sep_code = TRUE;
+ break;
case 'h': /* Used on Solaris. */
case OPTION_SONAME:
command_line.soname = optarg;
bfd/
* elf32-bfin.c (elf32_bfin_code_in_l1): New variable.
(elf32_bfin_data_in_l1): New variable.
(elf32_bfin_final_write_processing): New.
(elf_backend_final_write_processing): Define.
binutils/
* readelf.c (get_machine_flags): Deal with Blackfin specific
flags.
include/
* elf/bfin.h (EF_BFIN_CODE_IN_L1): Define.
(EF_BFIN_DATA_IN_L1): Define.
ld/
* Makefile.am (eelf32bfin.c): Depend on bfin.em.
(eelf32bfinfd.c): Likewise.
* Makefile.in: Regenerate.
* gen-doc.texi: Set Blackfin.
* ld.texinfo: Document Blackfin specific options.
* emulparams/bfin.sh (EXTRA_EM_FILE): Define.
* emultempl/bfin.em: New file.
Index: bfd/elf32-bfin.c
===================================================================
--- bfd/elf32-bfin.c.orig 2008-07-15 12:25:58.000000000 +0800
+++ bfd/elf32-bfin.c 2008-07-15 12:28:17.000000000 +0800
@@ -1119,6 +1119,22 @@
return (reloc_howto_type *) NULL;
}
+/* Set by ld emulation if --code-in-l1. */
+bfd_boolean elf32_bfin_code_in_l1 = 0;
+
+/* Set by ld emulation if --data-in-l1. */
+bfd_boolean elf32_bfin_data_in_l1 = 0;
+
+static void
+elf32_bfin_final_write_processing (bfd *abfd,
+ bfd_boolean linker ATTRIBUTE_UNUSED)
+{
+ if (elf32_bfin_code_in_l1)
+ elf_elfheader (abfd)->e_flags |= EF_BFIN_CODE_IN_L1;
+ if (elf32_bfin_data_in_l1)
+ elf_elfheader (abfd)->e_flags |= EF_BFIN_DATA_IN_L1;
+}
+
/* Return TRUE if the name is a local label.
bfin local labels begin with L$. */
static bfd_boolean
@@ -5626,6 +5642,8 @@
elf32_bfin_set_private_flags
#define bfd_elf32_bfd_print_private_bfd_data \
elf32_bfin_print_private_bfd_data
+#define elf_backend_final_write_processing \
+ elf32_bfin_final_write_processing
#define elf_backend_reloc_type_class elf32_bfin_reloc_type_class
#define elf_backend_can_gc_sections 1
#define elf_backend_special_sections elf32_bfin_special_sections
Index: binutils/readelf.c
===================================================================
--- binutils/readelf.c.orig 2008-07-15 12:25:54.000000000 +0800
+++ binutils/readelf.c 2008-07-15 12:28:17.000000000 +0800
@@ -2140,6 +2140,21 @@
decode_ARM_machine_flags (e_flags, buf);
break;
+ case EM_BLACKFIN:
+ if (e_flags & EF_BFIN_PIC)
+ strcat (buf, ", PIC");
+
+ if (e_flags & EF_BFIN_FDPIC)
+ strcat (buf, ", FDPIC");
+
+ if (e_flags & EF_BFIN_CODE_IN_L1)
+ strcat (buf, ", code in L1");
+
+ if (e_flags & EF_BFIN_DATA_IN_L1)
+ strcat (buf, ", data in L1");
+
+ break;
+
case EM_CYGNUS_FRV:
switch (e_flags & EF_FRV_CPU_MASK)
{
Index: include/elf/bfin.h
===================================================================
--- include/elf/bfin.h.orig 2008-07-15 12:25:54.000000000 +0800
+++ include/elf/bfin.h 2008-07-15 12:28:17.000000000 +0800
@@ -88,5 +88,8 @@
#define EF_BFIN_PIC 0x00000001 /* -fpic */
#define EF_BFIN_FDPIC 0x00000002 /* -mfdpic */
+#define EF_BFIN_CODE_IN_L1 0x00000010 /* --code-in-l1 */
+#define EF_BFIN_DATA_IN_L1 0x00000020 /* --data-in-l1 */
+
#define EF_BFIN_PIC_FLAGS (EF_BFIN_PIC | EF_BFIN_FDPIC)
#endif /* _ELF_BFIN_H */
Index: ld/Makefile.am
===================================================================
--- ld/Makefile.am.orig 2008-07-15 12:25:54.000000000 +0800
+++ ld/Makefile.am 2008-07-15 12:28:17.000000000 +0800
@@ -653,11 +653,11 @@
$(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/delta68.sc ${GEN_DEPENDS}
${GENSCRIPTS} delta68 "$(tdir_delta68)"
eelf32bfin.c: $(srcdir)/emulparams/bfin.sh \
- $(ELF_DEPS) \
+ $(ELF_DEPS) $(srcdir)/emultempl/bfin.em \
$(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32bfin "$(tdir_elf32bfin)" bfin
eelf32bfinfd.c: $(srcdir)/emulparams/elf32bfinfd.sh $(srcdir)/emulparams/bfin.sh \
- $(ELF_DEPS) \
+ $(ELF_DEPS) $(srcdir)/emultempl/bfin.em \
$(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32bfinfd "$(tdir_elf32bfinfd)" elf32bfinfd
eelf32_dlx.c: $(srcdir)/emulparams/elf32_dlx.sh \
Index: ld/gen-doc.texi
===================================================================
--- ld/gen-doc.texi.orig 2008-07-15 12:25:54.000000000 +0800
+++ ld/gen-doc.texi 2008-07-15 12:28:17.000000000 +0800
@@ -4,6 +4,7 @@
@c 2. Specific target machines
@set ARM
+@set Blackfin
@set H8300
@set HPPA
@set I960
Index: ld/ld.texinfo
===================================================================
--- ld/ld.texinfo.orig 2008-07-15 12:27:49.000000000 +0800
+++ ld/ld.texinfo 2008-07-15 12:28:17.000000000 +0800
@@ -21,6 +21,7 @@
@set UsesEnvVars
@set GENERIC
@set ARM
+@set Blackfin
@set H8300
@set HPPA
@set I960
@@ -140,6 +141,9 @@
@ifset ARM
* ARM:: ld and the ARM family
@end ifset
+@ifset Blackfin
+* Blackfin:: ld and the Blackfin family
+@end ifset
@ifset HPPA
* HPPA ELF32:: ld and HPPA 32-bit ELF
@end ifset
@@ -5367,6 +5371,9 @@
@ifset ARM
* ARM:: @command{ld} and the ARM family
@end ifset
+@ifset Blackfin
+* Blackfin:: @command{ld} and the Blackfin family
+@end ifset
@ifset HPPA
* HPPA ELF32:: @command{ld} and HPPA 32-bit ELF
@end ifset
@@ -5757,6 +5764,30 @@
@end ifclear
@end ifset
+@ifset Blackfin
+@ifclear GENERIC
+@raisesections
+@end ifclear
+
+@node Blackfin
+@section @command{ld} and the Blackfin family
+
+@cindex Put code in L1 instruction SRAM
+@kindex --code-in-l1
+The @samp{--code-in-l1} option adds a specific flag in the ELF header.
+This flag tells loader to put the code segments into Blackfin
+L1 instruction SRAM.
+
+@cindex Put code in L1 data SRAM
+@kindex --data-in-l1
+The @samp{--data-in-l1} option adds a specific flag in the ELF header.
+This flag tells loader to put the data segments into Blackfin L1 data SRAM.
+
+@ifclear GENERIC
+@lowersections
+@end ifclear
+@end ifset
+
@ifset HPPA
@ifclear GENERIC
@raisesections
Index: ld/emulparams/bfin.sh
===================================================================
--- ld/emulparams/bfin.sh.orig 2008-07-15 12:25:54.000000000 +0800
+++ ld/emulparams/bfin.sh 2008-07-15 12:28:17.000000000 +0800
@@ -10,3 +10,4 @@
GENERATE_SHLIB_SCRIPT=yes
EMBEDDED=yes
USER_LABEL_PREFIX=_
+EXTRA_EM_FILE=bfin
Index: ld/emulparams/elf32bfinfd.sh
===================================================================
--- ld/emulparams/elf32bfinfd.sh.orig 2008-07-15 12:25:58.000000000 +0800
+++ ld/emulparams/elf32bfinfd.sh 2008-07-15 12:28:17.000000000 +0800
@@ -34,3 +34,4 @@
*(.l1.text)
}
"
+EXTRA_EM_FILE=bfin
Index: ld/emultempl/bfin.em
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ ld/emultempl/bfin.em 2008-07-15 12:28:17.000000000 +0800
@@ -0,0 +1,64 @@
+# This shell script emits a C file. -*- C -*-
+# Copyright 2006 Free Software Foundation, Inc.
+#
+# This file is part of GLD, the Gnu Linker.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# 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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+#
+
+# This file is sourced from elf32.em, and defines extra bfin-elf
+# specific routines.
+#
+cat >>e${EMULATION_NAME}.c <<EOF
+
+#include "elf-bfd.h"
+
+/* Whether to put code in Blackfin L1 SRAM. */
+extern bfd_boolean elf32_bfin_code_in_l1;
+
+/* Whether to put (writable) data in Blackfin L1 SRAM. */
+extern bfd_boolean elf32_bfin_data_in_l1;
+
+EOF
+
+
+# Define some shell vars to insert bits of code into the standard elf
+# parse_args and list_options functions.
+#
+PARSE_AND_LIST_PROLOGUE='
+#define OPTION_CODE_IN_L1 300
+#define OPTION_DATA_IN_L1 301
+'
+
+PARSE_AND_LIST_LONGOPTS='
+ { "code-in-l1", no_argument, NULL, OPTION_CODE_IN_L1 },
+ { "data-in-l1", no_argument, NULL, OPTION_DATA_IN_L1 },
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _("\
+ --code-in-l1 Put code in l1.\n\
+ --data-in-l1 Put data in l1.\n"
+ ));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+ case OPTION_CODE_IN_L1:
+ elf32_bfin_code_in_l1 = TRUE;
+ break;
+ case OPTION_DATA_IN_L1:
+ elf32_bfin_data_in_l1 = TRUE;
+ break;
+'
Index: ld/Makefile.in
===================================================================
--- ld/Makefile.in.orig 2008-07-15 14:30:10.000000000 +0800
+++ ld/Makefile.in 2008-07-15 14:30:16.000000000 +0800
@@ -1482,11 +1482,11 @@
$(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/delta68.sc ${GEN_DEPENDS}
${GENSCRIPTS} delta68 "$(tdir_delta68)"
eelf32bfin.c: $(srcdir)/emulparams/bfin.sh \
- $(ELF_DEPS) \
+ $(ELF_DEPS) $(srcdir)/emultempl/bfin.em \
$(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32bfin "$(tdir_elf32bfin)" bfin
eelf32bfinfd.c: $(srcdir)/emulparams/elf32bfinfd.sh $(srcdir)/emulparams/bfin.sh \
- $(ELF_DEPS) \
+ $(ELF_DEPS) $(srcdir)/emultempl/bfin.em \
$(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
${GENSCRIPTS} elf32bfinfd "$(tdir_elf32bfinfd)" elf32bfinfd
eelf32_dlx.c: $(srcdir)/emulparams/elf32_dlx.sh \