aboutsummaryrefslogtreecommitdiff
path: root/binutils/copy.c
diff options
context:
space:
mode:
authorDavid Henkel-Wallace <gumby@cygnus>1991-03-21 21:29:07 +0000
committerDavid Henkel-Wallace <gumby@cygnus>1991-03-21 21:29:07 +0000
commitc074abeebcefe3b62f46ff8a62f3d4058ed32780 (patch)
tree97a36afc00d9cc840b84d89e40ffbd13cd3ad7f7 /binutils/copy.c
parent2fa0b342a5cd580781d2b9348a87f33a92d363fa (diff)
downloadgdb-c074abeebcefe3b62f46ff8a62f3d4058ed32780.zip
gdb-c074abeebcefe3b62f46ff8a62f3d4058ed32780.tar.gz
gdb-c074abeebcefe3b62f46ff8a62f3d4058ed32780.tar.bz2
Back from Intel with Steve
Diffstat (limited to 'binutils/copy.c')
-rw-r--r--binutils/copy.c410
1 files changed, 410 insertions, 0 deletions
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;
+}