/* [in] */ CLRDATA_ADDRESS address,
/* [in] */ ULONG32 size)
{
- InsertMemoryRegion(address, size);
+ InsertMemoryRegion((ULONG_PTR)address, size);
return S_OK;
}
if (auxvEntry.a_type < AT_MAX)
{
m_auxvValues[auxvEntry.a_type] = auxvEntry.a_un.a_val;
- TRACE("AUXV: %lu = %016lx\n", auxvEntry.a_type, auxvEntry.a_un.a_val);
+ TRACE("AUXV: %" PRIu " = %" PRIxA "\n", auxvEntry.a_type, auxvEntry.a_un.a_val);
result = true;
}
}
char* permissions = nullptr;
char* moduleName = nullptr;
- int c = sscanf(line, "%lx-%lx %m[-rwxsp] %lx %*[:0-9a-f] %*d %ms\n", &start, &end, &permissions, &offset, &moduleName);
+ int c = sscanf(line, "%" PRIx64 "-%" PRIx64 " %m[-rwxsp] %" PRIx64 " %*[:0-9a-f] %*d %ms\n", &start, &end, &permissions, &offset, &moduleName);
if (c == 4 || c == 5)
{
// r = read
{
Phdr ph;
if (!ReadMemory(phdrAddr, &ph, sizeof(ph))) {
- fprintf(stderr, "ReadMemory(%p, %lx) phdr FAILED\n", phdrAddr, sizeof(ph));
+ fprintf(stderr, "ReadMemory(%p, %" PRIx ") phdr FAILED\n", phdrAddr, sizeof(ph));
return false;
}
- TRACE("DSO: phdr %p type %d (%x) vaddr %016lx memsz %016lx offset %016lx\n",
+ TRACE("DSO: phdr %p type %d (%x) vaddr %" PRIxA " memsz %" PRIxA " offset %" PRIxA "\n",
phdrAddr, ph.p_type, ph.p_type, ph.p_vaddr, ph.p_memsz, ph.p_offset);
if (ph.p_type == PT_DYNAMIC)
for (;;) {
ElfW(Dyn) dyn;
if (!ReadMemory(dynamicAddr, &dyn, sizeof(dyn))) {
- fprintf(stderr, "ReadMemory(%p, %lx) dyn FAILED\n", dynamicAddr, sizeof(dyn));
+ fprintf(stderr, "ReadMemory(%p, %" PRIx ") dyn FAILED\n", dynamicAddr, sizeof(dyn));
return false;
}
- TRACE("DSO: dyn %p tag %ld (%lx) d_ptr %016lx\n", dynamicAddr, dyn.d_tag, dyn.d_tag, dyn.d_un.d_ptr);
+ TRACE("DSO: dyn %p tag %" PRId " (%" PRIx ") d_ptr %" PRIxA "\n", dynamicAddr, dyn.d_tag, dyn.d_tag, dyn.d_un.d_ptr);
if (dyn.d_tag == DT_DEBUG) {
rdebugAddr = reinterpret_cast<struct r_debug*>(dyn.d_un.d_ptr);
}
TRACE("DSO: rdebugAddr %p\n", rdebugAddr);
struct r_debug debugEntry;
if (!ReadMemory(rdebugAddr, &debugEntry, sizeof(debugEntry))) {
- fprintf(stderr, "ReadMemory(%p, %lx) r_debug FAILED\n", rdebugAddr, sizeof(debugEntry));
+ fprintf(stderr, "ReadMemory(%p, %" PRIx ") r_debug FAILED\n", rdebugAddr, sizeof(debugEntry));
return false;
}
for (struct link_map* linkMapAddr = debugEntry.r_map; linkMapAddr != nullptr;) {
struct link_map map;
if (!ReadMemory(linkMapAddr, &map, sizeof(map))) {
- fprintf(stderr, "ReadMemory(%p, %lx) link_map FAILED\n", linkMapAddr, sizeof(map));
+ fprintf(stderr, "ReadMemory(%p, %" PRIx ") link_map FAILED\n", linkMapAddr, sizeof(map));
return false;
}
// Read the module's name and make sure the memory is added to the core dump
}
}
moduleName[i] = '\0';
- TRACE("\nDSO: link_map entry %p l_ld %p l_addr (Ehdr) %lx %s\n", linkMapAddr, map.l_ld, map.l_addr, (char*)moduleName);
+ TRACE("\nDSO: link_map entry %p l_ld %p l_addr (Ehdr) %" PRIx " %s\n", linkMapAddr, map.l_ld, map.l_addr, (char*)moduleName);
// Read the ELF header and info adding it to the core dump
if (!GetELFInfo(map.l_addr)) {
return strncmp(name, sectionName, strlen(sectionName) + 1) == 0;
}
+bool
+ValidShdr(const std::set<MemoryRegion>& mappings, uint64_t elfBaseAddr, Shdr *shdrAddr)
+{
+ bool isValid = false;
+ const char *moduleName = nullptr;
+ for (const MemoryRegion& region : mappings)
+ {
+ if (elfBaseAddr == region.StartAddress())
+ moduleName = region.FileName();
+
+ if (!moduleName)
+ continue;
+
+ if ((uint64_t)shdrAddr < region.StartAddress() || (uint64_t)shdrAddr >= region.EndAddress())
+ continue;
+
+ if (!strcmp(region.FileName(), moduleName)) {
+ isValid = true;
+ break;
+ }
+ }
+
+ return isValid;
+}
+
//
// Add all the necessary ELF headers to the core dump
//
}
Ehdr ehdr;
if (!ReadMemory((void*)baseAddress, &ehdr, sizeof(ehdr))) {
- fprintf(stderr, "ReadMemory(%p, %lx) ehdr FAILED\n", (void*)baseAddress, sizeof(ehdr));
+ fprintf(stderr, "ReadMemory(%p, %" PRIx ") ehdr FAILED\n", (void*)baseAddress, sizeof(ehdr));
return false;
}
int phnum = ehdr.e_phnum;
assert(ehdr.e_shstrndx != SHN_XINDEX);
assert(ehdr.e_phentsize == sizeof(Phdr));
assert(ehdr.e_shentsize == sizeof(Shdr));
+#ifdef BIT64
assert(ehdr.e_ident[EI_CLASS] == ELFCLASS64);
+#else
+ assert(ehdr.e_ident[EI_CLASS] == ELFCLASS32);
+#endif
assert(ehdr.e_ident[EI_DATA] == ELFDATA2LSB);
- TRACE("ELF: type %d mach 0x%x ver %d flags 0x%x phnum %d phoff %016lx phentsize 0x%02x shnum %d shoff %016lx shentsize 0x%02x shstrndx %d\n",
+ TRACE("ELF: type %d mach 0x%x ver %d flags 0x%x phnum %d phoff %" PRIxA " phentsize 0x%02x shnum %d shoff %" PRIxA " shentsize 0x%02x shstrndx %d\n",
ehdr.e_type, ehdr.e_machine, ehdr.e_version, ehdr.e_flags, phnum, ehdr.e_phoff, ehdr.e_phentsize, shnum, ehdr.e_shoff, ehdr.e_shentsize, ehdr.e_shstrndx);
if (ehdr.e_phoff != 0 && phnum > 0)
{
Phdr ph;
if (!ReadMemory(phdrAddr, &ph, sizeof(ph))) {
- fprintf(stderr, "ReadMemory(%p, %lx) phdr FAILED\n", phdrAddr, sizeof(ph));
+ fprintf(stderr, "ReadMemory(%p, %" PRIx ") phdr FAILED\n", phdrAddr, sizeof(ph));
return false;
}
- TRACE("ELF: phdr %p type %d (%x) vaddr %016lx memsz %016lx paddr %016lx filesz %016lx offset %016lx align %016lx\n",
+ TRACE("ELF: phdr %p type %d (%x) vaddr %" PRIxA " memsz %" PRIxA " paddr %" PRIxA " filesz %" PRIxA " offset %" PRIxA " align %" PRIxA "\n",
phdrAddr, ph.p_type, ph.p_type, ph.p_vaddr, ph.p_memsz, ph.p_paddr, ph.p_filesz, ph.p_offset, ph.p_align);
if (ph.p_type == PT_DYNAMIC || ph.p_type == PT_NOTE || ph.p_type == PT_GNU_EH_FRAME)
if (baseAddress != m_auxvValues[AT_BASE] && ehdr.e_shoff != 0 && shnum > 0 && ehdr.e_shstrndx != SHN_UNDEF)
{
Shdr* shdrAddr = reinterpret_cast<Shdr*>(baseAddress + ehdr.e_shoff);
+ Shdr* stringTableShdrAddr = shdrAddr + ehdr.e_shstrndx;
+
+ // Check the section headers address. In some cases there isn't section header table in process memory.
+ if ((!ValidShdr(m_moduleMappings, baseAddress, shdrAddr) && !ValidShdr(m_otherMappings, baseAddress, shdrAddr)) ||
+ (!ValidShdr(m_moduleMappings, baseAddress, stringTableShdrAddr) && !ValidShdr(m_otherMappings, baseAddress, stringTableShdrAddr))) {
+ TRACE("ELF: %2d shdr %p Invalid section headers table address\n", ehdr.e_shstrndx, shdrAddr);
+ return true;
+ }
// Get the string table section header
Shdr stringTableSectionHeader;
- if (!ReadMemory(shdrAddr + ehdr.e_shstrndx, &stringTableSectionHeader, sizeof(stringTableSectionHeader))) {
- TRACE("ELF: %2d shdr %p ReadMemory string table section header FAILED\n", ehdr.e_shstrndx, shdrAddr + ehdr.e_shstrndx);
+ if (!ReadMemory(stringTableShdrAddr, &stringTableSectionHeader, sizeof(stringTableSectionHeader))) {
+ TRACE("ELF: %2d shdr %p ReadMemory string table section header FAILED\n", ehdr.e_shstrndx, stringTableShdrAddr);
return true;
}
+
// Get the string table
ArrayHolder<char> stringTable = new char[stringTableSectionHeader.sh_size];
if (!ReadMemory((void*)(baseAddress + stringTableSectionHeader.sh_offset), stringTable.GetPtr(), stringTableSectionHeader.sh_size)) {
TRACE("ELF: %2d shdr %p ReadMemory FAILED\n", sectionIndex, shdrAddr);
return true;
}
- TRACE("ELF: %2d shdr %p type %2d (%x) addr %016lx offset %016lx size %016lx link %08x info %08x name %4d %s\n",
+ TRACE("ELF: %2d shdr %p type %2d (%x) addr %" PRIxA " offset %" PRIxA " size %" PRIxA " link %08x info %08x name %4d %s\n",
sectionIndex, shdrAddr, sh.sh_type, sh.sh_type, sh.sh_addr, sh.sh_offset, sh.sh_size, sh.sh_link, sh.sh_info, sh.sh_name, &stringTable[sh.sh_name]);
if (sh.sh_name != SHN_UNDEF && sh.sh_offset > 0 && sh.sh_size > 0) {
NameCompare(name, ".note.gnu.ABI-tag") ||
NameCompare(name, ".gnu_debuglink"))
{
- TRACE("ELF: %s %p size %016lx\n", name, (void*)(baseAddress + sh.sh_offset), sh.sh_size);
+ TRACE("ELF: %s %p size %" PRIxA "\n", name, (void*)(baseAddress + sh.sh_offset), sh.sh_size);
InsertMemoryRegion(baseAddress + sh.sh_offset, sh.sh_size);
}
}
DacpGetModuleData moduleData;
if (SUCCEEDED(hr = moduleData.Request(clrDataModule)))
{
- TRACE("MODULE: %016lx dyn %d inmem %d file %d pe %016lx pdb %016lx", moduleData.LoadedPEAddress, moduleData.IsDynamic,
+ TRACE("MODULE: %" PRIA PRIx64 " dyn %d inmem %d file %d pe %" PRIA PRIx64 " pdb %" PRIA PRIx64, moduleData.LoadedPEAddress, moduleData.IsDynamic,
moduleData.IsInMemory, moduleData.IsFileLayout, moduleData.PEFile, moduleData.InMemoryPdbAddress);
if (!moduleData.IsDynamic && moduleData.LoadedPEAddress != 0)
{
// Add or change the module mapping for this PE image. The managed assembly images are
// already in the module mappings list but in .NET 2.0 they have the name "/dev/zero".
- MemoryRegion region(PF_R | PF_W | PF_X, baseAddress, baseAddress + PAGE_SIZE, 0, pszName);
+ MemoryRegion region(PF_R | PF_W | PF_X, (ULONG_PTR)baseAddress, (ULONG_PTR)(baseAddress + PAGE_SIZE), 0, pszName);
const auto& found = m_moduleMappings.find(region);
if (found == m_moduleMappings.end())
{
// The region overlaps/conflicts with one already in the set so add one page at a
// time to avoid the overlapping pages.
- uint64_t numberPages = region.Size() >> PAGE_SHIFT;
+ uint64_t numberPages = region.Size() / PAGE_SIZE;
for (int p = 0; p < numberPages; p++, start += PAGE_SIZE)
{
if (region.IsBackedByMemory())
{
uint64_t start = region.StartAddress();
- uint64_t numberPages = region.Size() >> PAGE_SHIFT;
+ uint64_t numberPages = region.Size() / PAGE_SIZE;
for (int p = 0; p < numberPages; p++, start += PAGE_SIZE)
{
BYTE buffer[1];
{
if (strncmp("PPid:\t", line, 6) == 0)
{
- *ppid = _atoi64(line + 6);
+ *ppid = atoll(line + 6);
}
else if (strncmp("Tgid:\t", line, 6) == 0)
{
- *tgid = _atoi64(line + 6);
+ *tgid = atoll(line + 6);
}
else if (strncmp("Name:\t", line, 6) == 0)
{
return false;
}
- TRACE("Writing %ld thread entries to core file\n", m_crashInfo.Threads().size());
+ TRACE("Writing %zd thread entries to core file\n", m_crashInfo.Threads().size());
// Write all the thread's state and registers
for (const ThreadInfo* thread : m_crashInfo.Threads())
}
}
- TRACE("Writing %ld memory regions to core file\n", m_crashInfo.MemoryRegions().size());
+ TRACE("Writing %zd memory regions to core file\n", m_crashInfo.MemoryRegions().size());
// Read from target process and write memory regions to core
uint64_t total = 0;
uint32_t read = 0;
if (FAILED(m_crashInfo.DataTarget()->ReadVirtual(address, m_tempBuffer, bytesToRead, &read))) {
- fprintf(stderr, "ReadVirtual(%016lx, %08x) FAILED\n", address, bytesToRead);
+ fprintf(stderr, "ReadVirtual(%" PRIA PRIx64 ", %08x) FAILED\n", address, bytesToRead);
return false;
}
}
}
- printf("Written %ld bytes (%ld pages) to core file\n", total, total >> PAGE_SHIFT);
+ printf("Written %" PRId64 " bytes (%" PRId64 " pages) to core file\n", total, total / PAGE_SIZE);
return true;
}
nhdr.n_descsz = m_crashInfo.GetAuxvSize();
nhdr.n_type = NT_AUXV;
- TRACE("Writing %ld auxv entries to core file\n", m_crashInfo.AuxvEntries().size());
+ TRACE("Writing %zd auxv entries to core file\n", m_crashInfo.AuxvEntries().size());
if (!WriteData(&nhdr, sizeof(nhdr)) ||
!WriteData("CORE\0AUX", 8)) {
struct NTFileEntry
{
- uint64_t StartAddress;
- uint64_t EndAddress;
- uint64_t Offset;
+ unsigned long StartAddress;
+ unsigned long EndAddress;
+ unsigned long Offset;
};
// Calculate the NT_FILE entries total size
size_t size = 0;
// Header, CORE, entry count, page size
- size = sizeof(Nhdr) + sizeof(NTFileEntry);
+ size = sizeof(Nhdr) + 8 + sizeof(count) + sizeof(size);
// start_address, end_address, offset
size += count * sizeof(NTFileEntry);
size_t count = m_crashInfo.ModuleMappings().size();
size_t pageSize = PAGE_SIZE;
- TRACE("Writing %ld NT_FILE entries to core file\n", m_crashInfo.ModuleMappings().size());
+ TRACE("Writing %zd NT_FILE entries to core file\n", m_crashInfo.ModuleMappings().size());
if (!WriteData(&nhdr, sizeof(nhdr)) ||
!WriteData("CORE\0FIL", 8) ||
- !WriteData(&count, 8) ||
- !WriteData(&pageSize, 8)) {
+ !WriteData(&count, sizeof(count)) ||
+ !WriteData(&pageSize, sizeof(pageSize))) {
return false;
}
return false;
}
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__arm__)
nhdr.n_descsz = sizeof(user_fpregs_struct);
nhdr.n_type = NT_FPREGSET;
if (!WriteData(&nhdr, sizeof(nhdr)) ||
}
#endif
+ nhdr.n_namesz = 6;
+
#if defined(__i386__)
nhdr.n_descsz = sizeof(user_fpxregs_struct);
nhdr.n_type = NT_PRXFPREG;
if (!WriteData(&nhdr, sizeof(nhdr)) ||
!WriteData("LINUX\0\0\0", 8) ||
- !WriteData(&thread.FPXRegisters(), sizeof(user_fpxregs_struct))) {
+ !WriteData(thread.FPXRegisters(), sizeof(user_fpxregs_struct))) {
+ return false;
+ }
+#endif
+
+#if defined(__arm__) && defined(__VFP_FP__) && !defined(__SOFTFP__)
+ nhdr.n_descsz = sizeof(user_vfpregs_struct);
+ nhdr.n_type = NT_ARM_VFP;
+ if (!WriteData(&nhdr, sizeof(nhdr)) ||
+ !WriteData("LINUX\0\0\0", 8) ||
+ !WriteData(thread.VFPRegisters(), sizeof(user_vfpregs_struct))) {
return false;
}
#endif
// See the LICENSE file in the project root for more information.
#include "createdump.h"
+#include <asm/ptrace.h>
#define FPREG_ErrorOffset(fpregs) *(DWORD*)&((fpregs).rip)
#define FPREG_ErrorSelector(fpregs) *(((WORD*)&((fpregs).rip)) + 2)
return false;
}
}
+
+#if defined(__arm__)
+ TRACE("Thread %04x PC %08lx SP %08lx\n", m_tid, (unsigned long)m_gpRegisters.ARM_pc, (unsigned long)m_gpRegisters.ARM_sp);
+#else
TRACE("Thread %04x RIP %016llx RSP %016llx\n", m_tid, (unsigned long long)m_gpRegisters.rip, (unsigned long long)m_gpRegisters.rsp);
+#endif
return true;
}
fprintf(stderr, "ptrace(GETFPXREGS, %d) FAILED %d (%s)\n", m_tid, errno, strerror(errno));
return false;
}
+#elif defined(__arm__) && defined(__VFP_FP__) && !defined(__SOFTFP__)
+
+#if defined(ARM_VFPREGS_SIZE)
+ assert(sizeof(m_vfpRegisters) == ARM_VFPREGS_SIZE);
+#endif
+
+ if (ptrace((__ptrace_request)PTRACE_GETVFPREGS, m_tid, nullptr, &m_vfpRegisters) == -1)
+ {
+ fprintf(stderr, "ptrace(PTRACE_GETVFPREGS, %d) FAILED %d (%s)\n", m_tid, errno, strerror(errno));
+ return false;
+ }
#endif
return true;
}
assert(sizeof(context.FltSave.XmmRegisters) == sizeof(m_fpRegisters.xmm_space));
memcpy(m_fpRegisters.xmm_space, context.FltSave.XmmRegisters, sizeof(m_fpRegisters.xmm_space));
+#elif defined(__arm__)
+ m_gpRegisters.ARM_sp = context.Sp;
+ m_gpRegisters.ARM_lr = context.Lr;
+ m_gpRegisters.ARM_pc = context.Pc;
+ m_gpRegisters.ARM_cpsr = context.Cpsr;
+
+ m_gpRegisters.ARM_r0 = context.R0;
+ m_gpRegisters.ARM_ORIG_r0 = context.R0;
+ m_gpRegisters.ARM_r1 = context.R1;
+ m_gpRegisters.ARM_r2 = context.R2;
+ m_gpRegisters.ARM_r3 = context.R3;
+ m_gpRegisters.ARM_r4 = context.R4;
+ m_gpRegisters.ARM_r5 = context.R5;
+ m_gpRegisters.ARM_r6 = context.R6;
+ m_gpRegisters.ARM_r7 = context.R7;
+ m_gpRegisters.ARM_r8 = context.R8;
+ m_gpRegisters.ARM_r9 = context.R9;
+ m_gpRegisters.ARM_r10 = context.R10;
+ m_gpRegisters.ARM_fp = context.R11;
+ m_gpRegisters.ARM_ip = context.R12;
+
+#if defined(__VFP_FP__) && !defined(__SOFTFP__)
+ m_vfpRegisters.fpscr = context.Fpscr;
+
+ assert(sizeof(context.D) == sizeof(m_vfpRegisters.fpregs));
+ memcpy(m_vfpRegisters.fpregs, context.D, sizeof(context.D));
+#endif
#else
#error Platform not supported
#endif
void
ThreadInfo::GetThreadStack(const CrashInfo& crashInfo, uint64_t* startAddress, size_t* size) const
{
+#if defined(__arm__)
+ *startAddress = m_gpRegisters.ARM_sp & PAGE_MASK;
+#else
*startAddress = m_gpRegisters.rsp & PAGE_MASK;
+#endif
*size = 4 * PAGE_SIZE;
const MemoryRegion* region = CrashInfo::SearchMemoryRegions(crashInfo.OtherMappings(), *startAddress);
if (g_diagnostics)
{
- TRACE("Thread %04x stack found in other mapping (size %08lx): ", m_tid, *size);
+ TRACE("Thread %04x stack found in other mapping (size %08zx): ", m_tid, *size);
region->Trace();
}
}
void
ThreadInfo::GetThreadCode(uint64_t* startAddress, size_t* size) const
{
+#if defined(__arm__)
+ *startAddress = m_gpRegisters.ARM_pc & PAGE_MASK;
+#elif defined(__x86_64__)
*startAddress = m_gpRegisters.rip & PAGE_MASK;
+#endif
*size = PAGE_SIZE;
}
memcpy(context->FltSave.XmmRegisters, m_fpRegisters.xmm_space, sizeof(context->FltSave.XmmRegisters));
}
// TODO: debug registers?
-#else
+#elif defined(__arm__)
+ if ((flags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
+ {
+ context->Sp = m_gpRegisters.ARM_sp;
+ context->Lr = m_gpRegisters.ARM_lr;
+ context->Pc = m_gpRegisters.ARM_pc;
+ context->Cpsr = m_gpRegisters.ARM_cpsr;
+
+ }
+ if ((flags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
+ {
+ context->R0 = m_gpRegisters.ARM_r0;
+ context->R1 = m_gpRegisters.ARM_r1;
+ context->R2 = m_gpRegisters.ARM_r2;
+ context->R3 = m_gpRegisters.ARM_r3;
+ context->R4 = m_gpRegisters.ARM_r4;
+ context->R5 = m_gpRegisters.ARM_r5;
+ context->R6 = m_gpRegisters.ARM_r6;
+ context->R7 = m_gpRegisters.ARM_r7;
+ context->R8 = m_gpRegisters.ARM_r8;
+ context->R9 = m_gpRegisters.ARM_r9;
+ context->R10 = m_gpRegisters.ARM_r10;
+ context->R11 = m_gpRegisters.ARM_fp;
+ context->R12 = m_gpRegisters.ARM_ip;
+ }
+ if ((flags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
+ {
+#if defined(__VFP_FP__) && !defined(__SOFTFP__)
+ context->Fpscr = m_vfpRegisters.fpscr;
+
+ assert(sizeof(context->D) == sizeof(m_vfpRegisters.fpregs));
+ memcpy(context->D, m_vfpRegisters.fpregs, sizeof(context->D));
+#endif
+ }
+#else
#error Platform not supported
#endif
}