+
+ /* Look through the special sections, and put them in the right
+ place in the link ordering. This is especially magic. */
+ for (i = 0; i < XCOFF_NUMBER_OF_SPECIAL_SECTIONS; i++)
+ {
+ asection *sec;
+ lang_output_section_statement_type *os;
+ lang_statement_union_type **pls;
+ lang_input_section_type *is;
+ const char *oname;
+ bfd_boolean start;
+
+ sec = special_sections[i];
+ if (sec == NULL)
+ continue;
+
+ /* Remove this section from the list of the output section.
+ This assumes we know what the script looks like. */
+ is = NULL;
+ os = lang_output_section_get (sec->output_section);
+ if (os == NULL)
+ einfo ("%P%F: can't find output section %s\n",
+ sec->output_section->name);
+
+ for (pls = &os->children.head; *pls != NULL; pls = &(*pls)->header.next)
+ {
+ if ((*pls)->header.type == lang_input_section_enum
+ && (*pls)->input_section.section == sec)
+ {
+ is = (lang_input_section_type *) * pls;
+ *pls = (*pls)->header.next;
+ break;
+ }
+
+ if ((*pls)->header.type == lang_wild_statement_enum)
+ {
+ lang_statement_union_type **pwls;
+
+ for (pwls = &(*pls)->wild_statement.children.head;
+ *pwls != NULL; pwls = &(*pwls)->header.next)
+ {
+
+ if ((*pwls)->header.type == lang_input_section_enum
+ && (*pwls)->input_section.section == sec)
+ {
+ is = (lang_input_section_type *) * pwls;
+ *pwls = (*pwls)->header.next;
+ break;
+ }
+ }
+
+ if (is != NULL)
+ break;
+ }
+ }
+
+ if (is == NULL)
+ {
+ einfo ("%P%F: can't find %s in output section\n",
+ bfd_get_section_name (sec->owner, sec));
+ }
+
+ /* Now figure out where the section should go. */
+ switch (i)
+ {
+
+ default: /* to avoid warnings */
+ case XCOFF_SPECIAL_SECTION_TEXT:
+ /* _text */
+ oname = ".text";
+ start = TRUE;
+ break;
+
+ case XCOFF_SPECIAL_SECTION_ETEXT:
+ /* _etext */
+ oname = ".text";
+ start = FALSE;
+ break;
+
+ case XCOFF_SPECIAL_SECTION_DATA:
+ /* _data */
+ oname = ".data";
+ start = TRUE;
+ break;
+
+ case XCOFF_SPECIAL_SECTION_EDATA:
+ /* _edata */
+ oname = ".data";
+ start = FALSE;
+ break;
+
+ case XCOFF_SPECIAL_SECTION_END:
+ case XCOFF_SPECIAL_SECTION_END2:
+ /* _end and end */
+ oname = ".bss";
+ start = FALSE;
+ break;
+ }
+
+ os = lang_output_section_find (oname);
+
+ if (start)
+ {
+ is->header.next = os->children.head;
+ os->children.head = (lang_statement_union_type *) is;
+ }
+ else
+ {
+ is->header.next = NULL;
+ lang_statement_append (&os->children,
+ (lang_statement_union_type *) is,
+ &is->header.next);
+ }
+ }
+
+ /* Executables and shared objects must always have .text, .data
+ and .bss output sections, so that the header can refer to them.
+ The kernel refuses to load objects that have missing sections. */
+ if (!bfd_link_relocatable (&link_info))
+ for (i = 0; i < ARRAY_SIZE (must_keep_sections); i++)
+ {
+ asection *sec;
+
+ sec = bfd_get_section_by_name (link_info.output_bfd,
+ must_keep_sections[i]);
+ if (sec == NULL)
+ einfo ("%P: can't find required output section %s\n", must_keep_sections[i]);
+ else
+ sec->flags |= SEC_KEEP;
+ }
+
+ before_allocation_default ();
+}
+
+static char *
+gld${EMULATION_NAME}_choose_target (int argc, char **argv)
+{
+ int i, j, jmax;
+ static char *from_outside;
+ static char *from_inside;
+ static char *argv_to_target[][2] = {
+ {NULL, "${OUTPUT_FORMAT}"},
+ {"-b32", "${OUTPUT_FORMAT_32BIT}"},
+ {"-b64", "${OUTPUT_FORMAT_64BIT}"},
+ };
+
+ jmax = 3;
+
+ from_outside = getenv (TARGET_ENVIRON);
+ if (from_outside != (char *) NULL)
+ return from_outside;
+
+ /* Set to default. */
+ from_inside = argv_to_target[0][1];
+ for (i = 1; i < argc; i++)
+ {
+ for (j = 1; j < jmax; j++)
+ {
+ if (0 == strcmp (argv[i], argv_to_target[j][0]))
+ from_inside = argv_to_target[j][1];
+ }
+ }
+
+ return from_inside;
+}
+
+/* Returns
+ 1 : state changed
+ 0 : no change */
+static int
+change_symbol_mode (char *input)
+{
+ char *symbol_mode_string[] = {
+ "# 32", /* 0x01 */
+ "# 64", /* 0x02 */
+ "# no32", /* 0x04 */
+ "# no64", /* 0x08 */
+ NULL,
+ };
+
+ unsigned int bit;
+ char *string;
+
+ for (bit = 0;; bit++)
+ {
+ string = symbol_mode_string[bit];
+ if (string == NULL)
+ return 0;
+
+ if (0 == strcmp (input, string))
+ {
+ symbol_mode = (1 << bit);
+ return 1;
+ }
+ }
+ /* should not be here */
+ return 0;
+}
+
+/* Returns
+ 1 : yes
+ 0 : ignore
+ -1 : error, try something else */
+static int
+is_syscall (char *input, unsigned int *flag)
+{
+ unsigned int bit;
+ char *string;
+
+ struct sc {
+ char *syscall_string;
+ unsigned int flag;
+ } s [] = {
+ { "svc" /* 0x01 */, XCOFF_SYSCALL32 },
+ { "svc32" /* 0x02 */, XCOFF_SYSCALL32 },
+ { "svc3264" /* 0x04 */, XCOFF_SYSCALL32 | XCOFF_SYSCALL64 },
+ { "svc64" /* 0x08 */, XCOFF_SYSCALL64 },
+ { "syscall" /* 0x10 */, XCOFF_SYSCALL32 },
+ { "syscall32" /* 0x20 */, XCOFF_SYSCALL32 },
+ { "syscall3264" /* 0x40 */, XCOFF_SYSCALL32 | XCOFF_SYSCALL64 },
+ { "syscall64" /* 0x80 */, XCOFF_SYSCALL64 },
+ { NULL, 0 },
+ };
+
+ *flag = 0;
+
+ for (bit = 0;; bit++)
+ {
+ string = s[bit].syscall_string;
+ if (string == NULL)
+ return -1;
+
+ if (0 == strcmp (input, string))
+ {
+ if (1 << bit & syscall_mask)
+ {
+ *flag = s[bit].flag;
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ }
+ /* should not be here */
+ return -1;