view cp/nucleus/symtab.c @ 650:6fca4100a886

include: change uint64_t LP64 definition to be unsigned long This matches what is normally used in the Unix world. Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
date Tue, 30 Jul 2019 14:56:02 -0400
parents 23c7ac98d616
children b482390e2b6b
line wrap: on
line source

/*
 * (C) Copyright 2007-2019  Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
 *
 * This file is released under the GPLv2.  See the COPYING file for more
 * details.
 */

#include <symtab.h>

Elf64_Ehdr *symtab;

static Elf64_Shdr *__get_section(int i)
{
	return ((void*)symtab) + symtab->e_shoff + symtab->e_shentsize * i;
}

static void *get_section(int type, int *entsize, int *size)
{
	Elf64_Shdr *cur;
	int getstr = 0;
	int i;

	/* we want the string table associated with the symbol table */
	if (type == SHT_STRTAB) {
		getstr = 1;
		type = SHT_SYMTAB;
	}

	for(i=0; i<symtab->e_shnum; i++) {
		cur = __get_section(i);

		if (cur->sh_type == type)
			goto found;
	}

	return NULL;

found:

	if (getstr)
		cur = __get_section(cur->sh_link);

	*entsize = cur->sh_entsize;
	*size = cur->sh_size;
	return ((void*)symtab) + cur->sh_offset;
}

void symtab_find_text_range(u64 *start, u64 *end)
{
	u64 s, e;
	Elf64_Sym *cur, *tab;
	int entsize, size;
	int bind, type;

	s = -1;
	e = 0;

	tab = get_section(SHT_SYMTAB, &entsize, &size);
	if (!tab)
		return;

	cur=tab;

	while(((void*)cur)-((void*)tab)<size) {
		cur = ((void*)cur) + entsize;

		bind = cur->st_info >> 4;
		type = cur->st_info & 0xf;

		if ((bind != STB_LOCAL) && (bind != STB_GLOBAL))
			continue;

		if ((type != STT_OBJECT) && (type != STT_FUNC))
			continue;

		if (s > cur->st_value)
			s = cur->st_value;
		if (e < (cur->st_value + cur->st_size))
			e = cur->st_value + cur->st_size;
	}

	*start = s;
	*end = e;
}

char *symtab_lookup(u64 addr, char *buf, int buflen)
{
	Elf64_Sym *cur, *tab;
	char *strtab;
	int entsize, size;
	int strsize, dummy;
	int bind, type;

	tab = get_section(SHT_SYMTAB, &entsize, &size);
	if (!tab)
		goto fail;

	strtab = get_section(SHT_STRTAB, &dummy, &strsize);
	if (!strtab)
		goto fail;

	cur=tab;

	while(((void*)cur)-((void*)tab)<size) {
		cur = ((void*)cur) + entsize;

		bind = cur->st_info >> 4;
		type = cur->st_info & 0xf;

		if ((bind != STB_LOCAL) && (bind != STB_GLOBAL))
			continue;

		if ((type != STT_OBJECT) && (type != STT_FUNC))
			continue;

		if (addr < cur->st_value)
			continue;
		if (addr >= (cur->st_value + cur->st_size))
			continue;

		/* ok, found the symbol */
		if (cur->st_name > strsize)
			goto fail;

		snprintf(buf, buflen, "%s+%#lx",
			 strtab + cur->st_name, addr - cur->st_value);
		return buf;
	}

fail:
	return "???";
}