/* 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; }