Support for xcoff64

This commit is contained in:
Tom Rix 2001-05-24 20:59:23 +00:00
parent beb1bf64d0
commit 3b1b01cf25
9 changed files with 515 additions and 240 deletions

View File

@ -1,3 +1,34 @@
2001-05-24 Tom Rix <trix@redhat.com>
* emultempl/aix.em : (gld${EMULATION_NAME}_read_file)
udate import file format.
(change_symbol_mode) New, same
(is_syscall) New, same
* emulparams/aixppc.sh : add SYSCALL_MASK and SYMBOL_MODE_MASK
* emulparams/aixppc64.sh : same
* emulparams/aixrs6.sh : same
* emulparams/ppcmacos.sh : same
* emultempl/aix.em : use strtoull to parse options
* Makefile.am : add eaixppc64 emulation for xcoff64
* Makefile.in : same
* configure.tgt : same
* scripttempl/aix.sc : default text section offset to 0x10000000
default data section offset to 0x20000000
add .sv3264 and .sv64 pseudo sections
loader and debug sections use the currect section offset.
* emultempl/aix.em : Add xcoff64 support
Add -binitfini support
(gld${EMULATION_NAME}_before_parse) -binitfini
(gld${EMULATION_NAME}_parse_args) same
(gld${EMULATION_NAME}_before_allocation) format change for special
sections
* emulparams/aixppc64.sh : New file for xcoff64 support
2000-01-18 H.J. Lu <hjl@gnu.org>
2001-05-23 Alexandre Oliva <aoliva@redhat.com>
* emultempl/elf32.em (ELF_INTERPRETER_SET_DEFAULT): Use this new

View File

@ -261,7 +261,8 @@ ALL_64_EMULATIONS = \
eelf64bmip.o \
eelf64btsmip.o \
eelf64ltsmip.o \
eelf64hppa.o
eelf64hppa.o \
eaixppc64.o
ALL_EMUL_EXTRA_OFILES = \
deffilep.o \
@ -324,6 +325,9 @@ GEN_DEPENDS = $(srcdir)/genscripts.sh stringify.sed
ea29k.c: $(srcdir)/emulparams/a29k.sh \
$(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/a29k.sc ${GEN_DEPENDS}
${GENSCRIPTS} a29k "$(tdir_a29k)"
eaixppc64.c: $(srcdir)/emulparams/aixppc64.sh \
$(srcdir)/emultempl/aix.em $(srcdir)/scripttempl/aix.sc ${GEN_DEPENDS}
${GENSCRIPTS} aixppc64 "$(tdir_aixppc64)"
eaixppc.c: $(srcdir)/emulparams/aixppc.sh \
$(srcdir)/emultempl/aix.em $(srcdir)/scripttempl/aix.sc ${GEN_DEPENDS}
${GENSCRIPTS} aixppc "$(tdir_aixppc)"

View File

@ -387,6 +387,7 @@ HFILES = ld.h ldctor.h ldemul.h ldexp.h ldfile.h \
ldlang.h ldlex.h ldmain.h ldmisc.h ldver.h \
ldwrite.h mri.h deffile.h pe-dll.h
ALL_64_EMULATIONS = eaixppc64.o eelf64_aix.o eelf64_ia64.o eelf_x86_64.o eelf64_s390.o eelf64_sparc.o eelf64alpha.o eelf64bmip.o eelf64btsmip.o eelf64ltsmip.o eelf64hppa.o
GENERATED_CFILES = ldgram.c ldlex.c deffilep.c
GENERATED_HFILES = ldgram.h ldemul-list.h deffilep.h
@ -1038,6 +1039,9 @@ stringify.sed: ${srcdir}/emultempl/$(STRINGIFY)
ea29k.c: $(srcdir)/emulparams/a29k.sh \
$(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/a29k.sc ${GEN_DEPENDS}
${GENSCRIPTS} a29k "$(tdir_a29k)"
eaixppc64.c: $(srcdir)/emulparams/aixppc64.sh \
$(srcdir)/emultempl/aix.em $(srcdir)/scripttempl/aix.sc ${GEN_DEPENDS}
${GENSCRIPTS} aixppc64 "$(tdir_aixppc64)"
eaixppc.c: $(srcdir)/emulparams/aixppc.sh \
$(srcdir)/emultempl/aix.em $(srcdir)/scripttempl/aix.sc ${GEN_DEPENDS}
${GENSCRIPTS} aixppc "$(tdir_aixppc)"

View File

@ -332,8 +332,12 @@ powerpc-*-macos*) targ_emul=ppcmacos ;;
powerpc-*-netware*) targ_emul=ppcnw ;;
powerpcle-*-pe) targ_emul=ppcpe ;;
powerpcle-*-winnt*) targ_emul=ppcpe ;;
powerpcle-*-cygwin*) targ_emul=ppcpe ;;
powerpc-*-aix*) targ_emul=aixppc ;;
powerpcle-*-cygwin*) targ_emul=ppcpe ;;
powerpc-*-aix*) targ_emul=aixppc
targ_extra_emuls="aixppc64"
tdir_aixppc64=${targ_alias}
;;
powerpc-*-beos*) targ_emul=aixppc ;;
rs6000-*-aix*) targ_emul=aixrs6 ;;
tic30-*-*aout*) targ_emul=tic30aout ;;

View File

@ -2,3 +2,5 @@ TEMPLATE_NAME=aix
SCRIPT_NAME=aix
OUTPUT_FORMAT="aixcoff-rs6000"
ARCH=powerpc
SYSCALL_MASK=0x77
SYMBOL_MODE_MASK=0x0d

14
ld/emulparams/aixppc64.sh Normal file
View File

@ -0,0 +1,14 @@
TEMPLATE_NAME=aix
SCRIPT_NAME=aix
OUTPUT_FORMAT="aixcoff64-rs6000"
ARCH=powerpc
SYSCALL_MASK=0xcc
SYMBOL_MODE_MASK=0x0e
#
# This script is called by genscripts.sh. genscripts does not produce the
# the correct lib search path for the aixppc64 because the default emulation
# is aixppc. Aix libs can have 32 bit and 64 bit objects in them so it is
# ok for both the aixppc and aixppc64 linkers to look at the same place.
# $libdir is defined in genscripts.sh before aixppc64.sh is sourced in
# so it will be valid.
LIB_PATH="/lib:/usr/lib:$libdir:/usr/local/lib"

View File

@ -4,10 +4,10 @@ cat >e${EMULATION_NAME}.c <<EOF
/* This file is is generated by a shell script. DO NOT EDIT! */
/* AIX emulation code for ${EMULATION_NAME}
Copyright 1991, 1993, 1995, 1996, 1997, 1998, 2000
Free Software Foundation, Inc.
Copyright (C) 1991, 93, 95, 96, 97, 1998 Free Software Foundation, Inc.
Written by Steve Chamberlain <sac@cygnus.com>
AIX support by Ian Lance Taylor <ian@cygnus.com>
AIX 64 bit support by Tom Rix <trix@redhat.com>
This file is part of GLD, the Gnu Linker.
@ -38,14 +38,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "ld.h"
#include "ldmain.h"
#include "ldemul.h"
#include "ldfile.h"
#include "ldmisc.h"
#include "ldexp.h"
#include "ldlang.h"
#include "ldfile.h"
#include "ldemul.h"
#include "ldctor.h"
#include "ldgram.h"
#include "coff/internal.h"
#include "coff/xcoff.h"
static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
static int gld${EMULATION_NAME}_parse_args PARAMS ((int, char **));
static void gld${EMULATION_NAME}_after_open PARAMS ((void));
@ -102,6 +105,9 @@ struct export_symbol_list
static struct export_symbol_list *export_symbols;
/* Maintains the 32 or 64 bit mode state of import file */
static unsigned int symbol_mode = 0x04;
/* This routine is called before anything else is done. */
static void
@ -111,6 +117,15 @@ gld${EMULATION_NAME}_before_parse()
ldfile_output_architecture = bfd_arch_${ARCH};
#endif /* not TARGET_ */
config.has_shared = true;
/*
* The link_info.[init|fini]_functions are initialized in ld/lexsup.c.
* Override them here so we can use the link_info.init_function as a
* state flag that lets the backend know that -binitfini has been done.
*/
link_info.init_function = NULL;
link_info.fini_function = NULL;
}
/* Handle AIX specific options. */
@ -125,27 +140,81 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
int indx;
int longind;
int optc;
long val;
bfd_signed_vma val;
char *end;
#define OPTION_IGNORE (300)
#define OPTION_AUTOIMP (OPTION_IGNORE + 1)
#define OPTION_ERNOTOK (OPTION_AUTOIMP + 1)
#define OPTION_EROK (OPTION_ERNOTOK + 1)
#define OPTION_EXPORT (OPTION_EROK + 1)
#define OPTION_IMPORT (OPTION_EXPORT + 1)
#define OPTION_LOADMAP (OPTION_IMPORT + 1)
#define OPTION_MAXDATA (OPTION_LOADMAP + 1)
#define OPTION_MAXSTACK (OPTION_MAXDATA + 1)
#define OPTION_MODTYPE (OPTION_MAXSTACK + 1)
#define OPTION_NOAUTOIMP (OPTION_MODTYPE + 1)
#define OPTION_NOSTRCMPCT (OPTION_NOAUTOIMP + 1)
#define OPTION_PD (OPTION_NOSTRCMPCT + 1)
#define OPTION_PT (OPTION_PD + 1)
#define OPTION_STRCMPCT (OPTION_PT + 1)
#define OPTION_UNIX (OPTION_STRCMPCT + 1)
enum {
OPTION_IGNORE = 300,
OPTION_AUTOIMP,
OPTION_ERNOTOK,
OPTION_EROK,
OPTION_EXPORT,
OPTION_IMPORT,
OPTION_INITFINI,
OPTION_LOADMAP,
OPTION_MAXDATA,
OPTION_MAXSTACK,
OPTION_MODTYPE,
OPTION_NOAUTOIMP,
OPTION_NOSTRCMPCT,
OPTION_PD,
OPTION_PT,
OPTION_STRCMPCT,
OPTION_UNIX
};
static struct option longopts[] = {
/*
b64 is an empty option. The native linker uses -b64 for xcoff64 support
Our linker uses -m aixppc64 for xcoff64 support. The choice for the
correct emulation is done in collect2.c via the environmental varible
LDEMULATION.
binitfini has special handling in the linker backend. The native linker
uses the arguemnts to generate a table of init and fini functions for
the executable. The important use for this option is to support aix 4.2+
c++ constructors and destructors. This is tied into gcc via collect2.c.
The function table is accessed by the runtime linker/loader by checking if
the first symbol in the loader symbol table is "__rtinit". The native
linker generates this table and the loader symbol. The gnu linker looks
for the symbol "__rtinit" and makes it the first loader symbol. It is the
responsiblity of the user to define the __rtinit symbol. The format for
__rtinit is given by the aix system file /usr/include/rtinit.h. You can
look at collect2.c to see an example of how this is done for 32 and 64 bit.
Below is an exmaple of a 32 bit assembly file that defines __rtinit.
.file "my_rtinit.s"
.csect .data[RW],3
.globl __rtinit
.extern init_function
.extern fini_function
__rtinit:
.long 0
.long f1i - __rtinit
.long f1f - __rtinit
.long f2i - f1i
.align 3
f1i: .long init_function
.long s1i - __rtinit
.long 0
f2i: .long 0
.long 0
.long 0
f1f: .long fini_function
.long s1f - __rtinit
.long 0
f2f: .long 0
.long 0
.long 0
.align 3
s1i: .string "init_function"
.align 3
s1f: .string "fini_function"
*/
static const struct option longopts[] = {
{"basis", no_argument, NULL, OPTION_IGNORE},
{"bautoimp", no_argument, NULL, OPTION_AUTOIMP},
{"bcomprld", no_argument, NULL, OPTION_IGNORE},
@ -163,6 +232,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
{"bhalt", required_argument, NULL, OPTION_IGNORE},
{"bI", required_argument, NULL, OPTION_IMPORT},
{"bimport", required_argument, NULL, OPTION_IMPORT},
{"binitfini", required_argument, NULL, OPTION_INITFINI},
{"bl", required_argument, NULL, OPTION_LOADMAP},
{"bloadmap", required_argument, NULL, OPTION_LOADMAP},
{"bmaxdata", required_argument, NULL, OPTION_MAXDATA},
@ -184,6 +254,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
{"bso", no_argument, NULL, OPTION_AUTOIMP},
{"bstrcmpct", no_argument, NULL, OPTION_STRCMPCT},
{"btextro", no_argument, &textro, 1},
{"b64", no_argument, NULL, 0},
{"static", no_argument, NULL, OPTION_NOAUTOIMP},
{"unix", no_argument, NULL, OPTION_UNIX},
{NULL, no_argument, NULL, 0}
@ -202,21 +273,21 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
The AIX linker uses : to separate the option from the argument;
changing it to = lets us treat it as a getopt option. */
indx = optind;
if (indx == 0)
if (indx == 0) {
indx = 1;
if (indx < argc && strncmp (argv[indx], "-b", 2) == 0)
{
char *s;
}
for (s = argv[indx]; *s != '\0'; s++)
{
if (*s == ':')
{
*s = '=';
break;
}
}
if (indx < argc && strncmp (argv[indx], "-b", 2) == 0) {
char *s;
for (s = argv[indx]; *s != '\0'; s++) {
if (*s == ':') {
*s = '=';
break;
}
}
}
/* We add s and u so to the short options list so that -s and -u on
the command line do not match -static and -unix. */
@ -238,7 +309,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
break;
case 'D':
val = strtol (optarg, &end, 0);
val = strtoll (optarg, &end, 0);
if (*end != '\0')
einfo ("%P: warning: ignoring invalid -D number %s\n", optarg);
else if (val != -1)
@ -265,7 +336,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
number, we assume the AIX option is intended. Otherwise, we
assume the usual GNU ld -T option is intended. We can't just
ignore the AIX option, because gcc passes it to the linker. */
val = strtoul (optarg, &end, 0);
val = strtoull (optarg, &end, 0);
if (*end != '\0')
{
optind = prevoptind;
@ -277,6 +348,41 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
case OPTION_IGNORE:
break;
case OPTION_INITFINI: {
/*
* The aix linker init fini has the format :
*
* -binitfini:[ Initial][:Termination][:Priority]
*
* it allows the Termination and Priority to be optional.
*
* Since we support only one init/fini pair, we ignore the Priority.
*
* Define the special symbol __rtinit.
*
* strtok does not correctly handle the case of -binitfini::fini: so
* do it by hand
*/
char *t, *i, *f;
i = t = optarg;
while (*t && ':' != *t) t++;
if (*t) *t++ = 0;
if (0 != strlen(i)) {
link_info.init_function = i;
}
f = t;
while (*t && ':' != *t) t++;
*t = 0;
if (0 != strlen(f)) {
link_info.fini_function = f;
}
}
break;
case OPTION_AUTOIMP:
link_info.static_link = false;
break;
@ -313,7 +419,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
break;
case OPTION_MAXDATA:
val = strtoul (optarg, &end, 0);
val = strtoull (optarg, &end, 0);
if (*end != '\0')
einfo ("%P: warning: ignoring invalid -bmaxdata number %s\n",
optarg);
@ -322,7 +428,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
break;
case OPTION_MAXSTACK:
val = strtoul (optarg, &end, 0);
val = strtoull (optarg, &end, 0);
if (*end != '\0')
einfo ("%P: warning: ignoring invalid -bmaxstack number %s\n",
optarg);
@ -355,7 +461,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
start on. The offset within the page should still be the
offset within the file, so we need to build an appropriate
expression. */
val = strtoul (optarg, &end, 0);
val = strtoull (optarg, &end, 0);
if (*end != '\0')
einfo ("%P: warning: ignoring invalid -pD number %s\n", optarg);
else
@ -378,7 +484,7 @@ gld${EMULATION_NAME}_parse_args (argc, argv)
/* This set the page that the .text section is supposed to start
on. The offset within the page should still be the offset
within the file. */
val = strtoul (optarg, &end, 0);
val = strtoull (optarg, &end, 0);
if (*end != '\0')
einfo ("%P: warning: ignoring invalid -pT number %s\n", optarg);
else
@ -499,22 +605,21 @@ gld${EMULATION_NAME}_before_allocation ()
struct filelist *fl;
struct export_symbol_list *el;
char *libpath;
asection *special_sections[6];
asection *special_sections[XCOFF_NUMBER_OF_SPECIAL_SECTIONS];
int i;
/* Handle the import and export files, if any. */
for (fl = import_files; fl != NULL; fl = fl->next)
gld${EMULATION_NAME}_read_file (fl->name, true);
for (el = export_symbols; el != NULL; el = el->next)
{
struct bfd_link_hash_entry *h;
h = bfd_link_hash_lookup (link_info.hash, el->name, false, false, false);
if (h == NULL)
einfo ("%P%F: bfd_link_hash_lookup of export symbol failed: %E\n");
if (! bfd_xcoff_export_symbol (output_bfd, &link_info, h, el->syscall))
einfo ("%P%F: bfd_xcoff_export_symbol failed: %E\n");
}
for (el = export_symbols; el != NULL; el = el->next) {
struct bfd_link_hash_entry *h;
h = bfd_link_hash_lookup (link_info.hash, el->name, false, false, false);
if (h == NULL)
einfo ("%P%F: bfd_link_hash_lookup of export symbol failed: %E\n");
if (! bfd_xcoff_export_symbol (output_bfd, &link_info, h, el->syscall))
einfo ("%P%F: bfd_xcoff_export_symbol failed: %E\n");
}
/* Track down all relocations called for by the linker script (these
are typically constructor/destructor entries created by
@ -562,109 +667,186 @@ gld${EMULATION_NAME}_before_allocation ()
/* Look through the special sections, and put them in the right
place in the link ordering. This is especially magic. */
for (i = 0; i < 6; i++)
{
asection *sec;
lang_output_section_statement_type *os;
lang_statement_union_type **pls;
lang_input_section_type *is;
const char *oname;
boolean start;
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;
boolean start;
sec = special_sections[i];
if (sec == NULL)
continue;
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_find (sec->output_section->name);
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)->next)
{
if ((*pls)->header.type == lang_input_section_enum
&& (*pls)->input_section.section == sec)
{
is = (lang_input_section_type *) *pls;
*pls = (*pls)->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)->next)
{
if ((*pwls)->header.type == lang_input_section_enum
&& (*pwls)->input_section.section == sec)
{
is = (lang_input_section_type *) *pwls;
*pwls = (*pwls)->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 0:
/* _text */
oname = ".text";
start = true;
break;
case 1:
/* _etext */
oname = ".text";
start = false;
break;
case 2:
/* _data */
oname = ".data";
start = true;
break;
case 3:
/* _edata */
oname = ".data";
start = false;
break;
case 4:
case 5:
/* _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);
}
/* 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_find (sec->output_section->name);
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)->next) {
if ((*pls)->header.type == lang_input_section_enum &&
(*pls)->input_section.section == sec) {
is = (lang_input_section_type *) *pls;
*pls = (*pls)->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)->next) {
if ((*pwls)->header.type == lang_input_section_enum &&
(*pwls)->input_section.section == sec) {
is = (lang_input_section_type *) *pwls;
*pwls = (*pwls)->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);
}
}
}
static int change_symbol_mode (char *input)
{
/*
* 1 : state changed
* 0 : no change
*/
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 (NULL == string)
return 0;
if (0 == strcmp(input, string)) {
symbol_mode = (1 << bit);
return 1;
}
}
/* should not be here */
return 0;
}
static int is_syscall(char *input)
{
/*
* 1 : yes
* 0 : ignore
* -1 : error, try something else
*/
unsigned int bit;
char *string;
char *syscall_string[] = {
"svc", /* 0x01 */
"svc32", /* 0x02 */
"svc3264", /* 0x04 */
"svc64", /* 0x08 */
"syscall", /* 0x10 */
"syscall32", /* 0x20 */
"syscall3264", /* 0x40 */
"syscall64", /* 0x80 */
NULL
};
for (bit = 0; ;bit++) {
string = syscall_string[bit];
if (NULL == string) {
return -1;
}
if (0 == strcmp(input, string)) {
if (1 << bit & ${SYSCALL_MASK}) {
return 1;
} else {
return 0;
}
}
}
/* should not be here */
return -1;
}
/* Read an import or export file. For an import file, this is called
by the before_allocation emulation routine. For an export file,
this is called by the parse_args emulation routine. */
@ -700,6 +882,15 @@ gld${EMULATION_NAME}_read_file (filename, import)
impmember = NULL;
lineno = 0;
/*
* default to 32 and 64 bit mode
* symbols at top of /lib/syscalls.exp do not have a mode modifier and they
* are not repeated, assume 64 bit routines also want to use them.
* See the routine change_symbol_mode for more information.
*/
symbol_mode = 0x04;
while ((c = getc (f)) != EOF)
{
char *s;
@ -720,10 +911,11 @@ gld${EMULATION_NAME}_read_file (filename, import)
s = (char *) obstack_base (o);
while (isspace ((unsigned char) *s))
++s;
if (*s == '\0'
|| *s == '*'
|| (*s == '#' && s[1] == ' ')
|| (! import && *s == '#' && s[1] == '!'))
if (*s == '\0' ||
*s == '*' ||
change_symbol_mode (s) ||
(*s == '#' && s[1] == ' ') ||
(! import && *s == '#' && s[1] == '!'))
{
obstack_free (o, obstack_base (o));
continue;
@ -802,100 +994,111 @@ gld${EMULATION_NAME}_read_file (filename, import)
continue;
}
/* This is a symbol to be imported or exported. */
symname = s;
syscall = false;
address = (bfd_vma) -1;
if (symbol_mode & ${SYMBOL_MODE_MASK}) {
while (! isspace ((unsigned char) *s) && *s != '\0')
++s;
if (*s != '\0')
{
char *se;
/* This is a symbol to be imported or exported. */
symname = s;
syscall = false;
address = (bfd_vma) -1;
*s++ = '\0';
while (! isspace ((unsigned char) *s) && *s != '\0')
++s;
if (*s != '\0')
{
char *se;
*s++ = '\0';
while (isspace ((unsigned char) *s))
++s;
while (isspace ((unsigned char) *s))
++s;
se = s;
while (! isspace ((unsigned char) *se) && *se != '\0')
++se;
if (*se != '\0')
{
*se++ = '\0';
while (isspace ((unsigned char) *se))
++se;
if (*se != '\0')
einfo ("%s%d: warning: syntax error in import/export file\n",
filename, lineno);
}
se = s;
while (! isspace ((unsigned char) *se) && *se != '\0')
++se;
if (*se != '\0')
{
*se++ = '\0';
while (isspace ((unsigned char) *se))
++se;
if (*se != '\0')
einfo ("%s%d: warning: syntax error in import/export file\n",
filename, lineno);
}
if (s == se)
{
/* There was no address after all. */
}
else if (strcasecmp (s, "svc") == 0
|| strcasecmp (s, "syscall") == 0)
syscall = true;
else
{
if (s != se) {
int status;
char *end;
address = strtoul (s, &end, 0);
if (*end != '\0')
einfo ("%s:%d: warning: syntax error in import/export file\n",
filename, lineno);
status = is_syscall(s);
switch (status) {
case 1:
/* this is a system call */
syscall = true;
break;
case 0:
/* ignore this system call */
break;
default:
/* not a system call, check for address */
address = strtoul (s, &end, 0);
if (*end != '\0') {
einfo ("%s:%d: warning: syntax error in import/export file\n", filename, lineno);
}
}
}
}
}
if (! import)
{
struct export_symbol_list *n;
ldlang_add_undef (symname);
n = ((struct export_symbol_list *)
xmalloc (sizeof (struct export_symbol_list)));
n->next = export_symbols;
n->name = xstrdup (symname);
n->syscall = syscall;
export_symbols = n;
}
else
{
h = bfd_link_hash_lookup (link_info.hash, symname, false, false,
true);
if (h == NULL || h->type == bfd_link_hash_new)
{
/* We can just ignore attempts to import an unreferenced
symbol. */
}
else
{
if (! bfd_xcoff_import_symbol (output_bfd, &link_info, h,
address, imppath, impfile,
impmember))
einfo ("%X%s:%d: failed to import symbol %s: %E\n",
filename, lineno, symname);
}
}
if (! import)
{
struct export_symbol_list *n;
ldlang_add_undef (symname);
n = ((struct export_symbol_list *)
xmalloc (sizeof (struct export_symbol_list)));
n->next = export_symbols;
n->name = xstrdup (symname);
n->syscall = syscall;
export_symbols = n;
}
else
{
h = bfd_link_hash_lookup (link_info.hash, symname, false, false,
true);
if (h == NULL || h->type == bfd_link_hash_new)
{
/* We can just ignore attempts to import an unreferenced
symbol. */
}
else
{
if (! bfd_xcoff_import_symbol (output_bfd, &link_info, h,
address, imppath, impfile,
impmember))
einfo ("%X%s:%d: failed to import symbol %s: %E\n",
filename, lineno, symname);
}
}
}
obstack_free (o, obstack_base (o));
}
if (obstack_object_size (o) > 0)
{
einfo ("%s:%d: warning: ignoring unterminated last line\n",
filename, lineno);
obstack_free (o, obstack_base (o));
}
einfo ("%s:%d: warning: ignoring unterminated last line\n",
filename, lineno);
obstack_free (o, obstack_base (o));
}
if (! keep)
{
obstack_free (o, NULL);
free (o);
if (! keep)
{
obstack_free (o, NULL);
free (o);
}
}
}
/* This routine saves us from worrying about declaring free. */
@ -986,7 +1189,7 @@ then
# Scripts compiled in.
# sed commands to quote an ld script as a C string.
sc="-f stringify.sed"
sc="-f ${srcdir}/emultempl/stringify.sed"
cat >>e${EMULATION_NAME}.c <<EOF
{
@ -1051,6 +1254,8 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
0, /* set_symbols */
gld${EMULATION_NAME}_parse_args,
gld${EMULATION_NAME}_unrecognized_file,
NULL /* find_potential_libraries */
NULL, /* list_options */
NULL, /* recognized_file */
NULL, /* find potential_libraries */
};
EOF

View File

@ -0,0 +1,4 @@
s/["\\]/\\&/g
s/$/\\n\\/
1 s/^/"/
$ s/$/n"/

View File

@ -10,6 +10,8 @@ ENTRY(__start)
SECTIONS
{
.pad 0 : { *(.pad) }
. = 0x10000000;
.text ${RELOCATING-0} : {
${RELOCATING+PROVIDE (_text = .);}
*(.text)
@ -22,11 +24,14 @@ SECTIONS
*(.tb)
${RELOCATING+PROVIDE (_etext = .);}
}
.data 0 : {
. = 0x20000000;
.data . : {
${RELOCATING+PROVIDE (_data = .);}
*(.data)
*(.rw)
*(.sv)
*(.sv64)
*(.sv3264)
*(.ua)
. = ALIGN(4);
${CONSTRUCTING+CONSTRUCTORS}
@ -45,10 +50,12 @@ SECTIONS
${RELOCATING+PROVIDE (_end = .);}
${RELOCATING+PROVIDE (end = .);}
}
.loader 0 : {
.loader : {
*(.loader)
}
.debug 0 : {
.debug : {
*(.debug)
}
}