<commit_before>/*
 * Copyright (c) 2011-2012 <NAME> <<EMAIL>>
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer
 *    in this position and unchanged.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/endian.h>
#include <sys/types.h>
#include <sys/elf_common.h>

#include <ctype.h>
#include <assert.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <gelf.h>
#include <link.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>

#include "pkg.h"
#include "private/pkg.h"
#include "private/event.h"
#include "private/elf_tables.h"

static int
register_shlibs(struct pkg *pkg, const char *namelist[])
{
	struct pkg_shlib *s;
	const char **name;
	bool found;

	assert(pkg != NULL);

	for (name = namelist; *name != NULL; name++) {
		s = NULL;
		found = false;
		while (pkg_shlibs(pkg, &s) == EPKG_OK) {
			if (strcmp(*name, pkg_shlib_name(s)) == 0) {
				/* already registered, but that's OK */
				found = true;
				break;
			}
		}
		if ( !found ) {
			pkg_shlib_new(&s);
			sbuf_set(&s->name, *name);
			STAILQ_INSERT_TAIL(&pkg->shlibs, s, next);
		}
	}
	return (EPKG_OK);
}

static int
add_forgotten_depends(struct pkgdb *db, struct pkg *pkg, const char *namelist[])
{
	struct pkg_dep *dep = NULL;
	struct pkgdb_it *it = NULL;
	struct pkg *d;
	Link_map *map;
	const char *deporigin, *depname, *depversion;
	const char **name;
	bool found;
	void *handle;

	for (name = namelist; *name != NULL; name++) {
		handle = dlopen(*name, RTLD_LAZY);
		if (handle == NULL) {
			pkg_emit_error("accessing shared library %s failed -- %s", name, dlerror());
			return (EPKG_FATAL);
		}

		dlinfo(handle, RTLD_DI_LINKMAP, &map);

		if ((it = pkgdb_query_which(db, map->l_name)) == NULL) {
			dlclose(handle);
			break; /* shlib not from any pkg */
		}
		d = NULL;
		if (pkgdb_it_next(it, &d, PKG_LOAD_BASIC) == EPKG_OK) {
			found = false;
			pkg_get(d, PKG_ORIGIN, &deporigin, PKG_NAME, &depname, PKG_VERSION, &depversion);

			dep = NULL;
			found = false;
			while (pkg_deps(pkg, &dep) == EPKG_OK) {
				if (strcmp(pkg_dep_get(dep, PKG_DEP_ORIGIN), deporigin) == 0) {
					found = true;
					break;
				}
			}
			if (!found) {
				pkg_emit_error("adding forgotten depends (%s): %s-%s",
					       map->l_name, depname, depversion);
				pkg_adddep(pkg, depname, deporigin, depversion);
			}
			pkg_free(d);
		}
		dlclose(handle);
		pkgdb_it_free(it);
	}
	return (EPKG_OK);
}

static int
analyse_elf(const char *fpath, const char ***namelist) 
{
	Elf *e;
	Elf_Scn *scn = NULL;
	GElf_Shdr shdr;
	Elf_Data *data;
	GElf_Dyn *dyn, dyn_mem;

	size_t numdyn;
	size_t dynidx;
	const char **name;

	int fd;

	if ((fd = open(fpath, O_RDONLY, 0)) < 0)
		return (EPKG_FATAL);

	if (( e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
		close(fd);
		return (EPKG_FATAL);
	}
	if (elf_kind(e) != ELF_K_ELF) {
		close(fd);
		return (EPKG_END); /* Not an elf file: no results */
	}

	while (( scn = elf_nextscn(e, scn)) != NULL) {
		if (gelf_getshdr(scn, &shdr) != &shdr) {
			close(fd);
			return (EPKG_FATAL);
		}
		if (shdr.sh_type == SHT_DYNAMIC)
			break;
	}

	if  (scn == NULL) {
		close(fd);
		return (EPKG_END); /* not dynamically linked: no results */
	}

	data = elf_getdata(scn, NULL);
	numdyn = shdr.sh_size / shdr.sh_entsize;

	if ( (*namelist = calloc(numdyn + 1, sizeof(**namelist))) == NULL ) {
		close(fd);
		return (EPKG_FATAL);
	}
	name = *namelist;

	for (dynidx = 0; dynidx < numdyn; dynidx++) {
		if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL) {
			close(fd);
			return (EPKG_FATAL);
		}

		if (dyn->d_tag != DT_NEEDED)
			continue;

		*name = elf_strptr(e, shdr.sh_link, dyn->d_un.d_val);
		name++;
	}

	pkg_free(p);
	if (e != NULL)
		elf_end(e);
	*name = NULL;
	close(fd);

	return (EPKG_OK);
}

int
pkg_analyse_init(void)
{
	if (elf_version(EV_CURRENT) == EV_NONE)
		return (EPKG_FATAL);<commit_msg>Fix spelling end_elf -> elf_end.<commit_after>/*
 * Copyright (c) 2011-2012 <NAME> <<EMAIL>>
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer
 *    in this position and unchanged.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <sys/endian.h>
#include <sys/types.h>
#include <sys/elf_common.h>

#include <ctype.h>
#include <assert.h>
#include <fcntl.h>
#include <dlfcn.h>
#include <gelf.h>
#include <link.h>
#include <stdbool.h>
#include <unistd.h>
#include <string.h>

#include "pkg.h"
#include "private/pkg.h"
#include "private/event.h"
#include "private/elf_tables.h"

static int
register_shlibs(struct pkg *pkg, const char *namelist[])
{
	struct pkg_shlib *s;
	const char **name;
	bool found;

	assert(pkg != NULL);

	for (name = namelist; *name != NULL; name++) {
		s = NULL;
		found = false;
		while (pkg_shlibs(pkg, &s) == EPKG_OK) {
			if (strcmp(*name, pkg_shlib_name(s)) == 0) {
				/* already registered, but that's OK */
				found = true;
				break;
			}
		}
		if ( !found ) {
			pkg_shlib_new(&s);
			sbuf_set(&s->name, *name);
			STAILQ_INSERT_TAIL(&pkg->shlibs, s, next);
		}
	}
	return (EPKG_OK);
}

static int
add_forgotten_depends(struct pkgdb *db, struct pkg *pkg, const char *namelist[])
{
	struct pkg_dep *dep = NULL;
	struct pkgdb_it *it = NULL;
	struct pkg *d;
	Link_map *map;
	const char *deporigin, *depname, *depversion;
	const char **name;
	bool found;
	void *handle;

	for (name = namelist; *name != NULL; name++) {
		handle = dlopen(*name, RTLD_LAZY);
		if (handle == NULL) {
			pkg_emit_error("accessing shared library %s failed -- %s", name, dlerror());
			return (EPKG_FATAL);
		}

		dlinfo(handle, RTLD_DI_LINKMAP, &map);

		if ((it = pkgdb_query_which(db, map->l_name)) == NULL) {
			dlclose(handle);
			break; /* shlib not from any pkg */
		}
		d = NULL;
		if (pkgdb_it_next(it, &d, PKG_LOAD_BASIC) == EPKG_OK) {
			found = false;
			pkg_get(d, PKG_ORIGIN, &deporigin, PKG_NAME, &depname, PKG_VERSION, &depversion);

			dep = NULL;
			found = false;
			while (pkg_deps(pkg, &dep) == EPKG_OK) {
				if (strcmp(pkg_dep_get(dep, PKG_DEP_ORIGIN), deporigin) == 0) {
					found = true;
					break;
				}
			}
			if (!found) {
				pkg_emit_error("adding forgotten depends (%s): %s-%s",
					       map->l_name, depname, depversion);
				pkg_adddep(pkg, depname, deporigin, depversion);
			}
			pkg_free(d);
		}
		dlclose(handle);
		pkgdb_it_free(it);
	}
	return (EPKG_OK);
}

static int
analyse_elf(const char *fpath, const char ***namelist) 
{
	Elf *e;
	Elf_Scn *scn = NULL;
	GElf_Shdr shdr;
	Elf_Data *data;
	GElf_Dyn *dyn, dyn_mem;

	size_t numdyn;
	size_t dynidx;
	const char **name;

	int fd;

	if ((fd = open(fpath, O_RDONLY, 0)) < 0)
		return (EPKG_FATAL);

	if (( e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
		close(fd);
		return (EPKG_FATAL);
	}
	if (elf_kind(e) != ELF_K_ELF) {
		close(fd);
		return (EPKG_END); /* Not an elf file: no results */
	}

	while (( scn = elf_nextscn(e, scn)) != NULL) {
		if (gelf_getshdr(scn, &shdr) != &shdr) {
			close(fd);
			return (EPKG_FATAL);
		}
		if (shdr.sh_type == SHT_DYNAMIC)
			break;
	}

	if  (scn == NULL) {
		close(fd);
		return (EPKG_END); /* not dynamically linked: no results */
	}

	data = elf_getdata(scn, NULL);
	numdyn = shdr.sh_size / shdr.sh_entsize;

	if ( (*namelist = calloc(numdyn + 1, sizeof(**namelist))) == NULL ) {
		close(fd);
		return (EPKG_FATAL);
	}
	name = *namelist;

	for (dynidx = 0; dynidx < numdyn; dynidx++) {
		if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL) {
			close(fd);
			return (EPKG_FATAL);
		}

		if (dyn->d_tag != DT_NEEDED)
			continue;

		*name = elf_strptr(e, shdr.sh_link, dyn->d_un.d_val);
		name++;
	}

cleanup:
	if ( e != NULL)
		elf_end(e);
	close(fd);

	return (EPKG_OK);
}

int
pkg_analyse_init(void)
{
	if (elf_version(EV_CURRENT) == EV_NONE)
		return (EPKG_FATAL);
{'fraction_non_alphanumeric': 0.1378966274196767, 'fraction_numerical': 0.0031929754540011976, 'mean_word_length': 3.7888198757763973, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 46, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2307840', 'n_tokens_mistral': 4232, 'n_tokens_neox': 3743, 'n_words': 1092}