RISC-V: Add PT_RISCV_ATTRIBUTES and add it to PHDR.
authorKito Cheng <kito.cheng@sifive.com>
Tue, 29 Jun 2021 06:36:35 +0000 (14:36 +0800)
committerNelson Chu <nelson.chu@sifive.com>
Tue, 6 Jul 2021 03:34:36 +0000 (11:34 +0800)
We added PT_RISCV_ATTRIBUTES to program header to make
.riscv.attribute easier to find in dynamic loader or kernel.

Ref:
https://github.com/riscv/riscv-elf-psabi-doc/pull/71

ChangeLog:

bfd/

* elfnn-riscv.c(RISCV_ATTRIBUTES_SECTION_NAME): New.
(riscv_elf_additional_program_headers): Ditto.
(riscv_elf_modify_segment_map): Ditto.
(elf_backend_additional_program_headers): Ditto.
(elf_backend_modify_segment_map): Ditto.
(elf_backend_obj_attrs_section): Use RISCV_ATTRIBUTES_SECTION_NAME
rather than string literal.

binutils/

* readelf.c(get_riscv_segment_type): New.
(get_segment_type): Handle EM_RISCV.

include/

* elf/riscv.h (PT_RISCV_ATTRIBUTES): New.
* testsuite/ld-elf/orphan-region.ld: Discard .riscv.attributes
section for simplify testcase.
* testsuite/ld-riscv-elf/attr-phdr.d: New.
* testsuite/ld-riscv-elf/attr-phdr.s: Ditto.
* testsuite/ld-riscv-elf/ld-riscv-elf.exp: Add attr-phdr to
testcase.

bfd/elfnn-riscv.c
binutils/readelf.c
include/elf/riscv.h
ld/testsuite/ld-elf/orphan-region.ld
ld/testsuite/ld-riscv-elf/attr-phdr.d [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/attr-phdr.s [new file with mode: 0644]
ld/testsuite/ld-riscv-elf/ld-riscv-elf.exp

index f206708a9f356eb119589228c8c68a048ed2c89c..4db3ca4e4b9992a80321582e9065edc9087e9ab5 100644 (file)
@@ -62,6 +62,8 @@
 #define ELF_MAXPAGESIZE                        0x1000
 #define ELF_COMMONPAGESIZE             0x1000
 
+#define RISCV_ATTRIBUTES_SECTION_NAME ".riscv.attributes"
+
 /* RISC-V ELF linker hash entry.  */
 
 struct riscv_elf_link_hash_entry
@@ -5158,6 +5160,64 @@ riscv_elf_is_target_special_symbol (bfd *abfd, asymbol *sym)
          || _bfd_elf_is_local_label_name (abfd, sym->name));
 }
 
+static int
+riscv_elf_additional_program_headers (bfd *abfd,
+                                     struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+  asection *s;
+  int ret = 0;
+
+  /* See if we need a PT_RISCV_ATTRIBUTES segment.  */
+  if (bfd_get_section_by_name (abfd, RISCV_ATTRIBUTES_SECTION_NAME))
+    ++ret;
+
+  return ret;
+}
+
+static bool
+riscv_elf_modify_segment_map (bfd *abfd,
+                             struct bfd_link_info *info)
+{
+  asection *s;
+  struct elf_segment_map *m, **pm;
+  size_t amt;
+
+  /* If there is a .riscv.attributes section, we need a PT_RISCV_ATTRIBUTES
+     segment.  */
+  s = bfd_get_section_by_name (abfd, RISCV_ATTRIBUTES_SECTION_NAME);
+  if (s != NULL)
+    {
+      for (m = elf_seg_map (abfd); m != NULL; m = m->next)
+       if (m->p_type == PT_RISCV_ATTRIBUTES)
+         break;
+      /* If there is already a PT_RISCV_ATTRIBUTES header, avoid adding
+        another.  */
+      if (m == NULL)
+       {
+         amt = sizeof (*m);
+         m = bfd_zalloc (abfd, amt);
+         if (m == NULL)
+           return false;
+
+         m->p_type = PT_RISCV_ATTRIBUTES;
+         m->count = 1;
+         m->sections[0] = s;
+
+         /* We want to put it after the PHDR and INTERP segments.  */
+         pm = &elf_seg_map (abfd);
+         while (*pm != NULL
+                && ((*pm)->p_type == PT_PHDR
+                    || (*pm)->p_type == PT_INTERP))
+           pm = &(*pm)->next;
+
+         m->next = *pm;
+         *pm = m;
+       }
+    }
+
+  return true;
+}
+
 #define TARGET_LITTLE_SYM                      riscv_elfNN_vec
 #define TARGET_LITTLE_NAME                     "elfNN-littleriscv"
 #define TARGET_BIG_SYM                         riscv_elfNN_be_vec
@@ -5190,6 +5250,9 @@ riscv_elf_is_target_special_symbol (bfd *abfd, asymbol *sym)
 #define elf_info_to_howto                      riscv_info_to_howto_rela
 #define bfd_elfNN_bfd_relax_section            _bfd_riscv_relax_section
 #define bfd_elfNN_mkobject                     elfNN_riscv_mkobject
+#define elf_backend_additional_program_headers \
+  riscv_elf_additional_program_headers
+#define elf_backend_modify_segment_map         riscv_elf_modify_segment_map
 
 #define elf_backend_init_index_section         _bfd_elf_init_1_index_section
 
@@ -5211,6 +5274,6 @@ riscv_elf_is_target_special_symbol (bfd *abfd, asymbol *sym)
 #undef  elf_backend_obj_attrs_section_type
 #define elf_backend_obj_attrs_section_type     SHT_RISCV_ATTRIBUTES
 #undef  elf_backend_obj_attrs_section
-#define elf_backend_obj_attrs_section          ".riscv.attributes"
+#define elf_backend_obj_attrs_section          RISCV_ATTRIBUTES_SECTION_NAME
 
 #include "elfNN-target.h"
index a6073f7ec8092e9a93542d20a953b9c0e87c301f..22153394800570fb009b12fccb716fdc37d7b26e 100644 (file)
@@ -4094,6 +4094,16 @@ get_tic6x_segment_type (unsigned long type)
     }
 }
 
+static const char *
+get_riscv_segment_type (unsigned long type)
+{
+  switch (type)
+    {
+    case PT_RISCV_ATTRIBUTES: return "RISCV_ATTRIBUTES";
+    default:                  return NULL;
+    }
+}
+
 static const char *
 get_hpux_segment_type (unsigned long type, unsigned e_machine)
 {
@@ -4203,6 +4213,9 @@ get_segment_type (Filedata * filedata, unsigned long p_type)
            case EM_S390_OLD:
              result = get_s390_segment_type (p_type);
              break;
+           case EM_RISCV:
+             result = get_riscv_segment_type (p_type);
+             break;
            default:
              result = NULL;
              break;
index fb376a096abd79763fb4e6196db2e0405b4fe454..80822835cd9ce888c9aa06b18e8643c901d6b1a3 100644 (file)
@@ -120,6 +120,11 @@ END_RELOC_NUMBERS (R_RISCV_max)
 /* Additional section types.  */
 #define SHT_RISCV_ATTRIBUTES 0x70000003 /* Section holds attributes.  */
 
+/* Processor specific program header types.  */
+
+/* Location of RISC-V ELF attribute section. */
+#define PT_RISCV_ATTRIBUTES 0x70000003
+
 /* Object attributes.  */
 enum
 {
index 2abf8bcb02a8eed7897852705d4b6463a55cd1ba..71834df647a5cf25c76c3c7814d74f4a2d0262bd 100644 (file)
@@ -7,5 +7,5 @@ SECTIONS
 {
        .text : ALIGN (4) { *(.text) } > region
        .rodata : ALIGN (4) { *(.rodata) } > region
-       /DISCARD/ : { *(.reginfo) *(.MIPS.abiflags) *(.trampolines) }
+       /DISCARD/ : { *(.reginfo) *(.MIPS.abiflags) *(.trampolines) *(.riscv.attributes) }
 }
diff --git a/ld/testsuite/ld-riscv-elf/attr-phdr.d b/ld/testsuite/ld-riscv-elf/attr-phdr.d
new file mode 100644 (file)
index 0000000..43f2ea5
--- /dev/null
@@ -0,0 +1,19 @@
+#name: PT_RISCV_ATTRIBUTES check
+#source: attr-phdr.s
+#as: -march=rv32ic
+#ld: -m[riscv_choose_ilp32_emul]
+#readelf: -l
+
+Elf file type is EXEC \(Executable file\)
+Entry point .*
+There are .* program headers, starting at offset .*
+
+Program Headers:
+  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
+  RISCV_ATTRIBUT .*
+  LOAD           .*
+
+ Section to Segment mapping:
+  Segment Sections...
+   00     .riscv.attributes 
+   01     .text 
diff --git a/ld/testsuite/ld-riscv-elf/attr-phdr.s b/ld/testsuite/ld-riscv-elf/attr-phdr.s
new file mode 100644 (file)
index 0000000..f075248
--- /dev/null
@@ -0,0 +1,9 @@
+       .attribute arch, "rv32i2p0_m2p0"
+       .option nopic
+       .text
+       .align  1
+       .globl  _start
+       .type   _start, @function
+_start:
+       ret
+       .size   _start, .-_start
index 1f1245af7074299c310ba90793735cc6a7d60a0b..1f6eceb3ae84f1b73f82e352272b7aae68eb39e6 100644 (file)
@@ -112,6 +112,7 @@ if [istarget "riscv*-*-*"] {
     run_dump_test "attr-merge-priv-spec-failed-04"
     run_dump_test "attr-merge-priv-spec-failed-05"
     run_dump_test "attr-merge-priv-spec-failed-06"
+    run_dump_test "attr-phdr"
     run_ld_link_tests [list \
        [list "Weak reference 32" "-T weakref.ld -m[riscv_choose_ilp32_emul]" "" \
            "-march=rv32i -mabi=ilp32" {weakref32.s} \