View | Details | Raw Unified | Return to bug 192253
Collapse All | Expand All

(-)b/sys/conf/kern.pre.mk (+1 lines)
Lines 23-32 _srcconf_included_: Link Here
23
KERNEL_KO?=	kernel
23
KERNEL_KO?=	kernel
24
KERNEL?=	kernel
24
KERNEL?=	kernel
25
KODIR?=		/boot/${KERNEL}
25
KODIR?=		/boot/${KERNEL}
26
LDSCRIPT_NAME?=	ldscript.$M
26
LDSCRIPT_NAME?=	ldscript.$M
27
LDSCRIPT?=	$S/conf/${LDSCRIPT_NAME}
27
LDSCRIPT?=	$S/conf/${LDSCRIPT_NAME}
28
LDFLAGS+=	--hash-style=gnu
28
29
29
M=		${MACHINE_CPUARCH}
30
M=		${MACHINE_CPUARCH}
30
31
31
AWK?=		awk
32
AWK?=		awk
32
CP?=		cp
33
CP?=		cp
(-)b/sys/conf/kmod.mk (-1 / +1 lines)
Lines 109-119 CFLAGS.gcc+= --param inline-unit-growth=100 Link Here
109
CFLAGS.gcc+= --param large-function-growth=1000
109
CFLAGS.gcc+= --param large-function-growth=1000
110
110
111
# Disallow common variables, and if we end up with commons from
111
# Disallow common variables, and if we end up with commons from
112
# somewhere unexpected, allocate storage for them in the module itself.
112
# somewhere unexpected, allocate storage for them in the module itself.
113
CFLAGS+=	-fno-common
113
CFLAGS+=	-fno-common
114
LDFLAGS+=	-d -warn-common
114
LDFLAGS+=	-d -warn-common --hash-style=gnu
115
115
116
CFLAGS+=	${DEBUG_FLAGS}
116
CFLAGS+=	${DEBUG_FLAGS}
117
.if ${MACHINE_CPUARCH} == amd64
117
.if ${MACHINE_CPUARCH} == amd64
118
CFLAGS+=	-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer
118
CFLAGS+=	-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer
119
.endif
119
.endif
(-)b/sys/kern/link_elf.c (-14 / +165 lines)
Lines 79-92 typedef struct elf_file { Link Here
79
	caddr_t		address;	/* Relocation address */
79
	caddr_t		address;	/* Relocation address */
80
#ifdef SPARSE_MAPPING
80
#ifdef SPARSE_MAPPING
81
	vm_object_t	object;		/* VM object to hold file pages */
81
	vm_object_t	object;		/* VM object to hold file pages */
82
#endif
82
#endif
83
	Elf_Dyn		*dynamic;	/* Symbol table etc. */
83
	Elf_Dyn		*dynamic;	/* Symbol table etc. */
84
85
	/* Adaptation of r234841 (DT_GNU_HASH for rtld-elf) to kernel linker */
86
	bool		valid_hash_sysv : 1;
87
	bool		valid_hash_gnu  : 1;
88
84
	Elf_Hashelt	nbuckets;	/* DT_HASH info */
89
	Elf_Hashelt	nbuckets;	/* DT_HASH info */
85
	Elf_Hashelt	nchains;
90
	Elf_Hashelt	nchains;
86
	const Elf_Hashelt *buckets;
91
	const Elf_Hashelt *buckets;
87
	const Elf_Hashelt *chains;
92
	const Elf_Hashelt *chains;
93
94
	Elf_Hashelt	nbuckets_gnu;	/* DT_GNU_HASH info */
95
	Elf_Word	symndx_gnu;	/* 1st accessible symbol on dynsym table */
96
	Elf_Word	maskwords_bm_gnu;	/* Bloom filter words - 1 (bitmask) */
97
	Elf_Word	shift2_gnu;	/* Bloom filter shift count */
98
	Elf_Addr	*bloom_gnu;	/* Bloom filter used by GNU hash func */
99
	const Elf_Hashelt	*buckets_gnu;
100
	const Elf_Hashelt	*chain_zero_gnu;
101
88
	caddr_t		hash;
102
	caddr_t		hash;
89
	caddr_t		strtab;		/* DT_STRTAB */
103
	caddr_t		strtab;		/* DT_STRTAB */
90
	int		strsz;		/* DT_STRSZ */
104
	int		strsz;		/* DT_STRSZ */
91
	const Elf_Sym	*symtab;		/* DT_SYMTAB */
105
	const Elf_Sym	*symtab;		/* DT_SYMTAB */
92
	Elf_Addr	*got;		/* DT_PLTGOT */
106
	Elf_Addr	*got;		/* DT_PLTGOT */
Lines 483-504 link_elf_preload_parse_symbols(elf_file_t ef) Link Here
483
static int
497
static int
484
parse_dynamic(elf_file_t ef)
498
parse_dynamic(elf_file_t ef)
485
{
499
{
486
	Elf_Dyn *dp;
500
	Elf_Dyn *dp;
487
	int plttype = DT_REL;
501
	int plttype = DT_REL;
502
	const Elf_Hashelt *hashtab;
488
503
489
	for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
504
	for (dp = ef->dynamic; dp->d_tag != DT_NULL; dp++) {
490
		switch (dp->d_tag) {
505
		switch (dp->d_tag) {
491
		case DT_HASH:
506
		case DT_HASH:
492
		{
507
		{
493
			/* From src/libexec/rtld-elf/rtld.c */
508
			/* From src/libexec/rtld-elf/rtld.c */
494
			const Elf_Hashelt *hashtab = (const Elf_Hashelt *)
509
			hashtab = (const Elf_Hashelt *)(ef->address +
495
			    (ef->address + dp->d_un.d_ptr);
510
			    dp->d_un.d_ptr);
496
			ef->nbuckets = hashtab[0];
511
			ef->nbuckets = hashtab[0];
497
			ef->nchains = hashtab[1];
512
			ef->nchains = hashtab[1];
498
			ef->buckets = hashtab + 2;
513
			ef->buckets = hashtab + 2;
499
			ef->chains = ef->buckets + ef->nbuckets;
514
			ef->chains = ef->buckets + ef->nbuckets;
515
516
			ef->valid_hash_sysv = (ef->nbuckets > 0 &&
517
			    ef->nchains > 0);
518
			break;
519
		}
520
		case DT_GNU_HASH:
521
		{
522
			Elf_Hashelt nmaskwords;
523
			size_t bloom_size32;
524
			bool nmw_power2;
525
526
			hashtab = (const Elf_Hashelt *)(ef->address +
527
			    dp->d_un.d_ptr);
528
529
			ef->nbuckets_gnu = hashtab[0];
530
			ef->symndx_gnu = hashtab[1];
531
			nmaskwords = hashtab[2];
532
			bloom_size32 = (__ELF_WORD_SIZE / 32) * nmaskwords;
533
			/* Number of bitmask words is required to be power of 2 */
534
			nmw_power2 = powerof2(nmaskwords);
535
			ef->maskwords_bm_gnu = nmaskwords - 1;
536
			ef->shift2_gnu = hashtab[3];
537
			ef->bloom_gnu = (Elf_Addr *)(hashtab + 4);
538
			ef->buckets_gnu = hashtab + 4 + bloom_size32;
539
			ef->chain_zero_gnu = ef->buckets_gnu + ef->nbuckets_gnu
540
			    - ef->symndx_gnu;
541
			ef->valid_hash_gnu = (nmw_power2 &&
542
			    ef->nbuckets_gnu > 0 && nmaskwords > 0);
500
			break;
543
			break;
501
		}
544
		}
502
		case DT_STRTAB:
545
		case DT_STRTAB:
503
			ef->strtab = (caddr_t) (ef->address + dp->d_un.d_ptr);
546
			ef->strtab = (caddr_t) (ef->address + dp->d_un.d_ptr);
504
			break;
547
			break;
Lines 560-573 parse_dynamic(elf_file_t ef) Link Here
560
		ef->pltrelasize = ef->pltrelsize;
603
		ef->pltrelasize = ef->pltrelsize;
561
		ef->pltrelsize = 0;
604
		ef->pltrelsize = 0;
562
	}
605
	}
563
606
564
	ef->ddbsymtab = ef->symtab;
607
	ef->ddbsymtab = ef->symtab;
565
	ef->ddbsymcnt = ef->nchains;
566
	ef->ddbstrtab = ef->strtab;
608
	ef->ddbstrtab = ef->strtab;
567
	ef->ddbstrcnt = ef->strsz;
609
	ef->ddbstrcnt = ef->strsz;
568
610
611
	/* Determine size of dynsym table (equal to nchains of sysv hash) */
612
	if (ef->valid_hash_sysv)
613
		ef->ddbsymcnt = ef->nchains;
614
	else if (ef->valid_hash_gnu) {
615
		const Elf_Word *hashval;
616
		Elf_Word bkt;
617
618
		ef->ddbsymcnt = 0;
619
		for (bkt = 0; bkt < ef->nbuckets_gnu; bkt++) {
620
			if (ef->buckets_gnu[bkt] == 0)
621
				continue;
622
			hashval = &ef->chain_zero_gnu[ef->buckets_gnu[bkt]];
623
			do
624
				ef->ddbsymcnt++;
625
			while ((*hashval++ & 1u) == 0);
626
		}
627
		ef->ddbsymcnt += ef->symndx_gnu;
628
	}
629
569
	return (0);
630
	return (0);
570
}
631
}
571
632
572
static int
633
static int
573
parse_dpcpu(elf_file_t ef)
634
parse_dpcpu(elf_file_t ef)
Lines 1220-1244 elf_hash(const char *name) Link Here
1220
	}
1281
	}
1221
	return (h);
1282
	return (h);
1222
}
1283
}
1223
1284
1224
static int
1285
static int
1225
link_elf_lookup_symbol(linker_file_t lf, const char* name, c_linker_sym_t* sym)
1286
link_elf_lookup_symbol_sysv(linker_file_t lf, const char* name,
1287
    c_linker_sym_t* sym)
1226
{
1288
{
1227
	elf_file_t ef = (elf_file_t) lf;
1289
	elf_file_t ef = (elf_file_t) lf;
1228
	unsigned long symnum;
1290
	unsigned long symnum;
1229
	const Elf_Sym* symp;
1291
	const Elf_Sym* symp;
1230
	const char *strp;
1292
	const char *strp;
1231
	unsigned long hash;
1293
	unsigned long hash;
1232
	int i;
1294
	int i;
1233
1295
1234
	/* If we don't have a hash, bail. */
1235
	if (ef->buckets == NULL || ef->nbuckets == 0) {
1236
		printf("link_elf_lookup_symbol: missing symbol hash table\n");
1237
		return (ENOENT);
1238
	}
1239
1240
	/* First, search hashed global symbols */
1296
	/* First, search hashed global symbols */
1241
	hash = elf_hash(name);
1297
	hash = elf_hash(name);
1242
	symnum = ef->buckets[hash % ef->nbuckets];
1298
	symnum = ef->buckets[hash % ef->nbuckets];
1243
1299
1244
	while (symnum != STN_UNDEF) {
1300
	while (symnum != STN_UNDEF) {
Lines 1287-1304 link_elf_lookup_symbol(linker_file_t lf, const char* name, c_linker_sym_t* sym) Link Here
1287
	}
1343
	}
1288
1344
1289
	return (ENOENT);
1345
	return (ENOENT);
1290
}
1346
}
1291
1347
1348
/*
1349
 * The GNU hash function is the Daniel J. Bernstein hash clipped to 32 bits
1350
 * unsigned in case it's implemented with a wider type.
1351
 */
1352
static uint32_t
1353
gnu_hash(const char *s)
1354
{
1355
	uint32_t h;
1356
	unsigned char c;
1357
1358
	h = 5381;
1359
	for (c = *s; c != '\0'; c = *++s)
1360
		h = h * 33 + c;
1361
	return (h & 0xffffffff);
1362
}
1363
1364
static int
1365
link_elf_lookup_symbol_gnu(linker_file_t lf, const char* name,
1366
    c_linker_sym_t* sym)
1367
{
1368
	elf_file_t ef = (elf_file_t)lf;
1369
	const Elf_Word *hashval;
1370
	unsigned long symnum;
1371
	const Elf_Sym *symp;
1372
	Elf_Addr bloom_word;
1373
	const char *strp;
1374
	Elf_Word bucket;
1375
	unsigned h1, h2;
1376
	uint32_t hash;
1377
1378
	hash = gnu_hash(name);
1379
1380
	/*
1381
	 * Bloom filter: compute bloom hashes; check for possible membership in
1382
	 * filter. There are no false negatives, so return ENOENT early.
1383
	 */
1384
	h1 = hash & (__ELF_WORD_SIZE - 1);
1385
	h2 = ((hash >> ef->shift2_gnu) & (__ELF_WORD_SIZE - 1));
1386
1387
	bloom_word = ef->bloom_gnu[(hash / __ELF_WORD_SIZE) &
1388
	    ef->maskwords_bm_gnu];
1389
1390
	if (((bloom_word >> h1) & (bloom_word >> h2) & 1) == 0)
1391
		return (ENOENT);
1392
1393
	/* Ok, it's (possibly) present? Look up in the hash table. */
1394
	bucket = ef->buckets_gnu[hash % ef->nbuckets_gnu];
1395
	if (bucket == 0)
1396
		return (ENOENT);
1397
	hashval = &ef->chain_zero_gnu[bucket];
1398
	do {
1399
		if (((*hashval ^ hash) >> 1) != 0)
1400
			continue;
1401
1402
		symnum = hashval - ef->chain_zero_gnu;
1403
		if (symnum >= ef->ddbsymcnt) {
1404
			printf("%s: corrupt symbol table\n", __func__);
1405
			return (ENOENT);
1406
		}
1407
1408
		symp = ef->symtab + symnum;
1409
		if (symp->st_name == 0) {
1410
			printf("%s: corrupt symbol table\n", __func__);
1411
			return (ENOENT);
1412
		}
1413
1414
		strp = ef->strtab + symp->st_name;
1415
		if (strcmp(name, strp) != 0)
1416
			continue;
1417
1418
		if (symp->st_shndx == SHN_UNDEF && (symp->st_value == 0 ||
1419
		    ELF_ST_TYPE(symp->st_info) != STT_FUNC))
1420
			return (ENOENT);
1421
1422
		*sym = (c_linker_sym_t)symp;
1423
		return (0);
1424
	} while ((*hashval++ & 1) == 0);
1425
	return (ENOENT);
1426
}
1427
1428
static int
1429
link_elf_lookup_symbol(linker_file_t lf, const char* name, c_linker_sym_t* sym)
1430
{
1431
	elf_file_t ef = (elf_file_t)lf;
1432
1433
	if (ef->valid_hash_gnu)
1434
		return (link_elf_lookup_symbol_gnu(lf, name, sym));
1435
	else if (ef->valid_hash_sysv)
1436
		return (link_elf_lookup_symbol_sysv(lf, name, sym));
1437
	else {
1438
		printf("link_elf_lookup_symbol: missing symbol hash table\n");
1439
		return (ENOENT);
1440
	}
1441
}
1442
1292
static int
1443
static int
1293
link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym,
1444
link_elf_symbol_values(linker_file_t lf, c_linker_sym_t sym,
1294
    linker_symval_t *symval)
1445
    linker_symval_t *symval)
1295
{
1446
{
1296
	elf_file_t ef = (elf_file_t) lf;
1447
	elf_file_t ef = (elf_file_t) lf;
1297
	const Elf_Sym* es = (const Elf_Sym*) sym;
1448
	const Elf_Sym* es = (const Elf_Sym*) sym;
1298
1449
1299
	if (es >= ef->symtab && es < (ef->symtab + ef->nchains)) {
1450
	if (es >= ef->symtab && es < (ef->symtab + ef->ddbsymcnt)) {
1300
		symval->name = ef->strtab + es->st_name;
1451
		symval->name = ef->strtab + es->st_name;
1301
		symval->value = (caddr_t) ef->address + es->st_value;
1452
		symval->value = (caddr_t) ef->address + es->st_value;
1302
		symval->size = es->st_size;
1453
		symval->size = es->st_size;
1303
		return (0);
1454
		return (0);
1304
	}
1455
	}
Lines 1453-1474 link_elf_each_function_nameval(linker_file_t file, Link Here
1453
const Elf_Sym *
1604
const Elf_Sym *
1454
elf_get_sym(linker_file_t lf, Elf_Size symidx)
1605
elf_get_sym(linker_file_t lf, Elf_Size symidx)
1455
{
1606
{
1456
	elf_file_t ef = (elf_file_t)lf;
1607
	elf_file_t ef = (elf_file_t)lf;
1457
1608
1458
	if (symidx >= ef->nchains)
1609
	if (symidx >= ef->ddbsymcnt)
1459
		return (NULL);
1610
		return (NULL);
1460
	return (ef->symtab + symidx);
1611
	return (ef->symtab + symidx);
1461
}
1612
}
1462
1613
1463
const char *
1614
const char *
1464
elf_get_symname(linker_file_t lf, Elf_Size symidx)
1615
elf_get_symname(linker_file_t lf, Elf_Size symidx)
1465
{
1616
{
1466
	elf_file_t ef = (elf_file_t)lf;
1617
	elf_file_t ef = (elf_file_t)lf;
1467
	const Elf_Sym *sym;
1618
	const Elf_Sym *sym;
1468
1619
1469
	if (symidx >= ef->nchains)
1620
	if (symidx >= ef->ddbsymcnt)
1470
		return (NULL);
1621
		return (NULL);
1471
	sym = ef->symtab + symidx;
1622
	sym = ef->symtab + symidx;
1472
	return (ef->strtab + sym->st_name);
1623
	return (ef->strtab + sym->st_name);
1473
}
1624
}
1474
1625
Lines 1486-1496 elf_lookup(linker_file_t lf, Elf_Size symidx, int deps) Link Here
1486
	const Elf_Sym *sym;
1637
	const Elf_Sym *sym;
1487
	const char *symbol;
1638
	const char *symbol;
1488
	Elf_Addr addr, start, base;
1639
	Elf_Addr addr, start, base;
1489
1640
1490
	/* Don't even try to lookup the symbol if the index is bogus. */
1641
	/* Don't even try to lookup the symbol if the index is bogus. */
1491
	if (symidx >= ef->nchains)
1642
	if (symidx >= ef->ddbsymcnt)
1492
		return (0);
1643
		return (0);
1493
1644
1494
	sym = ef->symtab + symidx;
1645
	sym = ef->symtab + symidx;
1495
1646
1496
	/*
1647
	/*
(-)b/usr.sbin/kldxref/ef.c (-3 / +177 lines)
Lines 32-42 Link Here
32
 * $FreeBSD$
32
 * $FreeBSD$
33
 */
33
 */
34
34
35
#include <sys/param.h>
35
#include <sys/param.h>
36
#include <sys/linker.h>
36
#include <sys/linker.h>
37
#include <stdbool.h>
37
#include <string.h>
38
#include <string.h>
39
#include <stdint.h>
38
#include <stdio.h>
40
#include <stdio.h>
39
#include <stdlib.h>
41
#include <stdlib.h>
40
#include <unistd.h>
42
#include <unistd.h>
41
#include <errno.h>
43
#include <errno.h>
42
#include <fcntl.h>
44
#include <fcntl.h>
Lines 73-82 struct ef_file { Link Here
73
	int		ef_verbose;
75
	int		ef_verbose;
74
	Elf_Rel *	ef_rel;			/* relocation table */
76
	Elf_Rel *	ef_rel;			/* relocation table */
75
	int		ef_relsz;		/* number of entries */
77
	int		ef_relsz;		/* number of entries */
76
	Elf_Rela *	ef_rela;		/* relocation table */
78
	Elf_Rela *	ef_rela;		/* relocation table */
77
	int		ef_relasz;		/* number of entries */
79
	int		ef_relasz;		/* number of entries */
80
81
	long		ef_symcnt;		/* Number of symbols */
82
83
	bool		ef_valid_hash_sysv : 1;
84
	bool		ef_valid_hash_gnu  : 1;
85
	Elf_Hashelt	ef_nbuckets_gnu;	/* DT_GNU_HASH info */
86
	Elf_Word	ef_symndx_gnu;		/* 1st accessible symbol on dynsym table */
87
	Elf_Word	ef_maskwords_bm_gnu;	/* Bloom filter words - 1 (bitmask) */
88
	Elf_Word	ef_shift2_gnu;		/* Bloom filter shift count */
89
	Elf_Addr *	ef_bloom_gnu;		/* Bloom filter used by GNU hash func */
90
	Elf_Hashelt *	ef_buckets_gnu;
91
	Elf_Hashelt *	ef_chain_zero_gnu;
78
};
92
};
79
93
80
static void ef_print_phdr(Elf_Phdr *);
94
static void ef_print_phdr(Elf_Phdr *);
81
static u_long ef_get_offset(elf_file_t, Elf_Off);
95
static u_long ef_get_offset(elf_file_t, Elf_Off);
82
static int ef_parse_dynamic(elf_file_t);
96
static int ef_parse_dynamic(elf_file_t);
Lines 165-175 elf_hash(const char *name) Link Here
165
	}
179
	}
166
	return h;
180
	return h;
167
}
181
}
168
182
169
static int
183
static int
170
ef_lookup_symbol(elf_file_t ef, const char* name, Elf_Sym** sym)
184
ef_lookup_symbol_sysv(elf_file_t ef, const char* name, Elf_Sym** sym)
171
{
185
{
172
	unsigned long symnum;
186
	unsigned long symnum;
173
	Elf_Sym* symp;
187
	Elf_Sym* symp;
174
	char *strp;
188
	char *strp;
175
	unsigned long hash;
189
	unsigned long hash;
Lines 208-217 ef_lookup_symbol(elf_file_t ef, const char* name, Elf_Sym** sym) Link Here
208
	}
222
	}
209
223
210
	return ENOENT;
224
	return ENOENT;
211
}
225
}
212
226
227
/*
228
 * The GNU hash function is the Daniel J. Bernstein hash clipped to 32 bits
229
 * unsigned in case it's implemented with a wider type.
230
 */
231
static uint32_t
232
gnu_hash(const char *s)
233
{
234
	uint32_t h;
235
	unsigned char c;
236
237
	h = 5381;
238
	for (c = *s; c != '\0'; c = *++s)
239
		h = h * 33 + c;
240
	return (h & 0xffffffff);
241
}
242
243
static int
244
ef_lookup_symbol_gnu(elf_file_t ef, const char* name, Elf_Sym** sym)
245
{
246
	const Elf_Word *hashval;
247
	unsigned long symnum;
248
	Elf_Sym *symp;
249
	Elf_Addr bloom_word;
250
	const char *strp;
251
	Elf_Word bucket;
252
	unsigned h1, h2;
253
	uint32_t hash;
254
255
	hash = gnu_hash(name);
256
257
	/*
258
	 * Bloom filter: compute bloom hashes; check for possible membership in
259
	 * filter. There are no false negatives, so return ENOENT early.
260
	 */
261
	h1 = hash & (__ELF_WORD_SIZE - 1);
262
	h2 = ((hash >> ef->ef_shift2_gnu) & (__ELF_WORD_SIZE - 1));
263
264
	bloom_word = ef->ef_bloom_gnu[(hash / __ELF_WORD_SIZE) &
265
	    ef->ef_maskwords_bm_gnu];
266
267
	if (((bloom_word >> h1) & (bloom_word >> h2) & 1) == 0)
268
		return (ENOENT);
269
270
	/* Ok, it's (possibly) present? Look up in the hash table. */
271
	bucket = ef->ef_buckets_gnu[hash % ef->ef_nbuckets_gnu];
272
	if (bucket == 0)
273
		return (ENOENT);
274
	hashval = &ef->ef_chain_zero_gnu[bucket];
275
	do {
276
		if (((*hashval ^ hash) >> 1) != 0)
277
			continue;
278
279
		symnum = hashval - ef->ef_chain_zero_gnu;
280
		if (symnum >= ef->ef_symcnt) {
281
			warnx("%s: file %s has corrupted symbol table\n",
282
			    __func__, ef->ef_name);
283
			return (ENOENT);
284
		}
285
286
		symp = ef->ef_symtab + symnum;
287
		if (symp->st_name == 0) {
288
			warnx("%s: file %s has corrupted symbol table\n",
289
			    __func__, ef->ef_name);
290
			return (ENOENT);
291
		}
292
293
		strp = ef->ef_strtab + symp->st_name;
294
		if (strcmp(name, strp) != 0)
295
			continue;
296
297
		if (symp->st_shndx == SHN_UNDEF && (symp->st_value == 0 ||
298
		    ELF_ST_TYPE(symp->st_info) != STT_FUNC))
299
			return (ENOENT);
300
301
		*sym = symp;
302
		return (0);
303
	} while ((*hashval++ & 1) == 0);
304
	return (ENOENT);
305
}
306
307
static int
308
ef_lookup_symbol(elf_file_t ef, const char* name, Elf_Sym** sym)
309
{
310
311
	if (ef->ef_valid_hash_gnu)
312
		return (ef_lookup_symbol_gnu(ef, name, sym));
313
	else if (ef->ef_valid_hash_sysv)
314
		return (ef_lookup_symbol_sysv(ef, name, sym));
315
	else {
316
		warnx("ef_lookup_symbol: file %s missing symbol hash table\n",
317
		    ef->ef_name);
318
		return (ENOENT);
319
	}
320
}
321
213
static int
322
static int
214
ef_lookup_set(elf_file_t ef, const char *name, long *startp, long *stopp,
323
ef_lookup_set(elf_file_t ef, const char *name, long *startp, long *stopp,
215
    long *countp)
324
    long *countp)
216
{
325
{
217
	Elf_Sym *sym;
326
	Elf_Sym *sym;
Lines 248-258 out: Link Here
248
static Elf_Addr
357
static Elf_Addr
249
ef_symaddr(elf_file_t ef, Elf_Size symidx)
358
ef_symaddr(elf_file_t ef, Elf_Size symidx)
250
{
359
{
251
	const Elf_Sym *sym;
360
	const Elf_Sym *sym;
252
361
253
	if (symidx >= ef->ef_nchains)
362
	if (symidx >= ef->ef_symcnt)
254
		return (0);
363
		return (0);
255
	sym = ef->ef_symtab + symidx;
364
	sym = ef->ef_symtab + symidx;
256
365
257
	if (ELF_ST_BIND(sym->st_info) == STB_LOCAL &&
366
	if (ELF_ST_BIND(sym->st_info) == STB_LOCAL &&
258
	    sym->st_shndx != SHN_UNDEF && sym->st_value != 0)
367
	    sym->st_shndx != SHN_UNDEF && sym->st_value != 0)
Lines 263-272 ef_symaddr(elf_file_t ef, Elf_Size symidx) Link Here
263
static int
372
static int
264
ef_parse_dynamic(elf_file_t ef)
373
ef_parse_dynamic(elf_file_t ef)
265
{
374
{
266
	Elf_Dyn *dp;
375
	Elf_Dyn *dp;
267
	Elf_Hashelt hashhdr[2];
376
	Elf_Hashelt hashhdr[2];
377
	Elf_Hashelt gnuhashhdr[4];
268
/*	int plttype = DT_REL;*/
378
/*	int plttype = DT_REL;*/
269
	int error;
379
	int error;
270
	Elf_Off rel_off;
380
	Elf_Off rel_off;
271
	Elf_Off rela_off;
381
	Elf_Off rela_off;
272
	int rel_sz;
382
	int rel_sz;
Lines 296-306 ef_parse_dynamic(elf_file_t ef) Link Here
296
				warnx("can't read hash table");
406
				warnx("can't read hash table");
297
				return error;
407
				return error;
298
			}
408
			}
299
			ef->ef_buckets = ef->ef_hashtab;
409
			ef->ef_buckets = ef->ef_hashtab;
300
			ef->ef_chains = ef->ef_buckets + ef->ef_nbuckets;
410
			ef->ef_chains = ef->ef_buckets + ef->ef_nbuckets;
411
412
			ef->ef_valid_hash_sysv = (ef->ef_nbuckets > 0 &&
413
			    ef->ef_nchains > 0);
301
			break;
414
			break;
415
		case DT_GNU_HASH:
416
		{
417
			Elf_Hashelt nmaskwords;
418
			size_t bloom_size32;
419
			bool nmw_power2;
420
421
			error = ef_read(ef, ef_get_offset(ef, dp->d_un.d_ptr),
422
			    sizeof(gnuhashhdr), gnuhashhdr);
423
			if (error) {
424
				warnx("can't read GNU hash header (%lx)",
425
				    ef_get_offset(ef, dp->d_un.d_ptr));
426
				return (error);
427
			}
428
429
			ef->ef_nbuckets_gnu = gnuhashhdr[0];
430
			ef->ef_symndx_gnu = gnuhashhdr[1];
431
			nmaskwords = gnuhashhdr[2];
432
			bloom_size32 = (__ELF_WORD_SIZE / 32) * nmaskwords;
433
			/* Number of bitmask words is required to be power of 2 */
434
			nmw_power2 = powerof2(nmaskwords);
435
			ef->ef_maskwords_bm_gnu = nmaskwords - 1;
436
			ef->ef_shift2_gnu = gnuhashhdr[3];
437
438
			error = ef_read_entry(ef, -1, bloom_size32 * 4,
439
			    (void**)&ef->ef_bloom_gnu);
440
			if (error) {
441
				warnx("can't read GNU bloom filter");
442
				return error;
443
			}
444
445
			error = ef_read_entry(ef, -1,
446
			    ef->ef_nbuckets_gnu * sizeof(Elf_Hashelt),
447
			    (void**)&ef->ef_buckets_gnu);
448
			if (error) {
449
				warnx("can't read GNU hash table");
450
				return error;
451
			}
452
453
			ef->ef_chain_zero_gnu = ef->ef_buckets_gnu +
454
			    ef->ef_nbuckets_gnu - ef->ef_symndx_gnu;
455
			ef->ef_valid_hash_gnu = (nmw_power2 &&
456
			    ef->ef_nbuckets_gnu > 0 && nmaskwords > 0);
457
			break;
458
		}
302
		case DT_STRTAB:
459
		case DT_STRTAB:
303
			ef->ef_stroff = dp->d_un.d_ptr;
460
			ef->ef_stroff = dp->d_un.d_ptr;
304
			break;
461
			break;
305
		case DT_STRSZ:
462
		case DT_STRSZ:
306
			ef->ef_strsz = dp->d_un.d_val;
463
			ef->ef_strsz = dp->d_un.d_val;
Lines 350-361 ef_parse_dynamic(elf_file_t ef) Link Here
350
	}
507
	}
351
	if (ef->ef_stroff == 0) {
508
	if (ef->ef_stroff == 0) {
352
		warnx("%s: no .dynstr section found\n", ef->ef_name);
509
		warnx("%s: no .dynstr section found\n", ef->ef_name);
353
		return EFTYPE;
510
		return EFTYPE;
354
	}
511
	}
512
	if (ef->ef_valid_hash_sysv)
513
		ef->ef_symcnt = ef->ef_nchains;
514
	else if (ef->ef_valid_hash_gnu) {
515
		const Elf_Word *hashval;
516
		Elf_Word bkt;
517
518
		ef->ef_symcnt = 0;
519
		for (bkt = 0; bkt < ef->ef_nbuckets_gnu; bkt++) {
520
			if (ef->ef_buckets_gnu[bkt] == 0)
521
				continue;
522
			hashval = &ef->ef_chain_zero_gnu[ef->ef_buckets_gnu[bkt]];
523
			do
524
				ef->ef_symcnt++;
525
			while ((*hashval++ & 1u) == 0);
526
		}
527
		ef->ef_symcnt += ef->ef_symndx_gnu;
528
	}
355
	if (ef_read_entry(ef, ef_get_offset(ef, ef->ef_symoff),
529
	if (ef_read_entry(ef, ef_get_offset(ef, ef->ef_symoff),
356
	    ef->ef_nchains * sizeof(Elf_Sym),
530
	    ef->ef_symcnt * sizeof(Elf_Sym),
357
		(void**)&ef->ef_symtab) != 0) {
531
		(void**)&ef->ef_symtab) != 0) {
358
		if (ef->ef_verbose)
532
		if (ef->ef_verbose)
359
			warnx("%s: can't load .dynsym section (0x%lx)",
533
			warnx("%s: can't load .dynsym section (0x%lx)",
360
			    ef->ef_name, (long)ef->ef_symoff);
534
			    ef->ef_name, (long)ef->ef_symoff);
361
		return EIO;
535
		return EIO;

Return to bug 192253