1/*-
2 * SPDX-License-Identifier: BSD-4-Clause
3 *
4 * Copyright (c) 2000, Boris Popov
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. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *    This product includes software developed by Boris Popov.
18 * 4. Neither the name of the author nor the names of any co-contributors
19 *    may be used to endorse or promote products derived from this software
20 *    without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35#include <sys/param.h>
36#include <sys/endian.h>
37#include <sys/queue.h>
38#include <sys/stat.h>
39#include <sys/module.h>
40
41#include <assert.h>
42#include <ctype.h>
43#include <err.h>
44#include <errno.h>
45#include <fts.h>
46#include <gelf.h>
47#include <libelf.h>
48#include <stdbool.h>
49#include <stdio.h>
50#include <stdlib.h>
51#include <string.h>
52#include <unistd.h>
53
54#include "ef.h"
55
56#define	MAXRECSIZE	(64 << 10)	/* 64k */
57#define check(val)	if ((error = (val)) != 0) break
58
59static bool dflag;	/* do not create a hint file, only write on stdout */
60static int verbose;
61
62static FILE *fxref;	/* current hints file */
63static int byte_order;
64static GElf_Ehdr ehdr;
65static char *ehdr_filename;
66
67static const char *xref_file = "linker.hints";
68
69/*
70 * A record is stored in the static buffer recbuf before going to disk.
71 */
72static char recbuf[MAXRECSIZE];
73static int recpos;	/* current write position */
74static int reccnt;	/* total record written to this file so far */
75
76static void
77intalign(void)
78{
79
80	recpos = roundup2(recpos, sizeof(int));
81}
82
83static void
84write_int(int val)
85{
86	char buf[4];
87
88	assert(byte_order != ELFDATANONE);
89	if (byte_order == ELFDATA2LSB)
90		le32enc(buf, val);
91	else
92		be32enc(buf, val);
93	fwrite(buf, sizeof(buf), 1, fxref);
94}
95
96static void
97record_start(void)
98{
99
100	recpos = 0;
101	memset(recbuf, 0, MAXRECSIZE);
102}
103
104static int
105record_end(void)
106{
107
108	if (recpos == 0) {
109		/*
110		 * Pretend to have written a record in debug mode so
111		 * the architecture check works.
112		 */
113		if (dflag)
114			reccnt++;
115		return (0);
116	}
117
118	if (reccnt == 0) {
119		/* File version record. */
120		write_int(1);
121	}
122
123	reccnt++;
124	intalign();
125	write_int(recpos);
126	return (fwrite(recbuf, recpos, 1, fxref) != 1 ? errno : 0);
127}
128
129static int
130record_buf(const void *buf, size_t size)
131{
132
133	if (MAXRECSIZE - recpos < size)
134		errx(1, "record buffer overflow");
135	memcpy(recbuf + recpos, buf, size);
136	recpos += size;
137	return (0);
138}
139
140/*
141 * An int is stored in target byte order and aligned
142 */
143static int
144record_int(int val)
145{
146	char buf[4];
147
148	assert(byte_order != ELFDATANONE);
149	if (byte_order == ELFDATA2LSB)
150		le32enc(buf, val);
151	else
152		be32enc(buf, val);
153
154	intalign();
155	return (record_buf(buf, sizeof(buf)));
156}
157
158/*
159 * A string is stored as 1-byte length plus data, no padding
160 */
161static int
162record_string(const char *str)
163{
164	int error;
165	size_t len;
166	u_char val;
167
168	if (dflag)
169		return (0);
170	val = len = strlen(str);
171	if (len > 255)
172		errx(1, "string %s too long", str);
173	error = record_buf(&val, sizeof(val));
174	if (error != 0)
175		return (error);
176	return (record_buf(str, len));
177}
178
179/* From sys/isa/pnp.c */
180static char *
181pnp_eisaformat(uint32_t id)
182{
183	uint8_t *data;
184	static char idbuf[8];
185	const char  hextoascii[] = "0123456789abcdef";
186
187	id = htole32(id);
188	data = (uint8_t *)&id;
189	idbuf[0] = '@' + ((data[0] & 0x7c) >> 2);
190	idbuf[1] = '@' + (((data[0] & 0x3) << 3) + ((data[1] & 0xe0) >> 5));
191	idbuf[2] = '@' + (data[1] & 0x1f);
192	idbuf[3] = hextoascii[(data[2] >> 4)];
193	idbuf[4] = hextoascii[(data[2] & 0xf)];
194	idbuf[5] = hextoascii[(data[3] >> 4)];
195	idbuf[6] = hextoascii[(data[3] & 0xf)];
196	idbuf[7] = 0;
197	return (idbuf);
198}
199
200struct pnp_elt
201{
202	int	pe_kind;	/* What kind of entry */
203#define TYPE_SZ_MASK	0x0f
204#define TYPE_FLAGGED	0x10	/* all f's is a wildcard */
205#define	TYPE_INT	0x20	/* Is a number */
206#define TYPE_PAIRED	0x40
207#define TYPE_LE		0x80	/* Matches <= this value */
208#define TYPE_GE		0x100	/* Matches >= this value */
209#define TYPE_MASK	0x200	/* Specifies a mask to follow */
210#define TYPE_U8		(1 | TYPE_INT)
211#define TYPE_V8		(1 | TYPE_INT | TYPE_FLAGGED)
212#define TYPE_G16	(2 | TYPE_INT | TYPE_GE)
213#define TYPE_L16	(2 | TYPE_INT | TYPE_LE)
214#define TYPE_M16	(2 | TYPE_INT | TYPE_MASK)
215#define TYPE_U16	(2 | TYPE_INT)
216#define TYPE_V16	(2 | TYPE_INT | TYPE_FLAGGED)
217#define TYPE_U32	(4 | TYPE_INT)
218#define TYPE_V32	(4 | TYPE_INT | TYPE_FLAGGED)
219#define TYPE_W32	(4 | TYPE_INT | TYPE_PAIRED)
220#define TYPE_D		7
221#define TYPE_Z		8
222#define TYPE_P		9
223#define TYPE_E		10
224#define TYPE_T		11
225	int	pe_offset;	/* Offset within the element */
226	char *	pe_key;		/* pnp key name */
227	TAILQ_ENTRY(pnp_elt) next; /* Link */
228};
229typedef TAILQ_HEAD(pnp_head, pnp_elt) pnp_list;
230
231/*
232 * this function finds the data from the pnp table, as described by the
233 * description and creates a new output (new_desc). This output table
234 * is a form that's easier for the agent that's automatically loading the
235 * modules.
236 *
237 * The format output is the simplified string from this routine in the
238 * same basic format as the pnp string, as documented in sys/module.h.
239 * First a string describing the format is output, the a count of the
240 * number of records, then each record. The format string also describes
241 * the length of each entry (though it isn't a fixed length when strings
242 * are present).
243 *
244 *	type	Output		Meaning
245 *	I	uint32_t	Integer equality comparison
246 *	J	uint32_t	Pair of uint16_t fields converted to native
247 *				byte order. The two fields both must match.
248 *	G	uint32_t	Greater than or equal to
249 *	L	uint32_t	Less than or equal to
250 *	M	uint32_t	Mask of which fields to test. Fields that
251 *				take up space increment the count. This
252 *				field must be first, and resets the count.
253 *	D	string		Description of the device this pnp info is for
254 *	Z	string		pnp string must match this
255 *	T	nothing		T fields set pnp values that must be true for
256 *				the entire table.
257 * Values are packed the same way that other values are packed in this file.
258 * Strings and int32_t's start on a 32-bit boundary and are padded with 0
259 * bytes. Objects that are smaller than uint32_t are converted, without
260 * sign extension to uint32_t to simplify parsing downstream.
261 */
262static int
263parse_pnp_list(struct elf_file *ef, const char *desc, char **new_desc,
264    pnp_list *list)
265{
266	const char *walker, *ep;
267	const char *colon, *semi;
268	struct pnp_elt *elt;
269	char type[8], key[32];
270	int off;
271	size_t new_desc_size;
272	FILE *fp;
273
274	TAILQ_INIT(list);
275	walker = desc;
276	ep = desc + strlen(desc);
277	off = 0;
278	fp = open_memstream(new_desc, &new_desc_size);
279	if (fp == NULL)
280		err(1, "Could not open new memory stream");
281	if (verbose > 1)
282		printf("Converting %s into a list\n", desc);
283	while (walker < ep) {
284		colon = strchr(walker, ':');
285		semi = strchr(walker, ';');
286		if (semi != NULL && semi < colon)
287			goto err;
288		if (colon - walker > sizeof(type))
289			goto err;
290		strncpy(type, walker, colon - walker);
291		type[colon - walker] = '\0';
292		if (semi != NULL) {
293			if (semi - colon >= sizeof(key))
294				goto err;
295			strncpy(key, colon + 1, semi - colon - 1);
296			key[semi - colon - 1] = '\0';
297			walker = semi + 1;
298			/* Fail safe if we have spaces after ; */
299			while (walker < ep && isspace(*walker))
300				walker++;
301		} else {
302			if (strlen(colon + 1) >= sizeof(key))
303				goto err;
304			strcpy(key, colon + 1);
305			walker = ep;
306		}
307		if (verbose > 1)
308			printf("Found type %s for name %s\n", type, key);
309		/* Skip pointer place holders */
310		if (strcmp(type, "P") == 0) {
311			off += elf_pointer_size(ef);
312			continue;
313		}
314
315		/*
316		 * Add a node of the appropriate type
317		 */
318		elt = malloc(sizeof(struct pnp_elt) + strlen(key) + 1);
319		TAILQ_INSERT_TAIL(list, elt, next);
320		elt->pe_key = (char *)(elt + 1);
321		elt->pe_offset = off;
322		if (strcmp(type, "U8") == 0)
323			elt->pe_kind = TYPE_U8;
324		else if (strcmp(type, "V8") == 0)
325			elt->pe_kind = TYPE_V8;
326		else if (strcmp(type, "G16") == 0)
327			elt->pe_kind = TYPE_G16;
328		else if (strcmp(type, "L16") == 0)
329			elt->pe_kind = TYPE_L16;
330		else if (strcmp(type, "M16") == 0)
331			elt->pe_kind = TYPE_M16;
332		else if (strcmp(type, "U16") == 0)
333			elt->pe_kind = TYPE_U16;
334		else if (strcmp(type, "V16") == 0)
335			elt->pe_kind = TYPE_V16;
336		else if (strcmp(type, "U32") == 0)
337			elt->pe_kind = TYPE_U32;
338		else if (strcmp(type, "V32") == 0)
339			elt->pe_kind = TYPE_V32;
340		else if (strcmp(type, "W32") == 0)
341			elt->pe_kind = TYPE_W32;
342		else if (strcmp(type, "D") == 0)	/* description char * */
343			elt->pe_kind = TYPE_D;
344		else if (strcmp(type, "Z") == 0)	/* char * to match */
345			elt->pe_kind = TYPE_Z;
346		else if (strcmp(type, "P") == 0)	/* Pointer -- ignored */
347			elt->pe_kind = TYPE_P;
348		else if (strcmp(type, "E") == 0)	/* EISA PNP ID, as uint32_t */
349			elt->pe_kind = TYPE_E;
350		else if (strcmp(type, "T") == 0)
351			elt->pe_kind = TYPE_T;
352		else
353			goto err;
354		/*
355		 * Maybe the rounding here needs to be more nuanced and/or somehow
356		 * architecture specific. Fortunately, most tables in the system
357		 * have sane ordering of types.
358		 */
359		if (elt->pe_kind & TYPE_INT) {
360			elt->pe_offset = roundup2(elt->pe_offset, elt->pe_kind & TYPE_SZ_MASK);
361			off = elt->pe_offset + (elt->pe_kind & TYPE_SZ_MASK);
362		} else if (elt->pe_kind == TYPE_E) {
363			/* Type E stored as Int, displays as string */
364			elt->pe_offset = roundup2(elt->pe_offset, sizeof(uint32_t));
365			off = elt->pe_offset + sizeof(uint32_t);
366		} else if (elt->pe_kind == TYPE_T) {
367			/* doesn't actually consume space in the table */
368			off = elt->pe_offset;
369		} else {
370			elt->pe_offset = roundup2(elt->pe_offset, elf_pointer_size(ef));
371			off = elt->pe_offset + elf_pointer_size(ef);
372		}
373		if (elt->pe_kind & TYPE_PAIRED) {
374			char *word, *ctx, newtype;
375
376			for (word = strtok_r(key, "/", &ctx);
377			     word; word = strtok_r(NULL, "/", &ctx)) {
378				newtype = elt->pe_kind & TYPE_FLAGGED ? 'J' : 'I';
379				fprintf(fp, "%c:%s;", newtype, word);
380			}
381		}
382		else {
383			char newtype;
384
385			if (elt->pe_kind & TYPE_FLAGGED)
386				newtype = 'J';
387			else if (elt->pe_kind & TYPE_GE)
388				newtype = 'G';
389			else if (elt->pe_kind & TYPE_LE)
390				newtype = 'L';
391			else if (elt->pe_kind & TYPE_MASK)
392				newtype = 'M';
393			else if (elt->pe_kind & TYPE_INT)
394				newtype = 'I';
395			else if (elt->pe_kind == TYPE_D)
396				newtype = 'D';
397			else if (elt->pe_kind == TYPE_Z || elt->pe_kind == TYPE_E)
398				newtype = 'Z';
399			else if (elt->pe_kind == TYPE_T)
400				newtype = 'T';
401			else
402				errx(1, "Impossible type %x\n", elt->pe_kind);
403			fprintf(fp, "%c:%s;", newtype, key);
404		}
405	}
406	if (ferror(fp) != 0) {
407		fclose(fp);
408		errx(1, "Exhausted space converting description %s", desc);
409	}
410	if (fclose(fp) != 0)
411		errx(1, "Failed to close memory stream");
412	return (0);
413err:
414	errx(1, "Parse error of description string %s", desc);
415}
416
417static void
418free_pnp_list(char *new_desc, pnp_list *list)
419{
420	struct pnp_elt *elt, *elt_tmp;
421
422	TAILQ_FOREACH_SAFE(elt, list, next, elt_tmp) {
423		TAILQ_REMOVE(list, elt, next);
424		free(elt);
425	}
426	free(new_desc);
427}
428
429static uint16_t
430parse_16(const void *p)
431{
432	if (byte_order == ELFDATA2LSB)
433		return (le16dec(p));
434	else
435		return (be16dec(p));
436}
437
438static uint32_t
439parse_32(const void *p)
440{
441	if (byte_order == ELFDATA2LSB)
442		return (le32dec(p));
443	else
444		return (be32dec(p));
445}
446
447static void
448parse_pnp_entry(struct elf_file *ef, struct pnp_elt *elt, const char *walker)
449{
450	uint8_t v1;
451	uint16_t v2;
452	uint32_t v4;
453	int	value;
454	char buffer[1024];
455
456	if (elt->pe_kind == TYPE_W32) {
457		v4 = parse_32(walker + elt->pe_offset);
458		value = v4 & 0xffff;
459		record_int(value);
460		if (verbose > 1)
461			printf("W32:%#x", value);
462		value = (v4 >> 16) & 0xffff;
463		record_int(value);
464		if (verbose > 1)
465			printf(":%#x;", value);
466	} else if (elt->pe_kind & TYPE_INT) {
467		switch (elt->pe_kind & TYPE_SZ_MASK) {
468		case 1:
469			memcpy(&v1, walker + elt->pe_offset, sizeof(v1));
470			if ((elt->pe_kind & TYPE_FLAGGED) && v1 == 0xff)
471				value = -1;
472			else
473				value = v1;
474			break;
475		case 2:
476			v2 = parse_16(walker + elt->pe_offset);
477			if ((elt->pe_kind & TYPE_FLAGGED) && v2 == 0xffff)
478				value = -1;
479			else
480				value = v2;
481			break;
482		case 4:
483			v4 = parse_32(walker + elt->pe_offset);
484			if ((elt->pe_kind & TYPE_FLAGGED) && v4 == 0xffffffff)
485				value = -1;
486			else
487				value = v4;
488			break;
489		default:
490			errx(1, "Invalid size somehow %#x", elt->pe_kind);
491		}
492		if (verbose > 1)
493			printf("I:%#x;", value);
494		record_int(value);
495	} else if (elt->pe_kind == TYPE_T) {
496		/* Do nothing */
497	} else { /* E, Z or D -- P already filtered */
498		if (elt->pe_kind == TYPE_E) {
499			v4 = parse_32(walker + elt->pe_offset);
500			strcpy(buffer, pnp_eisaformat(v4));
501		} else {
502			GElf_Addr address;
503
504			address = elf_address_from_pointer(ef, walker +
505			    elt->pe_offset);
506			buffer[0] = '\0';
507			if (address != 0) {
508				elf_read_string(ef, address, buffer,
509				    sizeof(buffer));
510				buffer[sizeof(buffer) - 1] = '\0';
511			}
512		}
513		if (verbose > 1)
514			printf("%c:%s;", elt->pe_kind == TYPE_E ? 'E' :
515			    (elt->pe_kind == TYPE_Z ? 'Z' : 'D'), buffer);
516		record_string(buffer);
517	}
518}
519
520static void
521record_pnp_info(struct elf_file *ef, const char *cval,
522    struct Gmod_pnp_match_info *pnp, const char *descr)
523{
524	pnp_list list;
525	struct pnp_elt *elt;
526	char *new_descr, *walker;
527	void *table;
528	size_t len;
529	int error, i;
530
531	if (verbose > 1)
532		printf("  pnp info for bus %s format %s %d entries of %d bytes\n",
533		    cval, descr, pnp->num_entry, pnp->entry_len);
534
535	/*
536	 * Parse descr to weed out the chaff and to create a list
537	 * of offsets to output.
538	 */
539	parse_pnp_list(ef, descr, &new_descr, &list);
540	record_int(MDT_PNP_INFO);
541	record_string(cval);
542	record_string(new_descr);
543	record_int(pnp->num_entry);
544	len = pnp->num_entry * pnp->entry_len;
545	error = elf_read_relocated_data(ef, pnp->table, len, &table);
546	if (error != 0) {
547		free_pnp_list(new_descr, &list);
548		return;
549	}
550
551	/*
552	 * Walk the list and output things. We've collapsed all the
553	 * variant forms of the table down to just ints and strings.
554	 */
555	walker = table;
556	for (i = 0; i < pnp->num_entry; i++) {
557		TAILQ_FOREACH(elt, &list, next) {
558			parse_pnp_entry(ef, elt, walker);
559		}
560		if (verbose > 1)
561			printf("\n");
562		walker += pnp->entry_len;
563	}
564
565	/* Now free it */
566	free_pnp_list(new_descr, &list);
567	free(table);
568}
569
570static int
571parse_entry(struct Gmod_metadata *md, const char *cval,
572    struct elf_file *ef, const char *kldname)
573{
574	struct Gmod_depend mdp;
575	struct Gmod_version mdv;
576	struct Gmod_pnp_match_info pnp;
577	char descr[1024];
578	GElf_Addr data;
579	int error;
580
581	data = md->md_data;
582	error = 0;
583	record_start();
584	switch (md->md_type) {
585	case MDT_DEPEND:
586		if (!dflag)
587			break;
588		check(elf_read_mod_depend(ef, data, &mdp));
589		printf("  depends on %s.%d (%d,%d)\n", cval,
590		    mdp.md_ver_preferred, mdp.md_ver_minimum, mdp.md_ver_maximum);
591		break;
592	case MDT_VERSION:
593		check(elf_read_mod_version(ef, data, &mdv));
594		if (dflag) {
595			printf("  interface %s.%d\n", cval, mdv.mv_version);
596		} else {
597			record_int(MDT_VERSION);
598			record_string(cval);
599			record_int(mdv.mv_version);
600			record_string(kldname);
601		}
602		break;
603	case MDT_MODULE:
604		if (dflag) {
605			printf("  module %s\n", cval);
606		} else {
607			record_int(MDT_MODULE);
608			record_string(cval);
609			record_string(kldname);
610		}
611		break;
612	case MDT_PNP_INFO:
613		check(elf_read_mod_pnp_match_info(ef, data, &pnp));
614		check(elf_read_string(ef, pnp.descr, descr, sizeof(descr)));
615		if (dflag) {
616			printf("  pnp info for bus %s format %s %d entries of %d bytes\n",
617			    cval, descr, pnp.num_entry, pnp.entry_len);
618		} else {
619			record_pnp_info(ef, cval, &pnp, descr);
620		}
621		break;
622	default:
623		warnx("unknown metadata record %d in file %s", md->md_type, kldname);
624	}
625	if (!error)
626		record_end();
627	return (error);
628}
629
630static int
631read_kld(char *filename, char *kldname)
632{
633	struct Gmod_metadata md;
634	struct elf_file ef;
635	GElf_Addr *p;
636	int error;
637	long entries, i;
638	char cval[MAXMODNAME + 1];
639
640	if (verbose || dflag)
641		printf("%s\n", filename);
642
643	error = elf_open_file(&ef, filename, verbose);
644	if (error != 0)
645		return (error);
646
647	if (reccnt == 0) {
648		ehdr = ef.ef_hdr;
649		byte_order = elf_encoding(&ef);
650		free(ehdr_filename);
651		ehdr_filename = strdup(filename);
652	} else if (!elf_compatible(&ef, &ehdr)) {
653		warnx("%s does not match architecture of %s",
654		    filename, ehdr_filename);
655		elf_close_file(&ef);
656		return (EINVAL);
657	}
658
659	do {
660		check(elf_read_linker_set(&ef, MDT_SETNAME, &p, &entries));
661
662		/*
663		 * Do a first pass to find MDT_MODULE.  It is required to be
664		 * ordered first in the output linker.hints stream because it
665		 * serves as an implicit record boundary between distinct klds
666		 * in the stream.  Other MDTs only make sense in the context of
667		 * a specific MDT_MODULE.
668		 *
669		 * Some compilers (e.g., GCC 6.4.0 xtoolchain) or binutils
670		 * (e.g., GNU binutils 2.32 objcopy/ld.bfd) can reorder
671		 * MODULE_METADATA set entries relative to the source ordering.
672		 * This is permitted by the C standard; memory layout of
673		 * file-scope objects is left implementation-defined.  There is
674		 * no requirement that source code ordering is retained.
675		 *
676		 * Handle that here by taking two passes to ensure MDT_MODULE
677		 * records are emitted to linker.hints before other MDT records
678		 * in the same kld.
679		 */
680		for (i = 0; i < entries; i++) {
681			check(elf_read_mod_metadata(&ef, p[i], &md));
682			check(elf_read_string(&ef, md.md_cval, cval,
683			    sizeof(cval)));
684			if (md.md_type == MDT_MODULE) {
685				parse_entry(&md, cval, &ef, kldname);
686				break;
687			}
688		}
689		if (error != 0) {
690			free(p);
691			warnc(error, "error while reading %s", filename);
692			break;
693		}
694
695		/*
696		 * Second pass for all !MDT_MODULE entries.
697		 */
698		for (i = 0; i < entries; i++) {
699			check(elf_read_mod_metadata(&ef, p[i], &md));
700			check(elf_read_string(&ef, md.md_cval, cval,
701			    sizeof(cval)));
702			if (md.md_type != MDT_MODULE)
703				parse_entry(&md, cval, &ef, kldname);
704		}
705		if (error != 0)
706			warnc(error, "error while reading %s", filename);
707		free(p);
708	} while(0);
709	elf_close_file(&ef);
710	return (error);
711}
712
713/*
714 * Create a temp file in directory root, make sure we don't
715 * overflow the buffer for the destination name
716 */
717static FILE *
718maketempfile(char *dest, const char *root)
719{
720	int fd;
721
722	if (snprintf(dest, MAXPATHLEN, "%s/lhint.XXXXXX", root) >=
723	    MAXPATHLEN) {
724		errno = ENAMETOOLONG;
725		return (NULL);
726	}
727
728	fd = mkstemp(dest);
729	if (fd < 0)
730		return (NULL);
731	fchmod(fd, 0644);	/* nothing secret in the file */
732	return (fdopen(fd, "w+"));
733}
734
735static char xrefname[MAXPATHLEN], tempname[MAXPATHLEN];
736
737static void
738usage(void)
739{
740
741	fprintf(stderr, "%s\n",
742	    "usage: kldxref [-Rdv] [-f hintsfile] path ..."
743	);
744	exit(1);
745}
746
747static int
748#if defined(__linux__) || defined(__APPLE__)
749compare(const FTSENT **a, const FTSENT **b)
750#else
751compare(const FTSENT *const *a, const FTSENT *const *b)
752#endif
753{
754
755	if ((*a)->fts_info == FTS_D && (*b)->fts_info != FTS_D)
756		return (1);
757	if ((*a)->fts_info != FTS_D && (*b)->fts_info == FTS_D)
758		return (-1);
759	return (strcmp((*a)->fts_name, (*b)->fts_name));
760}
761
762int
763main(int argc, char *argv[])
764{
765	FTS *ftsp;
766	FTSENT *p;
767	char *dot = NULL;
768	int opt, fts_options;
769	struct stat sb;
770
771	fts_options = FTS_PHYSICAL;
772
773	while ((opt = getopt(argc, argv, "Rdf:v")) != -1) {
774		switch (opt) {
775		case 'd':	/* no hint file, only print on stdout */
776			dflag = true;
777			break;
778		case 'f':	/* use this name instead of linker.hints */
779			xref_file = optarg;
780			break;
781		case 'v':
782			verbose++;
783			break;
784		case 'R':	/* recurse on directories */
785			fts_options |= FTS_COMFOLLOW;
786			break;
787		default:
788			usage();
789			/* NOTREACHED */
790		}
791	}
792	if (argc - optind < 1)
793		usage();
794	argc -= optind;
795	argv += optind;
796
797	if (stat(argv[0], &sb) != 0)
798		err(1, "%s", argv[0]);
799	if ((sb.st_mode & S_IFDIR) == 0 && !dflag) {
800		errno = ENOTDIR;
801		err(1, "%s", argv[0]);
802	}
803
804	if (elf_version(EV_CURRENT) == EV_NONE)
805		errx(1, "unsupported libelf");
806
807	ftsp = fts_open(argv, fts_options, compare);
808	if (ftsp == NULL)
809		exit(1);
810
811	for (;;) {
812		p = fts_read(ftsp);
813		if ((p == NULL || p->fts_info == FTS_D) && fxref) {
814			/* close and rename the current hint file */
815			fclose(fxref);
816			fxref = NULL;
817			if (reccnt != 0) {
818				rename(tempname, xrefname);
819			} else {
820				/* didn't find any entry, ignore this file */
821				unlink(tempname);
822				unlink(xrefname);
823			}
824		}
825		if (p == NULL)
826			break;
827		if (p->fts_info == FTS_D && !dflag) {
828			/* visiting a new directory, create a new hint file */
829			snprintf(xrefname, sizeof(xrefname), "%s/%s",
830			    ftsp->fts_path, xref_file);
831			fxref = maketempfile(tempname, ftsp->fts_path);
832			if (fxref == NULL)
833				err(1, "can't create %s", tempname);
834			byte_order = ELFDATANONE;
835			reccnt = 0;
836		}
837		/* skip non-files.. */
838		if (p->fts_info != FTS_F)
839			continue;
840		/*
841		 * Skip files that generate errors like .debug, .symbol and .pkgsave
842		 * by generally skipping all files not ending with ".ko" or that have
843		 * no dots in the name (like kernel).
844		 */
845		dot = strrchr(p->fts_name, '.');
846		if (dot != NULL && strcmp(dot, ".ko") != 0)
847			continue;
848		read_kld(p->fts_path, p->fts_name);
849	}
850	fts_close(ftsp);
851	return (0);
852}
853