diff options
Diffstat (limited to 'sys-devel/binutils/files/binutils-2.22-mint.patch')
-rw-r--r-- | sys-devel/binutils/files/binutils-2.22-mint.patch | 2656 |
1 files changed, 2656 insertions, 0 deletions
diff --git a/sys-devel/binutils/files/binutils-2.22-mint.patch b/sys-devel/binutils/files/binutils-2.22-mint.patch new file mode 100644 index 0000000..4c2442e --- /dev/null +++ b/sys-devel/binutils/files/binutils-2.22-mint.patch @@ -0,0 +1,2656 @@ +http://bugs.gentoo.org/show_bug.cgi?id=362559 + +diff -ur --new-file binutils-2.21.51.0.7/bfd/Makefile.am binutils-2.21.51.0.7-mint/bfd/Makefile.am +--- binutils-2.21.51.0.7/bfd/Makefile.am 2010-12-06 14:23:53.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/bfd/Makefile.am 2011-04-08 10:07:06.000000000 +0000 +@@ -379,6 +379,7 @@ + peigen.lo \ + plugin.lo \ + ppcboot.lo \ ++ prg-mint.lo \ + reloc16.lo \ + riscix.lo \ + som.lo \ +@@ -559,6 +560,7 @@ + pei-sh.c \ + plugin.c \ + ppcboot.c \ ++ prg-mint.c \ + reloc16.c \ + riscix.c \ + som.c \ +diff -ur --new-file binutils-2.21.51.0.7/bfd/Makefile.in binutils-2.21.51.0.7-mint/bfd/Makefile.in +--- binutils-2.21.51.0.7/bfd/Makefile.in 2010-12-06 14:23:53.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/bfd/Makefile.in 2011-04-08 10:07:06.000000000 +0000 +@@ -679,6 +679,7 @@ + peigen.lo \ + plugin.lo \ + ppcboot.lo \ ++ prg-mint.lo \ + reloc16.lo \ + riscix.lo \ + som.lo \ +@@ -859,6 +860,7 @@ + pei-sh.c \ + plugin.c \ + ppcboot.c \ ++ prg-mint.c \ + reloc16.c \ + riscix.c \ + som.c \ +diff -ur --new-file binutils-2.21.51.0.7/bfd/acinclude.m4 binutils-2.21.51.0.7-mint/bfd/acinclude.m4 +--- binutils-2.21.51.0.7/bfd/acinclude.m4 2009-12-14 15:46:47.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/bfd/acinclude.m4 2011-04-08 10:07:06.000000000 +0000 +@@ -5,7 +5,7 @@ + [AC_REQUIRE([AC_CANONICAL_TARGET]) + case "${host}" in + changequote(,)dnl +-*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows*) ++*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows* | *-*-mint*) + changequote([,])dnl + AC_DEFINE(USE_BINARY_FOPEN, 1, [Use b modifier when opening binary files?]) ;; + esac])dnl +diff -ur --new-file binutils-2.21.51.0.7/bfd/aoutx.h binutils-2.21.51.0.7-mint/bfd/aoutx.h +--- binutils-2.21.51.0.7/bfd/aoutx.h 2011-03-07 18:05:31.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/bfd/aoutx.h 2011-04-08 10:07:06.000000000 +0000 +@@ -1841,6 +1841,11 @@ + bfd_byte buffer[BYTES_IN_WORD]; + bfd_size_type amt = BYTES_IN_WORD; + ++ /* The MiNT backend writes past the string table. It therefore has to ++ know about the table size. */ ++ obj_aout_external_string_size (abfd) = _bfd_stringtab_size (tab) + ++ BYTES_IN_WORD; ++ + /* The string table starts with the size. */ + PUT_WORD (abfd, _bfd_stringtab_size (tab) + BYTES_IN_WORD, buffer); + if (bfd_bwrite ((void *) buffer, amt, abfd) != amt) +@@ -4220,10 +4225,17 @@ + return FALSE; + } + ++#ifdef MY_final_link_relocate_rel ++ r = MY_final_link_relocate_rel (howto, ++ input_bfd, input_section, ++ contents, r_addr, relocation, ++ (bfd_vma) 0, rel); ++#else + r = MY_final_link_relocate (howto, + input_bfd, input_section, + contents, r_addr, relocation, + (bfd_vma) 0); ++#endif + } + + if (r != bfd_reloc_ok) +diff -ur --new-file binutils-2.21.51.0.7/bfd/bfd-in.h binutils-2.21.51.0.7-mint/bfd/bfd-in.h +--- binutils-2.21.51.0.7/bfd/bfd-in.h 2010-11-12 17:32:58.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/bfd/bfd-in.h 2011-04-08 10:07:06.000000000 +0000 +@@ -742,6 +742,15 @@ + extern bfd_boolean bfd_sparclinux_size_dynamic_sections + (bfd *, struct bfd_link_info *); + ++/* MiNT executable support routines for the linker. */ ++ ++extern bfd_boolean bfd_m68kmint_set_extended_flags ++ (bfd *, flagword); ++extern bfd_boolean bfd_m68kmint_set_stack_size ++ (bfd *, bfd_signed_vma); ++extern bfd_boolean bfd_m68kmint_add_tpa_relocation_entry ++ (bfd *, bfd_vma); ++ + /* mmap hacks */ + + struct _bfd_window_internal; +diff -ur --new-file binutils-2.21.51.0.7/bfd/bfd-in2.h binutils-2.21.51.0.7-mint/bfd/bfd-in2.h +--- binutils-2.21.51.0.7/bfd/bfd-in2.h 2011-03-07 18:05:57.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/bfd/bfd-in2.h 2011-04-08 10:07:06.000000000 +0000 +@@ -749,6 +749,15 @@ + extern bfd_boolean bfd_sparclinux_size_dynamic_sections + (bfd *, struct bfd_link_info *); + ++/* MiNT executable support routines for the linker. */ ++ ++extern bfd_boolean bfd_m68kmint_set_extended_flags ++ (bfd *, flagword); ++extern bfd_boolean bfd_m68kmint_set_stack_size ++ (bfd *, bfd_signed_vma); ++extern bfd_boolean bfd_m68kmint_add_tpa_relocation_entry ++ (bfd *, bfd_vma); ++ + /* mmap hacks */ + + struct _bfd_window_internal; +diff -ur --new-file binutils-2.21.51.0.7/bfd/config.bfd binutils-2.21.51.0.7-mint/bfd/config.bfd +--- binutils-2.21.51.0.7/bfd/config.bfd 2011-01-04 17:51:04.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/bfd/config.bfd 2011-04-08 10:07:06.000000000 +0000 +@@ -823,6 +823,11 @@ + # targ_selvecs=m68kmach3_vec + # targ_cflags=-DSTAT_FOR_EXEC + ;; ++ m68*-*-mint*) ++ targ_defvec=aout0_big_vec ++ targ_selvecs=m68kmint_prg_vec ++ targ_underscore=yes ++ ;; + m68*-hp*-netbsd*) + targ_defvec=m68k4knetbsd_vec + targ_selvecs="m68knetbsd_vec hp300bsd_vec sunos_big_vec" +diff -ur --new-file binutils-2.21.51.0.7/bfd/configure binutils-2.21.51.0.7-mint/bfd/configure +--- binutils-2.21.51.0.7/bfd/configure 2011-03-07 18:05:31.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/bfd/configure 2011-04-08 10:07:07.000000000 +0000 +@@ -13623,7 +13623,7 @@ + + + case "${host}" in +-*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows*) ++*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows* | *-*-mint*) + + $as_echo "#define USE_BINARY_FOPEN 1" >>confdefs.h + ;; +@@ -15237,6 +15237,7 @@ + m68kcoff_vec) tb="$tb coff-m68k.lo cofflink.lo" ;; + m68kcoffun_vec) tb="$tb coff-u68k.lo coff-m68k.lo cofflink.lo" ;; + m68klinux_vec) tb="$tb m68klinux.lo aout32.lo" ;; ++ m68kmint_prg_vec) tb="$tb prg-mint.lo aout32.lo" ;; + m68knetbsd_vec) tb="$tb m68knetbsd.lo aout32.lo" ;; + m68ksysvcoff_vec) tb="$tb coff-svm68k.lo cofflink.lo" ;; + m88kbcs_vec) tb="$tb coff-m88k.lo" ;; +diff -ur --new-file binutils-2.21.51.0.7/bfd/configure.in binutils-2.21.51.0.7-mint/bfd/configure.in +--- binutils-2.21.51.0.7/bfd/configure.in 2011-03-07 18:05:31.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/bfd/configure.in 2011-04-08 10:07:07.000000000 +0000 +@@ -880,6 +880,7 @@ + m68kcoff_vec) tb="$tb coff-m68k.lo cofflink.lo" ;; + m68kcoffun_vec) tb="$tb coff-u68k.lo coff-m68k.lo cofflink.lo" ;; + m68klinux_vec) tb="$tb m68klinux.lo aout32.lo" ;; ++ m68kmint_prg_vec) tb="$tb prg-mint.lo aout32.lo" ;; + m68knetbsd_vec) tb="$tb m68knetbsd.lo aout32.lo" ;; + m68ksysvcoff_vec) tb="$tb coff-svm68k.lo cofflink.lo" ;; + m88kbcs_vec) tb="$tb coff-m88k.lo" ;; +diff -ur --new-file binutils-2.21.51.0.7/bfd/libaout.h binutils-2.21.51.0.7-mint/bfd/libaout.h +--- binutils-2.21.51.0.7/bfd/libaout.h 2009-10-09 22:25:42.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/bfd/libaout.h 2011-04-08 10:07:08.000000000 +0000 +@@ -422,6 +422,10 @@ + table, used when linking on SunOS. This is indexed by the symbol + index. */ + bfd_vma *local_got_offsets; ++ ++ /* A pointer for data used by aout extensions. (Currently only used ++ by MiNT executables (see prg-mint.c). */ ++ void *ext; + }; + + struct aout_data_struct +@@ -449,6 +453,7 @@ + #define obj_aout_string_window(bfd) (adata (bfd).string_window) + #define obj_aout_sym_hashes(bfd) (adata (bfd).sym_hashes) + #define obj_aout_dynamic_info(bfd) (adata (bfd).dynamic_info) ++#define obj_aout_ext(bfd) (adata (bfd).ext) + + /* We take the address of the first element of an asymbol to ensure that the + macro is only ever applied to an asymbol. */ +diff -ur --new-file binutils-2.21.51.0.7/bfd/prg-mint.c binutils-2.21.51.0.7-mint/bfd/prg-mint.c +--- binutils-2.21.51.0.7/bfd/prg-mint.c 1970-01-01 00:00:00.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/bfd/prg-mint.c 2011-04-08 10:07:08.000000000 +0000 +@@ -0,0 +1,1732 @@ ++/* BFD backend for traditional MiNT executables. ++ Copyright 1998, 2007, 2008, 2009 Free Software Foundation, Inc. ++ Originally written by Guido Flohr (guido@freemint.de). ++ Modified by Vincent Riviere (vincent.riviere@freesbee.fr). ++ ++ This file is part of BFD, the Binary File Descriptor library. ++ ++ 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 3 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. */ ++ ++/* The format of executables on Atari is actually not a.out, it is ++ only chosen as an approach which comes close enough. The layout of a ++ program image on disk looked like this: ++ ++ +-----------------+ ++ | 28 Bytes Header | ++ +-----------------+ ++ | Text segment | ++ +-----------------+ ++ | Data segment | ++ +-----------------+ ++ | BSS | ++ +-----------------+ ++ | Symbol table | ++ +-----------------+ ++ | TPA relocation | ++ +-----------------+ ++ ++ The 28 byte exec header used to look like this: ++ ++ struct old_exec_header ++ { ++ bfd_byte a_magic[2]; ++ bfd_byte a_text[4]; ++ bfd_byte a_data[4]; ++ bfd_byte a_bss[4]; ++ bfd_byte a_syms[4]; ++ bfd_byte a_resvd[4]; ++ bfd_byte a_abs[2]; ++ }; ++ ++ The first two bytes (A_MAGIC) contained an assembler branch ++ instruction to the beginning of the text segment. Because the ++ exec header had a fixed size and the text entry point was constant ++ this assembler instruction also had a constant value (0x601a). ++ In fact the operating system never really executed the branch ++ instruction but used this value (0x601a) as a magic value. ++ ++ TEXT, DATA and BSS were as one would expect them. The symbol ++ table wasn't. Several different formats were in use, none of them ++ very efficient, none of them powerful enough to support source ++ level debugging. I've changed that and the GNU symbol table will ++ now be used instead (unless the --traditional-format option was ++ given to the linker). ++ ++ If the last member A_ABS of the exec header is zero the program ++ image contains an additional table with relocation information ++ at the end of the image. The kernel can load program images at ++ virtually any address in the address space. In fact it will load ++ it at the start of the biggest block of free memory. This block ++ is then called the Transient Program Area TPA and the image has ++ to be relocated against the TPA at runtime. The relocation info ++ itself is in a simply way compressed: It starts with a four-byte ++ value, the first address within the image to be relocated. Now ++ following are one-byte offsets to the last address. The special ++ value of 1 (which is impossible as an offset) signifies that 254 ++ has to be added to the next offset. The table is finished with ++ a zero-byte. ++ ++ I now simply extended the header from its old 28 bytes to 256 ++ bytes. The first 28 bytes give home to a standard Atari header, ++ the rest is for extensions. The extension header starts with ++ a ``real'' assembler instruction, a far jump to the text entry ++ point. The extension header gives home to a standard a.out ++ exec header (currently NMAGIC) plus some extra ++ more or less useful fields plus space to future extensions. ++ For the OS the extension header will already belong to the text ++ segment, for BFD backends the text segment is 228 (or 0xe4) ++ bytes smaller than for the OS. This explains for example the ++ funny TEXT_START_ADDR 0xe4. ++ ++ The TARGET_PAGE_SIZE is 2 which is only fake. There is currently ++ no such thing as memory paging on the Atari (and this is why ++ ZMAGICs are disabled for now to allow for future enhancements). ++ ++ If you think that this whole file looks quite like a big hack ++ you're probably right. But the results (mainly the output of ++ the linker) seem to work and they allow to use up-to-date ++ binutils on the Atari until a better executable format (maybe ++ ELF) has been established for this machine. */ ++ ++#include "sysdep.h" ++#include "bfd.h" ++ ++#define N_HEADER_IN_TEXT(x) 0 ++#define BYTES_IN_WORD 4 ++#define ENTRY_CAN_BE_ZERO ++#define N_SHARED_LIB(x) 0 ++#define TEXT_START_ADDR 0xe4 ++#define TARGET_PAGE_SIZE 2 ++#define TARGET_IS_BIG_ENDIAN_P ++#define DEFAULT_ARCH bfd_arch_m68k ++#define N_TXTADDR(x) TEXT_START_ADDR ++ ++/* Do not "beautify" the CONCAT* macro args. Traditional C will not ++ remove whitespace added here, and thus will fail to concatenate ++ the tokens. */ ++#define MY(OP) CONCAT2 (m68kmint_prg_,OP) ++#define TARGETNAME "a.out-mintprg" ++#define NAME(x,y) CONCAT3 (mintprg,_32_,y) ++ ++/* We have to do quite a lot of magic to make the Atari format ++ for GEMDOS executables fit into the standard a.out format. ++ We start with the original header. */ ++#define external_exec mint_external_exec ++struct mint_external_exec ++{ ++ bfd_byte g_branch[2]; /* 0x601a. */ ++ bfd_byte g_text[4]; /* Length of text section. */ ++ bfd_byte g_data[4]; /* Length of data section. */ ++ bfd_byte g_bss[4]; /* Length of bss section. */ ++ bfd_byte g_syms[4]; /* Length of symbol table. */ ++ bfd_byte g_extmagic[4]; /* Always 0x4d694e54 ++ (in ASCII: ``MiNT''). */ ++ bfd_byte g_flags[4]; /* Atari special flags. */ ++ bfd_byte g_abs[2]; /* Non-zero if absolute (no relocation ++ info. */ ++ ++ /* We extend this header now to provide the information that the ++ binutils want to see. Everything following will actually be part ++ of the text segment (from MiNT's point of view). As a ++ consequence the text section has 228 bytes of redundancy. ++ ++ The following eight bytes should be treated as opaque. ++ If the word ``opaque'' always attracts your curiosity in ++ typedefs and structs, here's the explanation: These eight bytes ++ are really two assembler instructions. The first one moves ++ the contents of e_entry into register d0, the second one ++ jumps (pc-relative) to the entry point. See swap_exec_header_out ++ for details. */ ++ bfd_byte g_jump_entry[8]; ++ ++ /* Now following a standard a.out header. Note that the values ++ may differ from the one given on top. The traditional header ++ contains the values that the OS wants to see, the values below ++ are the values that make the binutils work. */ ++ bfd_byte e_info[4]; /* Magic number and stuff. */ ++ bfd_byte e_text[4]; /* Length of text section in bytes. */ ++ bfd_byte e_data[4]; /* Length of data section. */ ++ bfd_byte e_bss[4]; /* Length of standard symbol ++ table. */ ++ bfd_byte e_syms[4]; /* Length of symbol table. */ ++ bfd_byte e_entry[4]; /* Start address. */ ++ bfd_byte e_trsize[4]; /* Length of text relocation ++ info. */ ++ bfd_byte e_drsize[4]; /* Length of data relocation ++ info. */ ++ ++ bfd_byte g_tparel_pos[4]; /* File position of TPA relative ++ relocation info. */ ++ bfd_byte g_tparel_size[4]; /* Length of TPA relative relocation ++ info. */ ++ ++ /* This is for extensions. */ ++ bfd_byte g_stkpos[4]; /* If stacksize is hardcoded into ++ the executable you will find it ++ at file offset g_stkpos. If ++ not this is NULL. */ ++ ++ bfd_byte g_symbol_format[4]; /* Format of the symbol table. See ++ definitions for _MINT_SYMBOL_FORMAT* ++ above. */ ++ ++ /* Pad with zeros. */ ++ bfd_byte g_pad0[172]; ++}; ++#define EXEC_BYTES_SIZE 256 ++#define GEMDOS_HEADER_SIZE 28 ++ ++/* The following defines are required by aoutx.h. ++ They are not automatically defined in aout/aout64.h ++ if external_exec is defined. */ ++ ++#define OMAGIC 0407 /* Object file or impure executable. */ ++#define NMAGIC 0410 /* Code indicating pure executable. */ ++#define ZMAGIC 0413 /* Code indicating demand-paged executable. */ ++#define BMAGIC 0415 /* Used by a b.out object. */ ++#define QMAGIC 0314 /* Like ZMAGIC but with N_HEADER_IN_TEXT true. */ ++ ++/* Files using the following magic flags will not be loaded. */ ++#define N_BADMAG(x) (N_MAGIC(x) != NMAGIC) ++ ++/* For DRI symbol table format. */ ++struct dri_symbol ++{ ++ bfd_byte a_name[8]; /* Symbol name */ ++ bfd_byte a_type[2]; /* Type flag, i.e. A_TEXT etc; see below. */ ++ bfd_byte a_value[4]; /* value of this symbol (or sdb offset). */ ++}; ++#define DRI_SYMBOL_SIZE 14 ++ ++/* Simple values for a_type. */ ++#define A_UNDF 0 ++#define A_BSS 0x0100 ++#define A_TEXT 0x0200 ++#define A_DATA 0x0400 ++#define A_EXT 0x0800 /* External. */ ++#define A_EQREG 0x1000 /* Equated register. */ ++#define A_GLOBL 0x2000 /* Global. */ ++#define A_EQU 0x4000 /* Equated. */ ++#define A_DEF 0x8000 /* Defined. */ ++#define A_LNAM 0x0048 /* GST compatible long name. */ ++ /* File symbols ala aln. */ ++#define A_TFILE 0x0280 /* Text file corresponding to object module. */ ++#define A_TFARC 0x02C0 /* Text file archive. Unfortunately this ++ conflicts with the bits in A_LNAM. */ ++ ++/* The following include contains the definitions for internal a.out structures ++ as well as the prototypes for the NAME(...) functions defined in aoutx.h. */ ++ ++#include "libaout.h" ++ ++/* The following function is similar to _bfd_final_link_relocate, except it ++ adds the reloc structure as an additional parameter. ++ It will be used int aoutx.h. */ ++ ++static bfd_reloc_status_type ++m68kmint_prg_final_link_relocate_rel (reloc_howto_type *howto, ++ bfd *input_bfd, ++ asection *input_section, ++ bfd_byte *contents, ++ bfd_vma address, ++ bfd_vma value, ++ bfd_vma addend, ++ struct reloc_std_external *rel); ++ ++#define MY_final_link_relocate_rel m68kmint_prg_final_link_relocate_rel ++ ++/* The following include contains the definitions for the NAME(...) functions. */ ++ ++#include "aoutx.h" ++ ++/* Data structure that holds some private information for us. */ ++struct mint_internal_info ++{ ++ struct bfd_link_info *linkinfo; /* Remembered from final_link. */ ++ bfd_boolean traditional_format; /* Saved from link info. */ ++ int symbol_format; /* Format of the symbol table. */ ++ void *tparel; /* Data for TPA relative relocation ++ information. */ ++ file_ptr tparel_pos; /* File position of TPA relative ++ relocation information. */ ++ bfd_size_type tparel_size; /* Size of TPA relative relocation ++ information. */ ++ bfd_size_type dri_symtab_size; /* Size of traditional symbol table. */ ++ ++#define MINT_RELOC_CHUNKSIZE 0x1000 ++ bfd_vma *relocs; /* Array of address relocations. */ ++ unsigned long relocs_used; /* Number of relocation entries ++ already used up. */ ++ unsigned long relocs_allocated; /* Number of relocation entries ++ allocated. */ ++ ++ bfd_vma stkpos; /* File offset to value of _stksize. */ ++ ++ flagword prg_flags; /* Standard GEMDOS flags. */ ++ ++ bfd_boolean override_stack_size; /* TRUE if the executable stack size ++ must be overriden with stack_size. */ ++ bfd_signed_vma stack_size; ++ ++ bfd_boolean reloc_error; /* TRUE if an unhandled error during ++ relocation occured. */ ++}; ++ ++/* If --traditional-format was given to the linker an old-style DRI ++ symbol table is written into the executable. This is with respect ++ to many old debugging tools or disassemblers which expect this format. ++ Although created by the linker, these symbols will be ignored from ++ input files. */ ++#define _MINT_SYMBOL_FORMAT_GNU 0 ++#define _MINT_SYMBOL_FORMAT_DRI 1 ++ ++/* Declarations for the variables and functions ++ defined later in aout-target.h. */ ++ ++static const bfd_target * ++m68kmint_prg_callback (bfd *abfd); ++ ++static void ++MY_final_link_callback (bfd *abfd, ++ file_ptr *ptreloff, ++ file_ptr *pdreloff, ++ file_ptr *psymoff); ++ ++extern const bfd_target m68kmint_prg_vec; ++ ++/* Initialize a new BFD using our file format. */ ++ ++#define MY_mkobject m68kmint_prg_mkobject ++ ++static bfd_boolean ++m68kmint_prg_mkobject (bfd *abfd) ++{ ++ struct mint_internal_info *myinfo; ++ ++ if (!NAME (aout, mkobject (abfd))) ++ return FALSE; ++ ++ /* Allocate our private BFD data. */ ++ myinfo = bfd_zalloc (abfd, sizeof (*myinfo)); ++ if (myinfo == NULL) ++ return FALSE; ++ obj_aout_ext (abfd) = myinfo; ++ ++ return TRUE; ++} ++ ++/* Finish up the reading of an a.out file header. */ ++ ++#define MY_object_p m68kmint_prg_object_p ++ ++static const bfd_target * ++m68kmint_prg_object_p (bfd *abfd) ++{ ++ struct external_exec exec_bytes; /* Raw exec header from file. */ ++ struct internal_exec exec; /* Cleaned-up exec header. */ ++ const bfd_target *target; ++ bfd_size_type amt = EXEC_BYTES_SIZE; ++ struct mint_internal_info *myinfo; ++ ++ /* Read the exec bytesd from the file. */ ++ if (bfd_bread (&exec_bytes, amt, abfd) != amt) ++ { ++ if (bfd_get_error () != bfd_error_system_call) ++ bfd_set_error (bfd_error_wrong_format); ++ return NULL; ++ } ++ ++ /* Instead of byte-swapping we compare bytes. */ ++ if (exec_bytes.g_branch[0] != 0x60 ++ || exec_bytes.g_branch[1] != 0x1a ++ || exec_bytes.g_extmagic[0] != 'M' ++ || exec_bytes.g_extmagic[1] != 'i' ++ || exec_bytes.g_extmagic[2] != 'N' ++ || exec_bytes.g_extmagic[3] != 'T') ++ { ++ bfd_set_error (bfd_error_wrong_format); ++ return NULL; ++ } ++ ++ /* Swap the standard a.out fields. */ ++ NAME (aout, swap_exec_header_in) (abfd, &exec_bytes, &exec); ++ ++ /* Check a.out magic value. */ ++ if (N_BADMAG (exec)) ++ { ++ bfd_set_error (bfd_error_wrong_format); ++ return NULL; ++ } ++ ++ /* Initialize this BFD with the exec values. */ ++ target = NAME (aout, some_aout_object_p) (abfd, &exec, m68kmint_prg_callback); ++ ++ /* Allocate our private BFD data. */ ++ myinfo = bfd_zalloc (abfd, sizeof (*myinfo)); ++ if (myinfo == NULL) ++ return NULL; ++ obj_aout_ext (abfd) = myinfo; ++ ++ /* Now get the missing information. */ ++ myinfo->prg_flags = bfd_h_get_32 (abfd, exec_bytes.g_flags); ++ myinfo->stkpos = bfd_h_get_32 (abfd, exec_bytes.g_stkpos); ++ myinfo->symbol_format = bfd_h_get_32 (abfd, exec_bytes.g_symbol_format); ++ ++ /* TPA relocation information. */ ++ myinfo->tparel_pos = bfd_h_get_32 (abfd, exec_bytes.g_tparel_pos); ++ myinfo->tparel_size = bfd_h_get_32 (abfd, exec_bytes.g_tparel_size); ++ ++ /* FIXME: Currently we always read the TPA relative relocation ++ information. This is suboptimal because often times there ++ is no need for it. Read it only if need be! Maybe this should ++ also depend on abfd->cacheable? */ ++ if (myinfo->tparel_size == 0) ++ myinfo->tparel = bfd_zalloc (abfd, 4); ++ else ++ myinfo->tparel = bfd_alloc (abfd, myinfo->tparel_size); ++ ++ if (myinfo->tparel == NULL) ++ return NULL; ++ ++ if (myinfo->tparel_size == 0) ++ { ++ myinfo->tparel_size = 4; ++ } ++ else ++ { ++ /* Read the information from the bfd. */ ++ if (bfd_seek (abfd, myinfo->tparel_pos, SEEK_SET) != 0 ++ || (bfd_bread (myinfo->tparel, myinfo->tparel_size, abfd) ++ != myinfo->tparel_size)) ++ return NULL; ++ } ++ ++ return target; ++} ++ ++/* Free all information we have cached for this BFD. We can always ++ read it again later if we need it. */ ++ ++#define MY_bfd_free_cached_info m68kmint_prg_bfd_free_cached_info ++ ++static bfd_boolean ++m68kmint_prg_bfd_free_cached_info (bfd *abfd) ++{ ++ struct mint_internal_info *myinfo = obj_aout_ext (abfd); ++ ++ if (myinfo != NULL && myinfo->relocs != NULL) ++ { ++ free (myinfo->relocs); ++ myinfo->relocs = NULL; ++ } ++ ++ /* myinfo itself has been allocated by bfd_zalloc() ++ so will be automatically freed along with the BFD. ++ Same for myinfo->tparel. */ ++ ++ return NAME (aout, bfd_free_cached_info) (abfd); ++} ++ ++/* Write a DRI symbol with TYPE and VALUE. If the NAME of the ++ symbol exceeds 8 characters write a long symbol. If it ++ exceeds 22 characters truncate the name. */ ++ ++static int ++write_dri_symbol (bfd *abfd, const char *name, int type, bfd_vma value) ++{ ++ int written_bytes = 0; ++ struct dri_symbol sym; ++ int is_long_name = strlen (name) > sizeof (sym.a_name); ++ ++ if (is_long_name) ++ type |= A_LNAM; ++ ++ strncpy ((char*)sym.a_name, name, sizeof (sym.a_name)); ++ bfd_put_16 (abfd, type, sym.a_type); ++ bfd_put_32 (abfd, value, sym.a_value); ++ ++ if (bfd_bwrite (&sym, DRI_SYMBOL_SIZE, abfd) != DRI_SYMBOL_SIZE) ++ return -1; ++ written_bytes += DRI_SYMBOL_SIZE; ++ ++ if (is_long_name) ++ { ++ char more_name[DRI_SYMBOL_SIZE]; ++ ++ strncpy (more_name, name + sizeof (sym.a_name), DRI_SYMBOL_SIZE); ++ ++ if (bfd_bwrite (more_name, DRI_SYMBOL_SIZE, abfd) != DRI_SYMBOL_SIZE) ++ return -1; ++ written_bytes += DRI_SYMBOL_SIZE; ++ } ++ ++ return written_bytes; ++} ++ ++/* Emit a traditional DRI symbol table while linking. ++ Most of this code comes from aout_link_write_symbols() in aoutx.h. */ ++ ++static bfd_boolean ++link_write_traditional_syms (bfd *abfd, struct bfd_link_info *info) ++{ ++ bfd *input_bfd; ++ enum bfd_link_strip strip = info->strip; ++ enum bfd_link_discard discard = info->discard; ++ struct mint_internal_info *myinfo = obj_aout_ext (abfd); ++ bfd *last_archive = NULL; ++ ++ /* Position file pointer. */ ++ if (bfd_seek (abfd, obj_sym_filepos (abfd), SEEK_SET) != 0) ++ return FALSE; ++ ++ myinfo->dri_symtab_size = 0; ++ ++ for (input_bfd = info->input_bfds; input_bfd != NULL; input_bfd = input_bfd->link_next) ++ { ++ bfd_size_type sym_count = obj_aout_external_sym_count (input_bfd); ++ char *strings = obj_aout_external_strings (input_bfd); ++ struct external_nlist *sym = obj_aout_external_syms (input_bfd); ++ struct external_nlist *sym_end = sym + sym_count; ++ struct aout_link_hash_entry **sym_hash = obj_aout_sym_hashes (input_bfd); ++ bfd_boolean pass = FALSE; ++ bfd_boolean skip = FALSE; ++ bfd_boolean skip_next = FALSE; ++ int written_bytes; ++ int a_type; ++ bfd_boolean write_archive_name = FALSE; ++ bfd_vma val = 0; ++ ++ /* First write out a symbol for the archive if we do not ++ strip these symbols and if it differs from the last ++ one. */ ++ if (input_bfd->my_archive != last_archive ++ && input_bfd->my_archive != NULL) ++ { ++ write_archive_name = TRUE; ++ last_archive = input_bfd->my_archive; ++ } ++ ++ if (write_archive_name ++ && strip != strip_all ++ && (strip != strip_some ++ || bfd_hash_lookup (info->keep_hash, ++ input_bfd->my_archive->filename, ++ FALSE, FALSE) != NULL) ++ && discard != discard_all) ++ { ++ val = bfd_get_section_vma (abfd, ++ obj_textsec (input_bfd)->output_section) ++ + obj_textsec (input_bfd)->output_offset; ++ ++ written_bytes = write_dri_symbol (abfd, ++ input_bfd->my_archive->filename, ++ A_TFILE, val); ++ ++ if (written_bytes < 0) ++ return FALSE; ++ else ++ myinfo->dri_symtab_size += written_bytes; ++ } ++ ++ /* Now write out a symbol for the object file if we do not ++ strip these symbols. */ ++ if (strip != strip_all ++ && (strip != strip_some ++ || bfd_hash_lookup (info->keep_hash, input_bfd->filename, ++ FALSE, FALSE) != NULL) ++ && discard != discard_all) ++ { ++ val = bfd_get_section_vma (abfd, ++ obj_textsec (input_bfd)->output_section) ++ + obj_textsec (input_bfd)->output_offset; ++ ++ written_bytes = write_dri_symbol (abfd, input_bfd->filename, ++ A_TFILE, val); ++ if (written_bytes < 0) ++ return FALSE; ++ else ++ myinfo->dri_symtab_size += written_bytes; ++ } ++ ++ /* Now we have a problem. All symbols that we see have already ++ been marked written (because we write them a second time ++ here. If we would do it the clean way we would have ++ to traverse the entire symbol map and reset the written ++ flag. We hack here instead... */ ++#define mark_written(h) (* (int *) &h->written = (int) TRUE + 1) ++#define is_written(h) ((int) h->written == (int) TRUE + 1) ++ for (; sym < sym_end; sym++, sym_hash++) ++ { ++ const char *name; ++ int type; ++ struct aout_link_hash_entry *h; ++ asection *symsec; ++ val = 0; ++ ++ type = H_GET_8 (input_bfd, sym->e_type); ++ name = strings + GET_WORD (input_bfd, sym->e_strx); ++ ++ h = NULL; ++ ++ if (pass) ++ { ++ /* Pass this symbol through. It is the target of an ++ indirect or warning symbol. */ ++ val = GET_WORD (input_bfd, sym->e_value); ++ pass = FALSE; ++ } ++ else if (skip_next) ++ { ++ /* Skip this symbol, which is the target of an indirect ++ symbol that we have changed to no longer be an indirect ++ symbol. */ ++ skip_next = FALSE; ++ continue; ++ } ++ else ++ { ++ struct aout_link_hash_entry *hresolve = *sym_hash; ++ ++ /* We have saved the hash table entry for this symbol, if ++ there is one. Note that we could just look it up again ++ in the hash table, provided we first check that it is an ++ external symbol. */ ++ h = *sym_hash; ++ ++ /* Use the name from the hash table, in case the symbol was ++ wrapped. */ ++ if (h != NULL ++ && h->root.type != bfd_link_hash_warning) ++ name = h->root.root.string; ++ ++ /* If this is an indirect or warning symbol, then change ++ hresolve to the base symbol. */ ++ hresolve = h; ++ if (h != (struct aout_link_hash_entry *) NULL ++ && (h->root.type == bfd_link_hash_indirect ++ || h->root.type == bfd_link_hash_warning)) ++ { ++ hresolve = (struct aout_link_hash_entry*) h->root.u.i.link; ++ while (hresolve->root.type == bfd_link_hash_indirect ++ || hresolve->root.type == bfd_link_hash_warning) ++ hresolve = ((struct aout_link_hash_entry*) ++ hresolve->root.u.i.link); ++ } ++ ++ /* If the symbol has already been written out skip it. */ ++ if (h != NULL ++ && is_written (h)) ++ { ++ if ((type & N_TYPE) == N_INDR ++ || type == N_WARNING) ++ skip_next = TRUE; ++ continue; ++ } ++ ++ /* See if we are stripping this symbol. */ ++ skip = FALSE; ++ ++ /* Skip all debugger symbols. No way to output them in ++ DRI format. This will also reduce a lot of headaches. */ ++ if ((type & N_STAB) != 0) ++ skip = TRUE; ++ ++ switch (strip) ++ { ++ case strip_none: ++ case strip_debugger: ++ break; ++ case strip_some: ++ if (bfd_hash_lookup (info->keep_hash, name, FALSE, FALSE) ++ == NULL) ++ skip = TRUE; ++ break; ++ case strip_all: ++ skip = TRUE; ++ break; ++ } ++ ++ if (skip) ++ { ++ if (h != NULL) ++ mark_written (h); ++ continue; ++ } ++ ++ /* Get the value of the symbol. */ ++ if ((type & N_TYPE) == N_TEXT ++ || type == N_WEAKT) ++ symsec = obj_textsec (input_bfd); ++ else if ((type & N_TYPE) == N_DATA ++ || type == N_WEAKD) ++ symsec = obj_datasec (input_bfd); ++ else if ((type & N_TYPE) == N_BSS ++ || type == N_WEAKB) ++ symsec = obj_bsssec (input_bfd); ++ else if ((type & N_TYPE) == N_ABS ++ || type == N_WEAKA) ++ symsec = bfd_abs_section_ptr; ++ else if (((type & N_TYPE) == N_INDR ++ && (hresolve == NULL ++ || (hresolve->root.type != bfd_link_hash_defined ++ && hresolve->root.type != bfd_link_hash_defweak ++ && hresolve->root.type != bfd_link_hash_common))) ++ || type == N_WARNING) ++ { ++ /* Pass the next symbol through unchanged. The ++ condition above for indirect symbols is so that if ++ the indirect symbol was defined, we output it with ++ the correct definition so the debugger will ++ understand it. */ ++ pass = TRUE; ++ val = GET_WORD (input_bfd, sym->e_value); ++ symsec = NULL; ++ } ++ else ++ { ++ /* If we get here with an indirect symbol, it means that ++ we are outputting it with a real definition. In such ++ a case we do not want to output the next symbol, ++ which is the target of the indirection. */ ++ if ((type & N_TYPE) == N_INDR) ++ skip_next = TRUE; ++ ++ symsec = NULL; ++ ++ /* We need to get the value from the hash table. We use ++ hresolve so that if we have defined an indirect ++ symbol we output the final definition. */ ++ if (h == NULL) ++ { ++ switch (type & N_TYPE) ++ { ++ case N_SETT: ++ symsec = obj_textsec (input_bfd); ++ break; ++ case N_SETD: ++ symsec = obj_datasec (input_bfd); ++ break; ++ case N_SETB: ++ symsec = obj_bsssec (input_bfd); ++ break; ++ case N_SETA: ++ symsec = bfd_abs_section_ptr; ++ break; ++ default: ++ val = 0; ++ break; ++ } ++ } ++ else if (hresolve->root.type == bfd_link_hash_defined ++ || hresolve->root.type == bfd_link_hash_defweak) ++ { ++ asection *input_section; ++ asection *output_section; ++ ++ /* This case usually means a common symbol which was ++ turned into a defined symbol. */ ++ input_section = hresolve->root.u.def.section; ++ output_section = input_section->output_section; ++ BFD_ASSERT (bfd_is_abs_section (output_section) ++ || output_section->owner == abfd); ++ ++ /* The following reference to the output section VMA ++ is commented out because DRI symbols are relative ++ to the beginning of the section. */ ++ val = (hresolve->root.u.def.value ++ /*+ bfd_get_section_vma (abfd, output_section)*/ ++ + input_section->output_offset); ++ ++ /* TEXT symbols values must be adjusted ++ by adding the size of the extended header. */ ++ if (output_section == obj_textsec (abfd)) ++ val += TEXT_START_ADDR; ++ ++ /* Get the correct type based on the section. If ++ this is a constructed set, force it to be ++ globally visible. */ ++ if (type == N_SETT ++ || type == N_SETD ++ || type == N_SETB ++ || type == N_SETA) ++ type |= N_EXT; ++ ++ type &=~ N_TYPE; ++ ++ if (output_section == obj_textsec (abfd)) ++ type |= N_TEXT; ++ else if (output_section == obj_datasec (abfd)) ++ type |= N_DATA; ++ else if (output_section == obj_bsssec (abfd)) ++ type |= N_BSS; ++ else ++ type |= N_ABS; ++ } ++ else if (hresolve->root.type == bfd_link_hash_common) ++ val = hresolve->root.u.c.size; ++ else if (hresolve->root.type == bfd_link_hash_undefweak) ++ { ++ val = 0; ++ type = N_UNDF; ++ } ++ else ++ val = 0; ++ } ++ if (symsec != NULL) ++ { ++ /* The following reference to the output section VMA ++ is commented out because DRI symbols are relative ++ to the beginning of the section. */ ++ val = (/*symsec->output_section->vma ++ +*/ symsec->output_offset ++ + (GET_WORD (input_bfd, sym->e_value) ++ - symsec->vma)); ++ ++ /* TEXT symbols values must be adjusted ++ by adding the size of the extended header. */ ++ if (symsec == obj_textsec (input_bfd)) ++ val += TEXT_START_ADDR; ++ } ++ ++ /* If this is a global symbol set the written flag, and if ++ it is a local symbol see if we should discard it. */ ++ if (h != NULL) ++ { ++ mark_written (h); ++ } ++ else if ((type & N_TYPE) != N_SETT ++ && (type & N_TYPE) != N_SETD ++ && (type & N_TYPE) != N_SETB ++ && (type & N_TYPE) != N_SETA) ++ { ++ switch (discard) ++ { ++ case discard_none: ++ case discard_sec_merge: ++ break; ++ case discard_l: ++ if (bfd_is_local_label_name (input_bfd, name)) ++ skip = TRUE; ++ break; ++ default: ++ case discard_all: ++ skip = TRUE; ++ break; ++ } ++ if (skip) ++ { ++ pass = FALSE; ++ continue; ++ } ++ } ++ } ++ ++ /* Now find the nearest type in DRI format. */ ++ switch (type) ++ { ++ case N_ABS: ++ case N_ABS | N_EXT: ++ case N_SETA: ++ case N_SETA | N_EXT: ++ case N_WEAKA: ++ a_type = A_EQU | A_DEF | A_GLOBL; ++ break; ++ case N_TEXT: ++ case N_TEXT | N_EXT: ++ case N_SETT: ++ case N_SETT | N_EXT: ++ case N_WEAKT: ++ a_type = A_TEXT | A_DEF | A_GLOBL; ++ break; ++ case N_DATA: ++ case N_DATA | N_EXT: ++ case N_SETD: ++ case N_SETD | N_EXT: ++ case N_WEAKD: ++ a_type = A_DATA | A_DEF | A_GLOBL; ++ break; ++ case N_BSS: ++ case N_BSS | N_EXT: ++ case N_SETB: ++ case N_SETB | N_EXT: ++ case N_WEAKB: ++ a_type = A_BSS | A_DEF | A_GLOBL; ++ break; ++ default: ++ continue; ++ } ++ ++ written_bytes = write_dri_symbol (abfd, name, a_type, val); ++ if (written_bytes < 0) ++ return FALSE; ++ ++ myinfo->dri_symtab_size += written_bytes; ++ } ++ } ++ ++ obj_aout_external_string_size (abfd) = 0; ++ return TRUE; ++} ++ ++/* This is used for qsort() to sort addresses ++ for the TPA relocation table. */ ++ ++static int ++vma_cmp (const void *v1, const void *v2) ++{ ++ return (int) ((*((bfd_vma *) v1)) - (*((bfd_vma *) v2))); ++} ++ ++/* Alloc and fill the TPA relocation table. */ ++ ++static bfd_boolean ++fill_tparel (bfd *abfd) ++{ ++ struct mint_internal_info *myinfo = obj_aout_ext (abfd); ++ unsigned long i; ++ bfd_size_type bytes; ++ unsigned char *ptr; ++ ++ /* Sort the relocation info. */ ++ if (myinfo->relocs != NULL) ++ qsort (myinfo->relocs, myinfo->relocs_used, sizeof (bfd_vma), ++ vma_cmp); ++ ++ /* Now calculate the number of bytes we need. The relocation info ++ is encoded as follows: The first entry is a 32-bit value ++ denoting the first offset to relocate. All following entries ++ are relative to the preceding one. For relative offsets of ++ more than 254 bytes a value of 1 is used. The OS will then ++ add 254 bytes to the current offset. The list is then terminated ++ with the byte 0. */ ++ bytes = 4; /* First entry is a long. */ ++ for (i = 1; i < myinfo->relocs_used; i++) ++ { ++ unsigned long diff = myinfo->relocs[i] - myinfo->relocs[i - 1]; ++ BFD_ASSERT(diff > 0); ++ bytes += (diff + 253) / 254; ++ } ++ /* Last entry is (bfd_byte) 0 if there are some relocations. */ ++ if (myinfo->relocs_used > 0) ++ bytes++; ++ ++ myinfo->tparel_size = bytes; ++ myinfo->tparel = bfd_alloc (abfd, bytes); ++ if (myinfo->tparel == NULL) ++ return FALSE; ++ ++ /* Now fill the array. */ ++ ptr = (bfd_byte*) myinfo->tparel; ++ if (myinfo->relocs != NULL) ++ bfd_put_32 (abfd, myinfo->relocs[0], ptr); ++ else ++ bfd_put_32 (abfd, 0, ptr); ++ ptr += 4; ++ ++ for (i = 1; i < myinfo->relocs_used; i++) ++ { ++ unsigned long diff = myinfo->relocs[i] - myinfo->relocs[i - 1]; ++ while (diff > 254) ++ { ++ *ptr++ = 1; ++ diff -= 254; ++ } ++ *ptr++ = (bfd_byte) diff; ++ } ++ ++ if (myinfo->relocs_used > 0) ++ *ptr = 0; ++ ++ return TRUE; ++} ++ ++/* Final link routine. We need to use a call back to get the correct ++ offsets in the output file. And we need to malloc some internal ++ buffers. */ ++ ++#define MY_bfd_final_link m68kmint_prg_bfd_final_link ++ ++static bfd_boolean ++m68kmint_prg_bfd_final_link (bfd *abfd, struct bfd_link_info *info) ++{ ++ struct mint_internal_info *myinfo = obj_aout_ext (abfd); ++ struct bfd_link_hash_table *hash = info->hash; ++ enum bfd_link_strip original_strip = info->strip; ++ ++ if (info->relocatable) ++ { ++ _bfd_error_handler ("%B: relocatable output is not supported by format %s", ++ abfd, bfd_get_target (abfd)); ++ bfd_set_error (bfd_error_invalid_operation); ++ return FALSE; ++ } ++ ++ myinfo->linkinfo = info; ++ ++ /* Make sure that for now we never write zmagics. */ ++ abfd->flags &= ~D_PAGED; ++ ++ /* Find the __stksize symbol. This symbol is used for a MiNT ++ special kludge. The libc defines this symbol in an object file ++ initialized to a default value to make sure it is defined in ++ every output file. The start-up code in crtinit() then simply ++ sets the stacksize accordingly. In your programs (if they need ++ an unusual stacksize) you can then simply code: ++ ++ long _stksize = 0x2000; ++ ++ This will create a program stack of 2k. Since MiNT cannot detect ++ a stack overflow this is the only way to prevent program crashes ++ caused by a stack that is too small. ++ ++ The ancient linker ignored this feature, the ancient strip ++ program paid heed to it. By default, strip never stripped this ++ special symbol from the binary. ++ ++ Another program called ``printstk'' and its colleague ``fixstk'' ++ could be used to either print the current value of the stacksize ++ or to modify it without recompiling and rebuilding. These ++ programs traversed the symbol table and then took the appropriate ++ measures if the symbol was found. ++ ++ Here we do a different approach. Since we already expanded the ++ standard executable header we now hardcode the address (as a file ++ offset) that the __stksize symbol points to into the header. We ++ can now let strip safely remove the entry from the symbol table ++ and we're not dependent on a special format of the symbol table. ++ Because the address is kept in the header we will always be able ++ to manipulate the stacksize value later. */ ++ if (hash != NULL) ++ { ++ struct aout_link_hash_entry *h = ++ aout_link_hash_lookup (aout_hash_table (info), "__stksize", ++ FALSE, FALSE, FALSE); ++ asection *sec; ++ ++ if (h != NULL) ++ { ++ switch (h->root.type) ++ { ++ case bfd_link_hash_defined: ++ case bfd_link_hash_defweak: ++ sec = h->root.u.def.section->output_section; ++ BFD_ASSERT (sec->owner == abfd); ++ ++ myinfo->stkpos = (h->root.u.def.value + sec->vma ++ + h->root.u.def.section->output_offset ++ + GEMDOS_HEADER_SIZE); ++ break; ++ default: /* Ignore other types. */ ++ break; ++ } ++ } ++ } ++ ++ if ((abfd->flags & BFD_TRADITIONAL_FORMAT) != 0) ++ { ++ myinfo->traditional_format = TRUE; ++ myinfo->symbol_format = _MINT_SYMBOL_FORMAT_DRI; ++ } ++ ++ /* Unconditionally unset the traditional flag. The only effect in ++ the a.out code is to disable string hashing (with respect to ++ SunOS gdx). This is not necessary for us. */ ++ ++ abfd->flags &= ~BFD_TRADITIONAL_FORMAT; ++ ++ /* Do not write GNU symbols in traditional format. */ ++ if (myinfo->traditional_format) ++ info->strip = strip_all; ++ ++ if (NAME(aout,final_link) (abfd, info, MY_final_link_callback) ++ != TRUE) ++ return FALSE; ++ ++ if (myinfo->reloc_error) ++ return FALSE; ++ ++ /* Restore the strip status for the traditional symbols. */ ++ info->strip = original_strip; ++ ++ if (myinfo->traditional_format ++ && link_write_traditional_syms (abfd, info) != TRUE) ++ return FALSE; ++ ++ if (fill_tparel (abfd) != TRUE) ++ return FALSE; ++ ++ return TRUE; ++} ++ ++/* Copy private BFD header information from the input BFD. */ ++ ++#define MY_bfd_copy_private_header_data m68kmint_prg_bfd_copy_private_header_data ++ ++static bfd_boolean ++m68kmint_prg_bfd_copy_private_header_data (bfd *ibfd, bfd *obfd) ++{ ++ (void)obfd; /* Unused. */ ++ ++ /* We can only copy BFD files using our own file format. */ ++ if (ibfd->xvec != &m68kmint_prg_vec) ++ { ++ _bfd_error_handler ("%B: cannot convert from format %s to format %s", ++ ibfd, bfd_get_target (ibfd), bfd_get_target (obfd)); ++ bfd_set_error (bfd_error_invalid_operation); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++/* Copy backend specific data from one object module to another. ++ This function is used by objcopy and strip. */ ++ ++#define MY_bfd_copy_private_bfd_data m68kmint_prg_bfd_copy_private_bfd_data ++ ++static bfd_boolean ++m68kmint_prg_bfd_copy_private_bfd_data (bfd *ibfd, bfd *obfd) ++{ ++ struct mint_internal_info *myinfo_in; ++ struct mint_internal_info *myinfo_out; ++ ++ /* obfd uses our file format, ibfd may be foreign. */ ++ if (ibfd->xvec != &m68kmint_prg_vec) ++ return TRUE; ++ ++ myinfo_in = obj_aout_ext (ibfd); ++ BFD_ASSERT (myinfo_in != NULL); ++ ++ myinfo_out = obj_aout_ext (obfd); ++ BFD_ASSERT (myinfo_out != NULL); ++ ++ /* Copy myinfo. */ ++ memcpy (myinfo_out, myinfo_in, sizeof (*myinfo_out)); ++ ++ /* Copy tparel. */ ++ myinfo_out->tparel = bfd_alloc (obfd, myinfo_out->tparel_size); ++ if (myinfo_out->tparel == NULL) ++ return FALSE; ++ memcpy (myinfo_out->tparel, myinfo_in->tparel, myinfo_out->tparel_size); ++ ++ /* Normalize the type of empty symbols. */ ++ if (bfd_get_symcount (obfd) == 0) ++ myinfo_out->symbol_format = _MINT_SYMBOL_FORMAT_GNU; ++ ++ return TRUE; /* _bfd_generic_bfd_copy_private_bfd_data (ibfd, obfd); */ ++} ++ ++/* Merge private BFD information from an input BFD to the output BFD when linking. */ ++ ++#define MY_bfd_merge_private_bfd_data m68kmint_prg_merge_private_bfd_data ++ ++static bfd_boolean ++m68kmint_prg_merge_private_bfd_data (bfd *ibfd, bfd *obfd) ++{ ++ (void)obfd; /* Unused. */ ++ ++ /* Our file format cannot be used as linker input. */ ++ if (ibfd->xvec == &m68kmint_prg_vec) ++ { ++ _bfd_error_handler ("%B: file format %s cannot be used as linker input", ++ ibfd, bfd_get_target (ibfd)); ++ bfd_set_error (bfd_error_invalid_operation); ++ return FALSE; ++ } ++ ++ return TRUE; /* _bfd_generic_bfd_merge_private_bfd_data (ibfd, obfd); */ ++} ++ ++/* Find out the symbol name. */ ++ ++static const char * ++find_symbol_name (reloc_howto_type *howto, bfd *input_bfd, ++ bfd_byte *location, struct reloc_std_external *rel) ++{ ++ struct external_nlist *syms = obj_aout_external_syms (input_bfd); ++ char *strings = obj_aout_external_strings (input_bfd); ++ struct aout_link_hash_entry **sym_hashes ++ = obj_aout_sym_hashes (input_bfd); ++ struct aout_link_hash_entry *h = NULL; ++ const char *name; ++ bfd_size_type r_index; ++ int r_extern; ++ ++ if (bfd_get_reloc_size (howto) != 4) ++ return "(not a symbol)"; ++ ++ /* The input bfd is always big-endian. There is no need to ++ call bfd_header_big_endian (input_bfd). */ ++ r_index = ((rel->r_index[0] << 16) ++ | (rel->r_index[1] << 8) ++ | (rel->r_index[2])); ++ r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG)); ++ ++ if (sym_hashes != NULL) ++ h = sym_hashes[r_index]; ++ ++ if (!r_extern) ++ { ++ bfd_size_type i; ++ bfd_vma wanted_value = bfd_get_32 (input_bfd, location); ++ ++ name = NULL; ++ for (i = 0; i < obj_aout_external_sym_count (input_bfd); i++) ++ { ++ bfd_vma this_value = bfd_get_32 (input_bfd, syms[i].e_value); ++ ++ if (this_value == wanted_value) ++ { ++ bfd_byte symtype = bfd_get_8 (input_bfd, syms[i].e_type); ++ ++ /* Skip debug symbols and the like. */ ++ if ((symtype & N_STAB) != 0) ++ continue; ++ ++ /* This is dirty but preferable to a plethoria of ++ single comparisons. */ ++ if (symtype <= (N_BSS | N_EXT) ++ || (symtype >= N_WEAKU && symtype <= N_COMM)) ++ { ++ name = strings + GET_WORD (input_bfd, syms[i].e_strx); ++ break; ++ } ++ } ++ } ++ ++ /* FIXME: If the relocation is against a section there is ++ probably a symbol for that section floating around somewhere ++ in the bfd jungle. */ ++ if (name == NULL) ++ { ++ switch ((r_index & N_TYPE) & ~N_EXT) ++ { ++ case N_TEXT: ++ name = "text section"; ++ break; ++ case N_DATA: ++ name = "data section"; ++ break; ++ case N_BSS: ++ name = "bss section"; ++ break; ++ case N_ABS: ++ name = "absolute section"; ++ break; ++ default: ++ name = "unknown section"; ++ break; ++ } ++ } ++ } ++ else if (h != NULL) ++ name = h->root.root.string; ++ else if (r_index >= obj_aout_external_sym_count (input_bfd)) ++ name = "(unknown symbol)"; /* Shouldn't happen. */ ++ else ++ name = strings + GET_WORD (input_bfd, syms[r_index].e_strx); ++ ++ return name; ++} ++ ++/* This relocation routine is used by some of the backend linkers. ++ They do not construct asymbol or arelent structures, so there is no ++ reason for them to use bfd_perform_relocation. Also, ++ bfd_perform_relocation is so hacked up it is easier to write a new ++ function than to try to deal with it. ++ ++ This routine does a final relocation. Whether it is useful for a ++ relocatable link depends upon how the object format defines ++ relocations. ++ ++ FIXME: This routine ignores any special_function in the HOWTO, ++ since the existing special_function values have been written for ++ bfd_perform_relocation. ++ ++ HOWTO is the reloc howto information. ++ INPUT_BFD is the BFD which the reloc applies to. ++ INPUT_SECTION is the section which the reloc applies to. ++ CONTENTS is the contents of the section. ++ ADDRESS is the address of the reloc within INPUT_SECTION. ++ VALUE is the value of the symbol the reloc refers to. ++ ADDEND is the addend of the reloc. */ ++ ++/* The additional parameter REL is specific to this backend. ++ This function is derived from _bfd_final_link_relocate() ++ found in reloc.c. It adds additional checking for dangerous ++ relocations in MiNT sharable text sections, then it records ++ the relocated offset in myinfo->relocs[] for further processing. */ ++ ++static bfd_reloc_status_type ++m68kmint_prg_final_link_relocate_rel (reloc_howto_type *howto, ++ bfd *input_bfd, ++ asection *input_section, ++ bfd_byte *contents, ++ bfd_vma address, ++ bfd_vma value, ++ bfd_vma addend, ++ struct reloc_std_external *rel) ++{ ++ bfd_vma relocation; ++ bfd *output_bfd = input_section->output_section->owner; ++ struct mint_internal_info *myinfo = obj_aout_ext (output_bfd); ++ bfd_reloc_status_type retval; ++ int r_index; ++ int r_extern; ++ bfd_boolean need_tpa_relocation; ++ ++ /* The input bfd is always big-endian. There is no need to ++ call bfd_header_big_endian (input_bfd). */ ++ r_index = ((rel->r_index[0] << 16) ++ | (rel->r_index[1] << 8) ++ | (rel->r_index[2])); ++ r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_BIG)); ++ ++#define _MINT_F_SHTEXT 0x800 ++ ++ /* Sanity check the address. */ ++ if (address > bfd_get_section_limit (input_bfd, input_section)) ++ return bfd_reloc_outofrange; ++ ++ /* This function assumes that we are dealing with a basic relocation ++ against a symbol. We want to compute the value of the symbol to ++ relocate to. This is just VALUE, the value of the symbol, plus ++ ADDEND, any addend associated with the reloc. */ ++ relocation = value + addend; ++ ++ /* Check for dangerous relocations in images with a sharable ++ text section. */ ++ if ((myinfo->prg_flags & _MINT_F_SHTEXT) != 0 ++ && bfd_get_reloc_size (howto) == 4) ++ { ++ bfd_boolean error_found = FALSE; ++ const char *name = NULL; ++ ++ if (input_section == obj_textsec (input_bfd)) ++ { ++ if (!r_extern) ++ { ++ /* This is a relocation against another section. Only ++ relocations against the text section are allowed. */ ++ if (r_index != N_TEXT && r_index != (N_TEXT | N_EXT)) ++ error_found = TRUE; ++ } ++ else if (relocation > (input_section->output_section->vma ++ + input_section->output_section->size)) ++ { ++ error_found = TRUE; ++ } ++ else if (relocation == (input_section->output_section->vma ++ + input_section->output_section->size)) ++ { ++ name = find_symbol_name (howto, input_bfd, ++ contents + address, ++ rel); ++ if (strcmp (name, "_etext") == 0) ++ error_found = FALSE; ++ } ++ } ++ ++ if (error_found) ++ { ++ const struct bfd_link_callbacks *callbacks ++ = myinfo->linkinfo->callbacks; ++ ++ myinfo->reloc_error = TRUE; ++ ++ if (callbacks->reloc_dangerous != NULL) ++ { ++ if (name == NULL) ++ name = find_symbol_name (howto, input_bfd, ++ contents + address, ++ rel); ++ ++ callbacks->reloc_dangerous (myinfo->linkinfo, name, ++ input_bfd, ++ input_section, address); ++ } ++ } ++ } ++ ++ /* If the relocation is PC relative, we want to set RELOCATION to ++ the distance between the symbol (currently in RELOCATION) and the ++ location we are relocating. Some targets (e.g., i386-aout) ++ arrange for the contents of the section to be the negative of the ++ offset of the location within the section; for such targets ++ pcrel_offset is FALSE. Other targets (e.g., m88kbcs or ELF) ++ simply leave the contents of the section as zero; for such ++ targets pcrel_offset is TRUE. If pcrel_offset is FALSE we do not ++ need to subtract out the offset of the location within the ++ section (which is just ADDRESS). */ ++ if (howto->pc_relative) ++ { ++ relocation -= (input_section->output_section->vma ++ + input_section->output_offset); ++ if (howto->pcrel_offset) ++ relocation -= address; ++ } ++ ++ retval = _bfd_relocate_contents (howto, input_bfd, relocation, ++ contents + address); ++ ++ /* The symbol has to be relocated again iff the length of the relocation ++ is 2 words and it is not pc relative. */ ++ need_tpa_relocation = FALSE; ++ if (!howto->pc_relative && bfd_get_reloc_size (howto) == 4) ++ { ++ if (r_extern) ++ { ++ struct aout_link_hash_entry **sym_hashes = obj_aout_sym_hashes (input_bfd); ++ struct aout_link_hash_entry *h = sym_hashes[r_index]; ++ asection *output_section = h->root.u.def.section->output_section; ++ ++ /* Do not relocate absolute symbols. */ ++ if (output_section == obj_textsec (output_bfd) ++ || output_section == obj_datasec (output_bfd) ++ || output_section == obj_bsssec (output_bfd)) ++ { ++ need_tpa_relocation = TRUE; ++ } ++ } ++ else ++ { ++ need_tpa_relocation = TRUE; ++ } ++ } ++ ++ /* Here we add the TPA relocation entries for the address references ++ located inside the input sections. Note that if some references ++ to addresses are generated using data statements in the linker ++ script, they will not be relocated here because they do not ++ belong to any input section. */ ++ if (need_tpa_relocation) ++ { ++ bfd_vma tpa_address = input_section->output_section->vma ++ + input_section->output_offset + address; ++ ++ if (!bfd_m68kmint_add_tpa_relocation_entry(output_bfd, tpa_address)) ++ return bfd_reloc_other; ++ } ++ ++ return retval; ++} ++ ++/* Write out the TPA relocation table. */ ++ ++static bfd_boolean ++write_tparel (bfd *abfd, struct internal_exec *execp) ++{ ++ struct mint_internal_info* myinfo = obj_aout_ext (abfd); ++ ++ if (myinfo->dri_symtab_size == 0) ++ myinfo->tparel_pos = N_STROFF (*execp) ++ + obj_aout_external_string_size (abfd); ++ else ++ myinfo->tparel_pos = N_SYMOFF (*execp) ++ + myinfo->dri_symtab_size; ++ ++ if (bfd_seek (abfd, myinfo->tparel_pos, SEEK_SET) != 0) ++ return FALSE; ++ ++ if (bfd_bwrite (myinfo->tparel, myinfo->tparel_size, abfd) ++ != myinfo->tparel_size) ++ return FALSE; ++ ++ return TRUE; ++} ++ ++/* Write the full exec header. ++ This function must be called last to ensure that we have all the ++ information needed to fill the MiNT-specific header fields. */ ++ ++static bfd_boolean ++write_exec_header (bfd *abfd, struct internal_exec *execp, struct external_exec *exec_bytes) ++{ ++ struct mint_internal_info *myinfo = obj_aout_ext (abfd); ++ bfd_size_type symtab_size; ++ ++ bfd_h_put_16 (abfd, 0x601a, exec_bytes->g_branch); ++ ++ /* The OS will load our extension header fields into the text segment. */ ++ bfd_h_put_32 (abfd, execp->a_text + (EXEC_BYTES_SIZE - GEMDOS_HEADER_SIZE), ++ exec_bytes->g_text); ++ bfd_h_put_32 (abfd, execp->a_data, exec_bytes->g_data); ++ bfd_h_put_32 (abfd, execp->a_bss, exec_bytes->g_bss); ++ ++ /* The OS' notion of the size of the symbol table is another than ++ the bfd library's. We have to fill in the size of the table ++ itself plus the size of the string table but only if we have not written ++ a traditional symbol table. If we have written a traditional symbol ++ table we know the size. */ ++ if (myinfo->dri_symtab_size != 0) ++ symtab_size = myinfo->dri_symtab_size; ++ else ++ symtab_size = myinfo->tparel_pos - N_SYMOFF (*execp); ++ ++ bfd_h_put_32 (abfd, symtab_size, exec_bytes->g_syms); ++ ++ bfd_h_put_32 (abfd, 0x4d694e54, exec_bytes->g_extmagic); ++ bfd_h_put_32 (abfd, myinfo->prg_flags, exec_bytes->g_flags); ++ bfd_h_put_16 (abfd, 0, exec_bytes->g_abs); ++ ++ /* Generate the jump instruction to the entry point. In m68k ++ assembler mnemnonics it looks more or less like this: ++ ++ move.l exec_bytes->e_entry(pc),d0 ++ jmp -6(pc,d0.l) ++ ++ Sorry for the wrong syntax. As a real assembler addict I ++ never actually use an assembler. I edit my binaries manually ++ with a hex editor, looks much cooler and it strengthens your ++ abstraction abilities. */ ++ ++ exec_bytes->g_jump_entry[0] = 0x20; ++ exec_bytes->g_jump_entry[1] = 0x3a; ++ exec_bytes->g_jump_entry[2] = 0x00; ++ exec_bytes->g_jump_entry[3] = 0x1a; ++ exec_bytes->g_jump_entry[4] = 0x4e; ++ exec_bytes->g_jump_entry[5] = 0xfb; ++ exec_bytes->g_jump_entry[6] = 0x08; ++ exec_bytes->g_jump_entry[7] = 0xfa; ++ ++ bfd_h_put_32 (abfd, myinfo->tparel_pos, exec_bytes->g_tparel_pos); ++ bfd_h_put_32 (abfd, myinfo->tparel_size, exec_bytes->g_tparel_size); ++ bfd_h_put_32 (abfd, myinfo->stkpos, exec_bytes->g_stkpos); ++ ++ /* If there are no symbols, pretend they are in GNU format. */ ++ if (symtab_size == 0) ++ myinfo->symbol_format = _MINT_SYMBOL_FORMAT_GNU; ++ ++ bfd_h_put_32 (abfd, myinfo->symbol_format, exec_bytes->g_symbol_format); ++ ++ memset (&exec_bytes->g_pad0, 0, sizeof (exec_bytes->g_pad0)); ++ ++ /* The standard stuff. */ ++ NAME(aout, swap_exec_header_out) (abfd, execp, exec_bytes); ++ if (myinfo->symbol_format != _MINT_SYMBOL_FORMAT_GNU) ++ PUT_WORD (abfd, 0, exec_bytes->e_syms); ++ ++ if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) ++ return FALSE; ++ ++ if (bfd_bwrite (exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, abfd) ++ != EXEC_BYTES_SIZE) ++ return FALSE; ++ ++ /* Override the stack size. */ ++ if (myinfo->override_stack_size && myinfo->stkpos) ++ { ++ bfd_byte big_endian_stack_size[4]; ++ ++ bfd_put_32 (abfd, myinfo->stack_size, &big_endian_stack_size); ++ ++ if (bfd_seek (abfd, (file_ptr) myinfo->stkpos, SEEK_SET) != 0) ++ return FALSE; ++ ++ if (bfd_bwrite (big_endian_stack_size, 4, abfd) != 4) ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++/* Write an object file. ++ Section contents have already been written. We write the ++ file header, symbols, and relocation. */ ++ ++#define MY_write_object_contents m68kmint_prg_write_object_contents ++ ++static bfd_boolean ++m68kmint_prg_write_object_contents (bfd *abfd) ++{ ++ struct external_exec exec_bytes; ++ struct internal_exec *execp = exec_hdr (abfd); ++ bfd_size_type text_size; ++ file_ptr text_end; ++ ++ BFD_ASSERT (obj_aout_ext (abfd) != NULL); ++ ++ obj_reloc_entry_size (abfd) = RELOC_STD_SIZE; ++ ++ /* Most of the following code come from the WRITE_HEADERS macro ++ found in libaout.h. */ ++ ++ if (adata(abfd).magic == undecided_magic) ++ NAME (aout, adjust_sizes_and_vmas) (abfd, & text_size, & text_end); ++ ++ execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE; ++ execp->a_entry = bfd_get_start_address (abfd); ++ ++ execp->a_trsize = ((obj_textsec (abfd)->reloc_count) * ++ obj_reloc_entry_size (abfd)); ++ execp->a_drsize = ((obj_datasec (abfd)->reloc_count) * ++ obj_reloc_entry_size (abfd)); ++ ++ /* Now write out reloc info, followed by syms and strings. */ ++ ++ if (bfd_get_outsymbols (abfd) != NULL ++ && bfd_get_symcount (abfd) != 0) ++ { ++ if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET) != 0) ++ return FALSE; ++ ++ if (! NAME (aout, write_syms) (abfd)) ++ return FALSE; ++ } ++ ++ if (bfd_seek (abfd, (file_ptr) (N_TRELOFF (*execp)), SEEK_SET) != 0) ++ return FALSE; ++ if (!NAME (aout, squirt_out_relocs) (abfd, obj_textsec (abfd))) ++ return FALSE; ++ ++ if (bfd_seek (abfd, (file_ptr) (N_DRELOFF (*execp)), SEEK_SET) != 0) ++ return FALSE; ++ if (!NAME (aout, squirt_out_relocs) (abfd, obj_datasec (abfd))) ++ return FALSE; ++ ++ if (write_tparel (abfd, execp) != TRUE) ++ return FALSE; ++ ++ if (write_exec_header (abfd, execp, &exec_bytes) != TRUE) ++ return FALSE; ++ ++ return TRUE; ++} ++ ++/* Print private BFD data. Used by objdump -p. */ ++ ++#define MY_bfd_print_private_bfd_data m68kmint_prg_print_private_bfd_data ++ ++static bfd_boolean ++m68kmint_prg_print_private_bfd_data (bfd *abfd, void *ptr) ++{ ++ FILE *file = (FILE *) ptr; ++ struct mint_internal_info *myinfo = obj_aout_ext (abfd); ++ const char* symbol_format; ++ long stksize = 0; ++ ++ fprintf (file, "\n"); ++ ++ fprintf (file, " GEMDOS flags: 0x%08lx\n", (unsigned long) myinfo->prg_flags); ++ fprintf (file, "Start address: 0x%08lx\n", bfd_get_start_address (abfd)); ++ ++ /* Stack size. */ ++ if (myinfo->stkpos != 0) ++ { ++ if (bfd_seek (abfd, myinfo->stkpos, SEEK_SET) != 0 ++ || (bfd_bread (&stksize, sizeof(long), abfd) != sizeof(long))) ++ return FALSE; ++ ++ stksize = bfd_get_signed_32 (abfd, &stksize); ++ } ++ fprintf (file, " Stack size: %ld\n", stksize); ++ ++ /* Symbol format. */ ++ switch (myinfo->symbol_format) ++ { ++ case _MINT_SYMBOL_FORMAT_GNU: symbol_format = "stabs"; break; ++ case _MINT_SYMBOL_FORMAT_DRI: symbol_format = "DRI"; break; ++ default: symbol_format = "?"; break; ++ } ++ fprintf (file, "Symbol format: %s\n", symbol_format); ++ ++ return TRUE; ++} ++ ++/* Special case for NAME (aout, get_section_contents) ++ It is not declared in libaout.h, neither implemented in aoutx.h. ++ Instead, a macro named aout_32_get_section_contents is defined in libaout.h. ++ So the default value of MY_get_section_contents provided by aout-target.h ++ is not correct, it has to be defined here with the right value. */ ++ ++#define MY_get_section_contents aout_32_get_section_contents ++ ++/* The following include will define m68kmint_prg_vec ++ and a default implementation for all the MY_ functions ++ not overriden here. */ ++ ++#include "aout-target.h" ++ ++/* Set the GEMDOS executable flags. ++ It is called by the linker emulation script. */ ++ ++bfd_boolean ++bfd_m68kmint_set_extended_flags (bfd *abfd, flagword prg_flags) ++{ ++ struct mint_internal_info *myinfo; ++ ++ BFD_ASSERT(abfd->xvec == &m68kmint_prg_vec); ++ myinfo = obj_aout_ext (abfd); ++ BFD_ASSERT(myinfo != NULL); ++ ++ myinfo->prg_flags = prg_flags; ++ ++ return TRUE; ++} ++ ++/* Override the stack size. ++ It is called by the linker emulation script. */ ++ ++bfd_boolean ++bfd_m68kmint_set_stack_size (bfd *abfd, bfd_signed_vma stack_size) ++{ ++ struct mint_internal_info *myinfo; ++ ++ BFD_ASSERT(abfd->xvec == &m68kmint_prg_vec); ++ myinfo = obj_aout_ext (abfd); ++ BFD_ASSERT(myinfo != NULL); ++ ++ myinfo->stack_size = stack_size; ++ myinfo->override_stack_size = TRUE; ++ ++ return TRUE; ++} ++ ++/* Add a TPA relocation entry. ++ It is called by BFD when linking the input sections, and by the ++ linker when it generates a reference to an address (in particular, ++ when building the constructors list). */ ++ ++bfd_boolean ++bfd_m68kmint_add_tpa_relocation_entry (bfd *abfd, bfd_vma address) ++{ ++ struct mint_internal_info *myinfo; ++ ++ BFD_ASSERT(abfd->xvec == &m68kmint_prg_vec); ++ myinfo = obj_aout_ext (abfd); ++ BFD_ASSERT(myinfo != NULL); ++ ++ /* Enlarge the buffer if necessary. */ ++ if (myinfo->relocs_used * sizeof (bfd_vma) >= myinfo->relocs_allocated) ++ { ++ bfd_vma *newbuf; ++ myinfo->relocs_allocated += MINT_RELOC_CHUNKSIZE; ++ newbuf = bfd_realloc (myinfo->relocs, myinfo->relocs_allocated); ++ if (newbuf == NULL) ++ return FALSE; ++ ++ myinfo->relocs = newbuf; ++ } ++ ++ /* The TPA relative relocation actually just adds the address of ++ the text segment (i. e. beginning of the executable in memory) ++ to the addresses at the specified locations. This allows an ++ executable to be loaded everywhere in the address space without ++ memory management. */ ++ myinfo->relocs[myinfo->relocs_used++] = address; ++ ++ return TRUE; ++} +diff -ur --new-file binutils-2.21.51.0.7/bfd/targets.c binutils-2.21.51.0.7-mint/bfd/targets.c +--- binutils-2.21.51.0.7/bfd/targets.c 2011-01-04 17:51:04.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/bfd/targets.c 2011-04-08 10:07:08.000000000 +0000 +@@ -770,6 +770,7 @@ + extern const bfd_target m68kcoff_vec; + extern const bfd_target m68kcoffun_vec; + extern const bfd_target m68klinux_vec; ++extern const bfd_target m68kmint_prg_vec; + extern const bfd_target m68knetbsd_vec; + extern const bfd_target m68ksysvcoff_vec; + extern const bfd_target m88kbcs_vec; +diff -ur --new-file binutils-2.21.51.0.7/binutils/configure binutils-2.21.51.0.7-mint/binutils/configure +--- binutils-2.21.51.0.7/binutils/configure 2011-03-07 18:05:31.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/binutils/configure 2011-04-08 10:07:09.000000000 +0000 +@@ -13041,7 +13041,7 @@ + + + case "${host}" in +-*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows*) ++*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows* | *-*-mint*) + + $as_echo "#define USE_BINARY_FOPEN 1" >>confdefs.h + ;; +diff -ur --new-file binutils-2.21.51.0.7/binutils/dlltool.c binutils-2.21.51.0.7-mint/binutils/dlltool.c +--- binutils-2.21.51.0.7/binutils/dlltool.c 2010-12-06 14:23:54.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/binutils/dlltool.c 2011-04-08 10:07:09.000000000 +0000 +@@ -4360,7 +4360,7 @@ + if (*cp == '-') + dash = cp; + if ( +-#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__) ++#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__) || defined(__MINT__) + *cp == ':' || *cp == '\\' || + #endif + *cp == '/') +diff -ur --new-file binutils-2.21.51.0.7/binutils/dllwrap.c binutils-2.21.51.0.7-mint/binutils/dllwrap.c +--- binutils-2.21.51.0.7/binutils/dllwrap.c 2010-08-11 21:51:51.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/binutils/dllwrap.c 2011-04-08 10:07:09.000000000 +0000 +@@ -263,7 +263,7 @@ + dash = cp; + + if ( +-#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__) ++#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__) || defined(__MINT__) + *cp == ':' || *cp == '\\' || + #endif + *cp == '/') +diff -ur --new-file binutils-2.21.51.0.7/binutils/readelf.c binutils-2.21.51.0.7-mint/binutils/readelf.c +--- binutils-2.21.51.0.7/binutils/readelf.c 2011-04-08 09:37:05.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/binutils/readelf.c 2011-04-08 10:07:10.000000000 +0000 +@@ -9903,7 +9903,11 @@ + #ifndef __MSVCRT__ + /* PR 11128: Use two separate invocations in order to work + around bugs in the Solaris 8 implementation of printf. */ ++#if GCC_VERSION < 3000 ++ printf (" [%6lx] ", (unsigned long) (data - start)); ++#else + printf (" [%6tx] ", data - start); ++#endif + printf ("%s\n", data); + #else + printf (" [%6Ix] %s\n", (size_t) (data - start), data); +diff -ur --new-file binutils-2.21.51.0.7/binutils/resrc.c binutils-2.21.51.0.7-mint/binutils/resrc.c +--- binutils-2.21.51.0.7/binutils/resrc.c 2010-12-06 14:23:55.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/binutils/resrc.c 2011-04-08 10:07:10.000000000 +0000 +@@ -396,7 +396,7 @@ + *space = 0; + + if ( +-#if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32) ++#if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32) || defined (__MINT__) + strchr (cmd, '\\') || + #endif + strchr (cmd, '/')) +@@ -514,7 +514,7 @@ + if (*cp == '-') + dash = cp; + if ( +-#if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32) ++#if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32) || defined (__MINT__) + *cp == ':' || *cp == '\\' || + #endif + *cp == '/') +diff -ur --new-file binutils-2.21.51.0.7/gas/config/te-mint.h binutils-2.21.51.0.7-mint/gas/config/te-mint.h +--- binutils-2.21.51.0.7/gas/config/te-mint.h 1970-01-01 00:00:00.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/gas/config/te-mint.h 2011-04-08 10:07:10.000000000 +0000 +@@ -0,0 +1,30 @@ ++/* Copyright 2008 Free Software Foundation, Inc. ++ ++ This file is part of GAS, the GNU Assembler. ++ ++ GAS 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 3, ++ or (at your option) any later version. ++ ++ GAS 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 GAS; see the file COPYING. If not, write to the Free ++ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA ++ 02110-1301, USA. */ ++ ++#define TE_MINT ++ ++#define LOCAL_LABELS_DOLLAR 1 ++#define LOCAL_LABELS_FB 1 ++ ++/* These define interfaces. */ ++#ifdef OBJ_HEADER ++#include OBJ_HEADER ++#else ++#include "obj-format.h" ++#endif +diff -ur --new-file binutils-2.21.51.0.7/gas/configure.tgt binutils-2.21.51.0.7-mint/gas/configure.tgt +--- binutils-2.21.51.0.7/gas/configure.tgt 2011-01-04 17:51:04.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/gas/configure.tgt 2011-04-08 10:07:10.000000000 +0000 +@@ -266,6 +266,7 @@ + m68k-*-linux-*) fmt=elf em=linux ;; + m68k-*-uclinux*) fmt=elf em=uclinux ;; + m68k-*-gnu*) fmt=elf ;; ++ m68k-*-mint*) fmt=aout em=mint bfd_gas=yes ;; + m68k-*-netbsdelf*) fmt=elf em=nbsd ;; + m68k-*-netbsd*) fmt=aout em=nbsd bfd_gas=yes ;; + m68k-*-openbsd*) fmt=aout em=nbsd bfd_gas=yes ;; +diff -ur --new-file binutils-2.21.51.0.7/gas/testsuite/gas/all/weakref1u.d binutils-2.21.51.0.7-mint/gas/testsuite/gas/all/weakref1u.d +--- binutils-2.21.51.0.7/gas/testsuite/gas/all/weakref1u.d 2009-11-11 16:52:57.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/gas/testsuite/gas/all/weakref1u.d 2011-04-08 10:07:10.000000000 +0000 +@@ -3,7 +3,7 @@ + #source: weakref1.s + # aout turns undefined into *ABS* symbols. + # see weakref1.d for comments on the other not-targets +-#not-target: *-*-*aout m68k-*-netbsd m68k-*-openbsd* ns32k-*-netbsd alpha*-*-osf* *-*-ecoff ++#not-target: *-*-*aout m68k-*-netbsd m68k-*-openbsd* m68k-*-mint* ns32k-*-netbsd alpha*-*-osf* *-*-ecoff + + # the rest of this file is generated with the following script: + # # script begin +diff -ur --new-file binutils-2.21.51.0.7/gas/testsuite/gas/m68k/all.exp binutils-2.21.51.0.7-mint/gas/testsuite/gas/m68k/all.exp +--- binutils-2.21.51.0.7/gas/testsuite/gas/m68k/all.exp 2011-03-07 18:05:32.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/gas/testsuite/gas/m68k/all.exp 2011-04-08 10:10:06.000000000 +0000 +@@ -71,7 +71,7 @@ + + gas_test_error "p11673.s" "-march=isab" "movel immediate with offset unsupported on isab" + +- if { [istarget *-*-*aout] || [istarget *-*-netbsd] || [istarget *-*-openbsd*] } then { ++ if { [istarget *-*-*aout] || [istarget *-*-netbsd] || [istarget *-*-openbsd*] || [istarget *-*-mint*] } then { + run_dump_test p3041 + run_dump_test p3041data + run_dump_test p3041pcrel +diff -ur --new-file binutils-2.21.51.0.7/gas/testsuite/gas/m68k/br-isaa.d binutils-2.21.51.0.7-mint/gas/testsuite/gas/m68k/br-isaa.d +--- binutils-2.21.51.0.7/gas/testsuite/gas/m68k/br-isaa.d 2009-11-11 16:52:56.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/gas/testsuite/gas/m68k/br-isaa.d 2011-04-08 10:07:10.000000000 +0000 +@@ -1,7 +1,7 @@ + #name: br-isaa.d + #objdump: -dr + #as: -march=isaa -pcrel +-#not-target: *-*-*aout m68k-*-netbsd m68k-*-openbsd* ++#not-target: *-*-*aout m68k-*-netbsd m68k-*-openbsd* m68k-*-mint* + + .*: file format .* + +diff -ur --new-file binutils-2.21.51.0.7/gas/testsuite/gas/m68k/br-isab.d binutils-2.21.51.0.7-mint/gas/testsuite/gas/m68k/br-isab.d +--- binutils-2.21.51.0.7/gas/testsuite/gas/m68k/br-isab.d 2009-11-11 16:52:56.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/gas/testsuite/gas/m68k/br-isab.d 2011-04-08 10:07:10.000000000 +0000 +@@ -1,7 +1,7 @@ + #name: br-isab.d + #objdump: -dr + #as: -march=isab -pcrel +-#not-target: *-*-*aout m68k-*-netbsd m68k-*-openbsd* ++#not-target: *-*-*aout m68k-*-netbsd m68k-*-openbsd* m68k-*-mint* + + .*: file format .* + +diff -ur --new-file binutils-2.21.51.0.7/gas/testsuite/gas/m68k/br-isac.d binutils-2.21.51.0.7-mint/gas/testsuite/gas/m68k/br-isac.d +--- binutils-2.21.51.0.7/gas/testsuite/gas/m68k/br-isac.d 2009-11-11 16:52:56.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/gas/testsuite/gas/m68k/br-isac.d 2011-04-08 10:07:10.000000000 +0000 +@@ -1,7 +1,7 @@ + #name: br-isac.d + #objdump: -dr + #as: -march=isac -pcrel +-#not-target: *-*-*aout m68k-*-netbsd m68k-*-openbsd* ++#not-target: *-*-*aout m68k-*-netbsd m68k-*-openbsd* m68k-*-mint* + + .*: file format .* + +diff -ur --new-file binutils-2.21.51.0.7/include/filenames.h binutils-2.21.51.0.7-mint/include/filenames.h +--- binutils-2.21.51.0.7/include/filenames.h 2011-03-07 18:05:32.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/include/filenames.h 2011-04-08 10:07:27.000000000 +0000 +@@ -30,7 +30,7 @@ + extern "C" { + #endif + +-#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined (__CYGWIN__) ++#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined (__CYGWIN__) || defined (__MINT__) + # ifndef HAVE_DOS_BASED_FILE_SYSTEM + # define HAVE_DOS_BASED_FILE_SYSTEM 1 + # endif +diff -ur --new-file binutils-2.21.51.0.7/include/getopt.h binutils-2.21.51.0.7-mint/include/getopt.h +--- binutils-2.21.51.0.7/include/getopt.h 2005-05-10 22:46:48.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/include/getopt.h 2011-04-08 10:07:27.000000000 +0000 +@@ -106,7 +106,7 @@ + to find the declaration so provide a fully prototyped one. If it + is 1, we found it so don't provide any declaration at all. */ + #if !HAVE_DECL_GETOPT +-#if defined (__GNU_LIBRARY__) || defined (HAVE_DECL_GETOPT) ++#if defined (__GNU_LIBRARY__) || defined (__MINT__) || defined (HAVE_DECL_GETOPT) + /* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in unistd.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +diff -ur --new-file binutils-2.21.51.0.7/ld/Makefile.am binutils-2.21.51.0.7-mint/ld/Makefile.am +--- binutils-2.21.51.0.7/ld/Makefile.am 2011-03-07 18:05:32.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/ld/Makefile.am 2011-04-08 10:07:27.000000000 +0000 +@@ -308,6 +308,7 @@ + em68kelf.c \ + em68kelfnbsd.c \ + em68klinux.c \ ++ em68kmint.c \ + em68knbsd.c \ + em68kpsos.c \ + em88kbcs.c \ +@@ -1319,6 +1320,10 @@ + em68klinux.c: $(srcdir)/emulparams/m68klinux.sh \ + $(srcdir)/emultempl/linux.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS} + ${GENSCRIPTS} m68klinux "$(tdir_m68klinux)" ++em68kmint.c: $(srcdir)/emulparams/m68kmint.sh \ ++ $(srcdir)/emultempl/generic.em $(srcdir)/emultempl/mint.em \ ++ $(srcdir)/scripttempl/m68kmint.sc ${GEN_DEPENDS} ++ ${GENSCRIPTS} m68kmint "$(tdir_m68kmint)" + em68knbsd.c: $(srcdir)/emulparams/m68knbsd.sh \ + $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS} + ${GENSCRIPTS} m68knbsd "$(tdir_m68knbsd)" +diff -ur --new-file binutils-2.21.51.0.7/ld/Makefile.in binutils-2.21.51.0.7-mint/ld/Makefile.in +--- binutils-2.21.51.0.7/ld/Makefile.in 2011-03-07 18:05:32.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/ld/Makefile.in 2011-04-08 10:07:27.000000000 +0000 +@@ -614,6 +614,7 @@ + em68kelf.c \ + em68kelfnbsd.c \ + em68klinux.c \ ++ em68kmint.c \ + em68knbsd.c \ + em68kpsos.c \ + em88kbcs.c \ +@@ -1229,6 +1230,7 @@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68kelf.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68kelfnbsd.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68klinux.Po@am__quote@ ++@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68kmint.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68knbsd.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em68kpsos.Po@am__quote@ + @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/em88kbcs.Po@am__quote@ +@@ -2762,6 +2764,10 @@ + em68klinux.c: $(srcdir)/emulparams/m68klinux.sh \ + $(srcdir)/emultempl/linux.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS} + ${GENSCRIPTS} m68klinux "$(tdir_m68klinux)" ++em68kmint.c: $(srcdir)/emulparams/m68kmint.sh \ ++ $(srcdir)/emultempl/generic.em $(srcdir)/emultempl/mint.em \ ++ $(srcdir)/scripttempl/m68kmint.sc ${GEN_DEPENDS} ++ ${GENSCRIPTS} m68kmint "$(tdir_m68kmint)" + em68knbsd.c: $(srcdir)/emulparams/m68knbsd.sh \ + $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS} + ${GENSCRIPTS} m68knbsd "$(tdir_m68knbsd)" +diff -ur --new-file binutils-2.21.51.0.7/ld/configure binutils-2.21.51.0.7-mint/ld/configure +--- binutils-2.21.51.0.7/ld/configure 2011-03-07 18:05:32.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/ld/configure 2011-04-08 10:07:28.000000000 +0000 +@@ -16557,7 +16557,7 @@ + + + case "${host}" in +-*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows*) ++*-*-msdos* | *-*-go32* | *-*-mingw32* | *-*-cygwin* | *-*-windows* | *-*-mint*) + + $as_echo "#define USE_BINARY_FOPEN 1" >>confdefs.h + ;; +diff -ur --new-file binutils-2.21.51.0.7/ld/configure.tgt binutils-2.21.51.0.7-mint/ld/configure.tgt +--- binutils-2.21.51.0.7/ld/configure.tgt 2011-01-04 17:51:04.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/ld/configure.tgt 2011-04-08 10:07:28.000000000 +0000 +@@ -344,6 +344,7 @@ + tdir_m68klinux=`echo ${targ_alias} | sed -e 's/linux/linuxaout/'` ;; + m68k-*-uclinux*) targ_emul=m68kelf ;; + m68*-*-gnu*) targ_emul=m68kelf ;; ++m68*-*-mint*) targ_emul=m68kmint ;; + m68*-*-netbsd*4k*) targ_emul=m68k4knbsd + targ_extra_emuls="m68knbsd m68kelfnbsd" ;; + m68*-*-netbsdelf*) targ_emul=m68kelfnbsd +diff -ur --new-file binutils-2.21.51.0.7/ld/emulparams/m68kmint.sh binutils-2.21.51.0.7-mint/ld/emulparams/m68kmint.sh +--- binutils-2.21.51.0.7/ld/emulparams/m68kmint.sh 1970-01-01 00:00:00.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/ld/emulparams/m68kmint.sh 2011-04-08 10:07:28.000000000 +0000 +@@ -0,0 +1,6 @@ ++SCRIPT_NAME=m68kmint ++OUTPUT_FORMAT="a.out-mintprg" ++RELOCATEABLE_OUTPUT_FORMAT="a.out-zero-big" ++TEXT_START_ADDR=0xe4 ++ARCH=m68k ++EXTRA_EM_FILE=mint +diff -ur --new-file binutils-2.21.51.0.7/ld/emultempl/mint.em binutils-2.21.51.0.7-mint/ld/emultempl/mint.em +--- binutils-2.21.51.0.7/ld/emultempl/mint.em 1970-01-01 00:00:00.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/ld/emultempl/mint.em 2011-04-08 10:07:28.000000000 +0000 +@@ -0,0 +1,330 @@ ++# This shell script emits a C file. -*- C -*- ++# Copyright 2006, 2007 Free Software Foundation, Inc. ++# ++# This file is part of the GNU Binutils. ++# ++# 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 3 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 generic.em ++# ++fragment <<EOF ++ ++#include "getopt.h" ++#include "ldgram.h" ++ ++/* Standard GEMDOS program flags. */ ++#define _MINT_F_FASTLOAD 0x01 /* Don't clear heap. */ ++#define _MINT_F_ALTLOAD 0x02 /* OK to load in alternate RAM. */ ++#define _MINT_F_ALTALLOC 0x04 /* OK to malloc from alt. RAM. */ ++#define _MINT_F_BESTFIT 0x08 /* Load with optimal heap size. */ ++/* The memory flags are mutually exclusive. */ ++#define _MINT_F_MEMPROTECTION 0xf0 /* Masks out protection bits. */ ++#define _MINT_F_MEMPRIVATE 0x00 /* Memory is private. */ ++#define _MINT_F_MEMGLOBAL 0x10 /* Read/write access to mem allowed. */ ++#define _MINT_F_MEMSUPER 0x20 /* Only supervisor access allowed. */ ++#define _MINT_F_MEMREADABLE 0x30 /* Any read access OK. */ ++#define _MINT_F_SHTEXT 0x800 /* Program's text may be shared */ ++ ++/* Option flags. */ ++static flagword prg_flags = (_MINT_F_FASTLOAD | _MINT_F_ALTLOAD ++ | _MINT_F_ALTALLOC | _MINT_F_MEMPRIVATE); ++ ++/* If override_stack_size is TRUE, then the executable stack size ++ * must be overriden with the value of stack_size. */ ++static bfd_boolean override_stack_size = FALSE; ++static bfd_signed_vma stack_size; ++ ++/* MiNT format extra command line options. */ ++ ++/* Used for setting flags in the MiNT header. */ ++#define OPTION_FASTLOAD (300) ++#define OPTION_NO_FASTLOAD (OPTION_FASTLOAD + 1) ++#define OPTION_FASTRAM (OPTION_NO_FASTLOAD + 1) ++#define OPTION_NO_FASTRAM (OPTION_FASTRAM + 1) ++#define OPTION_FASTALLOC (OPTION_NO_FASTRAM + 1) ++#define OPTION_NO_FASTALLOC (OPTION_FASTALLOC + 1) ++#define OPTION_BESTFIT (OPTION_NO_FASTALLOC + 1) ++#define OPTION_NO_BESTFIT (OPTION_BESTFIT + 1) ++#define OPTION_BASEREL (OPTION_NO_BESTFIT + 1) ++#define OPTION_NO_BASEREL (OPTION_BASEREL + 1) ++#define OPTION_MEM_PRIVATE (OPTION_NO_BASEREL + 1) ++#define OPTION_MEM_GLOBAL (OPTION_MEM_PRIVATE + 1) ++#define OPTION_MEM_SUPER (OPTION_MEM_GLOBAL + 1) ++#define OPTION_MEM_READONLY (OPTION_MEM_SUPER + 1) ++#define OPTION_PRG_FLAGS (OPTION_MEM_READONLY + 1) ++#define OPTION_STACK (OPTION_PRG_FLAGS + 1) ++ ++static void ++gld${EMULATION_NAME}_add_options ++ (int ns ATTRIBUTE_UNUSED, char **shortopts ATTRIBUTE_UNUSED, int nl, ++ struct option **longopts, int nrl ATTRIBUTE_UNUSED, ++ struct option **really_longopts ATTRIBUTE_UNUSED) ++{ ++ static const struct option xtra_long[] = { ++ {"mfastload", no_argument, NULL, OPTION_FASTLOAD}, ++ {"mno-fastload", no_argument, NULL, OPTION_NO_FASTLOAD}, ++ {"mfastram", no_argument, NULL, OPTION_FASTRAM}, ++ {"mno-fastram", no_argument, NULL, OPTION_NO_FASTRAM}, ++ {"maltram", no_argument, NULL, OPTION_FASTRAM}, ++ {"mno-altram", no_argument, NULL, OPTION_NO_FASTRAM}, ++ {"mfastalloc", no_argument, NULL, OPTION_FASTALLOC}, ++ {"mno-fastalloc", no_argument, NULL, OPTION_NO_FASTALLOC}, ++ {"maltalloc", no_argument, NULL, OPTION_FASTALLOC}, ++ {"mno-altalloc", no_argument, NULL, OPTION_NO_FASTALLOC}, ++ {"mbest-fit", no_argument, NULL, OPTION_BESTFIT}, ++ {"mno-best-fit", no_argument, NULL, OPTION_NO_BESTFIT}, ++ {"mbaserel", no_argument, NULL, OPTION_BASEREL}, ++ {"mno-baserel", no_argument, NULL, OPTION_NO_BASEREL}, ++ {"mshared-text", no_argument, NULL, OPTION_BASEREL}, ++ {"mno-shared-text", no_argument, NULL, OPTION_NO_BASEREL}, ++ {"msharable-text", no_argument, NULL, OPTION_BASEREL}, ++ {"mno-sharable-text", no_argument, NULL, OPTION_NO_BASEREL}, ++ /* Memory protection bits. */ ++ {"mprivate-memory", no_argument, NULL, OPTION_MEM_PRIVATE }, ++ {"mglobal-memory", no_argument, NULL, OPTION_MEM_GLOBAL}, ++ {"msuper-memory", no_argument, NULL, OPTION_MEM_SUPER}, ++ {"mreadable-memory", no_argument, NULL, OPTION_MEM_READONLY}, ++ {"mreadonly-memory", no_argument, NULL, OPTION_MEM_READONLY}, ++ {"mprg-flags", required_argument, NULL, OPTION_PRG_FLAGS}, ++ {"stack", required_argument, NULL, OPTION_STACK}, ++ {NULL, no_argument, NULL, 0} ++ }; ++ ++ *longopts = (struct option *) ++ xrealloc (*longopts, nl * sizeof (struct option) + sizeof (xtra_long)); ++ memcpy (*longopts + nl, &xtra_long, sizeof (xtra_long)); ++} ++ ++static bfd_boolean ++gld${EMULATION_NAME}_handle_option (int optc) ++{ ++ switch (optc) ++ { ++ default: ++ return FALSE; ++ ++ case OPTION_FASTLOAD: ++ prg_flags |= _MINT_F_FASTLOAD; ++ break; ++ ++ case OPTION_NO_FASTLOAD: ++ prg_flags &= ~_MINT_F_FASTLOAD; ++ break; ++ ++ case OPTION_FASTRAM: ++ prg_flags |= _MINT_F_ALTLOAD; ++ break; ++ ++ case OPTION_NO_FASTRAM: ++ prg_flags &= ~_MINT_F_ALTLOAD; ++ break; ++ ++ case OPTION_FASTALLOC: ++ prg_flags |= _MINT_F_ALTALLOC; ++ break; ++ ++ case OPTION_NO_FASTALLOC: ++ prg_flags &= ~_MINT_F_ALTALLOC; ++ break; ++ ++ case OPTION_BESTFIT: ++ prg_flags |= _MINT_F_BESTFIT; ++ break; ++ ++ case OPTION_NO_BESTFIT: ++ prg_flags &= ~_MINT_F_BESTFIT; ++ break; ++ ++ case OPTION_BASEREL: ++ prg_flags |= _MINT_F_SHTEXT; ++ break; ++ ++ case OPTION_NO_BASEREL: ++ prg_flags &= ~_MINT_F_SHTEXT; ++ break; ++ ++ case OPTION_MEM_PRIVATE: ++ prg_flags &= ~_MINT_F_MEMPROTECTION; ++ break; ++ ++ case OPTION_MEM_GLOBAL: ++ prg_flags &= ~_MINT_F_MEMPROTECTION; ++ prg_flags |= _MINT_F_MEMPRIVATE; ++ break; ++ ++ case OPTION_MEM_SUPER: ++ prg_flags &= ~_MINT_F_MEMPROTECTION; ++ prg_flags |= _MINT_F_MEMSUPER; ++ break; ++ ++ case OPTION_MEM_READONLY: ++ prg_flags &= ~_MINT_F_MEMPROTECTION; ++ prg_flags |= _MINT_F_MEMREADABLE; ++ break; ++ ++ case OPTION_PRG_FLAGS: ++ { ++ char* tail; ++ unsigned long flag_value = strtoul (optarg, &tail, 0); ++ ++ if (*tail != '\0') ++ einfo (_("%P: warning: ignoring invalid program flags %s\n"), optarg); ++ else ++ prg_flags = flag_value; ++ ++ break; ++ } ++ case OPTION_STACK: ++ { ++ char* tail; ++ long size = strtol (optarg, &tail, 0); ++ ++ if (*tail == 'K' || *tail == 'k') ++ { ++ size *= 1024; ++ ++tail; ++ } ++ else if (*tail == 'M' || *tail == 'm') ++ { ++ size *= 1024*1024; ++ ++tail; ++ } ++ ++ if (*tail != '\0') ++ einfo (_("%P: warning: ignoring invalid stack size %s\n"), optarg); ++ else ++ { ++ stack_size = (bfd_signed_vma) size; ++ override_stack_size = TRUE; ++ } ++ ++ break; ++ } ++ } ++ return TRUE; ++} ++ ++/* This callback is called when ld is invoked ++ with the --help and --target-help options. */ ++ ++static void ++gld_${EMULATION_NAME}_list_options (FILE *file) ++{ ++ fprintf (file, _(" --m[no-]fastload Enable/Disable not cleaning the heap on startup\n")); ++ fprintf (file, _(" --m[no-]altram, --m[no-]fastram\n")); ++ fprintf (file, _(" Enable/Disable loading into alternate RAM\n")); ++ fprintf (file, _(" --m[no-]altalloc, --m[no-]fastalloc\n")); ++ fprintf (file, _(" Enable/Disable malloc from alternate RAM\n")); ++ fprintf (file, _(" --m[no-]best-fit Enable/Disable loading with optimal heap size\n")); ++ fprintf (file, _(" --m[no-]sharable-text, --m[no-]shared-text, --m[no-]baserel\n")); ++ fprintf (file, _(" Enable/Disable sharing the text segment\n")); ++ fprintf (file, "\n"); ++ fprintf (file, _("The following memory options are mutually exclusive:\n")); ++ fprintf (file, _(" --mprivate-memory Process memory is not accessible\n")); ++ fprintf (file, _(" --mglobal-memory Process memory is readable and writable\n")); ++ fprintf (file, _(" --msuper-memory Process memory is accessible in supervisor mode\n")); ++ fprintf (file, _(" --mreadonly-memory, --mreadable-memory\n")); ++ fprintf (file, _(" Process memory is readable but not writable\n")); ++ fprintf (file, "\n"); ++ fprintf (file, _(" --mprg-flags <value> Set all the flags with an integer raw value\n")); ++ fprintf (file, _(" --stack <size> Override the stack size (suffix k or M allowed)\n")); ++} ++ ++/* This callback is called by lang_for_each_statement. It checks that the ++ output sections speficied in the linker script are compatible with the MiNT ++ executable format. */ ++ ++static void ++gld${EMULATION_NAME}_check_output_sections (lang_statement_union_type *s) ++{ ++ if (s->header.type == lang_output_section_statement_enum) ++ { ++ lang_output_section_statement_type *oss = &s->output_section_statement; ++ ++ if (strcmp(oss->name, ".text") == 0 && oss->bfd_section->vma != ${TEXT_START_ADDR}) ++ einfo (_("%F%P: the VMA of section %A must be 0x%V, but actual value is 0x%V\n"), ++ oss->bfd_section, ${TEXT_START_ADDR}, oss->bfd_section->vma); ++ else if (strcmp(oss->name, ".data") == 0 && oss->addr_tree != NULL) ++ einfo (_("%F%P: the VMA of section %A must not be specified\n"), ++ oss->bfd_section); ++ else if (strcmp(oss->name, ".bss") == 0 && oss->addr_tree != NULL) ++ einfo (_("%F%P: the VMA of section %A must not be specified\n"), ++ oss->bfd_section); ++ } ++} ++ ++/* This callback is called by lang_for_each_statement. It looks for the data ++ statements of type REL generated by the linker, and adds a TPA relocation ++ entry for them. This is used by the CONSTRUCTORS list. */ ++ ++static void ++gld${EMULATION_NAME}_add_tpa_relocs (lang_statement_union_type *s) ++{ ++ if (s->header.type == lang_data_statement_enum) ++ { ++ lang_data_statement_type *ds = &s->data_statement; ++ ++ if (ds->exp->type.node_code == REL) ++ { ++ if (ds->type == LONG) ++ { ++ bfd_vma tpa_address = ds->output_section->vma + ds->output_offset; ++ if (!bfd_m68kmint_add_tpa_relocation_entry(link_info.output_bfd, tpa_address)) ++ einfo (_("%F%P:%B: unable to add a relocation entry\n"), link_info.output_bfd); ++ } ++ else ++ { ++ einfo (_("%F%P:%B: invalid size for TPA relocation entry in section %A, offset 0x%V\n"), ++ link_info.output_bfd, ds->output_section, ds->output_offset); ++ } ++ } ++ } ++} ++ ++/* Final emulation specific call. */ ++ ++static void ++gld${EMULATION_NAME}_finish (void) ++{ ++ /* Do nothing if we are not generating a MiNT executable (ex: binary). */ ++ if (strcmp (bfd_get_target (link_info.output_bfd), "${OUTPUT_FORMAT}") != 0) ++ return; ++ ++ /* Check the output sections. */ ++ lang_for_each_statement (gld${EMULATION_NAME}_check_output_sections); ++ ++ /* Set the GEMDOS executable header flags. */ ++ if (!bfd_m68kmint_set_extended_flags (link_info.output_bfd, prg_flags)) ++ einfo (_("%F%P:%B: unable to set the header flags\n"), link_info.output_bfd); ++ ++ /* Override the stack size. */ ++ if (override_stack_size) ++ if (!bfd_m68kmint_set_stack_size (link_info.output_bfd, stack_size)) ++ einfo (_("%F%P:%B: unable to set the stack size\n"), link_info.output_bfd); ++ ++ /* Generate TPA relocation entries for the data statements. */ ++ lang_for_each_statement (gld${EMULATION_NAME}_add_tpa_relocs); ++} ++ ++EOF ++ ++# Put these extra routines in ld_${EMULATION_NAME}_emulation ++# ++LDEMUL_ADD_OPTIONS=gld${EMULATION_NAME}_add_options ++LDEMUL_HANDLE_OPTION=gld${EMULATION_NAME}_handle_option ++LDEMUL_LIST_OPTIONS=gld_${EMULATION_NAME}_list_options ++LDEMUL_FINISH=gld${EMULATION_NAME}_finish +diff -ur --new-file binutils-2.21.51.0.7/ld/scripttempl/m68kmint.sc binutils-2.21.51.0.7-mint/ld/scripttempl/m68kmint.sc +--- binutils-2.21.51.0.7/ld/scripttempl/m68kmint.sc 1970-01-01 00:00:00.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/ld/scripttempl/m68kmint.sc 2011-04-08 10:07:28.000000000 +0000 +@@ -0,0 +1,35 @@ ++cat <<EOF ++${RELOCATING+OUTPUT_FORMAT(${OUTPUT_FORMAT})} ++${RELOCATING-OUTPUT_FORMAT(${RELOCATEABLE_OUTPUT_FORMAT})} ++${RELOCATING+${LIB_SEARCH_DIRS}} ++SECTIONS ++{ ++ ${RELOCATING+/* The VMA of the .text section is ${TEXT_START_ADDR} instead of 0 ++ because the extended MiNT header is just before, ++ at the beginning of the TEXT segment. */} ++ .text ${RELOCATING+${TEXT_START_ADDR}}: ++ { ++ CREATE_OBJECT_SYMBOLS ++ *(.text) ++ ${CONSTRUCTING+CONSTRUCTORS} ++ ${RELOCATING+_etext = .;} ++ ${RELOCATING+__etext = .;} ++ } ++ ++ .data : ++ { ++ *(.data) ++ ${RELOCATING+_edata = .;} ++ ${RELOCATING+__edata = .;} ++ } ++ ++ .bss : ++ { ++ ${RELOCATING+__bss_start = .;} ++ *(.bss) ++ *(COMMON) ++ ${RELOCATING+_end = .;} ++ ${RELOCATING+__end = .;} ++ } ++} ++EOF +diff -ur --new-file binutils-2.21.51.0.7/libiberty/hex.c binutils-2.21.51.0.7-mint/libiberty/hex.c +--- binutils-2.21.51.0.7/libiberty/hex.c 2007-03-16 15:48:30.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/libiberty/hex.c 2011-04-08 10:07:28.000000000 +0000 +@@ -24,7 +24,7 @@ + #include "libiberty.h" + #include "safe-ctype.h" /* for HOST_CHARSET_ASCII */ + +-#if EOF != -1 ++#if !(EOF == -1) /* gcc 2.95.3 has bug in '!=' operator for negative constants */ + #error "hex.c requires EOF == -1" + #endif + +diff -ur --new-file binutils-2.21.51.0.7/libiberty/safe-ctype.c binutils-2.21.51.0.7-mint/libiberty/safe-ctype.c +--- binutils-2.21.51.0.7/libiberty/safe-ctype.c 2005-06-22 20:53:36.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/libiberty/safe-ctype.c 2011-04-08 10:07:28.000000000 +0000 +@@ -119,7 +119,7 @@ + #include <safe-ctype.h> + #include <stdio.h> /* for EOF */ + +-#if EOF != -1 ++#if !(EOF == -1) /* gcc 2.95.3 has bug in '!=' operator for negative constants */ + #error "<safe-ctype.h> requires EOF == -1" + #endif + +--- binutils-2.21.51.0.7/ld/lexsup.c 2011-04-08 15:39:47.000000000 +0000 ++++ binutils-2.21.51.0.7-mint/ld/lexsup.c 2011-04-08 15:39:25.000000000 +0000 +@@ -57,6 +57,9 @@ + #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) + #endif + ++/* Report plugin symbols. */ ++bfd_boolean report_plugin_symbols; ++ + static void set_default_dirlist (char *); + static void set_section_start (char *, char *); + static void set_segment_start (const char *, char *); +--- binutils-2.22/ld/plugin.c 2011-11-21 09:29:39.000000000 +0000 ++++ binutils-2.22-mint/ld/plugin.c 2011-12-07 21:24:05.000000000 +0000 +@@ -36,9 +36,6 @@ + #include <windows.h> + #endif + +-/* Report plugin symbols. */ +-bfd_boolean report_plugin_symbols; +- + /* The suffix to append to the name of the real (claimed) object file + when generating a dummy BFD to hold the IR symbols sent from the + plugin. For cosmetic use only; appears in maps, crefs etc. */ +--- binutils-2.22/libiberty/configure 2011-12-08 00:17:02.000000000 +0000 ++++ binutils-2.22-mint/libiberty/configure 2011-12-08 00:17:39.000000000 +0000 +@@ -4888,6 +4888,8 @@ + i[34567]86-*-* | x86_64-*-*) + PICFLAG=-fpic + ;; ++ *-*-mint*) ++ ;; + m68k-*-*) + PICFLAG=-fpic + ;; |