View of xos/usr/lib/ld-so/object_info.c


XOS | Parent Directory | View | Download

/* 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 <http://www.gnu.org/licenses/>. */
 
#include "object_info.h"
 
#include "xmalloc.h"
 
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <stdarg.h>
 
/* 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;
}