/* Copyright (C) 2014 Stony Brook University This file is part of Graphene Library OS. Graphene Library OS is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Graphene Library OS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ /* * shim_debug.c * * This file contains codes for registering libraries to GDB. */ #include #include #include #include #include #include #include #include #include #ifndef DEBUG void clean_link_map_list(void) { /* do nothing */ } void remove_r_debug(void* addr) { __UNUSED(addr); /* do nothing */ } void append_r_debug(const char* uri, void* addr, void* dyn_addr) { __UNUSED(uri); __UNUSED(addr); __UNUSED(dyn_addr); /* do nothing */ } #else /* !DEBUG */ struct gdb_link_map { void* l_addr; char* l_name; void* l_ld; struct gdb_link_map *l_next, *l_prev; }; /* XXX: What lock protects this? vma_list_lock? */ static struct gdb_link_map* link_map_list = NULL; void clean_link_map_list(void) { if (!link_map_list) return; if (link_map_list->l_prev) link_map_list->l_prev->l_next = NULL; struct gdb_link_map* m = link_map_list; for (; m; m = m->l_next) { DkDebugDetachBinary(m->l_addr); free(m); } link_map_list = NULL; } void remove_r_debug(void* addr) { struct gdb_link_map* m = link_map_list; for (; m; m = m->l_next) if (m->l_addr == addr) break; if (!m) return; debug("remove a library for gdb: %s\n", m->l_name); if (m->l_prev) m->l_prev->l_next = m->l_next; if (m->l_next) m->l_next->l_prev = m->l_prev; DkDebugDetachBinary(addr); } void append_r_debug(const char* uri, void* addr, void* dyn_addr) { struct gdb_link_map* new = malloc(sizeof(struct gdb_link_map)); if (!new) return; int uri_len = strlen(uri); char* new_uri = malloc(uri_len + 1); if (!new_uri) { free(new); return; } memcpy(new_uri, uri, uri_len + 1); new->l_addr = addr; new->l_ld = dyn_addr; new->l_name = new_uri; struct gdb_link_map* prev = NULL; struct gdb_link_map** tail = &link_map_list; while (*tail) { prev = *tail; tail = &(*tail)->l_next; } debug("add a library for gdb: %s\n", uri); new->l_prev = prev; new->l_next = NULL; *tail = new; DkDebugAttachBinary(uri, addr); } BEGIN_CP_FUNC(gdb_map) { __UNUSED(obj); __UNUSED(size); __UNUSED(objp); struct gdb_link_map* m = link_map_list; struct gdb_link_map* newm = NULL; while (m) { ptr_t off = ADD_CP_OFFSET(sizeof(struct gdb_link_map)); newm = (struct gdb_link_map*)(base + off); memcpy(newm, m, sizeof(struct gdb_link_map)); newm->l_prev = newm->l_next = NULL; size_t len = strlen(newm->l_name); newm->l_name = (char*)(base + ADD_CP_OFFSET(len + 1)); memcpy(newm->l_name, m->l_name, len + 1); ADD_CP_FUNC_ENTRY(off); m = m->l_next; } } END_CP_FUNC(gdb_map) BEGIN_RS_FUNC(gdb_map) { __UNUSED(offset); struct gdb_link_map* map = (void*)(base + GET_CP_FUNC_ENTRY()); CP_REBASE(map->l_name); CP_REBASE(map->l_prev); CP_REBASE(map->l_next); struct gdb_link_map* prev = NULL; struct gdb_link_map** tail = &link_map_list; while (*tail) { prev = *tail; tail = &(*tail)->l_next; } map->l_prev = prev; *tail = map; DkDebugAttachBinary(map->l_name, map->l_addr); DEBUG_RS("base=%p,name=%s", map->l_addr, map->l_name); } END_RS_FUNC(gdb_map) #endif