summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/POSIX
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/POSIX')
-rw-r--r--lldb/source/Plugins/Process/POSIX/CMakeLists.txt1
-rw-r--r--lldb/source/Plugins/Process/POSIX/CrashReason.cpp315
-rw-r--r--lldb/source/Plugins/Process/POSIX/CrashReason.h62
-rw-r--r--lldb/source/Plugins/Process/POSIX/POSIXStopInfo.cpp15
-rw-r--r--lldb/source/Plugins/Process/POSIX/POSIXStopInfo.h22
-rw-r--r--lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp190
-rw-r--r--lldb/source/Plugins/Process/POSIX/ProcessMessage.h51
7 files changed, 402 insertions, 254 deletions
diff --git a/lldb/source/Plugins/Process/POSIX/CMakeLists.txt b/lldb/source/Plugins/Process/POSIX/CMakeLists.txt
index 8fd7bd1fc8a..3e1654fb9c5 100644
--- a/lldb/source/Plugins/Process/POSIX/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/POSIX/CMakeLists.txt
@@ -5,6 +5,7 @@ include_directories(../Linux)
include_directories(../Utility)
add_lldb_library(lldbPluginProcessPOSIX
+ CrashReason.cpp
POSIXStopInfo.cpp
POSIXThread.cpp
ProcessMessage.cpp
diff --git a/lldb/source/Plugins/Process/POSIX/CrashReason.cpp b/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
new file mode 100644
index 00000000000..4dd91a6f1de
--- /dev/null
+++ b/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
@@ -0,0 +1,315 @@
+//===-- CrashReason.cpp -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CrashReason.h"
+
+#include <sstream>
+
+namespace {
+
+void
+AppendFaultAddr (std::string& str, lldb::addr_t addr)
+{
+ std::stringstream ss;
+ ss << " (fault address: 0x" << std::hex << addr << ")";
+ str += ss.str();
+}
+
+CrashReason
+GetCrashReasonForSIGSEGV(const siginfo_t& info)
+{
+ assert(info.si_signo == SIGSEGV);
+
+ switch (info.si_code)
+ {
+ case SI_KERNEL:
+ // Linux will occasionally send spurious SI_KERNEL codes.
+ // (this is poorly documented in sigaction)
+ // One way to get this is via unaligned SIMD loads.
+ return CrashReason::eInvalidAddress; // for lack of anything better
+ case SEGV_MAPERR:
+ return CrashReason::eInvalidAddress;
+ case SEGV_ACCERR:
+ return CrashReason::ePrivilegedAddress;
+ }
+
+ assert(false && "unexpected si_code for SIGSEGV");
+ return CrashReason::eInvalidCrashReason;
+}
+
+CrashReason
+GetCrashReasonForSIGILL(const siginfo_t& info)
+{
+ assert(info.si_signo == SIGILL);
+
+ switch (info.si_code)
+ {
+ case ILL_ILLOPC:
+ return CrashReason::eIllegalOpcode;
+ case ILL_ILLOPN:
+ return CrashReason::eIllegalOperand;
+ case ILL_ILLADR:
+ return CrashReason::eIllegalAddressingMode;
+ case ILL_ILLTRP:
+ return CrashReason::eIllegalTrap;
+ case ILL_PRVOPC:
+ return CrashReason::ePrivilegedOpcode;
+ case ILL_PRVREG:
+ return CrashReason::ePrivilegedRegister;
+ case ILL_COPROC:
+ return CrashReason::eCoprocessorError;
+ case ILL_BADSTK:
+ return CrashReason::eInternalStackError;
+ }
+
+ assert(false && "unexpected si_code for SIGILL");
+ return CrashReason::eInvalidCrashReason;
+}
+
+CrashReason
+GetCrashReasonForSIGFPE(const siginfo_t& info)
+{
+ assert(info.si_signo == SIGFPE);
+
+ switch (info.si_code)
+ {
+ case FPE_INTDIV:
+ return CrashReason::eIntegerDivideByZero;
+ case FPE_INTOVF:
+ return CrashReason::eIntegerOverflow;
+ case FPE_FLTDIV:
+ return CrashReason::eFloatDivideByZero;
+ case FPE_FLTOVF:
+ return CrashReason::eFloatOverflow;
+ case FPE_FLTUND:
+ return CrashReason::eFloatUnderflow;
+ case FPE_FLTRES:
+ return CrashReason::eFloatInexactResult;
+ case FPE_FLTINV:
+ return CrashReason::eFloatInvalidOperation;
+ case FPE_FLTSUB:
+ return CrashReason::eFloatSubscriptRange;
+ }
+
+ assert(false && "unexpected si_code for SIGFPE");
+ return CrashReason::eInvalidCrashReason;
+}
+
+CrashReason
+GetCrashReasonForSIGBUS(const siginfo_t& info)
+{
+ assert(info.si_signo == SIGBUS);
+
+ switch (info.si_code)
+ {
+ case BUS_ADRALN:
+ return CrashReason::eIllegalAlignment;
+ case BUS_ADRERR:
+ return CrashReason::eIllegalAddress;
+ case BUS_OBJERR:
+ return CrashReason::eHardwareError;
+ }
+
+ assert(false && "unexpected si_code for SIGBUS");
+ return CrashReason::eInvalidCrashReason;
+}
+
+}
+
+std::string
+GetCrashReasonString (CrashReason reason, lldb::addr_t fault_addr)
+{
+ std::string str;
+
+ switch (reason)
+ {
+ default:
+ assert(false && "invalid CrashReason");
+ break;
+
+ case CrashReason::eInvalidAddress:
+ str = "invalid address";
+ AppendFaultAddr (str, fault_addr);
+ break;
+ case CrashReason::ePrivilegedAddress:
+ str = "address access protected";
+ AppendFaultAddr (str, fault_addr);
+ break;
+ case CrashReason::eIllegalOpcode:
+ str = "illegal instruction";
+ break;
+ case CrashReason::eIllegalOperand:
+ str = "illegal instruction operand";
+ break;
+ case CrashReason::eIllegalAddressingMode:
+ str = "illegal addressing mode";
+ break;
+ case CrashReason::eIllegalTrap:
+ str = "illegal trap";
+ break;
+ case CrashReason::ePrivilegedOpcode:
+ str = "privileged instruction";
+ break;
+ case CrashReason::ePrivilegedRegister:
+ str = "privileged register";
+ break;
+ case CrashReason::eCoprocessorError:
+ str = "coprocessor error";
+ break;
+ case CrashReason::eInternalStackError:
+ str = "internal stack error";
+ break;
+ case CrashReason::eIllegalAlignment:
+ str = "illegal alignment";
+ break;
+ case CrashReason::eIllegalAddress:
+ str = "illegal address";
+ break;
+ case CrashReason::eHardwareError:
+ str = "hardware error";
+ break;
+ case CrashReason::eIntegerDivideByZero:
+ str = "integer divide by zero";
+ break;
+ case CrashReason::eIntegerOverflow:
+ str = "integer overflow";
+ break;
+ case CrashReason::eFloatDivideByZero:
+ str = "floating point divide by zero";
+ break;
+ case CrashReason::eFloatOverflow:
+ str = "floating point overflow";
+ break;
+ case CrashReason::eFloatUnderflow:
+ str = "floating point underflow";
+ break;
+ case CrashReason::eFloatInexactResult:
+ str = "inexact floating point result";
+ break;
+ case CrashReason::eFloatInvalidOperation:
+ str = "invalid floating point operation";
+ break;
+ case CrashReason::eFloatSubscriptRange:
+ str = "invalid floating point subscript range";
+ break;
+ }
+
+ return str;
+}
+
+const char *
+CrashReasonAsString (CrashReason reason)
+{
+#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION
+ // Just return the code in ascii for integration builds.
+ chcar str[8];
+ sprintf(str, "%d", reason);
+#else
+ const char *str = nullptr;
+
+ switch (reason)
+ {
+ case CrashReason::eInvalidCrashReason:
+ str = "eInvalidCrashReason";
+ break;
+
+ // SIGSEGV crash reasons.
+ case CrashReason::eInvalidAddress:
+ str = "eInvalidAddress";
+ break;
+ case CrashReason::ePrivilegedAddress:
+ str = "ePrivilegedAddress";
+ break;
+
+ // SIGILL crash reasons.
+ case CrashReason::eIllegalOpcode:
+ str = "eIllegalOpcode";
+ break;
+ case CrashReason::eIllegalOperand:
+ str = "eIllegalOperand";
+ break;
+ case CrashReason::eIllegalAddressingMode:
+ str = "eIllegalAddressingMode";
+ break;
+ case CrashReason::eIllegalTrap:
+ str = "eIllegalTrap";
+ break;
+ case CrashReason::ePrivilegedOpcode:
+ str = "ePrivilegedOpcode";
+ break;
+ case CrashReason::ePrivilegedRegister:
+ str = "ePrivilegedRegister";
+ break;
+ case CrashReason::eCoprocessorError:
+ str = "eCoprocessorError";
+ break;
+ case CrashReason::eInternalStackError:
+ str = "eInternalStackError";
+ break;
+
+ // SIGBUS crash reasons:
+ case CrashReason::eIllegalAlignment:
+ str = "eIllegalAlignment";
+ break;
+ case CrashReason::eIllegalAddress:
+ str = "eIllegalAddress";
+ break;
+ case CrashReason::eHardwareError:
+ str = "eHardwareError";
+ break;
+
+ // SIGFPE crash reasons:
+ case CrashReason::eIntegerDivideByZero:
+ str = "eIntegerDivideByZero";
+ break;
+ case CrashReason::eIntegerOverflow:
+ str = "eIntegerOverflow";
+ break;
+ case CrashReason::eFloatDivideByZero:
+ str = "eFloatDivideByZero";
+ break;
+ case CrashReason::eFloatOverflow:
+ str = "eFloatOverflow";
+ break;
+ case CrashReason::eFloatUnderflow:
+ str = "eFloatUnderflow";
+ break;
+ case CrashReason::eFloatInexactResult:
+ str = "eFloatInexactResult";
+ break;
+ case CrashReason::eFloatInvalidOperation:
+ str = "eFloatInvalidOperation";
+ break;
+ case CrashReason::eFloatSubscriptRange:
+ str = "eFloatSubscriptRange";
+ break;
+ }
+#endif
+
+ return str;
+}
+
+CrashReason
+GetCrashReason(const siginfo_t& info)
+{
+ switch(info.si_signo)
+ {
+ case SIGSEGV:
+ return GetCrashReasonForSIGSEGV(info);
+ case SIGBUS:
+ return GetCrashReasonForSIGBUS(info);
+ case SIGFPE:
+ return GetCrashReasonForSIGFPE(info);
+ case SIGILL:
+ return GetCrashReasonForSIGILL(info);
+ }
+
+ assert(false && "unexpected signal");
+ return CrashReason::eInvalidCrashReason;
+}
diff --git a/lldb/source/Plugins/Process/POSIX/CrashReason.h b/lldb/source/Plugins/Process/POSIX/CrashReason.h
new file mode 100644
index 00000000000..f6d9ba553e4
--- /dev/null
+++ b/lldb/source/Plugins/Process/POSIX/CrashReason.h
@@ -0,0 +1,62 @@
+//===-- CrashReason.h -------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_CrashReason_H_
+#define liblldb_CrashReason_H_
+
+#include "lldb/lldb-types.h"
+
+#include <signal.h>
+
+#include <string>
+
+enum class CrashReason
+{
+ eInvalidCrashReason,
+
+ // SIGSEGV crash reasons.
+ eInvalidAddress,
+ ePrivilegedAddress,
+
+ // SIGILL crash reasons.
+ eIllegalOpcode,
+ eIllegalOperand,
+ eIllegalAddressingMode,
+ eIllegalTrap,
+ ePrivilegedOpcode,
+ ePrivilegedRegister,
+ eCoprocessorError,
+ eInternalStackError,
+
+ // SIGBUS crash reasons,
+ eIllegalAlignment,
+ eIllegalAddress,
+ eHardwareError,
+
+ // SIGFPE crash reasons,
+ eIntegerDivideByZero,
+ eIntegerOverflow,
+ eFloatDivideByZero,
+ eFloatOverflow,
+ eFloatUnderflow,
+ eFloatInexactResult,
+ eFloatInvalidOperation,
+ eFloatSubscriptRange
+};
+
+std::string
+GetCrashReasonString (CrashReason reason, lldb::addr_t fault_addr);
+
+const char *
+CrashReasonAsString (CrashReason reason);
+
+CrashReason
+GetCrashReason(const siginfo_t& info);
+
+#endif // #ifndef liblldb_CrashReason_H_
diff --git a/lldb/source/Plugins/Process/POSIX/POSIXStopInfo.cpp b/lldb/source/Plugins/Process/POSIX/POSIXStopInfo.cpp
index 6e2c140682b..3b8cea737bc 100644
--- a/lldb/source/Plugins/Process/POSIX/POSIXStopInfo.cpp
+++ b/lldb/source/Plugins/Process/POSIX/POSIXStopInfo.cpp
@@ -45,6 +45,15 @@ POSIXLimboStopInfo::ShouldNotify(Event *event_ptr)
//===----------------------------------------------------------------------===//
// POSIXCrashStopInfo
+POSIXCrashStopInfo::POSIXCrashStopInfo(POSIXThread &thread,
+ uint32_t status,
+ CrashReason reason,
+ lldb::addr_t fault_addr)
+ : POSIXStopInfo(thread, status)
+{
+ m_description = ::GetCrashReasonString(reason, fault_addr);
+}
+
POSIXCrashStopInfo::~POSIXCrashStopInfo() { }
lldb::StopReason
@@ -53,12 +62,6 @@ POSIXCrashStopInfo::GetStopReason() const
return lldb::eStopReasonException;
}
-const char *
-POSIXCrashStopInfo::GetDescription()
-{
- return ProcessMessage::GetCrashReasonString(m_crash_reason, m_fault_addr);
-}
-
//===----------------------------------------------------------------------===//
// POSIXNewThreadStopInfo
diff --git a/lldb/source/Plugins/Process/POSIX/POSIXStopInfo.h b/lldb/source/Plugins/Process/POSIX/POSIXStopInfo.h
index cbf309e5350..a1ee2ea6852 100644
--- a/lldb/source/Plugins/Process/POSIX/POSIXStopInfo.h
+++ b/lldb/source/Plugins/Process/POSIX/POSIXStopInfo.h
@@ -16,8 +16,10 @@
// Project includes
#include "lldb/Target/StopInfo.h"
+#include "CrashReason.h"
#include "POSIXThread.h"
-#include "ProcessMessage.h"
+
+#include <string>
//===----------------------------------------------------------------------===//
/// @class POSIXStopInfo
@@ -69,25 +71,13 @@ class POSIXCrashStopInfo
{
public:
POSIXCrashStopInfo(POSIXThread &thread, uint32_t status,
- ProcessMessage::CrashReason reason,
- lldb::addr_t fault_addr)
- : POSIXStopInfo(thread, status),
- m_crash_reason(reason),
- m_fault_addr(fault_addr)
- { }
-
+ CrashReason reason,
+ lldb::addr_t fault_addr);
~POSIXCrashStopInfo();
lldb::StopReason
GetStopReason() const;
-
- const char *
- GetDescription();
-
-private:
- ProcessMessage::CrashReason m_crash_reason;
- lldb::addr_t m_fault_addr;
-};
+};
//===----------------------------------------------------------------------===//
/// @class POSIXNewThreadStopInfo
diff --git a/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp b/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp
index 5c53627f9e0..02049a2af95 100644
--- a/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp
+++ b/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp
@@ -9,205 +9,19 @@
#include "ProcessMessage.h"
-#include <sstream>
-
using namespace lldb_private;
-namespace {
-
-inline void AppendFaultAddr(std::string& str, lldb::addr_t addr)
-{
- std::stringstream ss;
- ss << " (fault address: 0x" << std::hex << addr << ")";
- str += ss.str();
-}
-
-}
-
-const char *
-ProcessMessage::GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr)
-{
- static std::string str;
-
- switch (reason)
- {
- default:
- assert(false && "invalid CrashReason");
- break;
-
- case eInvalidAddress:
- str = "invalid address";
- AppendFaultAddr(str, fault_addr);
- break;
- case ePrivilegedAddress:
- str = "address access protected";
- AppendFaultAddr(str, fault_addr);
- break;
- case eIllegalOpcode:
- str = "illegal instruction";
- break;
- case eIllegalOperand:
- str = "illegal instruction operand";
- break;
- case eIllegalAddressingMode:
- str = "illegal addressing mode";
- break;
- case eIllegalTrap:
- str = "illegal trap";
- break;
- case ePrivilegedOpcode:
- str = "privileged instruction";
- break;
- case ePrivilegedRegister:
- str = "privileged register";
- break;
- case eCoprocessorError:
- str = "coprocessor error";
- break;
- case eInternalStackError:
- str = "internal stack error";
- break;
- case eIllegalAlignment:
- str = "illegal alignment";
- break;
- case eIllegalAddress:
- str = "illegal address";
- break;
- case eHardwareError:
- str = "hardware error";
- break;
- case eIntegerDivideByZero:
- str = "integer divide by zero";
- break;
- case eIntegerOverflow:
- str = "integer overflow";
- break;
- case eFloatDivideByZero:
- str = "floating point divide by zero";
- break;
- case eFloatOverflow:
- str = "floating point overflow";
- break;
- case eFloatUnderflow:
- str = "floating point underflow";
- break;
- case eFloatInexactResult:
- str = "inexact floating point result";
- break;
- case eFloatInvalidOperation:
- str = "invalid floating point operation";
- break;
- case eFloatSubscriptRange:
- str = "invalid floating point subscript range";
- break;
- }
-
- return str.c_str();
-}
-
-const char *
-ProcessMessage::PrintCrashReason(CrashReason reason)
-{
-#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION
- // Just return the code in asci for integration builds.
- chcar str[8];
- sprintf(str, "%d", reason);
-#else
- const char *str = NULL;
-
- switch (reason)
- {
- case eInvalidCrashReason:
- str = "eInvalidCrashReason";
- break;
-
- // SIGSEGV crash reasons.
- case eInvalidAddress:
- str = "eInvalidAddress";
- break;
- case ePrivilegedAddress:
- str = "ePrivilegedAddress";
- break;
-
- // SIGILL crash reasons.
- case eIllegalOpcode:
- str = "eIllegalOpcode";
- break;
- case eIllegalOperand:
- str = "eIllegalOperand";
- break;
- case eIllegalAddressingMode:
- str = "eIllegalAddressingMode";
- break;
- case eIllegalTrap:
- str = "eIllegalTrap";
- break;
- case ePrivilegedOpcode:
- str = "ePrivilegedOpcode";
- break;
- case ePrivilegedRegister:
- str = "ePrivilegedRegister";
- break;
- case eCoprocessorError:
- str = "eCoprocessorError";
- break;
- case eInternalStackError:
- str = "eInternalStackError";
- break;
-
- // SIGBUS crash reasons:
- case eIllegalAlignment:
- str = "eIllegalAlignment";
- break;
- case eIllegalAddress:
- str = "eIllegalAddress";
- break;
- case eHardwareError:
- str = "eHardwareError";
- break;
-
- // SIGFPE crash reasons:
- case eIntegerDivideByZero:
- str = "eIntegerDivideByZero";
- break;
- case eIntegerOverflow:
- str = "eIntegerOverflow";
- break;
- case eFloatDivideByZero:
- str = "eFloatDivideByZero";
- break;
- case eFloatOverflow:
- str = "eFloatOverflow";
- break;
- case eFloatUnderflow:
- str = "eFloatUnderflow";
- break;
- case eFloatInexactResult:
- str = "eFloatInexactResult";
- break;
- case eFloatInvalidOperation:
- str = "eFloatInvalidOperation";
- break;
- case eFloatSubscriptRange:
- str = "eFloatSubscriptRange";
- break;
- }
-#endif
-
- return str;
-}
-
const char *
ProcessMessage::PrintCrashReason() const
{
- return PrintCrashReason(m_crash_reason);
+ return CrashReasonAsString(m_crash_reason);
}
const char *
ProcessMessage::PrintKind(Kind kind)
{
#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION
- // Just return the code in asci for integration builds.
+ // Just return the code in ascii for integration builds.
chcar str[8];
sprintf(str, "%d", reason);
#else
diff --git a/lldb/source/Plugins/Process/POSIX/ProcessMessage.h b/lldb/source/Plugins/Process/POSIX/ProcessMessage.h
index 40462d0f0e1..f932e9fff27 100644
--- a/lldb/source/Plugins/Process/POSIX/ProcessMessage.h
+++ b/lldb/source/Plugins/Process/POSIX/ProcessMessage.h
@@ -10,7 +10,10 @@
#ifndef liblldb_ProcessMessage_H_
#define liblldb_ProcessMessage_H_
+#include "CrashReason.h"
+
#include <cassert>
+#include <string>
#include "lldb/lldb-defines.h"
#include "lldb/lldb-types.h"
@@ -36,44 +39,10 @@ public:
eExecMessage
};
- enum CrashReason
- {
- eInvalidCrashReason,
-
- // SIGSEGV crash reasons.
- eInvalidAddress,
- ePrivilegedAddress,
-
- // SIGILL crash reasons.
- eIllegalOpcode,
- eIllegalOperand,
- eIllegalAddressingMode,
- eIllegalTrap,
- ePrivilegedOpcode,
- ePrivilegedRegister,
- eCoprocessorError,
- eInternalStackError,
-
- // SIGBUS crash reasons,
- eIllegalAlignment,
- eIllegalAddress,
- eHardwareError,
-
- // SIGFPE crash reasons,
- eIntegerDivideByZero,
- eIntegerOverflow,
- eFloatDivideByZero,
- eFloatOverflow,
- eFloatUnderflow,
- eFloatInexactResult,
- eFloatInvalidOperation,
- eFloatSubscriptRange
- };
-
ProcessMessage()
: m_tid(LLDB_INVALID_PROCESS_ID),
m_kind(eInvalidMessage),
- m_crash_reason(eInvalidCrashReason),
+ m_crash_reason(CrashReason::eInvalidCrashReason),
m_status(0),
m_addr(0) { }
@@ -175,15 +144,9 @@ public:
return m_child_tid;
}
- static const char *
- GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr);
-
const char *
PrintCrashReason() const;
- static const char *
- PrintCrashReason(CrashReason reason);
-
const char *
PrintKind() const;
@@ -195,7 +158,7 @@ private:
int status = 0, lldb::addr_t addr = 0)
: m_tid(tid),
m_kind(kind),
- m_crash_reason(eInvalidCrashReason),
+ m_crash_reason(CrashReason::eInvalidCrashReason),
m_status(status),
m_addr(addr),
m_child_tid(0) { }
@@ -203,14 +166,14 @@ private:
ProcessMessage(lldb::tid_t tid, Kind kind, lldb::tid_t child_tid)
: m_tid(tid),
m_kind(kind),
- m_crash_reason(eInvalidCrashReason),
+ m_crash_reason(CrashReason::eInvalidCrashReason),
m_status(0),
m_addr(0),
m_child_tid(child_tid) { }
lldb::tid_t m_tid;
Kind m_kind : 8;
- CrashReason m_crash_reason : 8;
+ CrashReason m_crash_reason;
int m_status;
lldb::addr_t m_addr;
lldb::tid_t m_child_tid;
OpenPOWER on IntegriCloud