diff options
author | David Henkel-Wallace <gumby@cygnus> | 1991-03-21 21:29:07 +0000 |
---|---|---|
committer | David Henkel-Wallace <gumby@cygnus> | 1991-03-21 21:29:07 +0000 |
commit | c074abeebcefe3b62f46ff8a62f3d4058ed32780 (patch) | |
tree | 97a36afc00d9cc840b84d89e40ffbd13cd3ad7f7 /binutils | |
parent | 2fa0b342a5cd580781d2b9348a87f33a92d363fa (diff) | |
download | gdb-c074abeebcefe3b62f46ff8a62f3d4058ed32780.zip gdb-c074abeebcefe3b62f46ff8a62f3d4058ed32780.tar.gz gdb-c074abeebcefe3b62f46ff8a62f3d4058ed32780.tar.bz2 |
Back from Intel with Steve
Diffstat (limited to 'binutils')
-rw-r--r-- | binutils/TODO | 11 | ||||
-rw-r--r-- | binutils/alloca.c | 191 | ||||
-rw-r--r-- | binutils/copy.c | 410 | ||||
-rw-r--r-- | binutils/cplus-dem.c | 933 | ||||
-rw-r--r-- | binutils/gmalloc.c | 1116 | ||||
-rw-r--r-- | binutils/m68k-pinsn.c | 7 | ||||
-rwxr-xr-x | binutils/ostrip.c | 418 | ||||
-rw-r--r-- | binutils/sparc-pinsn.c | 7 | ||||
-rwxr-xr-x | binutils/strip.c | 364 |
9 files changed, 3453 insertions, 4 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)); +} |