/* Copyright (C) 2008 Emmanuel Varoquaux
This file is part of XOS.
This program 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.
This program 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 . */
#include "object_info.h"
#include "xmalloc.h"
#include
#include
#include
#include
/* object_info */
static void object_info_init_va(struct object_info_struct *object_info, const char *name, int type, va_list ap)
{
const char *filename;
object_info->name = xstrdup(name);
switch ((object_info->type = type)) {
case OI_EXEC: /* executable */
object_info->filename = NULL;
break;
case OI_FILE: /* fichier */
object_info->filename = xstrdup(va_arg(ap, const char *));
object_info->dev = va_arg(ap, dev_t);
object_info->ino = va_arg(ap, ino_t);
break;
case OI_VDSO: /* object partage dynamique virtuel */
object_info->filename = NULL;
break;
case OI_DYNAMIC_LINKER: /* l'editeur de liens dynamique */
if ((filename = va_arg(ap, const char *)))
object_info->filename = xstrdup(filename);
else
object_info->filename = NULL;
break;
case OI_NOT_FOUND: /* la recherche du nom a echoue */
object_info->filename = NULL;
break;
}
object_info->base_address = MAP_FAILED;
object_info->load_address = MAP_FAILED;
object_info->segment_table = NULL;
object_info->segment_count = 0;
clear_dynamic_data(&object_info->dynamic_data);
object_info->dependency_list = NULL;
object_info->dependency_list_size = 0;
object_info->reference_count = 0;
}
void object_info_init(struct object_info_struct *object_info, const char *name, int type, ...)
{
va_list ap;
va_start(ap, type);
object_info_init_va(object_info, name, type, ap);
va_end(ap);
}
void object_info_destroy(struct object_info_struct *object_info)
{
if (object_info->segment_table)
free(object_info->segment_table);
if (object_info->dependency_list)
free(object_info->dependency_list);
dispose_dynamic_data(&object_info->dynamic_data);
if (object_info->filename)
free(object_info->filename);
free(object_info->name);
}
int object_info_equals(struct object_info_struct *object_info1, struct object_info_struct *object_info2)
{
if (!strcmp(object_info1->name, object_info2->name))
return 1;
if (object_info1->type != object_info2->type)
return 0;
switch (object_info1->type) {
case OI_EXEC:
return 1;
case OI_FILE:
return object_info1->dev == object_info2->dev && object_info1->ino == object_info2->ino;
case OI_DYNAMIC_LINKER:
return 1;
case OI_VDSO:
case OI_NOT_FOUND:
default:
return 0;
}
}
void object_info_print(struct object_info_struct *object_info)
{
printf("\t");
if (!object_info->filename || strcmp(object_info->name, object_info->filename))
printf("%s => ", object_info->name);
if (object_info->type == OI_NOT_FOUND)
printf("not found\n");
else {
if (object_info->filename)
printf("%s", object_info->filename);
printf(" (0x%0*lx)\n", 2 * sizeof (unsigned long), (unsigned long)object_info->load_address);
}
}
/* object_info_list */
void object_info_list_init(struct object_info_list_struct *object_info_list)
{
object_info_list->first = NULL;
object_info_list->last = NULL;
}
void object_info_list_destroy(struct object_info_list_struct *object_info_list)
{
struct object_info_struct *object_info, *next_object_info;
for (object_info = object_info_list->first; object_info; object_info = next_object_info) {
next_object_info = object_info->next;
object_info_destroy(object_info);
free(object_info);
}
}
struct object_info_struct *object_info_list_insert(struct object_info_list_struct *object_info_list, const char *name, int type, ...)
{
va_list ap;
struct object_info_struct *object_info;
struct object_info_struct *object_info1, *object_info2;
/* construction d'un object_info */
object_info = xmalloc(sizeof (struct object_info_struct));
va_start(ap, type);
object_info_init_va(object_info, name, type, ap);
va_end(ap);
/* est-il deja dans la liste ? */
object_info1 = NULL;
object_info2 = object_info_list->first;
while (object_info2) {
if (object_info_equals(object_info2, object_info)) {
/* si oui, on ne l'insere pas et on le detruit */
object_info_destroy(object_info);
free(object_info);
return object_info2;
}
object_info1 = object_info2;
object_info2 = object_info2->next;
}
/* si non, on l'insere en fin de liste */
object_info->previous = object_info1;
object_info->next = NULL;
if (object_info1)
object_info1->next = object_info;
else
object_info_list->first = object_info;
object_info_list->last = object_info;
return object_info;
}