| // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #include "vm/globals.h" |
| #if defined(TARGET_OS_LINUX) |
| |
| #include <stdint.h> // NOLINT |
| #include <stdio.h> // NOLINT |
| #include <stdlib.h> // NOLINT |
| |
| #include "vm/gdbjit_linux.h" |
| |
| extern "C" { |
| typedef enum { |
| JIT_NOACTION = 0, |
| JIT_REGISTER_FN, |
| JIT_UNREGISTER_FN |
| } jit_actions_t; |
| |
| struct jit_code_entry { |
| struct jit_code_entry* next_entry; |
| struct jit_code_entry* prev_entry; |
| const char* symfile_addr; |
| uint64_t symfile_size; |
| }; |
| |
| struct jit_descriptor { |
| uint32_t version; |
| /* This type should be jit_actions_t, but we use uint32_t |
| to be explicit about the bitwidth. */ |
| uint32_t action_flag; |
| struct jit_code_entry* relevant_entry; |
| struct jit_code_entry* first_entry; |
| }; |
| |
| #ifndef GDB_JIT_SYMBOLS |
| /* GDB puts a breakpoint in this function. */ |
| void __attribute__((noinline)) __jit_debug_register_code() { } |
| |
| /* Make sure to specify the version statically, because the |
| debugger may check the version before we can set it. */ |
| struct jit_descriptor __jit_debug_descriptor = { 1, 0, 0, 0 }; |
| #endif |
| |
| static struct jit_code_entry* first_dynamic_region = NULL; |
| static struct jit_code_entry* last_dynamic_region = NULL; |
| |
| void addDynamicSection(const char* symfile_addr, uint64_t symfile_size) { |
| jit_code_entry* new_entry = reinterpret_cast<jit_code_entry*>( |
| malloc(sizeof(jit_code_entry))); |
| if (new_entry != NULL) { |
| new_entry->symfile_addr = symfile_addr; |
| new_entry->symfile_size = symfile_size; |
| new_entry->next_entry = NULL; |
| new_entry->prev_entry = last_dynamic_region; |
| if (first_dynamic_region == NULL) { |
| first_dynamic_region = new_entry; |
| } else { |
| last_dynamic_region->next_entry = new_entry; |
| } |
| last_dynamic_region = new_entry; |
| } |
| __jit_debug_descriptor.action_flag = JIT_REGISTER_FN; |
| __jit_debug_descriptor.relevant_entry = new_entry; |
| __jit_debug_descriptor.first_entry = first_dynamic_region; |
| __jit_debug_register_code(); |
| } |
| |
| void deleteDynamicSections() { |
| struct jit_code_entry* iterator = last_dynamic_region; |
| while (iterator != NULL) { |
| __jit_debug_descriptor.action_flag = JIT_UNREGISTER_FN; |
| __jit_debug_descriptor.relevant_entry = iterator; |
| __jit_debug_descriptor.first_entry = first_dynamic_region; |
| __jit_debug_register_code(); |
| iterator = iterator->prev_entry; |
| } |
| first_dynamic_region = NULL; |
| last_dynamic_region = NULL; |
| } |
| }; |
| |
| #endif // defined(TARGET_OS_LINUX) |