Files
Paweł Marczewski 5ef9bdc861 [Pal] Unify debug maps
- Use the same mechanism (debug_map) in Pal/Linux and Pal/Linux-SGX.
  Previously, Pal/Linux emulated the _r_debug structure, normally
  maintained by ld.so, but that cannot be done in SGX outer PAL,
  because it's loaded by ld.so already.
- Maintain the debug maps outside of SGX enclave. This allows
  initializing them before enclave start, and potentially makes
  them easier to use.
- Initialize PAL debug map before enclave start. Previously, this
  was done from inside the enclave, so you couldn't set a
  breakpoint too early (e.g. in pal_linux_main).
- Store only load address, without list of sections. This is to
  avoid parsing the list of sections just to report them to the
  debugger. Unfortunately, the GDB version that we support still
  needs these sections, but we can retrieve them in GDB plugin.
- Move Python GDB code related to debug maps to a common file.
2021-01-18 03:49:18 +01:00

87 lines
2.0 KiB
C

/* SPDX-License-Identifier: LGPL-3.0-or-later */
/* Copyright (C) 2020 Intel Corporation
* Paweł Marczewski <pawel@invisiblethingslab.com>
*/
#include "debug_map.h"
#include <asm/errno.h>
#include "spinlock.h"
struct debug_map* _Atomic g_debug_map = NULL;
/* Lock for modifying g_debug_map on our end. Even though the list can be read at any
* time, we need to prevent concurrent modification. */
static spinlock_t g_debug_map_lock = INIT_SPINLOCK_UNLOCKED;
static struct debug_map* debug_map_new(const char* name, void* addr) {
struct debug_map* map;
if (!(map = malloc(sizeof(*map))))
return NULL;
if (!(map->name = strdup(name))) {
free(map);
return NULL;
}
map->addr = addr;
map->next = NULL;
return map;
}
/* This function is hooked by our gdb integration script and should be left as is. */
__attribute__((__noinline__)) void debug_map_update_debugger(void) {
__asm__ volatile(""); // Required in addition to __noinline__ to prevent deleting this function.
// See GCC docs.
}
int debug_map_add(const char* name, void* addr) {
struct debug_map* map = debug_map_new(name, addr);
if (!map)
return -ENOMEM;
spinlock_lock(&g_debug_map_lock);
map->next = g_debug_map;
g_debug_map = map;
spinlock_unlock(&g_debug_map_lock);
debug_map_update_debugger();
return 0;
}
int debug_map_remove(void* addr) {
spinlock_lock(&g_debug_map_lock);
struct debug_map* prev = NULL;
struct debug_map* map = g_debug_map;
while (map) {
if (map->addr == addr)
break;
prev = map;
map = map->next;
}
if (!map) {
spinlock_unlock(&g_debug_map_lock);
return -EINVAL;
}
if (prev) {
prev->next = map->next;
} else {
g_debug_map = map->next;
}
spinlock_unlock(&g_debug_map_lock);
debug_map_update_debugger();
free(map->name);
free(map);
return 0;
}