Skip to content

Commit

Permalink
[Pal/Linux,Linux-SGX] Make sure g_debug_map is complete
Browse files Browse the repository at this point in the history
After this change, `g_debug_map` contains all loaded executables, even
the ones that were loaded by the system (such as main Gramine executable
or protobuf).

This is not necessary for GDB integration, but will help add features
such as crash location reporting (and it already helped simplify the SGX
profiling system).

Signed-off-by: Paweł Marczewski <pawel@invisiblethingslab.com>
  • Loading branch information
pwmarcz committed Oct 4, 2021
1 parent 1941b35 commit 06e3630
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 53 deletions.
4 changes: 4 additions & 0 deletions Pal/include/host/Linux-common/debug_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,8 @@ void debug_map_update_debugger(void);
int debug_map_add(const char* name, void* addr);
int debug_map_remove(void* addr);

/* Initialize `g_debug_map` with executable files already loaded by the system (main program, and
* dynamic libraries). Processes `/proc/self/maps`. */
int debug_map_init_from_proc_maps(void);

#endif /* DEBUG_MAP_H */
1 change: 0 additions & 1 deletion Pal/src/host/Linux-SGX/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,6 @@ executable('loader',
'sgx_platform.c',
'sgx_process.c',
'sgx_profile.c',
'sgx_profile_glibc.c',
'sgx_syscall.c',
'sgx_thread.c',
pal_linux_common_sources_urts,
Expand Down
3 changes: 0 additions & 3 deletions Pal/src/host/Linux-SGX/sgx_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,6 @@ void sgx_profile_sample_ocall_outer(void* ocall_func);

/* Record a new mapped ELF */
void sgx_profile_report_elf(const char* filename, void* addr);

/* Record all ELFs from outer PAL */
void sgx_profile_report_urts_elfs(void);
#endif

/* perf.data output (sgx_perf_data.h) */
Expand Down
18 changes: 15 additions & 3 deletions Pal/src/host/Linux-SGX/sgx_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,13 @@ static int initialize_enclave(struct pal_enclave* enclave, const char* manifest_
ret = sgx_profile_init();
if (ret < 0)
goto out;

/* Report all ELFs that are already loaded (URTS and dynamic libraries used by it) */
struct debug_map* map = g_debug_map;
while (map) {
sgx_profile_report_elf(map->name, map->addr);
map = map->next;
}
}
#endif

Expand Down Expand Up @@ -559,9 +566,6 @@ static int initialize_enclave(struct pal_enclave* enclave, const char* manifest_

debug_map_add(enclave->libpal_uri + URI_PREFIX_FILE_LEN, (void*)pal_area->addr);
sgx_profile_report_elf(enclave->libpal_uri + URI_PREFIX_FILE_LEN, (void*)pal_area->addr);

/* Report outer PAL maps to profiler, so that we can record samples pointing to outer PAL. */
sgx_profile_report_urts_elfs();
#endif

ret = 0;
Expand Down Expand Up @@ -1100,6 +1104,14 @@ int main(int argc, char* argv[], char* envp[]) {
setup_asan();
#endif

#ifdef DEBUG
ret = debug_map_init_from_proc_maps();
if (ret < 0) {
log_error("Failed to init debug maps");
return unix_to_pal_error(ret);
}
#endif

force_linux_to_grow_stack();

if (argc < 4)
Expand Down
38 changes: 0 additions & 38 deletions Pal/src/host/Linux-SGX/sgx_profile_glibc.c

This file was deleted.

59 changes: 51 additions & 8 deletions Pal/src/host/Linux-common/debug_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
* Paweł Marczewski <pawel@invisiblethingslab.com>
*/

#include "debug_map.h"

#include <asm/errno.h>
#include <asm/mman.h>

#include "debug_map.h"
#include "linux_utils.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. */
/* Lock for modifying g_debug_map on our end. Even though the list can be read by GDB 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) {
Expand All @@ -38,12 +39,26 @@ __attribute__((__noinline__)) void debug_map_update_debugger(void) {
}

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);

struct debug_map* map = g_debug_map;
while (map) {
if (map->addr == addr) {
bool name_matches = !strcmp(name, map->name);
spinlock_unlock(&g_debug_map_lock);
/* If the exact same map is already there, skip adding it and report success: this can
* happen when we encounter two executable ranges for the same file. */
return name_matches ? 0 : -EEXIST;
}
map = map->next;
}

map = debug_map_new(name, addr);
if (!map) {
spinlock_unlock(&g_debug_map_lock);
return -ENOMEM;
}

map->next = g_debug_map;
g_debug_map = map;

Expand Down Expand Up @@ -84,3 +99,31 @@ int debug_map_remove(void* addr) {

return 0;
}

/* Find a range that (likely) corresponds to a mapped executable file, and add it to debug maps. */
static int debug_map_init_callback(struct proc_maps_range* r, void* arg) {
__UNUSED(arg);

/* not executable */
if (!(r->prot & PROT_EXEC))
return 0;

/* no name */
if (!r->name)
return 0;

/* [vvar], [vdso] etc. */
if (r->name[0] != '/')
return 0;

/* /dev/sgx etc. */
if (strstartswith(r->name, "/dev/"))
return 0;

void* addr = (void*)(r->start - r->offset);
return debug_map_add(r->name, addr);
}

int debug_map_init_from_proc_maps(void) {
return parse_proc_maps("/proc/self/maps", debug_map_init_callback, /*arg=*/NULL);
}
7 changes: 7 additions & 0 deletions Pal/src/host/Linux/db_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

#include "api.h"
#include "asan.h"
#include "debug_map.h"
#include "elf/elf.h"
#include "linux_utils.h"
#include "pal.h"
Expand Down Expand Up @@ -236,6 +237,12 @@ noreturn void pal_linux_main(void* initial_rsp, void* fini_callback) {

init_slab_mgr();

#ifdef DEBUG
ret = debug_map_init_from_proc_maps();
if (ret < 0)
INIT_FAIL(-unix_to_pal_error(ret), "failed to init debug maps");
#endif

g_pal_loader_path = get_main_exec_path();
g_libpal_path = strdup(argv[1]);
if (!g_pal_loader_path || !g_libpal_path) {
Expand Down

0 comments on commit 06e3630

Please sign in to comment.