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 59 static bool dflag; /* do not create a hint file, only write on stdout */ 60 static int verbose; 61 62 static FILE *fxref; /* current hints file */ 63 static int byte_order; 64 static GElf_Ehdr ehdr; 65 static char *ehdr_filename; 66 67 static const char *xref_file = "linker.hints"; 68 69 /* 70 * A record is stored in the static buffer recbuf before going to disk. 71 */ 72 static char recbuf[MAXRECSIZE]; 73 static int recpos; /* current write position */ 74 static int reccnt; /* total record written to this file so far */ 75 76 static void 77 intalign(void) 78 { 79 80 recpos = roundup2(recpos, sizeof(int)); 81 } 82 83 static void 84 write_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 96 static void 97 record_start(void) 98 { 99 100 recpos = 0; 101 memset(recbuf, 0, MAXRECSIZE); 102 } 103 104 static int 105 record_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 129 static int 130 record_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 */ 143 static int 144 record_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 */ 161 static int 162 record_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 */ 180 static char * 181 pnp_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 200 struct 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 }; 229 typedef 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 */ 262 static int 263 parse_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); 413 err: 414 errx(1, "Parse error of description string %s", desc); 415 } 416 417 static void 418 free_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 429 static uint16_t 430 parse_16(const void *p) 431 { 432 if (byte_order == ELFDATA2LSB) 433 return (le16dec(p)); 434 else 435 return (be16dec(p)); 436 } 437 438 static uint32_t 439 parse_32(const void *p) 440 { 441 if (byte_order == ELFDATA2LSB) 442 return (le32dec(p)); 443 else 444 return (be32dec(p)); 445 } 446 447 static void 448 parse_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 520 static void 521 record_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 570 static int 571 parse_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 630 static int 631 read_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 */ 717 static FILE * 718 maketempfile(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 735 static char xrefname[MAXPATHLEN], tempname[MAXPATHLEN]; 736 737 static void 738 usage(void) 739 { 740 741 fprintf(stderr, "%s\n", 742 "usage: kldxref [-Rdv] [-f hintsfile] path ..." 743 ); 744 exit(1); 745 } 746 747 static int 748 #if defined(__linux__) || defined(__APPLE__) 749 compare(const FTSENT **a, const FTSENT **b) 750 #else 751 compare(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 762 int 763 main(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