aboutsummaryrefslogtreecommitdiff
path: root/binutils-1.9/size.c
diff options
context:
space:
mode:
Diffstat (limited to 'binutils-1.9/size.c')
-rw-r--r--binutils-1.9/size.c400
1 files changed, 400 insertions, 0 deletions
diff --git a/binutils-1.9/size.c b/binutils-1.9/size.c
new file mode 100644
index 0000000..8c000f7
--- /dev/null
+++ b/binutils-1.9/size.c
@@ -0,0 +1,400 @@
+/* Size of rel file utility (`size') for GNU.
+ Copyright (C) 1986 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 <stdio.h>
+#include <ar.h>
+#include <sys/types.h>
+#include <sys/file.h>
+
+#if !defined(A_OUT) && !defined(MACH_O)
+#define A_OUT
+#endif
+
+#ifdef A_OUT
+#ifdef COFF_ENCAPSULATE
+#include "a.out.encap.h"
+#else
+/* On native BSD systems, use the system's own a.out.h. */
+#include <a.out.h>
+#endif
+#endif
+
+#ifdef MACH_O
+#include <sys/loader.h>
+#endif
+
+#ifdef USG
+#include <fcntl.h>
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+/* Number of input file names specified. */
+int number_of_files;
+
+/* Current file's name */
+char *input_name;
+
+/* Current member's name, or 0 if processing a non-library file. */
+char *input_member;
+
+/* Offset within archive of the current member,
+ if we are processing an archive. */
+int member_offset;
+
+/* The name this program was run with. */
+char *program_name;
+
+char *malloc ();
+
+void do_one_file ();
+void do_one_rel_file ();
+void error_with_file ();
+void fatal ();
+void perror_name ();
+void print_file_name ();
+char *xmalloc ();
+char *concat ();
+
+void
+main (argc, argv)
+ char **argv;
+ int argc;
+{
+ int i;
+
+ program_name = argv[0];
+
+ number_of_files = argc - 1;
+
+ printf ("text\tdata\tbss\tdec\thex\n");
+
+ /* Now scan and describe the files. */
+
+ if (number_of_files == 0)
+ do_one_file ("a.out");
+ else
+ for (i = 1; i < argc; i++)
+ do_one_file (argv[i]);
+ exit (0);
+}
+
+/* Print the filename of the current file on 'outfile' (a stdio stream). */
+
+void
+print_file_name (outfile)
+ FILE *outfile;
+{
+ fprintf (outfile, "%s", input_name);
+ if (input_member)
+ fprintf (outfile, "(%s)", input_member);
+}
+
+/* process one input file */
+void scan_library ();
+
+void
+do_one_file (name)
+ char *name;
+{
+ int desc;
+ char armag[SARMAG];
+
+ desc = open (name, O_RDONLY, 0);
+
+ if (desc < 0)
+ {
+ perror_name (name);
+ return;
+ }
+
+ input_name = name;
+ input_member = 0;
+
+ if (SARMAG != read (desc, armag, SARMAG) || strncmp (armag, ARMAG, SARMAG))
+ do_one_rel_file (desc, 0L);
+ else
+ scan_library (desc);
+
+ close (desc);
+}
+
+/* Read in the archive data about one member.
+ SUBFILE_OFFSET is the address within the archive of the start of that data.
+
+ Return the length of the member's contents, which does
+ not include the archive data about the member.
+ If there are no more valid members, return zero. */
+
+int
+decode_library_subfile (desc, subfile_offset)
+ int desc;
+ int subfile_offset;
+{
+ int bytes_read;
+ int namelen;
+ int member_length;
+ char *name;
+ struct ar_hdr hdr1;
+
+ lseek (desc, subfile_offset, 0);
+
+ bytes_read = read (desc, &hdr1, sizeof hdr1);
+ if (!bytes_read)
+ ; /* end of archive */
+
+ else if (sizeof hdr1 != bytes_read)
+ error_with_file ("malformed library archive");
+
+ else if (sscanf (hdr1.ar_size, "%d", &member_length) != 1)
+ error_with_file ("malformatted header of archive member");
+
+ else
+ {
+ for (namelen = 0;
+ hdr1.ar_name[namelen] != 0
+ && hdr1.ar_name[namelen] != ' '
+ && hdr1.ar_name[namelen] != '/';
+ namelen++)
+ ;
+ name = (char *) xmalloc (namelen+1);
+ strncpy (name, hdr1.ar_name, namelen);
+ *(name + namelen) = 0;
+
+ input_member = name;
+
+ return member_length;
+ }
+ return 0; /* tell caller to exit loop */
+}
+
+/* Scan a library and describe each member. */
+
+void
+scan_library (desc)
+ int desc;
+{
+ int this_subfile_offset = SARMAG;
+ int member_length;
+
+ while (member_length = decode_library_subfile (desc, this_subfile_offset))
+ {
+ /* describe every member except the ranlib data if any */
+ if (strcmp (input_member, "__.SYMDEF"))
+ do_one_rel_file (desc, this_subfile_offset + sizeof (struct ar_hdr));
+
+ this_subfile_offset += ((member_length + sizeof (struct ar_hdr)) + 1) & -2;
+ }
+}
+
+/* Read a file's header and fill in various pieces of information.
+ Return 0 on failure, 1 on success. */
+
+int
+read_header_info (desc, offset, tsize, dsize, bsize)
+ int desc;
+ long int offset;
+ unsigned int *tsize;
+ unsigned int *dsize;
+ unsigned int *bsize;
+{
+ int len;
+
+#ifdef A_OUT
+ {
+ struct exec hdr;
+
+ lseek (desc, offset, 0);
+#ifdef HEADER_SEEK_FD
+ /* Skip the headers that encapsulate our data in some other format
+ such as COFF. */
+ HEADER_SEEK_FD (desc);
+#endif
+ len = read (desc, (char *) &hdr, sizeof (struct exec));
+ if (len == sizeof (struct exec) && !N_BADMAG (hdr))
+ {
+ *tsize = hdr.a_text;
+ *dsize = hdr.a_data;
+ *bsize = hdr.a_bss;
+ return 1;
+ }
+ }
+#endif
+
+#ifdef MACH_O
+ {
+ struct mach_header mach_header;
+ char *hdrbuf;
+ struct load_command *load_command;
+ struct segment_command *segment_command;
+ struct section *section;
+ int len, cmd, seg;
+
+ lseek (desc, offset, 0);
+ len = read (desc, (char *) &mach_header, sizeof (struct mach_header));
+ if (len == sizeof (struct mach_header) && mach_header.magic == MH_MAGIC)
+ {
+ hdrbuf = xmalloc (mach_header.sizeofcmds);
+ len = read (desc, hdrbuf, mach_header.sizeofcmds);
+ if (len != mach_header.sizeofcmds)
+ {
+ error_with_file ("failure reading Mach-O load commands");
+ return 0;
+ }
+ load_command = (struct load_command *) hdrbuf;
+ for (cmd = 0; cmd < mach_header.ncmds; ++cmd)
+ {
+ if (load_command->cmd == LC_SEGMENT)
+ {
+ segment_command = (struct segment_command *) load_command;
+ section = (struct section *) ((char *) (segment_command + 1));
+ for (seg = 0; seg < segment_command->nsects; ++seg, ++section)
+ {
+ if (!strncmp(SECT_TEXT, section->sectname, sizeof section->sectname))
+ *tsize = section->size;
+ else if (!strncmp(SECT_DATA, section->sectname, sizeof section->sectname))
+ *dsize = section->size;
+ else if (!strncmp(SECT_BSS, section->sectname, sizeof section->sectname))
+ *bsize = section->size;
+ }
+ }
+ load_command = (struct load_command *)
+ ((char *) load_command + load_command->cmdsize);
+ }
+ free (hdrbuf);
+ return 1;
+ }
+ }
+#endif
+
+ return 0;
+}
+
+void
+do_one_rel_file (desc, offset)
+ int desc;
+ long int offset;
+{
+ unsigned int tsize, dsize, bsize, total;
+
+ if (read_header_info (desc, offset, &tsize, &dsize, &bsize))
+ {
+ total = tsize + dsize + bsize;
+ printf ("%u\t%u\t%u\t%u\t%x", tsize, dsize, bsize, total, total);
+ }
+ else
+ {
+ error_with_file ("malformed input file (not rel or archive)");
+ return;
+ }
+
+ if (number_of_files > 1 || input_member)
+ {
+ printf ("\t");
+ print_file_name (stdout);
+ }
+ printf ("\n");
+}
+
+/* Report a fatal error.
+ STRING is a printf format string and ARG is one arg for it. */
+
+void
+fatal (string, arg)
+ char *string, *arg;
+{
+ fprintf (stderr, "%s: ", program_name);
+ fprintf (stderr, string, arg);
+ fprintf (stderr, "\n");
+ exit (1);
+}
+
+/* Report a nonfatal error.
+ STRING is a printf format string and ARG is one arg for it. */
+
+void
+error (string, arg)
+ char *string, *arg;
+{
+ fprintf (stderr, "%s: ", program_name);
+ fprintf (stderr, string, arg);
+ fprintf (stderr, "\n");
+}
+
+/* Report a nonfatal error.
+ STRING is printed, followed by the current file name. */
+
+void
+error_with_file (string)
+ char *string;
+{
+ fprintf (stderr, "%s: ", program_name);
+ print_file_name (stderr);
+ fprintf (stderr, ": ");
+ fprintf (stderr, string);
+ fprintf (stderr, "\n");
+}
+
+/* Report an error using the message for the last failed system call,
+ followed by the string NAME. */
+
+void
+perror_name (name)
+ char *name;
+{
+ extern int errno, sys_nerr;
+ extern char *sys_errlist[];
+ char *s;
+
+ if (errno < sys_nerr)
+ s = concat (name, ": ", sys_errlist[errno]);
+ else
+ s = concat (name, ": ", "unknown error");
+ error (s, name);
+}
+
+/* Like malloc but get fatal error if memory is exhausted. */
+
+char *
+xmalloc (size)
+ unsigned size;
+{
+ char *result = malloc (size);
+
+ if (!result)
+ fatal ("virtual memory exhausted", 0);
+ return result;
+}
+
+/* Return a newly-allocated string
+ whose contents concatenate those of S1, S2, S3. */
+
+char *
+concat (s1, s2, s3)
+ char *s1, *s2, *s3;
+{
+ int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
+ char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
+
+ strcpy (result, s1);
+ strcpy (result + len1, s2);
+ strcpy (result + len1 + len2, s3);
+ result[len1 + len2 + len3] = 0;
+
+ return result;
+}