arm: Fixes based on UBSan and static analysis

Another churn to clean up undefined behaviour, mostly ARM, but some
parts also touching the generic part of the code base.

Most of the fixes are simply ensuring that proper intialisation. One
of the more subtle changes is the return type of the sign-extension,
which is changed to uint64_t. This is to avoid shifting negative
values (undefined behaviour) in the ISA code.
This commit is contained in:
Andreas Hansson 2014-11-14 03:53:51 -05:00
parent 9ffe0e7ba6
commit 481eb6ae80
35 changed files with 82 additions and 74 deletions

View file

@ -172,7 +172,8 @@ class ArmFault : public FaultBase
};
ArmFault(ExtMachInst _machInst = 0, uint32_t _iss = 0) :
machInst(_machInst), issRaw(_iss), from64(false), to64(false) {}
machInst(_machInst), issRaw(_iss), from64(false), to64(false),
fromEL(EL0), toEL(EL0), fromMode(MODE_UNDEFINED) {}
// Returns the actual syndrome register to use based on the target
// exception level
@ -395,9 +396,11 @@ class AbortFault : public ArmFaultVals<T>
ArmFault::TranMethod tranMethod;
public:
AbortFault(Addr _faultAddr, bool _write, TlbEntry::DomainType _domain, uint8_t _source,
bool _stage2, ArmFault::TranMethod _tranMethod = ArmFault::UnknownTran) :
faultAddr(_faultAddr), write(_write), domain(_domain), source(_source),
AbortFault(Addr _faultAddr, bool _write, TlbEntry::DomainType _domain,
uint8_t _source, bool _stage2,
ArmFault::TranMethod _tranMethod = ArmFault::UnknownTran) :
faultAddr(_faultAddr), OVAddr(0), write(_write),
domain(_domain), source(_source), srcEncoded(0),
stage2(_stage2), s1ptw(false), tranMethod(_tranMethod)
{}

View file

@ -1281,7 +1281,10 @@ VldSingleOp64::VldSingleOp64(const char *mnem, ExtMachInst machInst,
RegIndex rm, uint8_t eSize, uint8_t dataSize,
uint8_t numStructElems, uint8_t index, bool wb,
bool replicate) :
PredMacroOp(mnem, machInst, __opClass)
PredMacroOp(mnem, machInst, __opClass),
eSize(0), dataSize(0), numStructElems(0), index(0),
wb(false), replicate(false)
{
RegIndex vx = NumFloatV8ArchRegs / 4;
RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);
@ -1352,7 +1355,9 @@ VstSingleOp64::VstSingleOp64(const char *mnem, ExtMachInst machInst,
RegIndex rm, uint8_t eSize, uint8_t dataSize,
uint8_t numStructElems, uint8_t index, bool wb,
bool replicate) :
PredMacroOp(mnem, machInst, __opClass)
PredMacroOp(mnem, machInst, __opClass),
eSize(0), dataSize(0), numStructElems(0), index(0),
wb(false), replicate(false)
{
RegIndex vx = NumFloatV8ArchRegs / 4;
RegIndex rnsp = (RegIndex) makeSP((IntRegIndex) rn);

View file

@ -101,7 +101,7 @@ class Memory64 : public MightBeMicro64
Memory64(const char *mnem, ExtMachInst _machInst, OpClass __opClass,
IntRegIndex _dest, IntRegIndex _base)
: MightBeMicro64(mnem, _machInst, __opClass),
dest(_dest), base(_base), uops(NULL)
dest(_dest), base(_base), uops(NULL), memAccessFlags(0)
{
baseIsSP = isSP(_base);
}

View file

@ -294,7 +294,6 @@ class RegImmImmOp : public PredOp
{
protected:
IntRegIndex dest;
IntRegIndex op1;
uint64_t imm1;
uint64_t imm2;

View file

@ -312,7 +312,7 @@ class PredMacroOp : public PredOp
/// Constructor
PredMacroOp(const char *mnem, ExtMachInst _machInst, OpClass __opClass) :
PredOp(mnem, _machInst, __opClass),
numMicroops(0)
numMicroops(0), microOps(nullptr)
{
// We rely on the subclasses of this object to handle the
// initialization of the micro-operations, since they are

View file

@ -84,7 +84,8 @@ let {{
diff += intWidth;
}
uint64_t topBits M5_VAR_USED = ~mask(diff+1);
uint64_t result = (Op164 >> imm1) | (Op164 << (intWidth - imm1));
uint64_t result = imm1 == 0 ? Op164 :
(Op164 >> imm1) | (Op164 << (intWidth - imm1));
result &= bitMask;
'''

View file

@ -185,7 +185,8 @@ let {{
if name == 'deint_neon_uop':
eCode = '''
VReg input[4]; // input data from scratch area
// input data from scratch area
VReg input[4] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
VReg output[2]; // output data to arch. SIMD regs
VReg temp;
temp.lo = 0;
@ -270,7 +271,8 @@ let {{
elif name == 'int_neon_uop':
eCode = '''
VReg input[4]; // input data from arch. SIMD regs
// input data from arch. SIMD regs
VReg input[4] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
VReg output[2]; // output data to scratch area
'''
@ -332,7 +334,8 @@ let {{
elif name == 'unpack_neon_uop':
eCode = '''
VReg input[4]; //input data from scratch area
//input data from scratch area
VReg input[4] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
VReg output[2]; //output data to arch. SIMD regs
'''
@ -398,7 +401,8 @@ let {{
elif name == 'pack_neon_uop':
eCode = '''
VReg input[4]; // input data from arch. SIMD regs
// input data from arch. SIMD regs
VReg input[4] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
VReg output[2]; // output data to scratch area
'''

View file

@ -61,9 +61,9 @@ using namespace ArmISA;
using namespace Linux;
LinuxArmSystem::LinuxArmSystem(Params *p)
: ArmSystem(p),
: ArmSystem(p), dumpStatsPCEvent(nullptr),
enableContextSwitchStatsDump(p->enable_context_switch_stats_dump),
kernelPanicEvent(NULL), kernelOopsEvent(NULL),
taskFile(nullptr), kernelPanicEvent(nullptr), kernelOopsEvent(nullptr),
bootReleaseAddr(p->boot_release_addr)
{
if (p->panic_on_panic) {

View file

@ -95,7 +95,7 @@ PMU::addEventProbe(unsigned int id, SimObject *obj, const char *probe_name)
// Flag the event as available in the PMCEID register if it is an
// architected event.
if (id < 0x40)
reg_pmceid |= (1 << id);
reg_pmceid |= (ULL(1) << id);
}
void

View file

@ -67,7 +67,6 @@ class ArmLiveProcess : public LiveProcess
class ArmLiveProcess32 : public ArmLiveProcess
{
protected:
ObjectFile::Arch arch;
ArmLiveProcess32(LiveProcessParams * params, ObjectFile *objFile,
ObjectFile::Arch _arch);
@ -84,7 +83,6 @@ class ArmLiveProcess32 : public ArmLiveProcess
class ArmLiveProcess64 : public ArmLiveProcess
{
protected:
ObjectFile::Arch arch;
ArmLiveProcess64(LiveProcessParams * params, ObjectFile *objFile,
ObjectFile::Arch _arch);

View file

@ -160,7 +160,7 @@ using namespace std;
using namespace ArmISA;
RemoteGDB::RemoteGDB(System *_system, ThreadContext *tc)
: BaseRemoteGDB(_system, tc, MAX_NUMREGS)
: BaseRemoteGDB(_system, tc, MAX_NUMREGS), notTakenBkpt(0), takenBkpt(0)
{
}

View file

@ -80,8 +80,8 @@ class Stage2LookUp : public BaseTLB::Translation
bool _functional, TLB::ArmTranslationType _tranType) :
stage1Tlb(s1Tlb), stage2Tlb(s2Tlb), stage1Te(s1Te), s1Req(_req),
transState(_transState), mode(_mode), timing(_timing),
functional(_functional), tranType(_tranType), fault(NoFault),
complete(false), selfDelete(false)
functional(_functional), tranType(_tranType), stage2Te(nullptr),
fault(NoFault), complete(false), selfDelete(false)
{
req.setVirt(0, s1Te.pAddr(s1Req->getVaddr()), s1Req->getSize(),
s1Req->getFlags(), s1Req->masterId(), 0);

View file

@ -108,7 +108,7 @@ Stage2MMU::readDataTimed(ThreadContext *tc, Addr descAddr,
Stage2MMU::Stage2Translation::Stage2Translation(Stage2MMU &_parent,
uint8_t *_data, Event *_event, Addr _oVAddr)
: data(_data), event(_event), parent(_parent), oVAddr(_oVAddr),
: data(_data), numBytes(0), event(_event), parent(_parent), oVAddr(_oVAddr),
fault(NoFault)
{
}

View file

@ -58,6 +58,7 @@ ArmSystem::ArmSystem(Params *p)
_haveLPAE(p->have_lpae),
_haveVirtualization(p->have_virtualization),
_haveGenericTimer(p->have_generic_timer),
_genericTimer(nullptr),
_highestELIs64(p->highest_el_is_64),
_resetAddr64(p->reset_addr_64),
_physAddrRange64(p->phys_addr_range_64),

View file

@ -90,7 +90,15 @@ TableWalker::~TableWalker()
;
}
TableWalker::WalkerState::WalkerState() : stage2Tran(NULL), l2Desc(l1Desc)
TableWalker::WalkerState::WalkerState() :
tc(nullptr), aarch64(false), el(EL0), physAddrRange(0), req(nullptr),
asid(0), vmid(0), isHyp(false), transState(nullptr),
vaddr(0), vaddr_tainted(0), isWrite(false), isFetch(false), isSecure(false),
secureLookup(false), rwTable(false), userTable(false), xnTable(false),
pxnTable(false), stage2Req(false), doingStage2(false),
stage2Tran(nullptr), timing(false), functional(false),
mode(BaseTLB::Read), tranType(TLB::NormalTran), l2Desc(l1Desc),
delayed(false), tableWalker(nullptr)
{
}

View file

@ -106,7 +106,7 @@ class TableWalker : public MemObject
bool _dirty;
/** Default ctor */
L1Descriptor()
L1Descriptor() : data(0), _dirty(false)
{
lookupLevel = L1;
}
@ -250,12 +250,13 @@ class TableWalker : public MemObject
bool _dirty;
/** Default ctor */
L2Descriptor()
L2Descriptor() : data(0), l1Parent(nullptr), _dirty(false)
{
lookupLevel = L2;
}
L2Descriptor(L1Descriptor &parent) : l1Parent(&parent)
L2Descriptor(L1Descriptor &parent) : data(0), l1Parent(&parent),
_dirty(false)
{
lookupLevel = L2;
}

View file

@ -75,6 +75,8 @@ TLB::TLB(const ArmTLBParams *p)
isStage2(p->is_stage2), stage2Req(false), _attr(0),
directToStage2(false), tableWalker(p->walker), stage2Tlb(NULL),
stage2Mmu(NULL), rangeMRU(1), bootUncacheability(false),
aarch64(false), aarch64EL(EL0), isPriv(false), isSecure(false),
isHyp(false), asid(0), vmid(0), dacr(0),
miscRegValid(false), curTranType(NormalTran)
{
tableWalker->setTlb(this);

View file

@ -223,7 +223,8 @@ namespace ArmISA
uint8_t _nextItstate;
uint8_t _size;
public:
PCState() : flags(0), nextFlags(0), _itstate(0), _nextItstate(0)
PCState() : flags(0), nextFlags(0), _itstate(0), _nextItstate(0),
_size(0)
{}
void
@ -233,7 +234,8 @@ namespace ArmISA
npc(val + (thumb() ? 2 : 4));
}
PCState(Addr val) : flags(0), nextFlags(0), _itstate(0), _nextItstate(0)
PCState(Addr val) : flags(0), nextFlags(0), _itstate(0),
_nextItstate(0), _size(0)
{ set(val); }
bool

View file

@ -47,8 +47,8 @@ class PCStateBase
Addr _pc;
Addr _npc;
PCStateBase() {}
PCStateBase(Addr val) { set(val); }
PCStateBase() : _pc(0), _npc(0) {}
PCStateBase(Addr val) : _pc(0), _npc(0) { set(val); }
public:
/**
@ -206,8 +206,8 @@ class UPCState : public SimplePCState<MachInst>
nupc(1);
}
UPCState() {}
UPCState(Addr val) { set(val); }
UPCState() : _upc(0), _nupc(0) {}
UPCState(Addr val) : _upc(0), _nupc(0) { set(val); }
bool
branching() const

View file

@ -92,7 +92,7 @@ mask(int first, int last)
*/
template <int N>
inline
int64_t
uint64_t
sext(uint64_t val)
{
int sign_bit = bits(val, N-1, N-1);

View file

@ -126,6 +126,8 @@ BaseCPU::BaseCPU(Params *p, bool is_checker)
_switchedOut(p->switched_out), _cacheLineSize(p->system->cacheLineSize()),
interrupts(p->interrupts), profileEvent(NULL),
numThreads(p->numThreads), system(p->system),
functionTraceStream(nullptr), currentFunctionStart(0),
currentFunctionEnd(0), functionEntryTick(0),
addressMonitor()
{
// if Python did not provide a valid ID, do it here

View file

@ -60,7 +60,8 @@ Decode::Decode(const std::string &name,
inputBuffer(name + ".inputBuffer", "insts", params.decodeInputBufferSize),
inputIndex(0),
inMacroop(false),
execSeqNum(InstId::firstExecSeqNum)
execSeqNum(InstId::firstExecSeqNum),
blocked(false)
{
if (outputWidth < 1)
fatal("%s: executeInputWidth must be >= 1 (%d)\n", name, outputWidth);

View file

@ -251,12 +251,6 @@ class Fetch1 : public Named
* prediction sequence numbers. */
InstSeqNum predictionSeqNum;
/** The sequence number expected for the next returned cache line. The
* responses queue should be ordered and so, if the front of that queue
* has a lower lineSeqNum than this, lines need to be discarded. If it
* has a higher lineSeqNum, our line hasn't appeared yet */
InstSeqNum expectedLineSeqNum;
/** Blocked indication for report */
bool blocked;

View file

@ -76,7 +76,8 @@ Fetch2::Fetch2(const std::string &name,
lastStreamSeqNum(InstId::firstStreamSeqNum),
fetchSeqNum(InstId::firstFetchSeqNum),
expectedStreamSeqNum(InstId::firstStreamSeqNum),
predictionSeqNum(InstId::firstPredictionSeqNum)
predictionSeqNum(InstId::firstPredictionSeqNum),
blocked(false)
{
if (outputWidth < 1)
fatal("%s: decodeInputWidth must be >= 1 (%d)\n", name, outputWidth);

View file

@ -280,8 +280,9 @@ class LSQUnit {
public:
/** Default constructor. */
LSQSenderState()
: mainPkt(NULL), pendingPacket(NULL), outstanding(1),
noWB(false), isSplit(false), pktToSend(false), cacheBlocked(false)
: mainPkt(NULL), pendingPacket(NULL), idx(0), outstanding(1),
isLoad(false), noWB(false), isSplit(false),
pktToSend(false), cacheBlocked(false)
{ }
/** Instruction who initiated the access to memory. */

View file

@ -39,7 +39,7 @@ using namespace std;
/**** SimpleRenameMap methods ****/
SimpleRenameMap::SimpleRenameMap()
: freeList(NULL)
: freeList(NULL), zeroReg(0)
{
}

View file

@ -172,7 +172,7 @@ class UnifiedRenameMap
typedef SimpleRenameMap::RenameInfo RenameInfo;
/** Default constructor. init() must be called prior to use. */
UnifiedRenameMap() {};
UnifiedRenameMap() : regFile(nullptr) {};
/** Destructor. */
~UnifiedRenameMap() {};

View file

@ -90,7 +90,8 @@ struct O3ThreadState : public ThreadState {
O3ThreadState(O3CPU *_cpu, int _thread_num, Process *_process)
: ThreadState(_cpu, _thread_num, _process),
cpu(_cpu), noSquashFromTC(false), trapPending(false)
cpu(_cpu), noSquashFromTC(false), trapPending(false),
tc(nullptr)
{
if (!FullSystem)
return;

View file

@ -110,7 +110,8 @@ AtomicSimpleCPU::AtomicSimpleCPU(AtomicSimpleCPUParams *p)
drain_manager(NULL),
icachePort(name() + ".icache_port", this),
dcachePort(name() + ".dcache_port", this),
fastmem(p->fastmem)
fastmem(p->fastmem), dcache_access(false), dcache_latency(0),
ppCommit(nullptr)
{
_status = Idle;
}

View file

@ -88,7 +88,8 @@ using namespace TheISA;
BaseSimpleCPU::BaseSimpleCPU(BaseSimpleCPUParams *p)
: BaseCPU(p),
branchPred(p->branchPred),
traceData(NULL), thread(NULL)
traceData(NULL), thread(NULL), _status(Idle), interval_stats(false),
inst()
{
if (FullSystem)
thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb,
@ -266,18 +267,6 @@ BaseSimpleCPU::regStats()
.prereq(dcacheStallCycles)
;
icacheRetryCycles
.name(name() + ".icache_retry_cycles")
.desc("ICache total retry cycles")
.prereq(icacheRetryCycles)
;
dcacheRetryCycles
.name(name() + ".dcache_retry_cycles")
.desc("DCache total retry cycles")
.prereq(dcacheRetryCycles)
;
statExecutedInstType
.init(Enums::Num_OpClass)
.name(name() + ".op_class")

View file

@ -262,18 +262,10 @@ class BaseSimpleCPU : public BaseCPU, public ExecContext
Stats::Scalar icacheStallCycles;
Counter lastIcacheStall;
// number of cycles stalled for I-cache retries
Stats::Scalar icacheRetryCycles;
Counter lastIcacheRetry;
// number of cycles stalled for D-cache responses
Stats::Scalar dcacheStallCycles;
Counter lastDcacheStall;
// number of cycles stalled for D-cache retries
Stats::Scalar dcacheRetryCycles;
Counter lastDcacheRetry;
/// @{
/// Total number of branches fetched
Stats::Scalar numBranches;

View file

@ -63,7 +63,8 @@ using namespace std;
SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num, System *_sys,
Process *_process, TheISA::TLB *_itb,
TheISA::TLB *_dtb, TheISA::ISA *_isa)
: ThreadState(_cpu, _thread_num, _process), isa(_isa), system(_sys),
: ThreadState(_cpu, _thread_num, _process), isa(_isa),
predicate(false), system(_sys),
itb(_itb), dtb(_dtb)
{
clearArchRegs();

View file

@ -247,7 +247,7 @@ class StaticInst : public RefCounted, public StaticInstFlags
/// instruction.
StaticInst(const char *_mnemonic, ExtMachInst _machInst, OpClass __opClass)
: _opClass(__opClass), _numSrcRegs(0), _numDestRegs(0),
_numFPDestRegs(0), _numIntDestRegs(0),
_numFPDestRegs(0), _numIntDestRegs(0), _numCCDestRegs(0),
machInst(_machInst), mnemonic(_mnemonic), cachedDisassembly(0)
{ }

View file

@ -43,8 +43,9 @@
#include "sim/system.hh"
ThreadState::ThreadState(BaseCPU *cpu, ThreadID _tid, Process *_process)
: numInst(0), numOp(0), numLoad(0), _status(ThreadContext::Halted),
baseCpu(cpu), _threadId(_tid), lastActivate(0), lastSuspend(0),
: numInst(0), numOp(0), numLoad(0), startNumLoad(0),
_status(ThreadContext::Halted), baseCpu(cpu),
_contextId(0), _threadId(_tid), lastActivate(0), lastSuspend(0),
profile(NULL), profileNode(NULL), profilePC(0), quiesceEvent(NULL),
kernelStats(NULL), process(_process), physProxy(NULL), virtProxy(NULL),
proxy(NULL), funcExeInst(0), storeCondFailures(0)

View file

@ -59,7 +59,7 @@ using namespace std;
using namespace TheISA;
RealView::RealView(const Params *p)
: Platform(p), system(p->system)
: Platform(p), system(p->system), gic(nullptr)
{}
void