static int writenote(struct memelfnote *men, FILE *core_fp, long *size) { Elf32_Nhdr en; en.n_namesz = strlen(men->name)+1; en.n_descsz = men->datasz; en.n_type = men->type; if(dump_write( core_fp, &en, sizeof(en), size) == -1) return 1; if(dump_write( core_fp, men->name, en.n_namesz, size) == -1) return 1; dump_seek( core_fp, roundup(dump_tell(core_fp), sizeof (Elf32_Word))); /* XXX */ if(dump_write( core_fp, men->data, men->datasz, size) == -1) return 1; dump_seek( core_fp, roundup(dump_tell(core_fp), sizeof (Elf32_Word))); /* XXX */ dump_seek( core_fp, roundup(dump_tell(core_fp), sizeof (Elf32_Word))); return 1; }
VMDump::VMDump(const char *fileName) : Dump(fileName, "rb") { char fmbk_id[8] = {0xc8, 0xc3, 0xd7, 0xc4, 0xc6, 0xd4, 0xc2, 0xd2}; ebcdicAsciiConv = iconv_open("ISO-8859-1", "EBCDIC-US"); /* Record 1: adsrRecord */ dump_seek(fh,0,SEEK_SET); dump_read(&adsrRecord,sizeof(adsrRecord),1,fh); if(debug) { char buf[1024]; int i; dump_seek(fh,adsrRecord.sec3_offset,SEEK_SET); dump_read(buf, adsrRecord.sec3_len,1,fh); ebcAsc(buf,adsrRecord.sec3_len); for(i=0; i < adsrRecord.sec3_len; i++) { if((buf[i]==0) || iscntrl(buf[i])) buf[i]=' '; } buf[adsrRecord.sec3_len]=0; printf("symptom string1: %s\n",buf); } /* Record 2: fmbk */ dump_seek(fh,0x1000,SEEK_SET); dump_read(&fmbkRecord,sizeof(fmbkRecord),1,fh); /* Check if this is a vmdump */ if(memcmp(fmbkRecord.id, fmbk_id, 8) != 0) { throw DumpException("Input file is not a vmdump"); } /* Record 3-7: fir records read by subclasses */ /* Record 8: albk */ dump_seek(fh,(fmbkRecord.rec_nr_access-1)*0x1000 ,SEEK_SET); dump_read(&albkRecord,sizeof(albkRecord),1,fh); }
VMDumpClassic::VMDumpClassic(const char *fileName) : VMDump(fileName) { int storageKeyPages,bitMapPages; pageOffset = 0; /* Record 9: asibk */ dump_seek(fh,fmbkRecord.rec_nr_access * 0x1000,SEEK_SET); dump_read(&asibkRecord,sizeof(asibkRecord),1,fh); /* Record 10: bitmaps */ dump_seek(fh,(fmbkRecord.rec_nr_access + 1)* 0x1000 ,SEEK_SET); bitmap = new char[asibkRecord.storage_size_2GB / (0x1000 * 8)]; dump_read(bitmap,asibkRecord.storage_size_2GB / (0x1000*8),1,fh); bitMapPages=asibkRecord.storage_size_2GB / (0x1000 * 8); if(bitMapPages % 0x1000 != 0) bitMapPages = bitMapPages/0x1000 + 1; else bitMapPages = bitMapPages/0x1000; storageKeyPages=asibkRecord.storage_size_2GB / 0x1000; if(storageKeyPages % 0x1000 != 0) { storageKeyPages = storageKeyPages/0x1000 + 1; } else { storageKeyPages = storageKeyPages/0x1000; } /* skip storage keys */ memoryStartRecord = (fmbkRecord.rec_nr_access + 1) *0x1000 /* 0x9000 */ + (bitMapPages + storageKeyPages)*0x1000; if(debug) { printf("Mem Offset: %llx\n",(long long)memoryStartRecord); } }
VMDump64::VMDump64(const char* filename) : VMDumpClassic(filename) { int i; if(!fh) { return; } dump_seek(fh,(fmbkRecord.rec_nr_fir-1)* 0x1000 ,SEEK_SET); dump_read(&fir64Record,sizeof(fir64Record),1,fh); fir64OtherRecords = new _fir_other_64[fir64Record.online_cpus]; for(i=0; i < fir64Record.online_cpus; i++) { /* fir other */ dump_read(&fir64OtherRecords[i],sizeof(fir64OtherRecords[i]),1, fh); } if(debug) printDebug(); }
void VMDump::readMem(char* buf, int size) { int i; if(pageOffset == 0) dump_seek(fh, memoryStartRecord, SEEK_SET); if(size % 0x1000 != 0) { throw(DumpException("internal error: VMDump::readMem() "\ "can only handle sizes which are multiples of page size")); } for(i = 0; i < size; i += 0x1000) { if(testPage(pageOffset)) { dump_read(buf + i, 0x1000,1,fh); } else { memset(buf + i, 0, 0x1000); } pageOffset += 1; } }
int elfcore(int fd, FILE *fp, const char *path, long coresize) { procfs_sysinfo *sysinfo; int sysinfo_len; procfs_info info; procfs_status status; int ret; procfs_mapinfo *mem = NULL, *mapinfos = NULL, *ldd_infos = NULL; int numnote=0, num, i, j, seg = 0, err, n_ldd_infos = 0; Elf32_Ehdr elf; Elf32_Phdr phdr; struct memelfnote notes[20], thread_note; off_t offset = 0, dataoff; uint64_t cur_tid_base = 0, cur_tid_size = 0; if (nodumpmem) { if (-1 == get_ldd_mapinfos(fd, &ldd_infos, &n_ldd_infos)) { /* should we bail out here? */ n_ldd_infos = 0; } } if((ret = devctl(fd, DCMD_PROC_SYSINFO, 0, 0, &sysinfo_len)) != EOK) { errno = ret; goto bailout; } if(sysinfo = alloca(sysinfo_len)) { if((ret = devctl(fd, DCMD_PROC_SYSINFO, sysinfo, sysinfo_len, 0)) != EOK) { errno = ret; goto bailout; } } if((ret = devctl(fd, DCMD_PROC_INFO, &info, sizeof info, 0)) != EOK) { errno = ret; goto bailout; } pagesize = sysconf( _SC_PAGESIZE ); if ( membuf == NULL && ((membuf = malloc( pagesize )) == NULL) ) { goto bailout; } // write elf header memcpy(elf.e_ident, ELFMAG, SELFMAG); elf.e_ident[EI_CLASS] = ELFCLASS32; elf.e_ident[EI_DATA] = ELFDATANATIVE; elf.e_ident[EI_VERSION] = EV_CURRENT; #if defined (__ARM__) elf.e_ident[EI_OSABI] = ELFOSABI_ARM; #endif memset(elf.e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); if((ret = devctl(fd, DCMD_PROC_PAGEDATA, NULL, 0, &num)) != EOK) { errno = ret; goto bailout; } mapinfos = malloc( num * sizeof *mem ); if ( mapinfos == NULL ) { goto bailout; } if((ret = devctl(fd, DCMD_PROC_PAGEDATA, mapinfos, num*sizeof(*mapinfos), &num)) != EOK) { errno = ret; goto bailout; } mem = malloc( (n_ldd_infos + num) * sizeof(*mem) ); if ( mem == NULL ) { goto bailout; } /* find the offending thread */ for(status.tid = 1; devctl(fd, DCMD_PROC_TIDSTATUS, &status, sizeof status, 0) == EOK; status.tid++) { dprintf(("thread %d.flags is %#x\n", status.tid, status.flags )); if(status.why == _DEBUG_WHY_SIGNALLED) { // This is the faulting thread... dprintf(("thread %d is was SIGNALLED\n", status.tid )); cur_tid = status.tid; cur_tid_base = status.stkbase; cur_tid_size = status.stksize; } dprintf(("thread %d.why is %#x\n", status.tid, status.why )); } if(cur_tid == 0) { /* can't find the faulting thread then we need to dump all stack information */ cur_tid_only = 0; } for(seg = 0, i = 0; i < num; i++) { if(!(mapinfos[i].flags & PG_HWMAPPED) || (nodumpmem && !(mapinfos[i].flags & MAP_STACK)) ) { continue; } if ( (nodumpphys && (mapinfos[i].flags & MAP_PHYS) && !(mapinfos[i].flags & MAP_ANON)) ) { continue; } /* if we only want to dump the offending tid's stack */ if(cur_tid_only && (mapinfos[i].flags & MAP_STACK) && !OFFENDING_THREAD(cur_tid_base, cur_tid_size, &mapinfos[i])) { continue; } memcpy(&mem[seg], &mapinfos[i], sizeof(*mem)); seg++; } dprintf(("ldd mapinfos:\n")); for(i = 0; i < n_ldd_infos; i++) { dprintf(("%svaddr=%#llx, offset=%#llx, size=%#llx, flags=%#x\n", ldd_infos[i].flags & PG_HWMAPPED?"*":"", ldd_infos[i].vaddr, ldd_infos[i].offset, ldd_infos[i].size, ldd_infos[i].flags )); memcpy( &mem[seg], &ldd_infos[i], sizeof(*mem));; seg++; } free(mapinfos); mapinfos = NULL; if(n_ldd_infos) { free(ldd_infos); ldd_infos = NULL; } num = seg; elf.e_type = ET_CORE; elf.e_machine = EM_NATIVE; elf.e_version = EV_CURRENT; elf.e_entry = 0; elf.e_phoff = sizeof(elf); elf.e_shoff = 0; #ifdef __SH__ { struct cpuinfo_entry *cpu; cpu = SYSPAGE_ENTRY(cpuinfo); switch ( SH4_PVR_FAM(cpu[0].cpu) ) { case SH4_PVR_SH4A: dprintf(("Noting SH4-A CPU\n")); elf.e_flags = EF_SH4A; break; case SH4_PVR_SH4: default: elf.e_flags = EF_SH4; break; } } #else elf.e_flags = 0; #endif elf.e_ehsize = sizeof(elf); elf.e_phentsize = sizeof(phdr); elf.e_phnum = seg+1; /* xxxx */ elf.e_shentsize = 0; elf.e_shnum = 0; elf.e_shstrndx = 0; if(dump_write( fp, &elf, sizeof elf, &coresize ) == -1) goto bailout; offset += sizeof elf; offset += (elf.e_phnum) * sizeof phdr; if(sysinfo) { // write QNT_CORE_SYSINFO note memset( notes, 0, sizeof notes ); notes[numnote].name = QNX_NOTE_NAME; notes[numnote].type = QNT_CORE_SYSINFO; notes[numnote].datasz = roundup(sysinfo_len, sizeof (Elf32_Word)); notes[numnote].data = sysinfo; numnote++; } // write QNT_CORE_INFO note notes[numnote].name = QNX_NOTE_NAME; notes[numnote].type = QNT_CORE_INFO; notes[numnote].datasz = sizeof(info); notes[numnote].data = &info; numnote++; /* Write notes phdr entry */ { int sz = 0; memset( &phdr, 0, sizeof phdr ); for(i = 0; i < numnote; i++) sz += notesize(¬es[i]); for(status.tid = 1; devctl(fd, DCMD_PROC_TIDSTATUS, &status, sizeof status, 0) == EOK; status.tid++) { procfs_greg greg; procfs_fpreg fpreg; int size; if ( (err = devctl(fd, DCMD_PROC_CURTHREAD, &status.tid, sizeof status.tid, 0 )) != EOK ) { continue; } if (cur_tid_only && (cur_tid != status.tid)) { continue; } fixup_stack_boundary( &status, mem, seg ); thread_note.name = QNX_NOTE_NAME; thread_note.type = QNT_CORE_STATUS; thread_note.datasz = sizeof(status); thread_note.data = &status; sz += notesize( &thread_note ); if(devctl(fd, DCMD_PROC_GETGREG, &greg, sizeof greg, &size) == EOK) { thread_note.name = QNX_NOTE_NAME; thread_note.type = QNT_CORE_GREG; thread_note.datasz = size; thread_note.data = &greg; sz += notesize( &thread_note ); } if(devctl(fd, DCMD_PROC_GETFPREG, &fpreg, sizeof fpreg, &size) == EOK) { thread_note.name = QNX_NOTE_NAME; thread_note.type = QNT_CORE_FPREG; thread_note.datasz = size; thread_note.data = &fpreg; sz += notesize( &thread_note ); } } phdr.p_type = PT_NOTE; phdr.p_offset = offset; phdr.p_vaddr = 0; phdr.p_paddr = 0; phdr.p_filesz = sz; phdr.p_memsz = 0; phdr.p_flags = 0; phdr.p_align = 0; offset += phdr.p_filesz; if(dump_write( fp, &phdr, sizeof(phdr), &coresize) == -1) goto bailout; } /* Page-align dumped data */ dataoff = offset = roundup(offset, pagesize); for ( i = 0; i < seg; i++ ) { memset( &phdr, 0, sizeof phdr ); phdr.p_type = PT_LOAD; phdr.p_offset = offset; phdr.p_vaddr = mem[i].vaddr; phdr.p_paddr = 0; phdr.p_memsz = mem[i].size; phdr.p_flags = PF_W|PF_R; if ( mem[i].flags & MAP_ELF ) phdr.p_flags |= PF_X; phdr.p_align = pagesize; phdr.p_filesz = phdr.p_memsz; offset += phdr.p_filesz; if(dump_write( fp, &phdr, sizeof(phdr), &coresize) == -1) goto bailout; } for(i = 0; i < numnote; i++) { if (!writenote(¬es[i], fp, &coresize )) goto bailout; } for(status.tid = 1; devctl(fd, DCMD_PROC_TIDSTATUS, &status, sizeof status, 0) == EOK; status.tid++) { procfs_greg greg; procfs_fpreg fpreg; int size; if ( devctl(fd, DCMD_PROC_CURTHREAD, &status.tid, sizeof status.tid, 0 ) != EOK ) { continue; } if ( cur_tid == 0 ) cur_tid = status.tid; if (cur_tid_only && (cur_tid != status.tid)) { continue; } else if ( status.tid == cur_tid ) { dprintf(("thread %d is current thread!\n", status.tid )); slog_tid( &status, path ); status.flags |= _DEBUG_FLAG_CURTID; } // write QNT_CORE_STATUS note thread_note.name = QNX_NOTE_NAME; thread_note.type = QNT_CORE_STATUS; thread_note.datasz = sizeof(status); thread_note.data = &status; if ( !writenote( &thread_note, fp, &coresize ) ) goto bailout; if(devctl(fd, DCMD_PROC_GETGREG, &greg, sizeof greg, &size) == EOK) { // write QNT_CORE_GREG note thread_note.name = QNX_NOTE_NAME; thread_note.type = QNT_CORE_GREG; thread_note.datasz = size; thread_note.data = &greg; if ( !writenote( &thread_note, fp, &coresize ) ) goto bailout; } if(devctl(fd, DCMD_PROC_GETFPREG, &fpreg, sizeof fpreg, &size) == EOK) { // write QNT_CORE_FPREG note thread_note.name = QNX_NOTE_NAME; thread_note.type = QNT_CORE_FPREG; thread_note.datasz = size; thread_note.data = &fpreg; if ( !writenote( &thread_note, fp, &coresize ) ) goto bailout; } } dump_seek( fp, dataoff ); for ( j = 0; j < seg; j++ ) { if ( lseek( fd, mem[j].vaddr, SEEK_SET ) == -1 ) goto bailout; if ( mem[j].flags & MAP_STACK ) dump_stack_memory( fd, fp, &mem[j], &coresize ); else if (!nodumpmem) dump_memory( fd, fp, &mem[j], &coresize ); } // Return EOK when accually writing ELF files free(mem); return EOK; bailout: if ( mapinfos != NULL ) { free(mapinfos); } if ( ldd_infos != NULL ) { free(ldd_infos); } if ( mem != NULL ) { free(mem); } return errno; }
void dump_stack_memory( int fd, FILE *fp, procfs_mapinfo *mem, long *size ) { int num, i, max, min, base; off_t here, there; if ( (mem->flags & PG_HWMAPPED) == 0 ) { dprintf(("Ignoring non-mapped stack region: %#llx @ %#llx\n", mem->size, mem->vaddr )); return; } base = mem->offset; // base = mem->vaddr; dprintf(("blanking %lld bytes of stack memory at %#x\n", mem->size, base )); //printf("vaddr=%#x, offset=%#x, size=%lld\n", mem->vaddr, mem->offset, mem->size ); here = dump_tell(fp); max = roundup( mem->size, pagesize ); min = (mem->offset - mem->vaddr); dprintf(("max=%#x, min = %#x (%#llx->%#llx)\n", max, min, mem->vaddr+min, mem->vaddr+max )); if (gzlevel != -1) { int rsize; /* forward dumping from mem->offset to mem->offset + mem->size in gz mode */ memset(membuf, 0, pagesize); for (i = 0; i < min; i += pagesize) { if( dump_write( fp, membuf, min(pagesize, min - i), size) == -1) return; } for (i = min; i < mem->size; i += pagesize) { if ( lseek( fd, mem->vaddr + i, SEEK_SET ) == -1 ) { memset(membuf, 0, pagesize); num = pagesize; } else { rsize = (i & ~(pagesize - 1)) + pagesize; if (rsize >= mem->size) { rsize = mem->size - i; } else { rsize -= i; } if ((num = read( fd, membuf, rsize)) != rsize) { memset(membuf, -1, pagesize); } } if( dump_write( fp, membuf, num, size) == -1) return; } return; } memset( membuf, 0, sizeof membuf ); for (i = 0; i < mem->size; i+= pagesize ) { if(dump_write( fp, membuf, min( pagesize, mem->size - i ), size) == -1) return; } there = dump_tell(fp); for ( i = max - pagesize; i >= min; i -= pagesize ) { dump_seek( fp, here + i ); if ( lseek( fd, mem->vaddr + i, SEEK_SET ) == -1 ) continue; /* read memory here */ // dprintf(("attempting to read @ %#llx\n", mem->vaddr + i )); if ( (num = read( fd, membuf, pagesize )) != pagesize ) { memset( membuf, -1, sizeof membuf ); num = pagesize; } if(dump_write( fp, membuf, num, size) == -1) return; fflush( fp ); if ( num != pagesize ) { dprintf(("cut short at %d+%d\n", i, num )); break; } // else // dprintf(("read %d bytes ok\n", num )); } dump_seek( fp, there ); }
VMDump64Big::VMDump64Big(const char* filename) : VMDump(filename) { int i,j; uint64_t pageNum, nrDumpedPages; if(!fh) { return; } /* Record 9: asibk */ dump_seek(fh,fmbkRecord.rec_nr_access * 0x1000,SEEK_SET); dump_read(&asibkRecordNew,sizeof(asibkRecordNew),1,fh); /* Record 10: bitmaps: */ /* Read all bitmap pages and setup bitmap array */ pageNum = 0; nrDumpedPages = asibkRecordNew.storage_size_def_store / 0x1000; memoryStartRecord = (fmbkRecord.rec_nr_access + 1) * 0x1000; bitmap = new char[asibkRecordNew.storage_size_def_store/(0x1000 * 8)]; if(!bitmap) { throw(DumpErrnoException("out of memory")); } memset(bitmap,0,asibkRecordNew.storage_size_def_store/(0x1000 * 8)); dump_seek(fh,(fmbkRecord.rec_nr_access + 1)* 0x1000 ,SEEK_SET); do { char bmIndexPage[0x1000]; dump_read(bmIndexPage,sizeof(bmIndexPage),1,fh); memoryStartRecord += 0x1000; for(i=0; i < 0x1000; i++) { if(testBitmapPage(bmIndexPage,i)) { char bmPage[0x1000]; dump_read(bmPage,sizeof(bmPage),1,fh); memoryStartRecord += 0x1000; for(j = 0; j < 0x1000; j++) { if(testBitmapKeyPage(bmPage, j)) { setPageBit(pageNum); } pageNum++; if(pageNum == nrDumpedPages) { goto all_bitmaps_read; } } } else { pageNum += 0x1000; // empty pages } } } while (pageNum < nrDumpedPages); all_bitmaps_read: if(debug) printf("Mem Offset: %llx\n",(long long)memoryStartRecord); dump_seek(fh,(fmbkRecord.rec_nr_fir-1)* 0x1000 ,SEEK_SET); dump_read(&fir64Record,sizeof(fir64Record),1,fh); fir64OtherRecords = new _fir_other_64[fir64Record.online_cpus]; for(i=0; i < fir64Record.online_cpus; i++) { /* fir other */ dump_read(&fir64OtherRecords[i],sizeof(fir64OtherRecords[i]),1, fh); } if(debug) printDebug(); }
Dump::DumpType VMDump::getDumpType(const char* inputFileName) { FILE* fh; struct _fmbk fmbk; struct _fir_basic fir; char fmbk_id[8] = {0xc8, 0xc3, 0xd7, 0xc4, 0xc6, 0xd4, 0xc2, 0xd2}; char msg[200]; fh = fopen(inputFileName,"r"); if(!fh) { sprintf(msg,"Could not open '%s'",inputFileName); throw DumpErrnoException(msg); } /* Record 2: fmbk */ dump_seek(fh,0x1000,SEEK_SET); if(fread(&fmbk,sizeof(fmbk),1,fh) != 1) { if(ferror(fh)) { sprintf(msg,"Could not read header of vmdump '%s'", inputFileName); fclose(fh); throw DumpErrnoException(msg); } else{ sprintf(msg,"Input file '%s' is not a vmdump", inputFileName); fclose(fh); throw DumpException(msg); } } /* Check if this is a vmdump */ if(memcmp(fmbk.id, fmbk_id, 8) != 0) { fclose(fh); sprintf(msg,"Input file '%s' is not a vmdump",inputFileName); throw DumpException(msg); } /* Record 3-7: fir */ dump_seek(fh,(fmbk.rec_nr_fir-1)* 0x1000,SEEK_SET); if(fread(&fir,sizeof(fir),1,fh) != 1) { if(ferror(fh)) { sprintf(msg,"Could not read header of vmdump '%s'", inputFileName); fclose(fh); throw DumpErrnoException(msg); } else{ sprintf(msg,"Could not read header of vmdump '%s'", inputFileName); fclose(fh); throw DumpException(msg); } } fclose(fh); if(fir.fir_format == 0) { return DT_VM32; } else if(fir.fir_format == 0x02) {/*XXX && (fir.dump_format == 0x1))*/ return DT_VM64_BIG; } else if(fir.fir_format == 0x82) { return DT_VM64; } else { return DT_UNKNOWN; } }