示例#1
0
static int section_match(const struct pt_section *lhs,
			 const struct pt_section *rhs)
{
	const char *lfilename, *rfilename;

	if (!lhs || !rhs)
		return -pte_internal;

	if (pt_section_offset(lhs) != pt_section_offset(rhs))
		return 0;

	if (pt_section_size(lhs) != pt_section_size(rhs))
		return 0;

	lfilename = pt_section_filename(lhs);
	rfilename = pt_section_filename(rhs);

	if (!lfilename || !rfilename)
		return -pte_internal;

	if (strcmp(lfilename, rfilename) != 0)
		return 0;

	return 1;
}
示例#2
0
int pt_section_clone(struct pt_section **pclone,
		     const struct pt_section *section, uint64_t offset,
		     uint64_t size)
{
	struct pt_section *clone;
	uint64_t begin, end, sbegin, send;

	if (!pclone || !section)
		return -pte_internal;

	begin = offset;
	end = begin + size;

	sbegin = pt_section_offset(section);
	send = sbegin + pt_section_size(section);

	if (begin < sbegin || send < end)
		return -pte_internal;

	clone = pt_mk_section(pt_section_filename(section), offset, size);
	if (!clone)
		return -pte_nomem;

	*pclone = clone;
	return 0;
}
示例#3
0
int pt_image_remove_by_name(struct pt_image *image, const char *name)
{
	struct pt_section_list **list;
	int removed;

	if (!image || !name)
		return -pte_invalid;

	removed = 0;
	for (list = &image->sections; *list;) {
		struct pt_section_list *trash;
		struct pt_section *section;
		const char *tname;

		trash = *list;
		section = trash->section;
		tname = pt_section_filename(section);

		if (tname && (strcmp(tname, name) == 0)) {
			if (image->cache == section)
				image->cache = NULL;

			*list = trash->next;
			pt_section_list_free(trash);

			removed += 1;
		} else
			list = &trash->next;
	}

	return removed;
}
示例#4
0
static struct ptunit_result filename_null(void)
{
	const char *name;

	name = pt_section_filename(NULL);
	ptu_null(name);

	return ptu_passed();
}
示例#5
0
int pt_image_remove_by_filename(struct pt_image *image, const char *filename,
				const struct pt_asid *uasid)
{
	struct pt_section_list **list;
	struct pt_asid asid;
	int errcode, removed;

	if (!image || !filename)
		return -pte_invalid;

	errcode = pt_asid_from_user(&asid, uasid);
	if (errcode < 0)
		return errcode;

	removed = 0;
	for (list = &image->sections; *list;) {
		struct pt_mapped_section *msec;
		const struct pt_section *sec;
		const struct pt_asid *masid;
		struct pt_section_list *trash;
		const char *tname;

		trash = *list;
		msec = &trash->section;
		masid = pt_msec_asid(msec);

		errcode = pt_asid_match(masid, &asid);
		if (errcode < 0)
			return errcode;

		if (!errcode) {
			list = &trash->next;
			continue;
		}

		sec = pt_msec_section(msec);
		tname = pt_section_filename(sec);

		if (tname && (strcmp(tname, filename) == 0)) {
			*list = trash->next;
			pt_section_list_free(trash);

			removed += 1;
		} else
			list = &trash->next;
	}

	return removed;
}
示例#6
0
static int pt_iscache_find_locked(struct pt_image_section_cache *iscache,
				  const char *filename, uint64_t offset,
				  uint64_t size, uint64_t laddr)
{
	uint16_t idx, end;

	if (!iscache || !filename)
		return -pte_internal;

	end = iscache->size;
	for (idx = 0; idx < end; ++idx) {
		const struct pt_iscache_entry *entry;
		const struct pt_section *section;
		const char *sec_filename;
		uint64_t sec_offset, sec_size;

		entry = &iscache->entries[idx];

		/* We do not zero-initialize the array - a NULL check is
		 * pointless.
		 */
		section = entry->section;
		sec_filename = pt_section_filename(section);
		sec_offset = pt_section_offset(section);
		sec_size = pt_section_size(section);

		if (entry->laddr != laddr)
			continue;

		if (sec_offset != offset)
			continue;

		if (sec_size != size)
			continue;

		/* We should not have a section without a filename. */
		if (!sec_filename)
			return -pte_internal;

		if (strcmp(sec_filename, filename) != 0)
			continue;

		return isid_from_index(idx);
	}

	return 0;
}
示例#7
0
static struct ptunit_result create(struct section_fixture *sfix)
{
	const char *name;
	uint8_t bytes[] = { 0xcc, 0xcc, 0xcc, 0xcc, 0xcc };
	uint64_t size;

	sfix_write(sfix, bytes);

	sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull);
	ptu_ptr(sfix->section);

	name = pt_section_filename(sfix->section);
	ptu_str_eq(name, sfix->name);

	size = pt_section_size(sfix->section);
	ptu_uint_eq(size, 0x3ull);

	return ptu_passed();
}
示例#8
0
int pt_image_add(struct pt_image *image, struct pt_section *section,
		 const struct pt_asid *asid, uint64_t vaddr, int isid)
{
	struct pt_section_list **list, *next, *removed;
	uint64_t begin, end;
	int errcode;

	if (!image || !section)
		return -pte_internal;

	next = pt_mk_section_list(section, asid, vaddr, isid);
	if (!next)
		return -pte_nomem;

	removed = NULL;
	errcode = 0;

	begin = vaddr;
	end = begin + pt_section_size(section);

	/* Check for overlaps while we move to the end of the list. */
	list = &(image->sections);
	while (*list) {
		const struct pt_mapped_section *msec;
		const struct pt_asid *masid;
		struct pt_section_list *current;
		struct pt_section *lsec;
		uint64_t lbegin, lend;

		current = *list;
		msec = &current->section;
		masid = pt_msec_asid(msec);

		errcode = pt_asid_match(masid, asid);
		if (errcode < 0)
			break;

		if (!errcode) {
			list = &((*list)->next);
			continue;
		}

		lbegin = pt_msec_begin(msec);
		lend = pt_msec_end(msec);

		if ((end <= lbegin) || (lend <= begin)) {
			list = &((*list)->next);
			continue;
		}

		/* The new section overlaps with @msec's section. */
		lsec = pt_msec_section(msec);

		/* Let's check for an identical overlap that may be the result
		 * of repeatedly copying images or repeatedly adding the same
		 * file.
		 */
		if ((begin == lbegin) && (end == lend) &&
		    (isid == current->isid)) {
			const char *fname, *lfname;

			fname = pt_section_filename(section);
			lfname = pt_section_filename(lsec);

			if (!fname || !lfname) {
				errcode = -pte_internal;
				break;
			}

			if (strcmp(fname, lfname) == 0) {
				/* There should not have been any removals or
				 * additions.
				 */
				if (removed || next->next) {
					errcode = -pte_internal;
					break;
				}

				pt_section_list_free(next);
				return 0;
			}
		}

		/* We remove @msec and insert new sections for the remaining
		 * parts, if any.  Those new sections are not mapped initially
		 * and need to be added to the end of the section list.
		 */
		*list = current->next;

		/* Keep a list of removed sections so we can re-add them in case
		 * of errors.
		 */
		current->next = removed;
		removed = current;

		/* Unmap the removed section.  If we need to re-add it, it will
		 * be moved to the end of the section list where the unmapped
		 * sections are.
		 */
		if (current->mapped) {
			pt_section_unmap(lsec);
			current->mapped = 0;
		}

		/* Add a section covering the remaining bytes at the front.
		 *
		 * We preserve the section identifier to indicate that the new
		 * section originated from the original section.
		 */
		if (lbegin < begin) {
			errcode = pt_image_clone(&next, msec, lbegin, begin,
						 current->isid);
			if (errcode < 0)
				break;
		}

		/* Add a section covering the remaining bytes at the back.
		 *
		 * We preserve the section identifier to indicate that the new
		 * section originated from the original section.
		 */
		if (end < lend) {
			errcode = pt_image_clone(&next, msec, end, lend,
						 current->isid);
			if (errcode < 0)
				break;
		}
	}

	if (errcode < 0) {
		pt_section_list_free_tail(next);

		/* Re-add removed sections to the tail of the section list. */
		for (; *list; list = &((*list)->next))
			;

		*list = removed;
		return errcode;
	}

	pt_section_list_free_tail(removed);

	*list = next;
	return 0;
}
示例#9
0
int pt_iscache_add(struct pt_image_section_cache *iscache,
		   struct pt_section *section, uint64_t laddr)
{
	uint16_t idx, end;
	int errcode;

	if (!iscache || !section)
		return -pte_internal;

	/* We must have a filename for @section. */
	if (!pt_section_filename(section))
		return -pte_internal;

	errcode = pt_iscache_lock(iscache);
	if (errcode < 0)
		return errcode;

	end = iscache->size;
	for (idx = 0; idx < end; ++idx) {
		const struct pt_iscache_entry *entry;
		struct pt_section *sec;

		entry = &iscache->entries[idx];

		/* We do not zero-initialize the array - a NULL check is
		 * pointless.
		 */
		sec = entry->section;

		errcode = section_match(section, sec);
		if (errcode <= 0) {
			if (errcode < 0)
				goto out_unlock;

			continue;
		}

		/* Use the cached section instead of the argument section.
		 *
		 * We'll be able to drop the argument section in this case and
		 * only keep one copy around and, more importantly, mapped.
		 */
		section = sec;

		/* If we also find a matching load address, we're done. */
		if (laddr == entry->laddr)
			break;
	}

	/* If we have not found a matching entry, add one. */
	if (idx == end) {
		struct pt_iscache_entry *entry;

		/* Expand the cache, if necessary. */
		if (iscache->capacity <= iscache->size) {
			/* We must never exceed the capacity. */
			if (iscache->capacity < iscache->size) {
				errcode = -pte_internal;
				goto out_unlock;
			}

			errcode = pt_iscache_expand(iscache);
			if (errcode < 0)
				goto out_unlock;

			/* Make sure it is big enough, now. */
			if (iscache->capacity <= iscache->size) {
				errcode = -pte_internal;
				goto out_unlock;
			}
		}

		errcode = pt_section_get(section);
		if (errcode < 0)
			goto out_unlock;

		idx = iscache->size++;

		entry = &iscache->entries[idx];
		entry->section = section;
		entry->laddr = laddr;
	}

	errcode = pt_iscache_unlock(iscache);
	if (errcode < 0)
		return errcode;

	return isid_from_index(idx);

 out_unlock:
	(void) pt_iscache_unlock(iscache);
	return errcode;
}