1 /* $NetBSD: dbsym.c,v 1.4 2014/08/17 19:12:59 joerg Exp $ */
4 * Copyright (c) 2001 Simon Burge (for Wasabi Systems)
5 * Copyright (c) 1996 Christopher G. Demetriou
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * <<Id: LICENSE_GC,v 1.1 2001/10/01 23:24:05 cgd Exp>>
33 #if HAVE_NBTOOL_CONFIG_H
34 #include "nbtool_config.h"
37 #include <sys/cdefs.h>
39 __COPYRIGHT("@(#) Copyright (c) 1996 Christopher G. Demetriou.\
40 Copyright 2001 Simon Burge.\
41 All rights reserved.");
42 __RCSID("$NetBSD: dbsym.c,v 1.4 2014/08/17 19:12:59 joerg Exp $");
45 #include <sys/param.h>
58 #include <elf/common.h>
59 #include <elf/external.h>
64 } db_symtab_symbols
[] = {
67 #define X_DB_SYMTABSIZE 1
68 { "_db_symtabsize", 0 },
72 int main(int, char **);
73 void usage(void) __attribute__((noreturn
));
74 int find_symtab(bfd
*, struct symbols
*);
75 int load_symtab(bfd
*, int fd
, char **, u_int32_t
*);
82 main(int argc
, char **argv
)
87 u_int32_t symtab_space
, symtabsize
;
89 char *bfdname
, *mappedkfile
, *symtab
;
95 while ((ch
= getopt(argc
, argv
, "b:Ppv")) != -1)
120 if ((kfd
= open(kfile
, O_RDWR
, 0)) == -1)
121 err(1, "open %s", kfile
);
124 if ((abfd
= bfd_fdopenr(kfile
, bfdname
, kfd
)) == NULL
) {
128 if (!bfd_check_format(abfd
, bfd_object
)) {
129 bfd_perror("check format");
133 if (!(bfd_get_file_flags(abfd
) & HAS_SYMS
))
134 errx(1, "no symbol table in %s", kfile
);
136 if (find_symtab(abfd
, db_symtab_symbols
) != 0)
137 errx(1, "could not find SYMTAB_SPACE in %s", kfile
);
139 fprintf(stderr
, "got SYMTAB_SPACE symbols from %s\n", kfile
);
141 if (load_symtab(abfd
, kfd
, &symtab
, &symtabsize
) != 0)
142 errx(1, "could not load symbol table from %s", kfile
);
144 fprintf(stderr
, "loaded symbol table from %s\n", kfile
);
146 if (fstat(kfd
, &ksb
) == -1)
147 err(1, "fstat %s", kfile
);
148 if (ksb
.st_size
!= (size_t)ksb
.st_size
)
149 errx(1, "%s too big to map", kfile
);
151 if ((mappedkfile
= mmap(NULL
, ksb
.st_size
, PROT_READ
| PROT_WRITE
,
152 MAP_FILE
| MAP_SHARED
, kfd
, 0)) == (caddr_t
)-1)
153 err(1, "mmap %s", kfile
);
155 fprintf(stderr
, "mapped %s\n", kfile
);
157 symtab_offset
= db_symtab_symbols
[X_DB_SYMTAB
].offset
;
158 symtab_space
= bfd_get_32(abfd
,
159 &mappedkfile
[db_symtab_symbols
[X_DB_SYMTABSIZE
].offset
]);
162 printf("%d %d\n", symtabsize
, symtab_space
);
166 printf("%d\n", symtabsize
);
170 if (symtabsize
> symtab_space
)
171 errx(1, "symbol table (%u bytes) too big for buffer (%u bytes)\n"
172 "Increase options SYMTAB_SPACE in your kernel config",
173 symtabsize
, symtab_space
);
176 fprintf(stderr
, "symtab size %d, space available %d\n",
177 symtabsize
, symtab_space
);
179 memcpy(mappedkfile
+ symtab_offset
, symtab
, symtabsize
);
182 fprintf(stderr
, "done copying image to file offset %#lx\n",
183 (long)db_symtab_symbols
[X_DB_SYMTAB
].offset
);
185 bfd_put_32(abfd
, symtabsize
,
186 &mappedkfile
[db_symtab_symbols
[X_DB_SYMTABSIZE
].offset
]);
189 munmap(mappedkfile
, ksb
.st_size
);
193 fprintf(stderr
, "exiting\n");
195 bfd_close_all_done(abfd
);
205 "usage: %s [-Ppv] [-b bfdname] kernel\n",
207 fprintf(stderr
, "supported targets:");
208 for (list
= bfd_target_list(); *list
!= NULL
; list
++)
209 fprintf(stderr
, " %s", *list
);
210 fprintf(stderr
, "\n");
215 find_symtab(bfd
*abfd
, struct symbols
*symbols
)
219 long number_of_symbols
;
220 asymbol
**symbol_table
= NULL
;
223 storage_needed
= bfd_get_symtab_upper_bound(abfd
);
224 if (storage_needed
<= 0)
227 if ((symbol_table
= (asymbol
**)malloc(storage_needed
)) == NULL
)
230 number_of_symbols
= bfd_canonicalize_symtab(abfd
, symbol_table
);
231 if (number_of_symbols
<= 0) {
236 for (i
= 0; i
< number_of_symbols
; i
++) {
237 for (s
= symbols
; s
->name
!= NULL
; s
++) {
238 const char *sym
= symbol_table
[i
]->name
;
241 * match symbol prefix '_' or ''.
242 * XXX: use bfd_get_symbol_leading_char() here?
244 if (!strcmp(s
->name
, sym
) ||
245 !strcmp(s
->name
+ 1, sym
)) {
247 (symbol_table
[i
]->section
->filepos
248 + symbol_table
[i
]->value
);
256 for (s
= symbols
; s
->name
!= NULL
; s
++) {
264 /* --------------------------- ELF gunk follows --------------------------- */
267 * The format of the symbols loaded by the boot program is:
270 * first section header
273 * last section header
274 * first symbol or string table section
277 * last symbol or string table section
281 /* Note elftype is local to load_symtab()... */
282 #define ELF_TYPE_64 0x01
283 #define ISELF64 (elftype & ELF_TYPE_64)
286 * Field sizes for the Elf exec header:
290 * unsigned char e_ident[ELF_NIDENT]; # Id bytes
291 * 16 16 e_type; # file type
292 * 16 16 e_machine; # machine type
293 * 32 32 e_version; # version number
294 * 32 64 e_entry; # entry point
295 * 32 64 e_phoff; # Program hdr offset
296 * 32 64 e_shoff; # Section hdr offset
297 * 32 32 e_flags; # Processor flags
298 * 16 16 e_ehsize; # sizeof ehdr
299 * 16 16 e_phentsize; # Program header entry size
300 * 16 16 e_phnum; # Number of program headers
301 * 16 16 e_shentsize; # Section header entry size
302 * 16 16 e_shnum; # Number of section headers
303 * 16 16 e_shstrndx; # String table index
307 Elf32_External_Ehdr e32hdr
;
308 Elf64_External_Ehdr e64hdr
;
309 char e_ident
[16]; /* XXX MAGIC NUMBER */
312 #define e32_hdr ehdr.e32hdr
313 #define e64_hdr ehdr.e64hdr
316 * Field sizes for Elf section headers
320 * 32 32 sh_name; # section name (.shstrtab index)
321 * 32 32 sh_type; # section type
322 * 32 64 sh_flags; # section flags
323 * 32 64 sh_addr; # virtual address
324 * 32 64 sh_offset; # file offset
325 * 32 64 sh_size; # section size
326 * 32 32 sh_link; # link to another
327 * 32 32 sh_info; # misc info
328 * 32 64 sh_addralign; # memory alignment
329 * 32 64 sh_entsize; # table entry size
332 /* Extract a 32 bit field from Elf32_Shdr */
333 #define SH_E32_32(x, n) bfd_get_32(abfd, s32hdr[(x)].n)
335 /* Extract a 32 bit field from Elf64_Shdr */
336 #define SH_E64_32(x, n) bfd_get_32(abfd, s64hdr[(x)].n)
338 /* Extract a 64 bit field from Elf64_Shdr */
339 #define SH_E64_64(x, n) bfd_get_64(abfd, s64hdr[(x)].n)
341 /* Extract a 32 bit field from either size Shdr */
342 #define SH_E32E32(x, n) (ISELF64 ? SH_E64_32(x, n) : SH_E32_32(x, n))
344 /* Extract a 32 bit field from Elf32_Shdr or 64 bit field from Elf64_Shdr */
345 #define SH_E32E64(x, n) (ISELF64 ? SH_E64_64(x, n) : SH_E32_32(x, n))
347 #define SH_NAME(x) SH_E32E32(x, sh_name)
348 #define SH_TYPE(x) SH_E32E32(x, sh_type)
349 #define SH_FLAGS(x) SH_E32E64(x, sh_flags)
350 #define SH_ADDR(x) SH_E32E64(x, sh_addr)
351 #define SH_OFFSET(x) SH_E32E64(x, sh_offset)
352 #define SH_SIZE(x) SH_E32E64(x, sh_size)
353 #define SH_LINK(x) SH_E32E32(x, sh_link)
354 #define SH_INFO(x) SH_E32E32(x, sh_info)
355 #define SH_ADDRALIGN(x) SH_E32E64(x, sh_addralign)
356 #define SH_ENTSIZE(x) SH_E32E64(x, sh_entsize)
359 load_symtab(bfd
*abfd
, int fd
, char **symtab
, u_int32_t
*symtabsize
)
362 Elf32_External_Shdr
*s32hdr
= NULL
;
363 Elf64_External_Shdr
*s64hdr
= NULL
;
365 u_int32_t osymtabsize
, sh_offset
;
366 int elftype
, e_shnum
, i
, sh_size
;
369 if (lseek(fd
, 0, SEEK_SET
) < 0)
371 if (read(fd
, &ehdr
, sizeof(ehdr
)) != sizeof(ehdr
))
375 * Check that we are targetting an Elf binary.
377 if (ehdr
.e_ident
[EI_MAG0
] != ELFMAG0
||
378 ehdr
.e_ident
[EI_MAG1
] != ELFMAG1
||
379 ehdr
.e_ident
[EI_MAG2
] != ELFMAG2
||
380 ehdr
.e_ident
[EI_MAG3
] != ELFMAG3
)
384 * Determine Elf size and endianness.
387 if (ehdr
.e_ident
[EI_CLASS
] == ELFCLASS64
)
388 elftype
|= ELF_TYPE_64
;
391 * Elf exec header. Only need to allocate space for now,
392 * the header is copied into place at the end.
394 *symtabsize
= ISELF64
? sizeof(Elf64_External_Ehdr
)
395 : sizeof(Elf32_External_Ehdr
);
399 * Section headers. Allocate a temporary copy that will
400 * be copied into place at the end.
402 sh_offset
= osymtabsize
= *symtabsize
;
404 ? bfd_get_16(abfd
, e64_hdr
.e_shnum
)
405 : bfd_get_16(abfd
, e32_hdr
.e_shnum
));
406 sh_size
= e_shnum
* (ISELF64
? sizeof(Elf64_External_Shdr
)
407 : sizeof(Elf32_External_Shdr
));
408 if ((shdr
= malloc(sh_size
)) == NULL
)
415 *symtabsize
+= roundup(sh_size
, ISELF64
? 8 : 4);
418 ? bfd_get_64(abfd
, e64_hdr
.e_shoff
)
419 : bfd_get_32(abfd
, e32_hdr
.e_shoff
));
420 if (lseek(fd
, e_shoff
, SEEK_SET
) < 0)
422 if (read(fd
, shdr
, sh_size
) != sh_size
)
425 for (i
= 0; i
< e_shnum
; i
++) {
426 if (SH_TYPE(i
) == SHT_SYMTAB
|| SH_TYPE(i
) == SHT_STRTAB
) {
427 osymtabsize
= *symtabsize
;
428 *symtabsize
+= roundup(SH_SIZE(i
), ISELF64
? 8 : 4);
429 if ((*symtab
= realloc(*symtab
, *symtabsize
)) == NULL
)
432 if (lseek(fd
, SH_OFFSET(i
), SEEK_SET
) < 0)
434 if (read(fd
, *symtab
+ osymtabsize
, SH_SIZE(i
)) !=
438 bfd_put_64(abfd
, osymtabsize
,
439 s64hdr
[i
].sh_offset
);
441 bfd_put_32(abfd
, osymtabsize
,
442 s32hdr
[i
].sh_offset
);
451 * Copy updated section headers.
453 memcpy(*symtab
+ sh_offset
, shdr
, sh_size
);
456 * Update and copy the exec header.
459 bfd_put_64(abfd
, 0, e64_hdr
.e_phoff
);
460 bfd_put_64(abfd
, sizeof(Elf64_External_Ehdr
), e64_hdr
.e_shoff
);
461 bfd_put_16(abfd
, 0, e64_hdr
.e_phentsize
);
462 bfd_put_16(abfd
, 0, e64_hdr
.e_phnum
);
464 bfd_put_32(abfd
, 0, e32_hdr
.e_phoff
);
465 bfd_put_32(abfd
, sizeof(Elf32_External_Ehdr
), e32_hdr
.e_shoff
);
466 bfd_put_16(abfd
, 0, e32_hdr
.e_phentsize
);
467 bfd_put_16(abfd
, 0, e32_hdr
.e_phnum
);
469 memcpy(*symtab
, &ehdr
, sizeof(ehdr
));