/* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
/* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
/* Copyright (C) 2014 OSCAR lab, 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 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 General Public License for more details.
You should have received a copy of the GNU 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
#include
struct gdb_link_map
{
void * l_addr;
char * l_name;
void * l_ld;
struct gdb_link_map *l_next, *l_prev;
};
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));
int uri_len = strlen(uri);
char * new_uri = malloc(uri_len + 1);
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);
}
DEFINE_MIGRATE_FUNC(gdb_map)
MIGRATE_FUNC_BODY(gdb_map)
{
struct gdb_link_map *m = link_map_list;
struct gdb_link_map *newm = NULL;
while (m) {
ADD_OFFSET(sizeof(struct gdb_link_map));
ADD_FUNC_ENTRY(*offset);
if (!dry) {
newm = (struct gdb_link_map *) (base + *offset);
memcpy(newm, m, sizeof(struct gdb_link_map));
newm->l_prev = newm->l_next = NULL;
}
ADD_OFFSET(strlen(m->l_name) + 1);
if (!dry) {
newm->l_name = (char *) (base + *offset);
memcpy(newm->l_name, m->l_name, strlen(m->l_name) + 1);
}
m = m->l_next;
}
}
END_MIGRATE_FUNC
RESUME_FUNC_BODY(gdb_map)
{
uint64_t off = GET_FUNC_ENTRY();
struct gdb_link_map *map = (struct gdb_link_map *) (base + off);
RESUME_REBASE(map->l_name);
RESUME_REBASE(map->l_prev);
RESUME_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;
#ifdef DEBUG_RESUME
debug("gdb: %s loaded at %p\n", map->l_name, map->l_addr);
#endif
DkDebugAttachBinary(map->l_name, map->l_addr);
}
END_RESUME_FUNC