static struct pt_section_list *pt_mk_section_list(struct pt_section *section, const struct pt_asid *asid, uint64_t vaddr, int isid) { struct pt_section_list *list; int errcode; list = malloc(sizeof(*list)); if (!list) return NULL; memset(list, 0, sizeof(*list)); errcode = pt_section_get(section); if (errcode < 0) goto out_mem; pt_msec_init(&list->section, section, asid, vaddr); list->isid = isid; return list; out_mem: free(list); return NULL; }
static struct ptunit_result get_null(void) { int errcode; errcode = pt_section_get(NULL); ptu_int_eq(errcode, -pte_internal); return ptu_passed(); }
static struct ptunit_result get_put(struct section_fixture *sfix) { uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; int errcode; sfix_write(sfix, bytes); sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); ptu_ptr(sfix->section); errcode = pt_section_get(sfix->section); ptu_int_eq(errcode, 0); errcode = pt_section_get(sfix->section); ptu_int_eq(errcode, 0); errcode = pt_section_put(sfix->section); ptu_int_eq(errcode, 0); errcode = pt_section_put(sfix->section); ptu_int_eq(errcode, 0); return ptu_passed(); }
static int worker(void *arg) { struct section_fixture *sfix; int it, errcode; sfix = arg; if (!sfix) return -pte_internal; for (it = 0; it < num_work; ++it) { uint8_t buffer[] = { 0xcc, 0xcc, 0xcc }; int read; errcode = pt_section_get(sfix->section); if (errcode < 0) return errcode; errcode = pt_section_map(sfix->section); if (errcode < 0) goto out_put; read = pt_section_read(sfix->section, buffer, 2, 0x0ull); if (read < 0) goto out_unmap; errcode = -pte_invalid; if ((read != 2) || (buffer[0] != 0x2) || (buffer[1] != 0x4)) goto out_unmap; errcode = pt_section_unmap(sfix->section); if (errcode < 0) goto out_put; errcode = pt_section_put(sfix->section); if (errcode < 0) return errcode; } return 0; out_unmap: (void) pt_section_unmap(sfix->section); out_put: (void) pt_section_put(sfix->section); return errcode; }
static struct ptunit_result get_overflow(struct section_fixture *sfix) { uint8_t bytes[] = { 0xcc, 0x2, 0x4, 0x6 }; int errcode; sfix_write(sfix, bytes); sfix->section = pt_mk_section(sfix->name, 0x1ull, 0x3ull); ptu_ptr(sfix->section); sfix->section->ucount = UINT16_MAX; errcode = pt_section_get(sfix->section); ptu_int_eq(errcode, -pte_internal); sfix->section->ucount = 1; return ptu_passed(); }
int pt_iscache_lookup(struct pt_image_section_cache *iscache, struct pt_section **section, uint64_t *laddr, int isid) { uint16_t index; int errcode, status; if (!iscache || !section || !laddr) return -pte_internal; if (isid <= 0) return -pte_bad_image; isid -= 1; if (isid > UINT16_MAX) return -pte_internal; index = (uint16_t) isid; errcode = pt_iscache_lock(iscache); if (errcode < 0) return errcode; if (iscache->size <= index) status = -pte_bad_image; else { const struct pt_iscache_entry *entry; entry = &iscache->entries[index]; *section = entry->section; *laddr = entry->laddr; status = pt_section_get(*section); } errcode = pt_iscache_unlock(iscache); if (errcode < 0) return errcode; return status; }
int pt_image_find(struct pt_image *image, struct pt_section **psection, uint64_t *laddr, const struct pt_asid *asid, uint64_t vaddr) { struct pt_mapped_section *msec; struct pt_section_list *slist; struct pt_section *section; int errcode; if (!image || !psection || !laddr) return -pte_internal; slist = image->sections; if (!slist) return -pte_nomap; if (!slist->mapped) return pt_image_find_cold(image, psection, laddr, asid, vaddr); msec = &slist->section; errcode = pt_image_check_msec(msec, asid, vaddr); if (errcode < 0) { if (errcode != -pte_nomap) return errcode; return pt_image_find_cold(image, psection, laddr, asid, vaddr); } section = pt_msec_section(msec); errcode = pt_section_get(section); if (errcode < 0) return errcode; *psection = section; *laddr = pt_msec_begin(msec); return slist->isid; }
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; }