Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ongoing] Experimental unwinding feature #405

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
unwind experimental
Import new version of dwarf file
  • Loading branch information
r1viollet committed Apr 13, 2024
commit 6afaebb72e94f930bb1ce4c8185c56e3f83eae60
222 changes: 119 additions & 103 deletions include/async-profiler/dwarf.h
Original file line number Diff line number Diff line change
@@ -1,153 +1,169 @@
/*
* Copyright 2021 Andrei Pangin
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* Copyright The async-profiler authors
* SPDX-License-Identifier: Apache-2.0
*/

#ifndef _DWARF_H
#define _DWARF_H

#include "arch.h"
#include <stddef.h>
#include "arch.h"


const int DW_REG_PLT = 128; // denotes special rule for PLT entries
const int DW_REG_INVALID = 255; // denotes unsupported configuration

const int DW_PC_OFFSET = 1;
const int DW_SAME_FP = 0x80000000;
const int DW_STACK_SLOT = sizeof(void*);


#if defined(__x86_64__)

# define DWARF_SUPPORTED true
#define DWARF_SUPPORTED true

const int DW_REG_FP = 6;
const int DW_REG_SP = 7;
const int DW_REG_PC = 16;
const int EMPTY_FRAME_SIZE = DW_STACK_SLOT;
const int LINKED_FRAME_SIZE = 2 * DW_STACK_SLOT;

#elif defined(__i386__)

# define DWARF_SUPPORTED true
#define DWARF_SUPPORTED true

const int DW_REG_FP = 5;
const int DW_REG_SP = 4;
const int DW_REG_PC = 8;
const int EMPTY_FRAME_SIZE = DW_STACK_SLOT;
const int LINKED_FRAME_SIZE = 2 * DW_STACK_SLOT;

#elif defined(__aarch64__)

#define DWARF_SUPPORTED true

const int DW_REG_FP = 29;
const int DW_REG_SP = 31;
const int DW_REG_PC = 30;
const int EMPTY_FRAME_SIZE = 0;
const int LINKED_FRAME_SIZE = 0;

#else

# define DWARF_SUPPORTED false
#define DWARF_SUPPORTED false

const int DW_REG_FP = 0;
const int DW_REG_SP = 1;
const int DW_REG_PC = 2;
const int EMPTY_FRAME_SIZE = 0;
const int LINKED_FRAME_SIZE = 0;

#endif

const int DW_REG_PLT = 128; // denotes special rule for PLT entries
const int DW_REG_INVALID = 255; // denotes unsupported configuration

const int DW_PC_OFFSET = 1;
const int DW_SAME_FP = 0x80000000;
const int DW_STACK_SLOT = sizeof(void *);

struct FrameDesc {
u32 loc;
int cfa;
int fp_off;

static FrameDesc default_frame;

static int comparator(const void *p1, const void *p2) {
FrameDesc *fd1 = (FrameDesc *)p1;
FrameDesc *fd2 = (FrameDesc *)p2;
return (int)(fd1->loc - fd2->loc);
}
u32 loc;
int cfa;
int fp_off;
int pc_off;

static FrameDesc empty_frame;
static FrameDesc default_frame;

static int comparator(const void* p1, const void* p2) {
FrameDesc* fd1 = (FrameDesc*)p1;
FrameDesc* fd2 = (FrameDesc*)p2;
return (int)(fd1->loc - fd2->loc);
}
};


class DwarfParser {
private:
const char *_name;
const char *_image_base;
const char *_ptr;

int _capacity;
int _count;
FrameDesc *_table;
FrameDesc *_prev;

u32 _code_align;
int _data_align;

const char *add(size_t size) {
const char *ptr = _ptr;
_ptr = ptr + size;
return ptr;
}

u8 get8() { return *_ptr++; }

u16 get16() { return *(u16 *)add(2); }

u32 get32() { return *(u32 *)add(4); }

u32 getLeb() {
u32 result = 0;
for (u32 shift = 0;; shift += 7) {
u8 b = *_ptr++;
result |= (b & 0x7f) << shift;
if ((b & 0x80) == 0) {
return result;
}
private:
const char* _name;
const char* _image_base;
const char* _ptr;

int _capacity;
int _count;
FrameDesc* _table;
FrameDesc* _prev;

u32 _code_align;
int _data_align;

const char* add(size_t size) {
const char* ptr = _ptr;
_ptr = ptr + size;
return ptr;
}
}

int getSLeb() {
int result = 0;
for (u32 shift = 0;; shift += 7) {
u8 b = *_ptr++;
result |= (b & 0x7f) << shift;
if ((b & 0x80) == 0) {
if ((b & 0x40) != 0 && (shift += 7) < 32) {
result |= -1 << shift;
}
return result;
}

u8 get8() {
return *_ptr++;
}

u16 get16() {
return *(u16*)add(2);
}

u32 get32() {
return *(u32*)add(4);
}
}

void skipLeb() {
while (*_ptr++ & 0x80) {}
}
u32 getLeb() {
u32 result = 0;
for (u32 shift = 0; ; shift += 7) {
u8 b = *_ptr++;
result |= (b & 0x7f) << shift;
if ((b & 0x80) == 0) {
return result;
}
}
}

const char *getPtr() {
const char *ptr = _ptr;
return ptr + *(int *)add(4);
}
int getSLeb() {
int result = 0;
for (u32 shift = 0; ; shift += 7) {
u8 b = *_ptr++;
result |= (b & 0x7f) << shift;
if ((b & 0x80) == 0) {
if ((b & 0x40) != 0 && (shift += 7) < 32) {
result |= -1 << shift;
}
return result;
}
}
}

void parse(const char *eh_frame_hdr, u64 adjust_eh_frame);
void parseCie();
void parseFde();
void parseInstructions(u32 loc, const char *end);
int parseExpression();
void skipLeb() {
while (*_ptr++ & 0x80) {}
}

void addRecord(u32 loc, u32 cfa_reg, int cfa_off, int fp_off);
FrameDesc *addRecordRaw(u32 loc, int cfa, int fp_off);
const char* getPtr() {
const char* ptr = _ptr;
return ptr + *(int*)add(4);
}

public:
DwarfParser(const char *name, const char *image_base,
const char *eh_frame_hdr, u64 adjust_eh_frame = 0);
void parse(const char* eh_frame_hdr, u64 adjust_eh_frame = 0);
void parseCie();
void parseFde();
void parseInstructions(u32 loc, const char* end);
int parseExpression();

// manual parse of fde
DwarfParser(const char *name, const char *image_base);
void addRecord(u32 loc, u32 cfa_reg, int cfa_off, int fp_off, int pc_off);
FrameDesc* addRecordRaw(u32 loc, int cfa, int fp_off, int pc_off);

void addFde(const char *fde, const char *cie);
public:
DwarfParser(const char* name, const char* image_base,
const char* eh_frame_hdr, u64 adjust_eh_frame = 0);

FrameDesc *table() const { return _table; }
FrameDesc* table() const {
return _table;
}

int count() const { return _count; }
int count() const {
return _count;
}
};

#endif // _DWARF_H
12 changes: 6 additions & 6 deletions include/logger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,15 @@ void LOG_set_logs_allowed_function(LogsAllowedCallback logs_allowed_function);
#define LG_IF_LVL_OK(level, ...) \
do { \
if (unlikely(LOG_is_logging_enabled_for_level(level))) { \
olprintfln(ABS(level), -1, MYNAME, __VA_ARGS__); \
ddprof::olprintfln(ABS(level), -1, MYNAME, __VA_ARGS__); \
} \
} while (false)

#define LG_ERR(...) LG_IF_LVL_OK(LL_ERROR, __VA_ARGS__)
#define LG_WRN(...) LG_IF_LVL_OK(LL_WARNING, __VA_ARGS__)
#define LG_NTC(...) LG_IF_LVL_OK(LL_NOTICE, __VA_ARGS__)
#define LG_NFO(...) LG_IF_LVL_OK(LL_INFORMATIONAL, __VA_ARGS__)
#define LG_DBG(...) LG_IF_LVL_OK(LL_DEBUG, __VA_ARGS__)
#define LG_ERR(...) LG_IF_LVL_OK(ddprof::LL_ERROR, __VA_ARGS__)
#define LG_WRN(...) LG_IF_LVL_OK(ddprof::LL_WARNING, __VA_ARGS__)
#define LG_NTC(...) LG_IF_LVL_OK(ddprof::LL_NOTICE, __VA_ARGS__)
#define LG_NFO(...) LG_IF_LVL_OK(ddprof::LL_INFORMATIONAL, __VA_ARGS__)
#define LG_DBG(...) LG_IF_LVL_OK(ddprof::LL_DEBUG, __VA_ARGS__)
#define PRINT_NFO(...) LG_IF_LVL_OK(-1 * LL_INFORMATIONAL, __VA_ARGS__)

} // namespace ddprof
Loading