xref: /netbsd-src/external/gpl3/binutils.old/usr.sbin/mdsetimage/bin_bfd.c (revision bdc22b2e01993381dcefeff2bc9b56ca75a4235c)
1 /*	$NetBSD: bin_bfd.c,v 1.3 2018/04/14 17:53:22 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1996, 2002 Christopher G. Demetriou
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  * <<Id: LICENSE_GC,v 1.1 2001/10/01 23:24:05 cgd Exp>>
30  */
31 
32 #if HAVE_NBTOOL_CONFIG_H
33 #include "nbtool_config.h"
34 #endif
35 
36 #include <sys/cdefs.h>
37 __RCSID("$NetBSD: bin_bfd.c,v 1.3 2018/04/14 17:53:22 christos Exp $");
38 
39 #include <stdio.h>
40 #include <string.h>
41 #include <stdlib.h>
42 #include <err.h>
43 #include <bfd.h>
44 #include "bin.h"
45 
46 void *
47 bin_open(int kfd, const char *kfile, const char *bfdname)
48 {
49 	bfd *abfd;
50 	bfd_init();
51 	if ((abfd = bfd_fdopenr(kfile, bfdname, kfd)) == NULL) {
52 		bfd_perror("open");
53 		exit(1);
54 	}
55 	if (!bfd_check_format(abfd, bfd_object)) {
56 		bfd_perror("check format");
57 		exit(1);
58 	}
59 	return abfd;
60 }
61 
62 int
63 bin_find_md_root(void *bin, const char *mappedkfile, off_t size,
64     unsigned long text_start,
65     const char *root_name, const char *size_name, size_t *md_root_offset,
66     size_t *md_root_size_offset, uint32_t *md_root_size, int verbose)
67 {
68 	bfd *abfd = bin;
69 	long i;
70 	long storage_needed;
71 	long number_of_symbols;
72 	asymbol **symbol_table = NULL;
73 	struct symbols {
74 		const char *name;
75 		size_t offset;
76 	} *s, symbols[3];
77 
78 	symbols[0].offset = 0;
79 	symbols[1].offset = 0;
80 	symbols[0].name = root_name;
81 	symbols[1].name = size_name;
82 	symbols[2].name = NULL;
83 
84 	storage_needed = bfd_get_symtab_upper_bound(abfd);
85 	if (storage_needed <= 0) {
86 		warnx("bfd storage needed error");
87 		return 1;
88 	}
89 
90 	symbol_table = malloc(storage_needed);
91 	if (symbol_table == NULL) {
92 		warn("symbol table");
93 		return 1;
94 	}
95 
96 	number_of_symbols = bfd_canonicalize_symtab(abfd, symbol_table);
97 	if (number_of_symbols <= 0) {
98 		warnx("can't canonicalize symbol table");
99 		free(symbol_table);
100 		return 1;
101 	}
102 
103 	for (i = 0; i < number_of_symbols; i++) {
104 		for (s = symbols; s->name != NULL; s++) {
105 			const char *sym = symbol_table[i]->name;
106 
107 			/*
108 			 * match symbol prefix '_' or ''.
109 			 */
110 			if (!strcmp(s->name, sym) ||
111 			    !strcmp(s->name + 1, sym)) {
112 				s->offset =
113 				    (size_t)(symbol_table[i]->section->filepos
114 				    + symbol_table[i]->value);
115 			}
116 		}
117 	}
118 
119 	free(symbol_table);
120 
121 	for (s = symbols; s->name != NULL; s++) {
122 		if (s->offset == 0) {
123 			warnx("missing offset for `%s'", s->name);
124 			return 1;
125 		}
126 	}
127 
128 	*md_root_offset = symbols[0].offset;
129 	*md_root_size_offset = symbols[1].offset;
130 	*md_root_size = bfd_get_32(abfd, &mappedkfile[*md_root_size_offset]);
131 
132 	return 0;
133 }
134 
135 void
136 bin_put_32(void *bin, off_t size, char *buf)
137 {
138 	bfd_put_32((struct bfd *)bin, size, buf);
139 }
140 
141 void
142 bin_close(void *bin)
143 {
144 	bfd_close_all_done((struct bfd *)bin);
145 }
146 
147 const char **
148 bin_supported_targets(void)
149 {
150 	return bfd_target_list();
151 }
152