aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Henkel-Wallace <gumby@cygnus>1991-03-21 21:29:07 +0000
committerDavid Henkel-Wallace <gumby@cygnus>1991-03-21 21:29:07 +0000
commitc074abeebcefe3b62f46ff8a62f3d4058ed32780 (patch)
tree97a36afc00d9cc840b84d89e40ffbd13cd3ad7f7
parent2fa0b342a5cd580781d2b9348a87f33a92d363fa (diff)
downloadgdb-c074abeebcefe3b62f46ff8a62f3d4058ed32780.zip
gdb-c074abeebcefe3b62f46ff8a62f3d4058ed32780.tar.gz
gdb-c074abeebcefe3b62f46ff8a62f3d4058ed32780.tar.bz2
Back from Intel with Steve
-rw-r--r--binutils/TODO11
-rw-r--r--binutils/alloca.c191
-rw-r--r--binutils/copy.c410
-rw-r--r--binutils/cplus-dem.c933
-rw-r--r--binutils/gmalloc.c1116
-rw-r--r--binutils/m68k-pinsn.c7
-rwxr-xr-xbinutils/ostrip.c418
-rw-r--r--binutils/sparc-pinsn.c7
-rwxr-xr-xbinutils/strip.c364
-rw-r--r--ld/config.h40
-rwxr-xr-xld/ld-emul.c7
-rwxr-xr-xld/ld-gld.c7
-rwxr-xr-xld/ld-gld960.c7
-rwxr-xr-xld/ld-lnk960.c7
-rwxr-xr-xld/ld.tex1014
-rw-r--r--ld/ldsym.c7
-rw-r--r--ld/ldsym.h59
-rw-r--r--ld/ldwarn.h22
18 files changed, 4613 insertions, 14 deletions
diff --git a/binutils/TODO b/binutils/TODO
new file mode 100644
index 0000000..026f86c
--- /dev/null
+++ b/binutils/TODO
@@ -0,0 +1,11 @@
+o - merge:
+ copy and strip
+ ar and ranlib
+ nm, size, and objdump
+
+o - make the long options more consistent.
+
+o - make ATT and BSD versions -- perhaps the options should be
+ controlled by an environment variable.
+
+o - Calling +help or +version should exit with a successful status (ie 0)
diff --git a/binutils/alloca.c b/binutils/alloca.c
new file mode 100644
index 0000000..9639def
--- /dev/null
+++ b/binutils/alloca.c
@@ -0,0 +1,191 @@
+/*
+ alloca -- (mostly) portable public-domain implementation -- D A Gwyn
+
+ last edit: 86/05/30 rms
+ include config.h, since on VMS it renames some symbols.
+ Use xmalloc instead of malloc.
+
+ This implementation of the PWB library alloca() function,
+ which is used to allocate space off the run-time stack so
+ that it is automatically reclaimed upon procedure exit,
+ was inspired by discussions with J. Q. Johnson of Cornell.
+
+ It should work under any C implementation that uses an
+ actual procedure stack (as opposed to a linked list of
+ frames). There are some preprocessor constants that can
+ be defined when compiling for your specific system, for
+ improved efficiency; however, the defaults should be okay.
+
+ The general concept of this implementation is to keep
+ track of all alloca()-allocated blocks, and reclaim any
+ that are found to be deeper in the stack than the current
+ invocation. This heuristic does not reclaim storage as
+ soon as it becomes invalid, but it will do so eventually.
+
+ As a special case, alloca(0) reclaims storage without
+ allocating any. It is a good idea to use alloca(0) in
+ your main control loop, etc. to force garbage collection.
+*/
+#ifndef lint
+static char SCCSid[] = "@(#)alloca.c 1.1"; /* for the "what" utility */
+#endif
+
+#ifdef emacs
+#include "config.h"
+#ifdef static
+/* actually, only want this if static is defined as ""
+ -- this is for usg, in which emacs must undefine static
+ in order to make unexec workable
+ */
+#ifndef STACK_DIRECTION
+you
+lose
+-- must know STACK_DIRECTION at compile-time
+#endif /* STACK_DIRECTION undefined */
+#endif /* static */
+#endif /* emacs */
+
+#ifdef X3J11
+typedef void *pointer; /* generic pointer type */
+#else
+typedef char *pointer; /* generic pointer type */
+#endif
+
+#define NULL 0 /* null pointer constant */
+
+extern void free();
+extern pointer xmalloc();
+
+/*
+ Define STACK_DIRECTION if you know the direction of stack
+ growth for your system; otherwise it will be automatically
+ deduced at run-time.
+
+ STACK_DIRECTION > 0 => grows toward higher addresses
+ STACK_DIRECTION < 0 => grows toward lower addresses
+ STACK_DIRECTION = 0 => direction of growth unknown
+*/
+
+#ifndef STACK_DIRECTION
+#define STACK_DIRECTION 0 /* direction unknown */
+#endif
+
+#if STACK_DIRECTION != 0
+
+#define STACK_DIR STACK_DIRECTION /* known at compile-time */
+
+#else /* STACK_DIRECTION == 0; need run-time code */
+
+static int stack_dir; /* 1 or -1 once known */
+#define STACK_DIR stack_dir
+
+static void
+find_stack_direction (/* void */)
+{
+ static char *addr = NULL; /* address of first
+ `dummy', once known */
+ auto char dummy; /* to get stack address */
+
+ if (addr == NULL)
+ { /* initial entry */
+ addr = &dummy;
+
+ find_stack_direction (); /* recurse once */
+ }
+ else /* second entry */
+ if (&dummy > addr)
+ stack_dir = 1; /* stack grew upward */
+ else
+ stack_dir = -1; /* stack grew downward */
+}
+
+#endif /* STACK_DIRECTION == 0 */
+
+/*
+ An "alloca header" is used to:
+ (a) chain together all alloca()ed blocks;
+ (b) keep track of stack depth.
+
+ It is very important that sizeof(header) agree with malloc()
+ alignment chunk size. The following default should work okay.
+*/
+
+#ifndef ALIGN_SIZE
+#define ALIGN_SIZE sizeof(double)
+#endif
+
+typedef union hdr
+{
+ char align[ALIGN_SIZE]; /* to force sizeof(header) */
+ struct
+ {
+ union hdr *next; /* for chaining headers */
+ char *deep; /* for stack depth measure */
+ } h;
+} header;
+
+/*
+ alloca( size ) returns a pointer to at least `size' bytes of
+ storage which will be automatically reclaimed upon exit from
+ the procedure that called alloca(). Originally, this space
+ was supposed to be taken from the current stack frame of the
+ caller, but that method cannot be made to work for some
+ implementations of C, for example under Gould's UTX/32.
+*/
+
+static header *last_alloca_header = NULL; /* -> last alloca header */
+
+pointer
+alloca (size) /* returns pointer to storage */
+ unsigned size; /* # bytes to allocate */
+{
+ auto char probe; /* probes stack depth: */
+ register char *depth = &probe;
+
+#if STACK_DIRECTION == 0
+ if (STACK_DIR == 0) /* unknown growth direction */
+ find_stack_direction ();
+#endif
+
+ /* Reclaim garbage, defined as all alloca()ed storage that
+ was allocated from deeper in the stack than currently. */
+
+ {
+ register header *hp; /* traverses linked list */
+
+ for (hp = last_alloca_header; hp != NULL;)
+ if (STACK_DIR > 0 && hp->h.deep > depth
+ || STACK_DIR < 0 && hp->h.deep < depth)
+ {
+ register header *np = hp->h.next;
+
+ free ((pointer) hp); /* collect garbage */
+
+ hp = np; /* -> next header */
+ }
+ else
+ break; /* rest are not deeper */
+
+ last_alloca_header = hp; /* -> last valid storage */
+ }
+
+ if (size == 0)
+ return NULL; /* no allocation required */
+
+ /* Allocate combined header + user data storage. */
+
+ {
+ register pointer new = xmalloc (sizeof (header) + size);
+ /* address of header */
+
+ ((header *)new)->h.next = last_alloca_header;
+ ((header *)new)->h.deep = depth;
+
+ last_alloca_header = (header *)new;
+
+ /* User storage begins just after header. */
+
+ return (pointer)((char *)new + sizeof(header));
+ }
+}
+
diff --git a/binutils/copy.c b/binutils/copy.c
new file mode 100644
index 0000000..601a2b7
--- /dev/null
+++ b/binutils/copy.c
@@ -0,0 +1,410 @@
+/*** copy.c -- copy object file from input to output, optionally massaging it */
+#include "sysdep.h"
+#include "bfd.h"
+
+asymbol **sympp;
+char *input_target = NULL;
+char *output_target = NULL;
+char *input_filename = NULL;
+char *output_filename = NULL;
+
+
+static void setup_sections();
+static void copy_sections();
+static boolean strip;
+static boolean verbose;
+
+/* IMPORTS */
+extern char *program_name;
+extern char *xmalloc();
+
+static
+void
+usage()
+{
+ fprintf(stderr,
+ "Usage %s [-S][-s srcfmt] [-d dtfmt] [-b bothfmts] infile [outfile]\n",
+ program_name);
+ exit(1);
+}
+
+
+/* Create a temp file in the same directory as supplied */
+static
+char *
+make_tempname(filename)
+char *filename;
+{
+ static char template[] = "stXXXXXX";
+ char *tmpname;
+ char * slash = strrchr( filename, '/' );
+ if (slash != (char *)NULL){
+ *slash = 0;
+ tmpname = xmalloc(strlen(filename) + sizeof(template) + 1 );
+ strcpy(tmpname, filename);
+ strcat(tmpname, "/" );
+ strcat(tmpname, template);
+ mktemp(tmpname );
+ *slash = '/';
+ } else {
+ tmpname = xmalloc(sizeof(template));
+ strcpy(tmpname, template);
+ mktemp(tmpname);
+ }
+ return tmpname;
+}
+
+/*
+ All the symbols have been read in and point to their owning input section.
+ They have been relocated to that they are all relative to the base of
+ their owning section. On the way out, all the symbols will be relocated to
+ their new location in the output file, through some complex sums.
+
+*/
+static void
+mangle_sections(ibfd, obfd)
+ bfd *ibfd;
+ bfd *obfd;
+{
+ asection *current = ibfd->sections;
+ for (; current != NULL; current = current->next) {
+ current->output_section = bfd_get_section_by_name(obfd, current->name);
+ current->output_offset = 0;
+ }
+}
+
+static
+void
+copy_object(ibfd, obfd)
+bfd *ibfd;
+bfd *obfd;
+{
+
+ unsigned int symcount;
+
+
+ if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
+ bfd_fatal(output_filename);
+
+
+ if (verbose)
+ printf("copy from %s(%s) to %s(%s)\n",
+ ibfd->filename, ibfd->xvec->name,
+ obfd->filename, obfd->xvec->name);
+
+ if ((bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false) ||
+ (bfd_set_file_flags(obfd, (bfd_get_file_flags(ibfd) &
+ ~(HAS_LINENO | HAS_DEBUG | HAS_SYMS | D_PAGED |
+ HAS_LOCALS))) == false) ||
+ bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false)
+ bfd_fatal(bfd_get_filename(ibfd));
+
+ /* Copy architecture of input file to output file */
+ if (!bfd_set_arch_mach(obfd, bfd_get_architecture(ibfd),
+ bfd_get_machine(ibfd))) {
+ fprintf(stderr, "Output file cannot represent architecture %s\n",
+ bfd_printable_arch_mach(bfd_get_architecture(ibfd),
+ bfd_get_machine(ibfd)));
+ }
+ if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
+ {
+ bfd_fatal(ibfd->filename);
+ }
+
+ sympp = (asymbol **) xmalloc(get_symtab_upper_bound(ibfd));
+ symcount = bfd_canonicalize_symtab(ibfd, sympp);
+
+ bfd_set_symtab(obfd, sympp, strip == true ? 0 : symcount);
+
+ /*
+ bfd mandates that all output sections be created and sizes set before
+ any output is done. Thus, we traverse all sections twice.
+ */
+ bfd_map_over_sections(ibfd, setup_sections, (void *) obfd);
+ bfd_map_over_sections(ibfd, copy_sections, (void *) obfd);
+ mangle_sections(ibfd, obfd);
+}
+static
+char *
+cat(a,b,c)
+char *a;
+char *b;
+char *c;
+{
+ int size = strlen(a) + strlen(b) + strlen(c);
+ char *r = xmalloc(size+1);
+ strcpy(r,a);
+ strcat(r,b);
+ strcat(r,c);
+ return r;
+}
+
+static void
+copy_archive(ibfd, obfd)
+bfd *ibfd;
+bfd *obfd;
+{
+ bfd **ptr =&( obfd->archive_head);
+ bfd *this_element;
+ /* Read each archive element in turn from the input, copy the
+ contents to a temp file, and keep the temp file handle */
+ char *dir = cat("./",make_tempname(this_element->filename),"copy-dir");
+
+ /* Make a temp directory to hold the contents */
+ mkdir(dir,0777);
+ obfd->has_armap = ibfd->has_armap;
+ this_element = bfd_openr_next_archived_file(ibfd, NULL);
+ while (this_element != (bfd *)NULL) {
+
+ /* Create an output file for this member */
+ char *output_name = cat(dir, "/",this_element->filename);
+ bfd *output_bfd = bfd_openw(output_name, output_target);
+
+ if (!bfd_set_format(obfd, bfd_get_format(ibfd)))
+ bfd_fatal(output_filename);
+
+ if (output_bfd == (bfd *)NULL) {
+ bfd_fatal(output_name);
+ }
+ if (bfd_check_format(this_element, bfd_object) == true) {
+ copy_object(this_element, output_bfd);
+ }
+
+ bfd_close(output_bfd);
+ /* Now open the newly output file and attatch to our list */
+ output_bfd = bfd_openr(output_name, output_target);
+ /* Mark it for deletion */
+
+ *ptr = output_bfd;
+
+ ptr =&( output_bfd->next);
+ this_element = bfd_openr_next_archived_file(ibfd, this_element);
+
+ }
+ *ptr = (bfd *)NULL;
+
+ if (!bfd_close(obfd))
+ bfd_fatal(output_filename);
+
+ /* Now delete all the files that we opened
+ We can't use the names in the obfd list since they may have been
+ trampled by the archive output code
+ */
+ for (this_element = ibfd->archive_head;
+ this_element != (bfd *)NULL;
+ this_element = this_element->next)
+ {
+ unlink(cat(dir,"/",this_element->filename));
+ }
+ unlink(dir);
+ if (!bfd_close(ibfd))
+ bfd_fatal(input_filename);
+
+}
+
+static
+boolean
+copy_file(input_filename, output_filename)
+ char *input_filename;
+ char *output_filename;
+{
+ bfd *ibfd;
+
+
+ ibfd = bfd_openr(input_filename, input_target);
+ if (ibfd == NULL)
+ bfd_fatal(input_filename);
+
+ if (bfd_check_format(ibfd, bfd_object)) {
+ bfd * obfd = bfd_openw(output_filename, output_target);
+ if (obfd == NULL)
+ bfd_fatal(output_filename);
+
+ copy_object(ibfd, obfd);
+
+ if (!bfd_close(obfd))
+ bfd_fatal(output_filename);
+
+ if (!bfd_close(ibfd))
+ bfd_fatal(input_filename);
+ }
+ else if (bfd_check_format(ibfd, bfd_archive)) {
+ bfd * obfd = bfd_openw(output_filename, output_target);
+ if (obfd == NULL)
+ bfd_fatal(output_filename);
+
+ copy_archive(ibfd, obfd);
+ }
+}
+
+
+
+/** Actually do the work */
+static void
+setup_sections(ibfd, isection, obfd)
+ bfd *ibfd;
+ sec_ptr isection;
+ bfd *obfd;
+{
+ sec_ptr osection;
+ char *err;
+ osection = bfd_make_section(obfd, bfd_section_name(ibfd, isection));
+ if (osection == NULL) {
+ err = "making";
+ goto loser;
+ }
+
+ if (!bfd_set_section_size(obfd,
+ osection,
+ bfd_section_size(ibfd, isection))) {
+ err = "size";
+ goto loser;
+ }
+
+ if (bfd_set_section_vma(obfd,
+ osection,
+ bfd_section_vma(ibfd, isection))
+ == false) {
+ err = "vma";
+ goto loser;
+ } /* on error */
+
+ if (bfd_set_section_alignment(obfd,
+ osection,
+ bfd_section_alignment(ibfd, isection))
+ == false) {
+ err = "alignment";
+ goto loser;
+ } /* on error */
+
+ if (!bfd_set_section_flags(obfd, osection,
+ bfd_get_section_flags(ibfd, isection))) {
+ err = "flags";
+ goto loser;
+ }
+
+ /* All went well */
+ return;
+
+loser:
+ fprintf(stderr, "%s: file \"%s\", section \"%s\": error in %s: %s\n",
+ program_name,
+ bfd_get_filename(ibfd), bfd_section_name(ibfd, isection),
+ err, bfd_errmsg(bfd_error));
+ exit(1);
+} /* setup_sections() */
+
+static void
+copy_sections(ibfd, isection, obfd)
+ bfd *ibfd;
+ sec_ptr isection;
+ bfd *obfd;
+{
+ static unsigned char *memhunk = NULL;
+ arelent **relpp;
+ int relcount;
+ sec_ptr osection;
+ unsigned long size;
+ osection = bfd_get_section_by_name(obfd,
+ bfd_section_name(ibfd, isection));
+
+ size = bfd_section_size(ibfd, isection);
+
+ if (size == 0)
+ return;
+
+ if (get_reloc_upper_bound(ibfd, isection) != 0) {
+ relpp = (arelent **) xmalloc(get_reloc_upper_bound(ibfd, isection));
+
+ relcount = bfd_canonicalize_reloc(ibfd, isection, relpp, sympp);
+
+ bfd_set_reloc(obfd, osection, relpp, relcount);
+ }
+
+ if (bfd_get_section_flags(ibfd, isection) & SEC_HAS_CONTENTS) {
+ memhunk = (unsigned char *) xmalloc(size);
+ /* now we have enough memory, just do it: */
+ if (!bfd_get_section_contents(ibfd, isection, memhunk, 0, size))
+ bfd_fatal(bfd_get_filename(ibfd));
+
+ if (!bfd_set_section_contents(obfd, osection, memhunk, 0, size))
+ bfd_fatal(bfd_get_filename(obfd));
+ } /* only if the section has contents. */
+
+ free(memhunk);
+}
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int i;
+
+
+ program_name = argv[0];
+
+ if (strcmp(program_name,"strip") == 0) {
+ strip = true;
+ }
+
+ for (i = 1; i < argc; i++)
+ {
+ if (argv[i][0] == '-') {
+ switch (argv[i][1]) {
+ case 'v':
+ verbose = true;
+ break;
+ case 'b':
+ i++;
+ input_target = output_target = argv[i];
+ break;
+ case 'S':
+ strip = true;
+ break;
+ case 's':
+ i++;
+ input_target = argv[i];
+ break;
+ case 'd':
+ i++;
+ output_target = argv[i];
+ break;
+ default:
+ usage();
+ }
+ }
+ else {
+ if (input_filename) {
+ output_filename = argv[i];
+ }
+ else {
+ input_filename = argv[i];
+ }
+ }
+ }
+
+ if (input_filename == (char *) NULL)
+ usage();
+
+ if (output_target == (char *) NULL)
+ output_target = input_target;
+
+ /* If there is no destination file then create a temp and rename
+ the result into the input */
+
+ if (output_filename == (char *)NULL) {
+ char * tmpname = make_tempname(input_filename);
+ if (copy_file(input_filename, tmpname)) {
+ output_filename = input_filename;
+ rename(tmpname, input_filename);
+ return 0;
+ }
+ }
+ else if (copy_file(input_filename, output_filename))
+ {
+ return 0;
+ }
+
+
+ return 1;
+}
diff --git a/binutils/cplus-dem.c b/binutils/cplus-dem.c
new file mode 100644
index 0000000..4cc6496
--- /dev/null
+++ b/binutils/cplus-dem.c
@@ -0,0 +1,933 @@
+/* Demangler for GNU C++
+ Copyright (C) 1989 Free Software Foundation, Inc.
+ written by James Clark (jjc@jclark.uucp)
+
+ 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This is for g++ 1.36.1 (November 6 version). It will probably
+ require changes for any other version.
+
+ Modified for g++ 1.36.2 (November 18 version). */
+
+/* This file exports one function
+
+ char *cplus_demangle (const char *name)
+
+ If `name' is a mangled function name produced by g++, then
+ a pointer to a malloced string giving a C++ representation
+ of the name will be returned; otherwise NULL will be returned.
+ It is the caller's responsibility to free the string which
+ is returned.
+
+ For example,
+
+ cplus_demangle ("_foo__1Ai")
+
+ returns
+
+ "A::foo(int)"
+
+ This file imports xmalloc and xrealloc, which are like malloc and
+ realloc except that they generate a fatal error if there is no
+ available memory. */
+
+#if 0 /* Should really be part of BFD */
+#define nounderscore 1 /* define this is names don't start with _ */
+#endif
+#include "sysdep.h"
+
+#include <ctype.h>
+
+#ifndef __STDC__
+#define const
+#endif
+
+#ifdef __STDC__
+extern char *cplus_demangle (const char *type);
+#else
+extern char *cplus_demangle ();
+#endif
+
+static char **typevec = 0;
+static int ntypes = 0;
+static int typevec_size = 0;
+
+static struct {
+ const char *in;
+ const char *out;
+} optable[] = {
+ "new", " new",
+ "delete", " delete",
+ "ne", "!=",
+ "eq", "==",
+ "ge", ">=",
+ "gt", ">",
+ "le", "<=",
+ "lt", "<",
+ "plus", "+",
+ "minus", "-",
+ "mult", "*",
+ "convert", "+", /* unary + */
+ "negate", "-", /* unary - */
+ "trunc_mod", "%",
+ "trunc_div", "/",
+ "truth_andif", "&&",
+ "truth_orif", "||",
+ "truth_not", "!",
+ "postincrement", "++",
+ "postdecrement", "--",
+ "bit_ior", "|",
+ "bit_xor", "^",
+ "bit_and", "&",
+ "bit_not", "~",
+ "call", "()",
+ "cond", "?:",
+ "alshift", "<<",
+ "arshift", ">>",
+ "component", "->",
+ "indirect", "*",
+ "method_call", "->()",
+ "addr", "&", /* unary & */
+ "array", "[]",
+ "nop", "", /* for operator= */
+};
+
+/* Beware: these aren't '\0' terminated. */
+
+typedef struct {
+ char *b; /* pointer to start of string */
+ char *p; /* pointer after last character */
+ char *e; /* pointer after end of allocated space */
+} string;
+
+#ifdef __STDC__
+static void string_need (string *s, int n);
+static void string_delete (string *s);
+static void string_init (string *s);
+static void string_clear (string *s);
+static int string_empty (string *s);
+static void string_append (string *p, const char *s);
+static void string_appends (string *p, string *s);
+static void string_appendn (string *p, const char *s, int n);
+static void string_prepend (string *p, const char *s);
+#if 0
+static void string_prepends (string *p, string *s);
+#endif
+static void string_prependn (string *p, const char *s, int n);
+static int get_count (const char **type, int *count);
+static int do_args (const char **type, string *decl);
+static int do_type (const char **type, string *result);
+static int do_arg (const char **type, string *result);
+static int do_args (const char **type, string *decl);
+static void munge_function_name (string *name);
+#else
+static void string_need ();
+static void string_delete ();
+static void string_init ();
+static void string_clear ();
+static int string_empty ();
+static void string_append ();
+static void string_appends ();
+static void string_appendn ();
+static void string_prepend ();
+static void string_prepends ();
+static void string_prependn ();
+static int get_count ();
+static int do_args ();
+static int do_type ();
+static int do_arg ();
+static int do_args ();
+static void munge_function_name ();
+#endif
+
+char *
+cplus_demangle (type)
+ const char *type;
+{
+ string decl;
+ int n;
+ int success = 0;
+ int constructor = 0;
+ int const_flag = 0;
+ int i;
+ const char *p, *premangle;
+
+ if (type == NULL || *type == '\0')
+ return NULL;
+#ifndef nounderscore
+ if (*type++ != '_')
+ return NULL;
+#endif
+ p = type;
+ while (*p != '\0' && !(*p == '_' && p[1] == '_'))
+ p++;
+ if (*p == '\0')
+ {
+ /* destructor */
+ if (type[0] == '_' && type[1] == '$' && type[2] == '_')
+ {
+ unsigned int l = (strlen (type) - 3)*2 + 3 + 2 + 1;
+ char *tem = (char *) xmalloc (l);
+ strcpy (tem, type + 3);
+ strcat (tem, "::~");
+ strcat (tem, type + 3);
+ strcat (tem, "()");
+ return tem;
+ }
+ /* static data member */
+ if (*type != '_' && (p = (char *) strchr (type, '$')) != NULL)
+ {
+ int n = strlen (type) + 2;
+ char *tem = (char *) xmalloc (n);
+ memcpy (tem, type, p - type);
+ strcpy (tem + (p - type), "::");
+ strcpy (tem + (p - type) + 2, p + 1);
+ return tem;
+ }
+ /* virtual table */
+ if (type[0] == '_' && type[1] == 'v' && type[2] == 't' && type[3] == '$')
+ {
+ int n = strlen (type + 4) + 14 + 1;
+ char *tem = (char *) xmalloc (n);
+ strcpy (tem, type + 4);
+ strcat (tem, " virtual table");
+ return tem;
+ }
+ return NULL;
+ }
+
+ string_init (&decl);
+
+ if (p == type)
+ {
+ if (!isdigit (p[2]))
+ {
+ string_delete (&decl);
+ return NULL;
+ }
+ constructor = 1;
+ }
+ else
+ {
+ string_appendn (&decl, type, p - type);
+ munge_function_name (&decl);
+ }
+ p += 2;
+
+ premangle = p;
+ switch (*p)
+ {
+ case 'C':
+ /* a const member function */
+ if (!isdigit (p[1]))
+ {
+ string_delete (&decl);
+ return NULL;
+ }
+ p += 1;
+ const_flag = 1;
+ /* fall through */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ n = 0;
+ do
+ {
+ n *= 10;
+ n += *p - '0';
+ p += 1;
+ }
+ while (isdigit (*p));
+ if (strlen (p) < n)
+ {
+ string_delete (&decl);
+ return NULL;
+ }
+ if (constructor)
+ {
+ string_appendn (&decl, p, n);
+ string_append (&decl, "::");
+ string_appendn (&decl, p, n);
+ }
+ else
+ {
+ string_prepend (&decl, "::");
+ string_prependn (&decl, p, n);
+ }
+#ifndef LONGERNAMES
+ p = premangle;
+#else
+ p += n;
+#endif
+ success = do_args (&p, &decl);
+ if (const_flag)
+ string_append (&decl, " const");
+ break;
+ case 'F':
+ p += 1;
+ success = do_args (&p, &decl);
+ break;
+ }
+
+ for (i = 0; i < ntypes; i++)
+ if (typevec[i] != NULL)
+ free (typevec[i]);
+ ntypes = 0;
+ if (typevec != NULL)
+ {
+ free ((char *)typevec);
+ typevec = NULL;
+ typevec_size = 0;
+ }
+
+ if (success)
+ {
+ string_appendn (&decl, "", 1);
+ return decl.b;
+ }
+ else
+ {
+ string_delete (&decl);
+ return NULL;
+ }
+}
+
+static int
+get_count (type, count)
+ const char **type;
+ int *count;
+{
+ if (!isdigit (**type))
+ return 0;
+ *count = **type - '0';
+ *type += 1;
+ /* see flush_repeats in cplus-method.c */
+ if (isdigit (**type))
+ {
+ const char *p = *type;
+ int n = *count;
+ do
+ {
+ n *= 10;
+ n += *p - '0';
+ p += 1;
+ }
+ while (isdigit (*p));
+ if (*p == '_')
+ {
+ *type = p + 1;
+ *count = n;
+ }
+ }
+ return 1;
+}
+
+/* result will be initialised here; it will be freed on failure */
+
+static int
+do_type (type, result)
+ const char **type;
+ string *result;
+{
+ int n;
+ int done;
+ int non_empty = 0;
+ int success;
+ string decl;
+ const char *remembered_type;
+
+ string_init (&decl);
+ string_init (result);
+
+ done = 0;
+ success = 1;
+ while (success && !done)
+ {
+ int member;
+ switch (**type)
+ {
+ case 'P':
+ *type += 1;
+ string_prepend (&decl, "*");
+ break;
+
+ case 'R':
+ *type += 1;
+ string_prepend (&decl, "&");
+ break;
+
+ case 'T':
+ *type += 1;
+ if (!get_count (type, &n) || n >= ntypes)
+ success = 0;
+ else
+ {
+ remembered_type = typevec[n];
+ type = &remembered_type;
+ }
+ break;
+
+ case 'F':
+ *type += 1;
+ if (!string_empty (&decl) && decl.b[0] == '*')
+ {
+ string_prepend (&decl, "(");
+ string_append (&decl, ")");
+ }
+ if (!do_args (type, &decl) || **type != '_')
+ success = 0;
+ else
+ *type += 1;
+ break;
+
+ case 'M':
+ case 'O':
+ {
+ int constp = 0;
+ int volatilep = 0;
+
+ member = **type == 'M';
+ *type += 1;
+ if (!isdigit (**type))
+ {
+ success = 0;
+ break;
+ }
+ n = 0;
+ do
+ {
+ n *= 10;
+ n += **type - '0';
+ *type += 1;
+ }
+ while (isdigit (**type));
+ if (strlen (*type) < n)
+ {
+ success = 0;
+ break;
+ }
+ string_append (&decl, ")");
+ string_prepend (&decl, "::");
+ string_prependn (&decl, *type, n);
+ string_prepend (&decl, "(");
+ *type += n;
+ if (member)
+ {
+ if (**type == 'C')
+ {
+ *type += 1;
+ constp = 1;
+ }
+ if (**type == 'V')
+ {
+ *type += 1;
+ volatilep = 1;
+ }
+ if (*(*type)++ != 'F')
+ {
+ success = 0;
+ break;
+ }
+ }
+ if ((member && !do_args (type, &decl)) || **type != '_')
+ {
+ success = 0;
+ break;
+ }
+ *type += 1;
+ if (constp)
+ {
+ if (non_empty)
+ string_append (&decl, " ");
+ else
+ non_empty = 1;
+ string_append (&decl, "const");
+ }
+ if (volatilep)
+ {
+ if (non_empty)
+ string_append (&decl, " ");
+ else
+ non_empty = 1;
+ string_append (&decl, "volatilep");
+ }
+ break;
+ }
+
+ case 'C':
+ if ((*type)[1] == 'P')
+ {
+ *type += 1;
+ if (!string_empty (&decl))
+ string_prepend (&decl, " ");
+ string_prepend (&decl, "const");
+ break;
+ }
+
+ /* fall through */
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ done = 0;
+ non_empty = 0;
+ while (success && !done)
+ {
+ switch (**type)
+ {
+ case 'C':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ else
+ non_empty = 1;
+ string_append (result, "const");
+ break;
+ case 'U':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ else
+ non_empty = 1;
+ string_append (result, "unsigned");
+ break;
+ case 'V':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ else
+ non_empty = 1;
+ string_append (result, "volatile");
+ break;
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ if (success)
+ switch (**type)
+ {
+ case '\0':
+ case '_':
+ break;
+ case 'v':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "void");
+ break;
+ case 'l':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "long");
+ break;
+ case 'i':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "int");
+ break;
+ case 's':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "short");
+ break;
+ case 'c':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "char");
+ break;
+ case 'r':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "long double");
+ break;
+ case 'd':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "double");
+ break;
+ case 'f':
+ *type += 1;
+ if (non_empty)
+ string_append (result, " ");
+ string_append (result, "float");
+ break;
+ case 'G':
+ *type += 1;
+ if (!isdigit (**type))
+ {
+ success = 0;
+ break;
+ }
+ /* fall through */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ n = 0;
+ do
+ {
+ n *= 10;
+ n += **type - '0';
+ *type += 1;
+ }
+ while (isdigit (**type));
+ if (strlen (*type) < n)
+ {
+ success = 0;
+ break;
+ }
+ if (non_empty)
+ string_append (result, " ");
+ string_appendn (result, *type, n);
+ *type += n;
+ break;
+ default:
+ success = 0;
+ break;
+ }
+
+ if (success)
+ {
+ if (!string_empty (&decl))
+ {
+ string_append (result, " ");
+ string_appends (result, &decl);
+ }
+ string_delete (&decl);
+ return 1;
+ }
+ else
+ {
+ string_delete (&decl);
+ string_delete (result);
+ return 0;
+ }
+}
+
+/* `result' will be initialised in do_type; it will be freed on failure */
+
+static int
+do_arg (type, result)
+ const char **type;
+ string *result;
+{
+ char *tem;
+ int len;
+ const char *start;
+ const char *end;
+
+ start = *type;
+ if (!do_type (type, result))
+ return 0;
+ end = *type;
+ if (ntypes >= typevec_size)
+ {
+ if (typevec_size == 0)
+ {
+ typevec_size = 3;
+ typevec = (char **) xmalloc (sizeof (char*)*typevec_size);
+ }
+ else
+ {
+ typevec_size *= 2;
+ typevec = (char **) xrealloc ((char *)typevec, sizeof (char*)*typevec_size);
+ }
+ }
+ len = end - start;
+ tem = (char *) xmalloc (len + 1);
+ memcpy (tem, start, len);
+ tem[len] = '\0';
+ typevec[ntypes++] = tem;
+ return 1;
+}
+
+/* `decl' must be already initialised, usually non-empty;
+ it won't be freed on failure */
+
+static int
+do_args (type, decl)
+ const char **type;
+ string *decl;
+{
+ string arg;
+ int need_comma = 0;
+ int dont_want_first;
+
+#ifndef LONGERNAMES
+ dont_want_first = 1;
+#else
+ dont_want_first = 0;
+#endif
+
+ string_append (decl, "(");
+
+ while (**type != '_' && **type != '\0' && **type != 'e' && **type != 'v')
+ {
+ if (**type == 'N')
+ {
+ int r;
+ int t;
+ *type += 1;
+ if (!get_count (type, &r) || !get_count (type, &t) || t >= ntypes)
+ return 0;
+ while (--r >= 0)
+ {
+ const char *tem = typevec[t];
+ if (need_comma)
+ string_append (decl, ", ");
+ if (!do_arg (&tem, &arg))
+ return 0;
+ string_appends (decl, &arg);
+ string_delete (&arg);
+ need_comma = 1;
+ }
+ }
+ else
+ {
+ if (need_comma)
+ string_append (decl, ", ");
+ if (!do_arg (type, &arg))
+ return 0;
+ if (dont_want_first)
+ dont_want_first = 0;
+ else
+ {
+ string_appends (decl, &arg);
+ need_comma = 1;
+ }
+ string_delete (&arg);
+ }
+ }
+
+ if (**type == 'v')
+ *type += 1;
+ else if (**type == 'e')
+ {
+ *type += 1;
+ if (need_comma)
+ string_append (decl, ",");
+ string_append (decl, "...");
+ }
+
+ string_append (decl, ")");
+ return 1;
+}
+
+static void
+munge_function_name (name)
+ string *name;
+{
+ if (!string_empty (name) && name->p - name->b >= 3
+ && name->b[0] == 'o' && name->b[1] == 'p' && name->b[2] == '$')
+ {
+ unsigned int i;
+ /* see if it's an assignment expression */
+ if (name->p - name->b >= 10 /* op$assign_ */
+ && memcmp (name->b + 3, "assign_", 7) == 0)
+ {
+ for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
+ {
+ int len = name->p - name->b - 10;
+ if (strlen (optable[i].in) == len
+ && memcmp (optable[i].in, name->b + 10, len) == 0)
+ {
+ string_clear (name);
+ string_append (name, "operator");
+ string_append (name, optable[i].out);
+ string_append (name, "=");
+ return;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0; i < sizeof (optable)/sizeof (optable[0]); i++)
+ {
+ int len = name->p - name->b - 3;
+ if (strlen (optable[i].in) == len
+ && memcmp (optable[i].in, name->b + 3, len) == 0)
+ {
+ string_clear (name);
+ string_append (name, "operator");
+ string_append (name, optable[i].out);
+ return;
+ }
+ }
+ }
+ return;
+ }
+ else if (!string_empty (name) && name->p - name->b >= 5
+ && memcmp (name->b, "type$", 5) == 0)
+ {
+ /* type conversion operator */
+ string type;
+ const char *tem = name->b + 5;
+ if (do_type (&tem, &type))
+ {
+ string_clear (name);
+ string_append (name, "operator ");
+ string_appends (name, &type);
+ string_delete (&type);
+ return;
+ }
+ }
+}
+
+/* a mini string-handling package */
+
+static void
+string_need (s, n)
+ string *s;
+ int n;
+{
+ if (s->b == NULL)
+ {
+ if (n < 32)
+ n = 32;
+ s->p = s->b = (char *) xmalloc (n);
+ s->e = s->b + n;
+ }
+ else if (s->e - s->p < n)
+ {
+ int tem = s->p - s->b;
+ n += tem;
+ n *= 2;
+ s->b = (char *) xrealloc (s->b, n);
+ s->p = s->b + tem;
+ s->e = s->b + n;
+ }
+}
+
+static void
+string_delete (s)
+ string *s;
+{
+ if (s->b != NULL)
+ {
+ free (s->b);
+ s->b = s->e = s->p = NULL;
+ }
+}
+
+static void
+string_init (s)
+ string *s;
+{
+ s->b = s->p = s->e = NULL;
+}
+
+static void
+string_clear (s)
+ string *s;
+{
+ s->p = s->b;
+}
+
+static int
+string_empty (s)
+ string *s;
+{
+ return s->b == s->p;
+}
+
+static void
+string_append (p, s)
+ string *p;
+ const char *s;
+{
+ int n;
+ if (s == NULL || *s == '\0')
+ return;
+ n = strlen (s);
+ string_need (p, n);
+ memcpy (p->p, s, n);
+ p->p += n;
+}
+
+static void
+string_appends (p, s)
+ string *p, *s;
+{
+ int n;
+ if (s->b == s->p)
+ return;
+ n = s->p - s->b;
+ string_need (p, n);
+ memcpy (p->p, s->b, n);
+ p->p += n;
+}
+
+static void
+string_appendn (p, s, n)
+ string *p;
+ const char *s;
+ int n;
+{
+ if (n == 0)
+ return;
+ string_need (p, n);
+ memcpy (p->p, s, n);
+ p->p += n;
+}
+
+static void
+string_prepend (p, s)
+ string *p;
+ const char *s;
+{
+ if (s == NULL || *s == '\0')
+ return;
+ string_prependn (p, s, strlen (s));
+}
+
+static void
+string_prependn (p, s, n)
+ string *p;
+ const char *s;
+ int n;
+{
+ char *q;
+
+ if (n == 0)
+ return;
+ string_need (p, n);
+ for (q = p->p - 1; q >= p->b; q--)
+ q[n] = q[0];
+ memcpy (p->b, s, n);
+ p->p += n;
+}
diff --git a/binutils/gmalloc.c b/binutils/gmalloc.c
new file mode 100644
index 0000000..0468551
--- /dev/null
+++ b/binutils/gmalloc.c
@@ -0,0 +1,1116 @@
+
+/* gmalloc.c - THIS FILE IS AUTOMAGICALLY GENERATED SO DON'T EDIT IT. */
+
+/* Single-file skeleton for GNU malloc.
+ Copyright 1989 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+ 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#define __ONEFILE
+
+/* DO NOT DELETE THIS LINE -- ansidecl.h INSERTED HERE. */
+/* Copyright (C) 1989 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library 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 1, or (at your option)
+any later version.
+
+The GNU C Library 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 the GNU C Library; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* ANSI and traditional C compatibility macros
+
+ ANSI C is assumed if __STDC__ is #defined.
+
+ Macros
+ PTR - Generic pointer type
+ LONG_DOUBLE - `long double' type
+ CONST - `const' keyword
+ VOLATILE - `volatile' keyword
+ SIGNED - `signed' keyword
+ PTRCONST - Generic const pointer (void *const)
+
+ EXFUN(name, prototype) - declare external function NAME
+ with prototype PROTOTYPE
+ DEFUN(name, arglist, args) - define function NAME with
+ args ARGLIST of types in ARGS
+ DEFUN_VOID(name) - define function NAME with no args
+ AND - argument separator for ARGS
+ NOARGS - null arglist
+ DOTS - `...' in args
+
+ For example:
+ extern int EXFUN(printf, (CONST char *format DOTS));
+ int DEFUN(fprintf, (stream, format),
+ FILE *stream AND CONST char *format DOTS) { ... }
+ void DEFUN_VOID(abort) { ... }
+*/
+
+#ifndef _ANSIDECL_H
+
+#define _ANSIDECL_H 1
+
+
+/* Every source file includes this file,
+ so they will all get the switch for lint. */
+/* LINTLIBRARY */
+
+
+#ifdef __STDC__
+
+#define PTR void *
+#define PTRCONST void *CONST
+#define LONG_DOUBLE long double
+
+#define AND ,
+#define NOARGS void
+#define CONST const
+#define VOLATILE volatile
+#define SIGNED signed
+#define DOTS , ...
+
+#define EXFUN(name, proto) name proto
+#define DEFUN(name, arglist, args) name(args)
+#define DEFUN_VOID(name) name(NOARGS)
+
+#else /* Not ANSI C. */
+
+#define PTR char *
+#define PTRCONST PTR
+#define LONG_DOUBLE double
+
+#define AND ;
+#define NOARGS
+#define CONST
+#define VOLATILE
+#define SIGNED
+#define DOTS
+
+#define EXFUN(name, proto) name()
+#define DEFUN(name, arglist, args) name arglist args;
+#define DEFUN_VOID(name) name()
+
+#endif /* ANSI C. */
+
+
+#endif /* ansidecl.h */
+
+#ifdef __STDC__
+#include <limits.h>
+#else
+/* DO NOT DELETE THIS LINE -- limits.h INSERTED HERE. */
+/* Number of bits in a `char'. */
+#define CHAR_BIT 8
+
+/* No multibyte characters supported yet. */
+#define MB_LEN_MAX 1
+
+/* Minimum and maximum values a `signed char' can hold. */
+#define SCHAR_MIN -128
+#define SCHAR_MAX 127
+
+/* Maximum value an `unsigned char' can hold. (Minimum is 0). */
+#define UCHAR_MAX 255U
+
+/* Minimum and maximum values a `char' can hold. */
+#ifdef __CHAR_UNSIGNED__
+#define CHAR_MIN 0
+#define CHAR_MAX 255U
+#else
+#define CHAR_MIN -128
+#define CHAR_MAX 127
+#endif
+
+/* Minimum and maximum values a `signed short int' can hold. */
+#define SHRT_MIN -32768
+#define SHRT_MAX 32767
+
+/* Maximum value an `unsigned short int' can hold. (Minimum is 0). */
+#define USHRT_MAX 65535U
+
+/* Minimum and maximum values a `signed int' can hold. */
+#define INT_MIN -2147483648
+#define INT_MAX 2147483647
+
+/* Maximum value an `unsigned int' can hold. (Minimum is 0). */
+#define UINT_MAX 4294967295U
+
+/* Minimum and maximum values a `signed long int' can hold.
+ (Same as `int'). */
+#define LONG_MIN (-LONG_MAX-1)
+#define LONG_MAX 2147483647
+
+/* Maximum value an `unsigned long int' can hold. (Minimum is 0). */
+#define ULONG_MAX 4294967295U
+#endif
+
+#ifdef __STDC__
+#include <stddef.h>
+#else
+/* DO NOT DELETE THIS LINE -- stddef.h INSERTED HERE. */
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+/* Signed type of difference of two pointers. */
+
+typedef long ptrdiff_t;
+
+/* Unsigned type of `sizeof' something. */
+
+#ifndef _SIZE_T /* in case <sys/types.h> has defined it. */
+#define _SIZE_T
+typedef unsigned long size_t;
+#endif /* _SIZE_T */
+
+/* A null pointer constant. */
+
+#undef NULL /* in case <stdio.h> has defined it. */
+#define NULL 0
+
+/* Offset of member MEMBER in a struct of type TYPE. */
+
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+#endif /* _STDDEF_H */
+#endif
+
+/* DO NOT DELETE THIS LINE -- stdlib.h INSERTED HERE. */
+/* Fake stdlib.h supplying the stuff needed by malloc. */
+
+#ifndef __ONEFILE
+#include <stddef.h>
+#endif
+
+extern void EXFUN(abort, (void));
+extern void EXFUN(free, (PTR));
+extern PTR EXFUN(malloc, (size_t));
+extern PTR EXFUN(realloc, (PTR, size_t));
+
+/* DO NOT DELETE THIS LINE -- string.h INSERTED HERE. */
+/* Fake string.h supplying stuff used by malloc. */
+#ifndef __ONEFILE
+#include <stddef.h>
+#endif
+
+extern PTR EXFUN(memcpy, (PTR, PTR, size_t));
+extern PTR EXFUN(memset, (PTR, int, size_t));
+#define memmove memcpy
+
+#define _MALLOC_INTERNAL
+/* DO NOT DELETE THIS LINE -- malloc.h INSERTED HERE. */
+/* Declarations for `malloc' and friends.
+ Copyright 1990 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+ 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef _MALLOC_H
+
+#define _MALLOC_H 1
+
+#ifndef __ONEFILE
+#define __need_NULL
+#define __need_size_t
+#define __need_ptrdiff_t
+#include <stddef.h>
+#endif
+
+#ifdef _MALLOC_INTERNAL
+
+#ifndef __ONEFILE
+#include <limits.h>
+#endif
+
+/* The allocator divides the heap into blocks of fixed size; large
+ requests receive one or more whole blocks, and small requests
+ receive a fragment of a block. Fragment sizes are powers of two,
+ and all fragments of a block are the same size. When all the
+ fragments in a block have been freed, the block itself is freed. */
+#define INT_BIT (CHAR_BIT * sizeof(int))
+#define BLOCKLOG (INT_BIT > 16 ? 12 : 9)
+#define BLOCKSIZE (1 << BLOCKLOG)
+#define BLOCKIFY(SIZE) (((SIZE) + BLOCKSIZE - 1) / BLOCKSIZE)
+
+/* Determine the amount of memory spanned by the initial heap table
+ (not an absolute limit). */
+#define HEAP (INT_BIT > 16 ? 4194304 : 65536)
+
+/* Number of contiguous free blocks allowed to build up at the end of
+ memory before they will be returned to the system. */
+#define FINAL_FREE_BLOCKS 8
+
+/* Where to start searching the free list when looking for new memory.
+ The two possible values are 0 and _heapindex. Starting at 0 seems
+ to reduce total memory usage, while starting at _heapindex seems to
+ run faster. */
+#define MALLOC_SEARCH_START _heapindex
+
+/* Data structure giving per-block information. */
+typedef union
+ {
+ /* Heap information for a busy block. */
+ struct
+ {
+ /* Zero for a large block, or positive giving the
+ logarithm to the base two of the fragment size. */
+ int type;
+ union
+ {
+ struct
+ {
+ size_t nfree; /* Free fragments in a fragmented block. */
+ size_t first; /* First free fragment of the block. */
+ } frag;
+ /* Size (in blocks) of a large cluster. */
+ size_t size;
+ } info;
+ } busy;
+ /* Heap information for a free block (that may be the first of
+ a free cluster). */
+ struct
+ {
+ size_t size; /* Size (in blocks) of a free cluster. */
+ size_t next; /* Index of next free cluster. */
+ size_t prev; /* Index of previous free cluster. */
+ } free;
+ } malloc_info;
+
+/* Pointer to first block of the heap. */
+extern char *_heapbase;
+
+/* Table indexed by block number giving per-block information. */
+extern malloc_info *_heapinfo;
+
+/* Address to block number and vice versa. */
+#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1)
+#define ADDRESS(B) ((PTR) (((B) - 1) * BLOCKSIZE + _heapbase))
+
+/* Current search index for the heap table. */
+extern size_t _heapindex;
+
+/* Limit of valid info table indices. */
+extern size_t _heaplimit;
+
+/* Doubly linked lists of free fragments. */
+struct list
+ {
+ struct list *next;
+ struct list *prev;
+ };
+
+/* Free list headers for each fragment size. */
+extern struct list _fraghead[];
+
+/* Instrumentation. */
+extern size_t _chunks_used;
+extern size_t _bytes_used;
+extern size_t _chunks_free;
+extern size_t _bytes_free;
+
+/* Internal version of free() used in morecore(). */
+extern void EXFUN(__free, (PTR __ptr));
+
+#endif /* _MALLOC_INTERNAL. */
+
+/* Underlying allocation function; successive calls should
+ return contiguous pieces of memory. */
+extern PTR EXFUN((*__morecore), (ptrdiff_t __size));
+
+/* Default value of previous. */
+extern PTR EXFUN(__default_morecore, (ptrdiff_t __size));
+
+/* Flag whether malloc has been called. */
+extern int __malloc_initialized;
+
+/* Hooks for debugging versions. */
+extern void EXFUN((*__free_hook), (PTR __ptr));
+extern PTR EXFUN((*__malloc_hook), (size_t __size));
+extern PTR EXFUN((*__realloc_hook), (PTR __ptr, size_t __size));
+
+/* Activate a standard collection of debugging hooks. */
+extern void EXFUN(mcheck, (void EXFUN((*func), (void))));
+
+/* Statistics available to the user. */
+struct mstats
+ {
+ size_t bytes_total; /* Total size of the heap. */
+ size_t chunks_used; /* Chunks allocated by the user. */
+ size_t bytes_used; /* Byte total of user-allocated chunks. */
+ size_t chunks_free; /* Chunks in the free list. */
+ size_t bytes_free; /* Byte total of chunks in the free list. */
+ };
+
+/* Pick up the current statistics. */
+extern struct mstats EXFUN(mstats, (NOARGS));
+
+#endif /* malloc.h */
+
+/* DO NOT DELETE THIS LINE -- free.c INSERTED HERE. */
+/* Free a block of memory allocated by `malloc'.
+ Copyright 1990 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+ 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stddef.h>
+#include <stdlib.h>
+
+#define _MALLOC_INTERNAL
+#include "malloc.h"
+#endif /* __ONEFILE */
+
+/* Debugging hook for free. */
+void EXFUN((*__free_hook), (PTR __ptr));
+
+/* Return memory to the heap. Like free() but don't call a __free_hook
+ if there is one. */
+void
+DEFUN(__free, (ptr), PTR ptr)
+{
+ int type;
+ size_t block, blocks;
+ register size_t i;
+ struct list *prev, *next;
+
+ block = BLOCK(ptr);
+
+ type = _heapinfo[block].busy.type;
+ switch (type)
+ {
+ case 0:
+ /* Get as many statistics as early as we can. */
+ --_chunks_used;
+ _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE;
+ _bytes_free += _heapinfo[block].busy.info.size * BLOCKSIZE;
+
+ /* Find the free cluster previous to this one in the free list.
+ Start searching at the last block referenced; this may benefit
+ programs with locality of allocation. */
+ i = _heapindex;
+ if (i > block)
+ while (i > block)
+ i = _heapinfo[i].free.prev;
+ else
+ {
+ do
+ i = _heapinfo[i].free.next;
+ while (i > 0 && i < block);
+ i = _heapinfo[i].free.prev;
+ }
+
+ /* Determine how to link this block into the free list. */
+ if (block == i + _heapinfo[i].free.size)
+ {
+ /* Coalesce this block with its predecessor. */
+ _heapinfo[i].free.size += _heapinfo[block].busy.info.size;
+ block = i;
+ }
+ else
+ {
+ /* Really link this block back into the free list. */
+ _heapinfo[block].free.size = _heapinfo[block].busy.info.size;
+ _heapinfo[block].free.next = _heapinfo[i].free.next;
+ _heapinfo[block].free.prev = i;
+ _heapinfo[i].free.next = block;
+ _heapinfo[_heapinfo[block].free.next].free.prev = block;
+ ++_chunks_free;
+ }
+
+ /* Now that the block is linked in, see if we can coalesce it
+ with its successor (by deleting its successor from the list
+ and adding in its size). */
+ if (block + _heapinfo[block].free.size == _heapinfo[block].free.next)
+ {
+ _heapinfo[block].free.size
+ += _heapinfo[_heapinfo[block].free.next].free.size;
+ _heapinfo[block].free.next
+ = _heapinfo[_heapinfo[block].free.next].free.next;
+ _heapinfo[_heapinfo[block].free.next].free.prev = block;
+ --_chunks_free;
+ }
+
+ /* Now see if we can return stuff to the system. */
+ blocks = _heapinfo[block].free.size;
+ if (blocks >= FINAL_FREE_BLOCKS && block + blocks == _heaplimit
+ && (*__morecore)(0) == ADDRESS(block + blocks))
+ {
+ register size_t bytes = blocks * BLOCKSIZE;
+ _heaplimit -= blocks;
+ (*__morecore)(- bytes);
+ _heapinfo[_heapinfo[block].free.prev].free.next
+ = _heapinfo[block].free.next;
+ _heapinfo[_heapinfo[block].free.next].free.prev
+ = _heapinfo[block].free.prev;
+ block = _heapinfo[block].free.prev;
+ --_chunks_free;
+ _bytes_free -= bytes;
+ }
+
+ /* Set the next search to begin at this block. */
+ _heapindex = block;
+ break;
+
+ default:
+ /* Do some of the statistics. */
+ --_chunks_used;
+ _bytes_used -= 1 << type;
+ ++_chunks_free;
+ _bytes_free += 1 << type;
+
+ /* Get the address of the first free fragment in this block. */
+ prev = (struct list *) ((char *) ADDRESS(block) +
+ (_heapinfo[block].busy.info.frag.first << type));
+
+ if (_heapinfo[block].busy.info.frag.nfree == (BLOCKSIZE >> type) - 1)
+ {
+ /* If all fragments of this block are free, remove them
+ from the fragment list and free the whole block. */
+ next = prev;
+ for (i = 1; i < BLOCKSIZE >> type; ++i)
+ next = next->next;
+ prev->prev->next = next;
+ if (next != NULL)
+ next->prev = prev->prev;
+ _heapinfo[block].busy.type = 0;
+ _heapinfo[block].busy.info.size = 1;
+
+ /* Keep the statistics accurate. */
+ ++_chunks_used;
+ _bytes_used += BLOCKSIZE;
+ _chunks_free -= BLOCKSIZE >> type;
+ _bytes_free -= BLOCKSIZE;
+
+ free(ADDRESS(block));
+ }
+ else if (_heapinfo[block].busy.info.frag.nfree != 0)
+ {
+ /* If some fragments of this block are free, link this
+ fragment into the fragment list after the first free
+ fragment of this block. */
+ next = (struct list *) ptr;
+ next->next = prev->next;
+ next->prev = prev;
+ prev->next = next;
+ if (next->next != NULL)
+ next->next->prev = next;
+ ++_heapinfo[block].busy.info.frag.nfree;
+ }
+ else
+ {
+ /* No fragments of this block are free, so link this
+ fragment into the fragment list and announce that
+ it is the first free fragment of this block. */
+ prev = (struct list *) ptr;
+ _heapinfo[block].busy.info.frag.nfree = 1;
+ _heapinfo[block].busy.info.frag.first = (unsigned int)
+ (((char *) ptr - (char *) NULL) % BLOCKSIZE >> type);
+ prev->next = _fraghead[type].next;
+ prev->prev = &_fraghead[type];
+ prev->prev->next = prev;
+ if (prev->next != NULL)
+ prev->next->prev = prev;
+ }
+ break;
+ }
+}
+
+/* Return memory to the heap. */
+void
+DEFUN(free, (ptr), PTR ptr)
+{
+ if (ptr == NULL)
+ return;
+
+ if (__free_hook != NULL)
+ (*__free_hook)(ptr);
+ else
+ __free (ptr);
+}
+
+/* DO NOT DELETE THIS LINE -- malloc.c INSERTED HERE. */
+/* Memory allocator `malloc'.
+ Copyright 1990 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+ 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define _MALLOC_INTERNAL
+#include "malloc.h"
+#endif /* __ONEFILE */
+
+/* How to really get more memory. */
+PTR EXFUN((*__morecore), (ptrdiff_t __size)) = __default_morecore;
+
+/* Debugging hook for `malloc'. */
+PTR EXFUN((*__malloc_hook), (size_t __size));
+
+/* Pointer to the base of the first block. */
+char *_heapbase;
+
+/* Block information table. Allocated with align/__free (not malloc/free). */
+malloc_info *_heapinfo;
+
+/* Number of info entries. */
+static size_t heapsize;
+
+/* Search index in the info table. */
+size_t _heapindex;
+
+/* Limit of valid info table indices. */
+size_t _heaplimit;
+
+/* Free lists for each fragment size. */
+struct list _fraghead[BLOCKLOG];
+
+/* Instrumentation. */
+size_t _chunks_used;
+size_t _bytes_used;
+size_t _chunks_free;
+size_t _bytes_free;
+
+/* Are you experienced? */
+int __malloc_initialized;
+
+/* Aligned allocation. */
+static PTR
+DEFUN(align, (size), size_t size)
+{
+ PTR result;
+ unsigned int adj;
+
+ result = (*__morecore)(size);
+ adj = (unsigned int) ((char *) result - (char *) NULL) % BLOCKSIZE;
+ if (adj != 0)
+ {
+ adj = BLOCKSIZE - adj;
+ (void) (*__morecore)(adj);
+ result = (char *) result + adj;
+ }
+ return result;
+}
+
+/* Set everything up and remember that we have. */
+static int
+DEFUN_VOID(initialize)
+{
+ heapsize = HEAP / BLOCKSIZE;
+ _heapinfo = (malloc_info *) align(heapsize * sizeof(malloc_info));
+ if (_heapinfo == NULL)
+ return 0;
+ memset(_heapinfo, 0, heapsize * sizeof(malloc_info));
+ _heapinfo[0].free.size = 0;
+ _heapinfo[0].free.next = _heapinfo[0].free.prev = 0;
+ _heapindex = 0;
+ _heapbase = (char *) _heapinfo;
+ __malloc_initialized = 1;
+ return 1;
+}
+
+/* Get neatly aligned memory, initializing or
+ growing the heap info table as necessary. */
+static PTR
+DEFUN(morecore, (size), size_t size)
+{
+ PTR result;
+ malloc_info *newinfo, *oldinfo;
+ size_t newsize;
+
+ result = align(size);
+ if (result == NULL)
+ return NULL;
+
+ /* Check if we need to grow the info table. */
+ if (BLOCK((char *) result + size) > heapsize)
+ {
+ newsize = heapsize;
+ while (BLOCK((char *) result + size) > newsize)
+ newsize *= 2;
+ newinfo = (malloc_info *) align(newsize * sizeof(malloc_info));
+ if (newinfo == NULL)
+ {
+ (*__morecore)(- size);
+ return NULL;
+ }
+ memset(newinfo, 0, newsize * sizeof(malloc_info));
+ memcpy(newinfo, _heapinfo, heapsize * sizeof(malloc_info));
+ oldinfo = _heapinfo;
+ newinfo[BLOCK(oldinfo)].busy.type = 0;
+ newinfo[BLOCK(oldinfo)].busy.info.size
+ = BLOCKIFY(heapsize * sizeof(malloc_info));
+ _heapinfo = newinfo;
+ __free(oldinfo);
+ heapsize = newsize;
+ }
+
+ _heaplimit = BLOCK((char *) result + size);
+ return result;
+}
+
+/* Allocate memory from the heap. */
+PTR
+DEFUN(malloc, (size), size_t size)
+{
+ PTR result;
+ size_t block, blocks, lastblocks, start;
+ register size_t i;
+ struct list *next;
+
+ if (size == 0)
+ return NULL;
+
+ if (__malloc_hook != NULL)
+ return (*__malloc_hook)(size);
+
+ if (!__malloc_initialized)
+ if (!initialize())
+ return NULL;
+
+ if (size < sizeof(struct list))
+ size = sizeof(struct list);
+
+ /* Determine the allocation policy based on the request size. */
+ if (size <= BLOCKSIZE / 2)
+ {
+ /* Small allocation to receive a fragment of a block.
+ Determine the logarithm to base two of the fragment size. */
+ register size_t log = 1;
+ --size;
+ while ((size /= 2) != 0)
+ ++log;
+
+ /* Look in the fragment lists for a
+ free fragment of the desired size. */
+ next = _fraghead[log].next;
+ if (next != NULL)
+ {
+ /* There are free fragments of this size.
+ Pop a fragment out of the fragment list and return it.
+ Update the block's nfree and first counters. */
+ result = (PTR) next;
+ next->prev->next = next->next;
+ if (next->next != NULL)
+ next->next->prev = next->prev;
+ block = BLOCK(result);
+ if (--_heapinfo[block].busy.info.frag.nfree != 0)
+ _heapinfo[block].busy.info.frag.first = (unsigned int)
+ (((char *) next->next - (char *) NULL) % BLOCKSIZE) >> log;
+
+ /* Update the statistics. */
+ ++_chunks_used;
+ _bytes_used += 1 << log;
+ --_chunks_free;
+ _bytes_free -= 1 << log;
+ }
+ else
+ {
+ /* No free fragments of the desired size, so get a new block
+ and break it into fragments, returning the first. */
+ result = malloc(BLOCKSIZE);
+ if (result == NULL)
+ return NULL;
+
+ /* Link all fragments but the first into the free list. */
+ for (i = 1; i < BLOCKSIZE >> log; ++i)
+ {
+ next = (struct list *) ((char *) result + (i << log));
+ next->next = _fraghead[log].next;
+ next->prev = &_fraghead[log];
+ next->prev->next = next;
+ if (next->next != NULL)
+ next->next->prev = next;
+ }
+
+ /* Initialize the nfree and first counters for this block. */
+ block = BLOCK(result);
+ _heapinfo[block].busy.type = log;
+ _heapinfo[block].busy.info.frag.nfree = i - 1;
+ _heapinfo[block].busy.info.frag.first = i - 1;
+
+ _chunks_free += (BLOCKSIZE >> log) - 1;
+ _bytes_free += BLOCKSIZE - (1 << log);
+ }
+ }
+ else
+ {
+ /* Large allocation to receive one or more blocks.
+ Search the free list in a circle starting at the last place visited.
+ If we loop completely around without finding a large enough
+ space we will have to get more memory from the system. */
+ blocks = BLOCKIFY(size);
+ start = block = MALLOC_SEARCH_START;
+ while (_heapinfo[block].free.size < blocks)
+ {
+ block = _heapinfo[block].free.next;
+ if (block == start)
+ {
+ /* Need to get more from the system. Check to see if
+ the new core will be contiguous with the final free
+ block; if so we don't need to get as much. */
+ block = _heapinfo[0].free.prev;
+ lastblocks = _heapinfo[block].free.size;
+ if (_heaplimit != 0 && block + lastblocks == _heaplimit &&
+ (*__morecore)(0) == ADDRESS(block + lastblocks) &&
+ (morecore((blocks - lastblocks) * BLOCKSIZE)) != NULL)
+ {
+ _heapinfo[block].free.size = blocks;
+ _bytes_free += (blocks - lastblocks) * BLOCKSIZE;
+ continue;
+ }
+ result = morecore(blocks * BLOCKSIZE);
+ if (result == NULL)
+ return NULL;
+ block = BLOCK(result);
+ _heapinfo[block].busy.type = 0;
+ _heapinfo[block].busy.info.size = blocks;
+ ++_chunks_used;
+ _bytes_used += blocks * BLOCKSIZE;
+ return result;
+ }
+ }
+
+ /* At this point we have found a suitable free list entry.
+ Figure out how to remove what we need from the list. */
+ result = ADDRESS(block);
+ if (_heapinfo[block].free.size > blocks)
+ {
+ /* The block we found has a bit left over,
+ so relink the tail end back into the free list. */
+ _heapinfo[block + blocks].free.size
+ = _heapinfo[block].free.size - blocks;
+ _heapinfo[block + blocks].free.next
+ = _heapinfo[block].free.next;
+ _heapinfo[block + blocks].free.prev
+ = _heapinfo[block].free.prev;
+ _heapinfo[_heapinfo[block].free.prev].free.next
+ = _heapinfo[_heapinfo[block].free.next].free.prev
+ = _heapindex = block + blocks;
+ }
+ else
+ {
+ /* The block exactly matches our requirements,
+ so just remove it from the list. */
+ _heapinfo[_heapinfo[block].free.next].free.prev
+ = _heapinfo[block].free.prev;
+ _heapinfo[_heapinfo[block].free.prev].free.next
+ = _heapindex = _heapinfo[block].free.next;
+ --_chunks_free;
+ }
+
+ _heapinfo[block].busy.type = 0;
+ _heapinfo[block].busy.info.size = blocks;
+ ++_chunks_used;
+ _bytes_used += blocks * BLOCKSIZE;
+ _bytes_free -= blocks * BLOCKSIZE;
+ }
+
+ return result;
+}
+
+/* DO NOT DELETE THIS LINE -- realloc.c INSERTED HERE. */
+/* Change the size of a block allocated by `malloc'.
+ Copyright 1990 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+ 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stdlib.h>
+#include <string.h>
+
+#define _MALLOC_INTERNAL
+#include "malloc.h"
+#endif /* __ONEFILE */
+
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
+
+/* Debugging hook for realloc. */
+PTR EXFUN((*__realloc_hook), (PTR __ptr, size_t __size));
+
+/* Resize the given region to the new size, returning a pointer
+ to the (possibly moved) region. This is optimized for speed;
+ some benchmarks seem to indicate that greater compactness is
+ achieved by unconditionally allocating and copying to a
+ new region. This module has incestuous knowledge of the
+ internals of both free and malloc. */
+PTR
+DEFUN(realloc, (ptr, size), PTR ptr AND size_t size)
+{
+ PTR result;
+ int type;
+ size_t block, blocks, oldlimit;
+
+ if (size == 0)
+ {
+ free(ptr);
+ return NULL;
+ }
+ else if (ptr == NULL)
+ return malloc(size);
+
+ if (__realloc_hook != NULL)
+ return (*__realloc_hook)(ptr, size);
+
+ block = BLOCK(ptr);
+
+ type = _heapinfo[block].busy.type;
+ switch (type)
+ {
+ case 0:
+ /* Maybe reallocate a large block to a small fragment. */
+ if (size <= BLOCKSIZE / 2)
+ {
+ result = malloc(size);
+ if (result != NULL)
+ {
+ memcpy(result, ptr, size);
+ free(ptr);
+ return result;
+ }
+ }
+
+ /* The new size is a large allocation as well;
+ see if we can hold it in place. */
+ blocks = BLOCKIFY(size);
+ if (blocks < _heapinfo[block].busy.info.size)
+ {
+ /* The new size is smaller; return
+ excess memory to the free list. */
+ _heapinfo[block + blocks].busy.type = 0;
+ _heapinfo[block + blocks].busy.info.size
+ = _heapinfo[block].busy.info.size - blocks;
+ _heapinfo[block].busy.info.size = blocks;
+ free(ADDRESS(block + blocks));
+ result = ptr;
+ }
+ else if (blocks == _heapinfo[block].busy.info.size)
+ /* No size change necessary. */
+ result = ptr;
+ else
+ {
+ /* Won't fit, so allocate a new region that will.
+ Free the old region first in case there is sufficient
+ adjacent free space to grow without moving. */
+ blocks = _heapinfo[block].busy.info.size;
+ /* Prevent free from actually returning memory to the system. */
+ oldlimit = _heaplimit;
+ _heaplimit = 0;
+ free(ptr);
+ _heaplimit = oldlimit;
+ result = malloc(size);
+ if (result == NULL)
+ {
+ (void) malloc(blocks * BLOCKSIZE);
+ return NULL;
+ }
+ if (ptr != result)
+ memmove(result, ptr, blocks * BLOCKSIZE);
+ }
+ break;
+
+ default:
+ /* Old size is a fragment; type is logarithm
+ to base two of the fragment size. */
+ if (size > 1 << (type - 1) && size <= 1 << type)
+ /* The new size is the same kind of fragment. */
+ result = ptr;
+ else
+ {
+ /* The new size is different; allocate a new space,
+ and copy the lesser of the new size and the old. */
+ result = malloc(size);
+ if (result == NULL)
+ return NULL;
+ memcpy(result, ptr, MIN(size, 1 << type));
+ free(ptr);
+ }
+ break;
+ }
+
+ return result;
+}
+
+/* DO NOT DELETE THIS LINE -- unix.c INSERTED HERE. */
+/* unix.c - get more memory with a UNIX system call.
+ Copyright 1990 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+ 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stddef.h>
+
+#define _MALLOC_INTERNAL
+#include "malloc.h"
+#endif /* __ONEFILE */
+
+extern PTR EXFUN(sbrk, (ptrdiff_t size));
+
+PTR
+DEFUN(__default_morecore, (size), ptrdiff_t size)
+{
+ PTR result;
+
+ result = sbrk(size);
+ if (result == (PTR) -1)
+ return NULL;
+ return result;
+}
+
+#define __getpagesize getpagesize
+/* DO NOT DELETE THIS LINE -- valloc.c INSERTED HERE. */
+/* Allocate memory on a page boundary.
+ Copyright 1990 Free Software Foundation
+ Written May 1989 by Mike Haertel.
+
+ 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ The author may be reached (Email) at the address mike@ai.mit.edu,
+ or (US mail) as Mike Haertel c/o Free Software Foundation. */
+
+#ifndef __ONEFILE
+#include "ansidecl.h"
+#include <stdlib.h>
+#endif /* __ONEFILE */
+
+extern size_t EXFUN(__getpagesize, (NOARGS));
+
+static size_t pagesize;
+
+PTR
+DEFUN(valloc, (size), size_t size)
+{
+ PTR result;
+ unsigned int adj;
+
+ if (pagesize == 0)
+ pagesize = __getpagesize();
+
+ result = malloc(size + pagesize);
+ if (result == NULL)
+ return NULL;
+ adj = (unsigned int) ((char *) result - (char *) NULL) % pagesize;
+ if (adj != 0)
+ result = (char *) result + pagesize - adj;
+ return result;
+}
diff --git a/binutils/m68k-pinsn.c b/binutils/m68k-pinsn.c
index 284f335..b84a869 100644
--- a/binutils/m68k-pinsn.c
+++ b/binutils/m68k-pinsn.c
@@ -20,9 +20,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* $Id$
$Log$
- Revision 1.1 1991/03/21 21:26:45 gumby
- Initial revision
+ Revision 1.1.1.1 1991/03/21 21:26:46 gumby
+ Back from Intel with Steve
+ * Revision 1.1 1991/03/21 21:26:45 gumby
+ * Initial revision
+ *
* Revision 1.1 1991/03/13 00:34:06 chrisb
* Initial revision
*
diff --git a/binutils/ostrip.c b/binutils/ostrip.c
new file mode 100755
index 0000000..6ba318c
--- /dev/null
+++ b/binutils/ostrip.c
@@ -0,0 +1,418 @@
+/* strip certain symbols from a rel file.
+ Copyright (C) 1986, 1990 Free Software Foundation, Inc.
+
+ 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include "sysdep.h"
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "getopt.h"
+#include "bfd.h"
+
+enum strip_action {
+ strip_undef,
+ strip_all, /* strip all symbols */
+ strip_debug, /* strip all debugger symbols */
+};
+
+/* Which symbols to remove. */
+enum strip_action strip_symbols;
+
+enum locals_action {
+ locals_undef,
+ locals_start_L, /* discard locals starting with L */
+ locals_all, /* discard all locals */
+};
+
+/* Which local symbols to remove. */
+enum locals_action discard_locals;
+
+/* The name this program was run with. */
+char *program_name;
+
+struct option long_options[] = {
+ {"strip-all", 0, 0, 's'},
+ {"strip-debug", 0, 0, 'S'},
+ {"discard-all", 0, 0, 'x'},
+ {"discard-locals", 0, 0, 'X'},
+ {0, 0, 0, 0},
+};
+
+static char *target = NULL;
+
+static int fatal_error;
+
+extern char *malloc();
+extern char *mktemp();
+extern char *realloc();
+extern char *strcpy();
+extern int exit();
+extern int fprintf();
+extern int free();
+extern int getpid();
+extern int kill();
+extern int perror();
+extern int sprintf();
+extern int unlink();
+
+#ifdef __STDC__
+static int strip_bfd(bfd *ibfd, bfd *obfd);
+static int strip_file(char *filetostrip);
+static void usage(void);
+#else
+static int strip_bfd();
+static int strip_file();
+static void usage();
+#endif /* __STDC__ */
+static void copy_sections ();
+static void setup_sections ();
+
+int main(argc, argv)
+char **argv;
+int argc;
+{
+ int ind;
+ int c;
+ program_name = argv[0];
+
+ strip_symbols = strip_undef; /* default is to strip everything. */
+ discard_locals = locals_undef;
+
+ while ((c = getopt_long (argc, argv, "gsST:xX", long_options, &ind)) != EOF) {
+ switch (c) {
+ case 0:
+ break;
+ case 's':
+ strip_symbols = strip_all;
+ break;
+ case 'g':
+ case 'S':
+ strip_symbols = strip_debug;
+ break;
+ case 'T':
+ target = optarg;
+ break;
+ case 'x':
+ discard_locals = locals_all;
+ break;
+ case 'X':
+ discard_locals = locals_start_L;
+ break;
+ default:
+ usage ();
+ } /* switch on option */
+ } /* for each option */
+
+ if (strip_symbols == strip_undef && discard_locals == locals_undef) {
+ strip_symbols = strip_all;
+ } /* Default is to strip all symbols. */
+
+
+ if (argc == optind) {
+ return(strip_file("a.out"));
+ } else {
+ int retval = 0;
+
+ for ( ; optind < argc; ++optind) {
+ retval &= strip_file(argv[optind]);
+ } /* for each file to strip */
+
+ return(retval);
+ } /* if no arguments given */
+
+} /* main() */
+
+static int delayed_signal;
+
+void delay_signal(signo)
+int signo;
+{
+ delayed_signal = signo;
+ signal(signo, delay_signal);
+} /* delay_signal() */
+
+static int sigint_handled = 0;
+static int sighup_handled = 0;
+static int sigterm_handled = 0;
+
+void handle_sigs() {
+ /* Effectively defer handling of asynchronous kill signals. */
+ delayed_signal = 0;
+
+ if (signal (SIGINT, SIG_IGN) != SIG_IGN) {
+ sigint_handled = 1;
+ signal(SIGINT, delay_signal);
+ } /* if not ignored */
+
+ if (signal (SIGHUP, SIG_IGN) != SIG_IGN) {
+ sighup_handled = 1;
+ signal(SIGHUP, delay_signal);
+ } /* if not ignored */
+
+ if (signal (SIGTERM, SIG_IGN) != SIG_IGN) {
+ sigterm_handled = 1;
+ signal(SIGTERM, delay_signal);
+ } /* if not ignored */
+
+ return;
+} /* handle_sigs() */
+
+void unhandle_sigs() {
+ /* Effectively undefer handling. */
+ if (sigint_handled)
+ signal (SIGINT, SIG_DFL);
+ if (sighup_handled)
+ signal (SIGHUP, SIG_DFL);
+ if (sigterm_handled)
+ signal (SIGTERM, SIG_DFL);
+
+ /* Handle any signal that came in while they were deferred. */
+ if (delayed_signal)
+ kill (getpid (), delayed_signal);
+
+ return;
+} /* unhandle_sigs() */
+
+static int strip_file(filetostrip)
+char *filetostrip;
+{
+ bfd *ibfd;
+ bfd *obfd;
+ char tmpfilename[] = "stXXXXXX";
+
+ if ((ibfd = bfd_openr(filetostrip, (char *)NULL)) == NULL) {
+ bfd_perror(filetostrip);
+ return(1);
+ } /* on error opening input */
+
+ obfd = bfd_openw(mktemp(tmpfilename),
+ target? target: bfd_get_target (ibfd));
+ if (obfd == NULL) {
+ bfd_perror(tmpfilename);
+
+ if (bfd_close(ibfd) == false) {
+ bfd_perror(bfd_get_filename(ibfd));
+ } /* on close error */
+
+ return(1);
+ } /* on error opening output */
+
+ handle_sigs();
+
+ if (bfd_check_format(ibfd, bfd_object) != false) {
+ if (bfd_set_format(obfd, bfd_get_format(ibfd)) != false) {
+ if (!strip_bfd(ibfd, obfd)) {
+ /* success */
+
+ if (bfd_close(ibfd) == false) {
+ bfd_perror(bfd_get_filename(ibfd));
+ } /* on close error */
+
+ if (bfd_close(obfd) == false) {
+ bfd_perror(bfd_get_filename(obfd));
+ } /* on close error */
+
+ rename(tmpfilename, filetostrip);
+ unhandle_sigs();
+ return(0);
+ } /* strip_bfd prints it's own failing messages */
+ } else {
+ bfd_perror(filetostrip);
+ } /* can't set format */
+ } else {
+ /* not an object file */
+ (void) fprintf(stderr, "File %s has format 0x%x that will not be stripped.\n",
+ filetostrip, (unsigned) bfd_get_format(ibfd));
+ } /* if anything fails along the way */
+
+
+ if (bfd_close(ibfd) == false) {
+ bfd_perror(bfd_get_filename(ibfd));
+ } /* on close error */
+
+ if (bfd_close(obfd) == false) {
+ bfd_perror(bfd_get_filename(obfd));
+ } /* on close error */
+
+ if (unlink(tmpfilename)) {
+ perror(tmpfilename);
+ } /* on error */
+
+ unhandle_sigs();
+
+ return(1);
+} /* strip_file() */
+
+
+boolean
+bfd_set_start_address (abfd, new_address)
+ bfd *abfd;
+ bfd_vma new_address;
+{
+ bfd_get_start_address (abfd) = new_address;
+ return true;
+}
+
+
+
+static int
+strip_bfd(ibfd, obfd)
+ bfd *ibfd;
+ bfd *obfd;
+{
+ if (bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false
+ || bfd_set_file_flags(obfd, bfd_get_file_flags(ibfd) & ~(HAS_LINENO | HAS_DEBUG | HAS_SYMS | HAS_LOCALS)) == false
+ || bfd_set_start_address(obfd, bfd_get_start_address(ibfd)) == false) {
+ bfd_perror(bfd_get_filename(ibfd));
+ return(1);
+ } /* on error setting file attributes */
+
+ /* bfd mandates that all output sections be created and sizes set before
+ any output is done. Thus, we traverse all sections twice. */
+
+ fatal_error = 0;
+ bfd_map_over_sections (ibfd, setup_sections, (void *)obfd);
+ if (!fatal_error)
+ bfd_map_over_sections (ibfd, copy_sections, (void *)obfd);
+ return fatal_error;
+}
+
+static void
+setup_sections(ibfd, isection, obfd)
+bfd *ibfd;
+sec_ptr isection;
+bfd *obfd;
+{
+ sec_ptr osection;
+ char *err;
+
+ do {
+ err = "making";
+ osection = bfd_make_section(obfd, bfd_section_name(ibfd, isection));
+ if (osection == NULL)
+ break;
+ err = "size";
+ if (!bfd_set_section_size(obfd, osection,
+ bfd_section_size(ibfd, isection)))
+ break;
+ err = "vma";
+ if (!bfd_set_section_vma(obfd, osection,
+ bfd_section_vma(ibfd, isection)))
+ break;
+ err = "alignment";
+ if (!bfd_set_section_alignment(obfd, osection,
+ bfd_section_alignment(ibfd, isection)))
+ break;
+ err = "flags";
+ if (!bfd_set_section_flags(obfd, osection,
+ bfd_get_section_flags(ibfd, isection)))
+ break;
+ return;
+ } while (0);
+
+ (void) fprintf(stderr, "file \"%s\", section \"%s\": error in %s: ",
+ bfd_get_filename(ibfd),
+ bfd_section_name(ibfd, isection),
+ err);
+
+ bfd_perror("");
+ fatal_error = 1;
+}
+
+static void
+copy_sections(ibfd, isection, obfd)
+bfd *ibfd;
+sec_ptr isection;
+bfd *obfd;
+{
+ static char *memhunk = NULL;
+ static unsigned memhunksize = 0;
+
+ sec_ptr osection;
+ unsigned long size;
+ flagword iflg;
+ char *temp;
+
+ osection = bfd_get_section_by_name (obfd,
+ bfd_section_name(ibfd, isection));
+
+ size = bfd_section_size(ibfd, isection);
+ iflg = bfd_get_section_flags(ibfd, isection);
+
+ /* either:
+ we don't need any memory because there's nothing in this section,
+ we had no memory so we got some,
+ we had some memory but not enough so we got more,
+ or we fail to allocat. */
+
+ if (size == 0)
+ return;
+
+ if (memhunk == NULL) {
+ memhunk = malloc (size);
+ memhunksize = size;
+ }
+
+ if (size > memhunksize) {
+ temp = realloc (memhunk, size);
+ memhunksize = size;
+ if (!temp) /* If realloc failed, blow away our mem */
+ free (memhunk);
+ memhunk = temp;
+ }
+
+ if (memhunk == NULL) {
+ /* failed to allocate or reallocate */
+ /* FIXME, we should just copy in pieces. */
+ (void) fprintf(stderr,
+ "Could not allocate %lu bytes in which to copy section.\n", size);
+ return;
+ }
+
+ /* now we have enough memory */
+
+ if (!bfd_get_section_contents(ibfd, isection, memhunk, 0, size)) {
+ bfd_perror(bfd_get_filename(ibfd));
+ fatal_error = 1;
+ return;
+ }
+ if (!bfd_set_section_contents(obfd, osection, memhunk, 0, size)) {
+ bfd_perror(bfd_get_filename(obfd));
+ fatal_error = 1;
+ return;
+ }
+}
+
+void
+usage ()
+{
+ fprintf (stderr, "\
+Usage: %s [-gsxSX] [+strip-all] [+strip-debug] [+discard-all]\n\
+ [+discard-locals] file...\n", program_name);
+ exit (1);
+}
+
+/*
+ * Local Variables:
+ * comment-column: 0
+ * fill-column: 131
+ * End:
+ */
+
+/* end of strip.c */
diff --git a/binutils/sparc-pinsn.c b/binutils/sparc-pinsn.c
index 550722b..041cade 100644
--- a/binutils/sparc-pinsn.c
+++ b/binutils/sparc-pinsn.c
@@ -20,9 +20,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/* $Id$
$Log$
- Revision 1.1 1991/03/21 21:26:55 gumby
- Initial revision
+ Revision 1.1.1.1 1991/03/21 21:26:56 gumby
+ Back from Intel with Steve
+ * Revision 1.1 1991/03/21 21:26:55 gumby
+ * Initial revision
+ *
* Revision 1.1 1991/03/13 00:34:40 chrisb
* Initial revision
*
diff --git a/binutils/strip.c b/binutils/strip.c
new file mode 100755
index 0000000..cd0f3af
--- /dev/null
+++ b/binutils/strip.c
@@ -0,0 +1,364 @@
+/*** strip.c -- strip certain symbols from a rel file.
+ Copyright (C) 1986, 1990 Free Software Foundation, Inc.
+
+ 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 1, 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* BUGS: When there's not enough memory, this should do the copy
+ in pieces rather than just fail as it does now */
+
+#include "sysdep.h"
+#include "bfd.h"
+
+#include "getopt.h"
+
+
+
+#include <signal.h>
+
+/* Various program options */
+
+int show_version = 0;
+
+/* Which symbols to remove. */
+enum strip_action {
+ strip_undef,
+ strip_all, /* strip all symbols */
+ strip_debug, /* strip all debugger symbols */
+} strip_symbols;
+
+/* Which local symbols to remove. */
+enum {
+ locals_undef,
+ locals_start_L, /* discard locals starting with L */
+ locals_all, /* discard all locals */
+} discard_locals;
+
+extern char *mktemp();
+
+/* IMPORTS */
+extern char *program_version;
+extern char *program_name;
+extern char *target;
+extern char *xmalloc();
+
+PROTO(static boolean, strip_file, (char *filetostrip));
+PROTO(static void, copy_sections, (bfd *ibfd, sec_ptr isection, bfd *obfd));
+PROTO(static void, setup_sections, (bfd *ibfd, sec_ptr isection, bfd *obfd));
+
+/** main, etc */
+
+static void
+usage ()
+{
+ fprintf (stderr, "strip %s\nUsage: %s [-gsxSX] files ...\n",
+ program_version, program_name);
+ exit (1);
+}
+
+struct option long_options[] = {{"strip-all", 0, 0, 's'},
+ {"strip-debug", 0, 0, 'S'},
+ {"discard-all", 0, 0, 'x'},
+ {"discard-locals", 0, 0, 'X'},
+ {0, 0, 0, 0}
+ };
+
+int
+main (argc, argv)
+ char **argv;
+ int argc;
+{
+ int ind;
+ int c;
+ program_name = argv[0];
+
+ strip_symbols = strip_undef; /* default is to strip everything. */
+ discard_locals = locals_undef;
+
+ while ((c = getopt_long (argc, argv, "gsST:xX", long_options, &ind)) != EOF) {
+ switch (c) {
+ case 0:
+ break;
+ case 's':
+ strip_symbols = strip_all;
+ break;
+ case 'g':
+ case 'S':
+ strip_symbols = strip_debug;
+ break;
+ case 'T':
+ target = optarg;
+ break;
+ case 'x':
+ discard_locals = locals_all;
+ break;
+ case 'X':
+ discard_locals = locals_start_L;
+ break;
+ default:
+ usage ();
+ }
+ }
+
+ /* Default is to strip all symbols: */
+ if (strip_symbols == strip_undef && discard_locals == locals_undef) {
+ strip_symbols = strip_all;
+ }
+
+ /* OK, all options now parsed. If no filename specified, do a.out. */
+ if (optind == argc) return !strip_file ("a.out");
+
+ /* We were given several filenames to do: */
+ while (optind < argc)
+ if (!strip_file (argv[optind++])) return 1;
+
+ return 0;
+}
+
+/** Hack signals */
+
+/* Why does strip need to do this, and anyway, if it does shouldn't this be
+ handled by bfd? */
+
+static int delayed_signal;
+
+static int sigint_handled = 0;
+static int sighup_handled = 0;
+static int sigterm_handled = 0;
+
+void
+delay_signal (signo)
+ int signo;
+{
+ delayed_signal = signo;
+ signal (signo, delay_signal);
+}
+
+/* Effectively defer handling of asynchronous kill signals. */
+void
+handle_sigs () /* puff puff */
+{
+ delayed_signal = 0;
+
+ if (signal (SIGINT, SIG_IGN) != SIG_IGN) {
+ sigint_handled = 1;
+ signal (SIGINT, delay_signal);
+ }
+
+ if (signal (SIGHUP, SIG_IGN) != SIG_IGN) {
+ sighup_handled = 1;
+ signal (SIGHUP, delay_signal);
+ }
+
+ if (signal (SIGTERM, SIG_IGN) != SIG_IGN) {
+ sigterm_handled = 1;
+ signal (SIGTERM, delay_signal);
+ }
+
+ return;
+}
+
+/* Effectively undefer handling. */
+void
+unhandle_sigs () /* put them down */
+{
+ if (sigint_handled) signal (SIGINT, SIG_DFL);
+
+ if (sighup_handled) signal (SIGHUP, SIG_DFL);
+
+ if (sigterm_handled) signal (SIGTERM, SIG_DFL);
+
+ /* Handle any signal that came in while they were deferred. */
+ if (delayed_signal)
+ kill (getpid (), delayed_signal);
+
+ return;
+}
+
+
+static boolean
+strip_file (filetostrip)
+ char *filetostrip;
+{
+ static char template[] = "stXXXXXX";
+ char *slash;
+ char *tmpname;
+ bfd *ibfd;
+ bfd *obfd;
+
+ ibfd = bfd_openr (filetostrip, target);
+
+ if (ibfd == NULL) bfd_fatal (filetostrip);
+
+ handle_sigs (); /* light up */
+
+ if (!bfd_check_format (ibfd, bfd_object)) {
+ fprintf (stderr, "Can't strip %s file %s.\n",
+ bfd_format_string (bfd_get_format (ibfd)), filetostrip);
+ exit (1);
+ }
+
+ slash = strrchr( filetostrip, '/' );
+ if ( slash ){
+ *slash = 0;
+ tmpname = xmalloc( strlen(filetostrip) + sizeof(template) + 1 );
+ strcpy( tmpname, filetostrip );
+ strcat( tmpname, "/" );
+ strcat( tmpname, template );
+ mktemp( tmpname );
+ *slash = '/';
+ } else {
+ tmpname = xmalloc( sizeof(template) );
+ strcpy( tmpname, template );
+ mktemp( tmpname );
+ }
+
+ obfd = bfd_openw (mktemp(tmpname), (target ? target : bfd_get_target (ibfd)));
+ if (obfd == NULL) bfd_fatal (tmpname);
+
+ if (!bfd_set_format (obfd, bfd_get_format (ibfd)))
+ bfd_fatal (tmpname);
+
+
+ if ((bfd_set_start_address (obfd, bfd_get_start_address (ibfd)) == false) ||
+ (bfd_set_file_flags (obfd, (bfd_get_file_flags (ibfd) &
+ ~(HAS_LINENO | HAS_DEBUG | HAS_SYMS |
+ HAS_LOCALS))) == false) ||
+ bfd_set_start_address (obfd, bfd_get_start_address (ibfd)) == false)
+ bfd_fatal (bfd_get_filename (ibfd));
+
+ /* Copy architecture of input file to output file */
+ if (!bfd_set_arch_mach (obfd, bfd_get_architecture (ibfd),
+ bfd_get_machine (ibfd))) {
+ fprintf(stderr, "Output file cannot represent architecture %s",
+ bfd_printable_arch_mach (bfd_get_architecture(ibfd),
+ bfd_get_machine (ibfd)));
+ }
+
+
+ /* bfd mandates that all output sections be created and sizes set before
+ any output is done. Thus, we traverse all sections twice. */
+ bfd_map_over_sections (ibfd, setup_sections, (void *)obfd);
+ bfd_map_over_sections (ibfd, copy_sections, (void *)obfd);
+
+ if (!bfd_close (obfd)) bfd_fatal (filetostrip);
+ if (!bfd_close (ibfd)) bfd_fatal (filetostrip);
+
+ rename(tmpname, filetostrip);
+ free(tmpname);
+
+ unhandle_sigs();
+
+ return true;
+}
+
+/** Actually do the work */
+static void
+setup_sections (ibfd, isection, obfd)
+ bfd *ibfd;
+ sec_ptr isection;
+ bfd *obfd;
+{
+ sec_ptr osection;
+ char *err;
+
+ osection = bfd_make_section (obfd, bfd_section_name (ibfd, isection));
+ if (osection == NULL) {
+ err = "making";
+ goto loser;
+ }
+
+ if (!bfd_set_section_size(obfd, osection, bfd_section_size(ibfd, isection))) {
+ err = "size";
+ goto loser;
+ }
+
+ if (!bfd_set_section_vma (obfd, osection, bfd_section_vma (ibfd, isection))) {
+ err = "vma";
+ goto loser;
+ }
+
+ if (bfd_set_section_alignment (obfd, osection,
+ bfd_section_alignment (ibfd, isection))
+ != true) {
+ err = "alignment";
+ goto loser;
+ } /* on error, I presume. */
+
+ if (!bfd_set_section_flags (obfd, osection,
+ bfd_get_section_flags (ibfd, isection))) {
+ err = "flags";
+ goto loser;
+ }
+
+ /* All went well */
+ return;
+
+ loser:
+ fprintf (stderr, "%s: file \"%s\", section \"%s\": error in %s: %s\n",
+ program_name,
+ bfd_get_filename (ibfd), bfd_section_name (ibfd, isection),
+ err, bfd_errmsg (bfd_error));
+ exit (1);
+}
+
+static void
+copy_sections (ibfd, isection, obfd)
+ bfd *ibfd;
+ sec_ptr isection;
+ bfd *obfd;
+{
+ static unsigned char *memhunk = NULL;
+ static unsigned memhunksize = 0;
+
+ sec_ptr osection;
+ unsigned long size;
+ flagword iflg;
+ unsigned char *temp;
+
+ osection = bfd_get_section_by_name (obfd, bfd_section_name (ibfd, isection));
+
+ size = bfd_section_size (ibfd, isection);
+ iflg = bfd_get_section_flags (ibfd, isection);
+
+ /* either:
+ we don't need any memory because there's nothing in this section,
+ we had no memory so we got some,
+ we had some memory but not enough so we got more,
+ or we fail to allocat. */
+
+ if (size == 0)
+ return;
+
+ if ((iflg & SEC_HAS_CONTENTS) == 0)
+ return;
+
+ if (memhunk == NULL) {
+ memhunk = (unsigned char *) xmalloc (size);
+ memhunksize = size;
+ }
+
+ if (size > memhunksize) {
+ temp = (unsigned char *) xrealloc ((char *) memhunk, size);
+ memhunksize = size;
+ memhunk = temp;
+ }
+
+ /* now we have enough memory, just do it: */
+ if (!bfd_get_section_contents (ibfd, isection, memhunk, 0, size))
+ bfd_fatal (bfd_get_filename (ibfd));
+
+ if (!bfd_set_section_contents (obfd, osection, memhunk, 0, size))
+ bfd_fatal (bfd_get_filename (obfd));
+}
diff --git a/ld/config.h b/ld/config.h
new file mode 100644
index 0000000..756956c
--- /dev/null
+++ b/ld/config.h
@@ -0,0 +1,40 @@
+/* config.h -
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+ This file is part of GLD, the Gnu Linker.
+
+ GLD 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 1, or (at your option)
+ any later version.
+
+ GLD 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 GLD; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Look in this environment name for the linker to pretend to be */
+#define EMULATION_ENVIRON "LDEMULATION"
+/* If in there look for the strings: */
+#define GLD_EMULATION_NAME "gld"
+#define GLD960_EMULATION_NAME "gld960"
+#define LNK960_EMULATION_NAME "lnk960"
+/* Otherwise default to this emulation */
+#define DEFAULT_EMULATION GLD960_EMULATION_NAME
+
+
+/* Look in this variable for a target format */
+#define TARGET_ENVIRON "GNUTARGET"
+/* If not there then choose this */
+#define GLD_TARGET "a.out-generic-big"
+#define LNK960_TARGET "coff-Intel-big"
+#define GLD960_TARGET "b.out.big"
+
+
+
+
diff --git a/ld/ld-emul.c b/ld/ld-emul.c
index 7eb23d4..c644a7c 100755
--- a/ld/ld-emul.c
+++ b/ld/ld-emul.c
@@ -22,9 +22,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
$Id$
$Log$
- Revision 1.1 1991/03/21 21:28:19 gumby
- Initial revision
+ Revision 1.1.1.1 1991/03/21 21:28:20 gumby
+ Back from Intel with Steve
+ * Revision 1.1 1991/03/21 21:28:19 gumby
+ * Initial revision
+ *
* Revision 1.1 1991/03/13 00:48:09 chrisb
* Initial revision
*
diff --git a/ld/ld-gld.c b/ld/ld-gld.c
index 4c3df1a..34d7fd6 100755
--- a/ld/ld-gld.c
+++ b/ld/ld-gld.c
@@ -20,8 +20,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
* $Id$
*
* $Log$
- * Revision 1.1 1991/03/21 21:28:24 gumby
- * Initial revision
+ * Revision 1.1.1.1 1991/03/21 21:28:25 gumby
+ * Back from Intel with Steve
+ *
+ * Revision 1.1 1991/03/21 21:28:24 gumby
+ * Initial revision
*
* Revision 1.2 1991/03/15 18:45:55 rich
* foo
diff --git a/ld/ld-gld960.c b/ld/ld-gld960.c
index 5e0c1a2..d2ac6bc 100755
--- a/ld/ld-gld960.c
+++ b/ld/ld-gld960.c
@@ -20,9 +20,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
$Id$
$Log$
- Revision 1.1 1991/03/21 21:28:26 gumby
- Initial revision
+ Revision 1.1.1.1 1991/03/21 21:28:27 gumby
+ Back from Intel with Steve
+ * Revision 1.1 1991/03/21 21:28:26 gumby
+ * Initial revision
+ *
* Revision 1.3 1991/03/16 22:27:24 rich
* fish
*
diff --git a/ld/ld-lnk960.c b/ld/ld-lnk960.c
index 0f82ebe..173bbdf 100755
--- a/ld/ld-lnk960.c
+++ b/ld/ld-lnk960.c
@@ -20,9 +20,12 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
$Id$
$Log$
- Revision 1.1 1991/03/21 21:28:28 gumby
- Initial revision
+ Revision 1.1.1.1 1991/03/21 21:28:29 gumby
+ Back from Intel with Steve
+ * Revision 1.1 1991/03/21 21:28:28 gumby
+ * Initial revision
+ *
* Revision 1.2 1991/03/15 18:45:55 rich
* foo
*
diff --git a/ld/ld.tex b/ld/ld.tex
new file mode 100755
index 0000000..1764ad5
--- /dev/null
+++ b/ld/ld.tex
@@ -0,0 +1,1014 @@
+\input texinfo
+@parindent=0pt
+@setfilename gld
+@c @@setchapternewpage odd
+@settitle GLD, The GNU linker
+@titlepage
+@title{gld}
+@subtitle{The gnu loader}
+@sp 1
+@subtitle Second Edition---gld version 2.0
+@subtitle January 1991
+@vskip 0pt plus 1filll
+Copyright @copyright{} 1991 Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided also that
+the entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this manual
+into another language, under the above conditions for modified versions.
+
+@author {Steve Chamberlain}
+@author {Cygnus Support}
+@author {steve@@cygnus.com}
+@end titlepage
+
+@node Top,,,
+@comment node-name, next, previous, up
+@ifinfo
+This file documents the GNU linker gld.
+@end ifinfo
+
+@c chapter What does a linker do ?
+@c chapter Command Language
+@noindent
+@chapter Overview
+
+
+The @code{gld} command combines a number of object and archive files,
+relocates their data and ties up symbol references. Often the last
+step in building a new compiled program to run is a call to @code{gld}.
+
+The @code{gld} command accepts Linker Command Language files in
+a superset of AT+T's Link Editor Command Language syntax,
+to provide explict and total control over the linking process.
+
+This version of @code{gld} uses the general purpose @code{bfd} libraries
+to operate on object files. This allows @code{gld} to read and
+write any of the formats supported by @code{bfd}, different
+formats may be linked together producing any available object file.
+
+Supported formats:
+@itemize @bullet
+@item
+Sun3 68k a.out
+@item
+IEEE-695 68k Object Module Format
+@item
+Oasys 68k Binary Relocatable Object File Format
+@item
+Sun4 sparc a.out
+@item
+88k bcs coff
+@item
+i960 coff little endian
+@item
+i960 coff big endian
+@item
+i960 b.out little endian
+@item
+i960 b.out big endian
+@item
+s-records
+@end itemize
+
+When linking similar formats, @code{gld} maintains all debugging
+information.
+
+@chapter Command line options
+
+@example
+ gld [ -Bstatic ] [ -D @var{datasize} ]
+ [ -c @var{filename} ]
+ [ -d ] | [ -dc ] | [ -dp ]
+ [ -i ]
+ [ -e @var{entry} ] [ -l @var{arch} ] [ -L @var{searchdir} ] [ -M ]
+ [ -N | -n | -z ] [ -noinhibit-exec ] [ -r ] [ -S ] [ -s ]
+ [ -f @var{fill} ]
+ [ -T @var{textorg} ] [ -Tdata @var{dataorg} ] [ -t ] [ -u @var{sym}]
+ [ -X ] [ -x ]
+ [-o @var{output} ] @var{objfiles}@dots{}
+@end example
+
+Command-line options to GNU @code{gld} may be specified in any order, and
+may be repeated at will. For the most part, repeating an option with a
+different argument will either have no further effect, or override prior
+occurrences (those further to the left on the command line) of an
+option.
+
+The exceptions which may meaningfully be present several times
+are @code{-L}, @code{-l}, and @code{-u}.
+
+@var{objfiles} may follow, precede, or be mixed in with
+command-line options; save that an @var{objfiles} argument may not be
+placed between an option flag and its argument.
+
+Option arguments must follow the option letter without intervening
+whitespace, or be given as separate arguments immediately following the
+option that requires them.
+
+@table @code
+@item @var{objfiles}@dots{}
+The object files @var{objfiles} to be linked; at least one must be specified.
+
+@item -Bstatic
+This flag is accepted for command-line compatibility with the SunOS linker,
+but has no effect on @code{gld}.
+
+@item -c @var{commandfile}
+Directs @code{gld} to read linkage commands from the file @var{commandfile}.
+
+@item -D @var{datasize}
+Use this option to specify a target size for the @code{data} segment of
+your linked program. The option is only obeyed if @var{datasize} is
+larger than the natural size of the program's @code{data} segment.
+
+@var{datasize} must be an integer specified in hexadecimal.
+
+@code{ld} will simply increase the size of the @code{data} segment,
+padding the created gap with zeros, and reduce the size of the
+@code{bss} segment to match.
+
+@item -d
+Force @code{ld} to assign space to common symbols
+even if a relocatable output file is specified (@code{-r}).
+
+@item -dc | -dp
+This flags is accepted for command-line compatibility with the SunOS linker,
+but has no effect on @code{gld}.
+
+@item -e @var{entry}
+Use @var{entry} as the explicit symbol for beginning execution of your
+program, rather than the default entry point. If this symbol is
+not specified, the symbol @code{start} is used as the entry address.
+If there is no symbol called @code{start}, then the entry address
+is set to the first address in the first output section
+(usually the @samp{text} section).
+
+@item -f @var{fill}
+Sets the default fill pattern for ``holes'' in the output file to
+the lowest two bytes of the expression specified.
+
+@item -i
+Produce an incremental link (same as option @code{-r}).
+
+@item -l @var{arch}
+Add an archive file @var{arch} to the list of files to link. This
+option may be used any number of times. @code{ld} will search its
+path-list for occurrences of @code{lib@var{arch}.a} for every @var{arch}
+specified.
+
+@c This also has a side effect of using the "c++ demangler" if we happen
+@c to specify -llibg++. Document? pesch@@cygnus.com, 24jan91
+
+@item -L @var{searchdir}
+This command adds path @var{searchdir} to the
+list of paths that @code{gld} will search for archive libraries. You
+may use this option any number of times.
+
+@c Should we make any attempt to list the standard paths searched
+@c without listing? When hacking on a new system I often want to know
+@c this, but this may not be the place... it's not constant across
+@c systems, of course, which is what makes it interesting.
+@c pesch@@cygnus.com, 24jan91.
+
+@item -M
+@itemx -m
+Print (to the standard output file) a link map---diagnostic information
+about where symbols are mapped by @code{ld}, and information on global
+common storage allocation.
+
+@item -N
+specifies read and writable @code{text} and @code{data} sections. If
+the output format supports Unix style magic numbers, then OMAGIC is set.
+
+@item -n
+sets the text segment to be read only, and @code{NMAGIC} is written
+if possible.
+
+@item -o @var{output}
+@var{output} is a name for the program produced by @code{ld}; if this
+option is not specified, the name @samp{a.out} is used by default.
+
+@item -r
+Generates relocatable output---i.e., generate an output file that can in
+turn serve as input to @code{gld}. As a side effect, this option also
+sets the output file's magic number to @code{OMAGIC}; see @samp{-N}. If this
+option is not specified, an absolute file is produced.
+
+@item -S
+Omits debugger symbol information (but not all symbols) from the output file.
+
+@item -s
+Omits all symbol information from the output file.
+
+@item -T @var{textorg}
+@itemx -Ttext @var{textorg}
+Use @var{textorg} as the starting address for the @code{text} segment of the
+output file. Both forms of this option are equivalent. The option
+argument must be a hexadecimal integer.
+
+@item -Tdata @var{dataorg}
+Use @var{dataorg} as the starting address for the @code{data} segment of
+the output file. The option argument must be a hexadecimal integer.
+
+@item -t
+Prints names of input files as @code{ld} processes them.
+
+@item -u @var{sym}
+Forces @var{sym} to be entered in the output file as an undefined symbol.
+This may, for example, trigger linking of additional modules from
+standard libraries. @code{-u} may be repeated with different option
+arguments to enter additional undefined symbols. This option is equivalent
+to the @code{EXTERN} linker command.
+
+@item -X
+If @code{-s} or @code{-S} is also specified, delete only local symbols
+beginning with @samp{L}.
+
+@item -z
+@code{-z} sets @code{ZMAGIC}, the default: the @code{text} segment is
+read-only, demand pageable, and shared.
+
+Specifying a relocatable output file (@code{-r}) will also set the magic
+number to @code{OMAGIC}.
+
+See description of @samp{-N}.
+
+
+@end table
+@chapter Command Language
+
+
+The command language allows explicit control over the linkage process, allowing
+specification of:
+@table @bullet
+@item input files
+@item file formats
+@item output file format
+@item addresses of sections
+@item placement of common blocks
+@item and more
+@end table
+
+A command file may be supplied to the linker, either explicitly through the
+@code{-c} option, or implicitly as an ordinary file. If the linker opens
+a file which does not have a reasonable object or archive format, it tries
+to read the file as if it were a command file.
+@section Structure
+To be added
+
+@section Expressions
+The syntax for expressions in the command language is identical to that of
+C expressions, with the following features:
+@table @bullet
+@item All expressions evaluated as integers and
+are of ``long'' or ``unsigned long'' type.
+@item All constants are integers.
+@item All of the C arithmetic operators are provided.
+@item Global variables may be referenced, defined and created.
+@item Build in functions may be called.
+@end table
+
+@section Expressions
+
+The linker has a practice of ``lazy evaluation'' for expressions; it only
+calculates an expression when absolutely necessary. For instance,
+when the linker reads in the command file it has to know the values
+of the start address and the length of the memory regions for linkage to continue, so these
+values are worked out, but other values (such as symbol values) are not
+known or needed until after storage allocation.
+They are evaluated later, when the other
+information, such as the sizes of output sections are available for use in
+the symbol assignment expression.
+
+When a linker expression is evaluated and assigned to a variable it is given
+either an absolute or a relocatable type. An absolute expression type
+is one in which the symbol contains the value that it will have in the
+output file, a relocateable expression type is one in which the value
+is expressed as a fixed offset from the base of a section.
+
+The type of the expression is controlled by its position in the script
+file. A symbol assigned within a @code{SECTION} specification is
+created relative to the base of the section, a symbol assigned in any
+other place is created as an absolute symbol. Since a symbol created
+within a @code{SECTION} specification is relative to the base of the
+section it will remain relocatable if relocatable output is requested.
+A symbol may be created with an absolute value even when assigned to
+within a @code{SECTION} specification by using the absolute assignment
+function @code{ABSOLUTE} For example, to create an absolute symbol
+whose address is the last byte of the output section @code{.data}:
+@example
+.data :
+ @{
+ *(.data)
+ _edata = ABSOLUTE(.) ;
+ @}
+@end example
+
+Unless quoted, symbol names start with a letter, underscore, point or
+minus sign and may include any letters, underscores, digits, points,
+and minus signs. Unquoted symbol names must not conflict with any
+keywords. To specify a symbol which contains odd characters or has
+the same name as a keyword surround it in double quotes:
+@example
+ ``SECTION'' = 9;
+ ``with a space'' = ``also with a space'' + 10;
+@end example
+
+@subsection Integers
+An octal integer is @samp{0} followed by zero or more of the octal
+digits (@samp{01234567}).
+
+A decimal integer starts with a non-zero digit followed by zero or
+more digits (@samp{0123456789}).
+
+A hexadecimal integer is @samp{0x} or @samp{0X} followed by one or
+more hexadecimal digits chosen from @samp{0123456789abcdefABCDEF}.
+
+Integers have the usual values. To denote a negative integer, use
+the unary operator @samp{-} discussed under expressions.
+
+Additionally the suffixes @code{K} and @code{M} may be used to multiply the
+previous constant by 1024 or
+@tex
+$1024^2$
+@end tex
+respectively.
+
+@example
+ _as_decimal = 57005;
+ _as_hex = 0xdead;
+ _as_octal = 0157255;
+
+ _4k_1 = 4K;
+ _4k_2 = 4096;
+ _4k_3 = 0x1000;
+@end example
+@subsection Operators
+The linker provides the standard C set of arithmetic operators, with
+the standard bindings and precedence levels:
+@example
+
+@end example
+@tex
+
+\vbox{\offinterlineskip
+\hrule
+\halign
+{\vrule#&\hfil#\hfil&\vrule#&\hfil#\hfil&\vrule#&\hfil#\hfil&\vrule#\cr
+height2pt&&&&&\cr
+&Level&& associativity &&Operators&\cr
+height2pt&&&&&\cr
+\noalign{\hrule}
+height2pt&&&&&\cr
+&highest&&&&&&\cr
+&1&&left&&$ ! - ~$&\cr
+height2pt&&&&&\cr
+&2&&left&&* / \%&\cr
+height2pt&&&&&\cr
+&3&&left&&+ -&\cr
+height2pt&&&&&\cr
+&4&&left&&$>> <<$&\cr
+height2pt&&&&&\cr
+&5&&left&&$== != > < <= >=$&\cr
+height2pt&&&&&\cr
+&6&&left&&\&&\cr
+height2pt&&&&&\cr
+&7&&left&&|&\cr
+height2pt&&&&&\cr
+&8&&left&&{\&\&}&\cr
+height2pt&&&&&\cr
+&9&&left&&||&\cr
+height2pt&&&&&\cr
+&10&&right&&? :&\cr
+height2pt&&&&&\cr
+&11&&right&&$${\&= += -= *= /=}&\cr
+&lowest&&&&&&\cr
+height2pt&&&&&\cr}
+\hrule}
+@end tex
+
+@section Built in Functions
+The command language provides built in functions for use in
+expressions in linkage scripts.
+@table @bullet
+@item @code{ALIGN(@var{exp})}
+returns the result of the current location counter (@code{dot})
+aligned to the next @var{exp} boundary, where @var{exp} is a power of
+two. This is equivalent to @code{(. + @var{exp} -1) & ~(@var{exp}-1)}.
+As an example, to align the output @code{.data} section to the
+next 0x2000 byte boundary after the preceding section and to set a
+variable within the section to the next 0x8000 boundary after the
+input sections:
+@example
+ .data ALIGN(0x2000) :@{
+ *(.data)
+ variable = ALIGN(0x8000);
+ @}
+@end example
+
+@item @code{ADDR(@var{section name})}
+returns the absolute address of the named section if the section has
+already been bound. In the following examples the @code{symbol_1} and
+@code{symbol_2} are assigned identical values:
+@example
+ .output1:
+ @{
+ start_of_output_1 $= .;
+ ...
+ @}
+ .output:
+ @{
+ symbol_1 = ADDR(.output1);
+ symbol_2 = start_of_output_1;
+ @}
+@end example
+
+@item @code{SIZEOF(@var{section name})}
+returns the size in bytes of the named section, if the section has
+been allocated. In the following example the @code{symbol_1} and
+@code{symbol_2} are assigned identical values:
+@example
+ .output @{
+ .start = . ;
+ ...
+ .end = .;
+ @}
+ symbol_1 = .end - .start;
+ symbol_2 = SIZEOF(.output);
+@end example
+
+@item @code{DEFINED(@var{symbol name})}
+Returns 1 if the symbol is in the linker global symbol table and is
+defined, otherwise it returns 0. This example shows the setting of a
+global symbol @code{begin} to the first location in the @code{.text}
+section, only if there is no other symbol
+called @code{begin} already:
+@example
+ .text: @{
+ begin = DEFINED(begin) ? begin : . ;
+ ...
+ @}
+@end example
+@end table
+@page
+@section MEMORY Directive
+The linker's default configuration is for all memory to be
+allocatable. This state may be overridden by using the @code{MEMORY}
+directive. The @code{MEMORY} directive describes the location and
+size of blocks of memory in the target. Careful use can describe
+memory regions which may or may not be used by the linker. The linker
+does not shuffle sections to fit into the available regions, but does
+move the requested sections into the correct regions and issue errors
+when the regions become too full. The syntax is:
+
+@example
+ MEMORY
+ @{
+@tex
+ $\bigl\lbrace {\it name_1} ({\it attr_1}):$ ORIGIN = ${\it origin_1},$ LENGTH $= {\it len_1} \bigr\rbrace $
+@end tex
+
+ @}
+@end example
+@table @code
+@item @var{name}
+is a name used internally by the linker to refer to the region. Any
+symbol name may be used. The region names are stored in a separate
+name space, and will not conflict with symbols, filenames or section
+names.
+@item @var{attr}
+is an optional list of attributes, parsed for compatibility with the
+AT+T linker
+but ignored by the both the AT+T and the gnu linker.
+@item @var{origin}
+is the start address of the region in physical memory expressed as
+standard linker expression which must evaluate to a constant before
+memory allocation is performed. The keyword @code{ORIGIN} may be
+abbreviated to @code{org} or @code{o}.
+@item @var{len}
+is the size in bytes of the region as a standard linker expression.
+The keyword @code{LENGTH} may be abbreviated to @code{len} or @code{l}
+@end table
+
+For example, to specify that memory has two regions available for
+allocation; one starting at 0 for 256k, and the other starting at
+0x40000000 for four megabytes:
+
+@example
+ MEMORY
+ @{
+ rom : ORIGIN= 0, LENGTH = 256K
+ ram : ORIGIN= 0x40000000, LENGTH = 4M
+ @}
+
+@end example
+
+If the combined output sections directed to a region are too big for
+the region the linker will emit an error message.
+@page
+@section SECTIONS Directive
+The @code{SECTIONS} directive
+controls exactly where input sections are placed into output sections, their
+order and to which output sections they are allocated.
+
+When no @code{SECTIONS} directives are specified, the default action
+of the linker is to place each input section into an identically named
+output section in the order that the sections appear in the first
+file, and then the order of the files.
+
+The syntax of the @code{SECTIONS} directive is:
+
+@example
+ SECTIONS
+ @{
+@tex
+ $\bigl\lbrace {\it name_n}\bigl[options\bigr]\colon$ $\bigl\lbrace {\it statements_n} \bigr\rbrace \bigl[ = {\it fill expression } \bigr] \bigl[ > mem spec \bigr] \bigr\rbrace $
+@end tex
+ @}
+@end example
+
+@table @code
+@item @var{name}
+controls the name of the output section. In formats which only support
+a limited number of sections, such as @code{a.out}, the name must be
+one of the names supported by the format (in the case of a.out,
+@code{.text}, @code{.data} or @code{.bss}). If the output format
+supports any number of sections, but with numbers and not names (in
+the case of IEEE), the name should be supplied as a quoted numeric
+string. A section name may consist of any sequence characters, but
+any name which does not conform to the standard @code{gld} symbol name
+syntax must be quoted. To copy sections 1 through 4 from a Oasys file
+into the @code{.text} section of an @code{a.out} file, and sections 13
+and 14 into the @code{data} section:
+@example
+
+ SECTION @{
+ .text :@{
+ *(``1'' ``2'' ``3'' ``4'')
+ @}
+
+ .data :@{
+ *(``13'' ``14'')
+ @}
+ @}
+@end example
+
+@item @var{fill expression}
+If present this
+expression sets the fill value. Any unallocated holes in the current output
+section when written to the output file will
+be filled with the two least significant bytes of the value, repeated as
+necessary.
+@page
+@item @var{options}
+the @var{options} parameter is a list of optional arguments specifying
+attributes of the output section, they may be taken from the following
+list:
+@table @bullet{}
+@item @var{addr expression}
+forces the output section to be loaded at a specified address. The
+address is specified as a standard linker expression. The following
+example generates section @var{output} at location
+@code{0x40000000}:
+@example
+ SECTIONS @{
+ output 0x40000000: @{
+ ...
+ @}
+ @}
+@end example
+Since the built in function @code{ALIGN} references the location
+counter implicitly, a section may be located on a certain boundary by
+using the @code{ALIGN} function in the expression. For example, to
+locate the @code{.data} section on the next 8k boundary after the end
+of the @code{.text} section:
+@example
+ SECTIONS @{
+ .text @{
+ ...
+ @}
+ .data ALIGN(4K) @{
+ ...
+ @}
+ @}
+@end example
+@end table
+@item @var{statements}
+is a list of file names, input sections and assignments. These statements control what is placed into the
+output section.
+The syntax of a single @var{statement} is one of:
+@table @bullet
+
+@item @var{symbol} [ $= | += | -= | *= | /= ] @var{ expression} @code{;}
+
+Global symbols may be created and have their values (addresses)
+altered using the assignment statement. The linker tries to put off
+the evaluation of an assignment until all the terms in the source
+expression are known; for instance the sizes of sections cannot be
+known until after allocation, so assignments dependent upon these are
+not performed until after allocation. Some expressions, such as those
+depending upon the location counter @code{dot}, @samp{.} must be
+evaluated during allocation. If the result of an expression is
+required, but the value is not available, then an error results: eg
+@example
+ SECTIONS @{
+ text 9+this_isnt_constant:
+ @{
+ @}
+ @}
+ testscript:21: Non constant expression for initial address
+@end example
+
+@item @code{CREATE_OBJECT_SYMBOLS}
+causes the linker to create a symbol for each input file and place it
+into the specified section set with the value of the first byte of
+data written from the input file. For instance, with @code{a.out}
+files it is conventional to have a symbol for each input file.
+@example
+ SECTIONS @{
+ .text 0x2020 :
+ @{
+ CREATE_OBJECT_SYMBOLS
+ *(.text)
+ _etext = ALIGN(0x2000);
+ @}
+ @}
+@end example
+Supplied with four object files, @code{a.o}, @code{b.o}, @code{c.o},
+and @code{d.o} a run of
+@code{gld} could create a map:
+@example
+From functions like :
+a.c:
+ afunction() { }
+ int adata=1;
+ int abss;
+
+00000000 A __DYNAMIC
+00004020 B _abss
+00004000 D _adata
+00002020 T _afunction
+00004024 B _bbss
+00004008 D _bdata
+00002038 T _bfunction
+00004028 B _cbss
+00004010 D _cdata
+00002050 T _cfunction
+0000402c B _dbss
+00004018 D _ddata
+00002068 T _dfunction
+00004020 D _edata
+00004030 B _end
+00004000 T _etext
+00002020 t a.o
+00002038 t b.o
+00002050 t c.o
+00002068 t d.o
+
+@end example
+
+@item @var{filename} @code{(} @var{section name list} @code{)}
+This command allocates all the named sections from the input object
+file supplied into the output section at the current point. Sections
+are written in the order they appear in the list so:
+@example
+ SECTIONS @{
+ .text 0x2020 :
+ @{
+ a.o(.data)
+ b.o(.data)
+ *(.text)
+ @}
+ .data :
+ @{
+ *(.data)
+ @}
+ .bss :
+ @{
+ *(.bss)
+ COMMON
+ @}
+ @}
+@end example
+will produce a map:
+@example
+
+ insert here
+@end example
+@item @code{* (} @var{section name list} @code{)}
+This command causes all sections from all input files which have not
+yet been assigned output sections to be assigned the current output
+section.
+
+@item @var{filename} @code{[COMMON]}
+This allocates all the common symbols from the specified file and places
+them into the current output section.
+
+@item @code{* [COMMON]}
+This allocates all the common symbols from the files which have not
+yet had their common symbols allocated and places them into the current
+output section.
+
+@item @var{filename}
+A filename alone within a @code{SECTIONS} statement will cause all the
+input sections from the file to be placed into the current output
+section at the current location. If the file name has been mentioned
+before with a section name list then only those
+sections which have not yet been allocated are noted.
+
+The following example reads all of the sections from file all.o and
+places them at the start of output section @code{outputa} which starts
+at location @code{0x10000}. All of the data from section @code{.input1} from
+file foo.o is placed next into the same output section. All of
+section @code{.input2} is read from foo.o and placed into output
+section @code{outputb}. Next all of section @code{.input1} is read
+from foo1.o. All of the remaining @code{.input1} and @code{.input2}
+sections from any files are written to output section @code{output3}.
+
+@example
+ SECTIONS
+ @{
+ outputa 0x10000 :
+ @{
+ all.o
+ foo.o (.input1)
+ @}
+ outputb :
+ @{
+ foo.o (.input2)
+ foo1.o (.input1)
+ @}
+ outputc :
+ @{
+ *(.input1)
+ *(.input2)
+ @}
+ @}
+
+@end example
+@end table
+@end table
+@section Using the Location Counter
+The special linker variable @code{dot}, @samp{.} always contains the
+current output location counter. Since the @code{dot} always refers to
+a location in an output section, it must always appear in an
+expression within a @code{SECTIONS} directive. The @code{dot} symbol
+may appear anywhere that an ordinary symbol may appear in an
+expression, but its assignments have a side effect. Assigning a value
+to the @code{dot} symbol will cause the location counter to be moved.
+This may be used to create holes in the output section. The location
+counter may never be moved backwards.
+@example
+ SECTIONS
+ @{
+ output :
+ @{
+ file1(.text)
+ . = . + 1000;
+ file2(.text)
+ . += 1000;
+ file3(.text)
+ . -= 32;
+ file4(.text)
+ @} = 0x1234;
+ @}
+@end example
+In the previous example, @code{file1} is located at the beginning of
+the output section, then there is a 1000 byte gap, filled with 0x1234.
+Then @code{file2} appears, also with a 1000 byte gap following before
+@code{file3} is loaded. Then the first 32 bytes of @code{file4} are
+placed over the last 32 bytes of @code{file3}.
+@section Command Language Syntax
+@section The Entry Point
+The linker chooses the first executable instruction in an output file from a list
+of possibilities, in order:
+@itemize @bullet
+@item
+The value of the symbol provided to the command line with the @code{-e} option, when
+present.
+@item
+The value of the symbol provided in the @code{ENTRY} directive,
+if present.
+@item
+The value of the symbol @code{start}, if present.
+@item
+The value of the symbol @code{_main}, if present.
+@item
+The address of the first byte of the @code{.text} section, if present.
+@item
+The value 0.
+@end itemize
+If the symbol @code{start} is not defined within the set of input
+files to a link, it may be generated by a simple assignment
+expression. eg.
+@example
+ start = 0x2020;
+@end example
+@section Section Attributes
+@section Allocation of Sections into Memory
+@section Defining Symbols
+@chapter Examples of operation
+The simplest case is linking standard Unix object files on a standard
+Unix system supported by the linker. To link a file hello.o:
+@example
+$ gld -o output /lib/crt0.o hello.o -lc
+@end example
+This tells gld to produce a file called @code{output} after linking
+the file @code{/lib/crt0.o} with @code{hello.o} and the library
+@code{libc.a} which will come from the standard search directories.
+@chapter Partial Linking
+Specifying the @code{-r} on the command line causes @code{gld} to
+perform a partial link.
+
+
+@chapter BFD
+
+The linker accesses object and archive files using the @code{bfd}
+libraries. These libraries allow the linker to use the same routines
+to operate on object files whatever the object file format.
+
+A different object file format can be supported simply by creating a
+new @code{bfd} back end and adding it to the library.
+
+Formats currently supported:
+@itemize @bullet
+@item
+Sun3 68k a.out
+@item
+IEEE-695 68k Object Module Format
+@item
+Oasys 68k Binary Relocatable Object File Format
+@item
+Sun4 sparc a.out
+@item
+88k bcs coff
+@item
+i960 coff little endian
+@item
+i960 coff big endian
+@item
+i960 b.out little endian
+@item
+i960 b.out big endian
+@end itemize
+
+As with most implementations, @code{bfd} is a compromise between
+several conflicting requirements. The major factor influencing
+@code{bfd} design was efficiency, any time used converting between
+formats is time which would not have been spent had @code{bfd} not
+been involved. This is partly offset by abstraction payback; since
+@code{bfd} simplifies applications and back ends, more time and care
+may be spent optimizing algorithms for a greater speed.
+
+One minor artifact of the @code{bfd} solution which the
+user should be aware of is information lossage.
+There are two places where useful information can be lost using the
+@code{bfd} mechanism; during conversion and during output.
+
+@section How it works
+When an object file is opened, @code{bfd}
+tries to automatically determine the format of the input object file, a
+descriptor is built in memory with pointers to routines to access
+elements of the object file's data structures.
+
+As different information from the the object files is required
+@code{bfd} reads from different sections of the file and processes
+them. For example a very common operation for the linker is processing
+symbol tables. Each @code{bfd} back end provides a routine for
+converting between the object file's representation of symbols and an
+internal canonical format. When the linker asks for the symbol table
+of an object file, it calls through the memory pointer to the relevant
+@code{bfd} back end routine which reads and converts the table into
+the canonical form. Linker then operates upon the common form. When
+the link is finished and the linker writes the symbol table of the
+output file, another @code{bfd} back end routine is called which takes
+the newly created symbol table and converts it into the output format.
+
+@section Information Leaks
+@table @bullet{}
+@item Information lost during output.
+The output formats supported by @code{bfd} do not provide identical
+facilities, and information which may be described in one form
+has no where to go in another format. One example of this would be
+alignment information in @code{b.out}. There is no where in an @code{a.out}
+format file to store alignment information on the contained data, so when
+a file is linked from @code{b.out} and an @code{a.out} image is produced,
+alignment information is lost. (Note that in this case the linker has the
+alignment information internally, so the link is performed correctly).
+
+Another example is COFF section names. COFF files may contain an
+unlimited number of sections, each one with a textual section name. If
+the target of the link is a format which does not have many sections
+(eg @code{a.out}) or has sections without names (eg the Oasys format)
+the link cannot be done simply. It is possible to circumvent this
+problem by describing the desired input section to output section
+mapping with the command language.
+
+@item Information lost during canonicalization.
+The @code{bfd}
+internal canonical form of the external formats is not exhaustive,
+there are structures in input formats for which there is no direct
+representation internally. This means that the @code{bfd} back ends
+cannot maintain all the data richness through the transformation
+between external to internal and back to external formats.
+
+This limitation is only a problem when using the linker to read one
+format and write another. Each @code{bfd} back end is responsible for
+maintaining as much data as possible, and the internal @code{bfd}
+canonical form has structures which are opaque to the @code{bfd} core,
+and exported only to the back ends. When a file is read in one format,
+the canonical form is generated for @code{bfd} and the linker. At the
+same time, the back end saves away any information which may otherwise
+be lost. If the data is then written back to the same back end, the
+back end routine will be able to use the canonical form provided by
+the @code{bfd} core as well as the information it prepared earlier.
+Since there is a great deal of commonality between back ends, this
+mechanism is very useful. There is no information lost when linking
+big endian COFF to little endian COFF, or from a.out to b.out. When a
+mixture of formats are linked, the information is only lost from the
+files with a different format to the destination.
+@end table
+@section Mechanism
+The smallest amount of information is preserved when there
+is a small union between the information provided by the source
+format, that stored by the canonical format and the information needed
+by the destination format. A brief description of the canonical form
+will help the user appreciate what is possible to be maintained
+between conversions.
+
+@table @bullet
+@item file level Information on target machine
+architecture, particular implementation and format type are stored on
+a per file basis. Other information includes a demand pageable bit and
+a write protected bit. Note that information like Unix magic numbers
+is not stored here, only the magic numbers meaning, so a ZMAGIC file
+would have both the demand pageable bit and the write protected text
+bit set.
+
+The byte order of the target is stored on a per file basis, so that
+both big and little endian object files may be linked together at the
+same time.
+@item section level
+Each section in the input file contains the name of the section, the
+original address in the object file, various flags, size and alignment
+information and pointers into other @code{bfd} data structures.
+@item symbol level
+Each symbol contains a pointer to the object file which originally
+defined it, its name, value and various flags bits. When a symbol
+table is read in all symbols are relocated to make them relative to
+the base of the section they were defined in, so each symbol points to
+the containing section. Each symbol also has a varying amount of
+hidden data to contain private data for the back end. Since the symbol
+points to the original file, the symbol private data format is
+accessible. Operations may be done to a list of symbols of wildly
+different formats without problems.
+
+Normal global and simple local symbols are maintained on output, so an
+output file, no matter the format will retain symbols pointing to
+functions, globals, statics and commons. Some symbol information is
+not worth retaining; in @code{a.out} type information is stored in the
+symbol table as long symbol names. This information would be useless
+to most coff debuggers and may be thrown away with appropriate command
+line switches. (Note that gdb does support stabs in coff).
+
+There is one word of type information within the symbol, so if the
+format supports symbol type information within symbols - (eg COFF,
+IEEE, Oasys) and the type is simple enough to fit within one word
+(nearly everything but aggregates) the information will be preserved.
+
+@item relocation level
+Each canonical relocation record contains a pointer to the symbol to
+relocate to, the offset of the data to relocate, the section the data
+is in and a pointer to a relocation type descriptor. Relocation is
+performed effectively by message passing through the relocation type
+descriptor and symbol pointer. It allows relocations to be performed
+on output data using a relocation method only available in one of the
+input formats. For instance, Oasys provides a byte relocation format.
+A relocation record requesting this relocation type would point
+indirectly to a routine to perform this, so the relocation may be
+performed on a byte being written to a COFF file, even though 68k COFF
+has no such relocation type.
+
+@item line numbers
+Line numbers have to be relocated along with the symbol information.
+Each symbol with an associated list of line number records points to
+the first record of the list. The head of a line number list consists
+of a pointer to the symbol, which allows divination of the address of
+the function who's line number is being described. The rest of the
+list is tuples offsets into the section and line indexes. Any format
+which can simply derive this information can pass it without lossage
+between formats (COFF, IEEE and Oasys).
+@end table
+
+
+@bye
+
+
diff --git a/ld/ldsym.c b/ld/ldsym.c
index 796060c..4b0001a 100644
--- a/ld/ldsym.c
+++ b/ld/ldsym.c
@@ -20,8 +20,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
* $Id$
*
* $Log$
- * Revision 1.1 1991/03/21 21:28:58 gumby
- * Initial revision
+ * Revision 1.1.1.1 1991/03/21 21:28:58 gumby
+ * Back from Intel with Steve
+ *
+ * Revision 1.1 1991/03/21 21:28:58 gumby
+ * Initial revision
*
* Revision 1.1 1991/03/13 00:48:32 chrisb
* Initial revision
diff --git a/ld/ldsym.h b/ld/ldsym.h
new file mode 100644
index 0000000..8a12bbc
--- /dev/null
+++ b/ld/ldsym.h
@@ -0,0 +1,59 @@
+/* ldsym.h -
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+ This file is part of GLD, the Gnu Linker.
+
+ GLD 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 1, or (at your option)
+ any later version.
+
+ GLD 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 GLD; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+typedef struct user_symbol_struct
+{
+ /* Point to next symbol in this hash chain */
+ struct user_symbol_struct *link;
+
+ /* Name of this symbol. */
+ char *name;
+
+ /* Pointer to next symbol in order of symbol creation */
+ struct user_symbol_struct *next;
+
+ /* Chain of asymbols we see from input files
+ note that we point to the entry in the canonical table of
+ the pointer to the asymbol, *not* the asymbol. This means
+ that we can run back and fix all refs to point to the
+ defs nearly for free.
+ */
+ asymbol **srefs_chain;
+ asymbol **sdefs_chain;
+
+ /* only ever point to the largest ever common definition -
+ * all the rest are turned into refs
+ * scoms and sdefs are never != NULL at same time
+ */
+ asymbol **scoms_chain;
+
+} ldsym_type;
+
+
+PROTO(ldsym_type *, ldsym_get, (char *));
+PROTO(ldsym_type *, ldsym_get_soft, (char *));
+PROTO(void, ldsym_print_symbol_table,(void));
+PROTO(void, ldsym_write, (void));
+
+#define FOR_EACH_LDSYM(x) \
+ extern ldsym_type *symbol_head; \
+ ldsym_type *x; \
+ for (x = symbol_head; x != (ldsym_type *)NULL; x = x->next)
+
diff --git a/ld/ldwarn.h b/ld/ldwarn.h
new file mode 100644
index 0000000..be0d107
--- /dev/null
+++ b/ld/ldwarn.h
@@ -0,0 +1,22 @@
+/* ldwarn.h -
+
+ Copyright (C) 1991 Free Software Foundation, Inc.
+
+ This file is part of GLD, the Gnu Linker.
+
+ GLD 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 1, or (at your option)
+ any later version.
+
+ GLD 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 GLD; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+
+PROTOX(void, ldwarn,(void));