+/* Map an ELF section header flag to its corresponding string. */
+typedef struct
+{
+ char *flag_name;
+ flagword flag_value;
+} elf_flags_to_name_table;
+
+static elf_flags_to_name_table elf_flags_to_names [] =
+{
+ { "SHF_WRITE", SHF_WRITE },
+ { "SHF_ALLOC", SHF_ALLOC },
+ { "SHF_EXECINSTR", SHF_EXECINSTR },
+ { "SHF_MERGE", SHF_MERGE },
+ { "SHF_STRINGS", SHF_STRINGS },
+ { "SHF_INFO_LINK", SHF_INFO_LINK},
+ { "SHF_LINK_ORDER", SHF_LINK_ORDER},
+ { "SHF_OS_NONCONFORMING", SHF_OS_NONCONFORMING},
+ { "SHF_GROUP", SHF_GROUP },
+ { "SHF_TLS", SHF_TLS },
+ { "SHF_MASKOS", SHF_MASKOS },
+ { "SHF_EXCLUDE", SHF_EXCLUDE },
+};
+
+/* Returns TRUE if the section is to be included, otherwise FALSE. */
+bfd_boolean
+bfd_elf_lookup_section_flags (struct bfd_link_info *info,
+ struct flag_info *flaginfo,
+ asection *section)
+{
+ const bfd_vma sh_flags = elf_section_flags (section);
+
+ if (!flaginfo->flags_initialized)
+ {
+ bfd *obfd = info->output_bfd;
+ const struct elf_backend_data *bed = get_elf_backend_data (obfd);
+ struct flag_info_list *tf = flaginfo->flag_list;
+ int with_hex = 0;
+ int without_hex = 0;
+
+ for (tf = flaginfo->flag_list; tf != NULL; tf = tf->next)
+ {
+ unsigned i;
+ flagword (*lookup) (char *);
+
+ lookup = bed->elf_backend_lookup_section_flags_hook;
+ if (lookup != NULL)
+ {
+ flagword hexval = (*lookup) ((char *) tf->name);
+
+ if (hexval != 0)
+ {
+ if (tf->with == with_flags)
+ with_hex |= hexval;
+ else if (tf->with == without_flags)
+ without_hex |= hexval;
+ tf->valid = TRUE;
+ continue;
+ }
+ }
+ for (i = 0; i < ARRAY_SIZE (elf_flags_to_names); ++i)
+ {
+ if (strcmp (tf->name, elf_flags_to_names[i].flag_name) == 0)
+ {
+ if (tf->with == with_flags)
+ with_hex |= elf_flags_to_names[i].flag_value;
+ else if (tf->with == without_flags)
+ without_hex |= elf_flags_to_names[i].flag_value;
+ tf->valid = TRUE;
+ break;
+ }
+ }
+ if (!tf->valid)
+ {
+ info->callbacks->einfo
+ (_("Unrecognized INPUT_SECTION_FLAG %s\n"), tf->name);
+ return FALSE;
+ }
+ }
+ flaginfo->flags_initialized = TRUE;
+ flaginfo->only_with_flags |= with_hex;
+ flaginfo->not_with_flags |= without_hex;
+ }
+
+ if ((flaginfo->only_with_flags & sh_flags) != flaginfo->only_with_flags)
+ return FALSE;
+
+ if ((flaginfo->not_with_flags & sh_flags) != 0)
+ return FALSE;
+
+ return TRUE;
+}
+