Index | Thread | Search

From:
Jonathan Gray <jsg@jsg.id.au>
Subject:
Re: btrace(8): cache ELF .symtab, .strtab in sorted array
To:
Scott Cheloha via tech <tech@openbsd.org>
Cc:
mpi@openbsd.org
Date:
Sat, 30 Mar 2024 18:59:02 +1100

Download raw body.

Thread
On Wed, Mar 13, 2024 at 07:58:28PM -0500, Scott Cheloha via tech wrote:
> Index: ksyms.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/btrace/ksyms.c,v
> diff -u -p -r1.8 -r1.7
> --- ksyms.c	14 Mar 2024 00:54:54 -0000	1.8
> +++ ksyms.c	12 Mar 2024 17:22:24 -0000	1.7
> @@ -1,4 +1,4 @@
> -/*	$OpenBSD: ksyms.c,v 1.8 2024/03/14 00:54:54 cheloha Exp $ */
> +/*	$OpenBSD: ksyms.c,v 1.7 2024/03/12 17:22:24 cheloha Exp $ */
>  
>  /*
>   * Copyright (c) 2016 Martin Pieuchot <mpi@openbsd.org>
> @@ -23,6 +23,7 @@
>  #include <err.h>
>  #include <fcntl.h>
>  #include <gelf.h>
> +#include <stdint.h>
>  #include <stdio.h>
>  #include <stdlib.h>
>  #include <string.h>
> @@ -30,60 +31,149 @@
>  
>  #include "btrace.h"
>  
> +struct sym {
> +	char *sym_name;
> +	unsigned long sym_value;	/* from st_value */
> +	unsigned long sym_size;		/* from st_size */
> +};
> +
>  struct syms {
> -	int		 fd;
> -	Elf		*elf;
> -	Elf_Scn		*symtab;
> -	size_t		 strtabndx, nsymb;
> +	struct sym *table;
> +	size_t nsymb;
>  };
>  
> -int		 kelf_parse(struct syms *);
> +int sym_compare_search(const void *, const void *);
> +int sym_compare_sort(const void *, const void *);
>  
>  struct syms *
>  kelf_open(const char *path)
>  {
> -	struct syms *syms;
> -	int error;
> +	char *name;
> +	Elf *elf;
> +	Elf_Data *data = NULL;
> +	Elf_Scn	*scn = NULL, *symtab;
> +	GElf_Sym sym;
> +	GElf_Shdr shdr;
> +	size_t i, shstrndx, strtabndx = SIZE_MAX, symtab_size;
> +	unsigned long diff;
> +	struct sym *tmp;
> +	struct syms *syms = NULL;
> +	int fd;
>  
>  	if (elf_version(EV_CURRENT) == EV_NONE)
>  		errx(1, "elf_version: %s", elf_errmsg(-1));
>  
> -	if ((syms = calloc(1, sizeof(*syms))) == NULL)
> -		err(1, NULL);
> -
> -	syms->fd = open(path, O_RDONLY);
> -	if (syms->fd == -1) {
> +	fd = open(path, O_RDONLY);
> +	if (fd == -1) {
>  		warn("open: %s", path);
> -		free(syms);
>  		return NULL;
>  	}
>  
> -	if ((syms->elf = elf_begin(syms->fd, ELF_C_READ, NULL)) == NULL) {
> +	if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
>  		warnx("elf_begin: %s", elf_errmsg(-1));
>  		goto bad;
>  	}
>  
> -	if (elf_kind(syms->elf) != ELF_K_ELF)
> +	if (elf_kind(elf) != ELF_K_ELF)
>  		goto bad;
>  
> -	error = kelf_parse(syms);
> -	if (error)
> +	if (elf_getshdrstrndx(elf, &shstrndx) != 0) {
> +		warnx("elf_getshdrstrndx: %s", elf_errmsg(-1));
>  		goto bad;
> +	}
>  
> -	return syms;
> +	while ((scn = elf_nextscn(elf, scn)) != NULL) {
> +		if (gelf_getshdr(scn, &shdr) != &shdr) {
> +			warnx("elf_getshdr: %s", elf_errmsg(-1));
> +			goto bad;
> +		}
> +		if ((name = elf_strptr(elf, shstrndx, shdr.sh_name)) == NULL) {
> +			warnx("elf_strptr: %s", elf_errmsg(-1));
> +			goto bad;
> +		}
> +		if (strcmp(name, ELF_SYMTAB) == 0 &&
> +		    shdr.sh_type == SHT_SYMTAB && shdr.sh_entsize != 0) {
> +			symtab = scn;
> +			symtab_size = shdr.sh_size / shdr.sh_entsize;
> +		}
> +		if (strcmp(name, ELF_STRTAB) == 0 &&
> +		    shdr.sh_type == SHT_STRTAB) {
> +			strtabndx = elf_ndxscn(scn);
> +		}
> +	}
> +	if (symtab == NULL) {
> +		warnx("%s: %s: section not found", path, ELF_SYMTAB);
> +		goto bad;
> +	}

only makes sense if symtab gets initialised

as noted by smatch:
/usr/src/usr.sbin/btrace/ksyms.c:104 kelf_open() error: uninitialized symbol 'symtab'.
/usr/src/usr.sbin/btrace/ksyms.c:119 kelf_open() error: uninitialized symbol 'symtab_size'.

Index: ksyms.c
===================================================================
RCS file: /cvs/src/usr.sbin/btrace/ksyms.c,v
diff -u -p -r1.9 ksyms.c
--- ksyms.c	16 Mar 2024 17:42:37 -0000	1.9
+++ ksyms.c	30 Mar 2024 07:44:40 -0000
@@ -51,7 +51,7 @@ kelf_open(const char *path)
 	char *name;
 	Elf *elf;
 	Elf_Data *data = NULL;
-	Elf_Scn	*scn = NULL, *symtab;
+	Elf_Scn	*scn = NULL, *symtab = NULL;
 	GElf_Sym sym;
 	GElf_Shdr shdr;
 	size_t i, shstrndx, strtabndx = SIZE_MAX, symtab_size;