Here are some changes I made to objdump which allow it to dump section contents as raw data. This is usefull if you need to make an image of an executable to load into memory with out the help of the operating systems. We use this to make boot images of the Linux kernel under ELF as well as for dynamic loading of kernel modules. Another case when they would be useful, is for making ROM Images. I've also enclosed source for another program called encaps which takes raw data and makes it a .o file. It's useful for adding resources are other data to a program without recompiling. We use it to include 16 bit minix assembly in the Linux kernel. Ross Biro biro@yggdrasil.com ------ CUT HERE ------ --- *** objdump.c.~1~ Wed Sep 28 13:06:43 1994 --- objdump.c Mon Nov 14 06:57:47 1994 *************** *** 15,24 **** --- 15,28 ---- You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + /* Added -k, -o, -q options for use with the Linux kernel + * 11/94 Ross Biro biro@yggdrasil.com + */ + #include "bfd.h" #include "sysdep.h" #include "getopt.h" #include "bucomm.h" #include *************** *** 38,47 **** --- 42,54 ---- extern char *program_version; int show_version = 0; /* show the version number */ int dump_section_contents; /* -s */ + int dump_section_raw=0; /* -k */ + int raw_offset=0; /* -o */ + int quiet=0; /* -q */ int dump_section_headers; /* -h */ boolean dump_file_header; /* -f */ int dump_symtab; /* -t */ int dump_dynamic_symtab; /* -T */ int dump_reloc_info; /* -r */ *************** *** 112,128 **** usage (stream, status) FILE *stream; int status; { fprintf (stream, "\ ! Usage: %s [-ahifdDrRtTxsl] [-b bfdname] [-m machine] [-j section-name]\n\ [--archive-headers] [--target=bfdname] [--disassemble]\n\ [--disassemble-all] [--file-headers] [--section-headers] [--headers]\n\ [--info] [--section=section-name] [--line-numbers]\n\ [--architecture=machine] [--reloc] [--full-contents] [--stabs]\n\ [--syms] [--all-headers] [--dynamic-syms] [--dynamic-reloc]\n\ ! [--version] [--help] objfile...\n\ at least one option besides -l (--line-numbers) must be given\n", program_name); exit (status); } --- 119,135 ---- usage (stream, status) FILE *stream; int status; { fprintf (stream, "\ ! Usage: %s [-ahifdDkoqrRtTxsl] [-b bfdname] [-m machine] [-j section-name]\n\ [--archive-headers] [--target=bfdname] [--disassemble]\n\ [--disassemble-all] [--file-headers] [--section-headers] [--headers]\n\ [--info] [--section=section-name] [--line-numbers]\n\ [--architecture=machine] [--reloc] [--full-contents] [--stabs]\n\ [--syms] [--all-headers] [--dynamic-syms] [--dynamic-reloc]\n\ ! [--version] [--help] [--offset=offset] [--raw] [--quiet] objfile...\n\ at least one option besides -l (--line-numbers) must be given\n", program_name); exit (status); } *************** *** 139,148 **** --- 146,158 ---- {"full-contents", no_argument, NULL, 's'}, {"headers", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'H'}, {"info", no_argument, NULL, 'i'}, {"line-numbers", no_argument, NULL, 'l'}, + {"offset", required_argument, NULL, 'o'}, + {"quiet", no_argument, NULL, 'q'}, + {"raw", no_argument, NULL, 'k'/* k for kernel */}, {"reloc", no_argument, NULL, 'r'}, {"section", required_argument, NULL, 'j'}, {"section-headers", no_argument, NULL, 'h'}, {"stabs", no_argument, &dump_stab_section_info, 1}, {"syms", no_argument, NULL, 't'}, *************** *** 980,992 **** list_matching_formats (matching); free (matching); } return; } ! ! printf ("\n%s: file format %s\n", bfd_get_filename (abfd), ! abfd->xvec->name); if (dump_ar_hdrs) print_arelt_descr (stdout, abfd, true); if (dump_file_header) dump_bfd_header (abfd); putchar ('\n'); --- 990,1002 ---- list_matching_formats (matching); free (matching); } return; } ! if (!quiet) ! printf ("\n%s: file format %s\n", bfd_get_filename (abfd), ! abfd->xvec->name); if (dump_ar_hdrs) print_arelt_descr (stdout, abfd, true); if (dump_file_header) dump_bfd_header (abfd); putchar ('\n'); *************** *** 1031,1042 **** } if (bfd_check_format (file, bfd_archive) == true) { bfd *last_arfile = NULL; ! ! printf ("In archive %s:\n", bfd_get_filename (file)); for (;;) { bfd_set_error (bfd_error_no_error); arfile = bfd_openr_next_archived_file (file, arfile); --- 1041,1052 ---- } if (bfd_check_format (file, bfd_archive) == true) { bfd *last_arfile = NULL; ! if (!quiet) ! printf ("In archive %s:\n", bfd_get_filename (file)); for (;;) { bfd_set_error (bfd_error_no_error); arfile = bfd_openr_next_archived_file (file, arfile); *************** *** 1073,1082 **** --- 1083,1093 ---- { asection *section; bfd_byte *data = 0; bfd_size_type datasize = 0; bfd_size_type i; + int err; for (section = abfd->sections; section != NULL; section = section->next) { int onaline = 16; *************** *** 1084,1128 **** if (only == (char *) NULL || strcmp (only, section->name) == 0) { if (section->flags & SEC_HAS_CONTENTS) { ! printf ("Contents of section %s:\n", section->name); if (bfd_section_size (abfd, section) == 0) continue; data = (bfd_byte *) xmalloc ((size_t) bfd_section_size (abfd, section)); datasize = bfd_section_size (abfd, section); bfd_get_section_contents (abfd, section, (PTR) data, 0, bfd_section_size (abfd, section)); ! for (i = 0; i < bfd_section_size (abfd, section); i += onaline) ! { ! bfd_size_type j; ! printf (" %04lx ", (unsigned long int) (i + section->vma)); ! for (j = i; j < i + onaline; j++) ! { ! if (j < bfd_section_size (abfd, section)) ! printf ("%02x", (unsigned) (data[j])); ! else ! printf (" "); ! if ((j & 3) == 3) ! printf (" "); ! } ! printf (" "); ! for (j = i; j < i + onaline; j++) ! { ! if (j >= bfd_section_size (abfd, section)) ! printf (" "); ! else ! printf ("%c", isprint (data[j]) ? data[j] : '.'); ! } ! putchar ('\n'); } free (data); } } } } --- 1095,1155 ---- if (only == (char *) NULL || strcmp (only, section->name) == 0) { if (section->flags & SEC_HAS_CONTENTS) { ! if (!quiet) ! printf ("Contents of section %s:\n", section->name); if (bfd_section_size (abfd, section) == 0) continue; data = (bfd_byte *) xmalloc ((size_t) bfd_section_size (abfd, section)); datasize = bfd_section_size (abfd, section); bfd_get_section_contents (abfd, section, (PTR) data, 0, bfd_section_size (abfd, section)); ! if (dump_section_raw) { ! if (section->vma < raw_offset) continue; ! if (fseek (stdout, section->vma-raw_offset, SEEK_SET)) { ! perror ("fseek"); ! } ! err =fwrite (data,1, bfd_section_size (abfd, section), stdout); ! if (err != bfd_section_size (abfd, section)) { ! perror ("fwrite"); ! return; } + + } else { + for (i = 0; i < bfd_section_size (abfd, section); i += onaline) + { + bfd_size_type j; + + printf (" %08lx ", (unsigned long int) (i + section->vma)); + for (j = i; j < i + onaline; j++) + { + if (j < bfd_section_size (abfd, section)) + printf ("%02x", (unsigned) (data[j])); + else + printf (" "); + if ((j & 3) == 3) + printf (" "); + } + + printf (" "); + for (j = i; j < i + onaline; j++) + { + if (j >= bfd_section_size (abfd, section)) + printf (" "); + else + printf ("%c", isprint (data[j]) ? data[j] : '.'); + } + putchar ('\n'); + } + } free (data); } } } } *************** *** 1504,1514 **** program_name = *argv; xmalloc_set_program_name (program_name); bfd_init (); ! while ((c = getopt_long (argc, argv, "ib:m:VdDlfahrRtTxsj:", long_options, (int *) 0)) != EOF) { seenflag = true; switch (c) --- 1531,1541 ---- program_name = *argv; xmalloc_set_program_name (program_name); bfd_init (); ! while ((c = getopt_long (argc, argv, "kqo:ib:m:VdDlfahrRtTxsj:", long_options, (int *) 0)) != EOF) { seenflag = true; switch (c) *************** *** 1549,1558 **** --- 1576,1595 ---- case 'd': disassemble = true; break; case 'D': disassemble = disassemble_all = true; + break; + case 'q': + quiet = 1; + break; + case 'k': + dump_section_raw = 1; + dump_section_contents = 1; + break; + case 'o': + raw_offset = atoi (optarg); break; case 's': dump_section_contents = 1; break; case 'r': ------ CUT HERE ------ *** objdump.1.~1~ Thu Sep 15 21:59:29 1994 --- objdump.1 Mon Nov 14 06:50:42 1994 *************** *** 29,45 **** --- 29,52 ---- .RB "[\|" \-i | \-\-info "\|]" .RB "[\|" "\-j\ "\c .I section\c .RB " | " "\-\-section="\c .I section\c + .RB "[\|" \-k | \-\-raw "\|]" \&\|] .RB "[\|" \-l | \-\-line\-numbers "\|]" .RB "[\|" "\-m\ "\c .I machine\c .RB " | " "\-\-architecture="\c .I machine\c \&\|] + .RB "[\|" "\-o\ "\c + .I offset\c + .RB " | " "\-\-offset="\c + .I offset\c + \&\|] + .RB "[\|" \-q | \-\-quiet "\|]" .RB "[\|" \-r | \-\-reloc "\|]" .RB "[\|" \-R | \-\-dynamic\-reloc "\|]" .RB "[\|" \-s | \-\-full\-contents "\|]" .RB "[\|" \-\-stabs "\|]" .RB "[\|" \-t | \-\-syms "\|]" *************** *** 181,190 **** --- 188,206 ---- Display information only for section \c .I name\c \& .TP + .B \-k + .TP + .B \-\-raw + Dump all the loadable section contents as raw data on stdout. + Useful for making + boot images or turning an executable into raw data. Some architectures + (such as elf) require that stdout be seekable for this to work. + + .TP .B \-l .TP .B \-\-line\-numbers Label the display (using debugging information) with the filename and source line numbers corresponding to the object code shown. *************** *** 202,211 **** --- 218,240 ---- .I machine\c \&. You can list available architectures using the `\|\c .B \-i\c \|' option. + + .TP + .BI "\-o " "offset"\c + .TP + .BI "\-\-offset=" "offset"\c + \& + The offset to make byte 0 of a raw dump. + + .TP + .B \-q + .TP + .B \-\-quiet + Supress most informational messages, useful with \fB\-k\fP. .TP .B \-r .TP .B \-\-reloc ------ CUT HERE ------ /* encaps.c */ /* Copyright (C) 1994 Yggdrasil Computing, Incorporated 4880 Stevens Creek Blvd. Suite 205 San Jose, CA 95129-1034 USA Tel (408) 261-6630 Fax (408) 261-6631 Encaps 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 2, or (at your option) any later version. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Written by Ross Biro Nov 94 */ #include #include #include #include #include #include #include #include #include #include #include "ansidecl.h" #include #define obstack_chunk_alloc malloc #define obstack_chunk_free free #define DEF_SEC_FLAGS SEC_ALLOC|SEC_LOAD|SEC_RELOC|SEC_HAS_CONTENTS /* This is the routine that does most of the work. */ /* file is the name of the output file target is the target type "a.out-i386-linux" for example secflags is ored with DEFAULT_SEC_FLAGS and then applied. It is used to say if the section is data or code. (Normally SEC_DATA. format is the file format to write (Normally bfd_object) symname is the name to give the symbol. secname is the name of the section (.data is good) fd is the file descriptor for the data to be put in the file. */ int encapsulate (const char *file, const char *target, unsigned long secflags, bfd_format format, const char *symname, char *lengthname, const char *secname, int fd) { bfd *abfd; asection *sec; size_t length; unsigned char *ptr; struct stat st; asymbol *syms[3]; asymbol *new; bfd_init(); bfd_check_init(); abfd = bfd_openw(file, target); if (abfd == NULL) { fprintf (stderr, "Error Openning %s file %s: %s\n",target, file, bfd_errmsg (bfd_get_error())); return (bfd_get_error()<<16| errno); } #ifdef __i386__ /* This wonderful poorly document call is absolutely necessary. */ /* The linker deals with this in a much better way. Perhaps the code should be borowed. */ bfd_default_set_arch_mach (abfd, bfd_arch_i386, 0); #endif if (!bfd_set_format (abfd, format)) { fprintf (stderr, "Error settting format: %s\n", bfd_errmsg (bfd_get_error())); return (bfd_get_error()<<16| errno); } sec = bfd_make_section (abfd, secname); if (sec == NULL) { fprintf (stderr, "Error Making Section: %s\n", bfd_errmsg (bfd_get_error())); return (bfd_get_error()<<16| errno); } if (!bfd_set_section_flags(abfd, sec, DEF_SEC_FLAGS | secflags)) { fprintf (stderr, "Error settting section flags %s\n", bfd_errmsg (bfd_get_error())); return (bfd_get_error()<<16| errno); } /* We are ready for the data. */ if (fstat (fd, &st)) { fprintf (stderr, "Error Stating Data File: %s\n", strerror (errno)); return (errno); } length = st.st_size; /* create a new symbol */ new = bfd_make_empty_symbol (abfd); if ((unsigned long)new < 4096) { fprintf (stderr, "Error allocating symbol: %s\n", bfd_errmsg (bfd_get_error())); return (bfd_get_error()<<16| errno); } new->name = symname; new->section = sec; new->flags = BSF_EXPORT; new->value =sizeof (char *); syms[0]=new; new = bfd_make_empty_symbol (abfd); if ((unsigned long)new < 4096) { fprintf (stderr, "Error allocating symbol: %s\n", bfd_errmsg (bfd_get_error())); return (bfd_get_error()<<16| errno); } new->name = lengthname; new->section = sec; new->flags = BSF_EXPORT; new->value =0; syms[1]=new; syms[2]=NULL; if (!bfd_set_symtab (abfd, syms, 2)) { fprintf (stderr, "Error setting symbol table: %s\n", bfd_errmsg (bfd_get_error())); return (bfd_get_error()<<16| errno); } /* mmap would be good here, but if I do it, I can't easily add the length info. Oh well ptr = mmap (0, length, PROT_READ, MAP_FILE|MAP_SHARED, fd, 0); if (ptr == NULL) { fprintf (stderr, "Error mmapping Data File: %s\n", strerror (errno)); return (errno); } */ ptr = malloc (length + sizeof (char *)); if (ptr == NULL) { fprintf (stderr, "Error allocating memory for data file: %s\n", strerror (errno)); return (errno); } /* this is technically a bug. For example a ctrl-z bg may break this. */ if (read (fd, ptr+sizeof (char *), length) != length) { fprintf (stderr, "Error reading file: %s\n", strerror (errno)); return (errno); } *(unsigned long*)ptr = length; if (! bfd_set_section_size (abfd, sec, length+sizeof(char *))) { fprintf (stderr, "Error settting section size %s:\n", bfd_errmsg (bfd_get_error())); return (bfd_get_error()<<16| errno); } if (! bfd_set_section_contents (abfd, sec, ptr, 0, length+sizeof (char *))) { fprintf (stderr, "Error settting section contents: %s\n", bfd_errmsg (bfd_get_error())); return (bfd_get_error()<<16| errno); } /* write out everything. */ bfd_close (abfd); return (0); } void usage (char *name) { fprintf (stderr, "usage %s: [-f format] [-n secname] [-t target] [-s secflags] output-file input-file symbol-name length-name\n", name); fpritnf (stderr," --format format file format to write.\n"); fpritnf (stderr," --section_name name of the section (normally .data)\n"); fpritnf (stderr," --target target target name (a.out-linux-i386 elf32-i386)\n"); fpritnf (stderr," --sectionflags flags flags to put in section header\n"); exit (1); } int main (int argc, char *argv[]) { int c; char *outfile=NULL; char *infile=NULL; char *target="a.out-i386-linux"; int secflags = SEC_DATA; bfd_format format = bfd_object; char *symname = NULL; char *lengthname = NULL; char *secname = ".data"; int fd = -1; int option_index; static struct option long_options[] = { {"help", 0, 0, 'h'}, {"format", 1, 0, 'f'}, {"section-name", 1, 0, 'n'}, {"target", 1, 0, 't'}, {"sectionflags", 1, 0, 's'}, }; while ((c = getopt_long (argc, argv, "hf:t:n:s:", long_options, &option_index)) > 0) { switch (c) { case 'h': case '?': default: usage(argv[0]); case 'f': format = atoi(optarg); break; case 'n': secname = optarg; break; case 't': target = optarg; break; case 's': secflags=atoi (optarg); break; } } if (argc - optind != 4) usage(argv[0]); outfile = argv[optind]; infile= argv[optind+1]; symname = argv[optind+2]; lengthname = argv[optind+3]; fd = open (infile, O_RDONLY); if (fd < 0) { fprintf (stderr, "error opening infile %s: %s\n", infile, strerror(errno)); exit (1); } if (encapsulate (outfile, target, secflags, format, symname, lengthname, secname, fd)) return (1); return (0); }