GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/nm/elf32.c Lines: 0 247 0.0 %
Date: 2016-12-06 Branches: 0 259 0.0 %

Line Branch Exec Source
1
#define ELFSIZE 32
2
/*	$OpenBSD: elf.c,v 1.34 2015/12/09 19:28:34 mmcc Exp $	*/
3
4
/*
5
 * Copyright (c) 2003 Michael Shalayeff
6
 * All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
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
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
21
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23
 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27
 * THE POSSIBILITY OF SUCH DAMAGE.
28
 */
29
30
#include <sys/mman.h>
31
#include <unistd.h>
32
#include <a.out.h>
33
#include <elf_abi.h>
34
#include <errno.h>
35
#include <err.h>
36
#include <stdint.h>
37
#include <stdio.h>
38
#include <stdlib.h>
39
#include <string.h>
40
#include <ctype.h>
41
#include "util.h"
42
#include "elfuncs.h"
43
44
#if ELFSIZE == 32
45
#define	swap_addr	swap32
46
#define	swap_off	swap32
47
#define	swap_sword	swap32
48
#define	swap_word	swap32
49
#define	swap_sxword	swap32
50
#define	swap_xword	swap32
51
#define	swap_half	swap16
52
#define	swap_quarter	swap16
53
#define	elf_fix_header	elf32_fix_header
54
#define	elf_load_shdrs	elf32_load_shdrs
55
#define	elf_load_phdrs	elf32_load_phdrs
56
#define	elf_fix_shdrs	elf32_fix_shdrs
57
#define	elf_fix_phdrs	elf32_fix_phdrs
58
#define	elf_fix_sym	elf32_fix_sym
59
#define	elf_size	elf32_size
60
#define	elf_symloadx	elf32_symloadx
61
#define	elf_symload	elf32_symload
62
#define	elf2nlist	elf32_2nlist
63
#define	elf_shn2type	elf32_shn2type
64
#elif ELFSIZE == 64
65
#define	swap_addr	swap64
66
#define	swap_off	swap64
67
#ifdef __alpha__
68
#define	swap_sword	swap64
69
#define	swap_word	swap64
70
#else
71
#define	swap_sword	swap32
72
#define	swap_word	swap32
73
#endif
74
#define	swap_sxword	swap64
75
#define	swap_xword	swap64
76
#define	swap_half	swap64
77
#define	swap_quarter	swap16
78
#define	elf_fix_header	elf64_fix_header
79
#define	elf_load_shdrs	elf64_load_shdrs
80
#define	elf_load_phdrs	elf64_load_phdrs
81
#define	elf_fix_shdrs	elf64_fix_shdrs
82
#define	elf_fix_phdrs	elf64_fix_phdrs
83
#define	elf_fix_sym	elf64_fix_sym
84
#define	elf_size	elf64_size
85
#define	elf_symloadx	elf64_symloadx
86
#define	elf_symload	elf64_symload
87
#define	elf2nlist	elf64_2nlist
88
#define	elf_shn2type	elf64_shn2type
89
#else
90
#error "Unsupported ELF class"
91
#endif
92
93
#define	ELF_SDATA	".sdata"
94
#define	ELF_TDATA	".tdata"
95
#define	ELF_SBSS	".sbss"
96
#define	ELF_TBSS	".tbss"
97
#define	ELF_PLT		".plt"
98
99
#ifndef	SHN_MIPS_ACOMMON
100
#define	SHN_MIPS_ACOMMON	SHN_LOPROC + 0
101
#endif
102
#ifndef	SHN_MIPS_TEXT
103
#define	SHN_MIPS_TEXT		SHN_LOPROC + 1
104
#endif
105
#ifndef	SHN_MIPS_DATA
106
#define	SHN_MIPS_DATA		SHN_LOPROC + 2
107
#endif
108
#ifndef	SHN_MIPS_SUNDEFINED
109
#define	SHN_MIPS_SUNDEFINED	SHN_LOPROC + 4
110
#endif
111
#ifndef	SHN_MIPS_SCOMMON
112
#define	SHN_MIPS_SCOMMON	SHN_LOPROC + 3
113
#endif
114
115
#ifndef	STT_PARISC_MILLI
116
#define	STT_PARISC_MILLI	STT_LOPROC + 0
117
#endif
118
119
int elf_shn2type(Elf_Ehdr *, u_int, const char *);
120
int elf2nlist(Elf_Sym *, Elf_Ehdr *, Elf_Shdr *, char *, struct xnlist *);
121
122
int
123
elf_fix_header(Elf_Ehdr *eh)
124
{
125
	/* nothing to do */
126
	if (eh->e_ident[EI_DATA] == ELF_TARG_DATA)
127
		return (0);
128
129
	eh->e_type = swap16(eh->e_type);
130
	eh->e_machine = swap16(eh->e_machine);
131
	eh->e_version = swap32(eh->e_version);
132
	eh->e_entry = swap_addr(eh->e_entry);
133
	eh->e_phoff = swap_off(eh->e_phoff);
134
	eh->e_shoff = swap_off(eh->e_shoff);
135
	eh->e_flags = swap32(eh->e_flags);
136
	eh->e_ehsize = swap16(eh->e_ehsize);
137
	eh->e_phentsize = swap16(eh->e_phentsize);
138
	eh->e_phnum = swap16(eh->e_phnum);
139
	eh->e_shentsize = swap16(eh->e_shentsize);
140
	eh->e_shnum = swap16(eh->e_shnum);
141
	eh->e_shstrndx = swap16(eh->e_shstrndx);
142
143
	return (1);
144
}
145
146
Elf_Shdr *
147
elf_load_shdrs(const char *name, FILE *fp, off_t foff, Elf_Ehdr *head)
148
{
149
	Elf_Shdr *shdr;
150
151
	elf_fix_header(head);
152
153
	if (head->e_shnum == 0) {
154
		warnx("%s: no section header table", name);
155
		return (NULL);
156
	}
157
158
	if (head->e_shstrndx >= head->e_shnum) {
159
		warnx("%s: inconsistent section header table", name);
160
		return (NULL);
161
	}
162
163
	if (head->e_shentsize < sizeof(Elf_Shdr)) {
164
		warnx("%s: inconsistent section header size", name);
165
		return (NULL);
166
	}
167
168
	if ((shdr = calloc(head->e_shnum, head->e_shentsize)) == NULL) {
169
		warn("%s: malloc shdr", name);
170
		return (NULL);
171
	}
172
173
	if (fseeko(fp, foff + head->e_shoff, SEEK_SET)) {
174
		warn("%s: fseeko", name);
175
		free(shdr);
176
		return (NULL);
177
	}
178
179
	if (fread(shdr, head->e_shentsize, head->e_shnum, fp) != head->e_shnum) {
180
		warnx("%s: premature EOF", name);
181
		free(shdr);
182
		return (NULL);
183
	}
184
185
	elf_fix_shdrs(head, shdr);
186
	return (shdr);
187
}
188
189
Elf_Phdr *
190
elf_load_phdrs(const char *name, FILE *fp, off_t foff, Elf_Ehdr *head)
191
{
192
	Elf_Phdr *phdr;
193
194
	if ((phdr = calloc(head->e_phentsize, head->e_phnum)) == NULL) {
195
		warn("%s: malloc phdr", name);
196
		return (NULL);
197
	}
198
199
	if (fseeko(fp, foff + head->e_phoff, SEEK_SET)) {
200
		warn("%s: fseeko", name);
201
		free(phdr);
202
		return (NULL);
203
	}
204
205
	if (fread(phdr, head->e_phentsize, head->e_phnum, fp) != head->e_phnum) {
206
		warnx("%s: premature EOF", name);
207
		free(phdr);
208
		return (NULL);
209
	}
210
211
	elf_fix_phdrs(head, phdr);
212
	return (phdr);
213
}
214
215
int
216
elf_fix_shdrs(Elf_Ehdr *eh, Elf_Shdr *shdr)
217
{
218
	int i;
219
220
	/* nothing to do */
221
	if (eh->e_ident[EI_DATA] == ELF_TARG_DATA)
222
		return (0);
223
224
	for (i = eh->e_shnum; i--; shdr++) {
225
		shdr->sh_name = swap32(shdr->sh_name);
226
		shdr->sh_type = swap32(shdr->sh_type);
227
		shdr->sh_flags = swap_xword(shdr->sh_flags);
228
		shdr->sh_addr = swap_addr(shdr->sh_addr);
229
		shdr->sh_offset = swap_off(shdr->sh_offset);
230
		shdr->sh_size = swap_xword(shdr->sh_size);
231
		shdr->sh_link = swap32(shdr->sh_link);
232
		shdr->sh_info = swap32(shdr->sh_info);
233
		shdr->sh_addralign = swap_xword(shdr->sh_addralign);
234
		shdr->sh_entsize = swap_xword(shdr->sh_entsize);
235
	}
236
237
	return (1);
238
}
239
240
int
241
elf_fix_phdrs(Elf_Ehdr *eh, Elf_Phdr *phdr)
242
{
243
	int i;
244
245
	/* nothing to do */
246
	if (eh->e_ident[EI_DATA] == ELF_TARG_DATA)
247
		return (0);
248
249
	for (i = eh->e_phnum; i--; phdr++) {
250
		phdr->p_type = swap32(phdr->p_type);
251
		phdr->p_flags = swap32(phdr->p_flags);
252
		phdr->p_offset = swap_off(phdr->p_offset);
253
		phdr->p_vaddr = swap_addr(phdr->p_vaddr);
254
		phdr->p_paddr = swap_addr(phdr->p_paddr);
255
		phdr->p_filesz = swap_xword(phdr->p_filesz);
256
		phdr->p_memsz = swap_xword(phdr->p_memsz);
257
		phdr->p_align = swap_xword(phdr->p_align);
258
	}
259
260
	return (1);
261
}
262
263
int
264
elf_fix_sym(Elf_Ehdr *eh, Elf_Sym *sym)
265
{
266
	/* nothing to do */
267
	if (eh->e_ident[EI_DATA] == ELF_TARG_DATA)
268
		return (0);
269
270
	sym->st_name = swap32(sym->st_name);
271
	sym->st_shndx = swap16(sym->st_shndx);
272
	sym->st_value = swap_addr(sym->st_value);
273
	sym->st_size = swap_xword(sym->st_size);
274
275
	return (1);
276
}
277
278
int
279
elf_shn2type(Elf_Ehdr *eh, u_int shn, const char *sn)
280
{
281
	switch (shn) {
282
	case SHN_MIPS_SUNDEFINED:
283
		if (eh->e_machine == EM_MIPS)
284
			return (N_UNDF | N_EXT);
285
		break;
286
287
	case SHN_UNDEF:
288
		return (N_UNDF | N_EXT);
289
290
	case SHN_ABS:
291
		return (N_ABS);
292
293
	case SHN_MIPS_ACOMMON:
294
		if (eh->e_machine == EM_MIPS)
295
			return (N_COMM);
296
		break;
297
298
	case SHN_MIPS_SCOMMON:
299
		if (eh->e_machine == EM_MIPS)
300
			return (N_COMM);
301
		break;
302
303
	case SHN_COMMON:
304
		return (N_COMM);
305
306
	case SHN_MIPS_TEXT:
307
		if (eh->e_machine == EM_MIPS)
308
			return (N_TEXT);
309
		break;
310
311
	case SHN_MIPS_DATA:
312
		if (eh->e_machine == EM_MIPS)
313
			return (N_DATA);
314
		break;
315
316
	default:
317
		/* TODO: beyond 8 a table-driven binsearch should be used */
318
		if (sn == NULL)
319
			return (-1);
320
		else if (!strcmp(sn, ELF_TEXT))
321
			return (N_TEXT);
322
		else if (!strcmp(sn, ELF_RODATA))
323
			return (N_SIZE);
324
		else if (!strcmp(sn, ELF_DATA))
325
			return (N_DATA);
326
		else if (!strcmp(sn, ELF_SDATA))
327
			return (N_DATA);
328
		else if (!strcmp(sn, ELF_TDATA))
329
			return (N_DATA);
330
		else if (!strcmp(sn, ELF_BSS))
331
			return (N_BSS);
332
		else if (!strcmp(sn, ELF_SBSS))
333
			return (N_BSS);
334
		else if (!strcmp(sn, ELF_TBSS))
335
			return (N_BSS);
336
		else if (!strncmp(sn, ELF_GOT, sizeof(ELF_GOT) - 1))
337
			return (N_DATA);
338
		else if (!strncmp(sn, ELF_PLT, sizeof(ELF_PLT) - 1))
339
			return (N_DATA);
340
	}
341
342
	return (-1);
343
}
344
345
/*
346
 * Devise xnlist's type from Elf_Sym.
347
 * XXX this task is done as well in libc and kvm_mkdb.
348
 */
349
int
350
elf2nlist(Elf_Sym *sym, Elf_Ehdr *eh, Elf_Shdr *shdr, char *shstr,
351
    struct xnlist *np)
352
{
353
	u_char stt;
354
	const char *sn;
355
	int type;
356
357
	if (sym->st_shndx < eh->e_shnum)
358
		sn = shstr + shdr[sym->st_shndx].sh_name;
359
	else
360
		sn = NULL;
361
#if 0
362
	{
363
		extern char *stab;
364
		printf("%d:%s %d %d %s\n", sym->st_shndx, sn? sn : "",
365
		    ELF_ST_TYPE(sym->st_info), ELF_ST_BIND(sym->st_info),
366
		    stab + sym->st_name);
367
	}
368
#endif
369
370
	switch (stt = ELF_ST_TYPE(sym->st_info)) {
371
	case STT_NOTYPE:
372
	case STT_OBJECT:
373
	case STT_TLS:
374
		type = elf_shn2type(eh, sym->st_shndx, sn);
375
		if (type < 0) {
376
			if (sn == NULL)
377
				np->nl.n_other = '?';
378
			else
379
				np->nl.n_type = stt == STT_NOTYPE ?
380
				    N_COMM : N_DATA;
381
		} else {
382
			/* a hack for .rodata check (; */
383
			if (type == N_SIZE) {
384
				np->nl.n_type = N_DATA;
385
				np->nl.n_other = 'r';
386
			} else
387
				np->nl.n_type = type;
388
		}
389
		if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
390
			np->nl.n_other = 'W';
391
		break;
392
393
	case STT_FUNC:
394
		type = elf_shn2type(eh, sym->st_shndx, NULL);
395
		np->nl.n_type = type < 0? N_TEXT : type;
396
		if (ELF_ST_BIND(sym->st_info) == STB_WEAK) {
397
			np->nl.n_other = 'W';
398
		} else if (sn != NULL && *sn != 0 &&
399
		    strcmp(sn, ELF_INIT) &&
400
		    strcmp(sn, ELF_TEXT) &&
401
		    strcmp(sn, ELF_FINI))	/* XXX GNU compat */
402
			np->nl.n_other = '?';
403
		break;
404
405
	case STT_SECTION:
406
		type = elf_shn2type(eh, sym->st_shndx, NULL);
407
		if (type < 0)
408
			np->nl.n_other = '?';
409
		else
410
			np->nl.n_type = type;
411
		break;
412
413
	case STT_FILE:
414
		np->nl.n_type = N_FN | N_EXT;
415
		break;
416
417
	case STT_PARISC_MILLI:
418
		if (eh->e_machine == EM_PARISC)
419
			np->nl.n_type = N_TEXT;
420
		else
421
			np->nl.n_other = '?';
422
		break;
423
424
	default:
425
		np->nl.n_other = '?';
426
		break;
427
	}
428
	if (np->nl.n_type != N_UNDF && ELF_ST_BIND(sym->st_info) != STB_LOCAL) {
429
		np->nl.n_type |= N_EXT;
430
		if (np->nl.n_other)
431
			np->nl.n_other = toupper((unsigned char)np->nl.n_other);
432
	}
433
434
	return (0);
435
}
436
437
int
438
elf_size(Elf_Ehdr *head, Elf_Shdr *shdr,
439
    u_long *ptext, u_long *pdata, u_long *pbss)
440
{
441
	int i;
442
443
	*ptext = *pdata = *pbss = 0;
444
445
	for (i = 0; i < head->e_shnum; i++) {
446
		if (!(shdr[i].sh_flags & SHF_ALLOC))
447
			;
448
		else if (shdr[i].sh_flags & SHF_EXECINSTR ||
449
		    !(shdr[i].sh_flags & SHF_WRITE))
450
			*ptext += shdr[i].sh_size;
451
		else if (shdr[i].sh_type == SHT_NOBITS)
452
			*pbss += shdr[i].sh_size;
453
		else
454
			*pdata += shdr[i].sh_size;
455
	}
456
457
	return (0);
458
}
459
460
int
461
elf_symloadx(const char *name, FILE *fp, off_t foff, Elf_Ehdr *eh,
462
    Elf_Shdr *shdr, char *shstr, long shstrsize, struct xnlist **pnames,
463
    struct xnlist ***psnames, size_t *pstabsize, int *pnrawnames,
464
    const char *strtab, const char *symtab)
465
{
466
	long symsize;
467
	struct xnlist *np;
468
	Elf_Sym sbuf;
469
	int i;
470
471
	for (i = 0; i < eh->e_shnum; i++) {
472
		if (shdr[i].sh_name >= shstrsize) {
473
			warnx("%s: corrupt file", name);
474
			return (1);
475
		}
476
		if (!strcmp(shstr + shdr[i].sh_name, strtab)) {
477
			*pstabsize = shdr[i].sh_size;
478
			if (*pstabsize > SIZE_MAX) {
479
				warnx("%s: corrupt file", name);
480
				return (1);
481
			}
482
483
			MMAP(stab, *pstabsize, PROT_READ, MAP_PRIVATE|MAP_FILE,
484
			    fileno(fp), foff + shdr[i].sh_offset);
485
			if (stab == MAP_FAILED)
486
				return (1);
487
		}
488
	}
489
	for (i = 0; i < eh->e_shnum; i++) {
490
		if (!strcmp(shstr + shdr[i].sh_name, symtab)) {
491
			symsize = shdr[i].sh_size;
492
			if (fseeko(fp, foff + shdr[i].sh_offset, SEEK_SET)) {
493
				warn("%s: fseeko", name);
494
				if (stab)
495
					MUNMAP(stab, *pstabsize);
496
				return (1);
497
			}
498
499
			*pnrawnames = symsize / sizeof(sbuf);
500
			if ((*pnames = calloc(*pnrawnames, sizeof(*np))) == NULL) {
501
				warn("%s: malloc names", name);
502
				if (stab)
503
					MUNMAP(stab, *pstabsize);
504
				*pnrawnames = 0;
505
				return (1);
506
			}
507
			if ((*psnames = calloc(*pnrawnames, sizeof(np))) == NULL) {
508
				warn("%s: malloc snames", name);
509
				if (stab)
510
					MUNMAP(stab, *pstabsize);
511
				free(*pnames);
512
				*pnames = NULL;
513
				*pnrawnames = 0;
514
				return (1);
515
			}
516
517
			for (np = *pnames; symsize > 0; symsize -= sizeof(sbuf)) {
518
				if (fread(&sbuf, 1, sizeof(sbuf),
519
				    fp) != sizeof(sbuf)) {
520
					warn("%s: read symbol", name);
521
					if (stab)
522
						MUNMAP(stab, *pstabsize);
523
					free(*pnames);
524
					free(*psnames);
525
					*pnames = NULL;
526
					*psnames = NULL;
527
					*pnrawnames = 0;
528
					return (1);
529
				}
530
531
				elf_fix_sym(eh, &sbuf);
532
533
				if (!sbuf.st_name ||
534
				    sbuf.st_name > *pstabsize)
535
					continue;
536
537
				elf2nlist(&sbuf, eh, shdr, shstr, np);
538
				np->nl.n_value = sbuf.st_value;
539
				np->nl.n_un.n_strx = sbuf.st_name;
540
				np->n_size = sbuf.st_size;
541
				np++;
542
			}
543
			*pnrawnames = np - *pnames;
544
		}
545
	}
546
	return (0);
547
}
548
549
int
550
elf_symload(const char *name, FILE *fp, off_t foff, Elf_Ehdr *eh,
551
    Elf_Shdr *shdr, struct xnlist **pnames, struct xnlist ***psnames,
552
    size_t *pstabsize, int *pnrawnames)
553
{
554
	long shstrsize;
555
	char *shstr;
556
557
	shstrsize = shdr[eh->e_shstrndx].sh_size;
558
	if (shstrsize == 0) {
559
		warnx("%s: no name list", name);
560
		return (1);
561
	}
562
563
	if ((shstr = malloc(shstrsize)) == NULL) {
564
		warn("%s: malloc shsrt", name);
565
		return (1);
566
	}
567
568
	if (fseeko(fp, foff + shdr[eh->e_shstrndx].sh_offset, SEEK_SET)) {
569
		warn("%s: fseeko", name);
570
		free(shstr);
571
		return (1);
572
	}
573
574
	if (fread(shstr, 1, shstrsize, fp) != shstrsize) {
575
		warnx("%s: premature EOF", name);
576
		free(shstr);
577
		return(1);
578
	}
579
580
	stab = NULL;
581
	*pnames = NULL; *psnames = NULL; *pnrawnames = 0;
582
	if (!dynamic_only) {
583
		elf_symloadx(name, fp, foff, eh, shdr, shstr, shstrsize, pnames,
584
		    psnames, pstabsize, pnrawnames, ELF_STRTAB, ELF_SYMTAB);
585
	}
586
	if (stab == NULL) {
587
		elf_symloadx(name, fp, foff, eh, shdr, shstr, shstrsize, pnames,
588
		    psnames, pstabsize, pnrawnames, ELF_DYNSTR, ELF_DYNSYM);
589
	}
590
591
	free(shstr);
592
	if (stab == NULL) {
593
		warnx("%s: no name list", name);
594
		free(*pnames);
595
		free(*psnames);
596
		return (1);
597
	}
598
599
	return (0);
600
}