git: c40fa3dc98d3 - main - kldxref: Refactor PNP entry parsing, no functional change
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 12 Dec 2023 23:30:49 UTC
The branch main has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=c40fa3dc98d3cd8c39605c19c9cc08026d8e72c9 commit c40fa3dc98d3cd8c39605c19c9cc08026d8e72c9 Author: John Baldwin <jhb@FreeBSD.org> AuthorDate: 2023-12-12 23:30:16 +0000 Commit: John Baldwin <jhb@FreeBSD.org> CommitDate: 2023-12-12 23:30:16 +0000 kldxref: Refactor PNP entry parsing, no functional change - Add a free_pnp_list to complement parse_pnp_list. Add freeing of 'new_desc' which was previously leaked. - Move body of loop that checked a single pnp list element against a table entry into a parse_pnp_entry function to reduce indentation and split parse_entry into a smaller function. - Similarly, split out a record_pnp_info function from parse_entry which builds the pnp_list and walks a table. Reviewed by: imp Sponsored by: DARPA Differential Revision: https://reviews.freebsd.org/D42965 --- usr.sbin/kldxref/kldxref.c | 247 +++++++++++++++++++++++++-------------------- 1 file changed, 139 insertions(+), 108 deletions(-) diff --git a/usr.sbin/kldxref/kldxref.c b/usr.sbin/kldxref/kldxref.c index ae0d22181688..913b64ee2a16 100644 --- a/usr.sbin/kldxref/kldxref.c +++ b/usr.sbin/kldxref/kldxref.c @@ -237,6 +237,7 @@ parse_pnp_list(const char *desc, char **new_desc, pnp_list *list) size_t new_desc_size; FILE *fp; + TAILQ_INIT(list); walker = desc; ep = desc + strlen(desc); off = 0; @@ -379,6 +380,142 @@ err: errx(1, "Parse error of description string %s", desc); } +static void +free_pnp_list(char *new_desc, pnp_list *list) +{ + struct pnp_elt *elt, *elt_tmp; + + TAILQ_FOREACH_SAFE(elt, list, next, elt_tmp) { + TAILQ_REMOVE(list, elt, next); + free(elt); + } + free(new_desc); +} + +static void +parse_pnp_entry(struct elf_file *ef, struct pnp_elt *elt, const char *walker) +{ + uint8_t v1; + uint16_t v2; + uint32_t v4; + int value; + char buffer[1024]; + + if (elt->pe_kind == TYPE_W32) { + memcpy(&v4, walker + elt->pe_offset, sizeof(v4)); + value = v4 & 0xffff; + record_int(value); + if (verbose > 1) + printf("W32:%#x", value); + value = (v4 >> 16) & 0xffff; + record_int(value); + if (verbose > 1) + printf(":%#x;", value); + } else if (elt->pe_kind & TYPE_INT) { + switch (elt->pe_kind & TYPE_SZ_MASK) { + case 1: + memcpy(&v1, walker + elt->pe_offset, sizeof(v1)); + if ((elt->pe_kind & TYPE_FLAGGED) && v1 == 0xff) + value = -1; + else + value = v1; + break; + case 2: + memcpy(&v2, walker + elt->pe_offset, sizeof(v2)); + if ((elt->pe_kind & TYPE_FLAGGED) && v2 == 0xffff) + value = -1; + else + value = v2; + break; + case 4: + memcpy(&v4, walker + elt->pe_offset, sizeof(v4)); + if ((elt->pe_kind & TYPE_FLAGGED) && v4 == 0xffffffff) + value = -1; + else + value = v4; + break; + default: + errx(1, "Invalid size somehow %#x", elt->pe_kind); + } + if (verbose > 1) + printf("I:%#x;", value); + record_int(value); + } else if (elt->pe_kind == TYPE_T) { + /* Do nothing */ + } else { /* E, Z or D -- P already filtered */ + if (elt->pe_kind == TYPE_E) { + memcpy(&v4, walker + elt->pe_offset, sizeof(v4)); + strcpy(buffer, pnp_eisaformat(v4)); + } else { + char *ptr; + + ptr = *(char **)(walker + elt->pe_offset); + buffer[0] = '\0'; + if (ptr != NULL) { + EF_SEG_READ_STRING(ef, (Elf_Off)ptr, + sizeof(buffer), buffer); + buffer[sizeof(buffer) - 1] = '\0'; + } + } + if (verbose > 1) + printf("%c:%s;", elt->pe_kind == TYPE_E ? 'E' : + (elt->pe_kind == TYPE_Z ? 'Z' : 'D'), buffer); + record_string(buffer); + } +} + +static void +record_pnp_info(struct elf_file *ef, const char *cval, + struct mod_pnp_match_info *pnp, const char *descr) +{ + pnp_list list; + struct pnp_elt *elt; + char *new_descr, *walker; + void *table; + size_t len; + int error, i; + + if (verbose > 1) + printf(" pnp info for bus %s format %s %d entries of %d bytes\n", + cval, descr, pnp->num_entry, pnp->entry_len); + + /* + * Parse descr to weed out the chaff and to create a list + * of offsets to output. + */ + parse_pnp_list(descr, &new_descr, &list); + record_int(MDT_PNP_INFO); + record_string(cval); + record_string(new_descr); + record_int(pnp->num_entry); + len = pnp->num_entry * pnp->entry_len; + table = malloc(len); + error = EF_SEG_READ_REL(ef, (Elf_Off)pnp->table, len, table); + if (error != 0) { + free_pnp_list(new_descr, &list); + free(table); + return; + } + + /* + * Walk the list and output things. We've collapsed all the + * variant forms of the table down to just ints and strings. + */ + walker = table; + for (i = 0; i < pnp->num_entry; i++) { + TAILQ_FOREACH(elt, &list, next) { + parse_pnp_entry(ef, elt, walker); + } + if (verbose > 1) + printf("\n"); + walker += pnp->entry_len; + } + + /* Now free it */ + free_pnp_list(new_descr, &list); + free(table); +} + static int parse_entry(struct mod_metadata *md, const char *cval, struct elf_file *ef, const char *kldname) @@ -388,10 +525,7 @@ parse_entry(struct mod_metadata *md, const char *cval, struct mod_pnp_match_info pnp; char descr[1024]; Elf_Off data; - int error, i; - size_t len; - char *walker; - void *table; + int error; data = (Elf_Off)md->md_data; error = 0; @@ -432,110 +566,7 @@ parse_entry(struct mod_metadata *md, const char *cval, printf(" pnp info for bus %s format %s %d entries of %d bytes\n", cval, descr, pnp.num_entry, pnp.entry_len); } else { - pnp_list list; - struct pnp_elt *elt, *elt_tmp; - char *new_descr; - - if (verbose > 1) - printf(" pnp info for bus %s format %s %d entries of %d bytes\n", - cval, descr, pnp.num_entry, pnp.entry_len); - /* - * Parse descr to weed out the chaff and to create a list - * of offsets to output. - */ - TAILQ_INIT(&list); - parse_pnp_list(descr, &new_descr, &list); - record_int(MDT_PNP_INFO); - record_string(cval); - record_string(new_descr); - record_int(pnp.num_entry); - len = pnp.num_entry * pnp.entry_len; - walker = table = malloc(len); - check(EF_SEG_READ_REL(ef, (Elf_Off)pnp.table, len, table)); - - /* - * Walk the list and output things. We've collapsed all the - * variant forms of the table down to just ints and strings. - */ - for (i = 0; i < pnp.num_entry; i++) { - TAILQ_FOREACH(elt, &list, next) { - uint8_t v1; - uint16_t v2; - uint32_t v4; - int value; - char buffer[1024]; - - if (elt->pe_kind == TYPE_W32) { - memcpy(&v4, walker + elt->pe_offset, sizeof(v4)); - value = v4 & 0xffff; - record_int(value); - if (verbose > 1) - printf("W32:%#x", value); - value = (v4 >> 16) & 0xffff; - record_int(value); - if (verbose > 1) - printf(":%#x;", value); - } else if (elt->pe_kind & TYPE_INT) { - switch (elt->pe_kind & TYPE_SZ_MASK) { - case 1: - memcpy(&v1, walker + elt->pe_offset, sizeof(v1)); - if ((elt->pe_kind & TYPE_FLAGGED) && v1 == 0xff) - value = -1; - else - value = v1; - break; - case 2: - memcpy(&v2, walker + elt->pe_offset, sizeof(v2)); - if ((elt->pe_kind & TYPE_FLAGGED) && v2 == 0xffff) - value = -1; - else - value = v2; - break; - case 4: - memcpy(&v4, walker + elt->pe_offset, sizeof(v4)); - if ((elt->pe_kind & TYPE_FLAGGED) && v4 == 0xffffffff) - value = -1; - else - value = v4; - break; - default: - errx(1, "Invalid size somehow %#x", elt->pe_kind); - } - if (verbose > 1) - printf("I:%#x;", value); - record_int(value); - } else if (elt->pe_kind == TYPE_T) { - /* Do nothing */ - } else { /* E, Z or D -- P already filtered */ - if (elt->pe_kind == TYPE_E) { - memcpy(&v4, walker + elt->pe_offset, sizeof(v4)); - strcpy(buffer, pnp_eisaformat(v4)); - } else { - char *ptr; - - ptr = *(char **)(walker + elt->pe_offset); - buffer[0] = '\0'; - if (ptr != NULL) { - EF_SEG_READ_STRING(ef, (Elf_Off)ptr, - sizeof(buffer), buffer); - buffer[sizeof(buffer) - 1] = '\0'; - } - } - if (verbose > 1) - printf("%c:%s;", elt->pe_kind == TYPE_E ? 'E' : (elt->pe_kind == TYPE_Z ? 'Z' : 'D'), buffer); - record_string(buffer); - } - } - if (verbose > 1) - printf("\n"); - walker += pnp.entry_len; - } - /* Now free it */ - TAILQ_FOREACH_SAFE(elt, &list, next, elt_tmp) { - TAILQ_REMOVE(&list, elt, next); - free(elt); - } - free(table); + record_pnp_info(ef, cval, &pnp, descr); } break; default: