6#if defined(DART_HOST_OS_ANDROID)
10#include <android/log.h>
16#include <sys/resource.h>
33 android_log_to_stderr,
35 "Send Dart VM logs to stdout and stderr instead of the Android "
43 generate_perf_events_symbols,
45 "Generate events symbols for profiling with perf");
47class PerfCodeObserver :
public CodeObserver {
49 PerfCodeObserver() : out_file_(nullptr) {
51 if (file_open ==
nullptr) {
54 intptr_t pid = getpid();
55 char* filename = OS::SCreate(
nullptr,
"/tmp/perf-%" Pd ".map", pid);
56 out_file_ = (*file_open)(filename,
true);
62 if ((file_close ==
nullptr) || (out_file_ ==
nullptr)) {
65 (*file_close)(out_file_);
68 virtual bool IsActive()
const {
69 return FLAG_generate_perf_events_symbols && (out_file_ !=
nullptr);
72 virtual void Notify(
const char*
name,
74 uword prologue_offset,
77 const CodeComments* comments) {
79 if ((file_write ==
nullptr) || (out_file_ ==
nullptr)) {
82 const char*
marker = optimized ?
"*" :
"";
84 OS::SCreate(Thread::Current()->zone(),
"%" Px " %" Px " %s%s\n",
base,
98 return static_cast<intptr_t
>(getpid());
101static bool LocalTime(int64_t seconds_since_epoch, tm* tm_result) {
102 time_t seconds =
static_cast<time_t
>(seconds_since_epoch);
103 if (seconds != seconds_since_epoch)
return false;
104 struct tm* error_code = localtime_r(&seconds, tm_result);
105 return error_code !=
nullptr;
110 bool succeeded = LocalTime(seconds_since_epoch, &decomposed);
112 return (succeeded && (decomposed.tm_zone !=
nullptr)) ? decomposed.tm_zone
118 bool succeeded = LocalTime(seconds_since_epoch, &decomposed);
121 return succeeded ?
static_cast<int>(decomposed.tm_gmtoff) : 0;
131 if (gettimeofday(&tv,
nullptr) < 0) {
135 return (
static_cast<int64_t
>(tv.tv_sec) * 1000000) + tv.tv_usec;
140 if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0) {
145 int64_t
result = ts.tv_sec;
163 if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &ts) != 0) {
167 int64_t
result = ts.tv_sec;
174#if defined(SUPPORT_TIMELINE)
175 if (Timeline::recorder_discards_clock_values())
return -1;
185#if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_X64) || \
186 defined(TARGET_ARCH_ARM64) || defined(TARGET_ARCH_RISCV64)
187 const int kMinimumAlignment = 16;
188#elif defined(TARGET_ARCH_ARM)
189 const int kMinimumAlignment = 8;
191#error Unsupported architecture.
193 intptr_t alignment = kMinimumAlignment;
198 ASSERT(alignment >= kMinimumAlignment);
203 return sysconf(_SC_NPROCESSORS_ONLN);
217 req.tv_sec = seconds;
220 int r = nanosleep(&req, &rem);
236 return reinterpret_cast<uintptr_t
>(
237 __builtin_extract_return_addr(__builtin_return_address(0)));
243 if (FLAG_android_log_to_stderr) {
247 __android_log_vprint(ANDROID_LOG_INFO,
"DartVM",
format,
args);
267 va_list measure_args;
268 va_copy(measure_args,
args);
282 va_copy(print_args,
args);
289 ASSERT(str !=
nullptr && strlen(str) > 0 && value !=
nullptr);
295 }
else if (str[0] ==
'+') {
298 if ((str[i] ==
'0') && (str[i + 1] ==
'x' || str[i + 1] ==
'X') &&
299 (str[i + 2] !=
'\0')) {
306 *
value =
static_cast<int64_t
>(strtoull(str, &endptr,
base));
310 return ((errno == 0) && (endptr != str) && (*endptr == 0));
315 if (FLAG_generate_perf_events_symbols) {
324 if (FLAG_android_log_to_stderr) {
328 __android_log_vprint(ANDROID_LOG_ERROR,
"DartVM",
format,
args);
349#if defined(ARCH_IS_64_BIT)
350#define ElfW(Type) Elf64_##Type
352#define ElfW(Type) Elf32_##Type
358 const Image instructions_image(snapshot_instructions);
359 if (
auto*
const image_build_id = instructions_image.build_id()) {
360 return {instructions_image.build_id_length(), image_build_id};
362 const uint8_t* dso_base =
GetAppDSOBase(snapshot_instructions);
363 const ElfW(Ehdr)& elf_header = *
reinterpret_cast<const ElfW(Ehdr)*
>(dso_base);
364 const ElfW(Phdr)*
const phdr_array =
365 reinterpret_cast<const ElfW(Phdr)*
>(dso_base + elf_header.e_phoff);
366 for (intptr_t i = 0; i < elf_header.e_phnum; i++) {
367 const ElfW(Phdr)&
header = phdr_array[i];
368 if (
header.p_type != PT_NOTE)
continue;
369 if ((
header.p_flags & PF_R) != PF_R)
continue;
370 const uint8_t*
const note_addr = dso_base +
header.p_vaddr;
371 const Elf32_Nhdr& note_header =
372 *
reinterpret_cast<const Elf32_Nhdr*
>(note_addr);
373 if (note_header.n_type != NT_GNU_BUILD_ID)
continue;
374 const char*
const note_contents =
375 reinterpret_cast<const char*
>(note_addr +
sizeof(Elf32_Nhdr));
377 if (note_header.n_namesz != strlen(ELF_NOTE_GNU) + 1)
continue;
378 if (strncmp(ELF_NOTE_GNU, note_contents, note_header.n_namesz) == 0) {
379 return {
static_cast<intptr_t
>(note_header.n_descsz),
380 reinterpret_cast<const uint8_t*
>(note_contents +
381 note_header.n_namesz)};
static const char marker[]
static void Register(CodeObserver *observer)
static DART_NORETURN void Exit(int code)
static int NumberOfAvailableProcessors()
static const char * GetTimeZoneName(int64_t seconds_since_epoch)
static void SleepMicros(int64_t micros)
static int64_t GetCurrentTimeMillis()
static void RegisterCodeObservers()
static int64_t GetCurrentMonotonicMicros()
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
static void Sleep(int64_t millis)
static void Print(const char *format,...) PRINTF_ATTRIBUTE(1
static bool StringToInt64(const char *str, int64_t *value)
static BuildId GetAppBuildId(const uint8_t *snapshot_instructions)
static const uint8_t * GetAppDSOBase(const uint8_t *snapshot_instructions)
static int64_t GetCurrentTimeMicros()
static intptr_t ActivationFrameAlignment()
static void static void static void VFPrint(FILE *stream, const char *format, va_list args)
static DART_NORETURN void Abort()
static char static char * VSCreate(Zone *zone, const char *format, va_list args)
static int64_t GetCurrentThreadCPUMicros()
static uintptr_t GetProgramCounter()
static intptr_t ProcessId()
static void PrepareToAbort()
static int64_t GetCurrentMonotonicFrequency()
static char * SCreate(Zone *zone, const char *format,...) PRINTF_ATTRIBUTE(2
static int64_t GetCurrentMonotonicTicks()
static int64_t GetCurrentMonotonicMicrosForTimeline()
static int GetTimeZoneOffsetInSeconds(int64_t seconds_since_epoch)
static int static int VSNPrint(char *str, size_t size, const char *format, va_list args)
static constexpr bool IsPowerOfTwo(T x)
void(* Dart_FileWriteCallback)(const void *data, intptr_t length, void *stream)
void(* Dart_FileCloseCallback)(void *stream)
void *(* Dart_FileOpenCallback)(const char *name, bool write)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static const uint8_t buffer[]
uint32_t uint32_t * format
#define DEFINE_FLAG(type, name, default_value, comment)
constexpr intptr_t kMicrosecondsPerMillisecond
constexpr intptr_t kMicrosecondsPerSecond
constexpr intptr_t kNanosecondsPerMicrosecond
void * malloc(size_t size)
constexpr intptr_t kNanosecondsPerSecond
static const char header[]