Skip to content

Commit e48ac23

Browse files
authored
A set of fixes related to clang, aarch64 and musl pecularities of vmstructs stack unwinder (#199)
* Use heuristic to get frame layout for aarch64 * Improve recovery from Java Anchor Frame * Add and extend tests for vmstructs based stackwalking * Adjust for Musl signal trampoline * Run non-crashy test configs first * Reduce crashiness and locking of tests * Use root symbols * Compensate for GH musl/x64 runner quirks * Emit 'skip_frames' error frame on java anchor fallback * Do not try to recover from invalid anchor frames * Use X-enums for better code clarity
1 parent 6fa1618 commit e48ac23

21 files changed

+596
-198
lines changed

ddprof-lib/src/main/cpp/codeCache.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ class CodeCache {
113113

114114
void expand();
115115
void makeImportsPatchable();
116-
void saveImport(ImportId id, void** entry);
116+
void saveImport(ImportId id, void** entry);
117117

118118
public:
119119
explicit CodeCache(const char *name, short lib_index = -1,
@@ -177,6 +177,9 @@ class CodeCache {
177177
}
178178

179179
int count() { return _count; }
180+
CodeBlob* blob(int idx) {
181+
return &_blobs[idx];
182+
}
180183
};
181184

182185
class CodeCacheArray {

ddprof-lib/src/main/cpp/dwarf.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ FrameDesc FrameDesc::empty_frame = {0, DW_REG_SP | EMPTY_FRAME_SIZE << 8,
8989
FrameDesc FrameDesc::default_frame = {0, DW_REG_FP | LINKED_FRAME_SIZE << 8,
9090
-LINKED_FRAME_SIZE,
9191
-LINKED_FRAME_SIZE + DW_STACK_SLOT};
92+
FrameDesc FrameDesc::default_clang_frame = {0, DW_REG_FP | LINKED_FRAME_CLANG_SIZE << 8, -LINKED_FRAME_CLANG_SIZE, -LINKED_FRAME_CLANG_SIZE + DW_STACK_SLOT};
9293

9394
DwarfParser::DwarfParser(const char *name, const char *image_base,
9495
const char *eh_frame_hdr) {
@@ -398,12 +399,17 @@ int DwarfParser::parseExpression() {
398399

399400
void DwarfParser::addRecord(u32 loc, u32 cfa_reg, int cfa_off, int fp_off,
400401
int pc_off) {
401-
// sanity asserts for the values fitting into 16bit
402-
assert(cfa_reg <= 0xffffffff);
403-
assert(static_cast<u32>(cfa_off) <= 0xffffffff);
402+
// Sanity asserts to be able to pack those two values into one u32 vq
403+
// Assert that the cfa_reg fits in 8 bits (0 to 255)
404+
assert(cfa_reg <= 0xFF);
405+
406+
// Assert that the cfa_off fits in a 24-bit signed range.
407+
// Signed 24-bit integer range: -2^23 (-8,388,608) to 2^23 - 1 (8,388,607)
408+
assert(cfa_off >= -8388608 && cfa_off <= 8388607);
404409

405410
// cfa_reg and cfa_off can be encoded to a single 32 bit value, considering the existing and supported systems
406-
u32 cfa = static_cast<u16>(cfa_off) << 16 | static_cast<u16>(cfa_reg);
411+
u32 cfa = static_cast<u32>(cfa_off) << 8 | static_cast<u32>(cfa_reg & 0xff);
412+
407413
if (_prev == NULL || (_prev->loc == loc && --_count >= 0) ||
408414
_prev->cfa != cfa || _prev->fp_off != fp_off || _prev->pc_off != pc_off) {
409415
_prev = addRecordRaw(loc, cfa, fp_off, pc_off);

ddprof-lib/src/main/cpp/dwarf.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const int DW_REG_SP = 7;
3636
const int DW_REG_PC = 16;
3737
const int EMPTY_FRAME_SIZE = DW_STACK_SLOT;
3838
const int LINKED_FRAME_SIZE = 2 * DW_STACK_SLOT;
39+
const int LINKED_FRAME_CLANG_SIZE = LINKED_FRAME_SIZE;
3940

4041
#elif defined(__i386__)
4142

@@ -46,6 +47,7 @@ const int DW_REG_SP = 4;
4647
const int DW_REG_PC = 8;
4748
const int EMPTY_FRAME_SIZE = DW_STACK_SLOT;
4849
const int LINKED_FRAME_SIZE = 2 * DW_STACK_SLOT;
50+
const int LINKED_FRAME_CLANG_SIZE = LINKED_FRAME_SIZE;
4951

5052
#elif defined(__aarch64__)
5153

@@ -55,13 +57,9 @@ const int DW_REG_FP = 29;
5557
const int DW_REG_SP = 31;
5658
const int DW_REG_PC = 30;
5759
const int EMPTY_FRAME_SIZE = 0;
58-
59-
// aarch64 function prologue looks like this (if frame pointer is used):
60-
// stp x29, x30, [sp, -16]! // Save FP (x29) and LR (x30)
61-
// mov x29, sp // Set FP to SP
62-
// ---
63-
// LINKED_FRAME_SIZE should be 16
64-
const int LINKED_FRAME_SIZE = 2 * DW_STACK_SLOT;
60+
const int LINKED_FRAME_SIZE = 0;
61+
// clang compiler uses different frame layout than GCC
62+
const int LINKED_FRAME_CLANG_SIZE = 2 * DW_STACK_SLOT;
6563

6664
#else
6765

@@ -72,6 +70,7 @@ const int DW_REG_SP = 1;
7270
const int DW_REG_PC = 2;
7371
const int EMPTY_FRAME_SIZE = 0;
7472
const int LINKED_FRAME_SIZE = 0;
73+
const int LINKED_FRAME_CLANG_SIZE = LINKED_FRAME_SIZE;
7574

7675
#endif
7776

@@ -83,6 +82,7 @@ struct FrameDesc {
8382

8483
static FrameDesc empty_frame;
8584
static FrameDesc default_frame;
85+
static FrameDesc default_clang_frame;
8686

8787
static int comparator(const void *p1, const void *p2) {
8888
FrameDesc *fd1 = (FrameDesc *)p1;

ddprof-lib/src/main/cpp/profiler.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,10 +252,10 @@ CodeBlob *Profiler::findRuntimeStub(const void *address) {
252252
return _runtime_stubs.findBlobByAddress(address);
253253
}
254254

255-
bool Profiler::isAddressInCode(const void *pc) {
255+
bool Profiler::isAddressInCode(const void *pc, bool include_stubs) {
256256
if (CodeHeap::contains(pc)) {
257257
return CodeHeap::findNMethod(pc) != NULL &&
258-
!(pc >= _call_stub_begin && pc < _call_stub_end);
258+
(include_stubs || !(pc >= _call_stub_begin && pc < _call_stub_end));
259259
} else {
260260
return _libs->findLibraryByAddress(pc) != NULL;
261261
}

ddprof-lib/src/main/cpp/profiler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ class Profiler {
243243
const char *getLibraryName(const char *native_symbol);
244244
const char *findNativeMethod(const void *address);
245245
CodeBlob *findRuntimeStub(const void *address);
246-
bool isAddressInCode(const void *pc);
246+
bool isAddressInCode(const void *pc, bool include_stubs = true);
247247

248248
static void segvHandler(int signo, siginfo_t *siginfo, void *ucontext);
249249
static void busHandler(int signo, siginfo_t *siginfo, void *ucontext);

0 commit comments

Comments
 (0)