Home | History | Annotate | Line # | Download | only in dbsym
dbsym.c revision 1.4
      1  1.4  joerg /* $NetBSD: dbsym.c,v 1.4 2014/08/17 19:12:59 joerg Exp $ */
      2  1.1  skrll 
      3  1.1  skrll /*
      4  1.1  skrll  * Copyright (c) 2001 Simon Burge (for Wasabi Systems)
      5  1.1  skrll  * Copyright (c) 1996 Christopher G. Demetriou
      6  1.1  skrll  * All rights reserved.
      7  1.1  skrll  *
      8  1.1  skrll  * Redistribution and use in source and binary forms, with or without
      9  1.1  skrll  * modification, are permitted provided that the following conditions
     10  1.1  skrll  * are met:
     11  1.1  skrll  * 1. Redistributions of source code must retain the above copyright
     12  1.1  skrll  *    notice, this list of conditions and the following disclaimer.
     13  1.1  skrll  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.1  skrll  *    notice, this list of conditions and the following disclaimer in the
     15  1.1  skrll  *    documentation and/or other materials provided with the distribution.
     16  1.1  skrll  * 3. The name of the author may not be used to endorse or promote products
     17  1.1  skrll  *    derived from this software without specific prior written permission.
     18  1.1  skrll  *
     19  1.1  skrll  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     20  1.1  skrll  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     21  1.1  skrll  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     22  1.1  skrll  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  1.1  skrll  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     24  1.1  skrll  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  1.1  skrll  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  1.1  skrll  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  1.1  skrll  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     28  1.1  skrll  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  1.1  skrll  *
     30  1.1  skrll  * <<Id: LICENSE_GC,v 1.1 2001/10/01 23:24:05 cgd Exp>>
     31  1.1  skrll  */
     32  1.1  skrll 
     33  1.1  skrll #if HAVE_NBTOOL_CONFIG_H
     34  1.1  skrll #include "nbtool_config.h"
     35  1.1  skrll #endif
     36  1.1  skrll 
     37  1.1  skrll #include <sys/cdefs.h>
     38  1.1  skrll #if !defined(lint)
     39  1.1  skrll __COPYRIGHT("@(#) Copyright (c) 1996 Christopher G. Demetriou.\
     40  1.1  skrll   Copyright 2001 Simon Burge.\
     41  1.1  skrll   All rights reserved.");
     42  1.4  joerg __RCSID("$NetBSD: dbsym.c,v 1.4 2014/08/17 19:12:59 joerg Exp $");
     43  1.1  skrll #endif /* not lint */
     44  1.1  skrll 
     45  1.1  skrll #include <sys/param.h>
     46  1.1  skrll #include <sys/mman.h>
     47  1.1  skrll #include <sys/stat.h>
     48  1.1  skrll 
     49  1.1  skrll #include <bfd.h>
     50  1.1  skrll #include <err.h>
     51  1.1  skrll #include <fcntl.h>
     52  1.1  skrll #include <stdio.h>
     53  1.1  skrll #include <stdlib.h>
     54  1.1  skrll #include <string.h>
     55  1.1  skrll #include <unistd.h>
     56  1.1  skrll 
     57  1.1  skrll /* BFD ELF headers */
     58  1.1  skrll #include <elf/common.h>
     59  1.1  skrll #include <elf/external.h>
     60  1.1  skrll 
     61  1.1  skrll struct symbols {
     62  1.1  skrll 	char *name;
     63  1.1  skrll 	size_t offset;
     64  1.1  skrll } db_symtab_symbols[] = {
     65  1.1  skrll #define	X_DB_SYMTAB	0
     66  1.1  skrll 	{ "_db_symtab", 0 },
     67  1.1  skrll #define	X_DB_SYMTABSIZE	1
     68  1.1  skrll 	{ "_db_symtabsize", 0 },
     69  1.1  skrll 	{ NULL, 0 }
     70  1.1  skrll };
     71  1.1  skrll 
     72  1.1  skrll int	main(int, char **);
     73  1.1  skrll void	usage(void) __attribute__((noreturn));
     74  1.1  skrll int	find_symtab(bfd *, struct symbols *);
     75  1.1  skrll int	load_symtab(bfd *, int fd, char **, u_int32_t *);
     76  1.1  skrll 
     77  1.1  skrll int	verbose;
     78  1.2    bsh int	printsize;
     79  1.4  joerg int	printsize2;
     80  1.1  skrll 
     81  1.1  skrll int
     82  1.1  skrll main(int argc, char **argv)
     83  1.1  skrll {
     84  1.1  skrll 	int ch, kfd;
     85  1.1  skrll 	struct stat ksb;
     86  1.1  skrll 	size_t symtab_offset;
     87  1.1  skrll 	u_int32_t symtab_space, symtabsize;
     88  1.1  skrll 	const char *kfile;
     89  1.1  skrll 	char *bfdname, *mappedkfile, *symtab;
     90  1.1  skrll 	bfd *abfd;
     91  1.1  skrll 
     92  1.1  skrll 	setprogname(argv[0]);
     93  1.1  skrll 
     94  1.1  skrll 	bfdname = NULL;
     95  1.4  joerg 	while ((ch = getopt(argc, argv, "b:Ppv")) != -1)
     96  1.1  skrll 		switch (ch) {
     97  1.1  skrll 		case 'b':
     98  1.1  skrll 			bfdname = optarg;
     99  1.1  skrll 			break;
    100  1.1  skrll 		case 'v':
    101  1.1  skrll 			verbose = 1;
    102  1.1  skrll 			break;
    103  1.2    bsh 		case 'p':
    104  1.2    bsh 			printsize = 1;
    105  1.2    bsh 			break;
    106  1.4  joerg 		case 'P':
    107  1.4  joerg 			printsize2 = 1;
    108  1.4  joerg 			break;
    109  1.1  skrll 		case '?':
    110  1.1  skrll 		default:
    111  1.1  skrll 			usage();
    112  1.1  skrll 	}
    113  1.1  skrll 	argc -= optind;
    114  1.1  skrll 	argv += optind;
    115  1.1  skrll 
    116  1.1  skrll 	if (argc != 1)
    117  1.1  skrll 		usage();
    118  1.1  skrll 	kfile = argv[0];
    119  1.1  skrll 
    120  1.1  skrll 	if ((kfd = open(kfile, O_RDWR, 0))  == -1)
    121  1.1  skrll 		err(1, "open %s", kfile);
    122  1.1  skrll 
    123  1.1  skrll 	bfd_init();
    124  1.1  skrll 	if ((abfd = bfd_fdopenr(kfile, bfdname, kfd)) == NULL) {
    125  1.1  skrll 		bfd_perror("open");
    126  1.1  skrll 		exit(1);
    127  1.1  skrll 	}
    128  1.1  skrll 	if (!bfd_check_format(abfd, bfd_object)) {
    129  1.1  skrll 		bfd_perror("check format");
    130  1.1  skrll 		exit(1);
    131  1.1  skrll 	}
    132  1.1  skrll 
    133  1.1  skrll 	if (!(bfd_get_file_flags(abfd) & HAS_SYMS))
    134  1.1  skrll 		errx(1, "no symbol table in %s", kfile);
    135  1.1  skrll 
    136  1.1  skrll 	if (find_symtab(abfd, db_symtab_symbols) != 0)
    137  1.1  skrll 		errx(1, "could not find SYMTAB_SPACE in %s", kfile);
    138  1.1  skrll 	if (verbose)
    139  1.1  skrll 		fprintf(stderr, "got SYMTAB_SPACE symbols from %s\n", kfile);
    140  1.1  skrll 
    141  1.1  skrll 	if (load_symtab(abfd, kfd, &symtab, &symtabsize) != 0)
    142  1.1  skrll 		errx(1, "could not load symbol table from %s", kfile);
    143  1.1  skrll 	if (verbose)
    144  1.1  skrll 		fprintf(stderr, "loaded symbol table from %s\n", kfile);
    145  1.1  skrll 
    146  1.1  skrll 	if (fstat(kfd, &ksb) == -1)
    147  1.1  skrll 		err(1, "fstat %s", kfile);
    148  1.1  skrll 	if (ksb.st_size != (size_t)ksb.st_size)
    149  1.1  skrll 		errx(1, "%s too big to map", kfile);
    150  1.1  skrll 
    151  1.1  skrll 	if ((mappedkfile = mmap(NULL, ksb.st_size, PROT_READ | PROT_WRITE,
    152  1.1  skrll 	    MAP_FILE | MAP_SHARED, kfd, 0)) == (caddr_t)-1)
    153  1.1  skrll 		err(1, "mmap %s", kfile);
    154  1.1  skrll 	if (verbose)
    155  1.1  skrll 		fprintf(stderr, "mapped %s\n", kfile);
    156  1.1  skrll 
    157  1.1  skrll 	symtab_offset = db_symtab_symbols[X_DB_SYMTAB].offset;
    158  1.1  skrll 	symtab_space = bfd_get_32(abfd,
    159  1.1  skrll 	    &mappedkfile[db_symtab_symbols[X_DB_SYMTABSIZE].offset]);
    160  1.1  skrll 
    161  1.2    bsh 	if (printsize) {
    162  1.2    bsh 		printf("%d %d\n", symtabsize, symtab_space);
    163  1.2    bsh 		goto done;
    164  1.2    bsh 	}
    165  1.4  joerg 	if (printsize2) {
    166  1.4  joerg 		printf("%d\n", symtabsize);
    167  1.4  joerg 		goto done;
    168  1.4  joerg 	}
    169  1.2    bsh 
    170  1.1  skrll 	if (symtabsize > symtab_space)
    171  1.1  skrll 		errx(1, "symbol table (%u bytes) too big for buffer (%u bytes)\n"
    172  1.1  skrll 		    "Increase options SYMTAB_SPACE in your kernel config",
    173  1.1  skrll 		    symtabsize, symtab_space);
    174  1.1  skrll 
    175  1.1  skrll 	if (verbose)
    176  1.1  skrll 		fprintf(stderr, "symtab size %d, space available %d\n",
    177  1.1  skrll 		    symtabsize, symtab_space);
    178  1.1  skrll 
    179  1.1  skrll 	memcpy(mappedkfile + symtab_offset, symtab, symtabsize);
    180  1.1  skrll 
    181  1.1  skrll 	if (verbose)
    182  1.1  skrll 		fprintf(stderr, "done copying image to file offset %#lx\n",
    183  1.1  skrll 		    (long)db_symtab_symbols[X_DB_SYMTAB].offset);
    184  1.1  skrll 
    185  1.1  skrll 	bfd_put_32(abfd, symtabsize,
    186  1.1  skrll 	    &mappedkfile[db_symtab_symbols[X_DB_SYMTABSIZE].offset]);
    187  1.1  skrll 
    188  1.2    bsh done:
    189  1.1  skrll 	munmap(mappedkfile, ksb.st_size);
    190  1.1  skrll 	close(kfd);
    191  1.1  skrll 
    192  1.1  skrll 	if (verbose)
    193  1.1  skrll 		fprintf(stderr, "exiting\n");
    194  1.1  skrll 
    195  1.1  skrll 	bfd_close_all_done(abfd);
    196  1.1  skrll 	exit(0);
    197  1.1  skrll }
    198  1.1  skrll 
    199  1.1  skrll void
    200  1.1  skrll usage(void)
    201  1.1  skrll {
    202  1.1  skrll 	const char **list;
    203  1.1  skrll 
    204  1.1  skrll 	fprintf(stderr,
    205  1.4  joerg 	    "usage: %s [-Ppv] [-b bfdname] kernel\n",
    206  1.1  skrll 	    getprogname());
    207  1.1  skrll 	fprintf(stderr, "supported targets:");
    208  1.1  skrll 	for (list = bfd_target_list(); *list != NULL; list++)
    209  1.1  skrll 		fprintf(stderr, " %s", *list);
    210  1.1  skrll 	fprintf(stderr, "\n");
    211  1.1  skrll 	exit(1);
    212  1.1  skrll }
    213  1.1  skrll 
    214  1.1  skrll int
    215  1.1  skrll find_symtab(bfd *abfd, struct symbols *symbols)
    216  1.1  skrll {
    217  1.1  skrll 	long i;
    218  1.1  skrll 	long storage_needed;
    219  1.1  skrll 	long number_of_symbols;
    220  1.1  skrll 	asymbol **symbol_table = NULL;
    221  1.1  skrll 	struct symbols *s;
    222  1.1  skrll 
    223  1.1  skrll 	storage_needed = bfd_get_symtab_upper_bound(abfd);
    224  1.1  skrll 	if (storage_needed <= 0)
    225  1.1  skrll 		return (1);
    226  1.1  skrll 
    227  1.1  skrll 	if ((symbol_table = (asymbol **)malloc(storage_needed)) == NULL)
    228  1.1  skrll 		return (1);
    229  1.1  skrll 
    230  1.1  skrll 	number_of_symbols = bfd_canonicalize_symtab(abfd, symbol_table);
    231  1.1  skrll 	if (number_of_symbols <= 0) {
    232  1.1  skrll 		free(symbol_table);
    233  1.1  skrll 		return (1);
    234  1.1  skrll 	}
    235  1.1  skrll 
    236  1.1  skrll 	for (i = 0; i < number_of_symbols; i++) {
    237  1.1  skrll 		for (s = symbols; s->name != NULL; s++) {
    238  1.1  skrll 		  const char *sym = symbol_table[i]->name;
    239  1.1  skrll 
    240  1.1  skrll 			/*
    241  1.1  skrll 			 * match symbol prefix '_' or ''.
    242  1.1  skrll 			 * XXX: use bfd_get_symbol_leading_char() here?
    243  1.1  skrll 			 */
    244  1.1  skrll 			if (!strcmp(s->name, sym) ||
    245  1.1  skrll 			    !strcmp(s->name + 1, sym)) {
    246  1.1  skrll 				s->offset = (size_t)
    247  1.1  skrll 				    (symbol_table[i]->section->filepos
    248  1.1  skrll                                     + symbol_table[i]->value);
    249  1.1  skrll 
    250  1.1  skrll 			}
    251  1.1  skrll 		}
    252  1.1  skrll 	}
    253  1.1  skrll 
    254  1.1  skrll 	free(symbol_table);
    255  1.1  skrll 
    256  1.1  skrll 	for (s = symbols; s->name != NULL; s++) {
    257  1.1  skrll 		if (s->offset == 0)
    258  1.1  skrll 			return (1);
    259  1.1  skrll 	}
    260  1.1  skrll 
    261  1.1  skrll 	return (0);
    262  1.1  skrll }
    263  1.1  skrll 
    264  1.1  skrll /* --------------------------- ELF gunk follows --------------------------- */
    265  1.1  skrll 
    266  1.1  skrll /*
    267  1.1  skrll  * The format of the symbols loaded by the boot program is:
    268  1.1  skrll  *
    269  1.1  skrll  *      Elf exec header
    270  1.1  skrll  *      first section header
    271  1.1  skrll  *      . . .
    272  1.1  skrll  *      . . .
    273  1.1  skrll  *      last section header
    274  1.1  skrll  *      first symbol or string table section
    275  1.1  skrll  *      . . .
    276  1.1  skrll  *      . . .
    277  1.1  skrll  *      last symbol or string table section
    278  1.1  skrll  */
    279  1.1  skrll 
    280  1.1  skrll 
    281  1.1  skrll /* Note elftype is local to load_symtab()... */
    282  1.1  skrll #define	ELF_TYPE_64	0x01
    283  1.1  skrll #define	ISELF64		(elftype & ELF_TYPE_64)
    284  1.1  skrll 
    285  1.1  skrll /*
    286  1.1  skrll  * Field sizes for the Elf exec header:
    287  1.1  skrll  *
    288  1.1  skrll  *    ELF32    ELF64
    289  1.1  skrll  *
    290  1.1  skrll  *    unsigned char      e_ident[ELF_NIDENT];    # Id bytes
    291  1.1  skrll  *     16       16       e_type;                 # file type
    292  1.1  skrll  *     16       16       e_machine;              # machine type
    293  1.1  skrll  *     32       32       e_version;              # version number
    294  1.1  skrll  *     32       64       e_entry;                # entry point
    295  1.1  skrll  *     32       64       e_phoff;                # Program hdr offset
    296  1.1  skrll  *     32       64       e_shoff;                # Section hdr offset
    297  1.1  skrll  *     32       32       e_flags;                # Processor flags
    298  1.1  skrll  *     16       16       e_ehsize;               # sizeof ehdr
    299  1.1  skrll  *     16       16       e_phentsize;            # Program header entry size
    300  1.1  skrll  *     16       16       e_phnum;                # Number of program headers
    301  1.1  skrll  *     16       16       e_shentsize;            # Section header entry size
    302  1.1  skrll  *     16       16       e_shnum;                # Number of section headers
    303  1.1  skrll  *     16       16       e_shstrndx;             # String table index
    304  1.1  skrll  */
    305  1.1  skrll 
    306  1.1  skrll typedef union {
    307  1.1  skrll 	Elf32_External_Ehdr e32hdr;
    308  1.1  skrll 	Elf64_External_Ehdr e64hdr;
    309  1.1  skrll 	char e_ident[16];		/* XXX MAGIC NUMBER */
    310  1.1  skrll } elf_ehdr;
    311  1.1  skrll 
    312  1.1  skrll #define	e32_hdr	ehdr.e32hdr
    313  1.1  skrll #define	e64_hdr	ehdr.e64hdr
    314  1.1  skrll 
    315  1.1  skrll /*
    316  1.1  skrll  * Field sizes for Elf section headers
    317  1.1  skrll  *
    318  1.1  skrll  *    ELF32    ELF64
    319  1.1  skrll  *
    320  1.1  skrll  *     32       32       sh_name;        # section name (.shstrtab index)
    321  1.1  skrll  *     32       32       sh_type;        # section type
    322  1.1  skrll  *     32       64       sh_flags;       # section flags
    323  1.1  skrll  *     32       64       sh_addr;        # virtual address
    324  1.1  skrll  *     32       64       sh_offset;      # file offset
    325  1.1  skrll  *     32       64       sh_size;        # section size
    326  1.1  skrll  *     32       32       sh_link;        # link to another
    327  1.1  skrll  *     32       32       sh_info;        # misc info
    328  1.1  skrll  *     32       64       sh_addralign;   # memory alignment
    329  1.1  skrll  *     32       64       sh_entsize;     # table entry size
    330  1.1  skrll  */
    331  1.1  skrll 
    332  1.1  skrll /* Extract a 32 bit field from Elf32_Shdr */
    333  1.1  skrll #define	SH_E32_32(x, n)		bfd_get_32(abfd, s32hdr[(x)].n)
    334  1.1  skrll 
    335  1.1  skrll /* Extract a 32 bit field from Elf64_Shdr */
    336  1.1  skrll #define	SH_E64_32(x, n)		bfd_get_32(abfd, s64hdr[(x)].n)
    337  1.1  skrll 
    338  1.1  skrll /* Extract a 64 bit field from Elf64_Shdr */
    339  1.1  skrll #define	SH_E64_64(x, n)		bfd_get_64(abfd, s64hdr[(x)].n)
    340  1.1  skrll 
    341  1.1  skrll /* Extract a 32 bit field from either size Shdr */
    342  1.1  skrll #define	SH_E32E32(x, n)	(ISELF64 ? SH_E64_32(x, n) : SH_E32_32(x, n))
    343  1.1  skrll 
    344  1.1  skrll /* Extract a 32 bit field from Elf32_Shdr or 64 bit field from Elf64_Shdr */
    345  1.1  skrll #define	SH_E32E64(x, n)	(ISELF64 ? SH_E64_64(x, n) : SH_E32_32(x, n))
    346  1.1  skrll 
    347  1.1  skrll #define	SH_NAME(x)	SH_E32E32(x, sh_name)
    348  1.1  skrll #define	SH_TYPE(x)	SH_E32E32(x, sh_type)
    349  1.1  skrll #define	SH_FLAGS(x)	SH_E32E64(x, sh_flags)
    350  1.1  skrll #define	SH_ADDR(x)	SH_E32E64(x, sh_addr)
    351  1.1  skrll #define	SH_OFFSET(x)	SH_E32E64(x, sh_offset)
    352  1.1  skrll #define	SH_SIZE(x)	SH_E32E64(x, sh_size)
    353  1.1  skrll #define	SH_LINK(x)	SH_E32E32(x, sh_link)
    354  1.1  skrll #define	SH_INFO(x)	SH_E32E32(x, sh_info)
    355  1.1  skrll #define	SH_ADDRALIGN(x)	SH_E32E64(x, sh_addralign)
    356  1.1  skrll #define	SH_ENTSIZE(x)	SH_E32E64(x, sh_entsize)
    357  1.1  skrll 
    358  1.1  skrll int
    359  1.1  skrll load_symtab(bfd *abfd, int fd, char **symtab, u_int32_t *symtabsize)
    360  1.1  skrll {
    361  1.1  skrll 	elf_ehdr ehdr;
    362  1.1  skrll 	Elf32_External_Shdr *s32hdr = NULL;
    363  1.1  skrll 	Elf64_External_Shdr *s64hdr = NULL;
    364  1.1  skrll 	void *shdr;
    365  1.1  skrll 	u_int32_t osymtabsize, sh_offset;
    366  1.1  skrll 	int elftype, e_shnum, i, sh_size;
    367  1.1  skrll 	off_t e_shoff;
    368  1.1  skrll 
    369  1.1  skrll 	if (lseek(fd, 0, SEEK_SET) < 0)
    370  1.1  skrll 		return (1);
    371  1.1  skrll 	if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
    372  1.1  skrll 		return (1);
    373  1.1  skrll 
    374  1.1  skrll 	/*
    375  1.1  skrll 	 * Check that we are targetting an Elf binary.
    376  1.1  skrll 	 */
    377  1.1  skrll 	if (ehdr.e_ident[EI_MAG0] != ELFMAG0 ||
    378  1.1  skrll 	    ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
    379  1.1  skrll 	    ehdr.e_ident[EI_MAG2] != ELFMAG2 ||
    380  1.1  skrll 	    ehdr.e_ident[EI_MAG3] != ELFMAG3)
    381  1.1  skrll 		return (1);
    382  1.1  skrll 
    383  1.1  skrll 	/*
    384  1.1  skrll 	 * Determine Elf size and endianness.
    385  1.1  skrll 	 */
    386  1.1  skrll 	elftype = 0;
    387  1.1  skrll 	if (ehdr.e_ident[EI_CLASS] == ELFCLASS64)
    388  1.1  skrll 		elftype |= ELF_TYPE_64;
    389  1.1  skrll 
    390  1.1  skrll 	/*
    391  1.1  skrll 	 * Elf exec header.  Only need to allocate space for now,
    392  1.1  skrll 	 * the header is copied into place at the end.
    393  1.1  skrll 	 */
    394  1.1  skrll 	*symtabsize = ISELF64 ? sizeof(Elf64_External_Ehdr)
    395  1.1  skrll 			      : sizeof(Elf32_External_Ehdr);
    396  1.1  skrll 	*symtab = NULL;
    397  1.1  skrll 
    398  1.1  skrll 	/*
    399  1.1  skrll 	 * Section headers.  Allocate a temporary copy that will
    400  1.1  skrll 	 * be copied into place at the end.
    401  1.1  skrll 	 */
    402  1.1  skrll 	sh_offset = osymtabsize = *symtabsize;
    403  1.1  skrll 	e_shnum = (ISELF64
    404  1.1  skrll 	    ? bfd_get_16(abfd, e64_hdr.e_shnum)
    405  1.1  skrll 	    : bfd_get_16(abfd, e32_hdr.e_shnum));
    406  1.1  skrll 	sh_size = e_shnum * (ISELF64 ? sizeof(Elf64_External_Shdr)
    407  1.1  skrll 				     : sizeof(Elf32_External_Shdr));
    408  1.1  skrll 	if ((shdr = malloc(sh_size)) == NULL)
    409  1.1  skrll 		return (1);
    410  1.1  skrll 	if (ISELF64)
    411  1.1  skrll 		s64hdr = shdr;
    412  1.1  skrll 	else
    413  1.1  skrll 		s32hdr = shdr;
    414  1.1  skrll 
    415  1.1  skrll 	*symtabsize += roundup(sh_size, ISELF64 ? 8 : 4);
    416  1.1  skrll 
    417  1.1  skrll 	e_shoff = (ISELF64
    418  1.1  skrll 	   ? bfd_get_64(abfd, e64_hdr.e_shoff)
    419  1.1  skrll 	   : bfd_get_32(abfd, e32_hdr.e_shoff));
    420  1.1  skrll 	if (lseek(fd, e_shoff, SEEK_SET) < 0)
    421  1.1  skrll 		goto out;
    422  1.1  skrll 	if (read(fd, shdr, sh_size) != sh_size)
    423  1.1  skrll 		goto out;
    424  1.1  skrll 
    425  1.1  skrll 	for (i = 0; i < e_shnum; i++) {
    426  1.1  skrll 		if (SH_TYPE(i) == SHT_SYMTAB || SH_TYPE(i) == SHT_STRTAB) {
    427  1.1  skrll 			osymtabsize = *symtabsize;
    428  1.1  skrll 			*symtabsize += roundup(SH_SIZE(i), ISELF64 ? 8 : 4);
    429  1.1  skrll 			if ((*symtab = realloc(*symtab, *symtabsize)) == NULL)
    430  1.1  skrll 				goto out;
    431  1.1  skrll 
    432  1.1  skrll 			if (lseek(fd, SH_OFFSET(i), SEEK_SET) < 0)
    433  1.1  skrll 				goto out;
    434  1.1  skrll 			if (read(fd, *symtab + osymtabsize, SH_SIZE(i)) !=
    435  1.1  skrll 			    SH_SIZE(i))
    436  1.1  skrll 				goto out;
    437  1.1  skrll 			if (ISELF64) {
    438  1.1  skrll 				bfd_put_64(abfd, osymtabsize,
    439  1.1  skrll 				    s64hdr[i].sh_offset);
    440  1.1  skrll 			} else {
    441  1.1  skrll 				bfd_put_32(abfd, osymtabsize,
    442  1.1  skrll 				    s32hdr[i].sh_offset);
    443  1.1  skrll 			}
    444  1.1  skrll 		}
    445  1.1  skrll 	}
    446  1.1  skrll 
    447  1.1  skrll 	if (*symtab == NULL)
    448  1.1  skrll 		goto out;
    449  1.1  skrll 
    450  1.1  skrll 	/*
    451  1.1  skrll 	 * Copy updated section headers.
    452  1.1  skrll 	 */
    453  1.1  skrll 	memcpy(*symtab + sh_offset, shdr, sh_size);
    454  1.1  skrll 
    455  1.1  skrll 	/*
    456  1.1  skrll 	 * Update and copy the exec header.
    457  1.1  skrll 	 */
    458  1.1  skrll 	if (ISELF64) {
    459  1.1  skrll 		bfd_put_64(abfd, 0, e64_hdr.e_phoff);
    460  1.1  skrll 		bfd_put_64(abfd, sizeof(Elf64_External_Ehdr), e64_hdr.e_shoff);
    461  1.1  skrll 		bfd_put_16(abfd, 0, e64_hdr.e_phentsize);
    462  1.1  skrll 		bfd_put_16(abfd, 0, e64_hdr.e_phnum);
    463  1.1  skrll 	} else {
    464  1.1  skrll 		bfd_put_32(abfd, 0, e32_hdr.e_phoff);
    465  1.1  skrll 		bfd_put_32(abfd, sizeof(Elf32_External_Ehdr), e32_hdr.e_shoff);
    466  1.1  skrll 		bfd_put_16(abfd, 0, e32_hdr.e_phentsize);
    467  1.1  skrll 		bfd_put_16(abfd, 0, e32_hdr.e_phnum);
    468  1.1  skrll 	}
    469  1.1  skrll 	memcpy(*symtab, &ehdr, sizeof(ehdr));
    470  1.1  skrll 
    471  1.1  skrll 	free(shdr);
    472  1.1  skrll 	return (0);
    473  1.1  skrll out:
    474  1.1  skrll 	free(shdr);
    475  1.1  skrll 	return (1);
    476  1.1  skrll }
    477