Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
19 changes: 18 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,19 @@ add_subdirectory(src/event_parser)
# elfutils
include(Findelfutils)

# -- Async profiler --
set(ASYNC_PROFILER_LIB_DIR ${CMAKE_SOURCE_DIR})
set(ASYNC_PROFILER_SRC_DIR ${ASYNC_PROFILER_LIB_DIR}/src/async-profiler)
set(ASYNC_PROFILER_LIB_INCLUDE ${ASYNC_PROFILER_LIB_DIR}/include/async-profiler)
aux_source_directory(${ASYNC_PROFILER_SRC_DIR} ASYNC_PROFILER_SOURCES)
add_library(async_prof_lib STATIC ${ASYNC_PROFILER_SOURCES})
target_include_directories(async_prof_lib PUBLIC ${ASYNC_PROFILER_LIB_INCLUDE}
${CMAKE_SOURCE_DIR}/include)
target_link_libraries(async_prof_lib PRIVATE dw elf Threads::Threads)
set_property(TARGET async_prof_lib PROPERTY POSITION_INDEPENDENT_CODE ON)
add_library(DDProf::AsyncProf ALIAS async_prof_lib)
# -------------------

# ---- Static analysis ----
include(ClangTidy)
include(Format)
Expand Down Expand Up @@ -148,7 +161,8 @@ aux_source_directory(src/jit JIT_SRC)
set(DDPROF_GLOBAL_SRC ${COMMON_SRC} ${DEMANGLER_SRC} ${PPROF_SRC} ${EXPORTER_SRC} ${EXE_SRC}
${JIT_SRC})

set(DDPROF_LIBRARY_LIST DDProf::Parser llvm-demangle ${ELFUTILS_LIBRARIES} Threads::Threads)
set(DDPROF_LIBRARY_LIST DDProf::Parser DDProf::AsyncProf llvm-demangle ${ELFUTILS_LIBRARIES}
Threads::Threads)

if(ON)
# Add the rust library - Refactoring ongoing. OFF for now
Expand Down Expand Up @@ -390,6 +404,9 @@ install(

# ---- Unit tests ----

aux_source_directory(${CMAKE_SOURCE_DIR}/src/async-profiler ASYNC_PROFILER_SRC)
set(ASYNC_PROFILER_INCLUDE ${CMAKE_SOURCE_DIR}/include/async-profiler)

# Unit tests Add infrastructure for enabling tests
option(BUILD_DDPROF_TESTING "Enable tests" ON)
if(${BUILD_DDPROF_TESTING})
Expand Down
87 changes: 87 additions & 0 deletions design_notes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
## things by pid
#################
DsoHdr
-- DSO

Lookups
-- pid / bin maps
-- mappings
-- runtime

DwflHdr
-- DwflWrapper
-- Visited pids

## Not by pid
#############
-- File info (dso_hdr)
-- Lookup
Dwarf symbol lookup
-- Symbol table

## Async profiler

parseLibraries parses everything in proc self.

### Step 1 -- ensure we can have one code array per PID

### Step 2 -- ensure symbols are shared across PIDs

### Step 3 -- ensure unwinding tables are shared across PIDs


### Junk notes
Write an API that can work with ddprof object model

LoadSymbolTable loads at a given base address
We want to store all symbols at an elf address

1) Rewrite parseLibraries <Hard>
we can use DSO information + file info
Ensure the cache is at elf address (not base)
Start is 0 or for non PIE,


2) Find library is by absolute address
- Keep that ?


### Issues

- We are moving from a lazy to an absolute load
- We don't have enough tests

- We are not consider elf versions (though do we care ?)
- read past sp --> check with



### Async profiler load in symbols_linux

--> Create code cache
library name
Index --> count of lib
image base --> start
image end --> end

--> Parse program headers
text_base --> set as base
---> parseDynamicSection
global offset table --> Example (Shit it is absolute)
GOT start == 0x5555556226b0
GOT start == 0x7ffff7ffd018

relocation -> relent size of relocation entry
!We already have ways to parse GOT, we don't care

---> parseDwarfInfo
parseDwarfInfo()
looks like the values are relative (wouhou)
then we set the dwarf table (so nothing to change)

-> VDSO
--> parse memory


// TODO tree of life

149 changes: 149 additions & 0 deletions include/async-profiler/arch.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* Copyright 2017 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.
*/

#ifndef _ARCH_H
#define _ARCH_H

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;

static inline u64 atomicInc(volatile u64 &var, u64 increment = 1) {
return __sync_fetch_and_add(&var, increment);
}

static inline int atomicInc(volatile int &var, int increment = 1) {
return __sync_fetch_and_add(&var, increment);
}

static inline u64 loadAcquire(u64 &var) {
return __atomic_load_n(&var, __ATOMIC_ACQUIRE);
}

static inline void storeRelease(u64 &var, u64 value) {
return __atomic_store_n(&var, value, __ATOMIC_RELEASE);
}

#if defined(__x86_64__) || defined(__i386__)

typedef unsigned char instruction_t;
const instruction_t BREAKPOINT = 0xcc;
const int BREAKPOINT_OFFSET = 0;

const int SYSCALL_SIZE = 2;
const int FRAME_PC_SLOT = 1;
const int ADJUST_RET = 1;
const int PLT_HEADER_SIZE = 16;
const int PLT_ENTRY_SIZE = 16;
const int PERF_REG_PC = 8; // PERF_REG_X86_IP

# define spinPause() asm volatile("pause")
# define rmb() asm volatile("lfence" : : : "memory")
# define flushCache(addr) \
asm volatile("mfence; clflush (%0); mfence" : : "r"(addr) : "memory")

#elif defined(__arm__) || defined(__thumb__)

typedef unsigned int instruction_t;
const instruction_t BREAKPOINT = 0xe7f001f0;
const instruction_t BREAKPOINT_THUMB = 0xde01de01;
const int BREAKPOINT_OFFSET = 0;

const int SYSCALL_SIZE = sizeof(instruction_t);
const int FRAME_PC_SLOT = 1;
const int ADJUST_RET = 0;
const int PLT_HEADER_SIZE = 20;
const int PLT_ENTRY_SIZE = 12;
const int PERF_REG_PC = 15; // PERF_REG_ARM_PC

# define spinPause() asm volatile("yield")
# define rmb() asm volatile("dmb ish" : : : "memory")
# define flushCache(addr) \
__builtin___clear_cache((char *)(addr), \
(char *)(addr) + sizeof(instruction_t))

#elif defined(__aarch64__)

typedef unsigned int instruction_t;
const instruction_t BREAKPOINT = 0xd4200000;
const int BREAKPOINT_OFFSET = 0;

const int SYSCALL_SIZE = sizeof(instruction_t);
const int FRAME_PC_SLOT = 1;
const int ADJUST_RET = 0;
const int PLT_HEADER_SIZE = 32;
const int PLT_ENTRY_SIZE = 16;
const int PERF_REG_PC = 32; // PERF_REG_ARM64_PC

# define spinPause() asm volatile("isb")
# define rmb() asm volatile("dmb ish" : : : "memory")
# define flushCache(addr) \
__builtin___clear_cache((char *)(addr), \
(char *)(addr) + sizeof(instruction_t))

#elif defined(__PPC64__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)

typedef unsigned int instruction_t;
const instruction_t BREAKPOINT = 0x7fe00008;
// We place the break point in the third instruction slot on PPCLE as the first
// two are skipped if the call comes from within the same compilation unit
// according to the LE ABI.
const int BREAKPOINT_OFFSET = 8;

const int SYSCALL_SIZE = sizeof(instruction_t);
const int FRAME_PC_SLOT = 2;
const int ADJUST_RET = 0;
const int PLT_HEADER_SIZE = 24;
const int PLT_ENTRY_SIZE = 24;
const int PERF_REG_PC = 32; // PERF_REG_POWERPC_NIP

# define spinPause() \
asm volatile("yield") // does nothing, but using or 1,1,1 would lead to
// other problems
# define rmb() \
asm volatile("sync" \
: \
: \
: "memory") // lwsync would do but better safe than sorry
# define flushCache(addr) \
__builtin___clear_cache((char *)(addr), \
(char *)(addr) + sizeof(instruction_t))

#else

# error "Compiling on unsupported arch"

#endif

// Return address signing support.
// Apple M1 has 47 bit virtual addresses.
#if defined(__aarch64__) && defined(__APPLE__)
# define ADDRESS_BITS 47
# define WX_MEMORY true
#else
# define WX_MEMORY false
#endif

#ifdef ADDRESS_BITS
static inline const void *stripPointer(const void *p) {
return (const void *)((unsigned long)p & ((1UL << ADDRESS_BITS) - 1));
}
#else
# define stripPointer(p) (p)
#endif

#endif // _ARCH_H
Loading