mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-24 19:37:15 +00:00
Bug 1403438 - Add profiler-lul on mips64-linux. r=sewardj
--HG-- extra : rebase_source : 9f507b59a77785d60a0944baf4dad27ec7d2e1c7
This commit is contained in:
parent
bd8a2fdfb5
commit
be9033b5a9
@ -107,7 +107,7 @@
|
||||
#endif
|
||||
|
||||
// Linux builds use LUL, which uses DWARF info to unwind stacks.
|
||||
#if defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_x86_linux)
|
||||
#if defined(GP_PLAT_amd64_linux) || defined(GP_PLAT_x86_linux) || defined(GP_PLAT_mips64_linux)
|
||||
# define HAVE_NATIVE_UNWIND
|
||||
# define USE_LUL_STACKWALK
|
||||
# include "lul/LulMain.h"
|
||||
|
@ -1856,6 +1856,21 @@ unsigned int DwarfCFIToModule::RegisterNames::ARM() {
|
||||
return 13 * 8;
|
||||
}
|
||||
|
||||
unsigned int DwarfCFIToModule::RegisterNames::MIPS() {
|
||||
/*
|
||||
8 "$zero", "$at", "$v0", "$v1", "$a0", "$a1", "$a2", "$a3",
|
||||
8 "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7",
|
||||
8 "$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7",
|
||||
8 "$t8", "$t9", "$k0", "$k1", "$gp", "$sp", "$fp", "$ra",
|
||||
9 "$lo", "$hi", "$pc", "$f0", "$f1", "$f2", "$f3", "$f4", "$f5",
|
||||
8 "$f6", "$f7", "$f8", "$f9", "$f10", "$f11", "$f12", "$f13",
|
||||
7 "$f14", "$f15", "$f16", "$f17", "$f18", "$f19", "$f20",
|
||||
7 "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27",
|
||||
6 "$f28", "$f29", "$f30", "$f31", "$fcsr", "$fir"
|
||||
*/
|
||||
return 8 + 8 + 8 + 8 + 9 + 8 + 7 + 7 + 6;
|
||||
}
|
||||
|
||||
// See prototype for comments.
|
||||
int32_t parseDwarfExpr(Summariser* summ, const ByteReader* reader,
|
||||
string expr, bool debug,
|
||||
|
@ -1210,6 +1210,9 @@ class DwarfCFIToModule: public CallFrameInfo::Handler {
|
||||
|
||||
// ARM.
|
||||
static unsigned int ARM();
|
||||
|
||||
// MIPS.
|
||||
static unsigned int MIPS();
|
||||
};
|
||||
|
||||
// Create a handler for the dwarf2reader::CallFrameInfo parser that
|
||||
|
@ -329,6 +329,79 @@ Summariser::Rule(uintptr_t aAddress, int aNewReg,
|
||||
mCurrRules.mXbpExpr = LExpr(NODEREF, DW_REG_INTEL_XBP, 0);
|
||||
}
|
||||
|
||||
#elif defined(GP_ARCH_mips64)
|
||||
// ---------------- mips ---------------- //
|
||||
//
|
||||
// Now, can we add the rule to our summary? This depends on whether
|
||||
// the registers and the overall expression are representable. This
|
||||
// is the heart of the summarisation process.
|
||||
switch (aNewReg) {
|
||||
|
||||
case DW_REG_CFA:
|
||||
// This is a rule that defines the CFA. The only forms we can
|
||||
// represent are: = SP+offset or = FP+offset.
|
||||
if (how != NODEREF) {
|
||||
reason1 = "rule for DW_REG_CFA: invalid |how|";
|
||||
goto cant_summarise;
|
||||
}
|
||||
if (oldReg != DW_REG_MIPS_SP && oldReg != DW_REG_MIPS_FP) {
|
||||
reason1 = "rule for DW_REG_CFA: invalid |oldReg|";
|
||||
goto cant_summarise;
|
||||
}
|
||||
mCurrRules.mCfaExpr = LExpr(how, oldReg, offset);
|
||||
break;
|
||||
|
||||
case DW_REG_MIPS_SP: case DW_REG_MIPS_FP: case DW_REG_MIPS_PC: {
|
||||
// This is a new rule for SP, FP or PC (the return address).
|
||||
switch (how) {
|
||||
case NODEREF: case DEREF:
|
||||
// Check the old register is one we're tracking.
|
||||
if (!registerIsTracked((DW_REG_NUMBER)oldReg) &&
|
||||
oldReg != DW_REG_CFA) {
|
||||
reason1 = "rule for SP/FP/PC: uses untracked reg";
|
||||
goto cant_summarise;
|
||||
}
|
||||
break;
|
||||
case PFXEXPR: {
|
||||
// Check that the prefix expression only mentions tracked registers.
|
||||
const vector<PfxInstr>* pfxInstrs = mSecMap->GetPfxInstrs();
|
||||
reason2 = checkPfxExpr(pfxInstrs, offset);
|
||||
if (reason2) {
|
||||
reason1 = "rule for SP/FP/PC: ";
|
||||
goto cant_summarise;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
goto cant_summarise;
|
||||
}
|
||||
LExpr expr = LExpr(how, oldReg, offset);
|
||||
switch (aNewReg) {
|
||||
case DW_REG_MIPS_FP: mCurrRules.mFPexpr = expr; break;
|
||||
case DW_REG_MIPS_SP: mCurrRules.mSPexpr = expr; break;
|
||||
case DW_REG_MIPS_PC: mCurrRules.mPCexpr = expr; break;
|
||||
default: MOZ_CRASH("impossible value for aNewReg");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// Leave |reason1| and |reason2| unset here, for the reasons
|
||||
// explained in the analogous point in the ARM case just above.
|
||||
goto cant_summarise;
|
||||
}
|
||||
|
||||
// On MIPS, it seems the old SP value before the call is always the
|
||||
// same as the CFA. Therefore, in the absence of any other way to
|
||||
// recover the SP, specify that the CFA should be copied.
|
||||
if (mCurrRules.mSPexpr.mHow == UNKNOWN) {
|
||||
mCurrRules.mSPexpr = LExpr(NODEREF, DW_REG_CFA, 0);
|
||||
}
|
||||
|
||||
// Also, gcc says "Undef" for FP when it is unchanged.
|
||||
if (mCurrRules.mFPexpr.mHow == UNKNOWN) {
|
||||
mCurrRules.mFPexpr = LExpr(NODEREF, DW_REG_MIPS_FP, 0);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# error "Unsupported arch"
|
||||
|
@ -164,6 +164,9 @@ bool DwarfCFIRegisterNames(const typename ElfClass::Ehdr* elf_header,
|
||||
case EM_X86_64:
|
||||
*num_dw_regnames = DwarfCFIToModule::RegisterNames::X86_64();
|
||||
return true;
|
||||
case EM_MIPS:
|
||||
*num_dw_regnames = DwarfCFIToModule::RegisterNames::MIPS();
|
||||
return true;
|
||||
default:
|
||||
MOZ_ASSERT(0);
|
||||
return false;
|
||||
|
@ -73,6 +73,10 @@ NameOf_DW_REG(int16_t aReg)
|
||||
case DW_REG_ARM_R13: return "r13";
|
||||
case DW_REG_ARM_R14: return "r14";
|
||||
case DW_REG_ARM_R15: return "r15";
|
||||
#elif defined(GP_ARCH_mips64)
|
||||
case DW_REG_MIPS_SP: return "sp";
|
||||
case DW_REG_MIPS_FP: return "fp";
|
||||
case DW_REG_MIPS_PC: return "pc";
|
||||
#else
|
||||
# error "Unsupported arch"
|
||||
#endif
|
||||
@ -132,6 +136,10 @@ RuleSet::Print(void(*aLog)(const char*)) const
|
||||
res += mR12expr.ShowRule(" R12");
|
||||
res += mR13expr.ShowRule(" R13");
|
||||
res += mR14expr.ShowRule(" R14");
|
||||
#elif defined(GP_ARCH_mips64)
|
||||
res += mPCexpr.ShowRule(" PC");
|
||||
res += mSPexpr.ShowRule(" SP");
|
||||
res += mFPexpr.ShowRule(" FP");
|
||||
#else
|
||||
# error "Unsupported arch"
|
||||
#endif
|
||||
@ -153,6 +161,10 @@ RuleSet::ExprForRegno(DW_REG_NUMBER aRegno) {
|
||||
case DW_REG_ARM_R12: return &mR12expr;
|
||||
case DW_REG_ARM_R11: return &mR11expr;
|
||||
case DW_REG_ARM_R7: return &mR7expr;
|
||||
#elif defined(GP_ARCH_mips64)
|
||||
case DW_REG_MIPS_SP: return &mSPexpr;
|
||||
case DW_REG_MIPS_FP: return &mFPexpr;
|
||||
case DW_REG_MIPS_PC: return &mPCexpr;
|
||||
# else
|
||||
# error "Unknown arch"
|
||||
# endif
|
||||
@ -902,6 +914,10 @@ TaggedUWord EvaluateReg(int16_t aReg, const UnwindRegs* aOldRegs,
|
||||
case DW_REG_ARM_R13: return aOldRegs->r13;
|
||||
case DW_REG_ARM_R14: return aOldRegs->r14;
|
||||
case DW_REG_ARM_R15: return aOldRegs->r15;
|
||||
#elif defined(GP_ARCH_mips64)
|
||||
case DW_REG_MIPS_SP: return aOldRegs->sp;
|
||||
case DW_REG_MIPS_FP: return aOldRegs->fp;
|
||||
case DW_REG_MIPS_PC: return aOldRegs->pc;
|
||||
#else
|
||||
# error "Unsupported arch"
|
||||
#endif
|
||||
@ -1094,6 +1110,10 @@ void UseRuleSet(/*MOD*/UnwindRegs* aRegs,
|
||||
aRegs->r13 = TaggedUWord();
|
||||
aRegs->r14 = TaggedUWord();
|
||||
aRegs->r15 = TaggedUWord();
|
||||
#elif defined(GP_ARCH_mips64)
|
||||
aRegs->sp = TaggedUWord();
|
||||
aRegs->fp = TaggedUWord();
|
||||
aRegs->pc = TaggedUWord();
|
||||
#else
|
||||
# error "Unsupported arch"
|
||||
#endif
|
||||
@ -1131,6 +1151,13 @@ void UseRuleSet(/*MOD*/UnwindRegs* aRegs,
|
||||
= aRS->mR14expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||
aRegs->r15
|
||||
= aRS->mR15expr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||
#elif defined(GP_ARCH_mips64)
|
||||
aRegs->sp
|
||||
= aRS->mSPexpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||
aRegs->fp
|
||||
= aRS->mFPexpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||
aRegs->pc
|
||||
= aRS->mPCexpr.EvaluateExpr(&old_regs, cfa, aStackImg, aPfxInstrs);
|
||||
#else
|
||||
# error "Unsupported arch"
|
||||
#endif
|
||||
@ -1183,6 +1210,14 @@ LUL::Unwind(/*OUT*/uintptr_t* aFramePCs,
|
||||
(int)regs.r14.Valid(), (unsigned long long int)regs.r14.Value());
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
mLog(buf);
|
||||
#elif defined(GP_ARCH_mips64)
|
||||
SprintfLiteral(buf,
|
||||
"LoopTop: pc %d/%llx sp %d/%llx fp %d/%llx\n",
|
||||
(int)regs.pc.Valid(), (unsigned long long int)regs.pc.Value(),
|
||||
(int)regs.sp.Valid(), (unsigned long long int)regs.sp.Value(),
|
||||
(int)regs.fp.Valid(), (unsigned long long int)regs.fp.Value());
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
mLog(buf);
|
||||
#else
|
||||
# error "Unsupported arch"
|
||||
#endif
|
||||
@ -1194,6 +1229,9 @@ LUL::Unwind(/*OUT*/uintptr_t* aFramePCs,
|
||||
#elif defined(GP_ARCH_arm)
|
||||
TaggedUWord ia = (*aFramesUsed == 0 ? regs.r15 : regs.r14);
|
||||
TaggedUWord sp = regs.r13;
|
||||
#elif defined(GP_ARCH_mips64)
|
||||
TaggedUWord ia = regs.pc;
|
||||
TaggedUWord sp = regs.sp;
|
||||
#else
|
||||
# error "Unsupported arch"
|
||||
#endif
|
||||
@ -1410,6 +1448,15 @@ LUL::Unwind(/*OUT*/uintptr_t* aFramePCs,
|
||||
|
||||
static const int LUL_UNIT_TEST_STACK_SIZE = 16384;
|
||||
|
||||
#if defined(GP_ARCH_mips64)
|
||||
static __attribute__((noinline))
|
||||
unsigned long __getpc(void) {
|
||||
unsigned long rtaddr;
|
||||
__asm__ volatile ("move %0, $31" : "=r"(rtaddr));
|
||||
return rtaddr;
|
||||
}
|
||||
#endif
|
||||
|
||||
// This function is innermost in the test call sequence. It uses LUL
|
||||
// to unwind, and compares the result with the sequence specified in
|
||||
// the director string. These need to agree in order for the test to
|
||||
@ -1480,6 +1527,22 @@ bool GetAndCheckStackTrace(LUL* aLUL, const char* dstring)
|
||||
startRegs.r7 = TaggedUWord(block[5]);
|
||||
const uintptr_t REDZONE_SIZE = 0;
|
||||
uintptr_t start = block[1] - REDZONE_SIZE;
|
||||
#elif defined(GP_ARCH_mips64)
|
||||
volatile uintptr_t block[3];
|
||||
MOZ_ASSERT(sizeof(block) == 24);
|
||||
__asm__ __volatile__(
|
||||
"sd $29, 8(%0) \n"
|
||||
"sd $30, 16(%0) \n"
|
||||
:
|
||||
:"r"(block)
|
||||
:"memory"
|
||||
);
|
||||
block[0] = __getpc();
|
||||
startRegs.pc = TaggedUWord(block[0]);
|
||||
startRegs.sp = TaggedUWord(block[1]);
|
||||
startRegs.fp = TaggedUWord(block[2]);
|
||||
const uintptr_t REDZONE_SIZE = 0;
|
||||
uintptr_t start = block[1] - REDZONE_SIZE;
|
||||
#else
|
||||
# error "Unsupported platform"
|
||||
#endif
|
||||
|
@ -152,6 +152,10 @@ struct UnwindRegs {
|
||||
TaggedUWord xbp;
|
||||
TaggedUWord xsp;
|
||||
TaggedUWord xip;
|
||||
#elif defined(GP_ARCH_mips64)
|
||||
TaggedUWord sp;
|
||||
TaggedUWord fp;
|
||||
TaggedUWord pc;
|
||||
#else
|
||||
# error "Unknown plat"
|
||||
#endif
|
||||
|
@ -53,6 +53,10 @@ enum DW_REG_NUMBER {
|
||||
DW_REG_INTEL_XBP = 5,
|
||||
DW_REG_INTEL_XSP = 4,
|
||||
DW_REG_INTEL_XIP = 8,
|
||||
#elif defined(GP_ARCH_mips64)
|
||||
DW_REG_MIPS_SP = 29,
|
||||
DW_REG_MIPS_FP = 30,
|
||||
DW_REG_MIPS_PC = 34,
|
||||
#else
|
||||
# error "Unknown arch"
|
||||
#endif
|
||||
@ -275,6 +279,10 @@ public:
|
||||
LExpr mR12expr;
|
||||
LExpr mR11expr;
|
||||
LExpr mR7expr;
|
||||
#elif defined(GP_ARCH_mips64)
|
||||
LExpr mPCexpr;
|
||||
LExpr mFPexpr;
|
||||
LExpr mSPexpr;
|
||||
#else
|
||||
# error "Unknown arch"
|
||||
#endif
|
||||
@ -291,6 +299,9 @@ static inline bool registerIsTracked(DW_REG_NUMBER reg) {
|
||||
case DW_REG_ARM_R7: case DW_REG_ARM_R11: case DW_REG_ARM_R12:
|
||||
case DW_REG_ARM_R13: case DW_REG_ARM_R14: case DW_REG_ARM_R15:
|
||||
return true;
|
||||
#elif defined(GP_ARCH_mips64)
|
||||
case DW_REG_MIPS_FP: case DW_REG_MIPS_SP: case DW_REG_MIPS_PC:
|
||||
return true;
|
||||
# else
|
||||
# error "Unknown arch"
|
||||
# endif
|
||||
|
@ -47,7 +47,7 @@ if CONFIG['MOZ_GECKO_PROFILER']:
|
||||
]
|
||||
|
||||
if CONFIG['OS_TARGET'] in ('Android', 'Linux'):
|
||||
if CONFIG['CPU_ARCH'] in ('arm', 'x86', 'x86_64'):
|
||||
if CONFIG['CPU_ARCH'] in ('arm', 'x86', 'x86_64', 'mips64'):
|
||||
UNIFIED_SOURCES += [
|
||||
'lul/AutoObjectMapper.cpp',
|
||||
'lul/LulCommon.cpp',
|
||||
|
Loading…
x
Reference in New Issue
Block a user