static int parse_vmstructs(jvm_agent_t* J) { VMStructEntry vmVar; VMStructEntry* vmp = &vmVar; uint64_t gHotSpotVMStructs; psaddr_t sym_addr; uint64_t base; int err; /* Clear *vmp now in case we jump to fail: */ memset(vmp, 0, sizeof(VMStructEntry)); err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr); CHECK_FAIL(err); err = read_pointer(J, sym_addr, &gHotSpotVMStructs); CHECK_FAIL(err); base = gHotSpotVMStructs; err = PS_OK; while (err == PS_OK) { memset(vmp, 0, sizeof(VMStructEntry)); err = parse_vmstruct_entry(J, base, vmp); if (err != PS_OK || vmp->typeName == NULL) { break; } if (vmp->typeName[0] == 'C' && strcmp("CodeCache", vmp->typeName) == 0) { /* Read _heaps field of type GrowableArray<CodeHeaps*>* */ if (strcmp("_heaps", vmp->fieldName) == 0) { err = read_pointer(J, vmp->address, &J->CodeCache_heaps_address); } } else if (vmp->typeName[0] == 'U' && strcmp("Universe", vmp->typeName) == 0) { if (strcmp("_narrow_oop._base", vmp->fieldName) == 0) { J->Universe_narrow_oop_base_address = vmp->address; } if (strcmp("_narrow_oop._shift", vmp->fieldName) == 0) { J->Universe_narrow_oop_shift_address = vmp->address; } } CHECK_FAIL(err); base += SIZE_VMStructEntry; if (vmp->typeName != NULL) free((void*)vmp->typeName); if (vmp->fieldName != NULL) free((void*)vmp->fieldName); } return PS_OK; fail: if (vmp->typeName != NULL) free((void*)vmp->typeName); if (vmp->fieldName != NULL) free((void*)vmp->fieldName); return -1; }
static int is_method(jvm_agent_t* J, uint64_t methodPtr) { uint64_t klass; int err = read_pointer(J, methodPtr, &klass); if (err != PS_OK) goto fail; return klass == J->Method_vtbl; fail: return 0; }
/* t = m_pos0 + (now - m_t0) * m_Tf */ int64_t TimeInterpolator::get_stream_usecs() { int64_t now; double dt; int64_t t_media; m_mutex.lock(); now = get_system_usecs(); if (m_state == PAUSED) { t_media = m_pos0; goto end; } dt = m_Tf * double(now - m_t0); if (dt < 0.0) dt = 0.0; t_media = m_pos0 + int64_t(dt); if (t_media < m_last) { ALOGW("time is rewinding: %lld Tf=%g t0=%lld pos0=%lld dt=%g " "now=%lld last=%lld now_last=%lld", t_media - m_last, m_Tf, m_t0, m_pos0, dt, now, m_last, m_now_last); } if (t_media >= read_pointer()) { if (m_state == ROLLING) { t_media = read_pointer(); ALOGE("UNDERRUN in %s", __func__); err_underrun(); } } m_last = t_media; m_now_last = now; end: /* t_media += m_latency; */ m_mutex.unlock(); ALOGV("%s == %lld (t0=%lld, pos0=%lld, Tf=%g, read=%lld, queued=%lld " "latency=%lld now=%lld, ", __func__, t_media, m_t0, m_pos0, m_Tf, m_read, m_queued, m_latency, now); return t_media; }
static void read_field(FILE *f, const save_field_t *field, void *base) { void *p = (byte *)base + field->ofs; int i; switch (field->type) { case F_BYTE: read_data(p, field->size, f); break; case F_SHORT: for (i = 0; i < field->size; i++) { ((short *)p)[i] = read_short(f); } break; case F_INT: for (i = 0; i < field->size; i++) { ((int *)p)[i] = read_int(f); } break; case F_FLOAT: for (i = 0; i < field->size; i++) { ((float *)p)[i] = read_float(f); } break; case F_VECTOR: read_vector(f, (vec_t *)p); break; case F_LSTRING: *(char **)p = read_string(f); break; case F_ZSTRING: read_zstring(f, (char *)p, field->size); break; case F_EDICT: *(edict_t **)p = read_index(f, sizeof(edict_t), g_edicts, game.maxentities - 1); break; case F_CLIENT: *(gclient_t **)p = read_index(f, sizeof(gclient_t), game.clients, game.maxclients - 1); break; case F_ITEM: *(gitem_t **)p = read_index(f, sizeof(gitem_t), itemlist, game.num_items - 1); break; case F_POINTER: *(void **)p = read_pointer(f, field->size); break; default: gi.error("%s: unknown field type", __func__); } }
static int read_volatiles(jvm_agent_t* J) { uint64_t ptr; int err; err = find_symbol(J, "UseCompressedOops", &J->Use_Compressed_Oops_address); if (err == PS_OK) { err = ps_pread(J->P, J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t)); CHECK_FAIL(err); } else { J->Use_Compressed_Oops = 0; } err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base); CHECK_FAIL(err); err = ps_pread(J->P, J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t)); CHECK_FAIL(err); err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low, &J->CodeCache_low); CHECK_FAIL(err); err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high, &J->CodeCache_high); CHECK_FAIL(err); err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap + OFFSET_VirtualSpace_low, &J->CodeCache_segmap_low); CHECK_FAIL(err); err = read_pointer(J, J->CodeCache_heap_address + OFFSET_CodeHeap_segmap + OFFSET_VirtualSpace_high, &J->CodeCache_segmap_high); CHECK_FAIL(err); err = ps_pread(J->P, J->CodeCache_heap_address + OFFSET_CodeHeap_log2_segment_size, &J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment)); CHECK_FAIL(err); return PS_OK; fail: return err; }
static signed fde_pointer_type(const u32 *cie) { const u8 *ptr = (const u8 *)(cie + 2); unsigned version = *ptr; if (version != 1) return -1; /* unsupported */ if (*++ptr) { const char *aug; const u8 *end = (const u8 *)(cie + 1) + *cie; uleb128_t len; /* check if augmentation size is first (and thus present) */ if (*ptr != 'z') return -1; /* check if augmentation string is nul-terminated */ if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL) return -1; ++ptr; /* skip terminator */ get_uleb128(&ptr, end); /* skip code alignment */ get_sleb128(&ptr, end); /* skip data alignment */ /* skip return address column */ version <= 1 ? (void)++ptr : (void)get_uleb128(&ptr, end); len = get_uleb128(&ptr, end); /* augmentation length */ if (ptr + len < ptr || ptr + len > end) return -1; end = ptr + len; while (*++aug) { if (ptr >= end) return -1; switch(*aug) { case 'L': ++ptr; break; case 'P': { signed ptrType = *ptr++; if (!read_pointer(&ptr, end, ptrType) || ptr > end) return -1; } break; case 'R': return *ptr; default: return -1; } } } return DW_EH_PE_native|DW_EH_PE_abs; }
void mr_push_kp_range(char* buf, int pos, int bound, int end, couchfile_modify_result *dst) { DBG("Moving items %d - %d into result.\r\n", bound, end); int current = 0; ei_decode_list_header(buf, &pos, NULL); while(current < end) { if(current >= bound) { DBG(" .... %d\r\n", current); mr_push_pointerinfo(read_pointer(buf,pos), dst); } ei_skip_term(buf, &pos); current++; } }
static int read_string_pointer(jvm_agent_t* J, uint64_t base, const char ** stringp) { uint64_t ptr; int err; char buffer[1024]; *stringp = NULL; err = read_pointer(J, base, &ptr); CHECK_FAIL(err); if (ptr != 0) { err = read_string(J->P, buffer, sizeof(buffer), ptr); CHECK_FAIL(err); *stringp = strdup(buffer); } return PS_OK; fail: return err; }
static int parse_vmstruct_entry(jvm_agent_t* J, uint64_t base, VMStructEntry* vmp) { uint64_t ptr; int err; err = read_string_pointer(J, base + OFFSET_VMStructEntrytypeName, &vmp->typeName); CHECK_FAIL(err); err = read_string_pointer(J, base + OFFSET_VMStructEntryfieldName, &vmp->fieldName); CHECK_FAIL(err); err = read_pointer(J, base + OFFSET_VMStructEntryaddress, &vmp->address); CHECK_FAIL(err); return PS_OK; fail: if (vmp->typeName != NULL) free((void*)vmp->typeName); if (vmp->fieldName != NULL) free((void*)vmp->fieldName); return err; }
char *str_ulong_vec(struct supersect *ss, const unsigned long *const *datap, const unsigned long *sizep) { struct supersect *data_ss; const unsigned long *data = read_pointer(ss, (void *const *)datap, &data_ss); unsigned long size = read_num(ss, sizep); char *buf = NULL; size_t bufsize = 0; FILE *fp = open_memstream(&buf, &bufsize); fprintf(fp, "[ "); size_t i; for (i = 0; i < size; ++i) fprintf(fp, "%lx ", read_num(data_ss, &data[i])); fprintf(fp, "]"); fclose(fp); return buf; }
const char *str_ksplice_patch_type(struct supersect *ss, const struct ksplice_patch *kpatch) { const char *const *strp; struct supersect *data_ss; switch(kpatch->type) { case KSPLICE_PATCH_TEXT: return strprintf("text\n repladdr: %s", str_pointer (ss, (void *const *)&kpatch->repladdr)); case KSPLICE_PATCH_DATA: return strprintf("data\n size: %x", kpatch->size); case KSPLICE_PATCH_EXPORT: strp = read_pointer(ss, &kpatch->contents, &data_ss); return strprintf("export\n newname: %s", read_string(data_ss, strp)); default: return "unknown"; } }
static void * extract_cie_info (fde *f, struct cie_info *c) { void *p; int i; c->augmentation = get_cie (f)->augmentation; if (strcmp (c->augmentation, "") != 0 && strcmp (c->augmentation, "eh") != 0 && c->augmentation[0] != 'z') return 0; p = c->augmentation + strlen (c->augmentation) + 1; if (strcmp (c->augmentation, "eh") == 0) { c->eh_ptr = read_pointer (p); p += sizeof (void *); } else c->eh_ptr = 0; p = decode_uleb128 (p, &c->code_align); p = decode_sleb128 (p, &c->data_align); c->ra_regno = *(unsigned char *)p++; /* If the augmentation starts with 'z', we now see the length of the augmentation fields. */ if (c->augmentation[0] == 'z') { p = decode_uleb128 (p, &i); p += i; } return p; }
void show_ksplice_reloc(struct supersect *ss, const struct ksplice_reloc *kreloc) { struct supersect *khowto_ss; const struct ksplice_reloc_howto *khowto = read_pointer(ss, (void *const *)&kreloc->howto, &khowto_ss); printf(" blank_addr: %s size: %x\n" " type: %s\n" " symbol: %s\n" " insn_addend: %lx\n" " target_addend: %lx\n" " pcrel: %x dst_mask: %lx rightshift: %x signed_addend: %x\n" "\n", str_pointer(ss, (void *const *)&kreloc->blank_addr), read_num(khowto_ss, &khowto->size), str_howto_type(khowto), str_ksplice_symbolp(ss, &kreloc->symbol), read_num(ss, &kreloc->insn_addend), read_num(ss, &kreloc->target_addend), read_num(khowto_ss, &khowto->pcrel), read_num(khowto_ss, &khowto->dst_mask), read_num(khowto_ss, &khowto->rightshift), read_num(khowto_ss, &khowto->signed_addend)); }
static int read_volatiles(jvm_agent_t* J) { int i; uint64_t array_data; uint64_t code_heap_address; int err; err = find_symbol(J, "UseCompressedOops", &J->Use_Compressed_Oops_address); if (err == PS_OK) { err = ps_pread(J->P, J->Use_Compressed_Oops_address, &J->Use_Compressed_Oops, sizeof(uint8_t)); CHECK_FAIL(err); } else { J->Use_Compressed_Oops = 0; } err = read_pointer(J, J->Universe_narrow_oop_base_address, &J->Universe_narrow_oop_base); CHECK_FAIL(err); err = ps_pread(J->P, J->Universe_narrow_oop_shift_address, &J->Universe_narrow_oop_shift, sizeof(uint32_t)); CHECK_FAIL(err); /* CodeCache_heaps_address points to GrowableArray<CodeHeaps*>, read _data field pointing to the first entry of type CodeCache* in the array */ err = read_pointer(J, J->CodeCache_heaps_address + OFFSET_GrowableArray_CodeHeap_data, &array_data); /* Read _len field containing the number of code heaps */ err = ps_pread(J->P, J->CodeCache_heaps_address + OFFSET_GrowableArray_CodeHeap_len, &J->Number_of_heaps, sizeof(J->Number_of_heaps)); /* Allocate memory for heap configurations */ J->Heap_low = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t)); J->Heap_high = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t)); J->Heap_segmap_low = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t)); J->Heap_segmap_high = (uint64_t*)calloc(J->Number_of_heaps, sizeof(uint64_t)); /* Read code heap configurations */ for (i = 0; i < J->Number_of_heaps; ++i) { /* Read address of heap */ err = read_pointer(J, array_data, &code_heap_address); CHECK_FAIL(err); err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_low, &J->Heap_low[i]); CHECK_FAIL(err); err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_memory + OFFSET_VirtualSpace_high, &J->Heap_high[i]); CHECK_FAIL(err); err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_segmap + OFFSET_VirtualSpace_low, &J->Heap_segmap_low[i]); CHECK_FAIL(err); err = read_pointer(J, code_heap_address + OFFSET_CodeHeap_segmap + OFFSET_VirtualSpace_high, &J->Heap_segmap_high[i]); CHECK_FAIL(err); /* Increment pointer to next entry */ array_data = array_data + POINTER_SIZE; } err = ps_pread(J->P, code_heap_address + OFFSET_CodeHeap_log2_segment_size, &J->SIZE_CodeCache_log2_segment, sizeof(J->SIZE_CodeCache_log2_segment)); CHECK_FAIL(err); return PS_OK; fail: return err; }
static void _stp_filename_lookup(struct _stp_module *mod, char ** filename, uint8_t *dirsecp, uint8_t *enddirsecp, unsigned fileidx, int user, int compat_task) { uint8_t *linep = dirsecp; static char fullpath [MAXSTRINGLEN]; char *dirname_entry = NULL, *filename_entry = NULL; unsigned diridx = 0, i, j; // skip past the directory table in the debug_line info while (*linep != 0 && linep < enddirsecp) { char *entry = (char *) linep; uint8_t *endnamep = (uint8_t *) memchr (entry, '\0', (size_t) (enddirsecp-linep)); if (endnamep == NULL || (endnamep + 1) > enddirsecp) return; linep = endnamep + 1; } if ((char) linep[0] != '\0') return; ++linep; // at the filename table for (i = 1; *linep != 0 && linep < enddirsecp; ++i) { uint8_t *endnamep = NULL; filename_entry = (char *) linep; endnamep = (uint8_t *) memchr (filename_entry, '\0', (size_t) (enddirsecp-linep)); if (endnamep == NULL || (endnamep + 1) > enddirsecp) return; // move the line pointer past the file name. account for the null byte linep = endnamep + 1; // save the directory index diridx = read_pointer ((const uint8_t **) &linep, enddirsecp, DW_EH_PE_leb128, user, compat_task); if (linep > enddirsecp) return; if (i == fileidx) break; filename_entry = NULL; // modification time read_pointer ((const uint8_t **) &linep, enddirsecp, DW_EH_PE_leb128, user, compat_task); // length of a file read_pointer ((const uint8_t **) &linep, enddirsecp, DW_EH_PE_leb128, user, compat_task); // check that nothing went wrong with reading the ulebs if (linep > enddirsecp) return; } if (filename_entry == NULL) return; // return just the linenumber // if dirid == 0, it's the compilation directory. otherwise retrieve the // directory path if the file path was relative if (diridx != 0 && filename_entry[0] != '/') { linep = dirsecp; for (j = 1; *linep != 0 && linep < enddirsecp; j++) { uint8_t *endnamep = NULL; dirname_entry = (char *) linep; endnamep = (uint8_t *) memchr (dirname_entry, '\0', (size_t) (enddirsecp-linep)); if (endnamep == NULL || (endnamep + 1) > enddirsecp) return; if (j == diridx) break; dirname_entry = NULL; linep = endnamep + 1; } if (dirname_entry == NULL) return; } // bring it all together // the filename was the full path if (filename_entry[0] == '/') *filename = filename_entry; // relative filename, and the dir corresponds to the compilation dir else if (diridx == 0) { char *slash = strrchr (mod->path, '/'); strlcpy(fullpath, mod->path, (size_t) (2 + slash - mod->path)); strlcat(fullpath, filename_entry, MAXSTRINGLEN); *filename = fullpath; } // relative filename and a directory from the table in the debug line data else { strlcpy(fullpath, dirname_entry, MAXSTRINGLEN); strlcat(fullpath, "/", MAXSTRINGLEN); strlcat(fullpath, filename_entry, MAXSTRINGLEN); *filename = fullpath; } }
unsigned long _stp_linenumber_lookup(unsigned long addr, struct task_struct *task, char ** filename, int need_filename) { struct _stp_module *m; struct _stp_section *sec; const char *modname = NULL; uint8_t *linep, *enddatap; int compat_task = _stp_is_compat_task(); int user = (task ? 1 : 0); // the portion below is encased in this conditional because some of the functions // and constants needed are encased in a similar condition #ifdef STP_NEED_LINE_DATA if (addr == 0) return 0; if (task) { unsigned long vm_start = 0; unsigned long vm_end = 0; #ifdef CONFIG_COMPAT /* Handle 32bit signed values in 64bit longs, chop off top bits. */ if (test_tsk_thread_flag(task, TIF_32BIT)) addr &= ((compat_ulong_t) ~0); #endif m = _stp_umod_lookup(addr, task, &modname, &vm_start, &vm_end); } else m = _stp_kmod_sec_lookup(addr, &sec); if (m == NULL || m->debug_line == NULL) return 0; // if addr is a kernel address, it will need to be adjusted if (!task) { int i; unsigned long offset = 0; // have to factor in the load_offset of (specifically) the .text section for (i=0; i<m->num_sections; i++) if (!strcmp(m->sections[i].name, ".text")) { offset = (m->sections[i].static_addr - m->sections[i].sec_load_offset); break; } if (addr < offset) return 0; addr = addr - offset; } linep = m->debug_line; enddatap = m->debug_line + m->debug_line_len; while (linep < enddatap) { // similar to print_debug_line_section() in elfutils unsigned int length = 4, curr_file_idx = 1, prev_file_idx = 1; unsigned int skip_to_seq_end = 0, op_index = 0; uint64_t unit_length, hdr_length, curr_addr = 0; uint8_t *endunitp, *endhdrp, *dirsecp, *stdopcode_lens_secp; uint16_t version; uint8_t opcode_base, line_range, min_instr_len = 0, max_ops = 1; unsigned long curr_linenum = 1; int8_t line_base; long cumm_line_adv = 0; unit_length = (uint64_t) read_pointer ((const uint8_t **) &linep, enddatap, DW_EH_PE_data4, user, compat_task); if (unit_length == 0xffffffff) { if (unlikely (linep + 8 > enddatap)) return 0; unit_length = (uint64_t) read_pointer ((const uint8_t **) &linep, enddatap, DW_EH_PE_data8, user, compat_task); length = 8; } if (unit_length < (length + 2) || (linep + unit_length) > enddatap) return 0; endunitp = linep + unit_length; version = read_pointer ((const uint8_t **) &linep, endunitp, DW_EH_PE_data2, user, compat_task); if (length == 4) hdr_length = (uint64_t) read_pointer ((const uint8_t **) &linep, endunitp, DW_EH_PE_data4, user, compat_task); else hdr_length = (uint64_t) read_pointer ((const uint8_t **) &linep, endunitp, DW_EH_PE_data8, user, compat_task); if ((linep + hdr_length) > endunitp || hdr_length < (version >= 4 ? 6 : 5)) return 0; endhdrp = linep + hdr_length; // minimum instruction length min_instr_len = *linep++; // max operations per instruction if (version >= 4) { max_ops = *linep++; if (max_ops == 0) return 0; // max operations per instruction is supposed to > 0; } // default value of the is_stmt register ++linep; // line base. this is a signed value. line_base = *linep++; // line range line_range = *linep++; if (line_range == 0) return 0; // opcode base opcode_base = *linep++; // opcodes stdopcode_lens_secp = linep - 1; // need this check if the header length check covers this region? if ((linep + opcode_base - 1) >= endhdrp) return 0; linep += opcode_base - 1; // at the directory table. don't need an other information from the header // in order to find the desired line number, so we will save a pointer to // this point and skip ahead to the end of the header. this portion of the // header will be visited again after a line number has been found if a // filename is needed. dirsecp = linep; linep = endhdrp; // iterating through the opcodes. will deal with three defined types of // opcode: special, extended and standard. there is also a portion at // the end of this loop that will deal with unknown (standard) opcodes. while (linep < endunitp) { uint8_t opcode = *linep++; long addr_adv = 0; if (opcode >= opcode_base) // special opcode { // line range was checked before this point. this variable is not altered after it is initialized. cumm_line_adv += (line_base + ((opcode - opcode_base) % line_range)); addr_adv = ((opcode - opcode_base) / line_range); } else if (opcode == 0) // extended opcode { int len; uint8_t subopcode; if (linep + 1 > endunitp) return 0; len = *linep++; if (linep + len > endunitp || len < 1) return 0; subopcode = *linep++; // the sub opcode switch (subopcode) { case DW_LNE_end_sequence: // reset the line and address. cumm_line_adv = 1 - curr_linenum; addr_adv = 0 - curr_addr; skip_to_seq_end = 0; op_index = 0; break; case DW_LNE_set_address: if ((len - 1) == 4) // account for the opcode (the -1) curr_addr = (uint64_t) read_pointer ((const uint8_t **) &linep, endunitp, DW_EH_PE_data4, user, compat_task); else if ((len - 1) == 8) curr_addr = (uint64_t) read_pointer ((const uint8_t **) &linep, endunitp, DW_EH_PE_data8, user, compat_task); else return 0; // if the set address is past the address we want, iterate // to the end of the sequence without doing more address // and linenumber calcs than necessary if (curr_addr > addr) skip_to_seq_end = 1; op_index = 0; break; default: // advance the ptr by the specified amount linep += len-1; break; } } else if (opcode <= DW_LNS_set_isa) // known standard opcode { uint8_t *linep_before = linep; switch (opcode) { case DW_LNS_advance_pc: addr_adv = read_pointer ((const uint8_t **) &linep, endunitp, DW_EH_PE_leb128, user, compat_task); break; case DW_LNS_fixed_advance_pc: addr_adv = read_pointer ((const uint8_t **) &linep, endunitp, DW_EH_PE_data2, user, compat_task); if (linep_before == linep) // the read failed return 0; op_index = 0; break; case DW_LNS_advance_line: cumm_line_adv += read_pointer ((const uint8_t **) &linep, endunitp, DW_EH_PE_leb128+DW_EH_PE_signed, user, compat_task); break; case DW_LNS_set_file: curr_file_idx = read_pointer ((const uint8_t **) &linep, endunitp, DW_EH_PE_leb128, user, compat_task); break; case DW_LNS_set_column: read_pointer ((const uint8_t **) &linep, endunitp, DW_EH_PE_leb128, user, compat_task); break; case DW_LNS_const_add_pc: addr_adv = ((255 - opcode_base) / line_range); break; case DW_LNS_set_isa: read_pointer ((const uint8_t **) &linep, endunitp, DW_EH_PE_leb128, user, compat_task); break; } if (linep > endunitp) // reading in the leb128 failed return 0; } else { int i; for (i=stdopcode_lens_secp[opcode]; i>0; --i) { read_pointer ((const uint8_t **) &linep, endunitp, DW_EH_PE_leb128, user, compat_task); if (linep > endunitp) return 0; } } // don't worry about doing line/address advances since we are waiting // till we hit the end of the sequence or the end of the unit at which // point the address and linenumber will be reset if (skip_to_seq_end == 1) continue; // calculate actual address advance if (opcode != 0 && opcode != DW_LNS_fixed_advance_pc) { addr_adv = min_instr_len * (op_index + addr_adv) / max_ops; op_index = (op_index + addr_adv) % max_ops; } // found an address that at least sort of matches the address we // were looking for if ((curr_addr <= addr && addr < (curr_addr + addr_adv)) || (curr_addr == addr && addr_adv != 0)) { if (need_filename) _stp_filename_lookup(m, filename, dirsecp, endhdrp, prev_file_idx, user, compat_task); return curr_linenum; } // update the linenumber and file index if the curr_addr is to be updated if (addr_adv != 0) { prev_file_idx = curr_file_idx; } if (prev_file_idx == curr_file_idx) { curr_linenum += cumm_line_adv; cumm_line_adv = 0; } curr_addr += addr_adv; } } #endif /* STP_NEED_LINE_DATA */ // no linenumber was found otherwise this function would have returned before this point return 0; }
uint32_t* read_uintptr(char *id) { return((uint32_t*) read_pointer(id)); }
static couchstore_error_t modify_node(couchfile_modify_request *rq, node_pointer *nptr, int start, int end, couchfile_modify_result *dst) { char *nodebuf = NULL; // FYI, nodebuf is a malloced block, not in the arena int bufpos = 1; int nodebuflen = 0; int errcode = 0; couchfile_modify_result *local_result = NULL; if (start == end) { return 0; } if (nptr) { if ((nodebuflen = pread_compressed(rq->db, nptr->pointer, (char **) &nodebuf)) < 0) { error_pass(COUCHSTORE_ERROR_READ); } } local_result = make_modres(dst->arena, rq); error_unless(local_result, COUCHSTORE_ERROR_ALLOC_FAIL); if (nptr == NULL || nodebuf[0] == 1) { //KV Node local_result->node_type = KV_NODE; while (bufpos < nodebuflen) { sized_buf cmp_key, val_buf; bufpos += read_kv(nodebuf + bufpos, &cmp_key, &val_buf); int advance = 0; while (!advance && start < end) { advance = 1; int cmp_val = rq->cmp.compare(&cmp_key, rq->actions[start].key); if (cmp_val < 0) { //Key less than action key mr_push_item(&cmp_key, &val_buf, local_result); } else if (cmp_val > 0) { //Key greater than action key switch (rq->actions[start].type) { case ACTION_INSERT: local_result->modified = 1; mr_push_item(rq->actions[start].key, rq->actions[start].value.data, local_result); break; case ACTION_REMOVE: local_result->modified = 1; break; case ACTION_FETCH: if (rq->fetch_callback) { //not found (*rq->fetch_callback)(rq, rq->actions[start].key, NULL, rq->actions[start].value.arg); } } start++; //Do next action on same item in the node, as our action was //not >= it. advance = 0; } else if (cmp_val == 0) { //Node key is equal to action key switch (rq->actions[start].type) { case ACTION_INSERT: local_result->modified = 1; mr_push_item(rq->actions[start].key, rq->actions[start].value.data, local_result); break; case ACTION_REMOVE: local_result->modified = 1; break; case ACTION_FETCH: if (rq->fetch_callback) { (*rq->fetch_callback)(rq, rq->actions[start].key, &val_buf, rq->actions[start].value.arg); } //Do next action on same item in the node, as our action was a fetch //and there may be an equivalent insert or remove //following. advance = 0; } start++; } } if (start == end && !advance) { //If we've exhausted actions then just keep this key mr_push_item(&cmp_key, &val_buf, local_result); } } while (start < end) { //We're at the end of a leaf node. switch (rq->actions[start].type) { case ACTION_INSERT: local_result->modified = 1; mr_push_item(rq->actions[start].key, rq->actions[start].value.data, local_result); break; case ACTION_REMOVE: local_result->modified = 1; break; case ACTION_FETCH: if (rq->fetch_callback) { //not found (*rq->fetch_callback)(rq, rq->actions[start].key, NULL, rq->actions[start].value.arg); } break; } start++; } } else if (nodebuf[0] == 0) { //KP Node local_result->node_type = KP_NODE; while (bufpos < nodebuflen && start < end) { sized_buf cmp_key, val_buf; bufpos += read_kv(nodebuf + bufpos, &cmp_key, &val_buf); int cmp_val = rq->cmp.compare(&cmp_key, rq->actions[start].key); if (bufpos == nodebuflen) { //We're at the last item in the kpnode, must apply all our //actions here. node_pointer *desc = read_pointer(dst->arena, &cmp_key, val_buf.buf); if (!desc) { errcode = COUCHSTORE_ERROR_ALLOC_FAIL; goto cleanup; } errcode = modify_node(rq, desc, start, end, local_result); if (errcode != COUCHSTORE_SUCCESS) { goto cleanup; } break; } if (cmp_val < 0) { //Key in node item less than action item and not at end //position, so just add it and continue. node_pointer *add = read_pointer(dst->arena, &cmp_key, val_buf.buf); if (!add) { errcode = COUCHSTORE_ERROR_ALLOC_FAIL; goto cleanup; } errcode = mr_push_pointerinfo(add, local_result); if (errcode != COUCHSTORE_SUCCESS) { goto cleanup; } } else if (cmp_val >= 0) { //Found a key in the node greater than the one in the current //action. Descend into the pointed node with as many actions as //are less than the key here. int range_end = start; while (range_end < end && rq->cmp.compare(rq->actions[range_end].key, &cmp_key) <= 0) { range_end++; } node_pointer *desc = read_pointer(dst->arena, &cmp_key, val_buf.buf); if (!desc) { errcode = COUCHSTORE_ERROR_ALLOC_FAIL; goto cleanup; } errcode = modify_node(rq, desc, start, range_end, local_result); start = range_end; if (errcode != COUCHSTORE_SUCCESS) { goto cleanup; } } } while (bufpos < nodebuflen) { sized_buf cmp_key, val_buf; bufpos += read_kv(nodebuf + bufpos, &cmp_key, &val_buf); node_pointer *add = read_pointer(dst->arena, &cmp_key, val_buf.buf); if (!add) { errcode = COUCHSTORE_ERROR_ALLOC_FAIL; goto cleanup; } errcode = mr_push_pointerinfo(add, local_result); if (errcode != COUCHSTORE_SUCCESS) { goto cleanup; } } } else { errcode = COUCHSTORE_ERROR_CORRUPT; goto cleanup; } //If we've done modifications, write out the last leaf node. error_pass(flush_mr(local_result)); if (!local_result->modified && nptr != NULL) { //If we didn't do anything, give back the pointer to the original mr_push_pointerinfo(nptr, dst); } else { //Otherwise, give back the pointers to the nodes we've created. dst->modified = 1; error_pass(mr_move_pointers(local_result, dst)); } cleanup: if (nodebuf) { free(nodebuf); } return errcode; }
static int name_for_methodPtr(jvm_agent_t* J, uint64_t methodPtr, char * result, size_t size) { short nameIndex; short signatureIndex; uint64_t constantPool; uint64_t constMethod; uint64_t nameSymbol; uint64_t signatureSymbol; uint64_t klassPtr; uint64_t klassSymbol; short klassSymbolLength; short nameSymbolLength; short signatureSymbolLength; char * nameString = NULL; char * klassString = NULL; char * signatureString = NULL; int err; err = read_pointer(J, methodPtr + OFFSET_Method_constMethod, &constMethod); CHECK_FAIL(err); err = read_pointer(J, constMethod + OFFSET_ConstMethod_constants, &constantPool); CHECK_FAIL(err); /* To get name string */ err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_name_index, &nameIndex, 2); CHECK_FAIL(err); err = read_pointer(J, constantPool + nameIndex * POINTER_SIZE + SIZE_ConstantPool, &nameSymbol); CHECK_FAIL(err); // The symbol is a CPSlot and has lower bit set to indicate metadata nameSymbol &= (~1); // remove metadata lsb err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_length, &nameSymbolLength, 2); CHECK_FAIL(err); nameString = (char*)calloc(nameSymbolLength + 1, 1); err = ps_pread(J->P, nameSymbol + OFFSET_Symbol_body, nameString, nameSymbolLength); CHECK_FAIL(err); /* To get signature string */ err = ps_pread(J->P, constMethod + OFFSET_ConstMethod_signature_index, &signatureIndex, 2); CHECK_FAIL(err); err = read_pointer(J, constantPool + signatureIndex * POINTER_SIZE + SIZE_ConstantPool, &signatureSymbol); CHECK_FAIL(err); signatureSymbol &= (~1); // remove metadata lsb err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_length, &signatureSymbolLength, 2); CHECK_FAIL(err); signatureString = (char*)calloc(signatureSymbolLength + 1, 1); err = ps_pread(J->P, signatureSymbol + OFFSET_Symbol_body, signatureString, signatureSymbolLength); CHECK_FAIL(err); /* To get klass string */ err = read_pointer(J, constantPool + OFFSET_ConstantPool_pool_holder, &klassPtr); CHECK_FAIL(err); err = read_pointer(J, klassPtr + OFFSET_Klass_name, &klassSymbol); CHECK_FAIL(err); err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_length, &klassSymbolLength, 2); CHECK_FAIL(err); klassString = (char*)calloc(klassSymbolLength + 1, 1); err = ps_pread(J->P, klassSymbol + OFFSET_Symbol_body, klassString, klassSymbolLength); CHECK_FAIL(err); result[0] = '\0'; if (snprintf(result, size, "%s.%s%s", klassString, nameString, signatureString) >= size) { // truncation goto fail; } if (nameString != NULL) free(nameString); if (klassString != NULL) free(klassString); if (signatureString != NULL) free(signatureString); return PS_OK; fail: if (debug) { fprintf(stderr, "name_for_methodPtr: FAIL \n\n"); } if (nameString != NULL) free(nameString); if (klassString != NULL) free(klassString); if (signatureString != NULL) free(signatureString); return -1; }
int modify_node(couchfile_modify_request *rq, couchfile_pointer_info *nptr, int start, int end, couchfile_modify_result *dst) { eterm_buf current_node; int curnode_pos = 0; int read_size = 0; int list_start_pos = 0; int node_len = 0; int node_bound = 0; int errcode = 0; int kpos = 0; char node_type[MAXATOMLEN + 1]; node_type[0] = 0; DBG("Enter modify_node. %d - %d\r\n", start, end); if(start == end) { return 0; } if(nptr == NULL) { current_node = empty_root; } else { if((read_size = pread_bin(rq->fd, nptr->pointer, ¤t_node.buf)) < 0) { return ERROR_READ_FILE; } current_node.size = read_size; DBG("... read node from %d\r\n", nptr->pointer); curnode_pos++; //Skip over 131. } couchfile_modify_result *local_result = make_modres(rq); ei_decode_tuple_header(current_node.buf, &curnode_pos, NULL); if(ei_decode_atom(current_node.buf, &curnode_pos, node_type) < 0) { errcode = ERROR_PARSE; goto cleanup; } list_start_pos = curnode_pos; if(ei_decode_list_header(current_node.buf, &curnode_pos, &node_len) < 0) { errcode = ERROR_PARSE; goto cleanup; } if(strcmp("kv_node", node_type) == 0) { local_result->node_type = KV_NODE; while(start < end) { DBG("act on kvnode item\r\n"); if(node_bound >= node_len) { //We're at the end of a leaf node. DBG(" ... exec action at end!\r\n"); switch(rq->actions[start].type) { case ACTION_INSERT: local_result->modified = 1; mr_push_action(&rq->actions[start], local_result); break; case ACTION_REMOVE: local_result->modified = 1; break; case ACTION_FETCH: if(rq->fetch_callback) { //not found (*rq->fetch_callback)(rq, rq->actions[start].key, NULL); } break; } start++; } else { kpos = find_first_gteq(current_node.buf, list_start_pos, rq->actions[start].cmp_key, &rq->cmp, node_bound); if(kpos < 0) { errcode = ERROR_PARSE; goto cleanup; } //Add items from node_bound up to but not including the current mr_push_kv_range(current_node.buf, list_start_pos, node_bound, rq->cmp.list_pos, local_result); if(rq->cmp.last_cmp_val > 0) // Node key > action key { DBG(" Inserting action before\r\n"); switch(rq->actions[start].type) { case ACTION_INSERT: local_result->modified = 1; mr_push_action(&rq->actions[start], local_result); break; case ACTION_REMOVE: local_result->modified = 1; break; case ACTION_FETCH: if(rq->fetch_callback) { //not found (*rq->fetch_callback)(rq, rq->actions[start].key, NULL); } break; } start++; node_bound = rq->cmp.list_pos; } else if(rq->cmp.last_cmp_val < 0) // Node key < action key { DBG(" -- Continue with this action\r\n"); node_bound = rq->cmp.list_pos + 1; mr_push_kv_range(current_node.buf, list_start_pos, node_bound - 1, node_bound, local_result); } else //Node key == action key { DBG(" Replacing value with action\r\n"); switch(rq->actions[start].type) { case ACTION_INSERT: local_result->modified = 1; mr_push_action(&rq->actions[start], local_result); node_bound = rq->cmp.list_pos + 1; break; case ACTION_REMOVE: local_result->modified = 1; node_bound = rq->cmp.list_pos + 1; break; case ACTION_FETCH: if(rq->fetch_callback) { eterm_buf cb_tmp; int cb_vpos = kpos; ei_decode_tuple_header(current_node.buf, &cb_vpos, NULL); ei_skip_term(current_node.buf, &cb_vpos); cb_tmp.buf = current_node.buf + cb_vpos; cb_tmp.size = cb_vpos; ei_skip_term(current_node.buf, &cb_vpos); cb_tmp.size = cb_vpos - cb_tmp.size; (*rq->fetch_callback)(rq, rq->actions[start].key, &cb_tmp); } node_bound = rq->cmp.list_pos; break; } start++; } } } //Push any items past the end of what we dealt with onto result. if(node_bound < node_len) { mr_push_kv_range(current_node.buf, list_start_pos, node_bound, node_len, local_result); } } else if(strcmp("kp_node", node_type) == 0) { local_result->node_type = KP_NODE; while(start < end) { kpos = find_first_gteq(current_node.buf, list_start_pos, rq->actions[start].cmp_key, &rq->cmp, node_bound); if(kpos < 0) { errcode = ERROR_PARSE; goto cleanup; } if(rq->cmp.list_pos == (node_len - 1)) //got last item in kp_node { //Push all items in node onto mr mr_push_kp_range(current_node.buf, list_start_pos, node_bound, rq->cmp.list_pos, local_result); DBG(" ...descending into final item of kpnode\r\n"); couchfile_pointer_info *desc = read_pointer(current_node.buf, kpos); errcode = modify_node(rq, desc, start, end, local_result); if(local_result->values_end->value.pointer != desc) { free(desc); } if(errcode < 0) { goto cleanup; } node_bound = node_len; break; } else { //Get all actions with key <= the key of the current item in the //kp_node //Push items in node up to but not including current onto mr mr_push_kp_range(current_node.buf, list_start_pos, node_bound, rq->cmp.list_pos - 1, local_result); int range_end = start; while(range_end < end && ((*rq->cmp.compare)(rq->actions[range_end].cmp_key, rq->cmp.last_cmp_key) <= 0)) { range_end++; } DBG(" ...descending into item %d of kpnode\r\n", rq->cmp.list_pos); node_bound = rq->cmp.list_pos + 1; couchfile_pointer_info *desc = read_pointer(current_node.buf, kpos); errcode = modify_node(rq, desc, start, range_end, local_result); if(local_result->values_end->value.pointer != desc) { free(desc); } if(errcode < 0) { goto cleanup; } start = range_end; } } DBG(".. Finished kp node, up to %d\r\n", node_bound); if(node_bound < node_len) { //Processed all the actions but haven't exhausted this kpnode. //push the rest of it onto the mr. mr_push_kp_range(current_node.buf, list_start_pos, node_bound, node_len, local_result); } } else { errcode = ERROR_PARSE; goto cleanup; } //If we've done modifications, write out the last leaf node. errcode = flush_mr(local_result); if(errcode == 0) { if(!local_result->modified && nptr != NULL) { //If we didn't do anything, give back the pointer to the original mr_push_pointerinfo(nptr, dst); } else { //Otherwise, give back the pointers to the nodes we've created. dst->modified = 1; errcode = mr_move_pointers(local_result, dst); } } cleanup: free_modres(local_result); if(current_node.buf != empty_root.buf) { free(current_node.buf); } return errcode; }
int start(void) #endif { int i; uint32_t apl; float ong; uint64_t apl64; uint16_t apl16; uint8_t apl8; void* ptr; double ong64; for (i = 0; i < 10; ++i) { apl64 = read_uint64("apples64"); #ifdef RUN fprintf(stderr, "\n(%d.a) got a 64 bit apple: %llu..", i, apl64); #endif ong64 = (double)apl64; write_float64("oranges64", ong64); #ifdef RUN fprintf(stderr, "\nsent a (double) orange: %le.", ong64); #endif apl = read_uint32("apples32"); #ifdef RUN fprintf(stderr, "\n(%d.b) got a 32-bit apple: %d.", i, apl); #endif ong = (float)apl; write_float32("oranges32", ong); #ifdef RUN fprintf(stderr, "\nsent a (float) orange: %f.", ong); #endif apl16 = read_uint16("apples16"); #ifdef RUN fprintf(stderr, "\n(%d.c) got a 16-bit apple: %d.", i, apl16); #endif apl8 = (uint8_t)apl; write_uint8("oranges8", apl8); #ifdef RUN fprintf(stderr, "\nsent an 8-bit orange: %d.", apl8); #endif ptr = read_pointer("apples32"); #ifdef RUN fprintf(stderr, "\n(%d.d) got a pointer apple: %d.", i, (unsigned int) ptr); #endif write_pointer("oranges32", ptr); #ifdef RUN fprintf(stderr, "\nsent a pointer orange: %d.", (unsigned int) ptr); #endif } #ifdef RUN fprintf(stderr, "\n"); #endif return 0; }
/* Unwind to previous to frame. Returns 0 if successful, negative * number in case of an error. */ int unwind(struct unwind_frame_info *frame, int is_ehframe) { #define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs]) const u32 *fde = NULL, *cie = NULL; const u8 *ptr = NULL, *end = NULL; unsigned long startLoc = 0, endLoc = 0, cfa; unsigned i; signed ptrType = -1; uleb128_t retAddrReg = 0; // struct unwind_table *table; void *unwind_table; struct local_unwind_table *table; struct unwind_state state; u64 reg_ptr = 0; if (UNW_PC(frame) == 0) return -EINVAL; if ((table = find_table(UNW_PC(frame)))) { // unsigned long tableSize = unwind_table_size; unsigned long tableSize = table->size; unwind_table = table->address; for (fde = unwind_table; tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde; tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) { if (!*fde || (*fde & (sizeof(*fde) - 1))) break; if (is_ehframe && !fde[1]) continue; /* this is a CIE */ else if (fde[1] == 0xffffffff) continue; /* this is a CIE */ if ((fde[1] & (sizeof(*fde) - 1)) || fde[1] > (unsigned long)(fde + 1) - (unsigned long)unwind_table) continue; /* this is not a valid FDE */ if (is_ehframe) cie = fde + 1 - fde[1] / sizeof(*fde); else cie = unwind_table + fde[1]; if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde) || (*cie & (sizeof(*cie) - 1)) || (cie[1] != 0xffffffff && cie[1]) || (ptrType = fde_pointer_type(cie)) < 0) { cie = NULL; /* this is not a (valid) CIE */ continue; } ptr = (const u8 *)(fde + 2); startLoc = read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, ptrType); endLoc = startLoc + read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, ptrType & DW_EH_PE_indirect ? ptrType : ptrType & (DW_EH_PE_FORM|DW_EH_PE_signed)); if (UNW_PC(frame) >= startLoc && UNW_PC(frame) < endLoc) break; cie = NULL; } } if (cie != NULL) { memset(&state, 0, sizeof(state)); state.cieEnd = ptr; /* keep here temporarily */ ptr = (const u8 *)(cie + 2); end = (const u8 *)(cie + 1) + *cie; if ((state.version = *ptr) != 1) cie = NULL; /* unsupported version */ else if (*++ptr) { /* check if augmentation size is first (and thus present) */ if (*ptr == 'z') { /* check for ignorable (or already handled) * nul-terminated augmentation string */ while (++ptr < end && *ptr) if (strchr("LPR", *ptr) == NULL) break; } if (ptr >= end || *ptr) cie = NULL; } ++ptr; } if (cie != NULL) { /* get code aligment factor */ state.codeAlign = get_uleb128(&ptr, end); /* get data aligment factor */ state.dataAlign = get_sleb128(&ptr, end); if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end) cie = NULL; else { retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end); /* skip augmentation */ if (((const char *)(cie + 2))[1] == 'z') ptr += get_uleb128(&ptr, end); if (ptr > end || retAddrReg >= ARRAY_SIZE(reg_info) || REG_INVALID(retAddrReg) || reg_info[retAddrReg].width != sizeof(unsigned long)) cie = NULL; } } if (cie != NULL) { state.cieStart = ptr; ptr = state.cieEnd; state.cieEnd = end; end = (const u8 *)(fde + 1) + *fde; /* skip augmentation */ if (((const char *)(cie + 2))[1] == 'z') { uleb128_t augSize = get_uleb128(&ptr, end); if ((ptr += augSize) > end) fde = NULL; } } if (cie == NULL || fde == NULL) return -ENXIO; state.org = startLoc; memcpy(&state.cfa, &badCFA, sizeof(state.cfa)); /* process instructions */ if (!processCFI(ptr, end, UNW_PC(frame), ptrType, &state) || state.loc > endLoc || state.regs[retAddrReg].where == Nowhere || state.cfa.reg >= ARRAY_SIZE(reg_info) || reg_info[state.cfa.reg].width != sizeof(unsigned long) || state.cfa.offs % sizeof(unsigned long)) { return -EIO; } /* update frame */ cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs; startLoc = min((unsigned long)UNW_SP(frame), cfa); endLoc = max((unsigned long)UNW_SP(frame), cfa); if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) { startLoc = min(STACK_LIMIT(cfa), cfa); endLoc = max(STACK_LIMIT(cfa), cfa); } #ifndef CONFIG_64BIT # define CASES CASE(8); CASE(16); CASE(32) #else # define CASES CASE(8); CASE(16); CASE(32); CASE(64) #endif for (i = 0; i < ARRAY_SIZE(state.regs); ++i) { if (REG_INVALID(i)) { if (state.regs[i].where == Nowhere) continue; return -EIO; } switch(state.regs[i].where) { default: break; case Register: if (state.regs[i].value >= ARRAY_SIZE(reg_info) || REG_INVALID(state.regs[i].value) || reg_info[i].width > reg_info[state.regs[i].value].width){ return -EIO; } switch(reg_info[state.regs[i].value].width) { #define CASE(n) \ case sizeof(u##n): \ state.regs[i].value = FRAME_REG(state.regs[i].value, \ const u##n); \ break CASES; #undef CASE default: return -EIO; } break; } } for (i = 0; i < ARRAY_SIZE(state.regs); ++i) { if (REG_INVALID(i)) continue; switch(state.regs[i].where) { case Nowhere: if (reg_info[i].width != sizeof(UNW_SP(frame)) || &FRAME_REG(i, __typeof__(UNW_SP(frame))) != &UNW_SP(frame)) continue; UNW_SP(frame) = cfa; break; case Register: switch(reg_info[i].width) { #define CASE(n) case sizeof(u##n): \ FRAME_REG(i, u##n) = state.regs[i].value; \ break CASES; #undef CASE default: return -EIO; } break; case Value: if (reg_info[i].width != sizeof(unsigned long)){ return -EIO;} FRAME_REG(i, unsigned long) = cfa + state.regs[i].value * state.dataAlign; break; case Memory: { unsigned long addr = cfa + state.regs[i].value * state.dataAlign; if ((state.regs[i].value * state.dataAlign) % sizeof(unsigned long) || addr < startLoc || addr + sizeof(unsigned long) < addr || addr + sizeof(unsigned long) > endLoc){ return -EIO;} switch(reg_info[i].width) { #define CASE(n) case sizeof(u##n): \ readmem(addr, KVADDR, ®_ptr,sizeof(u##n), "register", RETURN_ON_ERROR|QUIET); \ FRAME_REG(i, u##n) = (u##n)reg_ptr;\ break CASES; #undef CASE default: return -EIO; } } break; } } return 0; #undef CASES #undef FRAME_REG }
static void * execute_cfa_insn (void *p, struct frame_state_internal *state, struct cie_info *info, void **pc) { unsigned insn = *(unsigned char *)p++; unsigned reg; int offset; if (insn & DW_CFA_advance_loc) *pc += ((insn & 0x3f) * info->code_align); else if (insn & DW_CFA_offset) { reg = (insn & 0x3f); p = decode_uleb128 (p, &offset); offset *= info->data_align; state->s.saved[reg] = REG_SAVED_OFFSET; state->s.reg_or_offset[reg] = offset; } else if (insn & DW_CFA_restore) { reg = (insn & 0x3f); state->s.saved[reg] = REG_UNSAVED; } else switch (insn) { case DW_CFA_set_loc: *pc = read_pointer (p); p += sizeof (void *); break; case DW_CFA_advance_loc1: *pc += read_1byte (p); p += 1; break; case DW_CFA_advance_loc2: *pc += read_2byte (p); p += 2; break; case DW_CFA_advance_loc4: *pc += read_4byte (p); p += 4; break; case DW_CFA_offset_extended: p = decode_uleb128 (p, ®); p = decode_uleb128 (p, &offset); offset *= info->data_align; state->s.saved[reg] = REG_SAVED_OFFSET; state->s.reg_or_offset[reg] = offset; break; case DW_CFA_restore_extended: p = decode_uleb128 (p, ®); state->s.saved[reg] = REG_UNSAVED; break; case DW_CFA_undefined: case DW_CFA_same_value: case DW_CFA_nop: break; case DW_CFA_register: { unsigned reg2; p = decode_uleb128 (p, ®); p = decode_uleb128 (p, ®2); state->s.saved[reg] = REG_SAVED_REG; state->s.reg_or_offset[reg] = reg2; } break; case DW_CFA_def_cfa: p = decode_uleb128 (p, ®); p = decode_uleb128 (p, &offset); state->s.cfa_reg = reg; state->s.cfa_offset = offset; break; case DW_CFA_def_cfa_register: p = decode_uleb128 (p, ®); state->s.cfa_reg = reg; break; case DW_CFA_def_cfa_offset: p = decode_uleb128 (p, &offset); state->s.cfa_offset = offset; break; case DW_CFA_remember_state: { struct frame_state_internal *save = (struct frame_state_internal *) malloc (sizeof (struct frame_state_internal)); memcpy (save, state, sizeof (struct frame_state_internal)); state->saved_state = save; } break; case DW_CFA_restore_state: { struct frame_state_internal *save = state->saved_state; memcpy (state, save, sizeof (struct frame_state_internal)); free (save); } break; /* FIXME: Hardcoded for SPARC register window configuration. */ case DW_CFA_GNU_window_save: for (reg = 16; reg < 32; ++reg) { state->s.saved[reg] = REG_SAVED_OFFSET; state->s.reg_or_offset[reg] = (reg - 16) * sizeof (void *); } break; case DW_CFA_GNU_args_size: p = decode_uleb128 (p, &offset); state->s.args_size = offset; break; default: abort (); } return p; }
static int init_classsharing_workaround(void *cd, const prmap_t* pmap, const char* obj_name) { Debugger* dbg = (Debugger*) cd; JNIEnv* env = dbg->env; jobject this_obj = dbg->this_obj; const char* jvm_name = 0; if ((jvm_name = strstr(obj_name, "libjvm.so")) != NULL) { jvm_name = obj_name; } else { return 0; } struct ps_prochandle* ph = (struct ps_prochandle*) env->GetLongField(this_obj, p_ps_prochandle_ID); // initialize classes.jsa file descriptor field. dbg->env->SetIntField(this_obj, classes_jsa_fd_ID, -1); // check whether class sharing is on by reading variable "UseSharedSpaces" psaddr_t useSharedSpacesAddr = 0; ps_pglobal_lookup(ph, jvm_name, USE_SHARED_SPACES_SYM, &useSharedSpacesAddr); if (useSharedSpacesAddr == 0) { THROW_NEW_DEBUGGER_EXCEPTION_("can't find 'UseSharedSpaces' flag\n", 1); } // read the value of the flag "UseSharedSpaces" // Since hotspot types are not available to build this library. So // equivalent type "jboolean" is used to read the value of "UseSharedSpaces" // which is same as hotspot type "bool". jboolean value = 0; if (read_jboolean(ph, useSharedSpacesAddr, &value) != true) { THROW_NEW_DEBUGGER_EXCEPTION_("can't read 'UseSharedSpaces' flag", 1); } else if ((int)value == 0) { print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n"); return 1; } char classes_jsa[PATH_MAX]; psaddr_t sharedArchivePathAddrAddr = 0; ps_pglobal_lookup(ph, jvm_name, SHARED_ARCHIVE_PATH_SYM, &sharedArchivePathAddrAddr); if (sharedArchivePathAddrAddr == 0) { print_debug("can't find symbol 'Arguments::SharedArchivePath'\n"); THROW_NEW_DEBUGGER_EXCEPTION_("can't get shared archive path from debuggee", 1); } uintptr_t sharedArchivePathAddr = 0; if (read_pointer(ph, sharedArchivePathAddrAddr, &sharedArchivePathAddr) != true) { print_debug("can't find read pointer 'Arguments::SharedArchivePath'\n"); THROW_NEW_DEBUGGER_EXCEPTION_("can't get shared archive path from debuggee", 1); } if (read_string(ph, (psaddr_t)sharedArchivePathAddr, classes_jsa, sizeof(classes_jsa)) != true) { print_debug("can't find read 'Arguments::SharedArchivePath' value\n"); THROW_NEW_DEBUGGER_EXCEPTION_("can't get shared archive path from debuggee", 1); } print_debug("looking for %s\n", classes_jsa); // open the classes.jsa int fd = libsaproc_open(classes_jsa, O_RDONLY); if (fd < 0) { char errMsg[ERR_MSG_SIZE]; sprintf(errMsg, "can't open shared archive file %s", classes_jsa); THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1); } else { print_debug("opened shared archive file %s\n", classes_jsa); } // parse classes.jsa struct FileMapHeader* pheader = (struct FileMapHeader*) malloc(sizeof(struct FileMapHeader)); if (pheader == NULL) { close(fd); THROW_NEW_DEBUGGER_EXCEPTION_("can't allocate memory for shared file map header", 1); } memset(pheader, 0, sizeof(struct FileMapHeader)); // read FileMapHeader size_t n = read(fd, pheader, sizeof(struct FileMapHeader)); if (n != sizeof(struct FileMapHeader)) { char errMsg[ERR_MSG_SIZE]; sprintf(errMsg, "unable to read shared archive file map header from %s", classes_jsa); close(fd); free(pheader); THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1); } // check file magic if (pheader->_magic != 0xf00baba2) { char errMsg[ERR_MSG_SIZE]; sprintf(errMsg, "%s has bad shared archive magic 0x%x, expecting 0xf00baba2", classes_jsa, pheader->_magic); close(fd); free(pheader); THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1); } // check version if (pheader->_version != CURRENT_ARCHIVE_VERSION) { char errMsg[ERR_MSG_SIZE]; sprintf(errMsg, "%s has wrong shared archive version %d, expecting %d", classes_jsa, pheader->_version, CURRENT_ARCHIVE_VERSION); close(fd); free(pheader); THROW_NEW_DEBUGGER_EXCEPTION_(errMsg, 1); } if (_libsaproc_debug) { for (int m = 0; m < NUM_SHARED_MAPS; m++) { print_debug("shared file offset %d mapped at 0x%lx, size = %ld, read only? = %d\n", pheader->_space[m]._file_offset, pheader->_space[m]._base, pheader->_space[m]._used, pheader->_space[m]._read_only); } } // FIXME: For now, omitting other checks such as VM version etc. // store class archive file fd and map header in debugger object fields dbg->env->SetIntField(this_obj, classes_jsa_fd_ID, fd); dbg->env->SetLongField(this_obj, p_file_map_header_ID, (jlong)(uintptr_t) pheader); return 1; }
int start (void) #endif { uint64_t apl64; uint32_t i, apl; uint16_t apl16; uint8_t apl8,my_apl8; void *sptr, *rptr; double ong64, my_ong64; float ong, my_ong; int failure = 0; i = 0; while (i < 10) { #ifdef RUN apl = rand(); #else apl = i + 1; #endif my_ong = (float)apl; my_ong64 = (double)apl; apl64 = (uint64_t)apl; apl16 = (uint16_t)apl; my_apl8 = (uint8_t)apl16; write_uint64("apples64", apl64); #ifdef RUN fprintf(stderr, "\n(%d.a) sent a 64-bit apple: %llu..", i, apl64); #endif ong64 = read_float64("oranges64"); #ifdef RUN fprintf(stderr, "\ngot a (double) orange: %le.", ong64); #endif failure |= (my_ong64 != ong64); write_uint32("apples32", apl); #ifdef RUN fprintf(stderr, "\n(%d.b) sent a 32-bit apple: %d.", i, apl); #endif ong = read_float32("oranges32"); #ifdef RUN fprintf(stderr, "\ngot a (float) orange: %f.", ong); #endif failure |= (my_ong != ong); write_uint16("apples16", apl16); #ifdef RUN fprintf(stderr, "\n(%d.c) sent a 16-bit apple: %d.", i, apl16); #endif apl8 = read_uint8("oranges8"); #ifdef RUN fprintf(stderr, "\ngot an 8-bit orange: %d.", apl8); #endif sptr = (void*) &apl; write_pointer("apples32", sptr); #ifdef RUN fprintf(stderr, "\n(%d.d) sent a pointer apple: %d.", i, (unsigned int)sptr); #endif rptr = read_pointer("oranges32"); #ifdef RUN fprintf(stderr, "\ngot a pointer orange: %d.",(unsigned int) rptr); #endif failure |= (sptr != rptr); ++i; } #ifdef RUN if (failure == 0) fprintf(stderr, "\nAll conversions successful.\n"); else fprintf(stderr, "\nSome conversion(s) failed.\n"); #endif return failure; }
void gdb_save_stacktrace(const char *text_in, const char *text_out){ FILE *fin; FILE *fout; int number = 0; size_t nbytes = 300; fout = fopen(text_out, "w+"); fin = fopen(text_in, "r"); str = (char *) malloc (nbytes + 1); while(1){ size = getline (&str, &nbytes, fin); if (size == -1) break; if (size == 0) break; str[size-1] = '\0'; poz = 4; if(get_char(poz) == '0'){ read_pointer(); poz += 4; } char *func = read_name(); poz += 1; int tmppoz = poz; if (strcmp(func, "gdb_die") == 0) { fprintf(fout, "%s\n", c_rt_lib0get_die_additional_info()); while(get_char(tmppoz) != '"' && get_char(tmppoz) != '\0') ++tmppoz; fprintf(fout, "\""); while(1){ char tmp = get_char(++tmppoz); if(tmp == '"') break; if(tmp == '\0') break; if(tmp == '\\') tmp = get_char(++tmppoz); if(tmp == '"') fprintf(fout, "\""); fprintf(fout, "%c", tmp); } fprintf(fout, "\"\n"); fflush(fout); } tmppoz = size-3; while(is_num(get_char(tmppoz))) --tmppoz; int line = atoi(str+tmppoz+1); if(get_char(tmppoz) == ':') str[tmppoz] = '\0'; while(get_char(tmppoz)!=')') --tmppoz; tmppoz += 5; fprintf(fout, "%d %s %s %d", number, func, str+tmppoz, line); int param = 0; while(1) { if(get_char(poz) == ',') { poz +=2; } else if(get_char(poz) == '(') { poz +=1; if(get_char(poz) == ')') break; } else if(get_char(poz) == ')') { break; } else { break; } char *name = read_name(); void *ptr = NULL; if(get_char(poz) == '='){ ++poz; ptr = read_pointer(); } if(startsWith("___nl__", name) && ptr != NULL){ ImmT saved = dfile0ssave(ptr); NlString* p = toStringIfSim(saved); fprintf(fout, " \"p%d ", param); fprintString(fout, p->s, p->length); fprintf(fout, "\""); } else if(startsWith("___ref___", name) && ptr != NULL && *(ImmT*)ptr != NULL){ ImmT saved = dfile0ssave(*(ImmT*)ptr); NlString* p = toStringIfSim(saved); fprintf(fout, " \"p%d REF ", param); fprintString(fout, p->s, p->length); fprintf(fout, "\""); } else { fprintf(fout, " p%d %s=%p", param, name, ptr); } fflush(fout); ++param; } fprintf(fout, "\n"); fflush(fout); ++number; } free(str); fclose(fin); fclose(fout); }
static bool init_classsharing_workaround(struct ps_prochandle* ph) { lib_info* lib = ph->libs; while (lib != NULL) { // we are iterating over shared objects from the core dump. look for // libjvm.so. const char *jvm_name = 0; if ((jvm_name = strstr(lib->name, "/libjvm.so")) != 0) { char classes_jsa[PATH_MAX]; struct FileMapHeader header; size_t n = 0; int fd = -1, m = 0; uintptr_t base = 0, useSharedSpacesAddr = 0; uintptr_t sharedArchivePathAddrAddr = 0, sharedArchivePathAddr = 0; jboolean useSharedSpaces = 0; map_info* mi = 0; memset(classes_jsa, 0, sizeof(classes_jsa)); jvm_name = lib->name; useSharedSpacesAddr = lookup_symbol(ph, jvm_name, USE_SHARED_SPACES_SYM); if (useSharedSpacesAddr == 0) { print_debug("can't lookup 'UseSharedSpaces' flag\n"); return false; } // Hotspot vm types are not exported to build this library. So // using equivalent type jboolean to read the value of // UseSharedSpaces which is same as hotspot type "bool". if (read_jboolean(ph, useSharedSpacesAddr, &useSharedSpaces) != true) { print_debug("can't read the value of 'UseSharedSpaces' flag\n"); return false; } if ((int)useSharedSpaces == 0) { print_debug("UseSharedSpaces is false, assuming -Xshare:off!\n"); return true; } sharedArchivePathAddrAddr = lookup_symbol(ph, jvm_name, SHARED_ARCHIVE_PATH_SYM); if (sharedArchivePathAddrAddr == 0) { print_debug("can't lookup shared archive path symbol\n"); return false; } if (read_pointer(ph, sharedArchivePathAddrAddr, &sharedArchivePathAddr) != true) { print_debug("can't read shared archive path pointer\n"); return false; } if (read_string(ph, sharedArchivePathAddr, classes_jsa, sizeof(classes_jsa)) != true) { print_debug("can't read shared archive path value\n"); return false; } print_debug("looking for %s\n", classes_jsa); // open the class sharing archive file fd = pathmap_open(classes_jsa); if (fd < 0) { print_debug("can't open %s!\n", classes_jsa); ph->core->classes_jsa_fd = -1; return false; } else { print_debug("opened %s\n", classes_jsa); } // read FileMapHeader from the file memset(&header, 0, sizeof(struct FileMapHeader)); if ((n = read(fd, &header, sizeof(struct FileMapHeader))) != sizeof(struct FileMapHeader)) { print_debug("can't read shared archive file map header from %s\n", classes_jsa); close(fd); return false; } // check file magic if (header._magic != 0xf00baba2) { print_debug("%s has bad shared archive file magic number 0x%x, expecing 0xf00baba2\n", classes_jsa, header._magic); close(fd); return false; } // check version if (header._version != CURRENT_ARCHIVE_VERSION) { print_debug("%s has wrong shared archive file version %d, expecting %d\n", classes_jsa, header._version, CURRENT_ARCHIVE_VERSION); close(fd); return false; } ph->core->classes_jsa_fd = fd; // add read-only maps from classes.jsa to the list of maps for (m = 0; m < NUM_SHARED_MAPS; m++) { if (header._space[m]._read_only) { base = (uintptr_t) header._space[m]._base; // no need to worry about the fractional pages at-the-end. // possible fractional pages are handled by core_read_data. add_class_share_map_info(ph, (off_t) header._space[m]._file_offset, base, (size_t) header._space[m]._used); print_debug("added a share archive map at 0x%lx\n", base); } } return true; } lib = lib->next; } return true; }
static int nmethod_info(Nmethod_t *N) { jvm_agent_t *J = N->J; uint64_t nm = N->nm; int32_t err; if (debug > 2 ) fprintf(stderr, "\t nmethod_info: BEGIN \n"); /* Instructions */ err = read_pointer(J, nm + OFFSET_CodeBlob_code_begin, &N->instrs_beg); CHECK_FAIL(err); err = read_pointer(J, nm + OFFSET_CodeBlob_code_end, &N->instrs_end); CHECK_FAIL(err); err = read_pointer(J, nm + OFFSET_nmethod_deopt_handler_begin, &N->deopt_beg); CHECK_FAIL(err); err = ps_pread(J->P, nm + OFFSET_nmethod_orig_pc_offset, &N->orig_pc_offset, SZ32); CHECK_FAIL(err); /* Metadata */ err = ps_pread(J->P, nm + OFFSET_nmethod_metadata_offset, &N->metadata_beg, SZ32); CHECK_FAIL(err); err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_begin, &N->metadata_end, SZ32); CHECK_FAIL(err); /* scopes_pcs */ err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_pcs_offset, &N->scopes_pcs_beg, SZ32); CHECK_FAIL(err); err = ps_pread(J->P, nm + OFFSET_nmethod_dependencies_offset, &N->scopes_pcs_end, SZ32); CHECK_FAIL(err); /* scopes_data */ err = ps_pread(J->P, nm + OFFSET_nmethod_scopes_data_begin, &N->scopes_data_beg, POINTER_SIZE); CHECK_FAIL(err); if (debug > 2 ) { N->scopes_data_end = N->scopes_pcs_beg; fprintf(stderr, "\t nmethod_info: instrs_beg: %#x, instrs_end: %#x\n", N->instrs_beg, N->instrs_end); fprintf(stderr, "\t nmethod_info: deopt_beg: %#x \n", N->deopt_beg); fprintf(stderr, "\t nmethod_info: orig_pc_offset: %#x \n", N->orig_pc_offset); fprintf(stderr, "\t nmethod_info: metadata_beg: %#x, metadata_end: %#x\n", N->metadata_beg, N->metadata_end); fprintf(stderr, "\t nmethod_info: scopes_data_beg: %#x, scopes_data_end: %#x\n", N->scopes_data_beg, N->scopes_data_end); fprintf(stderr, "\t nmethod_info: scopes_pcs_beg: %#x, scopes_pcs_end: %#x\n", N->scopes_pcs_beg, N->scopes_pcs_end); fprintf(stderr, "\t nmethod_info: END \n\n"); } return PS_OK; fail: return err; }
static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc, signed ptrType, struct unwind_state *state) { union { const u8 *p8; const u16 *p16; const u32 *p32; } ptr; int result = 1; if (start != state->cieStart) { state->loc = state->org; result = processCFI(state->cieStart, state->cieEnd, 0, ptrType, state); if (targetLoc == 0 && state->label == NULL) return result; } for (ptr.p8 = start; result && ptr.p8 < end; ) { switch(*ptr.p8 >> 6) { uleb128_t value; case 0: switch(*ptr.p8++) { case DW_CFA_nop: break; case DW_CFA_set_loc: if ((state->loc = read_pointer(&ptr.p8, end, ptrType)) == 0) result = 0; break; case DW_CFA_advance_loc1: result = ptr.p8 < end && advance_loc(*ptr.p8++, state); break; case DW_CFA_advance_loc2: result = ptr.p8 <= end + 2 && advance_loc(*ptr.p16++, state); break; case DW_CFA_advance_loc4: result = ptr.p8 <= end + 4 && advance_loc(*ptr.p32++, state); break; case DW_CFA_offset_extended: value = get_uleb128(&ptr.p8, end); set_rule(value, Memory, get_uleb128(&ptr.p8, end), state); break; case DW_CFA_val_offset: value = get_uleb128(&ptr.p8, end); set_rule(value, Value, get_uleb128(&ptr.p8, end), state); break; case DW_CFA_offset_extended_sf: value = get_uleb128(&ptr.p8, end); set_rule(value, Memory, get_sleb128(&ptr.p8, end), state); break; case DW_CFA_val_offset_sf: value = get_uleb128(&ptr.p8, end); set_rule(value, Value, get_sleb128(&ptr.p8, end), state); break; case DW_CFA_restore_extended: case DW_CFA_undefined: case DW_CFA_same_value: set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0, state); break; case DW_CFA_register: value = get_uleb128(&ptr.p8, end); set_rule(value, Register, get_uleb128(&ptr.p8, end), state); break; case DW_CFA_remember_state: if (ptr.p8 == state->label) { state->label = NULL; return 1; } if (state->stackDepth >= MAX_STACK_DEPTH) return 0; state->stack[state->stackDepth++] = ptr.p8; break; case DW_CFA_restore_state: if (state->stackDepth) { const uleb128_t loc = state->loc; const u8 *label = state->label; state->label = state->stack[state->stackDepth - 1]; memcpy(&state->cfa, &badCFA, sizeof(state->cfa)); memset(state->regs, 0, sizeof(state->regs)); state->stackDepth = 0; result = processCFI(start, end, 0, ptrType, state); state->loc = loc; state->label = label; } else return 0; break; case DW_CFA_def_cfa: state->cfa.reg = get_uleb128(&ptr.p8, end); /*nobreak*/ case DW_CFA_def_cfa_offset: state->cfa.offs = get_uleb128(&ptr.p8, end); break; case DW_CFA_def_cfa_sf: state->cfa.reg = get_uleb128(&ptr.p8, end); /*nobreak*/ case DW_CFA_def_cfa_offset_sf: state->cfa.offs = get_sleb128(&ptr.p8, end) * state->dataAlign; break; case DW_CFA_def_cfa_register: state->cfa.reg = get_uleb128(&ptr.p8, end); break; /*todo case DW_CFA_def_cfa_expression: */ /*todo case DW_CFA_expression: */ /*todo case DW_CFA_val_expression: */ case DW_CFA_GNU_args_size: get_uleb128(&ptr.p8, end); break; case DW_CFA_GNU_negative_offset_extended: value = get_uleb128(&ptr.p8, end); set_rule(value, Memory, (uleb128_t)0 - get_uleb128(&ptr.p8, end), state); break; case DW_CFA_GNU_window_save: default: result = 0; break; } break; case 1: result = advance_loc(*ptr.p8++ & 0x3f, state); break; case 2: value = *ptr.p8++ & 0x3f; set_rule(value, Memory, get_uleb128(&ptr.p8, end), state); break; case 3: set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state); break; } if (ptr.p8 > end) result = 0; if (result && targetLoc != 0 && targetLoc < state->loc) return 1; } return result && ptr.p8 == end && (targetLoc == 0 || (/*todo While in theory this should apply, gcc in practice omits everything past the function prolog, and hence the location never reaches the end of the function. targetLoc < state->loc &&*/ state->label == NULL)); }