sl@0
|
1 |
// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
|
sl@0
|
2 |
// All rights reserved.
|
sl@0
|
3 |
// This component and the accompanying materials are made available
|
sl@0
|
4 |
// under the terms of the License "Eclipse Public License v1.0"
|
sl@0
|
5 |
// which accompanies this distribution, and is available
|
sl@0
|
6 |
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
sl@0
|
7 |
//
|
sl@0
|
8 |
// Initial Contributors:
|
sl@0
|
9 |
// Nokia Corporation - initial contribution.
|
sl@0
|
10 |
//
|
sl@0
|
11 |
// Contributors:
|
sl@0
|
12 |
//
|
sl@0
|
13 |
// Description:
|
sl@0
|
14 |
// e32\kernel\arm\cscmdatasave.cpp
|
sl@0
|
15 |
// SCM - Arm portion
|
sl@0
|
16 |
//
|
sl@0
|
17 |
//
|
sl@0
|
18 |
|
sl@0
|
19 |
#define __INCLUDE_REG_OFFSETS__ // for SP_R13U in nk_plat.h
|
sl@0
|
20 |
|
sl@0
|
21 |
|
sl@0
|
22 |
#include "arm_mem.h"
|
sl@0
|
23 |
#include "nk_plat.h"
|
sl@0
|
24 |
#include <scmdatatypes.h>
|
sl@0
|
25 |
#include <scmdatasave.h>
|
sl@0
|
26 |
|
sl@0
|
27 |
|
sl@0
|
28 |
/**
|
sl@0
|
29 |
* Reads the CPU registers at the time of the crash
|
sl@0
|
30 |
* @param aRegs struct to store the resulting CPU registers
|
sl@0
|
31 |
*/
|
sl@0
|
32 |
void SCMDataSave::ReadCPURegisters(SFullArmRegSet& aRegs)
|
sl@0
|
33 |
{
|
sl@0
|
34 |
aRegs =*(SFullArmRegSet*)iMonitor->iRegs;
|
sl@0
|
35 |
}
|
sl@0
|
36 |
|
sl@0
|
37 |
/**
|
sl@0
|
38 |
* Reads the user registers for a given thread - may not be the current thread
|
sl@0
|
39 |
* @param aThread thread whose registers we want to read
|
sl@0
|
40 |
* @param aRegs registers will be written here if available
|
sl@0
|
41 |
* @return KErrArgument if aThread is the current thread or any of the system wide error codes
|
sl@0
|
42 |
*/
|
sl@0
|
43 |
TInt SCMDataSave::ReadUserRegisters(DThread* aThread, TArmRegSet& aRegs, TUint32& aAvailableRegs)
|
sl@0
|
44 |
{
|
sl@0
|
45 |
TFileName filename;
|
sl@0
|
46 |
aThread->TraceAppendFullName(filename, EFalse);
|
sl@0
|
47 |
|
sl@0
|
48 |
//we retrieve the registers differently for the current thread
|
sl@0
|
49 |
if(aThread == &Kern::CurrentThread())
|
sl@0
|
50 |
{
|
sl@0
|
51 |
return KErrArgument;
|
sl@0
|
52 |
}
|
sl@0
|
53 |
|
sl@0
|
54 |
TUint32* stackPointer = (TUint32*)aThread->iNThread.iSavedSP; //Still need to check pointer somehow
|
sl@0
|
55 |
TUint32* stackTop = (TUint32*)((TUint32)aThread->iNThread.iStackBase +(TUint32)aThread->iNThread.iStackSize);
|
sl@0
|
56 |
TArmReg* out = (TArmReg*)(&aRegs);
|
sl@0
|
57 |
|
sl@0
|
58 |
//Get a pointer to this threads context table
|
sl@0
|
59 |
NThread::TUserContextType type = aThread->iNThread.UserContextType();
|
sl@0
|
60 |
const TArmContextElement* table = aThread->iNThread.UserContextTables()[type];
|
sl@0
|
61 |
|
sl@0
|
62 |
aAvailableRegs = 0;
|
sl@0
|
63 |
for(TInt i = 0; i<KArmRegisterCount; ++i)
|
sl@0
|
64 |
{
|
sl@0
|
65 |
TInt value = table[i].iValue;
|
sl@0
|
66 |
TInt type = table[i].iType;
|
sl@0
|
67 |
|
sl@0
|
68 |
if(type == TArmContextElement::EOffsetFromSp)
|
sl@0
|
69 |
{
|
sl@0
|
70 |
value = stackPointer[value];
|
sl@0
|
71 |
aAvailableRegs |= (1<<i);
|
sl@0
|
72 |
}
|
sl@0
|
73 |
else if(type == TArmContextElement::EOffsetFromStackTop)
|
sl@0
|
74 |
{
|
sl@0
|
75 |
value = stackTop[-value];
|
sl@0
|
76 |
aAvailableRegs |= (1<<i);
|
sl@0
|
77 |
}
|
sl@0
|
78 |
else if(type == TArmContextElement::ESpPlusOffset)
|
sl@0
|
79 |
{
|
sl@0
|
80 |
value = (TInt)(stackPointer + value);
|
sl@0
|
81 |
aAvailableRegs |= (1<<i);
|
sl@0
|
82 |
}
|
sl@0
|
83 |
|
sl@0
|
84 |
out[i] = value;
|
sl@0
|
85 |
}
|
sl@0
|
86 |
|
sl@0
|
87 |
return KErrNone;
|
sl@0
|
88 |
}
|
sl@0
|
89 |
|
sl@0
|
90 |
/**
|
sl@0
|
91 |
* Reads the system registers for a given thread
|
sl@0
|
92 |
* Can not be used on the current thread
|
sl@0
|
93 |
* @param aThread
|
sl@0
|
94 |
* @param aRegs
|
sl@0
|
95 |
* @param aAvailableRegs
|
sl@0
|
96 |
* @return KErrArgument if aThread is the current thread or any of the system wide error codes
|
sl@0
|
97 |
*/
|
sl@0
|
98 |
TInt SCMDataSave::ReadSystemRegisters(DThread* aThread, TArmRegSet& aRegs, TUint32& aAvailableRegs)
|
sl@0
|
99 |
{
|
sl@0
|
100 |
if(aThread == &Kern::CurrentThread())
|
sl@0
|
101 |
{
|
sl@0
|
102 |
return KErrArgument;
|
sl@0
|
103 |
}
|
sl@0
|
104 |
|
sl@0
|
105 |
TFileName filename;
|
sl@0
|
106 |
aThread->TraceAppendFullName(filename, EFalse);
|
sl@0
|
107 |
|
sl@0
|
108 |
TUint32* stackPointer = (TUint32*)aThread->iNThread.iSavedSP;
|
sl@0
|
109 |
TUint32* stackTop = (TUint32*)((TUint32)aThread->iNThread.iStackBase +(TUint32)aThread->iNThread.iStackSize);
|
sl@0
|
110 |
TArmReg* out = (TArmReg*)(&aRegs);
|
sl@0
|
111 |
|
sl@0
|
112 |
//Get a pointer to this threads context table
|
sl@0
|
113 |
const TArmContextElement* table = aThread->iNThread.UserContextTables()[NThread::EContextKernel];
|
sl@0
|
114 |
|
sl@0
|
115 |
aAvailableRegs = 0;
|
sl@0
|
116 |
for(TInt i = 0; i<KArmRegisterCount; ++i)
|
sl@0
|
117 |
{
|
sl@0
|
118 |
TInt value = table[i].iValue;
|
sl@0
|
119 |
TInt type = table[i].iType;
|
sl@0
|
120 |
|
sl@0
|
121 |
if(type == TArmContextElement::EOffsetFromSp)
|
sl@0
|
122 |
{
|
sl@0
|
123 |
//ensure we are still on the stack
|
sl@0
|
124 |
if(stackPointer + value >= stackTop)
|
sl@0
|
125 |
continue;
|
sl@0
|
126 |
|
sl@0
|
127 |
value = stackPointer[value];
|
sl@0
|
128 |
aAvailableRegs |= (1<<i);
|
sl@0
|
129 |
}
|
sl@0
|
130 |
else if(type == TArmContextElement::EOffsetFromStackTop)
|
sl@0
|
131 |
{
|
sl@0
|
132 |
//ensure we are still on the stack
|
sl@0
|
133 |
if(stackTop - value < (TUint32*)aThread->iNThread.iStackBase)
|
sl@0
|
134 |
continue;
|
sl@0
|
135 |
|
sl@0
|
136 |
value = stackTop[-value];
|
sl@0
|
137 |
aAvailableRegs |= (1<<i);
|
sl@0
|
138 |
}
|
sl@0
|
139 |
else if(type == TArmContextElement::ESpPlusOffset)
|
sl@0
|
140 |
{
|
sl@0
|
141 |
value = (TInt)(stackPointer + value);
|
sl@0
|
142 |
aAvailableRegs |= (1<<i);
|
sl@0
|
143 |
}
|
sl@0
|
144 |
|
sl@0
|
145 |
out[i] = value;
|
sl@0
|
146 |
}
|
sl@0
|
147 |
|
sl@0
|
148 |
return KErrNone;
|
sl@0
|
149 |
}
|
sl@0
|
150 |
|
sl@0
|
151 |
//EOF
|
sl@0
|
152 |
|