コード例 #1
0
ファイル: dwarf_init.c プロジェクト: Scarletts/LiteBSD
int
dwarf_init(int fd, int mode, Dwarf_Handler errhand, Dwarf_Ptr errarg,
    Dwarf_Debug *ret_dbg, Dwarf_Error *error)
{
	Dwarf_Debug dbg;
	Elf *elf;
	int ret;

	if (fd < 0 || ret_dbg == NULL) {
		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
		return (DW_DLV_ERROR);
	}

	if (mode != DW_DLC_READ) {
		DWARF_SET_ERROR(NULL, error, DW_DLE_ARGUMENT);
		return (DW_DLV_ERROR);
	}

	if (elf_version(EV_CURRENT) == EV_NONE) {
		DWARF_SET_ELF_ERROR(NULL, error);
		return (DW_DLV_ERROR);
	}

	if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
		DWARF_SET_ELF_ERROR(NULL, error);
		return (DW_DLV_ERROR);
	}

	if (_dwarf_alloc(&dbg, mode, error) != DW_DLE_NONE)
		return (DW_DLV_ERROR);

	if (_dwarf_elf_init(dbg, elf, error) != DW_DLE_NONE) {
		free(dbg);
		return (DW_DLV_ERROR);
	}

	if ((ret = _dwarf_init(dbg, 0, errhand, errarg, error)) !=
	    DW_DLE_NONE) {
		_dwarf_elf_deinit(dbg);
		free(dbg);
		if (ret == DW_DLE_DEBUG_INFO_NULL)
			return (DW_DLV_NO_ENTRY);
		else
			return (DW_DLV_ERROR);
	}

	*ret_dbg = dbg;

	return (DW_DLV_OK);
}
コード例 #2
0
static int
_dwarf_elf_relocate(Dwarf_Debug dbg, Elf *elf, Dwarf_Elf_Data *ed, size_t shndx,
    size_t symtab, Elf_Data *symtab_data, Dwarf_Error *error)
{
	GElf_Ehdr eh;
	GElf_Shdr sh;
	Elf_Scn *scn;
	Elf_Data *rel;
	int elferr;

	if (symtab == 0 || symtab_data == NULL)
		return (DW_DLE_NONE);

	if (gelf_getehdr(elf, &eh) == NULL) {
		DWARF_SET_ELF_ERROR(dbg, error);
		return (DW_DLE_ELF);
	}

	scn = NULL;
	(void) elf_errno();
	while ((scn = elf_nextscn(elf, scn)) != NULL) {
		if (gelf_getshdr(scn, &sh) == NULL) {
			DWARF_SET_ELF_ERROR(dbg, error);
			return (DW_DLE_ELF);
		}

		if (sh.sh_type != SHT_RELA || sh.sh_size == 0)
			continue;

		if (sh.sh_info == shndx && sh.sh_link == symtab) {
			if ((rel = elf_getdata(scn, NULL)) == NULL) {
				elferr = elf_errno();
				if (elferr != 0) {
					_DWARF_SET_ERROR(NULL, error,
					    DW_DLE_ELF, elferr);
					return (DW_DLE_ELF);
				} else
					return (DW_DLE_NONE);
			}

			ed->ed_alloc = malloc(ed->ed_data->d_size);
			if (ed->ed_alloc == NULL) {
				DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
				return (DW_DLE_MEMORY);
			}
			memcpy(ed->ed_alloc, ed->ed_data->d_buf,
			    ed->ed_data->d_size);
			_dwarf_elf_apply_reloc(dbg, ed->ed_alloc, rel,
			    symtab_data, eh.e_ident[EI_DATA]);

			return (DW_DLE_NONE);
		}
	}
	elferr = elf_errno();
	if (elferr != 0) {
		DWARF_SET_ELF_ERROR(dbg, error);
		return (DW_DLE_ELF);
	}

	return (DW_DLE_NONE);
}
コード例 #3
0
int
_dwarf_elf_init(Dwarf_Debug dbg, Elf *elf, Dwarf_Error *error)
{
	Dwarf_Obj_Access_Interface *iface;
	Dwarf_Elf_Object *e;
	const char *name;
	GElf_Shdr sh;
	Elf_Scn *scn;
	Elf_Data *symtab_data;
	size_t symtab_ndx;
	int elferr, i, j, n, ret;

	ret = DW_DLE_NONE;

	if ((iface = calloc(1, sizeof(*iface))) == NULL) {
		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
		return (DW_DLE_MEMORY);
	}

	if ((e = calloc(1, sizeof(*e))) == NULL) {
		free(iface);
		DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY);
		return (DW_DLE_MEMORY);
	}

	e->eo_elf = elf;
	e->eo_methods.get_section_info = _dwarf_elf_get_section_info;
	e->eo_methods.get_byte_order = _dwarf_elf_get_byte_order;
	e->eo_methods.get_length_size = _dwarf_elf_get_length_size;
	e->eo_methods.get_pointer_size = _dwarf_elf_get_pointer_size;
	e->eo_methods.get_section_count = _dwarf_elf_get_section_count;
	e->eo_methods.load_section = _dwarf_elf_load_section;

	iface->object = e;
	iface->methods = &e->eo_methods;

	dbg->dbg_iface = iface;

	if (gelf_getehdr(elf, &e->eo_ehdr) == NULL) {
		DWARF_SET_ELF_ERROR(dbg, error);
		ret = DW_DLE_ELF;
		goto fail_cleanup;
	}

	dbg->dbg_machine = e->eo_ehdr.e_machine;

	if (!elf_getshstrndx(elf, &e->eo_strndx)) {
		DWARF_SET_ELF_ERROR(dbg, error);
		ret = DW_DLE_ELF;
		goto fail_cleanup;
	}

	n = 0;
	symtab_ndx = 0;
	symtab_data = NULL;
	scn = NULL;
	(void) elf_errno();
	while ((scn = elf_nextscn(elf, scn)) != NULL) {
		if (gelf_getshdr(scn, &sh) == NULL) {
			DWARF_SET_ELF_ERROR(dbg, error);
			ret = DW_DLE_ELF;
			goto fail_cleanup;
		}

		if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) ==
		    NULL) {
			DWARF_SET_ELF_ERROR(dbg, error);
			ret = DW_DLE_ELF;
			goto fail_cleanup;
		}

		if (!strcmp(name, ".symtab")) {
			symtab_ndx = elf_ndxscn(scn);
			if ((symtab_data = elf_getdata(scn, NULL)) == NULL) {
				elferr = elf_errno();
				if (elferr != 0) {
					_DWARF_SET_ERROR(NULL, error,
					    DW_DLE_ELF, elferr);
					ret = DW_DLE_ELF;
					goto fail_cleanup;
				}
			}
			continue;
		}

		for (i = 0; debug_name[i] != NULL; i++) {
			if (!strcmp(name, debug_name[i]))
				n++;
		}
	}
	elferr = elf_errno();
	if (elferr != 0) {
		DWARF_SET_ELF_ERROR(dbg, error);
		return (DW_DLE_ELF);
	}

	e->eo_seccnt = n;

	if (n == 0)
		return (DW_DLE_NONE);

	if ((e->eo_data = calloc(n, sizeof(Dwarf_Elf_Data))) == NULL ||
	    (e->eo_shdr = calloc(n, sizeof(GElf_Shdr))) == NULL) {
		DWARF_SET_ERROR(NULL, error, DW_DLE_MEMORY);
		ret = DW_DLE_MEMORY;
		goto fail_cleanup;
	}

	scn = NULL;
	j = 0;
	while ((scn = elf_nextscn(elf, scn)) != NULL && j < n) {
		if (gelf_getshdr(scn, &sh) == NULL) {
			DWARF_SET_ELF_ERROR(dbg, error);
			ret = DW_DLE_ELF;
			goto fail_cleanup;
		}

		memcpy(&e->eo_shdr[j], &sh, sizeof(sh));

		if ((name = elf_strptr(elf, e->eo_strndx, sh.sh_name)) ==
		    NULL) {
			DWARF_SET_ELF_ERROR(dbg, error);
			ret = DW_DLE_ELF;
			goto fail_cleanup;
		}

		for (i = 0; debug_name[i] != NULL; i++) {
			if (strcmp(name, debug_name[i]))
				continue;

			(void) elf_errno();
			if ((e->eo_data[j].ed_data = elf_getdata(scn, NULL)) ==
			    NULL) {
				elferr = elf_errno();
				if (elferr != 0) {
					_DWARF_SET_ERROR(dbg, error,
					    DW_DLE_ELF, elferr);
					ret = DW_DLE_ELF;
					goto fail_cleanup;
				}
			}

			if (_libdwarf.applyrela) {
				if (_dwarf_elf_relocate(dbg, elf,
				    &e->eo_data[j], elf_ndxscn(scn), symtab_ndx,
				    symtab_data, error) != DW_DLE_NONE)
					goto fail_cleanup;
			}

			j++;
		}
	}

	assert(j == n);

	return (DW_DLE_NONE);

fail_cleanup:

	_dwarf_elf_deinit(dbg);

	return (ret);
}